跳转到内容

可变型代币(Jettons)

本页列出了使用 jettons的常见示例。

接受 jetton 转移

转账通知信息的结构如下

message(0x7362d09c) JettonTransferNotification {
queryId: Int as uint64;
amount: Int as coins;
sender: Address;
forwardPayload: Slice as remaining;
}

使用 receiver 功能接受令牌通知信息。

可使用 jetton 钱包状态初始值和计算 jetton 地址进行验证。 请注意,通知来自您的合约的 jetton 钱包,因此所有者地址栏应使用 myAddress()。 钱包的初始数据布局如下所示,但有时会有所不同。 请注意,“myJettonWalletAddress “也可以存储在合约存储中,以便在每次交易中减少 gas 使用量。

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 转送

要发送 jetton 传输,请使用 send()函数。 请注意,“myJettonWalletAddress” 也可以存储在合约存储中,以便在每次交易中减少 gas 使用量。

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(),
});
}

销毁 jetton

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(),
});
}

USDT jetton 业务

除了 JettonWalletData 将采用以下结构外,USDT(在 TON 上)的操作保持不变:

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()});
}