npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@the-hashgraph-group-ag/identity-client-sdk-js-holder

v0.6.0

Published

Holder Client SDK for OIDC4VCI credential issuance and management

Readme

Holder Client SDK

Client-side SDK for orchestrating credential issuance and presentation using OID4VCI, OID4VP, DID management, and self-issuance. You provide handlers for each domain; the SDK exposes a unified API via sdk.issuance, sdk.presentation, sdk.did, and sdk.selfIssuance.

Purpose

The Holder Client SDK is a client-side orchestrator for credential issuance (OID4VCI), presentation (OID4VP), decentralized identity (DID), and self-issued credentials. It is handler-based: you register one or more implementations of IOID4VCIHandler, IOID4VPHandler, IDIDHandler, and optionally ISelfIssuanceHandler. The first registered handler of each type becomes active; you can switch at runtime with useOID4VCIHandler, useOID4VPHandler, useDIDHandler, or useSelfIssuanceHandler.

Features

OID4VCI (Credential Issuance)

  • Resolve credential offer URIs
  • Get issuer and authorization server metadata
  • Request access tokens and credentials
  • Proof of possession (PoP)
  • Deferred credential issuance and polling

OID4VP (Credential Presentation)

  • Validate presentation requests and build verifiable presentations
  • Generate signed VP tokens (DataIntegrityProof, Ed25519Signature2020)
  • Match credentials to Presentation Definitions and create presentation submissions
  • DCQL-based and Presentation Definition–based flows

DID Management

  • Resolve, create, and deactivate DIDs via a pluggable handler

Self-Issuance

  • Compose and validate self-issued credentials via ISelfIssuanceHandler

DCQL

  • Parse and validate DCQL requests; match queries against credentials (see packages/holder/src/dcql/README.md).

Installation

pnpm add @the-hashgraph-group-ag/identity-client-sdk-js-holder

Getting Started

You must register at least one handler per namespace you use (issuance, presentation, did, selfIssuance). The SDK does not ship default implementations; you wire your own (e.g. from @the-hashgraph-group-ag/identity-client-sdk-js-holder handlers or custom).

import { HolderSDK } from '@the-hashgraph-group-ag/identity-client-sdk-js-holder';
import { OID4VCIIssuanceHandler } from '@the-hashgraph-group-ag/identity-client-sdk-js-holder';
import { OID4VPHandler } from '@the-hashgraph-group-ag/identity-client-sdk-js-holder';
import { DIDHandler } from '@the-hashgraph-group-ag/identity-client-sdk-js-holder';

const sdk = new HolderSDK({
  OID4VCIHandlers: [
    new OID4VCIIssuanceHandler({
      /* config */
    }),
  ],
  OID4VPHandlers: [
    new OID4VPHandler({
      /* config */
    }),
  ],
  DIDHandlers: [new DIDHandler({ didApiUrl: 'https://...' })],
});

// Issuance: resolve offer, then request credential
const resolved = await sdk.issuance.resolveCredentialOffer({ uri: credentialOfferUri });
const credential = await sdk.issuance.requestCredential({
  accessToken: '...',
  credentialIdentifier: resolved.credentialIdentifier,
  credentialDataSupplierInput: { credentialSubject: { name: 'Jane' } },
});

// Presentation: build VP from request
const vp = await sdk.presentation.buildPresentation(request, getProof);

// DID: resolve or create
const doc = await sdk.did.resolve({ did: 'did:hedera:testnet:...' });
const { did } = await sdk.did.create({ ...params, sign });

API Overview

HolderSDK

Constructor: new HolderSDK(options?: Partial<HolderSDKOptions>)

  • options.OID4VCIHandlers – optional array of IOID4VCIHandler
  • options.OID4VPHandlers – optional array of IOID4VPHandler
  • options.DIDHandlers – optional array of IDIDHandler
  • options.selfIssuanceHandlers – optional array of ISelfIssuanceHandler

Getters (throw HandlerNotSetError if no handler is set):

  • sdk.issuance – current IOID4VCIHandler
  • sdk.presentation – current IOID4VPHandler
  • sdk.did – current IDIDHandler
  • sdk.selfIssuance – current ISelfIssuanceHandler

Registration: registerHandler(handler), registerOID4VCIHandler(handler), registerOID4VPHandler(handler), registerDIDHandler(handler), registerSelfIssuanceHandler(handler).

Switch active handler: useOID4VCIHandler(handler), useOID4VPHandler(handler), useDIDHandler(handler), useSelfIssuanceHandler(handler).

List handlers: getOID4VCIHandlers(), getOID4VPHandlers(), getDIDHandlers(), getSelfIssuanceHandlers().

