Suite Mobile Architecture
Trezor Suite Mobile is a React Native application that brings Trezor wallet management to iOS and Android devices. Built with Expo SDK, it provides portfolio tracking, device connectivity, and cryptocurrency management on the go.
Overview
Suite Mobile combines native performance with cross-platform code sharing.
React Native 0.81.5 Cross-platform mobile framework
Expo SDK 54 Development tools and native modules
Redux Toolkit Centralized state management
Jotai Atomic state for UI components
Current Version : 26.3.1
Architecture Overview
┌────────────────────────────────────────┐
│ React Native Layer │
│ ┌──────────────────────────────────┐ │
│ │ @suite-native/app │ │
│ │ - Navigation (React Navigation) │ │
│ │ - Redux Store │ │
│ │ - Feature Modules │ │
│ └──────────────────────────────────┘ │
│ ┌──────────────────────────────────┐ │
│ │ Shared Code │ │
│ │ - @suite-common/* │ │
│ │ - @trezor/connect-mobile │ │
│ └──────────────────────────────────┘ │
└────────────────┬───────────────────────┘
│ React Native Bridge
┌────────────────┴───────────────────────┐
│ Native Layer │
│ ┌──────────────────────────────────┐ │
│ │ iOS (Swift/Objective-C) │ │
│ │ - USB/Bluetooth │ │
│ │ - Biometrics │ │
│ │ - Secure Storage │ │
│ │ - Native UI Components │ │
│ └──────────────────────────────────┘ │
│ ┌──────────────────────────────────┐ │
│ │ Android (Kotlin/Java) │ │
│ │ - USB/Bluetooth │ │
│ │ - Biometrics │ │
│ │ - Secure Storage │ │
│ │ - Native UI Components │ │
│ └──────────────────────────────────┘ │
└────────────────────────────────────────┘
Project Structure
Monorepo Organization
The mobile app is located in suite-native/ with a modular architecture:
suite-native/
├── app/ # 👑 Main application
│ ├── src/
│ │ ├── navigation/
│ │ ├── store/
│ │ └── App.tsx
│ ├── android/ # Android native code
│ ├── ios/ # iOS native code
│ ├── e2e/ # E2E tests (Detox)
│ └── package.json
├── accounts/ # Account management
├── alerts/ # Alert system
├── analytics/ # Mobile analytics
├── atoms/ # UI primitives
├── biometrics/ # Biometric auth
├── bluetooth/ # BLE connectivity
├── device/ # Device management
├── formatters/ # Data formatting
├── icons/ # Icon library
├── navigation/ # Navigation setup
├── module-*/ # Feature modules
├── receive/ # Receive flows
├── send/ # Send flows
├── state/ # Redux configuration
└── theme/ # Theming system
Total packages in suite-native/: 90+ modular packages
Feature Modules
Features are organized as self-contained modules:
module-home : Dashboard and portfolio overview
module-accounts-management : Account list and management
module-add-accounts : Add new cryptocurrency accounts
module-send : Send cryptocurrency flows
module-settings : App settings and configuration
module-device-onboarding : Device setup wizards
module-authorize-device : Device authorization
module-trading : Exchange integrations
module-earn : Staking features
Each module contains:
React components
Navigation screens
Business logic
Tests
Assets
Key Technologies
React Native Stack
Core Framework
Expo SDK
Navigation
State Management
React Native 0.81.5
JavaScript runtime with native bridge
Platform-specific components
Native module integration
Fast Refresh for development
// Platform-specific code
import { Platform } from 'react-native' ;
const component = Platform . select ({
ios : () => require ( './Component.ios' ),
android : () => require ( './Component.android' ),
})();
Expo SDK 54 Provides managed native modules:
expo-camera : QR code scanning
expo-clipboard : Clipboard access
expo-secure-store : Encrypted storage
expo-haptics : Haptic feedback
expo-image : Optimized images
expo-file-system : File operations
expo-updates : Over-the-air updates
import * as SecureStore from 'expo-secure-store' ;
await SecureStore . setItemAsync ( 'key' , 'value' );
React Navigation 7 Native navigation with:
Stack navigator
Bottom tabs
Modal screens
Deep linking
// Navigation structure
< NavigationContainer >
< Stack . Navigator >
< Stack . Screen name = "Home" component = { HomeScreen } />
< Stack . Screen name = "Accounts" component = { AccountsScreen } />
</ Stack . Navigator >
</ NavigationContainer >
Dual State System Redux Toolkit 2.11.2 : Global state
Wallet data
Device state
Transaction history
Settings
Jotai 2.15.0 : Component state
UI state (modals, sheets)
Form state
Temporary data
// Redux for persistent state
const accounts = useSelector ( selectAccounts );
// Jotai for UI state
const [ isModalOpen ] = useAtom ( modalOpenAtom );
Native Modules
@trezor/react-native-usb Native USB/HID transport:
Android: USB Host API
iOS: Not supported (cable limitations)
import { TrezorUSB } from '@trezor/react-native-usb' ;
// Android only
const devices = await TrezorUSB . enumerate ();
const session = await TrezorUSB . acquire ( device );
react-native-ble-plx 3.5.0 BLE support for Trezor Safe 3+:
Device scanning
Pairing
Encrypted communication
Connection management
import { BleManager } from 'react-native-ble-plx' ;
const manager = new BleManager ();
manager . startDeviceScan ( null , null , ( error , device ) => {
if ( device ?. name ?. includes ( 'Trezor' )) {
// Connect to device
}
});
Bluetooth support available on both iOS and Android for compatible Trezor models.
expo-local-authentication Biometric security:
Touch ID / Face ID (iOS)
Fingerprint / Face unlock (Android)
Fallback to PIN
import * as LocalAuthentication from 'expo-local-authentication' ;
const result = await LocalAuthentication . authenticateAsync ({
promptMessage: 'Authenticate to access wallet' ,
});
expo-secure-store Platform-specific secure storage:
iOS: Keychain
Android: EncryptedSharedPreferences
import * as SecureStore from 'expo-secure-store' ;
// Store sensitive data
await SecureStore . setItemAsync ( 'seed' , encryptedSeed , {
keychainAccessible: SecureStore . WHEN_UNLOCKED ,
});
Development Setup
Prerequisites
Install Node and Yarn
# Using NVM
nvm install
# Enable Yarn
corepack enable
Install Platform Tools
Follow React Native Android setup :
Install Android Studio
Install Android SDK (API 34+)
Configure ANDROID_HOME environment variable
Install Java Development Kit (JDK 17)
Linux : Install watchman# Ubuntu/Debian
sudo apt-get install watchman
macOS only Follow React Native iOS setup :
Install Xcode (latest version)
Install Xcode Command Line Tools:
Install CocoaPods:
sudo gem install cocoapods
Clone and Setup
git clone [email protected] :trezor/trezor-suite.git
cd trezor-suite
# Initialize submodules
git submodule update --init --recursive
git lfs install && git lfs pull
# Install dependencies
yarn
yarn build:essential
Prebuild Native Code
# Clean prebuild (first time or after native changes)
yarn native:prebuild:clean
# Or for specific platform
yarn native:prebuild:clean --platform android
yarn native:prebuild:clean --platform ios
Run yarn native:prebuild (or yarn p) after pulling/rebasing if native code changed.
Running the App
Start Metro Bundler
yarn native:start
# or shortcut
yarn s
Keep this running in a separate terminal.
Connect Device or Start Emulator
Physical Device:
Enable Developer Options
Enable USB Debugging
Connect via USB
Recommended: ADB over WiFi
Emulator:
Start from Android Studio
Or via command line:
emulator -avd Pixel_5_API_34
Build and Run
yarn native:android
# or shortcut
yarn a
First build takes ~10 minutes.
Reverse Ports
Enable communication with localhost services: yarn native:reverse-ports
# or shortcut
yarn ports
Reverses:
8081: Metro bundler
21328: Trezor Bridge
19121: Debug server
Use ADB over WiFi to free USB port for connecting Trezor device.
Start Metro Bundler
yarn native:start
# or shortcut
yarn s
Build and Run
Via CLI: yarn native:ios
# or shortcut
yarn ios
Via Xcode (for debugging native errors):# Open workspace
xed suite-native/app/ios
# Or
open suite-native/app/ios/TrezorSuite.xcworkspace
Then hit ▶️ Run button in Xcode. iOS Device Connection : Trezor can’t connect via USB on iOS due to cable limitations. Use portfolio tracker mode or connect via Desktop Suite as bridge (experimental).
Development Shortcuts
Quick commands available from repository root:
Shortcut Command Description yarn syarn native:startStart Metro bundler yarn pyarn native:prebuildRebuild native code yarn ayarn native:androidRun on Android yarn iosyarn native:iosRun on iOS yarn portsyarn native:reverse-portsReverse Android ports
Architecture Patterns
Component Structure
Atomic Design
Theme System
Navigation
Forms
UI components organized by complexity: Atoms (@suite-native/atoms):
Button, Text, Input
Icons, Badges
Basic UI primitives
Molecules :
Card, ListItem
Form fields
Combined atoms
Organisms :
Navigation bars
Bottom sheets
Complex components
Screens :
Full-page layouts
Feature screens
In feature modules
import { Button , Text } from '@suite-native/atoms' ;
< Button onPress = { handlePress } >
< Text > Send Bitcoin </ Text >
</ Button >
@suite-native/theme Unified theming with:
Color tokens
Typography scale
Spacing system
Component variants
import { useTheme } from '@suite-native/theme' ;
const Component = () => {
const { colors , spacing } = useTheme ();
return (
< View style = {{
backgroundColor : colors . backgroundPrimary ,
padding : spacing . large
}} >
{ /* content */ }
</ View >
);
};
@suite-native/navigation Type-safe navigation: // Define routes
type RootStackParamList = {
Home : undefined ;
AccountDetail : { accountKey : string };
Send : { accountKey : string ; address ?: string };
};
// Use navigation
import { useNavigation } from '@react-navigation/native' ;
const navigation = useNavigation < RootStackNavigationProp >();
navigation . navigate ( 'AccountDetail' , { accountKey: 'btc-0' });
@suite-native/forms Form handling with validation: import { useForm } from '@suite-native/forms' ;
const { values , errors , handleSubmit } = useForm ({
initialValues: { address: '' , amount: '' },
validate : ( values ) => {
// Validation logic
},
onSubmit : ( values ) => {
// Send transaction
},
});
State Management
Redux Store
Jotai Atoms
Persistence
Global Application State Located in @suite-native/state: // Store structure
{
wallet : {
accounts : [ ... ],
transactions : { ... },
blockchain : { ... },
},
device : {
devices : [ ... ],
selectedDevice : { ... },
},
analytics : { ... },
settings : { ... },
// ... more slices
}
Shared with Suite Desktop/Web : Many slices from @suite-common/wallet-coreComponent-Level State Used for:
UI state (modals, sheets)
Form state
Temporary data
Local preferences
import { atom , useAtom } from 'jotai' ;
const bottomSheetOpenAtom = atom ( false );
const Component = () => {
const [ isOpen , setIsOpen ] = useAtom ( bottomSheetOpenAtom );
// ...
};
Redux Persist State persisted to:
MMKV : Fast native storage (react-native-mmkv)
Secure Store : Sensitive data (expo-secure-store)
import { persistStore } from 'redux-persist' ;
import { MMKV } from 'react-native-mmkv' ;
const storage = new MMKV ();
const persistConfig = {
key: 'root' ,
storage: {
setItem : ( key , value ) => storage . set ( key , value ),
getItem : ( key ) => storage . getString ( key ),
removeItem : ( key ) => storage . delete ( key ),
},
};
Key Features
Device Connectivity
USB Connection (Android Only)
Native USB support using @trezor/react-native-usb:
User connects Trezor via USB OTG adapter
Android prompts for USB permission
App establishes HID connection
Communication via USB protocol
import { TrezorUSB } from '@trezor/react-native-usb' ;
// Request USB permission
const hasPermission = await TrezorUSB . requestPermission ( device );
// Acquire session
const session = await TrezorUSB . acquire ( device . path );
BLE support for Trezor Safe 3 and later: Features :
Device scanning
Automatic pairing
Encrypted communication
Connection persistence
Flow :
Enable Bluetooth on phone
Scan for Trezor devices
Select device from list
Pair and connect
Maintain connection for operations
import { useBluetooth } from '@suite-native/bluetooth' ;
const { devices , connect , isConnected } = useBluetooth ();
// Scan for devices
const trezorDevices = devices . filter ( d =>
d . name ?. includes ( 'Trezor' )
);
// Connect
await connect ( trezorDevices [ 0 ]);
Bluetooth works on both iOS and Android for compatible Trezor models.
Watch-only mode without device: Features :
Import accounts via XPUBs
View balances and transactions
Track portfolio value
No sending capability
Use cases :
iOS users (no USB support)
Portfolio monitoring
Public account tracking
import { addWatchOnlyAccount } from '@suite-native/accounts' ;
// Add account by XPUB
dispatch ( addWatchOnlyAccount ({
coin: 'btc' ,
xpub: 'xpub6...' ,
}));
Unique Android Features :
USB Device Connection : Direct USB-C or OTG
Background Services : Transaction monitoring
Widgets : Portfolio at-a-glance (future)
Deep Links : QR code / link handling
Configuration : android/app/src/main/AndroidManifest.xmlUnique iOS Features :
Face ID / Touch ID : Native biometric auth
Haptic Engine : Premium haptic feedback
Siri Shortcuts : Voice commands (future)
iCloud Sync : Settings backup (future)
Configuration : ios/TrezorSuite/Info.plist
Build & Release
Development Builds
Local Development Build
EAS Build
Ad-hoc builds for testing :# Build development client
yarn workspace @suite-native/app prebuild:clean
yarn workspace @suite-native/app android
# or
yarn workspace @suite-native/app ios
Includes:
Dev menu (shake gesture)
Fast Refresh
Debug logging
Expo DevTools
Cloud builds via Expo Application Services :# Build for testing
yarn native:adhoc
# Or with EAS directly
npx eas-cli build --profile adhoc --platform android
npx eas-cli build --profile adhoc --platform ios
Profiles in eas.json:
development: Dev client
adhoc: Internal testing
preview: Pre-release testing
production: App store builds
Environment Variables
Configure via .env files:
# .env.development.local
EXPO_PUBLIC_IS_SENTRY_ON_DEBUG_BUILD_ENABLED = true
EXPO_PUBLIC_IS_NATIVE_USB_LOGGER_ENABLED = true
EXPO_PUBLIC_IS_NATIVE_BLUETOOTH_LOGGER_ENABLED = true
# Feature flags
EXPO_PUBLIC_FF_TRADING_ENABLED = true
EXPO_PUBLIC_FF_STAKING_ENABLED = false
See Environment variables in Expo for details.
Runtime Version
When changing native code, bump runtimeVersion in app.config.ts:
export default {
// ...
runtimeVersion: '1.2.0' , // Increment this
}
Expo uses runtime version to determine if OTA updates are compatible with installed app.
Production Release
Prepare Release
# Update version
cd suite-native/app
npm version patch # or minor/major
# Run release script
cd ../..
./scripts/prepare-mobile-release.sh
Build for Stores
# iOS App Store
npx eas-cli build --profile production --platform ios
# Google Play Store
npx eas-cli build --profile production --platform android
Submit to Stores
# iOS
npx eas-cli submit --platform ios
# Android
npx eas-cli submit --platform android
Deploy OTA Update (Optional)
# Push update to existing builds
npx eas-cli update --branch production
Testing
Unit Tests
# Run all unit tests
yarn workspace @suite-native/app test:unit
# Watch mode
yarn workspace @suite-native/app test:unit --watch
# Coverage
yarn workspace @suite-native/app test:unit --coverage
E2E Tests (Detox)
# Build test app
yarn workspace @suite-native/app build:e2e android.debug
# Run tests
yarn workspace @suite-native/app test:e2e:android
# or
yarn workspace @suite-native/app test:e2e:ios
See suite-native E2E docs for details.
Debugging
Shake device or press:
Android : Ctrl+M (emulator) or shake
iOS : Cmd+D (simulator) or shake
Options :
Reload
Debug with Chrome
Toggle Performance Monitor
Show Inspector
Enable Fast Refresh
React Native Debugger
Install
brew install react-native-debugger
# or download from GitHub releases
Launch
open -a "React Native Debugger"
Connect
In debug menu, select “Debug”
Logging
import { logger } from '@suite-native/utils' ;
logger . debug ( 'Debug message' );
logger . info ( 'Info message' );
logger . warn ( 'Warning message' );
logger . error ( 'Error message' );
Environment flags :
# Enable USB transport logging
EXPO_PUBLIC_IS_NATIVE_USB_LOGGER_ENABLED = true
# Enable Bluetooth logging
EXPO_PUBLIC_IS_NATIVE_BLUETOOTH_LOGGER_ENABLED = true
Hermes Engine JavaScript engine optimized for React Native
Flash List High-performance list component (@shopify/flash-list)
Reanimated 3 Smooth animations running on UI thread
MMKV Storage Fast native key-value storage
Optimization Techniques
List Rendering
Animations
Memoization
import { FlashList } from '@shopify/flash-list' ;
< FlashList
data = { transactions }
renderItem = {({ item }) => <TransactionItem item = { item } /> }
estimatedItemSize = { 80 }
// Optimized for performance
/>
import Animated , { useSharedValue , withSpring } from 'react-native-reanimated' ;
const AnimatedComponent = () => {
const offset = useSharedValue ( 0 );
const animatedStyle = useAnimatedStyle (() => ({
transform: [{ translateY: withSpring ( offset . value ) }],
}));
return < Animated . View style ={ animatedStyle } />;
};
import { memo , useMemo } from 'react' ;
const ExpensiveComponent = memo (({ data }) => {
const processedData = useMemo (
() => heavyComputation ( data ),
[ data ]
);
return < View >{ /* render */ } </ View > ;
});
Troubleshooting
# Clean everything
yarn native:prebuild:clean
# Clear Metro cache
yarn native:start --reset-cache
# Clear Gradle cache (Android)
cd suite-native/app/android
./gradlew clean
# Clear Pods (iOS)
cd suite-native/app/ios
pod deintegrate
pod install
# Clear watchman
watchman watch-del-all
# Restart Metro
yarn native:start --reset-cache
Android :
Check USB debugging enabled
Run adb devices to verify connection
Try different USB cable
iOS :
Trust computer on device
Check Developer Mode enabled (iOS 16+)
Rebuild with Xcode
# Rebuild native code
yarn native:prebuild:clean
# Android
yarn native:android
# iOS - reinstall pods
cd suite-native/app/ios
pod install
cd ../../..
yarn native:ios
DEV Utils
Access developer menu in production builds (for development purposes only):
Go to Settings → About
Tap commit hash 7+ times
DEV utils menu appears
Features :
Feature flags toggle
Backend URL override
Connect device emulator
Debug overlays
Test notifications
DEV utils are for development only. Do not use with real wallets!
Key Differences: Mobile vs Desktop/Web
Feature Mobile Desktop Web Platform iOS/Android Windows/macOS/Linux Browser Framework React Native Electron React Device Connection USB (Android), BT USB/HID WebUSB Offline Support Partial Full No Biometrics Yes No No Notifications Yes No No Camera Yes No No File System Limited Full Very limited
Resources
React Native Docs Official React Native documentation
Expo Docs Expo SDK and EAS documentation
GitHub Repository Suite Native source code
Contributing Contribution guidelines
Next Steps
Monorepo Structure Understand the overall structure
Suite Desktop Compare with desktop architecture
Suite Web Compare with web architecture
Quick Start Get started with development