The key model
The recipient’s viewing and spending keys are generated and held inside Tachyon’s secure enclave onPOST /recipient/register. From then on, any action that needs those keys (listing stealth balances, deriving a stealth key to sweep funds, producing a disclosure record) is performed by the enclave after verifying a wallet signature from the user.
Integrators don’t store viewing keys client-side. The enclave is the source of truth; the wallet signature is the authorization.
This design means a lost device doesn’t lose the keys. A new device onboards by re-proving wallet ownership to the relayer.
Register a user
Read operations (all wallet-gated)
List the user’s stealth addresses
Derive a stealth key to sweep a specific delivery
What about client-side persistence?
Don’t, unless you have a specific reason. The common instinct is to cache a viewing key in the browser so the user “stays logged in”. We’d rather you didn’t:- Browsers leak. Any browser-side storage (localStorage, IndexedDB, even session storage) is within reach of XSS, extensions, or shared-device scenarios. The blast radius of a leaked viewing key is “everything this user ever receives”.
- The enclave is always available. Re-fetching on demand with a fresh wallet signature is a single round trip.
- The wallet is already the user’s identity. Asking them to sign once per session is a familiar UX pattern.
- Keep the derived stealth key, not the viewing key. Derived stealth keys are per-intent; one leaking compromises one delivery, not all future inflows.
- Encrypt with a key the user sets (PIN, biometric-unlock, wallet-signed KDF). Never in cleartext.
- On iOS/Android, use Keychain/Keystore; never raw app storage.
Backup and recovery
The enclave-resident keys are recoverable by re-registering with the same wallet signature. “Losing” a viewing key client-side is not a problem because there is no client-side source of truth. The user loses access only if they lose control of the wallet that registered the address. That’s the same failure mode as any other on-chain account, and your existing wallet-recovery UX covers it.There is no separate recovery phrase for viewing keys. Wallet ownership is the recovery mechanism.
Multiple wallets per user
If a user wants to treat two wallets as separate identities (say, one per workspace), each wallet registers independently and the relayer stores distinct key material for each. Switching is a session-level signing operation.What integrators do not manage
- Encryption of intent payloads (enclave handles it)
- Stealth address derivation (enclave handles it using the recipient’s enclave-held keys)
- Sweep transactions from the stealth address (gasless via
POST /recipient/relay-proxy)
Submit an intent
Build, sign, and submit your first intent.