Build on Solana
Custom NFT (Create YAML)
CIDL NFT
The following CIDL is the interface for a custom NFT use case. Each NFT will be a Gem that can be collectible through a video game. In this CIDL, we will demonstrate the minting, transferring, and burning process of an NFT.
cidl: "0.8"
info:
name: nft
title: Patika NFT
version: 0.0.1
license:
name: Unlicense
identifier: Unlicense
types:
GemMetadata:
solana:
seeds:
- name: "gem"
- name: mint
type: sol:pubkey
fields:
- name: color
type: string
solana:
attributes: [ cap:16 ]
- name: rarity
type: string
solana:
attributes: [ cap:16 ]
- name: short_description
type: string
solana:
attributes: [ cap:255 ]
- name: mint
type: sol:pubkey
- name: assoc_account
type: rs:option<sol:pubkey>
methods:
- name: mint
uses:
- csl_spl_token.initialize_mint2
- csl_spl_assoc_token.create
- csl_spl_token.mint_to
- csl_spl_token.set_authority
inputs:
- name: mint
type: csl_spl_token.Mint
solana:
attributes: [ init ]
- name: gem
type: GemMetadata
solana:
attributes: [ init ]
seeds:
mint: mint
- name: color
type: string
- name: rarity
type: string
- name: short_description
type: string
- name: transfer
uses:
- csl_spl_assoc_token.create
- csl_spl_token.transfer_checked
inputs:
- name: mint
type: csl_spl_token.Mint
- name: gem
type: GemMetadata
solana:
attributes: [ mut ]
seeds:
mint: mint
- name: burn
uses:
- csl_spl_token.burn
inputS:
- name: mint
type: csl_spl_token.Mint
- name: gem
type: GemMetadata
solana:
attributes: [ mut ]
seeds:
mint: mint
Note: Everything highlighted in green is specific to NFT; the rest is specific for business/use case.
General information
When writing the CIDL, the first step we need to take is to specify some general information about the contract we are going to build and the CIDL specification that we want to use, the CIDL specification documentation can be found here.
cidl: "0.8"
info:
name: nft
title: Patika NFT
version: 0.0.1
license:
name: Unlicense
identifier: Unlicense
- cidl: The CIDL specification version, currently on version 0.8
- info: Here we define general information about the contract like the name, title, version, and license information. All these fields are required. We can set some additional recommended fields in the info object. But I kept it out for simplicity.
Defining the GemMetadata account
Optionally, we can define custom types for our CIDL. These types will be transpile to a Solana Account when targeting the Solana blockchain. If we define the seeds to a data structure, this data structure will be transpile to a Solana account. Here you can find the doc regarding seed definitions.
types:
GemMetadata:
solana:
seeds:
- name: "gem"
- name: mint
type: sol:pubkey
fields:
- name: color
type: string
solana:
attributes: [ cap:16 ]
- name: rarity
type: string
solana:
attributes: [ cap:16 ]
- name: short_description
type: string
solana:
attributes: [ cap:255 ]
- name: mint
type: sol:pubkey
- name: assoc_account
type: rs:option<sol:pubkey>
We can define as many types we need for our program under the types section. The types section/block is a key-value pair, where the key is the structure's name and the value is an object where we can define additional configurations.
Under the fields block, we can specify the fields/properties for a given data structure. The fields is an array of objects, where each object must have the name and type property. The name will be the property's name, and the type will be the field's data type. All supported data types can be found here.
Here we are also introducing what we call a Blockchain Extension. Definition for it here. We can define multiple properties through the solana blockchain extension for the types. In this case, we defined the seeds of the type. This will tell the generator to transpile the GemMetadata account into a PDA.
Defining the mint, transfer, and burn instructions
A CIDL must have at least one method/instruction defined. We can define these instructions under the methods block. The methods block is an array of objects, where each object must have, at minimum, the name property defined.
methods:
- name: mint
uses:
- csl_spl_token.initialize_mint2
- csl_spl_assoc_token.create
- csl_spl_token.mint_to
- csl_spl_token.set_authority
inputs:
- name: mint
type: csl_spl_token.Mint
solana:
attributes: [ init ]
- name: gem
type: GemMetadata
solana:
attributes: [ init ]
seeds:
mint: mint
- name: color
type: string
- name: rarity
type: string
- name: short_description
type: string
- name: transfer
uses:
- csl_spl_assoc_token.create
- csl_spl_token.transfer_checked
inputs:
- name: mint
type: csl_spl_token.Mint
- name: gem
type: GemMetadata
solana:
attributes: [ mut ]
seeds:
mint: mint
- name: burn
uses:
- csl_spl_token.burn
inputs:
- name: mint
type: csl_spl_token.Mint
- name: gem
type: GemMetadata
solana:
attributes: [ mut ]
seeds:
mint: mint
Each method can optionally define an array of inputs, where each object must have the name, and type property define. The name will be the parameter’s name, and the type will be the parameter's data type. All supported data types can be found here.
Here, we are introducing two new properties/keywords. The “uses” keyword and “seeds” for input. Let’s look at the first one:
- name: mint
uses:
- csl_spl_token.initialize_mint2
- csl_spl_assoc_token.create
- csl_spl_token.mint_to
- csl_spl_token.set_authority
In solana, we can implement complex use cases thanks to CPI. The CIDL helps us reduce the amount of code we need to write to implement CPI. Through the “uses” property, we can indicate that a method will be calling a given instruction.
We will call four instructions for the mint instruction—one instruction from the csl_spl_assoc_token program and three other instructions from the csl_spl. CSL stands for Código Standard Library, a collection of CIDL built into the generator; thus, developers don’t need to import it manually.
The csl_spl_token is the CIDL representation of the Solana Token Program, and the csl_spl_assoc_token represents the Associated Token Program. In these CIDLs, some instructions add additional properties to facilitate the uses of the instructions.
Note: More documentation regarding imports and uses will come soon. This is a new feature we are launching for the Public Beta; thus, we are in the process of writing the doc for it.
The other new property is seeds for inputs. That concept is well documented here.
Useful Links
List of all built in instructions: Link is here.
Token standard: Link is here.