How to Mint NFTs in Algorand Blockchain

Introduction

 
In the previous article, We Demonstrated How to build an application using Algorand and PureStake API. Here we further demonstrate another Important Topic, which is Minting NFTs. So we will be going to learn how to create Algorand Standard Assets(ASAs)
 

What are Algorand Standard Assets (ASAs) 

 
Algorand Stanard Assets (ASA) provide a standardized layer-1 mechanism for representing all types of assets on the Algorand Blockchain. These can include fungible, non-fungible, restricted fungible, and restricted non-fungible assets. Example asset types are :
 
FUNGIBLE TOKEN NON-FUNGIBLE TOKEN RESTRICTED FUNGIBLE TOKEN RESTRICTED NON-FUNGIBLE TOKEN  
  • In-game Points
  • Stable Coins
  • loyalty points
  • System credits
  • Cryptocurrency 
  • In-game items
  • Supply chain
  • Real Estate
  • identity 
  • Certifications
  • Collectables
  • Securities
  • Gov's issued Fiat
  • Certifications
  • Real Estate
  • Ownership Registries
  • Regulatory Certifications 
 

What is a Non-Fungible Token(NFT)

 
NFT is a mechanism that allows the purchaser of your products to verify what they have purchased while ensuring that what you will selling cannot be traded. It enables participants in an ecosystem to ensure what they and what value they hold will not be affected by any other user or service.
 
It also prevents third-party players from making copies of what you are selling, which is essentially what happens in the case of digital products that can be duplicated and sold. 
 
Non-fungible tokens represent unique digital assets. One NFT can't exchange for another, which represents the same thing in the same way. For example, one token might represent a cat, while another represents a house in monopoly.
 

How to create NFTs

 
We are going to create NFT using Algorand Standard Assets(ASAs), which are constructed into the protocol and created using different types of transactions. This is distinct from some other blockchains where a smart contract is necessary to represent assets. But here you just need to specify a few parameters to identify it as an NFT and link to the metadata so that potential owners have the information they need to validate the integrity of the asset. For instance, you just need to set the total amount of units you want to create for the asset to 1 and set the number of decimals to 0. This ensures you create precisely one unit of your Algorand Standard Assets(ASA) and can't divide the newly minted asset. However, you can set the number of decimals to any number according to ARC-0003 NFT Standard up to the protocol limit.
 
Step 1: Set Configuration Module and the PureStake API
 
First You need to set the Algorand module and default configurations value for the Purestake API. 
  1. import json    
  2. import hashlib    
  3. import os    
  4. from algosdk import mnemonic    
  5. from algosdk.v2client import algod    
  6. from algosdk.future.transaction import AssetConfigTxn, wait_for_confirmation            
  7.             
  8. algod_token = 'YOUR API KEY HERE'            
  9. algod_address = 'https://testnet-algorand.api.purestake.io/ps2'            
  10. purestake_token = {'X-Api-key': algod_token}     
Step 2: Configure your Algorand Account 
 
Now you’ll need to recover your account using your mnemonic.
Important Note: Mnemonics control your account. Never share them or store them insecurely. The code below is for demonstration purposes only. 
  1. mnemonic_phrase = "YOUR MNEMONIC HERE";      
  2. account_private_key = mnemonic.to_private_key(mnemonic_phrase)      
  3. account_public_key = mnemonic.to_public_key(mnemonic_phrase)      
Note- In mnemonic_phrase you need to write your Account Passphrase
 

Checking Algorand Wallet Balance

  1. account_info = algod_client.account_info(account_public_key)        
  2. print("Account balance: {} microAlgos".format(account_info.get('amount')))      
Using this code you can check your Algos. And for creating NFT you have to store a minimum of 0.25 Algos. if not you can use Algorand Testnet Dispenser.
 
Step 3: Create the Client
 
To instantiate the client you need to connect PureStake API to your program.
  1. algodclient = algod.AlgodClient(algod_token, algod_address, headers=purestake_token)    
Step 4: Get the parameters
 
To get the params for the transaction before every Transaction.
  1. params = algod_client.suggested_params()    
Step 5: Create a JSON file
 
