MATTR Wallet SDK React Native - v6.1.3

wallet-sdk-react-native

Table of Contents

Licensing

Request or download the MATTR Pi SDK Trial Licence Agreement and the MATTR Customer Agreement and review these terms

Features

  • Manage local DIDs
  • DIDComm messaging
  • Validate a DID to domain linkage
  • Retrieve credentials over OpenID4VCI
  • Retrieve credentials over OIDC Bridge
  • Verify and present web semantic credentials
  • Verify compact credentials
  • Verify semantic compact credentials
  • Hold, verify and present mobile credentials

High level overview

High Level

Getting started

How to get access to MATTR Pi Wallet SDK

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 Get in touch.

Install dependencies

Add this SDK as a dependency to the react native app:

yarn add @mattrglobal/wallet-sdk-react-native

The SDK relies on a set of peer dependencies that contain native libraries and iOS pods. With React Native >=0.60 these dependencies will be autolinked.

Install the peer dependencies:

yarn add react-native-securerandom@1.0.1 realm@12.2.1 react-native-fs@2.20.0 react-native-secure-key-store@2.0.10 @mattrglobal/rn-bbs-signatures@1.0.0 react-native-get-random-values@1.7.0 @mattrglobal/react-native-cryptography@1.1.2 @mattrglobal/pairing-crypto-rn@0.4.1

[!NOTE] we tested with react-native 0.71.12

React Native <0.60

Please see the specific instructions for each dependency regarding linking prior to React Native 0.60.

Android only

Make sure the following repository is included under android/build.gradle > allprojects.repositories:

allprojects {
repositories {
...
maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
...
}
}

iOS only

Add the pod for bbs-signatures to the podfile in ios/Podfile:

  pod 'bbs-signatures', :git => 'https://github.com/mattrglobal/ffi-bbs-signatures'

Run pod install:

cd ios && pod install

Add arm64 to all profiles under: xcode -> Build Settings -> Excluded Architectures -> Any iOS Simulator SDK, it should show the following changes under xxx.xcodeproj for each of the profiles

"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64;

If your app was initially created with react-native@0.61.* or earlier versions, you may need to update your ios/*.xcodeproj configuration. Any reference of the DEAD_CODE_STRIPPING flag must be removed or set to YES, this is required to maintain compatibility for the newer & older versions of react-native.

- DEAD_CODE_STRIPPING = NO;

Usage

Wallet

Initialise a wallet instance

import { initialise } from "@mattrglobal/wallet-sdk-react-native";

const initialiseWalletResult = await initialise();

if (initialiseWalletResult.isErr()) {
// Handle error from initialiseWalletResult.error
return;
}

const wallet = initialiseWalletResult.value;

It is possible to maintain multiple isolated wallet instances. This can be achieved by using a different walletId during initialisation, as long as you close the current wallet instance before initialising a new one with a different walletId.

import { initialise } from "@mattrglobal/wallet-sdk-react-native";

// to use wallet1
const initialiseWallet1Result = await initialise({ walletId: "id1" });

if (initialiseWallet1Result.isErr()) {
// Handle error from initialiseWalletResult.error
return;
}
const wallet1 = initialiseWallet1Result.value;

// to use wallet2
await wallet1.close();
const initialiseWallet2Result = await initialise({ walletId: "id2" });
const wallet2 = initialiseWallet1Result.value;

Destroy the wallet

[!NOTE] you must close the wallet instance that is currently initialised before calling destroy, otherwise an exception will be thrown.

import { destroy } from "@mattrglobal/wallet-sdk-react-native";

await destroy({ walletId });

Retrieving credentials via OpenID4VCI

Discover credential offer details via offer URI

/***
* openid-credential-offer://?credential_offer=encodeURIComponent(JSON.stringify({ credential_issuer, credentials: [{credentialId}], request_parameters? }))
*/
const uri =
"openid-credential-offer://?credential_offer=%7B%22credential_issuer%22%3A%22https%3A%2F%2Fmyissuer.example.com%22%2C%22credentials%22%3A%5B%22707e920a-f342-443b-ae24-6946b7b5033e%22%5D%2C%22request_parameters%22%3A%7B%22login_hint%22%3A%22user%40example.com%22%2C%22prompt%22%3A%22login%22%7D%7D";

