Skip to content

ChainClient (Layer 2)

Layer 2 of the SDK talks directly to a Dilithia RPC node over HTTP. No wallet extension is required -- you only need an rpcUrl.

Use the ChainClient for read-only operations: checking balances, querying contracts, estimating gas, fetching receipts, and inspecting the shielded pool's on-chain state.


Creating a ChainClient

createChainClient(rpcUrl)

Factory function that returns a new ChainClient instance.

function createChainClient(rpcUrl: string): ChainClient
Parameter Type Description
rpcUrl string The RPC endpoint URL

Returns: A ChainClient instance.

import { createChainClient } from "@dilithia/browser-sdk";

// Use the rpcUrl from a wallet session
const session = await connect();
const chain = createChainClient(session.rpcUrl);

// Or provide your own
const chain = createChainClient("https://rpc.dilithia.network/rpc");

Account and Network

getBalance(address)

Get the native token balance for an address.

async getBalance(address: string): Promise<BalanceResult>
Parameter Type Description
address string Account address

Returns: BalanceResult with balance and address.

const { balance } = await chain.getBalance("dili1alice");
console.log("Balance:", balance, "DILI");

getNonce(address)

Get the current nonce for an account.

async getNonce(address: string): Promise<number>
Parameter Type Description
address string Account address

Returns: The next nonce as a number.

const nonce = await chain.getNonce("dili1alice");
console.log("Next nonce:", nonce);

getNetworkInfo()

Get information about the current network.

async getNetworkInfo(): Promise<NetworkInfo>

Returns: NetworkInfo derived from qsc_chain, qsc_head, and qsc_baseFee. Today networkId mirrors chainId and networkLabel is usually null unless a higher layer adds branding.

const info = await chain.getNetworkInfo();
console.log(`Chain ${info.chainId} at block ${info.blockHeight}, base fee ${info.baseFee}`);

chainId()

Convenience method that returns just the chain ID string.

async chainId(): Promise<string>

Returns: The chain ID string.

const id = await chain.chainId();
console.log("Chain ID:", id);

Queries

queryContract(contract, method, args?)

Query a contract (read-only). No signing, no gas cost.

async queryContract(
  contract: string,
  method: string,
  args?: Record<string, unknown>,
): Promise<unknown>
Parameter Type Description
contract string Contract address or name
method string Method to call
args Record<string, unknown> (optional) Method arguments

Returns: The return value from the contract method. The client unwraps the { ok, result } envelope returned by qsc-rs /query.

const totalSupply = await chain.queryContract("token", "totalSupply");

const allowance = await chain.queryContract("token", "allowance", {
  owner: "dili1alice",
  spender: "dili1dex",
});

Simulation and Gas

simulateCall(call)

Simulate a contract call without submitting it. Useful for previewing results or validating inputs.

async simulateCall(call: Record<string, unknown>): Promise<unknown>
Parameter Type Description
call Record<string, unknown> The call to simulate

Returns: The simulated result.

const result = await chain.simulateCall({
  contract: "token",
  method: "transfer",
  args: { to: "dili1bob", amount: 100 },
});
console.log("Simulation result:", result);

estimateGas(call)

Estimate gas cost for a call before submitting.

async estimateGas(call: Record<string, unknown>): Promise<GasEstimate>
Parameter Type Description
call Record<string, unknown> The call to estimate

Returns: GasEstimate with gasLimit, baseFee, and estimatedCost.

Note: this currently follows the node gas oracle (qsc_gasEstimate) and returns a network estimate, not a per-call execution trace.

const estimate = await chain.estimateGas({
  contract: "token",
  method: "transfer",
  args: { to: "dili1bob", amount: 100 },
});
console.log("Estimated cost:", estimate.estimatedCost, "DILI");

Receipts and History

getReceipt(txHash)

Fetch the receipt for a completed transaction.

async getReceipt(txHash: string): Promise<Receipt>
Parameter Type Description
txHash string The transaction hash

Returns: Receipt with status, block height, gas used, and fee paid.

Throws: If the transaction has not been included in a block yet.

const receipt = await chain.getReceipt("0xabc123...");
console.log("Status:", receipt.status);

waitForReceipt(txHash, maxAttempts?, delayMs?)

Poll for a transaction receipt until it appears or timeout.

async waitForReceipt(
  txHash: string,
  maxAttempts?: number,  // default: 30
  delayMs?: number,      // default: 2000
): Promise<Receipt>
Parameter Type Description
txHash string The transaction hash
maxAttempts number (optional) Maximum polling attempts. Default 30.
delayMs number (optional) Delay between attempts in ms. Default 2000.

Returns: Receipt once the transaction is confirmed.

Throws: Error if the receipt is not found after maxAttempts attempts.

const receipt = await chain.waitForReceipt(tx.txHash);
console.log("Confirmed at block", receipt.blockHeight);

Custom timeout (60 attempts, 1 s apart = 60 s max):

const receipt = await chain.waitForReceipt(tx.txHash, 60, 1000);

getTransactionHistory(address, limit?, cursor?)

Fetch transaction history for an account.

async getTransactionHistory(
  address: string,
  limit?: number,   // default: 20
  cursor?: number,  // default: 0
): Promise<TransactionHistoryPage>
Parameter Type Description
address string Account address
limit number (optional) Number of records to return. Default 20.
cursor number (optional) Cursor for the next page. Default 0.

Returns: A TransactionHistoryPage with txHashes, count, and nextCursor.

const history = await chain.getTransactionHistory("dili1alice");
console.log(history.txHashes, history.nextCursor);

Paginated:

const page2 = await chain.getTransactionHistory("dili1alice", 20, 20);

Shielded Pool (Read-Only)

These methods query on-chain shielded pool state. They do not require a wallet.

