This site requires Javascript to be enabled.

This guide outlines the following workflow:

  1. Creating your project
  2. Customizing your token parameters
  3. Deploying your token contract
  4. Minting and sending tokens
  5. Building the NFT dapp


Non-Fungible Tokens, or NFTs are an important part of the decentralized digital world.

In this guide, we will learn how to write, deploy, mint and transfer our own NFTs. We will also learn how to build a dapp website we can share with other users, so they can also mint and transfer tokens.

Creating your Project

If you are new to the platform and have not created a project before, please visit Setup to learn about the necessary installation requirements and familiarize yourself with the process before proceeding.

Now let’s create a new project, and on the template selection list select the CW721 with on-chain metadata template.

$ archway new basic-nft✔ Select a chain to use › Archway Testnet✔ Choose a name for your contract … basic-nft✔ Choose a starter template › CW721 with on-chain metadataCreating Archway project basic-nft...🔧   Destination: /Users/testuser/basic-nft ...🔧   project-name: basic-nft ...🔧   Generating template ...[ 1/19]   Done: .cargo/                                                                                                           🔧   Moving generated files into: `/Users/testuser/basic-nft`...💡   Initializing a fresh Git repository✨   Done! New project created /Users/testuser/basic-nft

Designing Your Tokens

The asset metadata is a critical element for any NFT. It defines information like the name, image URL, and other properties that can be pulled by NFT marketplaces to show relevant information to the users. Information like rarity, custom traits, etc., are all stored here.

In this example, we will keep our metadata on-chain. In other words, the contract will store the metadata in its internal state.

In the cw721-base code, NFT metadata is contained in the extension property of the TokenInfo struct:

#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]pub struct TokenInfo<T> {    /// The owner of the newly minted NFT    pub owner: Addr,    /// Approvals are stored here, as we clear them all upon transfer and cannot accumulate much    pub approvals: Vec<Approval>,    /// Universal resource identifier for this NFT    /// Should point to a JSON file that conforms to the ERC721    /// Metadata JSON Schema    pub token_uri: Option<String>,    /// You can add any custom metadata here when you extend cw721-base    pub extension: T,}

To use this extension property, here's how we define our metadata in the CW721 with on-chain metadata template we cloned into our project.

#[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug, Default)]pub struct Trait {    pub display_type: Option<String>,    pub trait_type: String,    pub value: String,}#[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug, Default)]pub struct Metadata {    pub image: Option<String>,    pub image_data: Option<String>,    pub external_url: Option<String>,    pub description: Option<String>,    pub name: Option<String>,    pub attributes: Option<Vec<Trait>>,    pub background_color: Option<String>,    pub animation_url: Option<String>,    pub youtube_url: Option<String>,}


This code is located in src/ of your project. You can also view it here.