> ## Documentation Index
> Fetch the complete documentation index at: https://docs.near.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Using NFTs

> Learn about NEAR non-fungible tokens (NFT) following NEP-171 and NEP-177 standards - mint, transfer, query, and trade unique digital assets with comprehensive examples.

export const TryOutOnLantstool = ({path, user = 'lantstool', repo = 'examples.near-protocol', branch = 'main'}) => {
  const lantstoolUrl = `https://app.lantstool.dev/import/gh/${user}/${repo}/${branch}/${path}`;
  const githubUrl = `https://github.com/${user}/${repo}/blob/${branch}/${path}`;
  const [code, setCode] = useState(null);
  function toRaw(ref) {
    const [org, repoName, , branchName, ...pathSeg] = new URL(ref).pathname.split('/').slice(1);
    return `https://raw.githubusercontent.com/${org}/${repoName}/${branchName}/${pathSeg.join('/')}`;
  }
  useEffect(() => {
    const rawUrl = toRaw(githubUrl);
    (async () => {
      try {
        let res;
        const validUntil = typeof window !== 'undefined' && localStorage.getItem(`${rawUrl}-until`);
        if (validUntil && Number(validUntil) > Date.now()) {
          res = localStorage.getItem(rawUrl);
        }
        if (!res) {
          res = await (await fetch(rawUrl)).text();
          if (typeof window !== 'undefined') {
            localStorage.setItem(rawUrl, res);
            localStorage.setItem(`${rawUrl}-until`, String(Date.now() + 60000));
          }
        }
        setCode(res);
      } catch {
        setCode('Error fetching code, please try reloading');
      }
    })();
  }, [githubUrl]);
  return <div>
      <p>
        Try it out on{' '}
        <a href={lantstoolUrl} target="_blank" rel="noopener noreferrer">
          Lantstool
        </a>
      </p>
      <div className="rounded-[0.625rem] border border-[#d0d7de] dark:border-[#30363d] overflow-hidden my-3 text-[0.8125rem] font-mono shadow-sm dark:shadow-[0_4px_24px_rgba(0,0,0,0.18)]">
        <div className="flex items-center gap-2 py-2 px-[0.875rem] bg-[#f6f8fa] dark:bg-[#161b22] border-b border-[#d0d7de] dark:border-[#30363d]">
          <svg width="15" height="15" viewBox="0 0 24 24" fill="currentColor" className="text-[#656d76] dark:text-[#8b949e]">
            <path d="M12 0C5.37 0 0 5.37 0 12c0 5.31 3.435 9.795 8.205 11.385.6.105.825-.255.825-.57 0-.285-.015-1.23-.015-2.235-3.015.555-3.795-.735-4.035-1.41-.135-.345-.72-1.41-1.23-1.695-.42-.225-1.02-.78-.015-.795.945-.015 1.62.87 1.845 1.23 1.08 1.815 2.805 1.305 3.495.99.105-.78.42-1.305.765-1.605-2.67-.3-5.46-1.335-5.46-5.925 0-1.305.465-2.385 1.23-3.225-.12-.3-.54-1.53.12-3.18 0 0 1.005-.315 3.3 1.23.96-.27 1.98-.405 3-.405s2.04.135 3 .405c2.295-1.56 3.3-1.23 3.3-1.23.66 1.65.24 2.88.12 3.18.765.84 1.23 1.905 1.23 3.225 0 4.605-2.805 5.625-5.475 5.925.435.375.81 1.095.81 2.22 0 1.605-.015 2.895-.015 3.3 0 .315.225.69.825.57A12.02 12.02 0 0 0 24 12c0-6.63-5.37-12-12-12z" />
          </svg>
          <span className="text-xs font-medium text-[#1f2328] dark:text-[#e6edf3]">
            {githubUrl.split('/').pop()}
          </span>
        </div>
        <div className="overflow-auto max-h-[480px] bg-white dark:bg-[#0d1117] [&_tr]:border-b-0 [&_td]:border-b-0">
          {code === null ? <div className="py-5 px-4 text-xs text-[#656d76] dark:text-[#6e7681]">Loading...</div> : <table className="w-full border-collapse leading-[1.6]">
              <tbody>
                {code.split('\n').map((line, i) => <tr key={i} className="align-top border-0">
                    <td style={{
    minWidth: '60px'
  }} className="select-none pl-2 pr-3 text-right text-[0.7rem] text-[#8c959f] dark:text-[#3d444d] w-[1%] whitespace-nowrap border-r border-0 border-r-[#d0d7de] dark:border-r-[#21262d]">
                      {i + 1}
                    </td>
                    <td className="pl-4 pr-6 text-[0.8125rem] text-[#1f2328] dark:text-[#e6edf3] whitespace-pre">
                      {line || ' '}
                    </td>
                  </tr>)}
              </tbody>
            </table>}
        </div>
      </div>
    </div>;
};