After that, you need to read your JSON file where you store your NFT data 
  1. {    
  2.     "name": "TESTNFT",    
  3.     "description": "ALGORAND TEST NFT",    
  4.     "image": "https:\/\/s3.amazonaws.com\/your-bucket\/images\/alice-nft.png",    
  5.     "image_integrity": "sha256-/tih/7ew0eziEZIVD4qoTWb0YrElAuRG3b40SnEstyk=",    
  6.     "properties": {    
  7.         "simple_property": "ALGORAND TEST NFT",    
  8.         "rich_property": {    
  9.             "name": "TESTNFT",    
  10.             "value": "001",    
  11.             "display_value": "001",    
  12.             "class": "emphasis",    
  13.             "css": {    
  14.                 "color": "#ffffff",    
  15.                 "font-weight": "bold",    
  16.                 "text-decoration": "underline"    
  17.             }    
  18.         },    
  19.         "array_property": {    
  20.             "name": "Artwork",    
  21.             "value": [1, 2, 3, 4],    
  22.             "class": "emphasis"    
  23.         }    
  24.     }    
  25. }    
Change this data according to what you want, like name, description, image, value and etc. after changing the data accordingly save this data in JSON format and call this JSON in a Python file.
 
Step 6: Read JSON file in python
 
Now you need to read the JSON file in a python program and convert that file into sha512_256 format :
  1. #JSON FILE    
  2. dir_path = os.path.dirname(os.path.realpath(__file__))    
  3. f = open (dir_path + '/NFTData.json'"r")    
  4.     
  5. #Reading from File    
  6. metadataJSON = json.loads(f.read())    
  7. metadataStr = json.dumps(metadataJSON)    
  8.     
  9. hash = hashlib.new("sha512_256")    
  10. hash.update(b"arc0003/amj")    
  11. hash.update(metadataStr.encode("utf-8"))    
  12. json_metadata_hash = hash.digest()    
Note- replace NFTData.json from your JSON file name
 
Step 7: Asset Creation transaction
  1. txn = AssetConfigTxn(    
  2.       sender=account_public_key,    
  3.       sp=params,    
  4.       total=1,    
  5.       default_frozen=False,    
  6.       unit_name="TESTNFT",    
  7.       asset_name="Algorand Test NFT",    
  8.       manager=account_public_key,    
  9.       reserve=None,    
  10.       freeze=None,    
  11.       clawback=None,    
  12.       strict_empty_address_check=False,    
  13.       url="https://path/to/my/asset/details",     
  14.       metadata_hash=json_metadata_hash,    
  15.       decimals=0)    
In the above code, AssetConfigTxn is a class of Algorand Python SDK where all the parameters are required for creating NFT. The parameters are :
  • sender: The account which is allocating the asset to their accounts Asset map.
  • total: The total number of base units of the asset to create. This number cannot be changed.
  • default_frozen: True to freeze holding for this asset by default.
  • unit_name: The name of a unit of this asset. Supplied on creation. Max size is 8 bytes.
  • manager: The address of the account that can manage the configuration of the asset and destroy it.
  • reserve: The address of the account that holds the reserve(non-minted) units of the asset. This address has no specific authority in the protocol.
  • freeze: The address of the account used to freeze the holding of this asset. If empty, freezing is not permitted.
  • clawback: The address of the account that can clawback holding of this asset. If empty, clawback is not permitted.
  • url: Specifies a URL where more information about the asset can be retrieved. Max size is 96 bytes.
  • metadata_hash: This field is intended to be a 32-bytes hash of some metadata that is relevant to your asset and/or asset holding. the format of this metadata is up to the application.
  • decimal: the number of digits to use after the decimal point when displaying the asset.\
Step 8: Sign in the transaction and wait for transactions
 
After assigning all the parameters you need to sign in the transaction using your private key to send the asset to Algorand Blockchain.
  1. # Sign with secret key of creator     
  2. try:     
  3.     stxn = txn.sign(account_public_key)      
  4.       
  5.     # Send the transaction to the network and retrieve the txid.      
  6.     txid = algod_client.send_transaction(stxn)      
  7.     print("Asset Creation Transaction ID: {}".format(txid))      
  8.       
  9.       
  10.     # Wait for the transaction to be confirmed      
  11.     confirmed_txn = wait_for_confirmation(algod_client, txid, 4)        
  12.     print("TXID: ", txid)      
  13.     print("Result confirmed in round: {}".format(confirmed_txn['confirmed-round']))     
  14. except Exception as e:      
  15.     print(e)    
In the above code, we are waiting for the transaction to get submitted and verified from the testnet. I have kept it under try-except so as to catch any error or exception which may cause hindrance.
 
You should see a response similar to the following:
  1. TXID : UZCV4JQB2NJ7USKXZIG755TQMIU55BUTMFOYRD4QVYWVOT5GOWBQ      
  2. Waiting for confirmation    
  3. Result confirmed in round: 21443800    
Step 10: Run All of the Code Together
 
