Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 28 additions & 54 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,54 +6,40 @@ APP20 combines encrypted communication, permissionless market making and STRK20

## Current status

APP20 requires confidential settlement for every new RFQ, Chat payment, invoice and offer. Public trade legs and one-sided swap acceptance are blocked. The new escrow is implemented for development; **confidential mainnet settlement and mainnet Chat are not available yet**. See [the settlement policy](docs/PRIVATE_SETTLEMENT_POLICY.md).

| Feature | Status |
| --- | --- |
| Mainnet maker registry and private-swap contract | Deployed; exact addresses and class hashes are pinned in the deployment manifest |
| RFQ UI | Automatic preliminary comparison, one funded offer, explicit swap review; minimum receive stays visible; maker onboarding at `/rfq/maker` |
| Becoming a maker | Permissionless registration, inventory funding/withdrawal, configuration export and a Node bot |
| Agent library | Downloadable `@app20/agent-sdk`, including Node wallet/proving integration; not published to the npm registry |
| Privy mainnet wallet | Implemented register/shield/transfer/unshield path; requires configured Privy backend credentials and a real-wallet acceptance test |
| Proving | Starkscan asynchronous STRK20 jobs through an authenticated APP20 Worker; plain HTTPS, **not OHTTP** |
| Mainnet chat | Not deployed. Localnet encrypted chat exists; there is no live mainnet send-chat API |
| Live private fill | Three mainnet swaps verified on 2026-09-07 using the Node SDK and real proofs; one operator wallet controlled maker and taker; browser wallet acceptance remains separate |

The RFQ browser screen currently uses Ready. Privy is a separate wallet and funds/recovery screen at `/recovery/privy`; changing wallets does not move balances. The Node SDK can provide its own private executor for settlement.

## Privacy: what is and is not hidden

RFQ requests and responses use authenticated encryption. Taker inputs and outputs use shielded notes. Funded quote terms and amounts, maker inventory/proceeds, requesting accounts, selected makers, and settlement timing/activity are public. This is not anonymous trading.
| RFQ | `/rfq` presents the confidential flow; mainnet activation is disabled |
| Confidential escrow | Cairo contract, independent party approvals, encrypted outputs, timeout refunds and Node SDK implemented; local tests use simulated proofs |
| 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 |
| Earlier mainnet maker/settlement contracts | Still deployed, with public funded terms; new registration, funding, quoting and settlement are disabled in this release |
| Historical recovery | Existing records, receipt reconciliation, expired reservation release, available inventory withdrawal and deactivation remain available |
| Agent library | Downloadable `@app20/agent-sdk`; not published to the npm registry |
| Privy wallet | Separate register/shield/transfer/unshield rail; configured credentials and real-wallet acceptance remain necessary |

### Proving payload exposure — accepted limitation
Three swaps verified on September 7, 2026 used the earlier public-term protocol. One operator controlled maker and taker. Their receipts do not prove the new confidential flow.

The selected proving transport is:
## Privacy boundary

`Browser or Node agent → APP20 Cloudflare Worker → Starkscan → STRK20 proving service`
New payments must use encrypted notes. RFQs and Chat swaps require both sides to approve one confidential atomic exchange. The application cannot revoke existing mainnet contracts or erase earlier public settlement data.

TLS protects traffic on each connection. It does **not** prevent APP20/Cloudflare or Starkscan/the proving operator from accessing proving payloads at their endpoints. The provider API key stays in Worker secret storage; wallet signing keys and viewing-key secrets stay with the wallet. Proving witnesses can still reveal transaction details. We do not call this route a blind relay or OHTTP.
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.

Starkscan's published capabilities, complete docs and OpenAPI were checked on 2026-09-07; none advertised an OHTTP gateway. An unpublished gateway may exist, but is not assumed. The operator accepted the HTTPS limitation. Existing `/api/ohttp/*` code remains separate and never silently downgrades encrypted requests.
### Proving payload exposure

The Worker does not log or persist proof request/response bodies. Agents authenticate with separately provisioned relay tokens; Privy users authenticate with Privy access tokens. Job capabilities bind result polling to the authenticated caller. Submission keys are scoped per caller. The Worker enforces request/concurrency limits; Starkscan also enforces its provisioned concurrency and daily budget. No unlimited public prover endpoint is exposed.
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**. Wallet signing and viewing-key secrets stay with the wallet; the proving witness can reveal transaction details.

