Rust数据校验库near-schema-checker-lib的使用,高效实现Near协议数据结构与模式验证

Rust数据校验库near-schema-checker-lib的使用,高效实现Near协议数据结构与模式验证

near-schema-checker-lib是一个用于NEAR协议数据结构和模式验证的Rust库,版本0.30.3,采用MIT或Apache-2.0双重许可。

安装方法

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

cargo add near-schema-checker-lib

或者在Cargo.toml中添加:

near-schema-checker-lib = "0.30.3"

示例代码

以下是使用near-schema-checker-lib进行NEAR协议数据结构验证的完整示例:

use near_schema_checker_lib::{validate_schema, SchemaError};
use serde_json::{json, Value};

fn main() -> Result<(), SchemaError> {
    // 定义NEAR协议数据的JSON Schema
    let schema = json!({
        "type": "object",
        "properties": {
            "account_id": {
                "type": "string",
                "pattern": "^[a-z0-9._-]+$"
            },
            "amount": {
                "type": "string",
                "pattern": "^[0-9]+$"
            },
            "action": {
                "type": "string",
                "enum": ["transfer", "stake", "create_account"]
            }
        },
        "required": ["account_id", "amount", "action"]
    });

    // 待验证的NEAR协议交易数据
    let transaction_data = json!({
        "account_id": "alice.near",
        "amount": "1000000000000000000000000",
        "action": "transfer"
    });

    // 执行验证
    validate_schema(&schema, &transaction_data)?;

    println!("Transaction data is valid!");
    Ok(())
}

特性

  1. 高效验证NEAR协议特定的数据结构
  2. 支持JSON Schema验证标准
  3. 与NEAR核心组件深度集成
  4. 提供详细的错误报告机制

这个库主要由nearprotocol-ci团队维护,是NEAR协议生态系统的核心组件之一。

完整示例代码

以下是基于提供内容的完整示例,展示了更复杂的NEAR协议数据结构验证场景:

use near_schema_checker_lib::{validate_schema, SchemaError};
use serde_json::{json, Value};

fn main() -> Result<(), SchemaError> {
    // 定义更复杂的NEAR协议JSON Schema
    let schema = json!({
        "$schema": "http://json-schema.org/draft-07/schema#",
        "title": "NEAR Protocol Transaction",
        "description": "Schema for validating NEAR transactions",
        "type": "object",
        "properties": {
            "sender": {
                "type": "string",
                "pattern": "^[a-z0-9._-]+$",
                "description": "发送者账户ID"
            },
            "receiver": {
                "type": "string",
                "pattern": "^[a-z0-9._-]+$",
                "description": "接收者账户ID"
            },
            "amount": {
                "type": "string",
                "pattern": "^[0-9]+$",
                "description": "转账金额(以yoctoNEAR为单位)"
            },
            "action": {
                "type": "string",
                "enum": ["transfer", "stake", "create_account", "delete_account", "add_key"],
                "description": "交易类型"
            },
            "gas": {
                "type": "string",
                "pattern": "^[0-9]+$",
                "description": "gas费用"
            },
            "public_key": {
                "type": "string",
                "pattern": "^ed25519:[A-Za-z0-9+/=]+$",
                "description": "公钥(可选)"
            }
        },
        "required": ["sender", "receiver", "amount", "action", "gas"],
        "additionalProperties": false
    });

    // 待验证的NEAR协议交易数据
    let transaction_data = json!({
        "sender": "alice.near",
        "receiver": "bob.near",
        "amount": "1000000000000000000000000", // 1 NEAR (以yoctoNEAR为单位)
        "action": "transfer",
        "gas": "100000000000000",
        "public_key": "ed25519:7P3k4Q4X8Jk6tY2RvT2v9JkXhY7sVv1W2z3X4y5Z6A7B8C9D0E"
    });

    // 执行验证
    match validate_schema(&schema, &transaction_data) {
        Ok(_) => println!("交易数据验证通过!"),
        Err(e) => eprintln!("验证失败: {:?}", e),
    }
    
    Ok(())
}

这个完整示例展示了:

  1. 更复杂的JSON Schema定义,包含更多NEAR协议特有的字段
  2. 添加了模式描述信息
  3. 包含了可选字段的验证
  4. 更完善的错误处理
  5. 展示了NEAR协议中常见的字段格式验证

在使用时,您可以根据实际需求调整schema和交易数据结构,以适应不同的NEAR协议验证场景。


1 回复

Rust数据校验库near-schema-checker-lib的使用:高效实现Near协议数据结构与模式验证

完整示例demo

以下是一个完整的NEAR合约示例,展示如何使用near-schema-checker-lib验证合约方法参数:

