Skip to main content

The Standard

In contrast with fungible tokens, non-fungible tokens (NFT) are unitary and therefore unique. This makes NFTs ideal to represent ownership of assets such as a piece of digital content, or a ticket for an event.

As with fungible tokens, NFTs are not stored in the user's wallet, instead, each NFT lives in a NFT contract. The NFT contract works as a bookkeeper, being in charge of creating, storing and transferring NFTs.

NFT & Marketplaces

Be mindful of not confusing an NFT with an NFT-marketplace. NFT simply store information (metadata), while NFT-marketplaces are contracts where NFT can be listed and exchanged for a price.


NEP-171 (NFT Interface)

NEP-171 is the blueprint for all non-fungible tokens on NEAR. It defines a common set of rules and functions that the contract MUST implement to be considered a non-fungible token contract.

tip

Notice that the NEP-171 defines the interface and expected behavior of a non-fungible token contract, but it does not dictate how the internal logic should be implemented

Different NFT contracts can have different internal implementations while still adhering to the NEP-171 standard


Interface

nft_token (read-only)

Returns the token information for a given token_id

nft_token(token_id: string): { token_id: string, owner_id: string } | null

nft_transfer

Transfers the token_id from the caller to the receiver_id, optionally the function can include a memo field to provide additional information to the contract

The caller must be the either the current owner of the token or an account that has been approved to transfer the token on behalf of the owner, such as a marketplace contract. The approval mechanism is defined in the NEP-178 standard.

Requirement: The caller must attach exactly 1 yoctoNEAR to the call

nft_transfer(receiver_id: string, token_id: string, approval_id?: number, memo: string?): void

nft_transfer_call

The function transfers the token_id to the receiver_id and calls the method nft_on_transfer(sender_id, previous_owner_id, token_id, msg) on receiver_id.

Optionally the function can include a memo for the NFT contract, and a msg field to which will be sent to the receiver contract.

📖 This function is useful to transfer NFTs to a contract and trigger some action on the receiver side in a single transaction, thus acting as attaching NFTs to a function call

nft_transfer_call(receiver_id: string, token_id: string, approval_id?: number, memo?: string, msg: string): Promise {}
nft_on_transfer

Smart contracts expecting to receive Non-Fungible Tokens must implement this method.

The method must return a boolean value indicating whether the token should be returned to the sender (true) or not (false).

nft_on_transfer(sender_id: string, previous_owner_id: string, token_id: string, msg: string): boolean

⚠️ Note that this method does not need to be implemented by the NFT contract itself, but rather by any contract that expects to receive non-fungible tokens


nft_resolve_transfer

This method is used as a callback to resolve the nft_transfer_call transaction, handling refunds if necessary.

It must return true if the token was successfully transferred to receiver_id, or false if the token was returned to owner_id.

nft_resolve_transfer(owner_id: string, receiver_id: string, token_id: string, approved_account_ids?: Record<string, number>): boolean

NEP-177 (NFT Metadata)

NEP-177 is an extension to the NEP-171 standard that defines the metadata for both non-fungible tokens and non-fungible token contracts.

Metadata provides key information , such as the contract's name or the NFT's title. Particularly, the following fields MUST be included in the smart contract and token's metadata:

type NFTContractMetadata = {
spec: string, // required, essentially a version like "nft-1.0.0"
name: string, // required, ex. "Mochi Rising — Digital Edition" or "Metaverse 3"
symbol: string, // required, ex. "MOCHI"
icon: string|null, // Data URL
base_uri: string|null, // Centralized gateway known to have reliable access to decentralized storage assets referenced by `reference` or `media` URLs
reference: string|null, // URL to a JSON file with more info
reference_hash: string|null, // Base64-encoded sha256 hash of JSON from reference field. Required if `reference` is included.
}

type TokenMetadata = {
title: string|null, // ex. "Arch Nemesis: Mail Carrier" or "Parcel #5055"
description: string|null, // free-form description
media: string|null, // URL to associated media, preferably to decentralized, content-addressed storage
media_hash: string|null, // Base64-encoded sha256 hash of content referenced by the `media` field. Required if `media` is included.
copies: number|null, // number of copies of this set of metadata in existence when token was minted.
issued_at: number|null, // When token was issued or minted, Unix epoch in milliseconds
expires_at: number|null, // When token expires, Unix epoch in milliseconds
starts_at: number|null, // When token starts being valid, Unix epoch in milliseconds
updated_at: number|null, // When token was last updated, Unix epoch in milliseconds
extra: string|null, // anything extra the NFT wants to store on-chain. Can be stringified JSON.
reference: string|null, // URL to an off-chain JSON file with more info.
reference_hash: string|null // Base64-encoded sha256 hash of JSON from reference field. Required if `reference` is included.
}

NEP-178 (NFT Approval Management)

NEP-178 is an extension to the NEP-171 standard that defines the approval management for non-fungible tokens.

The approval mechanism allows the owner of an NFT to authorize another account (for example, a marketplace contract) to transfer the token on their behalf.


Interface

nft_is_approved (read-only)

Returns whether an approved_account_id is actually approved to transfer the token_id on behalf of the token owner. If approval_id is provided, it will also check that the approval ID matches.

nft_is_approved(token_id: string, approved_account_id: string, approval_id?: number): boolean

nft_approve

Grants approval to account_id to transfer the token_id on behalf of the token owner. Optionally, the function can include a msg field to provide additional information to the contract.

Requirement: The caller must attach a deposit of at least 1 yoctoNEAR plus the storage cost for adding the new approval

nft_approve(token_id: string, account_id: string, msg?: string): void

nft_revoke

Revokes approval for account_id to transfer the token_id on behalf of the token owner.

Requirement: The caller must attach exactly 1 yoctoNEAR to the call

nft_revoke(token_id: string, account_id: string): void

nft_revoke_all

Revokes all approvals for the token_id.

Requirement: The caller must attach exactly 1 yoctoNEAR to the call

nft_revoke_all(token_id: string): void