@awarizon/react-native
Mobile wallet management for Expo and bare React Native. Adds hardware-backed key storage (iOS Keychain / Android Keystore), automatic wallet restore on app launch, and React Native-safe async crypto.
Requires Expo SDK 49+ or bare React Native 0.74+. @awarizon/web3 is also required — install it following the Setup Guide.
AwarizonProvider (React Native)
Same Provider pattern as @awarizon/react. Wrap your root layout to give all hooks access to the SDK.
import { AwarizonProvider } from "@awarizon/react-native" import { AwarizonWeb3 } from "@awarizon/web3" import { Stack } from "expo-router" const awarizon = new AwarizonWeb3({ chain: "base", apiKey: process.env.EXPO_PUBLIC_AWARIZON_API_KEY!, }) export default function RootLayout() { return ( <AwarizonProvider awarizon={awarizon}> <Stack /> </AwarizonProvider> ) }
Secure Storage Setup
createSecureStorage wraps expo-secure-store behind a simple adapter interface. Private keys are encrypted by the OS — never stored in plaintext on disk.
import * as ExpoSecureStore from "expo-secure-store" import { createSecureStorage } from "@awarizon/react-native" import { AwarizonWeb3 } from "@awarizon/web3" // Create the adapter — wraps the ExpoSecureStore module const storage = createSecureStorage(ExpoSecureStore) const awarizon = new AwarizonWeb3({ chain: "base", apiKey: process.env.EXPO_PUBLIC_AWARIZON_API_KEY!, })
On iOS, keys are stored in the Keychain and survive app reinstalls. On Android, they are encrypted with the Android Keystore and tied to the app package. Neither platform writes the key to disk in plaintext.
useRNWallet
The main hook for React Native. Handles wallet creation, import, and secure persistence. On every app launch, it automatically restores the last saved wallet from secure storage — no login screen needed.
import { Text, View, Button } from "react-native" import { useRNWallet, createSecureStorage } from "@awarizon/react-native" import * as ExpoSecureStore from "expo-secure-store" import { awarizon } from "./lib/awarizon" const storage = createSecureStorage(ExpoSecureStore) function WalletScreen() { const { address, // string | null isConnected, // boolean isLoading, // true during create / import / auto-restore error, // Error | null create, // () => Promise<CreatedWallet> importMnemonic, // (phrase, accountIndex?) => Promise<void> importPrivateKey, // (key) => Promise<void> deleteWallet, // () => Promise<void> — removes from storage (logout) } = useRNWallet({ awarizon, storage, walletId: "main", // storage namespace — default: "default" autoRestore: true, // restore on mount — default: true }) if (isLoading) return <Text>Loading wallet…</Text> if (!isConnected) { return ( <View> <Button title="Create Wallet" onPress={create} /> <Button title="Import Mnemonic" onPress={() => importMnemonic("word1 word2 ... word12")} /> {error && <Text style={{ color: "red" }}>{error.message}</Text>} </View> ) } return ( <View> <Text>Connected: {address}</Text> <Button title="Log Out" onPress={deleteWallet} /> </View> ) }
awarizonAwarizonWeb3REQThe SDK instance to attach the wallet to.storageSecureStorageAdapterREQAdapter from createSecureStorage(ExpoSecureStore).walletIdstringStorage namespace key. Use different IDs for multi-wallet apps. Default: "default".autoRestorebooleanAuto-restore the last saved wallet from storage on mount. Default: true.addressstring | nullActive wallet address, or null when no wallet is loaded.isConnectedbooleanTrue when a wallet is active (restored or newly created).isLoadingbooleanTrue during create, import, auto-restore, or deleteWallet.errorError | nullLast operation error. Cleared on the next successful operation.create() => PromiseGenerate a fresh wallet. Private key saved to secure storage immediately.importMnemonicfn(phrase, index?) → import from BIP-39 mnemonic and save.importPrivateKeyfn(key) → import from hex private key and save.deleteWallet() => PromiseRemove from secure storage and clear all state. Use this as your logout action.Auto-restore priority: on mount, useRNWallet checks for a saved private key first, then a saved mnemonic. If neither is found, the hook stays in a clean disconnected state — no error is thrown.
contract() · useRead() · useWrite() — Mobile
The same contract binding API from @awarizon/react is available in @awarizon/react-native. Works identically for any contract type.
import { contract, useRead, useWrite } from "@awarizon/react-native" import { ERC20_ABI, STAKING_ABI } from "@awarizon/web3" // Define once, outside any component const USDC = contract("0x833589...", ERC20_ABI) const STAKING = contract("0x...", STAKING_ABI) function MobilePortfolio({ user }: { user: `0x${string}` }) { const { data: balance } = useRead(USDC.balanceOf(user), { pollingInterval: 15_000 }) const { data: staked } = useRead(STAKING.balanceOf(user)) const { data: earned } = useRead(STAKING.earned(user), { pollingInterval: 15_000 }) const { write: transfer, isLoading: sending } = useWrite(USDC.transfer) const { write: stake, isLoading: staking } = useWrite(STAKING.stake) const { write: claim, isLoading: claiming } = useWrite(STAKING.getReward) return ( <View> <Text>Balance: {balance?.toString()} USDC</Text> <Text>Staked: {staked?.toString()}</Text> <Text>Earned: {earned?.toString()}</Text> <Pressable onPress={() => transfer(recipient, 100n)} disabled={sending}> <Text>Send</Text> </Pressable> <Pressable onPress={() => claim()} disabled={claiming}> <Text>Claim Rewards</Text> </Pressable> </View> ) }