From f4b3685bb7f2aedf3c3882b07b12178b7865050f Mon Sep 17 00:00:00 2001 From: srinjoyc Date: Wed, 1 Jul 2026 13:48:19 -0700 Subject: [PATCH 01/25] Expose wallet docs in navigation --- docs/pages/wallets/auth/email-otp.mdx | 4 ---- docs/pages/wallets/auth/google-oauth.mdx | 4 ---- docs/pages/wallets/auth/magic-link.mdx | 4 ---- docs/pages/wallets/auth/passkeys.mdx | 4 ---- docs/pages/wallets/export.mdx | 4 ---- docs/pages/wallets/hooks/use-authenticate-oauth.mdx | 4 ---- docs/pages/wallets/hooks/use-export-private-key.mdx | 4 ---- docs/pages/wallets/hooks/use-export-wallet.mdx | 4 ---- docs/pages/wallets/hooks/use-get-user-email.mdx | 4 ---- docs/pages/wallets/hooks/use-login-passkey.mdx | 4 ---- docs/pages/wallets/hooks/use-refresh-session.mdx | 4 ---- docs/pages/wallets/hooks/use-register-passkey.mdx | 4 ---- docs/pages/wallets/hooks/use-send-magic-link.mdx | 4 ---- docs/pages/wallets/hooks/use-send-otp.mdx | 4 ---- docs/pages/wallets/hooks/use-verify-magic-link.mdx | 4 ---- docs/pages/wallets/hooks/use-verify-otp.mdx | 4 ---- docs/pages/wallets/index.mdx | 4 ---- docs/pages/wallets/quickstart.mdx | 4 ---- docs/pages/wallets/session-management.mdx | 4 ---- docs/pages/wallets/wallet-api/send-transaction.mdx | 4 ---- docs/pages/wallets/wallet-api/sign-message.mdx | 4 ---- docs/pages/wallets/wallet-api/sign-typed-message.mdx | 4 ---- vocs.config.tsx | 4 ++-- 23 files changed, 2 insertions(+), 90 deletions(-) diff --git a/docs/pages/wallets/auth/email-otp.mdx b/docs/pages/wallets/auth/email-otp.mdx index c7aaf379..cd767ced 100644 --- a/docs/pages/wallets/auth/email-otp.mdx +++ b/docs/pages/wallets/auth/email-otp.mdx @@ -1,9 +1,5 @@ # Email OTP Authentication [Authenticate with a one-time code sent by email] -:::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 flow: send a verification code to the user's email, then verify the code they enter. ## Hooks diff --git a/docs/pages/wallets/auth/google-oauth.mdx b/docs/pages/wallets/auth/google-oauth.mdx index 03be8e3a..3b7a6670 100644 --- a/docs/pages/wallets/auth/google-oauth.mdx +++ b/docs/pages/wallets/auth/google-oauth.mdx @@ -1,9 +1,5 @@ # Google OAuth [Authenticate with Google sign-in] -:::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 using a popup-based flow. The SDK handles the popup, redirect, and session creation automatically. 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. diff --git a/docs/pages/wallets/auth/magic-link.mdx b/docs/pages/wallets/auth/magic-link.mdx index 8bd808cc..18bd23b0 100644 --- a/docs/pages/wallets/auth/magic-link.mdx +++ b/docs/pages/wallets/auth/magic-link.mdx @@ -1,9 +1,5 @@ # Magic Link Authentication [Authenticate with a link sent by email] -:::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. -::: - Magic links let users authenticate by clicking a link in their email. The link redirects to your app where the SDK completes the verification. ## Hooks diff --git a/docs/pages/wallets/auth/passkeys.mdx b/docs/pages/wallets/auth/passkeys.mdx index 2e9c5255..efe9a9e7 100644 --- a/docs/pages/wallets/auth/passkeys.mdx +++ b/docs/pages/wallets/auth/passkeys.mdx @@ -1,9 +1,5 @@ # Passkey Authentication [Register and login with WebAuthn passkeys] -:::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. -::: - Passkeys use the [WebAuthn](https://webauthn.guide/) standard for passwordless authentication. Users authenticate with biometrics (Face ID, Touch ID, fingerprint) or a hardware security key. ## Configure RP ID (optional) diff --git a/docs/pages/wallets/export.mdx b/docs/pages/wallets/export.mdx index 256f62f4..0bef671e 100644 --- a/docs/pages/wallets/export.mdx +++ b/docs/pages/wallets/export.mdx @@ -1,9 +1,5 @@ # Export Wallet [Let users export their seed phrase or private key] -:::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. -::: - The SDK supports exporting the user's wallet as a seed phrase or private key. The key material is displayed inside a secure iframe and never touches your application code. ## Hooks diff --git a/docs/pages/wallets/hooks/use-authenticate-oauth.mdx b/docs/pages/wallets/hooks/use-authenticate-oauth.mdx index a09ccc61..3ae8dd32 100644 --- a/docs/pages/wallets/hooks/use-authenticate-oauth.mdx +++ b/docs/pages/wallets/hooks/use-authenticate-oauth.mdx @@ -2,10 +2,6 @@ import MutationResult from '../shared/mutation-result.mdx' # useAuthenticateOAuth [Hook for authenticating with an OAuth provider] -:::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. -::: - ## Import ```tsx diff --git a/docs/pages/wallets/hooks/use-export-private-key.mdx b/docs/pages/wallets/hooks/use-export-private-key.mdx index d1f1d159..02fb6898 100644 --- a/docs/pages/wallets/hooks/use-export-private-key.mdx +++ b/docs/pages/wallets/hooks/use-export-private-key.mdx @@ -2,10 +2,6 @@ import MutationResult from '../shared/mutation-result.mdx' # useExportPrivateKey [Hook for exporting a private key] -:::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. -::: - ## Import ```tsx diff --git a/docs/pages/wallets/hooks/use-export-wallet.mdx b/docs/pages/wallets/hooks/use-export-wallet.mdx index 60438e3b..2c59fb8b 100644 --- a/docs/pages/wallets/hooks/use-export-wallet.mdx +++ b/docs/pages/wallets/hooks/use-export-wallet.mdx @@ -2,10 +2,6 @@ import MutationResult from '../shared/mutation-result.mdx' # useExportWallet [Hook for exporting the wallet seed phrase] -:::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. -::: - ## Import ```tsx diff --git a/docs/pages/wallets/hooks/use-get-user-email.mdx b/docs/pages/wallets/hooks/use-get-user-email.mdx index 6e92cc71..4a444520 100644 --- a/docs/pages/wallets/hooks/use-get-user-email.mdx +++ b/docs/pages/wallets/hooks/use-get-user-email.mdx @@ -2,10 +2,6 @@ import QueryResult from '../shared/query-result.mdx' # useGetUserEmail [Hook for getting the authenticated user's email] -:::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. -::: - ## Import ```tsx diff --git a/docs/pages/wallets/hooks/use-login-passkey.mdx b/docs/pages/wallets/hooks/use-login-passkey.mdx index dfa734b8..77ad68e9 100644 --- a/docs/pages/wallets/hooks/use-login-passkey.mdx +++ b/docs/pages/wallets/hooks/use-login-passkey.mdx @@ -2,10 +2,6 @@ import MutationResult from '../shared/mutation-result.mdx' # useLoginPasskey [Hook for logging in with an existing passkey] -:::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. -::: - ## Import ```tsx diff --git a/docs/pages/wallets/hooks/use-refresh-session.mdx b/docs/pages/wallets/hooks/use-refresh-session.mdx index 4262ea21..d49dc903 100644 --- a/docs/pages/wallets/hooks/use-refresh-session.mdx +++ b/docs/pages/wallets/hooks/use-refresh-session.mdx @@ -2,10 +2,6 @@ import MutationResult from '../shared/mutation-result.mdx' # useRefreshSession [Hook for manually refreshing the current session] -:::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. -::: - ## Import ```tsx diff --git a/docs/pages/wallets/hooks/use-register-passkey.mdx b/docs/pages/wallets/hooks/use-register-passkey.mdx index 54144213..cce8e49c 100644 --- a/docs/pages/wallets/hooks/use-register-passkey.mdx +++ b/docs/pages/wallets/hooks/use-register-passkey.mdx @@ -2,10 +2,6 @@ import MutationResult from '../shared/mutation-result.mdx' # useRegisterPasskey [Hook for registering a new passkey wallet] -:::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. -::: - ## Import ```tsx diff --git a/docs/pages/wallets/hooks/use-send-magic-link.mdx b/docs/pages/wallets/hooks/use-send-magic-link.mdx index 1d2690b5..73014bbe 100644 --- a/docs/pages/wallets/hooks/use-send-magic-link.mdx +++ b/docs/pages/wallets/hooks/use-send-magic-link.mdx @@ -2,10 +2,6 @@ import MutationResult from '../shared/mutation-result.mdx' # useSendMagicLink [Hook for sending a magic link email] -:::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. -::: - ## Import ```tsx diff --git a/docs/pages/wallets/hooks/use-send-otp.mdx b/docs/pages/wallets/hooks/use-send-otp.mdx index ffb2fb12..9c11647b 100644 --- a/docs/pages/wallets/hooks/use-send-otp.mdx +++ b/docs/pages/wallets/hooks/use-send-otp.mdx @@ -2,10 +2,6 @@ import MutationResult from '../shared/mutation-result.mdx' # useSendOTP [Hook for sending a one-time verification 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. -::: - ## Import ```tsx diff --git a/docs/pages/wallets/hooks/use-verify-magic-link.mdx b/docs/pages/wallets/hooks/use-verify-magic-link.mdx index 5810d1b8..cbc42e09 100644 --- a/docs/pages/wallets/hooks/use-verify-magic-link.mdx +++ b/docs/pages/wallets/hooks/use-verify-magic-link.mdx @@ -2,10 +2,6 @@ import MutationResult from '../shared/mutation-result.mdx' # useVerifyMagicLink [Hook for verifying a magic link and authenticating] -:::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. -::: - ## Import ```tsx diff --git a/docs/pages/wallets/hooks/use-verify-otp.mdx b/docs/pages/wallets/hooks/use-verify-otp.mdx index 4ee8832b..3f3af4ec 100644 --- a/docs/pages/wallets/hooks/use-verify-otp.mdx +++ b/docs/pages/wallets/hooks/use-verify-otp.mdx @@ -2,10 +2,6 @@ import MutationResult from '../shared/mutation-result.mdx' # useVerifyOTP [Hook for verifying a one-time code and authenticating] -:::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. -::: - ## Import ```tsx diff --git a/docs/pages/wallets/index.mdx b/docs/pages/wallets/index.mdx index 10fde545..2b7f8bb6 100644 --- a/docs/pages/wallets/index.mdx +++ b/docs/pages/wallets/index.mdx @@ -1,9 +1,5 @@ # ZeroDev Wallet [Smart embedded wallet for your app] -:::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. -::: - ZeroDev Wallet is the first **smart embedded wallet** -- an embedded wallet optimized for smart accounts. ## Demo diff --git a/docs/pages/wallets/quickstart.mdx b/docs/pages/wallets/quickstart.mdx index b1c1f17b..f976e343 100644 --- a/docs/pages/wallets/quickstart.mdx +++ b/docs/pages/wallets/quickstart.mdx @@ -1,9 +1,5 @@ # Quickstart [Get up and running in 5 minutes] -:::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. -::: - ## Installation :::code-group diff --git a/docs/pages/wallets/session-management.mdx b/docs/pages/wallets/session-management.mdx index 34c02ffa..0787da8e 100644 --- a/docs/pages/wallets/session-management.mdx +++ b/docs/pages/wallets/session-management.mdx @@ -1,9 +1,5 @@ # Session Management [Understand and control the session lifecycle] -:::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. -::: - The ZeroDev Wallet SDK manages sessions automatically. Sessions are created during authentication and persist across page reloads. ## Session lifecycle diff --git a/docs/pages/wallets/wallet-api/send-transaction.mdx b/docs/pages/wallets/wallet-api/send-transaction.mdx index e77368a5..c7647854 100644 --- a/docs/pages/wallets/wallet-api/send-transaction.mdx +++ b/docs/pages/wallets/wallet-api/send-transaction.mdx @@ -1,9 +1,5 @@ # Send a Transaction [Gasless transactions with Wagmi hooks] -:::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. -::: - Use standard Wagmi hooks to send transactions. The ZeroDev connector turns transactions into user operations (AA transactions) behind the scenes, achieving gas abstraction automatically so long as you have enabled it on the ZeroDev dashboard. ## `useSendTransaction` diff --git a/docs/pages/wallets/wallet-api/sign-message.mdx b/docs/pages/wallets/wallet-api/sign-message.mdx index c0539480..c369f800 100644 --- a/docs/pages/wallets/wallet-api/sign-message.mdx +++ b/docs/pages/wallets/wallet-api/sign-message.mdx @@ -1,9 +1,5 @@ # Sign a Message [Sign messages with Wagmi hooks] -:::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. -::: - To sign a message, use Wagmi's `useSignMessage` hook: ```tsx diff --git a/docs/pages/wallets/wallet-api/sign-typed-message.mdx b/docs/pages/wallets/wallet-api/sign-typed-message.mdx index 75af00fb..7d450487 100644 --- a/docs/pages/wallets/wallet-api/sign-typed-message.mdx +++ b/docs/pages/wallets/wallet-api/sign-typed-message.mdx @@ -1,9 +1,5 @@ # Sign a Typed Message [EIP-712 typed data signing] -:::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. -::: - EIP-712 typed data signing works through Wagmi's `useSignTypedData`. ```tsx diff --git a/vocs.config.tsx b/vocs.config.tsx index 2a13879a..21394992 100644 --- a/vocs.config.tsx +++ b/vocs.config.tsx @@ -441,8 +441,7 @@ export default defineConfig({ ], }, ], - // Embedded Wallet (alpha) — not advertised in the public pillar bar. - // Lives at /wallets/* and is only navigable for users who know the URL. + // Embedded Wallet. "/wallets": [ { text: "Embedded Wallet", @@ -1084,6 +1083,7 @@ export default defineConfig({ { href: '/onboarding/create-a-smart-account', text: 'Onboarding', match: function(p) { return p.indexOf('/onboarding') === 0; } }, { href: '/onramp/smart-routing-address', text: 'Onramp', match: function(p) { return p.indexOf('/onramp') === 0; } }, { href: '/smart-accounts/send-transactions', text: 'Smart Account', match: function(p) { return p.indexOf('/smart-accounts') === 0; } }, + { href: '/wallets', text: 'Wallets', match: function(p) { return p.indexOf('/wallets') === 0; } }, { href: '/advanced/migration', text: 'Advanced', match: function(p) { return p.indexOf('/advanced') === 0; } }, { href: '/api-and-toolings/infrastructure/gas-policies', text: 'API & Tooling', match: function(p) { return p.indexOf('/api-and-toolings') === 0; } } ]; From 0f14e9be180e359cfed9d07c4e93cee7352cbf04 Mon Sep 17 00:00:00 2001 From: srinjoyc Date: Wed, 1 Jul 2026 16:02:49 -0700 Subject: [PATCH 02/25] Update wallet docs --- docs/pages/wallets/auth/email-otp.mdx | 91 ++- docs/pages/wallets/auth/google-oauth.mdx | 66 ++- docs/pages/wallets/auth/magic-link.mdx | 113 ++-- docs/pages/wallets/auth/passkeys.mdx | 113 ++-- docs/pages/wallets/auth/wallet-ui-kit.mdx | 190 +++++++ .../wallets/hooks/use-send-magic-link.mdx | 18 - docs/pages/wallets/hooks/use-send-otp.mdx | 18 - docs/pages/wallets/quickstart.mdx | 238 ++++++-- docs/pages/wallets/sdk-reference.mdx | 518 ++++++++++++++++++ docs/pages/wallets/session-management.mdx | 126 +++-- vocs.config.tsx | 68 +-- 11 files changed, 1246 insertions(+), 313 deletions(-) create mode 100644 docs/pages/wallets/auth/wallet-ui-kit.mdx create mode 100644 docs/pages/wallets/sdk-reference.mdx diff --git a/docs/pages/wallets/auth/email-otp.mdx b/docs/pages/wallets/auth/email-otp.mdx index cd767ced..60cc16fb 100644 --- a/docs/pages/wallets/auth/email-otp.mdx +++ b/docs/pages/wallets/auth/email-otp.mdx @@ -1,26 +1,25 @@ -# Email OTP Authentication [Authenticate with a one-time code sent by email] +# Email OTP [Authenticate with a one-time code] -Email OTP is a two-step flow: send a verification code to the user's email, then verify the code they enter. +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. -## Hooks +## Add OTP login -- [`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(null) + const [otpEncryptionTargetBundle, setOtpEncryptionTargetBundle] = + useState(null) const { address, isConnected } = useAccount() - const { disconnectAsync } = useDisconnect() + const { disconnect } = useDisconnect() const sendOTP = useSendOTP() const verifyOTP = useVerifyOTP() @@ -28,7 +27,9 @@ function EmailOTPAuth() { return (

Connected: {address}

