> ## 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.

# Winning an NFT

> Lets make the auction winner get an NFT.

export const Github = ({url, start, end, fname, withSourceLink = true}) => {
  const [code, setCode] = useState(null);
  function toRaw(ref) {
    const fullUrl = ref.slice(ref.indexOf('https'));
    const [url] = fullUrl.split('#');
    const [org, repo, , branch, ...pathSeg] = new URL(url).pathname.split('/').slice(1);
    return `https://raw.githubusercontent.com/${org}/${repo}/${branch}/${pathSeg.join('/')}`;
  }
  async function fetchCode(url, fromLine, toLine) {
    let res;
    if (typeof window !== 'undefined') {
      const validUntil = localStorage.getItem(`${url}-until`);
      if (validUntil && Number(validUntil) > Date.now()) {
        res = localStorage.getItem(url);
      }
    }
    if (!res) {
      try {
        res = await (await fetch(url)).text();
        if (typeof window !== 'undefined') {
          localStorage.setItem(url, res);
          localStorage.setItem(`${url}-until`, String(Date.now() + 60000));
        }
      } catch {
        return 'Error fetching code, please try reloading';
      }
    }
    let body = res.split('\n');
    const from = fromLine ? Number(fromLine) - 1 : 0;
    const to = toLine ? Number(toLine) : body.length;
    body = body.slice(from, to);
    const precedingSpace = body.reduce((prev, line) => {
      if (line.length === 0) return prev;
      const spaces = line.match(/^\s+/);
      if (spaces) return Math.min(prev, spaces[0].length);
      return 0;
    }, Infinity);
    return body.map(line => line.slice(precedingSpace === Infinity ? 0 : precedingSpace)).join('\n');
  }
  function buildSourceUrl(url, start, end) {
    const base = url.split('#')[0];
    if (start && end) return `${base}#L${start}-L${end}`;
    if (start) return `${base}#L${start}`;
    return base;
  }
  useEffect(() => {
    const rawUrl = toRaw(url);
    fetchCode(rawUrl, start, end).then(res => setCode(res));
  }, [url, start, end]);
  const sourceUrl = buildSourceUrl(url, start, end);
  const startLine = start ? Number(start) : 1;
  const fileName = fname ?? sourceUrl.split('/').pop();
  return <div className="rounded-[0.625rem] border border-[#d0d7de] dark:border-[#30363d] overflow-hidden my-5 text-[0.8125rem] font-mono shadow-sm dark:shadow-[0_4px_24px_rgba(0,0,0,0.18)]">

      {}
      <div className="flex items-center justify-between py-2 px-[0.875rem] bg-[#f6f8fa] dark:bg-[#161b22] border-b border-[#d0d7de] dark:border-[#30363d]">
        <div className="flex items-center gap-2 text-[#656d76] dark:text-[#8b949e]">
          <svg width="15" height="15" viewBox="0 0 24 24" fill="currentColor">
            <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]">
            {fileName}
          </span>
        </div>
        {start && end && <span className="text-[0.6875rem] text-[#656d76] dark:text-[#8b949e] bg-[#eaeef2] dark:bg-[#21262d] border border-[#d0d7de] dark:border-[#30363d] rounded-full py-0.5 px-2">
            Lines {start}–{end}
          </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]">
                    {startLine + i}
                  </td>
                  <td className="pl-4 pr-6 text-[0.8125rem] text-[#1f2328] dark:text-[#e6edf3] whitespace-pre">
                    {line || ' '}
                  </td>
                </tr>)}
            </tbody>
          </table>}
      </div>

      {}
      {withSourceLink && <div className="flex justify-end py-1.5 px-[0.875rem] bg-[#f6f8fa] dark:bg-[#161b22] border-t border-[#d0d7de] dark:border-[#21262d]">
          <a href={sourceUrl} target="_blank" rel="noreferrer noopener" className="text-[0.6875rem] font-medium text-[#656d76] dark:text-[#8b949e] no-underline flex items-center gap-[0.3rem] hover:text-[#1f2328] dark:hover:text-[#e6edf3] transition-colors">
            View on GitHub
            <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
              <path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" />
              <polyline points="15 3 21 3 21 9" />
              <line x1="10" y1="14" x2="21" y2="3" />
            </svg>
          </a>
        </div>}
    </div>;
};

