Rust区块链工具库solana-cli-output的使用:Solana命令行输出解析与格式化插件

Metadata

pkg:cargo/solana-cli-output@3.0.0

大约17小时前

2021版本

Apache-2.0许可证

55.9 KiB

安装

在您的项目目录中运行以下Cargo命令:

cargo add solana-cli-output

或者在您的Cargo.toml文件中添加以下行:

solana-cli-output = “3.0.0”

主页

anza.xyz

文档

docs.rs/solana-cli-output/3.0.0

代码库

github.com/anza-xyz/agave

所有者

anza-team

提供的示例代码:

use solana_cli_output::{OutputFormat, CliOutput};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 创建CLI输出实例
    let mut output = CliOutput::new();
    
    // 设置输出格式为JSON
    output.set_format(OutputFormat::Json);
    
    // 解析Solana命令行输出
    let cli_output = r#"{
        "jsonrpc": "2.0",
        "result": {
            "context": {
                "slot": 123456789
            },
            "value": {
                "blockHeight": 1234567,
                "blockTime": 1640995200
            }
        },
        "id": 1
    }"#;
    
    // 格式化输出
    let formatted = output.parse_and_format(cli_output)?;
    println!("{}", formatted);
    
    Ok(())
}
use solana_cli_output::{OutputFormat, CliOutput, DisplayConfig};

// 更详细的配置示例
fn advanced_example() -> Result<(), Box<dyn std::error::Error>> {
    let mut output = CliOutput::new();
    
    // 配置显示选项
    let config = DisplayConfig {
        format: OutputFormat::JsonPretty,  // 美化JSON格式
        include_context: true,             // 包含上下文信息
        show_all: false,                   // 不显示所有字段
    };
    
    output.set_config(config);
    
    // 模拟Solana交易查询输出
    let transaction_output = r#"{
        "jsonrpc": "2.0",
        "result": {
            "slot": 123456789,
            "transaction": {
                "message": {
                    "accountKeys": [
                        "Alice111111111111111111111111111111111111111",
                        "Bob111111111111111111111111111111111111111111"
                    ],
                    "instructions": [
                        {
                            "programIdIndex": 0,
                            "accounts": [1],
                            "data": "base64:AA=="
                        }
                    ]
                },
                "signatures": [
                    "signature1"
                ]
            },
            "blockTime": 1640995200
        },
        "id": 1
    }"#;
    
    // 解析并格式化交易输出
    let formatted_tx = output.parse_and_format(transaction_output)?;
    println!("Formatted transaction:\n{}", formatted_tx);
    
    Ok(())
}
use solana_cli_output::{OutputFormat, CliOutput, Error};

// 错误处理示例
fn error_handling_example() {
    let output = CliOutput::new();
    
    // 无效的JSON输入
    let invalid_json = "invalid json content";
    
    match output.parse_and_format(invalid_json) {
        Ok(formatted) => {
            println!("Formatted output: {}", formatted);
        }
        Err(Error::ParseError(e)) => {
            eprintln!("Parse error: {}", e);
        }
        Err(Error::FormatError(e)) => {
            eprintln!("Format error: {}", e);
        }
        Err(e) => {
            eprintln!("Other error: {}", e);
        }
    }
}

完整示例demo:

use solana_cli_output::{OutputFormat, CliOutput, DisplayConfig, Error};
use std::error::Error;

// 综合示例:展示solana-cli-output库的主要功能
fn main() -> Result<(), Box<dyn Error>> {
    println!("=== Solana CLI输出格式化示例 ===");
    
    // 示例1:基础JSON格式化
    basic_json_formatting()?;
    
    // 示例2:高级配置格式化
    advanced_formatting()?;
    
    // 示例3:错误处理演示
    error_handling_demo();
    
    Ok(())
}

