Minting NFTs
In this tutorial you'll learn how to easily create your own NFTs without doing any software development by using a readily-available smart contract and a decentralized storage solution like IPFS.
Overview
This article will guide you in setting up an NFT smart contract, and show you how to build, test and deploy your NFT contract on NEAR. Once the contract is deployed, you'll learn how to mint non-fungible tokens from media files stored on IPFS and view them in your Wallet.
Prerequisites
To complete this tutorial successfully, you'll need:
Wallet
To store your non-fungible tokens you'll need a NEAR Wallet. If you don't have one yet, you can create one easily by following these instructions.
Tip: for this tutorial we'll use a
testnet
wallet account. Thetestnet
network is free and there's no need to deposit funds.
Once you have your Wallet account, you can click on the Collectibles tab where all your NFTs will be listed:
IPFS
The InterPlanetary File System (IPFS) is a protocol and peer-to-peer network for storing and sharing data in a distributed file system. IPFS uses content-addressing to uniquely identify each file in a global namespace connecting all computing devices.
Uploading the image
To upload the NFT image, you should use a decentralized storage provider such as IPFS.
This example uses IPFS, but you could use a different solution like Filecoin, Arweave, or a regular centralized Web2 hosting.
Once you have uploaded your file to IPFS, you'll get a unique CID
for your content, and a URL like:
https://bafyreiabag3ztnhe5pg7js4bj6sxuvkz3sdf76cjvcuqjoidvnfjz7vwrq.ipfs.dweb.link/
Non-fungible Token contract
This repository includes an example implementation of a non-fungible token contract which uses near-contract-standards and simulation tests.
Clone the NFT repository
In your terminal run the following command to clone the NFT repo:
git clone https://github.com/near-examples/NFT
Explore the smart contract
The source code for this contract can be found in nft/src/lib.rs
. This contract contains logic which follows the NEP-171 standard (NEAR Enhancement Proposal) and the implementation of this standard which can be found here.
At first, the code can be a bit overwhelming, but if we only consider the aspects involved with minting, we can break it down into 2 main categories - the contract struct and the minting process.
Contract Struct
The contract keeps track of two pieces of information - tokens
and metadata
. For the purpose of this tutorial we will only deal with the tokens
field.
#[near(contract_state)]
#[derive(PanicOnDefault)]
pub struct Contract {
tokens: NonFungibleToken,
metadata: LazyOption<NFTContractMetadata>,
}
The tokens are of type NonFungibleToken
which come from the core standards. There are several fields that make up the struct but for the purpose of this tutorial, we'll only be concerned with the owner_by_id
field. This keeps track of the owner for any given token.
pub struct NonFungibleToken {
// owner of contract
pub owner_id: AccountId,
// keeps track of the owner for any given token ID.
pub owner_by_id: TreeMap<TokenId, AccountId>,
...
}
Now that we've explored behind the scenes and where the data is being kept, let's move to the minting functionality.
Minting
In order for a token to be minted you will need to call the nft_mint
function. There are three arguments that are passed to this function:
token_id
receiver_id
token_metadata
This function executes self.tokens.mint
which calls the mint function in the core standards creating a record of the token with the owner being receiver_id
.
#[payable]
pub fn nft_mint(
&mut self,
token_id: TokenId,
receiver_id: ValidAccountId,
token_metadata: TokenMetadata,
) -> Token {
self.tokens.mint(token_id, receiver_id, Some(token_metadata))
}
This creates that record by inserting the token into the owner_by_id
data structure that we mentioned in the previous section.
self.owner_by_id.insert(&token_id, &owner_id);
Building the contract
To build your contract run the following command in your terminal which builds your contract using Rust's cargo
.
./scripts/build.sh
This will generate WASM binaries into your res/
directory. This WASM file is the smart contract we'll be deploying onto the NEAR blockchain.
Tip: If you run into errors make sure you have Rust installed and are in the root directory of the NFT example.
Testing the contract
Written in the smart contract there are pre-written tests that you can run. Run the following command in your terminal to perform these simple tests to verify that your contract code is working.
cargo test -- --nocapture
Note: the more complex simulation tests aren't performed with this command but you can find them in
tests/sim
.