Select Page

How to create and deploy smart contracts on the NEAR Protocol?

build defi app

NEAR Protocol is well-known for its ecosystem, which provides the most suitable environment for building decentralized applications. Using this protocol, developers can host serverless apps and smart contracts for connecting to open-finance networks and benefit from an ecosystem of reusable smart contracts. Developers and users prefer NEAR Protocol because of its convenient user interface, security and scalability.

NEAR Protocol helps in the following ways:

  • Application Buiding
    It helps in developing dApps by providing an easy development platform.
  • Easy User Interface
    Users onboard smoothly on NEAR Protocol because of its convenient user interface for accessing cryptos, tokens, wallets, keys or any other blockchain artifact.
  • Scalability
    It helps scale the applications seamlessly through the process of sharding. NEAR Protocol expands its capacity to scale the dApps via sharding with zero extra cost or effort from the users’ end.

Unlike the centralized cloud infrastructure, NEAR has a decentralized cloud-based infrastructure used by the developers for building applications on top of it. This decentralized data centre of the NEAR Protocol constitutes people all over the globe who are operating the nodes on the network. Thus, NEAR Protocol has a community-operated cloud-based infrastructure.

It is crucial for any blockchain platform to have low developer barriers, for its mainstream adoption. This being an important factor in blockchain platform selection, NEAR is one of the easiest and best platforms for easily developing dApps on it. For building a decentralized application on the blockchain, a smart contract is required to govern the development process. To suffice easy smart contract creation, NEAR Protocol thus supports AssemblyScript due to its similarity with the JavaScript and its ease of writing the smart contract.

This article will help you unfold the step-by-step process of smart contract creation on the NEAR Protocol.

Brief about NEAR Protocol

NEAR Protocol is one of the best examples of third-generation blockchains. It focuses on solving scalability issues and incentivizes the network to develop and launch dApp in the decentralized finance ecosystem. NEAR Protocol yields profit by staking and sharding on the network’s platform. It overcomes certain drawbacks such as low speed, low throughput and negligible cross-chain compatibility.

The core concept of NEAR Protocol’s design is based on sharding. Sharding reduces the computational load by splitting the network’s infrastructure into different parts called nodes, to manage a fraction of the platform’s transactions. The splitting up of network nodes instead of every node running the network’s code helps in easy retrieval and scaling of data on the decentralized network.

The NEAR blockchain network is permissionless and secure in nature. Its innovations consist of a different consensus mechanism known as the ‘Doomslug.’ NEAR’s architecture is also based on the Proof-of-Stake consensus mechanism. It is a community-run platform for cloud computing.

NEAR functions in the same way as a centralized data storage platform. For instance, the Amazon Web Services (AWS)- functions in the form of a base layer on which the applications are developed. The only difference between AWS and NEAR is that a distributed network of computers and not any single authority manages NEAR. Like AWS, NEAR allows the building of architecture around a network, a chain of computers and the native token NEAR. This platform has several components required for building on it:

  • Native token named NEAR
  • Mintbase
  • NFT minting platform
  • Flux protocol for developers’ market creation based on commodities, assets, etc

Let us now explore the distinct parts of the NEAR applications in the next section in the context of the smart contract layer.

What are the two distinct parts of NEAR apps?

NEAR web applications have two different parts in the form of a front-end and a back-end:

  • Smart Contracts
    They manage the on-chain storage and modification of data. Smart contracts require exposing ways to help clients “view” and “change” their state.
  • Interactions with Smart Contract-(s):-
    Similar to cloud API, we are entitled to interact with our contracts or the contracts that others deploy. We do this by using near-api-js Quickstart and Code Snippets available in the application.

Features of near-api-js

The fundamental aspect of the NEAR platform API is the JSON-RPC interface. The near-api-js wrap up the RPC interface and convenience functions and bring out the NEAR primitives in the form of JavaScript objects. near-api-js is used as the primary interface with the NEAR Protocol at the time of writing JavaScript (client or server-side). near-api-js has the following features:

  • Generation of key pairs
  • Transaction creation
  • Transaction signing
  • Transactions sending via network

