Getting started with Smart Wallets on Expo

We would go through the steps to get your environment setup for using Smart Wallets within a React Native application on Expo.

Pre-requisites

  • React Native version 0.76 or later
  • iOS Minumum Deployment Target: 17.0
  • Hermes and Fabric must be enabled (if using expo these are on by default)
  • The Signer package requires you to be on React Native’s new architecture. For information on how to enable it in your Expo project, check their documentation.
  • The Signer package is incompatible with Expo Go and as a result, you’d need to use a Development Build. Check the Expo Development Builds documentation for more information.

Create a new Expo project

If you don’t have an Expo project setup, you can create one using the following command:

$npx create-expo-app@latest

Upgrade to the latest version of Expo

The first thing we need to do is make sure we’re on the latest version of Expo (SDK 52 or later). The reason for this is that we need React Native version 0.76 or higher because it has TextEncoder natively supported.

For more information on upgrading an Expo project, check out the Expo documentation.

$npx expo install expo@latest

You can also use our quickstart template to get started quickly. Simply run

$npx create-expo-app@latest --template https://github.com/alchemyplatform/account-kit-expo-quickstart

Then you want to upgrade all dependencies to match the new Expo SDK version.

$npx expo install --fix

Set up shims

Once we’ve got our Expo project setup and running, we need to setup a few shims so we can use crypto libraries in React Native.

Install shim dependencies

$npm install --save node-libs-react-native crypto-browserify stream-browserify react-native-get-random-values

Register shim modules in Metro

Create or edit your metro.config.js file in the root of your project so that it includes the following:

metro.config.js
1// Learn more https://docs.expo.io/guides/customizing-metro
2const { getDefaultConfig } = require("expo/metro-config");
3const path = require("path");
4const projectRoot = __dirname;
5
6// Add aliases for file-system import based modules
7const ALIASES = {
8 "@noble/hashes/crypto": path.resolve(
9 projectRoot, // <-- Adjust this as fits your project setup
10 "node_modules/@noble/hashes/crypto.js",
11 ),
12};
13
14/** @type {import('expo/metro-config').MetroConfig} */
15const config = getDefaultConfig(__dirname);
16// [!code focus:9]
17// The following code ensures we have the necessary
18// shims for crypto built into our project
19config.resolver.extraNodeModules = {
20 ...config.resolver.extraNodeModules,
21 ...require("node-libs-react-native"),
22 crypto: require.resolve("crypto-browserify"),
23 stream: require.resolve("stream-browserify"),
24};
25
26config.resolver.resolveRequest = (context, moduleName, platform) => {
27 if (ALIASES[moduleName]) {
28 return {
29 filePath: ALIASES[moduleName],
30 type: "sourceFile",
31 };
32 }
33 return context.resolveRequest(context, moduleName, platform);
34};
35
36// The `account-kit/react-native` and it's supoorting packages leverages package.json `exports` which is not (yet) suported by default in Metro.
37// we can enable this support using:
38config.resolver.unstable_enablePackageExports = true;
39config.resolver.unstable_conditionNames = [
40 "browser",
41 "require",
42 "react-native",
43];
44
45module.exports = config;

Register global shims

Import the following packages at the topmost entry point of your app so that libraries that depend on globals like crypto have access to them.

If you are using expo-router, add the imports in your topmost _layout.tsx file in the app directory. However if you are using a different navigation library (e.g. react-navigation), add the imports in your topmost App.tsx file.

App.tsx or app/_layout.tsx
1import "node-libs-react-native/globals.js";
2import "react-native-get-random-values";
3
4// rest of App.tsx

Install Smart Wallets

That’s it! Now you can install the packages you want from Smart Wallets and start building your React Native Account Abstraction app.

If you get an error about mismatched peer dependencies for React, you can use --legacy-peer-deps in your install commands to avoid this error.

The @account-kit/react-native package is an ESM module. As such, have to add the following to your tsconfig.json’s compilerOptions:

1"module": "NodeNext",
2"moduleResolution": "nodenext",
$npm install --save @account-kit/react-native @account-kit/smart-contracts @account-kit/infra @account-kit/react-native-signer

Add supporting dependencies

To ensure the Signer package works correctly, you’ll need to add the following dependencies to your project:

$npm install --save react-native-mmkv zustand abitype react-native-inappbrowser-reborn viem wagmi @tanstack/react-query

The zustand library uses import.meta which is not supported in the latest version of Expo. To fix this, create a babel.config.js file with the following content:

1module.exports = function (api) {
2 api.cache(true);
3 return {
4 presets: [["babel-preset-expo", { unstable_transformImportMeta: true }]],
5 };
6};

Set iOS minimum deployment target

Since we require a minimum deployment target of iOS 17, you will need to instruct Expo to set this during pre-build. First, install expo-build-properties via:

$npx expo install expo-build-properties

Then add the plugin to your app.json:

1// app.json
2{
3 "expo": {
4 "plugins": [
5 [
6 "expo-build-properties",
7 {
8 "ios": {
9 "deploymentTarget": "17.0"
10 }
11 }
12 ]
13 ]
14 }
15}

Run a Prebuild!

Now that we’ve got everything setup, we can run a prebuild to ensure the native modules are properly built and added to your project.

$npx expo prebuild --platform android

Run the app

Because the app is using native modules, you cannot run it with expo go and instead need to use development builds. You can do this with the android and ios commands:

$npm run android

Common Issues

NotSupportedError: Cannot set “location”., js engine: hermes

If you get this error, you can add the following to you app.json within the expo config:

1"extra": {
2 "router": {
3 "origin": false
4 }
5}

Build error: androidx.browser:browser requires a higher Android Gradle Plugin (AGP) version or compileSdk version

If you get this error when running the Android app, you can fix this by updating the android/build.gradle to include the following override:

1allprojects {
2 configurations.all {
3 resolutionStrategy {
4 // Force a specific version of androidx.browser
5 force 'androidx.browser:browser:1.8.0'
6 }
7 }
8}

Related issue: https://github.com/alchemyplatform/aa-sdk/issues/1534

npm install fails due to mismatching peer dependencies

Our packages list a minimum version of React as 18.2.0, but the latest version of expo is on >=19. If you are using npm install it’s likely you’ll get errors about peer dependencies. To force a consistent version of react, you can add the following to your package.json:

1"overrides": {
2 "react": "19.0.0",
3 "react-dom": "19.0.0"
4}

Next steps

Now setup the signer!