AppKit React Native is a multichain web3 library by Reown that enables React Native applications to connect users with cryptocurrency wallets and interact with blockchain networks.
- Wallet Connection: Multi-wallet support via WalletConnect protocol and custom connectors (Coinbase, Phantom, etc.)
- Multichain Support: EVM (Ethereum, Polygon, Arbitrum, etc.), Solana, and Bitcoin
- User Authentication: Sign-In With X (SIWX) for decentralized authentication
- DeFi Features: Token swaps, on-ramp/off-ramp, transaction monitoring
- Native Modal UI: Pre-built, customizable React Native components
- Theme Support: Light/dark themes with customization options
packages/
├── core/ # Controllers, utilities, core business logic (@reown/appkit-core-react-native)
├── appkit/ # Main SDK entry point, hooks, components (@reown/appkit-react-native)
├── ui/ # Reusable UI components (@reown/appkit-ui-react-native)
├── common/ # Shared types, constants, utilities (@reown/appkit-common-react-native)
├── ethers/ # EVM adapter using ethers.js (@reown/appkit-ethers-react-native)
├── wagmi/ # EVM adapter using wagmi (@reown/appkit-wagmi-react-native)
├── solana/ # Solana blockchain adapter (@reown/appkit-solana-react-native)
├── bitcoin/ # Bitcoin blockchain adapter (@reown/appkit-bitcoin-react-native)
├── coinbase/ # Coinbase wallet connector (@reown/appkit-coinbase-react-native)
└── cli/ # CLI tools (@reown/appkit-cli-react-native)
apps/
├── native/ # Example React Native Expo app
└── gallery/ # UI component showcase
Controller Pattern (Valtio) State management via reactive controllers:
ModalController- Modal visibility and stateRouterController- Navigation between viewsConnectionsController- Wallet connections and networksSwapController- Token swap operationsSendController- Transfer operationsTransactionsController- Transaction history
Adapter Pattern Blockchain-specific implementations:
BlockchainAdapter- Base interface- EVM adapters (Ethers, Wagmi)
- Solana adapter
- Bitcoin adapter
Connector Pattern Wallet connection methods:
WalletConnectConnector- Default WalletConnect protocol- Custom connectors for Coinbase, Phantom, etc.
- React Native 0.72+ (tested with 0.76+)
- TypeScript 5.2+
- Valtio (state management)
- WalletConnect v2
- Ethers.js / Wagmi (EVM)
- Solana Web3.js
The UI layer is split between two packages:
packages/ui/src/ # Reusable UI library (@reown/appkit-ui-react-native)
├── components/ # 11 base primitives (Card, Icon, Text, Image, Modal, etc.)
├── composites/ # 42 feature-rich components (Button, ListItem, InputText, etc.)
├── layout/ # 3 layout helpers (FlexView, Overlay, Separator)
├── context/ # ThemeContext and ThemeProvider
├── hooks/ # useTheme, useAnimatedValue, useCustomDimensions
├── utils/ # UiUtil, ThemeUtil, TypesUtil, TransactionUtil
└── assets/ # SVG icons
packages/appkit/src/ # AppKit-specific UI (@reown/appkit-react-native)
├── modal/ # Modal wrapper and router
├── views/ # Route views (Connect, Account, Swap, Networks, etc.)
└── partials/ # 24 AppKit-specific composites (Header, Snackbar, QrCode, etc.)
Base Components (packages/ui/src/components/):
wui-card- Container with themed background/borderwui-icon- SVG icon renderer (60+ icons)wui-text- Typography with 23 variantswui-image- Image loader with error handlingwui-modal- Animated bottom sheetwui-pressable- Base pressable wrapperwui-shimmer- Loading skeletonwui-loading-spinner- Loading indicator
Composite Components (packages/ui/src/composites/):
wui-button- Primary button (size: sm/md, variant: fill/shade/accent)wui-list-item- Pressable list item with animationswui-input-text- Animated text input with focus stateswui-card-select- Wallet/Network selector cardwui-tabs- Animated tab switcherwui-qr-code- QR code with embedded logowui-snackbar- Toast notificationwui-avatar- Address-based avatar with gradient
Layout Components (packages/ui/src/layout/):
FlexView- Flex container replacing View (supports gap, padding arrays)Overlay- Semi-transparent overlaySeparator- Divider with optional text
Theme Colors (62 keys in DarkTheme/LightTheme):
accent-100toaccent-020- Primary brand colorsfg-100tofg-300- Foreground/text colorsbg-100tobg-300- Background colorssuccess-100,error-100- Semantic colorsgray-glass-001togray-glass-090- Glass morphism overlays
Design Tokens:
Spacing: '0' | '4xs' | '3xs' | '2xs' | 'xs' | 's' | 'm' | 'l' | 'xl' | '2xl' | '3xl' | '4xl'
0 2 4 6 8 12 14 16 20 24 32 40 (px)
BorderRadius: '5xs' | '4xs' | '3xs' | 'xxs' | 'xs' | 's' | 'm' | 'l' | '3xl' | 'full'
4 6 8 12 16 20 28 36 80 100 (px)
Typography (23 variants):
- Sizes:
medium-title,small-title,large,medium,paragraph,small,tiny,micro - Weights:
400,500,600,700 - Example:
paragraph-500,small-400,micro-700
Using Theme:
const Theme = useTheme();
// Returns themed color object that responds to light/dark modeAnimations use React Native's Animated API, preferring the native driver for GPU-accelerated properties (opacity, transforms) and falling back to useNativeDriver: false when animating unsupported properties like colors.
Modal Animation (native driver):
- Opening: Spring physics (damping: 25, stiffness: 220)
- Closing: Timing animation (150ms) for snappy UX
- Backdrop: Opacity fade (300ms in, 250ms out)
Component Animations (JS-driven, useNativeDriver: false):
useAnimatedValuehook for color interpolation on press statesAnimated.createAnimatedComponent(Pressable)for interactive elements- Color transitions between normal/pressed states
RouterController manages navigation between views defined in RouterControllerState (see packages/core/src/controllers/RouterController.ts for the up-to-date list of route IDs).
View categories:
- Account flows (account overview and default account views)
- Connection flows (social logins, external wallets, WalletConnect, etc.)
- Network management (network selection, switching, unsupported network messaging)
- On-ramp experiences (on-ramp setup, checkout, loading, settings)
- Swap flows (swap entry and swap preview/review)
- Wallet actions (receiving, sending, send preview/review)
- Informational views (e.g., "What is a network?", "What is a wallet?")
View Pattern:
export function MyView() {
const snapshot = useSnapshot(ControllerState);
const { padding } = useCustomDimensions();
return (
<ScrollView style={{ paddingHorizontal: padding }}>
<FlexView padding={['xs', '0', 'xs', '0']}>{/* Content */}</FlexView>
</ScrollView>
);
}FlexView Layout:
<FlexView
flexDirection="row"
alignItems="center"
justifyContent="space-between"
padding={['l', 'xl', 's', 'xl']} // [top, right, bottom, left]
>List Item:
<ListItem icon="wallet" imageSrc={imageUrl} chevron onPress={handlePress} loading={isLoading}>
<Text variant="paragraph-500" color="fg-100">
{name}
</Text>
</ListItem>Button:
<Button size="md" variant="fill" onPress={handlePress}>
Connect Wallet
</Button>- Use existing components - Never create custom primitives; use the
wui-*components - Follow theme system - All colors must come from theme, no hardcoded hex values
- Use FlexView - Prefer FlexView over View for layout consistency
- Spacing tokens - Use spacing tokens ('xs', 's', 'm', etc.) not pixel values
- Animation consistency - Use
useAnimatedValuehook for press state animations - Memoize list items - Use
React.memowith custom comparison for expensive list items - Test both themes - Verify changes work in both light and dark mode
Before pushing any solution, always run:
yarn format # Prettier formatting
yarn lint # ESLint checks
yarn test # Jest testsFollow existing code style in the codebase. Do not deviate from established patterns.
This SDK must work for both Expo and React Native CLI projects. Ensure any changes are compatible with both environments.
Keep external third-party dependencies minimal. Avoid adding new libraries if possible - the SDK must remain lightweight. If a new dependency is absolutely necessary, justify it clearly.
- Adapters: Blockchain-specific implementations (one per chain type)
- Connectors: Wallet connection methods
- Controllers: Valtio-based reactive state containers
- Namespaces: CAIP-style chain identifiers (e.g.,
eip155:1for Ethereum mainnet) - CAIP Addresses: Chain-agnostic addresses (e.g.,
eip155:1:0x...)
packages/appkit/src/AppKit.ts # Main SDK class (~900 LOC)
packages/appkit/src/hooks/ # React hooks (useAppKit, useAccount, etc.)
packages/core/src/controllers/ # State management controllers
packages/common/src/ # Shared types and network definitions
packages/ethers/src/adapter.ts # EVM adapter implementation
packages/solana/src/ # Solana adapter
packages/bitcoin/src/ # Bitcoin adapter
yarn install # Install dependencies
yarn ios # Run example on iOS simulator
yarn android # Run example on Android emulator
yarn build # Build all packages
yarn lint # Run ESLint
yarn test # Run Jest tests
yarn format # Run PrettierFollow conventional commits: fix:, feat:, refactor:, docs:, test:, chore:
When resolving Dependabot security alerts or dependency update PRs:
-
Direct dependencies - Update the version directly in the package's
package.jsonwhere it's declared. This is cleaner than using resolutions because:- It keeps the dependency version visible where the package is used
- Resolutions are meant for transitive dependencies you don't control
- Example: update storybook in
apps/gallery/package.json, not via root resolutions
-
Transitive dependencies - Use resolutions/overrides for dependencies you don't directly declare:
- Root
package.json→resolutionsfield (for yarn workspaces) - Specific package's
package.json→overridesfield (for npm packages like expo-multichain)
- Root
-
Update lockfiles - After making changes:
- Run
yarn installat root to updateyarn.lock - Run
npm installin the specific package directory to updatepackage-lock.json
- Run
-
Check for related packages - When updating a package, check if there are related packages that should be updated together (e.g., updating
storybookshould also update all@storybook/*addons to the same version for consistency) -
Never update to new major versions - Only apply patch/minor updates. Major version bumps can cause breaking changes and compatibility issues.
-
Run formatting before committing - Always run
yarn formatto fix any prettier issues before creating a commit.