Zolana documentation

Everything you need to send and receive private Solana transfers with Zolana: what each step does, exactly which wallet approvals to expect, and — most importantly — how to get your funds out of any intermediate state.

Devnet beta. Zolana currently runs on Solana devnet with test funds only. Nothing here moves real value. Amounts use wrapped SOL (wSOL) under the hood.

# Overview

Zolana is a metadata-privacy layer. The on-chain confidentiality (hiding the amount and the recipient of a transfer) is provided by the Umbra protocol — Groth16 zero-knowledge proofs plus Arcium multi-party computation. Zolana's job is everything around that: routing every network request through the Nym mixnet so your IP and request patterns don't betray you, bundling the ZK proving files locally so proving doesn't phone home, scheduling claims and withdrawals with timing jitter, and reporting honestly what is protected against whom.

A full private transfer has four stages, and the app shows all of them live:

Sender ready
Recipient checked
Funds prepared
Shielded to private balance
Private balance ready
6Sent privately to recipient
FIG 1 — the sender's live flow timeline in the app. Completed steps stay visible, so when the transfer finishes you can review the whole path.

# Modes & what's actually private

Zolana ships two profiles. The app banner always tells you which one you're in — and what it means. We never present a test mode as private.

ProfileTransportWhat it's forPrivacy posture
strict-maxNym mixnet, fail-closedThe real thing: every RPC read, indexer call, relayer submit and MPC poll leaves through the mixnet — or the action is blocked.On-chain confidentiality + origin-IP protection. Expect seconds per network round-trip; that latency is the privacy.
devnet-fastDirect clearnetFunctional testing of the same on-chain flow with fast feedback.Not network-private. The on-chain payload is still confidential, but your RPC provider sees your IP and request timing. The app shows a permanent amber warning in this mode.

# Quickstart

Install a Solana walletPhantom or Solflare in Chrome/Brave. Create (or pick) two wallets if you want to test both sides on one machine: one sender, one recipient.
Switch the wallet to devnetIn Phantom: Settings → Developer settings → enable testnet mode → select Solana devnet.
Get devnet SOLUse faucet.solana.com for the sender wallet. ~0.5 SOL is plenty; sends also need a small fee buffer beyond the amount. Fund the recipient wallet from the faucet too — never from the sender. Sending SOL from the sender to the recipient to cover its registration fee creates a public, direct A→B transfer on-chain that defeats the privacy of everything that follows.
Open the app and pick a sideThe app has two separate experiences — Send privately and Receive privately. The recipient must connect once before they can be sent to (this enables receiving for that wallet).

# Sending privately

Connect the sender walletClick Connect sender. Your wallet asks to approve the connection — connection only, no transaction.
First use only: privacy registrationThe first time a wallet uses Zolana it registers a privacy account on-chain (one signature). This creates the keys that let you hold a private balance. It never has to be repeated.
Enter recipient and amountThe recipient must have connected to Zolana at least once (see Receiving). The app checks this before anything moves and stops with a clear message if they haven't.
Click “Send privately” and follow the timelineThe app prepares funds (wrapping SOL→wSOL if needed), shields them into your private balance, waits for the private balance to be confirmed by the MPC network, then creates the private note for the recipient. Each stage lights up live (FIG 1), and the amber strip tells you when a wallet popup is coming and what it is for.
Check your wallet — approve shielding 0.040 SOL into your private balance (a zero-knowledge proof is built first; the popup can take a few seconds)
FIG 2 — the approval strip. Before every wallet popup, the app states which operation the signature belongs to, so you never sign blind.
Why several steps? A private send spends from your private balance, not your public wallet. If the private balance doesn't cover the amount, the app tops it up first (wrap → shield → claim). On later sends with balance left over, those steps are skipped automatically and the send is much faster.

Split across multiple recipients

The send card has a Split across multiple recipients panel. Paste several addresses (one per line), set a total and a minimum each, and Zolana funds your private balance once for the total, then issues one private note per recipient. Two options, both on by default and both good for privacy:

Every recipient must have opened Zolana once (same readiness check as a single send) — this is verified for all of them before any funds move. Each send is independent: if one fails mid-batch, the rest still go and the unsent funds simply stay in your private balance — press Split & send again to retry the remainder (you are never double-charged). The same honesty boundary applies: recipients and amounts are hidden per note, but the fact that your wallet made several private sends is public.

# Receiving privately

