Arch Network Logo
APL (Arch Program Library)

APL Token Program

Complete reference for the Arch Program Library Token Program - creating and managing fungible tokens

The APL Token Program is the foundation for creating and managing fungible tokens on the Arch Network. This documentation provides a comprehensive guide for developers implementing token functionality in their applications.

Overview

The Token Program enables:

  • Creation and management of fungible tokens (mints)
  • Token account management
  • Token transfers and delegations
  • Multisignature authorities
  • Account freezing and thawing

Program ID

AplToken111111111111111111111111

Account Types

Mint Account

The central record for a token type, containing:

FieldTypeDescription
mint_authorityCOption<Pubkey>Optional authority to mint new tokens
supplyu64Total number of tokens in circulation
decimalsu8Number of decimal places
is_initializedboolHas this mint been initialized
freeze_authorityCOption<Pubkey>Optional authority to freeze token accounts

Token Account

Holds token balances for a specific mint:

FieldTypeDescription
mintPubkeyThe token mint this account holds
ownerPubkeyOwner of this account
amountu64Number of tokens held
delegateCOption<Pubkey>Optional delegate authority
stateAccountStateAccount state (Uninitialized/Initialized/Frozen)
delegated_amountu64Amount delegated
close_authorityCOption<Pubkey>Optional authority to close the account

Multisig Account

Enables shared authority over token operations:

FieldTypeDescription
mu8Number of required signers
nu8Number of valid signers
is_initializedboolHas this multisig been initialized
signers[Pubkey; MAX_SIGNERS]Array of valid signer addresses

Instructions

Token Creation and Initialization

InitializeMint

Creates a new token type.

pub struct InitializeMint {
    pub decimals: u8,
    pub mint_authority: Pubkey,
    pub freeze_authority: COption<Pubkey>,
}

Required accounts:

  • [writable] The mint to initialize

Example:

let mint = Keypair::new();
let mint_authority = Keypair::new();
let decimals = 9;

let instruction = apl_token::instruction::initialize_mint(
    &apl_token::id(),
    &mint.pubkey(),
    &mint_authority.pubkey(),
    None, // No freeze authority
    decimals,
)?;

InitializeAccount

Creates a new account to hold tokens.

Required accounts:

  • [writable] The account to initialize
  • [] The mint this account is for
  • [] The owner of the new account

Example:

let account = Keypair::new();
let owner = Keypair::new();

let instruction = apl_token::instruction::initialize_account(
    &apl_token::id(),
    &account.pubkey(),
    &mint.pubkey(),
    &owner.pubkey(),
)?;

Token Operations

MintTo

Creates new tokens and adds them to a token account.

pub struct MintTo {
    pub amount: u64,
}

Required accounts:

  • [writable] The mint
  • [writable] The destination token account
  • [signer] The mint authority

Example:

let instruction = apl_token::instruction::mint_to(
    &apl_token::id(),
    &mint.pubkey(),
    &destination_account.pubkey(),
    &mint_authority.pubkey(),
    &[],
    1000000000, // 1 token with 9 decimals
)?;

Transfer

Transfers tokens from one account to another.

pub struct Transfer {
    pub amount: u64,
}

Required accounts:

  • [writable] The source token account
  • [writable] The destination token account
  • [signer] The source account owner

Example:

let instruction = apl_token::instruction::transfer(
    &apl_token::id(),
    &source_account.pubkey(),
    &destination_account.pubkey(),
    &owner.pubkey(),
    &[],
    500000000, // 0.5 tokens
)?;

TransferChecked

Transfers tokens with additional validation.

pub struct TransferChecked {
    pub amount: u64,
    pub decimals: u8,
}

Required accounts:

  • [writable] The source token account
  • [] The mint
  • [writable] The destination token account
  • [signer] The source account owner

Example:

let instruction = apl_token::instruction::transfer_checked(
    &apl_token::id(),
    &source_account.pubkey(),
    &mint.pubkey(),
    &destination_account.pubkey(),
    &owner.pubkey(),
    &[],
    500000000, // 0.5 tokens
    9, // decimals
)?;

Delegation

Approve

Allows a delegate to transfer tokens on behalf of the owner.

