React hooks and Wagmi connector for ZeroDev Wallet SDK with EIP-7702 gasless transactions.
- Wagmi Integration - Works seamlessly with the Wagmi ecosystem
- Multiple Auth Methods - Passkey (WebAuthn), Email OTP, OAuth (Google)
- Gasless Transactions - All transactions are gasless via EIP-7702
- Session Management - Auto-refresh with configurable thresholds
- Multi-Chain - Lazy kernel account creation per chain
- TypeScript - Full type safety with proper generics
- React Query - Built on TanStack Query for optimal UX
npm install @zerodev/wallet-react @zerodev/wallet-core wagmi viem
# or
yarn add @zerodev/wallet-react @zerodev/wallet-core wagmi viem
# or
pnpm add @zerodev/wallet-react @zerodev/wallet-core wagmi viemimport { createConfig, http } from 'wagmi'
import { sepolia } from 'wagmi/chains'
import { zeroDevWallet } from '@zerodev/wallet-react'
const config = createConfig({
chains: [sepolia],
connectors: [
zeroDevWallet({
projectId: 'YOUR_PROJECT_ID',
chains: [sepolia],
})
],
transports: {
[sepolia.id]: http('YOUR_RPC_URL'),
},
})import { WagmiProvider } from 'wagmi'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
const queryClient = new QueryClient()
function App() {
return (
<WagmiProvider config={config}>
<QueryClientProvider client={queryClient}>
<YourApp />
</QueryClientProvider>
</WagmiProvider>
)
}import { useRegisterPasskey, useAuthenticateOAuth, OAUTH_PROVIDERS } from '@zerodev/wallet-react'
function LoginPage() {
const registerPasskey = useRegisterPasskey()
const authenticateOAuth = useAuthenticateOAuth()
return (
<>
<button
onClick={() => registerPasskey.mutate()}
disabled={registerPasskey.isPending}
>
{registerPasskey.isPending ? 'Registering...' : 'Register with Passkey'}
</button>
<button
onClick={() => authenticateOAuth.mutate({ provider: OAUTH_PROVIDERS.GOOGLE })}
disabled={authenticateOAuth.isPending}
>
{authenticateOAuth.isPending ? 'Authenticating...' : 'Login with Google'}
</button>
</>
)
}import { useConnection, useSendTransaction, useDisconnect } from 'wagmi'
import { parseEther } from 'viem'
function Dashboard() {
const { address } = useConnection()
const { sendTransaction } = useSendTransaction()
const { disconnect } = useDisconnect()
return (
<>
<p>Address: {address}</p>
<button onClick={() =>
sendTransaction({
to: '0x...',
value: parseEther('0.01')
})
}>
Send Gasless Transaction
</button>
<button onClick={() => disconnect()}>
Logout
</button>
</>
)
}const registerPasskey = useRegisterPasskey()
const loginPasskey = useLoginPasskey()
// Register new passkey
await registerPasskey.mutateAsync()
// Login with existing passkey
await loginPasskey.mutateAsync()const authenticateOAuth = useAuthenticateOAuth()
// Opens popup, backend handles PKCE and token exchange
// No callback page or OAuth library needed - SDK handles everything
await authenticateOAuth.mutateAsync({
provider: OAUTH_PROVIDERS.GOOGLE
})const sendMagicLink = useSendMagicLink()
const verifyMagicLink = useVerifyMagicLink()
// Send magic link
const { otpId } = await sendMagicLink.mutateAsync({
email: 'user@example.com',
redirectURL: 'https://yourapp.com/verify',
})
// With custom OTP code settings
const { otpId } = await sendMagicLink.mutateAsync({
email: 'user@example.com',
redirectURL: 'https://yourapp.com/verify',
otpCodeCustomization: { length: 8, alphanumeric: false },
})
// Verify (on /verify page, extract code from URL)
const code = new URLSearchParams(window.location.search).get('code')
await verifyMagicLink.mutateAsync({ otpId, code })const sendOTP = useSendOTP()
const verifyOTP = useVerifyOTP()
// Send OTP code
const { otpId } = await sendOTP.mutateAsync({
email: 'user@example.com'
})
// With custom OTP code settings
const { otpId } = await sendOTP.mutateAsync({
email: 'user@example.com',
otpCodeCustomization: { length: 8, alphanumeric: false },
})
// Verify OTP code
await verifyOTP.mutateAsync({
code: '12345678',
otpId,
})Both useSendOTP and useSendMagicLink accept an optional otpCodeCustomization parameter:
| Field | Type | Description |
|---|---|---|
length |
6 | 7 | 8 | 9 |
Code length (default: 6) |
alphanumeric |
boolean |
Use alphanumeric characters instead of digits only (default: false) |
type ZeroDevWalletConnectorParams = {
projectId: string // Required: Your ZeroDev project ID
organizationId?: string // Optional: Turnkey organization ID
proxyBaseUrl?: string // Optional: KMS proxy URL
chains: readonly Chain[] // Required: Supported chains
rpId?: string // Optional: WebAuthn RP ID
sessionStorage?: StorageAdapter // Optional: Custom session storage
autoRefreshSession?: boolean // Optional: Auto-refresh (default: true)
sessionWarningThreshold?: number // Optional: Refresh threshold in ms (default: 60000)
}const registerPasskey = useRegisterPasskey({
mutation: {
onSuccess: () => {
console.log('Registration successful!')
router.push('/dashboard')
},
onError: (error) => {
console.error('Registration failed:', error)
analytics.track('auth_failed', { method: 'passkey' })
}
}
})const refreshSession = useRefreshSession()
await refreshSession.mutateAsync({})const exportWallet = useExportWallet()
// Container element must exist: <div id="export-container" />
await exportWallet.mutateAsync({
iframeContainerId: 'export-container'
})const exportPrivateKey = useExportPrivateKey()
// Container element must exist: <div id="export-container" />
await exportPrivateKey.mutateAsync({
iframeContainerId: 'export-container'
})const { data: authenticators, isLoading } = useAuthenticators()
// `authenticators` contains all authenticators linked to the current user:
// { oauths, passkeys, emailContacts, apiKeys }
console.log(authenticators?.oauths)
console.log(authenticators?.passkeys)
console.log(authenticators?.emailContacts)
console.log(authenticators?.apiKeys)All hooks follow the TanStack Query mutation pattern:
useRegisterPasskey()- Register with passkeyuseLoginPasskey()- Login with passkeyuseAuthenticateOAuth()- OAuth (Google popup)useSendMagicLink()- Send magic link via emailuseVerifyMagicLink()- Verify magic link codeuseSendOTP()- Send OTP via emailuseVerifyOTP()- Verify OTP codeuseRefreshSession()- Manually refresh sessionuseExportWallet()- Export wallet seed phraseuseExportPrivateKey()- Export wallet private keyuseAuthenticators()- Fetch all authenticators (oauths, passkeys, emailContacts, apiKeys) for the user
zeroDevWallet(params)- Wagmi connector factory
OAUTH_PROVIDERS.GOOGLE- Google OAuth provider constant
OAuthProvider- OAuth provider typeZeroDevWalletConnectorParams- Connector parametersZeroDevWalletState- Store state typeZeroDevProvider- EIP-1193 provider type
MIT