Sitemap

Building A Mobile EVM Wallet With React Native

Understanding The Tech Behind Building A Mobile Blockchain Application

--

Press enter or click to view image in full size
Building An iOS Mobile Wallet with React Native

The goal of this article isn’t to go through step-by-step building the application (you can do that with AI), but more so understanding the tech needed to build a mobile iOS app for an EVM wallet so that it can help you build one in the future.

Press enter or click to view image in full size
EVM iOS Wallet

For the sake of this article, we’ll be focusing specifically on iOS to understand its features, limitations and work arounds.

The functionality we’ll limit ourselves to are:

1 — Setup and manage a new wallet with a passphrase

2 — Backup the passphrase

3 — Add an RPC

4 — Retrieve Balance

5 — Transfer Transaction

Why React Native & Expo

Press enter or click to view image in full size
React Native & Expo

React Native lets you write your UI once in JavaScript and ship to both iOS and Android. When it comes to a wallet app, the real selling point is the update model. Native Swift apps must go through Apple’s review process for every change, which can take days. React Native (especially with Expo’s over-the-air updates via EAS Update) lets you push JS-layer fixes instantly, without a new App Store submission. For a wallet, where a bug could mean lost funds, that matters enormously.

Expo specifically adds a lot out of the box: expo-secure-store for Keychain access, expo-local-authentication for biometrics, and a managed build pipeline (EAS Build) that handles the notoriously painful iOS signing and provisioning certificates. You get a familiar React development experience instead of learning Swift and UIKit from scratch.

The tradeoff can be rough though. React Native has a reputation for being finicky. Native modules occasionally break between Expo SDK versions, the Metro bundler has its quirks, and you’ll hit moments where something works on Android but not iOS or vice versa. The bridge between JS and native code also adds a thin layer of complexity when you’re doing security-sensitive work.

Factoring this all in, most production mobile wallets have made exactly this bet. Rainbow Wallet and Coinbase Wallet SDK are all built on React Native.

What’s Not So Simple

Features 1, 3, and 4 are straight forward in terms of their functionality when prompting most LLMs. Backing up a passphrase and interacting with it correctly is the complicated part. Correctly in this case is securely, or as secure as possible.

iCloud Backup & Keychain

Press enter or click to view image in full size
iCloud Backup & Keychain

The naive approach to backing up a seed phrase seems simple: save it to iCloud or store it in the iOS Keychain, and retrieve it when needed. The problem is how you retrieve it; it’s in plain text.

iCloud Drive storage is essentially a synced filesystem. A file containing your 12-word mnemonic would sit on Apple’s servers, sync to every signed-in device, and be readable by your app (and anything that can compromise your app) as a raw string. That’s not a backup strategy; it’s a liability.

The iOS Keychain is better. It’s encrypted storage tied to your app’s bundle identifier, sandboxed from other apps, and persistent across reinstalls. You can gate items with kSecAttrAccessible flags like WhenUnlockedThisDeviceOnly to prevent the item from being included in unencrypted backups or read on other devices. You can even add kSecAccessControl with a biometric requirement so that reading the item triggers a Face ID prompt.

There’s still a fundamental ceiling here. When your app reads a Keychain item, the raw bytes surface in app memory. At that moment, a compromised JavaScript bundle, a malicious dependency in your node_modules, or a memory-inspection attack could exfiltrate the mnemonic. While Keychain is a good base, it’s ultimately not the final solution itself.

Apple On-Device Secure Enclave

Press enter or click to view image in full size
Apple Secure Enclave (SE)

Apple’s answer to the memory-exposure problem is the Secure Enclave (SE), which is a dedicated security coprocessor built into every iPhone since the 5s, isolated from the main application processor.

The key design principle: private keys generated inside the SE never leave it. Your application never holds the private key in memory. Instead, you send data to the SE, the SE performs the cryptographic operation (signing, decryption), and returns only the result. Even if your app, the OS, or the entire file system is compromised, the SE’s keys remain inaccessible.

Press enter or click to view image in full size
Secure Enclave Sequence Diagram

