Sending a Query

Instructions for sending an on-chain query into Axiom.

Build a query

Once the Axiom instance is initialized, build a new query by constructing a QueryBuilder:
const qb = ax.newQueryBuilder();
Our initial release allows queries with up to 64 pieces of on-chain data. Each piece of on-chain data is specified by blockNumber(required), address (optional), and slot (optional), which parametrize block headers, accounts, and account storage, respectively.
To create a query, add these to the QueryBuilder using the append method. If you need help finding the storage slot corresponding to a contract variable, see our page on finding storage slots or look up the relevant storage slot at
const UNI_V2_ADDR = "0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f";
await qb.append({blockNumber: 9221736});
await qb.append({blockNumber: 9221524, address: UNI_V2_ADDR});
await qb.append({blockNumber: 9221524, address: UNI_V2_ADDR, slot: 0});
await qb.append({blockNumber: 9221524, address: UNI_V2_ADDR, slot: 1});
The append function will validate the value at the slot. An error will be thrown if you attempt to read from a slot at an account that has not yet been created. Please note that blockNumbers on Goerli are in a different range than those on Mainnet, and contracts may have been deployed on one network but not the other.

Prepare the query

Once you are done, call the build method on the QueryBuilder to assemble your query in the correct format to be sent on-chain. This will result in two identifiers keccakQueryResponse and queryHash which are associated to the query on- and off-chain, respectively.
const {keccakQueryResponse, queryHash, query} = await;
This format consists of three pieces:
  • keccakQueryResponse: A Merkle-ized commitment to the query used as a unique identifier.
  • queryHash: A keccak256 hash of the query.
  • query : A complete specification of the query used as calldata.

Submit query onchain

The sendQuery function in the AxiomV1Query contract allows users to trustlessly query historic on-chain data. Make sure you have ethers installed and configured before continuing.
Then, build and send a query transaction using the output of QueryBuilder in the previous step:
const txResult = await axiomV1Query.sendQuery(
value: ethers.parseEther("0.01"), // Goerli payment value
const txReceipt = await txResult.wait();
This query transaction includes a payment of 0.01 ETH to be collected upon query fulfillment. See Fees for more information about fees and refunds.