@gramota/holder

Headless wallet — credential store + import/present/refill operations.

Install: pnpm add @gramota/holder

Source: github.com/gramota-org/gramota/tree/main/packages/holder

Classes

Holder

Defined in: @gramota/holder/dist/holder.d.ts:116

Constructors

Constructor
new Holder(config: HolderConfig): Holder;

Defined in: @gramota/holder/dist/holder.d.ts:129

Parameters
config

HolderConfig

Returns

Holder

Properties

credentials
readonly credentials: CredentialsApi;

Defined in: @gramota/holder/dist/holder.d.ts:126

Credential CRUD. holder.credentials.{receive, list, get, remove}(...).

offers
readonly offers: OffersApi;

Defined in: @gramota/holder/dist/holder.d.ts:128

OID4VCI offers. holder.offers.{parse, accept, authorize, claim}(...).

Accessors

publicKey
Get Signature
get publicKey(): JsonWebKey;

Defined in: @gramota/holder/dist/holder.d.ts:133

Public key — useful to share with issuers so they can bind credentials.

Returns

JsonWebKey

Methods

present()
present(options: PresentOptions): Promise<string>;

Defined in: @gramota/holder/dist/holder.d.ts:131

Build a selective-disclosure presentation against a stored credential.

Parameters
options

PresentOptions

Returns

Promise<string>

respond()
respond(requestUrl: string, options?: RespondOptions): Promise<RespondResult>;

Defined in: @gramota/holder/dist/holder.d.ts:145

Respond to an OID4VP Authorization Request URL.

The holder:

  1. Parses the URL.
  2. Runs DIF Presentation Exchange against stored credentials.
  3. Builds the presentation with selective disclosure.
  4. Builds the OID4VP authorization response form body.

Returns the body string ready to POST to response_uri, plus metadata.

Parameters
requestUrl

string

options?

RespondOptions

Returns

Promise<RespondResult>


InMemoryCredentialStore

Defined in: @gramota/holder/dist/store/memory.d.ts:4

Default in-process credential store. Loses data on process exit; use a persistent implementation for production.

Implements

Constructors

Constructor
new InMemoryCredentialStore(): InMemoryCredentialStore;
Returns

InMemoryCredentialStore

Methods

add()
add(credential: StoredCredential): Promise<void>;

Defined in: @gramota/holder/dist/store/memory.d.ts:6

Parameters
credential

StoredCredential

Returns

Promise<void>

Implementation of

CredentialStore.add

get()
get(id: string): Promise<StoredCredential>;

Defined in: @gramota/holder/dist/store/memory.d.ts:7

Parameters
id

string

Returns

Promise<StoredCredential>

Implementation of

CredentialStore.get

list()
list(query?: CredentialQuery): Promise<readonly StoredCredential[]>;

Defined in: @gramota/holder/dist/store/memory.d.ts:8

Parameters
query?

CredentialQuery

Returns

Promise<readonly StoredCredential[]>

Implementation of

CredentialStore.list

remove()
remove(id: string): Promise<boolean>;

Defined in: @gramota/holder/dist/store/memory.d.ts:9

Parameters
id

string

Returns

Promise<boolean>

Implementation of

CredentialStore.remove


HolderError

Defined in: @gramota/holder/dist/types.d.ts:87

Extends

  • GramotaError

Constructors

Constructor
new HolderError(
   code: HolderErrorCode, 
   message: string, 
   options?: {
  cause?: unknown;
}): HolderError;

Defined in: @gramota/holder/dist/types.d.ts:89

Parameters
code

HolderErrorCode

message

string

options?
cause?

unknown

Returns

HolderError

Overrides
GramotaError.constructor

Properties

cause?
readonly optional cause?: unknown;

Defined in: .pnpm/@gramota+core@0.2.1/node_modules/@gramota/core/dist/error.d.ts:44

Optional original error that caused this one. Always set when the Gramota package is wrapping a thrown exception from a dependency (Web Crypto, JOSE, fetch). Survives JSON.stringify(err) only via the cause property — Node 16.9+ logs it natively.

Inherited from
GramotaError.cause
code
readonly code: HolderErrorCode;

Defined in: @gramota/holder/dist/types.d.ts:88

Stable string that identifies the failure mode. Subclasses narrow the type; at runtime it's always a string. Use for branching, logs, and metrics labels — never serialize GramotaError.message for that purpose, message strings drift across versions.

Overrides
GramotaError.code
name
name: string;

Defined in: .pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es5.d.ts:1076

Inherited from
GramotaError.name
message
message: string;

Defined in: .pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es5.d.ts:1077

Inherited from
GramotaError.message
stack?
optional stack?: string;

