Rust NEAR协议开发库near-workspaces的使用:简化NEAR区块链智能合约测试与交互

Rust NEAR协议开发库near-workspaces的使用:简化NEAR区块链智能合约测试与交互

NEAR Workspaces (Rust版本)

这是一个用于自动化NEAR智能合约工作流程和编写测试的Rust库。该软件尚未最终完成,可能会发生变化。

简单测试案例

一个简单的测试示例,帮助我们熟悉near-workspaces框架。我们将通过NFT合约来展示如何使用near-workspaces-rs进行测试。

设置 - 导入

首先,我们需要声明一些方便的导入:

// 允许我们将参数转换为合约可读取的JSON字节的宏
use serde_json::json;

我们需要预编译WASM合约并知道其路径。在这个示例中,我们将指向NFT合约示例:

const NFT_WASM_FILEPATH: &str = "./examples/res/non_fungible_token.wasm";

设置 - 启动Sandbox并部署NFT合约

这包括启动我们的sandbox,加载wasm文件并将该wasm文件部署到sandbox环境中。

#[tokio::test]
async fn test_nft_contract() -> anyhow::Result<()> {
    let worker = near_workspaces::sandbox().await?;
    let wasm = std::fs::read(NFT_WASM_FILEPATH)?;
    let contract = worker.dev_deploy(&wasm).await?;

其中:

  • anyhow - 处理错误处理的crate,使开发人员的错误处理更加健壮
  • worker - 我们与sandbox环境交互的网关
  • contract - 开发人员与之交互的部署在sandbox上的合约

初始化合约 & 测试输出

然后我们将直接调用合约,初始化NFT合约的元数据:

    let outcome = contract
        .call("new_default_meta")
        .args_json(json!({
            "owner_id": contract.id(),
        }))
        .transact()  // 注意:我们在这里使用合约的密钥来签署交易
        .await?;

    // outcome包含日志、收据和交易结果等数据
    println!("new_default_meta outcome: {:#?}", outcome);

接下来,让我们通过nft_mint铸造一个NFT。这展示了一些我们可以提供的额外参数,如存款和gas:

    use near_gas::NearGas;
    use near_workspaces::types::NearToken;

    let deposit = NearToken::from_near(100);
    let outcome = contract
        .call("nft_mint")
        .args_json(json!({
            "token_id": "0",
            "token_owner_id": contract.id(),
            "token_metadata": {
                "title": "Olympus Mons",
                "description": "Tallest mountain in charted solar system",
                "copies": 1,
            },
        }))
        .deposit(deposit)
        // nft_mint可能消耗比默认gas更多的gas,所以提供我们自己的gas值:
        .gas(NearGas::from_tgas(300))
        .transact()
        .await?;

    println!("nft_mint outcome: {:#?}", outcome);

然后我们可以通过view调用nft_metadata来查看我们铸造的NFT的元数据:

    let result: serde_json::Value = contract
        .call("nft_metadata")
        .view()
        .await?
        .json()?;

    println!("--------------\n{}", result);
    println!("Dev Account ID: {}", contract.id());
    Ok(())
}

完整示例代码

以下是完整的NFT测试示例:

use serde_json::json;
use near_workspaces::types::NearToken;
use near_gas::NearGas;

const NFT_WASM_FILEPATH: &str = "./examples/res/non_fungible_token.wasm";

#[tokio::test]
async fn test_nft_contract() -> anyhow::Result<()> {
    // 设置sandbox环境并部署合约
    let worker = near_workspaces::sandbox().await?;
    let wasm = std::fs::read(NFT_WASM_FILEPATH)?;
    let contract = worker.dev_deploy(&wasm).await?;

    // 初始化NFT合约
    let outcome = contract
        .call("new_default_meta")
        .args_json(json!({
            "owner_id": contract.id(),
        }))
        .transact()
        .await?;
    println!("new_default_meta outcome: {:#?}", outcome);

    // 铸造NFT
    let deposit = NearToken::from_near(100);
    let outcome = contract
        .call("nft_mint")
        .args_json(json!({
            "token_id": "0",
            "token_owner_id": contract.id(),
            "token_metadata": {
                "title": "Olympus Mons",
                "description": "Tallest mountain in charted solar system",
                "copies": 1,
            },
        }))
        .deposit(deposit)
        .gas(NearGas::from_tgas(300))
        .transact()
        .await?;
    println!("nft_mint outcome: {:#?}", outcome);

    // 查看NFT元数据
    let result: serde_json::Value = contract
        .call("nft_metadata")
        .view()
        .await?
        .json()?;

    println!("--------------\n{}", result);
    println!("Dev Account ID: {}", contract.id());
    Ok(())
}

