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 ArchwayWe’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 counterIn 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 counterTo broadcast transactions we call the execute
function using our previous CosmWasmClient
reference. We call this function with the following parameters:
- userAddress - the address broadcasting the transaction
- ContractAddress - the address of the contract the user is transacting with
- entrypoint - arguments to be executed which match an entrypoint in the contract
- 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 yourselfYou'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.
- Vue.js
- React