Native Assets and NFTs

Minting assets and NFTs on Cardano refers to the process of creating and managing custom tokens or digital assets on the Cardano blockchain. These tokens can represent a variety of assets, such as cryptocurrencies, loyalty points, or even real-world assets like property or art.

Table of Content

Introduction

The process of minting assets on Cardano is relatively straightforward and can be done using the Cardano command-line interface (CLI) or through third-party tools like the Cardano Token Builder. In this guide, we will look into how to mint assets using the cardano-cli connection to our own cardano-node

Here are the basic steps involved in minting assets on Cardano:

  • Create a wallet: You will need to create a Cardano wallet that supports the minting of tokens. We created two wallets in the previous steps which we will use for this.
  • Generate a policy: You will need to generate a policy that defines the rules for the token that you want to create. This includes things like the token's name, symbol, total supply, and whether it is divisible or not.
  • Mint the token: Once you have generated the policy, you can use the cardano-cli or a third-party tool to mint the token on the Cardano blockchain. This involves submitting a transaction that specifies the policy and the number of tokens to be minted.
  • Manage the token: After the token has been minted, you can manage it using your Cardano wallet or a third-party tool. This includes tasks like sending or receiving the token, setting permissions for who can hold or trade the token, and updating the token's policy.

Difference between Tokens and NFTs

What is the difference between native assets and NFTs? From a technical point of view, NFTs are the same as native assets. But some additional characteristics make a native asset truly an NFT:

  • It must be 'non-fungible. This means you need to have unique identifiers or attributes attached to a token to make it distinguishable from others.
  • NFT's should live on the chain forever. Therefore we need some mechanism to ensure an NFT stays unique and can not be duplicated.

Since asset names are not unique and can be easily duplicated, Cardano NFTs need to be identified by the policyID. This ID is unique and attached permanently to the asset. The policy ID stems from a policy script that defines characteristics such as who can mint tokens and when those actions can be made.

Many NFT projects make the policyID under which the NFTs were minted publicly available, so anyone can differentiate fraudulent/duplicate NFTs from the original tokens.

Some services even offer to register your policyID to detect tokens that feature the same attributes as your token but were minted under a different policy.

IPFS

IPFS is a peer-to-peer (P2P) protocol and network designed to create a decentralized and distributed system for storing and sharing files.

IPFS is an alternative to the traditional client-server model of the internet, where files are stored on central servers and accessed by clients. Instead, IPFS uses a P2P network where files are stored across a distributed network of nodes. This means that files can be accessed quickly and efficiently from multiple locations, reducing the risk of data loss due to a single point of failure.

We will use IPFS to store the image on the internet, to make sure that it is stored in a decentralized manner

Here are some key features and benefits of IPFS:

  • Decentralization: IPFS is designed to be a decentralized network, which means that files are stored and accessed from multiple locations instead of a single central server. This reduces the risk of data loss or corruption due to a single point of failure.
  • Distributed Storage: IPFS stores files across a distributed network of nodes, which means that files can be accessed quickly and efficiently from multiple locations.
  • Content Addressing: IPFS uses content addressing, where files are identified by their content rather than their location. This makes it easier to access and share files, even if the original source is no longer available.
  • Version Control: IPFS supports version control, which means that multiple versions of the same file can be stored and accessed.
  • Immutable: IPFS is designed to create immutable files that cannot be modified once they are added to the network. This makes it a useful tool for creating permanent archives of data or for storing sensitive information that needs to be protected.

Overall, IPFS is an innovative and powerful technology that offers a range of benefits, including decentralization, distributed storage, content addressing, version control, and immutability.

Pinata IPFS

We will use Pinata for storing the image of the NFT online

Pinata IPFS is a cloud-based platform that provides easy and affordable access to the InterPlanetary File System (IPFS) network. It is designed to simplify the process of storing, sharing, and accessing files on the IPFS network.

With Pinata IPFS, users can upload their files to the platform, which then automatically distributes and replicates the files across multiple IPFS nodes. This ensures that the files are always available, even if one or more nodes go offline.

Create a free account and upload your image that we will turn into an NFT in the next steps.

After you upload your image, you should see a special code that identifies your image on the IPFS, something like this QmPanjt7mQWKmySWddGSvx8iyRDWNSGVn4W3KqHGcE4KiU and you can view it a web browser by constructing a link with it, like this:

https://ipfs.io/ipfs/QmPanjt7mQWKmySWddGSvx8iyRDWNSGVn4W3KqHGcE4KiU

Mint an NFT

Check your Keys

We will do the mint in a very technical way so you get familiar with using the Cardano infrastructure and interacting with the cardano-node. If you are after a quick'n'easy way of minting NFTs on the mainnet then search for a minting service on Cardano, there are multiply available.

You will need the payment keys and the address that you generated earlier in the workshop. Make sure that the following files are present in your working directory:

payment.skey
payment.vkey
payment.addr

Create NFT name

You will need to give your NFT a name. Set this as a variable by running the following in the terminal. The token name should be in hex format. We will set the variable $realtokenname and then convert it to $tokenname (name in hex format)

realtokenname="GUINCHO"
tokenname=$(echo -n $realtokenname | xxd -b -ps -c 80 | tr -d '\n')
tokenamount="1"
fee="0"
output="0"

We also set the token amount at 1 to ensure this is an NFT. The fee amount and output are set as placeholders, for now, they will get populated in the next steps

Set the IPFS code that you received when you uploaded your picture to Pinata IPFS

ipfs_hash="QmPanjt7mQWKmySWddGSvx8iyRDWNSGVn4W3KqHGcE4KiU"