near-api-js also provides support to interact with the other important primitives of the NEAR system mentioned below:

  • Key stores and keys
  • Accounts
  • Contracts
  • Wallets (client-side only)
  • Connection providers (currently RPC)

Now that we are familiar with two distinct parts of NEAR applications let us understand the tools and languages required to write and compile NEAR smart contracts in the next section. 

What language and tools are used to compile a smart contract on NEAR?

We can use any language that is supported by Web Assembly (Wasm) to compile a smart contract on the NEAR Protocol, but it currently supports the following:

Rust (near-sdk-rs)

Rust is a wrapper that helps improve the safety of the Rust programming language used to write high-value smart contracts.

AssemblyScript (near-sdk-as)

AssemblyScript is a group of helpers that helps the smart contracts look the same as TypeScript while compiling them in wasm to specifically execute them. It is currently not used in the development of financial decentralized applications because of the newness of the programming language and the compilation tools associated with it.

Now that we know about the languages and tools used for developing smart contracts on NEAR, Let us quickly look at the basics of calling and deploying a smart contract.

  • Calling Smart Contracts on NEAR Protocol
    For wrapping up the JSON-RPC calls, use the near-api-js Quickstarts and Code Snippets.
  • Deploying Smart Contracts
    There is a testnet where we are allowed to run our local network and a mainnet as in the NEAR Platform. The state of the smart contract is based on the type of network on which it is deployed and if we want to call it from the same network, we will need to check our configuration while deploying, testing and calling the smart contract.

How to build a NEAR smart contract using Rust?

This section will guide you in the process of creating, testing and running a smart contract on the NEAR Protocol. The example present in this section is of a simple smart contract that functions in the form of a Counter, incrementing, decrementing and returning the counter value.

Writing smart contracts on blockchain platforms is a huge paradigm shift. Currently, there are certain smart contract concepts on focus like state of the contract, transfer, account and balance information. The preferred language for writing a smart contract on NEAR is Rust.

Pre-requisites

  • Rust toolchain
  • A NEAR account
  • NEAR command-line interface (near-cli)

Set up requirements

Using the Rust environment create a NEAR account and then install near-cli.

Install Rust toolchain

Install the Rustup

Run the following command to install the Rustup:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

Configure the current shell

Insert the following command for the configuration of your current shell:

source $HOME/.cargo/env

Add the wasm target to the blockchain network

Run,

rustup target add wasm32-unknown-unknown

Create a NEAR Account

Create a NEAR account via NEAR wallet. NEAR has various development networks functioning independently via their own accountIDs.

Create a testnet account, just in case you already have a testnet account you do not have to follow the below-mentioned steps:

Reserve an Account ID

Secure your account

Select your account recovery method. The recovery phrase and ledger are two of the most secure methods.

E-mail/ Contact number account recovery

Insert the account activation code that you get and then the testnet account is created. After the recovery method is followed you will also be directed towards your account dashboard.

Installing the near-cli

Follow the below-mentioned steps to install the near-cli. You can skip these steps in case you already have a command-line interface:

Linux and macOS

  • Install the npm and node via a package manager like the nvm.
  • Check that you have the latest version of npm and NodeJS installed on your system.
  • Globally install the near-cli by running the following command,
    npm install -g near-cli

Windows

Use the Windows Subsystem for Linux (WSL).

  • Install the WSL
  • Then install the Node.js
  • Then change the npm default directory
  • Click on WSL and globally install the near-cli by running the following command: npm install -g near-cli

Modular blockchain solutions for new-age enterprise software

Build Smart Contract on NEAR protocol with LeewayHertz.

Repository Creation

Create a new project repository with the help of cargo. For this, you need to navigate back to the projects directory and then run the following commands:

$ cargo new rust-counter-tutorial
$ cd rust-counter-tutorial

These commands provide a new directory known as the rust-counter-tutorial. You can name the file as a project rust-counter-tutorial. Cargo will create files in the directory of a similar name.

Cargo will generate two files and now directory: Cargo.toml file and src directory with a main.rs file inside it.