pub struct Approve {
    pub amount: u64,
}

Required accounts:

  • [writable] The token account
  • [] The delegate
  • [signer] The account owner

Example:

let delegate = Keypair::new();

let instruction = apl_token::instruction::approve(
    &apl_token::id(),
    &token_account.pubkey(),
    &delegate.pubkey(),
    &owner.pubkey(),
    &[],
    1000000000, // 1 token
)?;

Revoke

Removes delegation authority.

Required accounts:

  • [writable] The token account
  • [signer] The account owner

Example:

let instruction = apl_token::instruction::revoke(
    &apl_token::id(),
    &token_account.pubkey(),
    &owner.pubkey(),
    &[],
)?;

Account Management

FreezeAccount

Freezes a token account, preventing transfers.

Required accounts:

  • [writable] The token account
  • [] The mint
  • [signer] The freeze authority

Example:

let instruction = apl_token::instruction::freeze_account(
    &apl_token::id(),
    &token_account.pubkey(),
    &mint.pubkey(),
    &freeze_authority.pubkey(),
    &[],
)?;

ThawAccount

Unfreezes a frozen token account.

Required accounts:

  • [writable] The token account
  • [] The mint
  • [signer] The freeze authority

Example:

let instruction = apl_token::instruction::thaw_account(
    &apl_token::id(),
    &token_account.pubkey(),
    &mint.pubkey(),
    &freeze_authority.pubkey(),
    &[],
)?;

CloseAccount

Closes a token account and reclaims rent.

Required accounts:

  • [writable] The token account
  • [writable] The destination for reclaimed rent
  • [signer] The account owner

Example:

let instruction = apl_token::instruction::close_account(
    &apl_token::id(),
    &token_account.pubkey(),
    &destination_account.pubkey(),
    &owner.pubkey(),
    &[],
)?;

Multisig Operations

InitializeMultisig

Creates a multisig account for shared authority.

pub struct InitializeMultisig {
    pub m: u8, // Required signatures
}

Required accounts:

  • [writable] The multisig account
  • [] The rent sysvar

Example:

let multisig = Keypair::new();
let signers = vec![signer1.pubkey(), signer2.pubkey(), signer3.pubkey()];

let instruction = apl_token::instruction::initialize_multisig(
    &apl_token::id(),
    &multisig.pubkey(),
    &signers,
    2, // Require 2 of 3 signatures
)?;

Error Codes

CodeNameDescription
0InvalidMintThe mint provided is not valid
1InvalidOwnerThe owner provided is not valid
2InvalidAmountThe amount provided is not valid
3InvalidDelegateThe delegate provided is not valid
4InvalidAccountThe account provided is not valid
5InvalidStateThe account state is not valid
6InvalidAuthorityThe authority provided is not valid
7InvalidCloseAuthorityThe close authority provided is not valid
8InvalidFreezeAuthorityThe freeze authority provided is not valid
9InvalidMintAuthorityThe mint authority provided is not valid
10InvalidSupplyThe supply provided is not valid
11InvalidDecimalsThe decimals provided are not valid
12InvalidInstructionThe instruction provided is not valid
13InvalidProgramIdThe program ID provided is not valid
14InvalidAccountDataThe account data provided is not valid
15InvalidAccountOwnerThe account owner provided is not valid
16InvalidAccountDataLengthThe account data length is not valid
17InvalidAccountDataFormatThe account data format is not valid
18InvalidAccountDataVersionThe account data version is not valid
19InvalidAccountDataDiscriminatorThe account data discriminator is not valid

Usage Examples

Creating a Token

use arch_sdk::prelude::*;
use apl_token::prelude::*;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Connect to Arch Network
    let client = ArchNetworkClient::new("http://localhost:9002").await?;
    
    // Create keypairs
    let mint_keypair = Keypair::new();
    let mint_authority = Keypair::new();
    let payer = Keypair::new();
    
    // Create mint account
    let mint_account = client.create_account(
        CreateAccountParams {
            space: 82, // Mint account size
            owner: apl_token::id(),
            payer: &payer,
        }
    ).await?;
    
    // Initialize mint
    let instruction = initialize_mint(
        &apl_token::id(),
        &mint_account.pubkey(),
        &mint_authority.pubkey(),
        None, // No freeze authority
        9, // 9 decimals
    )?;
    
    // Send transaction
    let transaction = Transaction::new()
        .add_instruction(instruction);
    
    let signature = client.send_transaction(transaction, &[&payer, &mint_authority]).await?;
    println!("Mint created: {}", signature);
    
    Ok(())
}

