---
title: Mint Tokens
description: Mint new token units to a token account with the mint authority.
url: /docs/tokens/basics/mint-tokens
type: tutorial
prerequisites:
  - /docs/tokens/basics/create-mint
  - /docs/tokens/basics/create-token-account
related:
  - /docs/tokens/basics/transfer-tokens
  - /docs/tokens/basics/burn-tokens
  - /docs/tokens/basics/set-authority
  - /docs/tokens/basics/approve-delegate
---

## What Does Minting Do?

Minting creates new units of an existing token and increases the mint's total
supply.

Only the mint authority can mint new tokens. The destination token account must
already exist and must belong to the same mint.

## How to Mint Tokens

Minting tokens uses the Token Program's _rs`MintTo`_ or _rs`MintToChecked`_
instruction.

The examples below use _rs`MintToChecked`_, which requires the caller to provide
the mint's decimals so the instruction can verify the expected token precision
before minting.

The [native mint](/docs/tokens/basics/sync-native) does not support minting.

### Source Reference

| Item                  | Description                                                                                                                                          | Token Program                                                                                                  | Token Extension Program                                                                                              |
| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| _rs`Mint`_            | The mint state stores the mint authority and total token supply.                                                                                     | [Source](https://github.com/solana-program/token/blob/program%40v9.0.0/interface/src/state.rs#L13-L30)         | [Source](https://github.com/solana-program/token-2022/blob/program%40v10.0.0/interface/src/state.rs#L25-L42)         |
| _rs`Account`_         | The token account state stores the destination balance updated by minting.                                                                           | [Source](https://github.com/solana-program/token/blob/program%40v9.0.0/interface/src/state.rs#L84-L108)        | [Source](https://github.com/solana-program/token-2022/blob/program%40v10.0.0/interface/src/state.rs#L99-L123)        |
| _rs`MintTo`_          | A mint instruction that mints tokens to an existing token account without requiring the caller to provide the mint's decimals.                       | [Source](https://github.com/solana-program/token/blob/program%40v9.0.0/interface/src/instruction.rs#L159-L177) | [Source](https://github.com/solana-program/token-2022/blob/program%40v10.0.0/interface/src/instruction.rs#L202-L220) |
| _rs`MintToChecked`_   | A mint instruction that requires the caller to provide the mint's decimals and checks that value before minting tokens to an existing token account. | [Source](https://github.com/solana-program/token/blob/program%40v9.0.0/interface/src/instruction.rs#L301-L325) | [Source](https://github.com/solana-program/token-2022/blob/program%40v10.0.0/interface/src/instruction.rs#L367-L391) |
| _rs`process_mint_to`_ | Shared processor logic for minting tokens.                                                                                                           | [Source](https://github.com/solana-program/token/blob/program%40v9.0.0/program/src/processor.rs#L521-L583)     | [Source](https://github.com/solana-program/token-2022/blob/program%40v10.0.0/program/src/processor.rs#L981-L1067)    |

### Typescript

The `Kit` examples below show the recommended approach using `@solana/kit`.
Legacy examples using `@solana/web3.js` are included for reference.

#### Kit

<CodeTabs storage="token-ts-kit" flags="r">

```ts !! title="Plugin"
import { createClient, generateKeyPairSigner, lamports } from "@solana/kit";
import { solanaRpc, rpcAirdrop } from "@solana/kit-plugin-rpc";
import { generatedPayer, airdropPayer } from "@solana/kit-plugin-signer";
import {
  findAssociatedTokenPda,
  tokenProgram,
  TOKEN_PROGRAM_ADDRESS
} from "@solana-program/token";

const client = await createClient()
  .use(generatedPayer())
  .use(
    solanaRpc({
      rpcUrl: "http://localhost:8899",
      rpcSubscriptionsUrl: "ws://localhost:8900"
    })
  )
  .use(rpcAirdrop())
  .use(airdropPayer(lamports(1_000_000_000n)))
  // !mark[/\.use\(tokenProgram\(\)\)/]
  .use(tokenProgram());

const mint = await generateKeyPairSigner();

// !collapse(1:9) collapsed
// Setup: create a mint before minting tokens to the payer's ATA.
await client.token.instructions
  .createMint({
    newMint: mint,
    decimals: 2,
    mintAuthority: client.payer.address,
    freezeAuthority: client.payer.address
  })
  .sendTransaction();

const result = await client.token.instructions
  // !mark(1:7)
  .mintToATA({
    mint: mint.address, // Mint for the token being minted.
    owner: client.payer.address, // Account that owns the token account receiving the minted tokens.
    mintAuthority: client.payer, // Authority allowed to mint new tokens.
    amount: 100n, // Token amount in base units.
    decimals: 2 // Decimals defined on the mint account.
  })
  .sendTransaction();

const [tokenAccount] = await findAssociatedTokenPda({
  mint: mint.address,
  owner: client.payer.address,
  tokenProgram: TOKEN_PROGRAM_ADDRESS
});

const mintAccount = await client.token.accounts.mint.fetch(mint.address);
const tokenAccountData = await client.token.accounts.token.fetch(tokenAccount);

console.log("Mint Address:", mint.address);
console.log("Mint Account:", mintAccount.data);
console.log("\nToken Account Address:", tokenAccount);
console.log("Token Account:", tokenAccountData.data);
console.log("\nTransaction Signature:", result.context.signature);
```

```ts !! title="Instruction Plan"
import { createClient, generateKeyPairSigner, lamports } from "@solana/kit";
import { solanaRpc, rpcAirdrop } from "@solana/kit-plugin-rpc";
import { generatedPayer, airdropPayer } from "@solana/kit-plugin-signer";
import {
  fetchMint,
  fetchToken,
  findAssociatedTokenPda,
  getCreateMintInstructionPlan,
  getMintToATAInstructionPlanAsync,
  TOKEN_PROGRAM_ADDRESS
} from "@solana-program/token";

const client = await createClient()
  .use(generatedPayer())
  .use(
    solanaRpc({
      rpcUrl: "http://localhost:8899",
      rpcSubscriptionsUrl: "ws://localhost:8900"
    })
  )
  .use(rpcAirdrop())
  .use(airdropPayer(lamports(1_000_000_000n)));

const mint = await generateKeyPairSigner();

// !collapse(1:10) collapsed
// Setup: create a mint before minting tokens to the payer's ATA.
await client.sendTransaction(
  getCreateMintInstructionPlan({
    payer: client.payer,
    newMint: mint,
    decimals: 2,
    mintAuthority: client.payer.address,
    freezeAuthority: client.payer.address
  })
);

const result = await client.sendTransaction(
  // !mark(1:8)
  await getMintToATAInstructionPlanAsync({
    payer: client.payer, // Account funding account creation.
    mint: mint.address, // Mint for the token being minted.
    owner: client.payer.address, // Account that owns the token account receiving the minted tokens.
    mintAuthority: client.payer, // Authority allowed to mint new tokens.
    amount: 100n, // Token amount in base units.
    decimals: 2 // Decimals defined on the mint account.
  })
);

const [tokenAccount] = await findAssociatedTokenPda({
  mint: mint.address,
  owner: client.payer.address,
  tokenProgram: TOKEN_PROGRAM_ADDRESS
});

const mintAccount = await fetchMint(client.rpc, mint.address);
const tokenAccountData = await fetchToken(client.rpc, tokenAccount);

console.log("Mint Address:", mint.address);
console.log("Mint Account:", mintAccount.data);
console.log("\nToken Account Address:", tokenAccount);
console.log("Token Account:", tokenAccountData.data);
console.log("\nTransaction Signature:", result.context.signature);
```

```ts !! title="Instructions"
import { createClient, generateKeyPairSigner, lamports } from "@solana/kit";
import { solanaRpc, rpcAirdrop } from "@solana/kit-plugin-rpc";
import { generatedPayer, airdropPayer } from "@solana/kit-plugin-signer";
import {
  fetchMint,
  fetchToken,
  findAssociatedTokenPda,
  getCreateAssociatedTokenInstructionAsync,
  getCreateMintInstructionPlan,
  getMintToCheckedInstruction,
  TOKEN_PROGRAM_ADDRESS
} from "@solana-program/token";

const client = await createClient()
  .use(generatedPayer())
  .use(
    solanaRpc({
      rpcUrl: "http://localhost:8899",
      rpcSubscriptionsUrl: "ws://localhost:8900"
    })
  )
  .use(rpcAirdrop())
  .use(airdropPayer(lamports(1_000_000_000n)));

const mint = await generateKeyPairSigner();

const [tokenAccount] = await findAssociatedTokenPda({
  mint: mint.address,
  owner: client.payer.address,
  tokenProgram: TOKEN_PROGRAM_ADDRESS
});

// !collapse(1:15) collapsed
// Setup: create a mint and the payer's ATA before minting tokens.
await client.sendTransaction([
  getCreateMintInstructionPlan({
    payer: client.payer,
    newMint: mint,
    decimals: 2,
    mintAuthority: client.payer.address,
    freezeAuthority: client.payer.address
  }),
  await getCreateAssociatedTokenInstructionAsync({
    payer: client.payer,
    mint: mint.address,
    owner: client.payer.address
  })
]);

const result = await client.sendTransaction([
  // !mark(1:7)
  getMintToCheckedInstruction({
    mint: mint.address, // Mint for the token being minted.
    token: tokenAccount, // Token account receiving the minted tokens.
    mintAuthority: client.payer, // Authority allowed to mint new tokens.
    amount: 100n, // Token amount in base units.
    decimals: 2 // Decimals defined on the mint account.
  })
]);

const mintAccount = await fetchMint(client.rpc, mint.address);
const tokenAccountData = await fetchToken(client.rpc, tokenAccount);

console.log("Mint Address:", mint.address);
console.log("Mint Account:", mintAccount.data);
console.log("\nToken Account Address:", tokenAccount);
console.log("Token Account:", tokenAccountData.data);
console.log("\nTransaction Signature:", result.context.signature);
```

</CodeTabs>

#### Web3.js

<CodeTabs storage="token-ts-legacy" flags="r">

```ts !! title="Helper Function"
import { Connection, Keypair, LAMPORTS_PER_SOL } from "@solana/web3.js";
import {
  createAssociatedTokenAccount,
  createMint,
  getAccount,
  getMint,
  mintToChecked,
  TOKEN_PROGRAM_ID
} from "@solana/spl-token";

// !collapse(1:39) collapsed
// Setup: create a mint and the payer's ATA before minting tokens.
const connection = new Connection("http://localhost:8899", "confirmed");
const latestBlockhash = await connection.getLatestBlockhash();

const feePayer = Keypair.generate();

const airdropSignature = await connection.requestAirdrop(
  feePayer.publicKey,
  LAMPORTS_PER_SOL
);
await connection.confirmTransaction({
  blockhash: latestBlockhash.blockhash,
  lastValidBlockHeight: latestBlockhash.lastValidBlockHeight,
  signature: airdropSignature
});

const mintPubkey = await createMint(
  connection,
  feePayer,
  feePayer.publicKey,
  feePayer.publicKey,
  2,
  Keypair.generate(),
  {
    commitment: "confirmed"
  },
  TOKEN_PROGRAM_ID
);

const associatedTokenAccount = await createAssociatedTokenAccount(
  connection,
  feePayer,
  mintPubkey,
  feePayer.publicKey,
  {
    commitment: "confirmed"
  },
  TOKEN_PROGRAM_ID
);

// !mark(1:14)
const result = await mintToChecked(
  connection, // Connection to the local validator.
  feePayer, // Account paying transaction fees.
  mintPubkey, // Mint for the token being minted.
  associatedTokenAccount, // Token account receiving the minted tokens.
  feePayer, // Authority allowed to mint new tokens.
  100, // Token amount in base units.
  2, // Decimals defined on the mint account.
  [], // Additional multisig signers.
  {
    commitment: "confirmed" // Confirmation options for the transaction.
  },
  TOKEN_PROGRAM_ID // Token program to invoke.
);

const mintAccount = await getMint(
  connection,
  mintPubkey,
  "confirmed",
  TOKEN_PROGRAM_ID
);
const tokenAccountData = await getAccount(
  connection,
  associatedTokenAccount,
  "confirmed",
  TOKEN_PROGRAM_ID
);

console.log("Mint Address:", mintPubkey.toBase58());
console.log("Mint Account:", mintAccount);
console.log(
  "\nAssociated Token Account Address:",
  associatedTokenAccount.toBase58()
);
console.log("Associated Token Account:", tokenAccountData);
console.log("\nTransaction Signature:", result);
```

```ts !! title="Instructions"
import {
  Connection,
  Keypair,
  sendAndConfirmTransaction,
  SystemProgram,
  Transaction,
  LAMPORTS_PER_SOL
} from "@solana/web3.js";
import {
  ASSOCIATED_TOKEN_PROGRAM_ID,
  createAssociatedTokenAccountInstruction,
  createInitializeMintInstruction,
  createMintToCheckedInstruction,
  getAccount,
  getAssociatedTokenAddressSync,
  getMinimumBalanceForRentExemptMint,
  getMint,
  MINT_SIZE,
  TOKEN_PROGRAM_ID
} from "@solana/spl-token";

// !collapse(1:60) collapsed
// Setup: create a mint and the payer's ATA before minting tokens.
const connection = new Connection("http://localhost:8899", "confirmed");
const latestBlockhash = await connection.getLatestBlockhash();

const feePayer = Keypair.generate();

const airdropSignature = await connection.requestAirdrop(
  feePayer.publicKey,
  LAMPORTS_PER_SOL
);
await connection.confirmTransaction({
  blockhash: latestBlockhash.blockhash,
  lastValidBlockHeight: latestBlockhash.lastValidBlockHeight,
  signature: airdropSignature
});

const mint = Keypair.generate();
const mintRent = await getMinimumBalanceForRentExemptMint(connection);
const associatedTokenAccount = getAssociatedTokenAddressSync(
  mint.publicKey,
  feePayer.publicKey,
  false, // allowOwnerOffCurve
  TOKEN_PROGRAM_ID,
  ASSOCIATED_TOKEN_PROGRAM_ID
);

await sendAndConfirmTransaction(
  connection,
  new Transaction({
    feePayer: feePayer.publicKey,
    blockhash: latestBlockhash.blockhash,
    lastValidBlockHeight: latestBlockhash.lastValidBlockHeight
  }).add(
    SystemProgram.createAccount({
      fromPubkey: feePayer.publicKey,
      newAccountPubkey: mint.publicKey,
      space: MINT_SIZE,
      lamports: mintRent,
      programId: TOKEN_PROGRAM_ID
    }),
    createInitializeMintInstruction(
      mint.publicKey,
      2,
      feePayer.publicKey,
      feePayer.publicKey,
      TOKEN_PROGRAM_ID
    ),
    createAssociatedTokenAccountInstruction(
      feePayer.publicKey,
      associatedTokenAccount,
      feePayer.publicKey,
      mint.publicKey,
      TOKEN_PROGRAM_ID,
      ASSOCIATED_TOKEN_PROGRAM_ID
    )
  ),
  [feePayer, mint]
);

const mintBlockhash = await connection.getLatestBlockhash();

const result = await sendAndConfirmTransaction(
  connection,
  new Transaction({
    feePayer: feePayer.publicKey,
    blockhash: mintBlockhash.blockhash,
    lastValidBlockHeight: mintBlockhash.lastValidBlockHeight
  }).add(
    // !mark(1:9)
    createMintToCheckedInstruction(
      mint.publicKey, // Mint for the token being minted.
      associatedTokenAccount, // Token account receiving the minted tokens.
      feePayer.publicKey, // Authority allowed to mint new tokens.
      100, // Token amount in base units.
      2, // Decimals defined on the mint account.
      [], // Additional multisig signers.
      TOKEN_PROGRAM_ID // Token program to invoke.
    )
  ),
  [feePayer]
);

const mintAccount = await getMint(
  connection,
  mint.publicKey,
  "confirmed",
  TOKEN_PROGRAM_ID
);
const tokenAccountData = await getAccount(
  connection,
  associatedTokenAccount,
  "confirmed",
  TOKEN_PROGRAM_ID
);

console.log("Mint Address:", mint.publicKey.toBase58());
console.log("Mint Account:", mintAccount);
console.log(
  "\nAssociated Token Account Address:",
  associatedTokenAccount.toBase58()
);
console.log("Associated Token Account:", tokenAccountData);
console.log("\nTransaction Signature:", result);
```

</CodeTabs>

### Rust

<CodeTabs storage="token-rs" flags="r">

```rust !! title="Rust"
use anyhow::Result;
use solana_client::nonblocking::rpc_client::RpcClient;
use solana_commitment_config::CommitmentConfig;
use solana_sdk::{
    program_pack::Pack,
    signature::{Keypair, Signer},
    transaction::Transaction,
};
use solana_system_interface::instruction::create_account;
use spl_associated_token_account_interface::{
    address::get_associated_token_address,
    instruction::create_associated_token_account,
};
use spl_token_interface::{
    id as token_program_id,
    instruction::{initialize_mint, mint_to_checked},
    state::{Account, Mint},
};

#[tokio::main]
async fn main() -> Result<()> {
    let client = RpcClient::new_with_commitment(
        String::from("http://localhost:8899"),
        CommitmentConfig::confirmed(),
    );

    // !collapse(1:48) collapsed
    // Setup: create a mint and the payer's ATA before minting tokens.
    let fee_payer = Keypair::new();
    let decimals = 2;

    let airdrop_signature = client
        .request_airdrop(&fee_payer.pubkey(), 1_000_000_000)
        .await?;
    loop {
        let confirmed = client.confirm_transaction(&airdrop_signature).await?;
        if confirmed {
            break;
        }
    }

    let mint = Keypair::new();
    let mint_rent = client
        .get_minimum_balance_for_rent_exemption(Mint::LEN)
        .await?;

    let latest_blockhash = client.get_latest_blockhash().await?;
    let setup_transaction = Transaction::new_signed_with_payer(
        &[
            create_account(
                &fee_payer.pubkey(),
                &mint.pubkey(),
                mint_rent,
                Mint::LEN as u64,
                &token_program_id(),
            ),
            initialize_mint(
                &token_program_id(),
                &mint.pubkey(),
                &fee_payer.pubkey(),
                Some(&fee_payer.pubkey()),
                decimals,
            )?,
            create_associated_token_account(
                &fee_payer.pubkey(),
                &fee_payer.pubkey(),
                &mint.pubkey(),
                &token_program_id(),
            ),
        ],
        Some(&fee_payer.pubkey()),
        &[&fee_payer, &mint],
        latest_blockhash,
    );
    client.send_and_confirm_transaction(&setup_transaction).await?;

    let associated_token_address = get_associated_token_address(&fee_payer.pubkey(), &mint.pubkey());
    let mint_amount = 100;

    let transaction = Transaction::new_signed_with_payer(
        &[
            // !mark(1:9)
            mint_to_checked(
                &token_program_id(), // Token program to invoke.
                &mint.pubkey(), // Mint for the token being minted.
                &associated_token_address, // Token account receiving the minted tokens.
                &fee_payer.pubkey(), // Authority allowed to mint new tokens.
                &[], // Additional multisig signers.
                mint_amount, // Token amount in base units.
                decimals, // Decimals defined on the mint account.
            )?,
        ],
        Some(&fee_payer.pubkey()),
        &[&fee_payer],
        latest_blockhash,
    );

    let transaction_signature = client.send_and_confirm_transaction(&transaction).await?;
    let mint_account = client.get_account(&mint.pubkey()).await?;
    let mint_data = Mint::unpack(&mint_account.data)?;
    let token_account = client.get_account(&associated_token_address).await?;
    let token_data = Account::unpack(&token_account.data)?;

    println!("Mint Address: {}", mint.pubkey());
    println!("Mint Account: {:#?}", mint_data);
    println!(
        "\nAssociated Token Account Address: {}",
        associated_token_address
    );
    println!("Associated Token Account: {:#?}", token_data);
    println!("\nTransaction Signature: {}", transaction_signature);

    Ok(())
}
```

</CodeTabs>

### Python

<CodeTabs flags="r">

```py !! title="Python"
#!/usr/bin/env python3

import asyncio
import json
from solana.rpc.async_api import AsyncClient
from solders.keypair import Keypair
from solders.message import Message
from solders.pubkey import Pubkey
from solders.system_program import create_account, CreateAccountParams
from solders.transaction import Transaction
from spl.token.async_client import AsyncToken
from spl.token.instructions import (
    create_associated_token_account,
    get_associated_token_address,
    initialize_mint,
    InitializeMintParams,
    mint_to_checked,
    MintToCheckedParams,
)
from spl.token.constants import MINT_LEN, TOKEN_PROGRAM_ID

DECIMALS = 2
AMOUNT_TO_MINT = 100

async def main():
    rpc = AsyncClient("http://localhost:8899")

    async with rpc:
        # !collapse(1:20) collapsed
        # Setup: create a mint and destination token account before minting tokens.
        fee_payer = Keypair()
        airdrop_signature = (await rpc.request_airdrop(fee_payer.pubkey(), 1_000_000_000)).value
        await rpc.confirm_transaction(airdrop_signature)
        mint = Keypair()
        destination_token_account = get_associated_token_address(fee_payer.pubkey(), mint.pubkey())
        mint_rent = (await rpc.get_minimum_balance_for_rent_exemption(MINT_LEN)).value
        setup_instructions = [
            create_account(CreateAccountParams(from_pubkey=fee_payer.pubkey(), to_pubkey=mint.pubkey(), lamports=mint_rent, space=MINT_LEN, owner=TOKEN_PROGRAM_ID)),
            initialize_mint(InitializeMintParams(decimals=DECIMALS, program_id=TOKEN_PROGRAM_ID, mint=mint.pubkey(), mint_authority=fee_payer.pubkey())),
            create_associated_token_account(fee_payer.pubkey(), fee_payer.pubkey(), mint.pubkey(), TOKEN_PROGRAM_ID),
        ]
        setup_blockhash = await rpc.get_latest_blockhash()
        setup_transaction = Transaction(
            [fee_payer, mint],
            Message(setup_instructions, fee_payer.pubkey()),
            setup_blockhash.value.blockhash,
        )
        await rpc.send_transaction(setup_transaction)
        token = AsyncToken(rpc, mint.pubkey(), TOKEN_PROGRAM_ID, fee_payer)

        # !mark(1:10)
        mint_tokens_instruction = mint_to_checked(
            MintToCheckedParams(
                program_id=TOKEN_PROGRAM_ID,  # Token program to invoke.
                mint=mint.pubkey(),  # Mint for the token being minted.
                dest=destination_token_account,  # Token account receiving the minted tokens.
                mint_authority=fee_payer.pubkey(),  # Authority allowed to mint new tokens.
                amount=AMOUNT_TO_MINT,  # Token amount in base units.
                decimals=DECIMALS,  # Decimals defined on the mint account.
            )
        )
        latest_blockhash = await rpc.get_latest_blockhash()
        transaction = Transaction(
            [fee_payer],
            Message([mint_tokens_instruction], fee_payer.pubkey()),
            latest_blockhash.value.blockhash,
        )
        result = await rpc.send_transaction(transaction)

        mint_info = await token.get_mint_info()
        destination_token_account_info = await token.get_account_info(destination_token_account)
        mint_account = {
            key: str(value) if isinstance(value, Pubkey) else value
            for key, value in mint_info._asdict().items()
        }
        token_account = {
            key: str(value) if isinstance(value, Pubkey) else value
            for key, value in destination_token_account_info._asdict().items()
        }

        print("Mint Address:", mint.pubkey())
        print("Mint Account:")
        print(json.dumps(mint_account, indent=2))
        print("\nToken Account Address:", destination_token_account)
        print("Token Account:")
        print(json.dumps(token_account, indent=2))
        print("\nTransaction Signature:", result.value)

if __name__ == "__main__":
    asyncio.run(main())
```

</CodeTabs>