Connect the recipient walletClick Connect recipient in the Receive view. First use triggers the same one-time privacy registration (one signature).
The inbox checks itselfZolana scans for private notes addressed to you and lists them under Incoming private transfers with live states. New transfers are scheduled for claim automatically, with a randomized delay that improves unlinkability.
Claim happens via relayer — no gas neededThe claim is submitted by a relayer, so your wallet needs no SOL and signs nothing for this step. This is deliberate: a recipient who funds their own claim leaves a trail.
Funds release to your walletAfter the claim, the funds sit in your private balance and a wallet release is scheduled. The release (withdraw) asks for one wallet signature. Then the SOL is in your wallet.
0.010 SOLclaim in ~3 min5j61oEW…
0.498 SOLready2Urc9kP…
FIG 3 — the incoming-transfers list. Each note shows amount, live state (scheduled / claiming / ready / available), and its on-chain reference.

# Every wallet approval, explained

For trust, here is the complete list of popups Zolana can ever trigger. The in-app amber strip (FIG 2) announces each one before it appears. If your wallet shows a popup that doesn't match this list, reject it.

WhenPopupWhat you are signingSignature?
Connect (both sides)Connect requestNothing on-chain — just allows the app to see your address and request signatures later.no tx
First use of a walletPrivacy registrationOne transaction creating your privacy account (encryption keys registered on-chain). Once per wallet, ever.1 signature
Send: funds preparationWrap SOL → wSOLA standard token wrap of exactly the displayed amount into your own token account. Skipped when you already hold enough wSOL.1 signature
Send: shieldingShield into private balanceThe deposit moving the displayed amount from your public wSOL into the shielded pool. A ZK proof is generated locally first, so this popup can lag a few seconds behind the strip's announcement.1 signature
Send: the private sendPrivate sendThe note creation that pays the recipient from your private balance. Recipient and amount are not visible on-chain.1 signature
Receive: claim— none —The claim is relayer-submitted precisely so you don't pay gas or leave a trail. The app says so in the strip.no popup
Receive: wallet release / Recover pendingWithdraw to walletMoving the displayed amount from your private balance into your public wallet balance.1 signature
Your keys never leave the wallet. Zolana never asks for your seed phrase or private key. All proving happens in your browser with locally bundled circuit files.

# Reading the live operation trace

The Operation trace panel at the bottom of the app is open by default and logs every step with timestamps as it happens: funds checks, proof generation, transaction signatures, relayer submissions, MPC callbacks, and any errors verbatim. Three things to know:

# Fund recovery guide — nothing is lost mid-flow

A private transfer crosses several on-chain states. The key design fact: every intermediate state is durable and recoverable. Funds are only ever in one of four places — your public wallet, your private balance, a shielded note addressed to you, or a shielded note addressed to the recipient. Below is what to do for every interruption, in the order the states occur.

S1 · Send was interrupted after shielding (browser closed, error at the send step)

Where the funds are: your private balance (or a self-shield note about to become it). Nothing is in limbo on the network's side.

S2 · Sent, but the recipient hasn't received anything yet

Where the funds are: a shielded note on-chain addressed to the recipient. It does not expire and cannot be taken by anyone else.

S3 · Claim failed or the browser closed while claiming

Where the funds are: still in the shielded note (a failed claim changes nothing on-chain) or already in the recipient's private balance if the claim landed.

S4 · Claimed, but the funds aren't in the wallet yet

Where the funds are: the recipient's private balance, with a scheduled wallet release.

Receive privately  Recover pending
FIG 4 — the two recovery actions in the Receive view. "Receive privately" re-runs the inbox/queue now; "Recover pending" withdraws any stuck private balance to your wallet.

S5 · The browser/device was lost entirely

Where the funds are: on-chain — shielded notes and private balances belong to your wallet keys, not to the browser.

S6 · Strict mode says the mixnet is unavailable

Where the funds are: wherever they were — nothing moves over clearnet, by design (fail-closed).

# Troubleshooting

