Complete API documentation for @orbinum/proof-generator.
npm install @orbinum/proof-generatorDependencies installed automatically:
@orbinum/circuits- Circuit artifacts (WASM, proving keys)@orbinum/groth16-proofs- Arkworks WASM proof generatorsnarkjs- Witness calculation
- Node.js: ≥ 22.0.0
- RAM: ≥ 2GB (for proof generation)
- Storage: ~50MB (circuit artifacts)
No build tools or manual downloads required.
import { generateProof, CircuitType } from '@orbinum/proof-generator';
// Default backend (snarkjs) — fastest
const result = await generateProof(CircuitType.Unshield, {
merkle_root: '0x...',
nullifier: '0x...',
amount: '100',
// ... circuit-specific inputs
});
// Arkworks backend — smaller artifacts
const result2 = await generateProof(CircuitType.Transfer, inputs, {
backend: 'arkworks',
});
console.log(result.proof); // '0xabcd...' (128-byte hex)
console.log(result.publicSignals); // ['0x...', ...]
console.log(result.circuitType); // CircuitType.UnshieldGenerates a 128-byte Groth16 proof from circuit inputs.
Parameters:
await generateProof(
circuitType: CircuitType,
inputs: CircuitInputs,
options?: GenerateOptions
)GenerateOptions:
interface GenerateOptions {
verbose?: boolean; // Log progress to console (default: false)
provider?: ArtifactProvider; // Override artifact source (default: auto-detected)
backend?: 'snarkjs' | 'arkworks'; // Proof backend (default: 'snarkjs')
}Returns: Promise<ProofResult>
interface ProofResult {
proof: string; // 128-byte hex proof (0x-prefixed)
publicSignals: string[]; // Public signals (hex-encoded, 0x-prefixed)
circuitType: CircuitType; // Circuit used
}Example:
import { generateProof, CircuitType } from '@orbinum/proof-generator';
const result = await generateProof(
CircuitType.Unshield,
{
merkle_root: '0x123abc...',
nullifier: '0x456def...',
amount: '1000000000000000000', // 1 ETH in wei
secret: '0x789012...',
path_elements: ['0x...', '0x...'],
path_index: '0',
},
{ verbose: true, backend: 'snarkjs' }
);
console.log(result.proof);
// "0xabcd1234ef56..."
console.log(result.publicSignals);
// ['0x...', '0x...', '0x...', '0x...', '0x...']High-level helper for the ValueProof circuit. Computes owner_hash = Poseidon(ownerPubkey)
and returns the decoded public signals alongside the proof.
Parameters:
await generateValueProof(
value: bigint, // Note value (u64)
ownerPubkey: bigint, // Owner public key (BN254 scalar)
blinding: bigint, // Blinding factor
assetId: bigint, // Asset ID (u32)
commitment: bigint, // Note commitment
options?: GenerateOptions
)Returns: Promise<ValueProofOutput>
interface ValueProofOutput {
proof: string; // 128-byte compressed proof (0x-prefixed)
publicSignals: string[]; // [commitment, value, asset_id, owner_hash]
decoded: {
commitment: string; // 0x-prefixed hex (32 bytes)
value: string; // Decimal string (u64)
assetId: number; // u32
ownerHash: string; // 0x-prefixed hex (32 bytes) — Poseidon(ownerPubkey)
};
}Example:
import { generateValueProof } from '@orbinum/proof-generator';
const result = await generateValueProof(
1000n, // value
ownerPubkey, // bigint
blinding, // bigint
42n, // assetId
commitment, // bigint
);
console.log(result.decoded.value); // '1000'
console.log(result.decoded.assetId); // 42
console.log(result.decoded.ownerHash); // '0x...' (always present)Supported circuits:
enum CircuitType {
Unshield = 'unshield', // Withdrawal to public address
Transfer = 'transfer', // Private transfer
ValueProof = 'value_proof', // Prove note value (commitment binding)
PrivateLink = 'private_link', // Privacy-preserving cross-chain identity dispatch
}Usage:
import { CircuitType } from '@orbinum/proof-generator';
await generateProof(CircuitType.Unshield, inputs);
await generateProof(CircuitType.Transfer, inputs);
await generateProof(CircuitType.ValueProof, inputs);
await generateProof(CircuitType.PrivateLink, inputs);By default the library detects the runtime environment and picks the appropriate provider:
- Node.js →
NodeArtifactProvider(reads fromnode_modules/@orbinum/circuitsviafs) - Browser / Web Worker (
windoworselfdefined) →WebArtifactProvider(fetches over HTTP)
import { NodeArtifactProvider } from '@orbinum/proof-generator';
const provider = new NodeArtifactProvider();
// optional: pass a custom path to @orbinum/circuits package root
const custom = new NodeArtifactProvider('/path/to/circuits');
const result = await generateProof(CircuitType.Unshield, inputs, { provider });Fetches artifacts over HTTP. Suitable for browsers, React Native, or any environment without a local filesystem.
import { WebArtifactProvider } from '@orbinum/proof-generator';
const provider = new WebArtifactProvider({
baseUrl: 'https://cdn.example.com/circuits',
// optional per-circuit URL overrides:
// wasmUrls?: Partial<Record<CircuitType, string>>
// zkeyUrls?: Partial<Record<CircuitType, string>>
// provingKeyUrls?: Partial<Record<CircuitType, string>>
});
const result = await generateProof(CircuitType.Unshield, inputs, { provider });Implement this interface to supply artifacts from any source (IPFS, S3, embedded buffers, etc.):
interface ArtifactProvider {
getCircuitWasm(circuitType: CircuitType): Promise<Uint8Array | string>;
getCircuitZkey(circuitType: CircuitType): Promise<Uint8Array | string>;
getCircuitProvingKey?(circuitType: CircuitType): Promise<Uint8Array>; // required for arkworks backend
}All errors extend ProofGeneratorError, which carries a machine-readable code string.
import {
ProofGeneratorError,
WitnessCalculationError,
ProofGenerationError,
CircuitNotFoundError,
InvalidInputsError,
} from '@orbinum/proof-generator';| Error class | code |
Thrown when |
|---|---|---|
InvalidInputsError |
INVALID_INPUTS |
Missing or malformed circuit inputs |
CircuitNotFoundError |
CIRCUIT_NOT_FOUND |
Circuit artifacts not found |
WitnessCalculationError |
WITNESS_CALCULATION_FAILED |
snarkjs witness step fails |
ProofGenerationError |
PROOF_GENERATION_FAILED |
Backend proof step fails |
Example:
try {
await generateProof(CircuitType.Unshield, inputs);
} catch (error) {
if (error instanceof InvalidInputsError) {
console.error('Bad inputs:', error.message); // error.code === 'INVALID_INPUTS'
} else if (error instanceof CircuitNotFoundError) {
console.error('Missing artifacts. Run: pnpm install');
} else if (error instanceof ProofGeneratorError) {
console.error(`Proof failed [${error.code}]:`, error.message);
}
}| Circuit | Public Signals | Key Inputs | Use Case |
|---|---|---|---|
| Unshield | 5 | merkle_root, nullifier, amount, recipient, asset_id, note fields, path_* |
Withdraw from pool to public address |
| Transfer | 5 | merkle_root, input/output nullifiers and commitments, note fields, path_* |
Private-to-private transfer |
| ValueProof | 4 | commitment, value, asset_id, owner_hash, note fields |
Prove note value without revealing extra state |
| PrivateLink | 2 | commitment, call_hash_fe |
Privacy-preserving cross-chain identity dispatch |
All public signals returned as 0x-prefixed hex strings:
{
proof: '0xabcd1234...', // 128 bytes = 256 hex chars (+ 0x prefix)
publicSignals: [
'0x...', // Signal 1
'0x...', // Signal 2
// ...
],
}See docs/backends.md for a full benchmark analysis.
| Circuit | snarkjs | arkworks |
|---|---|---|
| Unshield | ~1.3 s | ~7 s |
| Transfer | ~4.7 s | ~20 s |
| ValueProof | ~1.1 s | ~5 s |
| PrivateLink | ~0.7 s | ~3 s |
- **snarkjs** — default, fastest, uses `.zkey` proving keys
- **arkworks** — 2–3× smaller proof artifacts, uses `.ark` proving keys
### WASM initialization
The arkworks WASM module is initialized lazily on first use. Pre-initialize for latency-sensitive apps:
```typescript
import { initWasm } from '@orbinum/proof-generator';
await initWasm(); // call once at startup
- Peak: ~2 GB during proof generation
- WASM module: ~5 MB
- Circuit artifacts: ~20–50 MB total
Dependency not installed:
rm -rf node_modules pnpm-lock.yaml
pnpm installIncrease Node.js heap:
NODE_OPTIONS="--max-old-space-size=4096" node your-script.jsConfigure your bundler:
Webpack:
module.exports = {
experiments: { asyncWebAssembly: true },
};Vite:
export default {
build: { target: 'esnext' },
};Next.js:
/** @type {import('next').NextConfig} */
const nextConfig = {
webpack: config => {
config.experiments = { asyncWebAssembly: true };
return config;
},
};
module.exports = nextConfig;Ensure all required fields are present and properly formatted:
// ✅ Correct - string values
const inputs = {
merkle_root: '0x123abc...',
nullifier: '0x456def...',
amount: '1000000000000000000', // String (18 decimals)
// ... other required fields
};
// ✅ Also valid - BigInt values
const inputs = {
merkle_root: 123456n,
nullifier: 456789n,
amount: 1000000000000000000n,
};
// ❌ Avoid - number can lose precision
const inputs = {
amount: 1000000000000000000, // May lose precision
};Proof generation is compute-intensive. Expected times:
- Unshield: ~1.5s
- Transfer: ~3s
- ValueProof: ~0.8s
- PrivateLink: ~0.7s
For faster proofs, ensure:
- Node.js ≥ 22.0.0 (latest V8 optimizations)
- Sufficient RAM (≥ 2GB available)
- No CPU throttling
See docs/backends.md for backend architecture and benchmark analysis.
See docs/usage.md for usage examples with both backends.
See docs/development.md for development setup and contributing guide.