React Native Quickstart
Get started with WDK in React Native in under 3 minutes
The existing-app examples use @tetherto/wdk-react-native-core@1.0.0-beta.21. The starter path uses the dependency versions in its own repository lockfile.
What You'll Build
In this quickstart, you'll integrate WDK into a React Native app to create a multi-chain wallet that:
- Supports multiple blockchains (Bitcoin, Ethereum, Polygon, Arbitrum, TON, Tron)
- Manages multiple tokens (BTC, USD₮, XAU₮, and more)
- Provides secure seed generation and encrypted storage
- Shows real-time balances and transaction history
- Includes wallet creation, import, and unlock flows
You can try all features without real funds required. You can use the Pimlico or Candide faucets to get some Sepolia USD₮.
See the ERC-4337 configuration for quick setup and Sepolia testnet configuration.
Prerequisites
Before we start, make sure you have:
| Tool | Version | Why You Need It |
|---|---|---|
| Node.js | 22+ | To run JavaScript code |
| npm | Latest | To install packages |
| React Native | 0.81.0+ | Framework version |
| Android SDK | API 29+ | Android minimum SDK version |
| iOS | 15.1+ | iOS deployment target |
Quickstart Paths
You have 2 options for using WDK in a React Native. Choose your preferred starting point:
Get up and running in 3 minutes with our pre-configured starter template.
Option 1: Starter Template
The fastest way to get started is with our starter template. Note: this is still in alpha, and may be subject to breaking changes.
Step 1: Clone the Starter
git clone https://github.com/tetherto/wdk-starter-react-native.git
cd wdk-starter-react-nativeStep 2: Install Dependencies
npm installStep 3: Configure Environment
Create an environment file for the WDK Indexer API:
cp .env.example .envEdit .env and add your WDK Indexer API key:
EXPO_PUBLIC_WDK_INDEXER_BASE_URL=https://wdk-api.tether.io
EXPO_PUBLIC_WDK_INDEXER_API_KEY=your_actual_api_key_here
# Optional: For Tron network support
EXPO_PUBLIC_TRON_API_KEY=your_tron_api_key
EXPO_PUBLIC_TRON_API_SECRET=your_tron_api_secretWhere do I get an Indexer API key? The WDK Indexer is required for transaction history and balance indexing. Get your free API key from the Indexer API setup guide.
Step 4: Run Your App
npm run iosCongratulations! You now have a multi-chain wallet running.
Option 2: Add to Existing App
Integrate WDK into your existing React Native or Expo project using @tetherto/wdk-react-native-core.
Step 1: Install
Core requires expo-crypto >=55.0.0 <57.0.0 and react-native-bare-kit >=0.14.5 as peer dependencies. Use an Expo SDK whose expo-crypto version satisfies that range. In a bare React Native app, install and configure Expo modules before installing expo-crypto.
Install Core and its peer dependencies:
npm install @tetherto/wdk-react-native-core@1.0.0-beta.21 react-native-bare-kit
npx expo install expo-cryptoExpo autolinking discovers transitive native dependencies by default in SDK 54 and later. If your app uses React Native Community CLI autolinking or Expo's legacy_shallowReactNativeLinking, also add Keychain to the app's dependencies so it can be linked:
npm install 'react-native-keychain@^10.0.0'Rebuild the native app after installing dependencies, including iOS pods for bare React Native projects. Expo apps need a development build with the native modules included.
Step 2: Configure Android minSdkVersion
The library requires Android API 29 or higher to support react-native-bare-kit.
Add to your app.json or app.config.js:
{
"expo": {
"plugins": [
[
"expo-build-properties",
{
"android": {
"minSdkVersion": 29
}
}
]
]
}
}If you haven't installed expo-build-properties:
npx expo install expo-build-propertiesStep 3: Configure the Bundle
The WDK engine runs inside a Bare worklet. Use the @tetherto/wdk-worklet-bundler CLI to generate an HRPC bundle with only the modules you need:
# 1. Install the bundler CLI
npm install -g @tetherto/wdk-worklet-bundler@1.0.0-beta.14
# 2. Initialize configuration in your React Native project
wdk-worklet-bundler init
# 3. Edit wdk.config.js to configure your networks (see example below)
# 4. Install required WDK modules (pick the ones you need)
npm install @tetherto/wdk @tetherto/wdk-wallet-evm-erc-4337
# 5. Generate the bundle
wdk-worklet-bundler generateThis generates a .wdk/ directory in your project. Import it:
import { bundle } from './.wdk'Which WDK modules do I need? Each blockchain requires its own wallet module (e.g., wdk-wallet-evm-erc-4337 for Ethereum/Polygon, wdk-wallet-btc for Bitcoin). See the full list of available modules in the wdk-worklet-bundler documentation.
@tetherto/pear-wrk-wdk provides worklet transport and runtime handlers; it does not export a pre-built WDK bundle.
Step 4: Configure WDK Settings
Create a configuration file for your WDK setup (e.g., src/config/wdk.ts):
Set EXPO_PUBLIC_SEPOLIA_TEST_TOKEN_ADDRESS to a six-decimal USD₮ test token currently supported by your configured paymaster on Sepolia. Verify the address, decimals, and paymaster support through the provider's faucet and Sepolia deployment data. The address is public configuration. Use the same value in the wallet configuration and asset used for transfers.
The example uses Expo CLI environment-variable loading. For a bare React Native app, obtain the address through your existing public-config mechanism or replace the exported constant's value with the verified address; installing Expo modules alone does not load this environment variable.
// src/config/wdk.ts
import type { WdkConfigs } from '@tetherto/wdk-react-native-core'
export const sepoliaTestTokenAddress: string = process.env.EXPO_PUBLIC_SEPOLIA_TEST_TOKEN_ADDRESS ?? ''
if (!/^0x[0-9a-fA-F]{40}$/.test(sepoliaTestTokenAddress)) {
throw new Error('Set EXPO_PUBLIC_SEPOLIA_TEST_TOKEN_ADDRESS to your verified test token')
}
export const wdkConfigs: WdkConfigs = {
networks: {
ethereum: {
blockchain: 'ethereum',
config: {
chainId: 11155111, // Sepolia testnet
safeModulesVersion: '0.3.0',
provider: 'https://rpc.sepolia.org',
bundlerUrl: 'https://api.candide.dev/public/v3/11155111',
paymasterUrl: 'https://api.candide.dev/public/v3/11155111',
paymasterAddress: '0x8b1f6cb5d062aa2ce8d581942bbb960420d875ba',
transferMaxFee: 5000000,
paymasterToken: {
address: sepoliaTestTokenAddress,
},
},
},
// Add more networks as needed
},
}This example uses Sepolia testnet. Configure and fund the selected test token before sending. For production or mainnet configuration, see the Chain Configuration Guide.
Step 5: Add WdkAppProvider
Wrap your app with WdkAppProvider to enable wallet functionality throughout your app.
Add to your app/_layout.tsx:
// app/_layout.tsx
import { WdkAppProvider } from '@tetherto/wdk-react-native-core'
import { bundle } from '../.wdk'
import { Stack } from 'expo-router'
import { wdkConfigs } from '../src/config/wdk'
export default function RootLayout() {
return (
<WdkAppProvider bundle={{ bundle }} wdkConfigs={wdkConfigs}>
<Stack />
</WdkAppProvider>
)
}Step 6: Use Hooks
Now you can use the WDK hooks in any component inside WdkAppProvider:
Keep the selected wallet ID in your authenticated application state and pass it explicitly to Core. LOCKED.walletId is only an optional hint while a specific wallet is already being targeted.
import { useWdkApp, useWalletManager, useAccount } from '@tetherto/wdk-react-native-core'
function WalletScreen({
walletId,
authenticate,
}: {
walletId: string
authenticate: () => Promise<boolean>
}) {
const { state } = useWdkApp()
const { createWallet, unlock } = useWalletManager()
const { address } = useAccount({ network: 'ethereum', accountIndex: 0 })
const create = async () => {
if (await authenticate()) await createWallet(walletId)
}
const open = async () => {
if (await authenticate()) await unlock(state.walletId ?? walletId)
}
switch (state.status) {
case 'INITIALIZING':
case 'REINITIALIZING':
return <Text>Loading...</Text>
case 'NO_WALLET':
return <Button title="Create Wallet" onPress={create} />
case 'LOCKED':
return <Button title="Unlock" onPress={open} />
case 'READY':
return <Text>Address: {address}</Text>
case 'ERROR':
return <Text>Error: {state.error.message}</Text>
}
}For the full list of available hooks and their parameters, see the React Native Core API Reference.
Step 7: Rebuild and Run
For Expo projects, run prebuild to apply native changes:
npx expo prebuild --clean
npx expo run:ios
# or
npx expo run:androidCongratulations! You've successfully integrated WDK into your React Native app!
What's Next?
Now that you have WDK integrated, here's what you can explore:
Send Transactions
Use the useAccount() hook to send transactions:
// src/screens/SendScreen.tsx
import { useAccount, BaseAsset } from '@tetherto/wdk-react-native-core'
import { sepoliaTestTokenAddress } from '../config/wdk'
const usdt = new BaseAsset({
id: 'usdt-ethereum',
network: 'ethereum',
symbol: 'USDT',
name: 'Tether USD',
decimals: 6,
isNative: false,
address: sepoliaTestTokenAddress,
})
function SendScreen({ recipient }: { recipient: string }) {
const { address, send } = useAccount({ network: 'ethereum', accountIndex: 0 })
const handleSend = async () => {
if (!address) return
const result = await send({
to: recipient,
asset: usdt,
amount: '1000000', // 1 USDt (6 decimals)
})
if (result.success) {
console.log('TX hash:', result.hash, 'Fee:', result.fee)
} else {
console.error('TX failed:', result.error)
}
}
return <Button title="Send 1 USDt" onPress={handleSend} />
}This token configuration is for Sepolia. Validate the recipient for the configured chain and require the user to review the recipient, asset, amount, and fee before calling send().
Lock the Wallet
Use lock() to clear the active wallet identity and local address state:
function LockButton() {
const { lock } = useWalletManager()
const handleLock = async () => {
// This does not stop the worklet or confirm disposal completion.
await lock()
}
return <Button title="Lock" onPress={handleLock} />
}When a wallet is active, lock() sends a one-way full WDK disposal request and then resets local lifecycle flags. The Bare worklet and IPC connection stay running, and the call does not wait for worklet cleanup acknowledgement. Treat it as an application access boundary, not evidence that every seed or key copy was erased from memory.
Refresh Balances
import { useRefreshBalance } from '@tetherto/wdk-react-native-core'
const { mutate: refreshBalance } = useRefreshBalance()
// Refresh all balances for account 0
refreshBalance({ accountIndex: 0, type: 'wallet' })Troubleshooting
Android build fails with "Execution failed for task ':app:checkDebugAarMetadata'"
This means your minSdkVersion is too low. Make sure you've set it to 29:
{
"expo": {
"plugins": [
["expo-build-properties", { "android": { "minSdkVersion": 29 } }]
]
}
}Then rebuild:
npx expo prebuild --clean
npx expo run:android"useWdkApp must be used within WdkAppProvider"
Ensure your component is rendered inside WdkAppProvider. The provider must be at the root of your component tree:
// Correct
<WdkAppProvider bundle={{ bundle }} wdkConfigs={configs}>
<MyComponent /> {/* Can use useWdkApp() here */}
</WdkAppProvider>
// Wrong - hook used outside provider
<MyComponent /> {/* Cannot use useWdkApp() here */}
<WdkAppProvider bundle={{ bundle }} wdkConfigs={configs}>
...
</WdkAppProvider>No biometric prompt appears before a wallet operation
Core does not prompt for biometrics or enforce another authentication policy. Authenticate in your app before wallet operations or key access.
For background locking, revoke your app's authenticated state immediately and call lock(). If a guarded wallet operation is in progress, catch the rejection and retry lock() after it settles; a rejected call does not confirm that the SDK session is locked. Require authentication again on foreground. See the wallet lifecycle contract.
Worklet startup reports an error
Fix the reported bundle, configuration, or native startup cause, then restart the app before retrying.
Metro cache issues
If you see stale module errors after upgrading, clear the Metro cache:
npx expo start --clear
# or
npx react-native start --reset-cacheComplete Setup Checklist
For Expo projects:
- Install
@tetherto/wdk-react-native-coreplus itsexpo-cryptoandreact-native-bare-kitpeer dependencies - Configure Android minSdkVersion to 29 in
app.json - Set up bundle (custom or pre-built)
- Create
WdkConfigsconfiguration - Add
WdkAppProvidertoapp/_layout.tsx - Use hooks (
useWdkApp,useWalletManager,useAccount,useBalance) - Run
npx expo prebuild --cleanbefore building
For bare React Native:
- Install
@tetherto/wdk-react-native-coreplus itsexpo-cryptoandreact-native-bare-kitpeer dependencies - Install and configure Expo modules before adding
expo-crypto - Set minSdkVersion to 29 in
android/build.gradle - Set up bundle (custom or pre-built)
- Create
WdkConfigsconfiguration - Wrap root component with
WdkAppProvider - Rebuild native code
Learn More
Ready to dive deeper? Check out these resources:
Core Concepts
- React Native Core Docs - Full documentation for
@tetherto/wdk-react-native-core - API Reference - Complete hook and type reference
- Chain Configuration - Configure blockchain networks
Examples & Starters
- React Native Starter - Full-featured starter app
- React Native UI Kit - Pre-built wallet components