This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
This is a React Native cryptocurrency wallet mobile app (Rabby Mobile) organized as a Yarn 4 monorepo. It supports iOS/Android with multiple hardware wallet integrations.
- Repository: https://github.com/RabbyHub/rabby-mobile
- Package Manager: Yarn 4.12.0 (via Corepack)
- React Native: 0.81.6
- TypeScript: 5.7.3
- For
apps/mobileGoogle Play upload or Android store-release preflight work, readapps/mobile/skills/google-play-release.mdand keep the public workflow centered on./scripts/google-play.sh upload-internal-track; keep private inspection/report helpers under.codex. - For
apps/mobiledebug export or local file sharing flows, readapps/mobile/skills/file-share.mdand prefersrc/utils/shareLocalFile.tsover screen-local platform branching. - For
apps/mobiledebug, probe, or migration-diagnostics screens, readapps/mobile/skills/debug-pages.mdand keep the page focused on live state while moving instructions into help sheets and bulk actions into an actions sheet. - For
apps/mobilekeychain patching or upgrade work, readapps/mobile/skills/keychain-upgrade.mdbefore changing Android fallback behavior, authentication policy, or package wiring. - For
apps/mobilei18n locale files or translation backfills, readapps/mobile/skills/i18n-translation.mdand respect__skip_translationmarkers before adding missing keys. - For
apps/mobilecode changes, readapps/mobile/skills/import-cycles.mdand keep import-cycle detection, TypeScript typecheck, and Jest as the required self-validation set before handoff. - For
apps/mobilestore, hooks, or Home-path performance work, readapps/mobile/skills/perf-hooks.mdbefore changing selector boundaries or exposing large store state to React consumers. It captures the local rules around scene-picked minimal state, scene-level derived data, and limiting render fan-out.
# Build all packages
yarn build
# Lint (ESLint + Prettier + Yarn constraints)
yarn lint
# Fix linting issues
yarn lint:fix
# Run all tests across packages
yarn test
yarn test:verbose # Verbose output
# Run single package test
yarn workspace @rabby-wallet/<package-name> test
# Update README package list and dependency graph
yarn update-readme-content# Start Metro bundler (includes dependency build)
yarn start
yarn start:thrifty # Lower memory usage (8GB instead of 16GB)
yarn restart # Start with cache reset
# Run on devices
yarn ios
yarn android
# TypeScript type checking
yarn typecheck
# Import-cycle detection
yarn lint:cycles
yarn lint:cycles:eslint
# Jest tests
yarn test --runInBand
# Build web worker
yarn buildworker
yarn buildworker:prod:ios
yarn buildworker:prod:android
# Bundle analysis
yarn vbundle:ios
yarn vbundle:android
# Lint staged files (used by git hooks)
yarn lint:commit:fix
# Link native assets
yarn link-assets├── apps/
│ ├── mobile/ # Main React Native app
│ ├── mobile-local-pages/ # Local pages for WebView
│ ├── dev-console-cra/ # Dev console (CRA)
│ └── go.rabby.io/ # Go service
├── packages/ # Shared packages
│ ├── base-utils/ # Base utilities
│ ├── biz-utils/ # Business utilities
│ ├── eth-keyring-*/ # 6 keyring implementations (watch, ledger, keystone, gnosis, onekey, trezor)
│ ├── keyring-utils/ # Keyring utilities
│ ├── persist-store/ # Persistence layer
│ ├── service-address/ # Address management service
│ ├── service-keyring/ # Keyring service
│ ├── service-dapp/ # DApp service
│ ├── providers/ # Web3 providers
│ └── rn-webview-bridge/ # React Native WebView bridge
State Management:
- Zustand for global state:
src/store/{appchain,balance,tokens,protocols}.ts - Jotai: Deprecated. Please use Zustand
Navigation:
- React Navigation v7 with Native Stack
- Custom navigator in
src/utils/CustomNativeStackNavigator.ts - 9 nested navigators defined in
src/screens/Navigators/ - Navigation types in
src/navigation-type.ts
Styling:
- NativeWind (Tailwind CSS for React Native)
- RNEUI (React Native Elements UI) with custom theme
- Theme hooks: Prefer
useTheme2024()
Core Services Pattern:
- Services in
src/core/services/(39+ modules) - Controllers in
src/core/controllers/(RPC flow, provider, gnosis) - APIs in
src/core/apis/ - Storage abstraction with
persist-storepackage
Keyring & Security:
- 6 keyring types: Watch, Ledger, Keystone, Gnosis, OneKey, Trezor
- Hardware wallet transports via BLE
- Biometric authentication:
react-native-keychain+src/hooks/biometrics.ts - Security engine:
@rabby-wallet/rabby-security-engine
Database & Storage:
- TypeORM with SQLite via
@op-engineering/op-sqlite - MMKV for fast key-value storage
- Cloud storage backup support
Web3 Integration:
- Ethers.js v5.4.2 for primary Ethereum interactions
- Viem v2.17.4 for modern Ethereum operations
- WalletConnect v2.17.2
- Custom WebView bridge for dApp browser
Performance Patterns:
- Reanimated 3 for animations (use
useSharedValue, notuseStatefor animation state) - FlashList from Shopify for long lists
- Lazy loading with Suspense for heavy components
- Utilize React 19 transitions for non-urgent state updates.
- Jest with
ts-jestpreset for packages - Jest with
react-nativepreset for mobile app - Each package has its own
jest.config.js - Shared test setup in
/tests/setup.tsand/tests/setupAfterEnv/ - Run single test:
yarn workspace @rabby-wallet/<package> test --testNamePattern="pattern"
- Prefer
typeoverinterfacefor type definitions - Avoid
anytypes when possible - Use project references for build optimization
- Use
StyleSheet.create()over inline styles for performance - Use
FlatList/FlashListfor long lists with stablekeyprops (not array indices) - Clean up subscriptions/timers in
useEffectcleanup
- Use
useSharedValue(notuseState) for animation state - Add
'worklet';directive in worklet functions - Use
runOnJS()for JS calls from UI thread - Read
.valueonly in worklets
- Use selectors to subscribe to specific slices
- Use
shallowfor multiple values - Keep stores small and focused
- Never mutate state directly
- Always import Text, TextInput from
@/components/Typography(not fromreact-nativedirectly) - This wrapper ensures consistent
allowFontScaling: falsebehavior across the app - Available exports:
Text,TextInput,RNGHText,RNGHTextInput,AnimateableText,RNEUIText - ESLint rule
no-restricted-importsenforces this pattern
- Pre-push hook runs
yarn lint - Lint-staged runs on commit for staged files
- Main branch is
develop - For
apps/mobilecode changes, run the import-cycle suite (yarn workspace rabby-mobile lint:cycles,yarn workspace rabby-mobile lint:cycles:eslint),yarn workspace rabby-mobile typecheck, andyarn workspace rabby-mobile test --runInBandbefore handoff. If one is intentionally skipped, state the reason.
- Screens:
src/screens/(lazy and eager imports) - Components:
src/components/(legacy),src/components2024/(new theme) - Hooks:
src/hooks/(custom hooks) - Utils:
src/utils/(general utilities) - Core:
src/core/(services, APIs, controllers, bridges) - Store:
src/store/(Zustand stores) - Constants:
src/constant/ - Assets:
src/assets/
- Environment variables via
react-native-dotenv - Config files:
tailwind.config.js,metro.config.js,babel.config.js - Platform-specific code: Use
IS_ANDROID,IS_IOSfromsrc/core/native/utils