const discoveryResult = await wallet.openid.issuance.discover(uri);
if (discoveryResult.isErr()) {
// Handle error from discoveryResult.error
}
const { offer } = discoveryResult.value;

Or construct an offer manually

const offer: OpenidIssuanceCredentialOffer = {
issuer: "https://example.com/",
authorizeEndpoint: "https://example.com/oauth/authorize",
tokenEndpoint: "https://example.com/oauth/token",
credentialEndpoint: "https://example.com/oauth/credential",
credentials: [
{
profile: "web-semantic",
scope: "ldp_vc:UniversityDegreeCredential",
credentialDefinition: {
"@context": ["https://www.w3.org/2018/credentials/v1"],
type: ["VerifiableCredential", "UniversityDegreeCredential"],
},
},
],
};

Configure OAuth client id and redirect uri

const clientId = "myAppClientId";
const redirectUri = "myapp://credentials/callback";

Generate an authorization url and open in a web browser

import { Linking } from "react-native";

const generateAuthorizeUrlResult = await wallet.openid.issuance.generateAuthorizeUrl({ offer, clientId, redirectUri });

if (generateAuthorizeUrlResult.isErr()) {
// Handle error from generateAuthorizeUrlResult.error
return;
}

const { url, codeVerifier } = generateAuthorizeUrlResult.value;
await Linking.openURL(url);

Handle authorization success callback

myapp://credentials/callback?code=...&iss=...

Retrieve token

const retrieveTokenResult = await wallet.openid.issuance.retrieveToken({
offer,
clientId,
redirectUri,
codeVerifier,
code: route.params.code, // code comes authorization success callback above
});

if (retrieveTokenResult.isErr()) {
// Handle error from retrieveTokenResult.error
return;
}

const { accessToken } = retrieveTokenResult.value;

Retrieve credentials

const retrieveCredentialsResult = await wallet.openid.issuance.retrieveCredentials({
offer,
accessToken,
clientId,
});

retrieveCredentialsResult.forEach((credentialOfferResult) => {
if ("error" in credentialOfferResult) {
const { offer, error } = credentialOfferResult;

// Handle error from retrieveCredentialsResult.error
} else {
const { offer, result } = credentialOfferResult;
}
});

Retrieving credentials via OIDC Bridge

Discover OIDC credential offer

const discoverResult = await wallet.oidc.discover("openid://discovery?issuer=https://issuer.example.com");

if (discoverResult.isErr()) {
// Handle error from discoverResult.error
return;
}

const { offer } = discoverResult.value;

Create a local subject DID for the credential

const createDidResult = await wallet.did.createDid();

if (createDidResult.isErr()) {
// Handle error from createDidResult.error
return;
}

const { did } = createDidResult.value;

Generate an OpenID authorization url to request the credential

import { Linking } from "react-native";

const genUrlResult = await wallet.oidc.generateAuthorizeUrl({ offer, did });

if (genUrlResult.isErr()) {
// Handle error from genUrlResult.error
return;
}

const { url, codeVerifier, nonce } = genUrlResult.value;
await Linking.openURL(url);

Retrieve the credential on an authorization success callback

const retrieveResult = (retrieveCredential = await wallet.oidc.retrieveCredential({
offer,
codeVerifier,
nonce,
code: route.params.code, // code comes from part of the callback url
}));

if (retrieveResult.isErr()) {
// Handle error from retrieveResult.error
return;
}

const { credential } = retrieveResult.value;

DIDComm message

Resolve a didcomm message from a didcomm URI

const resolveDidCommUriResult = await wallet.did.messaging.resolveDidCommUri(uri);
if (resolveDidCommUriResult.isErr()) {
// Handle error from resolveDidCommUriResult.error
return;
}
const message = resolveDidCommUriResult.value;

Open a didcomm message that is signed or encrypted

import { isPresentationRequestJwm } from "wallet-sdk-react-native";
const openResult = await wallet.did.messaging.openDidCommMessage(message);
if (openResult.isErr()) {
// Handle error from openResult.error
return;
}

Web Semantic Credential

Verify a Web Semantic credential

const verifyResult = await wallet.credential.webSemantic.verifyCredential({ credential });

if (verifyResult.isErr()) {
// Handle error from verifyResult.error
return;
}

const { credentialVerified, status } = verifyResult.value;

Parse a presentation request (DIDComm message)

