A TypeScript SDK for interacting with PolkaVM Query (PVQ)
import { ApiPromise } from "@polkadot/api";
import { PvqProgram } from "@open-web3/pvq";
// Connect to a Polkadot node
const api = await ApiPromise.create({
provider: "ws://localhost:9944",
});
// Create PVQ program instance
const program = new PvqProgram(
api,
guestProgramBytes, // Uint8Array or hex string
programMetadata // Program metadata object
);
// Execute a query
const result = await program.entrypoint.sumBalance(
[21, ["15oF4uVJwmo4TdGW7VfQxNLavjCXviqxT9S1MgbjMNHr6Sp5"]],
{
gasLimit: 1000000000000000000n,
}
);
console.log("Query result:", result);
import { ApiPromise, WsProvider } from "@polkadot/api";
import { PvqProgram } from "@open-web3/pvq";
async function executeProgram() {
const provider = new WsProvider("ws://127.0.0.1:8000");
const api = await ApiPromise.create({ provider });
const guestProgram = "0x..."; // Your program bytecode
const metadata = {
// Your program metadata
};
const program = new PvqProgram(api, guestProgram, metadata);
try {
// Execute with default gas limit
const result = await program.entrypoint.sumBalance([
21,
["15oF4uVJwmo4TdGW7VfQxNLavjCXviqxT9S1MgbjMNHr6Sp5"],
]);
console.log("Success:", result.toJSON());
} catch (error) {
console.error("Execution failed:", error);
}
await api.disconnect();
}
// Execute with custom gas limit
const result = await program.entrypoint.sumBalance(
[21, ["15oF4uVJwmo4TdGW7VfQxNLavjCXviqxT9S1MgbjMNHr6Sp5"]],
{ gasLimit: 1000000000000000000n }
);
// Execute using entrypoint identifier
const result = await program.executeQuery(
"sum_balance",
{ gasLimit: 1000000n },
[21, ["15oF4uVJwmo4TdGW7VfQxNLavjCXviqxT9S1MgbjMNHr6Sp5"]]
);
// Execute with specific return type
const typedResult = await program.executeQuery<u64>(
"sum_balance",
{ gasLimit: 1000000n },
[21, ["15oF4uVJwmo4TdGW7VfQxNLavjCXviqxT9S1MgbjMNHr6Sp5"]]
);
// Fetch metadata from the chain
const metadata = await program.getMetadata();
console.log("Chain metadata:", metadata);
// Check whether the program's extensions match the extensions on the current chain
const matched = await program.checkExtensions();
console.log("Extensions matched:", matched); // true or throws error if not matched
// You can also check the cached result
console.log("Cached result:", program.extensionsMatched); // true/false/undefined
Main class for interacting with PVQ programs.
new PvqProgram(
api: ApiBase<ApiTypes>,
guestProgram: Uint8Array | `0x${string}`,
programMetadata: Record<string, unknown>
)
executeQuery<T = Codec>(entrypoint, options, params)
- Execute a query on the program with optional return type specificationcheckExtensions()
- Check if required extensions are availablegetMetadata()
- Get runtime metadata
entrypoint
- Object containing all available entrypoints as camelCase methodsextensionsMatched
- Boolean indicating if extensions check passed
Your program metadata should follow this structure:
{
"types": {
"types": [
{
"id": 0,
"type": {
"def": { "primitive": "u32" }
}
},
{
"id": 1,
"type": {
"def": { "array": { "len": 32, "type": 2 } }
}
},
{
"id": 2,
"type": {
"def": { "primitive": "u8" }
}
},
{
"id": 3,
"type": {
"def": { "primitive": "u64" }
}
},
{
"id": 4,
"type": {
"def": { "sequence": { "type": 1 } }
}
}
]
},
"extension_fns": [
[
"4071833530116166512",
1,
{
"name": "balance",
"inputs": [
{ "name": "asset", "ty": 0 },
{ "name": "who", "ty": 1 }
],
"output": 3
}
]
],
"entrypoints": [
{
"name": "sum_balance",
"inputs": [
{ "name": "asset", "ty": 0 },
{ "name": "accounts", "ty": 4 }
],
"output": 3
}
]
}