Smart contracts
I found it quite useful to explore the partially interactive Anatomy of a Contract
Introduction Official Near Introduction
Install dependencies
# Install Rust: https://www.rust-lang.org/tools/install
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# Contracts will be compiled to wasm, so we need to add the wasm target
rustup target add wasm32-unknown-unknown
# Install the NEAR CLI to deploy and interact with the contract
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/near/near-cli-rs/releases/latest/download/near-cli-rs-installer.sh | sh
# Install cargo near to help building the contract
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/near/cargo-near/releases/latest/download/cargo-near-installer.sh | sh
Create a smart contract default skeleton:
cargo near new hello-near
After ensuring you have an account you may build the smart contract:
cargo near build
Your wasm will be generated which will them be deployable for example to the test-net:
near contract deploy <created-account> use-file ./target/near/hello_near.wasm without-init-call network-config testnet sign-with-keychain send
Sample output:
near contract deploy vfp.testnet use-file ./target/near/hello_near.wasm without-init-call network-config testnet sign-with-keychain send
Unsigned transaction:
signer_id: vfp.testnet
receiver_id: vfp.testnet
actions:
-- deploy contract 3v7ievz4W6UKBwWubLvyJbSmsSEHnrnXJhRPqJNBQNaK
▹▸▹▹▹ Signing the transaction with a key saved in the secure keychain ...
Your transaction was signed successfully.
Public key: ed25519:2nh8uWoxsHDj9hzUKfkabtL7YDSTBNPSTDPsaz8ELQoX
Signature: ed25519:48m8ZqdQ3xjFkAogqQoameH6zgVC64kcKkh56PjidBe1B2AW6UUF8cND3QkvZu1SXqE18KzPYyYYxczih5ZjXZdD
▹▹▸▹▹ Sending transaction ...
--- Logs ---------------------------
Logs [vfp.testnet]: No logs
--- Result -------------------------
Empty result
------------------------------------
Contract code has been successfully deployed.
Gas burned: 7.4 Tgas
Transaction fee: 0.0007339617339116 NEAR
Transaction ID: C8anQCbcTMwsHyneBQhmTnrLeR4EcNuqkXt8YaDo9nGP
To see the transaction in the transaction explorer, please open this url in your browser:
https://explorer.testnet.near.org/transactions/C8anQCbcTMwsHyneBQhmTnrLeR4EcNuqkXt8YaDo9nGP
Here is your console command if you need to script it or re-run:
near contract deploy vfp.testnet use-file ./target/near/hello_near.wasm without-init-call network-config testnet sign-with-keychain send
Interacting with smart contracts
From the CLI
Querying the states:
near view <created-account> <function-name>
Updating status:
near call <created-account> set_greeting '{"greeting": "hola"}' -accountId <created-account>
// Instantiate a contract object let contract = Contract::new(account_id, contract_id, signer); // Call a method on the contract contract.call_method("method_name", json!({ "param": "value" })); // Get contract state let state: ContractState = contract.view_method("get_state", json!({}));
Handling tokens
// Transfer tokens from one account to another let sender = near.get_account("sender_account"); let recipient = near.get_account("recipient_account"); sender.transfer(&recipient, 100); // Check token balance let balance = recipient.get_balance();
Storage
In the context of smart contracts it is always a good idea to keep the storage requirements low. In that case you are invited to use the Native collections provided by the programming language, these will be serialized into a single value and stored together. If you do not have other alternative than storing big amount of data, then you better take a look at the SDK Collections provided by the NEAR SDk.
There is a very useful table in the Near documentation with the complexity for the typical operations of each of the provided structures. https://docs.near.org/build/smart-contracts/anatomy/collections#complexity
Vector.
Dynamic arrays
#![allow(unused)] fn main() { // Declare a vector of u64 elements let mut my_vector: Vec<u64> = Vec::new(); // Add elements to the vector my_vector.push(10); my_vector.push(20); my_vector.push(30); // Access elements in the vector let second_element = my_vector[1]; }
LookupSet
An unordered collection of unique elements. Efficient membership checks
#![allow(unused)] fn main() { // Declare a LookupSet of string elements let mut my_lookupset: LookupSet<String> = LookupSet::new(); // Add elements to the LookupSet my_lookupset.insert("apple".to_string()); my_lookupset.insert("banana".to_string()); // Check membership let contains_apple = my_lookupset.contains("apple".to_string()); }
UnorderedMap
A key-value data structure that does not guarantee any specific order of elements.
#![allow(unused)] fn main() { // Declare an UnorderedMap with u32 keys and string values let mut my_unorderedmap: UnorderedMap<u32, String> = UnorderedMap::new(); // Add key-value pairs to the UnorderedMap my_unorderedmap.insert(1, "value1".to_string()); my_unorderedmap.insert(2, "value2".to_string()); // Iterate over the key-value pairs for (key, value) in my_unorderedmap.iter() { // Process each key-value pair } ## UnorderedSets // Declare an UnorderedSet of u32 elements let mut my_unorderedset: UnorderedSet<u32> = UnorderedSet::new(); // Add elements to the UnorderedSet my_unorderedset.insert(1); my_unorderedset.insert(2);// Iterate over the elements for element in my_unorderedset.iter() { // Process each element } ## LookupMap // Declare a LookupMap with string keys and u64 values let mut my_lookupmap: LookupMap<String, u64> = LookupMap::new(); // Add key-value pairs to the LookupMap my_lookupmap.insert("key1".to_string(), 10); my_lookupmap.insert("key2".to_string(), 20); // Access values based on keys let value = my_lookupmap.get("key1".to_string()); ## TreeMap // Declare a TreeMap with u64 keys and string values let mut my_treemap: TreeMap<u64, String> = TreeMap::new(); // Add key-value pairs to the TreeMap my_treemap.insert(3, "value3".to_string()); my_treemap.insert(1, "value1".to_string()); my_treemap.insert(2, "value2".to_string()); // Iterate over the key-value pairs in sorted order for (key, value) in my_treemap.iter() { // Process each key-value pair } }