Beginner

 

How to write Token Program on Solana Blockchain

This tutorial will guide you on how to write a token program on the Solana blockchain. Solana’s programming model and terminology are explained in the background section, and instructions on how to set up and configure the necessary tools using JavaScript are provided. The tutorial then goes on to show examples of creating fungible and non-fungible tokens, as well as transferring, approving, and freezing tokens. Finally, the tutorial explains how to create and manage non-fungible tokens using the NFT program provided in the spl-token library.

Background

Solana’s programming model and the definitions of the Solana terms used in this document are available at:

https://docs.solana.com/developers

https://docs.solana.com/terminology

Setup with JavaScript
Yarn

yarn add @solana/spl-token

 

npm

npm install @solana/spl-token

 

Configuration

You can connect to different clusters using Connection in @solana/web3.js

const web3 = require('@solana/web3.js');
const connection = new web3.Connection(web3.clusterApiUrl('devnet'), 'confirmed');

 

Keypair​

You can either get your keypair using Keypair from @solana/web3.js, or let the user’s wallet handle the keypair and use sendTransaction from wallet-adapter

Airdrop SOL

Creating tokens and accounts requires SOL for account rent deposits and transaction fees. If the cluster you are targeting offers a faucet, you can get a little SOL for testing:

  • CLI
  • JS
import { clusterApiUrl, Connection, Keypair, LAMPORTS_PER_SOL } from '@solana/web3.js';

const payer = Keypair.generate();

const connection = new Connection(
clusterApiUrl('devnet'),
'confirmed'
);

const airdropSignature = await connection.requestAirdrop(
payer.publicKey,
LAMPORTS_PER_SOL,
);

await connection.confirmTransaction(airdropSignature);

 

By using console you can see airdrop Signature as sown below q3BJjy2mA5F5HWXDsoF1Kwo58EF6Drqjz2XbZhpZqTAfEP5Gpi2F1XSvYqW87ut3G7XdWJRQuztiqK86MErbfHB

Below are the examples of creating fungible tokens and view tokens.

import { createMint } from '@solana/spl-token';
import { clusterApiUrl, Connection, Keypair, LAMPORTS_PER_SOL } from '@solana/web3.js';

const payer = Keypair.generate();
const mintAuthority = Keypair.generate();
const freezeAuthority = Keypair.generate();

const connection = new Connection(
clusterApiUrl('devnet'),
'confirmed'
);

const mint = await createMint(
connection,
payer,
mintAuthority.publicKey,
freezeAuthority.publicKey,
9 // We are using 9 to match the CLI decimal default exactly
);

console.log(mint.toBase58());

 

The unique identifier of the token is AQoKYV7tYpTrFZN6P5oUufbQKAUr9mNYGe1TTJC9wajM.

Tokens when initially created by spl-token have no supply.

Use below function to check the supply

const mintInfo = await getMint(
connection,
mint
)

console.log(mintInfo.supply);
// 0

 

Let’s mint some. First create an account to hold a balance of the new AQoKYV7tYpTrFZN6P5oUufbQKAUr9mNYGe1TTJC9wajM

token:const tokenAccount = await getOrCreateAssociatedTokenAccount( connection, payer, mint, payer.publicKey ) console.log(tokenAccount.address.toBase58()); // 7UX2i7SucgLMQcfZ75s3VXmZZY4YRUyJN9X1RgfMoDUi

7UX2i7SucgLMQcfZ75s3VXmZZY4YRUyJN9X1RgfMoDUi is now an empty account:

const tokenAccountInfo = await getAccount(
connection,
tokenAccount.address
)

console.log(tokenAccountInfo.amount);
// 0

 

Mint 100 tokens into the account:

await mintTo(
connection,
payer,
mint,
tokenAccount.address,
mintAuthority,
100000000000 // because decimals for the mint are set to 9
)

 

The token supply and account balance now reflect the result of minting:

const mintInfo = await getMint(
connection,
mint
)

console.log(mintInfo.supply);
// 100

const tokenAccountInfo = await getAccount(
connection,
tokenAccount.address
)

console.log(tokenAccountInfo.amount);
// 100

 

Example: View all Tokens that you own

import {AccountLayout, TOKEN_PROGRAM_ID} from "@solana/spl-token";
import {clusterApiUrl, Connection, PublicKey} from "@solana/web3.js";

(async () => {

const connection = new Connection(clusterApiUrl('devnet'), 'confirmed');

const tokenAccounts = await connection.getTokenAccountsByOwner(
new PublicKey('8YLKoCu7NwqHNS8GzuvA2ibsvLrsg22YMfMDafxh1B15'),
{
programId: TOKEN_PROGRAM_ID,
}
);

console.log("Token Balance");
console.log("------------------------------------------------------------");
tokenAccounts.value.forEach((tokenAccount) => {
const accountData = AccountLayout.decode(tokenAccount.account.data);
console.log(`${new PublicKey(accountData.mint)} ${accountData.amount}`);
})

})();

By running above code you can see the token you own and its informtion below you can see

Token Balance
------------------------------------------------------------
7e2X5oeAAJyUTi4PfSGXFLGhyPw2H8oELm1mx87ZCgwF 84
AQoKYV7tYpTrFZN6P5oUufbQKAUr9mNYGe1TTJC9wajM 100
AQoKYV7tYpTrFZN6P5oUufbQKAUr9mNYGe1TTJC9wajM 0
AQoKYV7tYpTrFZN6P5oUufbQKAUr9mNYGe1TTJC9wajM 1

 

Congratulations You have done workshop-2 successfully