Skip to content

Mojito ME: initial React Native implementation - #1

Merged
erubboli merged 4 commits into
mainfrom
feat/initial-mobile-ui
Aug 23, 2026
Merged

erubboli merged 4 commits into
mainfrom
feat/initial-mobile-ui

Conversation

@erubboli

Copy link
Copy Markdown
Member

Initial React Native implementation of Mojito ME, ported from the Mojito Wallet and
Onboarding Demo designs.

main is an empty root commit, so this PR's diff is the entire codebase — reviewing it here
rather than pushing straight to main.

What's in it

Area Screens
Onboarding Welcome · Secure · PIN set/confirm · Seed reveal · Verify · Import · Discovery · Draw entropy
Wallet Home · DEX
Trade Atomic Swap · Bridge · Card
Flows Send · Receive · Settings
App Splash · Unlock

Architecture

  • src/theme.js converts the designs' oklch palette to sRGB once and feeds both the runtime
    and tailwind.config.js — one source of colour, no literals in screens.
  • src/ui is the shared library. Screens compose it rather than re-implementing surfaces:
    TokenPicker serves Send/Swap/Bridge identically, SuccessScreen serves all three terminal
    states, one useLoop backs every animation.
  • src/onboarding owns the flow and its own nav stack.

Decisions worth reviewing

Seed phrase is never rendered until revealed. CSS blur has no RN equivalent — expo-blur
degrades to a flat tint on Android, and even a real blur leaves the words in the view tree for
accessibility services. Hidden cells render a fixed-width mask instead (fixed width so word length
doesn't leak). Verified via uiautomator: the dump shows only ••••••.

Screenshot protection is honest per platform. Android gets FLAG_SECURE (verified — the screen
captures black, and releases on unmount). iOS can't block screenshots, so it detects them and warns
rather than displaying a claim it can't keep.

The bridge can't express an unroutable pair. Mintlayer is always one endpoint; only the
counterparty is selectable. Ethereum → Arbitrum is unrepresentable, not validated after the fact.

Deliberate simplifications carry a ponytail: comment naming the ceiling and the upgrade path.

Not done

No backend, no chain connectivity, no key management — all data is fixtures, cryptography is
mocked, and the README says so prominently. Still unbuilt: Address book, QR scanner, Notifications,
Activity, Connected dApps, Manage networks, Edit profile, DEX Trades/Depth, NFTs/DeFi tabs.

There is no UI test suite — only a unit test for the colour conversion. Worth adding; a green
typecheck has missed real runtime breakage here (a modal that swallowed every touch typechecked and
bundled fine).

Verification

npm run check (theme test + tsc --noEmit + eslint .) passes, Android bundle builds, and the
flow was exercised on an Android 15 emulator: onboarding end-to-end, entropy capture, bridge picker,
success states.

Follow-ups for a reviewer to confirm

  • conduct@mintlayer.org in CODE_OF_CONDUCT.md is unverified — I inferred it.
    security@mintlayer.org and its PGP key are confirmed.
  • The PGP key expires 2028-05-31; SECURITY.md will need updating.

Ports the Mojito Wallet and Onboarding Demo designs into an Expo + NativeWind
app, built as a shared component library rather than per-screen markup.

Layout — one file per component
- src/ui/ holds 43 components, one per file, with index.tsx as a re-export
  barrel. The directory listing is the inventory, so "check whether it already
  exists before building it" is something a contributor can actually do.
- src/screens/ and src/onboarding/screens/ are one screen per file.
- src/onboarding/ui/ holds the onboarding-only components on the same basis.
- Shared prop types, lockout constants and chart maths sit in small named
  modules (types.ts, context.ts, style.ts, chart.ts) rather than a grab bag.

Architecture
- src/theme.js converts the designs' oklch palette to sRGB once and feeds both
  the runtime and tailwind.config.js, so there is a single source of colour.
- One useLoop hook backs every animation; TokenPicker serves Send, Swap and
  Bridge; SuccessScreen serves all three terminal states.

Security-relevant decisions
- The recovery phrase is never rendered until revealed. CSS blur has no RN
  equivalent (expo-blur is a flat tint on Android), and a blurred word is still
  in the view tree, so hidden cells render a fixed-width mask instead.
- Android applies FLAG_SECURE while the phrase is on screen; iOS cannot block
  screenshots, so it detects them and warns instead of claiming protection.
- The bridge makes an unroutable pair unrepresentable: Mintlayer is always one
  endpoint, and only the counterparty is selectable.

Repo setup: MIT licence, security policy with PGP key, CI running
test + types + lint, issue/PR templates, code of conduct.
@erubboli
erubboli force-pushed the feat/initial-mobile-ui branch from 41b443c to 43ed4cc Compare August 22, 2026 19:54
@erubboli
erubboli merged commit 4bca617 into main Aug 23, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants