TL;DR: Web3 wallet onboarding in 2025 = embedded wallets + social/passkey login + gas sponsorship + multi-chain from day one. This post compares Dynamic, Web3Auth, Privy —then shows a copy-paste React & React Native quickstart that uses Openfort for in-app, non-custodial wallets, address fetching, chain switching, and sponsored transactions. Links and snippets are real and current.
Why another onboarding guide?
- “SDK wallet” posts are steady, but most skip multi-chain + RN.
- “Web3 wallet” is noisy (4–5 posts/day); let’s keep this dev-practical.
- The 2023 comparisons are dated—SDKs shipped major upgrades in 2024–2025.
| Capability | Dynamic | Web3Auth | Privy | Openfort |
|---|---|---|---|---|
| Social / passkey login | ✅ | ✅ | ✅ | ✅ (email/social/passkey) |
| Embedded non-custodial | ✅ | ✅ | ✅ | ✅ |
| Multi-chain (EVM + SVM) | ✅ | ✅ | ✅ | ✅ (EIP-1193 + Wagmi/Viem) |
| Mobile Focus | React Native | React Native | React Native | React Native + Swift |
| Gas sponsorship | Third Party | Third Party | Built-in | Built-in + Dashboard policies |
| Dev UX (hooks/components) | UI | UI | UI | headless or UI |
Sources & release notes: Dynamic SDK v4; Web3Auth product docs; Privy onboarding/wallets; Openfort docs (quickstart, wallet actions).
My take: if you need React + React Native parity, gasless by config, and standard EIP-1193 so you can use Wagmi/Viem without weird adapters, Openfort is the most “just-ship-it” today. If your org prefers MPC-first UX libraries, Web3Auth/Privy remain solid picks. Dynamic shines on polish and enterprise workflows.
Quick Start (React)
1. Install
npm install @openfort/react wagmi viem@^2.22.0 @tanstack/react-query 2. Providers: Openfort + Wagmi + Query
import React from "react"; import { AuthProvider, OpenfortProvider, getDefaultConfig, } from "@openfort/react"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { WagmiProvider, createConfig } from "wagmi"; import { polygonAmoy } from "viem/chains"; const config = createConfig( getDefaultConfig({ appName: "My Onboarding Demo", chains: [polygonAmoy], ssr: true, }) ); const queryClient = new QueryClient(); export function Providers({ children }: { children: React.ReactNode }) { return ( <WagmiProvider config={config}> <QueryClientProvider client={queryClient}> <OpenfortProvider publishableKey={import.meta.env.VITE_OPENFORT_PUB_KEY!} walletConfig={{ shieldPublishableKey: import.meta.env.VITE_OPENFORT_SHIELD_PUB_KEY!, // Optional: automatic recovery via your backend endpoint createEncryptedSessionEndpoint: "/api/shield-session", }} > <AuthProvider>{children}</AuthProvider> </OpenfortProvider> </QueryClientProvider> </WagmiProvider> ); } 3. Login + embedded wallet button:
import React from "react"; import { Providers } from "./Providers"; import { OpenfortButton } from "@openfort/react"; export default function App() { return ( <Providers> <h1>Onboard users in one click</h1> <OpenfortButton /> </Providers> ); } 4. Backend recovery endpoint (optional)
Use the one-click deploy or add a tiny /api/shield-session that returns a session—copied from the docs.
Get the wallet address (multi chain)
Under the hood, Openfort can expose an EIP-1193 provider, so you can use Wagmi/Viem normally.
import openfort from "./openfortConfig"; // see docs for setup const provider = await openfort.embeddedWallet.getEthereumProvider(); const [address] = await provider.request({ method: "eth_accounts", params: [] }); console.log("Active address:", address); Switch chains and re-use the same interface:
await provider.request({ method: "wallet_switchEthereumChain", params: [{ chainId: "0x5" }], // Goerli example }); Docs: EIP-1193 provider & network switching.
Tip: if you’re already on Wagmi, useAccount() gives you the active address; use switchChain (Viem/Wagmi) or the raw wallet_switchEthereumChain request
5. Sponsor gas in one line
Create a sponsor policy in the dashboard → paste the pol_... into your provider config:
<OpenfortProvider publishableKey={import.meta.env.VITE_OPENFORT_PUB_KEY!} walletConfig={{ shieldPublishableKey: import.meta.env.VITE_OPENFORT_SHIELD_PUB_KEY!, ethereumProviderPolicyId: { 80002: "pol_..." }, // polygonAmoy.id }} > {children} </OpenfortProvider> Then send transactions with Wagmi:
import { useCallback } from "react"; import { parseUnits } from "viem"; import { useAccount, useWriteContract } from "wagmi"; const usdc = "0xA0b8...eB48"; // replace const abi = [{ name: "transfer", type: "function", inputs: [{name:"to",type:"address"},{name:"amount",type:"uint256"}], outputs:[{name:"success",type:"bool"}]}] as const; export function useSendUsdc() { const { address } = useAccount(); const { writeContract } = useWriteContract(); return useCallback( async (to: `0x${string}`, amount: string) => { if (!address) throw new Error("Wallet not connected"); writeContract({ address: usdc, abi, functionName: "transfer", args: [to, parseUnits(amount, 6)] }); }, [address, writeContract] ); } How sponsorship is configured and applied → docs.
React Native notes (2025)
- RN SDK is live—use the same mental model (Auth → Embedded wallet → EIP-1193 provider bridge). Feature announcement here; follow the product docs for setup.
- Set up your RN env with Expo/CLI as usual. Then drop in Openfort’s RN package & providers, mirroring the React setup.
When to pick what (quick decision chart)
- I want MPC, social login, and a long vendor list → Start with Web3Auth or Privy, then layer gas/onramps.
- I want clean UI and enterprise onboarding polish → Dynamic (v4) is strong.
- I want React + RN parity, standard EIP-1193, gasless via config → Openfort. Docs are concise, and the provider is drop-in with Wagmi/Viem.
Links you’ll like:
- Openfort overview & React quickstart → docs & sample code.
- Wallet actions (send ERC-20) + gas sponsor policies.
Open question for you
Do you prefer “black-box” onboarding (fewer knobs, faster ship) or “lego-kit” onboarding (standard EIP-1193 + your hooks)? What did I miss for RN? Drop your stack & pain points—I’ll add a RN-only follow-up with code if there’s interest.
Top comments (0)