QubicTypeScript

callContractFunction

The underlying primitive for calling contract read functions — use it when no generated caller covers what you need.

callContractFunction(options)

All generated callers are thin wrappers around callContractFunction. Call it directly when you need to query a contract that isn't in the generated package yet — for example, a freshly deployed contract whose ABI hasn't been added to the registry snapshot.

import { callContractFunction } from "@qubic.org/contracts"
import { buildPayload, decodePayload } from "@qubic.org/registry"
import { identityToPublicKey, publicKeyToIdentity } from "@qubic.org/crypto"
import { createLiveClient } from "@qubic.org/rpc"

const live = createLiveClient()

const result = await callContractFunction({
  live,
  contractIndex: 42,
  inputType: 1,
  inputSize: 4,
  inputFields: [{ name: "epoch", type: "uint32", offset: 0, byteLength: 4 }],
  outputFields: [{ name: "state", type: "uint32", offset: 0, byteLength: 4 }],
  structs: {},
  input: { epoch: 213 },
})

if (result.ok) {
  console.log("State:", result.value.state)
} else {
  console.error("Error:", result.error.status, result.error.message)
}

Options

NameTypeDescription
liveSmartContractCallerAny object with querySmartContract. Typically from createLiveClient().
contractIndexnumberContract index on-chain.
inputTypenumberFunction input type number from the ABI.
inputSizenumberTotal byte length of the encoded input.
inputFieldsBinaryField[]Field definitions for encoding the input. From @qubic.org/registry.
outputFieldsBinaryField[]Field definitions for decoding the response. From @qubic.org/registry.
structsRecord<string, NamedStruct>Named struct definitions referenced by fields. Pass {} if none.
inputRecord<string, unknown>Input values — must match the field names in inputFields.
identityToPublicKey(id: string) => Uint8ArrayRequired when input contains id-type fields.
publicKeyToIdentity(pk: Uint8Array) => stringRequired when output contains id-type fields.

Returns Promise<Result<TOutput, QubicRpcError>>


When to use this

Use callContractFunction when:

  • A contract was deployed after the last registry snapshot, so no generated wrapper exists yet.
  • You need a function from an older ABI version that has since been replaced.
  • You're writing your own code generator and need the underlying primitive to test it.

For all contracts in the current generated package, use the namespace callers directly — they handle field definitions internally.


Using the registry for field definitions

When the contract ABI is available in @qubic.org/registry, use getAbi and getFunction to retrieve field definitions rather than writing them by hand:

import { callContractFunction } from "@qubic.org/contracts"
import { getAbi, getFunction } from "@qubic.org/registry"
import { identityToPublicKey, publicKeyToIdentity } from "@qubic.org/crypto"
import { createLiveClient } from "@qubic.org/rpc"
import registry from "@qubic.org/registry/registry.json"
import type { ContractRegistry } from "@qubic.org/registry"

const reg = registry as ContractRegistry
const live = createLiveClient()

// Look up field definitions from the registry
const { version } = getAbi(reg, 42, 213)  // contractIndex, epoch
const fn = getFunction(version, 1)          // inputType

const result = await callContractFunction({
  live,
  contractIndex: 42,
  inputType: fn.inputType,
  inputSize: fn.inputSize,
  inputFields: fn.inputFields,
  outputFields: fn.outputFields,
  structs: version.structs ?? {},
  input: { someField: 42 },
  identityToPublicKey,
  publicKeyToIdentity,
})

if (result.ok) {
  console.log("Output:", result.value)
} else {
  console.error("Error:", result.error.status, result.error.message)
}

On this page