From db091eb5f19650f608d71fcb9a39f1837c8dae1b Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 13 Oct 2025 18:34:05 +0300 Subject: [PATCH 1/6] Initial --- docs.json | 1 + standard/tokens/nft/dfsfs.ts | 30 ++++++ standard/tokens/nft/how-to-transfer.mdx | 116 ++++++++++++++++++++++++ 3 files changed, 147 insertions(+) create mode 100644 standard/tokens/nft/dfsfs.ts create mode 100644 standard/tokens/nft/how-to-transfer.mdx diff --git a/docs.json b/docs.json index a48c581e..22e0c1e9 100644 --- a/docs.json +++ b/docs.json @@ -321,6 +321,7 @@ "pages": [ "standard/tokens/nft/overview", "standard/tokens/nft/how-works", + "standard/tokens/nft/how-to-transfer", "standard/tokens/nft/cNFT-how-it-works" ] }, diff --git a/standard/tokens/nft/dfsfs.ts b/standard/tokens/nft/dfsfs.ts new file mode 100644 index 00000000..85414a29 --- /dev/null +++ b/standard/tokens/nft/dfsfs.ts @@ -0,0 +1,30 @@ +import { Address, toNano } from '@ton/core'; + +import { AssetsSDK, createApi, createSender, importKey, PinataStorageParams } from '@ton-community/assets-sdk'; + +async function main() { + const NETWORK = 'mainnet'; + const api = await createApi(NETWORK); + + const keyPair = await importKey(process.env.MNEMONIC!); + const sender = await createSender('highload-v2', keyPair, api); + + const storage: PinataStorageParams = { + pinataApiKey: process.env.PINATA_API_KEY!, + pinataSecretKey: process.env.PINATA_SECRET!, + }; + + const sdk = AssetsSDK.create({ + api: api, + storage: storage, + sender: sender, + }); + + const NFT_ADDRESS = Address.parse('MY_NFT_ADDRESS'); + const nftItem = await sdk.openNftItem(NFT_ADDRESS); + + const RECEIVER_ADDRESS = Address.parse('RECEIVER_ADDRESS'); + await nftItem.send(sender, RECEIVER_ADDRESS, {value: toNano(10)}) +} + +void main(); \ No newline at end of file diff --git a/standard/tokens/nft/how-to-transfer.mdx b/standard/tokens/nft/how-to-transfer.mdx new file mode 100644 index 00000000..04419488 --- /dev/null +++ b/standard/tokens/nft/how-to-transfer.mdx @@ -0,0 +1,116 @@ +--- +title: "NFT: how to transfer" +sidebarTitle: "How to transfer" +--- + +NFT transfer is an operation specified in [TEP 0062](https://github.com/ton-blockchain/TEPs/blob/master/text/0062-nft-standard.md). Its implementation must comply with this standard, +and NFT item contracts must support the logic described there. The NFT transfer message is +also specified and must comply with the corresponding TL-B scheme. This scheme involves, among other things, + +- `forward_amount`: the amount of nanotons to be sent to the destination address; +- `forward_payload`: optional custom data that should be sent to the destination address. + +If `forward_ton_amount > 0`, then `forward_payload` must comply with one of the [standard formats](https://github.com/ton-blockchain/TEPs/blob/master/text/0062-nft-standard.md#forward_payload-format). + +First, you can use your wallet app with NFTs, just follow the corresponding guides. +Second, you can use your favorite IDE. Below there are two illustrative examples: + +```typescript +import { Address, beginCell, internal, toNano } from "@ton/core"; +import { TonClient, WalletContractV4 } from "@ton/ton"; +import { mnemonicToPrivateKey } from "@ton/crypto"; + +async function main() { + const nftItemAddress = Address + .parse('put your NFT item address'); + const newOwner = Address + .parse('put new owner address'); + const destinationAddress = Address + .parse('put destination wallet address'); + + const forwardPayload = beginCell() + .storeUint(0, 32) // 0 opcode means we have a comment + .storeStringTail('you are the new owner') + .endCell(); + + const messageBody = beginCell() + .storeUint(0x5fcc3d14, 32) // opcode for NFT transfer + .storeUint(0, 64) // query id + .storeCoins(toNano(5)) // jetton amount, amount * 10^9 + .storeAddress(newOwner) // the address of the new NFT owner + .storeAddress(destinationAddress) // response destination + .storeBit(0) // no custom payload + .storeCoins(toNano('0.02')) // forward amount - if >0, will send notification message + .storeBit(1) // store forwardPayload as a reference + .storeRef(forwardPayload) + .endCell(); + + const nftTransferMessage = internal({ + to: nftItemAddress, + value: toNano('0.1'), + bounce: true, + body: messageBody + }); + + // connect to your regular wallet + const client = new TonClient({ + endpoint: 'https://toncenter.com/api/v2/jsonRPC', + }); + const provider = client.provider(destinationAddress); + + const your_mnemonic = 'put your mnemonic here, ...'; + const keyPair = await mnemonicToPrivateKey(your_mnemonic.split(" ")); + const walletContract = WalletContractV4.create({ + workchain: 0, + publicKey: keyPair.publicKey, + }); + + // send the transfer message through your wallet + const seqno = await walletContract.getSeqno(provider); + await walletContract.sendTransfer(provider, { + seqno: seqno, + secretKey: keyPair.secretKey, + messages: [ + nftTransferMessage, + ], + }); +} + +void main(); +``` + +However, there is an [SDK](https://github.com/ton-community/assets-sdk) that allows you to avoid manually creating all the necessary messages. +An example of how it can be used to send the NFT transfer message is provided below: + +```typescript +import { Address, toNano } from '@ton/core'; + +import { AssetsSDK, createApi, createSender, importKey, PinataStorageParams } from '@ton-community/assets-sdk'; + +async function main() { + const NETWORK = 'mainnet'; + const api = await createApi(NETWORK); + + const keyPair = await importKey(process.env.MNEMONIC!); + const sender = await createSender('highload-v2', keyPair, api); + + const storage: PinataStorageParams = { + pinataApiKey: process.env.PINATA_API_KEY!, + pinataSecretKey: process.env.PINATA_SECRET!, + }; + + const sdk = AssetsSDK.create({ + api: api, + storage: storage, + sender: sender, + }); + + const NFT_ADDRESS = Address.parse('MY_NFT_ADDRESS'); + const nftItem = await sdk.openNftItem(NFT_ADDRESS); + + const RECEIVER_ADDRESS = Address.parse('RECEIVER_ADDRESS'); + await nftItem.send(sender, RECEIVER_ADDRESS, {value: toNano(10)}) +} + +void main(); +``` From 09208e5384f4685f2f306b87272307209fc8af93 Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 13 Oct 2025 18:38:28 +0300 Subject: [PATCH 2/6] Delete side file --- standard/tokens/nft/dfsfs.ts | 30 ------------------------------ 1 file changed, 30 deletions(-) delete mode 100644 standard/tokens/nft/dfsfs.ts diff --git a/standard/tokens/nft/dfsfs.ts b/standard/tokens/nft/dfsfs.ts deleted file mode 100644 index 85414a29..00000000 --- a/standard/tokens/nft/dfsfs.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { Address, toNano } from '@ton/core'; - -import { AssetsSDK, createApi, createSender, importKey, PinataStorageParams } from '@ton-community/assets-sdk'; - -async function main() { - const NETWORK = 'mainnet'; - const api = await createApi(NETWORK); - - const keyPair = await importKey(process.env.MNEMONIC!); - const sender = await createSender('highload-v2', keyPair, api); - - const storage: PinataStorageParams = { - pinataApiKey: process.env.PINATA_API_KEY!, - pinataSecretKey: process.env.PINATA_SECRET!, - }; - - const sdk = AssetsSDK.create({ - api: api, - storage: storage, - sender: sender, - }); - - const NFT_ADDRESS = Address.parse('MY_NFT_ADDRESS'); - const nftItem = await sdk.openNftItem(NFT_ADDRESS); - - const RECEIVER_ADDRESS = Address.parse('RECEIVER_ADDRESS'); - await nftItem.send(sender, RECEIVER_ADDRESS, {value: toNano(10)}) -} - -void main(); \ No newline at end of file From a19dec989e26a8d875b9bc5f279a0dcaa802e846 Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 13 Oct 2025 19:32:02 +0300 Subject: [PATCH 3/6] Fixes --- standard/tokens/nft/how-to-transfer.mdx | 64 +++++++++++++------------ 1 file changed, 33 insertions(+), 31 deletions(-) diff --git a/standard/tokens/nft/how-to-transfer.mdx b/standard/tokens/nft/how-to-transfer.mdx index 04419488..d2ad9005 100644 --- a/standard/tokens/nft/how-to-transfer.mdx +++ b/standard/tokens/nft/how-to-transfer.mdx @@ -12,25 +12,22 @@ also specified and must comply with the corresponding TL-B scheme. This scheme i If `forward_ton_amount > 0`, then `forward_payload` must comply with one of the [standard formats](https://github.com/ton-blockchain/TEPs/blob/master/text/0062-nft-standard.md#forward_payload-format). -First, you can use your wallet app with NFTs, just follow the corresponding guides. -Second, you can use your favorite IDE. Below there are two illustrative examples: +First, you can use your wallet app with NFTs, just follow the corresponding guides (see [Tonkeeper](https://tonkeeper.helpscoutdocs.com/article/47-how-to-send-nft-to-another-wallet) for an instance). +Or you can do it manually. Below there are two illustrative examples: ```typescript -import { Address, beginCell, internal, toNano } from "@ton/core"; -import { TonClient, WalletContractV4 } from "@ton/ton"; +import { Address, beginCell, internal, toNano, SendMode } from "@ton/core"; +import { TonClient, WalletContractV5R1 } from "@ton/ton"; import { mnemonicToPrivateKey } from "@ton/crypto"; async function main() { - const nftItemAddress = Address - .parse('put your NFT item address'); - const newOwner = Address - .parse('put new owner address'); - const destinationAddress = Address - .parse('put destination wallet address'); + const nftItemAddress = Address.parse("put your NFT item address"); + const newOwner = Address.parse("put new owner address"); + const destinationAddress = Address.parse("put destination wallet address"); const forwardPayload = beginCell() .storeUint(0, 32) // 0 opcode means we have a comment - .storeStringTail('you are the new owner') + .storeStringTail("you are the new owner") .endCell(); const messageBody = beginCell() @@ -40,27 +37,27 @@ async function main() { .storeAddress(newOwner) // the address of the new NFT owner .storeAddress(destinationAddress) // response destination .storeBit(0) // no custom payload - .storeCoins(toNano('0.02')) // forward amount - if >0, will send notification message + .storeCoins(toNano("0.02")) // forward amount - if >0, will send notification message .storeBit(1) // store forwardPayload as a reference .storeRef(forwardPayload) .endCell(); const nftTransferMessage = internal({ to: nftItemAddress, - value: toNano('0.1'), + value: toNano("0.1"), bounce: true, - body: messageBody + body: messageBody, }); // connect to your regular wallet const client = new TonClient({ - endpoint: 'https://toncenter.com/api/v2/jsonRPC', + endpoint: "https://toncenter.com/api/v2/jsonRPC", }); const provider = client.provider(destinationAddress); - const your_mnemonic = 'put your mnemonic here, ...'; + const your_mnemonic = "put your mnemonic here, ..."; const keyPair = await mnemonicToPrivateKey(your_mnemonic.split(" ")); - const walletContract = WalletContractV4.create({ + const walletContract = WalletContractV5R1.create({ workchain: 0, publicKey: keyPair.publicKey, }); @@ -70,10 +67,9 @@ async function main() { await walletContract.sendTransfer(provider, { seqno: seqno, secretKey: keyPair.secretKey, - messages: [ - nftTransferMessage, - ], - }); + messages: [nftTransferMessage], + sendMode: SendMode.PAY_GAS_SEPARATELY, + }); } void main(); @@ -83,16 +79,22 @@ However, there is an [SDK](https://github.com/ton-community/assets-sdk) that all An example of how it can be used to send the NFT transfer message is provided below: ```typescript -import { Address, toNano } from '@ton/core'; +import { Address, toNano } from "@ton/core"; -import { AssetsSDK, createApi, createSender, importKey, PinataStorageParams } from '@ton-community/assets-sdk'; +import { + AssetsSDK, + createApi, + createSender, + importKey, + PinataStorageParams, +} from "@ton-community/assets-sdk"; async function main() { - const NETWORK = 'mainnet'; + const NETWORK = "testnet"; const api = await createApi(NETWORK); const keyPair = await importKey(process.env.MNEMONIC!); - const sender = await createSender('highload-v2', keyPair, api); + const sender = await createSender("highload-v2", keyPair, api); const storage: PinataStorageParams = { pinataApiKey: process.env.PINATA_API_KEY!, @@ -100,16 +102,16 @@ async function main() { }; const sdk = AssetsSDK.create({ - api: api, - storage: storage, - sender: sender, + api, + storage, + sender, }); - const NFT_ADDRESS = Address.parse('MY_NFT_ADDRESS'); + const NFT_ADDRESS = Address.parse("put your NFT item address"); const nftItem = await sdk.openNftItem(NFT_ADDRESS); - const RECEIVER_ADDRESS = Address.parse('RECEIVER_ADDRESS'); - await nftItem.send(sender, RECEIVER_ADDRESS, {value: toNano(10)}) + const RECEIVER_ADDRESS = Address.parse("put receiver address"); + await nftItem.send(sender, RECEIVER_ADDRESS, { value: toNano(10) }); } void main(); From 3f384919c4f1336f5065d580cbaffd1bfcc02fcd Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 14 Oct 2025 00:06:04 +0300 Subject: [PATCH 4/6] Impro --- standard/tokens/nft/how-to-transfer.mdx | 24 ++++++++--- standard/tokens/nft/sdsd.ts | 53 +++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 5 deletions(-) create mode 100644 standard/tokens/nft/sdsd.ts diff --git a/standard/tokens/nft/how-to-transfer.mdx b/standard/tokens/nft/how-to-transfer.mdx index d2ad9005..b6147a55 100644 --- a/standard/tokens/nft/how-to-transfer.mdx +++ b/standard/tokens/nft/how-to-transfer.mdx @@ -81,21 +81,35 @@ An example of how it can be used to send the NFT transfer message is provided be ```typescript import { Address, toNano } from "@ton/core"; +import { WalletContractV5R1, TonClient } from "@ton/ton"; + +import { mnemonicToPrivateKey } from "@ton/crypto"; + import { AssetsSDK, createApi, - createSender, - importKey, PinataStorageParams, } from "@ton-community/assets-sdk"; async function main() { + const client = new TonClient({ + endpoint: "https://toncenter.com/api/v2/jsonRPC", + }); + + const your_mnemonic = 'put your mnemonic here, ...'; + const keyPair = await mnemonicToPrivateKey(your_mnemonic.split(" ")); + + const wallet = WalletContractV5R1.create({ + workchain: 0, + publicKey: keyPair.publicKey, + }); + + const provider = client.provider(wallet.address); + const sender = wallet.sender(provider, keyPair.secretKey); + const NETWORK = "testnet"; const api = await createApi(NETWORK); - const keyPair = await importKey(process.env.MNEMONIC!); - const sender = await createSender("highload-v2", keyPair, api); - const storage: PinataStorageParams = { pinataApiKey: process.env.PINATA_API_KEY!, pinataSecretKey: process.env.PINATA_SECRET!, diff --git a/standard/tokens/nft/sdsd.ts b/standard/tokens/nft/sdsd.ts new file mode 100644 index 00000000..277d9f5c --- /dev/null +++ b/standard/tokens/nft/sdsd.ts @@ -0,0 +1,53 @@ +import { Address, toNano } from "@ton/core"; + +import { WalletContractV5R1, TonClient } from "@ton/ton"; + +import { mnemonicToPrivateKey } from "@ton/crypto"; + +import { + AssetsSDK, + createApi, + PinataStorageParams, +} from "@ton-community/assets-sdk"; + + +async function main() { + + const client = new TonClient({ + endpoint: 'https://toncenter.com/api/v2/jsonRPC', + }); + + const keyPair = await mnemonicToPrivateKey(['dsadasdadasdasdasdasdasdasdasdad']) + + const walet = WalletContractV5R1.create({ + workchain: 0, + publicKey: keyPair.publicKey + } + ); + + const provider = client.provider(walet.address); + + const sender = walet.sender(provider, keyPair.secretKey); + + const NETWORK = "testnet"; + const api = await createApi(NETWORK); + + const storage: PinataStorageParams = { + pinataApiKey: process.env.PINATA_API_KEY!, + pinataSecretKey: process.env.PINATA_SECRET!, + }; + + const sdk = AssetsSDK.create({ + api, + storage, + sender, + }); + + const NFT_ADDRESS = Address.parse("put your NFT item address"); + const nftItem = await sdk.openNftItem(NFT_ADDRESS); + + const RECEIVER_ADDRESS = Address.parse("put receiver address"); + await nftItem.send(sender, RECEIVER_ADDRESS, { value: toNano(10) }); +} + +void main(); \ No newline at end of file From 49586b9990f99cfad6058b343709d7b4c1a14a4e Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 14 Oct 2025 16:43:22 +0300 Subject: [PATCH 5/6] Fixes --- standard/tokens/nft/how-to-transfer.mdx | 83 ++----------------------- standard/tokens/nft/sdsd.ts | 53 ---------------- 2 files changed, 4 insertions(+), 132 deletions(-) delete mode 100644 standard/tokens/nft/sdsd.ts diff --git a/standard/tokens/nft/how-to-transfer.mdx b/standard/tokens/nft/how-to-transfer.mdx index b6147a55..a021d76a 100644 --- a/standard/tokens/nft/how-to-transfer.mdx +++ b/standard/tokens/nft/how-to-transfer.mdx @@ -13,90 +13,21 @@ also specified and must comply with the corresponding TL-B scheme. This scheme i If `forward_ton_amount > 0`, then `forward_payload` must comply with one of the [standard formats](https://github.com/ton-blockchain/TEPs/blob/master/text/0062-nft-standard.md#forward_payload-format). First, you can use your wallet app with NFTs, just follow the corresponding guides (see [Tonkeeper](https://tonkeeper.helpscoutdocs.com/article/47-how-to-send-nft-to-another-wallet) for an instance). -Or you can do it manually. Below there are two illustrative examples: +Or you can do it manually. Below there is an illustrative example: ```typescript -import { Address, beginCell, internal, toNano, SendMode } from "@ton/core"; -import { TonClient, WalletContractV5R1 } from "@ton/ton"; -import { mnemonicToPrivateKey } from "@ton/crypto"; - -async function main() { - const nftItemAddress = Address.parse("put your NFT item address"); - const newOwner = Address.parse("put new owner address"); - const destinationAddress = Address.parse("put destination wallet address"); - - const forwardPayload = beginCell() - .storeUint(0, 32) // 0 opcode means we have a comment - .storeStringTail("you are the new owner") - .endCell(); - - const messageBody = beginCell() - .storeUint(0x5fcc3d14, 32) // opcode for NFT transfer - .storeUint(0, 64) // query id - .storeCoins(toNano(5)) // jetton amount, amount * 10^9 - .storeAddress(newOwner) // the address of the new NFT owner - .storeAddress(destinationAddress) // response destination - .storeBit(0) // no custom payload - .storeCoins(toNano("0.02")) // forward amount - if >0, will send notification message - .storeBit(1) // store forwardPayload as a reference - .storeRef(forwardPayload) - .endCell(); - - const nftTransferMessage = internal({ - to: nftItemAddress, - value: toNano("0.1"), - bounce: true, - body: messageBody, - }); - - // connect to your regular wallet - const client = new TonClient({ - endpoint: "https://toncenter.com/api/v2/jsonRPC", - }); - const provider = client.provider(destinationAddress); - - const your_mnemonic = "put your mnemonic here, ..."; - const keyPair = await mnemonicToPrivateKey(your_mnemonic.split(" ")); - const walletContract = WalletContractV5R1.create({ - workchain: 0, - publicKey: keyPair.publicKey, - }); - - // send the transfer message through your wallet - const seqno = await walletContract.getSeqno(provider); - await walletContract.sendTransfer(provider, { - seqno: seqno, - secretKey: keyPair.secretKey, - messages: [nftTransferMessage], - sendMode: SendMode.PAY_GAS_SEPARATELY, - }); -} - -void main(); -``` - -However, there is an [SDK](https://github.com/ton-community/assets-sdk) that allows you to avoid manually creating all the necessary messages. -An example of how it can be used to send the NFT transfer message is provided below: - -```typescript -import { Address, toNano } from "@ton/core"; - -import { WalletContractV5R1, TonClient } from "@ton/ton"; +import { WalletContractV5R1, TonClient, Address, toNano } from "@ton/ton"; import { mnemonicToPrivateKey } from "@ton/crypto"; -import { - AssetsSDK, - createApi, - PinataStorageParams, -} from "@ton-community/assets-sdk"; +import { AssetsSDK, createApi } from "@ton-community/assets-sdk"; async function main() { const client = new TonClient({ endpoint: "https://toncenter.com/api/v2/jsonRPC", }); - const your_mnemonic = 'put your mnemonic here, ...'; + const your_mnemonic = "put your mnemonic here, ..."; const keyPair = await mnemonicToPrivateKey(your_mnemonic.split(" ")); const wallet = WalletContractV5R1.create({ @@ -110,14 +41,8 @@ async function main() { const NETWORK = "testnet"; const api = await createApi(NETWORK); - const storage: PinataStorageParams = { - pinataApiKey: process.env.PINATA_API_KEY!, - pinataSecretKey: process.env.PINATA_SECRET!, - }; - const sdk = AssetsSDK.create({ api, - storage, sender, }); diff --git a/standard/tokens/nft/sdsd.ts b/standard/tokens/nft/sdsd.ts deleted file mode 100644 index 277d9f5c..00000000 --- a/standard/tokens/nft/sdsd.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { Address, toNano } from "@ton/core"; - -import { WalletContractV5R1, TonClient } from "@ton/ton"; - -import { mnemonicToPrivateKey } from "@ton/crypto"; - -import { - AssetsSDK, - createApi, - PinataStorageParams, -} from "@ton-community/assets-sdk"; - - -async function main() { - - const client = new TonClient({ - endpoint: 'https://toncenter.com/api/v2/jsonRPC', - }); - - const keyPair = await mnemonicToPrivateKey(['dsadasdadasdasdasdasdasdasdasdad']) - - const walet = WalletContractV5R1.create({ - workchain: 0, - publicKey: keyPair.publicKey - } - ); - - const provider = client.provider(walet.address); - - const sender = walet.sender(provider, keyPair.secretKey); - - const NETWORK = "testnet"; - const api = await createApi(NETWORK); - - const storage: PinataStorageParams = { - pinataApiKey: process.env.PINATA_API_KEY!, - pinataSecretKey: process.env.PINATA_SECRET!, - }; - - const sdk = AssetsSDK.create({ - api, - storage, - sender, - }); - - const NFT_ADDRESS = Address.parse("put your NFT item address"); - const nftItem = await sdk.openNftItem(NFT_ADDRESS); - - const RECEIVER_ADDRESS = Address.parse("put receiver address"); - await nftItem.send(sender, RECEIVER_ADDRESS, { value: toNano(10) }); -} - -void main(); \ No newline at end of file From f8f126250863c644135e13267c25fc8254786d6c Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 14 Oct 2025 17:22:30 +0300 Subject: [PATCH 6/6] Fix --- standard/tokens/nft/how-to-transfer.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/standard/tokens/nft/how-to-transfer.mdx b/standard/tokens/nft/how-to-transfer.mdx index a021d76a..51089f85 100644 --- a/standard/tokens/nft/how-to-transfer.mdx +++ b/standard/tokens/nft/how-to-transfer.mdx @@ -10,7 +10,7 @@ also specified and must comply with the corresponding TL-B scheme. This scheme i - `forward_amount`: the amount of nanotons to be sent to the destination address; - `forward_payload`: optional custom data that should be sent to the destination address. -If `forward_ton_amount > 0`, then `forward_payload` must comply with one of the [standard formats](https://github.com/ton-blockchain/TEPs/blob/master/text/0062-nft-standard.md#forward_payload-format). +If `forward_amount > 0`, then `forward_payload` must comply with one of the [standard formats](https://github.com/ton-blockchain/TEPs/blob/master/text/0062-nft-standard.md#forward_payload-format). First, you can use your wallet app with NFTs, just follow the corresponding guides (see [Tonkeeper](https://tonkeeper.helpscoutdocs.com/article/47-how-to-send-nft-to-another-wallet) for an instance). Or you can do it manually. Below there is an illustrative example: