Upstream merge brings 52 commits from safe-global/safe-wallet-monorepo into the luxfi/safe-wallet@dev fork. Conflicts resolved: - yarn.lock: deleted (we are on pnpm) - apps/web/package.json: kept pnpm version + brand build scripts (build:safe / build:lux / build:hanzo) plus upstream's new generate-version.mjs step - apps/mobile/.../Signer/appKit.ts: took upstream's import pattern for shared/projectId, shared/metadata, shared/mmkvStorageAdapter Yarn sweep applied to 42 files (docs, github-actions, workflows, AGENTS, specs, codemods, scripts, READMEs). Net result: zero yarn-* command references anywhere outside node_modules. ❯ pnpm is the law in this fork. No yarn.
Safe{Mobile} app 📱
This project is now part of the @safe-global/safe-wallet monorepo! The monorepo setup allows centralized management
of multiple
applications and shared libraries. This workspace (apps/mobile) contains the Safe Mobile App.
You can run commands for this workspace in two ways:
- From the root of the monorepo using
pnpm --filtercommands - From within the
apps/mobiledirectory
Prerequisites
In the addition to the monorepo prerequisites, the mobile app requires the following:
- Expo CLI
- iOS/Android Development Tools
- Maestro if you want to run E2E tests
You can follow the expo documentation to install the CLI and set up your development environment.
Follow the Maestro documentation to install the tool for E2E testing.
Setup the project
- Install all dependencies from the root of the monorepo:
pnpm install
Running the app
There is a .env.example file in the root of the mobile app. Create a .env.local file and paste the contents of the .env.example
file into it and set the correct values for the environment variables.
For local development you need to place the google-services.json and GoogleService-Info.plist files in the root of
the mobile app.
If you use EAS to manage your environement variables you can issue the
eas env:pull
command. This will pull the variables from your eas project and place them in the .env.local file.
Running on iOS
From the root of the monorepo:
pnpm --filter @safe-global/mobile start:ios
Or directly from the apps/mobile directory:
pnpm start:ios
Note
From now on for brevity we will only show the command to run from the root of the monorepo. You can always run the command from the
apps/mobiledirectory you just need to omit theworkspace @safe-global/mobile.
Running on Android
From the root of the monorepo:
pnpm --filter @safe-global/mobile start:android
How to open the custom devtools menu
The app supports Redux, RTK Query, and React DevTools. To access these tools:
- Run the app.
- In the terminal where the Expo server is running, press
Shift + M. - Select the desired DevTools option for debugging. Happy debugging! 👨💻👩💻
Running the Storybook
Running in the browser
Run the storybook command from the root:
pnpm --filter @safe-global/mobile storybook:web
Running on a mobile device
To run the storybook on a mobile device:
pnpm --filter @safe-global/mobile storybook:[ios|android]
To View stories press i on iOS or a on Android.
How to run the E2E Tests
We use Maestro for E2E testing. Before running tests, install Maestro following the documentation for your OS.
Configure env variables
Maestro tests rely on environment variables that must be set before running tests. The
app-start.yml utility provides sensible defaults when variables are unset, but Maestro Studio does not read defaults from YAML files, so you must pass them explicitly.
| Variable | Description | iOS (production) | iOS (dev) | Android (production) | Android (dev) |
|---|---|---|---|---|---|
APP_ID |
Bundle / package identifier of the installed app | global.safe.mobileapp.ios |
global.safe.mobileapp.ios.dev |
global.safe.mobileapp |
global.safe.mobileapp.dev |
IS_DEV_MODE |
Set to "true" to dismiss dev-only dialogs on start |
false (default) |
true |
false (default) |
true |
SKIP_CLEAN_START |
Set to "true" to preserve app state between tests (used in suites) |
false (default) |
Tip
When
APP_IDis not set,app-start.ymldefaults to the production bundle ID for the current platform. If you built the app withAPP_VARIANT=development, you must pass the dev bundle ID or Maestro will hang at the "Launch app" step because it cannot find the app.
Run a dev build and E2E tests
To build the app for tests:
For iOS:
pnpm --filter @safe-global/mobile e2e:metro-ios
For Android:
pnpm --filter @safe-global/mobile e2e:metro-android
These commands include .e2e.ts|.e2e.tsx files for mocking services or adding test-specific code.
Run the tests
In a second terminal run:
pnpm --filter @safe-global/mobile e2e:run
Use Maestro Studio to write tests
To write tests with Maestro Studio, run:
maestro studio
Export the generated YAML file to the e2e folder and include it in the test suite.
Running E2E tests in CI
To run tests in CI, add the eas-build-ios:build-and-maestro-test label to a PR. This triggers the Expo CI pipeline to
execute the tests.
Unit tests
We use Jest and the React Native Testing Library for unit, component, and hook tests.
Run tests:
pnpm --filter @safe-global/mobile test
Run in watch mode:
pnpm --filter @safe-global/mobile test:watch
Check coverage:
pnpm --filter @safe-global/mobile test
Navigate to the coverage folder and open index.html in your browser.
Running ESLint & Prettier
This project uses ESLint, Prettier, and TypeScript for linting and formatting.
Run linting from the root:
pnpm --filter @safe-global/mobile lint
This command validates files with TypeScript, ESLint, and Prettier configurations.