前言作为和Aptos同期出名的Move语言生态双子星的Sui网络,在北京时间5月3日晚上8点,也已上线了主网。那么要进入Sui生态进行dapp的开发,要先记住一句话:万物皆是Object。为什么这么说呢?Sui借鉴了BTC的UTXO的模式,它将每个交易输出
<!--StartFragment-->
作为和 Aptos 同期出名的 Move 语言生态双子星的 Sui 网络,在北京时间5月3日晚上8点,也已上线了主网。那么要进入 Sui 生态进行 dapp 的开发,要先记住一句话:万物皆是 Object。
Sui 借鉴了 BTC 的 UTXO 的模式,它将每个交易输出视为一个未使用的交易,使得交易的输入和输出可以更精细地控制和跟踪。
用更为直观的方式来解读,在链上,我的资产,也是一个个 Object 的模式。看下图:
<!--EndFragment-->
<!--StartFragment-->
一个账号下可以有多种 Coin,每一种 Coin 都是由一个个的 Object 组成,所有这种 Coin 的 Object 的 balance 相加,就是账户下这种 Coin 的余额。
而 nft 作为非同质化代币,在 Sui 上的表现,也是一个 Object,只不过它是一种更为特殊的 Object。
<!--EndFragment--> <!--StartFragment-->
作为 dapp 开发,第一步势必是从连接插件钱包开始,这里我们使用 suiet 团队开发的库,相较于官方的,它对于其他钱包连接的支持更好
<!--EndFragment-->
yarn add @suiet/wallet-kit
<!--StartFragment-->
在项目的根文件中,引入 WalletProvider
(也就是在你 React 项目的根文件中,如果是 nextjs,则在 _app.tsx 中)
<WalletProvider>
<Component {...pageProps} />
</WalletProvider>
<!--EndFragment--> <!--StartFragment-->
ConnectButton
,点击后展开钱包列表<!--EndFragment-->
import { ConnectButton } from '@suiet/wallet-kit'
//...
<ConnectButton />
<!--StartFragment-->
这里 select 的参数,现在可以使用有 Suiet
、Sui Wallet
、Ethos Wallet
和 Martian Sui Wallet
这4种,分别对应4种钱包。其中 Sui Wallet
是官方钱包
<!--EndFragment-->
const { select } = useWallet()
<button onClick={() => select('Suiet')}>Connect wallet</button>
<!--StartFragment-->
<!--EndFragment-->
const { address, connected } = useWallet()
<!--StartFragment-->
<!--EndFragment-->
import { ethers } from 'ethers';
// 这里借用 ethers 库来帮我们处理 message,将其转为 Uint8Array 类型
const message = ethers.utils.toUtf8Bytes('test 123')
const { signature, messageBytes } = await signMessage({ message })
<!--StartFragment-->
这里要注意一下,sui 的交易和之前的 aptos、evm 都有所区别
<!--EndFragment-->
import { TransactionBlock } from '@mysten/sui.js';
const { signAndExecuteTransactionBlock } = useWallet()
const handleTransaction = async () => {
const tx = new TransactionBlock()
tx.moveCall({ target: \`${packageId}::${moduleName}::${functionName}\`, arguments: \[ tx.pure(参数1), tx.pure(参数2), ], typeArguments: \[], })
const result = await signAndExecuteTransactionBlock({ transactionBlock: tx, options: { showEffects: true }, }) console.log('result', result) // 通过result?.effects?.status?.status获取交易状态,成功为 'success',失败为'failure' }
<button onClick={handleTransaction}>Send Transaction</button>
<!--StartFragment-->
由于上文提到过 Sui 的核心:万物皆 object,在对资产进行交易时,需要传入作为费用的 objectId。
但这又会出现一个问题:如果我只有一个 object,我既要用这个 object 来作为交易费用,同时,我有需要一个 object 来支付这笔交易的 gasFee,那这交易应该怎么发呢?
这里就会引入一个新的概念:拆币(splitCoin)。也就是说,我需要发一笔交易,把一个 object 拆成了两个,一个足以支付交易费用,一个集合了剩余的 balance 的 object 来作为 gasFee。
例如:我的账户下当前只有一个 balance 为 0.5 的 object。我要发一笔交易,这个合约需要收 0.3 的费用。那么此时,我需要发送一笔拆币交易,将这个 0.5 的 object 拆出一个 0.3 的object,剩余部分作为一个 object 来作为 gasFee。
但如果每次交易都要分开发送两笔:拆币、调用合约,那太复杂了,这里我们将它们合并成一笔交易: <!--EndFragment-->
import { TransactionBlock } from '@mysten/sui.js';
const { signAndExecuteTransactionBlock } = useWallet()
const handleTransaction = async () => {
const tx = new TransactionBlock() const value = '300000000' // 这里是想要拆出的目标值
const \[coins] = tx.splitCoins(tx.gas, \[ tx.pure(BigInt(value)), ])
tx.moveCall({ target: \`${packageId}::${moduleName}::${functionName}\`, arguments: \[ tx.pure(参数1), tx.pure(参数2), tx.makeMoveVec({ objects: \[coins] }), ], typeArguments: \[], }) const result = await signAndExecuteTransactionBlock({ transactionBlock: tx, options: { showEffects: true }, }) console.log('result', result)
// 通过result?.effects?.status?.status获取交易状态,成功为 'success',失败为'failure' }
<button onClick={handleTransaction}>Send Transaction\</button>
<!--StartFragment-->
可以看到,这里的交易合并了 splitCoin
和 moveCall
两笔交易。为了确保所有人都能够正常交易,建议涉及到资产的交易,都加入 splitCoin
。
<!--EndFragment-->
import { Connection, JsonRpcProvider } from '@mysten/sui.js';
const suiProvider = new JsonRpcProvider(new Connection({ fullnode: \`${节点rpc地址}\` }))
<!--StartFragment-->
<!--EndFragment-->
const { totalBalance } = await suiProvider.getBalance({
owner: \`${你的地址}\`,
coinType: \`${币的类型地址}\` //如果不传,那么返回的就是 SUI 的 balance })
<!--StartFragment-->
<!--EndFragment-->
const allObjects = await suiProvider.getOwnedObjects({
owner: address,
options: {
showType: true,
showDisplay: true,
showContent: true,
}
});
<!--StartFragment-->
<!--EndFragment-->
import { Coin } from '@mysten/sui.js';
const objectIDs = (allObjectRefs?.data || \[])
.filter((item) => !Coin.isCoin(item))
.map((anObj) => anObj.data.objectId);
<!--StartFragment-->
<!--EndFragment-->
import { TransactionBlock, JsonRpcProvider, Connection } from '@mysten/sui.js';
const suiProvider = new JsonRpcProvider(new Connection({ fullnode: \`${节点rpc地址}\` }))
const tx = new TransactionBlock()
tx.moveCall({
target: \`${packageId}::${moduleName}::${functionName}\`,
arguments: \[ tx.pure(参数1), tx.pure(参数2), ], typeArguments: \[], })
const result = await suiProvider.devInspectTransactionBlock({
transactionBlock: tx, sender: \`${地址}\` })
<!--StartFragment-->
Sui 相对于 evm、aptos 生态,它是一种完全不同的链。不管是内部实现,还是对于 dapp 开发者来说,都是一种非常新奇的体验。
<!--EndFragment-->
Telegram:https://t.me/+P3Z7P_xQxbNlZWZl 来源:https://www.fabipingtai.com
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!