#account-id #near #owner #events #request-id #developing #smart-contracts

near-contract-tools

为NEAR协议开发智能合约的有用函数和宏

15个版本 (6个重大更新)

0.7.2 2022年12月16日
0.7.1 2022年11月19日
0.6.1 2022年9月22日
0.4.0 2022年7月11日

#1978 in 魔法豆

Download history 11/week @ 2024-03-10 70/week @ 2024-03-31 1/week @ 2024-04-07

每月下载量:158

GPL-3.0 许可证

115KB
2K SLoC

此包将重命名为 near-sdk-contract-tools

near-contract-tools

为NEAR协议开发智能合约的有用函数和宏。

此包收集了NEAR智能合约开发中的常见工具和模式

  • 存储费用管理
  • 所有者模式(提供派生宏)
  • 基于角色的访问控制
  • 暂停(提供派生宏)
  • NEP-297事件 提供派生宏
  • NEP-141(和 NEP-148)非同质化代币提供派生宏

不要与 near-contract-standards 混淆,它包含标准NEP的官方实现。此crate旨在与 near-contract-standards 相辅相成。

警告: 这仍然是一款早期软件,版本之间可能会有破坏性更改。我会尽力保持文档和变更日志的更新。如果您发现任何问题,请毫不犹豫地创建一个问题。

优点

  • 需要更少的代码行数
    • 在没有near-contract-tools的情况下,实现非同质化代币事件(铸造、转移和销毁)需要约100行代码。使用near-contract-tools,您可以在约40行代码中实现它们。
  • 更易于阅读
  • 遵循一致的模式
    • 每次您使用事件宏时,它都会以相同的方式实现事件。请参考此链接。如果没有它,您需要确保emitemit_many等所有功能(以及它们以相同的方式工作)。
  • 更全面
    • 接近合约标准也没有实现特性,这是near-contract-tools提供的另一个改进。

您可以将这个常用工具和模式的集合(主要以derive宏的形式)视为NEAR版的OpenZeppelin。

入门指南

rustup target add wasm32-unknown-unknown
cargo init
cargo add near-contract-tools
cargo add near-sdk
# https://raen.dev/guide/intro/getting-set-up.html
cargo install raen
# Implement a contract. See `workspaces-tests/src/bin/simple_multisig.rs` for example until we offer better examples here. Then:
near dev-deploy $(raen build --release -q)

示例用法

安装NEAR CLI后,调用如下:

near call dev-1662491554455-22903649156976 new --account-id example-acct-alice.testnet
near call dev-1662491554455-22903649156976 obtain_multisig_permission --account-id example-acct-alice.testnet
near call dev-1662491554455-22903649156976 request '{"action": "hello"}' --account-id example-acct-alice.testnet
near call dev-1662491554455-22903649156976 approve '{"request_id": 0}' --account-id example-acct-alice.testnet
near call dev-1662491554455-22903649156976 obtain_multisig_permission --account-id example-acct-bob.testnet
near call dev-1662491554455-22903649156976 approve '{"request_id": 0}' --account-id example-acct-bob.testnet
near call dev-1662491554455-22903649156976 execute '{"request_id": 0}' --account-id example-acct-bob.testnet

构建和测试

如果尚未安装,请安装cargo-make

cargo install cargo-make

运行测试

cargo test
cd workspaces-tests
cargo make test

示例

另请参阅:完整的集成测试

所有者

use near_sdk::{near_bindgen, AccountId};
use near_contract_tools::{owner::Owner, Owner};

#[derive(Owner)]
#[near_bindgen]
struct Contract {
    // ...
}

#[near_bindgen]
impl Contract {
    #[init]
    pub fn new(owner_id: AccountId) -> Self {
        let mut contract = Self {
            // ...
        };

        Owner::init(&mut contract, &owner_id);

        contract
    }

    pub fn owner_only(&self) {
        Self::require_owner();

        // ...
    }
}

Owner derive宏向区块链公开以下方法

