edge-currency-plugins 3.2.0 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/src/main/assets/edge-currency-plugins/edge-currency-plugins.js +41 -41
- package/lib/common/plugin/PluginState.js +73 -43
- package/lib/common/plugin/ServerScores.js +11 -0
- package/lib/common/plugin/types.js +1 -1
- package/lib/common/utxobased/db/{Processor.js → DataLayer.js} +15 -11
- package/lib/common/utxobased/db/Models/{ProcessorTransaction.js → TransactionData.js} +4 -6
- package/lib/common/utxobased/db/types.js +4 -4
- package/lib/common/utxobased/db/util/utxo.js +8 -8
- package/lib/common/utxobased/engine/ServerStates.js +324 -298
- package/lib/common/utxobased/engine/UtxoEngine.js +58 -55
- package/lib/common/utxobased/engine/{UtxoEngineState.js → UtxoEngineProcessor.js} +650 -714
- package/lib/common/utxobased/engine/types.js +4 -2
- package/lib/common/utxobased/engine/util/getOwnUtxosFromTx.js +4 -4
- package/lib/common/utxobased/info/bitcoin.js +2 -1
- package/lib/common/utxobased/info/bitcoincash.js +2 -1
- package/lib/common/utxobased/info/dash.js +2 -1
- package/lib/common/utxobased/info/digibyte.js +5 -1
- package/lib/common/utxobased/info/dogecoin.js +2 -1
- package/lib/common/utxobased/info/groestlcoin.js +4 -1
- package/lib/common/utxobased/info/litecoin.js +2 -1
- package/lib/common/utxobased/info/zcoin.js +4 -1
- package/lib/common/utxobased/network/Blockbook.js +33 -30
- package/lib/common/utxobased/network/BlockbookElectrum.js +79 -77
- package/lib/common/utxobased/network/Socket.js +84 -48
- package/lib/common/utxobased/network/windowWS.js +2 -2
- package/lib/src/common/plugin/PluginState.d.ts +4 -4
- package/lib/src/common/plugin/ServerScores.d.ts +1 -0
- package/lib/src/common/plugin/types.d.ts +4 -4
- package/lib/src/common/utxobased/db/{Processor.d.ts → DataLayer.d.ts} +17 -11
- package/lib/src/common/utxobased/db/Models/{ProcessorTransaction.d.ts → TransactionData.d.ts} +5 -5
- package/lib/src/common/utxobased/db/Models/baselet.d.ts +4 -4
- package/lib/src/common/utxobased/db/types.d.ts +9 -9
- package/lib/src/common/utxobased/db/util/utxo.d.ts +3 -3
- package/lib/src/common/utxobased/engine/ServerStates.d.ts +7 -7
- package/lib/src/common/utxobased/engine/{UtxoEngineState.d.ts → UtxoEngineProcessor.d.ts} +44 -42
- package/lib/src/common/utxobased/engine/types.d.ts +4 -4
- package/lib/src/common/utxobased/engine/util/getOwnUtxosFromTx.d.ts +3 -3
- package/lib/src/common/utxobased/engine/utils.d.ts +2 -2
- package/lib/src/common/utxobased/keymanager/keymanager.d.ts +3 -3
- package/lib/src/common/utxobased/network/Blockbook.d.ts +8 -7
- package/lib/src/common/utxobased/network/BlockbookElectrum.d.ts +4 -2
- package/lib/src/common/utxobased/network/Socket.d.ts +10 -8
- package/lib/src/common/utxobased/network/types.d.ts +1 -1
- package/lib/src/util/uriKeyParams.d.ts +4 -0
- package/lib/util/uriKeyParams.js +20 -0
- package/package.json +1 -1
- /package/lib/test/common/utxobased/db/{Processor.spec.d.ts → DataLayer.spec.d.ts} +0 -0
|
@@ -87,10 +87,6 @@ var _constants = require('./constants');
|
|
|
87
87
|
|
|
88
88
|
|
|
89
89
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
90
|
|
|
95
91
|
|
|
96
92
|
|
|
@@ -176,25 +172,6 @@ var _constants = require('./constants');
|
|
|
176
172
|
addresses: new Set(),
|
|
177
173
|
blockHeight: 0
|
|
178
174
|
})
|
|
179
|
-
const setPickNextTaskCB = (
|
|
180
|
-
callback
|
|
181
|
-
) => {
|
|
182
|
-
pickNextTaskCB = callback
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
const stop = async () => {
|
|
186
|
-
isEngineOn = false
|
|
187
|
-
log(`stopping server states`)
|
|
188
|
-
_socketQueue.removeIdFromQueue.call(void 0, walletInfo.id)
|
|
189
|
-
clearTimeout(reconnectTimer)
|
|
190
|
-
for (const uri of Object.keys(serverStatesCache)) {
|
|
191
|
-
const serverState = serverStatesCache[uri]
|
|
192
|
-
const { blockbook } = serverState
|
|
193
|
-
if (blockbook == null) continue
|
|
194
|
-
await blockbook.disconnect()
|
|
195
|
-
_utils.removeItem.call(void 0, serverStatesCache, uri)
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
175
|
|
|
199
176
|
const reconnect = () => {
|
|
200
177
|
if (isEngineOn) {
|
|
@@ -202,22 +179,11 @@ var _constants = require('./constants');
|
|
|
202
179
|
const reconnectionDelay = Math.max(5, reconnectCounter++) * 1000
|
|
203
180
|
reconnectTimer = setTimeout(() => {
|
|
204
181
|
clearTimeout(reconnectTimer)
|
|
205
|
-
refillServers()
|
|
182
|
+
instance.refillServers()
|
|
206
183
|
}, reconnectionDelay)
|
|
207
184
|
}
|
|
208
185
|
}
|
|
209
186
|
|
|
210
|
-
const refillServers = () => {
|
|
211
|
-
log(`refilling servers...`)
|
|
212
|
-
isEngineOn = true
|
|
213
|
-
_socketQueue.pushUpdate.call(void 0, {
|
|
214
|
-
id: walletInfo.id,
|
|
215
|
-
updateFunc: () => {
|
|
216
|
-
doRefillServers()
|
|
217
|
-
}
|
|
218
|
-
})
|
|
219
|
-
}
|
|
220
|
-
|
|
221
187
|
const doRefillServers = () => {
|
|
222
188
|
const includePatterns = ['wss:', 'ws:', 'electrumwss:', 'electrumws:']
|
|
223
189
|
if (serverList.length === 0) {
|
|
@@ -256,6 +222,38 @@ var _constants = require('./constants');
|
|
|
256
222
|
// Blockbook instance variable
|
|
257
223
|
let blockbook
|
|
258
224
|
|
|
225
|
+
// Queue space callback
|
|
226
|
+
async function* taskGeneratorFn()
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
{
|
|
230
|
+
// Exit if the connection is no longer active
|
|
231
|
+
if (uri == null || !(uri in serverStatesCache)) return false
|
|
232
|
+
|
|
233
|
+
const generator = pickNextTaskCB(uri)
|
|
234
|
+
let nextValue
|
|
235
|
+
while (true) {
|
|
236
|
+
const result
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
= await generator.next(nextValue)
|
|
240
|
+
|
|
241
|
+
if (_optionalChain([result, 'optionalAccess', _ => _.done]) === true) {
|
|
242
|
+
return result.value
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
const task = result.value
|
|
246
|
+
|
|
247
|
+
if (typeof task !== 'boolean') {
|
|
248
|
+
const taskMessage = `${task.method} params: ${JSON.stringify(
|
|
249
|
+
task.params
|
|
250
|
+
)}`
|
|
251
|
+
log(`${uri} nextTask: ${taskMessage}`)
|
|
252
|
+
}
|
|
253
|
+
nextValue = yield task
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
259
257
|
// Create a new blockbook instance based on the URI scheme
|
|
260
258
|
if (['electrumwss', 'electrumws'].includes(parsed.scheme)) {
|
|
261
259
|
// Electrum wrapper
|
|
@@ -263,22 +261,9 @@ var _constants = require('./constants');
|
|
|
263
261
|
asAddress: pluginInfo.engineInfo.asBlockbookAddress,
|
|
264
262
|
connectionUri: uri,
|
|
265
263
|
engineEmitter,
|
|
264
|
+
initOptions,
|
|
266
265
|
log,
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
) => {
|
|
270
|
-
// Exit if the connection is no longer active
|
|
271
|
-
if (!(uri in serverStatesCache)) return
|
|
272
|
-
|
|
273
|
-
const task = await pickNextTaskCB(uri)
|
|
274
|
-
if (task != null && typeof task !== 'boolean') {
|
|
275
|
-
const taskMessage = `${task.method} params: ${JSON.stringify(
|
|
276
|
-
task.params
|
|
277
|
-
)}`
|
|
278
|
-
log(`${uri} nextTask: ${taskMessage}`)
|
|
279
|
-
}
|
|
280
|
-
return task
|
|
281
|
-
},
|
|
266
|
+
taskGeneratorFn,
|
|
282
267
|
pluginInfo,
|
|
283
268
|
socketEmitter,
|
|
284
269
|
walletId: walletInfo.id
|
|
@@ -289,22 +274,9 @@ var _constants = require('./constants');
|
|
|
289
274
|
asAddress: pluginInfo.engineInfo.asBlockbookAddress,
|
|
290
275
|
connectionUri: uri,
|
|
291
276
|
engineEmitter,
|
|
277
|
+
initOptions,
|
|
292
278
|
log,
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
) => {
|
|
296
|
-
// Exit if the connection is no longer active
|
|
297
|
-
if (!(uri in serverStatesCache)) return
|
|
298
|
-
|
|
299
|
-
const task = await pickNextTaskCB(uri)
|
|
300
|
-
if (task != null && typeof task !== 'boolean') {
|
|
301
|
-
const taskMessage = `${task.method} params: ${JSON.stringify(
|
|
302
|
-
task.params
|
|
303
|
-
)}`
|
|
304
|
-
log(`${uri} nextTask: ${taskMessage}`)
|
|
305
|
-
}
|
|
306
|
-
return task
|
|
307
|
-
},
|
|
279
|
+
taskGeneratorFn,
|
|
308
280
|
socketEmitter,
|
|
309
281
|
walletId: walletInfo.id
|
|
310
282
|
})
|
|
@@ -338,304 +310,358 @@ var _constants = require('./constants');
|
|
|
338
310
|
}
|
|
339
311
|
}
|
|
340
312
|
|
|
341
|
-
const
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
313
|
+
const deferredWithServerScoring = (
|
|
314
|
+
serverUri,
|
|
315
|
+
deferred
|
|
316
|
+
) => {
|
|
317
|
+
const serverState = serverStatesCache[serverUri]
|
|
318
|
+
if (serverState == null)
|
|
319
|
+
throw new Error(`No blockbook connection with ${serverUri}`)
|
|
345
320
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
321
|
+
const queryTime = Date.now()
|
|
322
|
+
const deferredWithScoring = new _Deferred2.default()
|
|
323
|
+
deferredWithScoring.promise.then(
|
|
324
|
+
(value) => {
|
|
325
|
+
pluginState.serverScoreUp(serverUri, Date.now() - queryTime)
|
|
326
|
+
deferred.resolve(value)
|
|
327
|
+
},
|
|
328
|
+
(err) => {
|
|
329
|
+
pluginState.serverScoreDown(serverUri)
|
|
330
|
+
deferred.reject(err)
|
|
331
|
+
}
|
|
332
|
+
)
|
|
333
|
+
|
|
334
|
+
return deferredWithScoring
|
|
350
335
|
}
|
|
351
336
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
337
|
+
function* withServerScoring(
|
|
338
|
+
serverUri,
|
|
339
|
+
generator
|
|
340
|
+
) {
|
|
341
|
+
const serverState = serverStatesCache[serverUri]
|
|
342
|
+
if (serverState == null)
|
|
343
|
+
throw new Error(`No blockbook connection with ${serverUri}`)
|
|
356
344
|
|
|
357
|
-
|
|
358
|
-
|
|
345
|
+
const queryTime = Date.now()
|
|
346
|
+
let result
|
|
347
|
+
try {
|
|
348
|
+
result = yield* generator
|
|
349
|
+
pluginState.serverScoreUp(serverUri, Date.now() - queryTime)
|
|
350
|
+
} catch (error) {
|
|
351
|
+
pluginState.serverScoreDown(serverUri)
|
|
352
|
+
throw error
|
|
359
353
|
}
|
|
360
|
-
return
|
|
354
|
+
return result
|
|
361
355
|
}
|
|
362
356
|
|
|
363
|
-
const
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
357
|
+
const instance = {
|
|
358
|
+
async broadcastTx(transaction) {
|
|
359
|
+
return await new Promise((resolve, reject) => {
|
|
360
|
+
let resolved = false
|
|
361
|
+
let bad = 0
|
|
362
|
+
|
|
363
|
+
const wsUris = Object.keys(serverStatesCache).filter(
|
|
364
|
+
uri => serverStatesCache[uri].blockbook != null
|
|
365
|
+
)
|
|
366
|
+
|
|
367
|
+
// If there are no blockbook instances, reject the promise
|
|
368
|
+
if (wsUris.length < 1) {
|
|
369
|
+
reject(new Error('Unexpected error. Missing WebSocket connections.'))
|
|
370
|
+
// Exit early if there are blockbook instances
|
|
371
|
+
return
|
|
372
|
+
}
|
|
369
373
|
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
374
|
+
// Determine if there are any connected blockbook instances
|
|
375
|
+
const isAnyBlockbookConnected = wsUris.some(
|
|
376
|
+
uri => serverStatesCache[uri].blockbook.isConnected
|
|
377
|
+
)
|
|
378
|
+
|
|
379
|
+
if (isAnyBlockbookConnected) {
|
|
380
|
+
for (const uri of wsUris) {
|
|
381
|
+
const { blockbook } = serverStatesCache[uri]
|
|
382
|
+
if (blockbook == null) continue
|
|
383
|
+
blockbook
|
|
384
|
+
.broadcastTx(transaction)
|
|
385
|
+
.then(response => {
|
|
386
|
+
if (!resolved) {
|
|
387
|
+
resolved = true
|
|
388
|
+
resolve(response.result)
|
|
389
|
+
}
|
|
390
|
+
})
|
|
391
|
+
.catch((e) => {
|
|
392
|
+
if (++bad === wsUris.length) {
|
|
393
|
+
const msg = e != null ? `With error ${e.message}` : ''
|
|
394
|
+
log.error(
|
|
395
|
+
`broadcastTx fail: ${JSON.stringify(transaction)}\n${msg}`
|
|
396
|
+
)
|
|
397
|
+
reject(e)
|
|
398
|
+
}
|
|
399
|
+
})
|
|
400
|
+
}
|
|
401
|
+
}
|
|
373
402
|
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
403
|
+
// Broadcast through any HTTP URI that may be configured, only if no
|
|
404
|
+
// blockbook instances are connected.
|
|
405
|
+
if (!isAnyBlockbookConnected) {
|
|
406
|
+
// This is for the future when we want to get HTTP servers from the user
|
|
407
|
+
// settings:
|
|
408
|
+
// const httpUris = pluginState.getLocalServers(Infinity, [
|
|
409
|
+
// /^http(?:s)?:/i
|
|
410
|
+
// ])
|
|
411
|
+
|
|
412
|
+
const { nowNodesApiKey } = initOptions
|
|
413
|
+
const nowNodeUris = serverConfigs
|
|
414
|
+
.filter(config => config.type === 'blockbook-nownode')
|
|
415
|
+
.map(config => config.uris)
|
|
416
|
+
.flat(1)
|
|
417
|
+
|
|
418
|
+
// If there are no HTTP servers, reject the promise
|
|
419
|
+
if (nowNodeUris.length < 1) {
|
|
420
|
+
// If no HTTP servers are available, and we had no connected blockbook
|
|
421
|
+
// instances, reject the promise with a message indicating no
|
|
422
|
+
// available connections. It's clear we have some connection instances
|
|
423
|
+
// if we gotten to this point, but we just don't have any of those
|
|
424
|
+
// instances connected at this time.
|
|
425
|
+
reject(
|
|
426
|
+
new Error('No available connections. Check your internet signal.')
|
|
427
|
+
)
|
|
428
|
+
return
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
// If there is no key for the NowNode servers:
|
|
432
|
+
if (nowNodesApiKey == null) {
|
|
433
|
+
reject(new Error('Missing connection key for fallback servers.'))
|
|
434
|
+
return
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
for (const uri of nowNodeUris) {
|
|
438
|
+
log.warn('Falling back to NOWNode server broadcast over HTTP:', uri)
|
|
439
|
+
|
|
440
|
+
// HTTP Fallback
|
|
441
|
+
io.fetchCors(`${uri}/api/v2/sendtx/`, {
|
|
442
|
+
method: 'POST',
|
|
443
|
+
headers: {
|
|
444
|
+
'api-key': nowNodesApiKey
|
|
445
|
+
},
|
|
446
|
+
body: transaction.signedTx
|
|
447
|
+
})
|
|
448
|
+
.then(async response => {
|
|
449
|
+
if (!response.ok) {
|
|
450
|
+
throw new Error(
|
|
451
|
+
`Failed to broadcast transaction via Blockbook: HTTP ${response.status}`
|
|
452
|
+
)
|
|
453
|
+
}
|
|
454
|
+
const json = await response.json()
|
|
455
|
+
return _blockbookApi.asBlockbookResponse.call(void 0, (0, _blockbookApi.asBroadcastTxResponse))(json)
|
|
456
|
+
})
|
|
457
|
+
.then(response => {
|
|
458
|
+
if (!resolved) {
|
|
459
|
+
resolved = true
|
|
460
|
+
resolve(response.result)
|
|
461
|
+
}
|
|
462
|
+
})
|
|
463
|
+
.catch((e) => {
|
|
464
|
+
if (++bad === nowNodeUris.length) {
|
|
465
|
+
const msg = e != null ? `With error ${e.message}` : ''
|
|
466
|
+
log.error(
|
|
467
|
+
`broadcastTx fail: ${JSON.stringify(transaction)}\n${msg}`
|
|
468
|
+
)
|
|
469
|
+
reject(e)
|
|
470
|
+
}
|
|
471
|
+
})
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
})
|
|
475
|
+
},
|
|
377
476
|
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
477
|
+
getBlockHeight(uri) {
|
|
478
|
+
return serverStatesCache[uri].blockHeight
|
|
479
|
+
},
|
|
381
480
|
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
let bad = 0
|
|
481
|
+
getServerList() {
|
|
482
|
+
return serverList
|
|
483
|
+
},
|
|
386
484
|
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
485
|
+
getServerState(uri) {
|
|
486
|
+
return serverStatesCache[uri]
|
|
487
|
+
},
|
|
390
488
|
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
489
|
+
refillServers() {
|
|
490
|
+
log(`refilling servers...`)
|
|
491
|
+
isEngineOn = true
|
|
492
|
+
_socketQueue.pushUpdate.call(void 0, {
|
|
493
|
+
id: walletInfo.id,
|
|
494
|
+
updateFunc: () => {
|
|
495
|
+
doRefillServers()
|
|
496
|
+
}
|
|
497
|
+
})
|
|
498
|
+
},
|
|
397
499
|
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
)
|
|
500
|
+
setPickNextTaskCB(callback) {
|
|
501
|
+
pickNextTaskCB = callback
|
|
502
|
+
},
|
|
402
503
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
})
|
|
415
|
-
.catch((e) => {
|
|
416
|
-
if (++bad === wsUris.length) {
|
|
417
|
-
const msg = e != null ? `With error ${e.message}` : ''
|
|
418
|
-
log.error(
|
|
419
|
-
`broadcastTx fail: ${JSON.stringify(transaction)}\n${msg}`
|
|
420
|
-
)
|
|
421
|
-
reject(e)
|
|
422
|
-
}
|
|
423
|
-
})
|
|
424
|
-
}
|
|
504
|
+
setServerList(updatedServerList) {
|
|
505
|
+
serverList = updatedServerList
|
|
506
|
+
},
|
|
507
|
+
|
|
508
|
+
serverCanGetTx(uri, txid) {
|
|
509
|
+
const serverState = serverStatesCache[uri]
|
|
510
|
+
if (serverState == null) return false
|
|
511
|
+
if (serverState.txids.has(txid)) return true
|
|
512
|
+
|
|
513
|
+
for (const state of Object.values(serverStatesCache)) {
|
|
514
|
+
if (state.txids.has(txid)) return false
|
|
425
515
|
}
|
|
516
|
+
return true
|
|
517
|
+
},
|
|
426
518
|
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
if (
|
|
430
|
-
|
|
431
|
-
// settings:
|
|
432
|
-
// const httpUris = pluginState.getLocalServers(Infinity, [
|
|
433
|
-
// /^http(?:s)?:/i
|
|
434
|
-
// ])
|
|
435
|
-
|
|
436
|
-
const { nowNodeApiKey } = initOptions
|
|
437
|
-
const nowNodeUris = serverConfigs
|
|
438
|
-
.filter(config => config.type === 'blockbook-nownode')
|
|
439
|
-
.map(config => config.uris)
|
|
440
|
-
.flat(1)
|
|
441
|
-
|
|
442
|
-
// If there are no HTTP servers, reject the promise
|
|
443
|
-
if (nowNodeUris.length < 1) {
|
|
444
|
-
// If no HTTP servers are available, and we had no connected blockbook
|
|
445
|
-
// instances, reject the promise with a message indicating no
|
|
446
|
-
// available connections. It's clear we have some connection instances
|
|
447
|
-
// if we gotten to this point, but we just don't have any of those
|
|
448
|
-
// instances connected at this time.
|
|
449
|
-
reject(
|
|
450
|
-
new Error('No available connections. Check your internet signal.')
|
|
451
|
-
)
|
|
452
|
-
return
|
|
453
|
-
}
|
|
519
|
+
serverCanGetAddress(uri, address) {
|
|
520
|
+
const serverState = serverStatesCache[uri]
|
|
521
|
+
if (serverState == null) return false
|
|
522
|
+
if (serverState.addresses.has(address)) return true
|
|
454
523
|
|
|
455
|
-
|
|
456
|
-
if (
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
524
|
+
for (const state of Object.values(serverStatesCache)) {
|
|
525
|
+
if (state.addresses.has(address)) return false
|
|
526
|
+
}
|
|
527
|
+
return true
|
|
528
|
+
},
|
|
460
529
|
|
|
461
|
-
|
|
462
|
-
|
|
530
|
+
serverIsAwareOfAddress(uri, address) {
|
|
531
|
+
const serverState = serverStatesCache[uri]
|
|
532
|
+
if (serverState == null) return false
|
|
533
|
+
if (serverState.addresses.has(address)) return true
|
|
534
|
+
return false
|
|
535
|
+
},
|
|
463
536
|
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
`Failed to broadcast transaction via Blockbook: HTTP ${response.status}`
|
|
476
|
-
)
|
|
477
|
-
}
|
|
478
|
-
const json = await response.json()
|
|
479
|
-
return _blockbookApi.asBlockbookResponse.call(void 0, (0, _blockbookApi.asBroadcastTxResponse))(json)
|
|
480
|
-
})
|
|
481
|
-
.then(response => {
|
|
482
|
-
if (!resolved) {
|
|
483
|
-
resolved = true
|
|
484
|
-
resolve(response.result)
|
|
485
|
-
}
|
|
486
|
-
})
|
|
487
|
-
.catch((e) => {
|
|
488
|
-
if (++bad === nowNodeUris.length) {
|
|
489
|
-
const msg = e != null ? `With error ${e.message}` : ''
|
|
490
|
-
log.error(
|
|
491
|
-
`broadcastTx fail: ${JSON.stringify(transaction)}\n${msg}`
|
|
492
|
-
)
|
|
493
|
-
reject(e)
|
|
494
|
-
}
|
|
495
|
-
})
|
|
496
|
-
}
|
|
537
|
+
async stop() {
|
|
538
|
+
isEngineOn = false
|
|
539
|
+
log(`stopping server states`)
|
|
540
|
+
_socketQueue.removeIdFromQueue.call(void 0, walletInfo.id)
|
|
541
|
+
clearTimeout(reconnectTimer)
|
|
542
|
+
for (const uri of Object.keys(serverStatesCache)) {
|
|
543
|
+
const serverState = serverStatesCache[uri]
|
|
544
|
+
const { blockbook } = serverState
|
|
545
|
+
if (blockbook == null) continue
|
|
546
|
+
await blockbook.disconnect()
|
|
547
|
+
_utils.removeItem.call(void 0, serverStatesCache, uri)
|
|
497
548
|
}
|
|
498
|
-
}
|
|
499
|
-
}
|
|
549
|
+
},
|
|
500
550
|
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
551
|
+
watchAddresses(
|
|
552
|
+
serverUri,
|
|
553
|
+
addresses,
|
|
554
|
+
deferredAddressSub
|
|
555
|
+
) {
|
|
556
|
+
const serverState = serverStatesCache[serverUri]
|
|
557
|
+
if (serverState == null)
|
|
558
|
+
throw new Error(`No blockbook connection with ${serverUri}`)
|
|
509
559
|
|
|
510
|
-
|
|
560
|
+
const { blockbook } = serverState
|
|
511
561
|
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
562
|
+
// Add new addresses to the set of known addresses
|
|
563
|
+
for (const address of addresses) {
|
|
564
|
+
serverState.addresses.add(address)
|
|
565
|
+
}
|
|
516
566
|
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
deferred.promise
|
|
520
|
-
.then((value) => {
|
|
521
|
-
pluginState.serverScoreUp(uri, Date.now() - queryTime)
|
|
522
|
-
_optionalChain([deferredAddressSub, 'optionalAccess', _ => _.resolve, 'call', _2 => _2(value)])
|
|
523
|
-
})
|
|
524
|
-
.catch(() => {
|
|
567
|
+
const deferred = new _Deferred2.default()
|
|
568
|
+
deferred.promise.catch((err) => {
|
|
525
569
|
// Remove new addresses to the set of known addresses
|
|
526
570
|
for (const address of addresses) {
|
|
527
571
|
serverState.addresses.delete(address)
|
|
528
572
|
}
|
|
529
|
-
|
|
530
|
-
_optionalChain([deferredAddressSub, 'optionalAccess',
|
|
573
|
+
// Reject the deferredAddressSub promise if provided
|
|
574
|
+
_optionalChain([deferredAddressSub, 'optionalAccess', _2 => _2.reject, 'call', _3 => _3(err)])
|
|
531
575
|
})
|
|
532
|
-
blockbook.watchAddresses(Array.from(serverState.addresses), deferred)
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
const watchBlocks = (uri) => {
|
|
536
|
-
const serverState = serverStatesCache[uri]
|
|
537
|
-
if (serverState == null)
|
|
538
|
-
throw new Error(`No blockbook connection with ${uri}`)
|
|
539
576
|
|
|
540
|
-
|
|
577
|
+
blockbook.watchAddresses(
|
|
578
|
+
Array.from(serverState.addresses),
|
|
579
|
+
deferredWithServerScoring(serverUri, deferred)
|
|
580
|
+
)
|
|
581
|
+
},
|
|
541
582
|
|
|
542
|
-
|
|
583
|
+
watchBlocks(serverUri) {
|
|
584
|
+
const serverState = serverStatesCache[serverUri]
|
|
585
|
+
if (serverState == null)
|
|
586
|
+
throw new Error(`No blockbook connection with ${serverUri}`)
|
|
543
587
|
|
|
544
|
-
|
|
545
|
-
const deferred = new (0, _Deferred2.default)()
|
|
546
|
-
deferred.promise
|
|
547
|
-
.then(() => {
|
|
548
|
-
serverState.blockSubscriptionStatus = 'subscribed'
|
|
549
|
-
pluginState.serverScoreUp(uri, Date.now() - queryTime)
|
|
550
|
-
})
|
|
551
|
-
.catch(() => {
|
|
552
|
-
serverState.blockSubscriptionStatus = 'unsubscribed'
|
|
553
|
-
})
|
|
554
|
-
blockbook.watchBlocks(deferred)
|
|
555
|
-
}
|
|
588
|
+
const { blockbook } = serverState
|
|
556
589
|
|
|
557
|
-
|
|
558
|
-
return serverStatesCache[uri].blockHeight
|
|
559
|
-
}
|
|
590
|
+
serverState.blockSubscriptionStatus = 'subscribing'
|
|
560
591
|
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
broadcastTx,
|
|
572
|
-
watchAddresses,
|
|
573
|
-
watchBlocks,
|
|
574
|
-
getBlockHeight,
|
|
592
|
+
const deferred = new (0, _Deferred2.default)()
|
|
593
|
+
deferred.promise
|
|
594
|
+
.then(() => {
|
|
595
|
+
serverState.blockSubscriptionStatus = 'subscribed'
|
|
596
|
+
})
|
|
597
|
+
.catch(() => {
|
|
598
|
+
serverState.blockSubscriptionStatus = 'unsubscribed'
|
|
599
|
+
})
|
|
600
|
+
blockbook.watchBlocks(deferredWithServerScoring(serverUri, deferred))
|
|
601
|
+
},
|
|
575
602
|
|
|
576
603
|
//
|
|
577
604
|
// Task Methods:
|
|
578
605
|
//
|
|
579
606
|
|
|
580
|
-
addressQueryTask(
|
|
607
|
+
addressQueryTask: function* (
|
|
581
608
|
serverUri,
|
|
582
609
|
address,
|
|
583
|
-
params
|
|
584
|
-
deferred
|
|
610
|
+
params
|
|
585
611
|
) {
|
|
586
612
|
const serverState = serverStatesCache[serverUri]
|
|
587
613
|
if (serverState == null)
|
|
588
614
|
throw new Error(`No blockbook connection with ${serverUri}`)
|
|
589
615
|
|
|
590
|
-
return
|
|
591
|
-
|
|
592
|
-
{
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
616
|
+
return yield* withServerScoring(
|
|
617
|
+
serverUri,
|
|
618
|
+
(function* () {
|
|
619
|
+
return yield* serverState.blockbook.addressQueryTask(address, {
|
|
620
|
+
asBlockbookAddress: pluginInfo.engineInfo.asBlockbookAddress,
|
|
621
|
+
lastQueriedBlockHeight: params.lastQueriedBlockHeight,
|
|
622
|
+
page: params.page
|
|
623
|
+
})
|
|
624
|
+
})()
|
|
598
625
|
)
|
|
599
626
|
},
|
|
600
627
|
|
|
601
|
-
transactionQueryTask(
|
|
602
|
-
serverUri,
|
|
603
|
-
txId,
|
|
604
|
-
deferred
|
|
605
|
-
) {
|
|
628
|
+
transactionQueryTask: function* (serverUri, txId) {
|
|
606
629
|
const serverState = serverStatesCache[serverUri]
|
|
607
630
|
if (serverState == null)
|
|
608
631
|
throw new Error(`No blockbook connection with ${serverUri}`)
|
|
609
632
|
|
|
610
|
-
return
|
|
633
|
+
return yield* withServerScoring(
|
|
634
|
+
serverUri,
|
|
635
|
+
(function* () {
|
|
636
|
+
return yield* serverState.blockbook.transactionQueryTask(txId)
|
|
637
|
+
})()
|
|
638
|
+
)
|
|
611
639
|
},
|
|
612
640
|
|
|
613
|
-
transactionSpecialQueryTask(
|
|
614
|
-
serverUri,
|
|
615
|
-
txId,
|
|
616
|
-
deferred
|
|
617
|
-
) {
|
|
641
|
+
transactionSpecialQueryTask: function* (serverUri, txId) {
|
|
618
642
|
const serverState = serverStatesCache[serverUri]
|
|
619
643
|
if (serverState == null)
|
|
620
644
|
throw new Error(`No blockbook connection with ${serverUri}`)
|
|
621
645
|
|
|
622
|
-
return
|
|
646
|
+
return yield* withServerScoring(
|
|
647
|
+
serverUri,
|
|
648
|
+
(function* () {
|
|
649
|
+
return serverState.blockbook.transactionSpecialQueryTask(txId)
|
|
650
|
+
})()
|
|
651
|
+
)
|
|
623
652
|
},
|
|
624
|
-
utxoListQueryTask(
|
|
625
|
-
serverUri,
|
|
626
|
-
address,
|
|
627
|
-
deferred
|
|
628
|
-
) {
|
|
653
|
+
utxoListQueryTask: function* (serverUri, address) {
|
|
629
654
|
const serverState = serverStatesCache[serverUri]
|
|
630
655
|
if (serverState == null)
|
|
631
656
|
throw new Error(`No blockbook connection with ${serverUri}`)
|
|
632
657
|
|
|
633
|
-
return
|
|
634
|
-
|
|
635
|
-
{
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
658
|
+
return yield* withServerScoring(
|
|
659
|
+
serverUri,
|
|
660
|
+
(function* () {
|
|
661
|
+
return yield* serverState.blockbook.utxoListQueryTask(address, {
|
|
662
|
+
asBlockbookAddress: pluginInfo.engineInfo.asBlockbookAddress
|
|
663
|
+
})
|
|
664
|
+
})()
|
|
639
665
|
)
|
|
640
666
|
}
|
|
641
667
|
}
|