### 主要使用 Suiet Wallet套件 及 Mysten Sui.js套件 ## 參考資料 [Suiet Wallet Kit 文件](https://kit.suiet.app/docs/QuickStart) [Suiet Wallet Kit GitHub](https://github.com/suiet/wallet-kit) [Mysten sui.js api文件](https://sdk.mystenlabs.com/typedoc/index.html) [Mysten sui.js GitHub](https://github.com/MystenLabs/sui) [SUI 主網上線,前端開發者的DApp 開發指南](https://juejin.cn/post/7229984415329337400) ## 讓Demo Project跑起來 [Demo GitHub](https://github.com/ryan19910912/dapp_demo) git clone ``` git clone https://github.com/ryan19910912/dapp_demo.git ``` 進入到Demo專案並安裝Lib ``` npm install ``` 讓Demo專案跑起來 ``` npm run dev ``` ![](https://hackmd.io/_uploads/HkbuzL-o2.png) ## 連接錢包 ![](https://hackmd.io/_uploads/Sk9tMIbs3.png) ![](https://hackmd.io/_uploads/ByoqfUWsh.png) ## 程式解說 我們主要會修改main.jsx及App.jsx這2個檔案 ![](https://hackmd.io/_uploads/HJC2rLbj3.png) - ### main.jsx main.jsx主要是引入suiet wallet套件的樣式CSS檔及WalletProvider ![](https://hackmd.io/_uploads/HyZf8LZi3.png) - ### App.jsx App.jsx主要用來寫跟智能合約互動的主程式 ![](https://hackmd.io/_uploads/SkMNP8Ws2.png) - ConnectButton為Suiet Wallet套件內的連接錢包按鈕 ![](https://hackmd.io/_uploads/rkHpd8Ws3.png) - useWallet為Suiet Wallet套件內的錢包功能 ![](https://hackmd.io/_uploads/Byx1K8Ws3.png) ```typescript= export interface WalletContextState { configuredWallets: IWallet[]; //目前配置的錢包選項 detectedWallets: IWallet[]; allAvailableWallets: IWallet[]; //目前可用的錢包選項 chains: Chain[]; //所有的Sui鏈(id, name, rpcUrl) chain: Chain | undefined; //目前所在的Sui鏈 name: string | undefined; //錢包名稱 adapter: IWalletAdapter | undefined; account: WalletAccount | undefined; //錢包帳號資訊(常用) address: string | undefined; //錢包地址(account內也有) connecting: boolean; connected: boolean; //是否連線中 status: "disconnected" | "connected" | "connecting"; //目前連線狀態 } ``` ![](https://hackmd.io/_uploads/rJsitLboh.png) - devnetConnection、testnetConnection及mainnetConnet是Sui的節點Rpc Url ![](https://hackmd.io/_uploads/Sk6MO8Zih.png) - JsonRpcProvider主要用來查詢合約用 [JsonRpcProvider參考文件](http://typescript-sdk-docs.s3-website-us-east-1.amazonaws.com/classes/JsonRpcProvider.html) 需要先new一個JsonRpcProvider物件出來,並傳入節點Rpc Url ![](https://hackmd.io/_uploads/rJbwpIWj2.png) ![](https://hackmd.io/_uploads/Sy2xC8Zih.png) - TransactionBlock主要用來執行合約用 [TransactionBlock參考文件](http://typescript-sdk-docs.s3-website-us-east-1.amazonaws.com/classes/TransactionBlock.html) 需要先new一個TransactionBlock物件出來 並於最後該錢包使用簽名及執行交易區塊時,傳入TransactionBlock當作參數 ![](https://hackmd.io/_uploads/BkNIAL-o3.png) ### 常用的查詢方法 JsonRpcProvider內的方法 1. getOwnedObjects (取得該Owner底下所有物件資訊,可用Filter篩選) [getOwnedObjects參考文件](http://typescript-sdk-docs.s3-website-us-east-1.amazonaws.com/classes/JsonRpcProvider.html#getOwnedObjects) ```javascript= let ownedObject = { owner: wallet?.account?.address, options: { showType: true, showOwner: true, showContent: true, } } if (structType !== ""){ ownedObject.filter = { MatchAny: [ { StructType: structType } ] } } provider.getOwnedObjects( ownedObject ).then(data => { console.log("getOwnedObjectsFunction"); console.log(data); setOwendObjects(jsonFormat(data.data)); }); ``` 2. getObject (取得任何物件資訊,不管是SharedObject或是OwnedObject) [getObject參考文件](http://typescript-sdk-docs.s3-website-us-east-1.amazonaws.com/classes/JsonRpcProvider.html#getObject) ```javascript= provider.getObject({ id: objectId, options: { showType: true, showOwner: true, showContent: true, } }).then(data => { console.log("getObjectFunction"); console.log(data); setObject(jsonFormat(data.data)); }); ``` 3. getDynamicFields (取得動態欄位,通常用於查找Table) [getDynamicFields參考文件](http://typescript-sdk-docs.s3-website-us-east-1.amazonaws.com/classes/JsonRpcProvider.html#getDynamicFields) ```javascript= provider.getDynamicFields({ parentId: parentId, }).then(data => { console.log("getDynamicFieldsFunction"); console.log(data); setDynamicFields(jsonFormat(data.data)); }); ``` 4. getDynamicFieldObject (取得動態欄位內的物件資訊) [getDynamicFieldObject參考文件](http://typescript-sdk-docs.s3-website-us-east-1.amazonaws.com/classes/JsonRpcProvider.html#getDynamicFieldObject) ```javascript= provider.getDynamicFieldObject({ parentId: parentId, name: { type: type, value: value } }).then(data => { console.log("getDynamicFieldObjectFunction"); console.log(data); setDynamicFieldObject(jsonFormat(data.data)); }); ``` 5. getCoins (該Owner底下所有Coin資訊) [getCoins參考文件](http://typescript-sdk-docs.s3-website-us-east-1.amazonaws.com/classes/JsonRpcProvider.html#getCoins) ```javascript= provider.getCoins({ // coinType: coinType, owner: wallet?.address, }).then(data => { console.log("getCoinsFunction"); console.log(data); setCoins(jsonFormat(data.data)); }); ``` ### 常用的執行方法 TransactionBlock內的方法 1. splitCoins (拆分Coin) + transferObjects (傳遞物件給某個地址) [splitCoins參考文件](http://typescript-sdk-docs.s3-website-us-east-1.amazonaws.com/classes/TransactionBlock.html#splitCoins-2)、[transferObjects參考文件](http://typescript-sdk-docs.s3-website-us-east-1.amazonaws.com/classes/TransactionBlock.html#transferObjects-2) ```javascript= let txObj = new TransactionBlock(); let main_coin = splitCoin === "" ? txObj.gas : txObj.object(splitCoin); let [coins] = txObj.splitCoins(main_coin, [txObj.pure(Number(splitAmount) * 1000000000)]); txObj.transferObjects([coins], txObj.pure(wallet.account.address)); wallet.signAndExecuteTransactionBlock({ transactionBlock: txObj, options: { showEffects: true }, }).then(data => { console.log("splitCoinFunction"); console.log(data.effects); setSplitResult(jsonFormat(data.effects)); }); ``` 2. mergeCoins (合併Coin) [mergeCoins參考文件](http://typescript-sdk-docs.s3-website-us-east-1.amazonaws.com/classes/TransactionBlock.html#mergeCoins-2) ```javascript= let txObj = new TransactionBlock(); let merge_coins = []; let main_coin = mainCoin === "" ? txObj.gas : txObj.object(mainCoin); for (let coin_object_id of mergeCoin.split(",")) { merge_coins.push(txObj.object(coin_object_id)); } txObj.mergeCoins(main_coin, merge_coins); wallet.signAndExecuteTransactionBlock({ transactionBlock: txObj, options: { showEffects: true }, }).then(data => { console.log("mergeCoinFunction"); console.log(data.effects); setMergeResult(jsonFormat(data.effects)); }); ``` 3. moveCall (跟智能合約做互動) [moveCall參考文件](http://typescript-sdk-docs.s3-website-us-east-1.amazonaws.com/classes/TransactionBlock.html#moveCall-2) ```javascript= let txObj = new TransactionBlock(); let type_args = [ coinType ]; let args = [ txObj.object(objectId), txObj.pure(Number(maxSupply) * 1000000000), txObj.object(trader), txObj.pure(Number(commissionPercentage)), txObj.pure(name), txObj.pure(desc), ]; // call sui move smart contract txObj.moveCall({ target: `${packageId}::${moduleName}::${functionName}`, typeArguments: type_args, arguments: args, }) wallet.signAndExecuteTransactionBlock({ transactionBlock: txObj, options: { showEffects: true }, }).then(data => { console.log("moveCallFunction"); console.log(data.effects); setMoveCallResult(jsonFormat(data.effects)); }); ``` 最後都需要使用wallet.signAndExecuteTransactionBlock來讓用戶簽名並執行上述動作 ```javascript= wallet.signAndExecuteTransactionBlock({ transactionBlock: txObj, options: { showEffects: true }, }).then(data => { console.log("splitCoinFunction"); console.log(data.effects); setSplitResult(jsonFormat(data.effects)); }); ``` ### TransactionBlock傳遞參數方法詳解 ![](https://hackmd.io/_uploads/ryi7iP-o3.png) 介紹幾個常用的 1. pure (會自行判斷一般類型(數字、字串)及物件類型) (推薦) 2. object (用於傳遞物件) 3. makeMoveVec (用於傳遞陣列Vector) sui move合約範例 ```move= public entry fun merge_shares<T: drop>( shares1: &mut PuddleShares<T>, shares2Arr: vector<PuddleShares<T>>, _ctx: &mut TxContext, ) ``` Javascript範例 ```javascript= let objects_arr = []; merge_id_arr.forEach(merge_id => { objects_arr.push(txObj.object(merge_id)); }); txObj.pure(shares_id), txObj.makeMoveVec({ objects: objects_arr }) ```