@interop/wallet-core 0.68.0 → 0.70.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -41
- package/dist/clientAnnex/credentialAnchoredGenesis.d.ts +12 -1
- package/dist/clientAnnex/credentialAnchoredGenesis.d.ts.map +1 -1
- package/dist/clientAnnex/credentialAnchoredGenesis.js +9 -2
- package/dist/clientAnnex/credentialAnchoredGenesis.js.map +1 -1
- package/dist/clientAnnex/establish.d.ts +10 -0
- package/dist/clientAnnex/establish.d.ts.map +1 -1
- package/dist/clientAnnex/establish.js +14 -2
- package/dist/clientAnnex/establish.js.map +1 -1
- package/dist/clientAnnex/ladder.d.ts +103 -57
- package/dist/clientAnnex/ladder.d.ts.map +1 -1
- package/dist/clientAnnex/ladder.js +254 -335
- package/dist/clientAnnex/ladder.js.map +1 -1
- package/dist/clientAnnex/ladderAnchored.d.ts.map +1 -1
- package/dist/clientAnnex/ladderAnchored.js +10 -5
- package/dist/clientAnnex/ladderAnchored.js.map +1 -1
- package/dist/clientAnnex/mend.d.ts +19 -4
- package/dist/clientAnnex/mend.d.ts.map +1 -1
- package/dist/clientAnnex/mend.js +83 -35
- package/dist/clientAnnex/mend.js.map +1 -1
- package/dist/clientAnnex/recoveryLadderAnchored.d.ts +3 -15
- package/dist/clientAnnex/recoveryLadderAnchored.d.ts.map +1 -1
- package/dist/clientAnnex/recoveryLadderAnchored.js +22 -3
- package/dist/clientAnnex/recoveryLadderAnchored.js.map +1 -1
- package/dist/clientAnnex/rosterDeliveredEpochs.d.ts +13 -14
- package/dist/clientAnnex/rosterDeliveredEpochs.d.ts.map +1 -1
- package/dist/clientAnnex/rosterDeliveredEpochs.js +12 -12
- package/dist/clientAnnex/rosterDeliveredEpochs.js.map +1 -1
- package/dist/clients/grantState.d.ts +67 -0
- package/dist/clients/grantState.d.ts.map +1 -0
- package/dist/clients/grantState.js +72 -0
- package/dist/clients/grantState.js.map +1 -0
- package/dist/clients/index.d.ts +7 -0
- package/dist/clients/index.d.ts.map +1 -1
- package/dist/clients/index.js +6 -0
- package/dist/clients/index.js.map +1 -1
- package/dist/descriptors/index.d.ts +21 -46
- package/dist/descriptors/index.d.ts.map +1 -1
- package/dist/descriptors/index.js +21 -45
- package/dist/descriptors/index.js.map +1 -1
- package/dist/descriptors/logSource.d.ts +45 -56
- package/dist/descriptors/logSource.d.ts.map +1 -1
- package/dist/descriptors/logSource.js +64 -74
- package/dist/descriptors/logSource.js.map +1 -1
- package/dist/enrollment/connectCode.d.ts +4 -3
- package/dist/enrollment/connectCode.d.ts.map +1 -1
- package/dist/enrollment/connectCode.js +4 -3
- package/dist/enrollment/connectCode.js.map +1 -1
- package/dist/enrollment/index.d.ts +2 -2
- package/dist/enrollment/index.js +2 -2
- package/dist/enrollment/onboardingInvite.d.ts +1 -1
- package/dist/enrollment/onboardingInvite.js +1 -1
- package/dist/enrollment/onboardingResponse.js +1 -1
- package/dist/genesis/accountGenesis.d.ts +13 -1
- package/dist/genesis/accountGenesis.d.ts.map +1 -1
- package/dist/genesis/accountGenesis.js +11 -2
- package/dist/genesis/accountGenesis.js.map +1 -1
- package/dist/identity/index.d.ts +1 -1
- package/dist/identity/index.js +1 -1
- package/dist/index.d.ts +4 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -8
- package/dist/index.js.map +1 -1
- package/dist/keyring/kdf.d.ts +33 -19
- package/dist/keyring/kdf.d.ts.map +1 -1
- package/dist/keyring/kdf.js +36 -25
- package/dist/keyring/kdf.js.map +1 -1
- package/dist/keys/collectionLogStore.d.ts +73 -0
- package/dist/keys/collectionLogStore.d.ts.map +1 -0
- package/dist/keys/collectionLogStore.js +60 -0
- package/dist/keys/collectionLogStore.js.map +1 -0
- package/dist/keys/index.d.ts +18 -6
- package/dist/keys/index.d.ts.map +1 -1
- package/dist/keys/index.js +18 -6
- package/dist/keys/index.js.map +1 -1
- package/dist/keys/rosterLogStore.d.ts +44 -6
- package/dist/keys/rosterLogStore.d.ts.map +1 -1
- package/dist/keys/rosterLogStore.js +51 -238
- package/dist/keys/rosterLogStore.js.map +1 -1
- package/dist/keys/rosterStore.d.ts.map +1 -1
- package/dist/keys/rosterStore.js +2 -1
- package/dist/keys/rosterStore.js.map +1 -1
- package/dist/keys/spaceEpochs.d.ts +67 -34
- package/dist/keys/spaceEpochs.d.ts.map +1 -1
- package/dist/keys/spaceEpochs.js +80 -30
- package/dist/keys/spaceEpochs.js.map +1 -1
- package/dist/keys/userKeyCascade.d.ts +26 -1
- package/dist/keys/userKeyCascade.d.ts.map +1 -1
- package/dist/keys/userKeyCascade.js +29 -2
- package/dist/keys/userKeyCascade.js.map +1 -1
- package/dist/keys/userKeyRoster.d.ts +5 -0
- package/dist/keys/userKeyRoster.d.ts.map +1 -1
- package/dist/keys/userKeyRoster.js +5 -0
- package/dist/keys/userKeyRoster.js.map +1 -1
- package/dist/keys/userKeyRosterCascade.d.ts +54 -16
- package/dist/keys/userKeyRosterCascade.d.ts.map +1 -1
- package/dist/keys/userKeyRosterCascade.js +50 -22
- package/dist/keys/userKeyRosterCascade.js.map +1 -1
- package/dist/recovery/continuation.d.ts +5 -4
- package/dist/recovery/continuation.d.ts.map +1 -1
- package/dist/recovery/continuation.js +14 -13
- package/dist/recovery/continuation.js.map +1 -1
- package/dist/resourceLog/controller.d.ts +18 -6
- package/dist/resourceLog/controller.d.ts.map +1 -1
- package/dist/resourceLog/controller.js +5 -3
- package/dist/resourceLog/controller.js.map +1 -1
- package/dist/resourceLog/document.d.ts +10 -2
- package/dist/resourceLog/document.d.ts.map +1 -1
- package/dist/resourceLog/document.js +1 -2
- package/dist/resourceLog/document.js.map +1 -1
- package/dist/resourceLog/errors.d.ts +17 -43
- package/dist/resourceLog/errors.d.ts.map +1 -1
- package/dist/resourceLog/errors.js +17 -50
- package/dist/resourceLog/errors.js.map +1 -1
- package/dist/resourceLog/index.d.ts +4 -1
- package/dist/resourceLog/index.d.ts.map +1 -1
- package/dist/resourceLog/index.js +4 -1
- package/dist/resourceLog/index.js.map +1 -1
- package/dist/resourceLog/logClass.d.ts +69 -0
- package/dist/resourceLog/logClass.d.ts.map +1 -0
- package/dist/resourceLog/logClass.js +43 -0
- package/dist/resourceLog/logClass.js.map +1 -0
- package/dist/space/collections.d.ts +22 -2
- package/dist/space/collections.d.ts.map +1 -1
- package/dist/space/collections.js +18 -0
- package/dist/space/collections.js.map +1 -1
- package/dist/space/index.d.ts +8 -5
- package/dist/space/index.d.ts.map +1 -1
- package/dist/space/index.js +8 -5
- package/dist/space/index.js.map +1 -1
- package/dist/space/provisioning.d.ts +16 -6
- package/dist/space/provisioning.d.ts.map +1 -1
- package/dist/space/provisioning.js +11 -7
- package/dist/space/provisioning.js.map +1 -1
- package/dist/space/wasLink.d.ts +13 -2
- package/dist/space/wasLink.d.ts.map +1 -1
- package/dist/space/wasLink.js +28 -2
- package/dist/space/wasLink.js.map +1 -1
- package/dist/sync/engine.d.ts +4 -2
- package/dist/sync/engine.d.ts.map +1 -1
- package/dist/sync/engine.js.map +1 -1
- package/dist/sync/index.d.ts +9 -6
- package/dist/sync/index.d.ts.map +1 -1
- package/dist/sync/index.js +8 -5
- package/dist/sync/index.js.map +1 -1
- package/dist/sync/push.d.ts +0 -29
- package/dist/sync/push.d.ts.map +1 -1
- package/dist/sync/push.js +30 -28
- package/dist/sync/push.js.map +1 -1
- package/dist/sync/types.d.ts +39 -21
- package/dist/sync/types.d.ts.map +1 -1
- package/dist/sync/types.js +13 -7
- package/dist/sync/types.js.map +1 -1
- package/dist/unlock/index.d.ts +1 -1
- package/dist/unlock/index.d.ts.map +1 -1
- package/dist/unlock/index.js.map +1 -1
- package/dist/unlock/retire.d.ts +8 -1
- package/dist/unlock/retire.d.ts.map +1 -1
- package/dist/unlock/retire.js +8 -1
- package/dist/unlock/retire.js.map +1 -1
- package/dist/unlock/standingWebvh.d.ts +81 -19
- package/dist/unlock/standingWebvh.d.ts.map +1 -1
- package/dist/unlock/standingWebvh.js +170 -30
- package/dist/unlock/standingWebvh.js.map +1 -1
- package/dist/webvh/did.d.ts +2 -4
- package/dist/webvh/did.d.ts.map +1 -1
- package/dist/webvh/did.js +2 -4
- package/dist/webvh/did.js.map +1 -1
- package/dist/webvh/didWebvh.d.ts +3 -2
- package/dist/webvh/didWebvh.d.ts.map +1 -1
- package/dist/webvh/didWebvh.js +2 -1
- package/dist/webvh/didWebvh.js.map +1 -1
- package/dist/webvh/revokeClient.d.ts +13 -7
- package/dist/webvh/revokeClient.d.ts.map +1 -1
- package/dist/webvh/revokeClient.js +14 -7
- package/dist/webvh/revokeClient.js.map +1 -1
- package/package.json +4 -19
- package/dist/descriptors/acquire.d.ts +0 -122
- package/dist/descriptors/acquire.d.ts.map +0 -1
- package/dist/descriptors/acquire.js +0 -100
- package/dist/descriptors/acquire.js.map +0 -1
- package/dist/descriptors/cipher.d.ts +0 -71
- package/dist/descriptors/cipher.d.ts.map +0 -1
- package/dist/descriptors/cipher.js +0 -109
- package/dist/descriptors/cipher.js.map +0 -1
- package/dist/descriptors/errors.d.ts +0 -44
- package/dist/descriptors/errors.d.ts.map +0 -1
- package/dist/descriptors/errors.js +0 -46
- package/dist/descriptors/errors.js.map +0 -1
- package/dist/descriptors/refresh.d.ts +0 -62
- package/dist/descriptors/refresh.d.ts.map +0 -1
- package/dist/descriptors/refresh.js +0 -69
- package/dist/descriptors/refresh.js.map +0 -1
- package/dist/request/appKey.d.ts +0 -295
- package/dist/request/appKey.d.ts.map +0 -1
- package/dist/request/appKey.js +0 -516
- package/dist/request/appKey.js.map +0 -1
- package/dist/request/capabilityRequest.d.ts +0 -41
- package/dist/request/capabilityRequest.d.ts.map +0 -1
- package/dist/request/capabilityRequest.js +0 -46
- package/dist/request/capabilityRequest.js.map +0 -1
- package/dist/request/classify.d.ts +0 -226
- package/dist/request/classify.d.ts.map +0 -1
- package/dist/request/classify.js +0 -416
- package/dist/request/classify.js.map +0 -1
- package/dist/request/composeVp.d.ts +0 -52
- package/dist/request/composeVp.d.ts.map +0 -1
- package/dist/request/composeVp.js +0 -176
- package/dist/request/composeVp.js.map +0 -1
- package/dist/request/ephemeralExchange.d.ts +0 -100
- package/dist/request/ephemeralExchange.d.ts.map +0 -1
- package/dist/request/ephemeralExchange.js +0 -230
- package/dist/request/ephemeralExchange.js.map +0 -1
- package/dist/request/exchangeClient.d.ts +0 -142
- package/dist/request/exchangeClient.d.ts.map +0 -1
- package/dist/request/exchangeClient.js +0 -241
- package/dist/request/exchangeClient.js.map +0 -1
- package/dist/request/index.d.ts +0 -59
- package/dist/request/index.d.ts.map +0 -1
- package/dist/request/index.js +0 -59
- package/dist/request/index.js.map +0 -1
- package/dist/request/interactionRequest.d.ts +0 -23
- package/dist/request/interactionRequest.d.ts.map +0 -1
- package/dist/request/interactionRequest.js +0 -46
- package/dist/request/interactionRequest.js.map +0 -1
- package/dist/request/interactionUrl.d.ts +0 -42
- package/dist/request/interactionUrl.d.ts.map +0 -1
- package/dist/request/interactionUrl.js +0 -104
- package/dist/request/interactionUrl.js.map +0 -1
- package/dist/request/matching.d.ts +0 -95
- package/dist/request/matching.d.ts.map +0 -1
- package/dist/request/matching.js +0 -205
- package/dist/request/matching.js.map +0 -1
- package/dist/request/onboarding.d.ts +0 -94
- package/dist/request/onboarding.d.ts.map +0 -1
- package/dist/request/onboarding.js +0 -167
- package/dist/request/onboarding.js.map +0 -1
- package/dist/request/parse.d.ts +0 -63
- package/dist/request/parse.d.ts.map +0 -1
- package/dist/request/parse.js +0 -153
- package/dist/request/parse.js.map +0 -1
- package/dist/request/presentationSuite.d.ts +0 -71
- package/dist/request/presentationSuite.d.ts.map +0 -1
- package/dist/request/presentationSuite.js +0 -143
- package/dist/request/presentationSuite.js.map +0 -1
- package/dist/request/processRequest.d.ts +0 -45
- package/dist/request/processRequest.d.ts.map +0 -1
- package/dist/request/processRequest.js +0 -147
- package/dist/request/processRequest.js.map +0 -1
- package/dist/request/queryPredicates.d.ts +0 -98
- package/dist/request/queryPredicates.d.ts.map +0 -1
- package/dist/request/queryPredicates.js +0 -107
- package/dist/request/queryPredicates.js.map +0 -1
- package/dist/request/types.d.ts +0 -257
- package/dist/request/types.d.ts.map +0 -1
- package/dist/request/types.js +0 -2
- package/dist/request/types.js.map +0 -1
- package/dist/request/walletInput.d.ts +0 -93
- package/dist/request/walletInput.d.ts.map +0 -1
- package/dist/request/walletInput.js +0 -179
- package/dist/request/walletInput.js.map +0 -1
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import type { IDocumentLoader } from '@interop/data-integrity-core';
|
|
2
|
-
import type { IVerifiablePresentation, IVerifiableCredential, IZcap, PresentationSigner } from './types.js';
|
|
3
|
-
/**
|
|
4
|
-
* Shared JSON-LD document loader for presentation and credential signing: the
|
|
5
|
-
* standard security contexts plus the hosted App Connect context, resolved
|
|
6
|
-
* from the bundled `byoe-context` document so neither signing nor verification
|
|
7
|
-
* fetches it. Exported so single-VC issuance paths reuse the same context
|
|
8
|
-
* resolution the VP compose path uses.
|
|
9
|
-
*/
|
|
10
|
-
export declare const documentLoader: IDocumentLoader;
|
|
11
|
-
/**
|
|
12
|
-
* Creates a Verifiable Presentation for the requester.
|
|
13
|
-
*
|
|
14
|
-
* @param options {object}
|
|
15
|
-
* @param [options.presentationSigner] {PresentationSigner} - The authentication
|
|
16
|
-
* signer and the holder DID to name on a signed VP. Required when
|
|
17
|
-
* `didAuthRequested` is true; an unsigned (or zcap-only) VP needs none.
|
|
18
|
-
* @param [options.selectedVcs] {IVerifiableCredential[]} - VCs the user chose to
|
|
19
|
-
* share (empty for a DID-Auth-only or zcap-only response).
|
|
20
|
-
* @param [options.challenge] {string} - Required when DID Auth is requested.
|
|
21
|
-
* @param [options.domain] {string} - Signed into the proof when present;
|
|
22
|
-
* optional per the VPR spec.
|
|
23
|
-
* @param options.didAuthRequested {boolean} - Whether to sign the VP.
|
|
24
|
-
* @param [options.cryptosuite] {string} - Negotiated cryptosuite; falls back to
|
|
25
|
-
* the wallet default (Ed25519Signature2020) when absent.
|
|
26
|
-
* @param [options.zcaps] {IZcap[]} - Delegated capabilities to embed as the
|
|
27
|
-
* VP's `zcap` array (before signing, so a DIDAuth proof covers them).
|
|
28
|
-
* @param [options.appConnect] {{ firstRun: boolean }} - App Connect response
|
|
29
|
-
* marker to embed (before signing, like the grants).
|
|
30
|
-
* @param [options.documentLoader] {IDocumentLoader} - JSON-LD loader; defaults
|
|
31
|
-
* to the shared security loader.
|
|
32
|
-
* @returns {Promise<IVerifiablePresentation>}
|
|
33
|
-
*/
|
|
34
|
-
export declare function composeVp({ presentationSigner, selectedVcs, challenge, domain, didAuthRequested, cryptosuite, zcaps, appConnect, documentLoader: loader }: {
|
|
35
|
-
presentationSigner?: PresentationSigner;
|
|
36
|
-
selectedVcs?: IVerifiableCredential[];
|
|
37
|
-
challenge?: string;
|
|
38
|
-
domain?: string;
|
|
39
|
-
didAuthRequested: boolean;
|
|
40
|
-
cryptosuite?: string;
|
|
41
|
-
zcaps?: IZcap[];
|
|
42
|
-
appConnect?: {
|
|
43
|
-
firstRun: boolean;
|
|
44
|
-
};
|
|
45
|
-
documentLoader?: IDocumentLoader;
|
|
46
|
-
}): Promise<IVerifiablePresentation>;
|
|
47
|
-
/**
|
|
48
|
-
* @deprecated Use {@link composeVp}. Retained for Freewallet, which imports the
|
|
49
|
-
* `composeVP` spelling.
|
|
50
|
-
*/
|
|
51
|
-
export declare const composeVP: typeof composeVp;
|
|
52
|
-
//# sourceMappingURL=composeVp.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"composeVp.d.ts","sourceRoot":"","sources":["../../src/request/composeVp.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAA;AAGnE,OAAO,KAAK,EACV,uBAAuB,EACvB,qBAAqB,EACrB,KAAK,EACL,kBAAkB,EACnB,MAAM,YAAY,CAAA;AAEnB;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,EAAE,eAMzB,CAAA;AAsFJ;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAsB,SAAS,CAAC,EAC9B,kBAAkB,EAClB,WAAgB,EAChB,SAAS,EACT,MAAM,EACN,gBAAgB,EAChB,WAAW,EACX,KAAU,EACV,UAAU,EACV,cAAc,EAAE,MAAuB,EACxC,EAAE;IACD,kBAAkB,CAAC,EAAE,kBAAkB,CAAA;IACvC,WAAW,CAAC,EAAE,qBAAqB,EAAE,CAAA;IACrC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,gBAAgB,EAAE,OAAO,CAAA;IACzB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,KAAK,CAAC,EAAE,KAAK,EAAE,CAAA;IACf,UAAU,CAAC,EAAE;QAAE,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAA;IAClC,cAAc,CAAC,EAAE,eAAe,CAAA;CACjC,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAyDnC;AAED;;;GAGG;AACH,eAAO,MAAM,SAAS,kBAAY,CAAA"}
|
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
-
*/
|
|
4
|
-
/**
|
|
5
|
-
* Composes a Verifiable Presentation to send back to a requester. The VP is
|
|
6
|
-
* signed when DID Authentication was requested (proving control of the holder's
|
|
7
|
-
* DID over the request's `challenge`, and `domain` when the verifier sends
|
|
8
|
-
* one), and unsigned otherwise.
|
|
9
|
-
*
|
|
10
|
-
* Merged from DCW's `app/lib/composeVp.ts` and Freewallet's
|
|
11
|
-
* `src/lib/walletRequest/composeVP.ts`. The signer and holder DID are injected
|
|
12
|
-
* as a {@link PresentationSigner} -- each app resolves them from its own key
|
|
13
|
-
* material -- and the optional zcap / appConnect embedding (grants ride inside
|
|
14
|
-
* the VP, added before signing so a DIDAuth proof covers them) is carried over
|
|
15
|
-
* from Freewallet. The DIDAuth guard follows DCW: `challenge` is required,
|
|
16
|
-
* `domain` is optional (a wallet that needs the stricter "domain always
|
|
17
|
-
* present" invariant enforces it in its own wrapper before calling here).
|
|
18
|
-
*/
|
|
19
|
-
import * as vc from '@interop/vc';
|
|
20
|
-
import { securityLoader } from '@interop/security-document-loader';
|
|
21
|
-
import { contexts as byoeContexts, CONTEXT_URL_V1 } from 'byoe-context';
|
|
22
|
-
import { presentationSuiteFor } from './presentationSuite.js';
|
|
23
|
-
import { presentationVersionFor } from './classify.js';
|
|
24
|
-
/**
|
|
25
|
-
* Shared JSON-LD document loader for presentation and credential signing: the
|
|
26
|
-
* standard security contexts plus the hosted App Connect context, resolved
|
|
27
|
-
* from the bundled `byoe-context` document so neither signing nor verification
|
|
28
|
-
* fetches it. Exported so single-VC issuance paths reuse the same context
|
|
29
|
-
* resolution the VP compose path uses.
|
|
30
|
-
*/
|
|
31
|
-
export const documentLoader = (() => {
|
|
32
|
-
const loader = securityLoader({ fetchRemoteContexts: true });
|
|
33
|
-
for (const [url, context] of byoeContexts) {
|
|
34
|
-
loader.addStatic(url, context);
|
|
35
|
-
}
|
|
36
|
-
return loader.build();
|
|
37
|
-
})();
|
|
38
|
-
/**
|
|
39
|
-
* The hosted App Connect context URL appended to the VP `@context` when grants
|
|
40
|
-
* or the App Connect response marker are embedded. The context document
|
|
41
|
-
* defines the `zcap` (`@container: @set`) and `appConnect` (`@type: @json`)
|
|
42
|
-
* terms, which is what lets JSON-LD safe-mode canonicalization include (rather
|
|
43
|
-
* than reject) the members, so the authentication proof genuinely covers them.
|
|
44
|
-
*/
|
|
45
|
-
const APP_CONNECT_CONTEXT_URL = CONTEXT_URL_V1;
|
|
46
|
-
/**
|
|
47
|
-
* Reads a presentation's `@context` as a mutable array of entries.
|
|
48
|
-
*/
|
|
49
|
-
function contextEntries(presentation) {
|
|
50
|
-
const base = presentation['@context'];
|
|
51
|
-
return Array.isArray(base) ? [...base] : [base];
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* Writes a presentation's `@context` from an array of entries.
|
|
55
|
-
*/
|
|
56
|
-
function setContext(presentation, entries) {
|
|
57
|
-
;
|
|
58
|
-
presentation['@context'] = entries;
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* Appends the hosted App Connect context URL to the presentation's `@context`,
|
|
62
|
-
* once: a response carrying both grants and the marker still appends a single
|
|
63
|
-
* entry. Each embedded zcap additionally self-describes via its own
|
|
64
|
-
* `@context`; the profile context defines only the top-level members.
|
|
65
|
-
*/
|
|
66
|
-
function appendAppConnectContext(presentation) {
|
|
67
|
-
const entries = contextEntries(presentation);
|
|
68
|
-
if (entries.includes(APP_CONNECT_CONTEXT_URL)) {
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
setContext(presentation, [...entries, APP_CONNECT_CONTEXT_URL]);
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Embeds the delegated capabilities on the presentation and appends the App
|
|
75
|
-
* Connect context that defines the `zcap` term.
|
|
76
|
-
*/
|
|
77
|
-
function embedZcaps(presentation, zcaps) {
|
|
78
|
-
if (zcaps.length === 0) {
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
appendAppConnectContext(presentation);
|
|
82
|
-
presentation.zcap = zcaps;
|
|
83
|
-
}
|
|
84
|
-
/**
|
|
85
|
-
* Embeds the App Connect response marker (the wallet-provided `firstRun`
|
|
86
|
-
* signal) on the presentation and appends the App Connect context that defines
|
|
87
|
-
* the `appConnect` term (a JSON literal, so its `firstRun` boolean
|
|
88
|
-
* canonicalizes as one opaque value; embedding happens before signing, so the
|
|
89
|
-
* DIDAuth proof covers the marker the same way it covers the grants).
|
|
90
|
-
*/
|
|
91
|
-
function embedAppConnect(presentation, appConnect) {
|
|
92
|
-
if (!appConnect) {
|
|
93
|
-
return;
|
|
94
|
-
}
|
|
95
|
-
appendAppConnectContext(presentation);
|
|
96
|
-
presentation.appConnect = appConnect;
|
|
97
|
-
}
|
|
98
|
-
/**
|
|
99
|
-
* Creates a Verifiable Presentation for the requester.
|
|
100
|
-
*
|
|
101
|
-
* @param options {object}
|
|
102
|
-
* @param [options.presentationSigner] {PresentationSigner} - The authentication
|
|
103
|
-
* signer and the holder DID to name on a signed VP. Required when
|
|
104
|
-
* `didAuthRequested` is true; an unsigned (or zcap-only) VP needs none.
|
|
105
|
-
* @param [options.selectedVcs] {IVerifiableCredential[]} - VCs the user chose to
|
|
106
|
-
* share (empty for a DID-Auth-only or zcap-only response).
|
|
107
|
-
* @param [options.challenge] {string} - Required when DID Auth is requested.
|
|
108
|
-
* @param [options.domain] {string} - Signed into the proof when present;
|
|
109
|
-
* optional per the VPR spec.
|
|
110
|
-
* @param options.didAuthRequested {boolean} - Whether to sign the VP.
|
|
111
|
-
* @param [options.cryptosuite] {string} - Negotiated cryptosuite; falls back to
|
|
112
|
-
* the wallet default (Ed25519Signature2020) when absent.
|
|
113
|
-
* @param [options.zcaps] {IZcap[]} - Delegated capabilities to embed as the
|
|
114
|
-
* VP's `zcap` array (before signing, so a DIDAuth proof covers them).
|
|
115
|
-
* @param [options.appConnect] {{ firstRun: boolean }} - App Connect response
|
|
116
|
-
* marker to embed (before signing, like the grants).
|
|
117
|
-
* @param [options.documentLoader] {IDocumentLoader} - JSON-LD loader; defaults
|
|
118
|
-
* to the shared security loader.
|
|
119
|
-
* @returns {Promise<IVerifiablePresentation>}
|
|
120
|
-
*/
|
|
121
|
-
export async function composeVp({ presentationSigner, selectedVcs = [], challenge, domain, didAuthRequested, cryptosuite, zcaps = [], appConnect, documentLoader: loader = documentLoader }) {
|
|
122
|
-
if (!didAuthRequested && selectedVcs.length === 0 && zcaps.length === 0) {
|
|
123
|
-
throw new Error('A VP requires credentials, capabilities, or a DID Auth request.');
|
|
124
|
-
}
|
|
125
|
-
if (didAuthRequested && !challenge) {
|
|
126
|
-
throw new Error('A "challenge" is required for DID Auth.');
|
|
127
|
-
}
|
|
128
|
-
if (!didAuthRequested) {
|
|
129
|
-
// Return an unsigned VP. verify: false skips per-VC validation (including
|
|
130
|
-
// expiration checks). A zcap-only response rides here: the grants are
|
|
131
|
-
// individually signed and controller-bound, so they need no VP proof.
|
|
132
|
-
// With no cryptosuite to dictate it, the data model version follows the
|
|
133
|
-
// credentials being shared (a zcap-only response lands on 1.0).
|
|
134
|
-
const presentation = vc.createPresentation({
|
|
135
|
-
verifiableCredential: selectedVcs.length > 0 ? selectedVcs : undefined,
|
|
136
|
-
verify: false,
|
|
137
|
-
version: presentationVersionFor(selectedVcs)
|
|
138
|
-
});
|
|
139
|
-
embedZcaps(presentation, zcaps);
|
|
140
|
-
embedAppConnect(presentation, appConnect);
|
|
141
|
-
return presentation;
|
|
142
|
-
}
|
|
143
|
-
if (!presentationSigner) {
|
|
144
|
-
throw new Error('A "presentationSigner" is required for DID Auth.');
|
|
145
|
-
}
|
|
146
|
-
const { signer, holder } = presentationSigner;
|
|
147
|
-
// Sign with the cryptosuite the verifier requested (via VCALM
|
|
148
|
-
// `acceptedCryptosuites`), falling back to the wallet default. The suite
|
|
149
|
-
// dictates the VC data model version: eddsa-rdfc-2022 proofs require VC 2.0,
|
|
150
|
-
// the default Ed25519Signature2020 proof uses VC 1.0.
|
|
151
|
-
const { suite, version } = presentationSuiteFor({ signer, cryptosuite });
|
|
152
|
-
const presentation = vc.createPresentation({
|
|
153
|
-
holder,
|
|
154
|
-
verifiableCredential: selectedVcs.length > 0 ? selectedVcs : undefined,
|
|
155
|
-
verify: false,
|
|
156
|
-
version
|
|
157
|
-
});
|
|
158
|
-
// Embed the grants (and any App Connect marker) before signing so the
|
|
159
|
-
// authentication proof covers them; the grants additionally self-authenticate
|
|
160
|
-
// via their own delegation proofs and carry their own `@context`.
|
|
161
|
-
embedZcaps(presentation, zcaps);
|
|
162
|
-
embedAppConnect(presentation, appConnect);
|
|
163
|
-
return (await vc.signPresentation({
|
|
164
|
-
presentation,
|
|
165
|
-
challenge,
|
|
166
|
-
...(domain !== undefined && { domain }),
|
|
167
|
-
documentLoader: loader,
|
|
168
|
-
suite
|
|
169
|
-
}));
|
|
170
|
-
}
|
|
171
|
-
/**
|
|
172
|
-
* @deprecated Use {@link composeVp}. Retained for Freewallet, which imports the
|
|
173
|
-
* `composeVP` spelling.
|
|
174
|
-
*/
|
|
175
|
-
export const composeVP = composeVp;
|
|
176
|
-
//# sourceMappingURL=composeVp.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"composeVp.js","sourceRoot":"","sources":["../../src/request/composeVp.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
import type { FetchLike } from './types.js';
|
|
2
|
-
/**
|
|
3
|
-
* How often the requester polls the exchange for the wallet's response.
|
|
4
|
-
*/
|
|
5
|
-
export declare const EPHEMERAL_EXCHANGE_POLL_INTERVAL_MS = 3000;
|
|
6
|
-
/**
|
|
7
|
-
* How long the server keeps an ephemeral exchange. A poll past it can only
|
|
8
|
-
* ever find the exchange gone, so a caller with no other bound (a CLI) passes
|
|
9
|
-
* this as its `timeoutMs`; a UI offering the exchange for a shorter window
|
|
10
|
-
* (an invite countdown) picks its own.
|
|
11
|
-
*/
|
|
12
|
-
export declare const EPHEMERAL_EXCHANGE_TTL_MS: number;
|
|
13
|
-
/**
|
|
14
|
-
* The exchange path the interaction URL adds, with the interaction-URL
|
|
15
|
-
* version query the answering wallet's scanner expects.
|
|
16
|
-
*/
|
|
17
|
-
export declare const EPHEMERAL_EXCHANGE_INTERACTION_PATH = "/protocols?iuv=1";
|
|
18
|
-
/**
|
|
19
|
-
* Raised when the exchange is no longer on the server (a `404`): it either
|
|
20
|
-
* expired or was never created. The remedy is a fresh exchange, so a caller
|
|
21
|
-
* renders its "expired" state. Dispatch on `err.name` rather than
|
|
22
|
-
* `instanceof`: the transport is injected and may resolve to a different copy
|
|
23
|
-
* of this package, which makes the name the stable contract.
|
|
24
|
-
*
|
|
25
|
-
* Also what the answering side raises on a 404: `fetchInteractionProtocols`
|
|
26
|
-
* (`interactionUrl.ts`), the exchange client's `postToExchange`-based helpers
|
|
27
|
-
* (`exchangeClient.ts`), and `openInteractionRequest`
|
|
28
|
-
* (`interactionRequest.ts`), which composes both.
|
|
29
|
-
*/
|
|
30
|
-
export declare class EphemeralExchangeGoneError extends Error {
|
|
31
|
-
constructor(message?: string);
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* Raised when the poll's own `timeoutMs` elapses before the exchange
|
|
35
|
-
* completes. Distinct from {@link EphemeralExchangeGoneError}: the exchange
|
|
36
|
-
* may still be on the server and approvable, the requester just stopped
|
|
37
|
-
* waiting. Dispatch on `err.name`, for the same reason as the gone error.
|
|
38
|
-
*/
|
|
39
|
-
export declare class EphemeralExchangeTimeoutError extends Error {
|
|
40
|
-
constructor(message?: string);
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* REQUESTER: creates an ephemeral exchange holding the request as its stored
|
|
44
|
-
* request, and returns both the exchange URL (the requester polls it) and the
|
|
45
|
-
* interaction URL (what the QR code or printed link carries).
|
|
46
|
-
*
|
|
47
|
-
* The server relays the stored request verbatim as its reply to the begin
|
|
48
|
-
* POST, so the VPR details are stored wrapped as a VC-API exchange response
|
|
49
|
-
* (`{ verifiablePresentationRequest: request }`) -- the shape the answering
|
|
50
|
-
* wallet's classifier reads.
|
|
51
|
-
*
|
|
52
|
-
* The exchange URL is read from the `Location` response header, falling back
|
|
53
|
-
* to the body's `location` member -- deployments differ on which they set,
|
|
54
|
-
* and either alone is enough.
|
|
55
|
-
*
|
|
56
|
-
* @param options {object}
|
|
57
|
-
* @param options.serverUrl {string} the WAS server base URL
|
|
58
|
-
* @param options.request {unknown} the VPR details to store
|
|
59
|
-
* @param [options.fetch] {FetchLike}
|
|
60
|
-
* @returns {Promise<{ exchangeUrl: string, interactionUrl: string }>}
|
|
61
|
-
*/
|
|
62
|
-
export declare function createEphemeralExchange({ serverUrl, request, fetch: fetchImpl }: {
|
|
63
|
-
serverUrl: string;
|
|
64
|
-
request: unknown;
|
|
65
|
-
fetch?: FetchLike;
|
|
66
|
-
}): Promise<{
|
|
67
|
-
exchangeUrl: string;
|
|
68
|
-
interactionUrl: string;
|
|
69
|
-
}>;
|
|
70
|
-
/**
|
|
71
|
-
* REQUESTER: polls the exchange until the wallet posts its response, and
|
|
72
|
-
* resolves with that response body verbatim (the caller interprets it: an
|
|
73
|
-
* onboarding invite through `parseOnboardingResponse`, a capability request
|
|
74
|
-
* by reading the presentation's `zcap` member).
|
|
75
|
-
*
|
|
76
|
-
* A `404` means the exchange expired or was never there, and rejects with
|
|
77
|
-
* {@link EphemeralExchangeGoneError}. Every other failure -- a network error,
|
|
78
|
-
* another non-ok status, an unparseable body -- is transient and simply
|
|
79
|
-
* retried on the next tick. Two bounds end the wait early: the caller's
|
|
80
|
-
* `signal` rejects promptly with its own reason, and `timeoutMs` (measured
|
|
81
|
-
* from the call) rejects with {@link EphemeralExchangeTimeoutError}; either
|
|
82
|
-
* cancels an in-flight request. Without both, the poll runs until the
|
|
83
|
-
* exchange completes or disappears.
|
|
84
|
-
*
|
|
85
|
-
* @param options {object}
|
|
86
|
-
* @param options.exchangeUrl {string}
|
|
87
|
-
* @param [options.signal] {AbortSignal}
|
|
88
|
-
* @param [options.timeoutMs] {number} the poll's own deadline
|
|
89
|
-
* @param [options.intervalMs] {number}
|
|
90
|
-
* @param [options.fetch] {FetchLike}
|
|
91
|
-
* @returns {Promise<unknown>} the completed exchange's `response` member
|
|
92
|
-
*/
|
|
93
|
-
export declare function pollEphemeralExchange({ exchangeUrl, signal, timeoutMs, intervalMs, fetch: fetchImpl }: {
|
|
94
|
-
exchangeUrl: string;
|
|
95
|
-
signal?: AbortSignal;
|
|
96
|
-
timeoutMs?: number;
|
|
97
|
-
intervalMs?: number;
|
|
98
|
-
fetch?: FetchLike;
|
|
99
|
-
}): Promise<unknown>;
|
|
100
|
-
//# sourceMappingURL=ephemeralExchange.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ephemeralExchange.d.ts","sourceRoot":"","sources":["../../src/request/ephemeralExchange.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAE3C;;GAEG;AACH,eAAO,MAAM,mCAAmC,OAAO,CAAA;AAEvD;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,QAAiB,CAAA;AAEvD;;;GAGG;AACH,eAAO,MAAM,mCAAmC,qBAAqB,CAAA;AAErE;;;;;;;;;;;GAWG;AACH,qBAAa,0BAA2B,SAAQ,KAAK;gBACvC,OAAO,SAAmD;CAIvE;AAED;;;;;GAKG;AACH,qBAAa,6BAA8B,SAAQ,KAAK;gBAEpD,OAAO,SAA8D;CAKxE;AAcD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,uBAAuB,CAAC,EAC5C,SAAS,EACT,OAAO,EACP,KAAK,EAAE,SAA4B,EACpC,EAAE;IACD,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,OAAO,CAAA;IAChB,KAAK,CAAC,EAAE,SAAS,CAAA;CAClB,GAAG,OAAO,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,CAAC,CA8B3D;AAmCD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAsB,qBAAqB,CAAC,EAC1C,WAAW,EACX,MAAM,EACN,SAAS,EACT,UAAgD,EAChD,KAAK,EAAE,SAA4B,EACpC,EAAE;IACD,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,KAAK,CAAC,EAAE,SAAS,CAAA;CAClB,GAAG,OAAO,CAAC,OAAO,CAAC,CAyDnB"}
|
|
@@ -1,230 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
-
*/
|
|
4
|
-
/**
|
|
5
|
-
* The requester's half of an ephemeral exchange on a WAS server: creating an
|
|
6
|
-
* exchange that carries a Verifiable Presentation Request as its stored
|
|
7
|
-
* request, and polling that exchange until the answering wallet posts its
|
|
8
|
-
* response. Generic over what the request asks for -- a wallet's onboarding
|
|
9
|
-
* invite stores a `WalletOnboardingQuery` (`onboarding.ts`), a CLI asking for
|
|
10
|
-
* capabilities stores a zcap-only request (`capabilityRequest.ts`). Pure
|
|
11
|
-
* logic: no UI framework, no DOM, and no module-level mutable state; every
|
|
12
|
-
* run is per-instance, cancelled through the caller's `AbortSignal` or the
|
|
13
|
-
* poll's own deadline, with the network transport injected.
|
|
14
|
-
*
|
|
15
|
-
* These routes are deliberately unauthenticated (a capability-URL access model:
|
|
16
|
-
* the exchange URL is the secret, and it travels point-to-point, as a QR code
|
|
17
|
-
* or a printed link), so nothing here signs a request.
|
|
18
|
-
*/
|
|
19
|
-
import { log } from '../log.js';
|
|
20
|
-
/**
|
|
21
|
-
* How often the requester polls the exchange for the wallet's response.
|
|
22
|
-
*/
|
|
23
|
-
export const EPHEMERAL_EXCHANGE_POLL_INTERVAL_MS = 3000;
|
|
24
|
-
/**
|
|
25
|
-
* How long the server keeps an ephemeral exchange. A poll past it can only
|
|
26
|
-
* ever find the exchange gone, so a caller with no other bound (a CLI) passes
|
|
27
|
-
* this as its `timeoutMs`; a UI offering the exchange for a shorter window
|
|
28
|
-
* (an invite countdown) picks its own.
|
|
29
|
-
*/
|
|
30
|
-
export const EPHEMERAL_EXCHANGE_TTL_MS = 10 * 60 * 1000;
|
|
31
|
-
/**
|
|
32
|
-
* The exchange path the interaction URL adds, with the interaction-URL
|
|
33
|
-
* version query the answering wallet's scanner expects.
|
|
34
|
-
*/
|
|
35
|
-
export const EPHEMERAL_EXCHANGE_INTERACTION_PATH = '/protocols?iuv=1';
|
|
36
|
-
/**
|
|
37
|
-
* Raised when the exchange is no longer on the server (a `404`): it either
|
|
38
|
-
* expired or was never created. The remedy is a fresh exchange, so a caller
|
|
39
|
-
* renders its "expired" state. Dispatch on `err.name` rather than
|
|
40
|
-
* `instanceof`: the transport is injected and may resolve to a different copy
|
|
41
|
-
* of this package, which makes the name the stable contract.
|
|
42
|
-
*
|
|
43
|
-
* Also what the answering side raises on a 404: `fetchInteractionProtocols`
|
|
44
|
-
* (`interactionUrl.ts`), the exchange client's `postToExchange`-based helpers
|
|
45
|
-
* (`exchangeClient.ts`), and `openInteractionRequest`
|
|
46
|
-
* (`interactionRequest.ts`), which composes both.
|
|
47
|
-
*/
|
|
48
|
-
export class EphemeralExchangeGoneError extends Error {
|
|
49
|
-
constructor(message = 'The ephemeral exchange is no longer available.') {
|
|
50
|
-
super(message);
|
|
51
|
-
this.name = 'EphemeralExchangeGoneError';
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Raised when the poll's own `timeoutMs` elapses before the exchange
|
|
56
|
-
* completes. Distinct from {@link EphemeralExchangeGoneError}: the exchange
|
|
57
|
-
* may still be on the server and approvable, the requester just stopped
|
|
58
|
-
* waiting. Dispatch on `err.name`, for the same reason as the gone error.
|
|
59
|
-
*/
|
|
60
|
-
export class EphemeralExchangeTimeoutError extends Error {
|
|
61
|
-
constructor(message = 'Timed out waiting for the ephemeral exchange to complete.') {
|
|
62
|
-
super(message);
|
|
63
|
-
this.name = 'EphemeralExchangeTimeoutError';
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* Strips a trailing slash from a configured base URL, so joining a path onto
|
|
68
|
-
* it cannot produce a doubled separator.
|
|
69
|
-
*
|
|
70
|
-
* @param options {object}
|
|
71
|
-
* @param options.serverUrl {string}
|
|
72
|
-
* @returns {string}
|
|
73
|
-
*/
|
|
74
|
-
function normalizedServerUrl({ serverUrl }) {
|
|
75
|
-
return serverUrl.replace(/\/+$/, '');
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* REQUESTER: creates an ephemeral exchange holding the request as its stored
|
|
79
|
-
* request, and returns both the exchange URL (the requester polls it) and the
|
|
80
|
-
* interaction URL (what the QR code or printed link carries).
|
|
81
|
-
*
|
|
82
|
-
* The server relays the stored request verbatim as its reply to the begin
|
|
83
|
-
* POST, so the VPR details are stored wrapped as a VC-API exchange response
|
|
84
|
-
* (`{ verifiablePresentationRequest: request }`) -- the shape the answering
|
|
85
|
-
* wallet's classifier reads.
|
|
86
|
-
*
|
|
87
|
-
* The exchange URL is read from the `Location` response header, falling back
|
|
88
|
-
* to the body's `location` member -- deployments differ on which they set,
|
|
89
|
-
* and either alone is enough.
|
|
90
|
-
*
|
|
91
|
-
* @param options {object}
|
|
92
|
-
* @param options.serverUrl {string} the WAS server base URL
|
|
93
|
-
* @param options.request {unknown} the VPR details to store
|
|
94
|
-
* @param [options.fetch] {FetchLike}
|
|
95
|
-
* @returns {Promise<{ exchangeUrl: string, interactionUrl: string }>}
|
|
96
|
-
*/
|
|
97
|
-
export async function createEphemeralExchange({ serverUrl, request, fetch: fetchImpl = globalThis.fetch }) {
|
|
98
|
-
const url = `${normalizedServerUrl({ serverUrl })}/workflows/ephemeral/exchanges`;
|
|
99
|
-
const response = await fetchImpl(url, {
|
|
100
|
-
method: 'POST',
|
|
101
|
-
headers: { 'content-type': 'application/json' },
|
|
102
|
-
body: JSON.stringify({
|
|
103
|
-
request: { verifiablePresentationRequest: request }
|
|
104
|
-
})
|
|
105
|
-
});
|
|
106
|
-
if (!response.ok) {
|
|
107
|
-
throw new Error(`Could not create the ephemeral exchange (HTTP ${response.status}).`);
|
|
108
|
-
}
|
|
109
|
-
let exchangeUrl = response.headers?.get('location') ?? '';
|
|
110
|
-
if (!exchangeUrl) {
|
|
111
|
-
try {
|
|
112
|
-
const body = (await response.json());
|
|
113
|
-
exchangeUrl = body?.location ?? '';
|
|
114
|
-
}
|
|
115
|
-
catch (err) {
|
|
116
|
-
log.warn('Could not parse the created exchange body', { err });
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
if (!exchangeUrl) {
|
|
120
|
-
throw new Error('The created ephemeral exchange has no location.');
|
|
121
|
-
}
|
|
122
|
-
return {
|
|
123
|
-
exchangeUrl,
|
|
124
|
-
interactionUrl: `${exchangeUrl}${EPHEMERAL_EXCHANGE_INTERACTION_PATH}`
|
|
125
|
-
};
|
|
126
|
-
}
|
|
127
|
-
/**
|
|
128
|
-
* Sleeps for `delayMs`, rejecting promptly with the signal's reason if the
|
|
129
|
-
* signal aborts first. The timer is always cleared.
|
|
130
|
-
*
|
|
131
|
-
* @param options {object}
|
|
132
|
-
* @param options.delayMs {number}
|
|
133
|
-
* @param options.signal {AbortSignal}
|
|
134
|
-
* @returns {Promise<void>}
|
|
135
|
-
*/
|
|
136
|
-
function abortableDelay({ delayMs, signal }) {
|
|
137
|
-
return new Promise((resolve, reject) => {
|
|
138
|
-
if (signal.aborted) {
|
|
139
|
-
reject(signal.reason);
|
|
140
|
-
return;
|
|
141
|
-
}
|
|
142
|
-
const timer = setTimeout(() => {
|
|
143
|
-
signal.removeEventListener('abort', onAbort);
|
|
144
|
-
resolve();
|
|
145
|
-
}, delayMs);
|
|
146
|
-
function onAbort() {
|
|
147
|
-
clearTimeout(timer);
|
|
148
|
-
reject(signal.reason);
|
|
149
|
-
}
|
|
150
|
-
signal.addEventListener('abort', onAbort, { once: true });
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
/**
|
|
154
|
-
* REQUESTER: polls the exchange until the wallet posts its response, and
|
|
155
|
-
* resolves with that response body verbatim (the caller interprets it: an
|
|
156
|
-
* onboarding invite through `parseOnboardingResponse`, a capability request
|
|
157
|
-
* by reading the presentation's `zcap` member).
|
|
158
|
-
*
|
|
159
|
-
* A `404` means the exchange expired or was never there, and rejects with
|
|
160
|
-
* {@link EphemeralExchangeGoneError}. Every other failure -- a network error,
|
|
161
|
-
* another non-ok status, an unparseable body -- is transient and simply
|
|
162
|
-
* retried on the next tick. Two bounds end the wait early: the caller's
|
|
163
|
-
* `signal` rejects promptly with its own reason, and `timeoutMs` (measured
|
|
164
|
-
* from the call) rejects with {@link EphemeralExchangeTimeoutError}; either
|
|
165
|
-
* cancels an in-flight request. Without both, the poll runs until the
|
|
166
|
-
* exchange completes or disappears.
|
|
167
|
-
*
|
|
168
|
-
* @param options {object}
|
|
169
|
-
* @param options.exchangeUrl {string}
|
|
170
|
-
* @param [options.signal] {AbortSignal}
|
|
171
|
-
* @param [options.timeoutMs] {number} the poll's own deadline
|
|
172
|
-
* @param [options.intervalMs] {number}
|
|
173
|
-
* @param [options.fetch] {FetchLike}
|
|
174
|
-
* @returns {Promise<unknown>} the completed exchange's `response` member
|
|
175
|
-
*/
|
|
176
|
-
export async function pollEphemeralExchange({ exchangeUrl, signal, timeoutMs, intervalMs = EPHEMERAL_EXCHANGE_POLL_INTERVAL_MS, fetch: fetchImpl = globalThis.fetch }) {
|
|
177
|
-
// One internal signal folds the caller's abort and the deadline together,
|
|
178
|
-
// so a single `signal` reaches fetch and the delay. The caller's reason is
|
|
179
|
-
// forwarded verbatim; the deadline aborts with the timeout error.
|
|
180
|
-
const controller = new AbortController();
|
|
181
|
-
const onCallerAbort = () => controller.abort(signal?.reason);
|
|
182
|
-
if (signal?.aborted) {
|
|
183
|
-
onCallerAbort();
|
|
184
|
-
}
|
|
185
|
-
else {
|
|
186
|
-
signal?.addEventListener('abort', onCallerAbort, { once: true });
|
|
187
|
-
}
|
|
188
|
-
const deadline = timeoutMs === undefined
|
|
189
|
-
? undefined
|
|
190
|
-
: setTimeout(() => controller.abort(new EphemeralExchangeTimeoutError()), timeoutMs);
|
|
191
|
-
try {
|
|
192
|
-
for (;;) {
|
|
193
|
-
if (controller.signal.aborted) {
|
|
194
|
-
throw controller.signal.reason;
|
|
195
|
-
}
|
|
196
|
-
try {
|
|
197
|
-
const response = await fetchImpl(exchangeUrl, {
|
|
198
|
-
signal: controller.signal
|
|
199
|
-
});
|
|
200
|
-
if (response.status === 404) {
|
|
201
|
-
throw new EphemeralExchangeGoneError();
|
|
202
|
-
}
|
|
203
|
-
if (response.ok) {
|
|
204
|
-
const body = (await response.json());
|
|
205
|
-
if (body?.state === 'complete') {
|
|
206
|
-
return body.response;
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
catch (err) {
|
|
211
|
-
if (controller.signal.aborted) {
|
|
212
|
-
throw controller.signal.reason;
|
|
213
|
-
}
|
|
214
|
-
if (err?.name === 'EphemeralExchangeGoneError') {
|
|
215
|
-
throw err;
|
|
216
|
-
}
|
|
217
|
-
// Anything else is transient -- keep polling.
|
|
218
|
-
log.warn('Polling the ephemeral exchange failed; retrying', { err });
|
|
219
|
-
}
|
|
220
|
-
await abortableDelay({ delayMs: intervalMs, signal: controller.signal });
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
finally {
|
|
224
|
-
signal?.removeEventListener('abort', onCallerAbort);
|
|
225
|
-
if (deadline !== undefined) {
|
|
226
|
-
clearTimeout(deadline);
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
//# sourceMappingURL=ephemeralExchange.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ephemeralExchange.js","sourceRoot":"","sources":["../../src/request/ephemeralExchange.ts"],"names":[],"mappings":"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"}
|