import { isPresentationRequestJwm } from "wallet-sdk-react-native";
const openResult = await wallet.did.messaging.openDidCommMessage(message);

if (openResult.isErr() || !isPresentationRequestJwm(openResult.value)) {
return;
}

const presentationRequest = openResult.value;

Retrieve credentials matching a specific presentation request

const credentialData = [
{ id: "a", credential: credentialA },
{ id: "b", credential: credentialB },
];

const filterResult = await wallet.credential.webSemantic.filterCredentialsByQuery({
credentials: credentialData,
// Note that only the presentation request body should contain single query only, under the same query could contain multiple sub queries.
query: presentationRequest.body.query[0],
});

Create and send a presentation response for a presentation request

const createPresentationResult = await wallet.credential.webSemantic.createPresentation({
challenge: presentationRequest.body.challenge,
domain: presentationRequest.body.domain,
credentials,
holder: did,
});

if (createPresentationResult.isErr()) {
// Handle error from createPresentationResult.error
return;
}

const presentation = createPresentationResult.value;
const sendPresentationResult = await wallet.credential.webSemantic.sendPresentationResponse({
presentationRequest,
presentation,
});

Compact Credential

Verify a compact credential

const credentialPayload = "CSC:/1/....";
const verifyResult = await wallet.credential.compact.verifyCredential({ payload: credentialPayload });

if (verifyResult.isErr()) {
// Handle error from verifyResult.error
return;
}

if (result.value.verified) {
const { payload } = result.value;
} else {
const { reason } = result.value;
}

Semantic Compact Credential

Verify a semantic compact credential

const credentialPayload = "CSS:/1/....";
const verifyResult = await wallet.credential.compactSemantic.verifyCredential({ payload: credentialPayload });

if (verifyResult.isErr()) {
// Handle error from verifyResult.error
return;
}

if (result.value.verified) {
const { payload } = result.value;
} else {
const { reason } = result.value;
}

Extensions

The @mattrglobal/wallet-sdk-react-native package does not come with the following extensions by default.

Mobile Credential

To enable the mobile credential feature, an additional peer dependency @mattrglobal/mobile-credential-holder-react-native is needed. Install the following dependency in your app.

yarn add @mattrglobal/mobile-credential-holder-react-native

Platform iOS

Mobile credential presentation utilise Bluetooth connection. Make sure the NSBluetoothAlwaysUsageDescription and NSBluetoothPeripheralUsageDescription descriptions are configured inside Info.plist.

Platform Android

Additional configuration steps are required to bundle the native libraries.

Kotlin Support

This React Native library is written in Kotlin, so you must enable the Kotlin Gradle plugin. If your project was generated using the official React Native 0.73.0 template, you might have it enabled already.

Open the android/build.gradle script and apply the following changes:

 buildscript {
ext {
+ kotlinVersion = "1.9.0"

buildToolsVersion = "34.0.0"
minSdkVersion = 24
compileSdkVersion = 34
targetSdkVersion = 34
ndkVersion = "25.1.8937393"
}
repositories {
google()
mavenCentral()
}
dependencies {
classpath("com.android.tools.build:gradle")
classpath("com.facebook.react:react-native-gradle-plugin")

+ classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion")
+ classpath("org.jetbrains.kotlin:kotlin-android-extensions:$kotlinVersion")
}
}

Open the android/app/build.gradle script and apply the following changes:

  apply plugin: "com.android.application"
+ apply plugin: "org.jetbrains.kotlin.android"
apply plugin: "com.facebook.react"

Minimum requirements

  • kotlinVersion >= 1.9.0
  • minSdkVersion >= 24
Local Maven Repository

The precompiled MATTR Mobile Credential Holder Android Native SDK is provided in the published NPM package.

Open the android/build.gradle script and append the following changes:

 allprojects {
repositories {

google()
+ maven {
+ url = "$rootDir/../node_modules/@mattrglobal/mobile-credential-holder-react-native/android/frameworks"
+ }
}
}

Enable extension

Include the mobile credential holder extension during initialisation

import { initialise } from "@mattrglobal/wallet-sdk-react-native";
import MobileCredentialHolder from "@mattrglobal/mobile-credential-holder-react-native";

await initialise({ extensions: [MobileCredentialHolder], walletId });

The same extension is required when destroying a wallet instance