Defined in: .pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es5.d.ts:1078

Inherited from
GramotaError.stack

Interfaces

OffersApi

Defined in: @gramota/holder/dist/holder.d.ts:6

Stripe-style sub-API for OID4VCI credential offers. holder.offers.X(...).

Methods

parse()
parse(url: string): CredentialOffer;

Defined in: @gramota/holder/dist/holder.d.ts:9

Parse a credential offer URL with no network I/O — preview an offer before deciding to accept it.

Parameters
url

string

Returns

CredentialOffer

accept()
accept(url: string, options: AcceptOptions): Promise<StoredCredential>;

Defined in: @gramota/holder/dist/holder.d.ts:15

Accept a credential offer end-to-end via the pre-authorized code flow: parse → fetch metadata → token → proof JWT → credential request → validate → store. Returns the StoredCredential, same shape as holder.credentials.receive. Throws if the offer doesn't include a pre-authorized_code grant — use authorize + claim for auth-code.

Parameters
url

string

options

AcceptOptions

Returns

Promise<StoredCredential>

authorize()
authorize(url: string, options: AuthorizeOptions): Promise<AuthorizeResult>;

Defined in: @gramota/holder/dist/holder.d.ts:23

Step 1 of the OID4VCI auth-code flow. Returns the URL the wallet must navigate the user to, plus PKCE+state secrets to keep until step 2. The Holder caches flow context (metadata, offer, redirect_uri, client_id) keyed by state, so step 2 only needs the callback + verifier + state.

Parameters
url

string

options

AuthorizeOptions

Returns

Promise<AuthorizeResult>

claim()
claim(options: ClaimOptions): Promise<StoredCredential>;

Defined in: @gramota/holder/dist/holder.d.ts:27

Step 2: exchange the issuer's redirect-callback for a credential, validate it against trustedIssuers, and store it. Looks up the pending flow by state (same value passed to/from authorize).

Parameters
options

ClaimOptions

Returns

Promise<StoredCredential>


AcceptOptions

Defined in: @gramota/holder/dist/holder.d.ts:31

Options for holder.offers.accept(). Extends OID4VCI's accept options with trustedIssuers (same semantics as credentials.receive).

Extends

  • AcceptOfferOptions

Properties

trustedIssuers
trustedIssuers: readonly JsonWebKey[];

Defined in: @gramota/holder/dist/holder.d.ts:34

Trusted issuer JWKs the received credential's signature must verify against. The credential is rejected if it does not.

txCode?
optional txCode?: string;

Defined in: .pnpm/@gramota+oid4vci@0.3.0/node_modules/@gramota/oid4vci/dist/client.d.ts:69

Transaction code (PIN) — supplied when the offer's tx_code requires it.

Inherited from
AcceptOfferOptions.txCode
credentialConfigurationId?
optional credentialConfigurationId?: string;

Defined in: .pnpm/@gramota+oid4vci@0.3.0/node_modules/@gramota/oid4vci/dist/client.d.ts:71

Override which credential_configuration_id to request. Default: first.

Inherited from
AcceptOfferOptions.credentialConfigurationId
proofIat?
optional proofIat?: number;

Defined in: .pnpm/@gramota+oid4vci@0.3.0/node_modules/@gramota/oid4vci/dist/client.d.ts:73

Override iat in the proof JWT — for tests.

Inherited from
AcceptOfferOptions.proofIat
fetcher?
optional fetcher?: Fetcher;

Defined in: .pnpm/@gramota+oid4vci@0.3.0/node_modules/@gramota/oid4vci/dist/client.d.ts:75

Override fetcher per-call.

Inherited from
AcceptOfferOptions.fetcher

AuthorizeOptions

Defined in: @gramota/holder/dist/holder.d.ts:37

Options for holder.offers.authorize().

Properties

redirectUri
redirectUri: string;

Defined in: @gramota/holder/dist/holder.d.ts:40

Where the issuer should redirect the user after consent. Must match a redirect URI registered with / accepted by the issuer.

clientId?
optional clientId?: string;

Defined in: @gramota/holder/dist/holder.d.ts:43

OAuth client_id. Defaults to redirectUri (a common public-client pattern when the wallet has no separate registered identifier).

credentialConfigurationId?
optional credentialConfigurationId?: string;

Defined in: @gramota/holder/dist/holder.d.ts:45

Override which credential to request. Default: first id from the offer.

scope?
optional scope?: string;

Defined in: @gramota/holder/dist/holder.d.ts:47

Optional OAuth scope.

codeVerifier?
optional codeVerifier?: string;

Defined in: @gramota/holder/dist/holder.d.ts:49

Optional pre-existing PKCE verifier — for tests. Default: random.