Creating a Token Account

async fn create_token_account(
    client: &ArchNetworkClient,
    mint: &Pubkey,
    owner: &Pubkey,
    payer: &Keypair,
) -> Result<Pubkey, Box<dyn std::error::Error>> {
    // Create account
    let account = client.create_account(
        CreateAccountParams {
            space: 165, // Token account size
            owner: apl_token::id(),
            payer,
        }
    ).await?;
    
    // Initialize account
    let instruction = initialize_account(
        &apl_token::id(),
        &account.pubkey(),
        mint,
        owner,
    )?;
    
    // Send transaction
    let transaction = Transaction::new()
        .add_instruction(instruction);
    
    client.send_transaction(transaction, &[payer]).await?;
    
    Ok(account.pubkey())
}

Minting Tokens

async fn mint_tokens(
    client: &ArchNetworkClient,
    mint: &Pubkey,
    destination: &Pubkey,
    amount: u64,
    mint_authority: &Keypair,
    payer: &Keypair,
) -> Result<(), Box<dyn std::error::Error>> {
    let instruction = mint_to(
        &apl_token::id(),
        mint,
        destination,
        &mint_authority.pubkey(),
        &[],
        amount,
    )?;
    
    let transaction = Transaction::new()
        .add_instruction(instruction);
    
    client.send_transaction(transaction, &[mint_authority, payer]).await?;
    
    Ok(())
}

Transferring Tokens

async fn transfer_tokens(
    client: &ArchNetworkClient,
    source: &Pubkey,
    destination: &Pubkey,
    amount: u64,
    owner: &Keypair,
    payer: &Keypair,
) -> Result<(), Box<dyn std::error::Error>> {
    let instruction = transfer(
        &apl_token::id(),
        source,
        destination,
        &owner.pubkey(),
        &[],
        amount,
    )?;
    
    let transaction = Transaction::new()
        .add_instruction(instruction);
    
    client.send_transaction(transaction, &[owner, payer]).await?;
    
    Ok(())
}

CLI Usage

Create a Token Mint

# Create a new token mint
arch-cli token create-mint \
  --decimals 9 \
  --mint-authority ~/mint_authority.key \
  --keypair-path ~/payer.key

Create a Token Account

# Create a token account
arch-cli token create-account \
  --mint <MINT_ADDRESS> \
  --owner ~/owner.key \
  --keypair-path ~/payer.key

Mint Tokens

# Mint tokens to an account
arch-cli token mint-to \
  --mint <MINT_ADDRESS> \
  --destination <TOKEN_ACCOUNT> \
  --amount 1000000000 \
  --mint-authority ~/mint_authority.key \
  --keypair-path ~/payer.key

Transfer Tokens

# Transfer tokens between accounts
arch-cli token transfer \
  --source <SOURCE_ACCOUNT> \
  --destination <DESTINATION_ACCOUNT> \
  --amount 500000000 \
  --owner ~/owner.key \
  --keypair-path ~/payer.key

Best Practices

Security

  1. Secure Key Management: Store private keys securely and never share them
  2. Use Multisig: Implement multisig for important operations
  3. Regular Audits: Regularly audit token operations and balances
  4. Access Control: Implement proper access controls for mint authorities

Performance

  1. Batch Operations: Use batch operations for multiple transfers
  2. Account Management: Close unused accounts to reclaim rent
  3. Efficient Decimals: Choose appropriate decimal places for your use case
  4. Monitor Gas: Monitor transaction costs and optimize accordingly

Development

  1. Test Thoroughly: Test all operations in development before production
  2. Error Handling: Implement proper error handling in your applications
  3. Documentation: Document your token's purpose and operations
  4. Community: Follow community best practices and standards

Next Steps

Resources