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-routingBeta
Conversion and routing adapter
Quotes and routes a SOL balance into ZEC so participation can settle in the shielded pool.
- CONVERSION_PROVIDER_URL
- CONVERSION_PROVIDER_KEY
- 03 · zcash-settlementBeta
Zcash shielded settlement adapter
Validates shielded destinations and pays holder rewards into the Zcash shielded pool.
- ZCASH_LIGHTWALLETD_URL
- ZLAB_SETTLEMENT_SIGNER_URL
- 04 · private-marketsBeta
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 shielded ZEC.
- INDEXER_URL
- ZLAB_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 → ZEC quote with expiry, per-hop route disclosure and fee breakdown.
- Params
- { fromAmountSol: number }
- Returns
- ConversionQuote
- POST
/api/shielded-addressBech32/Bech32m validation. The address is checked and discarded — never logged, stored or echoed.
- Params
- { address: string }
- Returns
- ShieldedAddressCheck
- 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/shielded-address \
-H 'content-type: application/json' \
-d '{"address":"t1RwbKka3QmQ2fJ2AxHLGWRrKEHqmYm4Eay"}' | jq '.data'What is public, what is shielded, what is not built
A privacy product that is vague about its boundaries is a liability. This is the complete list, and it is the same list used on the protocol page and in the docs.
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 ZLAB does not change this, and nothing ZLAB 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 Zcash first does not make later Solana activity private.
Per-epoch total ZEC distributed
BetaPublished so the reward rule is auditable in aggregate. Total distribution should be checkable even when recipients are not.
Shielded today
Protected by Zcash itself, available now — for value that actually reaches the shielded pool.
ZEC held in the shielded pool
LiveAmounts and counterparties inside the Zcash shielded pool are not published. This is a property of Zcash, available today.
Which address received which reward
BetaPayouts land as shielded ZEC, 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.
Not yet protected
The parts that would make the headline literally true. None of these are implemented.
Your position size and direction
BetaThe objective. Requires confidential balances and private order submission, neither of which exists.
Your order before it executes
BetaRequires batching with a fixed cadence and a decoy policy to resist timing analysis. Open research problem.
Your relationship between a Solana address and a Zcash address
BetaA cross-chain route links the two by amount and timing unless it is deliberately broken. No provider is configured, and none will be adopted without this analysis published.
Your IP address and request timing
BetaVisible to whoever serves this front end and to the RPC provider. On-chain privacy does not survive network-level observation. Self-hosting the RPC and using Tor help; neither is on by default.
git clone <repo> zlab
cd zlab
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 → ZEC quotes and routing. - server
ZCASH_LIGHTWALLETD_URLEnables reading shielded settlement state. - server
ZLAB_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.