import { destroy } from "@mattrglobal/wallet-sdk-react-native";
import MobileCredentialHolder from "@mattrglobal/mobile-credential-holder-react-native";

await destroy({ extensions: [MobileCredentialHolder], walletId });

With the mobile credential holder extension, the SDK will be able to retrieve mobile credentials over OpenID4VCI.

import { CredentialProfileSupported } from "@mattrglobal/wallet-sdk-react-native";
const retrieveCredentialsResult = await wallet.openid.issuance.retrieveCredentials({
offer, // offer that contains mobile credentials
accessToken,
clientId,
});

retrieveCredentialsResult.forEach((credentialOfferResult) => {
if ("error" in credentialOfferResult) {
const { offer, error } = credentialOfferResult;
// Handle error from retrieveCredentialsResult.error
} else {
const { offer, result } = credentialOfferResult;
if (result.profile === CredentialProfileSupported.Mobile) {
const credentialId = result.credentialId;
}
}
});

The SDK manages the storage of any retrieved mobile credential. Credentials are accessible via the following:

// Get a mobile credential
const getCredentialResult = await wallet.credential.mobile.getCredential(credentialId);

// Get all mobile credentials
const getCredentialsResult = await wallet.credential.mobile.getCredentials();

// Delete a mobile credential
await wallet.credential.mobile.deleteCredential(credentialId);

The SDK only accepts a mobile credential that can be verified successfully by the trusted issuer certificates. The trusted issuer certificates list can be managed directly with the following functions

// Add new trusted issuer certificates
await wallet.credential.mobile.addTrustedIssuerCertificates(certificates);

// Get all trusted certificates
const certificates = await wallet.credential.mobile.getTrustedIssuerCertificates();

// Remove one of the trusted issuer certificate
await wallet.credential.mobile.deleteTrustedIssuerCertificate(id);

You may also instruct the SDK to automatically download and add certificates into the trusted list while retrieving a mobile credential via OpenID4VCI, when they are discoverable via the openid credential issuer metadata:

const retrieveCredentialsResult = await wallet.openid.issuance.retrieveCredentials({
offer, // offer that contains mobile credentials
accessToken,
clientId,
autoTrustMobileCredentialIaca: true, // enable auto trust
});

Mobile credentials support presenting a credential to a verifier device via bluetooth. The following example shows how you could start and respond to a credential presentation request from a verifier device.

[!NOTE] Only one presentation session is allowed at a time. You must terminate the existing session before starting a new one.

When a presentation request is received, you must respond to it before any new request can be received in the same session.

// start a new presentation session
const createPresentationSessionResult = await wallet.credential.mobile.createProximityPresentationSession({
onRequestReceived: (data) => {
// request received with error
if ("error" in data) {
const { error } = data;
return;
}

const requests = data.request;
requests.map(({ request, matchedCredentials }) => {
// obtain each request with matching credentials in the mobile credential store
});
},
onConnected: (data: unknown) => {
// presentation session is connected
},
onSessionTerminated: (data: unknown) => {
// presentation session is terminated
},
});

if (createPresentationSessionResult.isErr()) {
// handle error creating presentation session
}

const { deviceEngagement } = createPresentationSessionResult.value;
// Render device engagement string on a QRCode. A verifier app should scan and use it to establish the presentation session with this holder.

// construct and send a presentation response with the selected credentials
await wallet.credential.mobile.sendProximityPresentationResponse({ credentialIds });

// terminate the session
await wallet.credential.mobile.terminateProximityPresentationSession();

Ecosystem

The Ecosystem SDK provides the capabilities of the ecosystem feature. To enable the feature, an additional peer dependency @mattrglobal/ecosystem-sdk-react-native is needed, which can be installed with:

yarn add @mattrglobal/ecosystem-sdk-react-native

And then include the ecosystem SDK during initialisation:

import { initialise } from "@mattrglobal/wallet-sdk-react-native";
import Ecosystem from "@mattrglobal/ecosystem-sdk-react-native";

await initialise({ extensions: [Ecosystem], ecosystem: { url } });

The same extension is also required to destroy a wallet instance:

import { destroy } from "@mattrglobal/wallet-sdk-react-native";
import Ecosystem from "@mattrglobal/ecosystem-sdk-react-native";

await destroy({ extensions: [Ecosystem] });

