@bsv/sdk 1.3.33 → 1.3.35
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/cjs/package.json +1 -1
- package/dist/cjs/src/overlay-tools/LookupResolver.js +22 -23
- package/dist/cjs/src/overlay-tools/LookupResolver.js.map +1 -1
- package/dist/cjs/src/overlay-tools/SHIPBroadcaster.js +17 -15
- package/dist/cjs/src/overlay-tools/SHIPBroadcaster.js.map +1 -1
- package/dist/cjs/src/overlay-tools/index.js +8 -2
- package/dist/cjs/src/overlay-tools/index.js.map +1 -1
- package/dist/cjs/src/transaction/Beef.js +2 -0
- package/dist/cjs/src/transaction/Beef.js.map +1 -1
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/esm/src/overlay-tools/LookupResolver.js +22 -22
- package/dist/esm/src/overlay-tools/LookupResolver.js.map +1 -1
- package/dist/esm/src/overlay-tools/SHIPBroadcaster.js +17 -14
- package/dist/esm/src/overlay-tools/SHIPBroadcaster.js.map +1 -1
- package/dist/esm/src/overlay-tools/index.js +4 -0
- package/dist/esm/src/overlay-tools/index.js.map +1 -1
- package/dist/esm/src/transaction/Beef.js +2 -0
- package/dist/esm/src/transaction/Beef.js.map +1 -1
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/dist/types/src/overlay-tools/LookupResolver.d.ts +12 -1
- package/dist/types/src/overlay-tools/LookupResolver.d.ts.map +1 -1
- package/dist/types/src/overlay-tools/SHIPBroadcaster.d.ts +13 -4
- package/dist/types/src/overlay-tools/SHIPBroadcaster.d.ts.map +1 -1
- package/dist/types/src/overlay-tools/index.d.ts +2 -0
- package/dist/types/src/overlay-tools/index.d.ts.map +1 -1
- package/dist/types/src/transaction/Beef.d.ts.map +1 -1
- package/dist/types/tsconfig.types.tsbuildinfo +1 -1
- package/dist/umd/bundle.js +1 -1
- package/docs/overlay-tools.md +58 -14
- package/package.json +1 -1
- package/src/overlay-tools/LookupResolver.ts +30 -30
- package/src/overlay-tools/SHIPBroadcaster.ts +25 -21
- package/src/overlay-tools/__tests/LookupResolver.test.ts +3 -3
- package/src/overlay-tools/__tests/SHIPBroadcaster.test.ts +3 -3
- package/src/overlay-tools/index.ts +5 -0
- package/src/transaction/Beef.ts +2 -0
- package/src/transaction/__tests/Beef.test.ts +22 -3
package/docs/overlay-tools.md
CHANGED
|
@@ -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
|
|
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
|
|
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
|
-
| [
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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:
|
|
459
|
+
### Class: TopicBroadcaster
|
|
434
460
|
|
|
435
|
-
|
|
461
|
+
Broadcasts transactions to one or more overlay topics.
|
|
436
462
|
|
|
437
463
|
```ts
|
|
438
|
-
export default class
|
|
439
|
-
constructor(topics: string[], config
|
|
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
|
|
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://
|
|
539
|
-
|
|
540
|
-
|
|
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
|
@@ -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://
|
|
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
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
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())
|
|
@@ -50,10 +50,17 @@ export type STEAK = Record<string, AdmittanceInstructions>
|
|
|
50
50
|
|
|
51
51
|
/** Configuration options for the SHIP broadcaster. */
|
|
52
52
|
export interface SHIPBroadcasterConfig {
|
|
53
|
+
/**
|
|
54
|
+
* The network preset to use, unless other options override it.
|
|
55
|
+
* - mainnet: use mainnet resolver and HTTPS facilitator
|
|
56
|
+
* - testnet: use testnet resolver and HTTPS facilitator
|
|
57
|
+
* - local: directly send to localhost:8080 and a facilitator that permits plain HTTP
|
|
58
|
+
*/
|
|
59
|
+
networkPreset?: 'mainnet' | 'testnet' | 'local'
|
|
53
60
|
/** The facilitator used to make requests to Overlay Services hosts. */
|
|
54
61
|
facilitator?: OverlayBroadcastFacilitator
|
|
55
62
|
/** The resolver used to locate suitable hosts with SHIP */
|
|
56
|
-
resolver
|
|
63
|
+
resolver?: LookupResolver
|
|
57
64
|
/** 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. */
|
|
58
65
|
requireAcknowledgmentFromAllHostsForTopics?: 'all' | 'any' | string[]
|
|
59
66
|
/** Determines which topics (all, any, or a specific list) must be present within STEAK received from at least one host for the broadcast to be considered a success. */
|
|
@@ -71,13 +78,15 @@ const MAX_SHIP_QUERY_TIMEOUT = 1000
|
|
|
71
78
|
|
|
72
79
|
export class HTTPSOverlayBroadcastFacilitator implements OverlayBroadcastFacilitator {
|
|
73
80
|
httpClient: typeof fetch
|
|
81
|
+
allowHTTP: boolean
|
|
74
82
|
|
|
75
|
-
constructor (httpClient = fetch) {
|
|
83
|
+
constructor (httpClient = fetch, allowHTTP: boolean = false) {
|
|
76
84
|
this.httpClient = httpClient
|
|
85
|
+
this.allowHTTP = false
|
|
77
86
|
}
|
|
78
87
|
|
|
79
88
|
async send (url: string, taggedBEEF: TaggedBEEF): Promise<STEAK> {
|
|
80
|
-
if (!url.startsWith('https:')) {
|
|
89
|
+
if (!url.startsWith('https:') && !this.allowHTTP) {
|
|
81
90
|
throw new Error(
|
|
82
91
|
'HTTPS facilitator can only use URLs that start with "https:"'
|
|
83
92
|
)
|
|
@@ -99,15 +108,16 @@ export class HTTPSOverlayBroadcastFacilitator implements OverlayBroadcastFacilit
|
|
|
99
108
|
}
|
|
100
109
|
|
|
101
110
|
/**
|
|
102
|
-
*
|
|
111
|
+
* Broadcasts transactions to one or more overlay topics.
|
|
103
112
|
*/
|
|
104
|
-
export default class
|
|
113
|
+
export default class TopicBroadcaster implements Broadcaster {
|
|
105
114
|
private readonly topics: string[]
|
|
106
115
|
private readonly facilitator: OverlayBroadcastFacilitator
|
|
107
116
|
private readonly resolver: LookupResolver
|
|
108
117
|
private readonly requireAcknowledgmentFromAllHostsForTopics: | 'all' | 'any' | string[]
|
|
109
118
|
private readonly requireAcknowledgmentFromAnyHostForTopics: | 'all' | 'any' | string[]
|
|
110
119
|
private readonly requireAcknowledgmentFromSpecificHostsForTopics: Record<string, 'all' | 'any' | string[]>
|
|
120
|
+
private readonly networkPreset: 'mainnet' | 'testnet' | 'local'
|
|
111
121
|
|
|
112
122
|
/**
|
|
113
123
|
* Constructs an instance of the SHIP broadcaster.
|
|
@@ -115,7 +125,7 @@ export default class SHIPBroadcaster implements Broadcaster {
|
|
|
115
125
|
* @param {string[]} topics - The list of SHIP topic names where transactions are to be sent.
|
|
116
126
|
* @param {SHIPBroadcasterConfig} config - Configuration options for the SHIP broadcaster.
|
|
117
127
|
*/
|
|
118
|
-
constructor (topics: string[], config
|
|
128
|
+
constructor (topics: string[], config: SHIPBroadcasterConfig = {}) {
|
|
119
129
|
if (topics.length === 0) {
|
|
120
130
|
throw new Error('At least one topic is required for broadcast.')
|
|
121
131
|
}
|
|
@@ -123,21 +133,15 @@ export default class SHIPBroadcaster implements Broadcaster {
|
|
|
123
133
|
throw new Error('Every topic must start with "tm_".')
|
|
124
134
|
}
|
|
125
135
|
this.topics = topics
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
requireAcknowledgmentFromAllHostsForTopics,
|
|
130
|
-
requireAcknowledgmentFromAnyHostForTopics,
|
|
131
|
-
requireAcknowledgmentFromSpecificHostsForTopics
|
|
132
|
-
} = config ?? {}
|
|
133
|
-
this.facilitator = facilitator ?? new HTTPSOverlayBroadcastFacilitator()
|
|
134
|
-
this.resolver = resolver ?? new LookupResolver()
|
|
136
|
+
this.networkPreset = config.networkPreset ?? 'mainnet'
|
|
137
|
+
this.facilitator = config.facilitator ?? new HTTPSOverlayBroadcastFacilitator(undefined, this.networkPreset === 'local')
|
|
138
|
+
this.resolver = config.resolver ?? new LookupResolver({ networkPreset: this.networkPreset })
|
|
135
139
|
this.requireAcknowledgmentFromAllHostsForTopics =
|
|
136
|
-
requireAcknowledgmentFromAllHostsForTopics ?? []
|
|
140
|
+
config.requireAcknowledgmentFromAllHostsForTopics ?? []
|
|
137
141
|
this.requireAcknowledgmentFromAnyHostForTopics =
|
|
138
|
-
requireAcknowledgmentFromAnyHostForTopics ?? 'all'
|
|
142
|
+
config.requireAcknowledgmentFromAnyHostForTopics ?? 'all'
|
|
139
143
|
this.requireAcknowledgmentFromSpecificHostsForTopics =
|
|
140
|
-
requireAcknowledgmentFromSpecificHostsForTopics ?? {}
|
|
144
|
+
config.requireAcknowledgmentFromSpecificHostsForTopics ?? {}
|
|
141
145
|
}
|
|
142
146
|
|
|
143
147
|
/**
|
|
@@ -157,12 +161,12 @@ export default class SHIPBroadcaster implements Broadcaster {
|
|
|
157
161
|
'Transactions sent via SHIP to Overlay Services must be serializable to BEEF format.'
|
|
158
162
|
)
|
|
159
163
|
}
|
|
160
|
-
const interestedHosts = await this.findInterestedHosts()
|
|
164
|
+
const interestedHosts = this.networkPreset === 'local' ? ['http://localhost:8080'] : await this.findInterestedHosts()
|
|
161
165
|
if (Object.keys(interestedHosts).length === 0) {
|
|
162
166
|
return {
|
|
163
167
|
status: 'error',
|
|
164
168
|
code: 'ERR_NO_HOSTS_INTERESTED',
|
|
165
|
-
description:
|
|
169
|
+
description: `No ${this.networkPreset} hosts are interested in receiving this transaction.`
|
|
166
170
|
}
|
|
167
171
|
}
|
|
168
172
|
const hostPromises = Object.entries(interestedHosts).map(
|
|
@@ -190,7 +194,7 @@ export default class SHIPBroadcaster implements Broadcaster {
|
|
|
190
194
|
return {
|
|
191
195
|
status: 'error',
|
|
192
196
|
code: 'ERR_ALL_HOSTS_REJECTED',
|
|
193
|
-
description:
|
|
197
|
+
description: `All ${this.networkPreset} topical hosts have rejected the transaction.`
|
|
194
198
|
}
|
|
195
199
|
}
|
|
196
200
|
|
|
@@ -861,7 +861,7 @@ describe('LookupResolver', () => {
|
|
|
861
861
|
query: { test: 1 }
|
|
862
862
|
})
|
|
863
863
|
).rejects.toThrow(
|
|
864
|
-
'No competent hosts found by the SLAP trackers for lookup service: ls_foo'
|
|
864
|
+
'No competent mainnet hosts found by the SLAP trackers for lookup service: ls_foo'
|
|
865
865
|
)
|
|
866
866
|
|
|
867
867
|
expect(mockFacilitator.lookup.mock.calls).toEqual([
|
|
@@ -1054,7 +1054,7 @@ describe('LookupResolver', () => {
|
|
|
1054
1054
|
query: { test: 1 }
|
|
1055
1055
|
})
|
|
1056
1056
|
).rejects.toThrow(
|
|
1057
|
-
'No competent hosts found by the SLAP trackers for lookup service: ls_foo'
|
|
1057
|
+
'No competent mainnet hosts found by the SLAP trackers for lookup service: ls_foo'
|
|
1058
1058
|
)
|
|
1059
1059
|
|
|
1060
1060
|
expect(mockFacilitator.lookup.mock.calls).toEqual([
|
|
@@ -1628,7 +1628,7 @@ describe('LookupResolver', () => {
|
|
|
1628
1628
|
query: { test: 1 }
|
|
1629
1629
|
})
|
|
1630
1630
|
).rejects.toThrow(
|
|
1631
|
-
'No competent hosts found by the SLAP trackers for lookup service: ls_foo'
|
|
1631
|
+
'No competent mainnet hosts found by the SLAP trackers for lookup service: ls_foo'
|
|
1632
1632
|
)
|
|
1633
1633
|
|
|
1634
1634
|
expect(mockFacilitator.lookup.mock.calls.length).toBe(2)
|
|
@@ -279,7 +279,7 @@ describe('SHIPCast', () => {
|
|
|
279
279
|
expect(result).toEqual({
|
|
280
280
|
status: 'error',
|
|
281
281
|
code: 'ERR_NO_HOSTS_INTERESTED',
|
|
282
|
-
description: 'No hosts are interested in receiving this transaction.'
|
|
282
|
+
description: 'No mainnet hosts are interested in receiving this transaction.'
|
|
283
283
|
})
|
|
284
284
|
|
|
285
285
|
expect(mockResolver.query).toHaveBeenCalledWith(
|
|
@@ -343,7 +343,7 @@ describe('SHIPCast', () => {
|
|
|
343
343
|
expect(result).toEqual({
|
|
344
344
|
status: 'error',
|
|
345
345
|
code: 'ERR_ALL_HOSTS_REJECTED',
|
|
346
|
-
description: 'All
|
|
346
|
+
description: 'All mainnet topical hosts have rejected the transaction.'
|
|
347
347
|
})
|
|
348
348
|
|
|
349
349
|
expect(mockFacilitator.send).toHaveBeenCalled()
|
|
@@ -1081,7 +1081,7 @@ describe('SHIPCast', () => {
|
|
|
1081
1081
|
expect(response).toEqual({
|
|
1082
1082
|
status: 'error',
|
|
1083
1083
|
code: 'ERR_ALL_HOSTS_REJECTED',
|
|
1084
|
-
description: 'All
|
|
1084
|
+
description: 'All mainnet topical hosts have rejected the transaction.'
|
|
1085
1085
|
})
|
|
1086
1086
|
})
|
|
1087
1087
|
describe('SHIPCast private methods', () => {
|
|
@@ -2,4 +2,9 @@ export * from './LookupResolver.js'
|
|
|
2
2
|
export * from './SHIPBroadcaster.js'
|
|
3
3
|
export { default as OverlayAdminTokenTemplate } from './OverlayAdminTokenTemplate.js'
|
|
4
4
|
export { default as LookupResolver } from './LookupResolver.js'
|
|
5
|
+
|
|
6
|
+
// For intuitive clarity, we name this the Topic Broadcaster.
|
|
7
|
+
export { default as TopicBroadcaster } from './SHIPBroadcaster.js'
|
|
8
|
+
// Historically, it was also known by two other names:
|
|
5
9
|
export { default as SHIPBroadcaster } from './SHIPBroadcaster.js'
|
|
10
|
+
export { default as SHIPCast } from './SHIPBroadcaster.js'
|
package/src/transaction/Beef.ts
CHANGED
|
@@ -485,6 +485,8 @@ export class Beef {
|
|
|
485
485
|
* @returns A binary array representing the BEEF
|
|
486
486
|
*/
|
|
487
487
|
toBinary (): number[] {
|
|
488
|
+
// Always serialize in dependency sorted order.
|
|
489
|
+
this.sortTxs()
|
|
488
490
|
const writer = new Writer()
|
|
489
491
|
this.toWriter(writer)
|
|
490
492
|
return writer.toArray()
|
|
@@ -56,9 +56,7 @@ describe('Beef tests', () => {
|
|
|
56
56
|
beef.txs[0]._txid = undefined
|
|
57
57
|
|
|
58
58
|
expect(() => beef.txs[0].txid).toThrow('Internal')
|
|
59
|
-
expect(() => beef.toBinary()).toThrow(
|
|
60
|
-
'a valid serialized Transaction is expected'
|
|
61
|
-
)
|
|
59
|
+
expect(() => beef.toBinary()).toThrow('Internal')
|
|
62
60
|
|
|
63
61
|
beef.txs[0] = btx // Restore the original transaction
|
|
64
62
|
|
|
@@ -432,6 +430,25 @@ describe('Beef tests', () => {
|
|
|
432
430
|
expect(valid).toBe(false)
|
|
433
431
|
})
|
|
434
432
|
|
|
433
|
+
test('12_bumpIndexEncoding', async () => {
|
|
434
|
+
const b = Beef.fromString(bumpIndexEncoding)
|
|
435
|
+
// These are in the incorrect order!
|
|
436
|
+
expect(b.txs[1].txid).toBe('147050ccef091ca3d7a36661ca0928aa93a3a9a6dfe565977c2f56179d7a6159')
|
|
437
|
+
expect(b.txs[0].txid).toBe('0e579e9741f522e15536874090d20da7572a7e1ddd4bf42740f40e17c3605604')
|
|
438
|
+
const valid = b.isValid()
|
|
439
|
+
expect(valid).toBe(true)
|
|
440
|
+
expect(b.version).toBe(BEEF_V1)
|
|
441
|
+
const bytes = b.toBinary()
|
|
442
|
+
{
|
|
443
|
+
const b = Beef.fromBinary(bytes)
|
|
444
|
+
// These are now in the correct order!
|
|
445
|
+
expect(b.txs[0].txid).toBe('147050ccef091ca3d7a36661ca0928aa93a3a9a6dfe565977c2f56179d7a6159')
|
|
446
|
+
expect(b.txs[1].txid).toBe('0e579e9741f522e15536874090d20da7572a7e1ddd4bf42740f40e17c3605604')
|
|
447
|
+
const valid = b.isValid()
|
|
448
|
+
expect(valid).toBe(true)
|
|
449
|
+
expect(b.version).toBe(BEEF_V1)
|
|
450
|
+
}
|
|
451
|
+
})
|
|
435
452
|
})
|
|
436
453
|
|
|
437
454
|
const b58Beef10 =
|
|
@@ -479,3 +496,5 @@ const log2 = `BEEF with 1 BUMPS and 2 Transactions, isValid true
|
|
|
479
496
|
`
|
|
480
497
|
|
|
481
498
|
const wrongBumpTxid = '0100beef01fe4e6d0c001002fd909002088a382ec07a8cf47c6158b68e5822852362102d8571482d1257e0b7527e1882fd91900065cb01218f2506bb51155d243e4d6b32d69d1b5f2221c52e26963cfd8cf7283201fd4948008d7a44ae384797b0ae84db0c857e8c1083425d64d09ef8bc5e2e9d270677260501fd25240060f38aa33631c8d70adbac1213e7a5b418c90414e919e3a12ced63dd152fd85a01fd1312005ff132ee64a7a0c79150a29f66ef861e552d3a05b47d6303f5d8a2b2a09bc61501fd080900cc0baf21cf06b9439dfe05dce9bdb14ddc2ca2d560b1138296ef5769851a84b301fd85040063ccb26232a6e1d3becdb47a0f19a67a562b754e8894155b3ae7bba10335ce5101fd430200e153fc455a0f2c8372885c11af70af904dcf44740b9ebf3b3e5b2234cce550bc01fd20010077d5ea69d1dcc379dde65d6adcebde1838190118a8fae928c037275e78bd87910191000263e4f31684a25169857f2788aeef603504931f92585f02c4c9e023b2aa43d1014900de72292e0b3e5eeacfa2b657bf4d46c885559b081ee78632a99b318c1148d85c01250068a5f831ca99b9e7f3720920d6ea977fd2ab52b83d1a6567dafa4c8cafd941ed0113006a0b91d83f9056b702d6a8056af6365c7da626fc3818b815dd4b0de22d05450f0108009876ce56b68545a75859e93d200bdde7880d46f39384818b259ed847a9664ddf010500990bc5e95cacbc927b5786ec39a183f983fe160d52829cf47521c7eb369771c30103004fe794e50305f590b6010a51d050bf47dfeaabfdb949c5ee0673f577a59537d70100004dad44a358aea4d8bc1917912539901f5ae44e07a4748e1a9d3018814b0759d00201000000027b0a1b12c7c9e48015e78d3a08a4d62e439387df7e0d7a810ebd4af37661daaa000000006a47304402207d972759afba7c0ffa6cfbbf39a31c2aeede1dae28d8841db56c6dd1197d56a20220076a390948c235ba8e72b8e43a7b4d4119f1a81a77032aa6e7b7a51be5e13845412103f78ec31cf94ca8d75fb1333ad9fc884e2d489422034a1efc9d66a3b72eddca0fffffffff7f36874f858fb43ffcf4f9e3047825619bad0e92d4b9ad4ba5111d1101cbddfe010000006a473044022043f048043d56eb6f75024808b78f18808b7ab45609e4c4c319e3a27f8246fc3002204b67766b62f58bf6f30ea608eaba76b8524ed49f67a90f80ac08a9b96a6922cd41210254a583c1c51a06e10fab79ddf922915da5f5c1791ef87739f40cb68638397248ffffffff03e8030000000000001976a914b08f70bc5010fb026de018f19e7792385a146b4a88acf3010000000000001976a9147d48635f889372c3da12d75ce246c59f4ab907ed88acf7000000000000001976a914b8fbd58685b6920d8f9a8f1b274d8696708b51b088ac00000000010001000000018ae36502fdc82837319362c488fb9cb978e064daf600bbfc48389663fc5c160c000000006a47304402204a04841f6f626d30e21200e1c404ea80e319b643fe86f08e709413a89a493a4b022038a2e3e25a813d8d540c1a572fa8ec5fa2d2434bcea78d17902dcccddcc1c9484121028fd1afeee81361e801800afb264e35cdce3037ec6f7dc4f1d1eaba7ad519c948ffffffff01c8000000000000001976a9148ce2d21f9a75e98600be76b25b91c4fef6b40bcd88ac0000000000'
|
|
499
|
+
|
|
500
|
+
const bumpIndexEncoding = '0100beef01fe6e621900010200008cdbd6fe227cfafa6be4500cae6140c84b2ead61318063e92bdb6974f869cf33010259617a9d17562f7c9765e5dfa6a9a393aa2809ca6166a3d7a31c09efcc50701402010000000159617a9d17562f7c9765e5dfa6a9a393aa2809ca6166a3d7a31c09efcc507014130000006b4830450221009399820c643e5f2699b07ffa3289b22c6124e1317fd1ec41fb2431047dcf552f02201b7ee3ee3422fe1c33d8869a34a28fadddb9b790b3c5b332b7fafaaa8d4b413c4121029b15053bc379e2378cd6a84fb40b761b4e400faa4efd09280443731d4b3f8a8cffffffff0201000000000000001976a91423f2562a8092ed24eddc77c74387b44c561692a188ac03000000000000001976a9144ed83e2b3aae481f7fa48321024eb3d8e1f7417888ac00000000000100000001ee353cb1f4cb2b19bf7d2328f3c0a5fa2bd1aa94d0795934dd1d63756583b0ac000000006b4830450221009e779c3f04bb056da180b50ad3972b6fd552c52bd6337f572f08ca656625a4530220648e1fc5872d9bc3846f78edd79b4dc406dfecbab359e46b53c7d478747141684121022280e60c665907fb88a97f5e74dd4e1db0eba60a4dad18158ea8eb9495e242daffffffff2005000000000000001976a914e073bf1bf7b6160f7f68403a374717fdc4cce86d88ac4a000000000000001976a9145bbe83249067ec745d8e270c121c651f56ec2cf188ac42030000000000001976a914983a29113517769da9eace0ec25b760ad09c5f5988ac05000000000000001976a91402c75f3ec99db76e6cd2658a7c83c8bf21a0d14b88ac05000000000000001976a914de454fbce4e1be341d11cd5545664771f72d184088ac25000000000000001976a914b5c2a6831b5cdbc8985517f5d912064449ad118088ac3d010000000000001976a914e4566d91c063f99f7418f12d670b5da320160c8188ac05000000000000001976a914616dc74c3945895eafdac8da9174f95b4d91d75b88ac03010000000000001976a91476ae1c3f2c01a9a5f2aa7696cc9b89ea55b0d01688ac0d000000000000001976a9146d805d21013cc20351e5cd55ecaa7dcee59f2fde88ac05000000000000001976a914613408f68bdde1ff3f77a96abd4956a472766acf88ac21000000000000001976a914d7f0bcfa5b5cad93574a960627db60af8dac277c88ac05000000000000001976a9147e088fe21413442569fa59b6a5bf7e8fe6db71e388ac05000000000000001976a914e5ff336cbffc4ffef544ff4d131de68bf9b0aa1488ac05000000000000001976a9142145b563cd2766ba08d33ca0ecb5a6679268dfb788ac05000000000000001976a914da990487dff4910c8891cebcd00a569011f4f05188ac05000000000000001976a914100daf8fa5add521fb87b46ff51657728626c5fe88ac07000000000000001976a914de900668ddecd73f498c8560b8770231bef9616b88ac05000000000000001976a914dd08ccc14ebdcc534bb2320e7d3dba624a7ecd5388ac05000000000000001976a9141c5b5915e67a840fdcefd0db0ca1a1dfaaf4f3cf88ac06000000000000001976a91441815c6352756937fe6b2b17586dd6b39560321188ac05000000000000001976a91471dca8f8631f145ad5721f8387a764ae0ef2599888ac1d000000000000001976a9147e2621372c66ca3c6e6fca8cdb7eac42405d37fe88ac05000000000000001976a914d745ec07218bde8d179d49e4a6feca7f744f57e388ac05000000000000001976a91499456246822c4270ae73d6c7d8e1af690d1d31dd88ac05000000000000001976a914176dc7f479059d28593021e63bcb66bae6c2cc5388ac05000000000000001976a914a48809ce3c763a0a34c24ab2646fdf10cffdbc6588ac05000000000000001976a914e314da9f12f6bd888da53faa616890a2dce9eeb488ac05000000000000001976a91418f9185bb0ca144d934bd4845b3968d545e7ec8188ac17010000000000001976a9149db831932668077f8eebf597976ec61fc6ab90d588ac09000000000000001976a91479b349601390a6216994d44ca618db71e6e811ef88ac06000000000000001976a91451d25ac626a4b7c281b4200a3dcf34caae43f0df88ac000000000100'
|