With the Token Extension program, you can create NFTs and digital assets using the metadata extensions. Together, these extensions (metadata pointer and token metadata) allow you to put any desired metadata natively on-chain. All within a customizable key-value data store directly on the token's mint account, reducing costs and complexity.
These can be especially great for web3 games since we can now have these "additional metadata fields" within an on-chain key-value store, allowing games to save/access unique state within the NFT itself (like for a game character's stats or inventory).
Building the on-chain program
In this developer guide, we will demonstrate how to build these Token Extension based NFTs and custom metadata using an Anchor program. This program will save the level and the collected resources of a game player within an NFT.
This NFT will be created by the Anchor program so it is very easy to mint from the JavaScript client. Each NFT will have some basic structure provided via the Token Metadata interface:
- default on-chain fields -
name
,symbol
anduri
- the
uri
is a link to an offchain json file which contains the off chain metadata of the NFT
- the
- we will also have custom "additional fields" that we define
All of these fields are saved using the metadata extension which is pointed to the NFT's mint account, making them accessible to anyone or any program.
You can find a video walkthrough of this example on the Solana Foundation Youtube channel:
Other use case within games
These types of NFTs with customizable on-chain metadata open up many interesting possibilities for game developers. Especially since this metadata can be directly interacted with or managed by an on-chain program.
Some of these gaming related use cases include:
- save the level and XP of the player
- the current weapon and armor
- the current quest
- the list goes on!
Minting the NFT
In order to create the NFT we need to perform a following steps:
- Create a mint account
- Initialize the mint account
- Create a metadata pointer account
- Initialize the metadata pointer account
- Create the metadata account
- Initialize the metadata account
- Create the associated token account
- Mint the token to the associated token account
- Freeze the mint authority
Rust program code
Here is the rust code used to mint the NFT using the Token extension program:
JavaScript client code
Calling mint NFT from the client is very easy:
Quickstart example
The example above is based on the Solana Games Preset, which generates you a scaffold that includes a JavaScript and Unity client for this game, including the configuration for interacting with the Solana Anchor program.
You can run it yourself with the following command:
Setup your local environment
In order to run this example locally, you will need to make sure you have setup your local environment for Solana development, including installing and configuring the Anchor CLI. If you do not already, you can follow the previously linked setup guide to do so.
Project structure
The Anchor project is structured like this:
The entry point is in the lib.rs file. Here we define the program id and the instructions. The instructions are defined in the instructions folder. The state is defined in the state folder.
So the calls arrive in the lib.rs file and are then forwarded to the instructions. The instructions then call the state to get the data and update it.
You can find the mint NFT instruction in the instructions folder.
Anchor program
To finish setting up the Anchor program generated from the create-solana-game
tool:
cd program
to end the program directory- Run
anchor build
to build the program - Run
anchor deploy
to deploy the program - Copy the program id from the terminal into the
lib.rs
,anchor.toml
and within the Unity project in theAnchorService
and if you use JavaScript in theanchor.ts
file - Build and deploy again
NextJS client
To finish setting up the NextJS client generated from the create-solana-game
tool:
- Copy the
programId
intoapp/utils/anchor.ts
cd app
to end the app directory- Run
yarn install
to install the Node dependencies - Run
yarn dev
to start the client - After doing changes to the Anchor program make sure to copy over the types
from the program into the client so you can use them. You can find the
TypeScript types in the
target/idl
folder.
Run this example locally
Using Anchor's test
command with the --detach
flag will start and configure
your Solana local test validator to have the program deployed (and keep the
validator running after the tests complete):
Then you can set the Solana Explorer to use your
local test validator (which starts when running the anchor test
command) so
you can look at the transactions:
The program is also already deployed to net so you can try it out on devnet
.
The JavaScript client also has a button to mint the NFT. Starting the JavaScript
client:
Open the Unity project
First open the Unity project with Unity Version 2021.3.32.f1 (or similar), then
open the GameScene
or LoginScene
and hit play. Use the editor login button
in the bottom left.
If you can't get devnet SOL you can copy your address from the console and follow the instructions on this guide on how to get devnet SOL
Connect to the Solana test validator in Unity
If you want to avoid having to worry about maintaining devnet SOL, you can connect to your running local test validator from within Unity. Simply add these links on the wallet holder game object:
Run the JavaScript client
To start the JavaScript client and be able to interact with the game and program using your web browser:
- open the
app
directory within the repo - install the Node dependencies
- run the
dev
command to start the development server
To start changing the program and connecting to your own program follow the steps below.