light-mode-image
Learn
Management & OperationsMigration Guides

React Native Holder SDK v10.0.0 Migration Guide

A comprehensive guide to migrating to React Native Holder SDK v10.0.0, covering breaking changes, new features, and step-by-step migration instructions.

This is a draft migration guide, shared ahead of general availability to help you gauge migration effort and plan ahead of the release. We will update this page to a final copy when the SDK is generally available.

Overview

This guide provides a comprehensive overview of the changes introduced in React Native Holder SDK v10.0.0, including breaking changes, new features, and migration steps.

This release focuses on strengthening trust at issuance, improving predictability in credential handling, and increasing consistency across platforms. It introduces Wallet Attestation support and requires updates to the JavaScript/TypeScript layer to bridge the new platform configuration.

Key Features

  • Wallet Attestation support: The React Native Holder SDK now supports Wallet Attestation, allowing your holder application to prove to issuers that it is a trusted wallet before credentials are issued. The SDK is now tethered to a MATTR VII tenant, which issues wallet attestation tokens when required by an issuer.
  • Stronger application identity during issuance: Credential issuance flows now consistently use the application's real client_id, ensuring the holder is accurately represented when interacting with issuers. This improves compatibility with issuers applying stricter controls.
  • More predictable credential retrieval results: Credential retrieval responses are now more structured and deterministic, explicitly identifying success or failure with guaranteed fields per result type.
  • General stability and performance improvements: Multiple refinements reduce integration friction, increase consistency, and improve overall reliability.

Breaking Changes

This section outlines the breaking changes introduced in v10.0.0 that require updates to your existing implementation:

#ChangeImpact
1initialize(...) now requires platform configurationYou must create a holder application on your MATTR VII tenant and update all initialization call sites to provide tenant configuration.
2Pre-authorized code flow now uses the application's client_id instead of a default identifierEnsure your application has a valid configured client_id and issuers recognize it.
3Credential retrieval result shape updated to explicitly identify success or failure with guaranteed fieldsUpdate result parsing and handling logic.
4doctype renamed to docType in credential retrievalRename all usages of doctype to docType.
5MobileCredentialAuthenticationOption renamed to DeviceAuthenticationOptionUpdate imports, type references, and configuration objects.

Migration Steps

Create holder applications on your MATTR VII tenant

The React Native Holder SDK is now tethered to a MATTR VII tenant via the underlying native SDKs. The SDK will not function without registered holder applications on your tenant. This is required regardless of whether wallet attestation is used in your credential flows.

Since React Native targets both iOS and Android, you need to create two holder applications, one for each platform.

Create the iOS holder application

Make a request to create a holder application:

Request
POST /v1/holder/applications
Request body
{
    "name": "My RN Holder Application (iOS)",
    "clientId": "your-wallet-client-id",
    "type": "ios",
    "bundleId": "com.yourcompany.holderapp",
    "teamId": "YOUR_APPLE_TEAM_ID"
}
  • name: A unique name to identify this holder application.
  • clientId: The OAuth 2.0 client_id that identifies your wallet application. This value is included in attestation JWTs and must match the client_id configured on the issuer's Authorization Server.
  • type: Must be ios for the iOS target.
  • bundleId: The Bundle ID of your iOS app (must match your Xcode project configuration).
  • teamId: Your Apple Developer Team ID.

The response will include a unique id for your application, which must be used when initializing the SDK so that it can correctly identify and authenticate your application.

Create the Android holder application

Request
POST /v1/holder/applications
Request body
{
    "name": "My RN Holder Application (Android)",
    "clientId": "your-wallet-client-id",
    "type": "android",
    "packageName": "com.yourcompany.holderapp",
    "packageSigningCertificateThumbprints": [
        "1232584b6f6a892d356899fb9576c5f226a179e6199f2b7a1d837b5c234c5a8e"
    ]
}
  • name: A unique name to identify this holder application.
  • clientId: The OAuth 2.0 client_id that identifies your wallet application. This value is included in attestation JWTs and must match the client_id configured on the issuer's Authorization Server.
  • type: Must be android for the Android target.
  • packageName: The package name of your Android application.
  • packageSigningCertificateThumbprints: SHA-256 hex-encoded fingerprints of the signing key certificates used to sign your APK or app bundle. This ensures the tenant only accepts requests from known and trusted applications. Refer to Android app signing for more information.

The response will include a unique id for your application, which must be used when initializing the SDK so that it can correctly identify and authenticate your application.

Once both application configurations are created, your application will be able to use the SDK and interact with the MATTR VII platform (for example, to obtain attestation tokens).

