This site requires Javascript to be enabled.

Store and instantiate a contract with arch3.js

This tutorial will guide you through the process of storing and instantiating a contract using arch3.js. In this example, you will use the hackatom.wasm compiled contract. You can find the contract source code here.

You can also use your own compiled contract if you prefer.

Prerequisites

Before moving forward, ensure that you have completed the following prerequisites:

Create a new NPM project

Create a folder to store your project, and within that folder, execute the following command to initialize an NPM project:

npm init -y

A default package.json file is generated with a structure similar to the following:

{  "name": "test-project",  "version": "1.0.0",  "description": "",  "main": "index.js",  "scripts": {    "test": "echo \"Error: no test specified\" && exit 1"  },  "compilerOptions": {    "module": "CommonJS"  },  "author": "",  "license": "MIT"}

Add "type": "module", to the package.json file to enable the use of ES6 module import syntax in your Node.js application.

Install required packages

Execute the following command to install arch3.js:

npm install --save @archwayhq/arch3.js

Execute the following command to install the base64-js library, which is used to encode the compiled contract to base64 and then convert it to a ByteArray:

npm install --save base64-js

Execute the following command to install the dotenv library, which will be used for reading your mnemonic stored in a ".env" file:

npm install --save dotenv

Create .env file

Create a ".env" file that will be used to store your mnemonic and allows for not saving this sensitive information to your source control. In the ".env" file, add the following:

MNEMONIC="enter mnemonic here"
BENEFICIARY_ADDRESS="enter your archway beneficiary wallet address here"

You can now add your .env file to your .gitignore file so it’s not added to source control.

Create index.js file

In the root of your project folder create an index.js file. This file will contain the entire script that will be executed to complete the Store and Instantiate transactions.

Download compiled contract

Download the hackathon.wasm compiled contract and store it in the root of your project.

Script breakdown

Store contract

  1. Import the necessary dependencies in your index.js file:
import { SigningArchwayClient } from '@archwayhq/arch3.js';import { DirectSecp256k1HdWallet } from "@cosmjs/proto-signing";import fs from 'fs';import * as base64js from "base64-js";import dotenv from "dotenv";
  1. Configure dotenv:
dotenv.config();
  1. Create the main function which will contain the lines of code below:
async function main() {}
  1. Set up the network data:

mainnet

testnet

const network = {  chainId: 'archway-1',  endpoint: 'https://rpc.mainnet.archway.io',  prefix: 'archway',};
  1. Set up your wallet using your mnemonic:
const mnemonic = process.env.MNEMONIC;const wallet = await DirectSecp256k1HdWallet.fromMnemonic(mnemonic, { prefix: network.prefix });const accounts = await wallet.getAccounts();
  1. Set account and beneficiary addresses:
const accountAddress = accounts[0].address;const beneficiaryAddress = process.env.BENEFICIARY_ADDRESS;
  1. Create the SigningArchwayClient using connectWithSigner method.
const signingClient = await SigningArchwayClient.connectWithSigner(network.endpoint, wallet);
  1. Perform the following steps to read the file, encode it to base64, and convert it to a ByteArray:
const wasmCode = fs.readFileSync('./hackatom.wasm');const encoded = Buffer.from(wasmCode, 'binary').toString('base64');const contractData = base64js.toByteArray(encoded);
  1. Broadcast and sign the transaction with the signing client:
const uploadResult = await signingClient.upload(  accountAddress,  contractData,  'auto',  '',);if (uploadResult.code !== undefined && uploadResult.code !== 0) {  console.log("Storage failed:", uploadResult.log || uploadResult.rawLog);} else {  console.log("Storage successful:", uploadResult.transactionHash);}

Instantiate contract

  1. Retrieve the code ID for the stored contract:
const codeId = uploadResult.codeId;
  1. Create a msg object to instantiate the contract. You can also add some instantiation options:

mainnet

testnet

const msg = {  verifier: accountAddress,   beneficiary: beneficiaryAddress,};const instantiateOptions = {  memo: "Instantiating a new contract",  funds: [    {      denom: 'aarch',      amount: '1000000000000000000'    }  ],  admin: accounts[0].address};
  1. Broadcast and sign the transaction with the signing client:
const instantiateResult = await signingClient.instantiate(  accountAddress,  codeId,  msg,  'my-instance-label',  'auto',  instantiateOptions);
  1. Verify if the transaction was successful by checking the broadcastResult2. This is the final lines of code for fucntion main:
if (instantiateResult.code !== undefined && instantiateResult.code !== 0) {  console.log("Instantiation failed:", instantiateResult.log || instantiateResult.rawLog);} else {  console.log("Instantiation successful:", instantiateResult.transactionHash);}
  1. Call the main function. This will be done outside of the function:
main();

Full script

mainnet

testnet

import { SigningArchwayClient } from '@archwayhq/arch3.js';import { DirectSecp256k1HdWallet } from "@cosmjs/proto-signing";import fs from 'fs';import * as base64js from "base64-js";import dotenv from "dotenv";dotenv.config();async function main() {  const network = {    chainId: 'archway-1',    endpoint: 'https://rpc.mainnet.archway.io',    prefix: 'archway',  };  // Get wallet and accounts from mnemonic  const mnemonic = process.env.MNEMONIC;  const wallet = await DirectSecp256k1HdWallet.fromMnemonic(mnemonic, { prefix: network.prefix });  const accounts = await wallet.getAccounts();  const accountAddress = accounts[0].address;  const beneficiaryAddress = process.env.BENEFICIARY_ADDRESS;  const signingClient = await SigningArchwayClient.connectWithSigner(network.endpoint, wallet);  // Upload a contract  const wasmCode = fs.readFileSync('./hackatom.wasm');  const encoded = Buffer.from(wasmCode, 'binary').toString('base64');  const contractData = base64js.toByteArray(encoded);  const uploadResult = await signingClient.upload(    accountAddress,    contractData,    'auto',    '',  );  if (uploadResult.code !== undefined && uploadResult.code !== 0) {    console.log("Storage failed:", uploadResult.log || uploadResult.rawLog);  } else {    console.log("Storage successful:", uploadResult.transactionHash);  }  // Instantiate a contract  const codeId = uploadResult.codeId;  const msg = {    verifier: accountAddress,     beneficiary: beneficiaryAddress,  };  const instantiateOptions = {    memo: "Instantiating a new contract",    funds: [      {        denom: 'aarch',        amount: '1000000000000000000'      }    ],    admin: accounts[0].address  };  const instantiateResult = await signingClient.instantiate(    accountAddress,    codeId,    msg,    'my-instance-label',    'auto',    instantiateOptions  );  if (instantiateResult.code !== undefined && instantiateResult.code !== 0) {    console.log("Instantiation failed:", instantiateResult.log || instantiateResult.rawLog);  } else {    console.log("Instantiation successful:", instantiateResult.transactionHash);  }}main();

Execute script

Navigate to the root of your project folder in the terminal and run the following command:

node index.js

Clone and try it yourself

You can find a working example of this Node.js app in the dapp examples (Store and Instantiate) repository.