state?
optional state?: string;

Defined in: @gramota/holder/dist/holder.d.ts:51

Optional pre-existing CSRF state — for tests. Default: random.

fetcher?
optional fetcher?: Fetcher;

Defined in: @gramota/holder/dist/holder.d.ts:53

Optional fetcher override.


AuthorizeResult

Defined in: @gramota/holder/dist/holder.d.ts:56

Result of holder.offers.authorize().

Properties

authorizationUrl
authorizationUrl: string;

Defined in: @gramota/holder/dist/holder.d.ts:58

Open this URL in the user's browser.

codeVerifier
codeVerifier: string;

Defined in: @gramota/holder/dist/holder.d.ts:60

Persist with the user's session — passed to claim.

state
state: string;

Defined in: @gramota/holder/dist/holder.d.ts:63

Persist and verify against ?state= on the callback. Doubles as the lookup key for the pending flow inside the Holder.


ClaimOptions

Defined in: @gramota/holder/dist/holder.d.ts:66

Options for holder.offers.claim().

Properties

callbackUrl
callbackUrl: string;

Defined in: @gramota/holder/dist/holder.d.ts:68

The full callback URL the issuer redirected to (with ?code=&state=).

codeVerifier
codeVerifier: string;

Defined in: @gramota/holder/dist/holder.d.ts:70

From authorize's result.

state
state: string;

Defined in: @gramota/holder/dist/holder.d.ts:72

From authorize's result. Used as lookup key for the pending flow.

trustedIssuers
trustedIssuers: readonly JsonWebKey[];

Defined in: @gramota/holder/dist/holder.d.ts:74

Trusted issuer JWKs the received credential must verify against.

fetcher?
optional fetcher?: Fetcher;

Defined in: @gramota/holder/dist/holder.d.ts:76

Optional fetcher override.

proofIat?
optional proofIat?: number;

Defined in: @gramota/holder/dist/holder.d.ts:78

Override iat in the proof JWT — for tests.


RespondOptions

Defined in: @gramota/holder/dist/holder.d.ts:81

Options for holder.respondTo().

Properties

now?
optional now?: () => number;

Defined in: @gramota/holder/dist/holder.d.ts:83

Override "now" — for tests.

Returns

number

pickCredential?
optional pickCredential?: (candidates: readonly {
  credential: StoredCredential;
  disclose: readonly string[];
}[]) => {
  credential: StoredCredential;
  disclose: readonly string[];
};

Defined in: @gramota/holder/dist/holder.d.ts:86

When the verifier supplies multiple compatible credentials and you want to control which one is presented, pass a picker. Default: first match.

Parameters
candidates

readonly { credential: StoredCredential; disclose: readonly string[]; }[]

Returns
{
  credential: StoredCredential;
  disclose: readonly string[];
}
credential
credential: StoredCredential;
disclose
disclose: readonly string[];

RespondResult

Defined in: @gramota/holder/dist/holder.d.ts:95

Result of holder.respondTo().

Properties

body
body: string;

Defined in: @gramota/holder/dist/holder.d.ts:97

Form-encoded body to POST to the verifier's response_uri.

credential
credential: StoredCredential;

Defined in: @gramota/holder/dist/holder.d.ts:99

The matched credential (id + token + parsed).

disclosed
disclosed: readonly string[];

Defined in: @gramota/holder/dist/holder.d.ts:101

What was disclosed.

request
request: AuthorizationRequest;

Defined in: @gramota/holder/dist/holder.d.ts:103

The original parsed request, for caller logging.


CredentialsApi

Defined in: @gramota/holder/dist/holder.d.ts:106

Stripe-style sub-API for credential CRUD. holder.credentials.X(...).

Methods

receive()
receive(token: string, options: ReceiveOptions): Promise<StoredCredential>;

Defined in: @gramota/holder/dist/holder.d.ts:108

Validate and store an issued SD-JWT-VC.

Parameters
token

string

options

ReceiveOptions

Returns

Promise<StoredCredential>

get()
get(id: string): Promise<StoredCredential>;

Defined in: @gramota/holder/dist/holder.d.ts:110

Get one stored credential by id.

Parameters
id

string

Returns

Promise<StoredCredential>

list()
list(query?: CredentialQuery): Promise<readonly StoredCredential[]>;

Defined in: @gramota/holder/dist/holder.d.ts:112

List stored credentials, optionally filtered.

Parameters
query?

CredentialQuery

Returns

Promise<readonly StoredCredential[]>

remove()
remove(id: string): Promise<boolean>;

Defined in: @gramota/holder/dist/holder.d.ts:114

Remove a credential. Returns true if it existed.

