21 个版本 (3 个重大更改)
3.1.0 | 2021 年 4 月 7 日 |
---|---|
3.0.1 | 2021 年 3 月 25 日 |
3.0.0-pre-release | 2021 年 2 月 10 日 |
2.0.1 | 2021 年 1 月 14 日 |
0.7.0 | 2020 年 3 月 27 日 |
#539 in 魔法豆
每月下载量 1,440
88KB
2K SLoC
发行说明
发行说明和未发布更改可以在 变更日志 中找到
示例
使用 #[near]
包装一个结构体,它将生成与 NEAR 区块链兼容的智能合约
use near_sdk::{near, env};
#[near(contract_state)]
#[derive(Default)]
pub struct StatusMessage {
records: HashMap<AccountId, String>,
}
#[near]
impl StatusMessage {
pub fn set_status(&mut self, message: String) {
let account_id = env::signer_account_id();
self.records.insert(account_id, message);
}
pub fn get_status(&self, account_id: AccountId) -> Option<String> {
self.records.get(&account_id).cloned()
}
}
特性
可进行单元测试
使用 near-sdk
编写单元测试非常容易
#[test]
fn set_get_message() {
let mut contract = StatusMessage::default();
contract.set_status("hello".to_string());
assert_eq!("hello".to_string(), contract.get_status("bob_near".to_string()).unwrap());
}
以常规方式运行单元测试
cargo test --package status-message
异步跨合约调用
异步跨合约调用允许并行执行多个合约,并在另一个合约上进行后续聚合。 env
提供以下方法
promise_create
-- 在某个合约上安排函数执行;promise_then
-- 一旦函数执行,将回调附加到当前合约;promise_and
-- 组合器,允许在执行回调之前同时等待多个承诺;promise_return
-- 将承诺的执行结果视为当前函数的结果。
请参考 examples/cross-contract-high-level 以查看跨合约调用的各种用法,包括在合约内部执行的 系统级操作,例如余额转账(其他系统级操作的示例:账户创建、访问密钥创建/删除、合约部署等)。
初始化方法
我们可以定义一个初始化方法,用于初始化合约的状态。 #[init]
验证合约尚未初始化(合约状态不存在),否则会引发恐慌。
#[near]
impl StatusMessage {
#[init]
pub fn new(user: String, status: String) -> Self {
let mut res = Self::default();
res.records.insert(user, status);
res
}
}
即使你有初始化方法,你的智能合约仍然需要推导 Default
特性。如果你不想禁用默认初始化,则可以像这样禁止它
impl Default for StatusMessage {
fn default() -> Self {
near_sdk::env::panic_str("Contract should be initialized before the usage.")
}
}
您还可以使用 near_sdk::PanicOnDefault
辅助宏来禁止 Default
特性初始化。例如。
#[near(contract_state)]
#[derive(PanicOnDefault)]
pub struct StatusMessage {
records: HashMap<String, String>,
}
可支付方法
我们可以允许方法在函数调用时接受代币转账。这样,合约可以定义在使用时需要支付的代币费用。默认情况下,方法不是可支付的,如果在调用期间有人尝试向它们转账代币,它们将引发恐慌。这是出于安全考虑,以防有人意外在函数调用期间转账代币。
要声明一个可支付方法,只需使用 #[payable]
装饰器
#[payable]
pub fn my_method(&mut self) {
...
}
私有方法
通常,当一个合约需要为远程跨合约调用提供一个回调时,此回调方法应由合约本身调用。这是为了避免其他人调用它并破坏状态。常见的模式是使用一个断言来验证直接调用者(前驱账户 ID)与合约账户(当前账户 ID)匹配。宏 #[private]
通过将其简化为单行宏并提高可读性来简化此操作。
要声明一个私有方法,请使用 #[private]
装饰器
#[private]
pub fn my_method(&mut self) {
...
}
/// Which is equivalent to
pub fn my_method(&mut self ) {
if near_sdk::env::current_account_id() != near_sdk::env::predecessor_account_id() {
near_sdk::env::panic_str("Method my_method is private");
}
...
}
现在,只有合约本身的账户可以调用此方法,无论是直接还是通过承诺。
先决条件
要开发 Rust 合约,您需要
- 安装 Rustup
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
- 将 wasm 目标添加到您的工具链中
rustup target add wasm32-unknown-unknown
编写 Rust 合约
您可以参考 examples/status-message 示例,该示例展示了简单的 Rust 合约。
一般工作流程如下
-
创建一个crate并配置
Cargo.toml
,使其类似于 示例/status-message/Cargo.toml 中的配置; -
Crate需要一个代表智能合约本身的
pub
结构体- 该结构体需要实现
Default
特性,NEAR 将使用它来创建合约首次使用时的初始状态;
以下是一个智能合约结构体的示例
use near_sdk::{near, env}; #[near(contract_state)] #[derive(Default)] pub struct MyContract { data: HashMap<u64, u64> }
- 该结构体需要实现
-
定义NEAR将公开作为智能合约方法的函数
- 您可以自由地为结构体定义任何方法,但只有公共方法将被公开为智能合约方法;
- 方法需要使用
&self
、&mut self
或self
; - 使用
#[near]
宏装饰impl
部分。所有M.A.G.I.C.(Macros-Auto-Generated Injected Code)都发生在这里; - 如果您需要使用区块链接口,例如获取当前账户ID,则可以通过
env::*
访问它;
以下是一个智能合约方法的示例
#[near] impl MyContract { pub fn insert_data(&mut self, key: u64, value: u64) -> Option<u64> { self.data.insert(key) } pub fn get_data(&self, key: u64) -> Option<u64> { self.data.get(&key).cloned() } }
构建Rust合约
cargo-near
cargo-near
是构建和部署Rust合约的一种简单且推荐的方法。
安装
通过shell脚本安装预构建的二进制文件(Linux,macOS)
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/near/cargo-near/releases/latest/download/cargo-near-installer.sh | sh
通过powershell脚本安装预构建的二进制文件(Windows)
irm https://github.com/near/cargo-near/releases/latest/download/cargo-near-installer.ps1 | iex
将预构建的二进制文件安装到您的Node.js应用程序中
npm install cargo-near
从源代码编译和安装(Cargo)
cargo install cargo-near
或者,从git仓库安装最新版本
$ git clone https://github.com/near/cargo-near
$ cargo install --path cargo-near
使用方法
查看 cargo near --help
获取所有可用命令的完整列表,或运行 cargo near
进入交互模式。每个单独的命令也都有带 --help
标志的帮助,例如 cargo near build --help
。
cargo near
开始交互模式,允许探索所有可用命令。
cargo near build
构建NEAR智能合约及其 ABI(在包含合约Cargo.toml的目录中)。
cargo near create-dev-account
引导您在 测试网 上创建新的NEAR账户。
cargo near deploy
构建智能合约(相当于 cargo near build
)并引导您将其部署到区块链。
使用 cargo build
RUSTFLAGS='-C link-arg=-s' cargo build --target wasm32-unknown-unknown --release
使用可重现构建进行构建
由于WebAssembly编译器将大量调试信息包含到二进制文件中,结果二进制文件在不同机器上可能不同。为了能够以可重现的方式编译二进制文件,我们添加了一个Dockerfile,允许编译二进制文件。
NEAR合约标准
near-contract-standards
包 提供了 NEAR 合同标准的接口和实现
版本控制
语义版本控制
此包遵循 Cargo 的 semver 指南。
将尽量避免对状态造成破坏性的变更(任何数据类型的底层序列化格式)。如果发生此类变更,它将伴随一个主版本号,并伴随编译器错误。如果您遇到一个没有错误的情况,请 提出一个问题!
最低支持的 Rust 版本
当前最低支持的 Rust 版本是 1.76
。如果没有安全补丁发布需要升级 Rust 工具链,则不保证会保持这一版本。
贡献
如果您有兴趣贡献,请参阅 贡献指南。
依赖
约 2MB
约 45K SLoC