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.
Files changed (47) hide show
  1. package/android/src/main/assets/edge-currency-plugins/edge-currency-plugins.js +41 -41
  2. package/lib/common/plugin/PluginState.js +73 -43
  3. package/lib/common/plugin/ServerScores.js +11 -0
  4. package/lib/common/plugin/types.js +1 -1
  5. package/lib/common/utxobased/db/{Processor.js → DataLayer.js} +15 -11
  6. package/lib/common/utxobased/db/Models/{ProcessorTransaction.js → TransactionData.js} +4 -6
  7. package/lib/common/utxobased/db/types.js +4 -4
  8. package/lib/common/utxobased/db/util/utxo.js +8 -8
  9. package/lib/common/utxobased/engine/ServerStates.js +324 -298
  10. package/lib/common/utxobased/engine/UtxoEngine.js +58 -55
  11. package/lib/common/utxobased/engine/{UtxoEngineState.js → UtxoEngineProcessor.js} +650 -714
  12. package/lib/common/utxobased/engine/types.js +4 -2
  13. package/lib/common/utxobased/engine/util/getOwnUtxosFromTx.js +4 -4
  14. package/lib/common/utxobased/info/bitcoin.js +2 -1
  15. package/lib/common/utxobased/info/bitcoincash.js +2 -1
  16. package/lib/common/utxobased/info/dash.js +2 -1
  17. package/lib/common/utxobased/info/digibyte.js +5 -1
  18. package/lib/common/utxobased/info/dogecoin.js +2 -1
  19. package/lib/common/utxobased/info/groestlcoin.js +4 -1
  20. package/lib/common/utxobased/info/litecoin.js +2 -1
  21. package/lib/common/utxobased/info/zcoin.js +4 -1
  22. package/lib/common/utxobased/network/Blockbook.js +33 -30
  23. package/lib/common/utxobased/network/BlockbookElectrum.js +79 -77
  24. package/lib/common/utxobased/network/Socket.js +84 -48
  25. package/lib/common/utxobased/network/windowWS.js +2 -2
  26. package/lib/src/common/plugin/PluginState.d.ts +4 -4
  27. package/lib/src/common/plugin/ServerScores.d.ts +1 -0
  28. package/lib/src/common/plugin/types.d.ts +4 -4
  29. package/lib/src/common/utxobased/db/{Processor.d.ts → DataLayer.d.ts} +17 -11
  30. package/lib/src/common/utxobased/db/Models/{ProcessorTransaction.d.ts → TransactionData.d.ts} +5 -5
  31. package/lib/src/common/utxobased/db/Models/baselet.d.ts +4 -4
  32. package/lib/src/common/utxobased/db/types.d.ts +9 -9
  33. package/lib/src/common/utxobased/db/util/utxo.d.ts +3 -3
  34. package/lib/src/common/utxobased/engine/ServerStates.d.ts +7 -7
  35. package/lib/src/common/utxobased/engine/{UtxoEngineState.d.ts → UtxoEngineProcessor.d.ts} +44 -42
  36. package/lib/src/common/utxobased/engine/types.d.ts +4 -4
  37. package/lib/src/common/utxobased/engine/util/getOwnUtxosFromTx.d.ts +3 -3
  38. package/lib/src/common/utxobased/engine/utils.d.ts +2 -2
  39. package/lib/src/common/utxobased/keymanager/keymanager.d.ts +3 -3
  40. package/lib/src/common/utxobased/network/Blockbook.d.ts +8 -7
  41. package/lib/src/common/utxobased/network/BlockbookElectrum.d.ts +4 -2
  42. package/lib/src/common/utxobased/network/Socket.d.ts +10 -8
  43. package/lib/src/common/utxobased/network/types.d.ts +1 -1
  44. package/lib/src/util/uriKeyParams.d.ts +4 -0
  45. package/lib/util/uriKeyParams.js +20 -0
  46. package/package.json +1 -1
  47. /package/lib/test/common/utxobased/db/{Processor.spec.d.ts → DataLayer.spec.d.ts} +0 -0
@@ -16,10 +16,9 @@ var _EngineEmitter = require('../../plugin/EngineEmitter');
16
16
 
17
17
 
18
18
 
19
-
20
19
  var _utils = require('../../plugin/utils');
21
- var _ProcessorTransaction = require('../db/Models/ProcessorTransaction');
22
20
 
21
+ var _TransactionData = require('../db/Models/TransactionData');
23
22
 
24
23
 
25
24
 
@@ -39,7 +38,6 @@ var _keymanager = require('../keymanager/keymanager');
39
38
 
40
39
 
41
40
 
42
- var _Deferred = require('../network/Deferred'); var _Deferred2 = _interopRequireDefault(_Deferred);
43
41
 
44
42
  var _awaitlock = require('./await-lock'); var _awaitlock2 = _interopRequireDefault(_awaitlock);
45
43
  var _constants = require('./constants');
@@ -87,7 +85,7 @@ var _utils3 = require('./utils');
87
85
 
88
86
 
89
87
 
