Build against typed boundaries
Six adapter interfaces, ten HTTP endpoints, and a configuration surface where the absence of a value is meaningful rather than silently defaulted. Swap one factory in the registry and nothing in the UI changes except the status chips.
Adapter contracts
Each adapter carries an AdapterMeta describing what it does, what it does not do, and which environment keys would change that. The registry in src/lib/adapters/registry.ts is the only place that decides which implementation is active.
- 01 · solana-entryLive
Solana entry adapter
Wallet connection, network verification, and mainnet swap execution.
- NEXT_PUBLIC_SOLANA_CLUSTER
- NEXT_PUBLIC_SOLANA_RPC_URL
- 02 · conversion-routingPlanned
Conversion and routing adapter
Quotes and routes a SOL balance into XMR so participation can settle in the Monero.
- CONVERSION_PROVIDER_URL
- CONVERSION_PROVIDER_KEY
- 03 · monero-settlementBeta
Monero settlement adapter
Validates Monero destinations and is the interface a reward payout service would implement.
- MONERO_WALLET_RPC_URL
- ORANGECURVE_SETTLEMENT_SIGNER_URL
- 04 · private-marketsPlanned
Private asset and market layer
Confidential balances, private order flow and settlement proofs — the layer that makes the headline literal.
no configuration path — research track
- 05 · rewards-engineBeta
Rewards engine
Applies a token’s published fee split, weights holders by time-held balance, and pays the pot out in private XMR.
- INDEXER_URL
- ORANGECURVE_SETTLEMENT_SIGNER_URL
- 06 · indexerBeta
Indexer and API
Serves token listings, charts, trades and holder data, keeping public chain facts separate from private user state.
- INDEXER_URL
- INDEXER_KEY
- NEXT_PUBLIC_USE_INDEXER
HTTP API
Every endpoint validates its input with zod on the server, is rate limited per instance, returns a uniform { ok, data | error } envelope, and sends Cache-Control: no-store.
- GET
/api/statusMachine-readable build and capability status. The source of truth behind every status chip.
- Returns
- { build, capabilities, adapters[], protocolResearch[] }
- GET
/api/tokensToken listings with server-side filtering, sorting and pagination.
- Params
- tab, search, sort, dir, minMarketCap, maxMarketCap, minRewardRate, verifiedOnly, limit, offset
- Returns
- { items[], total, generatedAt, source }
- GET
/api/tokens/{id}One token with full detail and its immutable fee split.
- Returns
- TokenDetail
- GET
/api/tokens/{id}/candlesOHLCV series. Never longer than the token has existed.
- Params
- tf = 5m | 1h | 4h | 1d
- Returns
- Candle[]
- GET
/api/tokens/{id}/tradesRecent trades. Public data by definition on Solana today.
- Params
- limit ≤ 100
- Returns
- Trade[]
- GET
/api/tokens/{id}/holdersHolder table with time-weighted eligibility.
- Returns
- Holder[]
- POST
/api/quoteSOL → XMR quote with expiry, per-hop route disclosure and fee breakdown.
- Params
- { fromAmountSol: number }
- Returns
- ConversionQuote
- POST
/api/private-addressBech32/Bech32m validation. The address is checked and discarded — never logged, stored or echoed.
- Params
- { address: string }
- Returns
- PrivateAddressCheck
- POST
/api/launch/previewValidates a launch configuration and returns the exact immutable terms plus a cost estimate. Mints nothing — there is no create endpoint.
- Params
- LaunchConfig
- Returns
- { valid, mintingEnabled, terms, costEstimate, warning }
- GET
/api/rewardsAccruals, positions and epoch history for an address.
- Params
- wallet = <solana address>
- Returns
- { accruals[], epochs[], positions[] }
curl -s localhost:4100/api/status | jq '.data.capabilities'
curl -s 'localhost:4100/api/tokens?tab=graduating&sort=rewards&dir=desc&limit=5' \
| jq '.data.items[] | {symbol, rewardRate, curveProgress}'
curl -s localhost:4100/api/private-address \
-H 'content-type: application/json' \
-d '{"address":"t1RwbKka3QmQ2fJ2AxHLGWRrKEHqmYm4Eay"}' | jq '.data'What is public and what is private
Exactly which data is readable by anyone and which is protected by the Monero, named item by item.
Public today
Anyone can read this. Treat all of it as permanently on the record.
Token name, symbol and metadata
DevnetPublished at launch and intended to be public. Discovery does not work otherwise.
Bonding curve, graduation threshold and fee split
BetaCommitted before the first trade and immutable afterwards. Public by design — these are the rules everyone is trading under.
Your Solana address and its SOL balance
DevnetPublic on Solana. Connecting a wallet to OrangeCurve does not change this, and nothing OrangeCurve does can.
SPL token balances and transfers
DevnetPublic on Solana. A standard SPL token has readable balances and a readable transfer history. Routing SOL through Monero first does not make later Solana activity private.
Per-epoch total XMR distributed
BetaPublished so the reward rule is auditable in aggregate. Total distribution should be checkable even when recipients are not.
Private today
Protected by Monero itself, available now — for value that actually reaches the Monero.
XMR held in the Monero
LiveAmounts and counterparties inside the Monero Monero are not published. This is a property of Monero, available today.
Which address received which reward
BetaPayouts land as private XMR, so a reward stream does not become a public income record. The timing of a claim remains a signal; batching reduces it and does not remove it.
git clone <repo> orangecurve
cd orangecurve
npm install
cp .env.example .env.local
npm run dev # http://localhost:4100
npm run build # production build
npm run lint # eslint
npm run typecheck # tsc --noEmitNo credentials are required. With an empty .env.local the app runs against Solana devnet with the full catalogue, and any action that would move value is gated with an explanation rather than stubbed out.
- public
NEXT_PUBLIC_SOLANA_CLUSTERdevnet | testnet | mainnet-beta. Default devnet. - public
NEXT_PUBLIC_SOLANA_RPC_URLRPC endpoint. Verified by genesis hash at connect time. - public
NEXT_PUBLIC_LAUNCHPAD_PROGRAM_IDUnset ⇒ trading and minting are gated; browsing and review still work. - public
NEXT_PUBLIC_FEE_RECIPIENTProtocol fee address, rendered as an inspectable explorer link. - server
INDEXER_URL / INDEXER_KEYPoints the indexer adapter at your own verified on-chain index. - server
CONVERSION_PROVIDER_URL / _KEYEnables real SOL → XMR quotes and routing. - server
MONERO_WALLET_RPC_URLEnables reading private settlement state. - server
ORANGECURVE_SETTLEMENT_SIGNER_URLOut-of-process signer that holds payout authority. Never a key in this app. - server
RATE_LIMIT_PER_MINUTEPer-instance fixed-window limit. Default 60.
Anything prefixed NEXT_PUBLIC_ is compiled into the browser bundle and must never hold a secret. Server keys are read only from src/lib/config/server-env.ts, which is marked server-only so importing it from a client component is a build error rather than a leak.