No one will enter an auction if there's nothing to win, so let's add a prize. Why not an [NFT](/primitives/nft/nft)? NFTs are uniquely identifiable, easily swappable and their logic comes from an external contract so the prize will exist without the auction contract. Let's get to work!

***

## Listing the NFT

When we create an auction we need to list the NFT. To specify which NFT is being auctioned off we need the account ID of the NFT contract and the token ID of the NFT. We will specify these when the contract is initialized; amend `init` to add `nft_contract` and `token_id` as such:

<Tabs>
  <Tab title="🌐 JavaScript">
    <Github fname="main.ava.js" language="javascript" url="https://github.com/near-examples/auctions-tutorial/blob/main/contract-ts/02-winner-gets-nft/src/contract.ts#L22-L28" start="22" end="28" />
  </Tab>

  <Tab title="🦀 Rust">
    <Github fname="lib.rs" language="rust" url="https://github.com/near-examples/auctions-tutorial/blob/main/contract-rs/02-winner-gets-nft/src/lib.rs#L32-L49" start="32" end="49" />

    Note that `token_id` is of type `TokenId` which is a String type alias that the NFT standards use for future-proofing.
  </Tab>
</Tabs>

***

## Transferring the NFT to the winner

When the method `claim` is called the NFT needs to be transferred to the highest bidder. Operations regarding NFTs live on the NFT contract, so we make a cross-contract call to the NFT contract telling it to swap the owner of the NFT to the highest bidder. The method on the NFT contract to do this is `nft_transfer`.

<Tabs>
  <Tab title="🌐 JavaScript">
    <Github fname="contract.ts" language="javascript" url="https://github.com/near-examples/auctions-tutorial/blob/main/contract-ts/02-winner-gets-nft/src/contract.ts#L58-L60" start="58" end="60" />

    In near-sdk-js we cannot transfer the NFT and send the `$NEAR` independently so we will chain the promises.
  </Tab>

  <Tab title="🦀 Rust">
    We will create a new file in our source folder named `ext.rs`; here we are going to define the interface for the `nft_transfer` method. We define this interface as a `trait` and use the `ext_contract` macro to convert the NFT trait into a module with the method `nft_transfer`. Defining external methods in a separate file helps improve the readability of our code.

    We then use this method in our `lib.rs` file to transfer the NFT.

    <Github fname="lib.rs" url="https://github.com/near-examples/auctions-tutorial/blob/main/contract-rs/02-winner-gets-nft/src/lib.rs#L93-L96" start="93" end="96" />

    <Github fname="ext.rs" url="https://github.com/near-examples/auctions-tutorial/blob/main/contract-rs/02-winner-gets-nft/src/ext.rs" start="2" end="10" />
  </Tab>
</Tabs>

When calling this method we specify the NFT contract name, that we are attaching 30 Tgas to the call, that we are attaching a deposit of 1 YoctoNEAR to the call, and give the arguments `receiver_id` and `token_id`. The NFT requires that we attach 1 YoctoNEAR for [security reasons](/smart-contracts/security/one_yocto).

***

## NFT ownership problems

In our contract, we perform no checks to verify whether the contract actually owns the specified NFT. A bad actor could set up an auction where the NFT being auctioned doesn't belong to the auction contract, causing `nft_transfer` to fail and the winning bidder to lose their bid funds with nothing in return. We could make a cross-contract call to the NFT contract to verify ownership on initialization but this would become quite complex. Instead, we will do this check off-chain and validate the auction in the frontend.

***

## Displaying the contract object

Since we are now dealing with more information in our contract, instead of implementing a function to display each field we'll create a function to display the entire contract object. Since the contract doesn't include large complex data structures like a map displaying the contract state in its entirety is easily done.

<Tabs>
  <Tab title="🌐 JavaScript">
    <Github fname="main.ava.js" language="javascript" url="https://github.com/near-examples/auctions-tutorial/blob/main/contract-ts/02-winner-gets-nft/src/contract.ts#L73-L76" start="73" end="76" />
  </Tab>

  <Tab title="🦀 Rust">
    <Github fname="lib.rs" language="rust" url="https://github.com/near-examples/auctions-tutorial/blob/main/contract-rs/02-winner-gets-nft/src/lib.rs#L17-L26" start="17" end="26" />

    We add the `serilizers` macro to enable json serialization so the object as a whole can easily be displayed to the frontend without having to output each field individually.

    <Github fname="lib.rs" language="rust" url="https://github.com/near-examples/auctions-tutorial/blob/main/contract-rs/02-winner-gets-nft/src/lib.rs#L107-L109" start="107" end="109" />
  </Tab>