getCommitmentRoot()

Get the current Merkle root of the shielded pool commitment tree.

async getCommitmentRoot(): Promise<string>

Returns: The commitment root hash as a string.

const root = await chain.getCommitmentRoot();
console.log("Commitment root:", root);

isNullifierSpent(nullifier)

Check whether a nullifier has already been spent (used in a withdrawal).

async isNullifierSpent(nullifier: string): Promise<boolean>
Parameter Type Description
nullifier string The nullifier hash to check

Returns: true if the nullifier has been spent.

const spent = await chain.isNullifierSpent(withdrawal.nullifier);
if (spent) {
  console.log("This commitment has already been withdrawn.");
}

Name Service (Read-Only)

These methods query the on-chain name service. They do not require a wallet.

resolveName(name)

Resolve a name to its target address.

async resolveName(name: string): Promise<NameRecord>
Parameter Type Description
name string The name to resolve

Returns: NameRecord with name and address.

const record = await chain.resolveName("alice");
console.log("Address:", record.address);

reverseResolveName(address)

Reverse-resolve an address to its registered name.

async reverseResolveName(address: string): Promise<NameRecord>
Parameter Type Description
address string The address to reverse-resolve

Returns: NameRecord with name and address.

const record = await chain.reverseResolveName("dili1abc");
console.log("Name:", record.name);

isNameAvailable(name)

Check whether a name is available for registration.

async isNameAvailable(name: string): Promise<boolean>
Parameter Type Description
name string The name to check

Returns: true if the name is available.

const available = await chain.isNameAvailable("alice");
if (available) {
  console.log("Name is available!");
}

lookupName(name)

Look up detailed information about a registered name.

async lookupName(name: string): Promise<NameRecord>
Parameter Type Description
name string The name to look up

Returns: NameRecord with name, address, owner, and target.

const record = await chain.lookupName("alice");
console.log("Owner:", record.owner, "Target:", record.target);

getNameRecords(name)

Get all key-value records associated with a name.

async getNameRecords(name: string): Promise<Record<string, string>>
Parameter Type Description
name string The name to query

Returns: An object mapping record keys to their values.

const records = await chain.getNameRecords("alice");
console.log("Display name:", records.display_name);

getNamesByOwner(owner)

Get all names owned by an address.

async getNamesByOwner(owner: string): Promise<NameRecord[]>
Parameter Type Description
owner string The owner address

Returns: Array of NameRecord objects.

const names = await chain.getNamesByOwner("dili1abc");
names.forEach((n) => console.log(n.name));

getRegistrationCost(name)

Get the registration cost for a name.

async getRegistrationCost(name: string): Promise<RegistrationCost>
Parameter Type Description
name string The name to check

Returns: RegistrationCost with name, cost, and duration.

const cost = await chain.getRegistrationCost("alice");
console.log("Cost:", cost.cost, "Duration:", cost.duration);

Credentials (Read-Only)

These methods query on-chain credential state. They do not require a wallet.

getCredential(commitment)

Fetch a credential by its commitment hash.

async getCredential(commitment: string): Promise<Credential>
Parameter Type Description
commitment string The credential commitment hash

Returns: Credential with commitment, issuer, holder, schemaHash, and status.

const cred = await chain.getCredential("0xabc");
console.log("Issuer:", cred.issuer, "Status:", cred.status);

getSchema(schemaHash)

Fetch a credential schema by its hash.

async getSchema(schemaHash: string): Promise<CredentialSchema>
Parameter Type Description
schemaHash string The schema hash

Returns: CredentialSchema with name, version, and attributes.

const schema = await chain.getSchema("0xschema");
console.log("Schema:", schema.name, schema.version);

listCredentialsByHolder(holder)

List all credentials held by an address.

async listCredentialsByHolder(holder: string): Promise<Credential[]>
Parameter Type Description
holder string The holder address

Returns: Array of Credential objects.

const creds = await chain.listCredentialsByHolder("dili1holder");
creds.forEach((c) => console.log(c.commitment, c.status));

listCredentialsByIssuer(issuer)

List all credentials issued by an address.

async listCredentialsByIssuer(issuer: string): Promise<Credential[]>
Parameter Type Description
issuer string The issuer address

Returns: Array of Credential objects.

const creds = await chain.listCredentialsByIssuer("dili1issuer");
creds.forEach((c) => console.log(c.commitment, c.holder));

Multisig (Read-Only)

These methods query on-chain multisig wallet state. They do not require a wallet.

getMultisigWallet(address)

Fetch multisig wallet details.

async getMultisigWallet(address: string): Promise<MultisigWallet>
Parameter Type Description
address string The multisig wallet address

Returns: MultisigWallet with address, signers, threshold, and nonce.

const wallet = await chain.getMultisigWallet("dili1multisig");
console.log("Signers:", wallet.signers, "Threshold:", wallet.threshold);

getMultisigTx(wallet, txId)

Fetch a specific multisig transaction.

async getMultisigTx(wallet: string, txId: number): Promise<MultisigTx>
Parameter Type Description
wallet string The multisig wallet address
txId number The transaction ID

Returns: MultisigTx with txId, wallet, to, value, approvals, and executed.

const tx = await chain.getMultisigTx("dili1multisig", 0);
console.log("Approvals:", tx.approvals, "Executed:", tx.executed);

listMultisigPendingTxs(wallet)

List all pending (unexecuted) transactions for a multisig wallet.

async listMultisigPendingTxs(wallet: string): Promise<MultisigTx[]>
Parameter Type Description
wallet string The multisig wallet address

Returns: Array of MultisigTx objects.

const pending = await chain.listMultisigPendingTxs("dili1multisig");
pending.forEach((tx) => console.log("TX", tx.txId, "approvals:", tx.approvals.length));