本页列出了使用 jettons的常见示例。
转账通知信息的结构如下
message(0x7362d09c) JettonTransferNotification { queryId: Int as uint64; amount: Int as coins; sender: Address; forwardPayload: Slice as remaining;}
使用 receiver 功能接受令牌通知信息。
可使用 jetton 钱包状态初始值和计算 jetton 地址进行验证。 请注意,通知来自您的合约的 jetton 钱包,因此所有者地址栏应使用 myAddress()。 钱包的初始数据布局如下所示,但有时会有所不同。 请注意,“myJettonWalletAddress “也可以存储在合约存储中,以便在每次交易中减少 gas 使用量。
myAddress()
struct JettonWalletData { balance: Int as coins; ownerAddress: Address; jettonMasterAddress: Address; jettonWalletCode: Cell;} fun calculateJettonWalletAddress(ownerAddress: Address, jettonMasterAddress: Address, jettonWalletCode: Cell): Address { let initData = JettonWalletData{ balance: 0, ownerAddress, jettonMasterAddress, jettonWalletCode, }; return contractAddress(StateInit{code: jettonWalletCode, data: initData.toCell()});} contract Sample { jettonWalletCode: Cell; jettonMasterAddress: Address; init(jettonWalletCode: Cell, jettonMasterAddress: Address) { self.jettonWalletCode = jettonWalletCode; self.jettonMasterAddress = jettonMasterAddress; } receive(msg: JettonTransferNotification) { let myJettonWalletAddress = calculateJettonWalletAddress(myAddress(), self.jettonMasterAddress, self.jettonWalletCode); require(sender() == myJettonWalletAddress, "Notification not from your jetton wallet!"); // your logic of processing token notification }}
要发送 jetton 传输,请使用 send()函数。 请注意,“myJettonWalletAddress” 也可以存储在合约存储中,以便在每次交易中减少 gas 使用量。
send()
message(0xf8a7ea5) JettonTransfer { queryId: Int as uint64; amount: Int as coins; destination: Address; responseDestination: Address?; customPayload: Cell? = null; forwardTonAmount: Int as coins; forwardPayload: Slice as remaining;} receive("send") { let myJettonWalletAddress = calculateJettonWalletAddress(myAddress(), self.jettonMasterAddress, self.jettonWalletCode); send(SendParameters{ to: myJettonWalletAddress, value: ton("0.05"), body: JettonTransfer{ queryId: 42, amount: jettonAmount, // jetton amount you want to transfer destination: msg.userAddress, // address you want to transfer jettons. Note that this is address of jetton wallet owner, not jetton wallet itself responseDestination: msg.userAddress, // address where to send a response with confirmation of a successful transfer and the rest of the incoming message Toncoins customPayload: null, // in most cases will be null and can be omitted. Needed for custom logic on Jetton Wallets itself forwardTonAmount: 1, // amount that will be transferred with JettonTransferNotification. Needed for custom logic execution like in example below. If the amount is 0 notification won't be sent forwardPayload: rawSlice("F") // precomputed beginCell().storeUint(0xF, 4).endCell().beginParse(). This works for simple transfer, if needed any struct can be used as `forwardPayload` }.toCell(), });}
message(0x595f07bc) JettonBurn { queryId: Int as uint64; amount: Int as coins; responseDestination: Address?; customPayload: Cell? = null;} receive("burn") { let myJettonWalletAddress = calculateJettonWalletAddress(myAddress(), self.jettonMasterAddress, self.jettonWalletCode); send(SendParameters{ to: myJettonWalletAddress, body: JettonBurn{ queryId: 42, amount: jettonAmount, // jetton amount you want to burn responseDestination: someAddress, // address where to send a response with confirmation of a successful burn and the rest of the incoming message coins customPayload: null, // in most cases will be null and can be omitted. Needed for custom logic on jettons itself }.toCell(), });}
除了 JettonWalletData 将采用以下结构外,USDT(在 TON 上)的操作保持不变:
JettonWalletData
struct JettonWalletData { status: Ins as uint4; balance: Int as coins; ownerAddress: Address; jettonMasterAddress: Address;}
计算钱包地址的函数如下所示:
fun calculateJettonWalletAddress(ownerAddress: Address, jettonMasterAddress: Address, jettonWalletCode: Cell): Address { let initData = JettonWalletData{ status: 0, balance: 0, ownerAddress, jettonMasterAddress, }; return contractAddress(StateInit{code: jettonWalletCode, data: initData.toCell()});}