near-bindgen
Rust library for writing NEAR smart contracts.
Wrap a struct in #[near_bindgen]
and it generates a smart contract compatible with the NEAR blockchain:
```rust
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-bindgen
:
```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.")
}
}
```
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
#[near_bindgen]
#[derive(Default, BorshSerialize, BorshDeserialize)]
pub struct MyContract {
data: HashMap<u64, u64>
}
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