Rust Solana代币管理库solana-tokens的使用,高效处理Solana区块链上的代币转账与交易

Rust Solana代币管理库solana-tokens的使用,高效处理Solana区块链上的代币转账与交易

solana-tokens是一个用于批量管理Solana代币的命令行工具,它可以高效地处理Solana区块链上的代币转账与交易。

分发代币

将代币发送到<RECIPIENTS_CSV>文件中列出的接收者。

示例recipients.csv文件内容:

recipient,amount,lockup_date
3ihfUy1n9gaqihM5bJCiTAGLgWc5zo3DqVUS6T736NLM,42.0,
CYRJWqiSjLitBAcRxPvWpgX3s5TvmN2SuRY3eEYypFvT,43.0,

执行分发命令:

solana-tokens distribute-tokens --from <KEYPAIR> --input-csv <RECIPIENTS_CSV> --fee-payer <KEYPAIR>

分发相同数量的代币

可以简单地使用--transfer-amount参数指定要发送给每个接收者的相同代币数量。

示例recipients.csv文件内容:

recipient
6Vo87BaDhp4v4GHwVDhw5huhxVF8CyxSXYtkUwVHbbPv
7aHDubg5FBYj1SgmyBgU3ZJdtfuqYCQsJQK2pTR5JUqr
CYRJWqiSjLitBAcRxPvWpgX3s5TvmN2SuRY3eEYypFvT

执行分发命令:

solana-tokens distribute-tokens --transfer-amount 10 --from <KEYPAIR> --input-csv <RECIPIENTS_CSV> --fee-payer <KEYPAIR>

分发SPL代币

分发SPL代币与分发SOL类似,但需要--owner参数来签署交易。每个接收者账户必须是系统账户,将拥有SPL代币铸币的关联代币账户。

示例recipients.csv文件内容:

recipient,amount
CYRJWqiSjLitBAcRxPvWpgX3s5TvmN2SuRY3eEYypFvT,75400
C56nwrDVFpPrqwGYsTgQxv1ZraTh81H14PV4RHvZe36s,10000
7aHDubg5FBYj1SgmyBgU3ZJdtfuqYCQsJQK2pTR5JUqr,42100
7qQPmVAQxEQ5djPDCtiEUrxaPf8wKtLG1m6SB1brejJ1,20000

执行分发命令:

solana-tokens distribute-spl-tokens --from <ADDRESS> --owner <KEYPAIR> \
    --input-csv <RECIPIENTS_CSV> --fee-payer <KEYPAIR>

完整示例代码

以下是一个完整的Rust示例,展示如何使用solana-tokens库进行代币分发:

use solana_tokens::commands::{distribute_tokens, DistributeTokensConfig};
use solana_sdk::signer::keypair::Keypair;
use std::path::PathBuf;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 配置分发参数
    let config = DistributeTokensConfig {
        from: Keypair::new(), // 发送方密钥对
        input_csv: PathBuf::from("recipients.csv"), // 接收者CSV文件路径
        fee_payer: Keypair::new(), // 支付交易费用的密钥对
        dry_run: false, // 是否仅模拟运行
        transfer_amount: None, // 固定转账金额(可选)
        spl_token: None, // SPL代币铸币地址(可选)
        owner: None, // SPL代币所有者(可选)
        ..Default::default()
    };

    // 执行代币分发
    distribute_tokens(config)?;

    Ok(())
}

对于SPL代币分发,可以这样配置:

use solana_tokens::commands::{distribute_spl_tokens, DistributeSplTokensConfig};
use solana_sdk::{pubkey::Pubkey, signer::keypair::Keypair};
use std::path::PathBuf;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 配置SPL代币分发参数
    let config = DistributeSplTokensConfig {
        from: Pubkey::new_unique(), // 发送方地址
        input_csv: PathBuf::from("spl_recipients.csv"), // 接收者CSV文件路径
        fee_payer: Keypair::new(), // 支付交易费用的密钥对
        owner: Keypair::new(), // SPL代币所有者密钥对
        mint: Pubkey::new_unique(), // SPL代币铸币地址
        dry_run: false, // 是否仅模拟运行
        ..Default::default()
    };

    // 执行SPL代币分发
    distribute_spl_tokens(config)?;

    Ok(())
}

安装

可以通过Cargo安装solana-tokens:

cargo install solana-tokens

或作为库添加到项目中:

cargo add solana-tokens

或者在Cargo.toml中添加:

solana-tokens = "2.3.6"

完整示例Demo

以下是一个更完整的Rust示例,展示如何使用solana-tokens库进行代币分发,包括从文件读取密钥对和错误处理:

use solana_tokens::commands::{distribute_tokens, DistributeTokensConfig};
use solana_sdk::{
    signer::keypair::{read_keypair_file, Keypair},
    signature::Signer,
};
use std::{
    path::PathBuf,
    error::Error,
};

fn main() -> Result<(), Box<dyn Error>> {
    // 从文件读取发送方密钥对
    let sender_keypair = read_keypair_file("sender_keypair.json")?;
    let fee_payer_keypair = read_keypair_file("fee_payer_keypair.json")?;

    // 配置分发参数
    let config = DistributeTokensConfig {
        from: sender_keypair, // 发送方密钥对
        input_csv: PathBuf::from("recipients.csv"), // 接收者CSV文件路径
        fee_payer: fee_payer_keypair, // 支付交易费用的密钥对
        dry_run: false, // 是否仅模拟运行
        transfer_amount: Some(10), // 固定转账金额10 SOL
        spl_token: None, // 不使用SPL代币
        owner: None, // 不使用SPL代币所有者
        ..Default::default()
    };

    // 执行代币分发
    distribute_tokens(config)?;

    println!("代币分发成功完成!");
    Ok(())
}