On initialisation, previously mentioned, the internal storage is synced with latest policy relevant to the ecosystem ID provided. In case, storage becomes out of sync, the SDK provides managing the storage manually:

// storage can be synced manually
const syncResult = await wallet.ecosystem.sync({ reset: true });

// storage can be deleted manually
const deleteResult = await wallet.ecosystem.delete();

The main features of the SDK is to provide validation of a given credential and participant, who can be an issuer or a verifier, or both, and 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 });

Error handling

Functions that are expected to have an error path return a Neverthrow Result type that represents either success (Ok) or failure (Err).

Although this pattern is more verbose, it encourages the handling of possibly errors and reserves throwing exceptions for truly exceptional situations.

import { initialise } from "@mattrglobal/wallet-sdk-react-native";

const initialiseWalletResult = await initialise();

if (initialiseWalletResult.isErr()) {
// Handle error from initialiseWalletResult.error
return;
}

const wallet = initialiseWalletResult.value;

unwrap

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/wallet-sdk-react-native";

try {
const wallet = unwrap(await initialise());
} catch (error) {
// Handle thrown error
}

Change Log

6.1.3

Web Semantic Credential

  • Add support to validate the use of inline or remote contexts.
    await initWalletConfig({
...
credential: {
webSemantic: {
remoteContextUrlAllowList: [...], // a list of allowed remote context urls, default: undefined, set this to [] to block any remote context
remoteContextUrlAllowAny: true, // allow any remote context, default: true
inlineContextAllowAny: true, // allow any inline context, default: true
contextValidatorMaxDepth: 10, // max level of nested JsonLD document supported during context validation, default: 10
},
},
})

6.1.2

Bug Fixes

  • Fixed dependency issue on 6.1.1

6.1.1

Bug Fixes

  • Fixed network error detection for the following methods:

    • wallet.credential.webSemantic.createPresentation

Mobile Credential

  • Android Platform
    • Fixed error getting mobile credentials when one of the trusted issuer certificates is expired

6.1.0

Features

Mobile Credential

  • credential.mobile.sendProximityPresentationResponse added an optional parameter terminateSession: boolean which controls whether to terminate the session as a part of sending the response

Bug Fixes

Mobile Credential

  • Android Platform
    • Improved biometric authentication detection for devices with Android 10 (API Level 29) or lower
    • Improved local authentication error handling
    • Refined mobile credential verification result with detailed failure reason to improve the usability
    • Fixed device key JWK encoding with the correct padding
  • iOS Platform
    • Refined mobile credential verification result with detailed failure reason to improve the usability
    • Fixed proximity presentation response encoding issue for requests with no matched claims
    • Fixed Bluetooth connectivity detection for a proximity presentation session

6.0.0

BREAKING CHANGES

  • Rename fields on compact.verifyCredential and compactSemantic.verifyCredential
    • from assertExpiry to assertValidUntil
    • from assertNotBefore to assertValidFrom
  • rename values in VerifyFailureReasonType
    • from Expired to ValidUntil
    • from NotActive to ValidFrom

Features

Add support for web-semantic credentials with an issuanceDate in the future:

  • allow verification of web-semantic credentials with an issuanceDate in the future by adding an inactive status to VerifyWebSemanticCredentialResult to indicate that credential is inactive
  • allow creating presentations of web-semantic credentials with an issuanceDate

Expose NetworkError in case a remote request fails due to a network error or timeout in the following methods:

  • wallet.openid.isssuance.discover
  • wallet.openid.isssuance.retrieveToken

Bug Fixes

  • Refined did.messaging.resolveDidCommUri error results for remote DIDComm URI resolution responses, it could return

    • ResolveDidCommUriErrorType.NetworkError when the DIDComm URI is unresolvable
    • ResolveDidCommUriErrorType.InvalidDidCommUri when the resolution result does not conform to a valid DIDComm message
  • Improved network error detection for the following methods:

    • wallet.credential.webSemantic.createPresentation
    • wallet.did.messaging.openDidCommMessage

Notes

  • Dependency upgrades and vulnerability fixes
  • Removed the unused @mattrglobal/bbs-signatures dependency

5.0.0

