// developers

A small SDK over swappable adapters: pool, prover, verifier and relayer. Mock and production implementations share the same interfaces.

What's real today

We label mocks explicitly. Don't ship user funds on anything marked mock or planned.

  • SealedVault.sol

    Async deposits/redemptions at proven NAV, mandate hash, staleness guard — 12 tests incl. fuzz

    Contract tested
  • TradeJournal + AlphaRegistry

    Hash-chained trade commitments, verified performance claims — 8 tests

    Contract tested
  • RiskRegistry · PortfolioLens (PCP-1) · VaultFactory · SealedCollateralOracle

    Proof of Risk, the proof-carrying interface, alpha-gated launch, collateral pricing — 14 tests

    Contract tested
  • Vault / alpha / risk circuits

    Mock prover. Public inputs are fixed by the contracts

    Planned
  • Shielded custody layer

    MockCustody only — holdings are not actually sealed yet

    Planned
  • Vault performance data

    Seeded simulation, labeled as simulated in the UI

    Mock
  • Wallet connection (wagmi / viem)

    MetaMask & injected wallets; WalletConnect with a project ID

    Production
  • PrivacyPool.sol

    Deposits, nullifiers, association roots, ragequit, bounded pause — 19 tests

    Contract tested
  • PaymentRouter + ReceiptVerifier

    Invoice binding, caller binding, pool allowlist

    Contract tested
  • Withdrawal / receipt / credential circuits

    Mock prover only. Needs Poseidon tree + audited circuits

    Planned
  • On-chain pool adapter

    UI uses MockPoolAdapter (browser state)

    Planned
  • Relayer network

    Mock API routes; RelayerRegistry contract is implemented

    Mock
  • Payment links

    URL-encoded; production should sign links

    Mock

SDK

import { createCiphralClient } from "@/sdk";

const ciphral = createCiphralClient({ appUrl: "https://app.example" });
ciphral.isDemo; // true until real provers + on-chain adapter are configured

// Private payments
await ciphral.sendPrivatePayment({
  token: "USDC",
  amount: 250,
  recipient: "0x1234…",
  relayerId: "r-kestrel",       // or pick from GET /api/relayers
  mode: "strong",               // "standard" | "strong" | "maximum"
  invoice: { id: "INV-0142", merchant: "Acme Studio" },
});

// Payment links
const { url } = ciphral.createPaymentLink({
  handle: "alice", address: "0xabc…", token: "USDC",
  amount: 100, expiresInMs: 7 * 86_400_000, oneTime: true,
});

// Receipts
const { url: proofUrl } = await ciphral.generatePaymentProof(statement, { receiptSecret });
const result = await ciphral.verifyPaymentProof(proofUrl.split("/proof/")[1]);
// → { valid: true, sound: false }  // sound=false means mock verifier

// Private credentials
await ciphral.generateCredentialProof({
  kind: "credential",
  scope: "forum.example.org",
  claims: [{ id: "payments", threshold: 10, label: "10+ private payments" }],
});

Adapter interfaces

interface PoolAdapter {
  readonly isDemo: boolean;
  deposit(token: TokenSymbol, amount: number): Promise<Note[]>;
  send(req: SendRequest): Promise<SendResult>;
  withdraw(noteIds: string[], recipient: Address, relayerId: string): Promise<PoolActivity>;
}

interface WithdrawalProver {
  readonly isProduction: boolean;
  proveWithdrawal(witness: WithdrawalWitness, inputs: WithdrawalPublicInputs): Promise<Hex>;
}

interface StatementProver {
  readonly isProduction: boolean;
  prove(statement: Statement, witness: Record<string, unknown>): Promise<ProofEnvelope>;
}

interface StatementVerifier {
  verify(envelope: ProofEnvelope): Promise<{ valid: boolean; sound: boolean; reason?: string }>;
}

Relayer API

GET  /api/relayers         → { relayers: Relayer[] }          (mock)
POST /api/relay/quote      { relayerId, token, amount }
                           → { relayerFee, protocolFee, gasUnits, expiresAt }
POST /api/relay/submit     { relayerId, token, amount, proof, publicInputs }
                           → { reference, status, preview: true }  (never touches a chain)

Circuit ↔ contract contract

// SealedVault epoch proof (SealedVault.publicInputs)
[ oldState, newState, navPerShare, priceRoot, mandateHash, epoch,
  depositTotal, redeemTotal, sharesOutstanding, vault ]

// Proof of Risk (RiskRegistry.publicInputs)
[ stateCommitment, epoch, scenarioId, shockHash, maxLossBps, priceRoot, vault, registry ]

// Proof of Alpha (AlphaRegistry.publicInputs)
[ journalId, head, fromTs, toTs, returnBps+1e9, maxDrawdownBps, tradeCount, priceRoot, registry ]

// Withdrawal (PrivacyPool.publicInputs)
[ root, nullifierHash, recipient, relayer, fee, caller, context, associationRoot, pool ]

// Receipt:    [ receiptCommitment, invoiceHash, challenge ]
// Credential: [ claimType, threshold, stateRoot, scope, nullifier ]