Prerequisites
- Read “What is NEAR?”
- JavaScript development experience
Developers are the lifeblood of the blockchain ecosystem. For blockchain technology to gain mainstream adoption, it needs to lower the barriers for entry for developers and allow them to create fun and sophisticated apps for the regular folks to enjoy. It is for this very reason that NEAR’s smart contracts are written using AssemblyScript due to its similarity to JavaScript.
So, if you are keen on building on NEAR, you can use the following tools
- JavaScript SDK. Connect, sign, transact and deploy to any NEAR network from any JS context
- Rust Contract SDK. Build safe, secure contracts that manage high value assets
- AssemblyScript Contract SDK. Learn and prototype with zero friction using JS syntax
- JSON RPC API. All communications with the platform pass through this API including ours
- Command Line Interface. Full featured command line toolkit for developers and validators
- NEAR Explorer. A blockchain search tool allowing developers to view transaction details, accounts, block details and more
- NEAR Wallet. Create accounts, manage access keys, and more with our user friendly UI
- nearup. Manage deployments locally and join any public or private network
- Bridge. Fast, secure interoperability
- EVM. Ethereum-compatible virtual machine.
Alright, let’s take the first steps.
A Brief Overview
Applications on NEAR have two distinct parts – a back-end and front-end.
- Smart Contract (back-end): Storing and modifying data on the chain. Contracts need to expose methods that allow clients to “view” and “change” state.
- Interactions with Smart Contract (front-end): You can interact with your contracts or contracts deployed by other people. You do this by using near-api-js Quickstart and Code Snippets in your application.
Applications on NEAR have two distinct parts – a back-end and front-end. The backend is the…..
How to Build and Call Smart Contracts
NEAR currently supports:
- Rust – near-sdk-rs: A wrapper that provides improved safety for the Rust programming language for high-value contracts.
- AssemblyScript near-sdk-as: A collection of helpers that make your SmartContracts look similar to TypeScript while compiling to Wasm for execution.
NOTE: AssemblyScript is currently not recommended for production financial applications due to the newness of the language and compilation tools available.
Alright, let’s get serious.
Setting Up Testnet
The easiest way to create an account on NEAR is with NEAR Wallet. NEAR has several development networks operating independently of each other with their own accountIDs. Go, follow the steps to create a wallet. Make sure that you have followed the required steps for your security backup.
NOTE: Creating an account on mainnet is almost identical to testnet but will require initial funding for the account. Here is a guide to mainnet account creation.
It doesn’t matter, when deploying, whether the application is written in Rust or AssemblyScript. All contract code is compiled to WebAssembly and deployed to the network to be run inside a Wasm-compatible virtual machine. You will use a command like yarn dev for most applications but you can just as easily deploy an application using NEAR CLI with near dev-deploy for TestNet (or near deploy if you have already created an account).
All contract code is compiled to WebAssembly and deployed to the network to be run inside a _______
Now, do the following to warm yourself up:
- Look around in NEAR Explorer. Here you can search for all transactions and blocks produced on NEAR. Try searching for the account you just created and see the transactions you’ve created.
- Now install near-cli. This is a command line interface that allows you to interact seamlessly with NEAR. This NEAR docs has all of the near-cli commands with examples.
- Try running your first command: near login. This will redirect you to your NEAR Wallet and save your testnet account keys locally.
After checking out the testnet, you may feel free to run your local node. However, if you just wanna play around with the codes, then we suggest that you stick to the testnet.
How Do I Run A Node?
As with any blockchain-based ecosystem, NEAR Protocol runs on a collection of publicly maintained computers (or “nodes”).
You may decide to run a node of your own for a few reasons:
- To develop and deploy contracts on a node connected to MainNet, TestNet or BetaNet
- To develop and deploy contracts on a local (independent and isolated) node (sometimes called “LocalNet”).
- To join a network as a validator running a “validator node”
You can launch NEAR betanet and testnet nodes by installing nearup. You can do so by following the instructions at https://github.com/near/nearup
As with any blockchain-based ecosystem, NEAR Protocol runs on a collection of publicly maintained computers called _______
Running an Official Node using Docker
By default, NEAR uses Docker to run the client. So, the first thing you do is install Docker and nearup. Now, run your system with this:
nearup betanet
(If you prefer to use TestNet then just replace betanet with testnet in the command above)
You will then be prompted for an Account ID. You can leave this empty if you would just like to run a node. Validators should use the account ID of the account you want to stake with. Following that, you need to enter this code:
Enter your account ID (leave empty if not going to be a validator)
Now, your node will then start in the background with Docker. To check the logs inside Docker, run docker logs –follow nearcore.
Creating A Simple Code On NEAR
NEAR has a list of helpful programs or example codes that you can checkout with ease. So the code that we will be checking out is the Guest Book. Using the program allows you to sign in with NEAR and add a message to the guest book! A starter app built with an AssemblyScript backend and a React frontend.
Looking Into Guest Book Code
To run this project locally, you need to ensure the following.
- Make sure you have Node.js ≥ 12 installed (https://nodejs.org), then use it to install yarn: npm install –global yarn (or just npm i -g yarn)
- Install dependencies: yarn install (or just yarn)
- Run the local development server: yarn dev (see package.json for a full list of scripts you can run with yarn)
Now you’ll have a local development environment backed by the NEAR TestNet! Running yarn dev will tell you the URL you can visit in your browser to see the app.
Oh and make sure that you have the GitHub page open.
You may find this video useful as well.
Exploring The Code
As you can see there are two sides to the code – backend and frontend:
- The backend code lives in the /assembly folder. This code gets deployed to the NEAR blockchain when you run yarn deploy:contract. This is a NEAR smart contract.
- The frontend code lives in the /src folder. /src/index.html is a great place to start exploring. Note that it loads in /src/index.js, where you can learn how the frontend connects to the NEAR blockchain.
Backend Code
#1 Contract Data Model : assembly/model.ts
[code lang=”js”]import { context, u128, PersistentVector } from "near-sdk-as";
/**
* Exporting a new class PostedMessage so it can be used outside of this file.
*/
@nearBindgen
export class PostedMessage {
premium: boolean;
sender: string;
constructor(public text: string) {
this.premium = context.attachedDeposit >= u128.from('10000000000000000000000');
this.sender = context.sender;
}
}
/**
* collections.vector is a persistent collection. Any changes to it will
* be automatically saved in the storage.
* The parameter to the constructor needs to be unique across a single contract.
* It will be used as a prefix to all keys required to store data in the storage.
*/
export const messages = new PersistentVector<<PostedMessage>("m");[/code]
Analysis
@nearBindgen marks the class as serializable. Serializable is a marker interface used to “mark” classes so that the objects of these classes may get a certain capability.
The “PostedMessage” class has three features –
- premium to flag messages with attached NEAR tokens
- sender to track the signer of the guest book message
- text to hold the guest book message
Finally, “messages” is a collection of guest book messages stored as a PersistentVector of PostedMessage objects
#2 Contract Behavior : assembly/main.ts
[code lang=”js”]import { PostedMessage, messages } from './model';
// — contract code goes below
// The maximum number of latest messages the contract returns.
const MESSAGE_LIMIT = 10;
/**
* Adds a new message under the name of the sender's account id.\
* NOTE: This is a change method. Which means it will modify the state.\
* But right now we don't distinguish them with annotations yet.
*/
export function addMessage(text: string): void {
// Creating a new message and populating fields with our data
const message = new PostedMessage(text);
// Adding the message to end of the the persistent collection
messages.push(message);
}
/**
* Returns an array of last N messages.\
* NOTE: This is a view method. Which means it should NOT modify the state.
*/
export function getMessages(): PostedMessage[] {
const numMessages = min(MESSAGE_LIMIT, messages.length);
const startIndex = messages.length – numMessages;
const result = new Array<PostedMessage>(numMessages);
for(let i = 0; i < numMessages; i++) {
result[i] = messages[i + startIndex];
}
return result;
}[/code]
Analysis
MESSAGE_LIMIT is used to avoid unbounded calls (ie. potentially expensive) to retrieve guest book messages from storage
We are also using two different public functions in this contract – addMessage() and getMessages()
Frontend Code
#1 Network Connection : src/config.js
[code lang=”js”]const CONTRACT_NAME = process.env.CONTRACT_NAME || 'guest-book.testnet';
function getConfig(env) {
switch(env) {
case 'mainnet':
return {
networkId: 'mainnet',
nodeUrl: 'https://rpc.mainnet.near.org',
contractName: CONTRACT_NAME,
walletUrl: 'https://wallet.near.org',
helperUrl: 'https://helper.mainnet.near.org'
};
// This is an example app so production is set to testnet.
// You can move production to mainnet if that is applicable.
case 'production':
case 'development':
case 'testnet':
return {
networkId: 'default',
nodeUrl: 'https://rpc.testnet.near.org',
contractName: CONTRACT_NAME,
walletUrl: 'https://wallet.testnet.near.org',
helperUrl: 'https://helper.testnet.near.org'
};
case 'betanet':
return {
networkId: 'betanet',
nodeUrl: 'https://rpc.betanet.near.org',
contractName: CONTRACT_NAME,
walletUrl: 'https://wallet.betanet.near.org',
helperUrl: 'https://helper.betanet.near.org'
};
case 'local':
return {
networkId: 'local',
nodeUrl: 'http://localhost:3030',
keyPath: `${process.env.HOME}/.near/validator_key.json`,
walletUrl: 'http://localhost:4000/wallet',
contractName: CONTRACT_NAME
};
case 'test':
case 'ci':
return {
networkId: 'shared-test',
nodeUrl: 'https://rpc.ci-testnet.near.org',
contractName: CONTRACT_NAME,
masterAccount: 'test.near'
};
case 'ci-betanet':
return {
networkId: 'shared-test-staging',
nodeUrl: 'https://rpc.ci-betanet.near.org',
contractName: CONTRACT_NAME,
masterAccount: 'test.near'
};
default:
throw Error(`Unconfigured environment '${env}'. Can be configured in src/config.js.`);
}
}
module.exports = getConfig;[/code]
Analysis
The code above defines the data and endpoints required to connect to the NEAR network. The connection information defined here is included for MainNet, TestNet and BetaNet as well as the default LocalNet configuration
#2 Configuration : src/index.js
[code lang=”js”]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() {
const nearConfig = getConfig(process.env.NODE_ENV || 'testnet');
// Initializing connection to the NEAR TestNet
const near = await nearAPI.connect({
deps: {
keyStore: new nearAPI.keyStores.BrowserLocalStorageKeyStore()
},
…nearConfig
});
// Needed to access wallet
const walletConnection = new nearAPI.WalletConnection(near);
// Load in account data
let currentUser;
if(walletConnection.getAccountId()) {
currentUser = {
accountId: walletConnection.getAccountId(),
balance: (await walletConnection.account().state()).amount
};
}
// Initializing our contract APIs by contract name and configuration
const contract = await new nearAPI.Contract(walletConnection.account(), nearConfig.contractName, {
// View methods are read-only – they don't modify the state, but usually return some value
viewMethods: ['getMessages'],
// Change methods can modify the state, but you don't receive the returned value when called
changeMethods: ['addMessage'],
// 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')
);
});[/code]
Analysis
This is the meat and potatoes of the frontend section, when you configure connection to NEAR network. You may configure contract interface by injecting wallet connection and wiring up both contract methods.
Deploying A Smart Contract
Every smart contract in NEAR has its own associated account. When you run yarn dev, your smart contracts get deployed to the live NEAR TestNet with a temporary account. If you now want to make it permanent, here’s what you need to do.
Step 0: Install near-cli
Here’s how you globally install near-cli
npm install --global near-cli
This will give you the near CLI tool. Ensure that it’s installed with:
near --version
Step 1: Create an account for the contract
Visit NEAR Wallet and make a new account. You’ll be deploying these smart contracts to this new account.
Now authorize NEAR CLI for this new account, and follow the instructions it gives you:
near login
Step 2: Set contract name in code
Modify the line in src/config.js that sets the account name of the contract. Set it to the account id you used above.
const CONTRACT_NAME = process.env.CONTRACT_NAME || 'your-account-here!'
Step 3: change remote URL if you cloned this repo
If you fork the repository you will need to change the remote URL to a repo that you have “commit” access to. This will allow auto deployment to Github Pages from the command line.
- Go to GitHub and create a new repository for this project.
- Open your terminal and in the root of this project enter the following:
$ `git remote set-url origin https://github.com/YOUR_USERNAME/YOUR_REPOSITORY.git`
Step 4: Deploy!
You just need the following command to deploy your smart contract:
yarn deploy
This command does two things:
- Builds & deploys smart contracts to NEAR TestNet
- Builds & deploys frontend contract code to GitHub using gh-pages. This will only work if the project already has a repository set up on GitHub. Feel free to modify the deploy script in package.json to deploy elsewhere.
Every smart contract in NEAR has its own associated ____
What Next?
Alright, now that you know how to run a basic code, you may want to get deeper into NEAR. For that, checkout NEAR’s developer docs.
Top comment
I really like this guide. It’s help me a lot when I just started to work with web3.
I agree that developers are crucial to the growth and adoption of blockchain technology. As the technology continues to evolve, it's important for developers to have access to tools and platforms that make it easy for them to create and deploy applications that are both functional and user-friendly. NEAR's use of AssemblyScript as the language for its smart contracts is a smart move, as it allows developers to leverage their existing JavaScript skills to build on the platform. This can help to lower the barriers to entry for developers who may be new to blockchain technology, and make it easier for them to create and deploy applications that are both sophisticated and accessible to regular users. Overall, I think that the use of AssemblyScript by NEAR is a positive development for the blockchain ecosystem, as it can help to make the technology more accessible and user-friendly for developers and regular users alike.
Done
Very useful information!