React Native Configuration
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
import { createReactNativePasskeyStamper } from "@zerodev/wallet-core/react-native/stampers/passkey";
import { createSecureStoreStamper } from "@zerodev/wallet-core/react-native/stampers/secure-store";
import { asyncStorageAdapter } from "@zerodev/wallet-core/react-native/storage/async-storage";
import { zeroDevWallet } from "@zerodev/wallet-react";
import { createConfig, createStorage, http } from "wagmi";
import { arbitrumSepolia, sepolia } from "wagmi/chains";
const ZERODEV_PROJECT_ID = process.env.EXPO_PUBLIC_ZERODEV_PROJECT_ID ?? "";
export const RP_ID = "example.com";
const chains = [sepolia, arbitrumSepolia] as const;
export const wagmiConfig = createConfig({
chains,
connectors: [
zeroDevWallet({
projectId: ZERODEV_PROJECT_ID,
chains,
rpId: RP_ID,
apiKeyStamper: createSecureStoreStamper(),
passkeyStamper: createReactNativePasskeyStamper({ rpId: RP_ID }),
sessionStorage: asyncStorageAdapter,
persistStorage: asyncStorageAdapter,
}),
],
transports: {
[sepolia.id]: http(),
[arbitrumSepolia.id]: http(),
},
storage: createStorage({ storage: asyncStorageAdapter }),
multiInjectedProviderDiscovery: false,
});Connector options
On React Native, zeroDevWallet takes these options in addition to the shared ones (projectId, chains, …):
| Option | Required | Description |
|---|---|---|
rpId | Yes | The relying party ID — your app's domain (no scheme), e.g. example.com. Used for passkeys and as the Origin of the SDK's requests. See Domain Association. |
apiKeyStamper | Yes | Signs SDK requests with a device-bound API key. Use createSecureStoreStamper. |
sessionStorage | Yes | Storage adapter for session data. Use asyncStorageAdapter. |
persistStorage | No | Storage adapter for persisting wallet state across app restarts. Usually also asyncStorageAdapter. |
passkeyStamper | No | Only needed for passkey auth. Use createReactNativePasskeyStamper. |
The rpId is a domain, as defined by the WebAuthn standard. As long as you don't use passkeys or App Links for OAuth / magic-link redirects, it doesn't have to be a valid domain you own; otherwise the domain association must be served from it.
The connector automatically sends Origin: https://<rpId> on its requests — so if you specify an Access Control List of whitelisted Origins on the ZeroDev Dashboard, the same domain needs to be on the allowlist as https://<rpId>/.
Stampers
createSecureStoreStamper
Creates the API-key stamper that signs the SDK's requests. The keypair is generated on first use and stored in expo-secure-store (Keychain on iOS, Keystore-backed storage on Android).
import { createSecureStoreStamper } from "@zerodev/wallet-core/react-native/stampers/secure-store";
const apiKeyStamper = createSecureStoreStamper();Requires the expo-secure-store peer dependency:
npx expo install expo-secure-storecreateReactNativePasskeyStamper
Creates the passkey stamper used by useRegisterPasskey and useLoginPasskey. It wraps the native platform passkey APIs and requires the rpId to match a domain your app is associated with — see Domain Association and Passkeys on React Native for the full setup.
import { createReactNativePasskeyStamper } from "@zerodev/wallet-core/react-native/stampers/passkey";
const passkeyStamper = createReactNativePasskeyStamper({ rpId: "example.com" });Requires these peer dependencies (native module — rebuild your dev client after installing):
npx expo install @turnkey/react-native-passkey-stamper uuidIf your app doesn't use passkeys, omit passkeyStamper — the OTP, magic-link, and OAuth flows work without it.
Storage
asyncStorageAdapter
A storage adapter backed by @react-native-async-storage/async-storage. Use it for the connector's sessionStorage and persistStorage, and for Wagmi's own createStorage:
import { asyncStorageAdapter } from "@zerodev/wallet-core/react-native/storage/async-storage";
import { createStorage } from "wagmi";
const storage = createStorage({ storage: asyncStorageAdapter });Requires the @react-native-async-storage/async-storage peer dependency:
npx expo install @react-native-async-storage/async-storageHow React Native differs from web
- No platform defaults —
rpId,apiKeyStamper, andsessionStorageare required on React Native; on the web they have built-in defaults. - Crypto polyfill — import
react-native-get-random-valuesat the very top of your app's entry file (see the quickstart). - Wallet export is a component, not a hook —
useExportWalletanduseExportPrivateKeyare not available on React Native. UseZeroDevExportWebViewinstead. - OAuth uses deep links — instead of the web popup flow, use
useAuthenticateOAuthWithExpoWebBrowser.
Running the same Expo app on the web too? See React Native Web — the web build auto-defaults the stampers and storage, so the connector is just zeroDevWallet({ projectId, chains }).