Rust StarkNet账户管理库starknet-accounts的使用,实现StarkNet区块链账户创建、签名和交易功能

Rust StarkNet账户管理库starknet-accounts的使用,实现StarkNet区块链账户创建、签名和交易功能

安装

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

cargo add starknet-accounts

或者在Cargo.toml中添加:

starknet-accounts = "0.15.0"

完整示例代码

以下是一个使用starknet-accounts库实现StarkNet账户创建、签名和交易的完整示例:

use starknet_accounts::{
    Account, AccountFactory, OpenZeppelinAccountFactory, SingleOwnerAccount
};
use starknet_core::types::{
    FieldElement, InvokeTransactionResult, TransactionRequest
};
use starknet_providers::{Provider, SequencerGatewayProvider};
use starknet_signers::{LocalWallet, SigningKey};

#[tokio::main]
async fn main() {
    // 1. 初始化Provider连接StarkNet测试网
    let provider = SequencerGatewayProvider::starknet_alpha_goerli();
    
    // 2. 生成随机私钥
    let signing_key = SigningKey::from_random();
    let private_key = signing_key.secret_scalar();
    
    // 3. 创建账户工厂
    let factory = OpenZeppelinAccountFactory::new(
        FieldElement::from_hex_be("0x123...").unwrap(), // 类哈希
        FieldElement::from_hex_be("0x456...").unwrap(), // 盐
        provider.clone()
    ).await.unwrap();
    
    // 4. 部署新账户
    let account = factory.deploy(private_key).await.unwrap();
    println!("New account deployed: {:#x}", account.address());
    
    // 5. 准备交易
    let transaction = TransactionRequest::new(
        FieldElement::from_hex_be("0x789...").unwrap(), // 合约地址
        "transfer".to_string(), // 函数名
        vec![
            FieldElement::from_hex_be("0xabc...").unwrap(), // 接收方地址
            FieldElement::from(100u64) // 转账金额
        ]
    );
    
    // 6. 签名并发送交易
    let result: InvokeTransactionResult = account.execute(vec![transaction]).await.unwrap();
    println!("Transaction hash: {:#x}", result.transaction_hash);
}

代码说明

  1. Provider初始化:连接StarkNet测试网
  2. 密钥生成:使用SigningKey生成随机私钥
  3. 账户工厂:使用OpenZeppelin账户模板创建工厂
  4. 账户部署:部署新账户到StarkNet网络
  5. 交易构建:创建转账交易请求
  6. 交易执行:账户签名并发送交易

注意事项

  • 需要替换示例中的类哈希、盐和合约地址等参数
  • 实际使用中需要处理错误和交易状态
  • 部署账户需要支付gas费用

1 回复

Rust StarkNet账户管理库starknet-accounts使用指南

starknet-accounts是一个用于StarkNet区块链账户管理的Rust库,提供了账户创建、签名和交易发送等功能。

主要功能

  1. 创建和管理StarkNet账户
  2. 对交易进行签名
  3. 发送交易到StarkNet网络
  4. 支持不同类型的账户实现

安装

Cargo.toml中添加依赖:

[dependencies]
starknet-accounts = "0.3"
starknet = "0.3"
tokio = { version = "1.0", features = ["full"] }

基本使用方法

1. 创建本地账户

use starknet::core::types::FieldElement;
use starknet::core::utils::get_contract_address;
use starknet_accounts::{LocalWallet, SingleOwnerAccount};
use starknet_providers::jsonrpc::HttpTransport;
use starknet_providers::JsonRpcClient;

#[tokio::main]
async fn main() {
    // 初始化provider
    let provider = JsonRpcClient::new(HttpTransport::new(
        "https://starknet-goerli.infura.io/v3/YOUR_INFURA_KEY".parse().unwrap(),
    ));
    
    // 创建私钥
    let private_key = FieldElement::from_hex_be("YOUR_PRIVATE_KEY").unwrap();
    
    // 创建账户地址
    let address = get_contract_address(
        FieldElement::from_hex_be("0x123").unwrap(), // salt
        FieldElement::from_hex_be("0x456").unwrap(), // class hash
        &[private_key],
        FieldElement::from_hex_be("0x0").unwrap(), // constructor calldata
    );
    
    // 创建本地钱包
    let signer = LocalWallet::from(private_key);
    
    // 创建账户
    let account = SingleOwnerAccount::new(
        provider,
        signer,
        address,
        FieldElement::from_hex_be("0x534e5f474f45524c49").unwrap(), // chain_id (SN_GOERLI)
    );
}

2. 发送交易

use starknet::core::types::{FunctionCall, InvokeTransactionRequest};
use starknet::macros::selector;

