@bsv/sdk 1.3.32 → 1.3.34

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.
Files changed (45) hide show
  1. package/dist/cjs/package.json +1 -1
  2. package/dist/cjs/src/auth/certificates/MasterCertificate.js +25 -15
  3. package/dist/cjs/src/auth/certificates/MasterCertificate.js.map +1 -1
  4. package/dist/cjs/src/auth/certificates/VerifiableCertificate.js +6 -2
  5. package/dist/cjs/src/auth/certificates/VerifiableCertificate.js.map +1 -1
  6. package/dist/cjs/src/overlay-tools/LookupResolver.js +22 -23
  7. package/dist/cjs/src/overlay-tools/LookupResolver.js.map +1 -1
  8. package/dist/cjs/src/overlay-tools/SHIPBroadcaster.js +17 -15
  9. package/dist/cjs/src/overlay-tools/SHIPBroadcaster.js.map +1 -1
  10. package/dist/cjs/src/overlay-tools/index.js +8 -2
  11. package/dist/cjs/src/overlay-tools/index.js.map +1 -1
  12. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  13. package/dist/esm/src/auth/certificates/MasterCertificate.js +25 -15
  14. package/dist/esm/src/auth/certificates/MasterCertificate.js.map +1 -1
  15. package/dist/esm/src/auth/certificates/VerifiableCertificate.js +6 -2
  16. package/dist/esm/src/auth/certificates/VerifiableCertificate.js.map +1 -1
  17. package/dist/esm/src/overlay-tools/LookupResolver.js +22 -22
  18. package/dist/esm/src/overlay-tools/LookupResolver.js.map +1 -1
  19. package/dist/esm/src/overlay-tools/SHIPBroadcaster.js +17 -14
  20. package/dist/esm/src/overlay-tools/SHIPBroadcaster.js.map +1 -1
  21. package/dist/esm/src/overlay-tools/index.js +4 -0
  22. package/dist/esm/src/overlay-tools/index.js.map +1 -1
  23. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  24. package/dist/types/src/auth/certificates/MasterCertificate.d.ts +10 -4
  25. package/dist/types/src/auth/certificates/MasterCertificate.d.ts.map +1 -1
  26. package/dist/types/src/auth/certificates/VerifiableCertificate.d.ts +3 -1
  27. package/dist/types/src/auth/certificates/VerifiableCertificate.d.ts.map +1 -1
  28. package/dist/types/src/overlay-tools/LookupResolver.d.ts +12 -1
  29. package/dist/types/src/overlay-tools/LookupResolver.d.ts.map +1 -1
  30. package/dist/types/src/overlay-tools/SHIPBroadcaster.d.ts +13 -4
  31. package/dist/types/src/overlay-tools/SHIPBroadcaster.d.ts.map +1 -1
  32. package/dist/types/src/overlay-tools/index.d.ts +2 -0
  33. package/dist/types/src/overlay-tools/index.d.ts.map +1 -1
  34. package/dist/types/tsconfig.types.tsbuildinfo +1 -1
  35. package/dist/umd/bundle.js +1 -1
  36. package/docs/auth.md +25 -9
  37. package/docs/overlay-tools.md +58 -14
  38. package/package.json +1 -1
  39. package/src/auth/certificates/MasterCertificate.ts +37 -13
  40. package/src/auth/certificates/VerifiableCertificate.ts +8 -2
  41. package/src/overlay-tools/LookupResolver.ts +30 -30
  42. package/src/overlay-tools/SHIPBroadcaster.ts +25 -21
  43. package/src/overlay-tools/__tests/LookupResolver.test.ts +3 -3
  44. package/src/overlay-tools/__tests/SHIPBroadcaster.test.ts +3 -3
  45. package/src/overlay-tools/index.ts +5 -0
