Build

Architecture

A static app with a real Zcash wallet inside, a relay and a gateway that each see half, and an allowlist of upstreams. Nothing else.

Umbra Trade is a static web app. No Umbra Trade server holds keys, balances or the map of your wallets: there is a relay and a gateway that pass sealed requests, and neither sees both ends.

The system map

YOUR BROWSERAppScreens and ticketsStatic: no app serverWallet workerZcash's wallet in WASMSync, proofs, sendsEngineSizes, rests, timing,and the leak meterVenue adaptersFour venues andNEAR 1Click quotesVaultKeys and wallet list,encrypted on deviceCLOUDFLARERelay/relay/ohttpSees IP, not contentNo IP or cookies sentVERCEL · DUBLINGatewayOpens each requestSees content, not IPNo logs of its ownHolds Polymarket'sBuilder secret; signsonly Deposit Walletrelayer callsALLOWLIST ONLYUpstreamsZcash light serversNEAR Intents 1ClickPolymarket APIsPolymarket Perps APIHyperliquid APIJupiter, Solana RPCPolygon RPCGeckoTerminalDURABLE OBJECTLive feed/relay/live/*One socket per venue,market channels onlyno user channelsPUBLICVenue feedsHyperliquidPolymarketPolymarket PerpsImage proxy/relay/imgPublic, cached 24 hImage fetchChecked on every hopHeld assets: sealedImage hostsLogos and picturesSealed with Oblivious HTTP: every call about youPublic market data and pictures: the relay sees whichYOUR BROWSER · UMBRA TRADE.XYZAppScreens, charts, order ticketsWallet workerZcash's wallet in WASM: sync, proofsEngineSizes, rest rules, timing, leak meterVenue adaptersPolymarket, Perps, Hyperliquid, SolanaVaultKeys and wallet list, encryptedOHTTP · sealedCLOUDFLARE WORKERRelaySees your IP, not the contentNo IP, cookies or agent passed onsame sealed bytesVERCEL FUNCTION · DUBLINGatewaySees the content, not your IPWrites no logs of its ownSigns only Deposit Wallet callsHTTPS, from IrelandALLOWLIST ONLYUpstreamsZcash light servers, NEAR 1ClickPolymarket, Polymarket PerpsHyperliquid, Jupiter, Solana RPCPolygon RPC, GeckoTerminalPUBLIC DATA · NOT SEALEDLive feed and pictures/relay/live/*: one WebSocket per venue,market channels only/relay/img: public pictures, 24 h cachePictures of what you hold go sealedSealed (Oblivious HTTP)Public data, not sealed
Every call about you takes the vermilion path. The relay knows who is asking, the gateway knows what is asked, and neither knows both.
The map in the README, rendered from .github/diagrams/readme-system.mmd in light and dark.

The detailed map: every part in the browser, both lanes through the relay, and every upstream.

YOUR BROWSERAppScreens and ticketsStatic: no app serverWallet workerZcash's wallet in WASMSync, proofs, sendsEngineSizes, rests, timing,and the leak meterVenue adaptersFour venues andNEAR 1Click quotesVaultKeys and wallet list,encrypted on deviceCLOUDFLARERelay/relay/ohttpSees IP, not contentNo IP or cookies sentVERCEL · DUBLINGatewayOpens each requestSees content, not IPNo logs of its ownHolds Polymarket'sBuilder secret; signsonly Deposit Walletrelayer callsALLOWLIST ONLYUpstreamsZcash light serversNEAR Intents 1ClickPolymarket APIsPolymarket Perps APIHyperliquid APIJupiter, Solana RPCPolygon RPCGeckoTerminalDURABLE OBJECTLive feed/relay/live/*One socket per venue,market channels onlyno user channelsPUBLICVenue feedsHyperliquidPolymarketPolymarket PerpsImage proxy/relay/imgPublic, cached 24 hImage fetchChecked on every hopHeld assets: sealedImage hostsLogos and picturesSealed with Oblivious HTTP: every call about youPublic market data and pictures: the relay sees whichYOUR BROWSER · UMBRA TRADE.XYZAppScreens, charts, order ticketsWallet workerZcash's wallet in WASM: sync, proofsEngineSizes, rest rules, timing, leak meterVenue adaptersPolymarket, Perps, Hyperliquid, SolanaVaultKeys and wallet list, encryptedOHTTP · sealedCLOUDFLARE WORKERRelaySees your IP, not the contentNo IP, cookies or agent passed onsame sealed bytesVERCEL FUNCTION · DUBLINGatewaySees the content, not your IPWrites no logs of its ownSigns only Deposit Wallet callsHTTPS, from IrelandALLOWLIST ONLYUpstreamsZcash light servers, NEAR 1ClickPolymarket, Polymarket PerpsHyperliquid, Jupiter, Solana RPCPolygon RPC, GeckoTerminalPUBLIC DATA · NOT SEALEDLive feed and pictures/relay/live/*: one WebSocket per venue,market channels only/relay/img: public pictures, 24 h cachePictures of what you hold go sealedSealed (Oblivious HTTP)Public data, not sealed
Every call about you takes the vermilion path. The relay knows who is asking, the gateway knows what is asked, and neither knows both.

The two hops

YOUYour browserSeals every requestKEEPSKeys, balances andyour wallet listSENDSSealed calls about you(public prices plain)HOP 1 · CLOUDFLARERelayKnows who, not whatSEESYour IP addressRequest sizes, timesNEVER SEESWhat you askedWhich wallet it's forHOP 2 · VERCELGatewayDublin: what, not whoSEESThe request itselfThe relay's addressNEVER SEESYour IP or cookiesWho sent itALLOWLISTED HOSTUpstreamVenue, NEAR or ZcashSEESOne wallet's requestThe gateway's addressNEVER SEESYour IPYour other walletssealed requestsame sealed bytesHTTPS, from Irelandanswersealed answersealed answerThe app pins the gateway's key (packages/net/src/constants.ts), so the relay cannot swap in its own.YOUYour browserSeals every requestKEEPSKeys, balances andyour wallet listSENDSSealed calls about you(public prices plain)sealed both waysHOP 1 · CLOUDFLARERelayKnows who, not whatSEESYour IP addressRequest sizes, timesNEVER SEESWhat you askedWhich wallet it's forsame sealed bytesHOP 2 · VERCELGatewayDublin: what, not whoSEESThe request itselfThe relay's addressNEVER SEESYour IP or cookiesWho sent itHTTPS, from IrelandALLOWLISTED HOSTUpstreamVenue, NEAR or ZcashSEESOne wallet's requestThe gateway's addressNEVER SEESYour IPYour other walletsThe app pins the gateway's key, so therelay cannot swap in a key of its own.
Requests go left to right and answers come back sealed. To read a request together with your IP, the relay and the gateway would have to share what they each see.

The details of each hop, what it forwards and what it drops, are on Oblivious HTTP.

The money's route

ZCASH SHIELDED POOLYour balanceOrchard, Ironwood notesAmounts stay hiddenpublic hop0.01–1 ZEC only,random start20 s–3 min later,no memoNEAR INTENTS1Click depositSigned quote, checkedRefunds: fresh address~8 minUSDC or SOL;Polymarket'sbridge adds pUSDNEW KEY, NEVER USEDFresh venue wallet…/6874'/venue'/index'Trades, then goes homeon Polymarket,Perps, Hyperliquidor SolanaTHE VENUE'S MARKETTradeSigned by its own key(on Perps, by its proxy)trip homeclose, then oneswap to ZEC;under ~$1 staysas dustNEAR INTENTS1Click homeQuote to a freshshielded addresspublic hopa new addressevery tripSHIELDED POOLBack homeFresh address; rests2–6 h before it's spentjoins yourbalanceEvery quote's signature and terms are checked before any ZEC is sent.NEAR's confidential mode covers every funding and every trip home except Polymarket's.ZCASH SHIELDED POOLYour balanceOrchard and Ironwood notes,amounts and addresses hidden0.01–1 ZEC · random startNEAR INTENTS1Click deposit addressThe one public hop in. Signed quote,checked; refunds to a fresh addressabout 8 minNEW KEY, NEVER USEDFresh venue walletm/44'/coin'/6874'/venue'/index'USDC or SOL arrives (Polymarket: pUSD)tradeTHE VENUE'S OWN MARKETTradeSigned by its key (Perps: its proxy);under ~$1 left at close stays as dustclose, then send homeNEAR INTENTS1Click, the way homeSigned quote to a fresh shieldedaddress: the one public hop outZEC payoutFRESH SHIELDED ADDRESSBack homeRests 2–6 h before it is spent,then joins your balanceEvery quote is checked before ZEC is sent.
The money's whole route. Two hops go through NEAR: the funding, always at a standard size, and the trip home, at whatever the wallet holds. The wallet in between holds one position and no history.
The README's funding round trip, from .github/diagrams/readme-funding.mmd.
ZCASH SHIELDED POOLYour balanceOrchard, Ironwood notesAmounts stay hiddenpublic hop0.01–1 ZEC only,random start20 s–3 min later,no memoNEAR INTENTS1Click depositSigned quote, checkedRefunds: fresh address~8 minUSDC or SOL;Polymarket'sbridge adds pUSDNEW KEY, NEVER USEDFresh venue wallet…/6874'/venue'/index'Trades, then goes homeon Polymarket,Perps, Hyperliquidor SolanaTHE VENUE'S MARKETTradeSigned by its own key(on Perps, by its proxy)trip homeclose, then oneswap to ZEC;under ~$1 staysas dustNEAR INTENTS1Click homeQuote to a freshshielded addresspublic hopa new addressevery tripSHIELDED POOLBack homeFresh address; rests2–6 h before it's spentjoins yourbalanceEvery quote's signature and terms are checked before any ZEC is sent.NEAR's confidential mode covers every funding and every trip home except Polymarket's.ZCASH SHIELDED POOLYour balanceOrchard and Ironwood notes,amounts and addresses hidden0.01–1 ZEC · random startNEAR INTENTS1Click deposit addressThe one public hop in. Signed quote,checked; refunds to a fresh addressabout 8 minNEW KEY, NEVER USEDFresh venue walletm/44'/coin'/6874'/venue'/index'USDC or SOL arrives (Polymarket: pUSD)tradeTHE VENUE'S OWN MARKETTradeSigned by its key (Perps: its proxy);under ~$1 left at close stays as dustclose, then send homeNEAR INTENTS1Click, the way homeSigned quote to a fresh shieldedaddress: the one public hop outZEC payoutFRESH SHIELDED ADDRESSBack homeRests 2–6 h before it is spent,then joins your balanceEvery quote is checked before ZEC is sent.
The money's whole route. Two hops go through NEAR: the funding, always at a standard size, and the trip home, at whatever the wallet holds. The wallet in between holds one position and no history.

In the browser

PiecePackageWhat it does
Wallet workerpackages/zwalletZcash's zcash_client_sqlite 0.23 on wasm32-wasip1, in a Web Worker: sync, notes, proofs, sends
Vaultapps/webIndexedDB, every record AES-GCM encrypted under a non-extractable key, optionally wrapped by a passphrase
Enginepackages/engineStandard sizes, rest rules, random scheduling, the wallet registry, the leak meter, key paths (BIP 32, SLIP-0010)
Railspackages/railsNEAR 1Click quotes, deposits and status; every quote's ed25519 signature checked
Venuespackages/venuesPolymarket (official SDK in its own worker), Polymarket Perps, Hyperliquid (@nktkas/hyperliquid SDK), Solana (Jupiter Ultra)
OHTTPpackages/netThe RFC 9458 client and the gateway's pinned key
Chartpackages/chartA canvas engine for live lines and candles

On the network

ServiceWhereWhat it does
mitoshi-webCloudflare Worker, targeted placement near AWS eu-west-1Serves the static app with strict headers, relays sealed messages, proxies public pictures, holds one live feed per venue in a Durable Object
mitoshi-gatewayVercel Function, Dublin (dub1)Opens each sealed message, calls only the allowlist, seals the answer; holds the NEAR partner key and the Polymarket builder secret
mitoshi-docsCloudflare Worker, static assetsThis site

On this page