├── Cargo.toml
└── src
└── main.rs

Creating Files

For file creation, the NEAR smart contract has a very simple layout:

├── Cargo.toml
└── src
└── lib.rs

NEAR smart contracts have a primary file that contains the code: ./src/lib.rs

This is the Rust library’s conventional file name. Libraries work smoothly to do the compiling in the WebAssembly and to deploy the blockchain.

Editing Cargo.toml

Click and open the Cargo.toml in your preferred text editor. The file will be in Tam’s Obvious Minimal Language (TOML) format. TOML is Cargo’s configuration format that is same to the package.json file. Next, replace the entire content with the following commands of Cargo.toml file,

/Cargo.toml

[package]
name = "rust-counter-tutorial"
version = "0.1.0"
authors = ["NEAR Inc <hello@near.org>"]
edition = "2018"

[lib]
crate-type = ["cdylib", "rlib"]

[dependencies]
near-sdk = "3.1.0"

[profile.release]
codegen-units = 1
# Tell `rustc` to optimize for small code size.
opt-level = "z"
lto = true
debug = false
panic = "abort"
# Opt into extra safety checks on arithmetic operations https://stackoverflow.com/a/64136471/249801
overflow-checks = true

Create Lib.rs

Create the ./src/lib.rs file in the text editor. Copy and paste the content of lib.rs file. This instance utilizes the lib.rs file along with smart contract logics via struct, struct’s functions and the unit tests. All of this will be in one single file by running the below-mentioned command,

/src/lib.rs

//! This contract implements simple counter backed by storage on blockchain.
//!
//! The contract provides methods to [increment] / [decrement] counter and
//! [get it's current value][get_num] or [reset].
//!
//! [increment]: struct.Counter.html#method.increment
//! [decrement]: struct.Counter.html#method.decrement
//! [get_num]: struct.Counter.html#method.get_num
//! [reset]: struct.Counter.html#method.reset

use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize};
use near_sdk::{env, near_bindgen};

near_sdk::setup_alloc!();

// add the following attributes to prepare your code for serialization and invocation on the blockchain
// More built-in Rust attributes here: https://doc.rust-lang.org/reference/attributes.html#built-in-attributes-index
#[near_bindgen]
#[derive(Default, BorshDeserialize, BorshSerialize)]
pub struct Counter {
// See more data types at https://doc.rust-lang.org/book/ch03-02-data-types.html
val: i8, // i8 is signed. unsigned integers are also available: u8, u16, u32, u64, u128
}

#[near_bindgen]
impl Counter {
/// Returns 8-bit signed integer of the counter value.
///
/// This must match the type from our struct's 'val' defined above.
///
/// Note, the parameter is `&self` (without being mutable) meaning it doesn't modify state.
/// In the frontend (/src/main.js) this is added to the "viewMethods" array
/// using near-cli we can call this by:
///
/// ```bash
/// near view counter.YOU.testnet get_num
/// ```
pub fn get_num(&self) -> i8 {
return self.val;
}

/// Increment the counter.
///
/// Note, the parameter is "&mut self" as this function modifies state.
/// In the frontend (/src/main.js) this is added to the "changeMethods" array
/// using near-cli we can call this by:
///
/// ```bash
/// near call counter.YOU.testnet increment --accountId donation.YOU.testnet
/// ```
pub fn increment(&mut self) {
// note: adding one like this is an easy way to accidentally overflow
// real smart contracts will want to have safety checks
// e.g. self.val = i8::wrapping_add(self.val, 1);
// https://doc.rust-lang.org/std/primitive.i8.html#method.wrapping_add
self.val += 1;
let log_message = format!("Increased number to {}", self.val);
env::log(log_message.as_bytes());
after_counter_change();
}

/// Decrement (subtract from) the counter.
///
/// In (/src/main.js) this is also added to the "changeMethods" array
/// using near-cli we can call this by:
///
/// ```bash
/// near call counter.YOU.testnet decrement --accountId donation.YOU.testnet
/// ```
pub fn decrement(&mut self) {
// note: subtracting one like this is an easy way to accidentally overflow
// real smart contracts will want to have safety checks
// e.g. self.val = i8::wrapping_sub(self.val, 1);
// https://doc.rust-lang.org/std/primitive.i8.html#method.wrapping_sub
self.val -= 1;
let log_message = format!("Decreased number to {}", self.val);
env::log(log_message.as_bytes());
after_counter_change();
}

/// Reset to zero.
pub fn reset(&mut self) {
self.val = 0;
// Another way to log is to cast a string into bytes, hence "b" below:
env::log(b"Reset counter to zero");
}
}

