gill

Mint Tokens

Learn how to mint new token supply to a wallet using the gill JavaScript library.

Minting tokens creates new supply of an existing token and sends it to a wallet via its Associated Token Account (ATA). Only the mint authority signer can authorize minting new tokens.

This guide demonstrates how to mint tokens using the gill package, including automatically creating the destination wallet's ATA if it does not already exist.

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 a 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. When minting tokens, the mintAuthority must also be a signer to authorize the mint.

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:", .);

Understanding token amounts

When minting tokens, the amount you provide is in raw base units, not human-readable units. The conversion depends on the decimals value of your token mint.

For example, if your token has decimals = 9 (the most common for fungible tokens):

  • 1_000_000_000 (1e9) = 1 token
  • 5_000_000_000 (5e9) = 5 tokens
  • 1_000_000 (1e6) = 0.001 tokens

Decimals matter

With decimals = 9, to mint 100 tokens you would set amount to 100_000_000_000 (100e9). With decimals = 6, to mint 100 tokens you would set amount to 100_000_000 (100e6). Always check your token's decimals to calculate the correct raw amount.

Build the mint transaction

The simplest way to mint tokens is using the buildMintTokensTransaction() helper from gill/programs. It automatically derives the destination wallet's ATA and sets compute unit limits.

import { buildMintTokensTransaction } from "gill/programs";

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

const transaction = await buildMintTokensTransaction({
  feePayer: signer,
  version: "legacy",
  latestBlockhash,
  mint: mint.address,
  mintAuthority: signer,
  destination: destinationWallet,
  amount: 1_000_000_000, // 1 token (with decimals=9)
});

Where mint.address is the address of the token mint you previously created and destinationWallet is the wallet address that should receive the tokens.

Manually create the mint instructions

If you need more control over the transaction, you can use getMintTokensInstructions() to get the individual instructions and compose the transaction yourself.

First, derive the ATA for the destination wallet:

import { getAssociatedTokenAccountAddress } from "gill/programs";

const ata = await getAssociatedTokenAccountAddress(mint.address, destinationWallet);

Then create the instructions and build the transaction:

import { createTransaction } from "gill";
import { getMintTokensInstructions } from "gill/programs";

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

const instructions = getMintTokensInstructions({
  feePayer: signer,
  mint: mint.address,
  mintAuthority: signer,
  destination: destinationWallet,
  ata,
  amount: 1_000_000_000, // 1 token (with decimals=9)
});

const transaction = createTransaction({
  feePayer: signer,
  version: "legacy",
  instructions,
  latestBlockhash,
});

This gives you the same two instructions that buildMintTokensTransaction() creates under the hood:

  1. Create ATA (idempotent) — creates the destination's Associated Token Account if it does not already exist
  2. Mint to — mints the specified amount of tokens to the ATA

Sign and send the transaction

With your transaction fully created, you can now sign and send it:

import {
  signTransactionMessageWithSigners,
  getSignatureFromTransaction,
  getExplorerLink,
} 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 signers 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 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.

Using Token Extensions (Token22)

If your token was created with the Token Extensions program (Token22), pass the tokenProgram parameter to ensure the correct program is used:

import { TOKEN_2022_PROGRAM_ADDRESS, buildMintTokensTransaction } from "gill/programs";

const transaction = await buildMintTokensTransaction({
  feePayer: signer,
  version: "legacy",
  latestBlockhash,
  mint: mint.address,
  mintAuthority: signer,
  destination: destinationWallet,
  amount: 1_000_000_000,
  tokenProgram: TOKEN_2022_PROGRAM_ADDRESS,
});

The same tokenProgram parameter is available on getMintTokensInstructions() and getAssociatedTokenAccountAddress() as well.