- +
) } @@ -38,20 +39,25 @@ function EmailOTPAuth() {
setEmail(e.target.value)} + onChange={(event) => setEmail(event.target.value)} /> + - {sendOTP.isError &&

Error: {sendOTP.error.message}

} + + {sendOTP.error ?

{sendOTP.error.message}

: null}
) } @@ -59,19 +65,41 @@ function EmailOTPAuth() { return (

Code sent to {email}

+ setCode(e.target.value)} + onChange={(event) => setCode(event.target.value)} /> + + + - {verifyOTP.isError &&

Error: {verifyOTP.error.message}

} + + {verifyOTP.error ?

{verifyOTP.error.message}

: null}
) } @@ -79,8 +107,19 @@ function EmailOTPAuth() { ## 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 through [`useGetUserEmail`](/wallets/hooks/use-get-user-email). +- If you need link-based email login instead of manual code entry, use [Magic Link](/wallets/auth/magic-link). -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) diff --git a/docs/pages/wallets/auth/google-oauth.mdx b/docs/pages/wallets/auth/google-oauth.mdx index 3b7a6670..850a47a8 100644 --- a/docs/pages/wallets/auth/google-oauth.mdx +++ b/docs/pages/wallets/auth/google-oauth.mdx @@ -1,34 +1,42 @@ -# Google OAuth [Authenticate with Google sign-in] +# Google OAuth [Authenticate with Google] -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. +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. -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. +Use Google OAuth when you want a familiar social login flow without building the OAuth exchange yourself. -> **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. +## Dashboard setup -## Hook +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. -- [`useAuthenticateOAuth`](/wallets/hooks/use-authenticate-oauth) — Trigger the OAuth flow +If you want to use your own Google OAuth client, configure the client ID and secret in the ZeroDev dashboard. -## Example +:::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. +::: + +## Add Google login + +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 (

Connected: {address}

- +
) } @@ -36,21 +44,20 @@ function GoogleAuth() { return (
- {authenticateOAuth.isError && ( -

Error: {authenticateOAuth.error.message}

- )} + {authenticateOAuth.error ? ( +

{authenticateOAuth.error.message}

+ ) : null}
) } @@ -58,14 +65,21 @@ function GoogleAuth() { ## 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 through [`useGetUserEmail`](/wallets/hooks/use-get-user-email). -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) diff --git a/docs/pages/wallets/auth/magic-link.mdx b/docs/pages/wallets/auth/magic-link.mdx index 18bd23b0..672e5f4c 100644 --- a/docs/pages/wallets/auth/magic-link.mdx +++ b/docs/pages/wallets/auth/magic-link.mdx @@ -1,21 +1,28 @@ -# Magic Link Authentication [Authenticate with a link sent by email] +# Magic Link [Authenticate with an email link] -Magic links let users authenticate by clicking a link in their email. The link redirects to your app where the SDK completes the verification. +Magic links let users sign in by clicking a link in their email. The link returns the user to your app, where you verify the redirect and connect the wallet. -## Hooks +Use magic links when you want email login without asking the user to copy a code. -- [`useSendMagicLink`](/wallets/hooks/use-send-magic-link) — Send a magic link to an email address -- [`useVerifyMagicLink`](/wallets/hooks/use-verify-magic-link) — Verify the magic link and authenticate +## Configure your redirect URL -## Example +Magic links need a route in your app that can receive the redirect and call `useVerifyMagicLink`. For local development, this might be: -### Login page — send the magic link +```txt +http://localhost:3000/verify +``` + +Make sure the redirect origin is also added to the project's ACL allowlist in the ZeroDev dashboard. If your project uses custom email templates or custom link behavior, configure those settings in the dashboard before testing magic links. + +## Send the magic link + +Call `useSendMagicLink` from your login page. Store the returned `otpId` and `otpEncryptionTargetBundle` so the verify page can complete authentication. ```tsx -import { useState } from 'react' import { useSendMagicLink } from '@zerodev/wallet-react' +import { useState } from 'react' -function MagicLinkLogin() { +export function MagicLinkLogin() { const [email, setEmail] = useState('') const sendMagicLink = useSendMagicLink() @@ -23,69 +30,84 @@ function MagicLinkLogin() {
setEmail(e.target.value)} + onChange={(event) => setEmail(event.target.value)} /> + - {sendMagicLink.isSuccess && ( -

Check your email for the magic link!

- )} - {sendMagicLink.isError && ( -

Error: {sendMagicLink.error.message}

- )} + {sendMagicLink.isSuccess ?

Check your email

: null} + {sendMagicLink.error ?

{sendMagicLink.error.message}

: null}
) } ``` -### Verify page — handle the redirect +## Verify the link -When the user clicks the magic link, they're redirected to your `redirectURL` with query parameters. The verify page reads these and completes authentication: +On your verify route, read the `code` query parameter and the stored `otpId` and `otpEncryptionTargetBundle`, then call `useVerifyMagicLink`. ```tsx +import { useVerifyMagicLink } from '@zerodev/wallet-react' import { useEffect } from 'react' -import { useSearchParams } from 'next/navigation' import { useAccount } from 'wagmi' -import { useVerifyMagicLink } from '@zerodev/wallet-react' -function VerifyMagicLink() { - const searchParams = useSearchParams() - const { isConnected, address } = useAccount() +export function VerifyMagicLink() { + const { address, isConnected } = useAccount() const verifyMagicLink = useVerifyMagicLink() useEffect(() => { - const code = searchParams.get('code') - const otpId = sessionStorage.getItem('magicLinkOtpId') - - if (code && otpId && !isConnected) { - verifyMagicLink.mutateAsync({ otpId, code }) + const params = new URLSearchParams(window.location.search) + const code = params.get('code') + const otpId = sessionStorage.getItem('zerodevMagicLinkOtpId') + const otpEncryptionTargetBundle = sessionStorage.getItem( + 'zerodevMagicLinkBundle', + ) + + if ( + code && + otpId && + otpEncryptionTargetBundle && + !isConnected && + !verifyMagicLink.isPending + ) { + verifyMagicLink.mutate({ + otpId, + otpEncryptionTargetBundle, + code, + }) } - }, [searchParams]) + }, [isConnected, verifyMagicLink]) if (isConnected) { return

Connected: {address}

} if (verifyMagicLink.isPending) { - return

Verifying...

+ return

Verifying link...

} - if (verifyMagicLink.isError) { - return

Error: {verifyMagicLink.error.message}

+ if (verifyMagicLink.error) { + return

{verifyMagicLink.error.message}

} return

Waiting for verification...

@@ -94,10 +116,19 @@ function VerifyMagicLink() { ## How it works -1. **Send link**: `useSendMagicLink` sends an email with a magic link pointing to your `redirectURL`. It returns an `otpId` that you need for verification. +1. `useSendMagicLink` sends an email with a link to your `redirectURL` and returns an `otpId` plus an `otpEncryptionTargetBundle`. +2. The user clicks the link and lands back in your app with a `code` query parameter. +3. `useVerifyMagicLink` verifies the `otpId`, `otpEncryptionTargetBundle`, and `code`. +4. After verification succeeds, the SDK creates a session and connects the ZeroDev Wagmi connector. + +## Notes -2. **User clicks link**: The user clicks the link in their email, which redirects them to your app with a `code` query parameter. +- Store the `otpId` and `otpEncryptionTargetBundle` somewhere the verify route can read them. `sessionStorage` is enough for a same-browser flow. +- If users open the link on a different device or browser, you need an app-specific way to recover both values. +- Magic link email behavior depends on your project email configuration in the dashboard. -3. **Verify**: Your verify page calls `useVerifyMagicLink` with the `otpId` and `code`. If 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), [Email OTP](/wallets/auth/email-otp), or [Google OAuth](/wallets/auth/google-oauth) diff --git a/docs/pages/wallets/auth/passkeys.mdx b/docs/pages/wallets/auth/passkeys.mdx index efe9a9e7..841d5fec 100644 --- a/docs/pages/wallets/auth/passkeys.mdx +++ b/docs/pages/wallets/auth/passkeys.mdx @@ -1,33 +1,72 @@ -# Passkey Authentication [Register and login with WebAuthn passkeys] +# Passkey Authentication [Register and login with WebAuthn] -Passkeys use the [WebAuthn](https://webauthn.guide/) standard for passwordless authentication. Users authenticate with biometrics (Face ID, Touch ID, fingerprint) or a hardware security key. +Passkeys are the fastest passwordless option for most apps. Users authenticate with Face ID, Touch ID, a fingerprint, a device PIN, or a hardware security key. -## Configure RP ID (optional) +Use passkeys when you want an email-free wallet flow. Passkeys use [WebAuthn](https://webauthn.guide/), and the browser handles the passkey prompt. -Set `rpId` on the connector if you need a custom [relying party identifier](https://www.w3.org/TR/webauthn-2/#relying-party-identifier) (defaults to the current hostname): +## Configure Wagmi -```ts +Passkeys work with the same connector setup from the [Quickstart](/wallets/quickstart): + +```tsx +import { zeroDevWallet } from '@zerodev/wallet-react' +import { createConfig, http } from 'wagmi' +import { arbitrumSepolia } from 'wagmi/chains' + +const projectId = '' +const aaUrl = '' +const chainRpcUrl = 'https://sepolia-rollup.arbitrum.io/rpc' + +export const config = createConfig({ + chains: [arbitrumSepolia], + connectors: [ + zeroDevWallet({ + projectId, + aaUrl, + chains: [arbitrumSepolia], + mode: '7702', + }), + ], + transports: { + [arbitrumSepolia.id]: http(chainRpcUrl), + }, +}) +``` + +## Set a custom RP ID + +The relying party ID, or RP ID, is the domain WebAuthn uses to scope a passkey. A passkey registered for one RP ID can only be used later with that same RP ID. + +By default, the SDK uses the current hostname. Set `rpId` when you want passkeys to work across subdomains of the same site. + +```tsx zeroDevWallet({ - projectId: process.env.NEXT_PUBLIC_ZERODEV_PROJECT_ID!, - chains: [sepolia], - rpId: "example.com", -}); + projectId, + aaUrl, + chains: [arbitrumSepolia], + rpId: 'example.com', +}) ``` -## Hooks +Use a domain only. Do not include a protocol, path, or port. For example, if your app runs on `https://app.example.com` and you want passkeys to work across your app's subdomains, use `example.com`. + +Choose the RP ID before users register passkeys. You cannot transfer an existing passkey from one RP ID to another; changing the RP ID later usually means users must register new passkeys. + +Learn more in the [WebAuthn RP ID docs](https://www.w3.org/TR/webauthn-3/#rp-id). + +## Add passkey login -- [`useRegisterPasskey`](/wallets/hooks/use-register-passkey) — Create a new wallet with a passkey -- [`useLoginPasskey`](/wallets/hooks/use-login-passkey) — Sign in to an existing wallet +Use `useRegisterPasskey` for new users and `useLoginPasskey` for returning users. -## Example +Registration creates a new passkey. Login asks the user to choose an existing passkey and approve the browser prompt. In Chrome, for example, that prompt may use the OS password manager, device biometrics, a PIN, or a hardware security key. ```tsx +import { useLoginPasskey, useRegisterPasskey } from '@zerodev/wallet-react' import { useAccount, useDisconnect } from 'wagmi' -import { useRegisterPasskey, useLoginPasskey } from '@zerodev/wallet-react' -function PasskeyAuth() { +export function PasskeyLogin() { const { address, isConnected } = useAccount() - const { disconnectAsync } = useDisconnect() + const { disconnect } = useDisconnect() const registerPasskey = useRegisterPasskey() const loginPasskey = useLoginPasskey() @@ -35,7 +74,9 @@ function PasskeyAuth() { return (

Connected: {address}

- +
) } @@ -43,25 +84,23 @@ function PasskeyAuth() { return (
- {registerPasskey.isError && ( -

Registration error: {registerPasskey.error.message}

- )} - {loginPasskey.isError && ( -

Login error: {loginPasskey.error.message}

- )} + {registerPasskey.error ?

{registerPasskey.error.message}

: null} + {loginPasskey.error ?

{loginPasskey.error.message}

: null}
) } @@ -69,14 +108,20 @@ function PasskeyAuth() { ## How it works -1. **Register**: `useRegisterPasskey` triggers the browser's WebAuthn prompt. The user creates a passkey stored on their device. A new wallet is created and linked to the passkey. +1. `useRegisterPasskey` opens the browser's WebAuthn prompt and creates a wallet linked to the new passkey. +2. `useLoginPasskey` opens the WebAuthn prompt and authenticates an existing passkey. +3. After either flow succeeds, the SDK creates a session and connects the ZeroDev Wagmi connector. -2. **Login**: `useLoginPasskey` triggers the WebAuthn prompt. The user selects their existing passkey. The SDK authenticates and creates a session. - -After either flow, the Wagmi connector is connected and the user's address is available via `useAccount`. +Use `useAccount`, `useSignMessage`, and `useSendTransaction` after authentication. ## Notes -- No email is required for passkey auth — the passkey itself is the credential -- Passkeys are supported in all major browsers (Chrome, Safari, Firefox, Edge) -- Passkeys can sync across devices via iCloud Keychain, Google Password Manager, etc. +- Passkeys require a secure context. `localhost` works for local development; production apps should use HTTPS. +- The dashboard ACL allowlist must include the exact origin you open in the browser. +- Passkeys can sync across devices through platform password managers, depending on the user's device, browser, and account recovery settings. + +## Next steps + +- [Send a transaction](/wallets/wallet-api/send-transaction) +- [Sign a message](/wallets/wallet-api/sign-message) +- Integrate other login methods: [Email OTP](/wallets/auth/email-otp), [Magic Link](/wallets/auth/magic-link), or [Google OAuth](/wallets/auth/google-oauth) diff --git a/docs/pages/wallets/auth/wallet-ui-kit.mdx b/docs/pages/wallets/auth/wallet-ui-kit.mdx new file mode 100644 index 00000000..5edcfcae --- /dev/null +++ b/docs/pages/wallets/auth/wallet-ui-kit.mdx @@ -0,0 +1,190 @@ +# Wallet UI Kit [Optional prebuilt login UI] + +Use the Wallet UI Kit when you want a prebuilt login flow instead of building your own forms with the authentication hooks. The kit still uses a Wagmi-compatible ZeroDev connector, so after the user signs in you can use standard Wagmi hooks such as `useAccount`, `useSignMessage`, and `useSendTransaction`. + +For a fully custom UI, use the hook-based authentication pages instead: + +- [Passkeys](/wallets/auth/passkeys) +- [Email OTP](/wallets/auth/email-otp) +- [Magic Link](/wallets/auth/magic-link) +- [Google OAuth](/wallets/auth/google-oauth) + +## Install packages + +:::code-group + +```bash [npm] +npm i @zerodev/wallet-react-kit @zerodev/wallet-react @zerodev/wallet-core wagmi viem @tanstack/react-query +``` + +```bash [yarn] +yarn add @zerodev/wallet-react-kit @zerodev/wallet-react @zerodev/wallet-core wagmi viem @tanstack/react-query +``` + +```bash [pnpm] +pnpm i @zerodev/wallet-react-kit @zerodev/wallet-react @zerodev/wallet-core wagmi viem @tanstack/react-query +``` + +```bash [bun] +bun add @zerodev/wallet-react-kit @zerodev/wallet-react @zerodev/wallet-core wagmi viem @tanstack/react-query +``` + +::: + +## Configure Wagmi + +Import `zeroDevWallet` from `@zerodev/wallet-react-kit`. This connector wraps the base ZeroDev Wallet connector and controls the kit's auth UI state. + +```tsx +import { zeroDevWallet } from '@zerodev/wallet-react-kit' +import { createConfig, http } from 'wagmi' +import { arbitrumSepolia } from 'wagmi/chains' + +const projectId = '' +const aaUrl = '' +const chainRpcUrl = 'https://sepolia-rollup.arbitrum.io/rpc' + +export const config = createConfig({ + chains: [arbitrumSepolia], + connectors: [ + zeroDevWallet({ + projectId, + aaUrl, + chains: [arbitrumSepolia], + mode: '7702', + config: { + auth: { + enabledMethods: ['email', 'google', 'passkey'], + emailAuthMethod: 'otp', + }, + }, + }), + ], + transports: { + [arbitrumSepolia.id]: http(chainRpcUrl), + }, +}) +``` + +Only enable authentication methods that are configured for your project. This example uses OTP for email authentication. + +## Add providers and styles + +Import the kit stylesheet once at your app entry, then wrap your app with Wagmi and TanStack Query providers. + +```tsx +import { QueryClient, QueryClientProvider } from '@tanstack/react-query' +import '@zerodev/wallet-react-kit/styles.css' +import type { ReactNode } from 'react' +import { WagmiProvider } from 'wagmi' +import { config } from './wagmi' + +const queryClient = new QueryClient() + +export function WalletProviders({ children }: { children: ReactNode }) { + return ( + + + {children} + + + ) +} +``` + +## Render the login flow + +Call Wagmi's `connect` with the ZeroDev connector to start login. Render `` in the same provider tree; it displays the active auth screen while the connector is waiting for the user to finish authentication. + +```tsx +import { AuthFlow } from '@zerodev/wallet-react-kit' +import { useAccount, useConnect, useDisconnect } from 'wagmi' + +export function WalletLogin() { + const { address, isConnected } = useAccount() + const { connect, connectors, isPending } = useConnect() + const { disconnect } = useDisconnect() + const zeroDevConnector = connectors.find( + (connector) => connector.id === 'zerodev-wallet', + ) + + return ( +
+ {isConnected ? ( +
+

Connected: {address}

+ +
+ ) : ( + + )} + + +
+ ) +} + +function AuthPanel() { + return ( +
+ +
+ ) +} +``` + +## Size the container + +`AuthFlow` renders into the width you give it. Put it in a constrained container, modal, or drawer instead of letting it stretch across the full page on large screens. + +```tsx +
+ setLoginOpen(false)} /> +
+``` + +The `onClose` prop is optional. Use it when your app owns surrounding UI state, such as closing a modal after the user clicks the kit's close button. + +## Add signing confirmations beta + +The UI kit also includes `SignatureRequest`, an experimental prebuilt confirmation feature for signing and transaction requests. Mount it once in the same provider tree as your wallet UI. + +```tsx +import { AuthFlow, SignatureRequest } from '@zerodev/wallet-react-kit' + +export function WalletOverlays() { + return ( + <> +
+ +
+ +
+ +
+ + ) +} +``` + +By default, the kit prompts for signing and transaction methods such as `personal_sign`, `eth_signTypedData_v4`, and `eth_sendTransaction`. This confirmation feature is in beta and will continue improving over time. + +## Coming soon + +The Wallet UI Kit will add more prebuilt wallet components and screens over time, including onramps, asset management and portfolio views, and transaction history. To request early access, reach out to the [ZeroDev sales team](https://zerodev.app/contact). + +## Next steps + +- [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), [Magic Link](/wallets/auth/magic-link), or [Google OAuth](/wallets/auth/google-oauth) diff --git a/docs/pages/wallets/hooks/use-send-magic-link.mdx b/docs/pages/wallets/hooks/use-send-magic-link.mdx index 73014bbe..cab783bf 100644 --- a/docs/pages/wallets/hooks/use-send-magic-link.mdx +++ b/docs/pages/wallets/hooks/use-send-magic-link.mdx @@ -60,24 +60,6 @@ function SendMagicLink() { **Required.** The URL the user will be redirected to after clicking the magic link. This should be a page in your app that calls [`useVerifyMagicLink`](/wallets/hooks/use-verify-magic-link). -### otpCodeCustomization - -`{ length?: 6 | 7 | 8 | 9; alphanumeric?: boolean } | undefined` - -Optional customization for the generated verification code. - -#### length - -`6 | 7 | 8 | 9 | undefined` - -The number of characters in the code. Defaults to `6`. - -#### alphanumeric - -`boolean | undefined` - -Whether to use alphanumeric characters instead of digits only. Defaults to `false`. - ## Return Types [TanStack Query mutation docs](https://tanstack.com/query/v5/docs/react/reference/useMutation) diff --git a/docs/pages/wallets/hooks/use-send-otp.mdx b/docs/pages/wallets/hooks/use-send-otp.mdx index 9c11647b..1bfff47a 100644 --- a/docs/pages/wallets/hooks/use-send-otp.mdx +++ b/docs/pages/wallets/hooks/use-send-otp.mdx @@ -61,24 +61,6 @@ Optional email customization options. Custom template for the email content. -### otpCodeCustomization - -`{ length?: 6 | 7 | 8 | 9; alphanumeric?: boolean } | undefined` - -Optional customization for the generated OTP code. - -#### length - -`6 | 7 | 8 | 9 | undefined` - -The number of characters in the OTP code. Defaults to `6`. - -#### alphanumeric - -`boolean | undefined` - -Whether to use alphanumeric characters instead of digits only. Defaults to `false`. - ## Return Types [TanStack Query mutation docs](https://tanstack.com/query/v5/docs/react/reference/useMutation) diff --git a/docs/pages/wallets/quickstart.mdx b/docs/pages/wallets/quickstart.mdx index f976e343..326f894d 100644 --- a/docs/pages/wallets/quickstart.mdx +++ b/docs/pages/wallets/quickstart.mdx @@ -1,64 +1,113 @@ # Quickstart [Get up and running in 5 minutes] -## Installation +Add ZeroDev Wallet to any React app that can render client-side React components. Authenticate users with ZeroDev hooks, then use standard Wagmi hooks for wallet actions. + +Want less code to get started even faster? Try the optional [Wallet UI Kit](/wallets/auth/wallet-ui-kit) for a prebuilt login flow. + +For a complete working reference, see the [ZeroDev Wallet SDK demo app](https://github.com/zerodevapp/zerodev-wallet-sdk/tree/main/apps/zerodev-signer-demo). + +## Prerequisites + +You will need: + +- A ZeroDev account in the [ZeroDev Dashboard](https://dashboard.zerodev.app/). +- A project with at least one enabled network. +- Your project ID. +- The Bundler RPC URL for the network you want to use. +- Your app origin added to the project's ACL allowlist. + +## Install packages :::code-group ```bash [npm] -npm i @zerodev/wallet-react @zerodev/sdk wagmi viem @tanstack/react-query +npm i @zerodev/wallet-react @zerodev/wallet-core wagmi viem @tanstack/react-query ``` ```bash [yarn] -yarn add @zerodev/wallet-react @zerodev/sdk wagmi viem @tanstack/react-query +yarn add @zerodev/wallet-react @zerodev/wallet-core wagmi viem @tanstack/react-query ``` ```bash [pnpm] -pnpm i @zerodev/wallet-react @zerodev/sdk wagmi viem @tanstack/react-query +pnpm i @zerodev/wallet-react @zerodev/wallet-core wagmi viem @tanstack/react-query ``` ```bash [bun] -bun add @zerodev/wallet-react @zerodev/sdk wagmi viem @tanstack/react-query +bun add @zerodev/wallet-react @zerodev/wallet-core wagmi viem @tanstack/react-query ``` ::: -## 1. Configure Wagmi +## Allowlist your app origin + +Before testing authentication, add your app's origin to the project's ACL allowlist in the ZeroDev dashboard. + +For example, if you run your app at `http://localhost:3000` during development, add `http://localhost:3000` to the allowlist. + +## Add configuration values -Create a Wagmi config with the `zeroDevWallet` connector: +In the ZeroDev dashboard, open your project and copy its project ID. Then open the network you enabled for this app and copy its Bundler RPC URL. + +Add these values to your app's configuration. The exact environment variable prefix depends on your framework: + +```bash +ZERODEV_PROJECT_ID="your-project-id" +ZERODEV_AA_URL="your-chain-specific-zerodev-rpc-url" +ARBITRUM_SEPOLIA_RPC_URL="https://sepolia-rollup.arbitrum.io/rpc" +``` + +- `ZERODEV_PROJECT_ID` is your ZeroDev project ID. +- `ZERODEV_AA_URL` is the network-specific Bundler RPC URL from the dashboard. +- `ARBITRUM_SEPOLIA_RPC_URL` is the chain RPC used by Wagmi's transport. + +This example uses Arbitrum Sepolia. Replace the chain and RPC URLs if your project uses a different chain. + +## Configure Wagmi + +Create `src/wagmi.ts`: ```tsx -import { createConfig, http } from 'wagmi' -import { sepolia } from 'wagmi/chains' import { zeroDevWallet } from '@zerodev/wallet-react' +import { createConfig, http } from 'wagmi' +import { arbitrumSepolia } from 'wagmi/chains' + +const projectId = '' +const aaUrl = '' +const chainRpcUrl = 'https://sepolia-rollup.arbitrum.io/rpc' export const config = createConfig({ - chains: [sepolia], + chains: [arbitrumSepolia], connectors: [ zeroDevWallet({ - projectId: 'YOUR_ZERODEV_PROJECT_ID', - chains: [sepolia], + projectId, + aaUrl, + chains: [arbitrumSepolia], + mode: '7702', }), ], transports: { - [sepolia.id]: http(), + [arbitrumSepolia.id]: http(chainRpcUrl), }, }) ``` -Get your project ID from the [ZeroDev Dashboard](https://dashboard.zerodev.app/). +In your app, replace the inline constants with your framework's public runtime config or client-safe environment variable access. + +`7702` is the SDK default, but setting it explicitly makes the recommended mode clear. -## 2. Wrap your app +## Add providers -Wrap your application with `WagmiProvider` and `QueryClientProvider`: +Wrap your app with Wagmi and TanStack Query providers: ```tsx -import { WagmiProvider } from 'wagmi' import { QueryClient, QueryClientProvider } from '@tanstack/react-query' -import { config } from './wagmi-config' +import type { ReactNode } from 'react' +import { WagmiProvider } from 'wagmi' +import { config } from './wagmi' const queryClient = new QueryClient() -export default function App({ children }: { children: React.ReactNode }) { +export function WalletProviders({ children }: { children: ReactNode }) { return ( @@ -69,17 +118,17 @@ export default function App({ children }: { children: React.ReactNode }) { } ``` -## 3. Add authentication +## Authenticate users -Here's a basic example with passkey registration and login: +Start with passkeys for a minimal passwordless flow: ```tsx +import { useLoginPasskey, useRegisterPasskey } from '@zerodev/wallet-react' import { useAccount, useDisconnect } from 'wagmi' -import { useRegisterPasskey, useLoginPasskey } from '@zerodev/wallet-react' -function AuthPage() { +export function WalletLogin() { const { address, isConnected } = useAccount() - const { disconnectAsync } = useDisconnect() + const { disconnect } = useDisconnect() const registerPasskey = useRegisterPasskey() const loginPasskey = useLoginPasskey() @@ -87,8 +136,8 @@ function AuthPage() { return (

Connected: {address}