Wanting to use Non-Fungible Tokens (NFT) in your dApp? Here you will find all the information you need to get started creating your own tokens, registering users, transferring tokens, and integrating them into your smart contracts.

***

## Deploying a NFT Contract

If you want to deploy your own NFT contract, you can create one using our [reference implementation](https://github.com/near-examples/NFT).

<Tabs>
  <Tab title="🖥️ CLI">
    ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
    near deploy <account-id> --wasmFile contract.wasm --initFunction new
    ```
  </Tab>

  <Tab title="Lantstool" icon="https://mintcdn.com/neardocs/qO2GD-gji1aakHqN/assets/docs/tools/lantstool-logo-circle.svg?fit=max&auto=format&n=qO2GD-gji1aakHqN&q=85&s=e40405f8a9eda7a97dd89b9cc07a9ca9" width="100" height="100" data-path="assets/docs/tools/lantstool-logo-circle.svg">
    <TryOutOnLantstool path="docs/2.build/5.primitives/nft/deploy-nft-contract.json" />
  </Tab>
</Tabs>

### Global Contract

You can deploy a new Non-Fungible Token using our global NFT contract - a pre-deployed [standard NFT contract](https://github.com/near-examples/NFT) that you can reuse. [Global contracts](../../smart-contracts/global-contracts) are deployed once and can be reused by any account without incurring high storage costs.

<Tabs>
  <Tab title="By Account">
    ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
    near contract deploy <account-id> use-global-account-id nft.globals.primitives.testnet \
      with-init-call new \
      json-args '{"owner_id": "<account-id>", "metadata": {"spec": "nft-1.0.0", "name": "MY_NFT", "symbol": "NFT2000", "icon": "data:image/svg+xml,%3Csvg xmlns='\''http://www.w3.org/2000/svg'\'' viewBox='\''0 0 288 288'\''%3E%3Cg id='\''l'\'' data-name='\''l'\''%3E%3Cpath d='\''M187.58,79.81l-30.1,44.69a3.2,3.2,0,0,0,4.75,4.2L191.86,103a1.2,1.2,0,0,1,2,.91v80.46a1.2,1.2,0,0,1-2.12.77L102.18,77.93A15.35,15.35,0,0,0,90.47,72.5H87.34A15.34,15.34,0,0,0,72,87.84V201.16A15.34,15.34,0,0,0,87.34,216.5h0a15.35,15.35,0,0,0,13.08-7.31l30.1-44.69a3.2,3.2,0,0,0-4.75-4.2L96.14,186a1.2,1.2,0,0,1-2-.91V104.61a1.2,1.2,0,0,1,2.12-.77l89.55,107.23a15.35,15.35,0,0,0,11.71,5.43h3.13A15.34,15.34,0,0,0,216,201.16V87.84A15.34,15.34,0,0,0,200.66,72.5h0A15.35,15.35,0,0,0,187.58,79.81Z'\''/%3E%3C/g%3E%3C/svg%3E"}}' \
      prepaid-gas '100.0 Tgas' \
      attached-deposit '0 NEAR' \
      network-config testnet \
      sign-with-keychain \
      send
    ```
  </Tab>

  <Tab title="By Hash">
    ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
    near contract deploy <account-id> use-global-hash ivu1e9obVRnMJLSvVPRgtYefUYUS1L3f5eYHjS86zL9 \
      with-init-call new \
      json-args '{"owner_id": "<account-id>", "metadata": {"spec": "nft-1.0.0", "name": "MY_NFT", "symbol": "NFT2000", "icon": "data:image/svg+xml,%3Csvg xmlns='\''http://www.w3.org/2000/svg'\'' viewBox='\''0 0 288 288'\''%3E%3Cg id='\''l'\'' data-name='\''l'\''%3E%3Cpath d='\''M187.58,79.81l-30.1,44.69a3.2,3.2,0,0,0,4.75,4.2L191.86,103a1.2,1.2,0,0,1,2,.91v80.46a1.2,1.2,0,0,1-2.12.77L102.18,77.93A15.35,15.35,0,0,0,90.47,72.5H87.34A15.34,15.34,0,0,0,72,87.84V201.16A15.34,15.34,0,0,0,87.34,216.5h0a15.35,15.35,0,0,0,13.08-7.31l30.1-44.69a3.2,3.2,0,0,0-4.75-4.2L96.14,186a1.2,1.2,0,0,1-2-.91V104.61a1.2,1.2,0,0,1,2.12-.77l89.55,107.23a15.35,15.35,0,0,0,11.71,5.43h3.13A15.34,15.34,0,0,0,216,201.16V87.84A15.34,15.34,0,0,0,200.66,72.5h0A15.35,15.35,0,0,0,187.58,79.81Z'\''/%3E%3C/g%3E%3C/svg%3E"}}' \
      prepaid-gas '100.0 Tgas' \
      attached-deposit '0 NEAR' \
      network-config testnet \
      sign-with-keychain \
      send
    ```
  </Tab>
</Tabs>

<Note>
  Deploying by **hash** creates an immutable contract that never changes. Deploying by **account ID** creates an updatable contract that changes when the referenced account's contract is updated. Choose based on whether you want your FT contract to be updatable or permanent.
</Note>

***

## Minting a NFT

To create a new NFT (a.k.a. minting it) you will call the `nft_mint` method passing as arguments the metadata that defines the NFT.

<Tip>
  Use the [NEAR NFT Minting Tool](https://near.org/near/widget/ComponentDetailsPage?src=near/widget/NFTMint) to mint your own NFT directly from your browser.
</Tip>

<Accordion title="Manual Interaction">
  Here is how to directly interact with the factory contract through your application:

  <Tabs>
    <Tab title="🌐 WebApp">
      ```js theme={"theme":{"light":"github-light","dark":"github-dark"}}
      import { useNearWallet } from "near-connect-hooks";

      const CONTRACT_ADDRESS = 'nft.primitives.near';

      const { callFunction } = useNearWallet();

      await callFunction({
        contractId: CONTRACT_ADDRESS,
        method: 'nft_mint',
        args: {
          token_id: '1',
          receiver_id: 'bob.near',
          token_metadata: {
            title: 'NFT Primitive Token',
            description: 'Awesome NFT Primitive Token',
            media: 'string', // URL to associated media, preferably to decentralized, content-addressed storage
          },
        },
        deposit: 10000000000000000000000,
      });
      ```

      Learn more about adding [Near Connect](../../web3-apps/tutorials/wallet-login) to your application
    </Tab>

    <Tab title="🖥️ CLI">
      ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
      near call nft.primitives.near nft_mint '{"token_id": "1", "receiver_id": "bob.near", "token_metadata": {"title": "NFT Primitive Token", "description": "Awesome NFT Primitive Token", "media": "string"}}' --depositYocto 10000000000000000000000, --useAccount bob.near
      ```
    </Tab>

    <Tab title="Lantstool" icon="https://mintcdn.com/neardocs/qO2GD-gji1aakHqN/assets/docs/tools/lantstool-logo-circle.svg?fit=max&auto=format&n=qO2GD-gji1aakHqN&q=85&s=e40405f8a9eda7a97dd89b9cc07a9ca9" width="100" height="100" data-path="assets/docs/tools/lantstool-logo-circle.svg">
      <TryOutOnLantstool path="docs/2.build/5.primitives/nft/mint-nft-reference.json" />
    </Tab>

    <Tab title="📄 Contract">
      ```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
      // Validator interface, for cross-contract calls
      #[ext_contract(ext_nft_contract)]
      trait ExternalNftContract {
        fn nft_mint(&self, token_series_id: String, receiver_id: AccountId) -> Promise;
      }

      // Implement the contract structure
      #[near]
      impl Contract {
        #[payable]
        pub fn nft_mint(&mut self, token_series_id: String, receiver_id: AccountId) -> Promise {
          let promise = ext_nft_contract::ext(self.nft_contract.clone())
            .with_static_gas(Gas(30*TGAS))
            .with_attached_deposit(env::attached_deposit())
            .nft_mint(token_series_id, receiver_id);

          return promise.then( // Create a promise to callback query_greeting_callback
            Self::ext(env::current_account_id())
            .with_static_gas(Gas(30*TGAS))
            .nft_mint_callback()
          )
        }

        #[private] // Public - but only callable by env::current_account_id()
        pub fn nft_mint_callback(&self, #[callback_result] call_result: Result<TokenId, PromiseError>) -> Option<TokenId> {
          // Check if the promise succeeded
          if call_result.is_err() {
            log!("There was an error contacting NFT contract");
            return None;
          }

          // Return the token data
          let token_id: TokenId = call_result.unwrap();
          return Some(token_id);
        }
      }
      ```
    </Tab>
  </Tabs>

  <Info>
    See the [metadata standard](https://github.com/near/NEPs/tree/master/neps/nep-0177.md) for the full list of `TokenMetadata` parameters.
  </Info>

  <Warning>
    Values of gas and deposit might vary depending on which NFT contract you are calling.
  </Warning>
</Accordion>

<hr className="subsection" />

### Minting Collections

Many times people want to create multiple 100 copies of an NFT (this is called a collection). In such cases, what you actually need to do is to mint 100 different NFTs with the same metadata (but different `token-id`).

<Tip>
  Notice that [minting in Mintbase](#minting-a-nft) allows you to pass a `num_to_mint` parameter.
</Tip>

<hr className="subsection" />

### Royalties

You might have noticed that one of the parameters is a structure called royalties. Royalties enable you to create a list of users that should get paid when the token is sell in a marketplace. For example, if `anna` has `5%` of royalties, each time the NFT is sell, `anna` should get a 5% of the selling price.

***

## Querying NFT data

You can query the NFT's information and metadata by calling the `nft_token`.

<Tabs>
  <Tab title="🌐 WebApp">
    ```js theme={"theme":{"light":"github-light","dark":"github-dark"}}
    import { useNearWallet } from "near-connect-hooks";

    const CONTRACT_ADDRESS = 'nft.primitives.near';

    const { viewFunction } = useNearWallet();

    const response = await viewFunction({
      contractId: CONTRACT_ADDRESS,
      method: 'nft_token',
      args: {
        token_id: '1',
      },
    });
    ```

    Learn more about adding [Near Connect](../../web3-apps/tutorials/wallet-login) to your application

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

  <Tab title="🖥️ CLI">
    ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
    near view nft.primitives.near nft_token '{"token_id": "1"}'
    ```

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

  <Tab title="Lantstool" icon="https://mintcdn.com/neardocs/qO2GD-gji1aakHqN/assets/docs/tools/lantstool-logo-circle.svg?fit=max&auto=format&n=qO2GD-gji1aakHqN&q=85&s=e40405f8a9eda7a97dd89b9cc07a9ca9" width="100" height="100" data-path="assets/docs/tools/lantstool-logo-circle.svg">
    <TryOutOnLantstool path="docs/2.build/5.primitives/nft/query-nft-data-reference.json" />

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

  <Tab title="📄 Contract">
    ```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
    // Validator interface, for cross-contract calls
    #[ext_contract(ext_nft_contract)]
    trait ExternalNftContract {
      fn nft_token(&self, token_id: TokenId) -> Promise;
    }

    // Implement the contract structure
    #[near]
    impl Contract {
      pub fn nft_token(&self, token_id: TokenId) -> Promise {
        let promise = ext_nft_contract::ext(self.nft_contract.clone())
          .nft_token(token_id);

        return promise.then( // Create a promise to callback query_greeting_callback
          Self::ext(env::current_account_id())
          .nft_token_callback()
        )
      }

      #[private] // Public - but only callable by env::current_account_id()
      pub fn nft_token_callback(&self, #[callback_result] call_result: Result<Token, PromiseError>) -> Option<Token> {
        // Check if the promise succeeded
        if call_result.is_err() {
          log!("There was an error contacting NFT contract");
          return None;
        }

        // Return the token data
        let token_data: Token = call_result.unwrap();
        return Some(token_data);
      }
    }
    ```
  </Tab>
</Tabs>

***

## Transferring a NFT

Transferring an NFT can happen in two scenarios: (1) you ask to transfer an NFT, and (2) an [authorized account](#approving-users) asks to transfer the NFT.

In both cases, it is necessary to invoke the `nft_transfer` method, indicating the token id, the receiver, and an (optionally) an [approval\_id](https://github.com/near/NEPs/tree/master/neps/nep-0178.md).

<Tabs>
  <Tab title="🌐 WebApp">
    ```js theme={"theme":{"light":"github-light","dark":"github-dark"}}
    import { useNearWallet } from "near-connect-hooks";

    const CONTRACT_ADDRESS = 'nft.primitives.near';

    const { callFunction } = useNearWallet();

    await callFunction({
      contractId: CONTRACT_ADDRESS,
      method: 'nft_transfer',
      args: {
        token_id: '1',
        receiver_id: 'bob.near',
      },
      deposit: 1,
    });
    ```

    Learn more about adding [Near Connect](../../web3-apps/tutorials/wallet-login) to your application
  </Tab>

  <Tab title="🖥️ CLI">
    ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
      near call nft.primitives.near nft_transfer '{"token_id": "1", "receiver_id": "bob.near"}' --useAccount bob.near --deposit 0.000000000000000000000001
    ```
  </Tab>

  <Tab title="Lantstool" icon="https://mintcdn.com/neardocs/qO2GD-gji1aakHqN/assets/docs/tools/lantstool-logo-circle.svg?fit=max&auto=format&n=qO2GD-gji1aakHqN&q=85&s=e40405f8a9eda7a97dd89b9cc07a9ca9" width="100" height="100" data-path="assets/docs/tools/lantstool-logo-circle.svg">
    <TryOutOnLantstool path="docs/2.build/5.primitives/nft/transfer-nft-reference.json" />
  </Tab>

  <Tab title="📄 Contract">
    <Info>
      Please notice that a contract can only transfer an NFT that they own, or an NFT that they were approved to transfer.
    </Info>

    ```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
    const YOCTO_NEAR: u128 = 1;

    #[ext_contract(ext_nft_contract)]
    trait ExternalNftContract {
      fn nft_transfer(&self, receiver_id: AccountId, token_id: TokenId) -> Promise;
    }

    impl Contract {
      #[payable]
      pub fn nft_transfer(&mut self, receiver_id: AccountId, token_id: TokenId) -> Promise {
        let promise = ext_nft_contract::ext(self.nft_contract.clone())
          .with_attached_deposit(YOCTO_NEAR)
          .nft_transfer(receiver_id, token_id);

        return promise.then( // Create a promise to callback query_greeting_callback
          Self::ext(env::current_account_id())
          .nft_transfer_callback()
        )
      }

      #[private] // Public - but only callable by env::current_account_id()
      pub fn nft_transfer_callback(&self, #[callback_result] call_result: Result<(), PromiseError>) {
        // Check if the promise succeeded
        if call_result.is_err() {
          log!("There was an error contacting NFT contract");
        }
      }
    }
    ```
  </Tab>
</Tabs>

***

## Attaching NFTs to a Call

Natively, only NEAR tokens (Ⓝ) can be attached to a function calls. However, the NFT standard enables to attach a non-fungible tokens in a call by using the NFT-contract as intermediary. This means that, instead of you attaching tokens directly to the call, you ask the NFT-contract to do both a transfer and a function call in your name.

<Tabs>
  <Tab title="🖥️ CLI">
    ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
    near call <nft-contract> nft_transfer_call '{"receiver_id": "<receiver-contract>", "token_id": "<token_id>", "msg": "<a-string-message>"}' --useAccount <your-account> --depositYocto 1
    ```
  </Tab>

  <Tab title="Lantstool" icon="https://mintcdn.com/neardocs/qO2GD-gji1aakHqN/assets/docs/tools/lantstool-logo-circle.svg?fit=max&auto=format&n=qO2GD-gji1aakHqN&q=85&s=e40405f8a9eda7a97dd89b9cc07a9ca9" width="100" height="100" data-path="assets/docs/tools/lantstool-logo-circle.svg">
    <TryOutOnLantstool path="docs/2.build/5.primitives/nft/attach-nft-to-call.json" />
  </Tab>
</Tabs>

<Info>
  Optionally, a [`memo` parameter](https://github.com/near/NEPs/tree/master/neps/nep-0171.md#nft-interface) can be passed to provide more information to your contract.
</Info>

<hr className="subsection" />

### How Does it Work?

Assume you want to attach an NFT (🎫) to a call on the receiver contract. The workflow is as follows:

1. You call `nft_transfer_call` in the NFT-contract passing: the receiver, a message, and the token-id of 🎫.
2. The NFT contract transfers the NFT 🎫 to the receiver.
3. The NFT contract calls **`receiver.nft_on_transfer(sender, token-owner, token-id, msg)`**.
4. The NFT contract handles errors in the `nft_resolve_transfer` callback.
5. The NFT contract returns `true` if it succeeded.

#### The nft\_on\_transfer method

From the workflow above it follows that the receiver we want to call needs to implement the `nft_on_transfer` method. When executed, such method will know:

* Who is sending the NFT, since it is a parameter
* Who is the current owner, since it is a parameter
* Which NFT was transferred, since it is a parameter.
* If there are any parameters encoded as a message

The `nft_on_transfer` **must return true** if the NFT has to be **returned to the sender**.

***

## Approving Users

You can authorize other users to transfer an NFT you own. This is useful, for example, to enable listing your NFT in a marketplace. In such scenario, you **trust** that the marketplace will only transfer the NFT upon receiving a certain amount of money in exchange.

<Tabs>
  <Tab title="🖥️ CLI">
    ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
    near call <nft-contract> nft_approve '{
    "token_id": "<token-unique-id>",
    "account_id": "<authorized-account>",
    "msg": "<json-structure>"
    }' --useAccount <your-account> --depositYocto 1
    ```
  </Tab>

  <Tab title="Lantstool" icon="https://mintcdn.com/neardocs/qO2GD-gji1aakHqN/assets/docs/tools/lantstool-logo-circle.svg?fit=max&auto=format&n=qO2GD-gji1aakHqN&q=85&s=e40405f8a9eda7a97dd89b9cc07a9ca9" width="100" height="100" data-path="assets/docs/tools/lantstool-logo-circle.svg">
    <TryOutOnLantstool path="docs/2.build/5.primitives/nft/approve-user.json" />
  </Tab>
</Tabs>

<Info>
  If the `msg` parameter is included, then a cross-contract call will be made to `<authorized_account>.nft_on_approve(msg)`. Which in turn will make a callback to `nft_resolve_transfer` in your NFT contract.
</Info>

***

## Burn Tokens

While the NFT standard does not define a `burn` method, you can simply transfer tokens to an account that no one controls, such as [`0000000000000000000000000000000000000000000000000000000000000000`](https://nearblocks.io/es/address/0000000000000000000000000000000000000000000000000000000000000000) (64 zeros).

<Tabs>
  <Tab title="🌐 WebApp">
    ```js theme={"theme":{"light":"github-light","dark":"github-dark"}}
    import { useNearWallet } from "near-connect-hooks";

    const { callFunction } = useNearWallet();

    await callFunction({
      contractId: 'nft.primitives.near',
      method: 'nft_transfer',
      args: {
        token_id: '1',
        receiver_id: '0000000000000000000000000000000000000000000000000000000000000000',
      },
      deposit: 1,
    });
    ```

    Learn more about adding [Near Connect](../../web3-apps/tutorials/wallet-login) to your application
  </Tab>

  <Tab title="🖥️ CLI">
    ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
      near call nft.primitives.near nft_transfer '{"token_id": "1", "receiver_id": "0000000000000000000000000000000000000000000000000000000000000000"}' --useAccount bob.near --deposit 0.000000000000000000000001
    ```
  </Tab>
</Tabs>

***

## Tutorials

* [NFT Tutorial](/smart-contracts/tutorials/zero-to-hero/nfts-js) *Zero to Hero* (JavaScript SDK) - a set of tutorials that cover how to create a NFT contract using JavaScript.
* [NFT Tutorial](/smart-contracts/tutorials/zero-to-hero/nfts) *Zero to Hero* (Rust SDK) - a set of tutorials that cover how to create a NFT contract using Rust.
