Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
f4b3685
Expose wallet docs in navigation
srinjoyc Jul 1, 2026
0f14e9b
Update wallet docs
srinjoyc Jul 1, 2026
6fddc46
Verify wallet docs snippets
srinjoyc Jul 2, 2026
6ff7420
docs(wallets): rewrite ZeroDev Wallet introduction
srinjoyc Jul 2, 2026
f44c193
docs(wallets): remove SDK Reference page and nav entry
srinjoyc Jul 2, 2026
ef5bb94
docs(wallets): revise Wallet UI Kit intro
srinjoyc Jul 2, 2026
902e04a
Refine wallet docs tone and examples
srinjoyc Jul 2, 2026
a4de559
Update wallet docs for AA host config
srinjoyc Jul 2, 2026
f5948fd
docs(wallets): replace aaUrl with aaHost (host-only, multichain-safe)
SahilVasava Jul 2, 2026
3da4ab0
Update wallet UI package name
srinjoyc Jul 2, 2026
1aec5e5
Merge branch 'pr-77' into srinjoy/update-wallet-docs
srinjoyc Jul 2, 2026
666c957
docs(wallets): drop removed OTP customization, fix deprecated useGetU…
SahilVasava Jul 2, 2026
4a7041b
docs(wallets): rename @zerodev/react-wallet-ui to @zerodev/wallet-rea…
SahilVasava Jul 2, 2026
2980320
Merge pull request #78 from zerodevapp/sahil/docs-wallet-fixes
SahilVasava Jul 2, 2026
e20b768
docs(wallets): add React Native focused documentation
andrascodes Jun 5, 2026
389d53f
docs(wallets): update web documentation
andrascodes Jun 9, 2026
c3cb3e1
docs(wallets): add guide for react-native-web
andrascodes Jun 9, 2026
6947100
docs(wallets): improve react-native-web page
andrascodes Jun 10, 2026
8b16a14
docs(wallets): add steps to make iOS work
andrascodes Jun 11, 2026
db434b1
Merge pull request #65 from zerodevapp/andras/docs-wallets-add-react-…
srinjoyc Jul 2, 2026
aa74745
Update wallet docs for latest SDK feedback
srinjoyc Jul 2, 2026
30f9d35
Merge latest wallet docs updates
srinjoyc Jul 2, 2026
70fd966
Clean up wallet sidebar references
srinjoyc Jul 2, 2026
46260b2
Consolidate wallet signing docs
srinjoyc Jul 2, 2026
106f4da
Restore wallet API reference links
srinjoyc Jul 2, 2026
c4dd520
Remove unsupported Solana export references
srinjoyc Jul 2, 2026
949f468
Audit wallet docs against latest SDK
srinjoyc Jul 2, 2026
bf6e15e
Clarify smart wallet intro
srinjoyc Jul 2, 2026
af746df
Address wallet docs review feedback
srinjoyc Jul 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 66 additions & 30 deletions docs/pages/wallets/auth/email-otp.mdx
Original file line number Diff line number Diff line change
@@ -1,38 +1,35 @@
# Email OTP Authentication [Authenticate with a one-time code sent by email]
# Email OTP [Authenticate with a one-time code]

:::danger[IMPORTANT]
**USE FOR INTERNAL TESTING PURPOSES ONLY.** You may use these features solely for internal evaluation purposes on supported testnets. DO NOT use for production use or share with your users. Wallets created during this preview ("Alpha Wallets") will be discontinued. Any tokens remaining within Alpha Wallets will be permanently lost upon discontinuance. Any mainnet tokens sent to an Alpha Wallet will not be deposited and will be permanently lost when discontinued. We are unable to help recover any lost funds from Alpha Wallets. We provide all previews on an "as is" basis without warranty of any kind, and we may terminate or suspend the availability of any preview at any time.
:::
Email OTP is a two-step login flow: send a code to the user's email address, then verify the code they enter. Use OTP when you want a familiar email-based flow without redirecting the user away from your app. After verification succeeds, the ZeroDev Wagmi connector is connected.

Email OTP is a two-step flow: send a verification code to the user's email, then verify the code they enter.
## Add OTP login

## Hooks

- [`useSendOTP`](/wallets/hooks/use-send-otp) — Send a one-time code to an email address
- [`useVerifyOTP`](/wallets/hooks/use-verify-otp) — Verify the code and authenticate

## Example
Use `useSendOTP` to send the code and `useVerifyOTP` to complete authentication.

