SDK
Complete TypeScript and Rust SDK for integrating PixelOracle into your protocol. Oracle queries, ZK proof generation, cross-chain verification, and real-time data subscriptions -- all backed by Light Protocol ZK Compression on Solana.

Install the SDK
The SDK is available as an npm package for TypeScript/JavaScript projects and as a Cargo crate for Rust. Both packages support the full oracle API surface. The TypeScript SDK requires Node.js 18 or later and works with both ESM and CommonJS module systems. The Rust SDK requires Rust 1.75 or later and uses async/await via tokio.
npm install @pxoracl/sdk @pxoracl/zk-engine # Peer dependencies (Solana) npm install @solana/web3.js @lightprotocol/stateless.js
[dependencies] pxoracl-sdk = "0.9.2" pxoracl-zk = "0.9.2" solana-sdk = "1.18" light-sdk = "0.11"
Initialize the Client
Create a PxOracle instance with your connection, API key, and ZK configuration. The compression flag enables Light Protocol compressed PDAs for proof storage. All parameters except connection and apiKey have sensible defaults. The zkConfig object is optional unless you need custom circuit parameters for advanced proving workflows.
import { PxOracle } from '@pxoracl/sdk';
import { Connection } from '@solana/web3.js';
const oracle = new PxOracle({
connection: new Connection('https://api.mainnet-beta.solana.com'),
apiKey: process.env.PXORACL_API_KEY,
chain: 'solana',
compression: true,
zkConfig: {
circuit: 'oracle_v2',
hashFunction: 'sha256',
privacyLevel: 'full',
compressionEnabled: true,
stateTreeDepth: 26,
},
});API Methods
The SDK exposes five core methods. Each method returns a typed promise with full IntelliSense support in TypeScript. Error handling follows a consistent pattern where network errors throw PxOracleNetworkError and validation errors throw PxOracleValidationError, both extending the base PxOracleError class.
oracle.query
oracle.query(params: QueryParams): Promise<QueryResult>
Submits a single oracle query with optional ZK proof generation. This is the primary method for fetching verified data from the oracle network. When proof is set to true, the method generates a Groth16 zero-knowledge proof attesting to the correctness of the oracle response. The privacy parameter controls whether query inputs are encrypted via SHA-256 commitment before submission. Setting compression to true stores the proof in a Light Protocol compressed PDA, reducing on-chain storage cost by up to 1000x compared to a standard Solana account. The method handles the full pipeline internally: commitment generation, network submission, proof verification, and result parsing.
Promise<QueryResult> containing value, verified, zkProof, riskScore, timestamp
const result = await oracle.query({
asset: 'So11111111111111111111111111111111111111112',
dataType: 'price_feed',
proof: true,
privacy: 'full',
});
// result.verified -> boolean
// result.value -> number | string
// result.zkProof -> string (Groth16 proof hash)
// result.riskScore -> number (0-100)
// result.timestamp -> number (unix ms)oracle.verify
oracle.verify(proofHash: string, opts?: VerifyOpts): Promise<VerifyResult>
Verifies an existing ZK proof by its hash. Useful when you receive a proof hash from another party and need to confirm its validity independently. The method checks the proof against the on-chain verification key stored in the oracle program. When onChainVerify is true, the method submits a verification transaction to Solana and confirms the proof against the current state tree. The checkExpiry option rejects proofs older than maxAge milliseconds, preventing replay attacks with stale oracle data. Verification costs approximately 200,000 compute units on Solana.
Promise<VerifyResult> containing valid, circuit, verifiedAt, blockHeight
const verification = await oracle.verify(
'0x3f8a1c2de7b94f01...', {
checkExpiry: true,
maxAge: 60_000, // reject proofs older than 60s
onChainVerify: true, // verify against Solana state
}
);
// verification.valid -> boolean
// verification.circuit -> string
// verification.verifiedAt -> number
// verification.blockHeight -> numberoracle.subscribe
oracle.subscribe(params: SubscribeParams, cb: UpdateCallback): Subscription
Creates a WebSocket subscription for real-time oracle data updates. The callback fires at the configured interval with the latest data and proof validation status. Each update includes a sequence number for ordering guarantees. The subscription automatically reconnects with exponential backoff if the connection drops, starting at 1 second and maxing out at 30 seconds. Proof validation runs on every update when proof is true in the params. The subscription object exposes an unsubscribe method to cleanly close the connection and free resources.
Subscription object with unsubscribe() method
const sub = oracle.subscribe({
asset: 'TOKEN_MINT_ADDRESS',
dataType: 'price_feed',
interval: 5000,
proof: true,
}, (update) => {
console.log(update.value);
console.log(update.proofValid);
console.log(update.sequenceNumber);
});
// Auto-reconnects with exponential backoff
// sub.unsubscribe() to closeoracle.getProof
oracle.getProof(address: string, opts?: ProofOpts): Promise<ProofRecord[]>
Retrieves historical ZK proof records for a given asset address. Returns an array of proof records sorted by creation time in descending order. Each record contains the proof hash, verification status, circuit identifier, and creation timestamp. The includeCircuit option embeds the full circuit parameters used to generate each proof, which is useful for independent verification. Results are paginated via limit and after parameters. Proof records are stored in Light Protocol compressed PDAs, so historical queries are efficient even for assets with thousands of proofs.
Promise<ProofRecord[]> array of proof records with hash, verified, createdAt
const proofs = await oracle.getProof(
'So11111111111111111111111111111111111111112', {
limit: 20,
after: Date.now() - 86400_000, // last 24h
includeCircuit: true,
}
);
for (const p of proofs) {
console.log(p.proofHash, p.verified, p.createdAt);
}oracle.crossChain
oracle.crossChain(params: CrossChainParams): Promise<CrossChainResult>
Executes a cross-chain oracle query by routing through chain-specific bridge adapters. Currently supports Ethereum and BSC as source chains with Solana as the settlement layer. The method fetches data from the source chain, generates a storage proof against the source block header, bridges the result to Solana, and verifies the storage proof on-chain. When verifyStorageProof is true, the adapter checks the data against a Merkle Patricia Trie proof anchored to the source chain block hash. Bridge latency varies by source chain: Ethereum averages 12-15 seconds, BSC averages 3-5 seconds. The result includes the source block number for auditability.
Promise<CrossChainResult> with value, storageProofValid, bridgeLatency, sourceBlockNumber
const ethResult = await oracle.crossChain({
sourceChain: 'ethereum',
asset: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
dataType: 'price_feed',
proof: true,
verifyStorageProof: true,
});
// ethResult.value -> number
// ethResult.storageProofValid -> boolean
// ethResult.bridgeLatency -> number (ms)
// ethResult.sourceBlockNumber -> numberUse Cases
Three common integration patterns covering batch queries for portfolio dashboards, custom ZK circuit proving for privacy-sensitive applications, and Rust integration for on-chain program development.
Batch Query -- Portfolio Dashboard
Query up to 100 assets in a single call. Batch queries are cheaper than individual queries because proof generation is amortized across the batch. The SDK groups assets by chain and parallelizes bridge requests for cross-chain assets.
// Batch query up to 100 assets in a single call
const batch = await oracle.batchQuery([
{ asset: 'MINT_1', chain: 'solana', dataType: 'price_feed' },
{ asset: 'MINT_2', chain: 'solana', dataType: 'liquidity' },
{ asset: '0xA0b8...3f2E', chain: 'ethereum', dataType: 'price_feed' },
]);
for (const r of batch.results) {
console.log(`${r.chain}/${r.asset}: ${r.verified ? 'OK' : 'FAIL'}`);
}
// batch.totalCost -> number (in $PXCL)
// batch.proofCount -> number
// batch.latency -> number (ms)Custom ZK Circuit -- Private Oracle Proof
For advanced use cases, you can access the Groth16 prover directly. This gives you full control over commitment generation and proof creation. Proof generation runs locally and takes 300-500ms depending on circuit complexity. The resulting proof is 192 bytes and verifiable in approximately 200,000 compute units on Solana.
import { Groth16Prover } from '@pxoracl/zk-engine';
const prover = new Groth16Prover(oracle.getCircuit());
// Create a commitment without executing the query
const commitment = oracle.createCommitment({
asset: 'TOKEN_ADDRESS',
chain: 'solana',
dataType: 'price_feed',
nonce: crypto.randomUUID(),
});
// Generate Groth16 proof locally
const proof = await prover.fullProve(
commitment.privateInputs,
commitment.publicInputs,
);
console.log('Proof size:', proof.proofBytes.length, 'bytes');
// ~192 bytes, verifiable in ~200K compute units on SolanaRust Integration -- On-Chain Program
The Rust SDK mirrors the TypeScript API surface with native Solana types. Use it for building Anchor programs that consume oracle data, backend services that aggregate oracle feeds, or any Rust application that needs verified on-chain data. The Rust SDK uses the same underlying RPC calls and proof format as the TypeScript SDK, so proofs are interchangeable between languages.
use pxoracl_sdk::{PxOracle, QueryParams, DataType};
use solana_sdk::pubkey::Pubkey;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let oracle = PxOracle::new()
.rpc("https://api.mainnet-beta.solana.com")
.api_key(std::env::var("PXORACL_API_KEY")?)
.compression(true)
.build()?;
let result = oracle.query(QueryParams {
asset: Pubkey::from_str("So111...1112")?,
data_type: DataType::PriceFeed,
proof: true,
privacy: pxoracl_sdk::Privacy::Full,
}).await?;
println!("Verified: {}", result.verified);
println!("Value: {}", result.value);
println!("Proof: {}", result.zk_proof);
Ok(())
}