Rust NEAR协议系统级接口库near-sys的使用,实现与NEAR区块链底层交互的核心功能

以下是关于Rust NEAR协议系统级接口库near-sys的使用和实现与NEAR区块链底层交互核心功能的完整示例:

// 添加依赖到Cargo.toml
// near-sys = "0.2.4"

use near_sys as sys;
use std::ffi::CString;

fn main() {
    // 初始化NEAR环境
    unsafe {
        sys::near_init();
    }

    // 创建账户示例
    let account_id = CString::new("example.testnet").unwrap();
    unsafe {
        let account = sys::near_account_create(account_id.as_ptr());
        if account.is_null() {
            println!("Failed to create account");
            return;
        }
    }

    // 合约部署示例
    let contract_id = CString::new("contract.example.testnet").unwrap();
    let wasm_path = CString::new("./contract.wasm").unwrap();
    unsafe {
        let result = sys::near_deploy_contract(
            contract_id.as_ptr(),
            wasm_path.as_ptr()
        );
        if result != 0 {
            println!("Contract deployment failed with code: {}", result);
        }
    }

    // 合约调用示例
    let method_name = CString::new("update_status").unwrap();
    let args = CString::new(r#"{"message": "Hello NEAR"}"#).unwrap();
    unsafe {
        let result = sys::near_call_contract(
            contract_id.as_ptr(),
            method_name.as_ptr(),
            args.as_ptr(),
            0 // 使用0表示不附加任何代币
        );
        if result != 0 {
            println!("Contract call failed with code: {}", result);
        }
    }

    // 查询合约状态示例
    unsafe {
        let mut output = [0u8; 1024];
        let result = sys::near_view_contract(
            contract_id.as_ptr(),
            method_name.as_ptr(),
            args.as_ptr(),
            output.as_mut_ptr() as *mut i8,
            output.len() as u32
        );
        if result == 0 {
            let output_str = std::ffi::CStr::from_ptr(output.as_ptr() as *const i8)
                .to_str()
                .unwrap();
            println!("Contract state: {}", output_str);
        }
    }
}

这个示例展示了如何使用near-sys库与NEAR区块链进行基本交互:

  1. 首先初始化NEAR环境
  2. 创建新账户
  3. 部署WASM合约
  4. 调用合约方法
  5. 查询合约状态

注意:实际使用时需要处理更多的错误情况和内存管理。near-sys提供了对NEAR协议核心功能的低级访问,适合需要与NEAR区块链底层交互的高级场景。

以下是更完整的示例代码,包含了错误处理和资源清理:

// 添加依赖到Cargo.toml
// near-sys = "0.2.4"

use near_sys as sys;
use std::ffi::{CString, NulError};
use std::ptr;

// 错误处理枚举
#[derive(Debug)]
enum NearError {
    NullPointer,
    Utf8Error(std::str::Utf8Error),
    NulError(NulError),
    OperationFailed(i32),
}

impl From<std::str::Utf8Error> for NearError {
    fn from(err: std::str::Utf8Error) -> Self {
        NearError::Utf8Error(err)
    }
}

impl From<NulError> for NearError {
    fn from(err: NulError) -> Self {
        NearError::NulError(err)
    }
}

fn main() -> Result<(), NearError> {
    // 初始化NEAR环境
    unsafe {
        sys::near_init();
    }

    // 创建账户示例
    let account_id = CString::new("example.testnet")?;
    unsafe {
        let account = sys::near_account_create(account_id.as_ptr());
        if account.is_null() {
            return Err(NearError::NullPointer);
        }
        // 使用完后释放资源
        sys::near_account_free(account);
    }

    // 合约部署示例
    let contract_id = CString::new("contract.example.testnet")?;
    let wasm_path = CString::new("./contract.wasm")?;
    unsafe {
        let result = sys::near_deploy_contract(
            contract_id.as_ptr(),
            wasm_path.as_ptr()
        );
        if result != 0 {
            return Err(NearError::OperationFailed(result));
        }
    }

    // 合约调用示例
    let method_name = CString::new("update_status")?;
    let args = CString::new(r#"{"message": "Hello NEAR"}"#)?;
    unsafe {
        let result = sys::near_call_contract(
            contract_id.as_ptr(),
            method_name.as_ptr(),
            args.as_ptr(),
            0 // 使用0表示不附加任何代币
        );
        if result != 0 {
            return Err(NearError::OperationFailed(result));
        }
    }

    // 查询合约状态示例
    unsafe {
        let mut output = [0u8; 1024];
        let result = sys::near_view_contract(
            contract_id.as_ptr(),
            method_name.as_ptr(),
            args.as_ptr(),
            output.as_mut_ptr() as *mut i8,
            output.len() as u32
        );
        if result == 0 {
            let output_str = std::ffi::CStr::from_ptr(output.as_ptr() as *const i8)
                .to_str()?;
            println!("Contract state: {}", output_str);
        } else {
            return Err(NearError::OperationFailed(result));
        }
    }

    Ok(())
}

这个完整示例添加了:

  1. 完善的错误处理机制
  2. 资源释放逻辑
  3. 更健壮的指针检查
  4. 使用Result类型返回操作结果

实际使用时,您还需要考虑:

  1. 异步操作的处理
  2. 交易收据的验证
  3. gas费用的计算
  4. 账户密钥的管理
  5. 更复杂的内存管理

1 回复

Rust NEAR协议系统级接口库near-sys使用指南

near-sys是Rust语言实现的NEAR区块链协议系统级接口库,提供了与NEAR区块链底层交互的核心功能。

主要功能

  1. 提供NEAR协议底层系统调用的Rust绑定
  2. 实现与NEAR区块链节点的直接交互
  3. 支持合约开发中的低级操作
  4. 提供区块链状态访问接口

基本使用方法

添加依赖

Cargo.toml中添加:

[dependencies]
near-sys = "0.10.0"

基础示例

use near_sys as sys;
use std::ffi::CString;

fn main() {
    // 初始化NEAR环境
    unsafe {
        sys::near_sys_init();
    }
    
    // 创建一个账户ID
    let account_id = CString::new("example.testnet").unwrap();
    
    // 检查账户是否存在
    let exists = unsafe {
        sys::near_sys_account_exists(account_id.as_ptr())
    };
    
    println!("Account exists: {}", exists);
}

核心API使用示例

1. 读取区块链状态

use near_sys as sys;
use std::ffi::CString;

fn get_account_balance(account_id: &str) -> u128 {
    let account_cstr = CString::new(account_id).unwrap();
    unsafe {
        sys::near_sys_account_balance(account_cstr.as_ptr())
    }
}

2. 写入区块链状态

use near_sys as sys;
use std::ffi::CString;

fn transfer_tokens(from: &str, to: &str, amount:极简示例已展示完毕,下面提供一个完整的NEAR合约开发示例,整合了账户检查、余额查询、转账和存储操作:

```rust
use near_sys as sys;
use std::ffi::CString;

// 安全包装器示例
mod safe_wrapper {
    use super::*;
    
    pub fn account_exists(account_id: &str) -> Result<bool, String> {
        let account_cstr = CString::new(account_id)
            .map_err(|e| format!("Invalid account ID: {}", e))?;
            
        unsafe {
            Ok(sys::near_sys_account_exists(account_cstr.as_ptr()))
        }
    }
    
    pub fn get_balance(account_id: &str) -> Result<u128, String> {
        let account_cstr = CString::new(account_id)
            .map_err(|e| format!("Invalid account ID: {}", e))?;
            
        unsafe {
            Ok(sys::near_sys_account_balance(account_cstr.as_ptr()))
        }
    }
}

// 完整的合约示例
#[no_mangle]
pub extern "C" fn contract_entry() {
    // 1. 获取调用者
    let caller = unsafe {
        let mut buffer = [0u8; 64];
        let len = sys::near_sys_signer_account_id(buffer.as_mut_ptr(), buffer.len());
        String::from_utf8_lossy(&buffer[..len as usize]).into_owned()
    };
    
    println!("Contract called by: {}", caller);
    
    // 2. 检查账户是否存在
    match safe_wrapper::account_exists(&caller) {
        Ok(exists) => println!("Caller exists: {}", exists),
        Err(e) => println!("Error checking account: {}", e),
    }
    
    // 3. 获取账户余额
    match safe_wrapper::get_balance(&caller) {
        Ok(balance) => println!("Caller balance: {}", balance),
        Err(e) => println!("Error getting balance: {}", e),
    }
    
    // 4. 存储操作示例
    let key = CString::new("last_caller").unwrap();
    let value = CString::new(&caller).unwrap();
    
    unsafe {
        sys::near_sys_storage_write(
            key.as_ptr(),
            key.as_bytes().len() as u64,
            value.as_ptr(),
            value.as_bytes().len() as u64
        );
    }
    
    // 5. 读取存储值
    let mut buffer = [0u8; 64];
    let len = unsafe {
        sys::near_sys_storage_read(
            key.as_ptr(),
            key.as_bytes().len() as u64,
            buffer.as_mut_ptr(),
            buffer.len() as u64
        )
    };
    
    if len > 0 {
        let stored_value = String::from_utf8_lossy(&buffer[..len as usize]);
        println!("Last caller was: {}", stored_value);
    }
}

fn main() {
    // 初始化NEAR环境
    unsafe { sys::near_sys_init(); }
    
    // 模拟合约调用
    contract_entry();
}

注意事项

  1. 实际部署时应移除main函数,仅保留合约入口
  2. 所有NEAR系统调用都应进行错误处理
  3. 存储操作需要注意数据大小限制
  4. 跨合约调用需要考虑gas消耗

这个完整示例展示了如何:

  1. 创建安全的API包装器
  2. 处理各种NEAR系统调用
  3. 实现基本的合约逻辑
  4. 进行安全的存储操作
回到顶部