Starkscan delivers a completed result only once. Clients preserve the entire result, including screening `additional_data`, before using it. Browser journals encrypt results in IndexedDB with a browser-owned key; Node journals use owner-only files. Preserve these journals. An uncertain delivery stays fenced instead of automatically starting another proof. Clearing storage can destroy recovery material.

Direct contract discovery avoids another hosted indexer, but the RPC provider can observe requested channels, notes and timing. It may be slower than an indexer for large histories.
The Worker does not log or persist proof request/response bodies. Separate relay tokens, caller-bound polling and request/concurrency limits protect access. Clients preserve completed proving results, including screening `additional_data`, before use. Preserve encrypted browser journals or owner-only Node journals: unknown delivery or submission outcomes remain fenced instead of starting another proof. RPC providers can observe discovery queries and timing.

## Use the app

- `/rfq`: request a quote, check replies, review and accept a funded atomic swap; records remain below the form.
- `/rfq/maker`: register a public encryption key, fund available inventory, withdraw it, and export explicit bot pricing/fee limits.
- `/agents`: Node library, runnable bot and protocol instructions.
- `/recovery/privy`: sign in to the configured Privy project, select your account, register/shield/transfer/unshield, and manage recovery.
- `/chat`: localnet chat implementation; no mainnet Chat helper has been deployed. Chat loads messages after unlocking and refreshes every 60 seconds while visible and online. Unlocked access lasts across app navigation in this tab and clears on lock, disconnect, or account/network change. Backups and older history are under Chat settings.

The default RFQ flow is **amount + minimum receive → Get quotes → request the best funded offer → review → swap**. Comparison batches encrypted preliminary requests to at most five randomly selected active makers from a randomly chosen registry page (20 entries). It ranks valid replies by exact receive amount, excluding expired, below-minimum and insufficient-inventory prices. This is the best offer received, not a guarantee of the best market price. Pool and wallet/network fees are additional; the final review checks the current pool fee.

Only the selected maker receives a second request with a settlement commitment and can reserve inventory. A changed funded price requires explicit review; your original minimum remains enforced. Local recovery serializes reservation attempts across tabs, but is not an on-chain global one-winner constraint. Uncertain submissions stay fenced. Proving and transaction inclusion must complete before expiry.

**Advanced** allows a direct funded request to one maker. **Negotiate in Chat** preserves bilateral fixed-offer discussions and existing offer attachments; those attachments are not atomic RFQ settlement, and mainnet Chat still requires its separate deployment.

A maker must have output inventory and a running bot before executable quotes are available. Spreads are not guaranteed profit.
- `/rfq` and `/rfq/confidential`: confidential availability and, in the dedicated local workspace, the development escrow flow.
- `/rfq/maker`: inspect and recover older maker inventory; new public registration and funding are blocked.
- `/agents`: current Node API, confidential development and historical recovery instructions.
- `/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 deployed. Fixed offers may be discussed, but acceptance requiring a swap is blocked until the confidential wallet flow is available.

## Node.js library

Expand All @@ -70,24 +56,12 @@ npm install ./app20-agent-sdk-0.1.0.tgz
import { App20Client } from '@app20/agent-sdk';
const app = new App20Client();
await app.verify();
const { makers, nextOffset } = await app.listMakers();
const { makers } = await app.listMakers(); // Historical registry, read-only.
```

The library provides `createTransportKey`, `createOperatorConfig`, `runMaker`, encrypted quote preparation/submission/recovery, and `createPrivacyWallet`. The latter connects a local Starknet account and viewing-key provider to contract discovery and Starkscan proving. It returns an executor accepted by `app.settle(...)`, plus register/shield/transfer/unshield methods. It requires a relay token, persistent local state, and explicit gas budgets; no signing or proving starts on import.

Full API and recovery details: [packages/agent-sdk/README.md](packages/agent-sdk/README.md). Private keys, transport-key files, viewing keys, quote journals and proof journals must never be committed or shared in chat.

## Run a maker