use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize};
use near_sdk::{env, near_bindgen, serde_json};
use near_schema_checker_lib::{Schema, SchemaType, CustomValidator};
use lazy_static::lazy_static;

// 定义自定义验证器检查NEAR账户ID格式
fn validate_near_account(value: &serde_json::Value) -> Result<(), String> {
    if let Some(s) = value.as_str() {
        if s.ends_with(".near") {
            Ok(())
        } else {
            Err("账户ID必须以.near结尾".to_string())
        }
    } else {
        Err("账户ID必须是字符串".to_string())
    }
}

// 预编译常用Schema实例
lazy_static! {
    static ref TRANSFER_SCHEMA: Schema = Schema::new()
        .field("receiver_id", SchemaType::Custom(Box::new(CustomValidator::new(validate_near_account))))
        .field("amount", SchemaType::U128)
        .field("memo", SchemaType::Optional(Box::new(SchemaType::String)));
    
    static ref NFT_METADATA_SCHEMA: Schema = Schema::new()
        .field("title", SchemaType::String)
        .field("description", SchemaType::Optional(Box::new(SchemaType::String)))
        .field("media", SchemaType::String)
        .field("media_hash", SchemaType::Optional(Box::new(SchemaType::String)));
}

#[near_bindgen]
#[derive(BorshDeserialize, BorshSerialize)]
pub struct Contract {
    pub owner_id: String,
}

#[near_bindgen]
impl Contract {
    #[init]
    pub fn new(owner_id: String) -> Self {
        // 验证owner_id格式
        let owner_schema = Schema::new()
            .field("owner_id", SchemaType::Custom(Box::new(CustomValidator::new(validate_near_account))));
        
        owner_schema.validate(&serde_json::json!({"owner_id": owner_id.clone()}))
            .expect("无效的owner_id格式");

        Self { owner_id }
    }

    // 转账方法
    pub fn transfer(&mut self, params: serde_json::Value) {
        // 验证转账参数
        TRANSFER_SCHEMA.validate(&params)
            .unwrap_or_else(|e| env::panic_str(&format!("无效的转账参数: {}", e)));
        
        // 这里添加实际的转账逻辑...
        env::log_str("转账操作已验证通过");
    }

    // 创建NFT方法
    pub fn mint_nft(&mut self, metadata: serde_json::Value) {
        // 验证NFT元数据
        NFT_METADATA_SCHEMA.validate(&metadata)
            .unwrap_or_else(|e| env::panic_str(&format!("无效的NFT元数据: {}", e)));
        
        // 这里添加实际的NFT铸造逻辑...
        env::log_str("NFT元数据已验证通过");
    }
}

// 测试模块
#[cfg(test)]
mod tests {
    use super::*;
    use near_sdk::test_utils::{get_logs, VMContextBuilder};
    use near_sdk::{testing_env, AccountId, VMContext};

    fn get_context() -> VMContext {
        VMContextBuilder::new()
            .signer_account_id(AccountId::new_unchecked("alice.near".to_string()))
            .build()
    }

    #[test]
    fn test_transfer() {
        let context = get_context();
        testing_env!(context);
        
        let mut contract = Contract::new("owner.near".to_string());
        
        // 测试有效转账
        let valid_transfer = serde_json::json!({
            "receiver_id": "bob.near",
            "amount": "1000000000000000000000000"
        });
        contract.transfer(valid_transfer);
        assert_eq!(get_logs(), vec!["转账操作已验证通过"]);
        
        // 测试无效转账 - 会panic
        let invalid_transfer = serde_json::json!({
            "receiver_id": "invalid_account",
            "amount": "100"
        });
        let result = std::panic::catch_unwind(|| {
            contract.transfer(invalid_transfer);
        });
        assert!(result.is_err());
    }

    #[test]
    fn test_mint_nft() {
        let context = get_context();
        testing_env!(context);
        
        let mut contract = Contract::new("owner.near".to_string());
        
        // 测试有效NFT元数据
        let valid_metadata = serde_json::json!({
            "title": "My NFT",
            "media": "https://example.com/nft.jpg"
        });
        contract.mint_nft(valid_metadata);
        assert_eq!(get_logs(), vec!["NFT元数据已验证通过"]);
    }
}

这个完整示例展示了:

  1. 如何使用自定义验证器验证NEAR账户ID格式
  2. 如何使用预编译Schema实例提高性能
  3. 如何在合约方法中验证输入参数
  4. 如何编写测试用例验证数据校验功能
  5. 如何处理验证失败的情况

您可以根据实际需求修改Schema定义和验证逻辑,以适应不同的NEAR合约开发场景。

回到顶部