```tsx
import { useSendOTP, useVerifyOTP } from '@zerodev/wallet-react'
import { useState } from 'react'
import { useAccount, useDisconnect } from 'wagmi'
import { useSendOTP, useVerifyOTP } from '@zerodev/wallet-react'

function EmailOTPAuth() {
export function EmailOTPLogin() {
const [email, setEmail] = useState('')
const [code, setCode] = useState('')
const [otpId, setOtpId] = useState<string | null>(null)
const [otpEncryptionTargetBundle, setOtpEncryptionTargetBundle] =
useState<string | null>(null)

const { address, isConnected } = useAccount()
const { disconnectAsync } = useDisconnect()
const { disconnect } = useDisconnect()
const sendOTP = useSendOTP()
const verifyOTP = useVerifyOTP()

if (isConnected) {
return (
<div>
<p>Connected: {address}</p>
<button onClick={() => disconnectAsync()}>Logout</button>
<button type="button" onClick={() => disconnect()}>
Disconnect
</button>
</div>
)
}
Expand All @@ -42,49 +39,88 @@ function EmailOTPAuth() {
<div>
<input
type="email"
placeholder="Enter your email"
autoComplete="email"
placeholder="you@example.com"
value={email}
onChange={(e) => setEmail(e.target.value)}
onChange={(event) => setEmail(event.target.value)}
/>

<button
type="button"
disabled={sendOTP.isPending || !email}
onClick={async () => {
const result = await sendOTP.mutateAsync({ email })
setOtpId(result.otpId)
setOtpEncryptionTargetBundle(result.otpEncryptionTargetBundle)
}}
disabled={sendOTP.isPending || !email}
>
{sendOTP.isPending ? 'Sending...' : 'Send Code'}
{sendOTP.isPending ? 'Sending code...' : 'Send code'}
</button>
{sendOTP.isError && <p>Error: {sendOTP.error.message}</p>}

{sendOTP.error ? <p>{sendOTP.error.message}</p> : null}
</div>
)
}

return (
<div>
<p>Code sent to {email}</p>

<input
type="text"
placeholder="Enter verification code"
inputMode="numeric"
autoComplete="one-time-code"
placeholder="Enter code"
value={code}
onChange={(e) => setCode(e.target.value)}
onChange={(event) => setCode(event.target.value)}
/>

<button
onClick={() => verifyOTP.mutateAsync({ code, otpId })}
disabled={verifyOTP.isPending || !code}
type="button"
disabled={verifyOTP.isPending || !code || !otpEncryptionTargetBundle}
onClick={() =>
otpEncryptionTargetBundle &&
verifyOTP.mutate({
otpId,
otpEncryptionTargetBundle,
code,
})
}
>
{verifyOTP.isPending ? 'Verifying...' : 'Verify Code'}
{verifyOTP.isPending ? 'Verifying...' : 'Verify code'}
</button>
{verifyOTP.isError && <p>Error: {verifyOTP.error.message}</p>}

<button
type="button"
onClick={() => {
setOtpId(null)
setOtpEncryptionTargetBundle(null)
}}
>
Use a different email
</button>

{verifyOTP.error ? <p>{verifyOTP.error.message}</p> : null}
</div>
)
}
```

## How it works

1. **Send code**: `useSendOTP` sends a one-time verification code to the provided email address. It returns an `otpId` that identifies this verification attempt.
1. `useSendOTP` sends a one-time code and returns an `otpId` plus an `otpEncryptionTargetBundle`.
2. Store both values while the user enters the code.
3. `useVerifyOTP` verifies the `otpId`, `otpEncryptionTargetBundle`, and `code`.
4. After verification succeeds, the SDK creates a session and connects the ZeroDev Wagmi connector.

## Notes

- Keep the `otpId` and `otpEncryptionTargetBundle` on the client until verification completes. For a single-page flow, component state is enough.
- The authenticated user's email is available in `emailContacts` from [`useAuthenticators`](/wallets/hooks/use-authenticators).
- If you need link-based email login instead of manual code entry, use [Magic Link](/wallets/auth/magic-link).
- For full hook options and return values, see [`useSendOTP`](/wallets/hooks/use-send-otp) and [`useVerifyOTP`](/wallets/hooks/use-verify-otp).

2. **Verify code**: `useVerifyOTP` takes the `otpId` and the code the user entered. If the code is valid, the SDK authenticates and creates a session.
## Next steps

After verification, the Wagmi connector is connected and the user's address is available via `useAccount`.
- [Send a transaction](/wallets/wallet-api/send-transaction)
- [Sign a message](/wallets/wallet-api/sign-message)
- Integrate other login methods: [Passkeys](/wallets/auth/passkeys), [Magic Link](/wallets/auth/magic-link), or [Google OAuth](/wallets/auth/google-oauth)
69 changes: 40 additions & 29 deletions docs/pages/wallets/auth/google-oauth.mdx
Original file line number Diff line number Diff line change
@@ -1,75 +1,86 @@
# Google OAuth [Authenticate with Google sign-in]
# Google OAuth [Authenticate with Google]

:::danger[IMPORTANT]
**USE FOR INTERNAL TESTING PURPOSES ONLY.** You may use these features solely for internal evaluation purposes on supported testnets. DO NOT use for production use or share with your users. Wallets created during this preview ("Alpha Wallets") will be discontinued. Any tokens remaining within Alpha Wallets will be permanently lost upon discontinuance. Any mainnet tokens sent to an Alpha Wallet will not be deposited and will be permanently lost when discontinued. We are unable to help recover any lost funds from Alpha Wallets. We provide all previews on an "as is" basis without warranty of any kind, and we may terminate or suspend the availability of any preview at any time.
:::
Google OAuth lets users sign in with their Google account through a popup. The SDK opens the popup, handles the OAuth redirect, creates the session, and connects the ZeroDev Wagmi connector.

