gill

Create a Token with Metadata

Learn how to create a new Solana token, with metadata, using the gill JavaScript library.

Tokens are digital assets that represent ownership over diverse categories of assets. Tokenization enables the digitalization of property rights. Tokens on Solana are referred to as SPL (Solana Program Library) Tokens.

This article will demonstrate how to create a new SPL token using the gill package, including attaching metadata to the token for users to see and applications to display.

Install gill

Install gill using the core gill library:

npm install gill

Create an RPC connection

In order to send transactions and/or fetch data from the Solana blockchain, you will need an client connection. You can easily create a Solana client connection using the createSolanaClient() function.

The urlOrMoniker can be either a Solana network moniker (e.g. devnet, mainnet, localnet) or a full URL of your RPC provider.

import {  } from "gill";
 
const { ,  } = ({
  : "devnet", // `mainnet`, `localnet`, etc
});

Public RPC endpoints are subject to rate limits

Using a Solana moniker will connect to the public RPC endpoints. These are subject to rate limits and should not be used in production applications. Applications should find their own RPC provider and the URL provided from them.

Prepare a Signer

Every Solana transaction requires at least one "signer" to be the fee payer for the transaction. The following are common practices:

  • load a signer from a local keypair file (like ~/.config/solana/id.json, the one used by the Solana CLI)
  • loading the signer from an ENV variable (e.g. process.env.SERVER_SIGNER)
  • having a user's wallet be the signer via a front end application

Load a signer from a local keypair file

For backend scripts and some server environments, you can load a signer from your local filesystem:

import { type  } from "gill";
import {  } from "gill/node";
 
// This defaults to the file path used by the Solana CLI: `~/.config/solana/id.json`
const :  = await ();
.("signer:", .);

Decide which Token Program to use

To use the legacy Token Program:

import {  } from "gill/programs/token";
 
const  = ;

To use the Token Extensions Program (aka Token22):

import {  } from "gill/programs/token";
 
const  = ;

Generate a Mint and metadata address

import {  } from "gill";
 
const  = await ();

If you are using the legacy Token Program, you will need to derive the "metadata address" from Metaplex's Token Metadata program.

import {  } from "gill";
import {  } from "gill/programs";
 
const  = await ();
const  = await ();

Get the latest blockhash

const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();

Create a transaction that creates a token

Instead of manually crafting all of these instructions, you can also use gill's instruction builder function: getCreateTokenInstructions()

import { createTransaction } from "gill";
import { getMintSize } from "gill/programs/token";
 
const space = getMintSize();
 
const transaction = createTransaction({
  feePayer: signer,
  version: "legacy",
  instructions: [
    getCreateAccountInstruction({
      space,
      lamports: getMinimumBalanceForRentExemption(space),
      newAccount: mint,
      payer: signer,
      programAddress: tokenProgram,
    }),
    getInitializeMintInstruction(
      {
        mint: mint.address,
        mintAuthority: signer.address,
        freezeAuthority: signer.address,
        decimals: 9,
      },
      {
        programAddress: tokenProgram,
      },
    ),
    getCreateMetadataAccountV3Instruction({
      collectionDetails: null,
      isMutable: true,
      updateAuthority: signer,
      mint: mint.address,
      metadata: metadataAddress,
      mintAuthority: signer,
      payer: signer,
      data: {
        sellerFeeBasisPoints: 0,
        collection: null,
        creators: null,
        uses: null,
        name: "super sweet token",
        symbol: "SST",
        uri: "https://raw.githubusercontent.com/solana-developers/opos-asset/main/assets/Climate/metadata.json",
      },
    }),
  ],
  latestBlockhash,
});

Sign and send the transaction

With your transaction fully created, you can now sign the transaction to

import { signTransactionMessageWithSigners } from "gill";
 
const signedTransaction = await signTransactionMessageWithSigners(transaction);
 
console.log(
  "Explorer:",
  getExplorerLink({
    cluster: "devnet",
    transaction: getSignatureFromTransaction(signedTransaction),
  }),
);

If your transaction is already fully signed or has all signer's available, you can send and confirm it on the blockchain.

await sendAndConfirmTransaction(signedTransaction);

Pro Tip

If you do not need to know the transaction signature prior to sending the transaction AND you all signers are attached to the transaction, you can pass a fully signable transaction to the sendAndConfirmTransaction() function initialized from createSolanaClient(). It will then perform the signing operations prior to sending and confirming.

On this page