NFT Item
This file provides traits for NFT items compliant with the TEP-0062 standard.
Reference:
Messages
Transfer
Initiates a transfer of the 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
Notifies about the assignment of ownership.
message(0x05138d91) OwnershipAssigned {
    query_id: Int as uint64;
    prev_owner: Address;
    forward_payload: Slice as remaining;
}
Excesses
Handles any excesses in the process.
message(0xd53276db) Excesses {
    query_id: Int as uint64;
}
GetStaticData
Requests static data of the NFT item.
message(0x2fcb26a2) GetStaticData {
    query_id: Int as uint64;
}
ReportStaticData
Reports the requested static data.
message(0x8b771735) ReportStaticData {
    query_id: Int as uint64;
    index: Int as uint256;
    collection: Address;
}
NftData Structure
Describes the data structure of an NFT.
struct NftData {
    is_initialized: Bool;         
    index: Int;                   
    collection_address: Address;  
    owner_address: Address;       
    individual_content: Cell;     
}
NFTItemStandard Trait
Trait encompassing standards for an 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)
Handles a transfer message, initiating the mint or transfer process.
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)
Handles a request for static data.
receive(msg: GetStaticData){
    self._report_static_data(msg);
}
Internal Functions
_transfer_estimate_rest_value(ctx: Context): Int
Calculates the remaining value to be returned to the previous owner.
// @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)
Validates the transfer request.
// @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)
Handles the minting process of an 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)
Executes the transfer, sending appropriate notifications.
// @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)
Responds with the static data of the NFT item.
// @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
Retrieves the NFT data in compliance with TEP-64.
// @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
Gets the NFT data.
get fun get_nft_data(): NftData {
    return self._get_nft_data();
}