// unlike the struct's functions above, this function cannot use attributes #[derive(…)] or #[near_bindgen]
// any attempts will throw helpful warnings upon 'cargo build'
// while this function cannot be invoked directly on the blockchain, it can be called from an invoked function
fn after_counter_change() {
// show helpful warning that i8 (8-bit signed integer) will overflow above 127 or below -128
env::log("Make sure you don't overflow, my friend.".as_bytes());
}

/*
* the rest of this file sets up unit tests
* to run these, the command will be:
* cargo test --package rust-counter-tutorial -- --nocapture
* Note: 'rust-counter-tutorial' comes from cargo.toml's 'name' key
*/

// use the attribute below for unit tests
#[cfg(test)]
mod tests {
use super::*;
use near_sdk::MockedBlockchain;
use near_sdk::{testing_env, VMContext};

// part of writing unit tests is setting up a mock context
// in this example, this is only needed for env::log in the contract
// this is also a useful list to peek at when wondering what's available in env::*
fn get_context(input: Vec, is_view: bool) -> VMContext {
VMContext {
current_account_id: "alice.testnet".to_string(),
signer_account_id: "robert.testnet".to_string(),
signer_account_pk: vec![0, 1, 2],
predecessor_account_id: "jane.testnet".to_string(),
input,
block_index: 0,
block_timestamp: 0,
account_balance: 0,
account_locked_balance: 0,
storage_usage: 0,
attached_deposit: 0,
prepaid_gas: 10u64.pow(18),
random_seed: vec![0, 1, 2],
is_view,
output_data_receivers: vec![],
epoch_height: 19,
}
}

// mark individual unit tests with #[test] for them to be registered and fired
#[test]
fn increment() {
// set up the mock context into the testing environment
let context = get_context(vec![], false);
testing_env!(context);
// instantiate a contract variable with the counter at zero
let mut contract = Counter { val: 0 };
contract.increment();
println!("Value after increment: {}", contract.get_num());
// confirm that we received 1 when calling get_num
assert_eq!(1, contract.get_num());
}

#[test]
fn decrement() {
let context = get_context(vec![], false);
testing_env!(context);
let mut contract = Counter { val: 0 };
contract.decrement();
println!("Value after decrement: {}", contract.get_num());
// confirm that we received -1 when calling get_num
assert_eq!(-1, contract.get_num());
}

#[test]
fn increment_and_reset() {
let context = get_context(vec![], false);
testing_env!(context);
let mut contract = Counter { val: 0 };
contract.increment();
contract.reset();
println!("Value after reset: {}", contract.get_num());
// confirm that we received -1 when calling get_num
assert_eq!(0, contract.get_num());
}
}

Let us understand some of the above-mentioned codes by breaking them down in the upcoming sections of this article.

use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize};
use near_sdk::{env, near_bindgen};

You will see the standard inputs at the top of this file. All the packages following the use statement are saved in the Cargo.toml in dependencies. All the imports that involve serialization are utilized to group the codes/storage, so that it is all prepared for the blockchain.

Below-mentioned are some of the snippets from lib.rs file,

#[near_bindgen]
#[derive(Default, BorshDeserialize, BorshSerialize)]
pub struct Counter {
val: i8, // i8 is signed. unsigned integers are also available: u8, u16, u32, u64, u128
}

