@bsv/sdk 1.2.2 → 1.2.4
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/auth/Certificate.js +1 -1
- package/dist/cjs/src/auth/Certificate.js.map +1 -1
- package/dist/cjs/src/overlay-tools/LookupResolver.js +8 -5
- package/dist/cjs/src/overlay-tools/LookupResolver.js.map +1 -1
- package/dist/cjs/src/overlay-tools/OverlayAdminTokenTemplate.js.map +1 -1
- package/dist/cjs/src/overlay-tools/SHIPBroadcaster.js +2 -1
- package/dist/cjs/src/overlay-tools/SHIPBroadcaster.js.map +1 -1
- package/dist/cjs/src/transaction/Beef.js +19 -10
- package/dist/cjs/src/transaction/Beef.js.map +1 -1
- package/dist/cjs/src/transaction/Transaction.js +38 -6
- package/dist/cjs/src/transaction/Transaction.js.map +1 -1
- package/dist/cjs/src/wallet/CachedKeyDeriver.js.map +1 -1
- package/dist/cjs/src/wallet/KeyDeriver.js.map +1 -1
- package/dist/cjs/src/wallet/ProtoWallet.js.map +1 -1
- package/dist/cjs/src/wallet/WalletClient.js.map +1 -1
- package/dist/cjs/src/wallet/WalletError.js.map +1 -1
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/esm/src/auth/Certificate.js +1 -1
- package/dist/esm/src/auth/Certificate.js.map +1 -1
- package/dist/esm/src/overlay-tools/LookupResolver.js +8 -5
- package/dist/esm/src/overlay-tools/LookupResolver.js.map +1 -1
- package/dist/esm/src/overlay-tools/OverlayAdminTokenTemplate.js.map +1 -1
- package/dist/esm/src/overlay-tools/SHIPBroadcaster.js +2 -1
- package/dist/esm/src/overlay-tools/SHIPBroadcaster.js.map +1 -1
- package/dist/esm/src/transaction/Beef.js +19 -10
- package/dist/esm/src/transaction/Beef.js.map +1 -1
- package/dist/esm/src/transaction/Transaction.js +38 -6
- package/dist/esm/src/transaction/Transaction.js.map +1 -1
- package/dist/esm/src/wallet/CachedKeyDeriver.js.map +1 -1
- package/dist/esm/src/wallet/KeyDeriver.js.map +1 -1
- package/dist/esm/src/wallet/ProtoWallet.js.map +1 -1
- package/dist/esm/src/wallet/WalletClient.js.map +1 -1
- package/dist/esm/src/wallet/WalletError.js.map +1 -1
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/dist/types/src/auth/Certificate.d.ts.map +1 -1
- package/dist/types/src/overlay-tools/LookupResolver.d.ts +10 -3
- package/dist/types/src/overlay-tools/LookupResolver.d.ts.map +1 -1
- package/dist/types/src/overlay-tools/OverlayAdminTokenTemplate.d.ts.map +1 -1
- package/dist/types/src/overlay-tools/SHIPBroadcaster.d.ts.map +1 -1
- package/dist/types/src/transaction/Beef.d.ts.map +1 -1
- package/dist/types/src/transaction/Transaction.d.ts.map +1 -1
- package/dist/types/src/wallet/CachedKeyDeriver.d.ts.map +1 -1
- package/dist/types/src/wallet/KeyDeriver.d.ts.map +1 -1
- package/dist/types/src/wallet/ProtoWallet.d.ts.map +1 -1
- package/dist/types/src/wallet/Wallet.interfaces.d.ts +11 -11
- package/dist/types/src/wallet/Wallet.interfaces.d.ts.map +1 -1
- package/dist/types/src/wallet/WalletClient.d.ts.map +1 -1
- package/dist/types/src/wallet/WalletError.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 +19 -4
- package/package.json +1 -1
- package/src/auth/Certificate.ts +9 -9
- package/src/auth/index.ts +1 -1
- package/src/overlay-tools/LookupResolver.ts +25 -9
- package/src/overlay-tools/OverlayAdminTokenTemplate.ts +4 -4
- package/src/overlay-tools/SHIPBroadcaster.ts +11 -9
- package/src/overlay-tools/__tests/LookupResolver.test.ts +83 -42
- package/src/overlay-tools/__tests/SHIPBroadcaster.test.ts +5 -5
- package/src/overlay-tools/index.ts +1 -1
- package/src/transaction/Beef.ts +33 -48
- package/src/transaction/BeefParty.ts +4 -4
- package/src/transaction/BeefTx.ts +1 -1
- package/src/transaction/Transaction.ts +38 -10
- package/src/transaction/__tests/Transaction.test.ts +133 -4
- package/src/wallet/CachedKeyDeriver.ts +10 -10
- package/src/wallet/KeyDeriver.ts +8 -8
- package/src/wallet/ProtoWallet.ts +176 -176
- package/src/wallet/Wallet.interfaces.ts +19 -19
- package/src/wallet/WalletClient.ts +30 -30
- package/src/wallet/WalletError.ts +2 -2
package/docs/overlay-tools.md
CHANGED
|
@@ -169,12 +169,27 @@ Facilitates lookups to URLs that return answers.
|
|
|
169
169
|
|
|
170
170
|
```ts
|
|
171
171
|
export interface OverlayLookupFacilitator {
|
|
172
|
-
lookup: (url: string, question: LookupQuestion) => Promise<LookupAnswer>;
|
|
172
|
+
lookup: (url: string, question: LookupQuestion, timeout?: number) => Promise<LookupAnswer>;
|
|
173
173
|
}
|
|
174
174
|
```
|
|
175
175
|
|
|
176
176
|
See also: [LookupAnswer](#type-lookupanswer), [LookupQuestion](#interface-lookupquestion)
|
|
177
177
|
|
|
178
|
+
<details>
|
|
179
|
+
|
|
180
|
+
<summary>Interface OverlayLookupFacilitator Details</summary>
|
|
181
|
+
|
|
182
|
+
#### Property lookup
|
|
183
|
+
|
|
184
|
+
Returns a lookup answer for a lookup question
|
|
185
|
+
|
|
186
|
+
```ts
|
|
187
|
+
lookup: (url: string, question: LookupQuestion, timeout?: number) => Promise<LookupAnswer>
|
|
188
|
+
```
|
|
189
|
+
See also: [LookupAnswer](#type-lookupanswer), [LookupQuestion](#interface-lookupquestion)
|
|
190
|
+
|
|
191
|
+
</details>
|
|
192
|
+
|
|
178
193
|
Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](#functions), [Types](#types), [Variables](#variables)
|
|
179
194
|
|
|
180
195
|
---
|
|
@@ -294,7 +309,7 @@ Links: [API](#api), [Interfaces](#interfaces), [Classes](#classes), [Functions](
|
|
|
294
309
|
export class HTTPSOverlayLookupFacilitator implements OverlayLookupFacilitator {
|
|
295
310
|
fetchClient: typeof fetch;
|
|
296
311
|
constructor(httpClient = fetch)
|
|
297
|
-
async lookup(url: string, question: LookupQuestion): Promise<LookupAnswer>
|
|
312
|
+
async lookup(url: string, question: LookupQuestion, timeout: number = 5000): Promise<LookupAnswer>
|
|
298
313
|
}
|
|
299
314
|
```
|
|
300
315
|
|
|
@@ -310,7 +325,7 @@ Represents an SHIP transaction broadcaster.
|
|
|
310
325
|
```ts
|
|
311
326
|
export default class LookupResolver {
|
|
312
327
|
constructor(config?: LookupResolverConfig)
|
|
313
|
-
async query(question: LookupQuestion): Promise<LookupAnswer>
|
|
328
|
+
async query(question: LookupQuestion, timeout?: number): Promise<LookupAnswer>
|
|
314
329
|
}
|
|
315
330
|
```
|
|
316
331
|
|
|
@@ -325,7 +340,7 @@ See also: [LookupAnswer](#type-lookupanswer), [LookupQuestion](#interface-lookup
|
|
|
325
340
|
Given a LookupQuestion, returns a LookupAnswer. Aggregates across multiple services and supports resiliency.
|
|
326
341
|
|
|
327
342
|
```ts
|
|
328
|
-
async query(question: LookupQuestion): Promise<LookupAnswer>
|
|
343
|
+
async query(question: LookupQuestion, timeout?: number): Promise<LookupAnswer>
|
|
329
344
|
```
|
|
330
345
|
See also: [LookupAnswer](#type-lookupanswer), [LookupQuestion](#interface-lookupquestion)
|
|
331
346
|
|
package/package.json
CHANGED
package/src/auth/Certificate.ts
CHANGED
|
@@ -54,14 +54,14 @@ export default class Certificate {
|
|
|
54
54
|
* @param {Record<CertificateFieldNameUnder50Bytes, string>} fields - All the fields present in the certificate.
|
|
55
55
|
* @param {HexString} signature - Certificate signature by the certifier's private key, DER encoded hex string.
|
|
56
56
|
*/
|
|
57
|
-
constructor(
|
|
57
|
+
constructor (
|
|
58
58
|
type: Base64String,
|
|
59
59
|
serialNumber: Base64String,
|
|
60
60
|
subject: PubKeyHex,
|
|
61
61
|
certifier: PubKeyHex,
|
|
62
62
|
revocationOutpoint: OutpointString,
|
|
63
63
|
fields: Record<CertificateFieldNameUnder50Bytes, string>,
|
|
64
|
-
signature?: HexString
|
|
64
|
+
signature?: HexString
|
|
65
65
|
) {
|
|
66
66
|
this.type = type
|
|
67
67
|
this.serialNumber = serialNumber
|
|
@@ -78,7 +78,7 @@ export default class Certificate {
|
|
|
78
78
|
* @param {boolean} [includeSignature=true] - Whether to include the signature in the serialization.
|
|
79
79
|
* @returns {number[]} - The serialized certificate in binary format.
|
|
80
80
|
*/
|
|
81
|
-
toBin(includeSignature: boolean = true): number[] {
|
|
81
|
+
toBin (includeSignature: boolean = true): number[] {
|
|
82
82
|
const writer = new Utils.Writer()
|
|
83
83
|
|
|
84
84
|
// Write type (Base64String, 32 bytes)
|
|
@@ -134,7 +134,7 @@ export default class Certificate {
|
|
|
134
134
|
* @param {number[]} bin - The binary data representing the certificate.
|
|
135
135
|
* @returns {Certificate} - The deserialized Certificate object.
|
|
136
136
|
*/
|
|
137
|
-
static fromBin(bin: number[]): Certificate {
|
|
137
|
+
static fromBin (bin: number[]): Certificate {
|
|
138
138
|
const reader = new Utils.Reader(bin)
|
|
139
139
|
|
|
140
140
|
// Read type
|
|
@@ -166,7 +166,7 @@ export default class Certificate {
|
|
|
166
166
|
// Field name
|
|
167
167
|
const fieldNameLength = reader.readVarIntNum()
|
|
168
168
|
const fieldNameBytes = reader.read(fieldNameLength)
|
|
169
|
-
const fieldName = Utils.toUTF8(fieldNameBytes)
|
|
169
|
+
const fieldName = Utils.toUTF8(fieldNameBytes)
|
|
170
170
|
|
|
171
171
|
// Field value
|
|
172
172
|
const fieldValueLength = reader.readVarIntNum()
|
|
@@ -177,7 +177,7 @@ export default class Certificate {
|
|
|
177
177
|
}
|
|
178
178
|
|
|
179
179
|
// Read signature if present
|
|
180
|
-
let signature: string | undefined
|
|
180
|
+
let signature: string | undefined
|
|
181
181
|
if (!reader.eof()) {
|
|
182
182
|
const signatureLength = reader.readVarIntNum()
|
|
183
183
|
const signatureBytes = reader.read(signatureLength)
|
|
@@ -200,7 +200,7 @@ export default class Certificate {
|
|
|
200
200
|
*
|
|
201
201
|
* @returns {Promise<boolean>} - A promise that resolves to true if the signature is valid.
|
|
202
202
|
*/
|
|
203
|
-
async verify(): Promise<boolean> {
|
|
203
|
+
async verify (): Promise<boolean> {
|
|
204
204
|
// A verifier can be any wallet capable of verifying signatures
|
|
205
205
|
const verifier = new ProtoWallet('anyone')
|
|
206
206
|
const verificationData = this.toBin(false) // Exclude the signature from the verification data
|
|
@@ -221,7 +221,7 @@ export default class Certificate {
|
|
|
221
221
|
* @param {Wallet} certifier - The wallet representing the certifier.
|
|
222
222
|
* @returns {Promise<void>}
|
|
223
223
|
*/
|
|
224
|
-
async sign(certifier: Wallet): Promise<void> {
|
|
224
|
+
async sign (certifier: Wallet): Promise<void> {
|
|
225
225
|
const preimage = this.toBin(false) // Exclude the signature when signing
|
|
226
226
|
const { signature } = await certifier.createSignature({
|
|
227
227
|
data: preimage,
|
|
@@ -230,4 +230,4 @@ export default class Certificate {
|
|
|
230
230
|
})
|
|
231
231
|
this.signature = Utils.toHex(signature)
|
|
232
232
|
}
|
|
233
|
-
}
|
|
233
|
+
}
|
package/src/auth/index.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { default as Certificate } from './Certificate.js'
|
|
1
|
+
export { default as Certificate } from './Certificate.js'
|
|
@@ -49,6 +49,8 @@ export const DEFAULT_SLAP_TRACKERS: string[] = [
|
|
|
49
49
|
// Trackers known to host invalid or illegal records will be removed at the discretion of the BSV Association.
|
|
50
50
|
]
|
|
51
51
|
|
|
52
|
+
const MAX_TRACKER_WAIT_TIME = 1000
|
|
53
|
+
|
|
52
54
|
/** Configuration options for the Lookup resolver. */
|
|
53
55
|
export interface LookupResolverConfig {
|
|
54
56
|
/** The facilitator used to make requests to Overlay Services hosts. */
|
|
@@ -63,27 +65,41 @@ export interface LookupResolverConfig {
|
|
|
63
65
|
|
|
64
66
|
/** Facilitates lookups to URLs that return answers. */
|
|
65
67
|
export interface OverlayLookupFacilitator {
|
|
66
|
-
|
|
68
|
+
/**
|
|
69
|
+
* Returns a lookup answer for a lookup question
|
|
70
|
+
* @param url - Overlay Service URL to send the lookup question to.
|
|
71
|
+
* @param question - Lookup question to find an answer to.
|
|
72
|
+
* @param timeout - Specifics how long to wait for a lookup answer in milliseconds.
|
|
73
|
+
* @returns
|
|
74
|
+
*/
|
|
75
|
+
lookup: (url: string, question: LookupQuestion, timeout?: number) => Promise<LookupAnswer>
|
|
67
76
|
}
|
|
68
77
|
|
|
69
78
|
export class HTTPSOverlayLookupFacilitator implements OverlayLookupFacilitator {
|
|
70
79
|
fetchClient: typeof fetch
|
|
71
80
|
|
|
72
|
-
constructor(httpClient = fetch) {
|
|
81
|
+
constructor (httpClient = fetch) {
|
|
73
82
|
this.fetchClient = httpClient
|
|
74
83
|
}
|
|
75
84
|
|
|
76
|
-
async lookup(url: string, question: LookupQuestion): Promise<LookupAnswer> {
|
|
85
|
+
async lookup (url: string, question: LookupQuestion, timeout: number = 5000): Promise<LookupAnswer> {
|
|
77
86
|
if (!url.startsWith('https:')) {
|
|
78
87
|
throw new Error('HTTPS facilitator can only use URLs that start with "https:"')
|
|
79
88
|
}
|
|
80
|
-
const
|
|
89
|
+
const timeoutPromise = new Promise((_, reject) =>
|
|
90
|
+
setTimeout(() => reject(new Error('Request timed out')), timeout)
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
const fetchPromise = fetch(`${url}/lookup`, {
|
|
81
94
|
method: 'POST',
|
|
82
95
|
headers: {
|
|
83
96
|
'Content-Type': 'application/json'
|
|
84
97
|
},
|
|
85
98
|
body: JSON.stringify({ service: question.service, query: question.query })
|
|
86
99
|
})
|
|
100
|
+
|
|
101
|
+
const response: Response = await Promise.race([fetchPromise, timeoutPromise]) as Response
|
|
102
|
+
|
|
87
103
|
if (response.ok) {
|
|
88
104
|
return await response.json()
|
|
89
105
|
} else {
|
|
@@ -101,7 +117,7 @@ export default class LookupResolver {
|
|
|
101
117
|
private readonly hostOverrides: Record<string, string[]>
|
|
102
118
|
private readonly additionalHosts: Record<string, string[]>
|
|
103
119
|
|
|
104
|
-
constructor(config?: LookupResolverConfig) {
|
|
120
|
+
constructor (config?: LookupResolverConfig) {
|
|
105
121
|
const { facilitator, slapTrackers, hostOverrides, additionalHosts } = config ?? {} as LookupResolverConfig
|
|
106
122
|
this.facilitator = facilitator ?? new HTTPSOverlayLookupFacilitator()
|
|
107
123
|
this.slapTrackers = slapTrackers ?? DEFAULT_SLAP_TRACKERS
|
|
@@ -112,7 +128,7 @@ export default class LookupResolver {
|
|
|
112
128
|
/**
|
|
113
129
|
* Given a LookupQuestion, returns a LookupAnswer. Aggregates across multiple services and supports resiliency.
|
|
114
130
|
*/
|
|
115
|
-
async query(question: LookupQuestion): Promise<LookupAnswer> {
|
|
131
|
+
async query (question: LookupQuestion, timeout?: number): Promise<LookupAnswer> {
|
|
116
132
|
let competentHosts: string[] = []
|
|
117
133
|
if (question.service === 'ls_slap') {
|
|
118
134
|
competentHosts = this.slapTrackers
|
|
@@ -133,7 +149,7 @@ export default class LookupResolver {
|
|
|
133
149
|
|
|
134
150
|
// Use Promise.allSettled to handle individual host failures
|
|
135
151
|
const hostResponses = await Promise.allSettled(
|
|
136
|
-
competentHosts.map(async host => await this.facilitator.lookup(host, question))
|
|
152
|
+
competentHosts.map(async host => await this.facilitator.lookup(host, question, timeout))
|
|
137
153
|
)
|
|
138
154
|
|
|
139
155
|
const successfulResponses = hostResponses
|
|
@@ -180,7 +196,7 @@ export default class LookupResolver {
|
|
|
180
196
|
* @param service Service for which competent hosts are to be returned
|
|
181
197
|
* @returns Array of hosts competent for resolving queries
|
|
182
198
|
*/
|
|
183
|
-
private async findCompetentHosts(service: string): Promise<string[]> {
|
|
199
|
+
private async findCompetentHosts (service: string): Promise<string[]> {
|
|
184
200
|
const query: LookupQuestion = {
|
|
185
201
|
service: 'ls_slap',
|
|
186
202
|
query: {
|
|
@@ -190,7 +206,7 @@ export default class LookupResolver {
|
|
|
190
206
|
|
|
191
207
|
// Use Promise.allSettled to handle individual SLAP tracker failures
|
|
192
208
|
const trackerResponses = await Promise.allSettled(
|
|
193
|
-
this.slapTrackers.map(async tracker => await this.facilitator.lookup(tracker, query))
|
|
209
|
+
this.slapTrackers.map(async tracker => await this.facilitator.lookup(tracker, query, MAX_TRACKER_WAIT_TIME))
|
|
194
210
|
)
|
|
195
211
|
|
|
196
212
|
const hosts = new Set<string>()
|
|
@@ -15,7 +15,7 @@ export default class OverlayAdminTokenTemplate implements ScriptTemplate {
|
|
|
15
15
|
* @param script Locking script comprising a SHIP or SLAP token to decode
|
|
16
16
|
* @returns Decoded SHIP or SLAP advertisement
|
|
17
17
|
*/
|
|
18
|
-
static decode(script: LockingScript): { protocol: 'SHIP' | 'SLAP', identityKey: string, domain: string, topicOrService: string } {
|
|
18
|
+
static decode (script: LockingScript): { protocol: 'SHIP' | 'SLAP', identityKey: string, domain: string, topicOrService: string } {
|
|
19
19
|
const result = PushDrop.decode(script)
|
|
20
20
|
if (result.fields.length < 4) {
|
|
21
21
|
throw new Error('Invalid SHIP/SLAP advertisement!')
|
|
@@ -39,7 +39,7 @@ export default class OverlayAdminTokenTemplate implements ScriptTemplate {
|
|
|
39
39
|
* Constructs a new Overlay Admin template instance
|
|
40
40
|
* @param wallet Wallet to use for locking and unlocking
|
|
41
41
|
*/
|
|
42
|
-
constructor(wallet: Wallet) {
|
|
42
|
+
constructor (wallet: Wallet) {
|
|
43
43
|
this.pushDrop = new PushDrop(wallet)
|
|
44
44
|
}
|
|
45
45
|
|
|
@@ -50,7 +50,7 @@ export default class OverlayAdminTokenTemplate implements ScriptTemplate {
|
|
|
50
50
|
* @param topicOrService Topic or service to advertise
|
|
51
51
|
* @returns Locking script comprising the advertisement token
|
|
52
52
|
*/
|
|
53
|
-
async lock(protocol: 'SHIP' | 'SLAP', domain: string, topicOrService: string): Promise<LockingScript> {
|
|
53
|
+
async lock (protocol: 'SHIP' | 'SLAP', domain: string, topicOrService: string): Promise<LockingScript> {
|
|
54
54
|
const { publicKey: identityKey } = await this.pushDrop.wallet.getPublicKey({ identityKey: true })
|
|
55
55
|
return await this.pushDrop.lock(
|
|
56
56
|
[
|
|
@@ -70,7 +70,7 @@ export default class OverlayAdminTokenTemplate implements ScriptTemplate {
|
|
|
70
70
|
* @param protocol SHIP or SLAP, depending on the token to unlock
|
|
71
71
|
* @returns Script unlocker capable of unlocking the advertisement token
|
|
72
72
|
*/
|
|
73
|
-
unlock(protocol: 'SHIP' | 'SLAP'): {
|
|
73
|
+
unlock (protocol: 'SHIP' | 'SLAP'): {
|
|
74
74
|
sign: (tx: Transaction, inputIndex: number) => Promise<UnlockingScript>
|
|
75
75
|
estimateLength: (tx: Transaction, inputIndex: number) => Promise<number>
|
|
76
76
|
} {
|
|
@@ -56,14 +56,16 @@ export interface OverlayBroadcastFacilitator {
|
|
|
56
56
|
send: (url: string, taggedBEEF: TaggedBEEF) => Promise<STEAK>
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
+
const MAX_SHIP_QUERY_TIMEOUT = 1000
|
|
60
|
+
|
|
59
61
|
export class HTTPSOverlayBroadcastFacilitator implements OverlayBroadcastFacilitator {
|
|
60
62
|
httpClient: typeof fetch
|
|
61
63
|
|
|
62
|
-
constructor(httpClient = fetch) {
|
|
64
|
+
constructor (httpClient = fetch) {
|
|
63
65
|
this.httpClient = httpClient
|
|
64
66
|
}
|
|
65
67
|
|
|
66
|
-
async send(url: string, taggedBEEF: TaggedBEEF): Promise<STEAK> {
|
|
68
|
+
async send (url: string, taggedBEEF: TaggedBEEF): Promise<STEAK> {
|
|
67
69
|
if (!url.startsWith('https:')) {
|
|
68
70
|
throw new Error('HTTPS facilitator can only use URLs that start with "https:"')
|
|
69
71
|
}
|
|
@@ -100,7 +102,7 @@ export default class SHIPCast implements Broadcaster {
|
|
|
100
102
|
* @param {string[]} topics - The list of SHIP topic names where transactions are to be sent.
|
|
101
103
|
* @param {SHIPBroadcasterConfig} config - Configuration options for the SHIP broadcaster.
|
|
102
104
|
*/
|
|
103
|
-
constructor(topics: string[], config?: SHIPBroadcasterConfig) {
|
|
105
|
+
constructor (topics: string[], config?: SHIPBroadcasterConfig) {
|
|
104
106
|
if (topics.length === 0) {
|
|
105
107
|
throw new Error('At least one topic is required for broadcast.')
|
|
106
108
|
}
|
|
@@ -127,7 +129,7 @@ export default class SHIPCast implements Broadcaster {
|
|
|
127
129
|
* @param {Transaction} tx - The transaction to be sent.
|
|
128
130
|
* @returns {Promise<BroadcastResponse | BroadcastFailure>} A promise that resolves to either a success or failure response.
|
|
129
131
|
*/
|
|
130
|
-
async broadcast(tx: Transaction): Promise<BroadcastResponse | BroadcastFailure> {
|
|
132
|
+
async broadcast (tx: Transaction): Promise<BroadcastResponse | BroadcastFailure> {
|
|
131
133
|
let beef: number[]
|
|
132
134
|
try {
|
|
133
135
|
beef = tx.toBEEF()
|
|
@@ -269,7 +271,7 @@ export default class SHIPCast implements Broadcaster {
|
|
|
269
271
|
}
|
|
270
272
|
}
|
|
271
273
|
|
|
272
|
-
private checkAcknowledgmentFromAllHosts(hostAcknowledgments: Record<string, Set<string>>, requiredTopics: string[], require: 'all' | 'any'): boolean {
|
|
274
|
+
private checkAcknowledgmentFromAllHosts (hostAcknowledgments: Record<string, Set<string>>, requiredTopics: string[], require: 'all' | 'any'): boolean {
|
|
273
275
|
for (const acknowledgedTopics of Object.values(hostAcknowledgments)) {
|
|
274
276
|
if (require === 'all') {
|
|
275
277
|
for (const topic of requiredTopics) {
|
|
@@ -293,7 +295,7 @@ export default class SHIPCast implements Broadcaster {
|
|
|
293
295
|
return true
|
|
294
296
|
}
|
|
295
297
|
|
|
296
|
-
private checkAcknowledgmentFromAnyHost(hostAcknowledgments: Record<string, Set<string>>, requiredTopics: string[], require: 'all' | 'any'): boolean {
|
|
298
|
+
private checkAcknowledgmentFromAnyHost (hostAcknowledgments: Record<string, Set<string>>, requiredTopics: string[], require: 'all' | 'any'): boolean {
|
|
297
299
|
if (require === 'all') {
|
|
298
300
|
// All required topics must be acknowledged by at least one host
|
|
299
301
|
for (const acknowledgedTopics of Object.values(hostAcknowledgments)) {
|
|
@@ -322,7 +324,7 @@ export default class SHIPCast implements Broadcaster {
|
|
|
322
324
|
}
|
|
323
325
|
}
|
|
324
326
|
|
|
325
|
-
private checkAcknowledgmentFromSpecificHosts(hostAcknowledgments: Record<string, Set<string>>, requirements: Record<string, 'all' | 'any' | string[]>): boolean {
|
|
327
|
+
private checkAcknowledgmentFromSpecificHosts (hostAcknowledgments: Record<string, Set<string>>, requirements: Record<string, 'all' | 'any' | string[]>): boolean {
|
|
326
328
|
for (const [host, requiredTopicsOrAllAny] of Object.entries(requirements)) {
|
|
327
329
|
const acknowledgedTopics = hostAcknowledgments[host]
|
|
328
330
|
if (!acknowledgedTopics) {
|
|
@@ -368,7 +370,7 @@ export default class SHIPCast implements Broadcaster {
|
|
|
368
370
|
*
|
|
369
371
|
* @returns A mapping of URLs for hosts interested in this transaction. Keys are URLs, values are which of our topics the specific host cares about.
|
|
370
372
|
*/
|
|
371
|
-
private async findInterestedHosts(): Promise<Record<string, Set<string>>> {
|
|
373
|
+
private async findInterestedHosts (): Promise<Record<string, Set<string>>> {
|
|
372
374
|
// TODO: cache the list of interested hosts to avoid spamming SHIP trackers.
|
|
373
375
|
// TODO: Monetize the operation of the SHIP tracker system.
|
|
374
376
|
// TODO: Cache ship/slap lookup with expiry (every 5min)
|
|
@@ -380,7 +382,7 @@ export default class SHIPCast implements Broadcaster {
|
|
|
380
382
|
query: {
|
|
381
383
|
topics: this.topics
|
|
382
384
|
}
|
|
383
|
-
})
|
|
385
|
+
}, MAX_SHIP_QUERY_TIMEOUT)
|
|
384
386
|
if (answer.type !== 'output-list') {
|
|
385
387
|
throw new Error('SHIP answer is not an output list.')
|
|
386
388
|
}
|