# Non-Fungible Token (NEP-171)

```rust
// The base structure that will be returned for a token. If contract is using
// extensions such as Approval Management, Metadata, or other
// attributes may be included in this structure.
type Token = {
   token_id: string,
   owner_id: string,
 }

/******************/
/* CHANGE METHODS */
/******************/

// Simple transfer. Transfer a given `token_id` from current owner to
// `receiver_id`.
//
// Requirements
// * Caller of the method must attach a deposit of 1 yoctoⓃ for security purposes
// * Contract MUST panic if called by someone other than token owner or,
//   if using Approval Management, one of the approved accounts
// * `approval_id` is for use with Approval Management extension, see
//   that document for full explanation.
// * If using Approval Management, contract MUST nullify approved accounts on
//   successful transfer.
//
// Arguments:
// * `receiver_id`: the valid NEAR account receiving the token
// * `token_id`: the token to transfer
// * `approval_id` (optional): expected approval ID. A number smaller than
//    2^53, and therefore representable as JSON. See Approval Management
//    standard for full explanation.
// * `memo` (optional): for use cases that may benefit from indexing or
//    providing information for a transfer
function nft_transfer(
  receiver_id: string,
  token_id: string,
  approval_id: number|null,
  memo: string|null,
) {}

// Transfer token and call a method on a receiver contract. A successful
// workflow will end in a success execution outcome to the callback on the NFT
// contract at the method `nft_resolve_transfer`.
//
// You can think of this as being similar to attaching native NEAR tokens to a
// function call. It allows you to attach any Non-Fungible Token in a call to a
// receiver contract.
//
// Requirements:
// * Caller of the method must attach a deposit of 1 yoctoⓃ for security
//   purposes
// * Contract MUST panic if called by someone other than token owner or,
//   if using Approval Management, one of the approved accounts
// * The receiving contract must implement `nft_on_transfer` according to the
//   standard. If it does not, FT contract's `nft_resolve_transfer` MUST deal
//   with the resulting failed cross-contract call and roll back the transfer.
// * Contract MUST implement the behavior described in `nft_resolve_transfer`
// * `approval_id` is for use with Approval Management extension, see
//   that document for full explanation.
// * If using Approval Management, contract MUST nullify approved accounts on
//   successful transfer.
//
// Arguments:
// * `receiver_id`: the valid NEAR account receiving the token.
// * `token_id`: the token to send.
// * `approval_id` (optional): expected approval ID. A number smaller than
//    2^53, and therefore representable as JSON. See Approval Management
//    standard for full explanation.
// * `memo` (optional): for use cases that may benefit from indexing or
//    providing information for a transfer.
// * `msg`: specifies information needed by the receiving contract in
//    order to properly handle the transfer. Can indicate both a function to
//    call and the parameters to pass to that function.
function nft_transfer_call(
  receiver_id: string,
  token_id: string,
  msg: string,
  approval_id: number|null,
  memo: string|null,
): Promise {}


/****************/
/* VIEW METHODS */
/****************/

// Returns the token with the given `token_id` or `null` if no such token.
function nft_token(token_id: string): Token|null {}

// Finalize an `nft_transfer_call` chain of cross-contract calls.
//
// The `nft_transfer_call` process:
//
// 1. Sender calls `nft_transfer_call` on NFT contract
// 2. NFT contract transfers token from sender to receiver
// 3. NFT contract calls `nft_on_transfer` on receiver contract
// 4+. [receiver contract may make other cross-contract calls]
// N. NFT contract resolves promise chain with `nft_resolve_transfer`, and may
//    transfer token back to sender
//
// Requirements:
// * Contract MUST forbid calls to this function by any account except self
// * If promise chain failed, contract MUST revert token transfer
// * If promise chain resolves with `true`, contract MUST return token to
//   `owner_id`
//
// Arguments:
// * `previous_owner_id`: the original owner of the NFT.
// * `receiver_id`: the `receiver_id` argument given to `nft_transfer_call`
// * `token_id`: the `token_id` argument given to `nft_transfer_call`
// * `approved_account_ids` (optional): if using Approval Management, contract MUST provide
//   record of original approved accounts in this argument, and restore these
//   approved accounts and their approval IDs in case of revert.
//
// Returns true if token was successfully transferred to `receiver_id`.
function nft_resolve_transfer(
  previous_owner_id: string,
  receiver_id: string,
  token_id: string,
  approved_account_ids: null|Record<string, number>,
): boolean {}

// Receiver Interface: Take some action after receiving a non-fungible token
//
// Requirements:
// * Contract MUST restrict calls to this function to a set of whitelisted NFT
//   contracts
//
// Arguments:
// * `sender_id`: the sender of `nft_transfer_call`
// * `previous_owner_id`: the account that owned the NFT prior to it being
//   transferred to this contract, which can differ from `sender_id` if using
//   Approval Management extension
// * `token_id`: the `token_id` argument given to `nft_transfer_call`
// * `msg`: information necessary for this contract to know how to process the
//   request. This may include method names and/or arguments.
//
// Returns true if token should be returned to `sender_id`
function nft_on_transfer(
  sender_id: string,
  previous_owner_id: string,
  token_id: string,
  msg: string,
): Promise<boolean>;
```

Example Implementation - [https://github.com/near/near-sdk-rs/blob/master/near-contract-standards/src/non\_fungible\_token/core/core\_impl.rs](https://github.com/near/near-sdk-rs/blob/master/near-contract-standards/src/non_fungible_token/core/core_impl.rs)