BREAKING CHANGES

  • The initialise method could return the following errors:

    • UserAuthenticationUnrecoverableKeyError when user authentication key is unrecoverable, it requires re-initialisation of the SDK. This error type is only applicable on Android platform when @mattrglobal/mobile-credential-holder-react-native is enabled.
    • EcosystemInitialiseError when failed to initialise the @mattrglobal/ecosystem-sdk-react-native extension.
  • Refined error type for the did.messaging.resolveDidCommUri method to the following values:

    • ResolveDidCommUriErrorType.InvalidDidCommUri when provided URI does not resolve into a did comm message
    • ResolveDidCommUriErrorType.NetworkError when unable to resolve the DIDComm URI due to network issue
  • Expose NetworkError in case a remote request fails due to a network error or timeout in the following methods:

    • did.messaging.openDidCommMessage could return NetworkError when unable to resolve a remote DID document
    • credential.webSemantic.createPresentation could return NetworkError when unable to resolve a remote DID document

Features

  • Add Android support for mobile credential. Integration of the @mattrglobal/mobile-credential-holder-react-native extension into wallet sdk is now supported on both iOS and Android platforms. The current functionality includes

    • Retrieving mobile credentials over OpenID4VCI
    • Manage mobile credential store
    • Manage mobile credential trusted issuer certificates
    • Present mobile credentials to a verifier device over bluetooth
  • Cache the remote DID document resolution to prevent unnecessary requests.

  • Add support for ecosystem functionality from @mattrglobal/ecosystem-sdk-react-native extension. The current functionality includes:

    • Synchronize and cache ecosystem policies for the current ecosystem instance
    • Delete all cached policies of the current ecosystem instance
    • Validate that the specified issuer, or verifier, is authorized to issue, or verify, the credential, respectively
    • A new peer dependency is required @mattrglobal/ecosystem-sdk-react-native

Bug Fixes

  • Fix did.messaging.openDidCommMessage to return error result for remote resolution with non 2xx responses

Documentation

Notes

  • Dependency upgrades and vulnerability fixes

4.0.0

BREAKING CHANGES

  • No longer allow having multiple wallet instance with difference walletIds initialised at the same time. Before initialising a wallet instance with a different walletId, the current instance must be closed first.

    import { initialise } from "@mattrglobal/wallet-sdk-react-native";
    // Previously, the following is allowed.
    const initialiseResult1 = await initialise(walletId1);
    if (initialiseResult1.isErr()) {
    return;
    }
    const wallet1 = initialiseResult1.value;

    const initialiseResult2 = await initialise(walletId2);
    if (initialiseResult2.isErr()) {
    return;
    }
    const wallet2 = initialiseResult2.value;

    // Now, the existing wallet must be closed first
    const initialiseResult1 = await initialise(walletId1);
    if (initialiseResult1.isErr()) {
    return;
    }
    const wallet1 = initialiseResult1.value;
    await wallet1.close();

    const initialiseResult2 = await initialise(walletId2);
    if (initialiseResult2.isErr()) {
    return;
    }
    const wallet2 = initialiseResult2.value;
  • Wallet instance must be closed if it is currently initialised before calling destroy, otherwise an exception will be thrown.

  • Remove error type MalformedEncryptionKeyError that is actually unreacble on destroy method

  • Realm now requires >=12.1.0 as peer dependencies to avoid security vulnerability issue in Realm 11.

  • refine error types for wallet.credential.webSemantic.sendPresentationResponse

    • Removed SendWebSemanticPresentationResponseErrorType.FailedToSendPresentationResponse error type
    • Return SendWebSemanticPresentationResponseErrorType.VerificationFailed error when presentation response endpoint returns 400 Bad Request, which indicates an failure of verifying the presentation response
    • Return SendWebSemanticPresentationResponseErrorType.VerifierUnavailable error when presentation response endpoint, returns 504 Gateway Timeout, which indicates the verifier is unavailable. The details of the error will contain the verified for the result of the presentation verification.

Features

  • Add support for mobile credential (iOS Only). This allows user to integrate the mobile credential functionality from @mattrglobal/mobile-credential-holder-react-native into the wallet sdk. The current functionality includes

    • Retrieving mobile credentials over OpenID4VCI
    • Manage mobile credential store
    • Manage mobile credential trusted issuer certificates
    • Present mobile credentials to a verifier device over bluetooth
  • wallet.did.messaging.openDidCommMessage now checks JWM message expiries_time when available and return error if the message is expired.

  • wallet.credential.webSemantic.sendPresentationResponse now includes expires_time in the message

