The Stellar/Soroban implementation of the Opaque privacy protocol — DKSAP stealth addresses, on-chain ZK reputation, and a Freighter-powered browser wallet.
Launch the wallet → · GitHub · Solana sibling
Recipient Sender
───────── ──────
Publishes meta-address V ∥ S
Ephemeral key → one-time Stellar account
Pays XLM + announces on Soroban
WASM scanner finds it → sweep to main wallet
Opaque Stellar is the canonical Stellar port of Opaque — the same DKSAP cryptography and Groth16 reputation layer, settled on XLM + Soroban instead of Solana.
| Layer | What it does |
|---|---|
| Stealth payments | Fresh one-time receive accounts per payment — only you can derive the spend key |
| Soroban contracts | Registry, announcer, schemas, attestations, Groth16 + reputation verifiers |
| Browser wallet | Freighter signing · Rust→WASM scanner · snarkjs proofs — all on-device |
| ZK reputation | Prove traits without linking them to your public Stellar address |
Experimental software. Read DISCLAIMER.md before using real funds.
Rust · Stellar CLI · Node 20+ · Freighter · wasm-pack
git clone https://github.com/collinsadi/opauque-stellar.git
cd opauque-stellarContract IDs ship in deployments/v1/testnet.json — no deploy needed to try the UI.
npm run build:scanner # Rust → WASM scanner
npm run fetch:circuits # ZK artifacts (from release when published)
cd frontend
cp .env.example .env # VITE_STELLAR_NETWORK=testnet
npm install
npm run devOpen http://localhost:5173 · connect Freighter on testnet · initialize stealth keys.
For modern browsers, build with SIMD support for 1.5-3x faster scanning:
cd scanner
RUSTFLAGS="-C target-feature=+simd128,+bulk-memory" \
wasm-pack build --release --target web --profile wasm-simd --out-dir ../frontend/public/pkgBrowser requirements: Chrome 91+, Firefox 89+, Safari 16.4+. See WASM_SIMD_EVALUATION.md for details.
cp .env.example .env
stellar keys generate opaque-deployer --network testnet --fund
# Set STELLAR_DEPLOYER=opaque-deployer in .env
npm run deploy:testnet # build WASM + deploy + update manifest
npm run deploy:testnet -- --dry-run # preview onlyEverything has one job. If you only care about the wallet, start with frontend/.
opaque-stellar/
├── frontend/ React wallet (Freighter, send, receive, scan, reputation)
├── contracts/ 6 Soroban smart contracts (Rust workspace)
├── scanner/ DKSAP engine → WASM for the browser
├── circuits/ Circom Groth16 circuits + regression fixtures
├── deployments/ On-chain address book (contract IDs + WASM hashes) ← read this
├── scripts/ TypeScript tooling (deploy, verify, artifacts)
├── artifacts/ Pinned SHA-256 hashes for scanner + circuit builds
├── Cargo.toml Rust workspace root
├── soroban.toml Stellar CLI contract build config
├── deny.toml cargo-deny supply-chain policy
├── package.json Root npm scripts (tsx)
├── .env.example Deployer config for npm run deploy:*
├── SECURITY.md Vulnerability disclosure
└── DISCLAIMER.md Legal / experimental notice
The on-chain address book. After you deploy (or when we publish a release), deployments/v1/testnet.json holds every Soroban contract ID, WASM hash, and RPC URL. The frontend reads it at build time — you don't hardcode C… addresses in source. See deployments/README.md.
Deterministic test vectors for ZK regression. Each folder (v1/, v2/) has valid-input.json, invalid-input.json, and expected-public.json. CI runs npm run test:circuits to prove the Circom circuits still produce the same public outputs — no drift in proof semantics.
| Contract | Role |
|---|---|
stealth-registry |
Wallet → stealth meta-address |
stealth-announcer |
On-chain payment announcements (view tags) |
schema-registry |
Attestation schema definitions |
attestation-engine-v2 |
Issue / revoke credentials |
groth16-verifier |
BN254 proof verification |
reputation-verifier |
Merkle roots, nullifiers, PSR checks |
Build: stellar contract build · Test: cargo test --workspace
Stealth announcement schemes:
scheme_id |
Payloads |
|---|---|
1 |
secp256k1 DKSAP: 20-byte stealth id, 33-byte compressed ephemeral pubkey, metadata[0] view tag |
2 |
Stellar-native Ed25519 DKSAP: 32-byte raw Stellar account id, 32-byte Ed25519 ephemeral pubkey, metadata[0] view tag |
reputation-verifier.are_nullifiers_spent(ids) accepts up to 128 nullifier hashes per read and returns spent status in input order.
attestation-engine-v2.get_attestation_count() and get_storage_stats() expose write-maintained counters, so operator dashboards can read growth metrics without unbounded iteration.
All root tooling is TypeScript run via tsx:
| Command | Does |
|---|---|
npm run deploy:testnet |
Build + deploy all contracts + update manifest |
npm run build:scanner |
Compile scanner to frontend/public/pkg/ |
npm run fetch:circuits |
Download pinned ZK artifacts |
npm run verify:deployment |
Validate deployment manifests |
npm run verify:artifacts |
Check scanner/circuit SHA-256 hashes |
npm run test:circuits |
Groth16 regression against fixtures |
| File | Purpose |
|---|---|
.env (root) |
STELLAR_DEPLOYER, STELLAR_NETWORK for deploy scripts |
frontend/.env |
VITE_STELLAR_NETWORK, optional RPC overrides |
Contract IDs default from deployments/v1/<network>.json. Override with VITE_TESTNET_*_CONTRACT only for local dev.
Stealth master keys recover by re-signing with the same Freighter wallet — deterministic derivation, no server.
Manual ghost receives bind ephemeral keys to the browser. Back them up or you lose those funds on device loss.
Session cache (Remember signature) is not a backup — ~30 minutes per tab.
Stealth breaks the link between your public wallet and individual receives. It does not hide that you interacted with Opaque contracts, that you scanned announcements, or network-level metadata.
The in-app privacy threat model maps mitigations to code.
Opaque payment URLs encode amount, asset (XLM), and recipient meta-address for one-click sends. Generated in-app from the Receive tab.
Same DKSAP layout as EIP-5564 / ERC-6538. Meta-addresses are portable; settlement here is Stellar.
| Repo | Chain |
|---|---|
| opauque-stellar (this) | Stellar / Soroban |
| opaque-solana | Solana |
See .github/CONTRIBUTING.md. CI is strict: cargo test, clippy -D warnings, frontend lint/typecheck/vitest, circuit regression, manifest verification.
Report vulnerabilities via SECURITY.md.
MIT License · Built by Collins Adi
Every transaction deserves the right to be private.