Follow these steps to get your environment set up for using Smart Wallets within a React Native application on Expo.
- React Native version 0.76 or later
- iOS minimum deployment target: 17.0
- Hermes and Fabric must be enabled (if using Expo these are on by default)
- The authentication package requires React Native's new architecture. For information on how to enable it in your Expo project, see the documentation.
- The authentication package is incompatible with Expo Go, so you need to use a Development Build. See the Expo Development Builds documentation for more information.
If you don't have an Expo project setup, you can create one using the following command:
npx create-expo-app@latestMake sure you are on the latest version of Expo (SDK 52 or later). React Native version 0.76 or higher is required because it has TextEncoder natively supported.
For more information on upgrading an Expo project, check out the Expo documentation.
npx expo install expo@latestYou can also use the quickstart template to get started quickly. Run
npx create-expo-app@latest --template https://github.com/alchemyplatform/account-kit-expo-quickstartThen you want to upgrade all dependencies to match the new Expo SDK version.
npx expo install --fixOnce the Expo project is set up and running, set up a few shims so you can use crypto libraries in React Native.
npm install --save node-libs-react-native crypto-browserify stream-browserify react-native-get-random-valuesCreate or edit your metro.config.js file in the root of your project so that it includes the following:
// Learn more https://docs.expo.io/guides/customizing-metro
const { getDefaultConfig } = require("expo/metro-config");
const path = require("path");
const fs = require("fs");
const projectRoot = __dirname; // <-- Adjust this as fits your project setup
// Add aliases for file-system import based modules
const ALIASES = {
"@noble/hashes/crypto": path.resolve(
projectRoot,
"node_modules/@noble/hashes/crypto.js",
),
"@sinclair/typebox": path.resolve(
projectRoot,
"node_modules/@sinclair/typebox/build/cjs/index.js",
),
};
/** @type {import('expo/metro-config').MetroConfig} */
const config = getDefaultConfig(projectRoot);
// [!code focus:9]
// The following code ensures we have the necessary
// shims for crypto built into our project
config.resolver.extraNodeModules = {
...config.resolver.extraNodeModules,
...require("node-libs-react-native"),
crypto: require.resolve("crypto-browserify"),
stream: require.resolve("stream-browserify"),
};
config.resolver.resolveRequest = (context, moduleName, platform) => {
if (ALIASES[moduleName]) {
return {
filePath: ALIASES[moduleName],
type: "sourceFile",
};
}
// Handle .js/.jsx extensions on TypeScript files
if (
(moduleName.startsWith(".") || moduleName.startsWith("/")) &&
(moduleName.endsWith(".js") || moduleName.endsWith(".jsx"))
) {
const moduleFilePath = path.resolve(
context.originModulePath,
"..",
moduleName,
);
// if the file exists, we won't remove extension, and we'll fall back to normal resolution.
if (!fs.existsSync(moduleFilePath)) {
return context.resolveRequest(
context,
moduleName.replace(/\.[^/.]+$/, ""),
platform,
);
}
}
return context.resolveRequest(context, moduleName, platform);
};
// The `account-kit/react-native` and it's supoorting packages leverages package.json `exports` which is not (yet) suported by default in Metro.
// we can enable this support using:
config.resolver.unstable_enablePackageExports = true;
config.resolver.unstable_conditionNames = [
"browser",
"require",
"react-native",
];
module.exports = config;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.
import "node-libs-react-native/globals.js";
import "react-native-get-random-values";
// rest of App.tsxThat's it! Now install the packages you want from Smart Wallets and start building your React Native 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:
"module": "NodeNext",
"moduleResolution": "nodenext",npm install --save @account-kit/react-native @account-kit/smart-contracts @account-kit/infra @account-kit/react-native-signerTo ensure the authentication package works correctly, add the following dependencies to your project:
npm install --save react-native-mmkv zustand abitype react-native-inappbrowser-reborn viem wagmi @tanstack/react-queryThe 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:
module.exports = function (api) {
api.cache(true);
return {
presets: [["babel-preset-expo", { unstable_transformImportMeta: true }]],
};
};Since a minimum deployment target of iOS 17 is required, instruct Expo to set this during pre-build. First, install expo-build-properties via:
npx expo install expo-build-propertiesThen add the plugin to your app.json:
// app.json
{
"expo": {
"plugins": [
[
"expo-build-properties",
{
"ios": {
"deploymentTarget": "17.0"
}
}
]
]
}
}Now that everything is set up, run a prebuild to ensure the native modules are properly built and added to your project.
npx expo prebuild --platform androidBecause 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 androidIf you get this error, you can add the following to you app.json within the expo config:
"extra": {
"router": {
"origin": false
}
}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:
allprojects {
configurations.all {
resolutionStrategy {
// Force a specific version of androidx.browser
force 'androidx.browser:browser:1.8.0'
}
}
}Related issue: https://github.com/alchemyplatform/aa-sdk/issues/1534
The 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, you will likely get errors about peer dependencies. To force a consistent version of React, add the following to your package.json:
"overrides": {
"react": "19.0.0",
"react-dom": "19.0.0"
}Move on to app integration!