
Research
/Security News
Shai Hulud Strikes Again (v2)
Another wave of Shai-Hulud campaign has hit npm with more than 500 packages and 700+ versions affected.
@animo-id/expo-digital-credentials-api
Advanced tools
Expo wrapper around Android Digital Credentials API
Getting started  | Contributing  | License
An Expo Module to automatically set up and configure Digital Credentials API for Android in Expo apps.
[!NOTE]
This library integrates with experimental Android APIs, as well as draft versions of several specifications. Expect all APIs to break in future releases.
Install the module using the following command.
# yarn
yarn add @animo-id/expo-digital-credentials-api
# npm
npm install @animo-id/expo-digital-credentials-api
# npm
pnpm install @animo-id/expo-digital-credentials-api
Then prebuild the application so the Expo Module wrapper can be added as native dependency (If you aren't making any manual modification to the Android directories you can add them to the gitignore of your project and generate them on demand):
# yarn
yarn expo prebuild
# npm
npx expo prebuild
That's it, you now have the Digital Credentials API configured for your Android project.
[!WARNING]
You might need to set the Kotlin version of your project to 2.0.21. To do this, add theexpo-build-propertiesdependency to your project, and configure it withandroid.kotlinVersionset to'2.0.21'.[ "expo-build-properties", { "android": { "kotlinVersion": "2.0.21" } } ]
You can now import @animo-id/expo-digital-credentials-api in your application.
To make Android aware of the credentials availble in your wallet, you need to register the credentials. Every time the credentials in your application changes, you should call this method again.
When registering credentials you can also choose the matcher that is used. When registering credentials with a new matcher the old matcher will not be used anymore (the latest register call always overrides previous calls). The supported matchers are:
import {
registerCredentials,
RegisterCredentialsOptions,
} from "@animo-id/expo-digital-credentials-api";
// See RegisterCredentialsOptions for all options
await registerCredentials({
matcher: "cmwallet",
credentials: [
{
id: "1",
display: {
title: "Drivers License",
subtitle: "Issued by Utopia",
claims: [
{
path: ["org.iso.18013.5.1", "family_name"],
displayName: "Family Name",
},
],
iconDataUrl:
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAIAAAAlC+aJAAAAaUlEQVR4nOzPUQkAIQDA0OMwpxksY19D+PEQ9hJsY6/5vezXAbca0BrQGtAa0BrQGtAa0BrQGtAa0BrQGtAa0BrQGtAa0BrQGtAa0BrQGtAa0BrQGtAa0BrQGtAa0BrQGtAa0E4AAAD//7vSAeZjAN7dAAAAAElFTkSuQmCC",
},
credential: {
doctype: "org.iso.18013.5.1.mDL",
format: "mso_mdoc",
namespaces: {
"org.iso.18013.5.1": {
family_name: "Glastra",
},
},
},
},
{
id: "2",
display: {
title: "PID",
subtitle: "Issued by Utopia",
claims: [
{
path: ["first_name"],
displayName: "First Name",
},
{
path: ["address", "city"],
displayName: "Resident City",
},
],
iconDataUrl:
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAIAAAAlC+aJAAAAaUlEQVR4nOzPUQkAIQDA0OMwpxksY19D+PEQ9hJsY6/5vezXAbca0BrQGtAa0BrQGtAa0BrQGtAa0BrQGtAa0BrQGtAa0BrQGtAa0BrQGtAa0BrQGtAa0BrQGtAa0BrQGtAa0E4AAAD//7vSAeZjAN7dAAAAAElFTkSuQmCC",
},
credential: {
vct: "eu.europa.ec.eudi.pid.1",
format: "dc+sd-jwt",
claims: {
first_name: "Timo",
address: {
city: "Somewhere",
},
},
},
},
],
} satisfies RegisterCredentialsOptions);
When the user has selected a credential from your application, the application will be launched with an intent to retrieve the credentials. A custom component will be used and rendered as an overlay.
You should register the component as early as possible, usually in your index.ts file. If you're using Expo Router, follow these steps to setup a custom entry point.
The component will be rendered in a full screen window, but with a transparent background. This allows you to render an overlay rather than a full screen application. By default all screen content that you do not render something over, has an onPress handler and will abort the request. You can disable this by setting cancelOnPressBackground to false.
import { registerRootComponent } from "expo";
import App from "./App";
import { MyCustomComponent } from "./MyCustomComponent";
// import the component registration method
// make sure to import this from the /register path
// so it doesn't load the native module yet, as that will prevent the app from correctly loading
import registerGetCredentialComponent from "@animo-id/expo-digital-credentials-api/register";
// Registers the componetn to be used for sharing credentials
registerGetCredentialComponent(MyCustomComponent);
// Default expo method call
registerRootComponent(App);
The request is passed to the registered component as request and has type DigitalCredentialsRequest.
import {
type DigitalCredentialsRequest,
sendErrorResponse,
sendResponse,
} from "@animo-id/expo-digital-credentials-api";
import { Button } from "react-native";
import { Text, View } from "react-native";
export function MyCustomComponent({
request,
}: {
request: DigitalCredentialsRequest;
}) {
return (
<View style={{ width: "100%" }}>
<Button
title="Send Response"
onPress={() =>
sendResponse({ response: JSON.stringify({ vp_token: "something" }) })
}
/>
<Button
title="Send Error Response"
onPress={() =>
sendErrorResponse({ errorMessage: "Send error response" })
}
/>
</View>
);
}
If you're using Expo Router, the root application is automatically loaded and executed, even if a custom activity is launched in React Native, and thus your main application logic will be executed (although not visible).
To prevent this from happening, you can create a small wrapper that returns null when the current activity is the get credential activitiy using the isGetCredentialActivity method. Make sure to only call this method once your app component is loaded, to prevent the app loading to get stuck.
import { isGetCredentialActivity } from "@animo-id/expo-digital-credentials-api";
export default function App() {
const isDcApi = useMemo(() => isGetCredentialActivity(), []);
if (isDcApi) return null;
return <MainApp />;
}
Is there something you'd like to fix or add? Great, we love community contributions! To get involved, please follow our contribution guidelines.
Expo Digital Credentials Api is licensed under the Apache 2.0 license.
FAQs
Expo wrapper around Android Digital Credentials API
We found that @animo-id/expo-digital-credentials-api demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 4 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
/Security News
Another wave of Shai-Hulud campaign has hit npm with more than 500 packages and 700+ versions affected.

Product
Add real-time Socket webhook events to your workflows to automatically receive software supply chain alert changes in real time.

Security News
ENISA has become a CVE Program Root, giving the EU a central authority for coordinating vulnerability reporting, disclosure, and cross-border response.