The SE has its own encrypted memory, a hardware random number generator, and runs its own microkernel. When you require biometric authentication to use an SE key, the biometric check happens inside the SE itself and not in the OS where it could be spoofed. It’s the closest thing to a hardware wallet built into your phone.

Supported Cryptographic Algorithm Elliptical Curves

Press enter or click to view image in full size
Elliptical Curves

Here’s where EVM wallet development hits its biggest wall. The Secure Enclave only supports ECDSA on the NIST P-256 curve (kSecAttrKeyTypeECSECPrimeRandom). It does not support:

  • secp256k1 — the elliptic curve used by Ethereum and Bitcoin ❌
  • ed25519 — used by Solana ❌
  • Arbitrary data storage — you can’t put a 24-word mnemonic inside the SE ❌

You cannot put an Ethereum private key inside the Secure Enclave and have it sign transactions directly. The SE will simply refuse. This is the single biggest constraint in iOS wallet design, and it forces every major mobile wallet into the same architectural workaround.

Encryption Workaround

Since we can’t store secp256k1 keys in the SE directly, we use the SE for what it does support, which is to use that capability to protect what we actually need to store. This is the pattern used by most wallets.

Press enter or click to view image in full size
Encryption Workaround

The SE-wrapped encryption key pattern:

  1. Generate a P-256 keypair inside the Secure Enclave, gated by biometric authentication. The private key never leaves the SE.
  2. Generate an AES-256 symmetric key (the “wrapping key”) and store it in the Keychain.
  3. Encrypt the wrapping key using the SE’s P-256 public key. Store the ciphertext.
  4. Encrypt your mnemonic / secp256k1 private keys with the AES key. Store the ciphertext in Keychain or on disk.

To sign an Ethereum transaction:

Biometric prompt triggers → SE unwraps the AES key → AES key decrypts the mnemonic → derive the secp256k1 private key → sign → immediately zero the memory.

The mnemonic is in plaintext for milliseconds, only after a successful biometric prompt, and the root of trust (the SE keypair) is hardware-bound and non-exportable. No amount of JS compromise can extract the SE key.

iOS Simulator Limitations

Press enter or click to view image in full size
iOS Simulator

The iOS Simulator runs on your Mac’s x86/ARM processor, which means it doesn’t have a Secure Enclave. Biometric APIs exist in the Simulator, but Face ID is simulated (you trigger it via the menu: Features → Face ID → Matching Face) and kSecAttrTokenIDSecureEnclave operations simply fail or are silently downgraded.

This means you need two code paths:

  • Simulator: Fall back to standard Keychain storage without SE-backed keys. You can use expo-secure-store directly, or generate a software P-256 key stored in Keychain as a stand-in.
  • Physical device: Full SE-backed key generation with real biometric gating. NOTE: Due to the additional native modules needed, an Apple Paid Developer account is needed to build and deploy on your device for testing.

In practice, you’d detect this with a runtime check (expo-device's isDevice flag), or wrapping SE key generation in a try/catch that falls back gracefully. Flag your simulator builds clearly in development so you never accidentally test security-critical paths against the fake implementation.

The only way to properly test the full security model is to use real SE keys, real biometrics, and real attestation and load the app onto a physical iPhone via EAS Build or Xcode.

Next Steps

A few natural directions from here:

WalletConnect integration — letting the wallet connect to dApps via QR code is the feature that makes it actually useful day-to-day. The @walletconnect/web3wallet SDK handles the session management; the tricky part is routing signing requests back through your SE-wrapped key pipeline.

Transaction history — querying an indexer or a block explorer API gives you a proper activity feed without running your own node.

Push notifications for incoming transactions — requires a backend listener (or a webhook from a web service), but transforms the app from a read/sign tool into something that feels live.

If you want to build more on Berachain and see more examples. Take a look at our Berachain GitHub Guides Repo for a wide variety of implementations that include NextJS, Hardhat, Viem, Foundry, and more.

❤️ Don’t forget to show some love for this article 👏🏼.

--

--

Manny
Manny

Written by Manny

DevRel Engineer @ Berachain | Prev Polygon | Ankr & Web Application / Full Stack Developer