Rust StarkNet交互库starknet-providers的使用,支持与StarkNet区块链网络的高效通信和智能合约操作

Rust StarkNet交互库starknet-providers的使用

starknet-providers是一个Rust库,用于与StarkNet节点和排序器进行交互,支持与StarkNet区块链网络的高效通信和智能合约操作。

安装

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

cargo add starknet-providers

或者在Cargo.toml中添加以下行:

starknet-providers = "0.15.0"

示例代码

以下是一个使用starknet-providers与StarkNet网络交互的基本示例:

use starknet_providers::{Provider, JsonRpcProvider};
use starknet_core::types::FieldElement;

#[tokio::main]
async fn main() {
    // 创建一个JSON-RPC provider连接到StarkNet测试网
    let provider = JsonRpcProvider::new("https://starknet-testnet.public.blastapi.io");
    
    // 获取最新的区块号
    match provider.block_number().await {
        Ok(block_number) => println!("Latest block number: {}", block_number),
        Err(e) => eprintln!("Error getting block number: {}", e),
    }
    
    // 获取指定合约的存储值
    let contract_address = FieldElement::from_hex_be("0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef").unwrap();
    let key = FieldElement::from_hex_be("0x0").unwrap();
    
    match provider.get_storage_at(contract_address, key).await {
        Ok(value) => println!("Storage value: {}", value),
        Err(e) => eprintln!("Error getting storage value: {}", e),
    }
}

完整示例代码

以下是一个更完整的示例,展示如何使用starknet-providers进行多种操作:

use starknet_providers::{Provider, JsonRpcProvider};
use starknet_core::types::{FieldElement, BlockId, BlockTag};
use std::str::FromStr;

#[tokio::main]
async fn main() {
    // 初始化JSON-RPC provider
    let provider = JsonRpcProvider::new("https://starknet-testnet.public.blastapi.io");

    // 1. 获取链ID
    match provider.chain_id().await {
        Ok(chain_id) => println!("Chain ID: {}", chain_id),
        Err(e) => eprintln!("Error getting chain ID: {}", e),
    }

    // 2. 获取最新区块信息
    match provider.get_block_with_txs(BlockId::Tag(BlockTag::Latest)).await {
        Ok(block) => println!("Latest block hash: {:?}", block.block_hash),
        Err(e) => eprintln!("Error getting latest block: {}", e),
    }

    // 3. 查询合约存储
    let contract_address = FieldElement::from_hex_be(
        "0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
    ).unwrap();
    let key = FieldElement::from_hex_be("0x0").unwrap();
    
    match provider.get_storage_at(contract_address, key).await {
        Ok(value) => println!("Storage value: {}", value),
        Err(e) => eprintln!("Error getting storage value: {}", e),
    }

    // 4. 获取合约代码
    match provider.get_class_hash_at(contract_address).await {
        Ok(class_hash) => println!("Contract class hash: {}", class_hash),
        Err(e) => eprintln!("Error getting contract class hash: {}", e),
    }

    // 5. 获取交易状态
    let tx_hash = FieldElement::from_str("0x123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef").unwrap();
    match provider.get_transaction_status(tx_hash).await {
        Ok(status) => println!("Transaction status: {:?}", status),
        Err(e) => eprintln!("Error getting transaction status: {}", e),
    }
}

特性

  • 支持JSON-RPC协议与StarkNet节点通信
  • 提供基本的区块链操作如查询区块、交易和合约状态
  • 支持智能合约交互
  • 类型安全的API设计

许可证

该库采用MIT或Apache-2.0双许可证。


1 回复

Rust StarkNet交互库starknet-providers使用指南

starknet-providers是一个用于与StarkNet区块链网络交互的Rust库,它提供了高效通信和智能合约操作的功能。

主要特性

  • 支持与StarkNet节点的JSON-RPC通信
  • 提供同步和异步API
  • 支持智能合约部署和调用
  • 支持账户抽象操作
  • 提供交易状态查询功能

安装方法

在Cargo.toml中添加依赖:

[dependencies]
starknet-providers = "0.3"
tokio = { version = "1.0", features = ["full"] } # 如果需要异步支持

基本使用方法

1. 创建Provider

use starknet_providers::{JsonRpcClient, Provider};

// 连接到本地StarkNet节点
let provider = JsonRpcClient::new("http://localhost:9545");

2. 查询链信息

use starknet_providers::Provider;

let chain_id = provider.chain_id().await?;
println!("Chain ID: {}", chain_id);

let block_number = provider.block_number().await?;
println!("Current block number: {}", block_number);

3. 查询账户余额

use starknet_providers::Provider;
use starknet_core::types::FieldElement;

let account_address = FieldElement::from_hex_be("0x123...").unwrap();
let balance = provider.get_balance(account_address).await?;
println!("Account balance: {}", balance);

4. 调用智能合约

use starknet_providers::Provider;
use starknet_core::types::{FunctionCall, FieldElement};

