@did-btcr2/method 0.25.3 → 0.26.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/dist/.tsbuildinfo +1 -0
- package/dist/browser.js +125307 -122227
- package/dist/browser.mjs +125266 -122186
- package/dist/cjs/index.js +5043 -43
- package/dist/esm/core/beacon/aggregation/cohort/index.js.map +1 -1
- package/dist/esm/core/beacon/aggregation/cohort/messages/keygen/cohort-advert.js.map +1 -1
- package/dist/esm/core/beacon/aggregation/cohort/messages/keygen/cohort-ready.js.map +1 -1
- package/dist/esm/core/beacon/aggregation/cohort/messages/keygen/opt-in-accept.js.map +1 -1
- package/dist/esm/core/beacon/aggregation/cohort/messages/keygen/opt-in.js.map +1 -1
- package/dist/esm/core/beacon/aggregation/cohort/messages/keygen/subscribe.js.map +1 -1
- package/dist/esm/core/beacon/aggregation/cohort/messages/sign/aggregated-nonce.js.map +1 -1
- package/dist/esm/core/beacon/aggregation/cohort/messages/sign/authorization-request.js.map +1 -1
- package/dist/esm/core/beacon/aggregation/cohort/messages/sign/nonce-contribution.js.map +1 -1
- package/dist/esm/core/beacon/aggregation/cohort/messages/sign/request-signature.js.map +1 -1
- package/dist/esm/core/beacon/aggregation/cohort/messages/sign/signature-authorization.js.map +1 -1
- package/dist/esm/core/beacon/aggregation/communication/adapter/did-comm.js.map +1 -1
- package/dist/esm/core/beacon/aggregation/communication/adapter/nostr.js +1 -2
- package/dist/esm/core/beacon/aggregation/communication/adapter/nostr.js.map +1 -1
- package/dist/esm/core/beacon/aggregation/coordinator.js.map +1 -1
- package/dist/esm/core/beacon/aggregation/participant.js.map +1 -1
- package/dist/esm/core/beacon/aggregation/session/index.js.map +1 -1
- package/dist/esm/core/beacon/cas-beacon.js +6 -4
- package/dist/esm/core/beacon/cas-beacon.js.map +1 -1
- package/dist/esm/core/beacon/signal-discovery.js +1 -1
- package/dist/esm/core/beacon/signal-discovery.js.map +1 -1
- package/dist/esm/core/beacon/singleton-beacon.js +3 -3
- package/dist/esm/core/beacon/singleton-beacon.js.map +1 -1
- package/dist/esm/core/beacon/utils.js.map +1 -1
- package/dist/esm/core/identifier.js.map +1 -1
- package/dist/esm/core/resolver.js +41 -35
- package/dist/esm/core/resolver.js.map +1 -1
- package/dist/esm/core/update.js.map +1 -1
- package/dist/esm/did-btcr2.js +1 -1
- package/dist/esm/did-btcr2.js.map +1 -1
- package/dist/esm/utils/appendix.js +7 -6
- package/dist/esm/utils/appendix.js.map +1 -1
- package/dist/esm/utils/did-document-builder.js.map +1 -1
- package/dist/esm/utils/did-document.js +2 -2
- package/dist/esm/utils/did-document.js.map +1 -1
- package/dist/types/core/beacon/aggregation/cohort/index.d.ts +2 -2
- package/dist/types/core/beacon/aggregation/cohort/index.d.ts.map +1 -1
- package/dist/types/core/beacon/aggregation/cohort/messages/index.d.ts +10 -10
- package/dist/types/core/beacon/aggregation/cohort/messages/index.d.ts.map +1 -1
- package/dist/types/core/beacon/aggregation/cohort/messages/keygen/cohort-advert.d.ts +1 -1
- package/dist/types/core/beacon/aggregation/cohort/messages/keygen/cohort-advert.d.ts.map +1 -1
- package/dist/types/core/beacon/aggregation/cohort/messages/keygen/cohort-ready.d.ts +1 -1
- package/dist/types/core/beacon/aggregation/cohort/messages/keygen/cohort-ready.d.ts.map +1 -1
- package/dist/types/core/beacon/aggregation/cohort/messages/keygen/opt-in-accept.d.ts +1 -1
- package/dist/types/core/beacon/aggregation/cohort/messages/keygen/opt-in-accept.d.ts.map +1 -1
- package/dist/types/core/beacon/aggregation/cohort/messages/keygen/opt-in.d.ts +1 -1
- package/dist/types/core/beacon/aggregation/cohort/messages/keygen/opt-in.d.ts.map +1 -1
- package/dist/types/core/beacon/aggregation/cohort/messages/keygen/subscribe.d.ts +1 -1
- package/dist/types/core/beacon/aggregation/cohort/messages/keygen/subscribe.d.ts.map +1 -1
- package/dist/types/core/beacon/aggregation/cohort/messages/sign/aggregated-nonce.d.ts +1 -1
- package/dist/types/core/beacon/aggregation/cohort/messages/sign/aggregated-nonce.d.ts.map +1 -1
- package/dist/types/core/beacon/aggregation/cohort/messages/sign/authorization-request.d.ts +1 -1
- package/dist/types/core/beacon/aggregation/cohort/messages/sign/authorization-request.d.ts.map +1 -1
- package/dist/types/core/beacon/aggregation/cohort/messages/sign/nonce-contribution.d.ts +1 -1
- package/dist/types/core/beacon/aggregation/cohort/messages/sign/nonce-contribution.d.ts.map +1 -1
- package/dist/types/core/beacon/aggregation/cohort/messages/sign/request-signature.d.ts +1 -1
- package/dist/types/core/beacon/aggregation/cohort/messages/sign/request-signature.d.ts.map +1 -1
- package/dist/types/core/beacon/aggregation/cohort/messages/sign/signature-authorization.d.ts +1 -1
- package/dist/types/core/beacon/aggregation/cohort/messages/sign/signature-authorization.d.ts.map +1 -1
- package/dist/types/core/beacon/aggregation/communication/adapter/did-comm.d.ts +4 -4
- package/dist/types/core/beacon/aggregation/communication/adapter/did-comm.d.ts.map +1 -1
- package/dist/types/core/beacon/aggregation/communication/adapter/nostr.d.ts +6 -6
- package/dist/types/core/beacon/aggregation/communication/adapter/nostr.d.ts.map +1 -1
- package/dist/types/core/beacon/aggregation/communication/factory.d.ts +1 -1
- package/dist/types/core/beacon/aggregation/communication/factory.d.ts.map +1 -1
- package/dist/types/core/beacon/aggregation/communication/service.d.ts +3 -3
- package/dist/types/core/beacon/aggregation/communication/service.d.ts.map +1 -1
- package/dist/types/core/beacon/aggregation/coordinator.d.ts +3 -3
- package/dist/types/core/beacon/aggregation/coordinator.d.ts.map +1 -1
- package/dist/types/core/beacon/aggregation/participant.d.ts +6 -6
- package/dist/types/core/beacon/aggregation/participant.d.ts.map +1 -1
- package/dist/types/core/beacon/aggregation/session/index.d.ts +2 -2
- package/dist/types/core/beacon/aggregation/session/index.d.ts.map +1 -1
- package/dist/types/core/beacon/beacon.d.ts +5 -5
- package/dist/types/core/beacon/beacon.d.ts.map +1 -1
- package/dist/types/core/beacon/cas-beacon.d.ts +5 -5
- package/dist/types/core/beacon/cas-beacon.d.ts.map +1 -1
- package/dist/types/core/beacon/factory.d.ts +2 -2
- package/dist/types/core/beacon/factory.d.ts.map +1 -1
- package/dist/types/core/beacon/interfaces.d.ts +3 -3
- package/dist/types/core/beacon/interfaces.d.ts.map +1 -1
- package/dist/types/core/beacon/signal-discovery.d.ts +3 -3
- package/dist/types/core/beacon/signal-discovery.d.ts.map +1 -1
- package/dist/types/core/beacon/singleton-beacon.d.ts +5 -5
- package/dist/types/core/beacon/singleton-beacon.d.ts.map +1 -1
- package/dist/types/core/beacon/smt-beacon.d.ts +5 -5
- package/dist/types/core/beacon/smt-beacon.d.ts.map +1 -1
- package/dist/types/core/beacon/utils.d.ts +4 -4
- package/dist/types/core/beacon/utils.d.ts.map +1 -1
- package/dist/types/core/identifier.d.ts +2 -2
- package/dist/types/core/identifier.d.ts.map +1 -1
- package/dist/types/core/interfaces.d.ts +2 -2
- package/dist/types/core/interfaces.d.ts.map +1 -1
- package/dist/types/core/resolver.d.ts +8 -8
- package/dist/types/core/resolver.d.ts.map +1 -1
- package/dist/types/core/types.d.ts +6 -5
- package/dist/types/core/types.d.ts.map +1 -1
- package/dist/types/core/update.d.ts +5 -5
- package/dist/types/core/update.d.ts.map +1 -1
- package/dist/types/did-btcr2.d.ts +6 -6
- package/dist/types/did-btcr2.d.ts.map +1 -1
- package/dist/types/utils/appendix.d.ts +7 -7
- package/dist/types/utils/appendix.d.ts.map +1 -1
- package/dist/types/utils/did-document-builder.d.ts +3 -2
- package/dist/types/utils/did-document-builder.d.ts.map +1 -1
- package/dist/types/utils/did-document.d.ts +3 -3
- package/dist/types/utils/did-document.d.ts.map +1 -1
- package/package.json +7 -6
- package/src/core/beacon/aggregation/cohort/index.ts +3 -2
- package/src/core/beacon/aggregation/cohort/messages/index.ts +10 -10
- package/src/core/beacon/aggregation/cohort/messages/keygen/cohort-advert.ts +2 -1
- package/src/core/beacon/aggregation/cohort/messages/keygen/cohort-ready.ts +2 -1
- package/src/core/beacon/aggregation/cohort/messages/keygen/opt-in-accept.ts +2 -1
- package/src/core/beacon/aggregation/cohort/messages/keygen/opt-in.ts +2 -1
- package/src/core/beacon/aggregation/cohort/messages/keygen/subscribe.ts +2 -1
- package/src/core/beacon/aggregation/cohort/messages/sign/aggregated-nonce.ts +2 -1
- package/src/core/beacon/aggregation/cohort/messages/sign/authorization-request.ts +2 -1
- package/src/core/beacon/aggregation/cohort/messages/sign/nonce-contribution.ts +2 -1
- package/src/core/beacon/aggregation/cohort/messages/sign/request-signature.ts +2 -1
- package/src/core/beacon/aggregation/cohort/messages/sign/signature-authorization.ts +2 -1
- package/src/core/beacon/aggregation/communication/adapter/did-comm.ts +5 -4
- package/src/core/beacon/aggregation/communication/adapter/nostr.ts +9 -7
- package/src/core/beacon/aggregation/communication/factory.ts +1 -1
- package/src/core/beacon/aggregation/communication/service.ts +3 -3
- package/src/core/beacon/aggregation/coordinator.ts +12 -8
- package/src/core/beacon/aggregation/participant.ts +12 -7
- package/src/core/beacon/aggregation/session/index.ts +3 -2
- package/src/core/beacon/beacon.ts +5 -5
- package/src/core/beacon/cas-beacon.ts +13 -9
- package/src/core/beacon/factory.ts +2 -2
- package/src/core/beacon/interfaces.ts +3 -3
- package/src/core/beacon/signal-discovery.ts +5 -4
- package/src/core/beacon/singleton-beacon.ts +8 -7
- package/src/core/beacon/smt-beacon.ts +5 -5
- package/src/core/beacon/utils.ts +6 -4
- package/src/core/identifier.ts +3 -2
- package/src/core/interfaces.ts +2 -2
- package/src/core/resolver.ts +59 -51
- package/src/core/types.ts +6 -5
- package/src/core/update.ts +11 -7
- package/src/did-btcr2.ts +12 -10
- package/src/utils/appendix.ts +14 -16
- package/src/utils/did-document-builder.ts +3 -2
- package/src/utils/did-document.ts +10 -8
- package/dist/cjs/core/beacon/aggregation/cohort/index.js +0 -237
- package/dist/cjs/core/beacon/aggregation/cohort/index.js.map +0 -1
- package/dist/cjs/core/beacon/aggregation/cohort/messages/base.js +0 -26
- package/dist/cjs/core/beacon/aggregation/cohort/messages/base.js.map +0 -1
- package/dist/cjs/core/beacon/aggregation/cohort/messages/constants.js +0 -11
- package/dist/cjs/core/beacon/aggregation/cohort/messages/constants.js.map +0 -1
- package/dist/cjs/core/beacon/aggregation/cohort/messages/index.js +0 -98
- package/dist/cjs/core/beacon/aggregation/cohort/messages/index.js.map +0 -1
- package/dist/cjs/core/beacon/aggregation/cohort/messages/keygen/cohort-advert.js +0 -31
- package/dist/cjs/core/beacon/aggregation/cohort/messages/keygen/cohort-advert.js.map +0 -1
- package/dist/cjs/core/beacon/aggregation/cohort/messages/keygen/cohort-ready.js +0 -29
- package/dist/cjs/core/beacon/aggregation/cohort/messages/keygen/cohort-ready.js.map +0 -1
- package/dist/cjs/core/beacon/aggregation/cohort/messages/keygen/opt-in-accept.js +0 -27
- package/dist/cjs/core/beacon/aggregation/cohort/messages/keygen/opt-in-accept.js.map +0 -1
- package/dist/cjs/core/beacon/aggregation/cohort/messages/keygen/opt-in.js +0 -23
- package/dist/cjs/core/beacon/aggregation/cohort/messages/keygen/opt-in.js.map +0 -1
- package/dist/cjs/core/beacon/aggregation/cohort/messages/keygen/subscribe.js +0 -28
- package/dist/cjs/core/beacon/aggregation/cohort/messages/keygen/subscribe.js.map +0 -1
- package/dist/cjs/core/beacon/aggregation/cohort/messages/sign/aggregated-nonce.js +0 -29
- package/dist/cjs/core/beacon/aggregation/cohort/messages/sign/aggregated-nonce.js.map +0 -1
- package/dist/cjs/core/beacon/aggregation/cohort/messages/sign/authorization-request.js +0 -30
- package/dist/cjs/core/beacon/aggregation/cohort/messages/sign/authorization-request.js.map +0 -1
- package/dist/cjs/core/beacon/aggregation/cohort/messages/sign/nonce-contribution.js +0 -30
- package/dist/cjs/core/beacon/aggregation/cohort/messages/sign/nonce-contribution.js.map +0 -1
- package/dist/cjs/core/beacon/aggregation/cohort/messages/sign/request-signature.js +0 -30
- package/dist/cjs/core/beacon/aggregation/cohort/messages/sign/request-signature.js.map +0 -1
- package/dist/cjs/core/beacon/aggregation/cohort/messages/sign/signature-authorization.js +0 -31
- package/dist/cjs/core/beacon/aggregation/cohort/messages/sign/signature-authorization.js.map +0 -1
- package/dist/cjs/core/beacon/aggregation/cohort/status.js +0 -8
- package/dist/cjs/core/beacon/aggregation/cohort/status.js.map +0 -1
- package/dist/cjs/core/beacon/aggregation/communication/adapter/did-comm.js +0 -121
- package/dist/cjs/core/beacon/aggregation/communication/adapter/did-comm.js.map +0 -1
- package/dist/cjs/core/beacon/aggregation/communication/adapter/nostr.js +0 -246
- package/dist/cjs/core/beacon/aggregation/communication/adapter/nostr.js.map +0 -1
- package/dist/cjs/core/beacon/aggregation/communication/error.js +0 -12
- package/dist/cjs/core/beacon/aggregation/communication/error.js.map +0 -1
- package/dist/cjs/core/beacon/aggregation/communication/factory.js +0 -21
- package/dist/cjs/core/beacon/aggregation/communication/factory.js.map +0 -1
- package/dist/cjs/core/beacon/aggregation/communication/service.js +0 -2
- package/dist/cjs/core/beacon/aggregation/communication/service.js.map +0 -1
- package/dist/cjs/core/beacon/aggregation/coordinator.js +0 -343
- package/dist/cjs/core/beacon/aggregation/coordinator.js.map +0 -1
- package/dist/cjs/core/beacon/aggregation/participant.js +0 -435
- package/dist/cjs/core/beacon/aggregation/participant.js.map +0 -1
- package/dist/cjs/core/beacon/aggregation/session/index.js +0 -244
- package/dist/cjs/core/beacon/aggregation/session/index.js.map +0 -1
- package/dist/cjs/core/beacon/aggregation/session/status.js +0 -11
- package/dist/cjs/core/beacon/aggregation/session/status.js.map +0 -1
- package/dist/cjs/core/beacon/beacon.js +0 -25
- package/dist/cjs/core/beacon/beacon.js.map +0 -1
- package/dist/cjs/core/beacon/cas-beacon.js +0 -152
- package/dist/cjs/core/beacon/cas-beacon.js.map +0 -1
- package/dist/cjs/core/beacon/error.js +0 -37
- package/dist/cjs/core/beacon/error.js.map +0 -1
- package/dist/cjs/core/beacon/factory.js +0 -29
- package/dist/cjs/core/beacon/factory.js.map +0 -1
- package/dist/cjs/core/beacon/interfaces.js +0 -2
- package/dist/cjs/core/beacon/interfaces.js.map +0 -1
- package/dist/cjs/core/beacon/signal-discovery.js +0 -183
- package/dist/cjs/core/beacon/signal-discovery.js.map +0 -1
- package/dist/cjs/core/beacon/singleton-beacon.js +0 -107
- package/dist/cjs/core/beacon/singleton-beacon.js.map +0 -1
- package/dist/cjs/core/beacon/smt-beacon.js +0 -39
- package/dist/cjs/core/beacon/smt-beacon.js.map +0 -1
- package/dist/cjs/core/beacon/utils.js +0 -163
- package/dist/cjs/core/beacon/utils.js.map +0 -1
- package/dist/cjs/core/identifier.js +0 -248
- package/dist/cjs/core/identifier.js.map +0 -1
- package/dist/cjs/core/interfaces.js +0 -2
- package/dist/cjs/core/interfaces.js.map +0 -1
- package/dist/cjs/core/resolver.js +0 -476
- package/dist/cjs/core/resolver.js.map +0 -1
- package/dist/cjs/core/types.js +0 -2
- package/dist/cjs/core/types.js.map +0 -1
- package/dist/cjs/core/update.js +0 -112
- package/dist/cjs/core/update.js.map +0 -1
- package/dist/cjs/did-btcr2.js +0 -193
- package/dist/cjs/did-btcr2.js.map +0 -1
- package/dist/cjs/index.js.map +0 -1
- package/dist/cjs/utils/appendix.js +0 -203
- package/dist/cjs/utils/appendix.js.map +0 -1
- package/dist/cjs/utils/did-document-builder.js +0 -60
- package/dist/cjs/utils/did-document-builder.js.map +0 -1
- package/dist/cjs/utils/did-document.js +0 -424
- package/dist/cjs/utils/did-document.js.map +0 -1
package/src/core/identifier.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { Bytes, DocumentBytes, KeyBytes, SchnorrKeyPairObject } from '@did-btcr2/common';
|
|
2
|
+
import { BitcoinNetworkNames, IdentifierError, IdentifierTypes, INVALID_DID, METHOD_NOT_SUPPORTED } from '@did-btcr2/common';
|
|
2
3
|
import { CompressedSecp256k1PublicKey, SchnorrKeyPair } from '@did-btcr2/keypair';
|
|
3
4
|
import { bech32m } from '@scure/base';
|
|
4
|
-
import { DidCreateOptions } from '../did-btcr2.js';
|
|
5
|
+
import type { DidCreateOptions } from '../did-btcr2.js';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Components of a did:btcr2 identifier.
|
package/src/core/interfaces.ts
CHANGED
package/src/core/resolver.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { getNetwork } from '@did-btcr2/bitcoin';
|
|
2
2
|
import {
|
|
3
3
|
canonicalHash,
|
|
4
|
+
canonicalHashBytes,
|
|
4
5
|
canonicalize,
|
|
5
6
|
DateUtils,
|
|
6
7
|
encode as encodeHash,
|
|
@@ -12,23 +13,28 @@ import {
|
|
|
12
13
|
LATE_PUBLISHING_ERROR,
|
|
13
14
|
ResolveError
|
|
14
15
|
} from '@did-btcr2/common';
|
|
16
|
+
import type { HashBytes } from '@did-btcr2/common';
|
|
17
|
+
import type {
|
|
18
|
+
SignedBTCR2Update,
|
|
19
|
+
UnsignedBTCR2Update
|
|
20
|
+
} from '@did-btcr2/cryptosuite';
|
|
15
21
|
import {
|
|
16
22
|
BIP340Cryptosuite,
|
|
17
23
|
BIP340DataIntegrityProof,
|
|
18
|
-
SchnorrMultikey
|
|
19
|
-
SignedBTCR2Update,
|
|
20
|
-
UnsignedBTCR2Update
|
|
24
|
+
SchnorrMultikey
|
|
21
25
|
} from '@did-btcr2/cryptosuite';
|
|
22
26
|
import { CompressedSecp256k1PublicKey } from '@did-btcr2/keypair';
|
|
23
27
|
import { DidBtcr2 } from '../did-btcr2.js';
|
|
24
28
|
import { Appendix } from '../utils/appendix.js';
|
|
25
29
|
import { DidDocument, ID_PLACEHOLDER_VALUE } from '../utils/did-document.js';
|
|
26
30
|
import { BeaconFactory } from './beacon/factory.js';
|
|
27
|
-
import { BeaconService, BeaconSignal, BlockMetadata } from './beacon/interfaces.js';
|
|
31
|
+
import type { BeaconService, BeaconSignal, BlockMetadata } from './beacon/interfaces.js';
|
|
28
32
|
import { BeaconUtils } from './beacon/utils.js';
|
|
29
|
-
import { DidComponents
|
|
30
|
-
import {
|
|
31
|
-
import {
|
|
33
|
+
import type { DidComponents} from './identifier.js';
|
|
34
|
+
import { Identifier } from './identifier.js';
|
|
35
|
+
import type { SMTProof } from './interfaces.js';
|
|
36
|
+
import type { CASAnnouncement, Sidecar, SidecarData } from './types.js';
|
|
37
|
+
import { equalBytes } from '@noble/curves/utils.js';
|
|
32
38
|
|
|
33
39
|
/**
|
|
34
40
|
* The response object for DID Resolution.
|
|
@@ -46,7 +52,7 @@ export interface DidResolutionResponse {
|
|
|
46
52
|
/** The resolver needs a genesis document whose hash matches genesisHash. */
|
|
47
53
|
export interface NeedGenesisDocument {
|
|
48
54
|
readonly kind: 'NeedGenesisDocument';
|
|
49
|
-
/**
|
|
55
|
+
/** Hex-encoded SHA-256 hash from the DID identifier's genesisBytes. */
|
|
50
56
|
readonly genesisHash: string;
|
|
51
57
|
}
|
|
52
58
|
|
|
@@ -60,7 +66,7 @@ export interface NeedBeaconSignals {
|
|
|
60
66
|
/** The resolver needs a CAS Announcement whose canonical hash matches announcementHash. */
|
|
61
67
|
export interface NeedCASAnnouncement {
|
|
62
68
|
readonly kind: 'NeedCASAnnouncement';
|
|
63
|
-
/**
|
|
69
|
+
/** Hex-encoded canonical hash of the CAS Announcement. */
|
|
64
70
|
readonly announcementHash: string;
|
|
65
71
|
/** The beacon service that produced this signal. */
|
|
66
72
|
readonly beaconServiceId: string;
|
|
@@ -69,7 +75,7 @@ export interface NeedCASAnnouncement {
|
|
|
69
75
|
/** The resolver needs a SignedBTCR2Update whose canonical hash matches updateHash. */
|
|
70
76
|
export interface NeedSignedUpdate {
|
|
71
77
|
readonly kind: 'NeedSignedUpdate';
|
|
72
|
-
/**
|
|
78
|
+
/** Hex-encoded canonical hash of the signed update. */
|
|
73
79
|
readonly updateHash: string;
|
|
74
80
|
/** The beacon service that produced this signal. */
|
|
75
81
|
readonly beaconServiceId: string;
|
|
@@ -220,22 +226,22 @@ export class Resolver {
|
|
|
220
226
|
didComponents: DidComponents,
|
|
221
227
|
genesisDocument: object,
|
|
222
228
|
): DidDocument {
|
|
223
|
-
//
|
|
224
|
-
const
|
|
225
|
-
|
|
226
|
-
// Canonicalize and sha256 hash the currentDocument
|
|
227
|
-
const genesisDocumentBytes = canonicalHash(genesisDocument);
|
|
229
|
+
// Canonicalize and sha256 hash the genesis document
|
|
230
|
+
const genesisDocumentHash = canonicalHashBytes(genesisDocument);
|
|
228
231
|
|
|
229
|
-
//
|
|
230
|
-
if (genesisBytes
|
|
232
|
+
// Compare genesis bytes from identifier against the document hash (byte comparison)
|
|
233
|
+
if (!equalBytes(didComponents.genesisBytes, genesisDocumentHash)) {
|
|
231
234
|
throw new ResolveError(
|
|
232
|
-
`Initial document mismatch: genesisBytes !==
|
|
233
|
-
INVALID_DID_DOCUMENT, {
|
|
235
|
+
`Initial document mismatch: genesisBytes !== genesisDocumentHash`,
|
|
236
|
+
INVALID_DID_DOCUMENT, {
|
|
237
|
+
genesisBytes : encodeHash(didComponents.genesisBytes, 'hex'),
|
|
238
|
+
genesisDocumentHash : encodeHash(genesisDocumentHash, 'hex')
|
|
239
|
+
}
|
|
234
240
|
);
|
|
235
241
|
}
|
|
236
242
|
|
|
237
243
|
// Encode the did from the didComponents
|
|
238
|
-
const did = Identifier.encode(
|
|
244
|
+
const did = Identifier.encode(didComponents.genesisBytes, didComponents);
|
|
239
245
|
|
|
240
246
|
// Replace the placeholder did with the did throughout the currentDocument.
|
|
241
247
|
const currentDocument = JSON.parse(
|
|
@@ -256,14 +262,14 @@ export class Resolver {
|
|
|
256
262
|
const updateMap = new Map<string, SignedBTCR2Update>();
|
|
257
263
|
if(sidecar.updates?.length)
|
|
258
264
|
for(const update of sidecar.updates) {
|
|
259
|
-
updateMap.set(canonicalHash(update), update);
|
|
265
|
+
updateMap.set(canonicalHash(update, { encoding: 'hex' }), update);
|
|
260
266
|
}
|
|
261
267
|
|
|
262
268
|
// CAS Announcements map
|
|
263
269
|
const casMap = new Map<string, CASAnnouncement>();
|
|
264
270
|
if(sidecar.casUpdates?.length)
|
|
265
271
|
for(const update of sidecar.casUpdates) {
|
|
266
|
-
casMap.set(canonicalHash(update), update);
|
|
272
|
+
casMap.set(canonicalHash(update, { encoding: 'hex' }), update);
|
|
267
273
|
}
|
|
268
274
|
|
|
269
275
|
// SMT Proofs map
|
|
@@ -293,8 +299,8 @@ export class Resolver {
|
|
|
293
299
|
// Start the version number being processed at 1
|
|
294
300
|
let currentVersionId = 1;
|
|
295
301
|
|
|
296
|
-
// Initialize an empty array to hold the update hashes
|
|
297
|
-
const updateHashHistory:
|
|
302
|
+
// Initialize an empty array to hold the update hashes (raw bytes)
|
|
303
|
+
const updateHashHistory: HashBytes[] = [];
|
|
298
304
|
|
|
299
305
|
// 1. Sort updates by targetVersionId (ascending), using blockheight as tie-breaker
|
|
300
306
|
const updates = unsortedUpdates.sort(([upd0, blk0], [upd1, blk1]) =>
|
|
@@ -314,8 +320,8 @@ export class Resolver {
|
|
|
314
320
|
|
|
315
321
|
// Iterate over each (update block) pair
|
|
316
322
|
for(const [update, block] of updates) {
|
|
317
|
-
// Get the hash of the current document
|
|
318
|
-
const currentDocumentHash =
|
|
323
|
+
// Get the hash of the current document as raw bytes
|
|
324
|
+
const currentDocumentHash = canonicalHashBytes(response.didDocument);
|
|
319
325
|
|
|
320
326
|
// Safely convert block.time to timestamp
|
|
321
327
|
const blocktime = DateUtils.blocktimeToTimestamp(block.time);
|
|
@@ -345,12 +351,15 @@ export class Resolver {
|
|
|
345
351
|
|
|
346
352
|
// If update.targetVersionId == currentVersionId + 1, apply the update
|
|
347
353
|
else if (update.targetVersionId === currentVersionId + 1) {
|
|
348
|
-
// Check if update.sourceHash !== currentDocumentHash
|
|
349
|
-
|
|
350
|
-
|
|
354
|
+
// Check if update.sourceHash !== currentDocumentHash (byte comparison)
|
|
355
|
+
const sourceHashBytes = decodeHash(update.sourceHash, 'base64urlnopad');
|
|
356
|
+
if (!equalBytes(sourceHashBytes, currentDocumentHash)) {
|
|
351
357
|
throw new ResolveError(
|
|
352
358
|
`Hash mismatch: update.sourceHash !== currentDocumentHash`,
|
|
353
|
-
INVALID_DID_UPDATE, {
|
|
359
|
+
INVALID_DID_UPDATE, {
|
|
360
|
+
sourceHash : update.sourceHash,
|
|
361
|
+
currentDocumentHash : encodeHash(currentDocumentHash, 'hex')
|
|
362
|
+
}
|
|
354
363
|
);
|
|
355
364
|
}
|
|
356
365
|
// Apply the update to the currentDocument and set it in the response
|
|
@@ -358,8 +367,8 @@ export class Resolver {
|
|
|
358
367
|
|
|
359
368
|
// Create unsigned_update by removing the proof property from update.
|
|
360
369
|
const unsignedUpdate = JSONUtils.deleteKeys(update, ['proof']) as UnsignedBTCR2Update;
|
|
361
|
-
// Push the canonicalized unsigned update hash to the updateHashHistory
|
|
362
|
-
updateHashHistory.push(
|
|
370
|
+
// Push the canonicalized unsigned update hash bytes to the updateHashHistory
|
|
371
|
+
updateHashHistory.push(canonicalHashBytes(unsignedUpdate));
|
|
363
372
|
}
|
|
364
373
|
|
|
365
374
|
// If update.targetVersionId > currentVersionId + 1, throw LATE_PUBLISHING error
|
|
@@ -398,30 +407,31 @@ export class Resolver {
|
|
|
398
407
|
return response;
|
|
399
408
|
}
|
|
400
409
|
|
|
401
|
-
// ─── Private static: update internals ──────────────────────────────
|
|
402
|
-
|
|
403
410
|
/**
|
|
404
411
|
* Implements subsection {@link https://dcdpr.github.io/did-btcr2/#confirm-duplicate-update | 7.2.f.1 Confirm Duplicate Update}.
|
|
405
412
|
* This step confirms that an update with a lower-than-expected targetVersionId is a true duplicate.
|
|
406
413
|
* @param {SignedBTCR2Update} update The BTCR2 Signed Update to confirm as a duplicate.
|
|
407
|
-
* @param {
|
|
414
|
+
* @param {HashBytes[]} updateHashHistory The accumulated hash history for comparison.
|
|
408
415
|
* @returns {void} Does not return a value, but throws an error if the update is not a valid duplicate.
|
|
409
416
|
*/
|
|
410
|
-
private static confirmDuplicate(update: SignedBTCR2Update, updateHashHistory:
|
|
417
|
+
private static confirmDuplicate(update: SignedBTCR2Update, updateHashHistory: HashBytes[]): void {
|
|
411
418
|
// Create unsigned_update by removing the proof property from update.
|
|
412
419
|
const { proof: _, ...unsignedUpdate } = update;
|
|
413
420
|
|
|
414
|
-
// Hash unsignedUpdate with JSON Document Hashing algorithm
|
|
415
|
-
const unsignedUpdateHash =
|
|
421
|
+
// Hash unsignedUpdate with JSON Document Hashing algorithm (raw bytes)
|
|
422
|
+
const unsignedUpdateHash = canonicalHashBytes(unsignedUpdate);
|
|
416
423
|
|
|
417
424
|
// Let historicalUpdateHash equal updateHashHistory[updateHashIndex].
|
|
418
425
|
const historicalUpdateHash = updateHashHistory[update.targetVersionId - 2];
|
|
419
426
|
|
|
420
|
-
// Check if the updateHash matches the historical hash
|
|
421
|
-
if (
|
|
427
|
+
// Check if the updateHash matches the historical hash (byte comparison)
|
|
428
|
+
if (!equalBytes(historicalUpdateHash, unsignedUpdateHash)) {
|
|
422
429
|
throw new ResolveError(
|
|
423
|
-
`Invalid duplicate:
|
|
424
|
-
LATE_PUBLISHING_ERROR, {
|
|
430
|
+
`Invalid duplicate: unsigned update hash does not match historical hash`,
|
|
431
|
+
LATE_PUBLISHING_ERROR, {
|
|
432
|
+
unsignedUpdateHash : encodeHash(unsignedUpdateHash, 'hex'),
|
|
433
|
+
historicalHash : encodeHash(historicalUpdateHash, 'hex')
|
|
434
|
+
}
|
|
425
435
|
);
|
|
426
436
|
}
|
|
427
437
|
}
|
|
@@ -499,14 +509,14 @@ export class Resolver {
|
|
|
499
509
|
// Verify that updatedDocument is conformant to DID Core v1.1.
|
|
500
510
|
DidDocument.validate(updatedDocument);
|
|
501
511
|
|
|
502
|
-
// Canonicalize and hash the updatedDocument to get the currentDocumentHash.
|
|
503
|
-
const currentDocumentHash =
|
|
512
|
+
// Canonicalize and hash the updatedDocument to get the currentDocumentHash (raw bytes).
|
|
513
|
+
const currentDocumentHash = canonicalHashBytes(updatedDocument);
|
|
504
514
|
|
|
505
515
|
// Prepare the update targetHash for comparison with currentDocumentHash.
|
|
506
|
-
const updateTargetHash = update.targetHash;
|
|
516
|
+
const updateTargetHash = decodeHash(update.targetHash);
|
|
507
517
|
|
|
508
518
|
// Make sure the update.targetHash equals currentDocumentHash.
|
|
509
|
-
if (
|
|
519
|
+
if (!equalBytes(updateTargetHash, currentDocumentHash)) {
|
|
510
520
|
// If they do not match, throw INVALID_DID_UPDATE error.
|
|
511
521
|
throw new ResolveError(
|
|
512
522
|
`Invalid update: update.targetHash !== currentDocumentHash`,
|
|
@@ -518,8 +528,6 @@ export class Resolver {
|
|
|
518
528
|
return updatedDocument;
|
|
519
529
|
}
|
|
520
530
|
|
|
521
|
-
// ─── Instance: state machine ───────────────────────────────────────
|
|
522
|
-
|
|
523
531
|
/**
|
|
524
532
|
* Advance the state machine. Returns either:
|
|
525
533
|
* - `{ status: 'action-required', needs }` — caller must provide data via {@link provide}
|
|
@@ -546,7 +554,7 @@ export class Resolver {
|
|
|
546
554
|
}
|
|
547
555
|
|
|
548
556
|
// Need genesis document from caller
|
|
549
|
-
const genesisHash = encodeHash(this.#didComponents.genesisBytes);
|
|
557
|
+
const genesisHash = encodeHash(this.#didComponents.genesisBytes, 'hex');
|
|
550
558
|
return {
|
|
551
559
|
status : 'action-required',
|
|
552
560
|
needs : [{ kind: 'NeedGenesisDocument', genesisHash }]
|
|
@@ -692,13 +700,13 @@ export class Resolver {
|
|
|
692
700
|
|
|
693
701
|
case 'NeedCASAnnouncement': {
|
|
694
702
|
const announcement = data as CASAnnouncement;
|
|
695
|
-
this.#sidecarData.casMap.set(canonicalHash(announcement), announcement);
|
|
703
|
+
this.#sidecarData.casMap.set(canonicalHash(announcement, { encoding: 'hex' }), announcement);
|
|
696
704
|
break;
|
|
697
705
|
}
|
|
698
706
|
|
|
699
707
|
case 'NeedSignedUpdate': {
|
|
700
708
|
const update = data as SignedBTCR2Update;
|
|
701
|
-
this.#sidecarData.updateMap.set(canonicalHash(update), update);
|
|
709
|
+
this.#sidecarData.updateMap.set(canonicalHash(update, { encoding: 'hex' }), update);
|
|
702
710
|
break;
|
|
703
711
|
}
|
|
704
712
|
}
|
package/src/core/types.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { SMTProof } from './interfaces.js';
|
|
1
|
+
import type { SignedBTCR2Update } from '@did-btcr2/cryptosuite';
|
|
2
|
+
import type { SMTProof } from './interfaces.js';
|
|
4
3
|
|
|
5
4
|
/**
|
|
6
5
|
* {@link https://dcdpr.github.io/did-btcr2/data-structures.html#cas-announcement | CAS Announcement }
|
|
@@ -58,12 +57,14 @@ export type Sidecar = {
|
|
|
58
57
|
|
|
59
58
|
/**
|
|
60
59
|
* The Sidecar data structure used for Singleton Beacons.
|
|
60
|
+
* Map keyed by hex-encoded canonical hash of the signed update.
|
|
61
61
|
*/
|
|
62
|
-
export type SingletonBeaconSidecarData = Map<
|
|
62
|
+
export type SingletonBeaconSidecarData = Map<string, SignedBTCR2Update>;
|
|
63
63
|
/**
|
|
64
64
|
* The Sidecar data structure used for CAS Beacons.
|
|
65
|
+
* Map keyed by hex-encoded canonical hash of the CAS announcement.
|
|
65
66
|
*/
|
|
66
|
-
export type CASBeaconSidecarData = Map<
|
|
67
|
+
export type CASBeaconSidecarData = Map<string, CASAnnouncement>;
|
|
67
68
|
/**
|
|
68
69
|
* The Sidecar data structure used for SMT Beacons.
|
|
69
70
|
*/
|
package/src/core/update.ts
CHANGED
|
@@ -1,21 +1,25 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
KeyBytes,
|
|
3
|
+
PatchOperation} from '@did-btcr2/common';
|
|
1
4
|
import {
|
|
2
5
|
canonicalHash,
|
|
3
6
|
INVALID_DID_UPDATE,
|
|
4
7
|
JSONPatch,
|
|
5
|
-
KeyBytes,
|
|
6
|
-
PatchOperation,
|
|
7
8
|
UpdateError
|
|
8
9
|
} from '@did-btcr2/common';
|
|
9
|
-
import {
|
|
10
|
+
import type {
|
|
10
11
|
DataIntegrityConfig,
|
|
11
|
-
SchnorrMultikey,
|
|
12
12
|
SignedBTCR2Update,
|
|
13
13
|
UnsignedBTCR2Update
|
|
14
14
|
} from '@did-btcr2/cryptosuite';
|
|
15
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
SchnorrMultikey
|
|
17
|
+
} from '@did-btcr2/cryptosuite';
|
|
18
|
+
import type { Btcr2DidDocument, DidVerificationMethod } from '../utils/did-document.js';
|
|
19
|
+
import { DidDocument } from '../utils/did-document.js';
|
|
16
20
|
import { BeaconFactory } from './beacon/factory.js';
|
|
17
|
-
import { BeaconService } from './beacon/interfaces.js';
|
|
18
|
-
import { BitcoinConnection } from '@did-btcr2/bitcoin';
|
|
21
|
+
import type { BeaconService } from './beacon/interfaces.js';
|
|
22
|
+
import type { BitcoinConnection } from '@did-btcr2/bitcoin';
|
|
19
23
|
|
|
20
24
|
/**
|
|
21
25
|
* Implements {@link https://dcdpr.github.io/did-btcr2/operations/update.html | 7.3 Update}.
|
package/src/did-btcr2.ts
CHANGED
|
@@ -1,33 +1,35 @@
|
|
|
1
|
-
import { BitcoinConnection } from '@did-btcr2/bitcoin';
|
|
2
|
-
import {
|
|
1
|
+
import type { BitcoinConnection } from '@did-btcr2/bitcoin';
|
|
2
|
+
import type {
|
|
3
3
|
DocumentBytes,
|
|
4
4
|
HexString,
|
|
5
|
+
KeyBytes,
|
|
6
|
+
PatchOperation} from '@did-btcr2/common';
|
|
7
|
+
import {
|
|
5
8
|
IdentifierHrp,
|
|
6
9
|
INVALID_DID_DOCUMENT,
|
|
7
10
|
INVALID_DID_UPDATE,
|
|
8
|
-
KeyBytes,
|
|
9
11
|
METHOD_NOT_SUPPORTED,
|
|
10
12
|
MethodError,
|
|
11
|
-
PatchOperation,
|
|
12
13
|
UpdateError
|
|
13
14
|
} from '@did-btcr2/common';
|
|
14
|
-
import { SignedBTCR2Update } from '@did-btcr2/cryptosuite';
|
|
15
|
+
import type { SignedBTCR2Update } from '@did-btcr2/cryptosuite';
|
|
16
|
+
import type {
|
|
17
|
+
DidMethod} from '@web5/dids';
|
|
15
18
|
import {
|
|
16
19
|
Did,
|
|
17
20
|
DidError,
|
|
18
|
-
DidErrorCode
|
|
19
|
-
DidMethod,
|
|
21
|
+
DidErrorCode
|
|
20
22
|
} from '@web5/dids';
|
|
21
23
|
import * as ecc from '@bitcoinerlab/secp256k1';
|
|
22
24
|
import { hexToBytes } from '@noble/hashes/utils';
|
|
23
25
|
import { initEccLib } from 'bitcoinjs-lib';
|
|
24
|
-
import { BeaconService } from './core/beacon/interfaces.js';
|
|
26
|
+
import type { BeaconService } from './core/beacon/interfaces.js';
|
|
25
27
|
import { Identifier } from './core/identifier.js';
|
|
26
|
-
import { ResolutionOptions } from './core/interfaces.js';
|
|
28
|
+
import type { ResolutionOptions } from './core/interfaces.js';
|
|
27
29
|
import { Resolver } from './core/resolver.js';
|
|
28
30
|
import { Update } from './core/update.js';
|
|
29
31
|
import { Appendix } from './utils/appendix.js';
|
|
30
|
-
import { Btcr2DidDocument, DidVerificationMethod } from './utils/did-document.js';
|
|
32
|
+
import type { Btcr2DidDocument, DidVerificationMethod } from './utils/did-document.js';
|
|
31
33
|
|
|
32
34
|
export interface DidCreateOptions {
|
|
33
35
|
/** Type of identifier to create (key or external) */
|
package/src/utils/appendix.ts
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
import { HashBytes } from '@did-btcr2/common';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import type { HashBytes } from '@did-btcr2/common';
|
|
2
|
+
import type {
|
|
4
3
|
DidDocument,
|
|
4
|
+
DidService,
|
|
5
|
+
DidVerificationMethod} from '@web5/dids';
|
|
6
|
+
import {
|
|
5
7
|
DidError,
|
|
6
8
|
DidErrorCode,
|
|
7
|
-
DidService,
|
|
8
|
-
DidVerificationMethod,
|
|
9
9
|
DidVerificationRelationship
|
|
10
10
|
} from '@web5/dids';
|
|
11
|
-
import { createHelia } from 'helia';
|
|
12
11
|
import { CID } from 'multiformats';
|
|
13
12
|
import { create as createDigest } from 'multiformats/hashes/digest';
|
|
14
|
-
import { RootCapability } from '../core/interfaces.js';
|
|
13
|
+
import type { RootCapability } from '../core/interfaces.js';
|
|
15
14
|
|
|
16
15
|
/**
|
|
17
16
|
* Implements {@link https://dcdpr.github.io/did-btcr2/#appendix | 9. Appendix} methods.
|
|
@@ -67,10 +66,10 @@ export class Appendix {
|
|
|
67
66
|
}
|
|
68
67
|
|
|
69
68
|
/**
|
|
70
|
-
* Extracts the verification methods from a given DID Document
|
|
71
|
-
* @param
|
|
72
|
-
* @returns
|
|
73
|
-
* @throws
|
|
69
|
+
* Extracts the verification methods from a given DID Document.
|
|
70
|
+
* @param didDocument The DID Document to extract the verification methods from
|
|
71
|
+
* @returns An array of DidVerificationMethod objects
|
|
72
|
+
* @throws TypeError if the didDocument is not provided
|
|
74
73
|
*/
|
|
75
74
|
public static getVerificationMethods(didDocument: DidDocument): DidVerificationMethod[] {
|
|
76
75
|
if (!didDocument) throw new TypeError(`Required parameter missing: 'didDocument'`);
|
|
@@ -215,6 +214,10 @@ export class Appendix {
|
|
|
215
214
|
// Construct CID from hash bytes
|
|
216
215
|
const cid = CID.create(1, 1, createDigest(1, hashBytes));
|
|
217
216
|
|
|
217
|
+
// Lazy-load helia to avoid bundling its native deps into downstream CJS builds.
|
|
218
|
+
const { createHelia } = await import('helia');
|
|
219
|
+
const { strings } = await import('@helia/strings');
|
|
220
|
+
|
|
218
221
|
// Connect to IPFS/Helia node
|
|
219
222
|
const helia = await createHelia();
|
|
220
223
|
const node = strings(helia);
|
|
@@ -223,8 +226,3 @@ export class Appendix {
|
|
|
223
226
|
return await node.get(cid, {});
|
|
224
227
|
}
|
|
225
228
|
}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { DidDocumentError, INVALID_DID_DOCUMENT } from '@did-btcr2/common';
|
|
2
|
-
import { BeaconService } from '../core/beacon/interfaces.js';
|
|
3
|
-
import {
|
|
2
|
+
import type { BeaconService } from '../core/beacon/interfaces.js';
|
|
3
|
+
import type { DidVerificationMethod } from './did-document.js';
|
|
4
|
+
import { DidDocument } from './did-document.js';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* A builder class for constructing DID Documents.
|
|
@@ -1,20 +1,22 @@
|
|
|
1
1
|
import { getNetwork } from '@did-btcr2/bitcoin';
|
|
2
|
+
import type {
|
|
3
|
+
HashBytes,
|
|
4
|
+
JSONObject,
|
|
5
|
+
KeyBytes
|
|
6
|
+
} from '@did-btcr2/common';
|
|
2
7
|
import {
|
|
3
8
|
canonicalize,
|
|
4
9
|
DidDocumentError,
|
|
5
10
|
hash,
|
|
6
|
-
HashBytes,
|
|
7
11
|
IdentifierTypes,
|
|
8
12
|
INVALID_DID_DOCUMENT,
|
|
9
|
-
|
|
10
|
-
JSONUtils,
|
|
11
|
-
KeyBytes
|
|
13
|
+
JSONUtils
|
|
12
14
|
} from '@did-btcr2/common';
|
|
13
15
|
import { CompressedSecp256k1PublicKey } from '@did-btcr2/keypair';
|
|
14
|
-
import { DidDocument as W3CDidDocument, DidVerificationMethod as W3CDidVerificationMethod } from '@web5/dids';
|
|
16
|
+
import type { DidDocument as W3CDidDocument, DidVerificationMethod as W3CDidVerificationMethod } from '@web5/dids';
|
|
17
|
+
import { isDidService } from '@web5/dids/utils';
|
|
15
18
|
import { payments } from 'bitcoinjs-lib';
|
|
16
|
-
import { BeaconService } from '../core/beacon/interfaces.js';
|
|
17
|
-
import { BeaconUtils } from '../core/beacon/utils.js';
|
|
19
|
+
import type { BeaconService } from '../core/beacon/interfaces.js';
|
|
18
20
|
import { Identifier } from '../core/identifier.js';
|
|
19
21
|
import { Appendix } from './appendix.js';
|
|
20
22
|
|
|
@@ -342,7 +344,7 @@ export class DidDocument implements Btcr2DidDocument {
|
|
|
342
344
|
* @returns {boolean} True if the services are valid.
|
|
343
345
|
*/
|
|
344
346
|
private static isValidServices(service: unknown): boolean {
|
|
345
|
-
return Array.isArray(service) && service.every(
|
|
347
|
+
return Array.isArray(service) && service.every(isDidService);
|
|
346
348
|
}
|
|
347
349
|
|
|
348
350
|
/**
|