#[near_bindgen]
impl Counter { 
…

While you write the smart contracts, the format is to receive a struct with an associated impl, in which you can write the fundamental logic in the form of functions.

Modular blockchain solutions for new-age enterprise software

Build Smart Contract on NEAR protocol with LeewayHertz.

The Struct

You will declare your Counter and impl, by stating the definite functions to invoke them on the blockchains.

Follow the below-mentioned commands for the struct oj NEAR:

#[near_bindgen]
#[derive(Default, BorshDeserialize, BorshSerialize)]

These commands help compile in the WebAssemble to be supportive and optimized for the NEAR Protocol.

You can also utilize the reference env to write the logs as we have mentioned earlier in this article.

Look at some of the </>env functions given below:

  • signer_account_id – the account id of the account that signed the original transaction that leads to this execution
  • attached_deposit – if someone sent tokens along with the call
  • account balance – the balance attached to the given account

Unit Tests

The unit tests will start at,

mod tests {
…
}

and will continue till the end of the lib.rs file. The code mentioned above is boilerplate in nature.

Write a test

The customized unit test code that you make, will come in use in the following:

let mut contract = Counter{ val: 0 };
contract.increment();
// confirm that we received 1 when calling get_num
println!("Value after increment: {}", contract.get_num());
assert_eq!(1, contract.get_num());

Test and compile

Test the smart contract, then compile it and create a wasm release binary.

Test the code

Test the smart contract code via cargo,

cargo test -- --nocapture

You will then receive output in the form of:

running 3 tests
Value after decrement: -1
Value after increment: 1
Value after reset: 0
test tests::decrement ... ok
test tests::increment ... ok
test tests::increment_and_reset ... ok

test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

Compile the code

Once you get all the tests passed ok, continue with the compiling with the smart contract now,

cargo build --target wasm32-unknown-unknown --release

.
├── Cargo.lock ⟵ created during build to lock dependencies
├── Cargo.toml
├── src
│ └── lib.rs
└── target ⟵ created during build, holds the compiled wasm

Deploying smart contracts

With the newly compiled .wasm file deploy your smart contract. You will deploy it using the near-cli and the testnet of your NEAR account.

Login with near-cli,
near login
near deploy --wasmFile target/wasm32-unknown-unknown/release/rust_counter_tutorial.wasm --accountId YOUR_ACCOUNT_HERE

Why should you build on the NEAR Protocol?

NEAR protocol targets eliminating the blockages that appear in the way of adopting web 3.0. It provides speedy transactions with minimal processing cost. NEAR has a robust and progressive UX for dApp users on a decentralized finance platform. It is environmental friendly in nature, surfacing as one of the best digital market ecosystems. NEAR’s mechanism is based on the sharding technique and therefore, helps facilitate easy data retrieval and dApp scaling on the DeFi platforms.

NEAR uses an election mechanism which is known as the Threshold Proof-of-Stake (TPoS). With the help of the TPoS, NEAR creates a predetermined way to engage a huge number of participants to maintain the blockchain ecosystem. This leads to increased decentralization and security of the blockchain network. Using the TPoS mechanism, NEAR builds a fair reward system for dApp users.

Endnote

NEAR Protocol is one of the most technically superseding Protocols in comparison to the other blockchain networks. It equally focuses on building decentralized applications (dApp) with the help of sharding technology to attain scalability.

To achieve this goal NEAR Protocol provides features like human-readable account names and not cryptographic wallet addresses. It helps new dApp users to communicate with the dApps and smart contracts.

If you wish to develop NEAR smart contracts, connect with our blockchain experts to collaborate for the development process and further guidance.

Webinar Details

Author’s Bio

Akash Takyar
Akash Takyar
CEO LeewayHertz
Akash Takyar is the founder and CEO at LeewayHertz. The experience of building over 100+ platforms for startups and enterprises allows Akash to rapidly architect and design solutions that are scalable and beautiful.
Akash's ability to build enterprise-grade technology solutions has attracted over 30 Fortune 500 companies, including Siemens, 3M, P&G and Hershey’s. Akash is an early adopter of new technology, a passionate technology enthusiast, and an investor in AI and IoT startups.

Start a conversation by filling the form

Once you let us know your requirement, our technical expert will schedule a call and discuss your idea in detail post sign of an NDA.

All information will be kept confidential.

 

Insights