App · Agent guide · SDK documentation · Confidential RFQ guide
APP20 is a Starknet application for encrypted chat, shielded payments and confidential token swaps. Chat combines conversations with payments and invoices. The RFQ (request for quote) workspace demonstrates an exchange where both parties approve the terms and receive their assets together. STRK20 provides the privacy pool that holds balances as encrypted notes.
Chat and confidential swaps currently run in local development environments. Mainnet confidential trading and mainnet Chat are not enabled in this release. The desktop-first browser app and SDK expose network availability before execution.
New payments must spend encrypted notes. Swaps require an atomic exchange approved by both parties. Unsupported operations stop before funding or signing; they cannot fall back to public settlement or a one-sided payment. See the settlement policy.
| Feature | Status |
|---|---|
| RFQ | /rfq presents the confidential flow; mainnet contracts are deployed; real-proof settlement validation is pending |
| Confidential escrow | Cairo contract, independent party approvals, encrypted outputs, timeout refunds and Node SDK implemented; local tests use simulated proofs |
| Chat messages | Localnet encrypted conversations, public-key registration and replay-protected message delivery; no helper funding or asset transfer required |
| Chat payments and invoices | Localnet encrypted transfers from existing shielded notes, with an unfunded encrypted message operation |
| Chat swaps and invoice conversion | Blocked until confidential atomic settlement is supported; no one-sided payment fallback |
| Agent library | Confidential escrow integration and separate shielded-wallet operations; downloadable @app20/agent-sdk, not published to the npm registry |
| Mainnet proof tooling | Operator preflight and proof rehearsal implemented; proof generation does not establish accepted settlement or enable the app |
| Privy wallet | Separate register/shield/transfer/unshield rail; configured credentials and real-wallet acceptance remain necessary |
The confidential lab controls two disposable wallets. Independent wallet integration, authenticated private quote negotiation, real proof acceptance and independent review remain release requirements. An open permissionless maker market is not available through the current confidential flow.
App20ConfidentialEscrow is a dedicated policy account for one two-party trade:
- Agree on assets, exact amounts, recipients and a deadline. The public constructor stores a commitment to the terms, two distinct public signing keys, the deadline and pinned pool identity.
- Both parties approve setup. Each funds the escrow separately from its own shielded balance, using viewing material created only for this escrow.
- Both approve the exact exchange. The contract permits both agreed outputs together as encrypted notes, returning any surplus only to the original owner of that asset. Public deposits, withdrawals, OPEN outputs and unrelated calls are rejected by its action policy.
- After expiry, either party can authorize a fresh encrypted refund of its original asset without the other party's signature. Funding is not atomic: the first funder may have to wait until expiry if the peer stops participating.
The pool callback checks the actual execution deadline and prevents a second settlement. The SDK checks deployed identities, prepares operations, collects approvals and journals uncertain submissions. A contract implementation and simulated local execution are not evidence of a mainnet-ready service. See protocol and recovery details.
App20Chat registers chat public keys and emits encrypted message records. Its protected callback accepts only the configured privacy pool, binds the message payload to the computation and rejects replayed actions. Encryption and decryption happen in the clients.
The current app sends messages through an unfunded, proof-bound helper operation. A payment adds an encrypted transfer from existing shielded notes to the same batch; the helper does not settle swaps. Same-token invoices use that payment path. Plain messages require no asset transfer, although pool and network fees still apply. Chat offer acceptance and invoice conversion remain blocked.
Message content is encrypted for its recipients. Confidential escrow amounts, assets and destinations are private proof inputs; counterparties still know their agreement.
Shielding/unshielding expose their own amounts and assets and remain separate wallet operations. Escrow activity, timing, deadlines, fees, ephemeral signer keys and ciphertext/proof sizes remain visible. Counterparties know their agreement. Historical maker recovery remains public under the old contracts.
The hosted path is Browser or Node agent → APP20 Cloudflare Worker → Starkscan → STRK20 proving service. TLS protects connections but APP20/Cloudflare and the proving operator can access proving payloads. This is HTTPS JSON, not a verified OHTTP route. The hosted prover receives the private witness; keeping signing keys local does not hide transaction details or escrow viewing material included in that witness.
The Worker does not log or persist proof request/response bodies. Separate relay tokens, caller-bound polling and request/concurrency limits protect access. Preserve wallet recovery state and operation journals across restarts; investigate unknown proof or transaction outcomes before retrying. RPC providers can observe discovery queries and timing.
/rfq: one confidential swap workspace, with network availability shown before any signing./agents: Node SDK, confidential RFQ integration and current network support./recovery/privy: the separately configured wallet and recovery rail. Switching wallets does not move balances./chat: localnet encrypted conversations and payments. Incoming messages refresh after unlocking and every 60 seconds while visible and online. Mainnet Chat is not enabled. Fixed offers may be discussed, but acceptance requiring a swap is blocked.
Node 24+ and ESM:
curl -fSLO https://app20.io/downloads/app20-agent-sdk-0.1.0.tgz
curl -fSLO https://app20.io/downloads/app20-agent-sdk-0.1.0.sha256
shasum -a 256 -c app20-agent-sdk-0.1.0.sha256
npm install ./app20-agent-sdk-0.1.0.tgzimport { confidentialCapabilities } from '@app20/agent-sdk/confidential';
// Check support before asking a wallet to sign.
console.log(confidentialCapabilities.mainnetEnabled);Use @app20/agent-sdk/confidential to construct agreements, inspect escrow funding, collect approvals, settle locally and recover expired funding. createConfidentialClient blocks mainnet execution. The current source also includes createConfidentialProofClient, which prepares and proves operations without exposing funding or transaction submission. Build it from the checkout using the mainnet proof rehearsal guide.
createPrivacyWallet provides separately invoked registration, shielding, encrypted transfers, unshielding and reconciliation. There is no sendChat SDK API yet. See SDK details and adapter examples. Preserve journals and secure wallet material across restarts; an unknown submission outcome must be reconciled before retrying.
Use Node.js 24+ and npm. Build workspace exports before starting the frontend:
npm ci
npm run build:packages
npm run devThe normal dev server shows the app with its network restrictions. To execute the confidential swap and refund flow, install the pinned privacy-pool toolchain and start the disposable lab:
npm run pool:setup
npm run dev:confidential
# Open http://127.0.0.1:5198/rfqCreate an escrow, approve setup, fund each side and approve the exchange. A second, partially funded trade demonstrates the independent timeout refund. Stop the command with Ctrl-C to remove that lab's disposable wallets and state.
For Chat, use the separate Alice/Bob localnet environment. Its runner also requires Scarb 2.18.x as scarb on your PATH or at ~/.local/bin/scarb. Stop the confidential lab before starting it:
npm run dev:localnet
# Open http://127.0.0.1:5173/chat
# Stop from a separate terminal:
npm run localnet:stopLocalnet helpers, test tokens and chat contracts are not mainnet assets. Never fund development keys with real assets.
Public build variables:
VITE_PRIVY_APP_ID
VITE_PRIVY_CLIENT_ID
Set these in an ignored .env.production.local or your build environment. Configure app20.io as an allowed domain in Privy and enable the required Starknet embedded-wallet/signing functionality.
Cloudflare secrets (enter values through secret storage, never VITE_*):
npx wrangler secret put PRIVY_APP_SECRET
npx wrangler secret put STARKSCAN_API_KEY
npx wrangler secret put PROOF_CAPABILITY_SECRET
npx wrangler secret put OHTTP_SESSION_SECRET
npx wrangler secret put PROVER_AGENT_TOKEN_HASHESPROOF_CAPABILITY_SECRET and OHTTP_SESSION_SECRET must each be independently generated with at least 32 bytes of entropy. PROVER_AGENT_TOKEN_HASHES maps SHA-256 digests of individually issued high-entropy agent tokens to stable agent identifiers. Give each agent only its own token; never the Starkscan key. Rotate/revoke individual relay tokens by updating that mapping. An empty mapping enables no agent tokens.
Worker variables include the public PRIVY_APP_ID, PRIVY_MAINNET_ENABLED=true, and PRIVY_SUBMISSION_MODE=live. Live mode enables submission for real proofs; it is not evidence that a live transaction has passed. Missing required credentials fail closed. Mainnet pool/class pins come from the shared deployment module.
Starkscan's proving endpoint is POST /v1/SN_MAIN/prove, not the generic RPC method route. Poll /v1/SN_MAIN/prove/{jobId}. The SDK preserves submission idempotency and never automatically replaces an uncertain job. See Starkscan's proving contract.
npm run build:packages
npm run test:all
npm run buildAfter npm run pool:setup, validate the current escrow contract and SDK integration:
npm run check:confidential-contract
PATH="$PWD/vendor/bin:$PATH" RUST_LOG=warn node --test pool-harness/tests/confidential-rfq-sdk.e2e.test.mjsRun devnet tests serially with other devnet instances stopped. For the browser journey, start npm run dev:confidential, then run these in another terminal:
npx playwright install chromium
npm run test:confidential:browserBuild generates browser assets, the installable SDK archive and checksums, TypeScript checks and browser-secret scans. The local integration and browser tests use disposable wallets and simulated proofs. A mainnet acceptance claim additionally requires a real accepted proof, successful receipts and verified encrypted outputs. Detailed validation guide.
With the Worker configured, deploy the built app using npx wrangler deploy. Deploying the frontend does not enable confidential mainnet settlement or Chat.
The Worker serves the app and RPC/prover routes. Its API keys are not embedded in browser or SDK downloads. The provider determines proving throughput; a Worker forwards jobs and does not generate STARK proofs itself.
| Path | Purpose |
|---|---|
src/app/rfq/ConfidentialRfqPage.tsx |
Current RFQ screen and local lab entry |
src/app/chat, src/components/chat |
Conversations, encrypted messages, payments and invoices |
packages/agent-sdk |
Installable Node library and persistent wallet/proof integration |
packages/privy |
Privy signing, privacy wallet operations, discovery and proof providers |
workers/relay |
Authenticated RPC/proving relays and atomic quotas |
cairo/src/confidential_escrow.cairo |
Jointly approved confidential swap and timeout-refund policy |
cairo/src/lib.cairo |
Chat key registration and encrypted message helper |
pool-harness/src/confidential-lab.mjs |
Disposable wallets and local escrow execution through the SDK |
pool-harness/tests |
Privacy-pool integration and contract regression tests |
scripts/confidential-mainnet-proof.mjs |
Mainnet preflight and proof rehearsal without transaction submission |
Earlier deployed contracts remain available for explicit recovery; new trading through their public-term protocol is disabled in current clients. Existing positions can be inspected and reconciled through the historical recovery tools. Earlier maker-page bookmarks redirect to /rfq.
The three September 7 mainnet swaps in strk20.json belong to that earlier protocol, with one operator controlling both sides. They do not prove the current confidential escrow. Historical receipts, costs and recording status are kept in the mainnet runbook and demo notes.