准备消息
在使用TON Connect时,您应该为在各种交易中使用的Payload构造消息体。在此页面上,您可以找到与TON Connect SDK一起使用的payload的最相关示例。
期望您学习了创建TON Connect连接的基础知识。了解更多请参阅集成手册。
TON Connect JS SDK 示例
交易模板
无论开发者正在解决的任务级别如何,通常都需要使用来自@tonconnect/sdk或@tonconnect/ui的连接器实体。 基于@tonconnect/sdk和@tonconnect/ui创建的示例:
- @tonconnect/ui-react
- @tonconnect/ui
- @tonconnect/sdk
import { useTonConnectUI } from '@tonconnect/ui-react';
const [tonConnectUI] = useTonConnectUI();
const transaction = {
//transaction body
})
export const Settings = () => {
const [tonConnectUI, setOptions] = useTonConnectUI();
return (
<div>
<button onClick={() => tonConnectUI.sendTransaction(transaction)}>
Send transaction
</button>
</div>
);
};
import TonConnectUI from '@tonconnect/ui';
const tonConnectUI = new TonConnectUI({ //连接应用
manifestUrl: 'https://<YOUR_APP_URL>/tonconnect-manifest.json',
buttonRootId: '<YOUR_CONNECT_BUTTON_ANCHOR_ID>'
});
const transaction = {
//transaction body
}
const result = await tonConnectUI.sendTransaction(transaction)
import TonConnect from '@tonconnect/sdk';
const connector = new TonConnect();
await connector.sendTransaction({
//transaction body
})
常规 TON 转账
TON Connect SDK提供了发送消息的封装器,使准备两个钱包之间的Toncoin的常规转账作为默认交易无需载荷变得容易。
使用TON Connect JS SDK执行常规TON转账如下所示:
- @tonconnect/react-ui
- @tonconnect/ui
- @tonconnect/sdk
import { useTonConnectUI } from '@tonconnect/ui-react';
const [tonConnectUI] = useTonConnectUI();
const transaction = {
messages: [
{
address: "0:412410771DA82CBA306A55FA9E0D43C9D245E38133CB58F1457DFB8D5CD8892F", // 目的地址
amount: "20000000" //以nanotons计的Toncoin
}
]
}
export const Settings = () => {
const [tonConnectUI, setOptions] = useTonConnectUI();
return (
<div>
<button onClick={() => tonConnectUI.sendTransaction(transaction)}>
Send transaction
</button>
</div>
);
};
import TonConnectUI from '@tonconnect/ui';
const tonConnectUI = new TonConnectUI({ //连接应用
manifestUrl: 'https://<YOUR_APP_URL>/tonconnect-manifest.json',
buttonRootId: '<YOUR_CONNECT_BUTTON_ANCHOR_ID>'
});
const transaction = {
messages: [
{
address: "0:412410771DA82CBA306A55FA9E0D43C9D245E38133CB58F1457DFB8D5CD8892F", // 目的地址
amount: "20000000" //以nanotons计的Toncoin
}
]
}
const result = await tonConnectUI.sendTransaction(transaction)
import TonConnect from '@tonconnect/sdk';
const connector = new TonConnect();
await connector.sendTransaction({
messages: [
{
address: "0:412410771DA82CBA306A55FA9E0D43C9D245E38133CB58F1457DFB8D5CD8892F", // 目的地址
amount: "20000000" //以nanotons计的Toncoin
}
]
})
了解更多信息请参阅TON智能合约地址。
对于特定的自定义交易,必须定义特定的载荷。
添加评论的转账
最简单的例子是添加一个包含评论的载荷。更多详情请查看此页面。
在交易之前,需要通过@ton/ton JavaScript库准备一个body
cell。
import { beginCell } from '@ton/ton'
const body = beginCell()
.storeUint(0, 32) // 写入32个零位以表示后面将跟随文本评论
.storeStringTail("Hello, TON!") // 写下我们的文本评论
.endCell();
通过以下方式创建交易体:
- @tonconnect/react-ui
- @tonconnect/ui
- @tonconnect/sdk
import { useTonConnectUI } from '@tonconnect/ui-react';
const myTransaction = {
validUntil: Math.floor(Date.now() / 1000) + 360,
messages: [
{
address: destination,
amount: toNano("0.05"),
payload: body.toBoc().toString("base64") // body中带有评论的载荷
}
]
}
export const Settings = () => {
const [tonConnectUI, setOptions] = useTonConnectUI();
return (
<div>
<button onClick={() => tonConnectUI.sendTransaction(myTransaction)}>
Send transaction
</button>
</div>
);
};
import TonConnectUI from '@tonconnect/ui'
const transaction = {
validUntil: Math.floor(Date.now() / 1000) + 360,
messages: [
{
address: destination,
amount: toNano("0.05"),
payload: body.toBoc().toString("base64") // body中带有评论的载荷
}
]
}
const result = await tonConnectUI.sendTransaction(transaction)
import TonConnect from '@tonconnect/sdk';
const connector = new TonConnect();
await connector.sendTransaction({
validUntil: Math.floor(Date.now() / 1000) + 360,
messages: [
{
address: destination,
amount: toNano("0.05"),
payload: body.toBoc().toString("base64") // body中带有评论的载荷
}
]
})
Jetton 转账
根据以下方式进行的 Jetton 转账操作的 body
(TEP-74) 通常应如下所示:
import {beginCell, toNano} from '@ton/ton'
// transfer#0f8a7ea5 query_id:uint64 amount:(VarUInteger 16) destination:MsgAddress
// response_destination:MsgAddress custom_payload:(Maybe ^Cell)
// forward_ton_amount:(VarUInteger 16) forward_payload:(Either Cell ^Cell)
// = InternalMsgBody;
const body = beginCell()
.storeUint(0xf8a7ea5, 32) // jetton 转账操作码
.storeUint(0, 64) // query_id:uint64
.storeCoins(1000000) // amount:(VarUInteger 16) - 转账的 Jetton 金额(小数位 = 6 - jUSDT, 9 - 默认)
.storeAddress(Wallet_DST) // destination:MsgAddress
.storeAddress(Wallet_SRC) // response_destination:MsgAddress
.storeUint(0, 1) // custom_payload:(Maybe ^Cell)
.storeCoins(toNano(0.05)) // forward_ton_amount:(VarUInteger 16)
.storeUInt(0,1) // forward_payload:(Either Cell ^Cell)
.endCell();
然后,将带有此 body 的交易发送到发送者的 jettonWalletContract 执行:
- @tonconnect/react-ui
- @tonconnect/ui
- @tonconnect/sdk
import { useTonConnectUI } from '@tonconnect/ui-react';
const myTransaction = {
validUntil: Math.floor(Date.now() / 1000) + 360,
messages: [
{
address: jettonWalletContract, // 发送方 Jetton 钱包
amount: toNano("0.05"), // 用于手续费,超额部分将被退回
payload: body.toBoc().toString("base64") // 带有 Jetton 转账 body 的载荷
}
]
}
export const Settings = () => {
const [tonConnectUI, setOptions] = useTonConnectUI();
return (
<div>
<button onClick={() => tonConnectUI.sendTransaction(myTransaction)}>
Send transaction
</button>
</div>
);
};
import TonConnectUI from '@tonconnect/ui'
const transaction = {
validUntil: Math.floor(Date.now() / 1000) + 360,
messages: [
{
address: jettonWalletContract, // 发送方 Jetton 钱包
amount: toNano("0.05"), // 用于手续费,超额部分将被退回
payload: body.toBoc().toString("base64") // 带有 Jetton 转账 body 的载荷
}
]
}
const result = await tonConnectUI.sendTransaction(transaction)
import TonConnect from '@tonconnect/sdk';
const connector = new TonConnect();
//...
await connector.sendTransaction({
validUntil: Math.floor(Date.now() / 1000) + 360,
messages: [
{
address: jettonWalletContract, // 发送方 Jetton 钱包
amount: toNano("0.05"), // 用于手续费,超额部分将被退回
payload: body.toBoc().toString("base64") // 带有 Jetton 转账 body 的载荷
}
]
})
validUntil
- 消息有效的 UNIX 时间jettonWalletAddress
- 地址,基于 JettonMaser 和 Wallet 合约定义的 JettonWallet 地址balance
- 整数,用于gas费用的 Toncoin 金额,以 nanotons 计。body
- 用于 jettonContract 的载荷
Jetton 钱包状态初始化和地址准备示例
import { Address, TonClient, beginCell, StateInit, storeStateInit } from '@ton/ton'
async function main() {
const client = new TonClient({
endpoint: 'https://toncenter.com/api/v2/jsonRPC',
apiKey: '放置你的 api key'
})
const jettonWalletAddress = Address.parse('Sender_Jetton_Wallet');
let jettonWalletDataResult = await client.runMethod(jettonWalletAddress, 'get_wallet_data');
jettonWalletDataResult.stack.readNumber();
const ownerAddress = jettonWalletDataResult.stack.readAddress();
const jettonMasterAddress = jettonWalletDataResult.stack.readAddress();
const jettonCode = jettonWalletDataResult.stack.readCell();
const jettonData = beginCell()
.storeCoins(0)
.storeAddress(ownerAddress)
.storeAddress(jettonMasterAddress)
.storeRef(jettonCode)
.endCell();
const stateInit: StateInit = {
code: jettonCode,
data: jettonData
}
const stateInitCell = beginCell()
.store(storeStateInit(stateInit))
.endCell();
console.log(new Address(0, stateInitCell.hash()));
}
Jetton 销毁
Jetton 销毁(TEP-74) 的body
通常应该按照以下方式完成:
import {beginCell} from '@ton/ton'
// burn#595f07bc query_id:uint64 amount:(VarUInteger 16)
// response_destination:MsgAddress custom_payload:(Maybe ^Cell)
// = InternalMsgBody;
const body = beginCell()
.storeUint(0x595f07bc, 32) // jetton 销毁操作码
.storeUint(0, 64) // query_id:uint64
.storeCoins(1000000) // amount:(VarUInteger 16) - 以小数形式的 Jetton 金额
.storeAddress(Wallet_SRC) // response_destination:MsgAddress - 持有者的钱包
.storeUint(0, 1) // custom_payload:(Maybe ^Cell) - 通常没有载荷
.endCell();
消息放入以下请求中:
- @tonconnect/react-ui
- @tonconnect/ui
- @tonconnect/sdk
import { useTonConnectUI } from '@tonconnect/ui-react';
const myTransaction = {
validUntil: Math.floor(Date.now() / 1000) + 360,
messages: [
{
address: jettonWalletContract, // 持有者的 Jetton 钱包
amount: toNano("0.05"), // 用于手续费,超额部分将被退回
payload: body.toBoc().toString("base64") // 带有 Jetton 销毁 body 的载荷
}
]
}
export const Settings = () => {
const [tonConnectUI, setOptions] = useTonConnectUI();
return (
<div>
<button onClick={() => tonConnectUI.sendTransaction(myTransaction)}>
Send transaction
</button>
</div>
);
};
import TonConnectUI from '@tonconnect/ui'
const transaction = {
validUntil: Math.floor(Date.now() / 1000) + 360,
messages: [
{
address: jettonWalletContract, // 持有者的 Jetton 钱包
amount: toNano("0.05"), // 用于手续费,超额部分将被退回
payload: body.toBoc().toString("base64") // 带有 Jetton 销毁 body 的载荷
}
]
}
const result = await tonConnectUI.sendTransaction(transaction)
await connector.sendTransaction({
validUntil: Math.floor(Date.now() / 1000) + 360,
messages: [
{
address: jettonWalletContract, // 持有者的 Jetton 钱包
amount: toNano("0.05"), // 用于手续费,超额部分将被退回
payload: body.toBoc().toString("base64") // 带有 Jetton 销毁 body 的载荷
}
]
})
jettonWalletAddress
- Jetton 钱包合约地址,基于 JettonMaser 和 Wallet 合约定义amount
- 整数,用于gas费用的 Toncoin 金额,以 nanotons 计。body
- 带有burn#595f07bc
操作码的 Jetton 钱包载荷
NFT 转移
body
消息通常应按照以下方式进行:
import { beginCell, toNano} from '@ton/ton'
// transfer#5fcc3d14 query_id:uint64 new_owner:MsgAddress response_destination:MsgAddress custom_payload:(Maybe ^Cell)
// forward_amount:(VarUInteger 16) forward_payload:(Either Cell ^Cell) = InternalMsgBody;
const body = beginCell()
.storeUint(0x5fcc3d14, 32) // NFT 转移操作码 0x5fcc3d14
.storeUint(0, 64) // query_id:uint64
.storeAddress(NEW_OWNER_WALLET) // new_owner:MsgAddress
.storeAddress(Wallet_DST) // response_destination:MsgAddress
.storeUint(0, 1) // custom_payload:(Maybe ^Cell)
.storeCoins(toNano('0.000000001')) // forward_amount:(VarUInteger 16)
.storeUint(0,1) // forward_payload:(Either Cell ^Cell)
.endCell();
WALLET_DST
- 地址 - 初始 NFT 持有者地址,用于接收超额资金
将 NFTitem
转移给新所有者 NEW_OWNER_WALLET
。
- @tonconnect/react-ui
- @tonconnect/ui
- @tonconnect/sdk
import { useTonConnectUI } from '@tonconnect/ui-react';
const myTransaction = {
validUntil: Math.floor(Date.now() / 1000) + 360,
messages: [
{
address: jettonWalletContract, // 将要转移的 NFT 物品地址
amount: toNano("0.05"), // 用于佣金费,超额部分将被返回
payload: body.toBoc().toString("base64") // 带有 NFT 转移 body 的 payload
}
]
}
export const Settings = () => {
const [tonConnectUI, setOptions] = useTonConnectUI();
return (
<div>
<button onClick={() => tonConnectUI.sendTransaction(myTransaction)}>
Send transaction
</button>
</div>
);
};
import TonConnectUI from '@tonconnect/ui'
const transaction = {
validUntil: Math.floor(Date.now() / 1000) + 360,
messages: [
{
address: NFTitem, // 将要转移的 NFT 物品地址
amount: toNano("1.08"), // 用于佣金费,超额部分将被返回
payload: transferNftBody.toBoc().toString("base64") // 带有 transferNftBody 消息的 payload
}
]
}
const result = await tonConnectUI.sendTransaction(transaction)
await connector.sendTransaction({
validUntil: Math.floor(Date.now() / 1000) + 360,
messages: [
{
address: NFTitem, // 将要转移的 NFT 物品地址
amount: toNano("1.08"), // 用于佣金费,超额部分将被返回
payload: transferNftBody.toBoc().toString("base64") // 带有 transferNftBody 消息的 payload
}
]
})
NFTitem
- 地址 - 我们希望转移到新所有者NEW_OWNER_Wallet
的NFT项目智能合约的地址。balance
- 整数,用于gas支付的 Toncoin 数量(单位是nanotons)。body
- 用于 NFT 合约的载荷
NFT 销售(GetGems)
以下是根据合约nft-fixprice-sale-v3r2准备消息和交易以在GetGems市场上进行销售的示例。
要将 NFT 放置在 GetGems 销售合约上,我们应该准备特殊消息体 transferNftBody
,它将 NFT 转移到特殊的 NFT 销售合约。
const transferNftBody = beginCell()
.storeUint(0x5fcc3d14, 32) // NFT 转移操作码
.storeUint(0, 64) // query_id
.storeAddress(destinationAddress) // new_owner - GetGems 销售合约部署者,此操作不应更改
.storeAddress(walletAddress) // 超额资金的响应目的地
.storeBit(0) // 我们没有 custom_payload
.storeCoins(toNano("1")) // forward_amount
.storeBit(0) // 我们在此cell中存储 forward_payload
.storeUint(0x0fe0ede, 31) // 非 32,因为之前存储的 0 位将作为销售操作码读取
.storeRef(stateInitCell)
.storeRef(saleBody)
.endCell();
因为消息需要很多步骤,整个算法庞大,可以在此处找到:
显示创建 NFT 销售消息体的整个算法
import { Address, beginCell, StateInit, storeStateInit, toNano, Cell } from '@ton/ton'
async function main() {
const fixPriceV3R2Code = Cell.fromBase64('te6cckECCwEAArkAART/APSkE/S88sgLAQIBIAIDAgFIBAUAfvIw7UTQ0wDTH/pA+kD6QPoA1NMAMMABjh34AHAHyMsAFssfUATPFljPFgHPFgH6AszLAMntVOBfB4IA//7y8AICzQYHAFegOFnaiaGmAaY/9IH0gfSB9AGppgBgYaH0gfQB9IH0AGEEIIySsKAVgAKrAQH30A6GmBgLjYSS+CcH0gGHaiaGmAaY/9IH0gfSB9AGppgBgYOCmE44BgAEqYhOmPhW8Q4YBKGATpn8cIxbMbC3MbK2QV44LJOZlvKAVxFWAAyS+G8BJrpOEBFcCBFd0VYACRWdjYKdxjgthOjq+G6hhoaYPqGAD9gHAU4ADAgB92YIQO5rKAFJgoFIwvvLhwiTQ+kD6APpA+gAwU5KhIaFQh6EWoFKQcIAQyMsFUAPPFgH6AstqyXH7ACXCACXXScICsI4XUEVwgBDIywVQA88WAfoCy2rJcfsAECOSNDTiWnCAEMjLBVADzxYB+gLLaslx+wBwIIIQX8w9FIKAejy0ZSzjkIxMzk5U1LHBZJfCeBRUccF8uH0ghAFE42RFrry4fUD+kAwRlAQNFlwB8jLABbLH1AEzxZYzxYBzxYB+gLMywDJ7VTgMDcowAPjAijAAJw2NxA4R2UUQzBw8AXgCMACmFVEECQQI/AF4F8KhA/y8AkA1Dg5ghA7msoAGL7y4clTRscFUVLHBRWx8uHKcCCCEF/MPRQhgBDIywUozxYh+gLLassfFcs/J88WJ88WFMoAI/oCE8oAyYMG+wBxUGZFFQRwB8jLABbLH1AEzxZYzxYBzxYB+gLMywDJ7VQAlsjLHxPLPyPPFlADzxbKAIIJycOA+gLKAMlxgBjIywUmzxZw+gLLaszJgwb7AHFVUHAHyMsAFssfUATPFljPFgHPFgH6AszLAMntVNZeZYk=');
const marketplaceAddress = Address.parse('EQBYTuYbLf8INxFtD8tQeNk5ZLy-nAX9ahQbG_yl1qQ-GEMS'); // GetGems 地址
const marketplaceFeeAddress = Address.parse('EQCjk1hh952vWaE9bRguFkAhDAL5jj3xj9p0uPWrFBq_GEMS'); // GetGems 收费地址
const destinationAddress = Address.parse("EQAIFunALREOeQ99syMbO6sSzM_Fa1RsPD5TBoS0qVeKQ-AR"); // GetGems 销售合约部署者
const walletAddress = Address.parse('EQArLGBnGPvkxaJE57Y6oS4rwzDWuOE8l8_sghntXLkIt162');
const royaltyAddress = Address.parse('EQArLGBnGPvkxaJE57Y6oS4rwzDWuOE8l8_sghntXLkIt162');
const nftAddress = Address.parse('EQCUWoe7hLlklVxH8gduCf45vPNocsjRP4wbX42UJ0Ja0S2f');
const price = toNano('5'); // 5 TON
const feesData = beginCell()
.storeAddress(marketplaceFeeAddress)
// 5% - GetGems 收费
.storeCoins(price / BigInt(100) * BigInt(5))
.storeAddress(royaltyAddress)
// 5% - 版权费,可更改
.storeCoins(price / BigInt(100) * BigInt(5))
.endCell();
const saleData = beginCell()
.storeBit(0) // is_complete
.storeUint(Math.round(Date.now() / 1000), 32) // created_at
.storeAddress(marketplaceAddress) // marketplace_address
.storeAddress(nftAddress) // nft_address
.storeAddress(walletAddress) // previous_owner_address
.storeCoins(price) // 以nanotons计的全价
.storeRef(feesData) // fees_cell
.storeBit(0) // can_be_deployed_externally
.endCell();
const stateInit: StateInit = {
code: fixPriceV3R2Code,
data: saleData
};
const stateInitCell = beginCell()
.store(storeStateInit(stateInit))
.endCell();
// 仅示例,非必需
const saleContractAddress = new Address(0, stateInitCell.hash());
const saleBody = beginCell()
.storeUint(1, 32) // 只是接收硬币
.storeUint(0, 64)
.endCell();
const transferNftBody = beginCell()
.storeUint(0x5fcc3d14, 32) // NFT 转移操作码
.storeUint(0, 64) // query_id
.storeAddress(destinationAddress) // new_owner
.storeAddress(walletAddress) // 超额资金的响应目的地
.storeBit(0) // 我们没有 custom_payload
.storeCoins(toNano("1")) // forward_amount
.storeBit(0) // 我们在此cell中存储 forward_payload
// 非 32,因为我们存储了 0 位 | 部署者的销售操作码
.storeUint(0x0fe0ede, 31)
.storeRef(stateInitCell)
.storeRef(saleBody)
.endCell();
准备好的 transferNftBody
应发送到 NFT 物品合约,至少需要 1.08
TON,以成功处理。多余的部分将退还给发件人钱包。
- @tonconnect/react-ui
- @tonconnect/ui
- @tonconnect/sdk
import { useTonConnectUI } from '@tonconnect/ui-react';
const myTransaction = {
validUntil: Math.floor(Date.now() / 1000) + 360,
messages: [
{
address: NFTitem, // NFT 物品合约地址,应该放置于市场上
amount: toNano("1.08"), // 需要的gas费金额,多余的部分将返回
payload: transferNftBody.toBoc().toString("base64") // 带有 transferNftBody 消息的 payload
}
]
}
export const Settings = () => {
const [tonConnectUI, setOptions] = useTonConnectUI();
return (
<div>
<button onClick={() => tonConnectUI.sendTransaction(myTransaction)}>
Send transaction
</button>
</div>
);
};
import TonConnectUI from '@tonconnect/ui'
const transaction = {
validUntil: Math.floor(Date.now() / 1000) + 360,
messages: [
{
address: NFTitem, // NFT 物品合约地址,应该放置于市场上
amount: toNano("1.08"), // 需要的gas费金额,多余的部分将返回
payload: transferNftBody.toBoc().toString("base64") // 带有 transferNftBody 消息的 payload
}
]
}
const result = await tonConnectUI.sendTransaction(transaction)
await connector.sendTransaction({
validUntil: Math.floor(Date.now() / 1000) + 360,
messages: [
{
address: NFTitem, // NFT 物品合约地址,应该放置于市场上
amount: toNano("1.08"), // 需要的gas费金额,多余的部分将返回
payload: transferNftBody.toBoc().toString("base64") // 带有 transferNftBody 消息的 payload
}
]
})
NFT 购买 (GetGems)
购买 nft-fixprice-sale-v3r2 销售合约的 NFT 的过程可以通过常规转账进行,无需负荷,唯一重要的是准确的 TON 数量,按如下计算:
buyAmount = Nftprice TON + 1.0 TON
。
- @tonconnect/react-ui
- @tonconnect/ui
- @tonconnect/sdk
import { useTonConnectUI } from '@tonconnect/ui-react';
const myTransaction = {
validUntil: Math.floor(Date.now() / 1000) + 360,
messages: [
{
address: nftSaleContract, // 当前希望购买的 NFT 销售合约地址
amount: toNano(buyAmount), // NFT 价格 + 1 TON, 多余的会被返回
}
]
}
export const Settings = () => {
const [tonConnectUI, setOptions] = useTonConnectUI();
return (
<div>
<button onClick={() => tonConnectUI.sendTransaction(myTransaction)}>
Send transaction
</button>
</div>
);
};
import TonConnectUI from '@tonconnect/ui'
const transaction = {
validUntil: Math.floor(Date.now() / 1000) + 360,
messages: [
{
address: nftSaleContract, // 当前希望购买的 NFT 销售合约地址
amount: toNano(buyAmount), // NFT 价格 + 1 TON, 多余的会被返回
}
]
}
const result = await tonConnectUI.sendTransaction(transaction)
await connector.sendTransaction({
validUntil: Math.floor(Date.now() / 1000) + 360,
messages: [
{
address: nftSaleContract, // 当前希望购买的 NFT 销售合约地址
amount: toNano(buyAmount), // NFT 价格 + 1 TON, 多余的会被返回
}
]
})
TON Connect Python SDK
Python 示例使用 PyTonConnect 和 pytoniq。
from pytoniq_core import Address
from pytonconnect import TonConnect
阅读示例 源码。
常规 TON 转账
connector = TonConnect(
manifest_url='https://raw.githubusercontent.com/XaBbl4/pytonconnect/main/pytonconnect-manifest.json')
is_connected = await connector.restore_connection()
transaction = {
'valid_until': int(time.time() + 3600),
'messages': [
'address' :'0:0000000000000000000000000000000000000000000000000000000000000000', # 目的地址
'amount' : 1000000000, # 1 TON,数额应以nanocoins计
)
]
}
附带评论的转账
首先,通过以下函数实现带有评论的消息:
def get_comment_message(destination_address: str, amount: int, comment: str) -> dict:
data = {
'address': destination_address,
'amount': str(amount),
'payload': urlsafe_b64encode(
begin_cell()
.store_uint(0, 32) # 评论消息的操作码
.store_string(comment) # 储存评论
.end_cell() # 结束 cell
.to_boc() # 转换成 boc
)
.decode() # 编码成 url 安全的 base64
}
return data
带有评论的转账的最终交易体:
transaction = {
'valid_until': int(time.time() + 3600),
'messages': [
get_comment_message(
destination_address='0:0000000000000000000000000000000000000000000000000000000000000000',
amount=int(0.01 * 10**9), # 数额应以纳币指定
comment='hello world!'
)
]
}
了解更多关于 TON 智能合约地址。
Jetton 转账
构建 jetton 转账交易的函数示例:
from pytoniq_core import begin_cell
from base64 import urlsafe_b64encode
def get_jetton_transfer_message(jetton_wallet_address: str, recipient_address: str, transfer_fee: int, jettons_amount: int, response_address: str = None) -> dict:
data = {
'address': jetton_wallet_address,
'amount': str(transfer_fee),
'payload': urlsafe_b64encode(
begin_cell()
.store_uint(0xf8a7ea5, 32) # jetton 转账消息的操作码
.store_uint(0, 64) # query_id
.store_coins(jettons_amount)
.store_address(recipient_address) # 目的地址
.store_address(response_address or recipient_address) # 超额资金发送到的地址
.store_uint(0, 1) # 自定义负载
.store_coins(1) # 转发金额
.store_uint(0, 1) # 转发负载
.end_cell() # 结束 cell
.to_boc() # 转换成 boc
)
.decode() # 编码成 url 安全的 base64
}
return data
最终的交易体:
transaction = {
'valid_until': int(time.time() + 3600),
'messages': [
get_jetton_transfer_message(
jetton_wallet_address='EQCXsVvdxTVmSIvYv4tTQoQ-0Yq9mERGTKfbsIhedbN5vTVV',
recipient_address='0:0000000000000000000000000000000000000000000000000000000000000000',
transfer_fee=int(0.07 * 10**9),
jettons_amount=int(0.01 * 10**9), # 将jetton十进制数替换为9。例如对于 jUSDT 应该是 (amount * 10**6),
response_address=wallet_address
),
]
}
Jetton 销毁
构建 jetton 销毁交易的函数示例:
from pytoniq_core import begin_cell
from base64 import urlsafe_b64encode
def get_jetton_burn_message(jetton_wallet_address: str, transfer_fee: int, jettons_amount: int, response_address: str = None) -> dict:
data = {
'address': jetton_wallet_address,
'amount': str(transfer_fee),
'payload': urlsafe_b64encode(
begin_cell()
.store_uint(0x595f07bc, 32) # jetton 转账消息的操作码
.store_uint(0, 64) # query_id
.store_coins(jettons_amount)
.store_address(response_address) # # 超额资金发送到的地址
.end_cell() # 结束 cell
.to_boc() # 转换成 boc
)
.decode() # 编码成 url 安全的 base64
}
return data
最终的交易体:
transaction = {
'valid_until': int(time.time() + 3600),
'messages': [
get_jetton_burn_message(
jetton_wallet_address='EQCXsVvdxTVmSIvYv4tTQoQ-0Yq9mERGTKfbsIhedbN5vTVV',
transfer_fee=int(0.07 * 10 ** 9),
jettons_amount=int(0.01 * 10 ** 9), # 将jetton十进制数替换为9。例如对于 jUSDT 应该是 (amount * 10**6),
response_address=wallet_address
),
]
}
NFT 转账
NFT 转账交易函数的示例:
from pytoniq_core import begin_cell
from base64 import urlsafe_b64encode
def get_nft_transfer_message(nft_address: str, recipient_address: str, transfer_fee: int, response_address: str = None) -> dict:
data = {
'address': nft_address,
'amount': str(transfer_fee),
'payload': urlsafe_b64encode(
begin_cell()
.store_uint(0x5fcc3d14, 32) # nft 转账消息的操作码
.store_uint(0, 64) # query_id
.store_address(recipient_address) # 新主人
.store_address(response_address or recipient_address) # 超额资金发送到的地址
.store_uint(0, 1) # custom payload
.store_coins(1) # forward amount
.store_uint(0, 1) # forward payload
.end_cell() # 结束 cell
.to_boc() # 转换成 boc
)
.decode() # 编码成 url 安全的 base64
}
return data
最终的交易体:
transaction = {
'valid_until': int(time.time() + 3600),
'messages': [
get_nft_transfer_message(
nft_address='EQDrA-3zsJXTfGo_Vdzg8d07Da4vSdHZllc6W9qvoNoMstF-',
recipient_address='0:0000000000000000000000000000000000000000000000000000000000000000',
transfer_fee=int(0.07 * 10**9),
response_address=wallet_address
),
]
}
NFT 销售 (GetGems)
以下是在 GetGems 市场上进行销售时准备消息和交易的示例,根据合约 nft-fixprice-sale-v3r2。
为了将 NFT 放置在 GetGems 销售合约上,我们应该准备特殊的消息体 transferNftBody
,该消息体将 NFT 转移给特殊的 NFT 销售合约。
创建 NFT NFT Sale Body的示例
import time
from base64 import urlsafe_b64encode
from pytoniq_core.boc import Cell, begin_cell, Address
from pytoniq_core.tlb import StateInit
def get_sale_body(wallet_address: str, royalty_address: str, nft_address: str, price: int, amount: int):
# 合约代码
nft_sale_code_cell = Cell.one_from_boc('te6cckECCwEAArkAART/APSkE/S88sgLAQIBIAIDAgFIBAUAfvIw7UTQ0wDTH/pA+kD6QPoA1NMAMMABjh34AHAHyMsAFssfUATPFljPFgHPFgH6AszLAMntVOBfB4IA//7y8AICzQYHAFegOFnaiaGmAaY/9IH0gfSB9AGppgBgYaH0gfQB9IH0AGEEIIySsKAVgAKrAQH30A6GmBgLjYSS+CcH0gGHaiaGmAaY/9IH0gfSB9AGppgBgYOCmE44BgAEqYhOmPhW8Q4YBKGATpn8cIxbMbC3MbK2QV44LJOZlvKAVxFWAAyS+G8BJrpOEBFcCBFd0VYACRWdjYKdxjgthOjq+G6hhoaYPqGAD9gHAU4ADAgB92YIQO5rKAFJgoFIwvvLhwiTQ+kD6APpA+gAwU5KhIaFQh6EWoFKQcIAQyMsFUAPPFgH6AstqyXH7ACXCACXXScICsI4XUEVwgBDIywVQA88WAfoCy2rJcfsAECOSNDTiWnCAEMjLBVADzxYB+gLLaslx+wBwIIIQX8w9FIKAejy0ZSzjkIxMzk5U1LHBZJfCeBRUccF8uH0ghAFE42RFrry4fUD+kAwRlAQNFlwB8jLABbLH1AEzxZYzxYBzxYB+gLMywDJ7VTgMDcowAPjAijAAJw2NxA4R2UUQzBw8AXgCMACmFVEECQQI/AF4F8KhA/y8AkA1Dg5ghA7msoAGL7y4clTRscFUVLHBRWx8uHKcCCCEF/MPRQhgBDIywUozxYh+gLLassfFcs/J88WJ88WFMoAI/oCE8oAyYMG+wBxUGZFFQRwB8jLABbLH1AEzxZYzxYBzxYB+gLMywDJ7VQAlsjLHxPLPyPPFlADzxbKAIIJycOA+gLKAMlxgBjIywUmzxZw+gLLaszJgwb7AHFVUHAHyMsAFssfUATPFljPFgHPFgH6AszLAMntVNZeZYk=')
# 费用cell
marketplace_address = Address('EQBYTuYbLf8INxFtD8tQeNk5ZLy-nAX9ahQbG_yl1qQ-GEMS')
marketplace_fee_address = Address('EQCjk1hh952vWaE9bRguFkAhDAL5jj3xj9p0uPWrFBq_GEMS')
destination_address = Address('EQAIFunALREOeQ99syMbO6sSzM_Fa1RsPD5TBoS0qVeKQ-AR')
wallet_address = Address(wallet_address)
royalty_address = Address(royalty_address)
nft_address = Address(nft_address)
marketplace_fee = int(price * 5 / 100) # 5%
royalty_fee = int(price * 5 / 100) # 5%
fees_data_cell = (begin_cell()
.store_address(marketplace_fee_address)
.store_coins(marketplace_fee)
.store_address(royalty_address)
.store_coins(royalty_fee)
.end_cell())
sale_data_cell = (begin_cell()
.store_bit_int(0)
.store_uint(int(time.time()), 32)
.store_address(marketplace_address)
.store_address(nft_address)
.store_address(wallet_address)
.store_coins(price)
.store_ref(fees_data_cell)
.store_bit_int(0)
.end_cell())
state_init_cell = StateInit(code=nft_sale_code_cell, data=sale_data_cell).serialize()
sale_body = (begin_cell()
.store_uint(1, 32)
.store_uint(0, 64)
.end_cell())
transfer_nft_body = (begin_cell()
.store_uint(0x5fcc3d14, 32)
.store_uint(0, 64)
.store_address(destination_address)
.store_address(wallet_address)
.store_bit_int(0)
.store_coins(int(1 * 10**9))
.store_bit_int(0)
.store_uint(0x0fe0ede, 31)
.store_ref(state_init_cell)
.store_ref(sale_body)
.end_cell())
data = {
'address': nft_address.to_str(),
'amount': str(amount),
'payload': urlsafe_b64encode(transfer_nft_body.to_boc()).decode()
}
return data
最终交易体:
transaction = {
'valid_until': int(time.time() + 3600),
'messages': [
get_nft_transfer_message(
nft_address='EQDrA-3zsJXTfGo_Vdzg8d07Da4vSdHZllc6W9qvoNoMstF-',
recipient_address='0:0000000000000000000000000000000000000000000000000000000000000000',
transfer_fee=int(0.07 * 10**9),
response_address=wallet_address
),
]
}
NFT 购买 (GetGems)
使用 nft-fixprice-sale-v3r2 销售合约购买 NFT 的过程可以通过不含有效负载的常规转账进行,唯一重要的是准确的 TON 数额,计算方式如下:
buyAmount = Nftprice TON + 1.0 TON
。
transaction = {
'valid_until': int(time.time() + 3600),
'messages': [
{
'address': nft_address,
'amount': buyAmount,
]
}