Create Metadata
This assumes there already was a previous deployment to rinkeby, with the utilization of AdvancedCollectible[-1]
Setup
create new folder "metadata" in brownie project root
create new file: sample_metadata.py
create new folder within metadata, "rinkeby"
metadata_template = {
"name": "",
"description": "",
"image": "",
"attributes": [{"trait_type": "cuteness", "value": 100}]
}
create_metadata.py
In our scripts folder, create new file: create_metadata.py
We will use this script to assign the URI for each NFT.
from brownie import AdvancedCollectible, network
from metadata.sample_metadata import metadata_template
from pathlib import Path
breed_mapping = {0: "PUG", 1: "SHIBA_INU", 2: "ST_BERNARD"}
def get_breed(breed_number):
return breed_mapping[breed_number]
def main():
advanced_collectible = AdvancedCollectible[-1]
number_of_NFTS = advanced_collectible.tokenCounter()
print(f"The number of NFTs minted so far is {number_of_NFTS}")
for tokenID in range(number_of_NFTS):
breed = get_breed(advanced_collectible.tokenIdToBreed(tokenID))
metadata_filename = f"./metadata/{network.show_active()}/{tokenID}-{breed}.json"
collectible_metadata = metadata_template
if Path(metadata_filename).exists():
print(f"{metadata_filename} exists! Delete to overwrite")
else:
print(f"Creating Metadata file: {metadata_filename}")
collectible_metadata["name"] = breed
collectible_metadata["description"] = f"An adorable {breed} pup!"
print(collectible_metadata)
image_path = "./img" + breed.lower().replace("_", "-") + ".png"
image_uri = upload_to_ipfs()
collectible_metadata["image_uri"] = image_uri
call on previous rinkeby deployment
check number of NFTs minted
for each tokenID, get the breed via getbreed(), and structure the filename and path as metadata_filename

collectible_metadata collects the metadata_template to be used as a base for modification
We then check if the required metadata_filename exists, using Path library.
Else, we will create a new one using the template as reference, adding the following
name
description
image URI -> collectible_metadata["image_uri"] = image_uri
image-uri
How do we get the image URI? Currently the images are in our local img folder. We need them to be hosted on IPFS and pass their IPFS URI into collectible_metadata["image_uri"]
To that end, we will have to install IPFS cli: https://docs.ipfs.io/how-to/command-line-quick-start/
On running ipfs daemon on terminal we will see the following:

We will be working with /api/v0/add to add our file to IPFS: https://docs.ipfs.io/reference/http/api/#http-rpc-commands
def upload_to_ipfs(filepath):
# open image as binary - open(rb)
with Path(filepath).open("rb") as fp:
image_binary = fp.read()
ipfs_url = "http://127.0.0.1:5001" #get from WebUI
endpoint = "/api/v0/add"
response = requests.post(ipfs_url + endpoint, files={"file":image_binary}) #post request
ipfs_hash = response.json()["Hash"] #response returns dictionary
# "./img/0-PUG.png" -> split on /, grab last part of array, which is "0-PUG.png"
filename = filepath.split("/")[-1:][0]
image_uri = f"https://ipfs.io/ipfs/{ipfs_hash}?filename={filename}"
print(image_uri)
return image_uri
ipfs_url -> retrieved from running ipds daemon
endpoint -> as per api endpoint reference
response -> structuring and sending a post response (can also use curl)
ipfs_hash -> response returns JSON string on successful call to endpoint - decode it as a python dict via .json()

extract filename from filepath and together with the IPFS hash, construct the image URI
print(image_uri)
will return an ipfs link, like so:
https://ipfs.io/ipfs/QmUPjADFGEKmfohdTaNcWhp7VGk26h5jXDA7v3VtTnTLcW?filename=st-bernard.png
The image will be available as long as you are running your ipfs node.
To make the data highly available without needing to run a local IPFS daemon 24/7, you can request that a remote pinning service store a copy of your IPFS data on their IPFS nodes.
Creating metadate files
Now that we have filled all the fields in the metadata file, we are going to write it as a json file into our directory.
with open(metadata_filename, "w") as file:
json.dump(collectible_metadata, file)
upload_to_ipfs(metadata_filename)
This will create a json file in our metadata/rinkeby folder upon running:
brownie run scripts/advcollectible/create_metadata.py --network rinkeby

Final code at this point:
from brownie import AdvancedCollectible, network
from metadata.sample_metadata import metadata_template
from pathlib import Path
import requests, json
breed_mapping = {0: "PUG", 1: "SHIBA_INU", 2: "ST_BERNARD"}
def get_breed(breed_number):
return breed_mapping[breed_number]
def main():
advanced_collectible = AdvancedCollectible[-1]
number_of_NFTS = advanced_collectible.tokenCounter()
print(f"The number of NFTs minted so far is {number_of_NFTS}")
for tokenID in range(number_of_NFTS):
breed = get_breed(advanced_collectible.tokenIdToBreed(tokenID))
metadata_filename = f"./metadata/{network.show_active()}/{tokenID}-{breed}.json"
collectible_metadata = metadata_template
if Path(metadata_filename).exists():
print(f"{metadata_filename} exists! Delete to overwrite")
else:
print(f"Creating Metadata file: {metadata_filename}")
collectible_metadata["name"] = breed
collectible_metadata["description"] = f"An adorable {breed} pup!"
print(collectible_metadata)
# convert underscores to dashes to be URI compatible
image_path = "./img/" + breed.lower().replace("_", "-") + ".png"
image_uri = upload_to_ipfs(image_path)
collectible_metadata["image_uri"] = image_uri
with open(metadata_filename, "w") as file:
json.dump(collectible_metadata, file)
upload_to_ipfs(metadata_filename)
def upload_to_ipfs(filepath):
# open image as binary - opne(rb)
with Path(filepath).open("rb") as fp:
image_binary = fp.read()
ipfs_url = "http://127.0.0.1:5001" #get from WebUI
endpoint = "/api/v0/add"
response = requests.post(ipfs_url + endpoint, files={"file": image_binary}) #post request
ipfs_hash = response.json()["Hash"] #response returns dictionary.
# "./img/0-PUG.png" -> split on /, grab last part of array, which is "0-PUG.png"
filename = filepath.split("/")[-1:][0]
image_uri = f"https://ipfs.io/ipfs/{ipfs_hash}?filename={filename}"
print(image_uri)
return image_uri
Alternative: Pinata
deploy to Pinata -> upload_pinata.py
Reference: https://docs.pinata.cloud/api-pinning/pin-file
create account at Pinata and generate api key
11:20 - 11:31

You should also see the pinned file:

Last updated