Generate Policy Script

First generate the policy keys

cardano-cli address key-gen \
    --verification-key-file policy.vkey \
    --signing-key-file policy.skey

The policy script will only be valid for a few minutes, after which no additional minting will be possible with the same policy script. For this we need to find out the latest tip of the blockchain and set the deadline a few minutes ahead

cardano-cli query tip --testnet-magic 2
slotnumber=<slot number>

Create the policy.script file

echo "{" >> policy.script
echo "  \"type\": \"all\"," >> policy.script 
echo "  \"scripts\":" >> policy.script 
echo "  [" >> policy.script 
echo "   {" >> policy.script 
echo "     \"type\": \"before\"," >> policy.script 
echo "     \"slot\": $(expr $slotnumber + 43200)" >> policy.script
echo "   }," >> policy.script 
echo "   {" >> policy.script
echo "     \"type\": \"sig\"," >> policy.script 
echo "     \"keyHash\": \"$(cardano-cli address key-hash --payment-verification-key-file policy.vkey)\"" >> policy.script 
echo "   }" >> policy.script
echo "  ]" >> policy.script 
echo "}" >> policy.script

Set the script name to the file name, run this in the teminal

script="policy.script"

Generate the policyID from the policy.script

cardano-cli transaction policyid --script-file policy.script > policyID

Create Metadata

Tokens and NFTs on Cardano are a part of the ledger. Unlike on Ethereum, where metadata can be attached to a token through a smart contract, this isn't possible on Cardano because tokens are native and Cardano uses a UTXO ledger, which makes it hard to directly attach metadata to a token. So the link to the metadata needs to be established differently. Cardano has the ability to send metadata in a transaction, that's the way we can create a link between a token and the metadata. To make the link unique, the metadata should be appended to the same transaction when minting the token or NFT.

The following command creates a file with the Metadata. You should replace the description with something more appropriate to your image (e.g. "my favourite image ...")

echo "{" >> metadata.json
echo "  \"721\": {" >> metadata.json 
echo "    \"$(cat policyID)\": {" >> metadata.json 
echo "      \"$(echo $realtokenname)\": {" >> metadata.json
echo "        \"description\": \"Guincho in Cascais, Portugal, overlooking the Sintra mountain\"," >> metadata.json
echo "        \"name\": \"Guincho NFT\"," >> metadata.json
echo "        \"id\": \"1\"," >> metadata.json
echo "        \"image\": \"ipfs://$(echo $ipfs_hash)\"" >> metadata.json
echo "      }" >> metadata.json
echo "    }" >> metadata.json 
echo "  }" >> metadata.json 
echo "}" >> metadata.json

Build the Minting Transaction

Let's begin building our transaction. Before we start, we will again need some setup to make the transaction building easier. Query your payment address and take note of the different values present.

cardano-cli query utxo \
--address $(cat payment.addr) \
--testnet-magic 2

Your output should look something like this (fictional example):

                           TxHash                                 TxIx        Amount
--------------------------------------------------------------------------------------
b35a4ba9ef3ce21adcd6879d08553642224304704d206c74d3ffb3e6eed3ca28     0        1000000000 lovelace

Since we need each of those values in our transaction, we will store them individually in a corresponding variable:

txhash="b35a4ba9ef3ce21adcd6879d08553642224304704d206c74d3ffb3e6eed3ca28"
txix="0"
funds="1000000000"
policyid=$(cat policyID)
output=1400000

Here we are setting the output value to 1400000 Lovelace which is equivalent to 1.4 ADA. This amount is used because this is the minimum UTxO requirement.

If you're unsure, check if all of the other needed variables for the transaction are set, each echo should return a value, if something is missing, please make sure to go over all of the previous steps:

echo $fee
echo $address
echo $output
echo $tokenamount
echo $policyid
echo $tokenname
echo $slotnumber
echo $script

Build the transaction

cardano-cli transaction build \
--testnet-magic 2 \
--alonzo-era \
--tx-in $txhash#$txix \
--tx-out $address+$output+"$tokenamount $policyid.$tokenname" \
--change-address $address \
--mint="$tokenamount $policyid.$tokenname" \
--minting-script-file $script \
--metadata-json-file metadata.json  \
--invalid-hereafter $(expr $slotnumber + 43200) \
--witness-override 2 \
--out-file matx.raw

If the transaction gives an error and says something like Minimum required UTxO: Lovelace 1448244, then change your output amount to that larger number. After successfully running it should show you the estimated transaction fee Estimated transaction fee: Lovelace 187941

Sign the Transaction

Sign the built transaction with your payment key and the policy key

cardano-cli transaction sign  \
--signing-key-file payment.skey  \
--signing-key-file policy.skey  \
--testnet-magic 1097911063 \
--tx-body-file matx.raw  \
--out-file matx.signed

Submit the Transaction

cardano-cli transaction submit --tx-file matx.signed --testnet-magic 2

If you get Transaction successfully submitted. then it means that everything worked as planned, and your NFT has been minted and will appear in your wallet once the transaction is included in the next block  

Check the UTXO at your wallet address, you should see a new line added with the name of your NFT

cardano-cli query utxo \
--address $(cat payment.addr) \
--testnet-magic 2

References

Native Tokens and NFTs on Cardano

Minting NFTs - Cardano Developer Docs

Pinata IPFS

CIP 25 - Cardano Metadata Standard

License

This work is distributed under a Creative Commons Attribution 4.0 International (CC BY 4.0) The license allows you to copy and redistribute the material in any medium or format, as well as remix, transform, and build upon the material for any purpose, including commercial, as long as you give appropriate credit to the creator.