---
title: Create a Token Mint
description:
  Create a token mint and configure the mint's decimals, mint authority, and
  freeze authority.
url: /docs/tokens/basics/create-mint
type: tutorial
prerequisites:
  - /docs/tokens/basics
related:
  - /docs/tokens/basics/create-token-account
  - /docs/tokens/basics/mint-tokens
  - /docs/tokens/basics/set-authority
  - /docs/tokens/metaplex
---

## What Is a Mint Account

A mint account defines and uniquely identifies a token on Solana, and stores the
shared state that applies to all token accounts for that mint.

The Token Program defines the _rs`Mint`_ account type as:

```rust title="Mint Account Type"
/// Mint data.
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Mint {
  /// Optional authority used to mint new tokens. The mint authority may only
  /// be provided during mint creation. If no mint authority is present
  /// then the mint has a fixed supply and no further tokens may be
  /// minted.
  pub mint_authority: COption<Pubkey>,
  /// Total supply of tokens.
  pub supply: u64,
  /// Number of base 10 digits to the right of the decimal place.
  pub decimals: u8,
  /// Is `true` if this structure has been initialized
  pub is_initialized: bool,
  /// Optional authority to freeze token accounts.
  pub freeze_authority: COption<Pubkey>,
}
```

Every token has one mint account, and the mint address is the token's unique
identifier across wallets, applications, and explorers.

