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:
| # | Change | Impact |
|---|---|---|
| 1 | initialize(...) now requires platform configuration | You must create a holder application on your MATTR VII tenant and update all initialization call sites to provide tenant configuration. |
| 2 | Pre-authorized code flow now uses the application's client_id instead of a default identifier | Ensure your application has a valid configured client_id and issuers recognize it. |
| 3 | Credential retrieval result shape updated to explicitly identify success or failure with guaranteed fields | Update result parsing and handling logic. |
| 4 | doctype renamed to docType in credential retrieval | Rename all usages of doctype to docType. |
| 5 | MobileCredentialAuthenticationOption renamed to DeviceAuthenticationOption | Update 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:
POST /v1/holder/applications{
"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.0client_idthat identifies your wallet application. This value is included in attestation JWTs and must match theclient_idconfigured on the issuer's Authorization Server.type: Must beiosfor 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
POST /v1/holder/applications{
"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.0client_idthat identifies your wallet application. This value is included in attestation JWTs and must match theclient_idconfigured on the issuer's Authorization Server.type: Must beandroidfor 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:
- Pass as the
clientIdin the options when callingretrieveCredentials. - 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
applicationIdused on iOS corresponds to the holder application created with your app'sbundleIdandteamId. - The
applicationIdused on Android corresponds to the holder application created with your app'spackageNameand 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
/tokenendpoint. - The SDK requests credentials from an issuer's
/credentialendpoint 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:
- Coordinate with the issuer to register your wallet application as a trusted wallet provider. The issuer will provide you with a
client_idthat identifies your application. - Pass the issuer-provided
client_idin the options when callingretrieveCredentials.
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