跳至主要内容

NFT Item

這個智能合約為遵守TEP-0062標準的NFT Item提供了一個框架。。

Reference:

Messages

Transfer

發起 NFT Item 的交易。

message(0x5fcc3d14) Transfer {
query_id: Int as uint64;
new_owner: Address;
response_destination: Address;
custom_payload: Cell?;
forward_amount: Int as coins;
forward_payload: Slice as remaining;
}

OwnershipAssigned

通知 NFT Item 的所有者變更。

message(0x05138d91) OwnershipAssigned {
query_id: Int as uint64;
prev_owner: Address;
forward_payload: Slice as remaining;
}

Excesses

負責處理交易中的多餘 TON。

message(0xd53276db) Excesses {
query_id: Int as uint64;
}

GetStaticData

取得 NFT Item 的靜態 data。

message(0x2fcb26a2) GetStaticData {
query_id: Int as uint64;
}

ReportStaticData

回報 NFT Item 的靜態 data。

message(0x8b771735) ReportStaticData {
query_id: Int as uint64;
index: Int as uint256;
collection: Address;
}

NftData Structure

描述 NFT 的 data 結構。

struct NftData {
is_initialized: Bool;
index: Int;
collection_address: Address;
owner_address: Address;
individual_content: Cell;
}

NFTItemStandard Trait

實作 NFT Item 的標準。

contract ExampleNFTItem with NFTItemStandard {
override const gasConsumption: Int = ton("0.03");

collection_address: Address;
index: Int;
owner: Address;
individual_content: Cell;
is_initialized: Bool = false;

init(collection_address: Address, index: Int, owner: Address, individual_content: Cell) {
self.collection_address = collection_address;
self.index = index;
self.owner = owner;
self.individual_content = individual_content;
}
}

Messages Handling、Internal Functions and Get Methods

Messages Handling

receive(msg: Transfer)

處理交易訊息,發起 NFT Item 鑄造或轉移 NFT Item。

receive(msg: Transfer){
let ctx: Context = context();
let remain: Int = self._transfer_estimate_rest_value(ctx);
self._transfer_validate(ctx, msg, remain);
if (self.is_initialized == false) {
self.mint(ctx, msg);
} else {
self.transfer(ctx, msg, remain);
}
}

receive(msg: GetStaticData)

處理靜態 data 的請求。

receive(msg: GetStaticData){
self._report_static_data(msg);
}

Internal Functions

_transfer_estimate_rest_value(ctx: Context): Int

計算剩餘的 TON,需要返回給前一個所有者。

// @dev  _transfer_estimate_rest_value calculates the remain amount of nanotons that should be sent back to the old owner
inline fun _transfer_estimate_rest_value(ctx: Context): Int {
let remain: Int = ctx.value;
let tonBalanceBeforeMsg: Int = myBalance() - remain;
let storageFee: Int = self.minTonsForStorage - min(tonBalanceBeforeMsg, self.minTonsForStorage);
return remain - (storageFee + self.gasConsumption);
}

_transfer_validate(ctx: Context, msg: Transfer, remain: Int)

驗證交易請求。

// @dev  _transfer_validate checks if the request is valid (e.g. the sender is the current owner of the NFT item)
// throws error if the request is invalid
// @note one may override this function to implement custom validation logicTransferked
virtual inline fun _transfer_validate(ctx: Context, msg: Transfer, remain: Int) {
require(ctx.sender == self.owner || ctx.sender == self.collection_address, "NFTItemStandard: Only the owner or collection can transfer the NFT item");
}

mint(ctx: Context, msg: Transfer)

處理 NFT Item 的鑄造。

// @dev  mint usually performs the minting of the NFT item
// @note one may override this function to implement custom minting logic
virtual inline fun mint(ctx: Context, msg: Transfer) {
require(ctx.sender == self.collection_address, "NFTItemStandard: Only the collection can initialize the NFT item");
self.is_initialized = true;
self.owner = msg.new_owner;
send(SendParameters{
to: msg.response_destination,
value: 0,
mode: SendIgnoreErrors + SendRemainingValue,
body: Excesses { query_id: msg.query_id }.toCell()
});
}

transfer(ctx: Context, msg: Transfer, remain: Int)

執行 NFT Item 的轉移,並發送相關的通知。

// @dev  transfer performs the transfer of the NFT item
// if available, it will send OwnershipAssigned message to the new owner
// then, it will send Excesses message to the response_destination (old owner) if needed.
// @note one may override this function to implement custom transfer logic
virtual inline fun transfer(ctx: Context, msg: Transfer, remain: Int) {
self.owner = msg.new_owner;
if (msg.forward_amount > 0) {
send(SendParameters{
to: msg.new_owner,
value: msg.forward_amount,
mode: SendIgnoreErrors,
bounce: false,
body: OwnershipAssigned{
query_id: msg.query_id,
prev_owner: ctx.sender,
forward_payload: msg.forward_payload
}.toCell()
});
}
remain = remain - ctx.readForwardFee();
if (msg.response_destination != newAddress(0, 0) && remain > msg.forward_amount) {
send(SendParameters{
to: msg.response_destination,
value: remain - msg.forward_amount,
mode: SendPayGasSeparately,
body: Excesses { query_id: msg.query_id }.toCell()
});
}
}

_report_static_data(msg: GetStaticData)

回報 NFT Item 的靜態 data。

// @dev  _report_static_data sends a response with the static data of the NFT item
virtual inline fun _report_static_data(msg: GetStaticData) {
let ctx: Context = context();
send(SendParameters {
to: ctx.sender,
value: 0,
mode: SendRemainingValue,
bounce: false,
body: ReportStaticData{
query_id: msg.query_id,
index: self.index,
collection: self.collection_address
}.toCell()
});
}

_get_nft_data(): NftData

取得符合 TEP-64 的 NFT data。

// @dev  _get_nft_data returns the NFT data in the format that complies with TEP-64
virtual inline fun _get_nft_data(): NftData {
let builder: StringBuilder = beginString();
let collectionData: String = self.individual_content.asSlice().asString();
builder.append(collectionData);
builder.append(self.index.toString());
builder.append(".json");

return NftData {
is_initialized: self.is_initialized,
index: self.index,
collection_address: self.collection_address,
owner_address: self.owner,
individual_content: builder.toCell()
};
}

Get Methods

get_nft_data(): NftData

取得 NFT data。

get fun get_nft_data(): NftData {
return self._get_nft_data();
}