near-sdk
Rust library for writing NEAR smart contracts.
Previously known as near-bindgen
.
Wrap a struct in #[near_bindgen]
and it generates a smart contract compatible with the NEAR blockchain:
```rust
use nearsdk::{nearbindgen, env};
pub struct StatusMessage {
records: HashMap
impl StatusMessage { pub fn setstatus(&mut self, message: String) { let accountid = env::signeraccountid(); self.records.insert(account_id, message); }
pub fn get_status(&self, account_id: String) -> Option<String> {
self.records.get(&account_id).cloned()
}
} ```
Unit-testable. Writing unit tests is easy with near-sdk
:
```rust
fn setgetmessage() { let context = getcontext(vec![]); testingenv!(context); let mut contract = StatusMessage::default(); contract.setstatus("hello".tostring()); asserteq!("hello".tostring(), contract.getstatus("bobnear".to_string()).unwrap()); } ```
Run unit test the usual way:
bash
cargo test --package status-message
Asynchronous cross-contract calls. Asynchronous cross-contract calls allow parallel execution
of multiple contracts in parallel with subsequent aggregation on another contract.
env
exposes the following methods:
promise_create
-- schedules an execution of a function on some contract;promise_then
-- attaches the callback back to the current contract once the function is executed;promise_and
-- combinator, allows waiting on several promises simultaneously, before executing the callback;promise_return
-- treats the result of execution of the promise as the result of the current function.Follow examples/cross-contract-high-level to see various usages of cross contract calls, including system-level actions done from inside the contract like balance transfer (examples of other system-level actions are: account creation, access key creation/deletion, contract deployment, etc).
Initialization methods. We can define an initialization method that can be used to initialize the state of the contract.
```rust
impl StatusMessage {
#[init]
pub fn new(user: String, status: String) -> Self {
let mut res = Self::default();
res.records.insert(user, status);
res
}
}
Even if you have initialization method your smart contract is still expected to derive `Default` trait. If you don't
want to disable default initialization then you can prohibit it like this:
rust
impl Default for StatusMessage {
fn default() -> Self {
panic!("Contract should be initialized before the usage.")
}
}
```
Payable methods. We can allow methods to accept token transfer together with the function call. This is done so that contracts can define a fee in tokens that needs to be payed when they are used. By the default the methods are not payable and they will panic if someone will attempt to transfer tokens to them during the invocation. This is done for safety reason, in case someone accidentally transfers tokens during the function call.
To declare a payable method simply use #[payable]
decorator:
```rust
pub fn my_method(&mut self) { ... } ```
To develop Rust contracts you would need to:
* Install Rustup:
bash
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
* Add wasm target to your toolchain:
bash
rustup target add wasm32-unknown-unknown
You can follow the examples/status-message crate that shows a simple Rust contract.
The general workflow is the following:
1. Create a crate and configure the Cargo.toml
similarly to how it is configured in examples/status-message/Cargo.toml;
2. Crate needs to have one pub
struct that will represent the smart contract itself:
* The struct needs to implement Default
trait which
NEAR will use to create the initial state of the contract upon its first usage;
* The struct also needs to implement BorshSerialize
and BorshDeserialize
traits which NEAR will use to save/load contract's internal state;
Here is an example of a smart contract struct: ```rust use nearsdk::{nearbindgen, env};
#[near_bindgen]
#[derive(Default, BorshSerialize, BorshDeserialize)]
pub struct MyContract {
data: HashMap
Define methods that NEAR will expose as smart contract methods:
&self
, &mut self
, or self
;impl
section with #[near_bindgen]
macro. That is where all the M.A.G.I.C. (Macros-Auto-Generated Injected Code) is happeningenv::*
;Here is an example of smart contract methods: ```rust
impl MyContract {
pub fn insertdata(&mut self, key: u64, value: u64) -> Option
We can build the contract using rustc:
bash
RUSTFLAGS='-C link-arg=-s' cargo build --target wasm32-unknown-unknown --release
This repository is distributed under the terms of both the MIT license and the Apache License (Version 2.0). See LICENSE and LICENSE-APACHE for details.