ARC69 NFT Metadata and IPFS Integration
This tutorial guides you through creating an ARC69-compliant NFT with metadata stored on the blockchain and the image hosted on IPFS. It complements the video tutorial.
YouTube Tutorial
Generating an Account
Use the following Python code to generate a new account for managing your ARC69 assets:
from algosdk.account import generate_account
private_key, address = generate_account()
print(private_key, address)
Funding the Account
Once the account is generated, it needs funding to submit transactions. Visit the Algorand Testnet Faucet to add funds.
Displaying the NFT Image
For this tutorial, the image used is "Charmander.png". Make sure to place this image in the public/images/
directory and reference it appropriately. Here’s the file path:
ARC69 Metadata Structure
In an ARC69 NFT, the image is immutable, but metadata (stored in the note field) can be updated. Images are hosted off-chain on IPFS, which ensures efficient and decentralized storage.
In this example, we’ll use Pinata as our IPFS service. Generate an API key, secret, and JWT on Pinata and store them in your .env
file.
Example Code: Minting an ARC69 NFT
Below is a code snippet for minting an ARC69 NFT, including metadata in the note field. This code uploads the image to IPFS and sets up the NFT on Algorand.
from algosdk.v2client.algod import AlgodClient
from algosdk.transaction import wait_for_confirmation, AssetConfigTxn
from dotenv import load_dotenv
from pinata import Pinata
from algosdk.account import address_from_private_key
import os
import json
load_dotenv()
pinata_api_key = os.getenv('api_key')
pinata_api_secret = os.getenv('api_secret')
pinata_jwt = os.getenv('jwt')
pinata_client = Pinata(api_key=pinata_api_key, secret_key=pinata_api_secret, access_token=pinata_jwt)
algod_token = os.getenv('algod_token')
algod_server = os.getenv('algod_server')
algod_client = AlgodClient(algod_token, algod_server)
private_key = os.getenv('private_key')
address = address_from_private_key(private_key)
# Minting ARC69 NFT
image_path = './charmander.png'
response = pinata_client.pin_file(image_path)
image_ipfs_hash = response['data']['IpfsHash']
viewable_hash = f'https://gateway.pinata.cloud/ipfs/' + image_ipfs_hash
metadata = {
"standard": "arc69",
"mime_type": "image/png",
"properties": {
"Type": "Fire",
"Description": "A fire pokemon with a fiery tail",
"Level": "1",
"Experience": "0",
}
}
params = algod_client.suggested_params()
asset_config_transaction = AssetConfigTxn(
sender=address,
sp=params,
total=1,
decimals=0,
default_frozen=False,
manager=address,
reserve=address,
asset_name="Test Charmander",
unit_name="TC#1",
url=viewable_hash,
strict_empty_address_check=False,
note=json.dumps(metadata).encode()
)
signed_ac_tx = asset_config_transaction.sign(private_key)
tx_id = algod_client.send_transaction(signed_ac_tx)
print(tx_id)
wait_for_confirmation(algod_client, tx_id)
asset_index = algod_client.pending_transaction_info(tx_id)['asset-index']
print(asset_index)
Example Code: Updating ARC69 Metadata
After minting, you can update specific metadata fields, such as experience or level, by sending an asset configuration transaction with updated metadata in the note field.
metadata = {
"standard": "arc69",
"mime_type": "image/png",
"properties": {
"Type": "Fire",
"Description": "A fire pokemon with a fiery tail",
"Level": "4",
"Experience": "15",
}
}
asset_config_transaction = AssetConfigTxn(
index=asset_index,
sender=address,
sp=params,
manager=address,
reserve=address,
strict_empty_address_check=False,
note=json.dumps(metadata).encode()
)
signed_ac_tx = asset_config_transaction.sign(private_key)
tx_id = algod_client.send_transaction(signed_ac_tx)
print(tx_id)