-
) @@ -97,30 +146,143 @@ function AuthPage() { return (
+
+ ) +} +``` + +The auth hooks authenticate the user and connect the ZeroDev Wagmi connector. After auth succeeds, use normal Wagmi hooks such as `useAccount`, `useSignMessage`, and `useSendTransaction`. + +## Sign a message + +Message signing is offchain and does not require gas. + +```tsx +import { useSignMessage } from 'wagmi' + +export function SignMessageButton() { + const signMessage = useSignMessage() + + return ( +
+ + + {signMessage.data ?

Signature: {signMessage.data}

: null} + {signMessage.error ?

{signMessage.error.message}

: null} +
+ ) +} +``` + +## Send a gasless transaction + +To test gas sponsorship, configure a gas policy for your project and chain in the ZeroDev dashboard first. See [Gas Policies](/api-and-toolings/infrastructure/gas-policies) for setup details. + +This example sends a 0 ETH self-transfer. It exercises the full account abstraction transaction path without requiring the user to hold native gas. + +```tsx +import { + useAccount, + useSendTransaction, + useWaitForTransactionReceipt, +} from 'wagmi' + +export function SendTransactionButton() { + const { address } = useAccount() + const sendTransaction = useSendTransaction() + const receipt = useWaitForTransactionReceipt({ + hash: sendTransaction.data, + }) + + const isPending = + sendTransaction.isPending || + (Boolean(sendTransaction.data) && receipt.isLoading) + + return ( +
+ + + {sendTransaction.data ?

Hash: {sendTransaction.data}

: null} + {receipt.isSuccess ?

Transaction confirmed

: null} + {sendTransaction.error ?

{sendTransaction.error.message}

: null} + {receipt.error ?

{receipt.error.message}

: null}
) } ``` -After authentication, the user's wallet is available through standard Wagmi hooks like `useAccount`, `useSendTransaction`, and `useSignMessage`. +## Account modes + +ZeroDev Wallet supports two account modes: + +| Mode | Use when | Notes | +| --- | --- | --- | +| `7702` | You want the recommended default | Exposes the user's wallet address while enabling smart wallet features such as sponsorship. | +| `4337` | You need a counterfactual smart account address | Exposes the Kernel smart account address. The first transaction can deploy the account. | + +For most apps, use `7702`. + +## Other auth methods + +Passkeys are only one option. The white-label SDK also supports: + +- [Email OTP](/wallets/auth/email-otp) +- [Google OAuth](/wallets/auth/google-oauth) +- [Magic Link](/wallets/auth/magic-link) + +Each auth method connects the same ZeroDev Wagmi connector after successful authentication. + +## Optional UI kit + +The examples above use `@zerodev/wallet-react` so you can build your own UI. If you want a prebuilt login flow, use the optional [Wallet UI Kit](/wallets/auth/wallet-ui-kit). Keep the white-label hooks path if you want full control over layout, styling, and bundle size. + +## Troubleshooting + +- **Allowlist errors**: confirm that the dashboard allowlists the exact origin you are opening in the browser. +- **Sponsored transaction fails**: confirm that a gas policy exists for the project and chain. +- **Wrong chain**: make sure the chain in `createConfig`, the `aaUrl`, and the gas policy all refer to the same chain. -## Next Steps +## Next steps -- [Passkey Authentication](/wallets/auth/passkeys) — Full passkey guide -- [Email OTP](/wallets/auth/email-otp) — Authenticate with email codes -- [Google OAuth](/wallets/auth/google-oauth) — Social login with Google -- [Send Transactions](/wallets/wallet-api/send-transaction) — Send gasless transactions -- [Sign Messages](/wallets/wallet-api/sign-message) — Sign messages with the wallet -- [Session Management](/wallets/session-management) — Session lifecycle and refresh +- [Passkey Authentication](/wallets/auth/passkeys) +- [Email OTP](/wallets/auth/email-otp) +- [Google OAuth](/wallets/auth/google-oauth) +- [Send Transactions](/wallets/wallet-api/send-transaction) +- [Sign Messages](/wallets/wallet-api/sign-message) +- [Session Management](/wallets/session-management) diff --git a/docs/pages/wallets/sdk-reference.mdx b/docs/pages/wallets/sdk-reference.mdx new file mode 100644 index 00000000..90defc9b --- /dev/null +++ b/docs/pages/wallets/sdk-reference.mdx @@ -0,0 +1,518 @@ +# SDK Reference [ZeroDev Wallet React SDK] + +This page documents the public React SDK exports from `@zerodev/wallet-react`. Use the guide pages for complete workflows, and use this page when you need exact parameters and return values. + +## Import + +```ts +import { + OAUTH_PROVIDERS, + createZeroDevWalletStore, + generateOAuthNonce, + getZeroDevConnector, + getZeroDevStore, + getZeroDevWallet, + useAuthenticateOAuth, + useAuthenticators, + useExportPrivateKey, + useExportWallet, + useLoginPasskey, + useRefreshSession, + useRegisterPasskey, + useSendMagicLink, + useSendOTP, + useVerifyMagicLink, + useVerifyOTP, + verifyGoogleLoginUrl, + zeroDevWallet, + type GetOAuthSessionIdFn, + type OAuthProvider, + type WalletMode, + type ZeroDevProvider, + type ZeroDevWalletConnectorParams, + type ZeroDevWalletState, +} from "@zerodev/wallet-react"; +``` + +## Connector + +### `zeroDevWallet(params)` + +Creates the Wagmi connector used by `createConfig`. + +```ts +import { zeroDevWallet } from "@zerodev/wallet-react"; + +const connector = zeroDevWallet({ + projectId: "", + aaUrl: "", + chains: [arbitrumSepolia], + mode: "7702", +}); +``` + +#### Parameters + +| Name | Type | Required | Description | +| --- | --- | --- | --- | +| `projectId` | `string` | Yes | ZeroDev project ID from the dashboard. | +| `chains` | `readonly Chain[]` | Yes | Viem/Wagmi chain objects enabled for the project. The first chain is used as the default active chain. | +| `aaUrl` | `string` | No | Bundler/paymaster RPC URL. Required for `7702` and `4337` flows that send UserOperations or use gas sponsorship. If omitted, the connector derives the AA URL from `projectId` and chain ID. | +| `mode` | `"7702" \| "4337"` | No | Wallet mode. Defaults to `"7702"`. | +| `rpId` | `string` | No | Relying party ID for passkeys. For web apps, use the hostname that owns the passkey, for example `localhost` or `app.example.com`. | +| `organizationId` | `string` | No | Existing Turnkey organization ID, when you need to bind the wallet to a known organization. Most apps omit this. | +| `proxyBaseUrl` | `string` | No | Custom backend/proxy base URL for wallet services. Most apps use the default ZeroDev service. | +| `sessionStorage` | `StorageAdapter` | No | Storage adapter used by the wallet core session layer. | +| `persistStorage` | `StateStorage` | No | Zustand persistence storage for React connector state. The default persists session data under `zerodev-wallet`. | +| `apiKeyStamper` | `ApiKeyStamper \| Promise` | No | Advanced stamper override. Usually used by native or custom key management flows. | +| `passkeyStamper` | `PasskeyStamper \| Promise` | No | Advanced passkey stamper override. | +| `fetchOptions` | `CreateTransportOptions["fetchOptions"]` | No | Forwarded to Turnkey and AA transports. Web apps usually do not need this because browsers ignore custom `Origin` overrides. | +| `autoRefreshSession` | `boolean` | No | Enables automatic session refresh behavior in the provider layer. | +| `sessionWarningThreshold` | `number` | No | Milliseconds before expiry when the session should be considered expiring. | +| `autoInitialize` | `boolean \| () => boolean` | No | Controls whether connector setup initializes on mount. Defaults to true in browser and React Native environments. If false, initialization happens lazily on connect/provider/store access. | + +#### Returns + +`CreateConnectorFn`, suitable for Wagmi `createConfig({ connectors: [...] })`. + +#### Account modes + +| Mode | Address shown to Wagmi | Transaction path | When to use | +| --- | --- | --- | --- | +| `7702` | User wallet address | EIP-7702 Kernel UserOperations | Recommended default. Users keep a familiar wallet address while apps can use account abstraction features such as gas sponsorship. | +| `4337` | Counterfactual Kernel smart account address | ERC-4337 UserOperations | Use when you explicitly want a 4337 smart account address. | + +## Hook options + +All authentication, session, and export hooks are TanStack Query hooks. Mutation hooks return `UseMutationResult`, so you can use `mutate`, `mutateAsync`, `isPending`, `error`, `data`, and `reset`. + +Most hooks accept an optional `config` field when you need to pass a specific Wagmi config instead of using the nearest `WagmiProvider`. + +```ts +const { mutateAsync, isPending, error } = useRegisterPasskey({ + mutation: { + onSuccess: () => console.log("signed in"), + }, +}); +``` + +| Option | Type | Description | +| --- | --- | --- | +| `config` | `Config` | Optional Wagmi config override. | +| `mutation` | `UseMutationOptions` | Mutation options for auth, session, and export hooks. Not available on query hooks. | +| `query` | `UseQueryOptions` | Query options for `useAuthenticators`. | + +## Passkeys + +### `useRegisterPasskey(options?)` + +Registers a new passkey and authenticates the user. On success, the hook stores the session, derives the wallet account, and connects the ZeroDev connector in Wagmi. + +#### Mutation variables + +| Name | Type | Required | Description | +| --- | --- | --- | --- | +| `connector` | `Connector` | No | ZeroDev Wagmi connector override. Defaults to the connector with ID `zerodev-wallet` in the active Wagmi config. | + +#### Returns + +`UseMutationResult` + +```tsx +const registerPasskey = useRegisterPasskey(); + +; +``` + +### `useLoginPasskey(options?)` + +Authenticates with an existing passkey. On success, it stores the session, derives the wallet account, and connects the ZeroDev connector in Wagmi. + +#### Mutation variables + +| Name | Type | Required | Description | +| --- | --- | --- | --- | +| `connector` | `Connector` | No | ZeroDev Wagmi connector override. | + +#### Returns + +`UseMutationResult` + +```tsx +const loginPasskey = useLoginPasskey(); + +; +``` + +## Email OTP + +### `useSendOTP(options?)` + +Sends an email OTP code. + +#### Mutation variables + +| Name | Type | Required | Description | +| --- | --- | --- | --- | +| `email` | `string` | Yes | User email address. | +| `emailCustomization` | `{ magicLinkTemplate?: string }` | No | Optional email template customization. | +| `connector` | `Connector` | No | ZeroDev Wagmi connector override. | + +#### Returns + +`UseMutationResult<{ otpId: string; otpEncryptionTargetBundle: string }, Error, SendOTPVariables>` + +Store both returned values. `useVerifyOTP` needs the matching `otpId` and `otpEncryptionTargetBundle`. + +```tsx +const sendOTP = useSendOTP(); +const verifyOTP = useVerifyOTP(); + +const sent = await sendOTP.mutateAsync({ email }); + +await verifyOTP.mutateAsync({ + otpId: sent.otpId, + otpEncryptionTargetBundle: sent.otpEncryptionTargetBundle, + code, +}); +``` + +### `useVerifyOTP(options?)` + +Verifies an OTP code and authenticates the user. On success, it stores the session, derives the wallet account, and connects the ZeroDev connector in Wagmi. + +#### Mutation variables + +| Name | Type | Required | Description | +| --- | --- | --- | --- | +| `otpId` | `string` | Yes | OTP ID returned by `useSendOTP`. | +| `otpEncryptionTargetBundle` | `string` | Yes | Encryption target bundle returned by the matching `useSendOTP` call. | +| `code` | `string` | Yes | Code entered by the user. | +| `connector` | `Connector` | No | ZeroDev Wagmi connector override. | + +#### Returns + +`UseMutationResult` + +## Magic links + +### `useSendMagicLink(options?)` + +Sends a magic link email. + +#### Mutation variables + +| Name | Type | Required | Description | +| --- | --- | --- | --- | +| `email` | `string` | Yes | User email address. | +| `redirectURL` | `string` | Yes | URL the email link should return to after the user opens it. The URL must be allowlisted for the project. | +| `connector` | `Connector` | No | ZeroDev Wagmi connector override. | + +#### Returns + +`UseMutationResult<{ otpId: string; otpEncryptionTargetBundle: string }, Error, SendMagicLinkVariables>` + +Store both returned values. `useVerifyMagicLink` needs the matching `otpId` and `otpEncryptionTargetBundle`. + +```tsx +const sendMagicLink = useSendMagicLink(); + +const sent = await sendMagicLink.mutateAsync({ + email, + redirectURL: `${window.location.origin}/wallets/callback`, +}); +``` + +### `useVerifyMagicLink(options?)` + +Verifies the magic link code and authenticates the user. + +#### Mutation variables + +| Name | Type | Required | Description | +| --- | --- | --- | --- | +| `otpId` | `string` | Yes | OTP ID returned by `useSendMagicLink`. | +| `otpEncryptionTargetBundle` | `string` | Yes | Encryption target bundle returned by the matching `useSendMagicLink` call. | +| `code` | `string` | Yes | Code from the magic link redirect. | +| `connector` | `Connector` | No | ZeroDev Wagmi connector override. | + +#### Returns + +`UseMutationResult` + +## OAuth + +### `useAuthenticateOAuth(options?)` + +Starts the web OAuth flow using a popup and authenticates the user after the popup returns a session ID. The web hook uses `window.location.href` as the redirect URI and `window.location.origin` for popup polling. + +#### Options + +| Name | Type | Required | Description | +| --- | --- | --- | --- | +| `timeoutMs` | `number` | No | Popup polling timeout in milliseconds. Defaults to 5 minutes. | +| `config` | `Config` | No | Optional Wagmi config override. | +| `mutation` | `UseMutationOptions` | No | TanStack mutation options. | + +#### Mutation variables + +| Name | Type | Required | Description | +| --- | --- | --- | --- | +| `provider` | `OAuthProvider` | Yes | OAuth provider. Use `OAUTH_PROVIDERS.GOOGLE` for Google. | + +#### Returns + +`UseMutationResult` + +```tsx +const google = useAuthenticateOAuth(); + +; +``` + +### `OAUTH_PROVIDERS` + +Supported OAuth provider constants. + +| Name | Value | +| --- | --- | +| `OAUTH_PROVIDERS.GOOGLE` | `"google"` | + +### `OAuthProvider` + +Type union of supported OAuth provider values. Currently `"google"`. + +### `GetOAuthSessionIdFn` + +Function type for custom OAuth adapters. + +```ts +type GetOAuthSessionIdFn = (params: { + oauthUrl: string; + provider: OAuthProvider; +}) => Promise; +``` + +The web hook supplies this automatically. Custom platform flows use this shape to open the OAuth URL and return a session ID. + +## Sessions + +### `useRefreshSession(options?)` + +Refreshes the current authenticated session and updates connector state. + +#### Mutation variables + +| Name | Type | Required | Description | +| --- | --- | --- | --- | +| `connector` | `Connector` | No | ZeroDev Wagmi connector override. | + +#### Returns + +`UseMutationResult` + +Throws when there is no active session to refresh. + +```tsx +const refreshSession = useRefreshSession(); + +await refreshSession.mutateAsync({}); +``` + +## Authenticators + +### `useAuthenticators(options?)` + +Reads authenticators associated with the current user in the connected project/sub-organization. The result can include OAuth authenticators, passkeys, email contacts, and API keys. + +#### Options + +| Name | Type | Required | Description | +| --- | --- | --- | --- | +| `config` | `Config` | No | Optional Wagmi config override. | +| `query` | `UseQueryOptions` | No | TanStack query options, excluding `queryKey` and `queryFn`. | + +#### Returns + +`UseQueryResult` + +```tsx +const authenticators = useAuthenticators({ + query: { enabled: isConnected }, +}); +``` + +## Wallet export + +### `useExportWallet(options?)` + +Renders the secure Turnkey export iframe into a container element and injects the wallet export bundle. + +#### Mutation variables + +| Name | Type | Required | Description | +| --- | --- | --- | --- | +| `iframeContainerId` | `string` | Yes | DOM element ID where the export iframe should be mounted. | +| `iframeStyles` | `Record` | No | CSS styles passed to the iframe stamper. | +| `connector` | `Connector` | No | ZeroDev Wagmi connector override. | + +#### Returns + +`UseMutationResult` + +```tsx +const exportWallet = useExportWallet(); + +await exportWallet.mutateAsync({ + iframeContainerId: "export-wallet", + iframeStyles: { + width: "100%", + height: "260px", + }, +}); +``` + +### `useExportPrivateKey(options?)` + +Renders the secure Turnkey export iframe into a container element and injects a private key export bundle. + +#### Mutation variables + +| Name | Type | Required | Description | +| --- | --- | --- | --- | +| `iframeContainerId` | `string` | Yes | DOM element ID where the export iframe should be mounted. | +| `iframeStyles` | `Record` | No | CSS styles passed to the iframe stamper. | +| `address` | `string` | No | Specific wallet address/key to export. | +| `keyFormat` | `"Hexadecimal" \| "Solana"` | No | Export format. Defaults to `"Hexadecimal"`. | +| `connector` | `Connector` | No | ZeroDev Wagmi connector override. | + +#### Returns + +`UseMutationResult` + +```tsx +const exportPrivateKey = useExportPrivateKey(); + +await exportPrivateKey.mutateAsync({ + iframeContainerId: "export-private-key", + keyFormat: "Hexadecimal", +}); +``` + +## Store and connector helpers + +These helpers are lower-level escape hatches. Most apps should use Wagmi hooks and ZeroDev auth hooks instead. + +### `getZeroDevConnector(config)` + +Finds the ZeroDev connector in a Wagmi config. + +| Parameter | Type | Description | +| --- | --- | --- | +| `config` | `Config` | Wagmi config containing a `zerodev-wallet` connector. | + +Returns the ZeroDev connector, including `rpId` and `getStore()`. Throws if the connector is not found. + +### `getZeroDevStore(connector)` + +Gets the Zustand store associated with a ZeroDev connector. + +| Parameter | Type | Description | +| --- | --- | --- | +| `connector` | `Connector` | ZeroDev connector returned by `zeroDevWallet`. | + +Returns `Promise>`. + +### `getZeroDevWallet(store)` + +Reads the initialized wallet SDK instance from the ZeroDev store. + +| Parameter | Type | Description | +| --- | --- | --- | +| `store` | `ReturnType` | ZeroDev wallet store. | + +Returns `ZeroDevWalletSDK`. Throws `"Wallet not initialized"` if connector setup has not completed. + +### `createZeroDevWalletStore(options?)` + +Creates the internal Zustand store used by the connector. + +| Parameter | Type | Description | +| --- | --- | --- | +| `options.storage` | `StateStorage` | Optional custom persistence storage. | + +The store persists only `session` and `activeChainId` under the `zerodev-wallet` key. + +## OAuth utilities + +### `generateOAuthNonce(publicKey)` + +Computes the nonce expected in a Google OAuth URL for a wallet public key. + +| Parameter | Type | Description | +| --- | --- | --- | +| `publicKey` | `string` | Wallet public key, with or without `0x` prefix. | + +Returns a lowercase hex SHA-256 hash string without `0x`. + +### `verifyGoogleLoginUrl(loginUrl, publicKey)` + +Verifies that a Google OAuth URL is valid for the wallet public key. + +| Parameter | Type | Description | +| --- | --- | --- | +| `loginUrl` | `string` | OAuth URL returned by the backend. | +| `publicKey` | `string` | Wallet public key used to verify the nonce. | + +Returns `void`. Throws if the URL is malformed, the host is not `accounts.google.com`, the nonce is missing, or the nonce does not match `generateOAuthNonce(publicKey)`. + +## Types + +### `WalletMode` + +```ts +type WalletMode = "4337" | "7702"; +``` + +### `ZeroDevWalletConnectorParams` + +Connector parameter type for `zeroDevWallet`. It matches the connector parameters above. + +### `ZeroDevProvider` + +ZeroDev EIP-1193 provider type returned by the connector's `getProvider()` method. + +### `ZeroDevWalletState` + +Zustand store state type used internally by the connector. + +Important fields include: + +| Field | Type | Description | +| --- | --- | --- | +| `wallet` | `ZeroDevWalletSDK \| null` | Core wallet SDK instance. | +| `session` | `ZeroDevWalletSession \| null` | Active wallet session. | +| `activeChainId` | `number \| null` | Active chain ID. | +| `kernelAccounts` | `Map` | Per-chain Kernel accounts for `7702` and `4337` modes. | +| `kernelClients` | `Map` | Per-chain Kernel clients for account abstraction transactions. | +| `walletClients` | `Map` | Per-chain Viem wallet clients used internally by the connector. | +| `isExpiring` | `boolean` | Whether the session is near expiry. | + +## Related guides + +- [Quickstart](/wallets/quickstart) +- [Passkeys](/wallets/auth/passkeys) +- [Email OTP](/wallets/auth/email-otp) +- [Magic Link](/wallets/auth/magic-link) +- [Google OAuth](/wallets/auth/google-oauth) +- [Session Management](/wallets/session-management) +- [Send a Transaction](/wallets/wallet-api/send-transaction) +- [Export Wallet](/wallets/export) diff --git a/docs/pages/wallets/session-management.mdx b/docs/pages/wallets/session-management.mdx index 0787da8e..111056bd 100644 --- a/docs/pages/wallets/session-management.mdx +++ b/docs/pages/wallets/session-management.mdx @@ -1,97 +1,115 @@ -# Session Management [Understand and control the session lifecycle] +# Session Management [Control authenticated wallet sessions] -The ZeroDev Wallet SDK manages sessions automatically. Sessions are created during authentication and persist across page reloads. +The Wallet SDK creates a session after any successful authentication flow: passkey, email OTP, magic link, or Google OAuth. The session lets the SDK reconnect the ZeroDev Wagmi connector across reloads and sign wallet actions without asking the user to log in again each time. + +For most apps, the defaults are enough. ## Session lifecycle +```txt +Authenticate -> session created -> reconnect on reload -> refresh before expiry -> re-authenticate if expired ``` -Authenticate → Session Created → Auto-refresh → Expiry → Re-authenticate -``` -1. **Created**: A session is created when the user authenticates (passkey, OTP, OAuth, or magic link). The session contains a credential that allows the SDK to sign transactions. +The connector checks for an existing session when your app loads. If the session is valid, Wagmi reconnects and `useAccount` returns the wallet address. + +## Configure session behavior -2. **Persisted**: Sessions are stored in `localStorage` by default (configurable via `sessionStorage` connector option). On page reload, the connector checks for an existing session and reconnects automatically. +Session behavior is configured on the ZeroDev connector. + +```tsx +import { zeroDevWallet } from '@zerodev/wallet-react' +import { arbitrumSepolia } from 'wagmi/chains' -3. **Auto-refresh**: When `autoRefreshSession` is enabled (default), the SDK refreshes the session before it expires. The refresh happens `sessionWarningThreshold` milliseconds before expiry (default: 60 seconds). +const projectId = '' +const aaUrl = '' + +zeroDevWallet({ + projectId, + aaUrl, + chains: [arbitrumSepolia], + autoRefreshSession: true, + sessionWarningThreshold: 120_000, +}) +``` -4. **Expiry**: If a session expires without being refreshed, the Wagmi connector disconnects and the user needs to re-authenticate. +- `autoRefreshSession` refreshes the session before it expires. The default is `true`. +- `sessionWarningThreshold` controls how early the SDK refreshes the session before expiry. -## Refreshing sessions +Set `autoRefreshSession: false` only if you want to handle expiry yourself. -Use the [`useRefreshSession`](/wallets/hooks/use-refresh-session) hook to manually refresh the current session: +## Refresh a session manually + +Use `useRefreshSession` if your app wants an explicit refresh action. ```tsx import { useRefreshSession } from '@zerodev/wallet-react' -function SessionControls() { +export function RefreshSessionButton() { const refreshSession = useRefreshSession() return ( ) } ``` -## Auto-refresh configuration +## Detect disconnected sessions -Configure auto-refresh via the connector options: +When a session expires and cannot be refreshed, the connector disconnects. Use Wagmi's `useAccount` hook to update your UI. ```tsx -zeroDevWallet({ - projectId: 'YOUR_PROJECT_ID', - chains: [sepolia], - autoRefreshSession: true, // default: true - sessionWarningThreshold: 120_000, // refresh 2 minutes before expiry -}) -``` - -Set `autoRefreshSession: false` to disable auto-refresh and handle session expiry manually. +import { useAccount } from 'wagmi' -## Custom storage +export function SessionStatus() { + const { address, status } = useAccount() -By default, sessions are stored in `localStorage`. Provide a custom `StorageAdapter` for alternative storage: + if (status === 'connected') { + return

