Skip to main content

Building a dApp frontend

For building web frontends, you'll need the following npm packages to connect your web page to Archway Network.

@cosmjs/stargate#

@cosmjs/stargate is client library for the Cosmos SDK.

@cosmjs/cosmwasm-stargate#

@cosmjs/cosmwasm-stargate is an SDK to build CosmWasm clients. It extends @cosmjs/stargate with functionality for CosmWasm contracts.

Connecting to Archway#

We’ll need our dApp to connect to users’ wallets with a browser extension like Keplr wallet.

After installing the extension, you’ll notice Keplr is exposed to web pages as a property of the JavaScript window object of the active page.

Keplr also needs some metadata about the chain it’s connecting to, and the type of contracts stored there. Here's the parameters you'll need to connect to Archway’s Constantine testnet and enable CosmWasm smart contracts.

const ChainInfo = {  chainId: "constantine-1",  chainName: "Constantine Testnet",  rpc: "https://rpc.constantine-1.archway.tech" ,  rest: "https://api.constantine-1.archway.tech",  stakeCurrency: {coinDenom: "CONST",coinMinimalDenom: "uconst",coinDecimals: 6},  bip44: {coinType: 118},  bech32Config: {bech32PrefixAccAddr: "archway",bech32PrefixAccPub: "archwaypub",bech32PrefixValAddr: "archwayvaloper",bech32PrefixValPub: "archwayvaloperpub",bech32PrefixConsAddr: "archwayvalcons",bech32PrefixConsPub: "archwayvalconspub"  },  currencies: [{coinDenom: "CONST",coinMinimalDenom: "uconst",coinDecimals: 6}],  feeCurrencies: [{coinDenom: "CONST",coinMinimalDenom: "uconst",coinDecimals: 6}],  coinType: 118,  gasPriceStep: {low: 0,average: 0.1,high: 0.2},  features: ['cosmwasm']};

Now we can use ChainInfo to set up Keplr for Constantine testnet.

import { SigningCosmWasmClient } from '@cosmjs/cosmwasm-stargate';import { GasPrice } from "@cosmjs/stargate"; let accounts, CosmWasmClient, queryHandler, gasPrice;
async function connectKeplrWallet() {  if (window['keplr']) {    if (window.keplr['experimentalSuggestChain']) {      await window.keplr.experimentalSuggestChain()      await window.keplr.enable(ChainInfo.chainId);      const offlineSigner = await window.getOfflineSigner(ChainInfo.chainId);      CosmWasmClient = await SigningCosmWasmClient.connectWithSigner(ChainInfo.rpc, offlineSigner);           // This async waits for the user to authorize your dApp      // it returns their account address only after permissions      // to read that address are granted      accounts = await this.offlineSigner.getAccounts();       queryHandler = CosmWasmClient.queryClient.wasm.queryContractSmart;      // Gas price      gasPrice = GasPrice.fromString('0.002uconst');       console.log('Wallet connected', {        offlineSigner: offlineSigner,        CosmWasmClient: CosmWasmClient,        accounts: accounts,        chain: ChainInfo,        queryHandler: queryHandler,        gasPrice: gasPrice      });    } else {      console.warn('Error accessing experimental features, please update Keplr');    }  } else {    console.warn('Error accessing Keplr, please install Keplr');  }};

Querying the counter#

In the previous step we saved a reference to CosmWasmClient.queryClient.wasm.queryContractSmart. We'll use it to query our QueryMsg::GetCount entrypoint of the Increment contract.

Just like when we queried from CLI, we need to convert entrypoints to lowercase and snake case. In JavaScript the arguments become {get_count: {}}.

const getCount = async () => {  // Your contract address  const ContractAddress = process.env.CONTRACT_ADDRESS;  // Query arguments  let entrypoint = {    get_count: {}  };  // Do query type 'smart'  let queryResult = await queryHandler.query(ContractAddress, entrypoint);  console.log('GetCount Query', queryResult);},

Incrementing the counter#

To broadcast transactions we call the execute function using our previous CosmWasmClient reference. We call this function with the following parameters:

  1. userAddress - the address broadcasting the transaction
  2. ContractAddress - the address of the contract the user is transacting with
  3. entrypoint - arguments to be executed which match an entrypoint in the contract
  4. txFee - transaction fees calculated by the calculateFee function from @cosmjs/stargate

We convert the case of entrypoint arguments to lowercase and snake case again, so ExecuteMsg::Increment {} from our Rust contract becomes {increment: {}} in our JavaScript.

import { calculateFee } from "@cosmjs/stargate";
const incrementCounter = async () => {  // Your contract address  const ContractAddress = process.env.CONTRACT_ADDRESS;  // Tx arguments  let entrypoint = {    increment: {}  };  // Gas fee estimation  let txFee = calculateFee(300000, gasPrice);  // Send Tx  let tx = await CosmWasmClient.execute(userAddress, ContractAddress, entrypoint, txFee);  console.log('Increment Tx', tx);}

Clone it and try yourself#

You'll find working examples of dApp frontends for the Increment starter code template in the dApp examples repository. Examples are given in both Vue.js and React.