```sh
node public/downloads/app20-maker.mjs --init-key ./maker-key.json
node public/downloads/app20-maker.mjs operator.json --check
# Inject APP20_MAKER_SIGNING_KEY through local secret management.
export APP20_MAKER_TRANSPORT_FILE=./maker-key.json
node public/downloads/app20-maker.mjs operator.json --run
```
Use `@app20/agent-sdk/confidential` for the development escrow. The old `prepareQuote`, `submitRequest`, `settle`, registration and public inventory-funding APIs reject new execution. `createPrivacyWallet` retains explicitly invoked registration, shield, encrypted transfer, unshield and reconciliation; its old public-term settlement executor is disabled.

`--check` verifies deployments/configuration without loading a signer or submitting. Other commands include `--register`, `--fund`, `--withdraw`, `--deactivate`, `--release`, and `--reconcile`. Price, spread, trade sizes, price expiry, inventory and gas limits are operator inputs. Preserve the bot's state file and reconcile uncertain submissions before restarting. See [maker operations](docs/makers/README.md).
The maker CLI retains `--check`, `--reconcile`, `--release`, `--withdraw` and `--deactivate` for existing positions. `--register`, `--fund` and `--run` are blocked. Preserve existing state and reconcile uncertain submissions before recovery. See [maker recovery](docs/makers/README.md) and [SDK details](packages/agent-sdk/README.md). Private keys, viewing material and journals must never be committed or shared in chat.

## Develop

Expand All @@ -96,7 +70,7 @@ npm ci
npm run dev
```

Production uses the deployed mainnet configuration. Alice/Bob are development accounts only:
Production retains pinned deployment identities for wallet operations and historical recovery; it does not enable confidential settlement. Alice/Bob are development accounts only:

```sh
npm run dev:localnet
Expand Down Expand Up @@ -170,12 +144,12 @@ The Worker serves the app and RPC/prover routes. Its API keys are not embedded i

A new joint escrow exchanges both assets as encrypted STRK20 notes, with separate party approvals and independent timeout refunds. The Cairo contract, Node SDK and local browser workspace are implemented. Run `npm run dev:confidential` and open `http://127.0.0.1:5198/rfq/confidential`. See [the development guide](docs/CONFIDENTIAL_RFQ.md).

Mainnet activation is disabled pending real STARK proofs, independent wallet integration and review. Local contract executions use simulated proof facts. The existing mainnet RFQ continues to expose funded trade terms; Chat encryption does not conceal settlement amounts. The new path still exposes escrow activity, timing and fees, and a hosted prover sees its witness.
Mainnet activation is disabled pending real STARK proofs, independent wallet integration and review. Local contract executions use simulated proof facts. New execution through the earlier public-term RFQ path is blocked in the app and SDK. Chat payments also use encrypted transfers; Chat swaps remain blocked until the confidential wallet integration is ready. Escrow activity, timing and fees remain visible, and a hosted prover sees its witness.

## Hackathon demo

Three real mainnet swaps each exchanged **0.01 shielded STRK for 0.001 shielded USDC**. Successful receipts, `QuoteFilled` events, traces through APP20 and STRK20, and deployed class hashes were checked. The same operator controlled maker and taker; these are settlement smoke tests. The test maker is now inactive with no remaining inventory. See [mainnet evidence](deployments/mainnet/smoke-test-2026-09-07.json).

The three verified hashes are in `strk20.json`. Demo execution cost **35.863877034965690848 STRK** in network and pool fees; including the earlier deployment, fees total **63.910369825551435280 STRK**, below the 65 STRK ceiling. Another 0.5 STRK was exchanged for native USDC inventory, separately from fees.

See [demo status and submission checklist](docs/HACKATHON_DEMO.md) and [Remotion recording instructions](tools/demo-video/README.md). The current 2:16 `app20-demo-v8-confidential.mp4` includes Liam narration from ElevenLabs, localnet Chat, the new local confidential escrow and refund flow, subtitles, a macOS window frame and maker/agent previews. Mainnet confidential activation remains pending. Each source is clearly labelled. A public video URL is still required; `demo_video` remains empty.
See [demo status and submission checklist](docs/HACKATHON_DEMO.md) and [Remotion recording instructions](tools/demo-video/README.md). The prior 2:16 `app20-demo-v8-confidential.mp4` includes Liam narration from ElevenLabs, localnet Chat, the new local confidential escrow and refund flow, subtitles, a macOS window frame and maker/agent previews. Its Chat offer acceptance and maker onboarding scenes predate the private-only settlement policy and must be replaced before publication as the current product. Mainnet confidential activation remains pending. A public video URL is still required; `demo_video` remains empty.
Loading
Loading