Skip to main content

Winning an NFT

No one will enter an auction if there's nothing to win, so let's add a prize. Why not an 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:


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.

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

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.


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.

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.

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.


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.


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.


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

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}}' --accountId <accountId> --deposit 0.1 

You can also just buy an NFT with testnet $NEAR on a testnet marketplace like Mintbase.


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

Was this page helpful?