Build on private markets.
A read API with no keys and no per-client state, a relayer that submits proofs for you, and a small SDK that keeps keys in the user's browser.
Read API
Public data
Base URL https://api.yourdomain.xyz. No keys. Responses are JSON.
GET
/v1/syncLatest indexed block and note-tree root.GET
/v1/deploymentChain ID and every contract address.GET
/v1/recordsEncrypted notes since a cursor. Only your keys can read yours.GET
/v1/tree/path/:indexMerkle path for a note, used when proving.POST
/v1/nullifiersCheck which notes are already spent.GET
/v1/spot/poolsEvery pool with reserves and fee.POST
/v1/spot/quoteQuote a swap: amount out, impact, fee.GET
/v1/marketsMarkets with price, max leverage and status.GET
/v1/markets/:id/fundingHourly funding history for a market.Relayer
Submit proofs
The relayer submits a user's proof and pays the gas, so the user's public wallet never touches the trade.
POST
/v1/relay/:actionSubmit a proof. Actions: swap, perp-open, perp-close, lp-add, lp-remove, maker-post.GET
/v1/jobs/:idJob state: queued, proving, submitted, confirmed, refunded.GET
/v1/relayerRelayer address, fee and queue length.SDK
Keys stay client-side
npm i @uponly/private-sdk
import { deriveKeys, addressOf, scanCreated } from "@uponly/private-sdk";
// 1. One wallet signature makes the keys. Nothing leaves the browser.
const sig = await wallet.signMessage(CREATE_ACCOUNT_MESSAGE);
const keys = deriveKeys(sig);
// 2. Your private receiving address
const addr = addressOf(keys);
// 3. Find the notes that belong to you
const notes = await scanCreated(keys, { api: "https://api.yourdomain.xyz" });
Package and API names are placeholders until you publish them. The app in this repo runs the same flows on a built-in testnet simulator (assets/engine.js).
Try it
Live response
Sample GET /v1/markets built from the test oracle in your browser: