# Install Fordefi's React Native SDK

## Prerequisites

- A React Native project using React Native 0.81 or later *with the New Architecture enabled*.
- Node.js 20.19.4, or later and npm.
- JDK 17 (required by React Native 0.73+ and by the Fordefi Android modules).
- Your Android project must use Kotlin 2.x — the SDK modules resolve `kotlinVersion` from your root `build.gradle`.
- npm read access (via an npm access token or organization invitation) provided by Fordefi support.
- Platform minimums:
  - Android 7.0 (API level 24) or later;
  - iOS 13 or later, or your React Native version's minimum, if higher.


## Expo

The SDK includes native code and cannot run in Expo Go. Expo projects must use a development build created with `npx expo prebuild` or EAS Build.

## Step 1: Authenticate with npm

npm access required
Your npm account or access token must be granted read access to the package. Contact Fordefi support to obtain access.

Use either of the following:

- An npm access token configured in your **user level** `~/.npmrc` (recommended, so credentials are never committed to source control):

```ini
//registry.npmjs.org/:_authToken=${FORDEFI_NPM_TOKEN}
```
- `npm login` using an npm account that has been granted access to the package.


Warning
If you add the `_authToken` line to your project's `.npmrc` instead of `~/.npmrc`, make sure the file is listed in `.gitignore` so the token is not committed to source control. For CI environments, inject the token via an environment variable as shown above.

## Step 2: Install the SDK

From the root of your React Native project, run:

```bash
npm i @fordefi/wallet-sdk-react-native
```

If you intend to use [Cloud backup](/waas/end-user-backup-and-recovery/encrypted-backup-cloud), you must also install:

```bash
npm i @fordefi/backup-provider-react-native
```

## Step 3: Configure the Android build

The SDK ships as an Android library module that resolves its build versions from your project. Add these to the root `android/build.gradle`:

```gradle
buildscript {
    ext {
        minSdkVersion = 24          // required floor — declared by the SDK itself
        compileSdkVersion = 36
        targetSdkVersion = 36
        buildToolsVersion = "36.0.0"
        kotlinVersion = "2.2.20"
    }
}
```

These `ext` properties are not optional. The Fordefi Gradle modules read `minSdkVersion`, `compileSdkVersion`, `targetSdkVersion` and `kotlinVersion` from your root project, and Gradle configuration fails if they are absent. `compileSdkVersion 36` additionally requires Android Gradle Plugin 8.9.1 or later (and Gradle 8.13+ if you are on AGP 8.12).

In `android/app/build.gradle`, set the Java toolchain to 17 and resolve the native library conflict:

```gradle
android {
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_17
        targetCompatibility JavaVersion.VERSION_17
    }
    kotlinOptions { jvmTarget = '17' }

    packagingOptions {
        pickFirst '**/libc++_shared.so'
        pickFirst '**/libfbjni.so'
    }
}
```

Java 17 is required — both SDK modules compile at 17. The `pickFirst` entries are needed because the SDK ships its own `jni` payload alongside React Native's; without them the build fails at assemble time on duplicate files.

In `android/gradle.properties`, enable the New Architecture and restrict the ABI list:

```properties
newArchEnabled=true
reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86_64
```

The SDK ships native libraries for `arm64-v8a`, `armeabi-v7a` and `x86_64`. There is no 32-bit `x86` build, so including `x86` in `reactNativeArchitectures` produces an app that builds successfully and then fails at runtime on 32-bit x86 emulators.

Finally, in `android/app/src/main/AndroidManifest.xml`:

```xml
<uses-permission android:name="android.permission.INTERNET" />

<application android:allowBackup="false" ...>
```

The SDK declares no permissions of its own, so your app must declare `INTERNET` — without it, failures surface as network or auth errors. Setting `allowBackup="false"` is strongly recommended: end-user key material lives in secure device storage and should not be captured in device backups.

You do **not** need to register anything in `MainApplication` or `MainActivity` — autolinking handles it. You also do **not** need R8/ProGuard keep rules for the SDK; it ships its own consumer ProGuard rules.

## Step 4: Configure the iOS build

Install the pods:

```bash
cd ios && pod install && cd ..
```

Requirements:

- Deployment target iOS 13.0 or later, or your React Native version's minimum, if higher.
- New Architecture enabled (`RCTNewArchEnabled` set to `true` in `Info.plist`; unconditional on React Native 0.82+).


No changes to `AppDelegate` are needed — the native module is registered by autolinking.

## Step 5: Additional setup for cloud backup

Skip this step unless you installed `@fordefi/backup-provider-react-native`. These requirements come from the cloud provider SDK, not the wallet SDK.

### Google Drive — Android

In `android/app/build.gradle`:

```gradle
dependencies {
    implementation 'com.google.android.gms:play-services-auth:20.7.0'
    implementation('com.google.api-client:google-api-client-android:2.2.0') {
        exclude group: 'org.apache.httpcomponents'
        exclude module: 'guava-jdk5'
    }
    implementation('com.google.apis:google-api-services-drive:v3-rev20230822-2.0.0') {
        exclude group: 'org.apache.httpcomponents'
        exclude module: 'guava-jdk5'
    }
    implementation('com.google.http-client:google-http-client-gson:1.43.3') {
        exclude group: 'org.apache.httpcomponents', module: 'httpclient'
        exclude group: 'org.apache.httpcomponents', module: 'httpcore'
    }
}
```

The exclusions are mandatory — without them the build fails on duplicate classes. The dependencies themselves are required by the backup SDK's Google Drive integration but are not bundled with it; omitting them fails at backup time with `NoClassDefFoundError`, not at build time.

These Google libraries also require extra packaging rules, so extend the `packagingOptions` block from Step 3:

```gradle
packagingOptions {
    pickFirst '**/libc++_shared.so'
    pickFirst '**/libfbjni.so'
    exclude 'META-INF/DEPENDENCIES'
    exclude 'META-INF/LICENSE'
    exclude 'META-INF/LICENSE.txt'
    exclude 'META-INF/NOTICE'
    exclude 'META-INF/NOTICE.txt'
    exclude 'META-INF/ASL2.0'
}
```

Set the launch mode on your main activity so the Google sign-in redirect returns to the running activity:

```xml
<activity android:name=".MainActivity" android:launchMode="singleTask" ... />
```

In the Google Cloud console: enable the Drive API, then create an **Android** OAuth client with your package name and the SHA-1 fingerprint of **every** signing key you use.

Warning
A missing release SHA-1 is the most common cause of backup working in development and failing in production.

### Google Drive — iOS

Install the CocoaPods plugin that allows per-pod build types (it is required because these two pods must be dynamic frameworks while the rest of the project stays static — stock CocoaPods cannot express per-pod build types):

```bash
sudo gem install cocoapods-user-defined-build-types
```

Then in `ios/Podfile`:

```ruby
plugin 'cocoapods-user-defined-build-types'

enable_user_defined_build_types!

target 'YourApp' do
  pod 'GoogleSignIn', '7.0.0', :build_type => :dynamic_framework
  pod 'GoogleAPIClientForREST/Drive', '3.1.0', :build_type => :dynamic_framework
  # ...
end
```

Rerun `pod install --repo-update`. If the installation fails, remove `ios/Pods` and `node_modules` and try again.

Create an **iOS** OAuth client in the Google Cloud console, then register its reversed client ID as a URL scheme in `ios/YourApp/Info.plist`:

```xml
<key>CFBundleURLTypes</key>
<array>
  <dict>
    <key>CFBundleTypeRole</key><string>Editor</string>
    <key>CFBundleURLSchemes</key>
    <array><string>com.googleusercontent.apps.YOUR-IOS-CLIENT-ID</string></array>
  </dict>
</array>
```

Pass the same client ID to [`initBackupProvider`](/functioninitbackupprovider) as `googleDriveClientID` — the native URL scheme and the JS API must agree on this value.

### iCloud

This option is relevant for iOS only.

Enable the iCloud capability (key-value storage) for your target in Xcode, regenerate the provisioning profile, and confirm your entitlements file contains:

```xml
<key>com.apple.developer.icloud-container-identifiers</key><array/>
<key>com.apple.developer.icloud-services</key><array/>
<key>com.apple.developer.ubiquity-kvstore-identifier</key>
<string>$(TeamIdentifierPrefix)$(CFBundleIdentifier)</string>
```

See [Cloud backup](/waas/end-user-backup-and-recovery/encrypted-backup-cloud) for the runtime flow.

## Step 6: Verify the installation

Confirm the package resolved from the npm registry:

```bash
npm view @fordefi/wallet-sdk-react-native dist.tarball
```

(or check the `resolved` URL for the package in your lockfile).

Then run a native build — this is the real success criterion, since it exercises Steps 3–5:

```bash
npx react-native run-android
npx react-native run-ios
```

## Troubleshooting

| Error | Cause | Fix |
|  --- | --- | --- |
| `404 Not Found - @fordefi/wallet-sdk-react-native` | You are not authenticated, or your npm account has not been granted access to the private package. | Verify your token or `npm login`; contact Fordefi support to confirm your account has read access. |
| `403 Forbidden` / `401 Unauthorized` | Missing or invalid npm token | Rerun Step 1; verify your access with Fordefi support. |
| Install works locally but fails in CI. | Auth token only present in your local `~/.npmrc`. | Provide the token to CI via an environment variable or a CI-managed `.npmrc`. |
| Android build fails on duplicate `libc++_shared.so` / `libfbjni.so`. | The SDK ships its own `jni` payload alongside React Native's. | Add the `pickFirst` packaging rules from Step 3. |
| App builds but crashes at launch on an x86 emulator. | The SDK has no 32-bit `x86` native libraries. | Remove `x86` from `reactNativeArchitectures`; use an `x86_64` or ARM emulator. |


## Next steps

Continue to [Initialization](/waas/initialization) to set up the SDK in your app.