Use Google OAuth when you want a familiar social login flow without building the OAuth exchange yourself.

Google OAuth lets users sign in with their Google account using a popup-based flow. The SDK handles the popup, redirect, and session creation automatically.
## Dashboard setup

By default, the Google OAuth flow uses a Zerodev-managed Google account for authentication. This allows you to get started quickly without any additional configuration. You can customize the OAuth flow by providing your own Google OAuth client ID and secret in the developer dashboard.
The default Google OAuth configuration works out of the box for getting started. Add your app origin to the project's ACL allowlist before testing the popup flow.

> **Important:** Using custom credentials requires creating a new project with no wallets already created. You cannot switch an existing project from the default Zerodev-managed OAuth setup to a custom client configuration.
If you want to use your own Google OAuth client, configure the client ID and secret in the ZeroDev dashboard.

## Hook
:::warning[Custom OAuth credentials]
Custom Google OAuth credentials must be configured before wallets are created in the project. Create a new project if you need to switch from the default ZeroDev-managed OAuth configuration to your own credentials.
:::

- [`useAuthenticateOAuth`](/wallets/hooks/use-authenticate-oauth) — Trigger the OAuth flow
## Add Google login

## Example
Use `useAuthenticateOAuth` with `OAUTH_PROVIDERS.GOOGLE`.

```tsx
import { useAccount, useDisconnect } from 'wagmi'
import {
useAuthenticateOAuth,
OAUTH_PROVIDERS,
useAuthenticateOAuth,
} from '@zerodev/wallet-react'
import { useAccount, useDisconnect } from 'wagmi'

function GoogleAuth() {
export function GoogleLogin() {
const { address, isConnected } = useAccount()
const { disconnectAsync } = useDisconnect()
const { disconnect } = useDisconnect()
const authenticateOAuth = useAuthenticateOAuth()

if (isConnected) {
return (
<div>
<p>Connected: {address}</p>
<button onClick={() => disconnectAsync()}>Logout</button>
<button type="button" onClick={() => disconnect()}>
Disconnect
</button>
</div>
)
}

return (
<div>
<button
type="button"
disabled={authenticateOAuth.isPending}
onClick={() =>
authenticateOAuth.mutateAsync({
authenticateOAuth.mutate({
provider: OAUTH_PROVIDERS.GOOGLE,
})
}
disabled={authenticateOAuth.isPending}
>
{authenticateOAuth.isPending
? 'Signing in...'
: 'Sign in with Google'}
{authenticateOAuth.isPending ? 'Signing in...' : 'Continue with Google'}
</button>

{authenticateOAuth.isError && (
<p>Error: {authenticateOAuth.error.message}</p>
)}
{authenticateOAuth.error ? (
<p>{authenticateOAuth.error.message}</p>
) : null}
</div>
)
}
```

## How it works

1. **Open popup**: `useAuthenticateOAuth` opens a popup window to the KMS backend's OAuth endpoint.
1. `useAuthenticateOAuth` opens the OAuth popup.
2. The user signs in with Google.
3. The SDK completes the OAuth callback and creates a ZeroDev session.
4. The popup closes and the main window connects the ZeroDev Wagmi connector.

2. **Google sign-in**: The backend initiates the Google OAuth flow with PKCE. The user signs in with their Google account.
After the flow completes, use `useAccount`, `useSignMessage`, and `useSendTransaction` like any other Wagmi app.

3. **Backend callback**: Google redirects back to the backend, which exchanges the auth code for tokens and sets a session cookie.
## Notes

4. **Popup redirect**: The backend redirects the popup to your app with `?oauth_success=true`.
- Popup blockers can block OAuth if the mutation is not triggered directly from a user action.
- The dashboard ACL allowlist must include the exact origin that opens the popup.
- The authenticated user's email is available in `emailContacts` from [`useAuthenticators`](/wallets/hooks/use-authenticators).
- For full hook options and return values, see [`useAuthenticateOAuth`](/wallets/hooks/use-authenticate-oauth).

5. **Auto-detect**: The SDK detects the success parameter. If running in a popup, it sends a `postMessage` to the opener window and closes. The main window then calls the backend's auth endpoint (reading the session cookie) to get a session.
## Next steps

After the flow completes, the Wagmi connector is connected and the user's address is available via `useAccount`.
- [Send a transaction](/wallets/wallet-api/send-transaction)
- [Sign a message](/wallets/wallet-api/sign-message)
- Integrate other login methods: [Passkeys](/wallets/auth/passkeys), [Email OTP](/wallets/auth/email-otp), or [Magic Link](/wallets/auth/magic-link)
Loading