PixelOracle

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.

PixelOracle SDK -- ZK oracle integration toolkit
Installation

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 / terminal
npm install @pxoracl/sdk @pxoracl/zk-engine

# Peer dependencies (Solana)
npm install @solana/web3.js @lightprotocol/stateless.js
Cargo.toml
[dependencies]
pxoracl-sdk = "0.9.2"
pxoracl-zk = "0.9.2"
solana-sdk = "1.18"
light-sdk = "0.11"
Configuration

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.

config.ts
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,
  },
});
Reference

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.

Parameters
assetstringToken mint address or contract address
dataTypestringOne of: price_feed, liquidity, volume, metadata
proofbooleanGenerate Groth16 ZK proof (default false)
privacystringPrivacy level: none, partial, full
Returns

Promise<QueryResult> containing value, verified, zkProof, riskScore, timestamp

query.ts
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.

Parameters
proofHashstringThe ZK proof hash to verify
checkExpirybooleanReject expired proofs (default true)
maxAgenumberMaximum proof age in milliseconds
onChainVerifybooleanVerify against Solana state (default false)
Returns

Promise<VerifyResult> containing valid, circuit, verifiedAt, blockHeight

verify.ts
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 -> number

oracle.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.

Parameters
assetstringToken mint address to subscribe to
dataTypestringData type to stream
intervalnumberUpdate interval in milliseconds (min 1000)
proofbooleanInclude proof validation on each update
Returns

Subscription object with unsubscribe() method

subscribe.ts
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 close

oracle.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.

Parameters
addressstringAsset address to query proofs for
limitnumberMaximum records to return (default 50, max 500)
afternumberUnix timestamp in ms, return only proofs after this time
includeCircuitbooleanInclude circuit params in response
Returns

Promise<ProofRecord[]> array of proof records with hash, verified, createdAt

getProof.ts
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.

Parameters
sourceChainstringSource chain identifier: ethereum, bsc
assetstringContract address on the source chain
dataTypestringData type to query
proofbooleanGenerate ZK proof for bridged data
verifyStorageProofbooleanVerify against source chain state
Returns

Promise<CrossChainResult> with value, storageProofValid, bridgeLatency, sourceBlockNumber

crossChain.ts
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  -> number
Examples

Use 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-portfolio.ts
// 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.

zk-custom.ts
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 Solana

Rust 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.

main.rs
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(())
}