- Mint accounts uniquely represent a token on Solana and store its global metadata.
- Light mints are on-chain accounts like SPL mints, but the light token program sponsors the rent-exemption cost for you.
Light Rent Config Explained
Light Rent Config Explained
- The rent-exemption for light account creation is sponsored by the Light Token Program.
- Transaction payer’s pay rent
to keep accounts “active” - “Inactive” accounts (rent below one epoch) get automatically compressed.
- The account’s state is cryptographically preserved and will be loaded into hot account state in-flight, when the account is used again.
- At account creation ~17,208 lamports
and . - When the account’s rent is below 3h, the transaction payer tops up 776 lamports.
- TypeScript Client
- Rust Client
- Program Guide
createMintInterface is a unified interface that dispatches to different mint creation paths based on programId:TOKEN_PROGRAM_IDorTOKEN_2022_PROGRAM_ID→ delegates to SPL or T22createMint- Otherwise it defaults to
LIGHT_TOKEN_PROGRAM_ID→ creates a light-token mint
Find the source code
here.
1
Create Mint with Token Metadata
Installation
Installation
- npm
- yarn
- pnpm
Install packages in your working directory:Install the CLI globally:
Report incorrect code
Copy
Ask AI
npm install @lightprotocol/stateless.js@alpha \
@lightprotocol/compressed-token@alpha
Report incorrect code
Copy
Ask AI
npm install -g @lightprotocol/zk-compression-cli@alpha
Install packages in your working directory:Install the CLI globally:
Report incorrect code
Copy
Ask AI
yarn add @lightprotocol/stateless.js@alpha \
@lightprotocol/compressed-token@alpha
Report incorrect code
Copy
Ask AI
yarn global add @lightprotocol/zk-compression-cli@alpha
Install packages in your working directory:Install the CLI globally:
Report incorrect code
Copy
Ask AI
pnpm add @lightprotocol/stateless.js@alpha \
@lightprotocol/compressed-token@alpha
Report incorrect code
Copy
Ask AI
pnpm add -g @lightprotocol/zk-compression-cli@alpha
- Localnet
- Devnet
Report incorrect code
Copy
Ask AI
# start local test-validator in a separate terminal
light test-validator
In the code examples, use
createRpc() without arguments for localnet.Get an API key from Helius and add to
.env:.env
Report incorrect code
Copy
Ask AI
API_KEY=<your-helius-api-key>
In the code examples, use
createRpc(RPC_URL) with the devnet URL.The
mintAuthority must be a Signer for light-mints but can be just a
PublicKey for SPL/T22.- Action
- Instruction
Report incorrect code
Copy
Ask AI
import "dotenv/config";
import { Keypair } from "@solana/web3.js";
import { createRpc } from "@lightprotocol/stateless.js";
import { createMintInterface, createTokenMetadata } from "@lightprotocol/compressed-token";
import { homedir } from "os";
import { readFileSync } from "fs";
// devnet:
const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`;
// localnet:
// const RPC_URL = undefined;
const payer = Keypair.fromSecretKey(
new Uint8Array(
JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8"))
)
);
(async function () {
// devnet:
const rpc = createRpc(RPC_URL);
// localnet:
// const rpc = createRpc();
const { mint, transactionSignature } = await createMintInterface(
rpc,
payer,
payer,
null,
9,
undefined,
undefined,
undefined,
createTokenMetadata("Example Token", "EXT", "https://example.com/metadata.json")
);
console.log("Mint:", mint.toBase58());
console.log("Tx:", transactionSignature);
})();
Report incorrect code
Copy
Ask AI
import "dotenv/config";
import {
Keypair,
ComputeBudgetProgram,
PublicKey,
Transaction,
sendAndConfirmTransaction,
} from "@solana/web3.js";
import {
createRpc,
getBatchAddressTreeInfo,
selectStateTreeInfo,
CTOKEN_PROGRAM_ID,
} from "@lightprotocol/stateless.js";
import {
createMintInstruction,
createTokenMetadata,
} from "@lightprotocol/compressed-token";
import { homedir } from "os";
import { readFileSync } from "fs";
const COMPRESSED_MINT_SEED = Buffer.from("compressed_mint");
function findMintAddress(mintSigner: PublicKey): [PublicKey, number] {
return PublicKey.findProgramAddressSync(
[COMPRESSED_MINT_SEED, mintSigner.toBuffer()],
CTOKEN_PROGRAM_ID
);
}
// devnet:
const RPC_URL = `https://devnet.helius-rpc.com?api-key=${process.env.API_KEY!}`;
const rpc = createRpc(RPC_URL);
// localnet:
// const rpc = createRpc();
const payer = Keypair.fromSecretKey(
new Uint8Array(
JSON.parse(readFileSync(`${homedir()}/.config/solana/id.json`, "utf8"))
)
);
(async function () {
const mintSigner = Keypair.generate();
const addressTreeInfo = getBatchAddressTreeInfo();
const stateTreeInfo = selectStateTreeInfo(await rpc.getStateTreeInfos());
const [mintPda] = findMintAddress(mintSigner.publicKey);
const validityProof = await rpc.getValidityProofV2(
[],
[{ address: mintPda.toBytes(), treeInfo: addressTreeInfo }]
);
const ix = createMintInstruction(
mintSigner.publicKey,
9,
payer.publicKey,
null,
payer.publicKey,
validityProof,
addressTreeInfo,
stateTreeInfo,
createTokenMetadata(
"Example Token",
"EXT",
"https://example.com/metadata.json"
)
);
const tx = new Transaction().add(
ComputeBudgetProgram.setComputeUnitLimit({ units: 1_000_000 }),
ix
);
const signature = await sendAndConfirmTransaction(rpc, tx, [
payer,
mintSigner,
]);
console.log("Mint:", mintPda.toBase58());
console.log("Tx:", signature);
})();
CreateMint creates an on-chain mint account that can optionally include token metadata.
The instruction creates under the hood a compressed mint address for when the mint is inactive.Compare to SPL:1
Prerequisites
Dependencies
Dependencies
Cargo.toml
Report incorrect code
Copy
Ask AI
[dependencies]
light-compressed-token-sdk = "0.1"
light-client = "0.1"
light-token-types = "0.1"
solana-sdk = "2.2"
borsh = "0.10"
tokio = { version = "1.36", features = ["full"] }
[dev-dependencies]
light-program-test = "0.1" # For in-memory tests with LiteSVM
Developer Environment
Developer Environment
- In-Memory (LightProgramTest)
- Localnet (LightClient)
- Devnet (LightClient)
Test with Lite-SVM (…)
Report incorrect code
Copy
Ask AI
# Initialize project
cargo init my-light-project
cd my-light-project
# Run tests
cargo test
Report incorrect code
Copy
Ask AI
use light_program_test::{LightProgramTest, ProgramTestConfig};
use solana_sdk::signer::Signer;
#[tokio::test]
async fn test_example() {
// In-memory test environment
let mut rpc = LightProgramTest::new(ProgramTestConfig::default())
.await
.unwrap();
let payer = rpc.get_payer().insecure_clone();
println!("Payer: {}", payer.pubkey());
}
Connects to a local test validator.
- npm
- yarn
- pnpm
Report incorrect code
Copy
Ask AI
npm install -g @lightprotocol/zk-compression-cli@alpha
Report incorrect code
Copy
Ask AI
yarn global add @lightprotocol/zk-compression-cli@alpha
Report incorrect code
Copy
Ask AI
pnpm add -g @lightprotocol/zk-compression-cli@alpha
Report incorrect code
Copy
Ask AI
# Initialize project
cargo init my-light-project
cd my-light-project
# Start local test validator (in separate terminal)
light test-validator
Report incorrect code
Copy
Ask AI
use light_client::rpc::{LightClient, LightClientConfig, Rpc};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Connects to http://localhost:8899
let rpc = LightClient::new(LightClientConfig::local()).await?;
let slot = rpc.get_slot().await?;
println!("Current slot: {}", slot);
Ok(())
}
Replace
<your-api-key> with your actual API key. Get your API key here.Report incorrect code
Copy
Ask AI
use light_client::rpc::{LightClient, LightClientConfig, Rpc};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let rpc_url = "https://devnet.helius-rpc.com?api-key=<your_api_key>";
let rpc = LightClient::new(
LightClientConfig::new(rpc_url.to_string(), None, None)
).await?;
println!("Connected to Devnet");
Ok(())
}
2
Create Mint with Token Metadata
View Source Code or find full examples with tests: examples-light-token.
Report incorrect code
Copy
Ask AI
use light_client::{
indexer::{AddressWithTree, Indexer},
rpc::Rpc,
};
use light_program_test::{LightProgramTest, ProgramTestConfig};
use light_token_sdk::token::{
derive_mint_compressed_address, find_mint_address, CreateMint, CreateMintParams,
};
use light_token_interface::{
instructions::extensions::{
token_metadata::TokenMetadataInstructionData, ExtensionInstructionData,
},
state::AdditionalMetadata,
};
use solana_sdk::{signature::Keypair, signer::Signer};
#[tokio::test(flavor = "multi_thread")]
async fn create_mint() {
let mut rpc = LightProgramTest::new(ProgramTestConfig::new_v2(false, None))
.await
.unwrap();
let payer = rpc.get_payer().insecure_clone();
let mint_seed = Keypair::new();
let decimals = 9u8;
// Get address tree to store compressed address for when mint turns inactive
// We must create a compressed address at creation to ensure the mint does not exist yet
let address_tree = rpc.get_address_tree_v2();
// Get state tree to store mint when inactive
let output_queue = rpc.get_random_state_tree_info().unwrap().queue;
// Derive mint addresses
let compression_address =
derive_mint_compressed_address(&mint_seed.pubkey(), &address_tree.tree);
let mint = find_mint_address(&mint_seed.pubkey()).0; // on-chain Mint PDA
// Fetch validity proof to proof address does not exist yet
let rpc_result = rpc
.get_validity_proof(
vec![],
vec![AddressWithTree {
address: compression_address,
tree: address_tree.tree,
}],
None,
)
.await
.unwrap()
.value;
// Build CreateMintParams with token metadata extension
let params = CreateMintParams {
decimals,
address_merkle_tree_root_index: rpc_result.addresses[0].root_index, // stores mint compressed address
mint_authority: payer.pubkey(),
proof: rpc_result.proof.0.unwrap(),
compression_address, // address for compression when mint turns inactive
mint,
bump: find_mint_address(&mint_seed.pubkey()).1,
freeze_authority: None,
extensions: Some(vec![ExtensionInstructionData::TokenMetadata(
TokenMetadataInstructionData {
update_authority: Some(payer.pubkey().to_bytes().into()),
name: b"Example Token".to_vec(),
symbol: b"EXT".to_vec(),
uri: b"https://example.com/metadata.json".to_vec(),
additional_metadata: Some(vec![AdditionalMetadata {
key: b"type".to_vec(),
value: b"example".to_vec(),
}]),
},
)]),
rent_payment: 16, // ~24 hours rent
write_top_up: 766, // ~3 hours rent per write
};
// Build and send instruction (mint_seed must sign)
let instruction = CreateMint::new(
params,
mint_seed.pubkey(),
payer.pubkey(),
address_tree.tree,
output_queue,
)
.instruction()
.unwrap();
let sig = rpc
.create_and_send_transaction(&[instruction], &payer.pubkey(), &[&payer, &mint_seed])
.await
.unwrap();
println!("Mint: {}", mint);
println!("Tx: {}", sig);
let mint_account = rpc.get_account(mint).await.unwrap();
assert!(mint_account.is_some(), "Solana mint account should exist");
}
1
Configure Token Metadata
Report incorrect code
Copy
Ask AI
use light_token_interface::{
instructions::extensions::{
token_metadata::TokenMetadataInstructionData,
ExtensionInstructionData,
},
state::AdditionalMetadata,
};
let token_metadata = ExtensionInstructionData::TokenMetadata(
TokenMetadataInstructionData {
update_authority: Some(authority.to_bytes().into()),
name: b"My Token".to_vec(),
symbol: b"MTK".to_vec(),
uri: b"https://example.com/metadata.json".to_vec(),
additional_metadata: Some(vec![
AdditionalMetadata {
key: b"category".to_vec(),
value: b"utility".to_vec(),
},
]),
},
);
Fields must be set at light-mint creation. Standard fields (
name,
symbol, uri) can be updated by update_authority. For
additional_metadata, only existing keys can be modified or removed. New keys
cannot be added after creation.2
Configure Mint
Setdecimals, mint_authority, freeze_authority, and pass the token_metadata from the previous step.Report incorrect code
Copy
Ask AI
use light_token_sdk::token::CreateCMintParams;
let params = CreateCMintParams {
decimals: data.decimals,
address_merkle_tree_root_index: data.address_merkle_tree_root_index,
mint_authority: data.mint_authority,
proof: data.proof,
compression_address: data.compression_address,
mint: data.mint,
freeze_authority: data.freeze_authority,
extensions: data.extensions,
};
The client passes a validity proof that proves the light-mint address does not
exist in the address tree where it will be stored. You can safely ignore
compression_address and address_merkle_tree_root_index. The client passes
these for proof verification.3
System Accounts
Include system accounts such as the Light System Program required to interact with compressed state. The client includes them in the instruction.System Accounts List
System Accounts List
| Account | Description | |
|---|---|---|
| 1 | Verifies validity proofs and executes compressed account state transitions. | |
| 2 | CPI Authority PDA | PDA that authorizes CPIs from the Compressed Token Program to the Light System Program. |
| 3 | Registered Program PDA | Proves the Compressed Token Program is registered to use compression. |
| 4 | Signs CPI calls from the Light System Program to the Account Compression Program. | |
| 5 | Writes to state and address Merkle tree accounts. | |
| 6 | Solana System Program. |
Report incorrect code
Copy
Ask AI
use light_token_sdk::token::SystemAccountInfos;
let system_accounts = SystemAccountInfos {
light_system_program: light_system_program.clone(),
cpi_authority_pda: cpi_authority_pda.clone(),
registered_program_pda: registered_program_pda.clone(),
account_compression_authority: account_compression_authority.clone(),
account_compression_program: account_compression_program.clone(),
system_program: system_program.clone(),
};
4
Build Account Infos and CPI the light token program
- invoke (External signer)
- invoke_signed (PDA Authority)
Report incorrect code
Copy
Ask AI
use light_token_sdk::token::CreateMintCpi;
CreateMintCpi::new(
mint_seed.clone(),
authority.clone(),
payer.clone(),
address_tree.clone(),
output_queue.clone(),
compressible_config.clone(),
mint.clone(),
rent_sponsor.clone(),
system_accounts,
params,
)
.invoke()
Report incorrect code
Copy
Ask AI
use light_token_sdk::token::CreateMintCpi;
let signer_seeds: &[&[u8]] = &[b"authority", &[authority_bump]];
CreateMintCpi::new(
mint_seed.clone(),
authority.clone(),
payer.clone(),
address_tree.clone(),
output_queue.clone(),
compressible_config.clone(),
mint.clone(),
rent_sponsor.clone(),
system_accounts,
params,
)
.invoke_signed(&[signer_seeds])
Full Code Example
View Source Code or full examples with tests: examples-light-token.
- Anchor
- Native
Report incorrect code
Copy
Ask AI
#![allow(unexpected_cfgs)]
use anchor_lang::prelude::*;
use light_token_sdk::token::{CreateMintCpi, CreateMintParams, SystemAccountInfos};
use light_token_sdk::CompressedProof;
declare_id!("Ev7tKaozVxbZLVGcKcVcz8A9yKZjUf5ATqoNSe5BDkjj");
#[program]
pub mod light_token_anchor_create_mint {
use super::*;
pub fn create_mint<'info>(
ctx: Context<'_, '_, '_, 'info, CreateMintAccounts<'info>>,
decimals: u8,
address_merkle_tree_root_index: u16,
compression_address: [u8; 32],
proof: CompressedProof,
freeze_authority: Option<Pubkey>,
bump: u8,
rent_payment: Option<u8>,
write_top_up: Option<u32>,
) -> Result<()> {
let mint = light_token_sdk::token::find_mint_address(ctx.accounts.mint_seed.key).0;
let params = CreateMintParams {
decimals,
address_merkle_tree_root_index,
mint_authority: *ctx.accounts.authority.key,
proof,
compression_address,
mint,
bump,
freeze_authority,
extensions: None,
rent_payment: rent_payment.unwrap_or(16), // Default: ~24 hours
write_top_up: write_top_up.unwrap_or(766), // Default: ~3 hours per write
};
let system_accounts = SystemAccountInfos {
light_system_program: ctx.accounts.light_system_program.to_account_info(),
cpi_authority_pda: ctx.accounts.cpi_authority_pda.to_account_info(),
registered_program_pda: ctx.accounts.registered_program_pda.to_account_info(),
account_compression_authority: ctx.accounts.account_compression_authority.to_account_info(),
account_compression_program: ctx.accounts.account_compression_program.to_account_info(),
system_program: ctx.accounts.system_program.to_account_info(),
};
CreateMintCpi {
mint_seed: ctx.accounts.mint_seed.to_account_info(),
authority: ctx.accounts.authority.to_account_info(),
payer: ctx.accounts.payer.to_account_info(),
address_tree: ctx.accounts.address_tree.to_account_info(),
output_queue: ctx.accounts.output_queue.to_account_info(),
compressible_config: ctx.accounts.compressible_config.to_account_info(),
mint: ctx.accounts.mint.to_account_info(),
rent_sponsor: ctx.accounts.rent_sponsor.to_account_info(),
system_accounts,
cpi_context: None,
cpi_context_account: None,
params,
}
.invoke()?;
Ok(())
}
}
#[derive(Accounts)]
pub struct CreateMintAccounts<'info> {
pub mint_seed: Signer<'info>,
/// CHECK: Validated by light-token CPI
pub authority: AccountInfo<'info>,
#[account(mut)]
pub payer: Signer<'info>,
/// CHECK: Validated by light-token CPI
#[account(mut)]
pub address_tree: AccountInfo<'info>,
/// CHECK: Validated by light-token CPI
#[account(mut)]
pub output_queue: AccountInfo<'info>,
/// CHECK: Validated by light-token CPI
pub light_system_program: AccountInfo<'info>,
/// CHECK: Validated by light-token CPI
pub cpi_authority_pda: AccountInfo<'info>,
/// CHECK: Validated by light-token CPI
pub registered_program_pda: AccountInfo<'info>,
/// CHECK: Validated by light-token CPI
pub account_compression_authority: AccountInfo<'info>,
/// CHECK: Validated by light-token CPI
pub account_compression_program: AccountInfo<'info>,
pub system_program: Program<'info, System>,
/// CHECK: Validated by light-token CPI - use light_token_sdk::token::config_pda()
pub compressible_config: AccountInfo<'info>,
/// CHECK: Validated by light-token CPI - derived from find_mint_address(mint_seed)
#[account(mut)]
pub mint: AccountInfo<'info>,
/// CHECK: Validated by light-token CPI - use light_token_sdk::token::rent_sponsor_pda()
#[account(mut)]
pub rent_sponsor: AccountInfo<'info>,
}
Report incorrect code
Copy
Ask AI
use borsh::BorshDeserialize;
use light_token_interface::instructions::extensions::{
token_metadata::TokenMetadataInstructionData, ExtensionInstructionData,
};
use light_token_sdk::{
token::{CreateMintCpi, CreateMintParams, SystemAccountInfos},
CompressedProof,
};
use solana_program::{
account_info::AccountInfo, entrypoint::ProgramResult,
program_error::ProgramError, pubkey::Pubkey,
};
#[derive(BorshDeserialize)]
struct CreateMintData {
decimals: u8,
address_merkle_tree_root_index: u16,
mint_authority: Pubkey,
proof_a: [u8; 32],
proof_b: [u8; 64],
proof_c: [u8; 32],
compression_address: [u8; 32],
mint: Pubkey,
bump: u8,
freeze_authority: Option<Pubkey>,
rent_payment: u8,
write_top_up: u32,
metadata_name: Option<Vec<u8>>,
metadata_symbol: Option<Vec<u8>>,
metadata_uri: Option<Vec<u8>>,
}
pub fn create_mint_invoke(accounts: &[AccountInfo], data: &[u8]) -> ProgramResult {
let [mint_seed, authority, payer, address_tree, output_queue, compressible_config, mint, rent_sponsor, light_system_program, cpi_authority_pda, registered_program_pda, account_compression_authority, account_compression_program, system_program, _token_program] =
accounts
else {
return Err(ProgramError::NotEnoughAccountKeys);
};
let ix_data = CreateMintData::deserialize(&mut &data[..])
.map_err(|_| ProgramError::InvalidInstructionData)?;
// Build token metadata extension if metadata fields are provided
let extensions = match (
&ix_data.metadata_name,
&ix_data.metadata_symbol,
&ix_data.metadata_uri,
) {
(Some(name), Some(symbol), Some(uri)) => Some(vec![ExtensionInstructionData::TokenMetadata(
TokenMetadataInstructionData {
update_authority: Some(ix_data.mint_authority.to_bytes().into()),
name: name.clone(),
symbol: symbol.clone(),
uri: uri.clone(),
additional_metadata: None,
},
)]),
_ => None,
};
let params = CreateMintParams {
decimals: ix_data.decimals,
address_merkle_tree_root_index: ix_data.address_merkle_tree_root_index,
mint_authority: ix_data.mint_authority,
proof: CompressedProof {
a: ix_data.proof_a,
b: ix_data.proof_b,
c: ix_data.proof_c,
},
compression_address: ix_data.compression_address,
mint: ix_data.mint,
bump: ix_data.bump,
freeze_authority: ix_data.freeze_authority,
extensions,
rent_payment: ix_data.rent_payment,
write_top_up: ix_data.write_top_up,
};
let system_accounts = SystemAccountInfos {
light_system_program: light_system_program.clone(),
cpi_authority_pda: cpi_authority_pda.clone(),
registered_program_pda: registered_program_pda.clone(),
account_compression_authority: account_compression_authority.clone(),
account_compression_program: account_compression_program.clone(),
system_program: system_program.clone(),
};
CreateMintCpi::new(
mint_seed.clone(),
authority.clone(),
payer.clone(),
address_tree.clone(),
output_queue.clone(),
compressible_config.clone(),
mint.clone(),
rent_sponsor.clone(),
system_accounts,
params,
)
.invoke()
}
#[derive(BorshDeserialize)]
struct CreateMintSignedData {
decimals: u8,
address_merkle_tree_root_index: u16,
proof_a: [u8; 32],
proof_b: [u8; 64],
proof_c: [u8; 32],
compression_address: [u8; 32],
mint: Pubkey,
bump: u8,
freeze_authority: Option<Pubkey>,
rent_payment: u8,
write_top_up: u32,
authority_bump: u8,
metadata_name: Option<Vec<u8>>,
metadata_symbol: Option<Vec<u8>>,
metadata_uri: Option<Vec<u8>>,
}
pub fn create_mint_invoke_signed(accounts: &[AccountInfo], data: &[u8]) -> ProgramResult {
let [mint_seed, authority, payer, address_tree, output_queue, compressible_config, mint, rent_sponsor, light_system_program, cpi_authority_pda, registered_program_pda, account_compression_authority, account_compression_program, system_program, _token_program] =
accounts
else {
return Err(ProgramError::NotEnoughAccountKeys);
};
let ix_data = CreateMintSignedData::deserialize(&mut &data[..])
.map_err(|_| ProgramError::InvalidInstructionData)?;
let signer_seeds: &[&[u8]] = &[b"authority", &[ix_data.authority_bump]];
// Build token metadata extension if metadata fields are provided
let extensions = match (
&ix_data.metadata_name,
&ix_data.metadata_symbol,
&ix_data.metadata_uri,
) {
(Some(name), Some(symbol), Some(uri)) => Some(vec![ExtensionInstructionData::TokenMetadata(
TokenMetadataInstructionData {
update_authority: Some(authority.key.to_bytes().into()),
name: name.clone(),
symbol: symbol.clone(),
uri: uri.clone(),
additional_metadata: None,
},
)]),
_ => None,
};
let params = CreateMintParams {
decimals: ix_data.decimals,
address_merkle_tree_root_index: ix_data.address_merkle_tree_root_index,
mint_authority: *authority.key,
proof: CompressedProof {
a: ix_data.proof_a,
b: ix_data.proof_b,
c: ix_data.proof_c,
},
compression_address: ix_data.compression_address,
mint: ix_data.mint,
bump: ix_data.bump,
freeze_authority: ix_data.freeze_authority,
extensions,
rent_payment: ix_data.rent_payment,
write_top_up: ix_data.write_top_up,
};
let system_accounts = SystemAccountInfos {
light_system_program: light_system_program.clone(),
cpi_authority_pda: cpi_authority_pda.clone(),
registered_program_pda: registered_program_pda.clone(),
account_compression_authority: account_compression_authority.clone(),
account_compression_program: account_compression_program.clone(),
system_program: system_program.clone(),
};
CreateMintCpi::new(
mint_seed.clone(),
authority.clone(),
payer.clone(),
address_tree.clone(),
output_queue.clone(),
compressible_config.clone(),
mint.clone(),
rent_sponsor.clone(),
system_accounts,
params,
)
.invoke_signed(&[signer_seeds])
}