If you’d rather just drop in the code in its entirety, copy it below. You will need to enter your API key, mnemonic and other details to work properly.
  1. import json      
  2. import hashlib      
  3. import os      
  4. from algosdk import mnemonic      
  5. from algosdk.v2client import algod      
  6. from algosdk.future.transaction import AssetConfigTxn, wait_for_confirmation              
  7.               
  8. algod_token = 'YOUR API KEY HERE'              
  9. algod_address = 'https://testnet-algorand.api.purestake.io/ps2'              
  10. purestake_token = {'X-Api-key': algod_token}     
  11.     
  12. mnemonic_phrase = "YOUR MNEMONIC HERE";        
  13. account_private_key = mnemonic.to_private_key(mnemonic_phrase)        
  14. account_public_key = mnemonic.to_public_key(mnemonic_phrase)     
  15.     
  16. account_info = algod_client.account_info(account_public_key)          
  17. print("Account balance: {} microAlgos".format(account_info.get('amount')))     
  18.     
  19. algodclient = algod.AlgodClient(algod_token, algod_address, headers=purestake_token)        
  20.     
  21. params = algod_client.suggested_params()      
  22.     
  23. #JSON FILE      
  24. dir_path = os.path.dirname(os.path.realpath(__file__))      
  25. f = open (dir_path + '/NFTData.json'"r")      
  26.       
  27. #Reading from File      
  28. metadataJSON = json.loads(f.read())      
  29. metadataStr = json.dumps(metadataJSON)      
  30.       
  31. hash = hashlib.new("sha512_256")      
  32. hash.update(b"arc0003/amj")      
  33. hash.update(metadataStr.encode("utf-8"))      
  34. json_metadata_hash = hash.digest()      
  35.     
  36. txn = AssetConfigTxn(      
  37.       sender=account_public_key,      
  38.       sp=params,      
  39.       total=1,      
  40.       default_frozen=False,      
  41.       unit_name="TESTNFT",      
  42.       asset_name="Algorand Test NFT",      
  43.       manager=account_public_key,      
  44.       reserve=None,      
  45.       freeze=None,      
  46.       clawback=None,      
  47.       strict_empty_address_check=False,      
  48.       url="https://path/to/my/asset/details",       
  49.       metadata_hash=json_metadata_hash,      
  50.       decimals=0)      
  51. # Sign with secret key of creator       
  52. try:       
  53.     stxn = txn.sign(account_public_key)        
  54.         
  55.     # Send the transaction to the network and retrieve the txid.        
  56.     txid = algod_client.send_transaction(stxn)        
  57.     print("Asset Creation Transaction ID: {}".format(txid))        
  58.         
  59.         
  60.     # Wait for the transaction to be confirmed        
  61.     confirmed_txn = wait_for_confirmation(algod_client, txid, 4)          
  62.     print("TXID: ", txid)        
  63.     print("Result confirmed in round: {}".format(confirmed_txn['confirmed-round']))       
  64. except Exception as e:        
  65.     print(e)      
  66. try:    
  67.     ptx = algod_client.pending_transaction_info(txid)    
  68.     asset_id = ptx["asset-index"]    
  69.     print_created_asset(algod_client, accounts[1]['pk'], asset_id)    
  70.     print_asset_holding(algod_client, accounts[1]['pk'], asset_id)    
  71. except Exception as e:    
  72.     print(e)    
  73.     
  74. def print_created_asset(algodclient, account, assetid):    
  75.   account_info = algodclient.account_info(account)    
  76.   idx = 0;    
  77.   for my_account_info in account_info['created-assets']:    
  78.     scrutinized_asset = account_info['created-assets'][idx]    
  79.     idx = idx + 1           
  80.     if (scrutinized_asset['index'] == assetid):    
  81.       print("Asset ID: {}".format(scrutinized_asset['index']))    
  82.       print(json.dumps(my_account_info['params'], indent=4))    
  83.       break    
  84.     
  85. def print_asset_holding(algodclient, account, assetid):    
  86.     account_info = algodclient.account_info(account)    
  87.     idx = 0    
  88.     for my_account_info in account_info['assets']:    
  89.         scrutinized_asset = account_info['assets'][idx]    
  90.         idx = idx + 1            
  91.         if (scrutinized_asset['asset-id'] == assetid):    
  92.             print("Asset ID: {}".format(scrutinized_asset['asset-id']))    
  93.             print(json.dumps(scrutinized_asset, indent=4))    
  94.             break        

Conclusion

 
Thank you for reading the article, hope you got to know How to mint NFT in Algorand Blockchain, and how we can use PureStake Algorand Python SDK to create a simple application.
 
We will continue the Algorand series.