package/docs/auth.md CHANGED
@@ -463,14 +463,14 @@ export class MasterCertificate extends Certificate {
463
463
  declare signature?: HexString;
464
464
  masterKeyring: Record<CertificateFieldNameUnder50Bytes, Base64String>;
465
465
  constructor(type: Base64String, serialNumber: Base64String, subject: PubKeyHex, certifier: PubKeyHex, revocationOutpoint: OutpointString, fields: Record<CertificateFieldNameUnder50Bytes, Base64String>, masterKeyring: Record<CertificateFieldNameUnder50Bytes, Base64String>, signature?: HexString)
466
- static async createCertificateFields(creatorWallet: ProtoWallet, certifierOrSubject: WalletCounterparty, fields: Record<CertificateFieldNameUnder50Bytes, string>): Promise<CreateCertificateFieldsResult>
467
- static async createKeyringForVerifier(subjectWallet: ProtoWallet, certifier: WalletCounterparty, verifier: WalletCounterparty, fields: Record<CertificateFieldNameUnder50Bytes, Base64String>, fieldsToReveal: string[], masterKeyring: Record<CertificateFieldNameUnder50Bytes, Base64String>, serialNumber: Base64String): Promise<Record<CertificateFieldNameUnder50Bytes, string>>
466
+ static async createCertificateFields(creatorWallet: ProtoWallet, certifierOrSubject: WalletCounterparty, fields: Record<CertificateFieldNameUnder50Bytes, string>, privileged?: boolean, privilegedReason?: string): Promise<CreateCertificateFieldsResult>
467
+ static async createKeyringForVerifier(subjectWallet: ProtoWallet, certifier: WalletCounterparty, verifier: WalletCounterparty, fields: Record<CertificateFieldNameUnder50Bytes, Base64String>, fieldsToReveal: string[], masterKeyring: Record<CertificateFieldNameUnder50Bytes, Base64String>, serialNumber: Base64String, privileged?: boolean, privilegedReason?: string): Promise<Record<CertificateFieldNameUnder50Bytes, string>>
468
468
  static async issueCertificateForSubject(certifierWallet: ProtoWallet, subject: WalletCounterparty, fields: Record<CertificateFieldNameUnder50Bytes, string>, certificateType: string, getRevocationOutpoint = async (_serial: string): Promise<string> => {
469
469
  void _serial;
470
470
  return "Certificate revocation not tracked.";
471
471
  }, serialNumber?: string): Promise<MasterCertificate>
472
- static async decryptFields(subjectOrCertifierWallet: ProtoWallet, masterKeyring: Record<CertificateFieldNameUnder50Bytes, Base64String>, fields: Record<CertificateFieldNameUnder50Bytes, Base64String>, counterparty: WalletCounterparty): Promise<Record<CertificateFieldNameUnder50Bytes, string>>
473
- static async decryptField(subjectOrCertifierWallet: ProtoWallet, masterKeyring: Record<CertificateFieldNameUnder50Bytes, Base64String>, fieldName: Base64String, fieldValue: Base64String, counterparty: WalletCounterparty): Promise<{
472
+ static async decryptFields(subjectOrCertifierWallet: ProtoWallet, masterKeyring: Record<CertificateFieldNameUnder50Bytes, Base64String>, fields: Record<CertificateFieldNameUnder50Bytes, Base64String>, counterparty: WalletCounterparty, privileged?: boolean, privilegedReason?: string): Promise<Record<CertificateFieldNameUnder50Bytes, string>>
473
+ static async decryptField(subjectOrCertifierWallet: ProtoWallet, masterKeyring: Record<CertificateFieldNameUnder50Bytes, Base64String>, fieldName: Base64String, fieldValue: Base64String, counterparty: WalletCounterparty, privileged?: boolean, privilegedReason?: string): Promise<{
474
474
  fieldRevelationKey: number[];
475
475
  decryptedFieldValue: string;
476
476
  }>
@@ -486,7 +486,7 @@ This method returns a master keyring tied to a specific certifier or subject who
486
486
  and sign off on the fields, along with the encrypted certificate fields.
487
487
 
488
488
  ```ts
489
- static async createCertificateFields(creatorWallet: ProtoWallet, certifierOrSubject: WalletCounterparty, fields: Record<CertificateFieldNameUnder50Bytes, string>): Promise<CreateCertificateFieldsResult>
489
+ static async createCertificateFields(creatorWallet: ProtoWallet, certifierOrSubject: WalletCounterparty, fields: Record<CertificateFieldNameUnder50Bytes, string>, privileged?: boolean, privilegedReason?: string): Promise<CreateCertificateFieldsResult>
490
490
  ```
491
491
  See also: [CertificateFieldNameUnder50Bytes](./wallet.md#type-certificatefieldnameunder50bytes), [ProtoWallet](./wallet.md#class-protowallet), [WalletCounterparty](./wallet.md#type-walletcounterparty)
492
492
 
@@ -506,6 +506,10 @@ Argument Details
506
506
  + The certifier or subject who will validate the certificate fields.
507
507
  + **fields**
508
508
  + A record of certificate field names (under 50 bytes) mapped to their values.
509
+ + **privileged**
510
+ + Whether this is a privileged request.
511
+ + **privilegedReason**
512
+ + Reason provided for privileged access, required if this is a privileged operation. *
509
513
 
510
514
  #### Method createKeyringForVerifier
511
515
 
@@ -515,7 +519,7 @@ for the verifier's identity key. The result is a keyring containing the keys nec
515
519
  for the verifier to access the designated fields.
516
520
 
517
521
  ```ts
518
- static async createKeyringForVerifier(subjectWallet: ProtoWallet, certifier: WalletCounterparty, verifier: WalletCounterparty, fields: Record<CertificateFieldNameUnder50Bytes, Base64String>, fieldsToReveal: string[], masterKeyring: Record<CertificateFieldNameUnder50Bytes, Base64String>, serialNumber: Base64String): Promise<Record<CertificateFieldNameUnder50Bytes, string>>
522
+ static async createKeyringForVerifier(subjectWallet: ProtoWallet, certifier: WalletCounterparty, verifier: WalletCounterparty, fields: Record<CertificateFieldNameUnder50Bytes, Base64String>, fieldsToReveal: string[], masterKeyring: Record<CertificateFieldNameUnder50Bytes, Base64String>, serialNumber: Base64String, privileged?: boolean, privilegedReason?: string): Promise<Record<CertificateFieldNameUnder50Bytes, string>>
519
523
  ```
520
524
  See also: [Base64String](./wallet.md#type-base64string), [CertificateFieldNameUnder50Bytes](./wallet.md#type-certificatefieldnameunder50bytes), [ProtoWallet](./wallet.md#class-protowallet), [WalletCounterparty](./wallet.md#type-walletcounterparty)
521
525
 
@@ -533,6 +537,10 @@ Argument Details
533
537
  + An array of field names to be revealed to the verifier. Must be a subset of the certificate's fields.
534
538
  + **originator**
535
539
  + Optional originator identifier, used if additional context is needed for decryption and encryption operations.
540
+ + **privileged**
541
+ + Whether this is a privileged request.
542
+ + **privilegedReason**
543
+ + Reason provided for privileged access, required if this is a privileged operation. *
536
544
 
537
545
  Throws
538
546
 
@@ -552,7 +560,7 @@ The counterparty used for decryption depends on how the certificate fields were
552
560
  - Otherwise, the counterparty should always be the other party involved in the certificate issuance process (the subject or certifier).
553
561
 
554
562
  ```ts
555
- static async decryptFields(subjectOrCertifierWallet: ProtoWallet, masterKeyring: Record<CertificateFieldNameUnder50Bytes, Base64String>, fields: Record<CertificateFieldNameUnder50Bytes, Base64String>, counterparty: WalletCounterparty): Promise<Record<CertificateFieldNameUnder50Bytes, string>>
563
+ static async decryptFields(subjectOrCertifierWallet: ProtoWallet, masterKeyring: Record<CertificateFieldNameUnder50Bytes, Base64String>, fields: Record<CertificateFieldNameUnder50Bytes, Base64String>, counterparty: WalletCounterparty, privileged?: boolean, privilegedReason?: string): Promise<Record<CertificateFieldNameUnder50Bytes, string>>
556
564
  ```
557
565
  See also: [Base64String](./wallet.md#type-base64string), [CertificateFieldNameUnder50Bytes](./wallet.md#type-certificatefieldnameunder50bytes), [ProtoWallet](./wallet.md#class-protowallet), [WalletCounterparty](./wallet.md#type-walletcounterparty)
558
566
 
@@ -570,6 +578,10 @@ Argument Details
570
578
  + A record of encrypted field names and their values.
571
579
  + **counterparty**
572
580
  + The counterparty responsible for creating or signing the certificate. For self-signed certificates, use 'self'.
581
+ + **privileged**
582
+ + Whether this is a privileged request.
583
+ + **privilegedReason**
584
+ + Reason provided for privileged access, required if this is a privileged operation.
573
585
 
574
586
  Throws
575
587
 
@@ -1094,7 +1106,7 @@ export class VerifiableCertificate extends Certificate {
1094
1106
  keyring: Record<CertificateFieldNameUnder50Bytes, string>;
1095
1107
  decryptedFields?: Record<CertificateFieldNameUnder50Bytes, Base64String>;
1096
1108
  constructor(type: Base64String, serialNumber: Base64String, subject: PubKeyHex, certifier: PubKeyHex, revocationOutpoint: OutpointString, fields: Record<CertificateFieldNameUnder50Bytes, string>, keyring: Record<CertificateFieldNameUnder50Bytes, string>, signature?: HexString, decryptedFields?: Record<CertificateFieldNameUnder50Bytes, Base64String>)
1097
- async decryptFields(verifierWallet: ProtoWallet): Promise<Record<CertificateFieldNameUnder50Bytes, string>>
1109
+ async decryptFields(verifierWallet: ProtoWallet, privileged?: boolean, privilegedReason?: string): Promise<Record<CertificateFieldNameUnder50Bytes, string>>
1098
1110
  }
1099
1111
  ```
1100
1112
 
@@ -1105,7 +1117,7 @@ See also: [Base64String](./wallet.md#type-base64string), [Certificate](./auth.md
1105
1117
  Decrypts selectively revealed certificate fields using the provided keyring and verifier wallet
1106
1118
 
1107
1119
  ```ts
1108
- async decryptFields(verifierWallet: ProtoWallet): Promise<Record<CertificateFieldNameUnder50Bytes, string>>
1120
+ async decryptFields(verifierWallet: ProtoWallet, privileged?: boolean, privilegedReason?: string): Promise<Record<CertificateFieldNameUnder50Bytes, string>>
1109
1121
  ```
1110
1122
  See also: [CertificateFieldNameUnder50Bytes](./wallet.md#type-certificatefieldnameunder50bytes), [ProtoWallet](./wallet.md#class-protowallet)
1111
1123
 
@@ -1117,6 +1129,10 @@ Argument Details
1117
1129
 
1118
1130
  + **verifierWallet**
1119
1131
  + The wallet instance of the certificate's verifier, used to decrypt field keys.
1132
+ + **privileged**
1133
+ + Whether this is a privileged request.
1134
+ + **privilegedReason**
1135
+ + Reason provided for privileged access, required if this is a privileged operation.
1120
1136
 
1121
1137
  Throws
1122
1138
 
@@ -95,6 +95,7 @@ Configuration options for the Lookup resolver.
95
95
 
96
96
  ```ts
97
97
  export interface LookupResolverConfig {
98
+ networkPreset?: "mainnet" | "testnet" | "local";
98
99
  facilitator?: OverlayLookupFacilitator;
99
100
  slapTrackers?: string[];
100
101
  hostOverrides?: Record<string, string[]>;
@@ -129,6 +130,17 @@ Map of lookup service names to arrays of hosts to use in place of resolving via
129
130
  hostOverrides?: Record<string, string[]>
130
131
  ```
131
132
 
133
+ #### Property networkPreset
134
+
135
+ The network preset to use, unless other options override it.
136
+ - mainnet: use mainnet SLAP trackers and HTTPS facilitator
137
+ - testnet: use testnet SLAP trackers and HTTPS facilitator
138
+ - local: directly query from localhost:8080 and a facilitator that permits plain HTTP
139
+
140
+ ```ts
141
+ networkPreset?: "mainnet" | "testnet" | "local"
142
+ ```
143
+
132
144
  #### Property slapTrackers
133
145
 
134
146
  The list of SLAP trackers queried to resolve Overlay Services hosts for a given lookup service.
@@ -185,8 +197,9 @@ Configuration options for the SHIP broadcaster.
185
197
 
186
198
  ```ts
187
199
  export interface SHIPBroadcasterConfig {
200
+ networkPreset?: "mainnet" | "testnet" | "local";
188
201
  facilitator?: OverlayBroadcastFacilitator;
189
- resolver: LookupResolver;
202
+ resolver?: LookupResolver;
190
203
  requireAcknowledgmentFromAllHostsForTopics?: "all" | "any" | string[];
191
204
  requireAcknowledgmentFromAnyHostForTopics?: "all" | "any" | string[];
192
205
  requireAcknowledgmentFromSpecificHostsForTopics?: Record<string, "all" | "any" | string[]>;
@@ -204,6 +217,17 @@ facilitator?: OverlayBroadcastFacilitator
204
217
  ```
205
218
  See also: [OverlayBroadcastFacilitator](./overlay-tools.md#interface-overlaybroadcastfacilitator)
206
219
 
220
+ #### Property networkPreset
221
+
222
+ The network preset to use, unless other options override it.
223
+ - mainnet: use mainnet resolver and HTTPS facilitator
224
+ - testnet: use testnet resolver and HTTPS facilitator
225
+ - local: directly send to localhost:8080 and a facilitator that permits plain HTTP
226
+
227
+ ```ts
228
+ networkPreset?: "mainnet" | "testnet" | "local"
229
+ ```
230
+
207
231
  #### Property requireAcknowledgmentFromAllHostsForTopics
208
232
 
209
233
  Determines which topics (all, any, or a specific list) must be present within all STEAKs received from every host for the broadcast to be considered a success. By default, all hosts must acknowledge all topics.
@@ -233,7 +257,7 @@ requireAcknowledgmentFromSpecificHostsForTopics?: Record<string, "all" | "any" |
233
257
  The resolver used to locate suitable hosts with SHIP
234
258
 
235
259
  ```ts
236
- resolver: LookupResolver
260
+ resolver?: LookupResolver
237
261
  ```
238
262
  See also: [LookupResolver](./overlay-tools.md#class-lookupresolver)
239
263
 
@@ -262,7 +286,7 @@ Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](
262
286
  | [HTTPSOverlayLookupFacilitator](#class-httpsoverlaylookupfacilitator) |
263
287
  | [LookupResolver](#class-lookupresolver) |
264
288
  | [OverlayAdminTokenTemplate](#class-overlayadmintokentemplate) |
265
- | [SHIPBroadcaster](#class-shipbroadcaster) |
289
+ | [TopicBroadcaster](#class-topicbroadcaster) |
266
290
 
267
291
  Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](#functions), [Types](#types), [Enums](#enums), [Variables](#variables)
268
292
 
@@ -273,7 +297,8 @@ Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](
273
297
  ```ts
274
298
  export class HTTPSOverlayBroadcastFacilitator implements OverlayBroadcastFacilitator {
275
299
  httpClient: typeof fetch;
276
- constructor(httpClient = fetch)
300
+ allowHTTP: boolean;
301
+ constructor(httpClient = fetch, allowHTTP: boolean = false)
277
302
  async send(url: string, taggedBEEF: TaggedBEEF): Promise<STEAK>
278
303
  }
279
304
  ```
@@ -288,7 +313,8 @@ Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](
288
313
  ```ts
289
314
  export class HTTPSOverlayLookupFacilitator implements OverlayLookupFacilitator {
290
315
  fetchClient: typeof fetch;
291
- constructor(httpClient = fetch)
316
+ allowHTTP: boolean;
317
+ constructor(httpClient = fetch, allowHTTP: boolean = false)
292
318
  async lookup(url: string, question: LookupQuestion, timeout: number = 5000): Promise<LookupAnswer>
293
319
  }
294
320
  ```
@@ -304,7 +330,7 @@ Represents an SHIP transaction broadcaster.
304
330
 
305
331
  ```ts
306
332
  export default class LookupResolver {
307
- constructor(config?: LookupResolverConfig)
333
+ constructor(config: LookupResolverConfig = {})
308
334
  async query(question: LookupQuestion, timeout?: number): Promise<LookupAnswer>
309
335
  }
310
336
  ```
@@ -430,13 +456,13 @@ Argument Details
430
456
  Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](#functions), [Types](#types), [Enums](#enums), [Variables](#variables)
431
457
 
432
458
  ---
433
- ### Class: SHIPBroadcaster
459
+ ### Class: TopicBroadcaster
434
460
 
435
- Represents a SHIP transaction broadcaster.
461
+ Broadcasts transactions to one or more overlay topics.
436
462
 
437
463
  ```ts
438
- export default class SHIPBroadcaster implements Broadcaster {
439
- constructor(topics: string[], config?: SHIPBroadcasterConfig)
464
+ export default class TopicBroadcaster implements Broadcaster {
465
+ constructor(topics: string[], config: SHIPBroadcasterConfig = {})
440
466
  async broadcast(tx: Transaction): Promise<BroadcastResponse | BroadcastFailure>
441
467
  }
442
468
  ```
@@ -448,7 +474,7 @@ See also: [BroadcastFailure](./transaction.md#interface-broadcastfailure), [Broa
448
474
  Constructs an instance of the SHIP broadcaster.
449
475
 
450
476
  ```ts
451
- constructor(topics: string[], config?: SHIPBroadcasterConfig)
477
+ constructor(topics: string[], config: SHIPBroadcasterConfig = {})
452
478
  ```
453
479
  See also: [SHIPBroadcasterConfig](./overlay-tools.md#interface-shipbroadcasterconfig)
454
480
 
@@ -531,13 +557,31 @@ Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](
531
557
 
532
558
  ## Variables
533
559
 
560
+ | |
561
+ | --- |
562
+ | [DEFAULT_SLAP_TRACKERS](#variable-default_slap_trackers) |
563
+ | [DEFAULT_TESTNET_SLAP_TRACKERS](#variable-default_testnet_slap_trackers) |
564
+
565
+ Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](#functions), [Types](#types), [Enums](#enums), [Variables](#variables)
566
+
567
+ ---
568
+
534
569
  ### Variable: DEFAULT_SLAP_TRACKERS
535
570
 
536
571
  ```ts
537
572
  DEFAULT_SLAP_TRACKERS: string[] = [
538
- "https://overlay.babbage.systems",
539
- "https://overlay-example.babbage.systems",
540
- "https://office.babbage.systems"
573
+ "https://users.bapp.dev"
574
+ ]
575
+ ```
576
+
577
+ Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](#functions), [Types](#types), [Enums](#enums), [Variables](#variables)
578
+
579
+ ---
580
+ ### Variable: DEFAULT_TESTNET_SLAP_TRACKERS
581
+
582
+ ```ts
583
+ DEFAULT_TESTNET_SLAP_TRACKERS: string[] = [
584
+ "https://testnet-users.bapp.dev"
541
585
  ]
542
586
  ```
543
587
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bsv/sdk",
3
- "version": "1.3.32",
3
+ "version": "1.3.34",
4
4
  "type": "module",
5
5
  "description": "BSV Blockchain Software Development Kit",
6
6
  "main": "dist/cjs/mod.js",
@@ -76,6 +76,8 @@ export class MasterCertificate extends Certificate {
76
76
  * @param {ProtoWallet} creatorWallet - The wallet of the creator responsible for encrypting the fields.
77
77
  * @param {WalletCounterparty} certifierOrSubject - The certifier or subject who will validate the certificate fields.
78
78
  * @param {Record<CertificateFieldNameUnder50Bytes, string>} fields - A record of certificate field names (under 50 bytes) mapped to their values.
79
+ * @param {BooleanDefaultFalse} [privileged] - Whether this is a privileged request.
80
+ * @param {DescriptionString5to50Bytes} [privilegedReason] - Reason provided for privileged access, required if this is a privileged operation. *
79
81
  * @returns {Promise<CreateCertificateFieldsResult>} A promise resolving to an object containing:
80
82
  * - `certificateFields` {Record<CertificateFieldNameUnder50Bytes, Base64String>}:
81
83
  * The encrypted certificate fields.
@@ -85,7 +87,9 @@ export class MasterCertificate extends Certificate {
85
87
  static async createCertificateFields(
86
88
  creatorWallet: ProtoWallet,
87
89
  certifierOrSubject: WalletCounterparty,
88
- fields: Record<CertificateFieldNameUnder50Bytes, string>
90
+ fields: Record<CertificateFieldNameUnder50Bytes, string>,
91
+ privileged?: boolean,
92
+ privilegedReason?: string
89
93
  ): Promise<CreateCertificateFieldsResult> {
90
94
  const certificateFields: Record<
91
95
  CertificateFieldNameUnder50Bytes,
@@ -109,7 +113,9 @@ export class MasterCertificate extends Certificate {
109
113
  {
110
114
  plaintext: fieldSymmetricKey.toArray(),
111
115
  ...Certificate.getCertificateFieldEncryptionDetails(fieldName), // Only fieldName used on MasterCertificate
112
- counterparty: certifierOrSubject
116
+ counterparty: certifierOrSubject,
117
+ privileged,
118
+ privilegedReason
113
119
  }
114
120
  )
115
121
  masterKeyring[fieldName] = Utils.toBase64(encryptedFieldRevelationKey)
@@ -132,6 +138,8 @@ export class MasterCertificate extends Certificate {
132
138
  * @param {string[]} fieldsToReveal - An array of field names to be revealed to the verifier. Must be a subset of the certificate's fields.
133
139
  * @param {string} [originator] - Optional originator identifier, used if additional context is needed for decryption and encryption operations.
134
140
  * @returns {Promise<Record<CertificateFieldNameUnder50Bytes, string>>} - A keyring mapping field names to encrypted field revelation keys, allowing the verifier to decrypt specified fields.
141
+ * @param {BooleanDefaultFalse} [privileged] - Whether this is a privileged request.
142
+ * @param {DescriptionString5to50Bytes} [privilegedReason] - Reason provided for privileged access, required if this is a privileged operation. *
135
143
  * @throws {Error} Throws an error if:
136
144
  * - fieldsToReveal is not an array of strings.
137
145
  * - A field in `fieldsToReveal` does not exist in the certificate.
@@ -144,7 +152,9 @@ export class MasterCertificate extends Certificate {
144
152
  fields: Record<CertificateFieldNameUnder50Bytes, Base64String>,
145
153
  fieldsToReveal: string[],
146
154
  masterKeyring: Record<CertificateFieldNameUnder50Bytes, Base64String>,
147
- serialNumber: Base64String
155
+ serialNumber: Base64String,
156
+ privileged?: boolean,
157
+ privilegedReason?: string
148
158
  ): Promise<Record<CertificateFieldNameUnder50Bytes, string>> {
149
159
  if (!Array.isArray(fieldsToReveal)) {
150
160
  throw new Error('fieldsToReveal must be an array of strings')
@@ -165,7 +175,9 @@ export class MasterCertificate extends Certificate {
165
175
  masterKeyring,
166
176
  fieldName,
167
177
  fields[fieldName],
168
- certifier
178
+ certifier,
179
+ privileged,
180
+ privilegedReason
169
181
  )
170
182
  ).fieldRevelationKey
171
183
 
@@ -178,7 +190,9 @@ export class MasterCertificate extends Certificate {
178
190
  fieldName,
179
191
  serialNumber
180
192
  ),
181
- counterparty: verifier
193
+ counterparty: verifier,
194
+ privileged,
195
+ privilegedReason
182
196
  }
183
197
  )
184
198
 
@@ -220,22 +234,22 @@ export class MasterCertificate extends Certificate {
220
234
  void _serial // Explicitly acknowledge unused parameter
221
235
  return 'Certificate revocation not tracked.'
222
236
  },
223
- serialNumber?: string // ✅ Optional parameter
237
+ serialNumber?: string
224
238
  ): Promise<MasterCertificate> {
225
239
  // 1. Generate a random serialNumber if not provided
226
- const finalSerialNumber = serialNumber ?? Utils.toBase64(Random(32)) // ✅ Explicit nullish check
240
+ const finalSerialNumber = serialNumber ?? Utils.toBase64(Random(32))
227
241
 
228
242
  // 2. Create encrypted certificate fields and associated master keyring
229
243
  const { certificateFields, masterKeyring } =
230
244
  await this.createCertificateFields(certifierWallet, subject, fields)
231
245
 
232
246
  // 3. Obtain a revocation outpoint
233
- const revocationOutpoint = await getRevocationOutpoint(finalSerialNumber) // ✅ Use `finalSerialNumber`
247
+ const revocationOutpoint = await getRevocationOutpoint(finalSerialNumber)
234
248
 
235
249
  // 4. Create new MasterCertificate instance
236
250
  const certificate = new MasterCertificate(
237
251
  certificateType,
238
- finalSerialNumber, // ✅ Use `finalSerialNumber`
252
+ finalSerialNumber,
239
253
  subject,
240
254
  (await certifierWallet.getPublicKey({ identityKey: true })).publicKey,
241
255
  revocationOutpoint,
@@ -261,6 +275,8 @@ export class MasterCertificate extends Certificate {
261
275
  * @param {Record<CertificateFieldNameUnder50Bytes, Base64String>} masterKeyring - A record containing encrypted keys for each field.
262
276
  * @param {Record<CertificateFieldNameUnder50Bytes, Base64String>} fields - A record of encrypted field names and their values.
263
277
  * @param {WalletCounterparty} counterparty - The counterparty responsible for creating or signing the certificate. For self-signed certificates, use 'self'.
278
+ * @param {BooleanDefaultFalse} [privileged] - Whether this is a privileged request.
279
+ * @param {DescriptionString5to50Bytes} [privilegedReason] - Reason provided for privileged access, required if this is a privileged operation.
264
280
  * @returns {Promise<Record<CertificateFieldNameUnder50Bytes, string>>} A promise resolving to a record of field names and their decrypted values in plaintext.
265
281
  *
266
282
  * @throws {Error} Throws an error if the `masterKeyring` is invalid or if decryption fails for any field.
@@ -269,7 +285,9 @@ export class MasterCertificate extends Certificate {
269
285
  subjectOrCertifierWallet: ProtoWallet,
270
286
  masterKeyring: Record<CertificateFieldNameUnder50Bytes, Base64String>,
271
287
  fields: Record<CertificateFieldNameUnder50Bytes, Base64String>,
272
- counterparty: WalletCounterparty
288
+ counterparty: WalletCounterparty,
289
+ privileged?: boolean,
290
+ privilegedReason?: string
273
291
  ): Promise<Record<CertificateFieldNameUnder50Bytes, string>> {
274
292
  if (masterKeyring == null || Object.keys(masterKeyring).length === 0) {
275
293
  throw new Error('A MasterCertificate must have a valid masterKeyring!')
@@ -285,7 +303,9 @@ export class MasterCertificate extends Certificate {
285
303
  masterKeyring,
286
304
  fieldName,
287
305
  fields[fieldName],
288
- counterparty
306
+ counterparty,
307
+ privileged,
308
+ privilegedReason
289
309
  )
290
310
  ).decryptedFieldValue
291
311
  }
@@ -300,7 +320,9 @@ export class MasterCertificate extends Certificate {
300
320
  masterKeyring: Record<CertificateFieldNameUnder50Bytes, Base64String>,
301
321
  fieldName: Base64String,
302
322
  fieldValue: Base64String,
303
- counterparty: WalletCounterparty
323
+ counterparty: WalletCounterparty,
324
+ privileged?: boolean,
325
+ privilegedReason?: string
304
326
  ): Promise<{ fieldRevelationKey: number[], decryptedFieldValue: string }> {
305
327
  if (masterKeyring == null || Object.keys(masterKeyring).length === 0) {
306
328
  throw new Error('A MasterCertificate must have a valid masterKeyring!')
@@ -311,7 +333,9 @@ export class MasterCertificate extends Certificate {
311
333
  {
312
334
  ciphertext: Utils.toArray(masterKeyring[fieldName], 'base64'),
313
335
  ...Certificate.getCertificateFieldEncryptionDetails(fieldName), // Only fieldName used on MasterCertificate
314
- counterparty
336
+ counterparty,
337
+ privileged,
338
+ privilegedReason
315
339
  }
316
340
  )
317
341
 
@@ -54,10 +54,14 @@ export class VerifiableCertificate extends Certificate {
54
54
  * Decrypts selectively revealed certificate fields using the provided keyring and verifier wallet
55
55
  * @param {ProtoWallet} verifierWallet - The wallet instance of the certificate's verifier, used to decrypt field keys.
56
56
  * @returns {Promise<Record<CertificateFieldNameUnder50Bytes, string>>} - A promise that resolves to an object where each key is a field name and each value is the decrypted field value as a string.
57
+ * @param {BooleanDefaultFalse} [privileged] - Whether this is a privileged request.
58
+ * @param {DescriptionString5to50Bytes} [privilegedReason] - Reason provided for privileged access, required if this is a privileged operation.
57
59
  * @throws {Error} Throws an error if any of the decryption operations fail, with a message indicating the failure context.
58
60
  */
59
61
  async decryptFields(
60
- verifierWallet: ProtoWallet
62
+ verifierWallet: ProtoWallet,
63
+ privileged?: boolean,
64
+ privilegedReason?: string
61
65
  ): Promise<Record<CertificateFieldNameUnder50Bytes, string>> {
62
66
  if (this.keyring == null || Object.keys(this.keyring).length === 0) { // ✅ Explicitly check null and empty object
63
67
  throw new Error(
@@ -75,7 +79,9 @@ export class VerifiableCertificate extends Certificate {
75
79
  fieldName,
76
80
  this.serialNumber
77
81
  ),
78
- counterparty: this.subject
82
+ counterparty: this.subject,
83
+ privileged,
84
+ privilegedReason
79
85
  })
80
86
 
81
87
  const fieldValue = new SymmetricKey(fieldRevelationKey).decrypt(
@@ -37,11 +37,7 @@ export type LookupAnswer =
37
37
  /** Default SLAP trackers */
38
38
  export const DEFAULT_SLAP_TRACKERS: string[] = [
39
39
  // Babbage primary overlay service
40
- 'https://overlay.babbage.systems',
41
- // Babbage example overlay
42
- 'https://overlay-example.babbage.systems',
43
- // The Babbage office building
44
- 'https://office.babbage.systems'
40
+ 'https://users.bapp.dev'
45
41
 
46
42
  // NOTE: Other entities may submit pull requests to the library if they maintain SLAP overlay services.
47
43
  // Additional trackers run by different entities contribute to greater network resiliency.
@@ -51,10 +47,23 @@ export const DEFAULT_SLAP_TRACKERS: string[] = [
51
47
  // Trackers known to host invalid or illegal records will be removed at the discretion of the BSV Association.
52
48
  ]
53
49
 
50
+ /** Default testnet SLAP trackers */
51
+ export const DEFAULT_TESTNET_SLAP_TRACKERS: string[] = [
52
+ // Babbage primary testnet overlay service
53
+ 'https://testnet-users.bapp.dev'
54
+ ]
55
+
54
56
  const MAX_TRACKER_WAIT_TIME = 1000
55
57
 
56
58
  /** Configuration options for the Lookup resolver. */
57
59
  export interface LookupResolverConfig {
60
+ /**
61
+ * The network preset to use, unless other options override it.
62
+ * - mainnet: use mainnet SLAP trackers and HTTPS facilitator
63
+ * - testnet: use testnet SLAP trackers and HTTPS facilitator
64
+ * - local: directly query from localhost:8080 and a facilitator that permits plain HTTP
65
+ */
66
+ networkPreset?: 'mainnet' | 'testnet' | 'local'
58
67
  /** The facilitator used to make requests to Overlay Services hosts. */
59
68
  facilitator?: OverlayLookupFacilitator
60
69
  /** The list of SLAP trackers queried to resolve Overlay Services hosts for a given lookup service. */
@@ -83,9 +92,11 @@ export interface OverlayLookupFacilitator {
83
92
 
84
93
  export class HTTPSOverlayLookupFacilitator implements OverlayLookupFacilitator {
85
94
  fetchClient: typeof fetch
95
+ allowHTTP: boolean
86
96
 
87
- constructor (httpClient = fetch) {
97
+ constructor (httpClient = fetch, allowHTTP: boolean = false) {
88
98
  this.fetchClient = httpClient
99
+ this.allowHTTP = allowHTTP
89
100
  }
90
101
 
91
102
  async lookup (
@@ -93,7 +104,7 @@ export class HTTPSOverlayLookupFacilitator implements OverlayLookupFacilitator {
93
104
  question: LookupQuestion,
94
105
  timeout: number = 5000
95
106
  ): Promise<LookupAnswer> {
96
- if (!url.startsWith('https:')) {
107
+ if (!url.startsWith('https:') && !this.allowHTTP) {
97
108
  throw new Error(
98
109
  'HTTPS facilitator can only use URLs that start with "https:"'
99
110
  )
@@ -134,26 +145,14 @@ export default class LookupResolver {
134
145
  private readonly slapTrackers: string[]
135
146
  private readonly hostOverrides: Record<string, string[]>
136
147
  private readonly additionalHosts: Record<string, string[]>
137
-
138
- constructor (config?: LookupResolverConfig) {
139
- const defaultConfig: LookupResolverConfig = {
140
- facilitator: new HTTPSOverlayLookupFacilitator(),
141
- slapTrackers: DEFAULT_SLAP_TRACKERS,
142
- hostOverrides: {},
143
- additionalHosts: {}
144
- }
145
-
146
- const {
147
- facilitator = defaultConfig.facilitator,
148
- slapTrackers = defaultConfig.slapTrackers,
149
- hostOverrides = defaultConfig.hostOverrides,
150
- additionalHosts = defaultConfig.additionalHosts
151
- } = config ?? defaultConfig // ✅ Use a default object directly
152
-
153
- this.facilitator = facilitator ?? new HTTPSOverlayLookupFacilitator()
154
- this.slapTrackers = slapTrackers ?? []
155
- this.hostOverrides = hostOverrides ?? {}
156
- this.additionalHosts = additionalHosts ?? {}
148
+ private readonly networkPreset: 'mainnet' | 'testnet' | 'local'
149
+
150
+ constructor (config: LookupResolverConfig = {}) {
151
+ this.networkPreset = config.networkPreset ?? 'mainnet'
152
+ this.facilitator = config.facilitator ?? new HTTPSOverlayLookupFacilitator(undefined, this.networkPreset === 'local')
153
+ this.slapTrackers = config.slapTrackers ?? (this.networkPreset === 'mainnet' ? DEFAULT_SLAP_TRACKERS : DEFAULT_TESTNET_SLAP_TRACKERS)
154
+ this.hostOverrides = config.hostOverrides ?? {}
155
+ this.additionalHosts = config.additionalHosts ?? {}
157
156
  }
158
157
 
159
158
  /**
@@ -165,9 +164,11 @@ export default class LookupResolver {
165
164
  ): Promise<LookupAnswer> {
166
165
  let competentHosts: string[] = []
167
166
  if (question.service === 'ls_slap') {
168
- competentHosts = this.slapTrackers
167
+ competentHosts = this.networkPreset === 'local' ? ['http://localhost:8080'] : this.slapTrackers
169
168
  } else if (this.hostOverrides[question.service] != null) {
170
169
  competentHosts = this.hostOverrides[question.service]
170
+ } else if (this.networkPreset === 'local') {
171
+ competentHosts = ['http://localhost:8080']
171
172
  } else {
172
173
  competentHosts = await this.findCompetentHosts(question.service)
173
174
  }
@@ -179,7 +180,7 @@ export default class LookupResolver {
179
180
  }
180
181
  if (competentHosts.length < 1) {
181
182
  throw new Error(
182
- `No competent hosts found by the SLAP trackers for lookup service: ${question.service}`
183
+ `No competent ${this.networkPreset} hosts found by the SLAP trackers for lookup service: ${question.service}`
183
184
  )
184
185
  }
185
186
 
@@ -230,7 +231,6 @@ export default class LookupResolver {
230
231
  console.error('Error processing response outputs:', error)
231
232
  }
232
233
  }
233
- // ✅ Ensure function always returns a value
234
234
  return {
235
235
  type: 'output-list',
236
236
  outputs: Array.from(outputs.values())