Creating an AtomicAssets Collection

idmontie

Ivan Montiel

Posted on August 5, 2023

Creating an AtomicAssets Collection

Introduction

In this section, we are going to leverage the AtomicAssets Smart Contract to create a Collection on the WAX Testnet.

Let’s create our example Collection. In this set of tutorials and examples, we are going to create a new set of NFTs called “BabyChicks” - cute little chickens that you can hatch, collect, and trade.

The AtomicAssets Action

To get started, we’ll need to create a collection for our NFTs using AtomicAssets.

Let’s look at the createcol schema to start with.

createcol documentation

We will need to fill in all of this information when we write our script. Let’s take a look at each field:

  • author - in our examples, the author will be the same as the payer of our last examples: waxcourse123. This should be your account name.
  • collection_name - in this case, we will call it babychicknft. Note that this is of type name, not string. A name has some strict rules that we will cover later.
  • allow_notify - we will set this to true for now.
  • authorized_accounts - we will keep this empty.
  • notify_accounts - we will keep this empty.
  • market_fee - typically 5% (0.05) but this varies from project to project.
  • data - it’s always bugged me that this is a free-form attribute map, but if you want your project to take off on AtomicHub, you need a special set of attributes to get started. This is where most of the work will be when creating your collection.

Let’s dig deeper into the data section. Here is a template we will use to create our collection data:

const data = [
    { "key": "name", "value": ["string", "Baby Chicks"] },
    { "key": "img", "value": ["string", "QmRTg2dhvSR7Lbmwvfv4z5c7Eisj7Lb199wsc5ijXHGEBZ"] },
    { "key": "description", "value": ["string", "This is a collection created for tutorials"] },
    { "key": "url", "value": ["string", "https://capsulecat.com"] },
    {
        "key": "socials", "value": ["string", JSON.stringify({
            "twitter": "thecapsulecat",
            "github": "capsulecat",
        })]
    },
    {
        "key": "creator_info", "value": ["string", JSON.stringify({
            "address": "",
            "company": "",
            "name": "",
            "registration_number": ""
        })]
    },
    {
        "key": "images", "value": ["string", JSON.stringify({
            "banner_1920x500": "",
            "logo_512x512": ""
        })]
    }
]
Enter fullscreen mode Exit fullscreen mode

You’ll want to replace the url section with a string for your website, along with the socials for Twitter, Github, Facebook, Medium, Telegram, Youtube, and Discord if you have them. Something that AtomicHub verification will require is a creator_info section that requires your business’s address and registration number.

For the images, we will dive deeper into this in the future, but you can set them to HTTPS URLs or IFPS URLs.

To actually create this collection on the testnet, we will write a script that encapsulates all of the data we have above into a single transaction on the WAX blockchain.

Setting up NodeJS

We’ll use NodeJS to write scripts in since there already exist packages for communicating with the WAX blockchain and EOSIO based blockchains.

To get started with node within the VM:

cd babychicks/scripts
curl https://raw.githubusercontent.com/creationix/nvm/master/install.sh | bash
nvm install
nvm use
Enter fullscreen mode Exit fullscreen mode

If you are starting from scratch, you’ll want to create a workspace with:

npm init
Enter fullscreen mode Exit fullscreen mode

Then install some packages that will make implementation easier:

npm i --save node-fetch eosjs 
Enter fullscreen mode Exit fullscreen mode

If you are following along with the code on Github, you can just use the node setup there.

Creating a Script

Let’s create a JSON RPC API:

import fetch from 'node-fetch';
import { Api, JsonRpc } from "eosjs";
import { JsSignatureProvider } from "eosjs/dist/eosjs-jssig";

