Skip to main content

Development Server

Start the Expo development server with the dev client:
pnpm start
This command starts the Metro bundler and opens the Expo DevTools. You can then:
  • Press i to open iOS simulator
  • Press a to open Android emulator
  • Scan the QR code with Expo Go app (development builds only)
The development server runs on the default Expo port. The app uses a custom dev client, so you’ll need to build it first (see below).

Running on iOS

iOS development requires a Mac with Xcode installed.

Development Build

Run the app on iOS simulator or connected device:
1

Start iOS simulator

Open Xcode and launch a simulator, or connect a physical iOS device.
2

Run the development build

pnpm ios
This command:
  1. Builds the native iOS app
  2. Installs it on the simulator/device
  3. Starts the Metro bundler
  4. Opens the app automatically

iOS Simulator Selection

To run on a specific simulator:
# List available simulators
xcrun simctl list devices

# Run on specific simulator
pnpm ios --simulator="iPhone 15 Pro"

iOS Device Configuration

The app is configured with:
  • Bundle Identifier: bz.medusa.wallet
  • Supports iPad: Yes
  • Orientation: Portrait only
  • Required Capabilities: Camera, Face ID
Check app.json for the complete iOS configuration:
"ios": {
  "supportsTablet": true,
  "bundleIdentifier": "bz.medusa.wallet"
}

Running on Android

Development Build

Run the app on Android emulator or connected device:
1

Start Android emulator

Launch an Android Virtual Device (AVD) from Android Studio, or connect a physical Android device with USB debugging enabled.
2

Run the development build

pnpm android
This command:
  1. Builds the native Android app
  2. Installs it on the emulator/device
  3. Starts the Metro bundler on port 8082
  4. Opens the app automatically
The Android script uses a custom port (8082) to avoid conflicts:
"android": "expo run:android --port 8082"

Android Device Configuration

The app is configured with:
  • Package Name: bz.medusa.wallet
  • Version Code: 3
  • Target SDK: Latest (via Expo)
  • Permissions: Camera
  • Status Bar: Light content on dark background
"android": {
  "package": "bz.medusa.wallet",
  "versionCode": 3,
  "permissions": ["android.permission.CAMERA"],
  "adaptiveIcon": {
    "backgroundColor": "#0A0A0A"
  }
}

Android Emulator Tips

adb devices
You should see your emulator or device listed.
If the app can’t connect to Metro:
adb reverse tcp:8082 tcp:8082
adb shell pm clear bz.medusa.wallet
# View all logs
adb logcat

# Filter React Native logs
adb logcat | grep ReactNative

Platform Differences

When developing for both platforms, be aware of these differences:

iOS-Specific Features

  • Face ID: Configured with permission message
  • Haptics: Different feedback patterns
  • Status Bar: Managed by expo-status-bar
  • Safe Areas: Automatic handling for notches

iOS Configuration

// Platform-specific code
if (Platform.OS === 'ios') {
  // iOS-specific logic
}

Development Tools

React Query DevTools

The app includes React Query DevTools for debugging:
1

Enable DevTools

DevTools are automatically enabled in development mode:
// app/_layout.tsx
import { useReactQueryDevTools } from '@dev-plugins/react-query'

const queryClient = new QueryClient()
useReactQueryDevTools(queryClient)
2

Access DevTools

Open the Expo DevTools and navigate to the React Query panel to:
  • View active queries
  • Inspect cache state
  • Debug refetch behavior
  • Monitor network requests
Learn more about React Query DevTools in the Expo documentation.

Metro Bundler

The Metro bundler provides useful commands during development:

Reload App

Press r in the terminal

Open DevTools

Press d in the terminal

Toggle Element Inspector

Press i in the terminal

Clear Cache

Press Shift + r in the terminal

Remote Debugging

Debug JavaScript in Chrome DevTools:
  1. Shake your device (or press Cmd+D on iOS simulator / Cmd+M on Android emulator)
  2. Select “Debug” from the menu
  3. Chrome will open with DevTools
Remote debugging can cause performance issues. Use it only when necessary.

Code Quality

Ensure code quality before committing:
pnpm type-check

Pre-commit Workflow

Recommended workflow before committing:
# 1. Check types
pnpm type-check

# 2. Fix formatting
pnpm format:fix

# 3. Run linter
pnpm lint

# 4. Run tests
pnpm test

Production Builds

Production builds require EAS (Expo Application Services) configuration.

EAS Configuration

The app uses EAS for production builds:
// eas.json
{
  "build": {
    "development": {
      "developmentClient": true
    },
    "preview": {
      "distribution": "internal"
    },
    "production": {}
  }
}

Build Commands

# Development build
eas build --profile development --platform ios

# Production build
eas build --profile production --platform ios
EAS builds run on Expo’s servers. You’ll need an Expo account to use EAS Build.

Testing

Running Tests

The app includes unit and integration tests:
pnpm test

Test Structure

tests/
├── unit/
│   └── utils/              # Utility function tests
│       ├── wallet.test.ts
│       ├── format.test.ts
│       └── validation.test.ts
└── int/
    └── api/                # API integration tests
        └── medusa.test.ts

Writing Tests

Example test file:
import { formatBitcoin } from '@/utils/format'

describe('formatBitcoin', () => {
  it('should format satoshis correctly', () => {
    expect(formatBitcoin(100000000)).toBe('1.00000000')
  })
})

Troubleshooting

Clear the Metro cache:
pnpm start --clear
Or manually:
rm -rf node_modules/.cache
  1. Clean the build folder:
    cd ios
    xcodebuild clean
    cd ..
    
  2. Reinstall CocoaPods:
    cd ios
    rm -rf Pods Podfile.lock
    pod install
    cd ..
    
  3. Rebuild:
    pnpm ios
    
  1. Clean the Gradle cache:
    cd android
    ./gradlew clean
    cd ..
    
  2. Rebuild:
    pnpm android
    
Check the logs:iOS:
xcrun simctl spawn booted log stream --level debug
Android:
adb logcat
  1. Ensure you’re connected to the same network
  2. Restart Metro bundler
  3. Reload the app (r in terminal)

Performance Optimization

Use FlashList

Replace FlatList with @shopify/flash-list for better performance

Optimize Images

Use expo-image for optimized image loading

Memoization

Use React.memo() and useMemo() for expensive computations

Code Splitting

Lazy load components with React.lazy() and Suspense

Next Steps

Architecture

Learn about the app architecture

Contributing

Contribute to Medusa Wallet

Build docs developers (and LLMs) love