ShadowKit
Documentation · ZK + agentic governance
ShadowKit is an SDK for governance where the how stays private and the outcome is verifiable. Four primitives compose:
- Zero-knowledge votes — a Groth16 (BLS12-381) circuit proves membership and a hidden weight; identity, weight, and direction never go on-chain.
- Timelock seal — each vote’s
(direction, weight)is tlock-encrypted to the drand round at the deadline; the running tally is unknowable until close. - On-chain governance — a Soroban
GovVaultstores sealed votes, re-aggregates the revealed tally, and exposes an approval gate. - Bounded AI agent — an LLM plans the approved action; an on-chain policy contract rejects anything off-spec, so a hallucinating agent can never move funds wrongly.
Install
Section titled “Install”ShadowKit ships as scoped npm packages plus the Soroban contract WASM. Browser proving + sealing path:
npm install @shadowkit/zk-prover @shadowkit/snapshot-tool \ @shadowkit/tally-reveal @shadowkit/sharedAgent + x402 services (server / Worker side):
npm install @shadowkit/agent @shadowkit/x402-shared \ @shadowkit/x402-premium-data @shadowkit/x402-apiQuickstart — seal a vote
Section titled “Quickstart — seal a vote”Build a snapshot of eligible holders, generate a zero-knowledge proof, and timelock-seal the vote — all client-side. The witness never leaves the browser.
import { buildSnapshot } from "@shadowkit/snapshot-tool";import { generateVoteProof, nullifierFor } from "@shadowkit/zk-prover";
// 1) Merkle snapshot of eligible holders (leaf = Poseidon(Poseidon(secret), weight)).const snapshot = await buildSnapshot([ { secretCommit, weight: "1000" }, // ...more holders]);const { merklePath, pathIndices } = snapshot.getPath(myLeafIndex);
// 2) Prove + seal. direction/weight are hidden; only the 4 public signals are revealed.const { proof, publicSignals, sealedCiphertext } = await generateVoteProof( { secret, merklePath, pathIndices, weight: "1000", proposalId: "0", direction: 1, // yes — SEALED, never a public signal merkleRoot: snapshot.root, }, { wasmPath: "/zk/vote.wasm", zkeyPath: "/zk/vote_final.zkey" }, deadlineUnixSeconds, // tlock round derived from this);
// publicSignals = { merkleRoot, nullifier, proposalId, sealedCommitmentHash }// → submit GovVault.cast_vote(proposalId, proof, publicSignals, sealedCiphertext)Where to next
Section titled “Where to next” Architecture How the ZK, timelock, governance, and agent layers fit together.
Packages The four TypeScript libraries and their public APIs.
Contracts The Soroban contracts, deployed live on testnet, with explorer links.
Circuits The vote circuit, its constraints, and the binding public-signal order.
Agent The watch → reveal → plan → policy → execute loop.
x402 services Agent-pays + ShadowKit-sells, both over real x402 on Stellar.
Sealed-voting flow End-to-end: seal a vote, close, reveal, and execute.