Request or download the MATTR Pi SDK Trial Licence Agreement and the MATTR Customer Agreement and review these terms.
In this SDK mDocs are referred to as Mobile credentials and CWT credentials are referred to as Compact credentials.
| Technology | Version |
|---|---|
| Xcode | 15.2 or higher |
| iOS | 15(*) or higher |
| iPhone | iPhone 6S or higher |
| Technology | Version |
|---|---|
| Android Gradle Plugin | 8.3.0 |
| Gradle | 8.3 |
| Kotlin | 1.9.0 |
| JDK | 17 |
| Android min API level | 24 |
| Android target API level | 34 |
| Technology | Version |
|---|---|
| Node | v18 or higher |
| React Native | 0.78.x or higher |
SDK was tested with react-native 0.79 and 0.81
| Component | iOS size | Android size |
|---|---|---|
| Verifier sample app (React Native Verifier SDK + mobile extension + external/peers dependencies) | ~15MB(Compressed) ~22MB(TestFlight) | ~34MB(Compressed) ~82MB(Uncompressed) |
The verifier sample app includes minimal UI elements, so it serves as a good indication of the size requirements when adding the SDK into new or existing applications.
Refer to our SDK Docs landing page for step-by-step instructions to gain access to any of our SDKs.
Please reach out to us in case you need any assistance.
Add this SDK as a dependency to your react native app:
yarn add @mattrglobal/verifier-sdk-react-native
The SDK relies on the following private packages and peer dependencies:
Install required packages and peer dependencies:
yarn add @mattrglobal/react-native-cryptography@^2.1.2 react-native-file-access@^3.1.1 react-native-get-random-values@^1.11.0 react-native-mmkv@2.11.0
WARNING: Only use react-native-mmkv <= 2.11.0 as a dependency. MMKV >2.11.X uses a bad underlying MMKV version. For more information see https://github.com/mrousavy/react-native-mmkv/issues/707.
This SDK can be used in the same application with version 8.0.0 of the React Native mDocs Holder SDK (mobile-credential-holder-react-native).
Create a verifier:
import { init } from "@mattrglobal/verifier-sdk-react-native";
const initOptions: InitOptions = {
issuerCacheTtl: 60000,
revocationListCacheTtl: 60000,
trustedIssuers: ["did:web:example.com"], // defaults to trust any issuer
assertExpiry: true, // defaults to true
assertNotBefore: true, // defaults to true
checkRevocation: true, // defaults to true
};
const verifier = await init(initOptions);
Verify a credential:
const verifyResult = await verifier.compact.verify({ payload });
if (verifyResult.isErr()) {
// Handle error from verifyResult.error
return;
}
const { verified } = verifyResult.value;
Close the verifier:
console.log(verifier.isOpen()); // true
const closeVerifierResult = await verifier.close();
if (closeVerifierResult.isErr()) {
// Handle error from closeVerifierResult.error
return;
}
console.log(verifier.isOpen()); // false
Destroy the verifier:
await verifier.destroy();
console.log(verifier.isOpen()); // false
Get the cache expiry date:
const expiry = await verifier.compact.getCacheExpiry();
Refresh the items in the cache:
const refreshCacheResult = await verifier.compact.refreshCache();
if (refreshCacheResult.isErr()) {
/**
* The error contains the cache expiry date
* This date may have changed after partial refresh
*/
console.log(refreshCacheResult.error.expiryDate);
// Handle error from refreshCacheResult.error
return;
}
// New expiry date of the cache
const { expiryDate } = refreshCacheResult.value;
Refresh issuer items in the cache:
const refreshIssuerCacheResult = await verifier.compact.refreshIssuerCache();
if (refreshIssuerCacheResult.isErr()) {
/**
* The error contains the cache expiry date
* This date may have changed after partial refresh
*/
console.log(refreshIssuerCacheResult.error.expiryDate);
// Handle error from refreshIssuerCacheResult.error
return;
}
// New expiry date of the issuers cache
const { expiryDate } = refreshIssuerCacheResult.value;
Refresh revocation list items in the cache:
const refreshRevocationListCacheResult = await verifier.compact.refreshRevocationCache();
if (refreshRevocationListCacheResult.isErr()) {
/**
* The error contains the cache expiry date
* This date may have changed after partial refresh
*/
console.log(refreshRevocationListCacheResult.error.expiryDate);
// Handle error from refreshRevocationListCacheResult.error
return;
}
// New expiry date of the revocation list cache
const { expiryDate } = refreshRevocationListCacheResult.value;
The following extensions are not included in the @mattrglobal/verifier-sdk-react-native package by default.
In this SDK mDocs are referred to as Mobile Credentials.
To enable mDocs features, install the following peer dependency in your app:
yarn add @mattrglobal/mobile-credential-verifier-react-native
mDocs presentation utilises Bluetooth connection. Make sure the NSBluetoothAlwaysUsageDescription and
NSBluetoothPeripheralUsageDescription descriptions are configured inside Info.plist.
Additional configuration steps are required to bundle the native libraries.
The precompiled MATTR Android mDocs Verifier is provided in the published NPM package.
Open the android/build.gradle script and apply the following changes:
allprojects {
repositories {
…
google()
+ maven {
+ url = "$rootDir/../node_modules/@mattrglobal/mobile-credential-verifier-react-native/android/frameworks"
+ }
}
}
Include the mDocs verifier extension during initialization:
import { init } from "@mattrglobal/verifier-sdk-react-native";
import MobileCredentialVerifier from "@mattrglobal/mobile-credential-verifier-react-native";
await init({ extensions: [MobileCredentialVerifier] });
The SDK only verifies mDocs that were issued by a trusted issuer. The trusted issuer certificates list can be managed directly with the following functions:
// Add new trusted issuer certificates
await verifier.mobile.addTrustedIssuerCertificates(certificates);
// Get all trusted certificates
const certificates = await verifier.mobile.getTrustedIssuerCertificates();
// Remove one of the trusted issuer certificate
await verifier.mobile.deleteTrustedIssuerCertificate(id);
The mDocs verifier supports requesting a credential from a holder device via Bluetooth. The following example shows how you could start a session and request a credential presentation from a holder device:
Only one presentation session is allowed at a time. You must terminate the existing session before starting a new one.
// start a new presentation session
const createSessionResult = await verifier.mobile.createProximityPresentationSession({
deviceEngagement: "mdoc:owBjMS4wAYIB2BhYS6QBAiABIVgg_t9K0BaXU27ynODS5q8OcvBZ4m1HFEQwl61lhRD2rdciWCA7hKLr_xN6_bdznDePa_yY1tGdHsc8ni_88uVuehRU-QKBgwIBowD1AfQKUMW8DfgLrUclmxp2InJCddk" // proximity presentation device engagement string
onConnected: () => {
// handle onConnect event
},
onSessionTerminated: () => {
// handle onSessionTerminated event
},
});
if (createSessionResult.isErr()) {
const { error } = createSessionResult;
// handle error scenarios
return;
}
// Send session
const sendRequestResult = await verifier.mobile.sendProximityPresentationRequest({
// An optional opt-out flag to bypass additional checks that ensure the credential status is "valid" and not "invalid" or "suspended".
skipStatusCheck: true | false | undefined
mobileCredentialRequests: [{
docType: "org.iso.18013.5.1.mDL",
namespaces: {
"org.iso.18013.5.1": {
family_name: false,
driving_privileges: false,
},
},
}],
});
if (sendRequestResult.isErr()) {
const { error } = sendRequestResult;
// handle error scenarios
return;
}
const response = sendRequestResult.value;
// Terminate current active session
await verifier.mobile.terminateProximityPresentationSession();
The SDK caches status lists on the device and preloads them when verifier.mobile.addTrustedIssuerCertificates is invoked. Subsequent status list updates are lazy-loaded and only fetched when the status list's nextUpdate expires.
You may choose to refresh the cached status lists preemptively or periodically in-order to:
verifier.mobile.sendProximityPresentationRequest calls by keeping status lists up-to-date.More granular management methods are available to help scheduling updates, as shown below:
const statusListsCacheResult = await verifier.mobile.getTrustedIssuerStatusListsCacheInfo();
if(statusListsCacheResult.isErr()) {
const { error } = statusListsCacheResult;
// handle error scenarios
return;
}
const statusListCache = statusListsCacheResult.value;
if(statusListCache.nextUpdate?.getTime() > now.getTime()) {
// Status lists are still up-to-date
return;
}
const statusListInfoResult = await verifier.mobile.updateTrustedIssuerStatusLists();
if(statusListInfoResult.isErr()) {
const { error } = statusListInfoResult;
// handle error scenarios
return;
}
const statusListInfo = statusListInfoResult.value;
if(!statusListInfo.success) {
const { failedStatusLists } = statusListInfo;
// handle error scenarios
return;
}
if(statusListInfo.nextUpdate) {
// Optionally re-schedule the next update or background check
}
To enable Ecosystem features install the following peer dependency in your app:
yarn add @mattrglobal/ecosystem-sdk-react-native
And then include the Ecosystem SDK during initialization:
import { init } from "@mattrglobal/verifier-sdk-react-native";
import Ecosystem from "@mattrglobal/ecosystem-sdk-react-native";
await init({ extensions: [Ecosystem], ecosystem: { url } });
On initialization (see above) the internal storage is synced with the latest policy relevant to the provided ecosystem ID. If storage becomes out of sync, the SDK provides an option to manage the storage manually:
// storage can be synced manually
const syncResult = await verifier.ecosystem.sync({ reset: true });
// storage can be deleted manually
const deleteResult = await verifier.ecosystem.delete();
The main features of the Ecosystem SDK is to provide validation of a given credential and participant, who can be an issuer, a verifier or both. The SDK also checks whether the participant is authorised. This can be invoked with:
// validates the three aspects of the specified issuer
const validateIssuerResult = await Ecosystem.validateIssuer({ profile, identifier, type });
// validates the three aspects of the specified verifier
const validateVerifierResult = await Ecosystem.validateVerifier({ profile, identifier, type });
The SDK distinguishes between expected and unexpected errors to help you write clearer and more predictable code.
Expected errors are part of the normal operation of a function. In these cases, the SDK function will be wrapped in a Result object from the neverthrow library, with an explicit error type you can handle programmatically. Some functions do not have expected failure modes. When that’s the case, their return type will not be wrapped in a Result object. Although this pattern is more verbose, it encourages the handling of possible errors and reserves throwing exceptions for truly exceptional situations.
Unexpected errors represent bugs, SDK misuse, or system-level failures. In these cases the SDK will throw an exception which results in a rejected promise. Because the root cause is unknown or unrecoverable, we recommend handling them with a generic fallback strategy (e.g., showing an error screen or logging the issue) appropriate to your app’s context.
This separation ensures you know which errors to handle explicitly and which indicate deeper issues that need broader handling.
import { open } from "@mattrglobal/verifier-sdk-react-native";
const openVerifierResult = await open();
if (openVerifierResult.isErr()) {
// Handle error from openVerifierResult.error
return;
}
const verifier = openVerifierResult.value;
A utility function is provided for convenience if you decide not to handle your errors as results. This function will
simply throw an error if the function passed in returns a Result where Result.isErr() is true.
import { unwrap } from "@mattrglobal/verifier-sdk-react-native";
try {
const verifier = unwrap(await open());
} catch (error) {
// Handle thrown error
}
mDocs
The following changes reflect the update of the SDK's spelling convention from UK English to US English.
MobileCredentialVerifierErrorType.SdkNotInitialised to
MobileCredentialVerifierErrorType.SdkNotInitialized.mobile.createProximityPresentationSession method was updated as follows:onError callback function could be invoked with the following errors:MobileCredentialVerifierErrorType.FailedToCreateProximityPresentationSession when encountered issue while
creating a presentation session.MobileCredentialVerifierErrorType.UnknownError when encountered an unknown exception during the presentation
session.mobile.sendProximityPresentationRequest method was updated as follows:MobileCredentialVerificationFailureType.TrustedIssuerCertificateNotFound
when a presented credential cannot be verified due to missing a matched trusted issuer certificate.iOS Platform
IssuerNamespaces field, but according to the Concise Data Definition Language (CDDL) specification defined in
ISO/IEC 18013-5, this field must contain at least one entry. This update enforces that requirement, improving
interoperability and ensuring issued credentials are standards-compliant.mDocs
react-native-cryptography to 2.1.2.mDocs
mDocs
onTerminated callback instead of
onSessionTerminated.mDocs
mobile.createProximityPresentationSession function was updated as follows:ProximityPresentationSessionListener as a parameter instead of
ProximityPresentationSession.OnSessionTerminated.onEstablished method within the ProximityPresentationSessionListener protocol.onError method within the ProximityPresentationSessionListener
protocol.mobile.sendProximityPresentationRequest function replaces
mobile.ProximityPresentationSession.requestMobileCredentials.mobile.terminateProximityPresentationSession function replaces
mobile.ProximityPresentationSession.terminateSession.mobile.getInstance function. mobile.MobileCredentialVerifier is now only accessed as an object
internally.mobile.getCurrentProximityPresentationSession function. The mobile.ProximityPresentationSession class
is now an internal class.JSON Credentials
BbsBlsSignature2020).mDocs
registerForNfcDeviceEngagement and
deregisterForNfcDeviceEngagement.General
elliptic dependency, which was previously used for signature format conversion. This functionality is
now handled by an internal implementation.mDocs
mDocs
initialise method throws a runtime exception when the iOS system version is not supported.@mattrglobal/mobile-credential-verifier-react-native extension has refined the minimum supported iOS version in
podspec.mDocs
This SDK can now be used in the same application with compatible versions of the
mobile-credential-holder-react-native SDK, as detailed in the
installation
section.
mDocs Revocation Support
mobile.sendProximityPresentationRequest method now verifies the status of presented revocable mDocs.MobileCredentialStatusListInfo was added to the return type for both methods under
MobileCredentialResponse.credentials[].statusInfo. It is used to:mobile.getTrustedIssuerStatusListsCacheInfo method was added to retrieve cache details of previously retrieved
status lists.mobile.updateTrustedIssuerStatusLists method was added to update status lists when required.MobileCredentialStatusListInfo.nextUpdate
(retrieved from mobile.getTrustedIssuerStatusListsCacheInfo) expires to keep status lists up-to-date. This
approachs offers two advantages:sendProximityPresentationRequest calls, as network requests may be
needed to verify a credential's status if the cached status list expires.mDocs
mobile.sendProximityPresentationRequest method now checks the status of presented revocable mDocs by default. To
opt out of this behavior you must set the new skipStatusCheck parameter to false.react-native-fs peer-dependency has been replaced with
react-native-file-access@^3.1.1. You must add this new
dependency to your project.@mattrglobal/react-native-cryptography@2.1.1.mDocs
Realm database has been replaced with a custom storage system. Upgrading to this version will result in all data being lost.
The mobile.addTrustedIssuerCertificates method error types were updated as follows:
MobileCredentialVerifierErrorType.FailedToStoreCertificate when the given certificate is invalid.MobileCredentialVerifierErrorType.InvalidCertificate.The mobile.sendProximityPresentationRequest method error types were updated as follows:
ProximityPresentationSessionErrorType.UnsupportedCurve.ProximityPresentationSessionErrorType.RequestAlreadyInProgress.ProximityPresentationSessionErrorType.MobileCredentialVerificationFailed.The mobile.createProximityPresentationSession method error types were updated as follows:
ProximityPresentationSessionErrorType.UnsupportedCurve.Instead of throwing an exception, the mobile.sendProximityPresentationRequest method now returns a
MobileCredentialResponse with a credentials[x].verificationResult field to provide a more detailed verification
status (e.g. invalid credential, etc.).
mDocs
iOS Platform
mobile.addTrustedIssuerCertificates can now also accept input in the form of an unformatted PEM string.react-native-securerandom peer-dependency is no longer required.react-native-secure-key-store library with a local secure store implementation. Peer dependency
react-native-secure-key-store is no longer required.@mattrglobal/react-native-cryptography@2.0.0.The following verifier initialisation parameters have been renamed to maintain consistency (the functionality is not affected by this change):
assertNotBefore parameter has been renamed to assertValidFrom.assertExpiry parameter has been renamed to assertValidUntil.Introduced mDocs capabilities via extensions.
The verifyCredential method had been split and moved into the separate compact and compactSemantic namespaces to
simplify methods structure and usage. With this change trusted issuers and revocation lists are cached separately for
these namespaces.
verifier.compact.verify and verifier.compactSemantic.verifyIntroduced Ecosystem capabilities via extensions.
Introduced Compact and Compact Semantic Credentials verification capabilities.
Generated using TypeDoc