// 基础JSON格式化示例
fn basic_json_formatting() -> Result<(), Box<dyn Error>> {
    println!("\n--- 基础JSON格式化 ---");
    
    let mut output = CliOutput::new();
    output.set_format(OutputFormat::Json);
    
    // Solana区块信息输出
    let block_output = r#"{
        "jsonrpc": "2.0",
        "result": {
            "context": {
                "slot": 123456789
            },
            "value": {
                "blockHeight": 1234567,
                "blockTime": 1640995200,
                "transactions": 150,
                "parentSlot": 123456788
            }
        },
        "id": 1
    }"#;
    
    let formatted = output.parse_and_format(block_output)?;
    println!("格式化后的区块信息:\n{}", formatted);
    
    Ok(())
}

// 高级配置格式化示例
fn advanced_formatting() -> Result<(), Box<dyn Error>> {
    println!("\n--- 高级配置格式化 ---");
    
    let mut output = CliOutput::new();
    
    // 配置详细的显示选项
    let config = DisplayConfig {
        format: OutputFormat::JsonPretty,
        include_context: true,
        show_all: true,  // 显示所有字段
    };
    
    output.set_config(config);
    
    // Solana账户信息输出
    let account_output = r#"{
        "jsonrpc": "2.0",
        "result": {
            "context": {
                "slot": 123456790
            },
            "value": {
                "data": ["base64:AAECAwQ=", "base64"],
                "executable": false,
                "lamports": 1000000000,
                "owner": "11111111111111111111111111111111",
                "rentEpoch": 123
            }
        },
        "id": 1
    }"#;
    
    let formatted_account = output.parse_and_format(account_output)?;
    println!("格式化后的账户信息:\n{}", formatted_account);
    
    Ok(())
}

// 错误处理演示
fn error_handling_demo() {
    println!("\n--- 错误处理演示 ---");
    
    let output = CliOutput::new();
    
    // 测试无效的JSON输入
    let test_cases = vec![
        "invalid json",
        r#"{"incomplete": object"#,
        r#"{"valid": "json but not solana format"}"#
    ];
    
    for (i, test_input) in test_cases.iter().enumerate() {
        println!("\n测试用例 {}:", i + 1);
        match output.parse_and_format(test_input) {
            Ok(formatted) => {
                println!("成功格式化: {}", formatted);
            }
            Err(Error::ParseError(e)) => {
                println!("解析错误: {}", e);
            }
            Err(Error::FormatError(e)) => {
                println!("格式化错误: {}", e);
            }
            Err(e) => {
                println!("其他错误: {}", e);
            }
        }
    }
}

// 工具函数:创建自定义Solana输出
fn create_custom_solana_output() -> String {
    r#"{
        "jsonrpc": "2.0",
        "result": {
            "context": {
                "slot": 999999999
            },
            "value": {
                "customField": "customValue",
                "numberField": 42,
                "arrayField": [1, 2, 3]
            }
        },
        "id": 42
    }"#.to_string()
}

// 自定义输出格式化示例
fn custom_output_example() -> Result<(), Box<dyn Error>> {
    println!("\n--- 自定义输出格式化 ---");
    
    let mut output = CliOutput::new();
    output.set_format(OutputFormat::JsonPretty);
    
    let custom_output = create_custom_solana_output();
    let formatted = output.parse_and_format(&custom_output)?;
    
    println!("自定义输出格式化结果:\n{}", formatted);
    
    Ok(())
}

1 回复

Rust区块链工具库solana-cli-output的使用指南

概述

solana-cli-output是一个专为Solana区块链开发者设计的Rust工具库,用于解析和格式化Solana命令行工具的输出结果。该库提供了简洁的API来处理Solana CLI的各种输出格式,使开发者能够更轻松地集成和处理区块链数据。

主要功能

  • 解析Solana CLI的JSON输出
  • 格式化交易和账户信息
  • 处理错误信息和状态码
  • 支持自定义输出模板

安装方法

在Cargo.toml中添加依赖:

[dependencies]
solana-cli-output = "0.1.0"

基本用法

1. 解析账户信息

use solana_cli_output::{parse_account_output, DisplayFormat};

