Privy wallets
Mounting
@privy-io/react-auth crashes during server rendering. Load it with React.lazy(() => import("./privy-root")) inside <ClientOnly> + <Suspense>. Never import it at the top of a route file.
Read PRIVY_APP_ID with a server function in a route loader and pass it down. Lovable rejects VITE_* secret names.
EVM (Base, Ethereum, Tempo)
<PrivyProvider
appId={appId}
config={{
loginMethods: ["google", "email"],
embeddedWallets: { ethereum: { createOnLogin: "users-without-wallets" } },
defaultChain: chain,
supportedChains: [chain],
}}
>
Send with useSendTransaction():
await sendTransaction(
{ to: OUSD, data: encodeFunctionData({ abi: erc20Abi, functionName: "transfer", args: [to, amount] }), value: 0n, chainId },
{ address: wallet.address, sponsor: true },
);
Solana
embeddedWallets: { solana: { createOnLogin: "users-without-wallets" } }
Build the transfer transaction (see Chains) and send it with useSignAndSendTransaction from @privy-io/react-auth/solana. Check the Privy docs for your installed version — the Solana hooks moved between major releases.
Dashboard checklist
- Add the preview and published domains to Allowed origins.
- Enable the chain under Gas Sponsorship (Base, Ethereum, Tempo, Solana as needed).
- For Tempo, enable "Allow transactions from the client" — otherwise
sendTransactionhangs silently.