非同质化代币 (NFT)
此页列出了与 [NFTs]交互的常见例子(https://docs.ton.org/develop/dapps/asset-processing/nfts)。
接受 NFT 所有权分配
指派的 NFT 所有权的通知信息具有以下结构:
message(0x05138d91) NFTOwnershipAssigned { previousOwner: Address; forwardPayload: Slice as remaining;}
使用 receiver 函数来接受通知消息。
验证可以通过两种方式进行:
- 直接保存 NFT 项目地址并进行验证。
import "@stdlib/deploy";
message(0x05138d91) NFTOwnershipAssigned { previousOwner: Address; forwardPayload: Slice as remaining;}
contract SingleNft with Deployable { nftItemAddress: Address;
init(nftItemAddress: Address) { self.nftItemAddress = nftItemAddress; }
receive(msg: NFTOwnershipAssigned) { require(self.nftItemAddress == sender(), "NFT contract is not the sender");
// your logic of processing nft ownership assign notification }}
- 使用
StateInit
和派生的 NFT 项目地址。
import "@stdlib/deploy";
message(0x05138d91) NFTOwnershipAssigned { previousOwner: Address; forwardPayload: Slice as remaining;}
struct NFTItemInitData { index: Int as uint64; collectionAddress: Address;}
inline fun calculateNFTAddress(index: Int, collectionAddress: Address, nftCode: Cell): Address { let initData = NFTItemInitData{ index, collectionAddress, };
return contractAddress(StateInit{code: nftCode, data: initData.toCell()});}
contract NftInCollection with Deployable { nftCollectionAddress: Address; nftItemIndex: Int as uint64; nftCode: Cell;
init(nftCollectionAddress: Address, nftItemIndex: Int, nftCode: Cell) { self.nftCollectionAddress = nftCollectionAddress; self.nftItemIndex = nftItemIndex; self.nftCode = nftCode; }
receive(msg: NFTOwnershipAssigned) { let expectedNftAddress = calculateNFTAddress(self.nftItemIndex, self.nftCollectionAddress, self.nftCode); // or you can even store expectedNftAddress require(expectedNftAddress == sender(), "NFT contract is not the sender");
// your logic of processing nft ownership assign notification }}
由于NFT项目的初始数据布局可能各不相同,第一种方法往往更合适。
转移 NFT 项目
要发送 NFT 项目转移,请使用 send()
函数。
import "@stdlib/deploy";
message(0x5fcc3d14) NFTTransfer { queryId: Int as uint64; newOwner: Address; // address of the new owner of the NFT item. responseDestination: Address; // address where to send a response with confirmation of a successful transfer and the rest of the incoming message coins. customPayload: Cell? = null; // optional custom data. In most cases should be null forwardAmount: Int as coins; // the amount of nanotons to be sent to the new owner. forwardPayload: Slice as remaining; // optional custom data that should be sent to the new owner.}
contract Example { nftItemAddress: Address;
init(nftItemAddress: Address) { self.nftItemAddress = nftItemAddress; }
// ... add more code from previous examples ...
receive("transfer") { send(SendParameters{ to: self.nftItemAddress, value: ton("0.1"), body: NFTTransfer{ queryId: 42, // FIXME: Change this according to your needs newOwner: sender(), responseDestination: myAddress(), customPayload: null, forwardAmount: 1, forwardPayload: rawSlice("F"), // precomputed beginCell().storeUint(0xF, 4).endCell().beginParse() }.toCell(), }); }}
获取 NFT 静态信息
请注意,TON Blockchain 不允许合约相互调用 getters。 要从另一个合约接收数据,您必须交换消息。
message(0x2fcb26a2) NFTGetStaticData { queryId: Int as uint64;}
message(0x8b771735) NFTReportStaticData { queryId: Int as uint64; index: Int as uint256; collection: Address;}
struct NFTItemInitData { index: Int as uint64; collectionAddress: Address;}
inline fun calculateNFTAddress(index: Int, collectionAddress: Address, nftCode: Cell): Address { let initData = NFTItemInitData{ index, collectionAddress, };
return contractAddress(StateInit{code: nftCode, data: initData.toCell()});}
contract Example { nftCollectionAddress: Address; nftItemIndex: Int as uint64; nftCode: Cell;
init(nftCollectionAddress: Address, nftItemIndex: Int, nftCode: Cell) { self.nftCollectionAddress = nftCollectionAddress; self.nftItemIndex = nftItemIndex; self.nftCode = nftCode; }
// ... add more code from previous examples ...
receive("get static data") { // FIXME: Put proper address("[NFT_ADDRESS]") here let nftAddress = sender(); send(SendParameters{ to: nftAddress, value: ton("0.1"), body: NFTGetStaticData{ queryId: 42, }.toCell(), }); }
receive(msg: NFTReportStaticData) { let expectedNftAddress = calculateNFTAddress(msg.index, msg.collection, self.nftCode); require(expectedNftAddress == sender(), "NFT contract is not the sender");
// Save nft static data or do something }}
获取 NFT 版税参数
此处](https://github.com/ton-blockchain/TEPs/blob/master/text/0066-nft-royalty-standard.md)介绍了 NFT 版税参数。
message(0x693d3950) NFTGetRoyaltyParams { queryId: Int as uint64;}
message(0xa8cb00ad) NFTReportRoyaltyParams { queryId: Int as uint64; numerator: Int as uint16; denominator: Int as uint16; destination: Address;}
contract Example { nftCollectionAddress: Address;
init(nftCollectionAddress: Address) { self.nftCollectionAddress = nftCollectionAddress; }
// ... add more code from previous examples ...
receive("get royalty params") { send(SendParameters{ to: self.nftCollectionAddress, value: ton("0.1"), body: NFTGetRoyaltyParams{ queryId: 42, }.toCell(), }); }
receive(msg: NFTReportRoyaltyParams) { require(self.nftCollectionAddress == sender(), "NFT collection contract is not the sender");
// Do something with msg }}
NFT 集合方法
请注意,只有NFT所有者才能使用这些方法。
部署 NFT
message(0x1) NFTDeploy { queryId: Int as uint64; itemIndex: Int as uint64; amount: Int as coins; // amount to sent when deploying nft nftContent: Cell;}
contract Example { nftCollectionAddress: Address;
init(nftCollectionAddress: Address) { self.nftCollectionAddress = nftCollectionAddress; }
// ... add more code from previous examples ...
receive("deploy") { send(SendParameters{ to: self.nftCollectionAddress, value: ton("0.14"), body: NFTDeploy{ queryId: 42, itemIndex: 42, amount: ton("0.1"), nftContent: beginCell().endCell() // FIXME: Should be your content, mostly generated offchain }.toCell(), }); }}
更改所有者
message(0x3) NFTChangeOwner { queryId: Int as uint64; newOwner: Address;}
contract Example { nftCollectionAddress: Address;
init(nftCollectionAddress: Address) { self.nftCollectionAddress = nftCollectionAddress; }
// ... add more code from previous examples ...
receive("change owner") { send(SendParameters{ to: self.nftCollectionAddress, value: ton("0.05"), body: NFTChangeOwner{ queryId: 42, // FIXME: Put proper address("NEW_OWNER_ADDRESS") here newOwner: sender(), }.toCell(), }); }}