Notes

  • Dependencies upgrade and vulnerability fixes

3.0.0

BREAKING CHANGES

  • Support partial failure in wallet.webSemantic.retrieveCredentials method:

    • retrieveCredentials method no longer return error result if it fails to retrieve one of the credentials, instead it returns a union of credentials and errors.

      const retrieveCredentialsResult = await wallet.openid.issuance.retrieveCredentials({
      offer,
      accessToken,
      clientId,
      });

      /**
      * Example `retrieveCredentialsResult`
      * [
      * {
      * offer,
      * credential, // Successfully retrieved verifiable credential
      * },
      * {
      * offer,
      * error: { type, message, cause }, // Failure
      * }
      * ]
      */
  • Expose NetworkError in case a remote request fails due to a network error or timeout in the following methods:

    • wallet.credential.webSemantic.verifyCredential could return type VerifyWebSemanticCredentialErrorType.NetworkError
    • wallet.credential.webSemantic.deriveCredential could return type DeriveWebSemanticCredentialErrorType.NetworkError
    • wallet.credential.webSemantic.expandCredential could return type ExpandWebSemanticCredentialErrorType.NetworkError
    • wallet.credential.webSemantic.sendPresentationResponse could return type SendWebSemanticPresentationResponseErrorType.NetworkError
    • wallet.credential.webSemantic.filterCredentialsByQuery could return type PresentationRequestErrorType.NetworkError
    • wallet.openid.issuance.retrieveCredentials could return type RetrieveCredentialsErrorType.NetworkError in the new partial error format (see item above)
  • Consolidate create and open into initialise method

    // Previously
    import { create, open } from "@mattrglobal/wallet-sdk-react-native";
    const createWalletResult = await create();
    if (createWalletResult.isErr()) {
    return; // Handle error from createWalletResult.error
    }
    const openWalletResult = await open();
    if (openWalletResult.isErr()) {
    return; // Handle error from openWalletResult.error
    }
    const wallet = openWalletResult.value;
    ...

    // Now
    import { initialise } from "@mattrglobal/wallet-sdk-react-native";
    const initialiseResult = await initialise();
    if (initialiseResult.isErr()) {
    return; // Handle error from initialiseResult.error
    }
    const wallet = initialiseResult.value;
    ...

Bug Fixes

  • Fix webSemantic.verifyCredentials results
    • Do not assume isRevoked to be true if revocation status check failed
    • Do not assume expired to be false if credential signature verification failed

Notes

  • Add support for React Native 0.71

    • Require realm>=11.10.2

2.1.2

  • Add support for BbsSignature2022 verifiable credentials
  • A new peer dependency is required @mattrglobal/pairing-crypto-rn

2.1.1

  • Update change log
  • Address cve in semver dependency

2.1.0

Features

  • Add support to obtain compact and compact semantic credentials over OpenID4VCI
  • Add support to verify compact and compact semantic credentials

Bug Fixes

  • iOS: fix an issue that the keychain got reset after the wallet instance is created.

Notes

  • A new peer dependency is required @mattrglobal/react-native-cryptography

2.0.0

BREAKING CHANGES

  • Wallet SDK Interface:

    • Rename wallet.did.create to wallet.did.createDid
    • Rename wallet.did.delete to wallet.did.deleteDid
    • Rename wallet.did.list to wallet.did.listDids
    • Rename wallet.did.resolve to wallet.did.resolveDid
    • Rename wallet.wellKnownDidConfiguration to wallet.did.wellKnownDidConfiguration
    • Rename wallet.messaging to wallet.did.messaging
    • Rename wallet.credential.isSelectivelyDisclosable to wallet.credential.webSemantic.isCredentialSelectivelyDisclosable
    • Rename wallet.credential.derive to wallet.credential.webSemantic.deriveCredential
    • Rename wallet.credential.verify to wallet.credential.webSemantic.verifyCredential
    • Rename wallet.credential.expand to wallet.credential.webSemantic.expandCredential
    • Rename wallet.presentation.create to wallet.credential.webSemantic.createPresentation
    • Rename wallet.presentation.filterCredentialsByQuery to wallet.credential.webSemantic.filterCredentialsByQuery
    • Rename wallet.presentation.sendPresentationResponse to wallet.credential.webSemantic.sendPresentationResponse
  • Manual Credential Offer:

    • Replace format with profile
