# Preparation for NCD I ## Build and deploy a smart contract to NEAR protocol blockchain This note will walk you through a starter project that you may use in NCD I and will give you basic knowledge of its structure, internal work and problems you may encounter. ### Goals 1) Get familiar with project structure 2) Build the contract 3) Try different ways of deploying it --- ### Estimates for Time to Complete - Fastest time: 5 minutes (if you already know how to do this) - Most likely time: 12 minutes - Time to quit: 20 minutes (we can help you with some hints in this case) --- ## Requirements In order to have little to no troubles and awaitings during this course, you should have installed: - [npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) Node.JS package manager - [git](https://git-scm.com/downloads) version control - yarn (``npm install -g yarn@1.22.15``) - [near-cli](https://docs.near.org/docs/tools/near-cli#setup) Also, you have to use your testnet account. If you don't have one - [create](https://docs.near.org/docs/develop/basics/create-account#creating-a-testnet-account). ## First things first To start with, let's clone [repository](https://github.com/Learn-NEAR/starter--near-sdk-as) we'll be working with. You can do it through GitHub client or using ```git clone https://github.com/Learn-NEAR/starter--near-sdk-as``` command. Open project folder in terminal and run ``yarn``. ``yarn`` is a package manager that allows to download and solve project's dependencies - pieces of code that are required for project to work. You will see such output: ```shell=b PS C:\Github\starter--near-sdk-as> yarn yarn install v1.22.15 [1/4] Resolving packages... [2/4] Fetching packages... [3/4] Linking dependencies... [4/4] Building fresh packages... Done in 2.16s. ``` Let's have a closer look at the content of our project. ## Overview ### package.json ```json= { "name": "starter--near-sdk-as", "version": "0.0.1", "description": "Start with a basic project", "scripts": { "dev": "watch -d -n 1 'clear && yarn test'", "test": "yarn asp -f unit.spec", "clean": "rm -rf ./build && rm -rf ./neardev", "build": "asb --target debug", "build:release": "asb", "asp": "asp --verbose --nologo" }, "keywords": [], "author": "hello@near.org", "license": "ISC", "devDependencies": { "near-sdk-as": "^3.1.0" } } ``` What we see here is a configuration file for our project containing the name of project, version etc. What we are interested in are ``scripts``. Those are aliases for shell commands with specific options. For example, ``clean`` is a short name for a command that deletes folders ``build`` and ``neardev``, and ``build:release`` executes AssemblyScript ``asb (build)`` command. ### asconfig.json ```json= { "workspaces": [ "src/simple", "src/singleton" ] } ``` This file is a collection of folders with our contracts in them. When we execute ``build:release`` command, we compile contracts from each workspace into the output folder. More about them next. ### src Inside ``src`` are ``simple`` and ``singleton`` - our workspaces. They have the same structure, including tests and assembly folders. The difference between them is style they're written in. #### simple We say that an AssemblyScript contract is written in the "simple style" when the index.ts file (the contract entry point) includes a series of exported functions. In this case, all exported functions become public contract methods. ```javascript=a // return the string 'hello world' export function helloWorld(): string {} // read the given key from account (contract) storage export function read(key: string): string {} // write the given value at the given key to account (contract) storage export function write(key: string, value: string): string {} // private helper method used by read() and write() above private storageReport(): string {} ``` #### singleton We say that an AssemblyScript contract is written in the "singleton style" when the index.ts file (the contract entry point) has a single exported class (the name of the class doesn't matter) that is decorated with @nearBindgen. In this case, all methods on the class become public contract methods unless marked private. Also, all instance variables are stored as a serialized instance of the class under a special storage key named STATE. AssemblyScript uses JSON for storage serialization. ```javascript=a @nearBindgen export class Contract { // return the string 'hello world' helloWorld(): string {} // read the given key from account (contract) storage read(key: string): string {} // write the given value at the given key to account (contract) storage @mutateState() write(key: string, value: string): string {} // private helper method used by read() and write() above private storageReport(): string {} } ``` :::warning :warning: **Warning:** be careful when creating a new workspace - Don't forget to add it's location to ``asconfig.json`` - Your workspace **must** have ``assembly`` folder and ``index.ts`` file! ::: ### scripts Those are command line scenarios that recreate some certain behaviour using the contracts in this project. We're using them in the next section. :::info :Book: **Note:** Use OS of your preference, however, Windows users should take in consideration that you should launch your scripts not via PowerShell or cmd, use **Git Bash** instead. ::: :::warning :Warning: **Warning:** Mac with M1 chip has compatibility issues with WASM. ::: ## Building Let's say it once again, to build contracts in your workspaces execute ``yarn build:release``. You should see: ```shell=a $ yarn build:release yarn run v1.22.15 $ asb Done in 14.25s. ``` Great! You may notice creation of a new folder in our project called ``build`` that contains subfolder ``release``. ``release`` has 2 files: ``simple.wasm`` and ``singleton.wasm``. Those Wasm (WebAssembly) files are ready to be deployed to the NEAR network. Let's do it. ## Deploying To deploy our contract we will use NEAR CLI. Take a look at commands [here](https://github.com/near/near-cli#overview). After we're going to deploy our contracts to testnet using two different ways. ### ``dev-deploy`` The very first and quickest way to deploy a smart contract is to run ``near dev-deploy <WASM_file_path>``. We're going to work with ``singleton.wasm`` which path is ``./build/release/singleton.wasm/``. Our command will look like ``near dev-deploy ./build/release/simple.wasm``. ```shell=a $ near dev-deploy ../build/release/simple.wasm Starting deployment. Account id: dev-1634461056712-80360389036896, node: https://rpc.testnet.near.org, helper: https://helper.testnet.near.org, file: ../build/release/simple.wasm Transaction Id AJUDp6HrJhzwRsvnaSDFuuaWKW8kLzCBK4xy26BnzfQv To see the transaction in the transaction explorer, please open this url in your browser https://explorer.testnet.near.org/transactions/AJUDp6HrJhzwRsvnaSDFuuaWKW8kLzCBK4xy26BnzfQv Done deploying to dev-1634461056712-80360389036896 ``` :::warning :warning: **Warning:** the command above will only run from project root folder (``starter--near-sdk-as``). ::: :::danger :warning: **Error: ENOENT: no such file or directory** This error means that your path to WASM file is incorrect. ::: At this point one thing has happened that may have been unnoticed by you just yet. Now you will have a ``neardev`` subfolder in the project. ``dev-account`` file has a name of account to which we deployed a few moments ago. :::info :Book: **Note:** run ``cat ./neardev/dev-account`` to make sure that you have seen this account ID in console when deploying. ::: ### ``deploy`` Now we will deploy the contract to a specific account - to your testnet. Firstly, we have to log into our account. Run ``near login``. ```shell=a $ near login Please authorize NEAR CLI on at least one of your accounts. If your browser doesn't automatically open, please visit this URL https://wallet.testnet.near.org/login/?title=NEAR+CLI&public_key=<public_key> Please authorize at least one account at the URL above. ``` Check your browser. There should be a new page opened. Follwing steps are common to do, so you will get used to them extremely quickly. Following example logging into ``d3mage-dev.testnet`` account. ![](https://i.imgur.com/VF73yaa.png) ![](https://i.imgur.com/6wf8Dmr.png) :::warning :warning: **Note:** always check what site is asking for access and what type of access it is. dApps usually use *function access* key. ::: When you see a blank page in browser - you're good to return to a terminal. Enter your account name into command line. ```shell=a Which account did you authorize for use with NEAR CLI? Enter it here: d3mage-dev.testnet Logged in as [ d3mage-dev.testnet ] with public key [ ed25519:6aA1xx... ] successfully ``` After you've logged in you're able run the following command: ``near deploy --accountId <account_name> --wasmFile <WASM_file_path>`` For example, ``near deploy --accountId d3mage-dev.testnet --wasmFile ./build/release/singleton.wasm`` ```shell=a $ near deploy --accountId d3mage-dev.testnet --wasmFile ./build/release/singleton.wasm Starting deployment. Account id: d3mage-dev.testnet, node: https://rpc.testnet.near.org, helper: https://helper.testnet.near.org, file: ./build/release/singleton.wasm Transaction Id 6hv4bsfL4SSp9SGcwiTBCUuZxHucYmzLcAuVWsDdrk3d To see the transaction in the transaction explorer, please open this url in your browser https://explorer.testnet.near.org/transactions/6hv4bsfL4SSp9SGcwiTBCUuZxHucYmzLcAuVWsDdrk3d Done deploying to d3mage-dev.testnet ``` Check the link above to see transaction details. ### Difference between ``dev-deploy`` and ``deploy`` |Characteristics|``dev-deploy``|``deploy``| |:---------------:|:-------------:|:--------:| |General|Creates an account and deploys to it|Deploys to a provided account| |Arguments|WASM file|WASM file, accountId| |Access key|No access key|Full access key| |Network|Only testnet|No restrictions| # Further learning - [More on accounts](https://docs.near.org/docs/concepts/account#accounts-and-contracts) - [More on access keys](https://docs.near.org/docs/concepts/account#access-keys) - [Challenge: Managing keys with NEAR shell](https://github.com/near-examples/workshop--exploring-near-apis/blob/master/challenges/managing-keys-with-near-shell.md)