fn own_get_owner(&self) -> Option<AccountId>;
fn own_get_proposed_owner(&self) -> Option<AccountId>;
fn own_renounce_owner(&mut self);
fn own_propose_owner(&mut self, account_id: Option<AccountId>);
fn own_accept_owner(&mut self);

事件

可以将#[event]宏应用于结构体或枚举。

use near_contract_tools::{event, standard::nep297::Event};

#[event(standard = "nft", version = "1.0.0")]
pub struct MintEvent {
    pub owner_id: String,
    pub token_id: String,
}

let e = MintEvent {
    owner_id: "account".to_string(),
    token_id: "token_1".to_string(),
};

// Emits the event to the blockchain
e.emit();

可转让代币

要创建一个兼容NEP-141和NEP-148标准的合约,该合约会发出符合标准的事件(NEP-141、NEP-297)。

use near_contract_tools::FungibleToken;
use near_sdk::near_bindgen;

#[derive(FungibleToken)]
#[fungible_token(
    name = "My Fungible Token",
    symbol = "MYFT",
    decimals = 18,
    no_hooks
)]
#[near_bindgen]
struct FungibleToken {
    // ...
}

每个标准的独立宏也存在。

宏组合

有人可能希望在单个合约中组合多个宏的功能。所有宏都编写为可以独立工作,因此这应该不会出现问题。然而,有时可能希望宏以组合的方式一起工作。例如,为了使可转让代币可暂停,请使用可转让代币钩子要求在执行代币转让之前取消合约的暂停。

use near_contract_tools::{
    pause::Pause,
    standard::nep141::{Nep141Hook, Nep141Transfer},
    FungibleToken, Pause,
};
use near_sdk::near_bindgen;

#[derive(FungibleToken, Pause)]
#[fungible_token(name = "Pausable Fungible Token", symbol = "PFT", decimals = 18)]
#[near_bindgen]
struct Contract {}

impl Nep141Hook for Contract {
    fn before_transfer(&mut self, _transfer: &Nep141Transfer) {
        Contract::require_unpaused();
    }
}

注意:可以使用#[nep141(no_hooks)]#[fungible_token(no_hooks)]禁用钩子。

自定义Crate

如果您是库开发者,修改了near-contract-tools宏使用的某个crate(如serdenear-sdk),或者以不同名称使用crate,您可以在宏中指定crate名称,如下所示

#[event(
    // ...
    crate = "near_contract_tools",
    macros = "near_contract_tools_macros",
    serde = "serde",
)]
// ...

#[derive(Owner)]
#[owner(
    // ...
    near_sdk = "near_sdk",
)]

其他技巧

内部方法与外部方法

内部方法无法通过区块链调用。外部方法是公共的,可以被其他合约调用。

提案模式

提出所有权(而不是直接转让)通常是良好的实践,因为它可以防止您意外将所有权转让给无法访问的帐户(这将杀死合约)。

展开

cargo expand将生成一个包含所有生成的宏的巨大Rust文件

cargo install cargo-expand
cargo expand > expanded.rs

所有者特性

为了实现所有者特性,您只需实现一个函数:“root”。

请参阅src/slot.rs。它们是存储键的非常薄的包装器。它提供了一种命名空间/键组合功能,还提供了“读取”、“写入”、“存在”、“删除”等功能。

关于NEAR功能的提醒

  • assert_one_yocto()

    在 near_sdk 中,assert_one_yocto() 是一个需要完整访问密钥(通过要求存入一个 yoctonear,NEAR 的最小单位)的功能。

    这为什么重要呢?

    如果用户将他们的 NEAR 账户连接到 dapp 并授予 dapp 代表他们调用此智能合约上函数的权限,那么 dapp 仍然 无法代表他们调用 此函数(即任何调用 assert_one_yocto() 的函数)。

    唯一添加此要求(强制交易由完整访问密钥签名)的方式是要求进行一些非零转账。

贡献

入门指南

首先,运行 git config core.hooksPath hooks/ 安装此目录的钩子(不会影响其他项目的 git 钩子工作)。

作者

依赖关系

~5.5–7.5MB
~144K SLoC