对于SPL代币分发的完整示例:

use solana_tokens::commands::{distribute_spl_tokens, DistributeSplTokensConfig};
use solana_sdk::{
    pubkey::Pubkey,
    signer::keypair::{read_keypair_file, Keypair},
};
use std::{
    path::PathBuf,
    error::Error,
    str::FromStr,
};

fn main() -> Result<(), Box<dyn Error>> {
    // 从文件读取密钥对
    let owner_keypair = read_keypair_file("owner_keypair.json")?;
    let fee_payer_keypair = read_keypair_file("fee_payer_keypair.json")?;

    // 配置SPL代币分发参数
    let config = DistributeSplTokensConfig {
        from: Pubkey::from_str("TokenAccountAddressHere")?, // 发送方代币账户地址
        input_csv: PathBuf::from("spl_recipients.csv"), // 接收者CSV文件路径
        fee_payer: fee_payer_keypair, // 支付交易费用的密钥对
        owner: owner_keypair, // SPL代币所有者密钥对
        mint: Pubkey::from_str("TokenMintAddressHere")?, // SPL代币铸币地址
        dry_run: false, // 是否仅模拟运行
        ..Default::default()
    };

    // 执行SPL代币分发
    distribute_spl_tokens(config)?;

    println!("SPL代币分发成功完成!");
    Ok(())
}

1 回复

以下是基于您提供的solana-tokens库使用指南的完整示例代码,包含详细注释:

use solana_sdk::{
    pubkey::Pubkey,
    signer::keypair::{Keypair, read_keypair_file},
    commitment_config::CommitmentConfig
};
use solana_client::{
    rpc_client::RpcClient,
    client_error::ClientError
};
use solana_tokens::{
    commands,
    token::Token
};
use std::error::Error;

/// 完整的Solana代币转账示例
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    // 1. 初始化RPC客户端
    let rpc_url = "https://api.devnet.solana.com".to_string(); // 使用测试网
    let client = RpcClient::new_with_commitment(rpc_url, CommitmentConfig::confirmed());

    // 2. 加载或创建密钥对
    // 注意:实际使用中应从安全存储加载密钥,不要硬编码
    let payer = match read_keypair_file("payer-keypair.json") {
        Ok(kp) => kp,
        Err(_) => {
            let new_kp = Keypair::new();
            // 这里应该保存密钥到文件,示例中省略
            println!("生成新的支付账户: {}", new_kp.pubkey());
            new_kp
        }
    };

    // 3. 设置代币参数
    let token_mint = Pubkey::new_from_str("代币Mint地址")?; // 替换为实际的代币mint地址
    let source_account = read_keypair_file("source-keypair.json")?;
    let recipient_address = Pubkey::new_from_str("接收者地址")?;
    let transfer_amount = 100; // 转账数量

    // 4. 检查并创建代币账户(如果不存在)
    if !check_token_account_exists(&client, &recipient_address, &token_mint).await? {
        println!("为接收者创建代币账户...");
        let signature = commands::create_token_account(
            &client,
            &payer,
            &recipient_address,
            &token_mint,
        )?;
        println!("账户创建交易哈希: {}", signature);
    }

    // 5. 初始化代币客户端
    let token = Token::new(&client, token_mint);

    // 6. 检查源账户余额
    let balance = token.get_balance(&source_account.pubkey())?;
    println!("源账户当前余额: {}", balance);
    
    if balance < transfer_amount {
        return Err("余额不足".into());
    }

    // 7. 执行转账
    println!("正在转账 {} 代币到 {}...", transfer_amount, recipient_address);
    let signature = token.transfer(
        &source_account,
        &recipient_address,
        transfer_amount,
    )?;
    println!("转账成功! 交易哈希: {}", signature);

    // 8. 验证转账结果
    tokio::time::sleep(std::time::Duration::from_secs(5)).await; // 等待区块确认
    let new_balance = token.get_balance(&recipient_address)?;
    println!("接收账户新余额: {}", new_balance);

    Ok(())
}

/// 检查代币账户是否已存在
async fn check_token_account_exists(
    client: &RpcClient,
    owner: &Pubkey,
    mint: &Pubkey
) -> Result<bool, ClientError> {
    let accounts = client.get_token_accounts_by_owner(owner, solana_sdk::program_option::ProgramOpt::tok())?;
    accounts.iter().any(|(_, account)| account.mint == *mint)
}

关键点说明:

  1. 密钥管理:示例展示了从文件加载密钥对,实际应用中应使用更安全的方式管理私钥

  2. 错误处理:使用Rust的Result类型进行全面的错误处理

  3. 异步操作:使用tokio运行时处理异步操作,如等待交易确认

  4. 账户检查:转账前检查代币账户是否存在,避免不必要的创建操作

  5. 余额验证:转账前后都检查余额,确保操作成功

增强功能:

  1. 添加了代币账户存在性检查
  2. 包含余额验证逻辑
  3. 使用tokio进行异步处理
  4. 更完善的错误处理
  5. 实际操作前的状态检查

注意:实际使用时需要替换示例中的占位符(如代币Mint地址、接收者地址等)并确保配置文件存在。

回到顶部