Parameters
id

string

Returns

Promise<boolean>


StoredCredential

Defined in: @gramota/holder/dist/types.d.ts:7

A credential the holder has received and validated.

Properties

id
id: string;

Defined in: @gramota/holder/dist/types.d.ts:8

token
token: string;

Defined in: @gramota/holder/dist/types.d.ts:10

The original compact-serialised SD-JWT-VC issuance token.

parsed
parsed: ParsedSdJwt;

Defined in: @gramota/holder/dist/types.d.ts:12

Pre-parsed view; pre-computed for faster queries.

issuer
issuer: string;

Defined in: @gramota/holder/dist/types.d.ts:14

Issuer identifier, copied out of iss for indexed access.

receivedAt
receivedAt: number;

Defined in: @gramota/holder/dist/types.d.ts:16

Unix seconds of when the holder accepted this credential.


CredentialQuery

Defined in: @gramota/holder/dist/types.d.ts:19

Optional filter when listing stored credentials.

Properties

issuer?
optional issuer?: string;

Defined in: @gramota/holder/dist/types.d.ts:20

withClaim?
optional withClaim?: string;

Defined in: @gramota/holder/dist/types.d.ts:22

Match credentials that contain a given selectively-disclosable claim.


CredentialStore

Defined in: @gramota/holder/dist/types.d.ts:33

Persistence boundary (Strategy + Repository pattern).

Implementations are interchangeable — Holder depends only on this interface (Dependency Inversion). Default: InMemoryCredentialStore.

Future implementations: FileCredentialStore, EncryptedCredentialStore, IndexedDBCredentialStore (browser).

Methods

add()
add(credential: StoredCredential): Promise<void>;

Defined in: @gramota/holder/dist/types.d.ts:34

Parameters
credential

StoredCredential

Returns

Promise<void>

get()
get(id: string): Promise<StoredCredential>;

Defined in: @gramota/holder/dist/types.d.ts:35

Parameters
id

string

Returns

Promise<StoredCredential>

list()
list(query?: CredentialQuery): Promise<readonly StoredCredential[]>;

Defined in: @gramota/holder/dist/types.d.ts:36

Parameters
query?

CredentialQuery

Returns

Promise<readonly StoredCredential[]>

remove()
remove(id: string): Promise<boolean>;

Defined in: @gramota/holder/dist/types.d.ts:37

Parameters
id

string

Returns

Promise<boolean>


ReceiveOptions

Defined in: @gramota/holder/dist/types.d.ts:68

Properties

trustedIssuers
trustedIssuers: readonly JsonWebKey[];

Defined in: @gramota/holder/dist/types.d.ts:71

Public JWKs of issuers the holder trusts. The credential's signature must verify against at least one.


PresentOptions

Defined in: @gramota/holder/dist/types.d.ts:73

Properties

credentialId
credentialId: string;

Defined in: @gramota/holder/dist/types.d.ts:74

disclose
disclose: readonly string[];

Defined in: @gramota/holder/dist/types.d.ts:77

Names of object claims to selectively disclose. All must be available in the credential. To disclose nothing, pass [].

audience
audience: string;

Defined in: @gramota/holder/dist/types.d.ts:79

Verifier identifier — bound into the KB-JWT's aud claim.

nonce
nonce: string;

Defined in: @gramota/holder/dist/types.d.ts:81

Verifier challenge — bound into the KB-JWT's nonce claim.

now?
optional now?: () => number;

Defined in: @gramota/holder/dist/types.d.ts:83

Override "now" — for tests.

Returns

number

Type Aliases

CredentialId

type CredentialId = string;

Defined in: @gramota/holder/dist/types.d.ts:5

Identifier of a stored credential. UUID v4, generated at receive time.


HolderConfig

type HolderConfig = HolderSignerInput & {
  store?: CredentialStore;
};

Defined in: @gramota/holder/dist/types.d.ts:64

Configuration for a Holder instance.

Type Declaration

store?
optional store?: CredentialStore;

Storage backend. Default: in-memory (lost on process exit).


HolderErrorCode

type HolderErrorCode = 
  | "holder.invalid_input"
  | "holder.malformed_token"
  | "holder.no_trusted_issuers"
  | "holder.issuer_signature_invalid"
  | "holder.disclosure_forged"
  | "holder.cnf_missing"
  | "holder.cnf_mismatch"
  | "holder.credential_not_found"
  | "holder.disclosure_unavailable"
  | "holder.pd_unsatisfiable"
  | "holder.pd_required"
  | "holder.multi_credential_unsupported"
  | "holder.unknown_flow";

Defined in: @gramota/holder/dist/types.d.ts:86

Stable codes for HolderError.