메시지 준비
TON Connect를 사용하는 동안 다양한 트랜잭션에 사용되는 페이로드에 대한 메시지 본문을 구성해야 합니다. 이 페이지에서 TON Connect SDK와 함께 사용할 수 있는 페이로드의 가장 적절한 예시를 확인할 수 있습니다.
TON 커넥트 연동 생성에 대한 기본 사항을 학습하는 것이 좋습니다. 연동 매뉴얼](/개발/앱/톤커넥트/연동)을 통해 자세히 알아보세요.
TON Connect JS SDK 예제
트랜잭션 템플릿
개발자가 해결하는 작업의 수준에 관계없이 일반적으로 @tonconnect/sdk 또는 @tonconnect/ui의 커넥터 엔티티를 사용해야 합니다. 톤커넥트/sdk 및 톤커넥트/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({ //connect application
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 전송
톤 커넥트 SDK에는 메시지 전송을 위한 래퍼가 포함되어 있어 페이로드 없이 두 지갑 간 톤코인 정기 송금을 기본 트랜잭션으로 쉽게 준비할 수 있습니다.
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", // destination address
amount: "20000000" //Toncoin in nanotons
}
]
}
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({ //connect application
manifestUrl: 'https://<YOUR_APP_URL>/tonconnect-manifest.json',
buttonRootId: '<YOUR_CONNECT_BUTTON_ANCHOR_ID>'
});
const transaction = {
messages: [
{
address: "0:412410771DA82CBA306A55FA9E0D43C9D245E38133CB58F1457DFB8D5CD8892F", // destination address
amount: "20000000" //Toncoin in nanotons
}
]
}
const result = await tonConnectUI.sendTransaction(transaction)
import TonConnect from '@tonconnect/sdk';
const connector = new TonConnect();
await connector.sendTransaction({
messages: [
{
address: "0:412410771DA82CBA306A55FA9E0D43C9D245E38133CB58F1457DFB8D5CD8892F", // destination address
amount: "20000000" //Toncoin in nanotons
}
]
})
TON 스마트 컨트랙트 주소]에 대해 자세히 알아보세요(/학습/개요/주소).
특정 사용자 지정 트랜잭션의 경우 특정 페이로드를 정의해야 합니다.
댓글로 전송하기
가장 간단한 예는 댓글과 함께 페이로드를 추가하는 것입니다. 자세한 내용은 이 페이지를 참조하세요. 트랜잭션 전에 @ton/ton 자바스크립트 라이브러리를 통해 'body'셀을 준비해야 합니다.
import { beginCell } from '@ton/ton'
const body = beginCell()
.storeUint(0, 32) // write 32 zero bits to indicate that a text comment will follow
.storeStringTail("Hello, TON!") // write our text comment
.endCell();
트랜잭션 본문은 다음과 같이 생성됩니다:
- @tonconnect/react-ui
- @tonconnect/ui
- @tonconnect/sdk
import { useTonConnectUI } from '@tonconnect/ui-react';
import { toNano } from '@ton/ton'
const myTransaction = {
validUntil: Math.floor(Date.now() / 1000) + 360,
messages: [
{
address: destination,
amount: toNano(0.05).toString(),
payload: body.toBoc().toString("base64") // payload with comment in body
}
]
}
export const Settings = () => {
const [tonConnectUI, setOptions] = useTonConnectUI();
return (
<div>
<button onClick={() => tonConnectUI.sendTransaction(myTransaction)}>
Send transaction
</button>
</div>
);
};
import TonConnectUI from '@tonconnect/ui'
import { toNano } from '@ton/ton'
const transaction = {
validUntil: Math.floor(Date.now() / 1000) + 360,
messages: [
{
address: destination,
amount: toNano(0.05).toString(),
payload: body.toBoc().toString("base64") // payload with comment in body
}
]
}
const result = await tonConnectUI.sendTransaction(transaction)
import TonConnect from '@tonconnect/sdk';
import { toNano } from '@ton/ton'
const connector = new TonConnect();
await connector.sendTransaction({
validUntil: Math.floor(Date.now() / 1000) + 360,
messages: [
{
address: destination,
amount: toNano(0.05).toString(),
payload: body.toBoc().toString("base64") // payload with comment in body
}
]
})
제튼 전송
제톤 전송(TEP-74의 body
는 일반적으로 다음 방법에 따라 수행해야 합니다:
import { beginCell, toNano, Address } 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 transfer op code
.storeUint(0, 64) // query_id:uint64
.storeCoins(1000000) // amount:(VarUInteger 16) - Jetton amount for transfer (decimals = 6 - jUSDT, 9 - default)
.storeAddress(Address.parse(Wallet_DST)) // destination:MsgAddress
.storeAddress(Address.parse(Wallet_SRC)) // response_destination:MsgAddress
.storeUint(0, 1) // custom_payload:(Maybe ^Cell)
.storeCoins(toNano(0.05)) // forward_ton_amount:(VarUInteger 16) - if >0, will send notification message
.storeUint(0,1) // forward_payload:(Either Cell ^Cell)
.endCell();
다음으로, 이 본문이 포함된 트랜잭션을 발신자의 jettonWalletContract 실행으로 전송합니다:
- @tonconnect/react-ui
- @tonconnect/ui
- @tonconnect/sdk
import { useTonConnectUI } from '@tonconnect/ui-react';
import { toNano } from '@ton/ton'
const myTransaction = {
validUntil: Math.floor(Date.now() / 1000) + 360,
messages: [
{
address: jettonWalletContract, // sender jetton wallet
amount: toNano(0.05).toString(), // for commission fees, excess will be returned
payload: body.toBoc().toString("base64") // payload with jetton transfer body
}
]
}
export const Settings = () => {
const [tonConnectUI, setOptions] = useTonConnectUI();
return (
<div>
<button onClick={() => tonConnectUI.sendTransaction(myTransaction)}>
Send transaction
</button>
</div>
);
};
import TonConnectUI from '@tonconnect/ui'
import { toNano } from '@ton/ton'
const transaction = {
validUntil: Math.floor(Date.now() / 1000) + 360,
messages: [
{
address: jettonWalletContract, // sender jetton wallet
amount: toNano(0.05).toString(), // for commission fees, excess will be returned
payload: body.toBoc().toString("base64") // payload with jetton transfer body
}
]
}
const result = await tonConnectUI.sendTransaction(transaction)
import TonConnect from '@tonconnect/sdk';
import { toNano } from '@ton/ton'
const connector = new TonConnect();
//...
await connector.sendTransaction({
validUntil: Math.floor(Date.now() / 1000) + 360,
messages: [
{
address: jettonWalletContract, // sender jetton wallet
amount: toNano(0.05).toString(), // for commission fees, excess will be returned
payload: body.toBoc().toString("base64") // payload with jetton transfer body
}
]
})
- validUntil` - 메시지가 유효할 때까지의 UNIX 시간
- '젯튼월렛주소` - 젯튼마저와 월렛 컨트랙트를 기반으로 정의된 주소, 젯튼월렛 주소입니다.
- '잔액' - 나노톤 단위의 가스 결제를 위한 톤코인 금액, 정수입니다.
body
- jettonContract의 페이로드
제튼 월렛 상태 초기화 및 주소 준비 예시
import { Address, TonClient, beginCell, StateInit, storeStateInit } from '@ton/ton'
async function main() {
const client = new TonClient({
endpoint: 'https://toncenter.com/api/v2/jsonRPC',
apiKey: 'put your 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()));
}
댓글이 있는 제톤 전송
제톤 전송(TEP-74의 messageBody
는 일반 전송 body
직렬화 코멘트에 추가로 코멘트를 추가하고 이를 forwardPayload
에 패킹해야 합니다:
import { beginCell, toNano, Address } 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 destinationAddress = Address.parse('put destination wallet address');
const forwardPayload = beginCell()
.storeUint(0, 32) // 0 opcode means we have a comment
.storeStringTail('Hello, TON!')
.endCell();
const body = beginCell()
.storeUint(0x0f8a7ea5, 32) // opcode for jetton transfer
.storeUint(0, 64) // query id
.storeCoins(toNano(5)) // jetton amount, amount * 10^9
.storeAddress(destinationAddress) // TON wallet destination address
.storeAddress(destinationAddress) // response excess destination
.storeBit(0) // no custom payload
.storeCoins(toNano(0.02).toString()) // forward amount (if >0, will send notification message)
.storeBit(1) // we store forwardPayload as a reference
.storeRef(forwardPayload)
.endCell();
다음으로, 이 본문이 포함된 트랜잭션을 발신자의 jettonWalletContract 실행으로 전송합니다:
- @tonconnect/react-ui
- @tonconnect/ui
- @tonconnect/sdk
import { useTonConnectUI } from '@tonconnect/ui-react';
import { toNano } from '@ton/ton'
const jettonWalletContract = Address.parse('put your jetton wallet address');
const myTransaction = {
validUntil: Math.floor(Date.now() / 1000) + 360,
messages: [
{
address: jettonWalletContract, // sender jetton wallet
amount: toNano(0.05).toString(), // for commission fees, excess will be returned
payload: body.toBoc().toString("base64") // payload with jetton transfer and comment body
}
]
}
export const Settings = () => {
const [tonConnectUI, setOptions] = useTonConnectUI();
return (
<div>
<button onClick={() => tonConnectUI.sendTransaction(myTransaction)}>
Send transaction
</button>
</div>
);
};
import TonConnectUI from '@tonconnect/ui'
import { toNano } from '@ton/ton'
const transaction = {
validUntil: Math.floor(Date.now() / 1000) + 360,
messages: [
{
address: jettonWalletContract, // sender jetton wallet
amount: toNano(0.05).toString(), // for commission fees, excess will be returned
payload: body.toBoc().toString("base64") // payload with jetton transfer and comment body
}
]
}
const result = await tonConnectUI.sendTransaction(transaction)
import TonConnect from '@tonconnect/sdk';
import { toNano } from '@ton/ton'
const connector = new TonConnect();
//...
await connector.sendTransaction({
validUntil: Math.floor(Date.now() / 1000) + 360,
messages: [
{
address: jettonWalletContract, // sender jetton wallet
amount: toNano(0.05).toString(), // for commission fees, excess will be returned
payload: body.toBoc().toString("base64") // payload with jetton transfer and comment body
}
]
})
- validUntil` - 메시지가 유효할 때까지의 UNIX 시간
- '젯튼월렛주소` - 젯튼마저와 월렛 컨트랙트를 기반으로 정의된 주소, 젯튼월렛 주소입니다.
- '잔액' - 나노톤 단위의 가스 결제를 위한 톤코인 금액, 정수입니다.
body
- jettonContract의 페이로드
제튼 월렛 상태 초기화 및 주소 준비 예시
import { Address, TonClient, beginCell, StateInit, storeStateInit } from '@ton/ton'
async function main() {
const client = new TonClient({
endpoint: 'https://toncenter.com/api/v2/jsonRPC',
apiKey: 'put your 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()));
}
제톤 번
제톤 번(TEP-74의 바디
는 일반적으로 다음과 같은 방법으로 수행해야 합니다:
import { beginCell, Address } 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 burn op code
.storeUint(0, 64) // query_id:uint64
.storeCoins(1000000) // amount:(VarUInteger 16) - Jetton amount in decimal
.storeAddress(Address.parse(Wallet_SRC)) // response_destination:MsgAddress - owner's wallet
.storeUint(0, 1) // custom_payload:(Maybe ^Cell) - w/o payload typically
.endCell();
메시지 위치를 다음 요청에 넣습니다:
- @tonconnect/react-ui
- @tonconnect/ui
- @tonconnect/sdk
import { useTonConnectUI } from '@tonconnect/ui-react';
import { toNano } from '@ton/ton'
const myTransaction = {
validUntil: Math.floor(Date.now() / 1000) + 360,
messages: [
{
address: jettonWalletContract, // owner's jetton wallet
amount: toNano(0.05).toString(), // for commission fees, excess will be returned
payload: body.toBoc().toString("base64") // payload with a jetton burn body
}
]
}
export const Settings = () => {
const [tonConnectUI, setOptions] = useTonConnectUI();
return (
<div>
<button onClick={() => tonConnectUI.sendTransaction(myTransaction)}>
Send transaction
</button>
</div>
);
};
import TonConnectUI from '@tonconnect/ui'
import { toNano } from '@ton/ton'
const transaction = {
validUntil: Math.floor(Date.now() / 1000) + 360,
messages: [
{
address: jettonWalletContract, // owner's jetton wallet
amount: toNano(0.05).toString(), // for commission fees, excess will be returned
payload: body.toBoc().toString("base64") // payload with a jetton burn body
}
]
}
const result = await tonConnectUI.sendTransaction(transaction)
await connector.sendTransaction({
validUntil: Math.floor(Date.now() / 1000) + 360,
messages: [
{
address: jettonWalletContract, // owner's jetton wallet
amount: toNano(0.05).toString(), // for commission fees, excess will be returned
payload: body.toBoc().toString("base64") // payload with a jetton burn body
}
]
})
- '젯튼월렛주소' - 젯튼마저와 월렛 컨트랙트를 기반으로 정의된 젯튼 월렛 컨트랙트 주소입니다.
- '금액' - 정수로, 나노톤 단위의 가스 결제용 톤코인 금액입니다.
- body
-
burn#595f07bc` 연산 코드가 있는 제튼 지갑의 페이로드입니다.
NFT 전송
본문` 메시지는 일반적으로 다음과 같은 방식으로 작성해야 합니다:
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 transfer op code 0x5fcc3d14
.storeUint(0, 64) // query_id:uint64
.storeAddress(Address.parse(NEW_OWNER_WALLET)) // new_owner:MsgAddress
.storeAddress(Address.parse(Wallet_DST)) // response_destination:MsgAddress
.storeUint(0, 1) // custom_payload:(Maybe ^Cell)
.storeCoins(toNano(0.000000001).toString()) // 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';
import { toNano } from '@ton/ton'
const myTransaction = {
validUntil: Math.floor(Date.now() / 1000) + 360,
messages: [
{
address: jettonWalletContract, // NFT Item address, which will be transferred
amount: toNano(0.05).toString(), // for commission fees, excess will be returned
payload: body.toBoc().toString("base64") // payload with a NFT transfer body
}
]
}
export const Settings = () => {
const [tonConnectUI, setOptions] = useTonConnectUI();
return (
<div>
<button onClick={() => tonConnectUI.sendTransaction(myTransaction)}>
Send transaction
</button>
</div>
);
};
import TonConnectUI from '@tonconnect/ui'
import { toNano } from '@ton/ton'
const transaction = {
validUntil: Math.floor(Date.now() / 1000) + 360,
messages: [
{
address: NFTitem, // NFT Item address, which will be transferred
amount: toNano(0.05).toString(), // for commission fees, excess will be returned
payload: body.toBoc().toString("base64") // payload with a NFT transfer body
}
]
}
const result = await tonConnectUI.sendTransaction(transaction)
await connector.sendTransaction({
validUntil: Math.floor(Date.now() / 1000) + 360,
messages: [
{
address: NFTitem, // NFT Item address, which will be transferred
amount: toNano(0.05).toString(), // for commission fees, excess will be returned
payload: body.toBoc().toString("base64") // payload with a NFT transfer body
}
]
})
NFTitem
- 주소 - 새 소유자NEW_OWNER_WALLET
에게 전송할 NFT 아이템 스마트 컨트랙트의 주소입니다.- '잔액' - 나노톤 단위의 가스 결제를 위한 톤코인 금액, 정수입니다.
body
- NFT 컨트랙트에 대한 페이로드
NFT 판매(GetGems)
다음은 겟젬 마켓플레이스에서 판매할 메시지와 거래를 준비하는 예시입니다. nft-fixprice-sale-v3r2 계약에 따라.
겟젬 판매 컨트랙트에 NFT를 배치하려면, 특별한 NFT 판매 컨트랙트로 전송할 특별한 메시지 본문 'transferNftBody'를 준비해야 합니다.
const transferNftBody = beginCell()
.storeUint(0x5fcc3d14, 32) // Opcode for NFT transfer
.storeUint(0, 64) // query_id
.storeAddress(Address.parse(destinationAddress)) // new_owner - GetGems sale contracts deployer, should never change for this operation
.storeAddress(Address.parse(walletAddress)) // response_destination for excesses
.storeBit(0) // we do not have custom_payload
.storeCoins(toNano(1).toString()) // forward_amount
.storeBit(0) // we store forward_payload is this cell
.storeUint(0x0fe0ede, 31) // not 32, because previous 0 will be read as do_sale opcode in deployer
.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 Address
const marketplaceFeeAddress = Address.parse('EQCjk1hh952vWaE9bRguFkAhDAL5jj3xj9p0uPWrFBq_GEMS'); // GetGems Address for Fees
const destinationAddress = Address.parse("EQAIFunALREOeQ99syMbO6sSzM_Fa1RsPD5TBoS0qVeKQ-AR"); // GetGems sale contracts deployer
const walletAddress = Address.parse('EQArLGBnGPvkxaJE57Y6oS4rwzDWuOE8l8_sghntXLkIt162');
const royaltyAddress = Address.parse('EQArLGBnGPvkxaJE57Y6oS4rwzDWuOE8l8_sghntXLkIt162');
const nftAddress = Address.parse('EQCUWoe7hLlklVxH8gduCf45vPNocsjRP4wbX42UJ0Ja0S2f');
const price = toNano(5).toString(); // 5 TON
const feesData = beginCell()
.storeAddress(marketplaceFeeAddress)
// 5% - GetGems fee
.storeCoins(price / BigInt(100) * BigInt(5))
.storeAddress(royaltyAddress)
// 5% - Royalty, can be changed
.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) // full price in 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();
// not needed, just for example
const saleContractAddress = new Address(0, stateInitCell.hash());
const saleBody = beginCell()
.storeUint(1, 32) // just accept coins on deploy
.storeUint(0, 64)
.endCell();
const transferNftBody = beginCell()
.storeUint(0x5fcc3d14, 32) // Opcode for NFT transfer
.storeUint(0, 64) // query_id
.storeAddress(destinationAddress) // new_owner
.storeAddress(walletAddress) // response_destination for excesses
.storeBit(0) // we do not have custom_payload
.storeCoins(toNano(1).toString()) // forward_amount
.storeBit(0) // we store forward_payload is this cell
// not 32, because we stored 0 bit before | do_sale opcode for deployer
.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';
import { toNano } from '@ton/ton'
const myTransaction = {
validUntil: Math.floor(Date.now() / 1000) + 360,
messages: [
{
address: NFTitem, //address of the NFT Item contract, that should be placed on market
amount: toNano(1.08).toString(), // amount that will require on gas fees, excess will be return
payload: transferNftBody.toBoc().toString("base64") // payload with the transferNftBody message
}
]
}
export const Settings = () => {
const [tonConnectUI, setOptions] = useTonConnectUI();
return (
<div>
<button onClick={() => tonConnectUI.sendTransaction(myTransaction)}>
Send transaction
</button>
</div>
);
};
import TonConnectUI from '@tonconnect/ui'
import { toNano } from '@ton/ton'
const transaction = {
validUntil: Math.floor(Date.now() / 1000) + 360,
messages: [
{
address: NFTitem, //address of NFT Item contract, that should be placed on market
amount: toNano(1.08).toString(), // amount that will require on gas fees, excess will be return
payload: transferNftBody.toBoc().toString("base64") // payload with the transferNftBody message
}
]
}
const result = await tonConnectUI.sendTransaction(transaction)
await connector.sendTransaction({
validUntil: Math.floor(Date.now() / 1000) + 360,
messages: [
{
address: NFTitem, //address of NFT Item contract, that should be placed on market
amount: toNano(1.08).toString(), // amount that will require on gas fees, excess will be return
payload: transferNftBody.toBoc().toString("base64") // payload with the transferNftBody message
}
]
})
NFT 구매(겟젬)
nft-fixprice-sale-v3r2](https://github.com/getgems-io/nft-contracts/blob/main/packages/contracts/sources/nft-fixprice-sale-v3r2.fc) 판매 계약에 대한 NFT 구매 과정은 페이로드없이 일반 이체로 진행할 수 있으며, 중요한 것은 정확한 TON 금액이며 다음과 같이 계산됩니다: '매수금액 = Nftprice TON + 1.0 TON'.
- @tonconnect/react-ui
- @tonconnect/ui
- @tonconnect/sdk
import { useTonConnectUI } from '@tonconnect/ui-react';
import { toNano } from '@ton/ton'
const myTransaction = {
validUntil: Math.floor(Date.now() / 1000) + 360,
messages: [
{
address: nftSaleContract, // NFT Sale contract, that is current desired NFT Item
amount: toNano(buyAmount), // NFT Price + exactly 1 TON, excess will be returned
}
]
}
export const Settings = () => {
const [tonConnectUI, setOptions] = useTonConnectUI();
return (
<div>
<button onClick={() => tonConnectUI.sendTransaction(myTransaction)}>
Send transaction
</button>
</div>
);
};
import TonConnectUI from '@tonconnect/ui'
import { toNano } from '@ton/ton'
const transaction = {
validUntil: Math.floor(Date.now() / 1000) + 360,
messages: [
{
address: nftSaleContract, // NFT Sale contract, that is current desired NFT Item
amount: toNano(buyAmount), // NFT Price + exactly 1 TON, excess will be returned
}
]
}
const result = await tonConnectUI.sendTransaction(transaction)
await connector.sendTransaction({
validUntil: Math.floor(Date.now() / 1000) + 360,
messages: [
{
address: nftSaleContract, // NFT Sale contract, that is current desired NFT Item
amount: toNano(buyAmount), // NFT Price + exactly 1 TON, excess will be returned
}
]
})
TON 연결 파이썬 SDK
파이썬 예제에서는 파이톤커넥트 및 파이토닉을 사용하고 있습니다.
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', # destination address
'amount' : 1000000000, # amount should be specified in nanocoins, 1 TON
}
]
}
댓글로 전송
먼저 다음 함수를 통해 댓글이 포함된 메시지를 구현합니다:
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) # op code for comment message
.store_string(comment) # store comment
.end_cell() # end cell
.to_boc() # convert it to boc
)
.decode() # encode it to urlsafe base64
}
return data
댓글이 포함된 전송을 위한 최종 거래 본문입니다:
transaction = {
'valid_until': int(time.time() + 3600),
'messages': [
get_comment_message(
destination_address='0:0000000000000000000000000000000000000000000000000000000000000000',
amount=int(0.01 * 10**9), # amount should be specified in nanocoins
comment='hello world!'
)
]
}
TON 스마트 컨트랙트 주소]에 대해 자세히 알아보세요(/학습/개요/주소).
제턴 전송
제톤 전송 트랜잭션을 구축하는 함수 예제입니다:
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) # op code for jetton transfer message
.store_uint(0, 64) # query_id
.store_coins(jettons_amount)
.store_address(recipient_address) # destination address
.store_address(response_address or recipient_address) # address send excess to
.store_uint(0, 1) # custom payload
.store_coins(1) # forward amount
.store_uint(0, 1) # forward payload
.end_cell() # end cell
.to_boc() # convert it to boc
)
.decode() # encode it to urlsafe 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), # replace 9 for jetton decimal. For example for jUSDT it should be (amount * 10**6)
response_address=wallet_address
),
]
}
제톤 번
제튼 번 트랜잭션 구축 기능의 예시입니다:
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) # op code for jetton burn message
.store_uint(0, 64) # query_id
.store_coins(jettons_amount)
.store_address(response_address) # address send excess to
.end_cell() # end cell
.to_boc() # convert it to boc
)
.decode() # encode it to urlsafe 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), # replace 9 for jetton decimal. For example for jUSDT it should be (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) # op code for nft transfer message
.store_uint(0, 64) # query_id
.store_address(recipient_address) # new owner
.store_address(response_address or recipient_address) # address send excess to
.store_uint(0, 1) # custom payload
.store_coins(1) # forward amount
.store_uint(0, 1) # forward payload
.end_cell() # end cell
.to_boc() # convert it to boc
)
.decode() # encode it to urlsafe 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)
다음은 겟젬 마켓플레이스에서 판매할 메시지와 거래를 준비하는 예시입니다. nft-fixprice-sale-v3r2 계약에 따라.
겟젬 판매 컨트랙트에 NFT를 배치하려면, 특별한 NFT 판매 컨트랙트로 전송할 특별한 메시지 본문 'transferNftBody'를 준비해야 합니다.
NFT 판매 본문 생성 예시
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):
# contract code
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=')
# fees 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_sale_body(
nft_address='EQDrA-3zsJXTfGo_Vdzg8d07Da4vSdHZllc6W9qvoNoMstF-',
wallet_address='0:0000000000000000000000000000000000000000000000000000000000000000',
royalty_address='0:0000000000000000000000000000000000000000000000000000000000000000',
price=int(5 * 10**9),
amount=int(1.08 * 10**9)
),
]
}
NFT 구매(겟젬)
nft-fixprice-sale-v3r2](https://github.com/getgems-io/nft-contracts/blob/main/packages/contracts/sources/nft-fixprice-sale-v3r2.fc) 판매 계약에 대한 NFT 구매 과정은 페이로드없이 일반 이체로 진행할 수 있으며, 중요한 것은 정확한 TON 금액이며 다음과 같이 계산됩니다: '매수금액 = Nftprice TON + 1.0 TON'.
transaction = {
'valid_until': int(time.time() + 3600),
'messages': [
{
'address': nft_address,
'amount': buyAmount,
}
]
}
TON Connect Go SDK
톤커넥트](https://github.com/cameo-engineering/tonconnect) 및 톤타일즈-고를 사용하는 예가 있습니다.
import "github.com/cameo-engineering/tonconnect"
import "github.com/xssnick/tonutils-go/address"
여기에서 톤커넥트 세션을 생성하고 메시지로 구성된 트랜잭션을 전송하는 방법을 확인할 수 있습니다.
s, _ := tonconnect.NewSession()
// create ton links
// ...
// create new message msg and transaction
boc, _ := s.SendTransaction(ctx, *tx)
추가 예제에서는 메시지와 트랜잭션만 생성됩니다.
일반 TON 전송
일반 TON 전송 메시지 작성 기능의 예시입니다:
import (
"fmt"
"github.com/cameo-engineering/tonconnect"
)
func Transfer(dest string, amount uint64) (*tonconnect.Message, error) {
msg, err := tonconnect.NewMessage(
dest,
fmt.Sprintf("%d", amount), // nanocoins to transfer/compute message
)
return msg, err
}
최종 거래 본문:
msg, err := Transfer("0QBZ_35Wy144n2GBM93YpcV4KOKcIjDJk8DdX4kyXEEHcbLZ", uint64(math.Pow(10, 9)))
if err != nil {
log.Fatal(err)
}
tx, err := tonconnect.NewTransaction(
tonconnect.WithTimeout(10*time.Minute),
tonconnect.WithTestnet(),
tonconnect.WithMessage(*msg),
)
if err != nil {
log.Fatal(err)
}
댓글로 전송하기
댓글 메시지가 포함된 빌딩 전송 기능의 예시입니다:
import (
"fmt"
"github.com/cameo-engineering/tonconnect"
"github.com/xssnick/tonutils-go/tvm/cell"
)
func TransferWithComment(dest string, amount uint64, comment string) (*tonconnect.Message, error) {
payload, _ := cell.BeginCell().
MustStoreUInt(0, 32).
MustStoreStringSnake(comment).
EndCell().MarshalJSON()
msg, err := tonconnect.NewMessage(
dest,
fmt.Sprintf("%d", amount), // nanocoins to transfer/compute message
tonconnect.WithPayload(payload))
return msg, err
}
최종 거래 본문:
msg, err := TransferWithComment("0QBZ_35Wy144n2GBM93YpcV4KOKcIjDJk8DdX4kyXEEHcbLZ", uint64(math.Pow(10, 9)), "new comment")
if err != nil {
log.Fatal(err)
}
tx, err := tonconnect.NewTransaction(
tonconnect.WithTimeout(10*time.Minute),
tonconnect.WithTestnet(),
tonconnect.WithMessage(*msg),
)
if err != nil {
log.Fatal(err)
}
제턴 전송
제톤 전송 메시지 기능의 예입니다:
import (
"fmt"
"github.com/cameo-engineering/tonconnect"
"github.com/xssnick/tonutils-go/address"
"github.com/xssnick/tonutils-go/tvm/cell"
)
func JettonTransferMessage(jetton_wallet_address string, amount uint64,
jettons_amount uint64, recipient_address, response_address string,
fwd_amount uint64, fwd_payload *cell.Cell) (*tonconnect.Message, error) {
payload, _ := cell.BeginCell().
MustStoreUInt(0xf8a7ea5, 32). // op code for jetton transfer message (op::transfer)
MustStoreUInt(0, 64). // query_id
MustStoreCoins(jettons_amount).
MustStoreAddr(address.MustParseAddr(recipient_address)). // address send excess to
MustStoreAddr(address.MustParseAddr(response_address)).
MustStoreUInt(0, 1). // custom payload
MustStoreCoins(fwd_amount). // set 0 if don't want transfer notification
MustStoreMaybeRef(fwd_payload).
EndCell().MarshalJSON()
msg, err := tonconnect.NewMessage(
jetton_wallet_address,
fmt.Sprintf("%d", amount), // nanocoins to transfer/compute message
tonconnect.WithPayload(payload))
if err != nil {
return nil, err
}
return msg, nil
}
최종 거래 본문:
msg, err := JettonTransferMessage("kQA8Q7m_pSNPr6FcqRYxllpAZv-0ieXy_KYER2iP195hBXiX",
uint64(math.Pow(10, 9)),
uint64(10),
"0QBZ_35Wy144n2GBM93YpcV4KOKcIjDJk8DdX4kyXEEHcbL2",
"EQBuObr2M7glm08w6cBGjIuuCbmvBFGwuVs6qb3AQpac9XpX",
uint64(0), nil)
if err != nil {
log.Fatal(err)
}
tx, err := tonconnect.NewTransaction(
tonconnect.WithTimeout(10*time.Minute),
tonconnect.WithTestnet(),
tonconnect.WithMessage(*msg),
)
if err != nil {
log.Fatal(err)
}
제톤 번
제톤 번 메시지 기능의 예입니다:
import (
"fmt"
"github.com/cameo-engineering/tonconnect"
"github.com/xssnick/tonutils-go/address"
"github.com/xssnick/tonutils-go/tvm/cell"
)
func JettonBurnMessage(jetton_wallet_address string, amount uint64,
jettons_amount uint64, response_address string) (*tonconnect.Message, error) {
payload, _ := cell.BeginCell().
MustStoreUInt(0xf8a7ea5, 32). // op code for jetton burn message (op::burn)
MustStoreUInt(0, 64). // query_id
MustStoreCoins(jettons_amount). // jetton amount to burn
MustStoreAddr(address.MustParseAddr(response_address)). // address send excess to
EndCell().MarshalJSON()
msg, err := tonconnect.NewMessage(
jetton_wallet_address,
fmt.Sprintf("%d", amount), // nanocoins to transfer/compute message
tonconnect.WithPayload(payload))
if err != nil {
return nil, err
}
return msg, nil
}
최종 거래 본문:
msg, err := JettonBurnMessage("kQA8Q7m_pSNPr6FcqRYxllpAZv-0ieXy_KYER2iP195hBXiX",
uint64(math.Pow(10, 9)),
uint64(10),
"EQBuObr2M7glm08w6cBGjIuuCbmvBFGwuVs6qb3AQpac9XpX")
if err != nil {
log.Fatal(err)
}
tx, err := tonconnect.NewTransaction(
tonconnect.WithTimeout(10*time.Minute),
tonconnect.WithTestnet(),
tonconnect.WithMessage(*msg),
)
if err != nil {
log.Fatal(err)
}
NFT 전송
NFT 전송 메시지의 함수 예시입니다:
import (
"fmt"
"github.com/cameo-engineering/tonconnect"
"github.com/xssnick/tonutils-go/address"
"github.com/xssnick/tonutils-go/tvm/cell"
)
func NftTransferMessage(nft_address string, amount uint64, recipient_address, response_address string,
fwd_amount uint64, fwd_payload *cell.Cell) (*tonconnect.Message, error) {
payload, _ := cell.BeginCell().
MustStoreUInt(0x5fcc3d14, 32). // op code for nft transfer message (op::transfer())
MustStoreUInt(0, 64). // query_id
MustStoreAddr(address.MustParseAddr(recipient_address)). // new owner
MustStoreAddr(address.MustParseAddr(response_address)). // address send excess to
MustStoreUInt(0, 1). // custom payload
MustStoreCoins(fwd_amount). // set 0 if don't want transfer notification
MustStoreMaybeRef(fwd_payload).
EndCell().MarshalJSON()
msg, err := tonconnect.NewMessage(
nft_address,
fmt.Sprintf("%d", amount), // nanocoins to transfer/compute message
tonconnect.WithPayload(payload))
if err != nil {
return nil, err
}
return msg, nil
}
최종 거래 본문:
msg, err := NftTransferMessage("EQDrA-3zsJXTfGo_Vdzg8d07Da4vSdHZllc6W9qvoNoMstF-",
uint64(math.Pow(10, 9)),
"0QBZ_35Wy144n2GBM93YpcV4KOKcIjDJk8DdX4kyXEEHcbL2",
"0QBZ_35Wy144n2GBM93YpcV4KOKcIjDJk8DdX4kyXEEHcbL2",
uint64(0), nil)
if err != nil {
log.Fatal(err)
}
tx, err := tonconnect.NewTransaction(
tonconnect.WithTimeout(10*time.Minute),
tonconnect.WithTestnet(),
tonconnect.WithMessage(*msg),
)
if err != nil {
log.Fatal(err)
}
NFT 판매(GetGems)
다음은 겟젬 마켓플레이스에서 판매할 메시지와 거래를 준비하는 예시입니다. nft-fixprice-sale-v3r2 계약에 따라.
겟젬 판매 컨트랙트에 NFT를 배치하려면, 특별한 NFT 판매 컨트랙트로 전송할 특별한 메시지 본문 'transferNftBody'를 준비해야 합니다.
transferNftBody := cell.BeginCell().
MustStoreUInt(0x5fcc3d14, 32). // opcode for NFT transfer
MustStoreUInt(0, 64). // query_id
MustStoreAddress(destinationAddress). // new_owner - GetGems sale contracts deployer, should never change for this operation
MustStoreAddress(walletAddress). // response_destination for excesses
MustStoreUInt(0, 1). // we do not have custom_payload
MustStoreCoins(1.08*math.Pow(10, 9)). // forward_amount
MustStoreUInt(0, 1). // we store forward_payload is this cell
MustStoreUInt(0x0fe0ede, 31). // not 32, because previous 0 will be read as do_sale opcode in deployer (op::do_sale)
MustStoreRef(stateInitCell).
MustStoreRef(saleBody).
EndCell()
메시지에는 많은 단계가 필요하기 때문에 전체 알고리즘이 방대하며 여기에서 찾을 수 있습니다:
NFT 세일 메시지 본문 생성을 위한 전체 알고리즘 표시
import (
"fmt"
"math"
"time"
"github.com/cameo-engineering/tonconnect"
"github.com/xssnick/tonutils-go/address"
"github.com/xssnick/tonutils-go/tlb"
"github.com/xssnick/tonutils-go/tvm/cell"
)
func NftSaleMessage(wallet, royalty, nft string, amount, price uint64) (*tonconnect.Message, error) {
fixPriceV3R2Code := new(cell.Cell)
fixPriceV3R2Code.UnmarshalJSON([]byte("te6cckECCwEAArkAART/APSkE/S88sgLAQIBIAIDAgFIBAUAfvIw7UTQ0wDTH/pA+kD6QPoA1NMAMMABjh34AHAHyMsAFssfUATPFljPFgHPFgH6AszLAMntVOBfB4IA//7y8AICzQYHAFegOFnaiaGmAaY/9IH0gfSB9AGppgBgYaH0gfQB9IH0AGEEIIySsKAVgAKrAQH30A6GmBgLjYSS+CcH0gGHaiaGmAaY/9IH0gfSB9AGppgBgYOCmE44BgAEqYhOmPhW8Q4YBKGATpn8cIxbMbC3MbK2QV44LJOZlvKAVxFWAAyS+G8BJrpOEBFcCBFd0VYACRWdjYKdxjgthOjq+G6hhoaYPqGAD9gHAU4ADAgB92YIQO5rKAFJgoFIwvvLhwiTQ+kD6APpA+gAwU5KhIaFQh6EWoFKQcIAQyMsFUAPPFgH6AstqyXH7ACXCACXXScICsI4XUEVwgBDIywVQA88WAfoCy2rJcfsAECOSNDTiWnCAEMjLBVADzxYB+gLLaslx+wBwIIIQX8w9FIKAejy0ZSzjkIxMzk5U1LHBZJfCeBRUccF8uH0ghAFE42RFrry4fUD+kAwRlAQNFlwB8jLABbLH1AEzxZYzxYBzxYB+gLMywDJ7VTgMDcowAPjAijAAJw2NxA4R2UUQzBw8AXgCMACmFVEECQQI/AF4F8KhA/y8AkA1Dg5ghA7msoAGL7y4clTRscFUVLHBRWx8uHKcCCCEF/MPRQhgBDIywUozxYh+gLLassfFcs/J88WJ88WFMoAI/oCE8oAyYMG+wBxUGZFFQRwB8jLABbLH1AEzxZYzxYBzxYB"))
marketplaceAddress := address.MustParseAddr("EQBYTuYbLf8INxFtD8tQeNk5ZLy-nAX9ahQbG_yl1qQ-GEMS") // GetGems Address
marketplaceFeeAddress := address.MustParseAddr("EQCjk1hh952vWaE9bRguFkAhDAL5jj3xj9p0uPWrFBq_GEMS") // GetGems Address for Fees
destinationAddress := address.MustParseAddr("EQAIFunALREOeQ99syMbO6sSzM_Fa1RsPD5TBoS0qVeKQ-AR") // GetGems sale contracts deployer
walletAddress := address.MustParseAddr(wallet)
royaltyAddress := address.MustParseAddr(royalty)
nftAddress := address.MustParseAddr(nft)
feesData := cell.BeginCell().
MustStoreAddr(marketplaceFeeAddress).
// 5% - GetGems fee
MustStoreCoins(price * 100 * 5).
MustStoreAddr(royaltyAddress).
// 5% - Royalty, can be changed
MustStoreCoins(price / 100 * 5).
EndCell()
saleData := cell.BeginCell().
MustStoreUInt(0, 1). // is_complete
MustStoreUInt(uint64(time.Now().UTC().Unix()), 32). // created_at
MustStoreAddr(marketplaceAddress). // marketplace_address
MustStoreAddr(nftAddress). // nft_address
MustStoreAddr(walletAddress). // previous_owner_address
MustStoreCoins(price). // full price in nanotons
MustStoreRef(feesData). // fees_cell
MustStoreUInt(0, 1). // can_be_deployed_externally
EndCell()
stateInit := &tlb.StateInit{
Data: saleData,
Code: fixPriceV3R2Code,
}
stateInitCell, err := tlb.ToCell(stateInit)
if err != nil {
return nil, err
}
// not needed, just for example
// saleContractAddress := address.NewAddress(0, 0, stateInitCell.Hash())
saleBody := cell.BeginCell().
MustStoreUInt(1, 32). // just accept coins on deploy
MustStoreUInt(0, 64).
EndCell()
transferNftBody, err := cell.BeginCell().
MustStoreUInt(0x5fcc3d14, 32). // opcode for NFT transfer
MustStoreUInt(0, 64). // query_id
MustStoreAddr(destinationAddress). // new_owner - GetGems sale contracts deployer, should never change for this operation
MustStoreAddr(walletAddress). // response_destination for excesses
MustStoreUInt(0, 1). // we do not have custom_payload
MustStoreCoins(uint64(1*math.Pow(10, 9))). // forward_amount
MustStoreUInt(0, 1). // we store forward_payload is this cell
MustStoreUInt(0x0fe0ede, 31). // not 32, because previous 0 will be read as do_sale opcode in deployer (op::do_sale)
MustStoreRef(stateInitCell).
MustStoreRef(saleBody).
EndCell().MarshalJSON()
if err != nil {
return nil, err
}
msg, err := tonconnect.NewMessage(
nftAddress.String(),
fmt.Sprintf("%d", amount),
tonconnect.WithPayload(transferNftBody))
if err != nil {
return nil, err
}
return msg, nil
}
최종 거래 본문입니다:
msg, err := NftSaleMessage("EQArLGBnGPvkxaJE57Y6oS4rwzDWuOE8l8_sghntXLkIt162",
"EQArLGBnGPvkxaJE57Y6oS4rwzDWuOE8l8_sghntXLkIt162",
"EQCUWoe7hLlklVxH8gduCf45vPNocsjRP4wbX42UJ0Ja0S2f",
uint64(1.08*math.Pow(10, 9)), uint64(5*math.Pow(10, 9)))
if err != nil {
log.Fatal(err)
}
tx, err := tonconnect.NewTransaction(
tonconnect.WithTimeout(10*time.Minute),
tonconnect.WithTestnet(),
tonconnect.WithMessage(*msg),
)
if err != nil {
log.Fatal(err)
}
NFT 구매(겟젬)
nft-fixprice-sale-v3r2](https://github.com/getgems-io/nft-contracts/blob/main/packages/contracts/sources/nft-fixprice-sale-v3r2.fc) 판매 계약에 대한 NFT 구매 과정은 페이로드없이 일반 이체로 진행할 수 있으며, 중요한 것은 정확한 TON 금액이며 다음과 같이 계산됩니다: '매수금액 = Nftprice TON + 1.0 TON'.
msg, err := tonconnect.NewMessage(nftAddress, buyAmount)
if err != nil {
log.Fatal(err)
}
tx, err := tonconnect.NewTransaction(
tonconnect.WithTimeout(10*time.Minute),
tonconnect.WithTestnet(),
tonconnect.WithMessage(*msg),
)
if err != nil {
log.Fatal(err)
}
작성자
- 아스파이트](https://t.me/aspite)에서 제공하는 자바스크립트 예제
- Python 예제 제공: @yunwine
- @gleb498](https://t.me/gleb498)에서 제공한 Go 예제
참고 항목
- 톤 커넥트 SDK
- [톤 커넥트 - 메시지 보내기](/개발/앱/톤 커넥트/트랜잭션)
- [스마트 컨트랙트 개발 - 메시지 보내기(crwd)lbracketdwrc로우 레벨](/개발/스마트 컨트랙트/메시지)
- [TON 제톤 처리](/개발/앱/자산 처리/제톤)
- [TON에서 NFT 처리](/개발/앱/자산 처리/nfts)