The InitiaJS SDK offers a powerful LCDClient that simplifies the process of querying data from both the Initia L1 and rollups. This client encapsulates various endpoints and methods into user-friendly helper functions, organized under sub-categories of the lcd client based on their corresponding Cosmos SDK modules.

In this tutorial, we’ll explore several examples demonstrating how to leverage these helper functions to retrieve key data points efficiently using the SDK.

For demonstration purposes, we will assume that all of these examples are implemented in a file named src/query.ts.

Querying Account Balance

To query the balance of an account, we can use the balance function from the bank module. This function takes in an address and returns the balance of the account.

First, we will make the necessary imports and initialize the LCDClient.

import { LCDClient, Coin } from '@initia/initia.js';

const lcdUrl = 'https://lcd.testnet.initia.xyz';
const lcd: LCDClient = new LCDClient(lcdUrl, {
    chainId: '[chain-id]',
    gasPrices: '0.15uinit', // default gas prices
    gasAdjustment: '2.0',   // default gas adjustment for fee estimation
});
Adjust gasPrices and gasAdjustment according to current network conditions for optimal transaction processing.

Next, we will create a function to query the balance of an account. This function will take in an address and return the balance of the account.

Note that response from the query is paginated, so we need to handle the pagination properly in the function. Specifically, response that are paginated will return a next_key in the pagination object, which we can use to get the next page of results. We will then keep looping through the results until we have all the pages, which we will know is the case when next_key is null.

async function queryBalance(address: string) {
  let allCoins: Coin[] = [];
  let nextKey: string | null = null;

  do {
    const [coins, pagination] = await lcd.bank.balance(address, { 'pagination.key': nextKey || undefined });
    allCoins = [...allCoins, ...coins];
    nextKey = pagination.next_key || null;
  } while (nextKey);

  console.log(`${address} has:`);
  allCoins.forEach((coin: Coin) => {
    console.log(`- ${coin.amount.toString()} ${coin.denom}`);
  });
}

We can then call the function with an address to query the balance of the account.

queryBalance('init1w4cqq6udjqtvl5xx0x6gjeyzgwtze8c05kysnu');

If successful, you should see an output similar to the following:

init1w4cqq6udjqtvl5xx0x6gjeyzgwtze8c05kysnu has:
- 721662 move/944f8dd8dc49f96c25fea9849f16436dcfa6d564eec802f3ef7f8b3ea85368ff
- 1000000 uinit

Complete Example

src/query.ts
import { LCDClient, Coin } from '@initia/initia.js';

const lcdUrl = 'https://lcd.testnet.initia.xyz';
const lcd: LCDClient = new LCDClient(lcdUrl, {});

async function queryBalance(address: string) {
  let allCoins: Coin[] = [];
  let nextKey: string | null = null;

  do {
    const [coins, pagination] = await lcd.bank.balance(address, { 'pagination.key': nextKey || undefined });
    allCoins = [...allCoins, ...coins];
    nextKey = pagination.next_key || null;
  } while (nextKey);

  console.log(`${address} has:`);
  allCoins.forEach((coin: Coin) => {
    console.log(`- ${coin.amount.toString()} ${coin.denom}`);
  });
}

queryBalance('init1w4cqq6udjqtvl5xx0x6gjeyzgwtze8c05kysnu');

VM-Agnostic Queries

VM-agnostic queries are queries that can be used across all VMs.

  • balance() : query the balance of an account
const balances = await lcd.bank.balance('init14l3c2vxrdvu6y0sqykppey930s4kufsvt97aeu')
  • blockInfo(): query the block information
const blockInfo = await lcd.tendermint.blockInfo(10000) // If no height is given, the latest block is returned. 
  • txInfo(): query the transaction information
const txInfo = await lcd.tx.txInfo('6DFEE8E4BFC38341E8AADBD74A23588D8DE94FA38052CB5721DDA780A24F8B1D')
  • price(): query the oracle price
const currenyPair = new CurrencyPair('BTC', 'USD')
const price = await lcd.oracle.price(currenyPair)

VM-Specific Queries

MoveVM

  • viewfunction(): query the move contract view functions
// `object.move`
// 
// #[view]
// public fun owner<T: key>(object: Object<T>): address acquires ObjectCore {
//     ...
// }

const res = await lcd.move.viewFunction(
    '0x1',                                               // owner of the module
    'object',                                            // name of the module
    'owner',                                             // function name
    ["0x1::object::ObjectCore"],                         // type arguments
    [
        bcs.object().serialize('0xc4f0b3c2300c99b0d7717ce43cd76821407a34c79587542919876a8c241a2f94').toBase64(),
    ]                                                    // arguments
)
  • viewJSON(): query the move contract view functions with JSON arguments
const res = await lcd.move.viewJSON(
    '0x1',                                               // owner of the module
    'object',                                            // name of the module
    'owner',                                             // function name
    ["0x1::object::ObjectCore"],                         // type arguments
    [
        `"0xc4f0b3c2300c99b0d7717ce43cd76821407a34c79587542919876a8c241a2f94"`,
    ]                                                    // arguments
)
  • resources(): query the move contract resources
const resources = await lcd.move.resources('0x1')
const resource = await lcd.move.resource('0x1', '0x1::code::ModuleStore')
  • modules(): query the move contract modules
const modules = await lcd.move.module('0x1')
const module = await lcd.move.module('0x1', 'object')
  • tableInfo(): query the move contract table info
const tableHandle = '0xc8c40eef193fc150fcb54264419bd3e39339c2ee8ba5834aed7826a9841cfb53'
const entryKeyBytes = 'A0vD7ATVOvfCWo1T7H8Pz2MOt5k6rvsScYEGgXe0QDw='

const tableInfo = await lcd.move.tableInfo(tableHandle)
const tableEntries = await lcd.move.tableEntries(tableHandle)
const tableEntry = await lcd.move.tableEntry(tableHandle,entryKeyBytes)

WasmVM

  • contractInfo(): query the wasm contract info
const contractInfo = await lcd.wasm.contractInfo('init14mv62l7x4ducykg0crfa9a22egf8yrltmxzy84zn0wqgmr496jqs5z7k0c')
const contracts = await lcd.wasm.contractsByCode(1) 
  • smartContractState(): query the wasm smart contract state
const contractState = await lcd.wasm
  .smartContractState(
    'init1jue5rlc9dkurt3etr57duutqu7prchqrk2mes2227m52kkrual3qdrydg6',  // contract address
    Buffer.from(
      JSON.stringify({                                                  // query data 
        get_stage_info: {
            stage: 1,
        },
      })
    ).toString('base64')
  )
const allContractStates = await lcd.wasm.allContractState('init14mv62l7x4ducykg0crfa9a22egf8yrltmxzy84zn0wqgmr496jqs5z7k0c')

EVM

  • call(): query the evm contract
const contractInfo = JSON.parse(
  fs
    .readFileSync(
      '../solidity/evm-example/artifacts/contracts/example.sol/example.json' // path of build response
    )
    .toString()
);
const contract = new ethers.Contract(contractAddress, contractInfo.abi)

const res = await lcd.evm
  .call(
    'init1jvxywa6dmdxumr9nhdez838af06f9v42w0rd26',    // sender
    '0x16e999092BF37913a3eff185949997b6f7bd698c',     // contract_addr
    contract.interface.encodeFunctionData(
      'getPoints', [2, 0, 10]                         // hex encoded execution input bytes
    ).slice(2),
    false                                             // whether to return the trace
  )