The Capsule SDK for React Native allows you to easily integrate secure and scalable wallet functionalities into your mobile applications. This guide covers the installation, setup, and usage of the Capsule SDK.

Prerequisites

To use Capsule, you need an API key. This key authenticates your requests to Capsule services and is essential for integration.

Don’t have an API key yet? Request access to the Developer Portal to create API keys, manage billing, teams, and more.

Dependency Installation

To get started with the Capsule SDK in your React Native project, install the required packages:

Here’s the more compact version:

Project Setup

Follow these steps to set up the Capsule SDK in your React Native environment:

1

Set Up Associated Domains

In order for passkeys to work, you need to set up associated domains in your Xcode project linked to the Capsule domain.

  1. Open your project in Xcode
  2. Select your target and go to “Signing & Capabilities”
  3. Click ”+ Capability” and add “Associated Domains”
  4. Add the following domains:
    • webcredentials:app.beta.usecapsule.com
    • webcredentials:app.usecapsule.com

For additional information on associated domains, refer to the Apple Developer documentation.

Important: Your teamId + bundleIdentifier must be registered with the Capsule team to set up associated domains. For example, if your Team ID is A1B2C3D4E5 and Bundle Identifier is com.yourdomain.yourapp, provide A1B2C3D4E5.com.yourdomain.yourapp to Capsule. This is required by Apple for passkey security. Note: Allow up to 24 hours for domain propagation.

2

iOS Additional Setup

iOS requires an additional setup of installing CocoaPods. Many dependencies require native code installation via CocoaPods to work correctly. To install CocoaPods, run the following commands in your project root:

cd ios
bundle install
bundle exec pod install
cd ..

It’s important to rerun pod install every time you add a new dependency to your project. Pods references the package.json file to install the required dependencies.

3

Configure Polyfills and Shims

React Native does not provide a built-in support for many modules like crypto, buffer, and process that are required by the Capsule SDK. To add support for these modules, you need to configure polyfills and shims in your project to make them available.

  1. Configure Metro bundler: Create or update metro.config.js in your project root to include the required modules:
metro.config.js
const { getDefaultConfig, mergeConfig } = require("@react-native/metro-config");
const nodeLibs = require("node-libs-react-native");

const config = {
  resolver: {
    extraNodeModules: {
      ...nodeLibs,
      crypto: require.resolve("react-native-quick-crypto"),
      buffer: require.resolve("@craftzdog/react-native-buffer"),
    },
  },
};

module.exports = mergeConfig(getDefaultConfig(__dirname), config);

You can replace any of the modules with your preferred alternatives if needed.

  1. Create a shim.js file in your project root and add the following code:
shim.js
if (typeof process === "undefined") {
  global.process = require("process");
} else {
  const bProcess = require("process");
  for (var p in bProcess) {
    if (!(p in process)) {
      process[p] = bProcess[p];
    }
  }
}

require("@usecapsule/react-native-wallet").shim();
  1. Now import the shim.js file in your root component or entry file:
index.js
import "./shim";
// Other imports...

Important: The shim.js file must be imported before any other imports in your project to ensure that the required modules are available.

4

Add WebView Crypto Polyfill

Import and add the PolyfillCrypto component from react-native-webview-crypto to your root component or entry file:

import PolyfillCrypto from "react-native-webview-crypto";

export default function App() {
  return (
    <>
      <PolyfillCrypto />
      {/* Your app components */}
    </>
  );
}

The PolyfillCrypto component must be added before any other components in your app to ensure that the crypto.sublte API is available.

When running your application if you see any errors related to missing modules, make sure to check the polyfills and shims setup in your project. For additional troubleshooting steps, refer to our troubleshooting guide.

Using the Capsule SDK

The Capsule SDK provides two main authentication flows: creating a new user and logging in an existing user. Both flows utilize Native Passkeys for secure and seamless authentication. Follow the steps below to implement these flows in your React Native application.

Beta Testing Credentials In the BETA Environment, you can use any email ending in @test.usecapsule.com (like dev@test.usecapsule.com) or US phone numbers (+1) in the format (area code)-555-xxxx (like (425)-555-1234). Any OTP code will work for verification with these test credentials. These credentials are for beta testing only. You can delete test users anytime in the beta developer console to free up user slots.

Create New User

This flow guides you through the process of registering a new user, verifying their email, and setting up their wallet.

1

Initialize Capsule Client

First, set up the Capsule client to enable SDK interactions:

import { CapsuleMobile, Environment } from '@usecapsule/react-native-wallet';