要运行上述NFT示例,执行:

cargo run --example nft

1 回复

Rust NEAR协议开发库near-workspaces使用指南

near-workspaces是一个用于简化NEAR区块链智能合约测试与交互的Rust库,它提供了一套方便的API来与NEAR协议进行交互。

主要特性

  • 简化本地测试环境设置
  • 提供沙盒环境进行合约测试
  • 支持与测试网和主网交互
  • 方便的账户和合约管理

安装方法

在Cargo.toml中添加依赖:

[dependencies]
near-workspaces = "0.5"
tokio = { version = "1", features = ["full"] }

基本使用方法

1. 初始化工作区

use near_workspaces::Workspace;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // 创建沙盒环境
    let worker = near_workspaces::sandbox().await?;
    
    // 或者连接测试网
    // let worker = near_workspaces::testnet().await?;
    
    Ok(())
}

2. 创建账户

let account = worker.dev_create_account().await?;
println!("Account ID: {}", account.id());

3. 部署合约

// 编译后的wasm合约路径
let wasm = std::path::PathBuf:: from("res/my_contract.wasm");
let contract = worker.dev_deploy(&std::fs::read(wasm)?).await?;

println!("Contract deployed at: {}", contract.id());

4. 调用合约方法

// 调用view方法
let result: String = contract
    .view("get_greeting")
    .args_json(serde_json::json!({}))
    .await?
    .json()?;

println!("Greeting: {}", result);

// 调用change方法
let outcome = contract
    .call("set_greeting")
    .args_json(serde_json::json!({"message": "Hello from workspaces!"}))
    .transact()
    .await?;

println!("Transaction outcome: {:?}", outcome);

高级功能

1. 批量交易

let outcome = contract
    .batch(&worker)
    .call(
        "method1",
        serde_json::json!({"param": "value"}),
    )
    .call(
        "method2",
        serde_json::json!({"param": 42}),
    )
    .transact()
    .await?;

2. 模拟主网环境

let worker = near_workspaces::sandbox()
    .rpc_addr("https://rpc.mainnet.near.org")
    .await?;

3. 测试错误处理

let result = contract
    .call("failing_method")
    .args_json(serde_json::json!({}))
    .transact()
    .await;

assert!(result.is_err());

完整示例

use near_workspaces::Workspace;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // 1. 初始化沙盒环境
    let worker = near_workspaces::sandbox().await?;
    
    // 2. 创建测试账户
    let account = worker.dev_create_account().await?;
    
    // 3. 部署合约
    let wasm = std::path::PathBuf::from("res/hello_near.wasm");
    let contract = worker.dev_deploy(&std::fs::read(wasm)?).await?;
    
    // 4. 调用合约方法
    let greeting: String = contract
        .view("get_greeting")
        .args_json(serde_json::json!({}))
        .await?
        .json()?;
    
    println!("Initial greeting: {}", greeting);
    
    // 5. 修改状态
    let outcome = contract
        .call("set_greeting")
        .args_json(serde_json::json!({"message": "Hello Workspaces!"}))
        .transact()
        .await?;
    
    println!("Transaction result: {:?}", outcome);
    
    // 6. 验证修改
    let new_greeting: String = contract
        .view("get_greeting")
        .args_json(serde_json::json!({}))
        .await?
        .json()?;
    
    println!("Updated greeting: {}", new_greeting);
    
    Ok(())
}

注意事项

  1. 需要Tokio运行时支持异步操作
  2. 测试时建议使用沙盒环境,速度快且无需真实代币
  3. 与主网交互时需要配置正确的RPC地址和账户凭据
  4. 合约方法调用时注意参数类型匹配

near-workspaces大大简化了NEAR智能合约的测试流程,是开发NEAR DApp不可或缺的工具。

回到顶部