# A Complete Tutorial for Beginners in Near Protocol 1. Entrance of The New(Near) World: Near-cli 2. Setup a localnet 3. Develop a Smart Contract 4. Develop a Front-end for your Smart Contract 5. Resources ## 1. Entrance of The New(Near) World: Near-cli [near-cli](https://github.com/near/near-cli) is a NodeJS command line interface that utilizes [near-api-js](https://github.com/near/near-api-js) to connect to and interact with the [NEAR blockchain](https://explorer.near.org/). * Installation ![](https://i.imgur.com/VZcs5HQ.jpg) Ensure you have installed Node version 12 or above,install by running: `$ npm install -g near-cli` Now you are in the front of the NEAR world. * Choose your network ![](https://i.imgur.com/z2HFY3G.jpg) As a Dapp developer, we can just focus on testnet and mainnet.But you should know there are [more networks](https://docs.near.org/docs/concepts/networks) NEAR Protocol operates on for different purposes. Now we switch to the testnet for a quick explore. > $ export NEAR_ENV=testnet * Create account and Login > $ near login You will be redirected to the website of NEAR Wallet.You can create an account or select an account you already have. After you confirm the authorization,you will login successfully. Now, Your Access Key stored locally in a hidden directory called .near-credentials `~/.near-credentials/testnet`. Run the following command to show details of your account's state: > $ near state $YOUR_ACCOUNT_ID For a more comprehensive command explanation,please visit [Near Docs](https://docs.near.org/docs/tools/near-cli#overview) If you need a faucet to get more NEAR coins, check [this](https://monocrowd.github.io/near-faucet/) out. ## 2. Setup a localnet(Optional) If you want to feel all parts of the NEAR, you might want to build it from scratch. ![](https://i.imgur.com/7tnx0JT.jpg) * Compilation The following commands requires [the rust toolchain](https://www.rust-lang.org/tools/install) and [git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git). >$ git clone https://github.com/near/nearcore.git >$ cd nearcore >$ brew install cmake protobuf clang llvm #for MacOS >$ apt update && apt install -y git binutils-dev libcurl4-openssl-dev zlib1g-dev libdw-dev libiberty-dev cmake gcc g++ python docker.io protobuf-compiler libssl-dev pkg-config clang llvm #For Linux >$ make neard Then this will start the compilation process. It will take some time. * Initialize Localnet >$ mkdir res >$ cp target/release/neard res/ >$ cd res ##make `res` directory as working directory >$ ./neard --home ./ init After last command, there will be four json file: `config.json` - Configuration parameters which are responsive for how the node will work. `genesis.json` - A file with all the data the network started with at genesis. This contains initial accounts, contracts, access keys, and other records which represents the initial state of the blockchain. `node_key.json` - A file which contains a public and private key for the node. Also includes an optional account_id parameter which is required to run a validator node (not covered in this doc). `validator_key.json` - A file which contains a public and private key for local test.near account which belongs to the only local network validator. * Run a Node We can leave them as them are, then start a validator: > $ ./neard --home ./ run Now we can switch to the localnet, and use near-cli as usual: > $ export NEAR_ENV=localnet > $ near create-account hello.test.near --masterAccount test.near --initialBalance 1000 > $ near state hello.test.near Sometimes we need to put `validator_key.json` in `~/.near` directory. For example if you want to run a [web-based wallet](https://github.com/near/near-wallet) locally. ## 3. Develop a Smart Contract There are two technologies to write and compile Smart Contracts on the NEAR platform: Rust-lang and AssemblyScript. We use the Rust-lang in this Turtorial. * Clone [this project](https://github.com/near-examples/rust-template) * Write A Guest Book ```rust #[near_bindgen] #[derive(BorshDeserialize,BorshSerialize,PanicOnDefault)] pub struct Contract { pub msgs:UnorderedMap<AccountId,Message> } ``` This is the core struct of this Smart Contract.Everyone `AccountId` can leave a `Message`. `UnorderedMap` is one of the `near_sdk::collections`, designed to split the data into chunks and defer reading and writing to the store until needed. These data structures will handle the low-level storage interactions and aim to have a similar API to the `std::collections` in the Rust-lang. ```rust #[derive(BorshDeserialize, BorshSerialize, Serialize, Deserialize)] #[serde(crate = "near_sdk::serde")] pub struct Message{ is_premium:bool, time:u64, content:String } ``` In general, `serde` Serializer and Deserializer will be used for contract calls and cross-contract calls for a better DevX, where `Borsh` can be used to optimize using less gas by having smaller parameter serialization and less deserialization computation within the contract. ```rust #[near_bindgen] impl Contract { #[init] pub fn new() -> Self { Self{ msgs: UnorderedMap::new(b"m".to_vec()) } } pub fn check_exist(&self,account_id:AccountId) -> bool{ if let Some(_) = self.msgs.get(&account_id){ true }else{ false } } #[payable] pub fn add_msg(&mut self,msg_content:String){ assert_ne!(self.check_exist(env::signer_account_id()) ,true,"You can only sign the guest book once"); let msg = Message{ is_premium: if env::attached_deposit()>0{true} else {false}, time: env::block_timestamp(), content:msg_content }; self.msgs.insert(&env::signer_account_id(), &msg); } pub fn get_msgs(&self,from_index:u64,limit:u64) -> Vec<(AccountId,Message)>{ env::log(format!("from: {}, limit: {}",from_index,limit).as_ref()); let keys = self.msgs.keys_as_vector(); let values = self.msgs.values_as_vector(); (from_index..std::cmp::min(from_index + limit, self.msgs.len())) .map(|index| (keys.get(index).unwrap(), values.get(index).unwrap())) .collect() } } ``` By the default the methods are not payable and they will panic if someone will attempt to transfer tokens to them during the invocation. To declare a method as payable,we use the `#[payable]` annotation within the near_bindgen macro. * Compile and Deploy `build.sh` is a script for building this project. A wasm file will be generated in `res` directory in the root of this project. You can deploy this wasm file in both testnet or localnet with the following command: > $ near dev-deploy --wasmFile res/*.wasm It will automatically generate a dev-account and deploy this smart contract. Or you can deploy it by specifying account id: > $ near deploy --wasmFile res/*.wasm --accountId $ID After deployment,you can invoke this smart contract by `near-cli`. > $ near call $CONTRACT_ID add_msg '{"msg_content":"Hello "}' --deposit 1 --accountId $MY_ACCOUNT_ID or use a view method: > $ near view $CONTRACT_ID get_msgs '{"from_index":0,"limit":10}' View or Call, it depends on if it is a mutable method. To go through full code of this example, you can check [here](https://github.com/2efPer/guesst-book-allin1). ![](https://github.com/2efPer/guesst-book-allin1/raw/master/screenshot.png) ## 4. Develop a Front-end for your Smart Contract [near-api-js](https://github.com/near/near-api-js) is a JavaScript/TypeScript library for development of front-end applications on the NEAR platform. [Here](https://github.com/2efPer/guesst-book-allin1/tree/master/web) is my almost-Front-end-template project ,you can modify it as you want. It requires you familiar with `npm` and `react`. The basic usage of `near-api-js` in like this: ``` javascript import React from 'react'; import ReactDOM from 'react-dom'; import App from './App'; import getConfig from './config.js'; import * as nearAPI from 'near-api-js'; // Initializing contract async function initContract() { // get network configuration values from config.js // based on the network ID we pass to getConfig() const nearConfig = getConfig(process.env.NODE_ENV || 'testnet'); // create a keyStore for signing transactions using the user's key // which is located in the browser local storage after user logs in const keyStore = new nearAPI.keyStores.BrowserLocalStorageKeyStore(); // Initializing connection to the NEAR testnet const near = await nearAPI.connect({ keyStore, ...nearConfig }); // Initialize wallet connection const walletConnection = new nearAPI.WalletConnection(near); // Load in user's account data let currentUser; if (walletConnection.getAccountId()) { currentUser = { // Gets the accountId as a string accountId: walletConnection.getAccountId(), // Gets the user's token balance balance: (await walletConnection.account().state()).amount, }; } // Initializing our contract APIs by contract name and configuration const contract = await new nearAPI.Contract( // User's accountId as a string walletConnection.account(), // accountId of the contract we will be loading // NOTE: All contracts on NEAR are deployed to an account and // accounts can only have one contract deployed to them. nearConfig.contractName, { // View methods are read-only – they don't modify the state, but usually return some value viewMethods: ['get_msgs','check_exist'], // Change methods can modify the state, but you don't receive the returned value when called changeMethods: ['add_msg'], // Sender is the account ID to initialize transactions. // getAccountId() will return empty string if user is still unauthorized sender: walletConnection.getAccountId(), } ); return { contract, currentUser, nearConfig, walletConnection }; } window.nearInitPromise = initContract().then( ({ contract, currentUser, nearConfig, walletConnection }) => { ReactDOM.render( <App contract={contract} currentUser={currentUser} nearConfig={nearConfig} wallet={walletConnection} />, document.getElementById('root') ); } ); ``` For a quick check you can visit [HERE](https://docs.near.org/docs/api/naj-quick-reference). Change your own contract name in `config.js`, then use the following command to run this front-end project. > cd web && npm install && npm start ## 5. More Resources 1. [Storage on NEAR](https://docs.near.org/docs/concepts/data-storage) 2. [Account Access Keys](https://docs.near.org/docs/concepts/account#access-keys) 3. [Gas costs on NEAR](https://docs.near.org/docs/concepts/gas#the-cost-of-common-actions) 4. [NEAR Protocol Specification](https://nomicon.io/) 5. [NEAR-sdk for SmartContract](https://www.near-sdk.io/) 6. [NEAR-sdk for Frontend](https://docs.near.org/docs/api/naj-quick-reference) 7. [NEAR Smart Contract examples](https://github.com/near-examples)