fn main() {
    let json_output = r#"
    {
        "pubkey": "9wFFyR8...",
        "lamports": 1461600,
        "owner": "11111111111111111111111111111111",
        "executable": false
    }"#;

    match parse_account_output(json_output) {
        Ok(account_info) => {
            println!("账户余额: {} SOL", account_info.lamports_to_sol());
            println!("格式化输出:\n{}", account_info.format(DisplayFormat::Human));
        }
        Err(e) => eprintln!("解析错误: {}", e),
    }
}

2. 处理交易结果

use solana_cli_output::{parse_transaction_output, TransactionDisplay};

fn handle_transaction() {
    let tx_output = r#"
    {
        "slot": 12345,
        "transaction": {
            "signatures": ["5Q..."],
            "message": {"instructions": [...]}
        },
        "meta": {
            "err": null,
            "fee": 5000,
            "status": {"Ok": null}
        }
    }"#;

    let tx_info = parse_transaction_output(tx_output).unwrap();
    println!("交易状态: {}", tx_info.status());
    println!("手续费: {} lamports", tx_info.fee());
}

3. 自定义格式化

use solana_cli_output::{OutputParser, CustomFormatter};

fn custom_formatting() {
    let parser = OutputParser::new();
    let formatter = CustomFormatter::new()
        .with_date_format("%Y-%m-%d %H:%M:%S")
        .with_number_separators(true);

    let data = get_solana_cli_data(); // 获取CLI输出
    let formatted = parser.parse_and_format(data, &formatter);
    println!("{}", formatted);
}

高级特性

错误处理

use solana_cli_output::{ErrorParser, CliError};

fn analyze_errors() {
    let error_output = r#"
    {
        "code": 123,
        "message": "Insufficient funds",
        "data": {"required": 1000000, "available": 500000}
    }"#;

    match ErrorParser::parse(error_output) {
        Ok(cli_error) => {
            println!("错误代码: {}", cli_error.code);
            println!("建议解决方案: {}", cli_error.suggest_solution());
        }
        Err(e) => eprintln!("无法解析错误信息: {}", e),
    }
}

批量处理

use solana_cli_output::BatchProcessor;

async fn process_multiple_outputs() {
    let outputs = vec![output1, output2, output3];
    let processor = BatchProcessor::new()
        .with_concurrency(4)
        .with_timeout(std::time::Duration::from_secs(30));

    let results = processor.process_batch(outputs).await;
    for result in results {
        println!("处理结果: {:?}", result);
    }
}

配置选项

use solana_cli_output::{OutputConfig, NumberFormat, DateStyle};

let config = OutputConfig::default()
    .number_format(NumberFormat::Commas)
    .date_style(DateStyle::Relative)
    .max_decimals(6)
    .show_all_fields(false);

完整示例代码

// 完整示例:使用solana-cli-output库处理Solana CLI输出
use solana_cli_output::{
    parse_account_output, 
    parse_transaction_output, 
    DisplayFormat,
    OutputParser,
    CustomFormatter,
    ErrorParser,
    OutputConfig,
    NumberFormat,
    DateStyle
};
use tokio; // 用于异步处理

#[tokio::main]
async fn main() {
    // 示例1:解析账户信息
    println!("=== 账户信息解析示例 ===");
    let account_json = r#"
    {
        "pubkey": "9wFFyR8f8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7",
        "lamports": 1461600,
        "owner": "11111111111111111111111111111111",
        "executable": false,
        "rentEpoch": 123
    }"#;
    
    match parse_account_output(account_json) {
        Ok(account) => {
            println!("账户余额: {:.6} SOL", account.lamports_to_sol());
            println!("格式化输出:\n{}", account.format(DisplayFormat::Human));
        }
        Err(e) => eprintln!("账户解析错误: {}", e),
    }

    // 示例2:处理交易结果
    println!("\n=== 交易处理示例 ===");
    let transaction_json = r#"
    {
        "slot": 1234567,
        "transaction": {
            "signatures": ["5Qpr8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7Vf8V7
回到顶部