export function createApiRpc() {
    const privateKey = process.env.WAX_PRIVATE_KEY;
    const endpoint = process.env.WAX_ENDPOINT;

    assert(privateKey, "Missing WAX_PRIVATE_KEY");
    assert(endpoint, "Missing WAX_ENDPOINT");

    const signatureProvider = new JsSignatureProvider([privateKey]);

    const rpc = new JsonRpc(endpoint, {
        fetch,
    });

    const apiRpc = new Api({
        rpc,
        signatureProvider,
        textDecoder: new TextDecoder(),
        textEncoder: new TextEncoder(),
    });

    return apiRpc;
}
Enter fullscreen mode Exit fullscreen mode

We expect our script to be called with some Environment Variables set: WAX_ACCOUNT, WAX_PRIVATE_KEY and WAX_ENDPOINT . When we call our script, we can set the environment variables in the command.

Let’s create a wrapper function for sending actions as a single transaction on the blockchain:

const TAPOS = {
    blocksBehind: 3,
    expireSeconds: 30,
};

export function transact(actions) {
    const apiRpc = createApiRpc();

    return apiRpc.transact({ actions }, TAPOS);
}
Enter fullscreen mode Exit fullscreen mode

TAPOS stands for Transaction as Proof of Stake. You typically won’t need to tweak these settings, but you can read more on Github.

Finally, let’s wrap this up by creating a transaction for creating the collection with the data from above:

async function createCollection() {
    const author = process.env.WAX_ACCOUNT;

    if (!author) {
        throw new Error("Missing WAX_ACCOUNT");
    }

    try {
        await transact([
            {
                account: "atomicassets",
                name: "createcol",
                authorization: [
                    {
                        actor: author,
                        permission: "active",
                    },
                ],
                data: {
                    author,
                    collection_name: collectionName('babychicknft'),
                    allow_notify: true,
                    authorized_accounts: [
                        name(author),
                    ],
                    notify_accounts: [],
                    market_fee: 0.05,
                    data: data,
                },
            },
        ])
    } catch (error) {
        console.error(error);
        return false;
    }
}

(async () => {
    const result = await createCollection();
    console.log(result);
})()
Enter fullscreen mode Exit fullscreen mode

In the repo on Github, you will see that these functions we went through are split up into reusable functions. We will be reusing the transact and createApiRpc utilities in future sections.

The last thing we skipped over was a utility called name. This isn’t necessary, but when writing scripts you will find that different APIs provide different behavior for names.

When an API expects a name, it wants a string that adheres to some rules – the string must be 12 characters or less, can only contain letters, a dot, and the numbers 1 to 5, and must follow some other rules. The name utility in the above code performs these checks and throws an error before sending the transaction to the blockchain. Some APIs will throw and error and let you know that the provided name is invalid. Some APIs strip invalid characters from the name and don’t tell you until you go to verify the transaction on the blockchain and find out that the name you sent isn’t the name that was saved.

Running the Script

Pulling it all-together, we can run the script to create the collection on the testnet:

WAX_ACCOUNT=waxcourse123 \
WAX_PRIVATE_KEY="<YOUR WAX ACCOUNT ACTIVE PRIVATE KEY>" \
WAX_ENDPOINT=https://testnet.wax.pink.gg \
  node ./src/000-create-collection.js
Enter fullscreen mode Exit fullscreen mode

Example output if all goes well:

Example output

You can see the collection on the WAX Testnet AtomicHub marketplace: https://wax-test.atomichub.io/explorer/collection/wax-testnet/babychicknft.

Conclusion

In this section, we covered using NodeJS scripting to create an AtomicAssets collection. We will commonly use off-chain scripts to create, edit, and update AtomicAssets information like our Collection, and in future sections, our Schema and Templates. Using scripts helps us save time and RAM costs on the blockchain by just running Actions directly.

Upcoming sections will cover Schemas and Templates. Once those are created, we can interact with our collection using a Smart Contract that we will write.

Next post: Creating AtomicAssets Schemas

E-book

Get this entire WAX tutorial as an e-book on Amazon.

Additional links

💖 💪 🙅 🚩
idmontie
Ivan Montiel

Posted on August 5, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related