
Security News
Feross on the 10 Minutes or Less Podcast: Nobody Reads the Code
Socket CEO Feross Aboukhadijeh joins 10 Minutes or Less, a podcast by Ali Rohde, to discuss the recent surge in open source supply chain attacks.
@tetherto/wdk-react-native-provider
Advanced tools
React Native library providing wallet context and WDK service integration
A React Native library providing wallet context and WDK (Wallet Development Kit) service integration for building secure, multi-chain cryptocurrency wallets.
npm install @tetherto/wdk-react-native-provider
The library requires Android minSdkVersion 29 to properly run react-native-bare-kit.
For Expo projects with prebuild:
Add to your app.json or app.config.js:
{
"expo": {
"plugins": [
[
"expo-build-properties",
{
"android": {
"minSdkVersion": 29
}
}
]
]
}
}
For bare React Native projects:
Update android/build.gradle:
buildscript {
ext {
minSdkVersion = 29
// ... other config
}
}
This library requires several peer dependencies. Install them using:
npm install \
@craftzdog/react-native-buffer \
@react-native-async-storage/async-storage \
@tetherto/pear-wrk-wdk \
@tetherto/wdk-secret-manager \
b4a \
bip39 \
browserify-zlib \
decimal.js \
events \
http2-wrapper \
https-browserify \
nice-grpc-web \
path-browserify \
process \
querystring-es3 \
react-native-bare-kit \
react-native-crypto \
react-native-device-info \
react-native-get-random-values \
react-native-keychain \
react-native-tcp-socket \
react-native-url-polyfill \
sodium-javascript \
stream-browserify \
stream-http
The library requires Node.js core module polyfills for React Native. Configure your Metro bundler using the provided helper function.
For Expo projects:
Update your metro.config.js:
const { getDefaultConfig } = require('expo/metro-config');
const { configureMetroForWDK } = require('@tetherto/wdk-react-native-provider/metro-polyfills');
const config = getDefaultConfig(__dirname);
const configWdk = configureMetroForWDK(config);
module.exports = configWdk;
Manual configuration (if needed):
If you prefer to manually configure the polyfills:
const { getDefaultConfig } = require('expo/metro-config');
const { getMetroPolyfills } = require('@tetherto/wdk-react-native-provider/metro-polyfills');
const config = getDefaultConfig(__dirname);
config.resolver.extraNodeModules = {
...config.resolver.extraNodeModules,
...getMetroPolyfills(),
};
module.exports = config;
Note: Runtime polyfills for Buffer, process, and crypto are automatically initialized when you import from @tetherto/wdk-react-native-provider. No additional setup is required.
Wrap your app with the WalletProvider and provide the required configuration.
For Expo Router projects:
Add the provider to your app/_layout.tsx file to make the useWallet hook accessible throughout your app:
// app/_layout.tsx
import { WalletProvider } from '@tetherto/wdk-react-native-provider';
import { Stack } from 'expo-router';
// Define your chain configurations
const CHAINS_CONFIG = {
ethereum: {
chainId: 1,
blockchain: 'ethereum',
provider: 'https://mainnet.gateway.tenderly.co/YOUR_KEY',
bundlerUrl: 'https://api.candide.dev/public/v3/ethereum',
paymasterUrl: 'https://api.candide.dev/public/v3/ethereum',
paymasterAddress: '0x8b1f6cb5d062aa2ce8d581942bbb960420d875ba',
entrypointAddress: '0x0000000071727De22E5E9d8BAf0edAc6f37da032',
transferMaxFee: 5000000,
swapMaxFee: 5000000,
bridgeMaxFee: 5000000,
paymasterToken: {
address: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
},
},
bitcoin: {
host: 'api.ordimint.com',
port: 50001,
},
// ... add other chains as needed
};
export default function RootLayout() {
return (
<WalletProvider
config={{
indexer: {
apiKey: 'your-api-key-here',
url: 'https://your-indexer-url.com',
},
chains: CHAINS_CONFIG,
enableCaching: true, // Optional: enable caching for better performance
}}
>
<Stack />
</WalletProvider>
);
}
For standard React Native projects:
Wrap your root component:
// App.tsx
import { WalletProvider } from '@tetherto/wdk-react-native-provider';
const CHAINS_CONFIG = {
ethereum: {
chainId: 1,
blockchain: 'ethereum',
provider: 'https://mainnet.gateway.tenderly.co/YOUR_KEY',
bundlerUrl: 'https://api.candide.dev/public/v3/ethereum',
paymasterUrl: 'https://api.candide.dev/public/v3/ethereum',
paymasterAddress: '0x8b1f6cb5d062aa2ce8d581942bbb960420d875ba',
entrypointAddress: '0x0000000071727De22E5E9d8BAf0edAc6f37da032',
transferMaxFee: 5000000,
swapMaxFee: 5000000,
bridgeMaxFee: 5000000,
paymasterToken: {
address: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
},
},
bitcoin: {
host: 'api.ordimint.com',
port: 50001,
},
// ... other chains
};
function App() {
return (
<WalletProvider
config={{
indexer: {
apiKey: 'your-api-key-here',
url: 'https://your-indexer-url.com',
},
chains: CHAINS_CONFIG,
enableCaching: true, // Optional: enable caching for balances and transactions
}}
>
<YourApp />
</WalletProvider>
);
}
Access wallet functionality using the useWallet hook:
import { useWallet } from '@tetherto/wdk-react-native-provider';
function WalletScreen() {
const {
wallet,
balances,
transactions,
isLoading,
isInitialized,
isUnlocked,
createWallet,
unlockWallet,
refreshWalletBalance,
refreshTransactions,
} = useWallet();
// Create a new wallet
const handleCreateWallet = async () => {
try {
const wallet = await createWallet({
name: 'Imported Wallet',
mnemonic: 'your twelve word seed phrase goes here',
});
console.log('Wallet created:', wallet);
} catch (error) {
console.error('Failed to create wallet:', error);
}
};
// Unlock wallet
const handleUnlockWallet = async () => {
try {
await unlockWallet();
console.log('Wallet unlocked');
} catch (error) {
console.error('Failed to unlock wallet:', error);
}
};
if (!isInitialized) {
return <Text>Initializing...</Text>;
}
if (!wallet) {
return (
<View>
<Button title="Create Wallet" onPress={handleCreateWallet} />
<Button title="Import Wallet" onPress={handleImportWallet} />
</View>
);
}
if (!isUnlocked) {
return <Button title="Unlock Wallet" onPress={handleUnlockWallet} />;
}
return (
<View>
<Text>Wallet Name: {wallet.name}</Text>
<Button title="Refresh Balance" onPress={refreshWalletBalance} />
<Button title="Refresh Transactions" onPress={refreshTransactions} />
</View>
);
}
The main provider component that manages wallet state.
Props:
config.indexer (object, required): Indexer service configuration
config.indexer.apiKey (string, required): API key for the indexer serviceconfig.indexer.url (string, required): URL of the indexer serviceconfig.indexer.version (string, optional): API version (defaults to 'v1')config.chains (ChainsConfig, required): Chain configuration object containing network-specific settingsconfig.enableCaching (boolean, optional): Enable caching for balances and transactions to improve performanceSee Chain Configuration for detailed configuration options.
Hook to access wallet context and functionality.
Returns:
{
// State
wallet?: Wallet | null;
addresses?: AddressMap;
balances: {
list: Amount[];
map: BalanceMap;
isLoading: boolean;
};
transactions: {
list: Transaction[];
map: TransactionMap;
isLoading: boolean;
};
isLoading: boolean;
error: string | null;
isInitialized: boolean;
isUnlocked: boolean;
// Actions
createWallet: (params: { name: string; mnemonic?: string }) => Promise<Wallet | null>;
clearWallet: () => Promise<void>;
clearError: () => void;
refreshWalletBalance: () => Promise<void>;
refreshTransactions: () => Promise<void>;
unlockWallet: () => Promise<boolean | undefined>;
}
Low-level service for direct wallet operations. Available as a singleton.
import { WDKService } from '@tetherto/wdk-react-native-provider';
// Initialize WDK
await WDKService.initialize();
// Create seed
const seed = await WDKService.createSeed({ prf: 'passkey' });
// Import seed phrase
await WDKService.importSeedPhrase({
prf: 'passkey',
seedPhrase: 'your mnemonic here',
});
// Create wallet
const wallet = await WDKService.createWallet({
walletName: 'My Wallet',
prf: 'passkey',
});
// Get balances
const balances = await WDKService.resolveWalletBalances(
enabledAssets,
addressMap
);
// Send transaction
const result = await WDKService.sendByNetwork(
NetworkType.ETHEREUM,
0, // account index
100, // amount
'0x...', // recipient address
AssetTicker.USDT
);
The library supports multiple blockchain networks, each with its own configuration structure.
The chains configuration object supports the following blockchain networks:
const chains = {
ethereum?: EVMChainConfig;
arbitrum?: EVMChainConfig;
polygon?: EVMChainConfig;
ton?: TONChainConfig;
bitcoin?: BitcoinChainConfig;
tron?: TronChainConfig;
}
For Ethereum, Polygon, and Arbitrum:
const ethereumConfig = {
chainId: 1,
blockchain: 'ethereum',
provider: 'https://mainnet.gateway.tenderly.co/YOUR_KEY',
bundlerUrl: 'https://api.candide.dev/public/v3/ethereum',
paymasterUrl: 'https://api.candide.dev/public/v3/ethereum',
paymasterAddress: '0x8b1f6cb5d062aa2ce8d581942bbb960420d875ba',
entrypointAddress: '0x0000000071727De22E5E9d8BAf0edAc6f37da032',
transferMaxFee: 5000000,
swapMaxFee: 5000000,
bridgeMaxFee: 5000000,
paymasterToken: {
address: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
},
safeModulesVersion: '0.3.0', // Optional, for Polygon
};
const tonConfig = {
tonApiClient: {
url: 'https://tonapi.io',
},
tonClient: {
url: 'https://toncenter.com/api/v2/jsonRPC',
},
paymasterToken: {
address: 'EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs',
},
transferMaxFee: 1000000000,
};
const bitcoinConfig = {
host: 'api.ordimint.com',
port: 50001,
};
const tronConfig = {
chainId: 3448148188,
provider: 'https://trongrid.io',
gasFreeProvider: 'https://gasfree.io',
apiKey: 'your-api-key',
apiSecret: 'your-api-secret',
serviceProvider: 'TKtWbdzEq5ss9vTS9kwRhBp5mXmBfBns3E',
verifyingContract: 'THQGuFzL87ZqhxkgqYEryRAd7gqFqL5rdc',
transferMaxFee: 10000000,
swapMaxFee: 1000000,
bridgeMaxFee: 1000000,
paymasterToken: {
address: 'TXYZopYRdj2D9XRtbG411XZZ3kM5VkAeBf',
},
};
import { WalletProvider } from '@tetherto/wdk-react-native-provider';
const chains = {
ethereum: {
chainId: 1,
blockchain: 'ethereum',
provider: 'https://mainnet.gateway.tenderly.co/YOUR_KEY',
bundlerUrl: 'https://api.candide.dev/public/v3/ethereum',
paymasterUrl: 'https://api.candide.dev/public/v3/ethereum',
paymasterAddress: '0x8b1f6cb5d062aa2ce8d581942bbb960420d875ba',
entrypointAddress: '0x0000000071727De22E5E9d8BAf0edAc6f37da032',
transferMaxFee: 5000000,
swapMaxFee: 5000000,
bridgeMaxFee: 5000000,
paymasterToken: {
address: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
},
},
polygon: {
chainId: 137,
blockchain: 'polygon',
provider: 'https://polygon.gateway.tenderly.co/YOUR_KEY',
bundlerUrl: 'https://api.candide.dev/public/v3/polygon',
paymasterUrl: 'https://api.candide.dev/public/v3/polygon',
paymasterAddress: '0x8b1f6cb5d062aa2ce8d581942bbb960420d875ba',
entrypointAddress: '0x0000000071727De22E5E9d8BAf0edAc6f37da032',
transferMaxFee: 5000000,
swapMaxFee: 5000000,
bridgeMaxFee: 5000000,
paymasterToken: {
address: '0xc2132d05d31c914a87c6611c10748aeb04b58e8f',
},
safeModulesVersion: '0.3.0',
},
arbitrum: {
chainId: 42161,
blockchain: 'arbitrum',
provider: 'https://arbitrum.gateway.tenderly.co/YOUR_KEY',
bundlerUrl: 'https://api.candide.dev/public/v3/arbitrum',
paymasterUrl: 'https://api.candide.dev/public/v3/arbitrum',
paymasterAddress: '0x8b1f6cb5d062aa2ce8d581942bbb960420d875ba',
entrypointAddress: '0x0000000071727De22E5E9d8BAf0edAc6f37da032',
transferMaxFee: 5000000,
swapMaxFee: 5000000,
bridgeMaxFee: 5000000,
paymasterToken: {
address: '0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9',
},
},
ton: {
tonApiClient: {
url: 'https://tonapi.io',
},
tonClient: {
url: 'https://toncenter.com/api/v2/jsonRPC',
},
paymasterToken: {
address: 'EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs',
},
transferMaxFee: 1000000000,
},
bitcoin: {
host: 'api.ordimint.com',
port: 50001,
},
tron: {
chainId: 3448148188,
provider: 'https://trongrid.io',
gasFreeProvider: 'https://gasfree.io',
apiKey: 'your-api-key',
apiSecret: 'your-api-secret',
serviceProvider: 'TKtWbdzEq5ss9vTS9kwRhBp5mXmBfBns3E',
verifyingContract: 'THQGuFzL87ZqhxkgqYEryRAd7gqFqL5rdc',
transferMaxFee: 10000000,
swapMaxFee: 1000000,
bridgeMaxFee: 1000000,
paymasterToken: {
address: 'TXYZopYRdj2D9XRtbG411XZZ3kM5VkAeBf',
},
},
};
function App() {
return (
<WalletProvider
config={{
indexer: {
apiKey: 'your-indexer-api-key',
url: 'https://your-indexer-url.com',
},
chains,
enableCaching: true, // Optional: enable caching for better performance
}}
>
<YourApp />
</WalletProvider>
);
}
const { wallet, addresses, balances, transactions } = useWallet();
if (wallet) {
// Addresses
if (addresses) {
Object.entries(addresses).forEach(([ticker, addressList]) => {
console.log(`${ticker}: ${addressList[0]?.value}`);
});
}
// Balances - available as both list and map
balances.list.forEach(balance => {
console.log(`${balance.denomination}: ${balance.value}`);
});
// Or access by ticker from the map
const usdtBalance = balances.map.USDT?.[0];
console.log('USDT Balance:', usdtBalance?.value);
// Check loading state
if (balances.isLoading) {
console.log('Loading balances...');
}
// Transactions - available as both list and map
transactions.list.forEach(tx => {
console.log('Transaction:', tx);
});
// Or access by ticker from the map
const usdtTransactions = transactions.map.USDT;
console.log('USDT Transactions:', usdtTransactions);
// Check loading state
if (transactions.isLoading) {
console.log('Loading transactions...');
}
}
import { NetworkType } from '@tetherto/wdk-react-native-provider';
// Available networks:
NetworkType.SEGWIT // Bitcoin
NetworkType.ETHEREUM // Ethereum
NetworkType.POLYGON // Polygon
NetworkType.ARBITRUM // Arbitrum
NetworkType.TON // TON
NetworkType.SOLANA // Solana
NetworkType.TRON // Tron
import { AssetTicker } from '@tetherto/wdk-react-native-provider';
// Available assets:
AssetTicker.BTC // Bitcoin
AssetTicker.USDT // Tether USD
AssetTicker.XAUT // Tether Gold
This library is written in TypeScript and includes complete type definitions. Import types as needed:
import type {
// Provider configuration
WalletProviderConfig,
// Wallet types
Amount,
Transaction,
Wallet,
// Enums (also available as values)
AssetTicker,
NetworkType,
} from '@tetherto/wdk-react-native-provider';
Note: Chain configuration types (ChainsConfig, EVMChainConfig, TONChainConfig, etc.) are defined in the underlying @tetherto/pear-wrk-wdk package. TypeScript will infer these types when you use them in the WalletProviderConfig, so explicit imports are typically not needed.
See CONTRIBUTING.md for development workflow and guidelines.
npm run prepare
npm run typecheck
npm run lint
npm test
If you're experiencing issues, verify you've completed all setup steps:
For Expo projects:
npm install @tetherto/wdk-react-native-providerapp.json:
{
"expo": {
"plugins": [
["expo-build-properties", { "android": { "minSdkVersion": 29 } }]
]
}
}
metro.config.js:
const { configureMetroForWDK } = require('@tetherto/wdk-react-native-provider/metro-polyfills');
const config = getDefaultConfig(__dirname);
const configWdk = configureMetroForWDK(config);
module.exports = configWdk;
WalletProvider to app/_layout.tsx with proper configuseWallet() hook in your componentsisInitialized before creating walletsFor bare React Native projects:
android/build.gradlemetro.config.jsWalletProvidernpx react-native run-android or npx react-native run-iosThe WDK service is initialized automatically when the WalletProvider mounts. If you see this error, ensure:
WalletProviderisInitialized before performing wallet operations:const { isInitialized, createWallet } = useWallet();
if (isInitialized) {
await createWallet({ name: 'My Wallet' });
}
Ensure a wallet has been created or imported before attempting transactions:
const { wallet, createWallet } = useWallet();
if (!wallet) {
await createWallet({ name: 'My Wallet' });
}
If you see errors like Unable to resolve "stream" or other Node.js core modules:
npx expo start --clear or npx react-native start --reset-cachenode_modules and reinstall: rm -rf node_modules && npm installnpx expo prebuild --cleanThis usually means minSdkVersion is too low. Ensure you've set minSdkVersion to 29:
For Expo:
{
"expo": {
"plugins": [
["expo-build-properties", { "android": { "minSdkVersion": 29 } }]
]
}
}
Then rebuild: npx expo run:android or npx expo prebuild --clean && npx expo run:android
Some peer dependencies may not have type definitions. You can ignore these by adding to your tsconfig.json:
{
"compilerOptions": {
"skipLibCheck": true
}
}
See the contributing guide to learn how to contribute to the repository and the development workflow.
Apache-2.0
Made with ❤️ by Tether
FAQs
React Native library providing wallet context and WDK service integration
We found that @tetherto/wdk-react-native-provider demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 3 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Socket CEO Feross Aboukhadijeh joins 10 Minutes or Less, a podcast by Ali Rohde, to discuss the recent surge in open source supply chain attacks.

Research
/Security News
Campaign of 108 extensions harvests identities, steals sessions, and adds backdoors to browsers, all tied to the same C2 infrastructure.

Security News
OpenAI rotated macOS signing certificates after a malicious Axios package reached its CI pipeline in a broader software supply chain attack.