Prepare
Each side proves, from a credential, that it is valid and screened, without revealing who it is.
Settle large stablecoin trades without showing the market your hand, and prove you're clean without showing who you are.
Private, atomic OTC settlement on Arc
Prefunding, side letters and chat confirmations leave one party exposed until the other delivers.
Each side proves, from a credential, that it is valid and screened, without revealing who it is.
Both sides lock the same terms. They stay private until settlement.
If both proofs and both commitments match, both legs move in one transaction. Otherwise nothing moves.
Before it settles, the terms are a hash. After, they are public. Who is behind each side stays private, unless a regulator holds the key.
Synthetic example. The proofs are public inputs; the credential never is.
Each side proves three things before anything moves, without saying who it is.
01Credential valid and not revoked.
02Not on the sanctions list in use.
03Bound to this trade and to the address that trades.
25,378 constraints, 13 public signals. Proves in 879 ms, verifies in 8 ms. Measured with snarkjs on an Apple M4, 14 Oct 2026.
Open contracts, an SDK, and transactions your custody policy can approve.
// Public inputs of every proof, recorded on Arc
tradeId the trade it belongs to
tradingAddress the address that trades
issuersRoot the issuers accepted
sanctionsRoot the sanctions list in use
revocationRoot the revocations in force
minTier the policy tier required
validAt when the proof was made
regulatorKey the key that can open the subjectimport { KeelsonClient, proveCompliance } from "@keelson/sdk";
const keelson = new KeelsonClient({ publicClient, walletClient, deployment });
const context = await keelson.loadContext(lists);
const proof = await proveCompliance({
held, tradeId, tradingAddress, context, keys,
});
await keelson.attest(proof);
await keelson.commit(tradeId, termsHash);
await keelson.settle(tradeId, terms, salt);// The calls a party signs, and nothing else
ComplianceRegistry.attest(a, b, c, signals)
Settlement.commit(tradeId, termsHash)
Settlement.settle(tradeId, terms, salt)