Sending Queries with a NodeJS Script
Developers that don't need a UI for their Axiom on-chain app may want to send queries via a Node.js script. Following the information on this page requires that you previously selected the Script
choice from npx create-axiom-app
.
We give a tutorial here on how to send a query from Node.js. See SDK Reference for the full reference.
Getting started
Once you've generated the Script
scaffold of the Axiom app, you can find the script located in app/index.ts
. The main interface for a Node.js script is the Axiom
class exported from @axiom-crypto/client
. The class is instantiated via the following constructor, and then initialized.
const axiom = new Axiom({
circuit: circuit,
compiledCircuit: compiledCircuit,
chainId: "11155111", // Sepolia
provider: process.env.PROVIDER_URI_SEPOLIA as string,
privateKey: process.env.PRIVATE_KEY_SEPOLIA as string,
callback: {
target: "0x4A4e2D8f3fBb3525aD61db7Fc843c9bf097c362e",
},
});
await axiom.init();
The Axiom configuration parameters are explained here:
circuit
: the exported circuit function from your circuit file (here, it'sapp/axiom/average.circuit.ts
)compiledCircuit
: the compiled circuit json file from thenpx axiom circuit compile
commandchainId
: the chain ID that the circuit will read its on-chain data fromprovider
: a node provider (such as Quicknode, Alchemy, Infura); should be hidden and specified in the.env
fileprivateKey
: your test account's private key; should be hidden and specified in the.env
filecallback
: callback datatarget
: address of the smart contract that will receive the callback (your contract)extraData
: (optional) additional data to send (data size must be a multiple of 32 bytes)
Proving
After initialization, you are now ready to generate a compute proof of your circuit. You can now call axiom.prove
with some inputs as a json file (or a javascript object).
import inputs from './axiom/data/inputs.json';
...
await axiom.prove(inputs);
Sending the Query
The output of axiom.prove
is arguments that will be passed into axiom.sendQuery
to actually send the query on-chain.
const receipt = await axiom.sendQuery();
Sending the Query with IPFS
Another option for sending a query also involves an on-chain transaction, but the query data is provided by pinning that data to IPFS. We currently provide support for Pinata and Quicknode, with wider support planned in the near future.
If you have a specific service that you'd like to have support for, you can also open an issue or a PR in our axiom-tools repository.
The flow for sending a query with IPFS is essentially the same, with a few minor differences. You will need to update the Axiom
initialization object to include an ipfsClient
and then eventually call sendQueryWithIpfs
. An example is provided below:
import { PinataIpfsClient, QuicknodeIpfsClient } from "@axiom-crypto/tools";
// Use either Pinata or Quicknode
const ipfsClient = new PinataIpfsClient(process.env.PINATA_JWT);
// const ipfsClient = new QuicknodeIpfsClient(process.env.QUICKNODE_API_KEY, process.env.QUICKNODE_GATEWAY);
const axiom = new Axiom({
circuit: circuit,
compiledCircuit: compiledCircuit,
chainId: "11155111", // Sepolia
provider: process.env.PROVIDER_URI_SEPOLIA as string,
privateKey: process.env.PRIVATE_KEY_SEPOLIA as string,
callback: {
target: "0x4A4e2D8f3fBb3525aD61db7Fc843c9bf097c362e",
},
// Additional `ipfsClient` field
options: {
ipfsClient: ipfsClient,
},
});
await axiom.init();
await axiom.prove(inputs);
// Use `sendQueryWithIpfs`
const receipt = await axiom.sendQueryWithIpfs();
Viewing the status of a Query
You can view the status of your query by going to Axiom Explorer. You can find your specific query by checking your query's queryId
via args.queryId
.
Using Different Chains
We currently support Ethereum Mainnet, Sepolia, and Base Sepolia. You can simply modify the chainId
and provider
fields to the appropriate values for the chain you want to use. Ensure that the privateKey
that you pass in is also funded on the chain that you are using and that the callback target is a valid contract that will accept an Axiom callback. For example, if you want to use Base Sepolia:
const axiom = new Axiom({
circuit: circuit,
compiledCircuit: compiledCircuit,
chainId: "84532", // Base Sepolia
provider: process.env.PROVIDER_URI_BASE_SEPOLIA as string,
privateKey: process.env.PRIVATE_KEY_BASE_SEPOLIA as string,
callback: {
target: "0x81908149E769236F1c9e62b468d07899CB95890F",
},
});