The clientId you configure here is the same value you must:

  1. Pass as the clientId in the options when calling retrieveCredentials.
  2. Register with each issuer you intend to interact with, so the issuer can identify and trust requests coming from your wallet application.

Update SDK initialization with platform configuration

The initialization API now requires platform configuration to be passed through the JS/TS layer into the native SDKs.

Since React Native bridges both iOS and Android, and each platform has its own holder application registered on your MATTR VII tenant (see Step 1), your initialization code must pass the correct platform-specific applicationId at runtime. Use Platform.OS to select the appropriate value:

  import { initialize } from "@mattrglobal/mobile-credential-holder-react-native";
+ import { Platform } from "react-native";

- await initialize({ instanceId: "your-instance-id" });
+ const applicationId =
+     Platform.OS === "android"
+         ? "your-android-holder-application-id"
+         : "your-ios-holder-application-id";
+
+ await initialize({
+     instanceId: "your-instance-id",
+     platformConfiguration: {
+         tenantUrl: "https://your-tenant.vii.mattr.global",
+         applicationId,
+     },
+ });

Replace the placeholder values with the id returned when you created each holder application. In practice, you would typically store these values in a configuration file or environment variables.

Confirm that:

  • The applicationId used on iOS corresponds to the holder application created with your app's bundleId and teamId.
  • The applicationId used on Android corresponds to the holder application created with your app's packageName and signing certificate thumbprints.
  • Environment-specific tenant URLs are correctly configured.

Handle new Wallet Attestation error modes

Wallet Attestation introduces new error scenarios that can occur during credential issuance. These errors may arise when:

  • The SDK requests an attestation token from your MATTR VII tenant.
  • The SDK presents wallet attestation credentials to an issuer's Authorization Server at its /token endpoint.
  • The SDK requests credentials from an issuer's /credential endpoint with DPoP-bound access tokens.

The following methods are affected:

  • retrieveCredentials — may return new error types in both the thrown error and per-credential results.

New error types will be added to MobileCredentialHolderError and RetrieveCredentialError (a breaking change requiring updates to error type handling).

Update your error handling, logging, analytics, and support diagnostics to account for new wallet attestation error cases. An exhaustive list of new errors will be provided with the final migration guide.

Update client_id configuration

Previously, the client_id passed to retrieveCredentials was not shared with the issuer during the pre-authorized code flow, so any value would work. This is no longer the case — the SDK now presents the client_id to the issuer as part of wallet attestation, and the issuer validates it against its list of trusted wallet providers.

To prepare for this change:

  1. Coordinate with the issuer to register your wallet application as a trusted wallet provider. The issuer will provide you with a client_id that identifies your application.
  2. Pass the issuer-provided client_id in the options when calling retrieveCredentials.
  const result = await retrieveCredentials({
      credentialOffer: offer,
-     clientId: "any-value",
+     clientId: "issuer-provided-client-id"
  });

Issuance flows that previously worked with an arbitrary client_id will fail if the issuer requires a trusted wallet provider. Ensure you have coordinated with each issuer and obtained the correct client_id before upgrading. Test direct issuance flows to confirm credentials are issued successfully.

Update credential retrieval result handling

RetrieveCredentialsResponse has changed from an array of flat objects with optional fields to an array of RetrieveCredentialItem — a discriminated union with isSuccess as the discriminator. Each item is either a RetrieveCredentialSuccess (with guaranteed docType and credentialId) or a RetrieveCredentialFailure (with guaranteed docType and error).

Update your result iteration logic to narrow on isSuccess:

  const result = await retrieveCredentials(options);

  if (result.isOk()) {
      for (const item of result.value) {
-         if (item.credentialId) {
-             // Use item.doctype and item.credentialId
+         if (item.isSuccess) {
+             // item.docType and item.credentialId are guaranteed
          } else {
-             // Use item.doctype and item.error
+             // item.docType and item.error are guaranteed
          }
      }
  }

Update TypeScript type guards, tests, and any downstream logic that checked for optional fields.

Rename doctype to docType

The credential retrieval field has been renamed from doctype to docType. Update all usages across your codebase:

- const documentType = credential.doctype;
+ const documentType = credential.docType;

Update models, serializers, mocks, tests, and any cross-platform abstraction layers.

Rename MobileCredentialAuthenticationOption to DeviceAuthenticationOption

Update all TypeScript imports, type references, and configuration objects:

- import { MobileCredentialAuthenticationOption } from "@mattrglobal/mobile-credential-holder-react-native";
+ import { DeviceAuthenticationOption } from "@mattrglobal/mobile-credential-holder-react-native";

- const authOption: MobileCredentialAuthenticationOption = ...;
+ const authOption: DeviceAuthenticationOption = ...;

How would you rate this page?

Last updated on

On this page