Handler interfaces

  • IOID4VCIHandler – getAuthorizationServerMetadata, getCredentialIssuerMetadata, resolveCredentialOffer, requestCredential, requestDeferredCredential, pollDeferredCredential, createProofOfPossession, requestAccessToken, requestCNonce.
  • IOID4VPHandler – validateRequest, buildPresentation, getAuthorizationServerMetadata, generateVPToken, formatAsVPToken, formatMultipleVPTokens, matchPresentationDefinition, createPresentationSubmission, createSubmissionFromMatchResult, formatVPTokenForPresentationDefinition, verifyPresentationSubmission.
  • IDIDHandler – resolve, create, deactivate.
  • ISelfIssuanceHandler – compose, validate.

OID4VCI flow (example)

// Construct the SDK without a fixed issuer URL when you want to be host-agnostic.
const sdk = new HolderSDK({
  OID4VCIHandlers: [new OID4VCIHandler({ id: 'default' })],
  // ...other handlers...
});

// `resolveCredentialOffer` discovers the issuer host from the offer and
// exposes it as `issuerUrl` on the returned object.
const resolved = await sdk.issuance.resolveCredentialOffer({ uri: credentialOfferUri });

// `requestAccessToken` is optional on `IOID4VCIHandler`; the bundled
// `OID4VCIHandler` always implements it, so we assert it here.
const tokenResponse = await sdk.issuance.requestAccessToken!({
  preAuthorizedCode: resolved.preAuthorizedCode,
  grantType: 'urn:ietf:params:oauth:grant-type:pre-authorized_code',
  issuerUrl: resolved.issuerUrl,
});

const credential = await sdk.issuance.requestCredential({
  accessToken: tokenResponse.access_token,
  credentialIdentifier: resolved.credentialIdentifier,
  credentialDataSupplierInput: { credentialSubject: { name: 'Jane', degree: 'BSc' } },
  issuerUrl: resolved.issuerUrl,
});

You can also pin a default issuer host at construction time (new OID4VCIHandler({ id, url })) and skip issuerUrl per call — the constructor URL becomes the fallback. If neither is provided, calls throw ValidationError.

OID4VP flow (agnostic verifier host)

// Construct the SDK without a fixed verifier URL when you want to be host-agnostic.
const sdk = new HolderSDK({
  OID4VPHandlers: [new OID4VPHandler({ id: 'default' })],
  // ...other handlers...
});

// `parseRequestUri` extracts the verifier host once, at QR-parse time.
const { request_uri, request_uri_method, verifierUrl } = sdk.presentation.parseRequestUri(qrUri);

const jwt = await sdk.presentation.getVpRequestJwt(request_uri, request_uri_method);
const request = sdk.presentation.decodeJwtPayload(jwt);
sdk.presentation.validateRequest(request);

// ...build VP token (unchanged flow)...

const result = await sdk.presentation.verifyPresentationSubmission({
  state: request.state,
  vp_token: vpTokenString,
  presentation_submission: submissionString,
  verifierUrl,
});

You can also pin a default verifier host at construction time (new OID4VPHandler({ id, url })) and skip verifierUrl per call — the constructor URL becomes the fallback. If neither is provided, calls throw ValidationError.

OID4VP: generate VP token

const vp = await sdk.presentation.generateVPToken({
  holderDid: 'did:hedera:testnet:...',
  privateKey: privateKeyHexOrPemOrUint8Array,
  credentials: [credential],
  proofPurpose: 'authentication',
  challenge: 'nonce-from-verifier',
  verificationMethodKey: 'did-root-key',
});

Supported private key formats: hex (96 or 64 chars), PEM PKCS#8, Uint8Array (32- or 64-byte).

DCQL

See DCQL README for parsing, validation, and matching of DCQL requests.

Error handling

Errors are thrown from the core package (@the-hashgraph-group-ag/identity-client-sdk-js-core):

  • HandlerNotSetError – thrown when you access sdk.issuance, sdk.presentation, sdk.did, or sdk.selfIssuance and no handler has been registered for that namespace. Register at least one handler (e.g. in the constructor or via registerOID4VCIHandler etc.) before using the getter.
  • HttpError – thrown by handlers when an HTTP request returns 4xx/5xx (e.g. responseInterceptors: [throwOnHttpError]). Has status, data, headers.
  • ValidationError – thrown when input validation fails (e.g. invalid DID, missing required field). Has message and optional field.

Use instanceof to handle them: if (err instanceof HandlerNotSetError) { ... }.

Development

Testing

pnpm test:all
pnpm test:utils
pnpm test:sdk

Building

pnpm build