const capsule = new CapsuleMobile(Environment.BETA, YOUR_API_KEY);

Capsule offers two hosted environments: Environment.BETA (alias Environment.DEVELOPMENT) for testing, and Environment.PROD (alias Environment.PRODUCTION) for live use. Select the environment that matches your current development phase.

2

Register New User

Create a new user account by calling the createUser method. This will automatically send a verification email to the user:

const handleCreateUser = async (email: string): Promise<void> => {
  try {
    await capsule.createUser(email);
    console.log("User created. Verification email sent.");
  } catch (error) {
    console.error("Error creating user:", error);
  }
};
3

Verify Email

Once the user receives the verification code, call the verifyEmailBiometricsId method to confirm their email:

const handleVerifyEmail = async (code: string): Promise<string | undefined> => {
  try {
    const biometricsId = await capsule.verifyEmailBiometricsId(code);
    console.log("Email verified successfully");
    return biometricsId;
  } catch (error) {
    console.error("Error verifying email:", error);
  }
};
4

Register Passkey and Create Wallet

Use the returned biometricsId to register the user’s passkey and create their wallet:

import { webcrypto } from 'crypto';

const handleRegisterPasskeyAndCreateWallet = async (email: string, biometricsId: string): Promise<{ wallets: any, recoverySecret: string } | undefined> => {
  try {
    await capsule.registerPasskey(email, biometricsId, webcrypto);
    console.log("Passkey registered successfully");
    const { wallets, recoverySecret } = await capsule.createWalletPerMissingType(false);
    console.log("User wallet created");
    return { wallets, recoverySecret };
  } catch (error) {
    console.error("Error registering passkey or creating wallet:", error);
  }
};
5

Complete New User Flow

Implement the full flow by combining all the previous steps:

const handleNewUserFlow = async (email: string, verificationCode: string): Promise<void> => {
  await handleCreateUser(email);
  const biometricsId = await handleVerifyEmail(verificationCode);
  if (biometricsId) {
    const result = await handleRegisterPasskeyAndCreateWallet(email, biometricsId);
    if (result) {
      console.log("Wallet created:", result.wallets);
      console.log("Recovery Secret:", result.recoverySecret);
      // Securely display or store the recovery secret for the user
    }
  }
};

It’s crucial to securely share the recoverySecret with the user. This secret is necessary for account recovery in case the user loses access to their device. Ensure you have a secure method to display or store this secret for the user.

Login Existing User

This flow demonstrates how to authenticate an existing user using their email and passkey.

1

Initialize Capsule Client

Ensure the Capsule client is set up (if not already done):

import { CapsuleMobile, Environment } from '@usecapsule/react-native-wallet';

const capsule = new CapsuleMobile(Environment.BETA, YOUR_API_KEY);
2

Check User Existence and Login

Verify if the user exists and log them in using their passkey:

const handleLogin = async (email: string): Promise<void> => {
  try {
    const userExists = await capsule.checkIfUserExists(email);
    if (userExists) {
      await capsule.login();
      console.log("User logged in successfully");
    } else {
      console.log("User does not exist. Please create a new account.");
    }
  } catch (error) {
    console.error("Login error:", error);
  }
};

The login method allows passing in an email if you want to specifically select a passkey for that email. If no email is provided, the user will be prompted to select a passkey from the available options.

By following these steps, you can implement a secure and user-friendly authentication system in your React Native application using the Capsule SDK.

Examples

For practical implementation of the Capsule SDK in React Native environments, check out our GitHub repository:

Next Steps

After integrating Capsule, you can explore other features and integrations to enhance your Capsule experience. Here are some resources to help you get started:

Ecosystems

Learn how to use Capsule with popular Web3 clients and wallet connectors. We’ll cover integration with key libraries for EVM, Solana, and Cosmos ecosystems.

If you’re ready to go live with your Capsule integration, make sure to review our go-live checklist:

Troubleshooting

If you encounter issues during the integration or usage of the Capsule SDK in your React Native application, here are some common problems and their solutions:

For a more comprehensive list of solutions, visit our troubleshooting guide:

Integration Support

If you’re experiencing issues that aren’t resolved by our troubleshooting resources, please contact our team for assistance. To help us resolve your issue quickly, please include the following information in your request:

  1. 1

    A detailed description of the problem you’re encountering.

  2. 2

    Any relevant error messages or logs.

  3. 3

    Steps to reproduce the issue.

  4. 4

    Details about your system or environment (e.g., device, operating system, software version).

Providing this information will enable our team to address your concerns more efficiently.