</Tabs>

## Testing with multiple contracts

In our tests, we're now going to be using two contracts; the auction contract and an NFT contract. Sandbox testing is great as it allows us to test multiple contracts in a realistic environment.

In our tests folder, we need the WASM for an NFT contract. For this tutorial, we compiled an example NFT contract from [this repo](https://github.com/near-examples/NFT/tree/master).

To deploy the NFT contract, this time we're going to use `dev deploy` which creates an account with a random ID and deploys the contract to it by specifying the path to the WASM file. After deploying we will initialize the contract with default metadata and specify an account ID which will be the owner of the NFT contract (though the owner of the NFT contract is irrelevant in this example). Default metadata sets information such as the name and symbol of the NFT contract to default values.

<Tabs>
  <Tab title="🌐 JavaScript">
    <Github fname="main.ava.js" language="javascript" url="https://github.com/near-examples/auctions-tutorial/blob/main/contract-ts/02-winner-gets-nft/sandbox-test/main.ava.js#L24-L25" start="24" end="25" />
  </Tab>

  <Tab title="🦀 Rust">
    <Github fname="test_basics.rs" language="rust" url="https://github.com/near-examples/auctions-tutorial/blob/main/contract-rs/02-winner-gets-nft/tests/test_basics.rs#L30-L39" start="30" end="39" />
  </Tab>
</Tabs>

***

## Minting an NFT

To start a proper auction the auction contract should own an NFT. To do this the auction account calls the NFT contract to mint a new NFT providing information such as the image for the NFT.

<Tabs>
  <Tab title="🌐 JavaScript">
    <Github fname="main.ava.js" language="javascript" url="https://github.com/near-examples/auctions-tutorial/blob/main/contract-ts/02-winner-gets-nft/sandbox-test/main.ava.js#L28-L39" start="28" end="39" />
  </Tab>

  <Tab title="🦀 Rust">
    <Github fname="test_basics.rs" language="rust" url="https://github.com/near-examples/auctions-tutorial/blob/main/contract-rs/02-winner-gets-nft/tests/test_basics.rs#L42-L60" start="42" end="60" />
  </Tab>
</Tabs>

***

## Verifying ownership of an NFT

After `claim` is called, the test should verify that the auction winner now owns the NFT. This is done by calling `nft_token` on the NFT contract and specifying the token ID which will return the account ID that the token belongs to.

<Tabs>
  <Tab title="🌐 JavaScript">
    <Github fname="main.ava.js" language="javascript" url="https://github.com/near-examples/auctions-tutorial/blob/main/contract-ts/02-winner-gets-nft/sandbox-test/main.ava.js#L105-L106" start="105" end="106" />
  </Tab>

  <Tab title="🦀 Rust">
    <Github fname="test_basics.rs" language="rust" url="https://github.com/near-examples/auctions-tutorial/blob/main/contract-rs/02-winner-gets-nft/tests/test_basics.rs#L151-L164" start="151" end="164" />
  </Tab>
</Tabs>

***

## Getting an NFT

If you would like to interact with the new contract via the CLI you can mint an NFT from a pre-deployed NFT contract

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
near call nft.examples.testnet nft_mint '{"token_id": "TYPE_A_UNIQUE_VALUE_HERE", "receiver_id": "<accountId>", "metadata": { "title": "GO TEAM", "description": "The Team Goes", "media": "https://bafybeidl4hjbpdr6u6xvlrizwxbrfcyqurzvcnn5xoilmcqbxfbdwrmp5m.ipfs.dweb.link/", "copies": 1}}' --useAccount <accountId> --deposit 0.1 
```

***

## Conclusion

In this part of the tutorial we have added NFTs as a reward which has taught us how to interact with NFT standards, make cross-contract calls and test multiple contracts that interact with each other in workspaces. In the [next part](./3.2-ft) we'll learn how to interact with fungible token standards by adapting the auction to receive bids in FTs. This will allow users to launch auctions in different tokens, including stablecoins.