Message / symptomWhat it meansWhat to do
"recipient is not ready to receive"The recipient wallet has never connected to Zolana, so it has no privacy account.Have the recipient open the app and click Connect recipient once (one-time registration). Then send again.
"not enough SOL to prepare wSOL"The amount plus the fee buffer exceeds the sender's devnet SOL.Get more devnet SOL from the faucet, or send a smaller amount.
"self-shield note was not indexed yet"The protocol indexer is lagging behind the chain.Wait ~1–2 minutes and click Send privately again — it resumes from the private-balance check (S1), nothing is lost.
"private balance is not ready yet"The MPC callback that finalizes your balance hasn't landed yet.Usually under a minute on devnet. Retry the send; it picks up where it left off.
"skipped stale/already-claimed note"The protocol scanner re-returns spent notes; Zolana filters the ones it already settled.Nothing — informational only.
"mixnet setup failed" / "mixnet unavailable"Strict mode could not establish the Nym transport.See S6. Wait/retry; nothing falls back silently.
Wallet popup is slow to appearFor shield/send, a zero-knowledge proof is computed in your browser first (seconds, device-dependent).Watch the amber strip — it announces the popup before it arrives. Don't re-click; the button is disabled while a send runs.
No wallet detectedThe browser has no Solana wallet extension.Install Phantom or Solflare, then reload the page.

# FAQ

Why is it slower than a normal Solana transfer?

Three honest reasons: ZK proofs are computed in your browser (seconds), the Arcium MPC network confirms private-balance operations asynchronously (tens of seconds), and in strict mode every network round-trip crosses three mixnet hops (~2.3s median vs ~0.4s direct, measured live). Zolana is built for transfers where privacy is worth seconds — and we position it exactly that way.

Why do claims and releases have random delays?

If a claim always followed its send by a fixed interval, an observer could link the two by timing alone. The jitter is part of the privacy, and you can always see the schedule on each item. Note the jitter is mode-dependent: strict-max spreads claims/releases over minutes; devnet-fast uses zero delay for fast testing (it is not network-private anyway). Also, the Recover pending button withdraws immediately and intentionally skips the release jitter — use it when you want funds now and the timing trade-off is acceptable.

What does Zolana store on my device?

Only the receive queue (note references, schedule times, signatures) in your browser's IndexedDB, keyed to your wallet address. No keys, no seed phrases, no balances. Losing it loses no funds (see S5). On a shared machine this is still a local linkage record, so the Receive view has a Clear local history button that wipes it on demand — your on-chain funds are unaffected and the inbox simply re-scans the chain next time you connect.

What does the relayer learn about me?

The relayer submits your claim, so it learns your wallet address as the claim recipient and when you claim (the claim transaction names your wallet publicly on-chain anyway). What it does not learn in strict mode is your IP — it sees a mixnet exit — and it cannot tell which deposit funded you, nor can it redirect funds: the ZK proof binds the claim to your registered keys.

What does my wallet extension see?

Your wallet (Phantom, Solflare, …) is outside Zolana's control and is its own trust boundary. It does its own clearnet RPC for connecting, showing balances, and simulating every transaction you sign — so the wallet vendor sees the transaction content and your IP regardless of Zolana's mixnet transport. This is inherent to browser wallets; we state it plainly rather than imply Zolana can mask it. Use a wallet you trust.

Is devnet-fast mode private?

The on-chain part, yes; the network part, no — and the app shows a permanent warning saying exactly that. Use strict-max for real network privacy.

What does it cost?

Phase A is fee-free (fee = 0) and has no token. You pay only Solana network fees on the transactions you sign.

# The privacy boundary, stated plainly

Zolana's claims are per-observer and bounded. Against a single passive observer (your RPC provider, your ISP, one network vantage point) the goal is to close the vector to near-chance, and that is what we test against devnet in CI. Against an active adversary running multiple mixnet hops, the cost is raised — not eliminated. A global passive observer watching all links at once is out of scope, and we say so.

What is always public, by protocol design: your wallet signs the pool deposit (so the chain — and Umbra's public indexer — records that your wallet used the pool), and the relayer-submitted claim transaction publicly names the recipient's wallet. What Zolana hides is who you paid, the amount, your network origin, and the link between a specific deposit and a specific claim. It does not hide the fact that you used the pool.

Anonymity-set context: the deposit→claim unlinkability is statistical — only as strong as the crowd of unspent notes in the pool. On devnet that crowd is minimal (a handful of test transfers), so an observer can often correlate a deposit and a claim by amount and timing; treat devnet as functional testing, not real privacy. On mainnet, Zolana rides Umbra's active pool, where the set is materially larger. The app surfaces this posture in the "Anon set" chip rather than hiding it, and never prints a fabricated number.

Finally, anything you do outside the app — pasting an address into a public explorer, or funding the recipient's wallet from the sender — is outside the boundary; the app warns where it matters.