Privy: white-label wallet infrastructure, the technical view logoPrivy: white-label wallet infrastructure, the technical view
Privy's TEE-and-sharding key model, the User / Treasury / Agent wallet products, the React provider pattern, server-side wallet operations, and how recovery actually works.
devrels.xyz/a/73Privy is the embedded-wallet infrastructure most consumer Solana apps reach for first. 120M+ accounts across 2,000+ teams, three distinct wallet products on one shared key-management foundation. This article is the technical view — the keys, the accounts, the SDKs, the recovery model.
The key model
Privy uses Trusted Execution Environments (TEEs) + Shamir Secret Sharing to hold user keys. No single party — including Privy itself — can derive a user's private key from the data they hold.
User's private key → split into N shares via SSS (typically 3-of-5)
Share A → sealed inside a TEE on Privy's infra
Share B → sealed inside a different TEE (different cloud region)
Share C → derived from the user's password (PBKDF2'd)
Share D → stored on Privy's backend, accessible only on auth
Share E → recovery share (email-able, MPC-recoverable)
To sign:
3-of-5 shares are reconstructed inside a TEE
Signature is produced
Reconstructed key is discarded; never leaves the enclaveThe user's password is one of the shares — without it, no coalition of Privy operators can sign. Combined with TEE isolation, this gives the property: even with full server compromise, Privy can't spend user funds.
Three wallet products
Same underlying key model, three different surface APIs for different use cases:
- User wallets — embedded in consumer apps. The user is the owner; they sign via the React SDK (auth + confirm). The signing UI is whatever your app renders.
- Treasury wallets — owned by the dev team, not the user. For protocol-side operations (paying gas, holding treasuries, automated jobs). Accessed via the server SDK with API key auth.
- Agent wallets — for AI agents. Same as treasury wallets but with policy controls (spending limits, program allow-lists, time-of-day windows) that gate every signature attempt.
Client-side integration (React)
import { PrivyProvider, usePrivy, useSolanaWallets } from "@privy-io/react-auth"
import { Connection, SystemProgram, PublicKey, Transaction } from "@solana/web3.js"
// 1. Wrap your app
export function App({ children }: { children: React.ReactNode }) {
return (
<PrivyProvider
appId={process.env.NEXT_PUBLIC_PRIVY_APP_ID!}
config={{
embeddedWallets: { createOnLogin: "all-users" },
loginMethods: ["email", "google", "wallet"],
defaultChain: { name: "solana" },
}}
>
{children}
</PrivyProvider>
)
}
// 2. Use the embedded wallet
function SendSol() {
const { authenticated } = usePrivy()
const { wallets } = useSolanaWallets()
const wallet = wallets[0]
async function send() {
const conn = new Connection("https://api.mainnet-beta.solana.com")
const tx = new Transaction().add(
SystemProgram.transfer({
fromPubkey: new PublicKey(wallet.address),
toPubkey: new PublicKey("..."),
lamports: 10_000_000,
})
)
const sig = await wallet.sendTransaction(tx, conn)
console.log("https://solscan.io/tx/" + sig)
}
return <button onClick={send} disabled={!authenticated}>Send</button>
}Server-side wallet operations
For treasury and agent flows, use the server SDK with your app's secret API key:
import { PrivyClient } from "@privy-io/server-auth"
const privy = new PrivyClient(process.env.PRIVY_APP_ID!, process.env.PRIVY_APP_SECRET!)
// Create a treasury wallet
const wallet = await privy.walletApi.create({
chainType: "solana",
policyIds: [policyId], // optional policy enforcement
})
// Sign a transaction server-side (no user interaction)
const result = await privy.walletApi.solana.signTransaction({
walletId: wallet.id,
transaction: tx, // base64-encoded
})
// Or send-and-sign in one call
const result2 = await privy.walletApi.solana.signAndSendTransaction({
walletId: wallet.id,
transaction: tx,
caip2: "solana:mainnet",
})Policy-gated signing for agents
Agent wallets attach to a policy evaluated server-side before every signature:
const policy = await privy.policyApi.create({
name: "Trading bot",
chainType: "solana",
rules: [
{
// Allow up to 5 SOL/day to Jupiter program
method: "signTransaction",
action: "ALLOW",
conditions: [
{ field: "program_id", operator: "EQUALS", value: JUPITER_PROGRAM_ID },
{ field: "lamports", operator: "LESS_THAN", value: 5_000_000_000 },
{ field: "lamports_per_day", operator: "LESS_THAN", value: 5_000_000_000 },
],
},
{ method: "signTransaction", action: "DENY", conditions: [] }, // default deny
],
})
await privy.walletApi.update({ id: wallet.id, policyIds: [policy.id] })Recovery
Two recovery paths, both designed so neither Privy nor a single user mistake can destroy access:
- Password recovery. If the user forgets their password, the system uses other shares + email verification to allow a password reset.
- Self-custody export. Users can export their private key at any time — useful for migrating to an external wallet or holding the key directly. Recovery becomes the user's problem after export.
When to reach for Privy
Privy fits when you want consumer-app embedded wallets at scale — millions of users, social login, zero seed-phrase UX, and a path forward for treasury ops and agent automation under the same vendor relationship.
Compared against alternatives in the embedded wallet showdown: Privy wins on raw deployed scale, Dynamic wins on connect- plus-embedded hybrids, Magic wins on enterprise sharding flexibility, Crossmint wins on stablecoin orchestration, Lazorkit wins on Solana-only passkey UX.
References
Privy is the boring infrastructure layer most Solana consumer apps standardise on. The TEE + SSS key model is the part to understand if you're evaluating whether it meets your security bar.
Keep reading
Email/social/passkey login → portable MPC wallets; sign via SDK or REST without exposing full keys.
Twelve words are not “half as safe” in the way people mean. Here is the entropy math, the checksum, and the practical tradeoffs.
Most wallets optimize for onboarding; Unruggable optimizes for not getting drained. The project spans a pure-bash ATM-style CLI wallet, a Rust/Dioxus app for all five platforms with MPC instead of seed phrases, and an open-firmware ESP32 signer that only signs when you physically press the button. The first hardware run already sold out.
Get new articles in your inbox
Technical deep-dives on Solana tooling, infrastructure, and ecosystem. No noise.
