// 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 testedTradeJournal + AlphaRegistry
Hash-chained trade commitments, verified performance claims — 8 tests
Contract testedRiskRegistry · PortfolioLens (PCP-1) · VaultFactory · SealedCollateralOracle
Proof of Risk, the proof-carrying interface, alpha-gated launch, collateral pricing — 14 tests
Contract testedVault / alpha / risk circuits
Mock prover. Public inputs are fixed by the contracts
PlannedShielded custody layer
MockCustody only — holdings are not actually sealed yet
PlannedVault performance data
Seeded simulation, labeled as simulated in the UI
MockWallet connection (wagmi / viem)
MetaMask & injected wallets; WalletConnect with a project ID
ProductionPrivacyPool.sol
Deposits, nullifiers, association roots, ragequit, bounded pause — 19 tests
Contract testedPaymentRouter + ReceiptVerifier
Invoice binding, caller binding, pool allowlist
Contract testedWithdrawal / receipt / credential circuits
Mock prover only. Needs Poseidon tree + audited circuits
PlannedOn-chain pool adapter
UI uses MockPoolAdapter (browser state)
PlannedRelayer network
Mock API routes; RelayerRegistry contract is implemented
MockPayment 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 ]