## Example
Wrap a struct in `#[near_bindgen]` and it generates a smart contract compatible with the NEAR blockchain:
```rust
#[near_bindgen]
#[derive(Default, BorshDeserialize, BorshSerialize)]
pub struct StatusMessage {
records: HashMap,
}
#[near_bindgen]
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: String) -> Option {
self.records.get(&account_id).cloned()
}
}
```
## Features
* **Unit-testable.** Writing unit tests is easy with `near-bindgen`:
```rust
#[test]
fn set_get_message() {
let context = get_context(vec![]);
testing_env!(context);
let mut contract = StatusMessage::default();
contract.set_status("hello".to_string());
assert_eq!("hello".to_string(), contract.get_status("bob_near".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](https://github.com/nearprotocol/near-bindgen/tree/master/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
#[near_bindgen]
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.")
}
}
```
## Pre-requisites
To develop Rust contracts you would need to:
* Install [Rustup](https://rustup.rs/):
```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
```
## Writing Rust Contract
You can follow the [examples/status-message](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](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
}
```
3. Define methods that NEAR will expose as smart contract methods:
* You are free to define any methods for the struct but only public methods will be exposed as smart contract methods;
* Methods need to use either `&self`, `&mut self`, or `self`;
* Decorate the `impl` section with `#[near_bindgen]` macro. That is where all the M.A.G.I.C. (Macros-Auto-Generated Injected Code) is happening
* If you need to use blockchain interface, e.g. to get the current account id then you can access it with `env::*`;
Here is an example of smart contract methods:
```rust
#[near_bindgen]
impl MyContract {
pub fn insert_data(&mut self, key: u64, value: u64) -> Option {
self.data.insert(key)
}
pub fn get_data(&self, key: u64) -> Option {
self.data.get(&key).cloned()
}
}
```
## Building Rust Contract
We can build the contract using rustc:
```bash
RUSTFLAGS='-C link-arg=-s' cargo build --target wasm32-unknown-unknown --release
```