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:
Field | Type | Description |
---|---|---|
mint_authority | COption<Pubkey> | Optional authority to mint new tokens |
supply | u64 | Total number of tokens in circulation |
decimals | u8 | Number of decimal places |
is_initialized | bool | Has this mint been initialized |
freeze_authority | COption<Pubkey> | Optional authority to freeze token accounts |
Token Account
Holds token balances for a specific mint:
Field | Type | Description |
---|---|---|
mint | Pubkey | The token mint this account holds |
owner | Pubkey | Owner of this account |
amount | u64 | Number of tokens held |
delegate | COption<Pubkey> | Optional delegate authority |
state | AccountState | Account state (Uninitialized/Initialized/Frozen) |
delegated_amount | u64 | Amount delegated |
close_authority | COption<Pubkey> | Optional authority to close the account |
Multisig Account
Enables shared authority over token operations:
Field | Type | Description |
---|---|---|
m | u8 | Number of required signers |
n | u8 | Number of valid signers |
is_initialized | bool | Has 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
Code | Name | Description |
---|---|---|
0 | InvalidMint | The mint provided is not valid |
1 | InvalidOwner | The owner provided is not valid |
2 | InvalidAmount | The amount provided is not valid |
3 | InvalidDelegate | The delegate provided is not valid |
4 | InvalidAccount | The account provided is not valid |
5 | InvalidState | The account state is not valid |
6 | InvalidAuthority | The authority provided is not valid |
7 | InvalidCloseAuthority | The close authority provided is not valid |
8 | InvalidFreezeAuthority | The freeze authority provided is not valid |
9 | InvalidMintAuthority | The mint authority provided is not valid |
10 | InvalidSupply | The supply provided is not valid |
11 | InvalidDecimals | The decimals provided are not valid |
12 | InvalidInstruction | The instruction provided is not valid |
13 | InvalidProgramId | The program ID provided is not valid |
14 | InvalidAccountData | The account data provided is not valid |
15 | InvalidAccountOwner | The account owner provided is not valid |
16 | InvalidAccountDataLength | The account data length is not valid |
17 | InvalidAccountDataFormat | The account data format is not valid |
18 | InvalidAccountDataVersion | The account data version is not valid |
19 | InvalidAccountDataDiscriminator | The 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
- Secure Key Management: Store private keys securely and never share them
- Use Multisig: Implement multisig for important operations
- Regular Audits: Regularly audit token operations and balances
- Access Control: Implement proper access controls for mint authorities
Performance
- Batch Operations: Use batch operations for multiple transfers
- Account Management: Close unused accounts to reclaim rent
- Efficient Decimals: Choose appropriate decimal places for your use case
- Monitor Gas: Monitor transaction costs and optimize accordingly
Development
- Test Thoroughly: Test all operations in development before production
- Error Handling: Implement proper error handling in your applications
- Documentation: Document your token's purpose and operations
- Community: Follow community best practices and standards
Next Steps
Associated Token Account
Learn about associated token accounts
Token Guide
Complete guide to creating tokens
SDK Reference
Learn to use the SDKs
Examples
Explore example implementations