Connected: {address}

+ } -```tsx -import { type StorageAdapter } from '@zerodev/wallet-core' + if (status === 'reconnecting') { + return

Reconnecting...

+ } -const customStorage: StorageAdapter = { - getItem: async (key: string) => { /* ... */ }, - setItem: async (key: string, value: string) => { /* ... */ }, - removeItem: async (key: string) => { /* ... */ }, + return

Signed out

} - -zeroDevWallet({ - projectId: 'YOUR_PROJECT_ID', - chains: [sepolia], - sessionStorage: customStorage, -}) ``` -This is useful for React Native apps where `localStorage` is not available. +## Use custom storage -## Detecting session expiry - -When a session expires, the Wagmi connector disconnects. You can detect this using the Wagmi `useAccount` hook: +On the web, sessions use browser storage by default. Provide a custom storage adapter if your environment needs something else. ```tsx -import { useAccount } from 'wagmi' - -function SessionStatus() { - const { status, isConnected } = useAccount() - - if (status === 'disconnected') { - return

Session expired — please sign in again

- } +import type { StorageAdapter } from '@zerodev/wallet-core' +import { arbitrumSepolia } from 'wagmi/chains' - if (isConnected) { - return

Connected

- } +const projectId = '' +const aaUrl = '' - return null +const sessionStorageAdapter: StorageAdapter = { + getItem: async (key) => window.sessionStorage.getItem(key), + setItem: async (key, value) => window.sessionStorage.setItem(key, value), + removeItem: async (key) => window.sessionStorage.removeItem(key), } + +zeroDevWallet({ + projectId, + aaUrl, + chains: [arbitrumSepolia], + sessionStorage: sessionStorageAdapter, +}) ``` + +Custom storage is also required in environments that do not provide browser `localStorage`, such as React Native. + +## Next steps + +- [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), [Magic Link](/wallets/auth/magic-link), or [Google OAuth](/wallets/auth/google-oauth) diff --git a/vocs.config.tsx b/vocs.config.tsx index 21394992..b3abf920 100644 --- a/vocs.config.tsx +++ b/vocs.config.tsx @@ -479,20 +479,10 @@ export default defineConfig({ text: "Google OAuth", link: "/wallets/auth/google-oauth", }, - ], - }, - { - text: "Features", - collapsed: true, - items: [ { text: "Session Management", link: "/wallets/session-management", }, - { - text: "Export Wallet", - link: "/wallets/export", - }, ], }, { @@ -511,58 +501,20 @@ export default defineConfig({ text: "Sign a Typed Message", link: "/wallets/wallet-api/sign-typed-message", }, - ], - }, - { - text: "Hooks", - collapsed: true, - items: [ - { - text: "useRegisterPasskey", - link: "/wallets/hooks/use-register-passkey", - }, - { - text: "useLoginPasskey", - link: "/wallets/hooks/use-login-passkey", - }, - { - text: "useAuthenticateOAuth", - link: "/wallets/hooks/use-authenticate-oauth", - }, { - text: "useSendOTP", - link: "/wallets/hooks/use-send-otp", - }, - { - text: "useVerifyOTP", - link: "/wallets/hooks/use-verify-otp", - }, - { - text: "useSendMagicLink", - link: "/wallets/hooks/use-send-magic-link", - }, - { - text: "useVerifyMagicLink", - link: "/wallets/hooks/use-verify-magic-link", - }, - { - text: "useGetUserEmail", - link: "/wallets/hooks/use-get-user-email", - }, - { - text: "useRefreshSession", - link: "/wallets/hooks/use-refresh-session", - }, - { - text: "useExportWallet", - link: "/wallets/hooks/use-export-wallet", - }, - { - text: "useExportPrivateKey", - link: "/wallets/hooks/use-export-private-key", + text: "Export Wallet", + link: "/wallets/export", }, ], }, + { + text: "Wallet UI Kit", + link: "/wallets/auth/wallet-ui-kit", + }, + { + text: "SDK Reference", + link: "/wallets/sdk-reference", + }, ], }, ], From 6fddc46f46a00ad0e32c720e964133becc2b114a Mon Sep 17 00:00:00 2001 From: srinjoyc Date: Wed, 1 Jul 2026 17:26:13 -0700 Subject: [PATCH 03/25] Verify wallet docs snippets --- docs/pages/wallets/auth/magic-link.mdx | 11 ++--- docs/pages/wallets/auth/wallet-ui-kit.mdx | 43 ++++++++++++++++--- .../wallets/hooks/use-send-magic-link.mdx | 28 ++++++------ .../wallets/hooks/use-verify-magic-link.mdx | 15 +++++-- docs/pages/wallets/sdk-reference.mdx | 2 - .../wallets/wallet-api/send-transaction.mdx | 17 +++++--- .../wallets/wallet-api/sign-typed-message.mdx | 3 +- 7 files changed, 80 insertions(+), 39 deletions(-) diff --git a/docs/pages/wallets/auth/magic-link.mdx b/docs/pages/wallets/auth/magic-link.mdx index 672e5f4c..3d221dbb 100644 --- a/docs/pages/wallets/auth/magic-link.mdx +++ b/docs/pages/wallets/auth/magic-link.mdx @@ -6,13 +6,13 @@ Use magic links when you want email login without asking the user to copy a code ## Configure your redirect URL -Magic links need a route in your app that can receive the redirect and call `useVerifyMagicLink`. For local development, this might be: +Magic links need a route in your app that can receive the redirect and call `useVerifyMagicLink`. Configure the magic-link URL template for your project in the ZeroDev dashboard. For local development, this might be: ```txt http://localhost:3000/verify ``` -Make sure the redirect origin is also added to the project's ACL allowlist in the ZeroDev dashboard. If your project uses custom email templates or custom link behavior, configure those settings in the dashboard before testing magic links. +Make sure the redirect origin is also added to the project's ACL allowlist in the ZeroDev dashboard. ## Send the magic link @@ -40,10 +40,7 @@ export function MagicLinkLogin() { type="button" disabled={sendMagicLink.isPending || !email} onClick={async () => { - const result = await sendMagicLink.mutateAsync({ - email, - redirectURL: `${window.location.origin}/verify`, - }) + const result = await sendMagicLink.mutateAsync({ email }) sessionStorage.setItem('zerodevMagicLinkOtpId', result.otpId) sessionStorage.setItem( @@ -116,7 +113,7 @@ export function VerifyMagicLink() { ## How it works -1. `useSendMagicLink` sends an email with a link to your `redirectURL` and returns an `otpId` plus an `otpEncryptionTargetBundle`. +1. `useSendMagicLink` sends an email with the configured magic link and returns an `otpId` plus an `otpEncryptionTargetBundle`. 2. The user clicks the link and lands back in your app with a `code` query parameter. 3. `useVerifyMagicLink` verifies the `otpId`, `otpEncryptionTargetBundle`, and `code`. 4. After verification succeeds, the SDK creates a session and connects the ZeroDev Wagmi connector. diff --git a/docs/pages/wallets/auth/wallet-ui-kit.mdx b/docs/pages/wallets/auth/wallet-ui-kit.mdx index 5edcfcae..8cea48f4 100644 --- a/docs/pages/wallets/auth/wallet-ui-kit.mdx +++ b/docs/pages/wallets/auth/wallet-ui-kit.mdx @@ -136,7 +136,15 @@ export function WalletLogin() { function AuthPanel() { return ( -
+
) @@ -145,10 +153,18 @@ function AuthPanel() { ## Size the container -`AuthFlow` renders into the width you give it. Put it in a constrained container, modal, or drawer instead of letting it stretch across the full page on large screens. +`AuthFlow` is designed to render as a wallet-sized panel. Put it in a constrained container, modal, or drawer instead of letting it stretch across the full page on large screens. ```tsx -
+
setLoginOpen(false)} />
``` @@ -165,13 +181,26 @@ import { AuthFlow, SignatureRequest } from '@zerodev/wallet-react-kit' export function WalletOverlays() { return ( <> -
+
-
- -
+ ) } diff --git a/docs/pages/wallets/hooks/use-send-magic-link.mdx b/docs/pages/wallets/hooks/use-send-magic-link.mdx index cab783bf..199161e8 100644 --- a/docs/pages/wallets/hooks/use-send-magic-link.mdx +++ b/docs/pages/wallets/hooks/use-send-magic-link.mdx @@ -28,12 +28,12 @@ function SendMagicLink() { /> ; -``` - -### `useLoginPasskey(options?)` - -Authenticates with an existing passkey. On success, it stores the session, derives the wallet account, and connects the ZeroDev connector in Wagmi. - -#### Mutation variables - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `connector` | `Connector` | No | ZeroDev Wagmi connector override. | - -#### Returns - -`UseMutationResult` - -```tsx -const loginPasskey = useLoginPasskey(); - -; -``` - -## Email OTP - -### `useSendOTP(options?)` - -Sends an email OTP code. - -#### Mutation variables - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `email` | `string` | Yes | User email address. | -| `emailCustomization` | `{ magicLinkTemplate?: string }` | No | Optional email template customization. | -| `connector` | `Connector` | No | ZeroDev Wagmi connector override. | - -#### Returns - -`UseMutationResult<{ otpId: string; otpEncryptionTargetBundle: string }, Error, SendOTPVariables>` - -Store both returned values. `useVerifyOTP` needs the matching `otpId` and `otpEncryptionTargetBundle`. - -```tsx -const sendOTP = useSendOTP(); -const verifyOTP = useVerifyOTP(); - -const sent = await sendOTP.mutateAsync({ email }); - -await verifyOTP.mutateAsync({ - otpId: sent.otpId, - otpEncryptionTargetBundle: sent.otpEncryptionTargetBundle, - code, -}); -``` - -### `useVerifyOTP(options?)` - -Verifies an OTP code and authenticates the user. On success, it stores the session, derives the wallet account, and connects the ZeroDev connector in Wagmi. - -#### Mutation variables - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `otpId` | `string` | Yes | OTP ID returned by `useSendOTP`. | -| `otpEncryptionTargetBundle` | `string` | Yes | Encryption target bundle returned by the matching `useSendOTP` call. | -| `code` | `string` | Yes | Code entered by the user. | -| `connector` | `Connector` | No | ZeroDev Wagmi connector override. | - -#### Returns - -`UseMutationResult` - -## Magic links - -### `useSendMagicLink(options?)` - -Sends a magic link email. - -#### Mutation variables - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `email` | `string` | Yes | User email address. | -| `connector` | `Connector` | No | ZeroDev Wagmi connector override. | - -#### Returns - -`UseMutationResult<{ otpId: string; otpEncryptionTargetBundle: string }, Error, SendMagicLinkVariables>` - -Store both returned values. `useVerifyMagicLink` needs the matching `otpId` and `otpEncryptionTargetBundle`. - -```tsx -const sendMagicLink = useSendMagicLink(); - -const sent = await sendMagicLink.mutateAsync({ - email, -}); -``` - -### `useVerifyMagicLink(options?)` - -Verifies the magic link code and authenticates the user. - -#### Mutation variables - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `otpId` | `string` | Yes | OTP ID returned by `useSendMagicLink`. | -| `otpEncryptionTargetBundle` | `string` | Yes | Encryption target bundle returned by the matching `useSendMagicLink` call. | -| `code` | `string` | Yes | Code from the magic link redirect. | -| `connector` | `Connector` | No | ZeroDev Wagmi connector override. | - -#### Returns - -`UseMutationResult` - -## OAuth - -### `useAuthenticateOAuth(options?)` - -Starts the web OAuth flow using a popup and authenticates the user after the popup returns a session ID. The web hook uses `window.location.href` as the redirect URI and `window.location.origin` for popup polling. - -#### Options - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `timeoutMs` | `number` | No | Popup polling timeout in milliseconds. Defaults to 5 minutes. | -| `config` | `Config` | No | Optional Wagmi config override. | -| `mutation` | `UseMutationOptions` | No | TanStack mutation options. | - -#### Mutation variables - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `provider` | `OAuthProvider` | Yes | OAuth provider. Use `OAUTH_PROVIDERS.GOOGLE` for Google. | - -#### Returns - -`UseMutationResult` - -```tsx -const google = useAuthenticateOAuth(); - -; -``` - -### `OAUTH_PROVIDERS` - -Supported OAuth provider constants. - -| Name | Value | -| --- | --- | -| `OAUTH_PROVIDERS.GOOGLE` | `"google"` | - -### `OAuthProvider` - -Type union of supported OAuth provider values. Currently `"google"`. - -### `GetOAuthSessionIdFn` - -Function type for custom OAuth adapters. - -```ts -type GetOAuthSessionIdFn = (params: { - oauthUrl: string; - provider: OAuthProvider; -}) => Promise; -``` - -The web hook supplies this automatically. Custom platform flows use this shape to open the OAuth URL and return a session ID. - -## Sessions - -### `useRefreshSession(options?)` - -Refreshes the current authenticated session and updates connector state. - -#### Mutation variables - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `connector` | `Connector` | No | ZeroDev Wagmi connector override. | - -#### Returns - -`UseMutationResult` - -Throws when there is no active session to refresh. - -```tsx -const refreshSession = useRefreshSession(); - -await refreshSession.mutateAsync({}); -``` - -## Authenticators - -### `useAuthenticators(options?)` - -Reads authenticators associated with the current user in the connected project/sub-organization. The result can include OAuth authenticators, passkeys, email contacts, and API keys. - -#### Options - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `config` | `Config` | No | Optional Wagmi config override. | -| `query` | `UseQueryOptions` | No | TanStack query options, excluding `queryKey` and `queryFn`. | - -#### Returns - -`UseQueryResult` - -```tsx -const authenticators = useAuthenticators({ - query: { enabled: isConnected }, -}); -``` - -## Wallet export - -### `useExportWallet(options?)` - -Renders the secure Turnkey export iframe into a container element and injects the wallet export bundle. - -#### Mutation variables - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `iframeContainerId` | `string` | Yes | DOM element ID where the export iframe should be mounted. | -| `iframeStyles` | `Record` | No | CSS styles passed to the iframe stamper. | -| `connector` | `Connector` | No | ZeroDev Wagmi connector override. | - -#### Returns - -`UseMutationResult` - -```tsx -const exportWallet = useExportWallet(); - -await exportWallet.mutateAsync({ - iframeContainerId: "export-wallet", - iframeStyles: { - width: "100%", - height: "260px", - }, -}); -``` - -### `useExportPrivateKey(options?)` - -Renders the secure Turnkey export iframe into a container element and injects a private key export bundle. - -#### Mutation variables - -| Name | Type | Required | Description | -| --- | --- | --- | --- | -| `iframeContainerId` | `string` | Yes | DOM element ID where the export iframe should be mounted. | -| `iframeStyles` | `Record` | No | CSS styles passed to the iframe stamper. | -| `address` | `string` | No | Specific wallet address/key to export. | -| `keyFormat` | `"Hexadecimal" \| "Solana"` | No | Export format. Defaults to `"Hexadecimal"`. | -| `connector` | `Connector` | No | ZeroDev Wagmi connector override. | - -#### Returns - -`UseMutationResult` - -```tsx -const exportPrivateKey = useExportPrivateKey(); - -await exportPrivateKey.mutateAsync({ - iframeContainerId: "export-private-key", - keyFormat: "Hexadecimal", -}); -``` - -## Store and connector helpers - -These helpers are lower-level escape hatches. Most apps should use Wagmi hooks and ZeroDev auth hooks instead. - -### `getZeroDevConnector(config)` - -Finds the ZeroDev connector in a Wagmi config. - -| Parameter | Type | Description | -| --- | --- | --- | -| `config` | `Config` | Wagmi config containing a `zerodev-wallet` connector. | - -Returns the ZeroDev connector, including `rpId` and `getStore()`. Throws if the connector is not found. - -### `getZeroDevStore(connector)` - -Gets the Zustand store associated with a ZeroDev connector. - -| Parameter | Type | Description | -| --- | --- | --- | -| `connector` | `Connector` | ZeroDev connector returned by `zeroDevWallet`. | - -Returns `Promise>`. - -### `getZeroDevWallet(store)` - -Reads the initialized wallet SDK instance from the ZeroDev store. - -| Parameter | Type | Description | -| --- | --- | --- | -| `store` | `ReturnType` | ZeroDev wallet store. | - -Returns `ZeroDevWalletSDK`. Throws `"Wallet not initialized"` if connector setup has not completed. - -### `createZeroDevWalletStore(options?)` - -Creates the internal Zustand store used by the connector. - -| Parameter | Type | Description | -| --- | --- | --- | -| `options.storage` | `StateStorage` | Optional custom persistence storage. | - -The store persists only `session` and `activeChainId` under the `zerodev-wallet` key. - -## OAuth utilities - -### `generateOAuthNonce(publicKey)` - -Computes the nonce expected in a Google OAuth URL for a wallet public key. - -| Parameter | Type | Description | -| --- | --- | --- | -| `publicKey` | `string` | Wallet public key, with or without `0x` prefix. | - -Returns a lowercase hex SHA-256 hash string without `0x`. - -### `verifyGoogleLoginUrl(loginUrl, publicKey)` - -Verifies that a Google OAuth URL is valid for the wallet public key. - -| Parameter | Type | Description | -| --- | --- | --- | -| `loginUrl` | `string` | OAuth URL returned by the backend. | -| `publicKey` | `string` | Wallet public key used to verify the nonce. | - -Returns `void`. Throws if the URL is malformed, the host is not `accounts.google.com`, the nonce is missing, or the nonce does not match `generateOAuthNonce(publicKey)`. - -## Types - -### `WalletMode` - -```ts -type WalletMode = "4337" | "7702"; -``` - -### `ZeroDevWalletConnectorParams` - -Connector parameter type for `zeroDevWallet`. It matches the connector parameters above. - -### `ZeroDevProvider` - -ZeroDev EIP-1193 provider type returned by the connector's `getProvider()` method. - -### `ZeroDevWalletState` - -Zustand store state type used internally by the connector. - -Important fields include: - -| Field | Type | Description | -| --- | --- | --- | -| `wallet` | `ZeroDevWalletSDK \| null` | Core wallet SDK instance. | -| `session` | `ZeroDevWalletSession \| null` | Active wallet session. | -| `activeChainId` | `number \| null` | Active chain ID. | -| `kernelAccounts` | `Map` | Per-chain Kernel accounts for `7702` and `4337` modes. | -| `kernelClients` | `Map` | Per-chain Kernel clients for account abstraction transactions. | -| `walletClients` | `Map` | Per-chain Viem wallet clients used internally by the connector. | -| `isExpiring` | `boolean` | Whether the session is near expiry. | - -## Related guides - -- [Quickstart](/wallets/quickstart) -- [Passkeys](/wallets/auth/passkeys) -- [Email OTP](/wallets/auth/email-otp) -- [Magic Link](/wallets/auth/magic-link) -- [Google OAuth](/wallets/auth/google-oauth) -- [Session Management](/wallets/session-management) -- [Send a Transaction](/wallets/wallet-api/send-transaction) -- [Export Wallet](/wallets/export) diff --git a/vocs.config.tsx b/vocs.config.tsx index b3abf920..61c53311 100644 --- a/vocs.config.tsx +++ b/vocs.config.tsx @@ -511,10 +511,6 @@ export default defineConfig({ text: "Wallet UI Kit", link: "/wallets/auth/wallet-ui-kit", }, - { - text: "SDK Reference", - link: "/wallets/sdk-reference", - }, ], }, ], From ef5bb94d74276c73321d822a991a35144ab524cc Mon Sep 17 00:00:00 2001 From: srinjoyc Date: Thu, 2 Jul 2026 05:40:13 -0700 Subject: [PATCH 06/25] docs(wallets): revise Wallet UI Kit intro Drop the subtitle, frame the kit as drop-in UI for faster time to market with flexible adoption, note upcoming screens (transaction confirmation, portfolio, history, balances), and inline the custom-UI auth links. Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/pages/wallets/auth/wallet-ui-kit.mdx | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/docs/pages/wallets/auth/wallet-ui-kit.mdx b/docs/pages/wallets/auth/wallet-ui-kit.mdx index 8cea48f4..42f14ad9 100644 --- a/docs/pages/wallets/auth/wallet-ui-kit.mdx +++ b/docs/pages/wallets/auth/wallet-ui-kit.mdx @@ -1,13 +1,12 @@ -# Wallet UI Kit [Optional prebuilt login UI] +# Wallet UI Kit -Use the Wallet UI Kit when you want a prebuilt login flow instead of building your own forms with the authentication hooks. The kit still uses a Wagmi-compatible ZeroDev connector, so after the user signs in you can use standard Wagmi hooks such as `useAccount`, `useSignMessage`, and `useSendTransaction`. +The Wallet UI Kit gives you prebuilt, drop-in UI that helps you get started and get to market faster. Right now it covers login: use it when you want a ready-made authentication flow instead of building your own forms with the authentication hooks. The kit uses a Wagmi-compatible ZeroDev connector, so after the user signs in you can use standard Wagmi hooks such as `useAccount`, `useSignMessage`, and `useSendTransaction`. -For a fully custom UI, use the hook-based authentication pages instead: +It's all your choice: use every component, use just a few, customize the state and flows, or replace them with your own UI over time. -- [Passkeys](/wallets/auth/passkeys) -- [Email OTP](/wallets/auth/email-otp) -- [Magic Link](/wallets/auth/magic-link) -- [Google OAuth](/wallets/auth/google-oauth) +More UI is on the way — a transaction confirmation screen is in progress, with data-driven components for portfolio management, transaction history, chain-abstracted balances, and more to follow. + +For a fully custom UI, use the hook-based authentication pages instead: [Passkeys](/wallets/auth/passkeys), [Email OTP](/wallets/auth/email-otp), [Magic Link](/wallets/auth/magic-link), or [Google OAuth](/wallets/auth/google-oauth). ## Install packages From 902e04a3bb517a0a300bcc1ece47b1ca528d5302 Mon Sep 17 00:00:00 2001 From: srinjoyc Date: Thu, 2 Jul 2026 05:57:03 -0700 Subject: [PATCH 07/25] Refine wallet docs tone and examples --- docs/pages/wallets/auth/magic-link.mdx | 2 +- docs/pages/wallets/auth/wallet-ui-kit.mdx | 54 ++++++++++++--- docs/pages/wallets/index.mdx | 16 ++--- docs/pages/wallets/quickstart.mdx | 16 ++--- .../wallets/wallet-api/send-transaction.mdx | 67 +++++++++++-------- .../pages/wallets/wallet-api/sign-message.mdx | 26 ++++--- .../wallets/wallet-api/sign-typed-message.mdx | 56 +++++++++------- 7 files changed, 146 insertions(+), 91 deletions(-) diff --git a/docs/pages/wallets/auth/magic-link.mdx b/docs/pages/wallets/auth/magic-link.mdx index 3d221dbb..caad1336 100644 --- a/docs/pages/wallets/auth/magic-link.mdx +++ b/docs/pages/wallets/auth/magic-link.mdx @@ -4,7 +4,7 @@ Magic links let users sign in by clicking a link in their email. The link return Use magic links when you want email login without asking the user to copy a code. -## Configure your redirect URL +## Configure the magic-link URL Magic links need a route in your app that can receive the redirect and call `useVerifyMagicLink`. Configure the magic-link URL template for your project in the ZeroDev dashboard. For local development, this might be: diff --git a/docs/pages/wallets/auth/wallet-ui-kit.mdx b/docs/pages/wallets/auth/wallet-ui-kit.mdx index 42f14ad9..f2cf3095 100644 --- a/docs/pages/wallets/auth/wallet-ui-kit.mdx +++ b/docs/pages/wallets/auth/wallet-ui-kit.mdx @@ -1,13 +1,23 @@ # Wallet UI Kit -The Wallet UI Kit gives you prebuilt, drop-in UI that helps you get started and get to market faster. Right now it covers login: use it when you want a ready-made authentication flow instead of building your own forms with the authentication hooks. The kit uses a Wagmi-compatible ZeroDev connector, so after the user signs in you can use standard Wagmi hooks such as `useAccount`, `useSignMessage`, and `useSendTransaction`. +The Wallet UI Kit gives you prebuilt React UI for ZeroDev Wallet. Use it when you want to get started faster with a ready-made login flow instead of building every authentication screen yourself. -It's all your choice: use every component, use just a few, customize the state and flows, or replace them with your own UI over time. +The kit uses a Wagmi-compatible ZeroDev connector, so after the user signs in you can use standard Wagmi hooks such as `useAccount`, `useSignMessage`, and `useSendTransaction`. -More UI is on the way — a transaction confirmation screen is in progress, with data-driven components for portfolio management, transaction history, chain-abstracted balances, and more to follow. +The current kit covers login and an experimental confirmation screen for signature signing and transaction confirmations that is currently in beta. This confirmation UI will improve over time. More wallet UI components are coming, including onramps, asset management and portfolio views, transaction history, and chain-abstracted balances. For a fully custom UI, use the hook-based authentication pages instead: [Passkeys](/wallets/auth/passkeys), [Email OTP](/wallets/auth/email-otp), [Magic Link](/wallets/auth/magic-link), or [Google OAuth](/wallets/auth/google-oauth). +## Before you start + +In the [ZeroDev Dashboard](https://dashboard.zerodev.app/), make sure your project has: + +- The app origin added to the project's ACL allowlist, such as `http://localhost:3000` for local development. +- The auth methods you plan to show in the UI Kit configured for the project. +- At least one enabled network and its Bundler RPC URL. + +This guide uses Arbitrum Sepolia and email OTP. Replace the chain, RPC URLs, and enabled auth methods for your app. + ## Install packages :::code-group @@ -65,7 +75,7 @@ export const config = createConfig({ }) ``` -Only enable authentication methods that are configured for your project. This example uses OTP for email authentication. +Only include auth methods that are enabled for your project. This example uses OTP for email authentication; use the hook-based [Magic Link](/wallets/auth/magic-link) guide if you want to build a magic-link flow yourself. ## Add providers and styles @@ -93,7 +103,7 @@ export function WalletProviders({ children }: { children: ReactNode }) { ## Render the login flow -Call Wagmi's `connect` with the ZeroDev connector to start login. Render `` in the same provider tree; it displays the active auth screen while the connector is waiting for the user to finish authentication. +Call Wagmi's `connect` with the ZeroDev connector to start login. Render `` in the same provider tree; it displays the active auth screen while the connector waits for the user to finish authentication. ```tsx import { AuthFlow } from '@zerodev/wallet-react-kit' @@ -152,7 +162,7 @@ function AuthPanel() { ## Size the container -`AuthFlow` is designed to render as a wallet-sized panel. Put it in a constrained container, modal, or drawer instead of letting it stretch across the full page on large screens. +`AuthFlow` renders into the space you give it. Put it in a constrained wallet-sized container, modal, or drawer instead of letting it stretch across the full page on large screens. ```tsx
{ - if (!isConnected || !isAddress(to)) return; + if (!isConnected || !isAddress(to)) return sendTransaction({ to, value: parseEther(amount), - }); - }; + }) + } return (

From: {address}

setTo(e.target.value)} /> setAmount(e.target.value)} /> - - {data &&

Tx hash: {data}

} + {data ?

Transaction hash: {data}

: null} + {error ?

Transaction failed: {error.message}

: null}
- ); + ) } ``` ## `useWriteContract` ```tsx -import { useWriteContract } from "wagmi"; -import { parseAbi } from "viem"; +import { parseAbi } from 'viem' +import { useWriteContract } from 'wagmi' const NFT_ABI = parseAbi([ - "function mint(address _to) public", -]); + 'function mint(address _to) public', +]) export function MintNftGasless({ contractAddress, recipient, }: { - contractAddress: `0x${string}`; - recipient: `0x${string}`; + contractAddress: `0x${string}` + recipient: `0x${string}` }) { - const { writeContract, data, isPending, error } = useWriteContract(); + const { writeContract, data, isPending, error } = useWriteContract() const mint = () => writeContract({ address: contractAddress, abi: NFT_ABI, - functionName: "mint", + functionName: 'mint', args: [recipient], - }); + }) return (
- - {data &&

Tx hash: {data}

} - {error &&

Mint failed: {error.message}

} + {data ?

Transaction hash: {data}

: null} + {error ?

Mint failed: {error.message}

: null}
- ); + ) } ``` + +## Next steps + +- [Sign a message](/wallets/wallet-api/sign-message) +- [Sign typed data](/wallets/wallet-api/sign-typed-message) +- [Session management](/wallets/session-management) diff --git a/docs/pages/wallets/wallet-api/sign-message.mdx b/docs/pages/wallets/wallet-api/sign-message.mdx index c369f800..9fe0baec 100644 --- a/docs/pages/wallets/wallet-api/sign-message.mdx +++ b/docs/pages/wallets/wallet-api/sign-message.mdx @@ -1,27 +1,33 @@ # Sign a Message [Sign messages with Wagmi hooks] -To sign a message, use Wagmi's `useSignMessage` hook: +Use Wagmi's `useSignMessage` hook to ask the connected ZeroDev wallet to sign an offchain message. Message signing does not submit a transaction and does not require gas. ```tsx -import { useSignMessage } from "wagmi"; +import { useSignMessage } from 'wagmi' export function SignMessage() { - const { signMessage, data, isPending, error } = useSignMessage(); + const { signMessage, data, isPending, error } = useSignMessage() const handleSign = () => signMessage({ - message: "Hello from ZeroDev Wallet", - }); + message: 'Hello from ZeroDev Wallet', + }) return (
- - {data &&

Signature: {data}

} - {error &&

Signing failed: {error.message}

} + {data ?

Signature: {data}

: null} + {error ?

Signing failed: {error.message}

: null}
- ); + ) } ``` + +## Next steps + +- [Send a transaction](/wallets/wallet-api/send-transaction) +- [Sign typed data](/wallets/wallet-api/sign-typed-message) +- [Session management](/wallets/session-management) diff --git a/docs/pages/wallets/wallet-api/sign-typed-message.mdx b/docs/pages/wallets/wallet-api/sign-typed-message.mdx index d9e719f0..ae63380e 100644 --- a/docs/pages/wallets/wallet-api/sign-typed-message.mdx +++ b/docs/pages/wallets/wallet-api/sign-typed-message.mdx @@ -1,57 +1,63 @@ # Sign a Typed Message [EIP-712 typed data signing] -EIP-712 typed data signing works through Wagmi's `useSignTypedData`. +Use Wagmi's `useSignTypedData` hook to sign EIP-712 typed data with the connected ZeroDev wallet. Typed-data signing is offchain and does not require gas. ```tsx -import { useSignTypedData } from "wagmi"; -import { arbitrumSepolia } from "wagmi/chains"; +import { useSignTypedData } from 'wagmi' +import { arbitrumSepolia } from 'wagmi/chains' const typedData = { domain: { - name: "Ether Mail", - version: "1", + name: 'Ether Mail', + version: '1', chainId: arbitrumSepolia.id, - verifyingContract: "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC", + verifyingContract: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC', }, types: { Person: [ - { name: "name", type: "string" }, - { name: "wallet", type: "address" }, + { name: 'name', type: 'string' }, + { name: 'wallet', type: 'address' }, ], Mail: [ - { name: "from", type: "Person" }, - { name: "to", type: "Person" }, - { name: "contents", type: "string" }, + { name: 'from', type: 'Person' }, + { name: 'to', type: 'Person' }, + { name: 'contents', type: 'string' }, ], }, - primaryType: "Mail", + primaryType: 'Mail', message: { from: { - name: "Alice", - wallet: "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826", + name: 'Alice', + wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826', }, to: { - name: "Bob", - wallet: "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB", + name: 'Bob', + wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB', }, - contents: "Hello, Bob!", + contents: 'Hello, Bob!', }, -} as const; +} as const export function SignTypedData() { - const { signTypedData, data, isPending, error } = useSignTypedData(); + const { signTypedData, data, isPending, error } = useSignTypedData() - const handleSign = () => signTypedData(typedData); + const handleSign = () => signTypedData(typedData) return (
- - {data &&

Signature: {data}

} - {error &&

Signing failed: {error.message}

} + {data ?

Signature: {data}

: null} + {error ?

Signing failed: {error.message}

: null}
- ); + ) } ``` + +## Next steps + +- [Sign a message](/wallets/wallet-api/sign-message) +- [Send a transaction](/wallets/wallet-api/send-transaction) +- [Session management](/wallets/session-management) From a4de55948ef67a47cf95d6419489b9c92549c314 Mon Sep 17 00:00:00 2001 From: srinjoyc Date: Thu, 2 Jul 2026 06:15:23 -0700 Subject: [PATCH 08/25] Update wallet docs for AA host config --- docs/pages/wallets/auth/passkeys.mdx | 3 --- docs/pages/wallets/auth/wallet-ui-kit.mdx | 7 ++----- docs/pages/wallets/quickstart.mdx | 11 ++++------- docs/pages/wallets/session-management.mdx | 4 ---- docs/pages/wallets/wallet-api/send-transaction.mdx | 2 +- 5 files changed, 7 insertions(+), 20 deletions(-) diff --git a/docs/pages/wallets/auth/passkeys.mdx b/docs/pages/wallets/auth/passkeys.mdx index 841d5fec..2de9c232 100644 --- a/docs/pages/wallets/auth/passkeys.mdx +++ b/docs/pages/wallets/auth/passkeys.mdx @@ -14,7 +14,6 @@ import { createConfig, http } from 'wagmi' import { arbitrumSepolia } from 'wagmi/chains' const projectId = '' -const aaUrl = '' const chainRpcUrl = 'https://sepolia-rollup.arbitrum.io/rpc' export const config = createConfig({ @@ -22,7 +21,6 @@ export const config = createConfig({ connectors: [ zeroDevWallet({ projectId, - aaUrl, chains: [arbitrumSepolia], mode: '7702', }), @@ -42,7 +40,6 @@ By default, the SDK uses the current hostname. Set `rpId` when you want passkeys ```tsx zeroDevWallet({ projectId, - aaUrl, chains: [arbitrumSepolia], rpId: 'example.com', }) diff --git a/docs/pages/wallets/auth/wallet-ui-kit.mdx b/docs/pages/wallets/auth/wallet-ui-kit.mdx index f2cf3095..44e5a1ca 100644 --- a/docs/pages/wallets/auth/wallet-ui-kit.mdx +++ b/docs/pages/wallets/auth/wallet-ui-kit.mdx @@ -14,9 +14,9 @@ In the [ZeroDev Dashboard](https://dashboard.zerodev.app/), make sure your proje - The app origin added to the project's ACL allowlist, such as `http://localhost:3000` for local development. - The auth methods you plan to show in the UI Kit configured for the project. -- At least one enabled network and its Bundler RPC URL. +- At least one enabled network. -This guide uses Arbitrum Sepolia and email OTP. Replace the chain, RPC URLs, and enabled auth methods for your app. +This guide uses Arbitrum Sepolia and email OTP. Replace the chain, chain RPC URL, and enabled auth methods for your app. ## Install packages @@ -50,7 +50,6 @@ import { createConfig, http } from 'wagmi' import { arbitrumSepolia } from 'wagmi/chains' const projectId = '' -const aaUrl = '' const chainRpcUrl = 'https://sepolia-rollup.arbitrum.io/rpc' export const config = createConfig({ @@ -58,7 +57,6 @@ export const config = createConfig({ connectors: [ zeroDevWallet({ projectId, - aaUrl, chains: [arbitrumSepolia], mode: '7702', config: { @@ -226,7 +224,6 @@ If you only want the prebuilt login UI, you can omit `SignatureRequest`. To forc ```tsx zeroDevWallet({ projectId, - aaUrl, chains: [arbitrumSepolia], mode: '7702', config: { diff --git a/docs/pages/wallets/quickstart.mdx b/docs/pages/wallets/quickstart.mdx index cdbbb3a1..ea8b9d27 100644 --- a/docs/pages/wallets/quickstart.mdx +++ b/docs/pages/wallets/quickstart.mdx @@ -13,7 +13,6 @@ You will need: - A ZeroDev account in the [ZeroDev Dashboard](https://dashboard.zerodev.app/). - A project with at least one enabled network. - Your project ID. -- The Bundler RPC URL for the network you want to use. - Your app origin added to the project's ACL allowlist. ## Install packages @@ -46,18 +45,16 @@ For example, if you run your app at `http://localhost:3000` during development, ## Add configuration values -In the ZeroDev dashboard, open your project and copy its project ID. Then open the network you enabled for this app and copy its Bundler RPC URL. +In the ZeroDev dashboard, open your project and copy its project ID. Make sure the network you want to use is enabled for the project. Add these values to your app's configuration. The exact environment variable prefix depends on your framework: ```bash ZERODEV_PROJECT_ID="your-project-id" -ZERODEV_AA_URL="your-chain-specific-zerodev-rpc-url" ARBITRUM_SEPOLIA_RPC_URL="https://sepolia-rollup.arbitrum.io/rpc" ``` - `ZERODEV_PROJECT_ID` is your ZeroDev project ID. -- `ZERODEV_AA_URL` is the network-specific Bundler RPC URL from the dashboard. - `ARBITRUM_SEPOLIA_RPC_URL` is the chain RPC used by Wagmi's transport. This example uses Arbitrum Sepolia. Replace the chain and RPC URLs if your project uses a different chain. @@ -72,7 +69,6 @@ import { createConfig, http } from 'wagmi' import { arbitrumSepolia } from 'wagmi/chains' const projectId = '' -const aaUrl = '' const chainRpcUrl = 'https://sepolia-rollup.arbitrum.io/rpc' export const config = createConfig({ @@ -80,7 +76,6 @@ export const config = createConfig({ connectors: [ zeroDevWallet({ projectId, - aaUrl, chains: [arbitrumSepolia], mode: '7702', }), @@ -95,6 +90,8 @@ In your app, replace the inline constants with your framework's public runtime c `7702` is the SDK default, but setting it explicitly makes the recommended mode clear. +The SDK builds the bundler and paymaster URL from your project ID and the active chain. You usually do not need to configure this URL yourself. If you are using a custom or staging ZeroDev AA host, pass only the host origin with `aaHost`, for example `https://rpc.zerodev.app`, not a full `/api/v3/.../chain/...` URL. + ## Add providers Wrap your app with Wagmi and TanStack Query providers: @@ -276,7 +273,7 @@ The examples above use `@zerodev/wallet-react` so you can build your own UI. If - **Allowlist errors**: confirm that the dashboard allowlists the exact origin you are opening in the browser. - **Sponsored transaction fails**: confirm that a gas policy exists for the project and chain. -- **Wrong chain**: make sure the chain in `createConfig`, the `aaUrl`, and the gas policy all refer to the same chain. +- **Wrong chain**: make sure the chain in `createConfig`, the enabled dashboard network, and the gas policy all refer to the same chain. ## Next steps diff --git a/docs/pages/wallets/session-management.mdx b/docs/pages/wallets/session-management.mdx index 111056bd..9d299092 100644 --- a/docs/pages/wallets/session-management.mdx +++ b/docs/pages/wallets/session-management.mdx @@ -21,11 +21,9 @@ import { zeroDevWallet } from '@zerodev/wallet-react' import { arbitrumSepolia } from 'wagmi/chains' const projectId = '' -const aaUrl = '' zeroDevWallet({ projectId, - aaUrl, chains: [arbitrumSepolia], autoRefreshSession: true, sessionWarningThreshold: 120_000, @@ -90,7 +88,6 @@ import type { StorageAdapter } from '@zerodev/wallet-core' import { arbitrumSepolia } from 'wagmi/chains' const projectId = '' -const aaUrl = '' const sessionStorageAdapter: StorageAdapter = { getItem: async (key) => window.sessionStorage.getItem(key), @@ -100,7 +97,6 @@ const sessionStorageAdapter: StorageAdapter = { zeroDevWallet({ projectId, - aaUrl, chains: [arbitrumSepolia], sessionStorage: sessionStorageAdapter, }) diff --git a/docs/pages/wallets/wallet-api/send-transaction.mdx b/docs/pages/wallets/wallet-api/send-transaction.mdx index e8ca3d77..ac107816 100644 --- a/docs/pages/wallets/wallet-api/send-transaction.mdx +++ b/docs/pages/wallets/wallet-api/send-transaction.mdx @@ -2,7 +2,7 @@ Use standard Wagmi hooks to send transactions. The ZeroDev connector turns transactions into UserOperations behind the scenes, so transactions can be sponsored when your project has a matching gas policy in the ZeroDev dashboard. -Before testing gasless transactions, make sure the chain in your Wagmi config, the ZeroDev Bundler RPC URL, and the dashboard gas policy all refer to the same network. +Before testing gasless transactions, make sure the chain in your Wagmi config, the enabled dashboard network, and the dashboard gas policy all refer to the same network. ## `useSendTransaction` From f5948fdf6c6ef2f70e7b03c06acfe3661dd5c764 Mon Sep 17 00:00:00 2001 From: Sahil Vasava Date: Thu, 2 Jul 2026 20:18:27 +0700 Subject: [PATCH 09/25] docs(wallets): replace aaUrl with aaHost (host-only, multichain-safe) --- docs/pages/wallets/auth/passkeys.mdx | 6 +++--- docs/pages/wallets/auth/wallet-ui-kit.mdx | 6 +++--- docs/pages/wallets/quickstart.mdx | 12 ++++++------ docs/pages/wallets/session-management.mdx | 8 ++++---- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/docs/pages/wallets/auth/passkeys.mdx b/docs/pages/wallets/auth/passkeys.mdx index 841d5fec..41b58c20 100644 --- a/docs/pages/wallets/auth/passkeys.mdx +++ b/docs/pages/wallets/auth/passkeys.mdx @@ -14,7 +14,7 @@ import { createConfig, http } from 'wagmi' import { arbitrumSepolia } from 'wagmi/chains' const projectId = '' -const aaUrl = '' +const aaHost = 'https://rpc.zerodev.app' const chainRpcUrl = 'https://sepolia-rollup.arbitrum.io/rpc' export const config = createConfig({ @@ -22,7 +22,7 @@ export const config = createConfig({ connectors: [ zeroDevWallet({ projectId, - aaUrl, + aaHost, chains: [arbitrumSepolia], mode: '7702', }), @@ -42,7 +42,7 @@ By default, the SDK uses the current hostname. Set `rpId` when you want passkeys ```tsx zeroDevWallet({ projectId, - aaUrl, + aaHost, chains: [arbitrumSepolia], rpId: 'example.com', }) diff --git a/docs/pages/wallets/auth/wallet-ui-kit.mdx b/docs/pages/wallets/auth/wallet-ui-kit.mdx index f2cf3095..fe320a67 100644 --- a/docs/pages/wallets/auth/wallet-ui-kit.mdx +++ b/docs/pages/wallets/auth/wallet-ui-kit.mdx @@ -50,7 +50,7 @@ import { createConfig, http } from 'wagmi' import { arbitrumSepolia } from 'wagmi/chains' const projectId = '' -const aaUrl = '' +const aaHost = 'https://rpc.zerodev.app' const chainRpcUrl = 'https://sepolia-rollup.arbitrum.io/rpc' export const config = createConfig({ @@ -58,7 +58,7 @@ export const config = createConfig({ connectors: [ zeroDevWallet({ projectId, - aaUrl, + aaHost, chains: [arbitrumSepolia], mode: '7702', config: { @@ -226,7 +226,7 @@ If you only want the prebuilt login UI, you can omit `SignatureRequest`. To forc ```tsx zeroDevWallet({ projectId, - aaUrl, + aaHost, chains: [arbitrumSepolia], mode: '7702', config: { diff --git a/docs/pages/wallets/quickstart.mdx b/docs/pages/wallets/quickstart.mdx index cdbbb3a1..74febafe 100644 --- a/docs/pages/wallets/quickstart.mdx +++ b/docs/pages/wallets/quickstart.mdx @@ -46,18 +46,18 @@ For example, if you run your app at `http://localhost:3000` during development, ## Add configuration values -In the ZeroDev dashboard, open your project and copy its project ID. Then open the network you enabled for this app and copy its Bundler RPC URL. +In the ZeroDev dashboard, open your project and copy its project ID. Make sure the network you want to use is enabled for the project. Add these values to your app's configuration. The exact environment variable prefix depends on your framework: ```bash ZERODEV_PROJECT_ID="your-project-id" -ZERODEV_AA_URL="your-chain-specific-zerodev-rpc-url" +ZERODEV_AA_HOST="https://rpc.zerodev.app" ARBITRUM_SEPOLIA_RPC_URL="https://sepolia-rollup.arbitrum.io/rpc" ``` - `ZERODEV_PROJECT_ID` is your ZeroDev project ID. -- `ZERODEV_AA_URL` is the network-specific Bundler RPC URL from the dashboard. +- `ZERODEV_AA_HOST` is the ZeroDev bundler and paymaster host. It is optional and defaults to `https://rpc.zerodev.app`; set it only when you target staging or self-hosted infrastructure. The SDK derives the per-chain URL from this host, so the same value works across every chain. - `ARBITRUM_SEPOLIA_RPC_URL` is the chain RPC used by Wagmi's transport. This example uses Arbitrum Sepolia. Replace the chain and RPC URLs if your project uses a different chain. @@ -72,7 +72,7 @@ import { createConfig, http } from 'wagmi' import { arbitrumSepolia } from 'wagmi/chains' const projectId = '' -const aaUrl = '' +const aaHost = 'https://rpc.zerodev.app' const chainRpcUrl = 'https://sepolia-rollup.arbitrum.io/rpc' export const config = createConfig({ @@ -80,7 +80,7 @@ export const config = createConfig({ connectors: [ zeroDevWallet({ projectId, - aaUrl, + aaHost, chains: [arbitrumSepolia], mode: '7702', }), @@ -276,7 +276,7 @@ The examples above use `@zerodev/wallet-react` so you can build your own UI. If - **Allowlist errors**: confirm that the dashboard allowlists the exact origin you are opening in the browser. - **Sponsored transaction fails**: confirm that a gas policy exists for the project and chain. -- **Wrong chain**: make sure the chain in `createConfig`, the `aaUrl`, and the gas policy all refer to the same chain. +- **Wrong chain**: make sure the chain in `createConfig` and the gas policy refer to the same chain, and that the chain is enabled for the project. `aaHost` is host-only, so the SDK derives the correct per-chain URL automatically. ## Next steps diff --git a/docs/pages/wallets/session-management.mdx b/docs/pages/wallets/session-management.mdx index 111056bd..1cdd7ffd 100644 --- a/docs/pages/wallets/session-management.mdx +++ b/docs/pages/wallets/session-management.mdx @@ -21,11 +21,11 @@ import { zeroDevWallet } from '@zerodev/wallet-react' import { arbitrumSepolia } from 'wagmi/chains' const projectId = '' -const aaUrl = '' +const aaHost = 'https://rpc.zerodev.app' zeroDevWallet({ projectId, - aaUrl, + aaHost, chains: [arbitrumSepolia], autoRefreshSession: true, sessionWarningThreshold: 120_000, @@ -90,7 +90,7 @@ import type { StorageAdapter } from '@zerodev/wallet-core' import { arbitrumSepolia } from 'wagmi/chains' const projectId = '' -const aaUrl = '' +const aaHost = 'https://rpc.zerodev.app' const sessionStorageAdapter: StorageAdapter = { getItem: async (key) => window.sessionStorage.getItem(key), @@ -100,7 +100,7 @@ const sessionStorageAdapter: StorageAdapter = { zeroDevWallet({ projectId, - aaUrl, + aaHost, chains: [arbitrumSepolia], sessionStorage: sessionStorageAdapter, }) From 3da4ab01021af8c5a13f75a7793b3f914d37cd81 Mon Sep 17 00:00:00 2001 From: srinjoyc Date: Thu, 2 Jul 2026 06:20:47 -0700 Subject: [PATCH 10/25] Update wallet UI package name --- docs/pages/wallets/auth/wallet-ui-kit.mdx | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/pages/wallets/auth/wallet-ui-kit.mdx b/docs/pages/wallets/auth/wallet-ui-kit.mdx index 44e5a1ca..9ed56bce 100644 --- a/docs/pages/wallets/auth/wallet-ui-kit.mdx +++ b/docs/pages/wallets/auth/wallet-ui-kit.mdx @@ -23,29 +23,29 @@ This guide uses Arbitrum Sepolia and email OTP. Replace the chain, chain RPC URL :::code-group ```bash [npm] -npm i @zerodev/wallet-react-kit @zerodev/wallet-react @zerodev/wallet-core wagmi viem @tanstack/react-query +npm i @zerodev/react-wallet-ui @zerodev/wallet-react @zerodev/wallet-core wagmi viem @tanstack/react-query ``` ```bash [yarn] -yarn add @zerodev/wallet-react-kit @zerodev/wallet-react @zerodev/wallet-core wagmi viem @tanstack/react-query +yarn add @zerodev/react-wallet-ui @zerodev/wallet-react @zerodev/wallet-core wagmi viem @tanstack/react-query ``` ```bash [pnpm] -pnpm i @zerodev/wallet-react-kit @zerodev/wallet-react @zerodev/wallet-core wagmi viem @tanstack/react-query +pnpm i @zerodev/react-wallet-ui @zerodev/wallet-react @zerodev/wallet-core wagmi viem @tanstack/react-query ``` ```bash [bun] -bun add @zerodev/wallet-react-kit @zerodev/wallet-react @zerodev/wallet-core wagmi viem @tanstack/react-query +bun add @zerodev/react-wallet-ui @zerodev/wallet-react @zerodev/wallet-core wagmi viem @tanstack/react-query ``` ::: ## Configure Wagmi -Import `zeroDevWallet` from `@zerodev/wallet-react-kit`. This connector wraps the base ZeroDev Wallet connector and controls the kit's auth UI state. +Import `zeroDevWallet` from `@zerodev/react-wallet-ui`. This connector wraps the base ZeroDev Wallet connector and controls the kit's auth UI state. ```tsx -import { zeroDevWallet } from '@zerodev/wallet-react-kit' +import { zeroDevWallet } from '@zerodev/react-wallet-ui' import { createConfig, http } from 'wagmi' import { arbitrumSepolia } from 'wagmi/chains' @@ -81,7 +81,7 @@ Import the kit stylesheet once at your app entry, then wrap your app with Wagmi ```tsx import { QueryClient, QueryClientProvider } from '@tanstack/react-query' -import '@zerodev/wallet-react-kit/styles.css' +import '@zerodev/react-wallet-ui/styles.css' import type { ReactNode } from 'react' import { WagmiProvider } from 'wagmi' import { config } from './wagmi' @@ -104,7 +104,7 @@ export function WalletProviders({ children }: { children: ReactNode }) { Call Wagmi's `connect` with the ZeroDev connector to start login. Render `` in the same provider tree; it displays the active auth screen while the connector waits for the user to finish authentication. ```tsx -import { AuthFlow } from '@zerodev/wallet-react-kit' +import { AuthFlow } from '@zerodev/react-wallet-ui' import { useAccount, useConnect, useDisconnect } from 'wagmi' export function WalletLogin() { @@ -187,7 +187,7 @@ Import the kit stylesheet once, and make sure your app's global CSS does not bro The UI Kit also includes `SignatureRequest`, an experimental confirmation screen for signature signing and transaction requests that is currently in beta. Mount it once in the same provider tree as your wallet UI. ```tsx -import { AuthFlow, SignatureRequest } from '@zerodev/wallet-react-kit' +import { AuthFlow, SignatureRequest } from '@zerodev/react-wallet-ui' export function WalletOverlays() { return ( From 666c957564477f99e679210462eba4f21de94b92 Mon Sep 17 00:00:00 2001 From: Sahil Vasava Date: Thu, 2 Jul 2026 22:47:28 +0700 Subject: [PATCH 11/25] docs(wallets): drop removed OTP customization, fix deprecated useGetUserEmail refs, align magic-link keys --- docs/pages/wallets/auth/email-otp.mdx | 2 +- docs/pages/wallets/auth/google-oauth.mdx | 2 +- docs/pages/wallets/auth/magic-link.mdx | 8 +++---- docs/pages/wallets/hooks/use-send-otp.mdx | 27 +++++++++-------------- 4 files changed, 16 insertions(+), 23 deletions(-) diff --git a/docs/pages/wallets/auth/email-otp.mdx b/docs/pages/wallets/auth/email-otp.mdx index 60cc16fb..3504cd97 100644 --- a/docs/pages/wallets/auth/email-otp.mdx +++ b/docs/pages/wallets/auth/email-otp.mdx @@ -115,7 +115,7 @@ export function EmailOTPLogin() { ## 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 through [`useGetUserEmail`](/wallets/hooks/use-get-user-email). +- The authenticated user's email and linked login methods are available through `useAuthenticators`. - If you need link-based email login instead of manual code entry, use [Magic Link](/wallets/auth/magic-link). ## Next steps diff --git a/docs/pages/wallets/auth/google-oauth.mdx b/docs/pages/wallets/auth/google-oauth.mdx index 850a47a8..06c3b6b2 100644 --- a/docs/pages/wallets/auth/google-oauth.mdx +++ b/docs/pages/wallets/auth/google-oauth.mdx @@ -76,7 +76,7 @@ After the flow completes, use `useAccount`, `useSignMessage`, and `useSendTransa - 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 through [`useGetUserEmail`](/wallets/hooks/use-get-user-email). +- The authenticated user's email and linked login methods are available through `useAuthenticators`. ## Next steps diff --git a/docs/pages/wallets/auth/magic-link.mdx b/docs/pages/wallets/auth/magic-link.mdx index caad1336..f914ddc7 100644 --- a/docs/pages/wallets/auth/magic-link.mdx +++ b/docs/pages/wallets/auth/magic-link.mdx @@ -42,9 +42,9 @@ export function MagicLinkLogin() { onClick={async () => { const result = await sendMagicLink.mutateAsync({ email }) - sessionStorage.setItem('zerodevMagicLinkOtpId', result.otpId) + sessionStorage.setItem('magicLinkOtpId', result.otpId) sessionStorage.setItem( - 'zerodevMagicLinkBundle', + 'magicLinkBundle', result.otpEncryptionTargetBundle, ) }} @@ -75,9 +75,9 @@ export function VerifyMagicLink() { useEffect(() => { const params = new URLSearchParams(window.location.search) const code = params.get('code') - const otpId = sessionStorage.getItem('zerodevMagicLinkOtpId') + const otpId = sessionStorage.getItem('magicLinkOtpId') const otpEncryptionTargetBundle = sessionStorage.getItem( - 'zerodevMagicLinkBundle', + 'magicLinkBundle', ) if ( diff --git a/docs/pages/wallets/hooks/use-send-otp.mdx b/docs/pages/wallets/hooks/use-send-otp.mdx index 1bfff47a..5192afc7 100644 --- a/docs/pages/wallets/hooks/use-send-otp.mdx +++ b/docs/pages/wallets/hooks/use-send-otp.mdx @@ -29,8 +29,7 @@ function SendCode() { + + {data?.id ?

Batch ID: {data.id}

: null} + {callsStatus.data?.status ? ( +

Status: {callsStatus.data.status}

+ ) : null} + {error ?

Batch failed: {error.message}

: null} + {callsStatus.error ?

{callsStatus.error.message}

: null} +
+ ) +} +``` + +## Notes + +- `useSendCalls` sends an EIP-5792 `wallet_sendCalls` request through the connected wallet. +- Batches can be sponsored when your project has a matching gas policy for the chain. +- In `7702` mode, the exposed wallet address stays the user's address while the batch still uses smart wallet execution. +- In `4337` mode, the batch executes through the user's Kernel smart account. +- Use `useWaitForCallsStatus` with the returned `id` to track confirmation. +- Use `BigInt(...)` instead of BigInt literals such as `0n` if your TypeScript target is lower than `ES2020`. + +## Next steps + +- [Send a transaction](/wallets/wallet-api/send-transaction) +- [Sign a message](/wallets/wallet-api/sign-message) +- [Wallet UI Kit](/wallets/auth/wallet-ui-kit) diff --git a/docs/pages/wallets/wallet-api/send-transaction.mdx b/docs/pages/wallets/wallet-api/send-transaction.mdx index ac107816..5ae49644 100644 --- a/docs/pages/wallets/wallet-api/send-transaction.mdx +++ b/docs/pages/wallets/wallet-api/send-transaction.mdx @@ -82,6 +82,7 @@ export function MintNftGasless({ ## Next steps +- [Batch transactions](/wallets/wallet-api/batch-transactions) - [Sign a message](/wallets/wallet-api/sign-message) - [Sign typed data](/wallets/wallet-api/sign-typed-message) - [Session management](/wallets/session-management) diff --git a/vocs.config.tsx b/vocs.config.tsx index 61c53311..b59f5618 100644 --- a/vocs.config.tsx +++ b/vocs.config.tsx @@ -493,6 +493,10 @@ export default defineConfig({ text: "Send a Transaction", link: "/wallets/wallet-api/send-transaction", }, + { + text: "Batch Transactions", + link: "/wallets/wallet-api/batch-transactions", + }, { text: "Sign a Message", link: "/wallets/wallet-api/sign-message", From 70fd966358684fbdff03e46a324dfcd703f99d30 Mon Sep 17 00:00:00 2001 From: srinjoyc Date: Thu, 2 Jul 2026 09:43:09 -0700 Subject: [PATCH 19/25] Clean up wallet sidebar references --- docs/pages/wallets/connector-options.mdx | 4 ---- docs/pages/wallets/hooks/export-web-view.mdx | 4 ---- ...thenticate-oauth-with-expo-web-browser.mdx | 4 ---- .../wallets/hooks/use-authenticators.mdx | 4 +++- .../wallets/react-native/configuration.mdx | 4 ---- .../react-native/domain-association.mdx | 4 ---- .../wallets/react-native/export-wallet.mdx | 4 ---- .../wallets/react-native/google-oauth.mdx | 4 ---- .../pages/wallets/react-native/magic-link.mdx | 4 ---- docs/pages/wallets/react-native/passkeys.mdx | 4 ---- .../pages/wallets/react-native/quickstart.mdx | 4 ---- docs/pages/wallets/react-native/web.mdx | 4 ---- vocs.config.tsx | 24 +++++++++---------- 13 files changed, 15 insertions(+), 57 deletions(-) diff --git a/docs/pages/wallets/connector-options.mdx b/docs/pages/wallets/connector-options.mdx index 0a42be0e..76201f9b 100644 --- a/docs/pages/wallets/connector-options.mdx +++ b/docs/pages/wallets/connector-options.mdx @@ -1,9 +1,5 @@ # Connector Options [Configure the zeroDevWallet connector] -:::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. -::: - The `zeroDevWallet` connector is configured through the options below. Only `projectId` and `chains` are required — on the web, everything else falls back to a sensible default. ```tsx diff --git a/docs/pages/wallets/hooks/export-web-view.mdx b/docs/pages/wallets/hooks/export-web-view.mdx index bfe95166..45efc1e7 100644 --- a/docs/pages/wallets/hooks/export-web-view.mdx +++ b/docs/pages/wallets/hooks/export-web-view.mdx @@ -1,9 +1,5 @@ # ZeroDevExportWebView [Component for exporting a wallet on React Native] -:::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. -::: - A React Native component that renders Turnkey's export iframe inside an isolated WebView, so the decrypted seed phrase or private key never touches your app's JavaScript. It replaces the web-only [`useExportWallet`](/wallets/hooks/use-export-wallet) and [`useExportPrivateKey`](/wallets/hooks/use-export-private-key) hooks on React Native. Mounting the component starts the export; unmounting it dismisses the secret. See [Export Wallet on React Native](/wallets/react-native/export-wallet) for the full guide. diff --git a/docs/pages/wallets/hooks/use-authenticate-oauth-with-expo-web-browser.mdx b/docs/pages/wallets/hooks/use-authenticate-oauth-with-expo-web-browser.mdx index 6314078a..75e3e9b9 100644 --- a/docs/pages/wallets/hooks/use-authenticate-oauth-with-expo-web-browser.mdx +++ b/docs/pages/wallets/hooks/use-authenticate-oauth-with-expo-web-browser.mdx @@ -2,10 +2,6 @@ import MutationResult from "../shared/mutation-result.mdx"; # useAuthenticateOAuthWithExpoWebBrowser [Hook for authenticating with an OAuth provider on React Native] -:::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. -::: - The React Native counterpart of [`useAuthenticateOAuth`](/wallets/hooks/use-authenticate-oauth). Instead of the web popup flow, it opens the system auth browser via `expo-web-browser` and completes the flow when the OAuth redirect deep-links back into the app — whichever arrives first, the browser result or the deep link. Requires the `expo-web-browser` and `expo-linking` peer dependencies. See [Google OAuth on React Native](/wallets/react-native/google-oauth) for the full setup, including the callback route and Dashboard allowlisting. diff --git a/docs/pages/wallets/hooks/use-authenticators.mdx b/docs/pages/wallets/hooks/use-authenticators.mdx index 8ba96c7d..5d7ca4b9 100644 --- a/docs/pages/wallets/hooks/use-authenticators.mdx +++ b/docs/pages/wallets/hooks/use-authenticators.mdx @@ -1,6 +1,8 @@ import QueryResult from '../shared/query-result.mdx' -# useAuthenticators [Hook for getting the authenticated user's login methods] +# Get Login Methods [Read the authenticated user's login methods] + +Use `useAuthenticators` after the wallet is connected to read the login methods linked to the current user, such as email contacts, OAuth identities, and passkeys. ## Import diff --git a/docs/pages/wallets/react-native/configuration.mdx b/docs/pages/wallets/react-native/configuration.mdx index 59a2a61a..96269eb5 100644 --- a/docs/pages/wallets/react-native/configuration.mdx +++ b/docs/pages/wallets/react-native/configuration.mdx @@ -1,9 +1,5 @@ # React Native Configuration [Stampers, storage, and connector options] -:::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. -::: - On the web, the `zeroDevWallet` connector falls back to platform defaults for key storage and session persistence. React Native has no equivalent defaults, so the storages and stampers must be configured explicitly. ## Full example diff --git a/docs/pages/wallets/react-native/domain-association.mdx b/docs/pages/wallets/react-native/domain-association.mdx index 095fac4c..e079bef5 100644 --- a/docs/pages/wallets/react-native/domain-association.mdx +++ b/docs/pages/wallets/react-native/domain-association.mdx @@ -1,9 +1,5 @@ # Domain Association [Link your app to a domain you own] -:::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. -::: - :::warning[Example setup — for development only] This guide continues from the Expo starter project set up in the [quickstart](/wallets/react-native/quickstart), and shows an example setup for development. The committed debug keystore and the throwaway Vercel deployment are not suitable for production — a production app signs with a securely managed release key (e.g. [EAS credentials](https://docs.expo.dev/app-signing/app-credentials/); with [Play App Signing](https://support.google.com/googleplay/android-developer/answer/9842756), `assetlinks.json` must list Google's app-signing certificate fingerprint, not your upload key) and serves the verification files from your real product domain. ::: diff --git a/docs/pages/wallets/react-native/export-wallet.mdx b/docs/pages/wallets/react-native/export-wallet.mdx index 5c2d69dc..2bb9d594 100644 --- a/docs/pages/wallets/react-native/export-wallet.mdx +++ b/docs/pages/wallets/react-native/export-wallet.mdx @@ -1,9 +1,5 @@ # Export Wallet on React Native [Reveal the seed phrase or private key via WebView] -:::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. -::: - The web export hooks ([`useExportWallet`](/wallets/hooks/use-export-wallet) and [`useExportPrivateKey`](/wallets/hooks/use-export-private-key)) are **not available on React Native**. Export can't go through a plain hook — the secret must never touch your JS. Use [`ZeroDevExportWebView`](/wallets/hooks/export-web-view) instead: it renders Turnkey's export iframe inside an isolated WebView, so the plaintext stays in the iframe's context. diff --git a/docs/pages/wallets/react-native/google-oauth.mdx b/docs/pages/wallets/react-native/google-oauth.mdx index 80119ec5..a51f9702 100644 --- a/docs/pages/wallets/react-native/google-oauth.mdx +++ b/docs/pages/wallets/react-native/google-oauth.mdx @@ -1,9 +1,5 @@ # Google OAuth on React Native [Native OAuth with Expo WebBrowser] -:::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. -::: - On the web, [Google OAuth](/wallets/auth/google-oauth) uses a popup. Native apps don't have popups — instead, the SDK opens the system auth browser and returns to your app via a deep link. The [`useAuthenticateOAuthWithExpoWebBrowser`](/wallets/hooks/use-authenticate-oauth-with-expo-web-browser) hook handles both ends of that round trip on both platforms: the auth session (`ASWebAuthenticationSession` on iOS, Custom Tabs on Android) intercepts the custom-scheme redirect itself, so no domain setup is needed. :::info diff --git a/docs/pages/wallets/react-native/magic-link.mdx b/docs/pages/wallets/react-native/magic-link.mdx index cac0a314..bacafcd6 100644 --- a/docs/pages/wallets/react-native/magic-link.mdx +++ b/docs/pages/wallets/react-native/magic-link.mdx @@ -1,9 +1,5 @@ # Magic Link on React Native [Sign in with a link sent by email] -:::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. -::: - The [`useSendMagicLink`](/wallets/hooks/use-send-magic-link) and [`useVerifyMagicLink`](/wallets/hooks/use-verify-magic-link) hooks work identically to [the web](/wallets/auth/magic-link) on React Native, but the redirect needs platform setup. A magic link needs a verified `https` callback — an **App Link** on Android, a **Universal Link** on iOS — so that tapping the link in the email opens the app. Email clients (e.g. Gmail) don't render custom-scheme links, so a plain `https` link on your verified domain is required. diff --git a/docs/pages/wallets/react-native/passkeys.mdx b/docs/pages/wallets/react-native/passkeys.mdx index 35e6db18..2c954858 100644 --- a/docs/pages/wallets/react-native/passkeys.mdx +++ b/docs/pages/wallets/react-native/passkeys.mdx @@ -1,9 +1,5 @@ # Passkeys on React Native [Native WebAuthn on Android & iOS] -:::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. -::: - The [`useRegisterPasskey`](/wallets/hooks/use-register-passkey) and [`useLoginPasskey`](/wallets/hooks/use-login-passkey) hooks work identically to [the web](/wallets/auth/passkeys) on React Native, but they require a native passkey stamper and some platform setup. Passkeys (WebAuthn) require the OS to verify that your app and your `rpId` domain belong together. On Android, the installed APK's signing-cert SHA-256 must match what the domain publishes in `/.well-known/assetlinks.json`; on iOS, the app's Team ID + bundle identifier must appear in the domain's `/.well-known/apple-app-site-association` and the app must carry the matching `webcredentials:` entitlement. Both are covered by the [Domain Association](/wallets/react-native/domain-association) setup. diff --git a/docs/pages/wallets/react-native/quickstart.mdx b/docs/pages/wallets/react-native/quickstart.mdx index a979e9df..59bfbf1b 100644 --- a/docs/pages/wallets/react-native/quickstart.mdx +++ b/docs/pages/wallets/react-native/quickstart.mdx @@ -1,9 +1,5 @@ # React Native Quickstart [Get an Embedded Wallet running in Expo] -:::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. -::: - ZeroDev Wallet runs on React Native. The same Wagmi-based API you use [on the web](/wallets/quickstart) works in native apps — the main difference is that on React Native the storages and stampers must be configured explicitly, since there are no platform defaults. This guide walks you through setting up the SDK in an [Expo](https://expo.dev/) app and signing in with email OTP. Once connected, sending transactions and signing messages is plain Wagmi. diff --git a/docs/pages/wallets/react-native/web.mdx b/docs/pages/wallets/react-native/web.mdx index 2bc5c7e3..8fbb3a87 100644 --- a/docs/pages/wallets/react-native/web.mdx +++ b/docs/pages/wallets/react-native/web.mdx @@ -1,9 +1,5 @@ # React Native Web [Run your Expo app on the web] -:::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. -::: - The Expo app from the [quickstart](/wallets/react-native/quickstart) also runs on the web via [`react-native-web`](https://necolas.github.io/react-native-web/). The only work is swapping a few React-Native-only integrations for web variants, then adjusting routing so the auth routes that still matter on web can mount. :::info[The web build auto-defaults everything] diff --git a/vocs.config.tsx b/vocs.config.tsx index 7b43e63f..0bc7fca2 100644 --- a/vocs.config.tsx +++ b/vocs.config.tsx @@ -475,6 +475,10 @@ export default defineConfig({ text: "Google OAuth", link: "/wallets/react-native/google-oauth", }, + { + text: "Expo OAuth API", + link: "/wallets/hooks/use-authenticate-oauth-with-expo-web-browser", + }, { text: "Domain Association", link: "/wallets/react-native/domain-association", @@ -491,6 +495,10 @@ export default defineConfig({ text: "Export Wallet", link: "/wallets/react-native/export-wallet", }, + { + text: "Export WebView API", + link: "/wallets/hooks/export-web-view", + }, { text: "React Native Web", link: "/wallets/react-native/web", @@ -517,6 +525,10 @@ export default defineConfig({ text: "Google OAuth", link: "/wallets/auth/google-oauth", }, + { + text: "Get Login Methods", + link: "/wallets/hooks/use-authenticators", + }, { text: "Session Management", link: "/wallets/session-management", @@ -543,18 +555,6 @@ export default defineConfig({ text: "Sign a Typed Message", link: "/wallets/wallet-api/sign-typed-message", }, - { - text: "useAuthenticators", - link: "/wallets/hooks/use-authenticators", - }, - { - text: "useAuthenticateOAuthWithExpoWebBrowser", - link: "/wallets/hooks/use-authenticate-oauth-with-expo-web-browser", - }, - { - text: "ZeroDevExportWebView", - link: "/wallets/hooks/export-web-view", - }, ], }, { From 46260b2ab600ad16dcb3726fd7eaefa5cb06a300 Mon Sep 17 00:00:00 2001 From: srinjoyc Date: Thu, 2 Jul 2026 09:48:29 -0700 Subject: [PATCH 20/25] Consolidate wallet signing docs --- docs/pages/wallets/auth/wallet-ui-kit.mdx | 2 +- .../wallets/wallet-api/send-transaction.mdx | 2 +- .../pages/wallets/wallet-api/sign-message.mdx | 68 ++++++++++++- .../wallets/wallet-api/sign-typed-message.mdx | 63 ------------ vocs.config.tsx | 98 +++++++++---------- 5 files changed, 114 insertions(+), 119 deletions(-) delete mode 100644 docs/pages/wallets/wallet-api/sign-typed-message.mdx diff --git a/docs/pages/wallets/auth/wallet-ui-kit.mdx b/docs/pages/wallets/auth/wallet-ui-kit.mdx index e9abc8f2..6b29c4cf 100644 --- a/docs/pages/wallets/auth/wallet-ui-kit.mdx +++ b/docs/pages/wallets/auth/wallet-ui-kit.mdx @@ -185,7 +185,7 @@ Import the kit stylesheet once. If your app has broad global element styles, sco The current Wallet UI Kit package is focused on login. After the user signs in, use the standard Wallet API pages for wallet actions: - [Sign a message](/wallets/wallet-api/sign-message) -- [Sign typed data](/wallets/wallet-api/sign-typed-message) +- [Sign messages](/wallets/wallet-api/sign-message) - [Send a transaction](/wallets/wallet-api/send-transaction) - [Batch transactions](/wallets/wallet-api/batch-transactions) diff --git a/docs/pages/wallets/wallet-api/send-transaction.mdx b/docs/pages/wallets/wallet-api/send-transaction.mdx index 5ae49644..ca23db84 100644 --- a/docs/pages/wallets/wallet-api/send-transaction.mdx +++ b/docs/pages/wallets/wallet-api/send-transaction.mdx @@ -84,5 +84,5 @@ export function MintNftGasless({ - [Batch transactions](/wallets/wallet-api/batch-transactions) - [Sign a message](/wallets/wallet-api/sign-message) -- [Sign typed data](/wallets/wallet-api/sign-typed-message) +- [Sign messages](/wallets/wallet-api/sign-message) - [Session management](/wallets/session-management) diff --git a/docs/pages/wallets/wallet-api/sign-message.mdx b/docs/pages/wallets/wallet-api/sign-message.mdx index 9fe0baec..4c9e3b2c 100644 --- a/docs/pages/wallets/wallet-api/sign-message.mdx +++ b/docs/pages/wallets/wallet-api/sign-message.mdx @@ -1,6 +1,10 @@ -# Sign a Message [Sign messages with Wagmi hooks] +# Sign Messages [Sign messages and typed data with Wagmi hooks] -Use Wagmi's `useSignMessage` hook to ask the connected ZeroDev wallet to sign an offchain message. Message signing does not submit a transaction and does not require gas. +Use Wagmi's signing hooks to ask the connected ZeroDev wallet to sign offchain data. Signing does not submit a transaction and does not require gas. + +## Sign a Message + +Use `useSignMessage` for plain text messages. ```tsx import { useSignMessage } from 'wagmi' @@ -26,8 +30,66 @@ export function SignMessage() { } ``` +## Sign Typed Data + +Use `useSignTypedData` for EIP-712 typed data. + +```tsx +import { useSignTypedData } from 'wagmi' +import { arbitrumSepolia } from 'wagmi/chains' + +const typedData = { + domain: { + name: 'Ether Mail', + version: '1', + chainId: arbitrumSepolia.id, + verifyingContract: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC', + }, + types: { + Person: [ + { name: 'name', type: 'string' }, + { name: 'wallet', type: 'address' }, + ], + Mail: [ + { name: 'from', type: 'Person' }, + { name: 'to', type: 'Person' }, + { name: 'contents', type: 'string' }, + ], + }, + primaryType: 'Mail', + message: { + from: { + name: 'Alice', + wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826', + }, + to: { + name: 'Bob', + wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB', + }, + contents: 'Hello, Bob!', + }, +} as const + +export function SignTypedData() { + const { signTypedData, data, isPending, error } = useSignTypedData() + + const handleSign = () => signTypedData(typedData) + + return ( +
+ + + {data ?

Signature: {data}

: null} + {error ?

Signing failed: {error.message}

: null} +
+ ) +} +``` + ## Next steps - [Send a transaction](/wallets/wallet-api/send-transaction) -- [Sign typed data](/wallets/wallet-api/sign-typed-message) +- [Batch transactions](/wallets/wallet-api/batch-transactions) - [Session management](/wallets/session-management) diff --git a/docs/pages/wallets/wallet-api/sign-typed-message.mdx b/docs/pages/wallets/wallet-api/sign-typed-message.mdx deleted file mode 100644 index ae63380e..00000000 --- a/docs/pages/wallets/wallet-api/sign-typed-message.mdx +++ /dev/null @@ -1,63 +0,0 @@ -# Sign a Typed Message [EIP-712 typed data signing] - -Use Wagmi's `useSignTypedData` hook to sign EIP-712 typed data with the connected ZeroDev wallet. Typed-data signing is offchain and does not require gas. - -```tsx -import { useSignTypedData } from 'wagmi' -import { arbitrumSepolia } from 'wagmi/chains' - -const typedData = { - domain: { - name: 'Ether Mail', - version: '1', - chainId: arbitrumSepolia.id, - verifyingContract: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC', - }, - types: { - Person: [ - { name: 'name', type: 'string' }, - { name: 'wallet', type: 'address' }, - ], - Mail: [ - { name: 'from', type: 'Person' }, - { name: 'to', type: 'Person' }, - { name: 'contents', type: 'string' }, - ], - }, - primaryType: 'Mail', - message: { - from: { - name: 'Alice', - wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826', - }, - to: { - name: 'Bob', - wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB', - }, - contents: 'Hello, Bob!', - }, -} as const - -export function SignTypedData() { - const { signTypedData, data, isPending, error } = useSignTypedData() - - const handleSign = () => signTypedData(typedData) - - return ( -
- - - {data ?

Signature: {data}

: null} - {error ?

Signing failed: {error.message}

: null} -
- ) -} -``` - -## Next steps - -- [Sign a message](/wallets/wallet-api/sign-message) -- [Send a transaction](/wallets/wallet-api/send-transaction) -- [Session management](/wallets/session-management) diff --git a/vocs.config.tsx b/vocs.config.tsx index 0bc7fca2..90c3ef0d 100644 --- a/vocs.config.tsx +++ b/vocs.config.tsx @@ -459,52 +459,6 @@ export default defineConfig({ text: "Demo", link: "https://zerodev-signer-demo.vercel.app/", }, - { - text: "React Native", - collapsed: true, - items: [ - { - text: "Expo Quickstart", - link: "/wallets/react-native/quickstart", - }, - { - text: "Configuration", - link: "/wallets/react-native/configuration", - }, - { - text: "Google OAuth", - link: "/wallets/react-native/google-oauth", - }, - { - text: "Expo OAuth API", - link: "/wallets/hooks/use-authenticate-oauth-with-expo-web-browser", - }, - { - text: "Domain Association", - link: "/wallets/react-native/domain-association", - }, - { - text: "Magic Link", - link: "/wallets/react-native/magic-link", - }, - { - text: "Passkeys", - link: "/wallets/react-native/passkeys", - }, - { - text: "Export Wallet", - link: "/wallets/react-native/export-wallet", - }, - { - text: "Export WebView API", - link: "/wallets/hooks/export-web-view", - }, - { - text: "React Native Web", - link: "/wallets/react-native/web", - }, - ], - }, { text: "Authentication", collapsed: true, @@ -548,19 +502,61 @@ export default defineConfig({ link: "/wallets/wallet-api/batch-transactions", }, { - text: "Sign a Message", + text: "Sign Messages", link: "/wallets/wallet-api/sign-message", }, - { - text: "Sign a Typed Message", - link: "/wallets/wallet-api/sign-typed-message", - }, ], }, { text: "Wallet UI Kit", link: "/wallets/auth/wallet-ui-kit", }, + { + text: "React Native", + collapsed: true, + items: [ + { + text: "Expo Quickstart", + link: "/wallets/react-native/quickstart", + }, + { + text: "Configuration", + link: "/wallets/react-native/configuration", + }, + { + text: "Google OAuth", + link: "/wallets/react-native/google-oauth", + }, + { + text: "Expo OAuth API", + link: "/wallets/hooks/use-authenticate-oauth-with-expo-web-browser", + }, + { + text: "Domain Association", + link: "/wallets/react-native/domain-association", + }, + { + text: "Magic Link", + link: "/wallets/react-native/magic-link", + }, + { + text: "Passkeys", + link: "/wallets/react-native/passkeys", + }, + { + text: "Export Wallet", + link: "/wallets/react-native/export-wallet", + }, + { + text: "Export WebView API", + link: "/wallets/hooks/export-web-view", + }, + { + text: "React Native Web", + link: "/wallets/react-native/web", + }, + ], + }, ], }, ], From 106f4dad94c20aea349705c6bf90090d93e4c6d3 Mon Sep 17 00:00:00 2001 From: srinjoyc Date: Thu, 2 Jul 2026 10:04:35 -0700 Subject: [PATCH 21/25] Restore wallet API reference links --- docs/pages/wallets/auth/email-otp.mdx | 1 + docs/pages/wallets/auth/google-oauth.mdx | 1 + docs/pages/wallets/auth/magic-link.mdx | 1 + docs/pages/wallets/auth/passkeys.mdx | 1 + docs/pages/wallets/session-management.mdx | 2 ++ vocs.config.tsx | 4 ++++ 6 files changed, 10 insertions(+) diff --git a/docs/pages/wallets/auth/email-otp.mdx b/docs/pages/wallets/auth/email-otp.mdx index b3af40d4..e6cdb559 100644 --- a/docs/pages/wallets/auth/email-otp.mdx +++ b/docs/pages/wallets/auth/email-otp.mdx @@ -117,6 +117,7 @@ export function EmailOTPLogin() { - 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). ## Next steps diff --git a/docs/pages/wallets/auth/google-oauth.mdx b/docs/pages/wallets/auth/google-oauth.mdx index d41496dd..bac02a39 100644 --- a/docs/pages/wallets/auth/google-oauth.mdx +++ b/docs/pages/wallets/auth/google-oauth.mdx @@ -77,6 +77,7 @@ After the flow completes, use `useAccount`, `useSignMessage`, and `useSendTransa - 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). ## Next steps diff --git a/docs/pages/wallets/auth/magic-link.mdx b/docs/pages/wallets/auth/magic-link.mdx index f914ddc7..473b934a 100644 --- a/docs/pages/wallets/auth/magic-link.mdx +++ b/docs/pages/wallets/auth/magic-link.mdx @@ -123,6 +123,7 @@ export function VerifyMagicLink() { - Store the `otpId` and `otpEncryptionTargetBundle` somewhere the verify route can read them. `sessionStorage` is enough for a same-browser flow. - If users open the link on a different device or browser, you need an app-specific way to recover both values. - Magic link email behavior depends on your project email configuration in the dashboard. +- For full hook options and return values, see [`useSendMagicLink`](/wallets/hooks/use-send-magic-link) and [`useVerifyMagicLink`](/wallets/hooks/use-verify-magic-link). ## Next steps diff --git a/docs/pages/wallets/auth/passkeys.mdx b/docs/pages/wallets/auth/passkeys.mdx index 41b58c20..eca93d69 100644 --- a/docs/pages/wallets/auth/passkeys.mdx +++ b/docs/pages/wallets/auth/passkeys.mdx @@ -119,6 +119,7 @@ Use `useAccount`, `useSignMessage`, and `useSendTransaction` after authenticatio - Passkeys require a secure context. `localhost` works for local development; production apps should use HTTPS. - The dashboard ACL allowlist must include the exact origin you open in the browser. - Passkeys can sync across devices through platform password managers, depending on the user's device, browser, and account recovery settings. +- For full hook options and return values, see [`useRegisterPasskey`](/wallets/hooks/use-register-passkey) and [`useLoginPasskey`](/wallets/hooks/use-login-passkey). ## Next steps diff --git a/docs/pages/wallets/session-management.mdx b/docs/pages/wallets/session-management.mdx index 6518a25c..202c1b8c 100644 --- a/docs/pages/wallets/session-management.mdx +++ b/docs/pages/wallets/session-management.mdx @@ -59,6 +59,8 @@ export function RefreshSessionButton() { } ``` +For full hook options and return values, see [`useRefreshSession`](/wallets/hooks/use-refresh-session). + ## Detect disconnected sessions When a session expires and cannot be refreshed, the connector disconnects. Use Wagmi's `useAccount` hook to update your UI. diff --git a/vocs.config.tsx b/vocs.config.tsx index 90c3ef0d..eeff0ac3 100644 --- a/vocs.config.tsx +++ b/vocs.config.tsx @@ -505,6 +505,10 @@ export default defineConfig({ text: "Sign Messages", link: "/wallets/wallet-api/sign-message", }, + { + text: "Export Wallet", + link: "/wallets/export", + }, ], }, { From c4dd520269e0dc79b5ddab200ab7cfa2930b4bec Mon Sep 17 00:00:00 2001 From: srinjoyc Date: Thu, 2 Jul 2026 10:15:43 -0700 Subject: [PATCH 22/25] Remove unsupported Solana export references --- docs/pages/wallets/export.mdx | 5 ++--- docs/pages/wallets/hooks/use-export-private-key.mdx | 7 +++---- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/docs/pages/wallets/export.mdx b/docs/pages/wallets/export.mdx index 0bef671e..fe6da3bb 100644 --- a/docs/pages/wallets/export.mdx +++ b/docs/pages/wallets/export.mdx @@ -98,11 +98,10 @@ exportWallet.mutateAsync({ }) ``` -## Private key formats +## Private key format -`useExportPrivateKey` supports two key formats: +`useExportPrivateKey` exports a standard hex-encoded private key. | Format | Description | |--------|-------------| | `'Hexadecimal'` | Standard hex-encoded private key (default) | -| `'Solana'` | Solana-compatible key format | diff --git a/docs/pages/wallets/hooks/use-export-private-key.mdx b/docs/pages/wallets/hooks/use-export-private-key.mdx index 02fb6898..a3ea3228 100644 --- a/docs/pages/wallets/hooks/use-export-private-key.mdx +++ b/docs/pages/wallets/hooks/use-export-private-key.mdx @@ -63,12 +63,11 @@ The address of the account to export the private key for. If omitted, uses the c ### keyFormat -`'Hexadecimal' | 'Solana' | undefined` +`'Hexadecimal' | undefined` The format for the exported private key. - `'Hexadecimal'` — Standard hex-encoded private key (default) -- `'Solana'` — Solana-compatible key format ### connector @@ -82,13 +81,13 @@ The Wagmi connector to export the key for. If omitted, uses the currently active ### mutate -`(variables: { iframeContainerId: string; iframeStyles?: Record; address?: string; keyFormat?: 'Hexadecimal' | 'Solana'; connector?: Connector }) => void` +`(variables: { iframeContainerId: string; iframeStyles?: Record; address?: string; keyFormat?: 'Hexadecimal'; connector?: Connector }) => void` The mutation function to initiate the private key export. Renders a secure iframe containing the private key in the specified container. ### mutateAsync -`(variables: { iframeContainerId: string; iframeStyles?: Record; address?: string; keyFormat?: 'Hexadecimal' | 'Solana'; connector?: Connector }) => Promise` +`(variables: { iframeContainerId: string; iframeStyles?: Record; address?: string; keyFormat?: 'Hexadecimal'; connector?: Connector }) => Promise` Similar to [`mutate`](#mutate) but returns a promise. Resolves when the export iframe is rendered. From 949f468284bc7262f90d789edea830f035df0245 Mon Sep 17 00:00:00 2001 From: srinjoyc Date: Thu, 2 Jul 2026 10:41:33 -0700 Subject: [PATCH 23/25] Audit wallet docs against latest SDK --- docs/pages/wallets/auth/wallet-ui-kit.mdx | 3 +- docs/pages/wallets/connector-options.mdx | 7 +- .../wallets/hooks/use-export-private-key.mdx | 2 +- .../pages/wallets/hooks/use-export-wallet.mdx | 2 +- .../pages/wallets/hooks/use-login-passkey.mdx | 14 +++- .../wallets/hooks/use-refresh-session.mdx | 2 +- .../wallets/hooks/use-register-passkey.mdx | 14 +++- .../wallets/hooks/use-send-magic-link.mdx | 12 ++- docs/pages/wallets/hooks/use-send-otp.mdx | 12 ++- .../wallets/hooks/use-verify-magic-link.mdx | 12 ++- docs/pages/wallets/hooks/use-verify-otp.mdx | 2 +- docs/pages/wallets/quickstart.mdx | 8 +- .../wallets/wallet-api/batch-transactions.mdx | 74 ++++++++++--------- .../wallets/wallet-api/send-transaction.mdx | 1 - 14 files changed, 100 insertions(+), 65 deletions(-) diff --git a/docs/pages/wallets/auth/wallet-ui-kit.mdx b/docs/pages/wallets/auth/wallet-ui-kit.mdx index 6b29c4cf..ff9db4fa 100644 --- a/docs/pages/wallets/auth/wallet-ui-kit.mdx +++ b/docs/pages/wallets/auth/wallet-ui-kit.mdx @@ -185,11 +185,10 @@ Import the kit stylesheet once. If your app has broad global element styles, sco The current Wallet UI Kit package is focused on login. After the user signs in, use the standard Wallet API pages for wallet actions: - [Sign a message](/wallets/wallet-api/sign-message) -- [Sign messages](/wallets/wallet-api/sign-message) - [Send a transaction](/wallets/wallet-api/send-transaction) - [Batch transactions](/wallets/wallet-api/batch-transactions) -Signature and transaction confirmation screens are coming soon. Reach out to the [ZeroDev sales team](https://zerodev.app/contact) if you want early access. +Signature confirmation UI is experimental and transaction confirmation screens are coming soon. Reach out to the [ZeroDev sales team](https://zerodev.app/contact) if you want early access. ## Coming soon diff --git a/docs/pages/wallets/connector-options.mdx b/docs/pages/wallets/connector-options.mdx index 76201f9b..6aa9272d 100644 --- a/docs/pages/wallets/connector-options.mdx +++ b/docs/pages/wallets/connector-options.mdx @@ -28,13 +28,12 @@ zeroDevWallet({ ### mode -`'EOA' | '4337' | '7702'` +`'4337' | '7702'` The account mode exposed to Wagmi. Defaults to `'7702'`. - `'7702'` — An EOA delegated to a Kernel smart account via [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702). The address equals the EOA address; transactions are bundled as UserOperations and can be sponsored. - `'4337'` — A counterfactual [ERC-4337](https://eips.ethereum.org/EIPS/eip-4337) Kernel smart account. The address differs from the EOA and the account is deployed on the first UserOperation; transactions are bundled as UserOperations. -- `'EOA'` — A plain EOA. Transactions are sent directly via the chain's RPC, with no bundler and no sponsorship. ### rpId @@ -130,11 +129,11 @@ Advanced. Overrides the sub-organization the SDK operates against. Advanced. Base URL for a custom backend proxy in front of the ZeroDev wallet API. -### aaUrl +### aaHost `string | undefined` -Advanced. Overrides the account-abstraction bundler/paymaster URL. +Advanced. Overrides the account-abstraction bundler and paymaster host. Pass only the host origin, such as `https://rpc.zerodev.app`; the SDK derives the per-chain URL from your project ID, active chain, and host. ## React Native diff --git a/docs/pages/wallets/hooks/use-export-private-key.mdx b/docs/pages/wallets/hooks/use-export-private-key.mdx index a3ea3228..394f6b6b 100644 --- a/docs/pages/wallets/hooks/use-export-private-key.mdx +++ b/docs/pages/wallets/hooks/use-export-private-key.mdx @@ -41,7 +41,7 @@ function ExportKey() { } ``` -## Parameters +## Mutation Parameters ### iframeContainerId diff --git a/docs/pages/wallets/hooks/use-export-wallet.mdx b/docs/pages/wallets/hooks/use-export-wallet.mdx index 2c59fb8b..49fe1964 100644 --- a/docs/pages/wallets/hooks/use-export-wallet.mdx +++ b/docs/pages/wallets/hooks/use-export-wallet.mdx @@ -40,7 +40,7 @@ function ExportSeedPhrase() { } ``` -## Parameters +## Mutation Parameters ### iframeContainerId diff --git a/docs/pages/wallets/hooks/use-login-passkey.mdx b/docs/pages/wallets/hooks/use-login-passkey.mdx index 77ad68e9..534378e6 100644 --- a/docs/pages/wallets/hooks/use-login-passkey.mdx +++ b/docs/pages/wallets/hooks/use-login-passkey.mdx @@ -33,9 +33,15 @@ function Login() { } ``` -## Parameters +## Mutation Parameters -This hook takes no mutation variables. It triggers the browser's WebAuthn prompt to authenticate with an existing passkey. +This hook can be called without mutation variables. It triggers the browser's WebAuthn prompt to authenticate with an existing passkey. + +### connector + +`Connector | undefined` + +Optional Wagmi connector to log in with. If omitted, the hook uses the configured ZeroDev connector. ## Return Types @@ -43,13 +49,13 @@ This hook takes no mutation variables. It triggers the browser's WebAuthn prompt ### mutate -`() => void` +`(variables?: { connector?: Connector }) => void` The mutation function to log in with a passkey. Triggers the WebAuthn browser prompt. ### mutateAsync -`() => Promise` +`(variables?: { connector?: Connector }) => Promise` Similar to [`mutate`](#mutate) but returns a promise. Resolves when the passkey is verified and the wallet is connected. diff --git a/docs/pages/wallets/hooks/use-refresh-session.mdx b/docs/pages/wallets/hooks/use-refresh-session.mdx index d49dc903..062e4601 100644 --- a/docs/pages/wallets/hooks/use-refresh-session.mdx +++ b/docs/pages/wallets/hooks/use-refresh-session.mdx @@ -27,7 +27,7 @@ function SessionControls() { } ``` -## Parameters +## Mutation Parameters This hook takes an empty object `{}` as its mutation variable. An optional `connector` can be provided if you have multiple connectors configured. diff --git a/docs/pages/wallets/hooks/use-register-passkey.mdx b/docs/pages/wallets/hooks/use-register-passkey.mdx index cce8e49c..ccea1383 100644 --- a/docs/pages/wallets/hooks/use-register-passkey.mdx +++ b/docs/pages/wallets/hooks/use-register-passkey.mdx @@ -33,9 +33,15 @@ function Register() { } ``` -## Parameters +## Mutation Parameters -This hook takes no mutation variables. It triggers the browser's WebAuthn prompt to create a new passkey. +This hook can be called without mutation variables. It triggers the browser's WebAuthn prompt to create a new passkey. + +### connector + +`Connector | undefined` + +Optional Wagmi connector to register the passkey with. If omitted, the hook uses the configured ZeroDev connector. ## Return Types @@ -43,13 +49,13 @@ This hook takes no mutation variables. It triggers the browser's WebAuthn prompt ### mutate -`() => void` +`(variables?: { connector?: Connector }) => void` The mutation function to register a passkey. Triggers the WebAuthn browser prompt. ### mutateAsync -`() => Promise` +`(variables?: { connector?: Connector }) => Promise` Similar to [`mutate`](#mutate) but returns a promise. Resolves when the passkey is registered and the wallet is connected. diff --git a/docs/pages/wallets/hooks/use-send-magic-link.mdx b/docs/pages/wallets/hooks/use-send-magic-link.mdx index 199161e8..15faaa45 100644 --- a/docs/pages/wallets/hooks/use-send-magic-link.mdx +++ b/docs/pages/wallets/hooks/use-send-magic-link.mdx @@ -46,7 +46,7 @@ function SendMagicLink() { } ``` -## Parameters +## Mutation Parameters ### email @@ -56,19 +56,25 @@ function SendMagicLink() { Configure the magic-link URL template for your project in the ZeroDev dashboard. The redirect page should call [`useVerifyMagicLink`](/wallets/hooks/use-verify-magic-link). +### connector + +`Connector | undefined` + +Optional Wagmi connector to send the magic link with. If omitted, the hook uses the configured ZeroDev connector. + ## Return Types [TanStack Query mutation docs](https://tanstack.com/query/v5/docs/react/reference/useMutation) ### mutate -`(variables: { email: string }) => void` +`(variables: { email: string; connector?: Connector }) => void` The mutation function to send the magic link. ### mutateAsync -`(variables: { email: string }) => Promise<{ otpId: string; otpEncryptionTargetBundle: string }>` +`(variables: { email: string; connector?: Connector }) => Promise<{ otpId: string; otpEncryptionTargetBundle: string }>` Similar to [`mutate`](#mutate) but returns a promise. diff --git a/docs/pages/wallets/hooks/use-send-otp.mdx b/docs/pages/wallets/hooks/use-send-otp.mdx index 5192afc7..528d7f98 100644 --- a/docs/pages/wallets/hooks/use-send-otp.mdx +++ b/docs/pages/wallets/hooks/use-send-otp.mdx @@ -40,7 +40,7 @@ function SendCode() { } ``` -## Parameters +## Mutation Parameters ### email @@ -48,19 +48,25 @@ function SendCode() { **Required.** The email address to send the verification code to. +### connector + +`Connector | undefined` + +Optional Wagmi connector to send the OTP with. If omitted, the hook uses the configured ZeroDev connector. + ## Return Types [TanStack Query mutation docs](https://tanstack.com/query/v5/docs/react/reference/useMutation) ### mutate -`(variables: { email: string }) => void` +`(variables: { email: string; connector?: Connector }) => void` The mutation function to send the OTP. ### mutateAsync -`(variables: { email: string }) => Promise<{ otpId: string; otpEncryptionTargetBundle: string }>` +`(variables: { email: string; connector?: Connector }) => Promise<{ otpId: string; otpEncryptionTargetBundle: string }>` Similar to [`mutate`](#mutate) but returns a promise. diff --git a/docs/pages/wallets/hooks/use-verify-magic-link.mdx b/docs/pages/wallets/hooks/use-verify-magic-link.mdx index 4a91ebd0..3933aa80 100644 --- a/docs/pages/wallets/hooks/use-verify-magic-link.mdx +++ b/docs/pages/wallets/hooks/use-verify-magic-link.mdx @@ -39,7 +39,7 @@ function VerifyPage() { } ``` -## Parameters +## Mutation Parameters ### otpId @@ -59,19 +59,25 @@ function VerifyPage() { **Required.** The encryption target bundle returned by [`useSendMagicLink`](/wallets/hooks/use-send-magic-link). +### connector + +`Connector | undefined` + +Optional Wagmi connector to verify the magic link with. If omitted, the hook uses the configured ZeroDev connector. + ## Return Types [TanStack Query mutation docs](https://tanstack.com/query/v5/docs/react/reference/useMutation) ### mutate -`(variables: { otpId: string; otpEncryptionTargetBundle: string; code: string }) => void` +`(variables: { otpId: string; otpEncryptionTargetBundle: string; code: string; connector?: Connector }) => void` The mutation function to verify the magic link. ### mutateAsync -`(variables: { otpId: string; otpEncryptionTargetBundle: string; code: string }) => Promise` +`(variables: { otpId: string; otpEncryptionTargetBundle: string; code: string; connector?: Connector }) => Promise` Similar to [`mutate`](#mutate) but returns a promise. Resolves when the magic link is verified and the wallet is connected. diff --git a/docs/pages/wallets/hooks/use-verify-otp.mdx b/docs/pages/wallets/hooks/use-verify-otp.mdx index f534da53..52b299dc 100644 --- a/docs/pages/wallets/hooks/use-verify-otp.mdx +++ b/docs/pages/wallets/hooks/use-verify-otp.mdx @@ -52,7 +52,7 @@ function VerifyCode({ } ``` -## Parameters +## Mutation Parameters ### code diff --git a/docs/pages/wallets/quickstart.mdx b/docs/pages/wallets/quickstart.mdx index 5511129f..a0651430 100644 --- a/docs/pages/wallets/quickstart.mdx +++ b/docs/pages/wallets/quickstart.mdx @@ -20,19 +20,19 @@ You will need: :::code-group ```bash [npm] -npm i @zerodev/wallet-react @zerodev/wallet-core wagmi viem @tanstack/react-query +npm i @zerodev/wallet-react @zerodev/wallet-core wagmi viem @wagmi/core @tanstack/react-query ``` ```bash [yarn] -yarn add @zerodev/wallet-react @zerodev/wallet-core wagmi viem @tanstack/react-query +yarn add @zerodev/wallet-react @zerodev/wallet-core wagmi viem @wagmi/core @tanstack/react-query ``` ```bash [pnpm] -pnpm add @zerodev/wallet-react @zerodev/wallet-core wagmi viem @tanstack/react-query +pnpm add @zerodev/wallet-react @zerodev/wallet-core wagmi viem @wagmi/core @tanstack/react-query ``` ```bash [bun] -bun add @zerodev/wallet-react @zerodev/wallet-core wagmi viem @tanstack/react-query +bun add @zerodev/wallet-react @zerodev/wallet-core wagmi viem @wagmi/core @tanstack/react-query ``` ::: diff --git a/docs/pages/wallets/wallet-api/batch-transactions.mdx b/docs/pages/wallets/wallet-api/batch-transactions.mdx index 65613ddc..d45d7f0e 100644 --- a/docs/pages/wallets/wallet-api/batch-transactions.mdx +++ b/docs/pages/wallets/wallet-api/batch-transactions.mdx @@ -11,8 +11,10 @@ By default, batches are atomic: if one call reverts, the whole batch reverts. This example sends a 0 ETH self-transfer and an ERC-20 transfer in one batch. Replace the contract, calldata, and values with the calls your app needs. ```tsx -import { encodeFunctionData, erc20Abi } from 'viem' -import { useAccount, useSendCalls, useWaitForCallsStatus } from 'wagmi' +import { waitForCallsStatus } from '@wagmi/core' +import { useState } from 'react' +import { type Address, type Hex, encodeFunctionData, erc20Abi } from 'viem' +import { useAccount, useConfig, useSendCalls } from 'wagmi' export function BatchCalls({ tokenAddress, @@ -20,33 +22,42 @@ export function BatchCalls({ tokenAddress: `0x${string}` }) { const { address, isConnected } = useAccount() - const { sendCalls, data, isPending, error } = useSendCalls() - const callsStatus = useWaitForCallsStatus({ - id: data?.id, - query: { - enabled: Boolean(data?.id), - }, - }) - - const sendBatch = () => { + const config = useConfig() + const { sendCallsAsync, isPending, error } = useSendCalls() + const [status, setStatus] = useState(null) + const [transactionHash, setTransactionHash] = useState< + `0x${string}` | null + >(null) + + const sendBatch = async () => { if (!isConnected || !address) return + setStatus(null) + setTransactionHash(null) + + const calls: { + to: Address + value?: bigint + data?: Hex + }[] = [ + { + to: address, + value: BigInt(0), + }, + { + to: tokenAddress, + data: encodeFunctionData({ + abi: erc20Abi, + functionName: 'transfer', + args: [address, BigInt(1_000_000)], + }), + }, + ] + + const { id } = await sendCallsAsync({ calls }) - sendCalls({ - calls: [ - { - to: address, - value: BigInt(0), - }, - { - to: tokenAddress, - data: encodeFunctionData({ - abi: erc20Abi, - functionName: 'transfer', - args: [address, BigInt(1_000_000)], - }), - }, - ], - }) + const result = await waitForCallsStatus(config, { id }) + setStatus(result.status ?? null) + setTransactionHash(result.receipts?.[0]?.transactionHash ?? null) } return ( @@ -55,12 +66,9 @@ export function BatchCalls({ {isPending ? 'Sending batch...' : 'Send batch'} - {data?.id ?