#[tokio::main]
async fn main() {
    // ... 前面的账户创建代码
    
    // 准备调用数据
    let call = FunctionCall {
        contract_address: FieldElement::from_hex_be("0xCONTRACT_ADDRESS").unwrap(),
        entry_point_selector: selector!("transfer"),
        calldata: vec![
            FieldElement::from_hex_be("0xRECIPIENT").unwrap(),
            FieldElement::from_hex_be("1000000000000000000").unwrap(), // 1 ETH
            FieldElement::ZERO,
        ],
    };
    
    // 创建调用交易请求
    let tx_request = InvokeTransactionRequest {
        sender_address: address,
        calldata: call.calldata,
        signature: vec![],
        max_fee: FieldElement::from_hex_be("1000000000000000").unwrap(),
        nonce: FieldElement::ZERO,
    };
    
    // 执行交易
    let result = account.execute(vec![call]).send().await.unwrap();
    
    println!("Transaction hash: {:#x}", result.transaction_hash);
}

3. 查询账户信息

#[tokio::main]
async fn main() {
    // ... 前面的账户创建代码
    
    // 查询nonce
    let nonce = account.get_nonce().await.unwrap();
    println!("Current nonce: {}", nonce);
    
    // 查询余额
    let balance = provider
        .call(
            FunctionCall {
                contract_address: FieldElement::from_hex_be("0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7").unwrap(), // ETH合约地址
                entry_point_selector: selector!("balanceOf"),
                calldata: vec![address],
            },
            None,
        )
        .await
        .unwrap();
    
    println!("ETH balance: {}", balance[0]);
}

高级功能

1. 使用多重签名账户

use starknet_accounts::MultiSigAccount;

#[tokio::main]
async fn main() {
    // 创建多个签名者
    let signer1 = LocalWallet::from(FieldElement::from_hex_be("PRIVATE_KEY1").unwrap());
    let signer2 = LocalWallet::from(FieldElement::from_hex_be("PRIVATE_KEY2").unwrap());
    
    // 创建多重签名账户
    let account = MultiSigAccount::new(
        provider,
        vec![signer1, signer2],
        address,
        FieldElement::from_hex_be("0x534e5f474f45524c49").unwrap(), // chain_id
        2, // 需要的签名数
    );
}

2. 使用硬件钱包签名

use starknet_accounts::LedgerWallet;

#[tokio::main]
async fn main() {
    // 创建Ledger钱包
    let signer = LedgerWallet::new("path/to/ledger").unwrap();
    
    // 创建账户
    let account = SingleOwnerAccount::new(
        provider,
        signer,
        address,
        FieldElement::from_hex_be("0x534e5f474f45524c49").unwrap(),
    );
}

注意事项

  1. 妥善保管私钥,不要硬编码在代码中
  2. 生产环境使用环境变量或安全的密钥管理系统
  3. 发送交易前确保账户有足够的ETH支付gas费用
  4. 注意处理nonce,避免重复使用

完整示例

以下是一个完整的StarkNet账户管理示例,包含创建账户、查询余额和发送交易:

use starknet::core::types::{FieldElement, FunctionCall, InvokeTransactionRequest};
use starknet::core::utils::get_contract_address;
use starknet::macros::selector;
use starknet_accounts::{LocalWallet, SingleOwnerAccount};
use starknet_providers::jsonrpc::HttpTransport;
use starknet_providers::JsonRpcClient;

#[tokio::main]
async fn main() {
    // 1. 初始化provider
    let provider = JsonRpcClient::new(HttpTransport::new(
        "https://starknet-goerli.infura.io/v3/YOUR_INFURA_KEY".parse().unwrap(),
    ));
    
    // 2. 创建账户
    let private_key = FieldElement::from_hex_be("YOUR_PRIVATE_KEY").unwrap();
    let address = get_contract_address(
        FieldElement::from_hex_be("0x123").unwrap(),
        FieldElement::from_hex_be("0x456").unwrap(),
        &[private_key],
        FieldElement::from_hex_be("0x0").unwrap(),
    );
    
    let signer = LocalWallet::from(private_key);
    let account = SingleOwnerAccount::new(
        provider.clone(),
        signer,
        address,
        FieldElement::from_hex_be("0x534e5f474f45524c49").unwrap(),
    );
    
    // 3. 查询余额
    let balance = provider
        .call(
            FunctionCall {
                contract_address: FieldElement::from_hex_be("0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7").unwrap(),
                entry_point_selector: selector!("balanceOf"),
                calldata: vec![address],
            },
            None,
        )
        .await
        .unwrap();
    println!("Current ETH balance: {}", balance[0]);
    
    // 4. 发送交易
    let call = FunctionCall {
        contract_address: FieldElement::from_hex_be("0xCONTRACT_ADDRESS").unwrap(),
        entry_point_selector: selector!("transfer"),
        calldata: vec![
            FieldElement::from_hex_be("0xRECIPIENT").unwrap(),
            FieldElement::from_hex_be("1000000000000000000").unwrap(),
            FieldElement::ZERO,
        ],
    };
    
    let result = account.execute(vec![call]).send().await.unwrap();
    println!("Transaction hash: {:#x}", result.transaction_hash);
}
回到顶部