let contract_address = FieldElement::from_hex_be("0x456...").unwrap();
let entry_point_selector = FieldElement::from_hex_be("0x789...").unwrap();

let call = FunctionCall {
    contract_address,
    entry_point_selector,
    calldata: vec![], // 根据合约ABI填充
};

let result = provider.call(call, None).await?;
println!("Call result: {:?}", result);

5. 发送交易

use starknet_providers::Provider;
use starknet_core::types::{
    BroadcastedInvokeTransaction, InvokeTransactionV1, FieldElement
};

let tx = BroadcastedInvokeTransaction::V1(InvokeTransactionV1 {
    sender_address: FieldElement::from_hex_be("0xabc...").unwrap(),
    calldata: vec![], // 根据交易内容填充
    max_fee: FieldElement::from_dec_str("1000000").unwrap(),
    signature: vec![], // 签名数据
    nonce: FieldElement::ZERO,
});

let tx_hash = provider.add_invoke_transaction(tx).await?;
println!("Transaction hash: 0x{:x}", tx_hash);

异步API示例

use starknet_providers::{JsonRpcClient, Provider};
use starknet_core::types::FieldElement;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let provider = JsonRpcClient::new("https://starknet-mainnet.infura.io/v3/YOUR_API_KEY");
    
    let block = provider.get_block_with_txs(BlockId::Number(12345)).await?;
    println!("Block transactions: {:?}", block.transactions);
    
    Ok(())
}

错误处理

match provider.get_block_with_txs(BlockId::Number(12345)).await {
    Ok(block) => println!("Got block: {:?}", block),
    Err(starknet_providers::ProviderError::StarknetError(error)) => {
        eprintln!("StarkNet error: {}", error.message);
    }
    Err(e) => eprintln!("Other error: {}", e),
}

高级功能

批量请求

use starknet_providers::{Provider, JsonRpcClient};
use starknet_core::types::{BlockId, BlockTag};

let provider = JsonRpcClient::new("http://localhost:9545");

let batch = vec![
    provider.get_block_with_txs(BlockId::Tag(BlockTag::Latest)),
    provider.chain_id(),
    provider.syncing(),
];

let results = futures::future::join_all(batch).await;

自定义HTTP客户端

use starknet_providers::{JsonRpcClient, Provider};
use reqwest::Client;

let http_client = Client::builder()
    .timeout(std::time::Duration::from_secs(30))
    .build()?;

let provider = JsonRpcClient::with_client(
    "http://localhost:9545",
    http_client,
);

注意事项

  1. 确保StarkNet节点版本与库兼容
  2. 处理交易时注意gas费用和nonce管理
  3. 生产环境建议使用重试机制处理暂时性错误
  4. 敏感操作(如私钥签名)应在安全环境中进行

完整示例代码

use starknet_providers::{JsonRpcClient, Provider};
use starknet_core::types::{
    BlockId, BlockTag, FieldElement, FunctionCall,
    BroadcastedInvokeTransaction, InvokeTransactionV1
};
use std::error::Error;

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    // 1. 初始化Provider
    let provider = JsonRpcClient::new("http://localhost:9545");
    
    // 2. 查询链信息
    let chain_id = provider.chain_id().await?;
    println!("Chain ID: {}", chain_id);
    
    let block_number = provider.block_number().await?;
    println!("Current block number: {}", block_number);
    
    // 3. 查询账户余额
    let account_address = FieldElement::from_hex_be("0x123...").unwrap();
    let balance = provider.get_balance(account_address).await?;
    println!("Account balance: {}", balance);
    
    // 4. 调用智能合约
    let contract_address = FieldElement::from_hex_be("0x456...").unwrap();
    let entry_point_selector = FieldElement::from_hex_be("0x789...").unwrap();
    
    let call = FunctionCall {
        contract_address,
        entry_point_selector,
        calldata: vec![], // 根据合约ABI填充
    };
    
    let result = provider.call(call, None).await?;
    println!("Call result: {:?}", result);
    
    // 5. 发送交易
    let tx = BroadcastedInvokeTransaction::V1(InvokeTransactionV1 {
        sender_address: FieldElement::from_hex_be("0xabc...").unwrap(),
        calldata: vec![], // 根据交易内容填充
        max_fee: FieldElement::from_dec_str("1000000").unwrap(),
        signature: vec![], // 签名数据
        nonce: FieldElement::ZERO,
    });
    
    let tx_hash = provider.add_invoke_transaction(tx).await?;
    println!("Transaction hash: 0x{:x}", tx_hash);
    
    // 批量请求示例
    let batch = vec![
        provider.get_block_with_txs(BlockId::Tag(BlockTag::Latest)),
        provider.chain_id(),
        provider.syncing(),
    ];
    
    let results = futures::future::join_all(batch).await;
    println!("Batch results: {:?}", results);
    
    Ok(())
}

这个库为Rust开发者提供了与StarkNet交互的完整工具集,可以方便地构建StarkNet上的去中心化应用。

回到顶部