Batch ID: {data.id}

: null} - {callsStatus.data?.status ? ( -

Status: {callsStatus.data.status}

- ) : null} + {status ?

Status: {status}

: null} + {transactionHash ?

Hash: {transactionHash}

: null} {error ?

Batch failed: {error.message}

: null} - {callsStatus.error ?

{callsStatus.error.message}

: null}
) } @@ -72,7 +80,7 @@ export function BatchCalls({ - Batches can be sponsored when your project has a matching gas policy for the chain. - In `7702` mode, the exposed wallet address stays the user's address while the batch still uses smart wallet execution. - In `4337` mode, the batch executes through the user's Kernel smart account. -- Use `useWaitForCallsStatus` with the returned `id` to track confirmation. +- Use `waitForCallsStatus` with the returned `id` to wait for the batch result. - Use `BigInt(...)` instead of BigInt literals such as `0n` if your TypeScript target is lower than `ES2020`. ## Next steps diff --git a/docs/pages/wallets/wallet-api/send-transaction.mdx b/docs/pages/wallets/wallet-api/send-transaction.mdx index ca23db84..f03e98d1 100644 --- a/docs/pages/wallets/wallet-api/send-transaction.mdx +++ b/docs/pages/wallets/wallet-api/send-transaction.mdx @@ -83,6 +83,5 @@ export function MintNftGasless({ ## Next steps - [Batch transactions](/wallets/wallet-api/batch-transactions) -- [Sign a message](/wallets/wallet-api/sign-message) - [Sign messages](/wallets/wallet-api/sign-message) - [Session management](/wallets/session-management) From bf6e15e1a204d71299ae0ab3bf977f912a965eb6 Mon Sep 17 00:00:00 2001 From: srinjoyc Date: Thu, 2 Jul 2026 10:51:18 -0700 Subject: [PATCH 24/25] Clarify smart wallet intro --- docs/pages/wallets/index.mdx | 10 ++++------ vocs.config.tsx | 4 ++-- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/docs/pages/wallets/index.mdx b/docs/pages/wallets/index.mdx index c7cd6fdd..fedf9fbb 100644 --- a/docs/pages/wallets/index.mdx +++ b/docs/pages/wallets/index.mdx @@ -1,8 +1,6 @@ -# ZeroDev Smart Wallet +# Smart Wallet -ZeroDev Wallet is a **smart embedded wallet** — an embedded wallet built natively on smart accounts. Your users sign in with a familiar login and get a self-custodial wallet that can use gas sponsorship, batching, permissions, and chain abstraction without requiring seed phrases or gas tokens. - -Most embedded wallets start as EOAs and add smart accounts later. ZeroDev Wallet is smart-account-first, so account abstraction features are part of the core wallet flow instead of a separate integration. +ZeroDev Smart Wallet is a smart-account-first embedded wallet for apps that need onboarding, signing, and transactions in one SDK. Users sign in with familiar login methods, then get a self-custodial web3 wallet they can use to interact onchain while your app gets a Wagmi-compatible wallet stack you can fully control. ## How it works @@ -24,7 +22,7 @@ That's what makes every wallet **self-custodial**: only the authenticated user c - Authenticate with [passkeys](/wallets/auth/passkeys), [Google OAuth](/wallets/auth/google-oauth), [email OTP](/wallets/auth/email-otp), or [magic links](/wallets/auth/magic-link). - Drop in the prebuilt [Wallet UI Kit](/wallets/auth/wallet-ui-kit) for a faster login integration with less code. -- Keep users self-custodial — they can [export their wallet](/wallets/export) at any time. +- Let users [export their wallet](/wallets/export) at any time. **Wallet actions** @@ -34,7 +32,7 @@ That's what makes every wallet **self-custodial**: only the authenticated user c ## Why ZeroDev Wallet -ZeroDev Wallet is smart-account-first: every wallet can use smart account execution through EIP-7702 or ERC-4337 from the moment a user signs in, instead of starting as a plain EOA with features layered on top. That, plus a single platform for the whole account lifecycle, gives you everything to build a bespoke, app-native onchain experience: +Most embedded wallets start with a signer and leave smart account infrastructure for you to assemble later. ZeroDev Wallet is built around the full account lifecycle, so you can build a bespoke, app-native onchain experience: - **Smart from the first transaction.** Users get a smart account the moment they sign in — no separate upgrade step, no migrating from an EOA later. - **App-like, one-click flows.** Sponsor gas and batch multiple onchain actions into a single tap, so users get flows that feel like a modern app instead of a string of wallet pop-ups, approvals, and gas prompts. diff --git a/vocs.config.tsx b/vocs.config.tsx index eeff0ac3..f2c681df 100644 --- a/vocs.config.tsx +++ b/vocs.config.tsx @@ -441,10 +441,10 @@ export default defineConfig({ ], }, ], - // Embedded Wallet. + // Smart Wallet. "/wallets": [ { - text: "Embedded Wallet", + text: "Smart Wallet", collapsed: false, items: [ { From af746dfe76ce1568105a7e2f9b8eb3139485415b Mon Sep 17 00:00:00 2001 From: srinjoyc Date: Thu, 2 Jul 2026 11:42:50 -0700 Subject: [PATCH 25/25] Address wallet docs review feedback --- docs/pages/wallets/auth/wallet-ui-kit.mdx | 4 ++-- docs/pages/wallets/react-native/magic-link.mdx | 10 +++------- docs/pages/wallets/react-native/web.mdx | 8 +++----- 3 files changed, 8 insertions(+), 14 deletions(-) diff --git a/docs/pages/wallets/auth/wallet-ui-kit.mdx b/docs/pages/wallets/auth/wallet-ui-kit.mdx index ff9db4fa..31548d64 100644 --- a/docs/pages/wallets/auth/wallet-ui-kit.mdx +++ b/docs/pages/wallets/auth/wallet-ui-kit.mdx @@ -4,7 +4,7 @@ The Wallet UI Kit gives you prebuilt React UI for ZeroDev Wallet. Use it when yo The kit uses a Wagmi-compatible ZeroDev connector, so after the user signs in you can use standard Wagmi hooks such as `useAccount`, `useSignMessage`, and `useSendTransaction`. -The current kit covers login. More wallet UI components are coming, including signature and transaction confirmations, onramps, asset management and portfolio views, transaction history, and chain-abstracted balances. +The current kit covers login. More wallet UI components are coming, including prebuilt confirmation screens, onramps, asset management and portfolio views, transaction history, and chain-abstracted balances. For a fully custom UI, use the hook-based authentication pages instead: [Passkeys](/wallets/auth/passkeys), [Email OTP](/wallets/auth/email-otp), [Magic Link](/wallets/auth/magic-link), or [Google OAuth](/wallets/auth/google-oauth). If you want to customize the UI Kit flow itself, use the kit's `useAuth` hook from `@zerodev/wallet-react-ui` to read and drive the auth state. @@ -188,7 +188,7 @@ The current Wallet UI Kit package is focused on login. After the user signs in, - [Send a transaction](/wallets/wallet-api/send-transaction) - [Batch transactions](/wallets/wallet-api/batch-transactions) -Signature confirmation UI is experimental and transaction confirmation screens are coming soon. Reach out to the [ZeroDev sales team](https://zerodev.app/contact) if you want early access. +Prebuilt signature and transaction confirmation screens are coming soon. Reach out to the [ZeroDev sales team](https://zerodev.app/contact) if you want early access. ## Coming soon diff --git a/docs/pages/wallets/react-native/magic-link.mdx b/docs/pages/wallets/react-native/magic-link.mdx index bacafcd6..f7ac4885 100644 --- a/docs/pages/wallets/react-native/magic-link.mdx +++ b/docs/pages/wallets/react-native/magic-link.mdx @@ -4,7 +4,7 @@ The [`useSendMagicLink`](/wallets/hooks/use-send-magic-link) and [`useVerifyMagi A magic link needs a verified `https` callback — an **App Link** on Android, a **Universal Link** on iOS — so that tapping the link in the email opens the app. Email clients (e.g. Gmail) don't render custom-scheme links, so a plain `https` link on your verified domain is required. -The flow: send → the backend emails `${redirectURL}?code=` → the user taps it → the app opens at `/verify-email` → the route pairs the `code` from the URL with the persisted `otpId`/`otpEncryptionTargetBundle` and verifies. +The flow: send → the backend emails the dashboard-configured redirect URL with `?code=` → the user taps it → the app opens at `/verify-email` → the route pairs the `code` from the URL with the persisted `otpId`/`otpEncryptionTargetBundle` and verifies. ## Prerequisites @@ -85,7 +85,6 @@ import { useState } from "react"; import { Button, Text, TextInput } from "react-native"; import { savePendingMagicLink } from "@/lib/magic-link-pending"; -import { RP_ID } from "@/wagmi.config"; export function MagicLinkFlow() { const [email, setEmail] = useState(""); @@ -105,10 +104,7 @@ export function MagicLinkFlow() { title="Send magic link" disabled={send.isPending || !email} onPress={() => - send.mutate( - { email, redirectURL: `https://${RP_ID}/verify-email` }, - { onSuccess: savePendingMagicLink }, - ) + send.mutate({ email }, { onSuccess: savePendingMagicLink }) } /> @@ -116,7 +112,7 @@ export function MagicLinkFlow() { } ``` -- `redirectURL` must match the intent-filter host and the route path exactly; the backend emails `${redirectURL}?code=`. +- The Magic Link Redirect URL configured in the dashboard must match the intent-filter host and route path exactly; the emailed link adds the `code` query parameter. - The mutation's response is exactly what the saver takes, so `onSuccess: savePendingMagicLink` passes it directly. TanStack Query awaits async `onSuccess` callbacks before flipping `isSuccess`, so "Check your email" can't appear before the bundle is persisted. ### 3. Add the `verify-email` route diff --git a/docs/pages/wallets/react-native/web.mdx b/docs/pages/wallets/react-native/web.mdx index 8fbb3a87..74e3b4e8 100644 --- a/docs/pages/wallets/react-native/web.mdx +++ b/docs/pages/wallets/react-native/web.mdx @@ -140,13 +140,11 @@ export function WalletExport() { ### Cross-platform components -Components with no RN-only imports — `passkey-flow.tsx` and `magic-link-flow.tsx` — need no `.web` variant; the same file runs on both platforms. For magic link, just make the `redirectURL` point at the right origin per platform: +Components with no RN-only imports — `passkey-flow.tsx` and `magic-link-flow.tsx` — need no `.web` variant; the same file runs on both platforms. For magic link, configure the Magic Link Redirect URL in the ZeroDev Dashboard for each origin you support, such as your native App Link domain and your web app origin: ```ts -const redirectURL = - Platform.OS === "web" - ? `${window.location.origin}/verify-email` - : `https://${RP_ID}/verify-email`; +// Native: https://wallet.example.com/verify-email +// Web: https://app.example.com/verify-email ``` ## 2. Route only the callbacks that still matter on web