90
- function makeUtxoEngineState(
88
+ function makeUtxoEngineProcessor(
91
89
  config
92
90
  ) {
93
91
  const {
@@ -96,7 +94,7 @@ var _utils3 = require('./utils');
96
94
  options,
97
95
  pluginState,
98
96
  pluginInfo,
99
- processor,
97
+ dataLayer,
100
98
  walletInfo,
101
99
  walletTools
102
100
  } = config
@@ -105,38 +103,36 @@ var _utils3 = require('./utils');
105
103
  const { walletFormats } = walletInfo.keys
106
104
 
107
105
  const taskCache = {
108
- blockWatching: false,
106
+ addressForTransactionsCache: {},
107
+ addressForUtxosCache: {},
109
108
  addressSubscribeCache: {},
110
- addressTransactionCache: {},
111
- addressUtxoCache: {},
112
- rawUtxoCache: {},
113
- processorUtxoCache: {},
114
- updateTransactionCache: {},
115
- updateTransactionSpecificCache: {}
109
+ blockbookUtxoCache: {},
110
+ dataLayerUtxoCache: {},
111
+ transactionSpecificUpdateCache: {},
112
+ transactionUpdateCache: {}
116
113
  }
117
114
 
118
115
  const clearTaskCache = () => {
119
- taskCache.blockWatching = false
120
- for (const key of Object.keys(taskCache.addressSubscribeCache)) {
121
- _utils.removeItem.call(void 0, taskCache.addressSubscribeCache, key)
116
+ for (const key of Object.keys(taskCache.addressForTransactionsCache)) {
117
+ _utils.removeItem.call(void 0, taskCache.addressForTransactionsCache, key)
122
118
  }
123
- for (const key of Object.keys(taskCache.addressTransactionCache)) {
124
- _utils.removeItem.call(void 0, taskCache.addressTransactionCache, key)
119
+ for (const key of Object.keys(taskCache.addressForUtxosCache)) {
120
+ _utils.removeItem.call(void 0, taskCache.addressForUtxosCache, key)
125
121
  }
126
- for (const key of Object.keys(taskCache.addressUtxoCache)) {
127
- _utils.removeItem.call(void 0, taskCache.addressUtxoCache, key)
122
+ for (const key of Object.keys(taskCache.addressSubscribeCache)) {
123
+ _utils.removeItem.call(void 0, taskCache.addressSubscribeCache, key)
128
124
  }
129
- for (const key of Object.keys(taskCache.rawUtxoCache)) {
130
- _utils.removeItem.call(void 0, taskCache.rawUtxoCache, key)
125
+ for (const key of Object.keys(taskCache.blockbookUtxoCache)) {
126
+ _utils.removeItem.call(void 0, taskCache.blockbookUtxoCache, key)
131
127
  }
132
- for (const key of Object.keys(taskCache.processorUtxoCache)) {
133
- _utils.removeItem.call(void 0, taskCache.processorUtxoCache, key)
128
+ for (const key of Object.keys(taskCache.dataLayerUtxoCache)) {
129
+ _utils.removeItem.call(void 0, taskCache.dataLayerUtxoCache, key)
134
130
  }
135
- for (const key of Object.keys(taskCache.updateTransactionCache)) {
136
- _utils.removeItem.call(void 0, taskCache.updateTransactionCache, key)
131
+ for (const key of Object.keys(taskCache.transactionSpecificUpdateCache)) {
132
+ _utils.removeItem.call(void 0, taskCache.transactionSpecificUpdateCache, key)
137
133
  }
138
- for (const key of Object.keys(taskCache.updateTransactionSpecificCache)) {
139
- _utils.removeItem.call(void 0, taskCache.updateTransactionSpecificCache, key)
134
+ for (const key of Object.keys(taskCache.transactionUpdateCache)) {
135
+ _utils.removeItem.call(void 0, taskCache.transactionUpdateCache, key)
140
136
  }
141
137
  }
142
138
 
@@ -184,24 +180,23 @@ var _utils3 = require('./utils');
184
180
  pluginState,
185
181
  walletInfo
186
182
  })
187
- const commonArgs = {
183
+ const common = {
188
184
  pluginInfo,
189
185
  walletInfo,
190
186
  walletTools,
191
- processor,
187
+ dataLayer,
192
188
  emitter,
193
189
  taskCache,
194
190
  updateProgressRatio,
195
191
  io,
196
192
  log,
197
193
  serverStates,
198
- pluginState,
199
194
  walletFormats,
200
195
  lock
201
196
  }
202
197
 
203
- serverStates.setPickNextTaskCB(async serverUri => {
204
- return await exports.pickNextTask.call(void 0, commonArgs, serverUri)
198
+ serverStates.setPickNextTaskCB(serverUri => {
199
+ return pickNextTask(common, serverUri)
205
200
  })
206
201
 
207
202
  let running = false
@@ -210,18 +205,18 @@ var _utils3 = require('./utils');
210
205
  running = true
211
206
 
212
207
  await initializeAddressSubscriptions()
213
- await setLookAhead(commonArgs)
208
+ await setLookAhead(common)
214
209
  }
215
210
 
216
211
  emitter.on(
217
212
  _EngineEmitter.EngineEvent.BLOCK_HEIGHT_CHANGED,
218
213
  async (_uri, _blockHeight) => {
219
- const txs = await processor.fetchTransactions({
214
+ const txs = await dataLayer.fetchTransactions({
220
215
  blockHeight: 0
221
216
  })
222
217
  for (const tx of txs) {
223
218
  if (tx == null) continue
224
- taskCache.updateTransactionCache[tx.txid] = { processing: false }
219
+ taskCache.transactionUpdateCache[tx.txid] = { processing: false }
225
220
  }
226
221
  }
227
222
  )
@@ -232,20 +227,19 @@ var _utils3 = require('./utils');
232
227
  const state = taskCache.addressSubscribeCache[response.address]
233
228
  if (state != null) {
234
229
  const { path } = state
235
- taskCache.addressUtxoCache[response.address] = {
230
+ taskCache.addressForUtxosCache[response.address] = {
236
231
  processing: false,
237
232
  path
238
233
  }
239
- addToAddressTransactionCache(
240
- commonArgs,
241
- response.address,
242
- path,
243
- 0,
244
- taskCache.addressTransactionCache
245
- ).catch(() => {
234
+ addToAddressForTransactionsCache(common, {
235
+ address: response.address,
236
+ changePath: path,
237
+ blockHeight: 0,
238
+ addressForTransactionsCache: taskCache.addressForTransactionsCache
239
+ }).catch(() => {
246
240
  throw new Error('failed to add to transaction cache')
247
241
  })
248
- setLookAhead(commonArgs).catch(e => {
242
+ setLookAhead(common).catch(e => {
249
243
  log(e)
250
244
  })
251
245
  }
@@ -253,7 +247,7 @@ var _utils3 = require('./utils');
253
247
  )
254
248
 
255
249
  // Initialize the addressSubscribeCache with the existing addresses already
256
- // processed by the processor. This happens only once before any call to
250
+ // processed by the DataLayer. This happens only once before any call to
257
251
  // setLookAhead.
258
252
  const initializeAddressSubscriptions = async () => {
259
253
  const addressBalanceChanges
@@ -269,10 +263,10 @@ var _utils3 = require('./utils');
269
263
  format,
270
264
  changeIndex: branch
271
265
  }
272
- const branchAddressCount = processor.numAddressesByFormatPath(
266
+ const branchAddressCount = dataLayer.numAddressesByFormatPath(
273
267
  changePath
274
268
  )
275
- // If the processor has not processed any addresses then the loop
269
+ // If the DataLayer has not processed any addresses then the loop
276
270
  // condition will only iterate once when branchAddressCount is 0 for the
277
271
  // first address in the derivation path.
278
272
  for (
@@ -280,29 +274,29 @@ var _utils3 = require('./utils');
280
274
  addressIndex < branchAddressCount;
281
275
  addressIndex++
282
276
  ) {
283
- const processorAddress = await processor.fetchAddress({
277
+ const addressData = await dataLayer.fetchAddress({
284
278
  format,
285
279
  changeIndex: branch,
286
280
  addressIndex
287
281
  })
288
- if (processorAddress == null) {
282
+ if (addressData == null) {
289
283
  throw new Error(
290
- `Missing processor address ${format} ${branch} ${addressIndex} during initialization`
284
+ `Missing data-layer address with '${format}/${branch}/${addressIndex}' path during initialization`
291
285
  )
292
286
  }
293
287
  const { address } = walletTools.scriptPubkeyToAddress({
294
288
  changePath,
295
- scriptPubkey: processorAddress.scriptPubkey
289
+ scriptPubkey: addressData.scriptPubkey
296
290
  })
297
291
  addressesToSubscribe.add(address)
298
- if (processorAddress.balance != null) {
292
+ if (addressData.balance != null) {
299
293
  addressBalanceChanges.push({
300
- scriptPubkey: processorAddress.scriptPubkey,
301
- balance: processorAddress.balance
294
+ scriptPubkey: addressData.scriptPubkey,
295
+ balance: addressData.balance
302
296
  })
303
297
  }
304
298
  }
305
- addToAddressSubscribeCache(commonArgs.taskCache, addressesToSubscribe, {
299
+ addToAddressSubscribeCache(common.taskCache, addressesToSubscribe, {
306
300
  format,
307
301
  changeIndex: branch
308
302
  })
@@ -348,11 +342,12 @@ var _utils3 = require('./utils');
348
342
  address: publicAddress,
349
343
  nativeBalance = '0',
350
344
  legacyAddress
351
- } = await internalGetFreshAddress({
352
- ...commonArgs,
353
- format: privateKeyFormat,
345
+ } = await internalGetFreshAddress(common, {
354
346
  forceIndex,
355
- changeIndex: branch
347
+ changePath: {
348
+ format: privateKeyFormat,
349
+ changeIndex: branch
350
+ }
356
351
  })
357
352
 
358
353
  const freshAddress = {
@@ -378,11 +373,12 @@ var _utils3 = require('./utils');
378
373
  const {
379
374
  address,
380
375
  nativeBalance = '0'
381
- } = await internalGetFreshAddress({
382
- ...commonArgs,
383
- format,
376
+ } = await internalGetFreshAddress(common, {
384
377
  forceIndex,
385
- changeIndex: branch
378
+ changePath: {
379
+ format,
380
+ changeIndex: branch
381
+ }
386
382
  })
387
383
 
388
384
  freshAddress.segwitAddress = address
@@ -395,10 +391,10 @@ var _utils3 = require('./utils');
395
391
 
396
392
  async deriveScriptAddress(script) {
397
393
  const { address } = await internalDeriveScriptAddress({
398
- walletTools: commonArgs.walletTools,
399
- engineInfo: commonArgs.pluginInfo.engineInfo,
400
- processor: commonArgs.processor,
401
- taskCache: commonArgs.taskCache,
394
+ walletTools: common.walletTools,
395
+ engineInfo: common.pluginInfo.engineInfo,
396
+ dataLayer: common.dataLayer,
397
+ taskCache: common.taskCache,
402
398
  format: walletInfo.keys.privateKeyFormat,
403
399
  script
404
400
  })
@@ -410,8 +406,8 @@ var _utils3 = require('./utils');
410
406
  async addGapLimitAddresses(addresses) {
411
407
  const promises = addresses.map(async address => {
412
408
  const scriptPubkey = walletTools.addressToScriptPubkey(address)
413
- await processor.saveAddress(
414
- _types5.makeIAddress.call(void 0, {
409
+ await dataLayer.saveAddress(
410
+ _types5.makeAddressData.call(void 0, {
415
411
  scriptPubkey,
416
412
  used: true
417
413
  })
@@ -457,8 +453,8 @@ var _utils3 = require('./utils');
457
453
  })
458
454
 
459
455
  // Make a new IAddress and save it
460
- await processor.saveAddress(
461
- _types5.makeIAddress.call(void 0, { scriptPubkey, redeemScript, path })
456
+ await dataLayer.saveAddress(
457
+ _types5.makeAddressData.call(void 0, { scriptPubkey, redeemScript, path })
462
458
  )
463
459
 
464
460
  taskCache.addressSubscribeCache[address] = {
@@ -469,7 +465,6 @@ var _utils3 = require('./utils');
469
465
  }
470
466
  },
471
467
  async processUtxos(utxos) {
472
- // Map of scriptPubkey to IUTXOs
473
468
  const utxoMap = new Map()
474
469
  const utxoIds = new Set()
475
470
 
@@ -487,7 +482,7 @@ var _utils3 = require('./utils');
487
482
  // Process UTXO sets for each scriptPubkey in map
488
483
  for (const [scriptPubkey, utxos] of utxoMap.entries()) {
489
484
  // Get saved utxo set
490
- const savedUtxos = await processor.fetchUtxos({ scriptPubkey })
485
+ const savedUtxos = await dataLayer.fetchUtxos({ scriptPubkey })
491
486
  // Filter UTXOs to de-duplicate (and undefined utxo as a type assert)
492
487
  const filteredUtxos = savedUtxos.filter(
493
488
  utxo => utxo != null && !utxoIds.has(_optionalChain([utxo, 'optionalAccess', _ => _.id]))
@@ -496,15 +491,62 @@ var _utils3 = require('./utils');
496
491
  // Add updated utxos to utxo set
497
492
  const combinedUtxos = [...filteredUtxos, ...utxos]
498
493
 
499
- await processProcessorUtxos({
500
- ...commonArgs,
494
+ await processDataLayerUtxos(common, {
501
495
  scriptPubkey,
502
496
  utxos: combinedUtxos
503
497
  })
504
498
  }
505
499
  }
506
500
  }
507
- } exports.makeUtxoEngineState = makeUtxoEngineState;
501
+ } exports.makeUtxoEngineProcessor = makeUtxoEngineProcessor;
502
+
503
+ const internalDeriveScriptAddress = async (args
504
+
505
+
506
+
507
+
508
+
509
+
510
+
511
+
512
+
513
+
514
+ ) => {
515
+ const { walletTools, engineInfo, dataLayer, format, taskCache, script } = args
516
+ if (engineInfo.scriptTemplates == null) {
517
+ throw new Error(
518
+ `cannot derive script address ${script} without defined script template`
519
+ )
520
+ }
521
+
522
+ const scriptTemplate = engineInfo.scriptTemplates[script]
523
+
524
+ const path = {
525
+ format,
526
+ changeIndex: _keymanager.derivationLevelScriptHash.call(void 0, scriptTemplate),
527
+ addressIndex: 0
528
+ }
529
+
530
+ // save the address to the dataLayer and add it to the cache
531
+ const { address, scriptPubkey, redeemScript } = walletTools.getScriptAddress({
532
+ path,
533
+ scriptTemplate
534
+ })
535
+ await dataLayer.saveAddress(
536
+ _types5.makeAddressData.call(void 0, { scriptPubkey, redeemScript, path })
537
+ )
538
+ const addresses = new Set()
539
+ addresses.add(address)
540
+ addToAddressSubscribeCache(taskCache, addresses, {
541
+ format: path.format,
542
+ changeIndex: path.changeIndex
543
+ })
544
+ return { address, scriptPubkey, redeemScript }
545
+ }
546
+
547
+ const internalGetFreshAddress = async (
548
+ common,
549
+ args
508
550
 
509
551
 
510
552
 
@@ -512,9 +554,42 @@ var _utils3 = require('./utils');
512
554
 
513
555
 
514
556
 
557
+ ) => {
558
+ const { changePath, forceIndex } = args
515
559
 
560
+ const numAddresses = common.dataLayer.numAddressesByFormatPath(changePath)
516
561
 
562
+ const path = {
563
+ format: changePath.format,
564
+ changeIndex: changePath.changeIndex,
565
+ // while syncing, we may hit negative numbers when only subtracting. Use the address at /0 in that case.
566
+ addressIndex: Math.max(
567
+ numAddresses - common.pluginInfo.engineInfo.gapLimit,
568
+ 0
569
+ )
570
+ }
571
+ if (forceIndex != null) {
572
+ path.addressIndex = forceIndex
573
+ }
517
574
 
575
+ const iAddress = await common.dataLayer.fetchAddress(path)
576
+ const nativeBalance = _nullishCoalesce(_optionalChain([iAddress, 'optionalAccess', _2 => _2.balance]), () => ( '0'))
577
+ const { scriptPubkey } =
578
+ await _asyncNullishCoalesce(iAddress, async () => ( (await common.walletTools.getScriptPubkey(path))))
579
+
580
+ if (scriptPubkey == null) {
581
+ throw new Error('Unknown address path')
582
+ }
583
+ const address = common.walletTools.scriptPubkeyToAddress({
584
+ changePath: path,
585
+ scriptPubkey
586
+ })
587
+
588
+ return {
589
+ ...address,
590
+ nativeBalance
591
+ }
592
+ }
518
593
 
519
594
 
520
595
 
@@ -573,37 +648,41 @@ var _utils3 = require('./utils');
573
648
 
574
649
 
575
650
 
576
- const setLookAhead = async (common) => {
577
- const {
578
- pluginInfo: { engineInfo },
579
- lock,
580
- processor,
581
- walletFormats,
582
- walletTools
583
- } = common
584
651
 
652
+
653
+
654
+
655
+
656
+ const setLookAhead = async (common) => {
585
657
  // Wait for the lock to be released before continuing invocation.
586
658
  // This is to ensure that setLockAhead is not called while the lock is held.
587
- await lock.acquireAsync()
659
+ await common.lock.acquireAsync()
588
660
 
589
661
  try {
590
- for (const format of walletFormats) {
591
- const branches = _utils3.getFormatSupportedBranches.call(void 0, engineInfo, format)
662
+ for (const format of common.walletFormats) {
663
+ const branches = _utils3.getFormatSupportedBranches.call(void 0,
664
+ common.pluginInfo.engineInfo,
665
+ format
666
+ )
592
667
  for (const branch of branches) {
593
668
  await deriveKeys({ format, changeIndex: branch })
594
669
  }
595
670
  }
596
671
  } finally {
597
- lock.release()
672
+ common.lock.release()
598
673
  }
599
674
 
600
675
  async function deriveKeys(changePath) {
601
676
  const addressesToSubscribe = new Set()
602
- const totalAddressCount = processor.numAddressesByFormatPath(changePath)
603
- let lastUsedIndex = await processor.lastUsedIndexByFormatPath(changePath)
677
+ const totalAddressCount = common.dataLayer.numAddressesByFormatPath(
678
+ changePath
679
+ )
680
+ let lastUsedIndex = await common.dataLayer.lastUsedIndexByFormatPath(
681
+ changePath
682
+ )
604
683
 
605
684
  // Loop until the total address count equals the lookahead count
606
- let lookAheadIndex = lastUsedIndex + engineInfo.gapLimit
685
+ let lookAheadIndex = lastUsedIndex + common.pluginInfo.engineInfo.gapLimit
607
686
  let nextAddressIndex = totalAddressCount
608
687
  while (nextAddressIndex <= lookAheadIndex) {
609
688
  const path = {
@@ -611,24 +690,28 @@ const setLookAhead = async (common) => {
611
690
  addressIndex: nextAddressIndex
612
691
  }
613
692
 
614
- const { scriptPubkey, redeemScript } = walletTools.getScriptPubkey(path)
615
- const { address } = walletTools.scriptPubkeyToAddress({
693
+ const { scriptPubkey, redeemScript } = common.walletTools.getScriptPubkey(
694
+ path
695
+ )
696
+ const { address } = common.walletTools.scriptPubkeyToAddress({
616
697
  changePath: path,
617
698
  scriptPubkey
618
699
  })
619
700
 
620
701
  // Make a new IAddress and save it
621
- await processor.saveAddress(
622
- _types5.makeIAddress.call(void 0, { scriptPubkey, redeemScript, path })
702
+ await common.dataLayer.saveAddress(
703
+ _types5.makeAddressData.call(void 0, { scriptPubkey, redeemScript, path })
623
704
  )
624
705
 
625
706
  // Add the displayAddress to the set of addresses to subscribe to after loop
626
707
  addressesToSubscribe.add(address)
627
708
 
628
709
  // Update the state for the loop
629
- lastUsedIndex = await processor.lastUsedIndexByFormatPath(changePath)
630
- lookAheadIndex = lastUsedIndex + engineInfo.gapLimit
631
- nextAddressIndex = processor.numAddressesByFormatPath(changePath)
710
+ lastUsedIndex = await common.dataLayer.lastUsedIndexByFormatPath(
711
+ changePath
712
+ )
713
+ lookAheadIndex = lastUsedIndex + common.pluginInfo.engineInfo.gapLimit
714
+ nextAddressIndex = common.dataLayer.numAddressesByFormatPath(changePath)
632
715
  }
633
716
 
634
717
  // Add all the addresses to the subscribe cache for registering subscriptions later
@@ -653,24 +736,27 @@ const addToAddressSubscribeCache = (
653
736
  })
654
737
  }
655
738
 
656
- const addToAddressTransactionCache = async (
739
+ const addToAddressForTransactionsCache = async (
657
740
  common,
658
- address,
659
- changePath,
660
- blockHeight,
661
- addressTransactionCache
741
+ args
742
+
743
+
744
+
745
+
746
+
662
747
  ) => {
663
- const { walletTools, processor } = common
748
+ const { address, changePath, addressForTransactionsCache } = args
749
+ let { blockHeight } = args
664
750
  // Fetch the blockHeight for the address from the database
665
- const scriptPubkey = walletTools.addressToScriptPubkey(address)
751
+ const scriptPubkey = common.walletTools.addressToScriptPubkey(address)
666
752
 
667
753
  if (blockHeight === 0) {
668
754
  const { lastQueriedBlockHeight = 0 } =
669
- await _asyncNullishCoalesce((await processor.fetchAddress(scriptPubkey)), async () => ( {}))
755
+ await _asyncNullishCoalesce((await common.dataLayer.fetchAddress(scriptPubkey)), async () => ( {}))
670
756
  blockHeight = lastQueriedBlockHeight
671
757
  }
672
758
 
673
- addressTransactionCache[address] = {
759
+ addressForTransactionsCache[address] = {
674
760
  processing: false,
675
761
  path: changePath,
676
762
  page: 1, // Page starts on 1
@@ -678,88 +764,96 @@ const addToAddressTransactionCache = async (
678
764
  }
679
765
  }
680
766
 
767
+ const transactionChanged = async (args
681
768
 
682
769
 
683
770
 
684
771
 
685
772
 
686
773
 
687
-
688
-
689
-
690
- const transactionChanged = async (
691
- args
692
774
  ) => {
693
- const { emitter, walletTools, processor, pluginInfo, tx, walletId } = args
775
+ const { dataLayer, emitter, pluginInfo, tx, walletTools, walletId } = args
694
776
  emitter.emit(_EngineEmitter.EngineEvent.TRANSACTIONS_CHANGED, [
695
- await _ProcessorTransaction.toEdgeTransaction.call(void 0, {
777
+ await _TransactionData.toEdgeTransaction.call(void 0, {
696
778
  walletId,
697
779
  tx,
698
780
  walletTools,
699
- processor,
781
+ dataLayer,
700
782
  pluginInfo
701
783
  })
702
784
  ])
703
785
  }; exports.transactionChanged = transactionChanged
704
786
 
705
- const pickNextTask = async (
706
- args,
707
- serverUri
708
- ) => {
709
- const { pluginInfo, taskCache, serverStates } = args
787
+ /**
788
+ * Some currencies require an additional blockbook payload 'getTransactionSpecific' in order
789
+ * to provide all relevant transaction data. Since this is currency-specific, we can limit
790
+ * the usage to currencies that require it.
791
+ **/
792
+ const needsTxSpecific = (common) => {
793
+ return common.pluginInfo.engineInfo.txSpecificHandling != null
794
+ }
795
+
796
+ /**
797
+ * The pickNextTask generator is responsible for selecting the next WsTask
798
+ * to be done by the network layer. It will yield WsTasks or booleans for early
799
+ * exit, and it will return a boolean when it's done.
800
+ */
801
+
802
+
803
+
710
804
 
805
+
806
+
807
+
808
+ async function* pickNextTask(
809
+ common,
810
+ serverUri
811
+ ) {
711
812
  const {
813
+ addressForTransactionsCache,
814
+ addressForUtxosCache,
712
815
  addressSubscribeCache,
713
- addressUtxoCache,
714
- rawUtxoCache,
715
- processorUtxoCache,
716
- addressTransactionCache,
717
- updateTransactionCache,
718
- updateTransactionSpecificCache
719
- } = taskCache
816
+ blockbookUtxoCache,
817
+ dataLayerUtxoCache,
818
+ transactionSpecificUpdateCache,
819
+ transactionUpdateCache
820
+ } = common.taskCache
720
821
 
721
- /**
722
- * Some currencies require an additional blockbook payload 'getTransactionSpecific' in order
723
- * to provide all relevant transaction data. Since this is currency-specific, we can limit
724
- * the useage to currencies that require it.
725
- **/
726
- const needsTxSpecific = pluginInfo.engineInfo.txSpecificHandling != null
727
-
728
- const serverState = serverStates.getServerState(serverUri)
729
- if (serverState == null) return
822
+ const serverState = common.serverStates.getServerState(serverUri)
823
+ if (serverState == null) return false
730
824
 
731
825
  // subscribe all servers to new blocks
732
826
  if (serverState.blockSubscriptionStatus === 'unsubscribed') {
733
- serverStates.watchBlocks(serverUri)
827
+ common.serverStates.watchBlocks(serverUri)
734
828
  return true
735
829
  }
736
830
 
737
831
  // Loop processed utxos, these are just database ops, triggers setLookAhead
738
- if (Object.keys(processorUtxoCache).length > 0) {
739
- for (const [scriptPubkey, state] of Object.entries(processorUtxoCache)) {
832
+ if (Object.keys(dataLayerUtxoCache).length > 0) {
833
+ for (const [scriptPubkey, cacheItem] of Object.entries(
834
+ dataLayerUtxoCache
835
+ )) {
740
836
  // Only process when all utxos for a specific address have been gathered
741
- if (!state.processing && state.full) {
742
- state.processing = true
743
- await processProcessorUtxos({
744
- ...args,
837
+ if (!cacheItem.processing && cacheItem.full) {
838
+ cacheItem.processing = true
839
+ await processDataLayerUtxos(common, {
745
840
  scriptPubkey,
746
- utxos: state.utxos
841
+ utxos: cacheItem.utxos
747
842
  })
748
- _utils.removeItem.call(void 0, processorUtxoCache, scriptPubkey)
843
+ _utils.removeItem.call(void 0, dataLayerUtxoCache, scriptPubkey)
749
844
  return true
750
845
  }
751
846
  }
752
847
  }
753
848
 
754
849
  // Loop unparsed utxos, some require a network call to get the full tx data
755
- for (const [utxoId, state] of Object.entries(rawUtxoCache)) {
756
- const utxo = state.blockbookUtxo
757
- if (utxo == null) continue
758
- if (!state.processing) {
850
+ for (const [utxoId, cacheItem] of Object.entries(blockbookUtxoCache)) {
851
+ const utxo = cacheItem.blockbookUtxo
852
+ if (!cacheItem.processing) {
759
853
  // check if we need to fetch additional network content for legacy purpose type
760
854
  const purposeType = _utils3.pathToPurposeType.call(void 0,
761
- state.path,
762
- pluginInfo.engineInfo.scriptTemplates
855
+ cacheItem.path,
856
+ common.pluginInfo.engineInfo.scriptTemplates
763
857
  )
764
858
  if (
765
859
  purposeType === _keymanager.BIP43PurposeTypeEnum.Airbitz ||
@@ -767,50 +861,36 @@ const addToAddressTransactionCache = async (
767
861
  purposeType === _keymanager.BIP43PurposeTypeEnum.ReplayProtection
768
862
  ) {
769
863
  // if we do need to make a network call, check with the serverState
770
- if (!serverStates.serverCanGetTx(serverUri, utxo.txid)) return
864
+ if (!common.serverStates.serverCanGetTx(serverUri, utxo.txid))
865
+ return false
771
866
  }
772
- state.processing = true
773
- _utils.removeItem.call(void 0, rawUtxoCache, utxoId)
774
- const wsTask = await processRawUtxo({
775
- ...args,
776
- ...state,
777
- address: state.address,
867
+ cacheItem.processing = true
868
+ _utils.removeItem.call(void 0, blockbookUtxoCache, utxoId)
869
+ yield* processBlockbookUtxo(common, {
778
870
  serverUri,
779
- utxo,
780
- id: `${utxo.txid}_${utxo.vout}`
871
+ cacheItem
781
872
  })
782
- return _nullishCoalesce(wsTask, () => ( true))
783
873
  }
784
874
  }
785
875
 
786
876
  // Loop to process addresses to utxos
787
- for (const [address, state] of Object.entries(addressUtxoCache)) {
877
+ for (const [address, cacheItem] of Object.entries(addressForUtxosCache)) {
788
878
  // Check if we need to fetch address UTXOs
789
879
  if (
790
- !state.processing &&
791
- serverStates.serverCanGetAddress(serverUri, address)
880
+ !cacheItem.processing &&
881
+ common.serverStates.serverCanGetAddress(serverUri, address)
792
882
  ) {
793
- state.processing = true
883
+ cacheItem.processing = true
794
884
 
795
- _utils.removeItem.call(void 0, addressUtxoCache, address)
885
+ _utils.removeItem.call(void 0, addressForUtxosCache, address)
796
886
 
797
- // Fetch and process address UTXOs
798
- const wsTask = await processAddressUtxos({
799
- ...args,
800
- ...state,
887
+ // Fetch and process address for UTXOs
888
+ yield* processAddressForUtxos(common, {
801
889
  address,
890
+ cacheItem,
891
+ serverState,
802
892
  serverUri
803
893
  })
804
- wsTask.deferred.promise
805
- .then(() => {
806
- serverState.addresses.add(address)
807
- })
808
- .catch(err => {
809
- addressUtxoCache[address] = state
810
- console.error(err)
811
- args.log('error in addressUtxoCache:', err)
812
- })
813
- return wsTask
814
894
  }
815
895
  }
816
896
 
@@ -818,11 +898,11 @@ const addToAddressTransactionCache = async (
818
898
  if (Object.keys(addressSubscribeCache).length > 0) {
819
899
  // These are addresses to which the server has not subscribed
820
900
  const newAddresses = []
821
- const blockHeight = serverStates.getBlockHeight(serverUri)
901
+ const blockHeight = common.serverStates.getBlockHeight(serverUri)
822
902
 
823
903
  // Loop each address in the cache
824
- for (const [address, state] of Object.entries(addressSubscribeCache)) {
825
- const isAddressNewlySubscribed = !serverStates.serverIsAwareOfAddress(
904
+ for (const [address, cacheItem] of Object.entries(addressSubscribeCache)) {
905
+ const isAddressNewlySubscribed = !common.serverStates.serverIsAwareOfAddress(
826
906
  serverUri,
827
907
  address
828
908
  )
@@ -832,61 +912,52 @@ const addToAddressTransactionCache = async (
832
912
  newAddresses.push(address)
833
913
  }
834
914
 
835
- // Add to the addressTransactionCache if they're not yet added:
915
+ // Add to the addressForTransactionsCache if they're not yet added:
836
916
  // Only process newly watched addresses
837
- if (state.processing) continue
917
+ if (cacheItem.processing) continue
838
918
 
839
919
  // Add the newly watched addresses to the UTXO cache
840
920
  if (isAddressNewlySubscribed) {
841
- addressUtxoCache[address] = {
921
+ addressForUtxosCache[address] = {
842
922
  processing: false,
843
- path: state.path
923
+ path: cacheItem.path
844
924
  }
845
925
  }
846
926
 
847
- await addToAddressTransactionCache(
848
- args,
927
+ await addToAddressForTransactionsCache(common, {
849
928
  address,
850
- state.path,
929
+ changePath: cacheItem.path,
851
930
  blockHeight,
852
- addressTransactionCache
853
- )
854
- state.processing = true
931
+ addressForTransactionsCache
932
+ })
933
+ cacheItem.processing = true
855
934
  }
856
935
 
857
936
  // Subscribe to any new addresses
858
937
  if (newAddresses.length > 0) {
859
- serverStates.watchAddresses(serverUri, newAddresses)
938
+ common.serverStates.watchAddresses(serverUri, newAddresses)
860
939
  return true
861
940
  }
862
941
  }
863
942
 
864
943
  // filled when transactions potentially changed (e.g. through new block notification)
865
- if (Object.keys(updateTransactionSpecificCache).length > 0) {
944
+ if (Object.keys(transactionSpecificUpdateCache).length > 0) {
866
945
  let hasProcessedAtLeastOnce = false
867
- for (const [txId, state] of Object.entries(
868
- updateTransactionSpecificCache
946
+ for (const [txId, cacheItem] of Object.entries(
947
+ transactionSpecificUpdateCache
869
948
  )) {
870
- if (!state.processing && serverStates.serverCanGetTx(serverUri, txId)) {
949
+ if (
950
+ !cacheItem.processing &&
951
+ common.serverStates.serverCanGetTx(serverUri, txId)
952
+ ) {
871
953
  hasProcessedAtLeastOnce = true
872
- state.processing = true
873
- _utils.removeItem.call(void 0, updateTransactionSpecificCache, txId)
874
- const updateTransactionSpecificTask = updateTransactionsSpecific({
875
- ...args,
954
+ cacheItem.processing = true
955
+ _utils.removeItem.call(void 0, transactionSpecificUpdateCache, txId)
956
+ yield* processTransactionsSpecificUpdate(common, {
957
+ serverState,
876
958
  serverUri,
877
959
  txId
878
960
  })
879
- // once resolved, add the txid to the server cache
880
- updateTransactionSpecificTask.deferred.promise
881
- .then(() => {
882
- serverState.txids.add(txId)
883
- })
884
- .catch(err => {
885
- updateTransactionSpecificCache[txId] = state
886
- console.error(err)
887
- args.log('error in updateTransactionSpecificCache:', err)
888
- })
889
- return updateTransactionSpecificTask
890
961
  }
891
962
  }
892
963
  // This condition prevents infinite loops
@@ -894,30 +965,21 @@ const addToAddressTransactionCache = async (
894
965
  }
895
966
 
896
967
  // filled when transactions potentially changed (e.g. through new block notification)
897
- if (Object.keys(updateTransactionCache).length > 0) {
968
+ if (Object.keys(transactionUpdateCache).length > 0) {
898
969
  let hasProcessedAtLeastOnce = false
899
- for (const [txId, state] of Object.entries(updateTransactionCache)) {
900
- if (!state.processing && serverStates.serverCanGetTx(serverUri, txId)) {
970
+ for (const [txId, cacheItem] of Object.entries(transactionUpdateCache)) {
971
+ if (
972
+ !cacheItem.processing &&
973
+ common.serverStates.serverCanGetTx(serverUri, txId)
974
+ ) {
901
975
  hasProcessedAtLeastOnce = true
902
- state.processing = true
903
- _utils.removeItem.call(void 0, updateTransactionCache, txId)
904
- const updateTransactionTask = updateTransactions({
905
- ...args,
976
+ cacheItem.processing = true
977
+ _utils.removeItem.call(void 0, transactionUpdateCache, txId)
978
+ yield* processTransactionUpdate(common, {
979
+ serverState,
906
980
  serverUri,
907
- needsTxSpecific,
908
981
  txId
909
982
  })
910
- // once resolved, add the txid to the server cache
911
- updateTransactionTask.deferred.promise
912
- .then(() => {
913
- serverState.txids.add(txId)
914
- })
915
- .catch(err => {
916
- updateTransactionCache[txId] = state
917
- console.error(err)
918
- args.log('error in updateTransactionCache:', err)
919
- })
920
- return updateTransactionTask
921
983
  }
922
984
  }
923
985
  // This condition prevents infinite loops
@@ -925,399 +987,276 @@ const addToAddressTransactionCache = async (
925
987
  }
926
988
 
927
989
  // loop to get and process transaction history of single addresses, triggers setLookAhead
928
- for (const [address, state] of Object.entries(addressTransactionCache)) {
990
+ for (const [address, cacheItem] of Object.entries(
991
+ addressForTransactionsCache
992
+ )) {
929
993
  if (
930
- !state.processing &&
931
- serverStates.serverCanGetAddress(serverUri, address)
994
+ !cacheItem.processing &&
995
+ common.serverStates.serverCanGetAddress(serverUri, address)
932
996
  ) {
933
- state.processing = true
997
+ cacheItem.processing = true
934
998
 
935
- _utils.removeItem.call(void 0, addressTransactionCache, address)
999
+ _utils.removeItem.call(void 0, addressForTransactionsCache, address)
936
1000
 
937
1001
  // Fetch and process address UTXOs
938
- const wsTask = await processAddressTransactions({
939
- ...args,
940
- addressTransactionState: state,
1002
+ yield* processAddressForTransactions(common, {
941
1003
  address,
942
- needsTxSpecific,
1004
+ cacheItem,
1005
+ serverState,
943
1006
  serverUri
944
1007
  })
945
- wsTask.deferred.promise
946
- .then(() => {
947
- serverState.addresses.add(address)
948
- })
949
- .catch(err => {
950
- addressTransactionCache[address] = state
951
- console.error(err)
952
- args.log('error in updateTransactionCache:', err)
953
- })
954
- return wsTask
955
1008
  }
956
1009
  }
957
- }; exports.pickNextTask = pickNextTask
958
-
959
-
960
1010
 
1011
+ // Nothing to do
1012
+ return false
1013
+ } exports.pickNextTask = pickNextTask;
961
1014
 
962
-
963
-
964
- const updateTransactionsSpecific = (
1015
+ /**
1016
+ * Process a transaction specific update from the TransactionSpecificUpdateCache
1017
+ * by querying the network for the transaction data using the specific handling
1018
+ * query and processing the data into the DataLayer.
1019
+ */
1020
+ async function* processTransactionsSpecificUpdate(
1021
+ common,
965
1022
  args
966
- ) => {
967
- const {
968
- walletInfo,
969
- emitter,
970
- walletTools,
971
- pluginInfo,
972
- processor,
973
- serverUri,
974
- txId,
975
- taskCache
976
- } = args
977
- const deferred = new _Deferred2.default()
978
- deferred.promise
979
- .then(async (txResponse) => {
980
- // Grab tx to update it
981
- const txs = await processor.fetchTransactions({ txId })
982
- let tx = txs[0]
983
- if (tx == null) return
984
-
985
- if (pluginInfo.engineInfo.txSpecificHandling != null) {
986
- // Do coin-specific things to it
987
- tx = pluginInfo.engineInfo.txSpecificHandling(tx, txResponse)
988
- }
989
-
990
- // Process and save new tx
991
- const processedTx = await processor.saveTransaction({
992
- tx
993
- })
994
-
995
- await exports.transactionChanged.call(void 0, {
996
- walletId: walletInfo.id,
997
- emitter,
998
- walletTools,
999
- processor,
1000
- pluginInfo,
1001
- tx: processedTx
1002
- })
1003
- })
1004
- .catch(err => {
1005
- console.error(err)
1006
- args.log('error in updateTransactionsSpecific:', err)
1007
- taskCache.updateTransactionSpecificCache[txId] = { processing: false }
1008
- })
1009
-
1010
- return args.serverStates.transactionSpecialQueryTask(
1011
- serverUri,
1012
- txId,
1013
- deferred
1014
- )
1015
- }
1016
-
1017
1023
 
1018
1024
 
1019
1025
 
1020
1026
 
1027
+ ) {
1028
+ const { serverState, serverUri, txId } = args
1029
+ try {
1030
+ const txResponse = yield* common.serverStates.transactionSpecialQueryTask(
1031
+ serverUri,
1032
+ txId
1033
+ )
1034
+ // Grab tx to update it
1035
+ const txs = await common.dataLayer.fetchTransactions({ txId })
1036
+ let tx = txs[0]
1037
+ if (tx == null) return true
1038
+
1039
+ if (common.pluginInfo.engineInfo.txSpecificHandling != null) {
1040
+ // Do coin-specific things to it
1041
+ tx = common.pluginInfo.engineInfo.txSpecificHandling(tx, txResponse)
1042
+ }
1021
1043
 
1022
-
1023
- const updateTransactions = (
1024
- args
1025
- ) => {
1026
- const {
1027
- walletInfo,
1028
- emitter,
1029
- walletTools,
1030
- txId,
1031
- needsTxSpecific,
1032
- pluginInfo,
1033
- processor,
1034
- serverUri,
1035
- taskCache
1036
- } = args
1037
- const deferred = new _Deferred2.default()
1038
- deferred.promise
1039
- .then(async (txResponse) => {
1040
- // check if raw tx is still not confirmed, if so, don't change anything
1041
- if (txResponse.blockHeight < 1) return
1042
- // Create new tx from raw tx
1043
- const tx = processTransactionResponse({ ...args, txResponse })
1044
- // Remove any existing input utxos from the processor
1045
- for (const input of tx.inputs) {
1046
- await processor.removeUtxos([`${input.txId}_${input.outputIndex}`])
1047
- }
1048
- // Update output utxos's blockHeight any existing input utxos from the processor
1049
- const utxoIds = tx.outputs.map(output => `${tx.txid}_${output.n}`)
1050
- const utxos = await processor.fetchUtxos({
1051
- utxoIds
1052
- })
1053
- for (const utxo of utxos) {
1054
- if (utxo == null) continue
1055
- utxo.blockHeight = tx.blockHeight
1056
- await processor.saveUtxo(utxo)
1057
- }
1058
- // Process and save new tx
1059
- const processedTx = await processor.saveTransaction({
1060
- tx
1061
- })
1062
-
1063
- await exports.transactionChanged.call(void 0, {
1064
- walletId: walletInfo.id,
1065
- emitter,
1066
- walletTools,
1067
- processor,
1068
- pluginInfo,
1069
- tx: processedTx
1070
- })
1071
-
1072
- if (needsTxSpecific) {
1073
- // Add task to grab transactionSpecific payload
1074
- taskCache.updateTransactionSpecificCache[txId] = {
1075
- processing: false
1076
- }
1077
- }
1078
- })
1079
- .catch(err => {
1080
- console.error(err)
1081
- args.log('error in updateTransactions:', err)
1082
- taskCache.updateTransactionCache[txId] = { processing: false }
1044
+ // Process and save new tx
1045
+ const processedTx = await common.dataLayer.saveTransaction({
1046
+ tx
1083
1047
  })
1084
1048
 
1085
- return args.serverStates.transactionQueryTask(serverUri, txId, deferred)
1086
- }
1087
-
1088
-
1089
-
1090
-
1091
-
1092
-
1093
-
1094
-
1095
-
1096
-
1097
-
1098
-
1099
-
1100
-
1101
-
1102
-
1103
- const internalDeriveScriptAddress = async ({
1104
- walletTools,
1105
- engineInfo,
1106
- processor,
1107
- format,
1108
- taskCache,
1109
- script
1110
- }) => {
1111
- if (engineInfo.scriptTemplates == null) {
1112
- throw new Error(
1113
- `cannot derive script address ${script} without defined script template`
1114
- )
1115
- }
1049
+ await exports.transactionChanged.call(void 0, {
1050
+ walletId: common.walletInfo.id,
1051
+ emitter: common.emitter,
1052
+ walletTools: common.walletTools,
1053
+ dataLayer: common.dataLayer,
1054
+ pluginInfo: common.pluginInfo,
1055
+ tx: processedTx
1056
+ })
1116
1057
 
1117
- const scriptTemplate = engineInfo.scriptTemplates[script]
1058
+ // Add the txid to the server cache
1059
+ serverState.txids.add(txId)
1118
1060
 
1119
- const path = {
1120
- format,
1121
- changeIndex: _keymanager.derivationLevelScriptHash.call(void 0, scriptTemplate),
1122
- addressIndex: 0
1061
+ return true
1062
+ } catch (err) {
1063
+ console.error(err)
1064
+ common.log('error while processing transaction specific update:', err)
1065
+ common.taskCache.transactionSpecificUpdateCache[txId] = {
1066
+ processing: false
1067
+ }
1068
+ return false
1123
1069
  }
1124
-
1125
- // save the address to the processor and add it to the cache
1126
- const { address, scriptPubkey, redeemScript } = walletTools.getScriptAddress({
1127
- path,
1128
- scriptTemplate
1129
- })
1130
- await processor.saveAddress(
1131
- _types5.makeIAddress.call(void 0, { scriptPubkey, redeemScript, path })
1132
- )
1133
- const addresses = new Set()
1134
- addresses.add(address)
1135
- addToAddressSubscribeCache(taskCache, addresses, {
1136
- format: path.format,
1137
- changeIndex: path.changeIndex
1138
- })
1139
- return { address, scriptPubkey, redeemScript }
1140
1070
  }
1141
1071
 
1072
+ /**
1073
+ * Processes a transaction update from the TransactionUpdateCache by querying
1074
+ * the network for the transaction data and processing it into the DataLayer.
1075
+ */
1076
+ async function* processTransactionUpdate(
1077
+ common,
1078
+ args
1142
1079
 
1143
1080
 
1144
1081
 
1145
1082
 
1083
+ ) {
1084
+ const { serverState, serverUri, txId } = args
1146
1085
 
1147
-
1148
-
1149
-
1150
-
1151
-
1152
- const internalGetFreshAddress = async (
1153
- args
1154
- ) => {
1155
- const {
1156
- format,
1157
- changeIndex: branch,
1158
- walletTools,
1159
- processor,
1160
- forceIndex
1161
- } = args
1162
-
1163
- const numAddresses = processor.numAddressesByFormatPath({
1164
- format,
1165
- changeIndex: branch
1166
- })
1167
-
1168
- const path = {
1169
- format,
1170
- changeIndex: branch,
1171
- // while syncing, we may hit negative numbers when only subtracting. Use the address at /0 in that case.
1172
- addressIndex: Math.max(
1173
- numAddresses - args.pluginInfo.engineInfo.gapLimit,
1174
- 0
1086
+ try {
1087
+ const txResponse = yield* common.serverStates.transactionQueryTask(
1088
+ serverUri,
1089
+ txId
1175
1090
  )
1176
- }
1177
- if (forceIndex != null) {
1178
- path.addressIndex = forceIndex
1179
- }
1091
+ // check if blockbook tx is still not confirmed, if so, don't change anything
1092
+ if (txResponse.blockHeight < 1) return false
1093
+ // Create new tx from raw tx
1094
+ const tx = processTransactionResponse(common, { txResponse })
1095
+ // Remove any existing input utxos from the dataLayer
1096
+ for (const input of tx.inputs) {
1097
+ await common.dataLayer.removeUtxos([`${input.txId}_${input.outputIndex}`])
1098
+ }
1099
+ // Update output utxos's blockHeight any existing input utxos from the dataLayer
1100
+ const utxoIds = tx.outputs.map(output => `${tx.txid}_${output.n}`)
1101
+ const utxos = await common.dataLayer.fetchUtxos({
1102
+ utxoIds
1103
+ })
1104
+ for (const utxo of utxos) {
1105
+ if (utxo == null) continue
1106
+ utxo.blockHeight = tx.blockHeight
1107
+ await common.dataLayer.saveUtxo(utxo)
1108
+ }
1109
+ // Process and save new tx
1110
+ const processedTx = await common.dataLayer.saveTransaction({
1111
+ tx
1112
+ })
1180
1113
 
1181
- const iAddress = await processor.fetchAddress(path)
1182
- const nativeBalance = _nullishCoalesce(_optionalChain([iAddress, 'optionalAccess', _2 => _2.balance]), () => ( '0'))
1183
- const { scriptPubkey } = await _asyncNullishCoalesce(iAddress, async () => ( (await walletTools.getScriptPubkey(path))))
1114
+ await exports.transactionChanged.call(void 0, {
1115
+ walletId: common.walletInfo.id,
1116
+ emitter: common.emitter,
1117
+ walletTools: common.walletTools,
1118
+ dataLayer: common.dataLayer,
1119
+ pluginInfo: common.pluginInfo,
1120
+ tx: processedTx
1121
+ })
1184
1122
 
1185
- if (scriptPubkey == null) {
1186
- throw new Error('Unknown address path')
1187
- }
1188
- const address = walletTools.scriptPubkeyToAddress({
1189
- changePath: path,
1190
- scriptPubkey
1191
- })
1123
+ if (needsTxSpecific(common)) {
1124
+ // Add task to grab transactionSpecific payload
1125
+ common.taskCache.transactionSpecificUpdateCache[txId] = {
1126
+ processing: false
1127
+ }
1128
+ }
1192
1129
 
1193
- return {
1194
- ...address,
1195
- nativeBalance
1130
+ // Add the txid to the server cache
1131
+ serverState.txids.add(txId)
1132
+
1133
+ return true
1134
+ } catch (err) {
1135
+ console.error(err)
1136
+ common.log('error while processing transaction update:', err)
1137
+ common.taskCache.transactionUpdateCache[txId] = { processing: false }
1138
+ return false
1196
1139
  }
1197
1140
  }
1198
1141
 
1142
+ /**
1143
+ * Processes an address for transactions by querying the network for the
1144
+ * transaction data.
1145
+ */
1146
+ async function* processAddressForTransactions(
1147
+ common,
1148
+ args
1199
1149
 
1200
1150
 
1201
1151
 
1202
1152
 
1203
1153
 
1154
+ ) {
1155
+ const { address, cacheItem, serverState, serverUri } = args
1156
+ const { page = 1, blockHeight } = cacheItem
1157
+ const addressForTransactionsCache =
1158
+ common.taskCache.addressForTransactionsCache
1204
1159
 
1205
-
1206
- const processAddressTransactions = async (
1207
- args
1208
- ) => {
1209
- const {
1210
- walletInfo,
1211
- address,
1212
- addressTransactionState,
1213
- emitter,
1214
- needsTxSpecific,
1215
- pluginInfo,
1216
- processor,
1217
- walletTools,
1218
- taskCache,
1219
- pluginState,
1220
- serverUri
1221
- } = args
1222
- const { page = 1, blockHeight } = addressTransactionState
1223
- const addressTransactionCache = taskCache.addressTransactionCache
1224
-
1225
- const scriptPubkey = walletTools.addressToScriptPubkey(address)
1226
- const addressData = await processor.fetchAddress(scriptPubkey)
1160
+ const scriptPubkey = common.walletTools.addressToScriptPubkey(address)
1161
+ const addressData = await common.dataLayer.fetchAddress(scriptPubkey)
1227
1162
  if (addressData == null) {
1228
1163
  throw new Error(`could not find address with script pubkey ${scriptPubkey}`)
1229
1164
  }
1230
1165
 
1231
- const queryTime = Date.now()
1232
- const deferred = new _Deferred2.default()
1233
- deferred.promise
1234
- .then(async (value) => {
1235
- pluginState.serverScoreUp(serverUri, Date.now() - queryTime)
1236
- const { transactions = [], txs, unconfirmedTxs, totalPages } = value
1237
-
1238
- // If address is used and previously not marked as used, mark as used.
1239
- const used = txs > 0 || unconfirmedTxs > 0
1240
- if (!addressData.used && used && page === 1) {
1241
- addressData.used = true
1166
+ try {
1167
+ const addressResponse = yield* common.serverStates.addressQueryTask(
1168
+ serverUri,
1169
+ address,
1170
+ {
1171
+ lastQueriedBlockHeight: addressData.lastQueriedBlockHeight,
1172
+ page
1242
1173
  }
1174
+ )
1175
+ const {
1176
+ transactions = [],
1177
+ txs,
1178
+ unconfirmedTxs,
1179
+ totalPages
1180
+ } = addressResponse
1181
+
1182
+ // If address is used and previously not marked as used, mark as used.
1183
+ const used = txs > 0 || unconfirmedTxs > 0
1184
+ if (!addressData.used && used && page === 1) {
1185
+ addressData.used = true
1186
+ }
1243
1187
 
1244
- // Process and save the address's transactions
1245
- for (const txResponse of transactions) {
1246
- const tx = processTransactionResponse({ ...args, txResponse })
1247
- const processedTx = await processor.saveTransaction({
1248
- tx,
1249
- scriptPubkeys: [scriptPubkey]
1250
- })
1251
- await exports.transactionChanged.call(void 0, {
1252
- walletId: walletInfo.id,
1253
- emitter,
1254
- walletTools,
1255
- processor,
1256
- pluginInfo,
1257
- tx: processedTx
1258
- })
1188
+ // Process and save the address's transactions
1189
+ for (const txResponse of transactions) {
1190
+ const tx = processTransactionResponse(common, { txResponse })
1191
+ const processedTx = await common.dataLayer.saveTransaction({
1192
+ tx,
1193
+ scriptPubkeys: [scriptPubkey]
1194
+ })
1195
+ await exports.transactionChanged.call(void 0, {
1196
+ walletId: common.walletInfo.id,
1197
+ emitter: common.emitter,
1198
+ walletTools: common.walletTools,
1199
+ dataLayer: common.dataLayer,
1200
+ pluginInfo: common.pluginInfo,
1201
+ tx: processedTx
1202
+ })
1259
1203
 
1260
- if (needsTxSpecific) {
1261
- // Add task to grab transactionSpecific payload
1262
- taskCache.updateTransactionSpecificCache[tx.txid] = {
1263
- processing: false
1264
- }
1204
+ if (needsTxSpecific(common)) {
1205
+ // Add task to grab transactionSpecific payload
1206
+ common.taskCache.transactionSpecificUpdateCache[tx.txid] = {
1207
+ processing: false
1265
1208
  }
1266
1209
  }
1210
+ }
1267
1211
 
1268
- // Halt on finishing the processing of address transaction until
1269
- // we have progressed through all of the blockbook pages
1270
- if (page < totalPages) {
1271
- // Add the address back to the cache, incrementing the page
1272
- addressTransactionCache[address] = {
1273
- ...addressTransactionState,
1274
- processing: false,
1275
- page: page + 1
1276
- }
1277
- return
1212
+ // Halt on finishing the processing of address transaction until
1213
+ // we have progressed through all of the blockbook pages
1214
+ if (page < totalPages) {
1215
+ // Add the address back to the cache, incrementing the page
1216
+ addressForTransactionsCache[address] = {
1217
+ ...cacheItem,
1218
+ processing: false,
1219
+ page: page + 1
1278
1220
  }
1221
+ return true
1222
+ }
1279
1223
 
1280
- // Update the lastQueriedBlockHeight for the address
1281
- addressData.lastQueriedBlockHeight = blockHeight
1282
-
1283
- // Save/update the fully-processed address
1284
- await processor.saveAddress(addressData)
1285
-
1286
- // Update the progress now that the transactions for an address have processed
1287
- await args.updateProgressRatio()
1224
+ // Update the lastQueriedBlockHeight for the address
1225
+ addressData.lastQueriedBlockHeight = blockHeight
1288
1226
 
1289
- // Call setLookAhead to update the lookahead
1290
- await setLookAhead(args)
1291
- })
1292
- .catch(err => {
1293
- // Log the error for debugging purposes without crashing the engine
1294
- // This will cause frozen wallet syncs
1295
- console.error(err)
1296
- addressTransactionCache[address] = addressTransactionState
1297
- })
1298
-
1299
- return args.serverStates.addressQueryTask(
1300
- serverUri,
1301
- address,
1302
- {
1303
- lastQueriedBlockHeight: addressData.lastQueriedBlockHeight,
1304
- page
1305
- },
1306
- deferred
1307
- )
1308
- }
1227
+ // Save/update the fully-processed address
1228
+ await common.dataLayer.saveAddress(addressData)
1309
1229
 
1230
+ // Update the progress now that the transactions for an address have processed
1231
+ await common.updateProgressRatio()
1310
1232
 
1233
+ // Call setLookAhead to update the lookahead
1234
+ await setLookAhead(common)
1311
1235
 
1236
+ // Add the address to the server cache
1237
+ serverState.addresses.add(address)
1312
1238
 
1239
+ return true
1240
+ } catch (err) {
1241
+ // Log the error for debugging purposes without crashing the engine
1242
+ // This will cause frozen wallet syncs
1243
+ console.error(err)
1244
+ common.log('error while processing address for transactions:', err)
1245
+ addressForTransactionsCache[address] = { ...cacheItem, processing: false }
1246
+ return false
1247
+ }
1248
+ }
1313
1249
 
1250
+ /**
1251
+ * Processes a blockbook transaction response object (a blockbook transaction).
1252
+ * It will simply convert the blockbook transaction into a TransactionData
1253
+ * object to be saved in the DataLayer
1254
+ */
1314
1255
  const processTransactionResponse = (
1256
+ common,
1315
1257
  args
1316
1258
  ) => {
1317
- const {
1318
- txResponse,
1319
- pluginInfo: { coinInfo }
1320
- } = args
1259
+ const { txResponse } = args
1321
1260
  const inputs = txResponse.vin.map(vin => {
1322
1261
  const scriptPubkey =
1323
1262
  // Note: Blockbook has empirically not sent a hex value as the
@@ -1328,7 +1267,7 @@ const processTransactionResponse = (
1328
1267
  'unknown'
1329
1268
  )({
1330
1269
  address: vin.addresses[0],
1331
- coin: coinInfo.name
1270
+ coin: common.pluginInfo.coinInfo.name
1332
1271
  })
1333
1272
  return {
1334
1273
  txId: vin.txid,
@@ -1347,7 +1286,7 @@ const processTransactionResponse = (
1347
1286
  'unknown'
1348
1287
  )({
1349
1288
  address: vout.addresses[0],
1350
- coin: coinInfo.name
1289
+ coin: common.pluginInfo.coinInfo.name
1351
1290
  })))
1352
1291
  return {
1353
1292
  n: vout.n,
@@ -1370,87 +1309,88 @@ const processTransactionResponse = (
1370
1309
  }
1371
1310
  }
1372
1311
 
1312
+ /**
1313
+ * Process a given address for UTXO data by querying the network for UTXO data
1314
+ * and processing it into the `blockbookUtxoCache` to later be processed by
1315
+ * `processBlockbookUtxo`.
1316
+ */
1317
+ async function* processAddressForUtxos(
1318
+ common,
1319
+ args
1373
1320
 
1374
1321
 
1375
1322
 
1376
1323
 
1377
1324
 
1378
-
1379
-
1380
- const processAddressUtxos = async (
1381
- args
1382
- ) => {
1325
+ ) {
1326
+ const { address, cacheItem, serverState, serverUri } = args
1383
1327
  const {
1384
- address,
1385
- walletTools,
1386
- processor,
1387
- taskCache,
1388
- path,
1389
- pluginState,
1390
- serverUri
1391
- } = args
1392
- const { addressUtxoCache, rawUtxoCache, processorUtxoCache } = taskCache
1393
- const queryTime = Date.now()
1394
- const deferred = new _Deferred2.default()
1395
- deferred.promise
1396
- .then(async (utxos) => {
1397
- pluginState.serverScoreUp(serverUri, Date.now() - queryTime)
1398
- const scriptPubkey = walletTools.addressToScriptPubkey(address)
1399
- const addressData = await processor.fetchAddress(scriptPubkey)
1400
- if (addressData == null || addressData.path == null) {
1401
- return
1402
- }
1328
+ addressForUtxosCache,
1329
+ blockbookUtxoCache,
1330
+ dataLayerUtxoCache
1331
+ } = common.taskCache
1332
+ try {
1333
+ const utxos = yield* common.serverStates.utxoListQueryTask(
1334
+ serverUri,
1335
+ address
1336
+ )
1337
+ const scriptPubkey = common.walletTools.addressToScriptPubkey(address)
1338
+ const addressData = await common.dataLayer.fetchAddress(scriptPubkey)
1339
+ if (addressData == null || addressData.path == null) {
1340
+ return true
1341
+ }
1403
1342
 
1404
- if (utxos.length === 0) {
1405
- addToProcessorUtxoCache(processorUtxoCache, path, scriptPubkey, 0)
1406
- return
1407
- }
1343
+ if (utxos.length === 0) {
1344
+ addToDataLayerUtxoCache(
1345
+ dataLayerUtxoCache,
1346
+ cacheItem.path,
1347
+ scriptPubkey,
1348
+ 0
1349
+ )
1350
+ return true
1351
+ }
1408
1352
 
1409
- for (const utxo of utxos) {
1410
- const utxoId = `${utxo.txid}_${utxo.vout}`
1411
- rawUtxoCache[utxoId] = {
1412
- blockbookUtxo: utxo,
1413
- processing: false,
1414
- requiredCount: utxos.length,
1415
- path,
1416
- // TypeScript yells otherwise
1417
- address: { ...addressData, path: addressData.path }
1418
- }
1353
+ for (const utxo of utxos) {
1354
+ const utxoId = `${utxo.txid}_${utxo.vout}`
1355
+ blockbookUtxoCache[utxoId] = {
1356
+ blockbookUtxo: utxo,
1357
+ processing: false,
1358
+ requiredCount: utxos.length,
1359
+ path: cacheItem.path,
1360
+ // TypeScript yells otherwise
1361
+ address: { ...addressData, path: addressData.path }
1419
1362
  }
1420
- })
1421
- .catch(() => {
1422
- args.processing = false
1423
- addressUtxoCache[address] = {
1424
- processing: args.processing,
1425
- path
1426
- }
1427
- })
1428
-
1429
- return args.serverStates.utxoListQueryTask(serverUri, address, deferred)
1430
- }
1363
+ }
1431
1364
 
1365
+ serverState.addresses.add(address)
1432
1366
 
1367
+ return true
1368
+ } catch (err) {
1369
+ console.error(err)
1370
+ common.log('error while processing address for UTXOs:', err)
1371
+ addressForUtxosCache[address] = { ...cacheItem, processing: false }
1372
+ return false
1373
+ }
1374
+ }
1433
1375
 
1376
+ /**
1377
+ * Processes UtxoData from the DataLayerUtxoCache by saving/removing UTXOs
1378
+ * to/from the DataLayer and updating the address balance.
1379
+ */
1380
+ const processDataLayerUtxos = async (
1381
+ common,
1382
+ args
1434
1383
 
1435
1384
 
1436
1385
 
1437
- const processProcessorUtxos = async (
1438
- args
1439
1386
  ) => {
1440
- const {
1441
- utxos,
1442
- processor,
1443
- scriptPubkey,
1444
- log,
1445
- emitter,
1446
- pluginInfo: { currencyInfo }
1447
- } = args
1387
+ const { utxos, scriptPubkey } = args
1448
1388
 
1449
1389
  const updatedUtxos = Object.fromEntries(
1450
1390
  [...utxos].map(utxo => [utxo.id, utxo])
1451
1391
  )
1452
1392
  const utxoIdsToRemove = []
1453
- const currentUtxos = await processor.fetchUtxos({ scriptPubkey })
1393
+ const currentUtxos = await common.dataLayer.fetchUtxos({ scriptPubkey })
1454
1394
 
1455
1395
  //
1456
1396
  // Modify existing UTXO set
@@ -1475,7 +1415,7 @@ const processProcessorUtxos = async (
1475
1415
  }
1476
1416
 
1477
1417
  // Remove any spent UTXOs that have confirmations
1478
- await processor.removeUtxos(utxoIdsToRemove)
1418
+ await common.dataLayer.removeUtxos(utxoIdsToRemove)
1479
1419
 
1480
1420
  //
1481
1421
  // Save updated UTXO set
@@ -1488,7 +1428,7 @@ const processProcessorUtxos = async (
1488
1428
  newBalance = _biggystring.add.call(void 0, utxo.value, newBalance)
1489
1429
  }
1490
1430
  // Save new UTXOs
1491
- await processor.saveUtxo(utxo)
1431
+ await common.dataLayer.saveUtxo(utxo)
1492
1432
  }
1493
1433
 
1494
1434
  //
@@ -1497,10 +1437,14 @@ const processProcessorUtxos = async (
1497
1437
 
1498
1438
  // Address balance and emit address balance change event
1499
1439
  if (newBalance !== oldBalance) {
1500
- log('address balance changed:', { scriptPubkey, oldBalance, newBalance })
1501
- emitter.emit(
1440
+ common.log('address balance changed:', {
1441
+ scriptPubkey,
1442
+ oldBalance,
1443
+ newBalance
1444
+ })
1445
+ common.emitter.emit(
1502
1446
  _EngineEmitter.EngineEvent.ADDRESS_BALANCE_CHANGED,
1503
- currencyInfo.currencyCode,
1447
+ common.pluginInfo.currencyInfo.currencyCode,
1504
1448
  [
1505
1449
  {
1506
1450
  scriptPubkey,
@@ -1510,13 +1454,13 @@ const processProcessorUtxos = async (
1510
1454
  )
1511
1455
 
1512
1456
  // Update balances for address that have this scriptPubkey
1513
- const address = await processor.fetchAddress(scriptPubkey)
1457
+ const address = await common.dataLayer.fetchAddress(scriptPubkey)
1514
1458
 
1515
1459
  if (address == null) {
1516
1460
  throw new Error('address not found when processing UTXO transactions')
1517
1461
  }
1518
1462
 
1519
- await processor.saveAddress({
1463
+ await common.dataLayer.saveAddress({
1520
1464
  ...address,
1521
1465
  balance: newBalance,
1522
1466
  used: true
@@ -1524,43 +1468,32 @@ const processProcessorUtxos = async (
1524
1468
  }
1525
1469
 
1526
1470
  // Update the progress now that the UTXOs for an address have been processed
1527
- await args.updateProgressRatio()
1471
+ await common.updateProgressRatio()
1528
1472
 
1529
- await setLookAhead(args).catch(err => {
1530
- log.error(err)
1473
+ await setLookAhead(common).catch(err => {
1474
+ common.log.error(err)
1531
1475
  throw err
1532
1476
  })
1533
1477
  }
1534
1478
 
1479
+ /**
1480
+ * Process a blockbook UTXO from the cache by querying the network for
1481
+ * the UTXO's transaction data to get its script for legacy addresses.
1482
+ * After the network fetching, the UTXO is processed into a UtxoData object
1483
+ * to be later processed into the DataLayer.
1484
+ */
1485
+ async function* processBlockbookUtxo(
1486
+ common,
1487
+ args
1535
1488
 
1536
1489
 
1537
1490
 
1538
-
1539
-
1540
-
1541
-
1542
-
1543
-
1544
- const processRawUtxo = async (
1545
- args
1546
- ) => {
1547
- const {
1548
- utxo,
1549
- id,
1550
- address,
1551
- pluginInfo,
1552
- processor,
1553
- path,
1554
- taskCache,
1555
- requiredCount,
1556
- pluginState,
1557
- serverUri,
1558
- log
1559
- } = args
1560
- const { rawUtxoCache, processorUtxoCache } = taskCache
1491
+ ) {
1492
+ const { serverUri, cacheItem } = args
1493
+ const { blockbookUtxoCache, dataLayerUtxoCache } = common.taskCache
1561
1494
  const purposeType = _utils3.pathToPurposeType.call(void 0,
1562
- path,
1563
- pluginInfo.engineInfo.scriptTemplates
1495
+ cacheItem.path,
1496
+ common.pluginInfo.engineInfo.scriptTemplates
1564
1497
  )
1565
1498
  const scriptType = _utils3.getScriptTypeFromPurposeType.call(void 0, purposeType)
1566
1499
  let script
@@ -1568,24 +1501,24 @@ const processRawUtxo = async (
1568
1501
 
1569
1502
  // Function to call once we are finished
1570
1503
  const done = () => {
1571
- const processorUtxo = {
1572
- id,
1573
- txid: utxo.txid,
1574
- vout: utxo.vout,
1575
- value: utxo.value,
1576
- scriptPubkey: address.scriptPubkey,
1504
+ const utxoData = {
1505
+ id: `${cacheItem.blockbookUtxo.txid}_${cacheItem.blockbookUtxo.vout}`,
1506
+ txid: cacheItem.blockbookUtxo.txid,
1507
+ vout: cacheItem.blockbookUtxo.vout,
1508
+ value: cacheItem.blockbookUtxo.value,
1509
+ scriptPubkey: cacheItem.address.scriptPubkey,
1577
1510
  script,
1578
1511
  redeemScript,
1579
1512
  scriptType,
1580
- blockHeight: _nullishCoalesce(utxo.height, () => ( -1)),
1513
+ blockHeight: _nullishCoalesce(cacheItem.blockbookUtxo.height, () => ( -1)),
1581
1514
  spent: false
1582
1515
  }
1583
- addToProcessorUtxoCache(
1584
- processorUtxoCache,
1585
- path,
1586
- address.scriptPubkey,
1587
- requiredCount,
1588
- processorUtxo
1516
+ addToDataLayerUtxoCache(
1517
+ dataLayerUtxoCache,
1518
+ cacheItem.path,
1519
+ cacheItem.address.scriptPubkey,
1520
+ cacheItem.requiredCount,
1521
+ utxoData
1589
1522
  )
1590
1523
  }
1591
1524
 
@@ -1593,46 +1526,42 @@ const processRawUtxo = async (
1593
1526
  case _keymanager.BIP43PurposeTypeEnum.Airbitz:
1594
1527
  case _keymanager.BIP43PurposeTypeEnum.Legacy:
1595
1528
  case _keymanager.BIP43PurposeTypeEnum.ReplayProtection:
1596
- redeemScript = address.redeemScript
1529
+ redeemScript = cacheItem.address.redeemScript
1597
1530
 
1598
1531
  // Legacy UTXOs need the previous transaction hex as the script
1599
1532
  // If we do not currently have it, add it to the queue to fetch it
1600
1533
  {
1601
- const [tx] = await processor.fetchTransactions({
1602
- txId: utxo.txid
1534
+ const [tx] = await common.dataLayer.fetchTransactions({
1535
+ txId: cacheItem.blockbookUtxo.txid
1603
1536
  })
1604
1537
  if (tx == null) {
1605
- const queryTime = Date.now()
1606
- const deferred = new _Deferred2.default()
1607
- deferred.promise
1608
- .then((txResponse) => {
1609
- pluginState.serverScoreUp(serverUri, Date.now() - queryTime)
1610
- const processedTx = processTransactionResponse({
1611
- ...args,
1612
- txResponse
1613
- })
1614
- script = processedTx.hex
1615
- // Only after we have successfully fetched the tx, set our script and call done
1616
- done()
1617
- })
1618
- .catch(err => {
1619
- // If something went wrong, add the UTXO back to the queue
1620
- log('error in processRawUtxo:', err)
1621
- const utxoId = `${utxo.txid}_${utxo.vout}`
1622
- rawUtxoCache[utxoId] = {
1623
- blockbookUtxo: utxo,
1624
- processing: false,
1625
- path,
1626
- address,
1627
- requiredCount
1628
- }
1629
- })
1538
+ try {
1539
+ const txResponse = yield* common.serverStates.transactionQueryTask(
1540
+ serverUri,
1541
+ cacheItem.blockbookUtxo.txid
1542
+ )
1630
1543
 
1631
- return args.serverStates.transactionQueryTask(
1632
- serverUri,
1633
- utxo.txid,
1634
- deferred
1635
- )
1544
+ const processedTx = processTransactionResponse(common, {
1545
+ txResponse
1546
+ })
1547
+ script = processedTx.hex
1548
+ // Only after we have successfully fetched the tx, set our script and call done
1549
+ done()
1550
+
1551
+ return true
1552
+ } catch (err) {
1553
+ // If something went wrong, add the UTXO back to the queue
1554
+ common.log('error while processing Blockbook UTXO:', err)
1555
+ const utxoId = `${cacheItem.blockbookUtxo.txid}_${cacheItem.blockbookUtxo.vout}`
1556
+ blockbookUtxoCache[utxoId] = {
1557
+ blockbookUtxo: cacheItem.blockbookUtxo,
1558
+ processing: false,
1559
+ path: cacheItem.path,
1560
+ address: cacheItem.address,
1561
+ requiredCount: cacheItem.requiredCount
1562
+ }
1563
+ return false
1564
+ }
1636
1565
  } else {
1637
1566
  script = tx.hex
1638
1567
  }
@@ -1640,39 +1569,46 @@ const processRawUtxo = async (
1640
1569
 
1641
1570
  break
1642
1571
  case _keymanager.BIP43PurposeTypeEnum.WrappedSegwit:
1643
- script = address.scriptPubkey
1644
- if (address.redeemScript == null) {
1572
+ script = cacheItem.address.scriptPubkey
1573
+ if (cacheItem.address.redeemScript == null) {
1645
1574
  throw new Error(
1646
1575
  'Address redeem script not defined, but required for p2sh wrapped segwit utxo processing'
1647
1576
  )
1648
1577
  }
1649
- redeemScript = address.redeemScript
1578
+ redeemScript = cacheItem.address.redeemScript
1650
1579
 
1651
1580
  break
1652
1581
  case _keymanager.BIP43PurposeTypeEnum.Segwit:
1653
- script = address.scriptPubkey
1582
+ script = cacheItem.address.scriptPubkey
1654
1583
 
1655
1584
  break
1656
1585
  }
1657
1586
 
1658
1587
  // Since we have everything, call done
1659
1588
  done()
1589
+
1590
+ return true
1660
1591
  }
1661
1592
 
1662
- const addToProcessorUtxoCache = (
1663
- processorUtxoCache,
1593
+ /**
1594
+ * This adds a UtxoData object to the DataLayerUtxoCache. It will mark the cache
1595
+ * with processing and full flags which tell the pickNextTask routine when to
1596
+ * process the UtxoData into the data-later.
1597
+ */
1598
+ const addToDataLayerUtxoCache = (
1599
+ dataLayerUtxoCache,
1664
1600
  path,
1665
1601
  scriptPubkey,
1666
1602
  requiredCount,
1667
1603
  utxo
1668
1604
  ) => {
1669
- const processorUtxos = _nullishCoalesce(processorUtxoCache[scriptPubkey], () => ( {
1605
+ const dataLayerUtxos = _nullishCoalesce(dataLayerUtxoCache[scriptPubkey], () => ( {
1670
1606
  utxos: [],
1671
1607
  processing: false,
1672
1608
  path,
1673
1609
  full: false
1674
1610
  }))
1675
- if (utxo != null) processorUtxos.utxos.push(utxo)
1676
- processorUtxoCache[scriptPubkey] = processorUtxos
1677
- processorUtxos.full = processorUtxos.utxos.length >= requiredCount
1611
+ if (utxo != null) dataLayerUtxos.utxos.push(utxo)
1612
+ dataLayerUtxoCache[scriptPubkey] = dataLayerUtxos
1613
+ dataLayerUtxos.full = dataLayerUtxos.utxos.length >= requiredCount
1678
1614
  }