For example, USD Coin (USDC) has the mint address
`EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v`. The mint address uniquely
identifies USDC throughout the Solana ecosystem. You can view this mint on
[Solana Explorer](https://explorer.solana.com/address/EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v).

## How to Create a Mint Account

Creating a mint requires two instructions:

1. The System Program's _rs`CreateAccount`_ instruction creates a new
   rent-exempt account and assigns the Token Program as the program owner of the
   new account.
2. The Token Program's _rs`InitializeMint`_ or _rs`InitializeMint2`_ instruction
   initializes the new account as a mint.

Include the _rs`CreateAccount`_ instruction and the mint initialization
instruction in the same transaction.

During mint initialization, the Token Program checks that the mint account is
not already initialized and is rent-exempt. The Token Program then writes the
mint authority, freeze authority, decimals, and _rs`is_initialized`_ flag into
the mint account data.

### Source Reference

| Item                           | Description                                                                                           | Token Program                                                                                                  | Token Extension Program                                                                                              |
| ------------------------------ | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| _rs`Mint`_                     | The base mint state stored in every mint account.                                                     | [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`InitializeMint`_           | A mint initialization instruction that expects the rent sysvar account in its accounts list.          | [Source](https://github.com/solana-program/token/blob/program%40v9.0.0/interface/src/instruction.rs#L24-L44)   | [Source](https://github.com/solana-program/token-2022/blob/program%40v10.0.0/interface/src/instruction.rs#L50-L74)   |
| _rs`InitializeMint2`_          | A mint initialization instruction that does not require the rent sysvar account in its accounts list. | [Source](https://github.com/solana-program/token/blob/program%40v9.0.0/interface/src/instruction.rs#L401-L414) | [Source](https://github.com/solana-program/token-2022/blob/program%40v10.0.0/interface/src/instruction.rs#L471-L486) |
| _rs`_process_initialize_mint`_ | Shared processor logic for mint initialization.                                                       | [Source](https://github.com/solana-program/token/blob/program%40v9.0.0/program/src/processor.rs#L27-L60)       | [Source](https://github.com/solana-program/token-2022/blob/program%40v10.0.0/program/src/processor.rs#L87-L130)      |
| _rs`process_initialize_mint`_  | Public handler for _rs`InitializeMint`_.                                                              | [Source](https://github.com/solana-program/token/blob/program%40v9.0.0/program/src/processor.rs#L62-L70)       | [Source](https://github.com/solana-program/token-2022/blob/program%40v10.0.0/program/src/processor.rs#L132-L140)     |
| _rs`process_initialize_mint2`_ | Public handler for _rs`InitializeMint2`_.                                                             | [Source](https://github.com/solana-program/token/blob/program%40v9.0.0/program/src/processor.rs#L72-L81)       | [Source](https://github.com/solana-program/token-2022/blob/program%40v10.0.0/program/src/processor.rs#L142-L151)     |

### 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 { tokenProgram } 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();

const result = await client.token.instructions
  // !mark(1:6)
  .createMint({
    newMint: mint, // New mint account to create.
    decimals: 9, // Decimals to define on the mint account.
    mintAuthority: client.payer.address, // Authority allowed to mint new tokens.
    freezeAuthority: client.payer.address // Authority allowed to freeze token accounts.
  })
  .sendTransaction();

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

console.log("Mint Address:", mint.address);
console.log("Mint Account:", mintAccount.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, getCreateMintInstructionPlan } 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 result = await client.sendTransaction(
  // !mark(1:7)
  getCreateMintInstructionPlan({
    payer: client.payer, // Account funding account creation.
    newMint: mint, // New mint account to create.
    decimals: 9, // Decimals to define on the mint account.
    mintAuthority: client.payer.address, // Authority allowed to mint new tokens.
    freezeAuthority: client.payer.address // Authority allowed to freeze token accounts.
  })
);

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

console.log("Mint Address:", mint.address);
console.log("Mint Account:", mintAccount.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 { getCreateAccountInstruction } from "@solana-program/system";
import {
  fetchMint,
  getInitializeMintInstruction,
  getMintSize,
  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)));

// Generate keypair to use as address of mint
const mint = await generateKeyPairSigner();

// Get default mint account size (in bytes)
const space = BigInt(getMintSize());

// Get minimum balance for rent exemption
const rent = await client.rpc.getMinimumBalanceForRentExemption(space).send();

// Create and initialize the mint account in one transaction
const result = await client.sendTransaction([
  // !mark(1:13)
  getCreateAccountInstruction({
    payer: client.payer, // Account funding account creation.
    newAccount: mint, // New mint account to create.
    lamports: rent, // Lamports funding the new account rent.
    space, // Account size in bytes.
    programAddress: TOKEN_PROGRAM_ADDRESS // Program that owns the new account.
  }),
  getInitializeMintInstruction({
    mint: mint.address, // Mint account to initialize.
    decimals: 9, // Decimals to define on the mint account.
    mintAuthority: client.payer.address, // Authority allowed to mint new tokens.
    freezeAuthority: client.payer.address // Authority allowed to freeze token accounts.
  })
]);

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

console.log("Mint Address:", mint.address);
console.log("Mint Account:", mintAccount.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 { createMint, getMint, TOKEN_PROGRAM_ID } from "@solana/spl-token";

// !collapse(1:15) collapsed
// Setup: create and fund the fee payer before creating the mint.
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
});

// !mark(1:12)
const mintPubkey = await createMint(
  connection,
  feePayer,
  feePayer.publicKey, // Authority allowed to mint new tokens.
  feePayer.publicKey, // Authority allowed to freeze token accounts.
  9, // Decimals to define on the mint account.
  Keypair.generate(), // New mint account to create.
  {
    commitment: "confirmed"
  },
  TOKEN_PROGRAM_ID
);

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

console.log("Mint Address:", mintPubkey.toBase58());
console.log("Mint Account:", mintAccount);
```

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

// !collapse(1:18) collapsed
// Setup: create and fund the fee payer before creating the mint.
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 result = await sendAndConfirmTransaction(
  connection,
  new Transaction({
    feePayer: feePayer.publicKey,
    blockhash: latestBlockhash.blockhash,
    lastValidBlockHeight: latestBlockhash.lastValidBlockHeight
  }).add(
    // !mark(1:14)
    SystemProgram.createAccount({
      fromPubkey: feePayer.publicKey, // Account funding account creation.
      newAccountPubkey: mint.publicKey, // New mint account to create.
      space: MINT_SIZE, // Account size in bytes.
      lamports: mintRent, // Lamports funding the new account rent.
      programId: TOKEN_PROGRAM_ID // Program that owns the new account.
    }),
    createInitializeMintInstruction(
      mint.publicKey, // Mint account to initialize.
      9, // Decimals to define on the mint account.
      feePayer.publicKey, // Authority allowed to mint new tokens.
      feePayer.publicKey, // Authority allowed to freeze token accounts.
      TOKEN_PROGRAM_ID
    )
  ),
  [feePayer, mint]
);

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

console.log("Mint Address:", mint.publicKey.toBase58());
console.log("Mint Account:", mintAccount);
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_token_interface::{id as token_program_id, instruction::initialize_mint, state::Mint};

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

    // !collapse(1:17) collapsed
    // Setup: create and fund the fee payer before creating the mint.
    let fee_payer = Keypair::new();

    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 transaction = Transaction::new_signed_with_payer(
        &[
            // !mark(1:14)
            create_account(
                &fee_payer.pubkey(), // Account funding account creation.
                &mint.pubkey(), // New mint account to create.
                mint_rent, // Lamports funding the new account rent.
                Mint::LEN as u64, // Account size in bytes.
                &token_program_id(), // Program that owns the new account.
            ),
            initialize_mint(
                &token_program_id(),
                &mint.pubkey(), // Mint account to initialize.
                &fee_payer.pubkey(), // Authority allowed to mint new tokens.
                Some(&fee_payer.pubkey()), // Authority allowed to freeze token accounts.
                9, // Decimals to define on the mint account.
            )?,
        ],
        Some(&fee_payer.pubkey()),
        &[&fee_payer, &mint],
        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)?;

    println!("Mint Address: {}", mint.pubkey());
    println!("Mint Account: {:#?}", mint_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.system_program import create_account, CreateAccountParams
from solders.transaction import Transaction
from spl.token.async_client import AsyncToken
from spl.token.instructions import initialize_mint, InitializeMintParams
from spl.token.constants import MINT_LEN, TOKEN_PROGRAM_ID

DECIMALS = 9

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

    async with rpc:
        # !collapse(1:6) collapsed
        # Setup: create and fund the fee payer before creating the mint.
        fee_payer = Keypair()
        mint = Keypair()
        airdrop_signature = (await rpc.request_airdrop(fee_payer.pubkey(), 1_000_000_000)).value
        await rpc.confirm_transaction(airdrop_signature)
        mint_rent = (await rpc.get_minimum_balance_for_rent_exemption(MINT_LEN)).value

        # !mark(1:20)
        create_mint_instructions = [
            create_account(
                CreateAccountParams(
                    from_pubkey=fee_payer.pubkey(),  # Account funding account creation.
                    to_pubkey=mint.pubkey(),  # New mint account to create.
                    lamports=mint_rent,  # Lamports funding the new account rent.
                    space=MINT_LEN,  # Account size in bytes.
                    owner=TOKEN_PROGRAM_ID,  # Program that owns the new account.
                )
            ),
            initialize_mint(
                InitializeMintParams(
                    program_id=TOKEN_PROGRAM_ID,  # Token program to invoke.
                    mint=mint.pubkey(),  # Mint account to initialize.
                    decimals=DECIMALS,  # Decimals to define on the mint account.
                    mint_authority=fee_payer.pubkey(),  # Authority allowed to mint new tokens.
                    freeze_authority=fee_payer.pubkey(),  # Authority allowed to freeze token accounts.
                )
            ),
        ]
        latest_blockhash = await rpc.get_latest_blockhash()
        transaction = Transaction(
            [fee_payer, mint],
            Message(create_mint_instructions, fee_payer.pubkey()),
            latest_blockhash.value.blockhash,
        )
        result = await rpc.send_transaction(transaction)

        token = AsyncToken(rpc, mint.pubkey(), TOKEN_PROGRAM_ID, fee_payer)
        mint_info = await token.get_mint_info()
        mint_account = {
            "mint_authority": None if mint_info.mint_authority is None else str(mint_info.mint_authority),
            "supply": mint_info.supply,
            "decimals": mint_info.decimals,
            "is_initialized": mint_info.is_initialized,
            "freeze_authority": None if mint_info.freeze_authority is None else str(mint_info.freeze_authority),
        }

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

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

</CodeTabs>

## How to Add Metadata

A mint account only stores basic token information (supply, decimals,
authorities). To add human-readable metadata like a name, symbol, and image to
your token, you have two options:

<Cards>
  <Card title="Metaplex Token Metadata" href="/docs/tokens/metaplex">
   Add metadata using the Metaplex Token Metadata Program. Works with both, the original Token Program and Token-2022.
  </Card>

  <Card title="Token Extensions Metadata" href="/docs/tokens/extensions/metadata">
   Use the built-in metadata extension with Token-2022. 
   The metadata extension is only available for mint accounts created with Token-2022.
   To add metadata to mint accounts created with the original Token Program, use the Metaplex Token Metadata Program.
  </Card>
</Cards>
