- Create a self-custodial private wallet
- Receive private transfers with a Solana address
- Deposit tokens to a private balance
- Send privately to a Solana address
- Withdraw to any Solana address
- Decrypt private balances and transaction history locally
- Shielded Keypair – in your key management for encryption
- Privacy Interface and SDK – to build private transactions
- User Flows – to integrate into your wallet
Context for your AI
Add a Private Wallet to an existing Solana wallet
View prompt
View prompt
1
Integrate the Shielded Keypair
A private wallet integration adds a shielded keypair to your key management. A shielded keypair signs, encrypts and decrypts transactions.The shielded keypair is a bundle of the signing, nullifier, and viewing keys.- Signing key: The wallet’s Ed25519 Solana keypair to sign transactions.
- Viewing key: A P-256 keypair, used to encrypt and decrypt transactions.
- Nullifier key:
- For seed-based wallets choose Derive from seed phrase.
- For non-seed-based wallets choose Derive from EdDSA signature.
- Derive from seed phrase
- Derive from EdDSA signature
A seed-based wallet derives the shielded keypair from one BIP-39 mnemonic and an account index (
0, 1, …).Each account index maps one Solana keypair to one shielded keypair.
You can recover the shielded keypair the same way you recover the Solana keypair.For example:- Account 0: Solana keypair 0 and shielded keypair 0
- Account 1: Solana keypair 1 and shielded keypair 1
The shielded signing key is that account’s Solana Ed25519 key.
The nullifier and viewing keys are additional keys derived from the same seed.
Example Implementation: TypeScript example · Rust example
2
Integrate the Privacy Interface and SDK
The Privacy Interface enables your code to use the Privacy SDK to build private transactions without accessing the key material directly. Your key management implements the Privacy Interface in two parts.- Signing Interface for Transaction Building with the Privacy SDK. View Source: TypeScript/ Rust
- Encryption & Decryption Interface. View Source: TypeScript/ Rust
The Privacy Interface is stateless and therefore does not store balances or transaction history.
For performance, we recommend caching user balances and transaction history locally.
On Proof Generation
Zero-knowledge proof generation requires plaintext inputs of the complete user transaction data and nullifier keys.Currently, server proof generation is available through the standard Helius RPC URL.Local proof generation is coming soon. End-to-end encrypted server proof generation on AWS Nitro is planned before mainnet launch.3
Integrate User Flows
Create Private Wallet
A private wallet is created in two steps:- Derive the shielded keypair
- Register the Solana address in the on-chain registry.
Each registry record is a PDA owned by the , which anyone can look up to see whether a Solana address can receive private transfers.
Sync Private Balance & Transaction History
Balance sync fetches encrypted state from the RPC and decrypts it in the wallet.The RPC does not decrypt. Only the owner can decrypt a private balance with a viewing key.A wallet should decrypt and update balances before private transactions and wherever it runs backfills: on wallet unlock, private wallet open, app resume, network reconnect, stream gap, or wallet restore.
Read a Private Balance
Read Private Transaction History
Deposit to a Private Balance
Users can deposit to a private balance in two ways:- On-ramp from a fiat balance to a private crypto balance
- Deposit from a public SPL account to a private balance
On-/Off-Ramp
On-/Off-ramp fiat directly to and from a private balance.
Deposit
Deposit from a public crypto balance.
Private Transfers
Users can send private transfers to any Solana wallet address.For every private transfer, the Privacy SDK looks up the wallet address in the onchain registry to check if the recipient has a private wallet.The Privacy SDK can resolve a private transfer to a private-to-public withdrawal, when the recipient does not have a Private Wallet.We recommend labeling the transaction in the UI as a withdrawal to ensure the user does not withdraw to a public balance by accident.
Private Transfer
Transfer privately to a private balance.
Withdraw to a Public Balance
Withdrawals can be used in two ways:- As fallback for private transfers to recipients that don’t have a private wallet, or
- Direct withdrawal to a public SPL token account.
Withdraw
Withdraw to a public crypto balance.