const offer: OpenidIssuanceCredentialOffer = {
...,
credentials: [
{
scope: "ldp_vc:UniversityDegreeCredential",
profile: "web-semantic",
credentialDefinition: {
"@context": ["https://www.w3.org/2018/credentials/v1"],
type: ["VerifiableCredential", "UniversityDegreeCredential"],
},
}
],
};
  • Retrieve Credentials:
    • Update return type of wallet.openid.issuance.retrieveCredentials
      • Replace format with profile
{
credentials: {
credential,
profile,
did,
}[];
}

Features

  • Add new top-level method qrcode

Bug Fixes

  • Replace big-integer with bignumber.js for the BigInt polyfill

1.7.1

Notes

  • Internal package maintenance
  • Update iOS installation docs

1.7.0

Features

  • Add support for resolving DIDCommUri

1.6.0

Features

  • Expose document loader timeout value (httpRequestTimeoutMs) under InitOptions and set the default value to 5 seconds.

1.5.0

Features

  • Add support for dynamic discovery (discover credential offer details via offer URI)
/**
* openid-credential-offer://?credential_offer=encodeURIComponent(JSON.stringify({ credential_issuer, credentials: [{credentialId}], request_parameters? }))
*/
const uri =
"openid-credential-offer://?credential_offer=%7B%22credential_issuer%22%3A%22https%3A%2F%2Fmyissuer.example.com%22%2C%22credentials%22%3A%5B%22707e920a-f342-443b-ae24-6946b7b5033e%22%5D%2C%22request_parameters%22%3A%7B%22login_hint%22%3A%22ken.huang%40mattr.global%22%2C%22prompt%22%3A%22login%22%7D%7D";

const offer = unwrap(await wallet.openid.issuance.discover(uri));

Export types:

  • FilterCredentialsByQueryError
  • FilterCredentialsByQueryResponse
  • PresentationRequestError

Update OpenId issuance offer types (WebSemantic)

const offer: OpenidIssuanceCredentialOffer = {
issuer: "https://example.com/",
authorizeEndpoint: "https://example.com/oauth/authorize",
tokenEndpoint: "https://example.com/oauth/token",
credentialEndpoint: "https://example.com/oauth/credential",
credentials: [
{
format: "ldp_vc",
scope: "UniversityDegreeCredential",
credentialDefinition: {
"@context": ["https://www.w3.org/2018/credentials/v1"],
type: ["VerifiableCredential", "UniversityDegreeCredential"],
},
},
],
};

Bug fixes

  • Updated retrieveCredentials to support deprecated options

1.4.1

Bug Fixes

  • Fix React Native android linking

1.4.0

Features

  • Expose some internal types and functions
  • Export types:
    • SecureKeyValueStoreErrorType
    • assertUnreachable

1.3.0

Features

  • Add support for React Native 0.70.0
  • Add support for Hermes engine
  • Migrate to use react-native-secure-key-store 2.0.10

1.2.1

Notes

  • Internal package maintenance

1.2.0

Features

  • Expose type validation functions:
    • isType
    • assertType
    • OpenidIssuanceCredentialOfferValidator
    • AuthorizeRequestParametersValidator
    • CredentialOfferedValidator
    • OpenidIssuanceGenerateAuthorizeUrlOptionsValidator
    • OpenidIssuanceRetrieveCredentialsOptionsValidator

1.1.1

Notes

  • Internal package maintenance

1.1.0

Features

  • Add support for obtaining multiple credentials over OpenID4VCI
  • Add support for React Native 0.68.5

1.0.5

Notes

  • Internal package maintenance

1.0.4

Notes

  • Internal package maintenance

1.0.3

Notes

  • Internal package maintenance

1.0.2

Notes

  • Internal package maintenance

1.0.1

Bug Fixes

  • Add missing polyfil and fix build error

Notes

  • Upgrade @mattrglobal/rn-bbs-signatures version

1.0.0

Features

  • Initialise a wallet
  • Manage local DIDs
  • Verify issuer DIDs to domain linkage
  • Obtain credentials over OIDC Bridge from the issuer
  • Verify credentials
  • Handle presentation request and present credentials to verifier
  • Create and open DID Comm messages

Generated using TypeDoc