- Docs
- Developers
- Store and instantiate a contract with arch3.js
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:
- Install Node.js on your system
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
- 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";
- Configure dotenv:
dotenv.config();
- Create the main function which will contain the lines of code below:
async function main() {}
- Set up the network data:
mainnet
testnet
const network = { chainId: 'archway-1', endpoint: 'https://rpc.mainnet.archway.io', prefix: 'archway',};
- 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();
- Set account and beneficiary addresses:
const accountAddress = accounts[0].address;const beneficiaryAddress = process.env.BENEFICIARY_ADDRESS;
- Create the SigningArchwayClient using connectWithSigner method.
const signingClient = await SigningArchwayClient.connectWithSigner(network.endpoint, wallet);
- 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);
- 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
- Retrieve the code ID for the stored contract:
const codeId = uploadResult.codeId;
- 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};
- Broadcast and sign the transaction with the signing client:
const instantiateResult = await signingClient.instantiate( accountAddress, codeId, msg, 'my-instance-label', 'auto', instantiateOptions);
- 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);}
- 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.