edge-currency-plugins 3.4.4 → 3.5.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 (35) hide show
  1. package/android/src/main/assets/edge-currency-plugins/edge-currency-plugins.js +50 -48
  2. package/lib/common/plugin/CurrencyPlugin.js +23 -11
  3. package/lib/common/plugin/EngineEmitter.js +27 -3
  4. package/lib/common/plugin/PluginState.js +20 -37
  5. package/lib/common/plugin/types.js +5 -3
  6. package/lib/common/utxobased/db/Models/TransactionData.js +6 -0
  7. package/lib/common/utxobased/engine/UtxoEngine.js +55 -35
  8. package/lib/common/utxobased/engine/UtxoEngineProcessor.js +91 -43
  9. package/lib/common/utxobased/info/badcoin.js +3 -1
  10. package/lib/common/utxobased/info/bitcoin.js +8 -1
  11. package/lib/common/utxobased/info/bitcoincash.js +8 -1
  12. package/lib/common/utxobased/info/bitcoincashtestnet.js +3 -1
  13. package/lib/common/utxobased/info/bitcoingold.js +3 -1
  14. package/lib/common/utxobased/info/bitcoingoldtestnet.js +3 -1
  15. package/lib/common/utxobased/info/bitcoinsv.js +3 -1
  16. package/lib/common/utxobased/info/bitcointestnet.js +3 -1
  17. package/lib/common/utxobased/info/dash.js +8 -1
  18. package/lib/common/utxobased/info/digibyte.js +3 -1
  19. package/lib/common/utxobased/info/dogecoin.js +8 -1
  20. package/lib/common/utxobased/info/eboost.js +3 -1
  21. package/lib/common/utxobased/info/feathercoin.js +3 -1
  22. package/lib/common/utxobased/info/groestlcoin.js +3 -1
  23. package/lib/common/utxobased/info/litecoin.js +8 -1
  24. package/lib/common/utxobased/info/qtum.js +3 -1
  25. package/lib/common/utxobased/info/ravencoin.js +3 -1
  26. package/lib/common/utxobased/info/smartcash.js +3 -1
  27. package/lib/common/utxobased/info/ufo.js +3 -1
  28. package/lib/common/utxobased/info/vertcoin.js +3 -1
  29. package/lib/common/utxobased/info/zcoin.js +8 -1
  30. package/lib/common/utxobased/network/blockbookApi.js +1 -1
  31. package/lib/src/common/plugin/EngineEmitter.d.ts +6 -3
  32. package/lib/src/common/plugin/PluginState.d.ts +7 -4
  33. package/lib/src/common/plugin/types.d.ts +8 -4
  34. package/lib/src/common/utxobased/engine/UtxoEngineProcessor.d.ts +6 -10
  35. package/package.json +3 -3
@@ -1,4 +1,5 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true});
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});var _cleaners = require('cleaners');
2
+
2
3
 
3
4
 
4
5
 
@@ -17,7 +18,7 @@ var _UtxoEngine = require('../utxobased/engine/UtxoEngine');
17
18
  var _CurrencyTools = require('./CurrencyTools');
18
19
  var _EngineEmitter = require('./EngineEmitter');
19
20
  var _PluginState = require('./PluginState');
20
-
21
+ var _types5 = require('./types');
21
22
 
22
23
  let hasMemletBeenSet = false
23
24
 
@@ -29,13 +30,15 @@ let hasMemletBeenSet = false
29
30
  const { initOptions, io, log, nativeIo, pluginDisklet } = pluginOptions
30
31
  const currencyTools = _CurrencyTools.makeCurrencyTools.call(void 0, io, pluginInfo)
31
32
  const { defaultSettings, pluginId, currencyCode } = currencyInfo
33
+
32
34
  const pluginState = _PluginState.makePluginState.call(void 0, {
33
- io,
35
+ defaultSettings: _types3.asUtxoUserSettings.call(void 0, defaultSettings),
34
36
  currencyCode,
35
- pluginId,
36
- pluginDisklet,
37
+ infoPayload: _cleaners.asMaybe.call(void 0, (0, _types5.asInfoPayload))(pluginOptions.infoPayload),
38
+ io,
37
39
  log,
38
- defaultSettings: _types3.asUtxoUserSettings.call(void 0, defaultSettings)
40
+ pluginId,
41
+ pluginDisklet
39
42
  })
40
43
 
41
44
  if (!hasMemletBeenSet) {
@@ -49,7 +52,7 @@ let hasMemletBeenSet = false
49
52
  }
50
53
  }
51
54
 
52
- return {
55
+ const instance = {
53
56
  currencyInfo,
54
57
 
55
58
  async makeCurrencyEngine(
@@ -64,10 +67,9 @@ let hasMemletBeenSet = false
64
67
  currencyTools,
65
68
  initOptions: _types3.asUtxoInitOptions.call(void 0, initOptions),
66
69
  io,
67
- options: {
68
- ...pluginOptions,
69
- ...engineOptions,
70
- emitter
70
+ emitter,
71
+ engineOptions: {
72
+ ...engineOptions
71
73
  },
72
74
  pluginState
73
75
  }
@@ -81,6 +83,16 @@ let hasMemletBeenSet = false
81
83
  throw e
82
84
  })
83
85
  return currencyTools
86
+ },
87
+
88
+ async updateInfoPayload(infoPayload) {
89
+ try {
90
+ pluginState.infoPayload = _types5.asInfoPayload.call(void 0, infoPayload)
91
+ } catch (_) {
92
+ log.warn('invalid infoPayload', infoPayload)
93
+ }
84
94
  }
85
95
  }
96
+
97
+ return instance
86
98
  } exports.makeCurrencyPlugin = makeCurrencyPlugin;
@@ -3,6 +3,7 @@
3
3
 
4
4
 
5
5
 
6
+
6
7
  var _events = require('events');
7
8
 
8
9
 
@@ -54,6 +55,24 @@ var _events = require('events');
54
55
 
55
56
 
56
57
 
58
+
59
+
60
+
61
+
62
+
63
+
64
+
65
+
66
+
67
+
68
+
69
+
70
+
71
+
72
+
73
+
74
+
75
+
57
76
 
58
77
 
59
78
 
@@ -76,6 +95,9 @@ var _events = require('events');
76
95
  class EngineEmitter extends _events.EventEmitter {} exports.EngineEmitter = EngineEmitter;
77
96
 
78
97
  var EngineEvent; (function (EngineEvent) {
98
+ const SEEN_TX_CHECKPOINT = 'seen:tx:checkpoint'; EngineEvent["SEEN_TX_CHECKPOINT"] = SEEN_TX_CHECKPOINT;
99
+ const TRANSACTIONS = 'transactions'; EngineEvent["TRANSACTIONS"] = TRANSACTIONS;
100
+ /** @deprecated Use TRANSACTIONS */
79
101
  const TRANSACTIONS_CHANGED = 'transactions:changed'; EngineEvent["TRANSACTIONS_CHANGED"] = TRANSACTIONS_CHANGED;
80
102
  const WALLET_BALANCE_CHANGED = 'wallet:balance:changed'; EngineEvent["WALLET_BALANCE_CHANGED"] = WALLET_BALANCE_CHANGED;
81
103
  const ADDRESS_BALANCE_CHANGED = 'address:balance:changed'; EngineEvent["ADDRESS_BALANCE_CHANGED"] = ADDRESS_BALANCE_CHANGED;
@@ -93,16 +115,18 @@ var EngineEvent; (function (EngineEvent) {
93
115
  ) => {
94
116
  const emitter = new EngineEmitter()
95
117
 
96
- emitter.on(EngineEvent.TRANSACTIONS_CHANGED, callbacks.onTransactionsChanged)
97
- emitter.on(EngineEvent.WALLET_BALANCE_CHANGED, callbacks.onBalanceChanged)
118
+ emitter.on(EngineEvent.ADDRESSES_CHECKED, callbacks.onAddressesChecked)
98
119
  emitter.on(
99
120
  EngineEvent.BLOCK_HEIGHT_CHANGED,
100
121
  (_uri, height) => {
101
122
  callbacks.onBlockHeightChanged(height)
102
123
  }
103
124
  )
104
- emitter.on(EngineEvent.ADDRESSES_CHECKED, callbacks.onAddressesChecked)
125
+ emitter.on(EngineEvent.SEEN_TX_CHECKPOINT, callbacks.onSeenTxCheckpoint)
126
+ emitter.on(EngineEvent.TRANSACTIONS, callbacks.onTransactions)
127
+ emitter.on(EngineEvent.TRANSACTIONS_CHANGED, callbacks.onTransactionsChanged)
105
128
  emitter.on(EngineEvent.TXIDS_CHANGED, callbacks.onTxidsChanged)
129
+ emitter.on(EngineEvent.WALLET_BALANCE_CHANGED, callbacks.onBalanceChanged)
106
130
 
107
131
  return emitter
108
132
  }; exports.makeEngineEmitter = makeEngineEmitter
@@ -1,7 +1,4 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }// Typescript translation from original code in edge-currency-bitcoin
2
-
3
- var _cleaners = require('cleaners');
4
-
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }
5
2
 
6
3
  var _memlet = require('memlet');
7
4
 
@@ -14,15 +11,11 @@ var _memlet = require('memlet');
14
11
 
15
12
  var _ServerScores = require('./ServerScores');
16
13
 
17
- // Info server endpoint to getting ServerListInfo data
18
- const serverListInfoUrl = 'https://info1.edge.app/v1/blockbook/'
14
+
19
15
  // The filename for ServerInfoCache data (see ServerScores.ts)
20
16
  // Perhaps this should be in ServerScores.ts file, but that'll take some refactoring
21
17
  const SERVER_CACHE_FILE = 'serverCache.json'
22
18
 
23
- // ServerListInfo data structure from info server and saved to disk
24
- const asServerListInfo = _cleaners.asObject.call(void 0, _cleaners.asEither.call(void 0, _cleaners.asArray.call(void 0, _cleaners.asString), _cleaners.asNull))
25
-
26
19
  /** A JSON object (as opposed to an array or primitive). */
27
20
 
28
21
 
@@ -53,19 +46,15 @@ const asServerListInfo = _cleaners.asObject.call(void 0, _cleaners.asEither.call
53
46
 
54
47
 
55
48
 
49
+
50
+
51
+
56
52
 
57
53
 
58
54
 
59
55
 
60
56
  function makePluginState(settings) {
61
- const {
62
- io,
63
- defaultSettings,
64
- currencyCode,
65
- pluginId,
66
- pluginDisklet,
67
- log
68
- } = settings
57
+ const { defaultSettings, log, pluginDisklet, pluginId } = settings
69
58
 
70
59
  let engines = []
71
60
  const memlet = _memlet.makeMemlet.call(void 0, pluginDisklet)
@@ -118,27 +107,21 @@ const asServerListInfo = _cleaners.asObject.call(void 0, _cleaners.asEither.call
118
107
  onDirtyServer
119
108
  })
120
109
 
121
- const fetchServers = async () => {
122
- log(`${pluginId} - GET ${serverListInfoUrl}`)
123
-
124
- try {
125
- const response = await io.fetch(serverListInfoUrl)
126
- if (!response.ok) {
127
- throw new Error(`Failed with status ${response.status}`)
128
- }
129
- const responseBody = await response.json()
130
- const serverListInfo = asServerListInfo(responseBody)
131
-
132
- return _nullishCoalesce(serverListInfo[currencyCode], () => ( []))
133
- } catch (error) {
134
- log.warn(
135
- `${pluginId} - GET ${serverListInfoUrl} failed: ${error.toString()}`
136
- )
110
+ const getInfoPayloadServers = async () => {
111
+ if (instance.infoPayload == null) {
112
+ log.warn(`info server list list empty`)
137
113
  return []
138
114
  }
115
+
116
+ const servers = Object.keys(instance.infoPayload.blockbookServers)
117
+ log.warn(`info server list`, servers)
118
+
119
+ return servers
139
120
  }
140
121
 
141
122
  const instance = {
123
+ infoPayload: settings.infoPayload,
124
+
142
125
  /**
143
126
  * Begins notifying the engine of state changes. Used at connection time.
144
127
  */
@@ -210,11 +193,11 @@ const asServerListInfo = _cleaners.asObject.call(void 0, _cleaners.asEither.call
210
193
  // Use the default servers from info file as final fallback
211
194
  defaultSettings.blockbookServers))
212
195
  } else {
213
- const fetchedServers = await fetchServers()
196
+ const infoPayloadServers = await getInfoPayloadServers()
214
197
  newServers =
215
- fetchedServers.length > 0
216
- ? // Use the servers from the network query
217
- fetchedServers
198
+ infoPayloadServers.length > 0
199
+ ? // Use the servers from the info-server
200
+ infoPayloadServers
218
201
  : // Use the default servers from info file as final fallback
219
202
  defaultSettings.blockbookServers
220
203
  }
@@ -364,12 +364,14 @@ var _types3 = require('../utxobased/db/types');
364
364
 
365
365
 
366
366
 
367
-
368
-
369
-
370
367
  const asLocalWalletMetadata = _cleaners.asObject.call(void 0, {
371
368
  balance: _cleaners.asString,
372
369
  // scriptPubkey -> balance
373
370
  addressBalances: _cleaners.asObject.call(void 0, _cleaners.asString),
374
371
  lastSeenBlockHeight: _cleaners.asNumber
375
372
  }); exports.asLocalWalletMetadata = asLocalWalletMetadata
373
+
374
+ const asInfoPayload = _cleaners.asObject.call(void 0, {
375
+ blockbookServers: _cleaners.asObject.call(void 0, _cleaners.asBoolean)
376
+ }); exports.asInfoPayload = asInfoPayload
377
+
@@ -101,6 +101,12 @@ var _bnjs = require('bn.js'); var _bnjs2 = _interopRequireDefault(_bnjs);
101
101
  memos: [],
102
102
  nativeAmount: tx.ourAmount,
103
103
  networkFee: tx.fees,
104
+ networkFees: [
105
+ {
106
+ tokenId: null,
107
+ nativeAmount: tx.fees
108
+ }
109
+ ],
104
110
  ourReceiveAddresses,
105
111
  signedTx: tx.hex,
106
112
  tokenId: null,
@@ -61,9 +61,6 @@ var _getOwnUtxosFromTx = require('./util/getOwnUtxosFromTx');
61
61
 
62
62
 
63
63
  var _utils3 = require('./utils');
64
-
65
-
66
-
67
64
  var _UtxoEngineProcessor = require('./UtxoEngineProcessor');
68
65
  var _UtxoWalletTools = require('./UtxoWalletTools');
69
66
 
@@ -73,19 +70,14 @@ var _UtxoWalletTools = require('./UtxoWalletTools');
73
70
  const {
74
71
  pluginInfo,
75
72
  pluginDisklet,
76
- // Rename to make it explicit that this is sensitive memory
77
- options,
73
+ emitter,
74
+ engineOptions,
78
75
  io,
79
76
  pluginState
80
77
  } = config
81
- const {
82
- walletLocalDisklet,
83
- walletLocalEncryptedDisklet,
84
- emitter,
85
- log
86
- } = options
78
+ const { walletLocalDisklet, walletLocalEncryptedDisklet, log } = engineOptions
87
79
  const { currencyInfo, engineInfo, coinInfo } = pluginInfo
88
- const userSettings = _types7.asUtxoUserSettings.call(void 0, options.userSettings)
80
+ const userSettings = _types7.asUtxoUserSettings.call(void 0, engineOptions.userSettings)
89
81
 
90
82
  // We should move the active server list to the engine state,
91
83
  // since multiple accounts can be logged in at once,
@@ -120,7 +112,7 @@ var _UtxoWalletTools = require('./UtxoWalletTools');
120
112
  disklet: pluginDisklet,
121
113
  pluginInfo,
122
114
  io,
123
- log: config.options.log
115
+ log: config.engineOptions.log
124
116
  })
125
117
 
126
118
  const metadata = await _Metadata.makeMetadata.call(void 0, {
@@ -136,12 +128,36 @@ var _UtxoWalletTools = require('./UtxoWalletTools');
136
128
  // private keys.
137
129
  let nonceDataLayer
138
130
 
131
+ /**
132
+ * This is a stateful function, which means it is both a setter and a getter.
133
+ * The state is the cached seenTxCheckpoint for the engine during runtime.
134
+ * It is initialized with the seenTxCheckpoint state from the core via
135
+ * `EdgeCurrencyEngineOptions`.
136
+ * It is updated by the engine's processor as the wallet syncs.
137
+ * Once the wallet fully syncs, the seenTxCheckpoint value is emitted to the
138
+ * `onSeenTxCheckpoint` callback so the core can persist this state to disk.
139
+ */
140
+ const seenTxCheckpoint = ((state) => (
141
+ value
142
+ ) => {
143
+ if (value != null) state = value
144
+ return state
145
+ })()
146
+
147
+ // Initialize the seenTxCheckpoint with the value from the core.
148
+ seenTxCheckpoint(config.engineOptions.seenTxCheckpoint)
149
+
150
+ emitter.on(_EngineEmitter.EngineEvent.SEEN_TX_CHECKPOINT, checkpoint => {
151
+ seenTxCheckpoint(checkpoint)
152
+ })
153
+
139
154
  const engineProcessor = _UtxoEngineProcessor.makeUtxoEngineProcessor.call(void 0, {
140
155
  ...config,
141
- walletTools,
142
- walletInfo,
143
156
  dataLayer,
144
- pluginState
157
+ pluginState,
158
+ seenTxCheckpoint,
159
+ walletTools,
160
+ walletInfo
145
161
  })
146
162
 
147
163
  const engine = {
@@ -700,6 +716,12 @@ var _UtxoWalletTools = require('./UtxoWalletTools');
700
716
  memos,
701
717
  nativeAmount,
702
718
  networkFee,
719
+ networkFees: [
720
+ {
721
+ tokenId: null,
722
+ nativeAmount: networkFee
723
+ }
724
+ ],
703
725
  otherParams,
704
726
  ourReceiveAddresses,
705
727
  signedTx: '',
@@ -738,26 +760,23 @@ var _UtxoWalletTools = require('./UtxoWalletTools');
738
760
  })
739
761
  if (rbfTx != null) {
740
762
  rbfTx.blockHeight = -1
741
- await _UtxoEngineProcessor.transactionChanged.call(void 0, {
742
- walletId: walletInfo.id,
743
- tx: rbfTx,
763
+ await dataLayer.saveTransaction({
764
+ tx: rbfTx
765
+ })
766
+ const rbfEdgeTx = await _TransactionData.toEdgeTransaction.call(void 0, {
767
+ dataLayer,
744
768
  pluginInfo,
745
- emitter,
746
- walletTools,
747
- dataLayer
769
+ tx: rbfTx,
770
+ walletId: walletInfo.id,
771
+ walletTools
748
772
  })
773
+ emitter.emit(_EngineEmitter.EngineEvent.TRANSACTIONS, [
774
+ { isNew: false, transaction: rbfEdgeTx }
775
+ ])
749
776
  }
750
777
  }
751
778
 
752
779
  const tx = _TransactionData.fromEdgeTransaction.call(void 0, edgeTx)
753
- await _UtxoEngineProcessor.transactionChanged.call(void 0, {
754
- walletId: walletInfo.id,
755
- tx,
756
- pluginInfo,
757
- emitter,
758
- walletTools,
759
- dataLayer
760
- })
761
780
  await dataLayer.saveTransaction({
762
781
  tx,
763
782
  scriptPubkeys: _optionalChain([edgeTx, 'access', _11 => _11.otherParams, 'optionalAccess', _12 => _12.ourScriptPubkeys])
@@ -983,11 +1002,12 @@ var _UtxoWalletTools = require('./UtxoWalletTools');
983
1002
 
984
1003
  const tmpEngineProcessor = _UtxoEngineProcessor.makeUtxoEngineProcessor.call(void 0, {
985
1004
  ...config,
986
- options: {
987
- ...config.options,
1005
+ dataLayer: tmpDataLayer,
1006
+ emitter: tmpEmitter,
1007
+ engineOptions: {
1008
+ ...config.engineOptions,
988
1009
  walletLocalDisklet: tmpDisklet,
989
- walletLocalEncryptedDisklet: tmpEncryptedDisklet,
990
- emitter: tmpEmitter
1010
+ walletLocalEncryptedDisklet: tmpEncryptedDisklet
991
1011
  },
992
1012
  pluginInfo: {
993
1013
  ...pluginInfo,
@@ -997,7 +1017,7 @@ var _UtxoWalletTools = require('./UtxoWalletTools');
997
1017
  gapLimit: 0
998
1018
  }
999
1019
  },
1000
- dataLayer: tmpDataLayer,
1020
+ seenTxCheckpoint: () => '0',
1001
1021
  walletTools: tmpWalletTools,
1002
1022
  walletInfo: tmpWalletInfo
1003
1023
  })
@@ -83,22 +83,25 @@ var _utils3 = require('./utils');
83
83
 
84
84
 
85
85
 
86
+
86
87
 
87
88
 
88
89
  function makeUtxoEngineProcessor(
89
90
  config
90
91
  ) {
91
92
  const {
93
+ dataLayer,
92
94
  initOptions,
93
95
  io,
94
- options,
96
+ emitter,
97
+ engineOptions,
95
98
  pluginState,
96
99
  pluginInfo,
97
- dataLayer,
100
+ seenTxCheckpoint,
98
101
  walletInfo,
99
102
  walletTools
100
103
  } = config
101
- const { emitter, log } = options
104
+ const { log } = engineOptions
102
105
 
103
106
  const { walletFormats } = walletInfo.keys
104
107
 
@@ -169,6 +172,27 @@ var _utils3 = require('./utils');
169
172
  }
170
173
  }
171
174
 
175
+ const updateSeenTxCheckpoint = () => {
176
+ // Only update the seenTxCheckpoint if the wallet is fully synced.
177
+ // This ensure that initial syncs without a defined seenTxCheckpoint,
178
+ // will not incorrectly update the seenTxCheckpoint in the middle of an
179
+ // initial sync.
180
+ if (processedPercent < 1) return
181
+
182
+ const seenTxCheckpoint = common.seenTxCheckpoint()
183
+ const seenTxBlockHeight =
184
+ seenTxCheckpoint != null ? parseInt(seenTxCheckpoint) : undefined
185
+
186
+ // Update the seenTxCheckpoint
187
+ if (
188
+ seenTxBlockHeight == null ||
189
+ common.maxSeenTxBlockHeight > seenTxBlockHeight
190
+ ) {
191
+ const newSeenTxCheckpoint = common.maxSeenTxBlockHeight.toString()
192
+ common.emitter.emit(_EngineEmitter.EngineEvent.SEEN_TX_CHECKPOINT, newSeenTxCheckpoint)
193
+ }
194
+ }
195
+
172
196
  const lock = new (0, _awaitlock2.default)()
173
197
 
174
198
  const serverStates = _ServerStates.makeServerStates.call(void 0, {
@@ -188,8 +212,11 @@ var _utils3 = require('./utils');
188
212
  emitter,
189
213
  taskCache,
190
214
  updateProgressRatio,
215
+ updateSeenTxCheckpoint,
191
216
  io,
192
217
  log,
218
+ maxSeenTxBlockHeight: 0,
219
+ seenTxCheckpoint,
193
220
  serverStates,
194
221
  walletFormats,
195
222
  lock
@@ -211,12 +238,16 @@ var _utils3 = require('./utils');
211
238
  emitter.on(
212
239
  _EngineEmitter.EngineEvent.BLOCK_HEIGHT_CHANGED,
213
240
  async (_uri, _blockHeight) => {
241
+ // Add all unconfirmed transactions to the cache to check if these
242
+ // transactions have been confirmed:
214
243
  const txs = await dataLayer.fetchTransactions({
215
244
  blockHeight: 0
216
245
  })
217
246
  for (const tx of txs) {
218
247
  if (tx == null) continue
219
- taskCache.transactionUpdateCache[tx.txid] = { processing: false }
248
+ taskCache.transactionUpdateCache[tx.txid] = {
249
+ processing: false
250
+ }
220
251
  }
221
252
  }
222
253
  )
@@ -649,6 +680,9 @@ const internalGetFreshAddress = async (
649
680
 
650
681
 
651
682
 
683
+
684
+
685
+
652
686
 
653
687
 
654
688
 
@@ -764,26 +798,6 @@ const addToAddressForTransactionsCache = async (
764
798
  }
765
799
  }
766
800
 
767
- const transactionChanged = async (args
768
-
769
-
770
-
771
-
772
-
773
-
774
- ) => {
775
- const { dataLayer, emitter, pluginInfo, tx, walletTools, walletId } = args
776
- emitter.emit(_EngineEmitter.EngineEvent.TRANSACTIONS_CHANGED, [
777
- await _TransactionData.toEdgeTransaction.call(void 0, {
778
- walletId,
779
- tx,
780
- walletTools,
781
- dataLayer,
782
- pluginInfo
783
- })
784
- ])
785
- }; exports.transactionChanged = transactionChanged
786
-
787
801
  /**
788
802
  * Some currencies require an additional blockbook payload 'getTransactionSpecific' in order
789
803
  * to provide all relevant transaction data. Since this is currency-specific, we can limit
@@ -975,7 +989,7 @@ const needsTxSpecific = (common) => {
975
989
  hasProcessedAtLeastOnce = true
976
990
  cacheItem.processing = true
977
991
  _utils.removeItem.call(void 0, transactionUpdateCache, txId)
978
- yield* processTransactionUpdate(common, {
992
+ yield* processCheckTransactionConfirmation(common, {
979
993
  serverState,
980
994
  serverUri,
981
995
  txId
@@ -1046,14 +1060,16 @@ async function* processTransactionsSpecificUpdate(
1046
1060
  tx
1047
1061
  })
1048
1062
 
1049
- await exports.transactionChanged.call(void 0, {
1050
- walletId: common.walletInfo.id,
1051
- emitter: common.emitter,
1052
- walletTools: common.walletTools,
1063
+ const edgeTx = await _TransactionData.toEdgeTransaction.call(void 0, {
1053
1064
  dataLayer: common.dataLayer,
1054
1065
  pluginInfo: common.pluginInfo,
1055
- tx: processedTx
1066
+ tx: processedTx,
1067
+ walletId: common.walletInfo.id,
1068
+ walletTools: common.walletTools
1056
1069
  })
1070
+ common.emitter.emit(_EngineEmitter.EngineEvent.TRANSACTIONS, [
1071
+ { isNew: false, transaction: edgeTx }
1072
+ ])
1057
1073
 
1058
1074
  // Add the txid to the server cache
1059
1075
  serverState.txids.add(txId)
@@ -1070,10 +1086,12 @@ async function* processTransactionsSpecificUpdate(
1070
1086
  }
1071
1087
 
1072
1088
  /**
1073
- * Processes a transaction update from the TransactionUpdateCache by querying
1089
+ * Processes an item from transactionUpdateCache by querying
1074
1090
  * the network for the transaction data and processing it into the DataLayer.
1091
+ * It updates the transaction and all of the transaction's UTXO with the
1092
+ * blockHeight received from the network.
1075
1093
  */
1076
- async function* processTransactionUpdate(
1094
+ async function* processCheckTransactionConfirmation(
1077
1095
  common,
1078
1096
  args
1079
1097
 
@@ -1111,14 +1129,16 @@ async function* processTransactionUpdate(
1111
1129
  tx
1112
1130
  })
1113
1131
 
1114
- await exports.transactionChanged.call(void 0, {
1115
- walletId: common.walletInfo.id,
1116
- emitter: common.emitter,
1117
- walletTools: common.walletTools,
1132
+ const edgeTx = await _TransactionData.toEdgeTransaction.call(void 0, {
1118
1133
  dataLayer: common.dataLayer,
1119
1134
  pluginInfo: common.pluginInfo,
1120
- tx: processedTx
1135
+ tx: processedTx,
1136
+ walletId: common.walletInfo.id,
1137
+ walletTools: common.walletTools
1121
1138
  })
1139
+ common.emitter.emit(_EngineEmitter.EngineEvent.TRANSACTIONS, [
1140
+ { isNew: false, transaction: edgeTx }
1141
+ ])
1122
1142
 
1123
1143
  if (needsTxSpecific(common)) {
1124
1144
  // Add task to grab transactionSpecific payload
@@ -1134,7 +1154,9 @@ async function* processTransactionUpdate(
1134
1154
  } catch (err) {
1135
1155
  console.error(err)
1136
1156
  common.log('error while processing transaction update:', err)
1137
- common.taskCache.transactionUpdateCache[txId] = { processing: false }
1157
+ common.taskCache.transactionUpdateCache[txId] = {
1158
+ processing: false
1159
+ }
1138
1160
  return false
1139
1161
  }
1140
1162
  }
@@ -1185,22 +1207,45 @@ async function* processAddressForTransactions(
1185
1207
  addressData.used = true
1186
1208
  }
1187
1209
 
1210
+ const seenTxCheckpoint = common.seenTxCheckpoint()
1211
+ const seenTxBlockHeight =
1212
+ seenTxCheckpoint != null ? parseInt(seenTxCheckpoint) : undefined
1213
+
1188
1214
  // Process and save the address's transactions
1189
1215
  for (const txResponse of transactions) {
1216
+ const [existingTx] = await common.dataLayer.fetchTransactions({
1217
+ txId: txResponse.txid
1218
+ })
1219
+
1190
1220
  const tx = processTransactionResponse(common, { txResponse })
1191
1221
  const processedTx = await common.dataLayer.saveTransaction({
1192
1222
  tx,
1193
1223
  scriptPubkeys: [scriptPubkey]
1194
1224
  })
1195
- await exports.transactionChanged.call(void 0, {
1196
- walletId: common.walletInfo.id,
1197
- emitter: common.emitter,
1198
- walletTools: common.walletTools,
1225
+ const edgeTx = await _TransactionData.toEdgeTransaction.call(void 0, {
1199
1226
  dataLayer: common.dataLayer,
1200
1227
  pluginInfo: common.pluginInfo,
1201
- tx: processedTx
1228
+ tx: processedTx,
1229
+ walletId: common.walletInfo.id,
1230
+ walletTools: common.walletTools
1202
1231
  })
1203
1232
 
1233
+ // Keep track of transactions which are determined to be unseen:
1234
+ const isNew =
1235
+ seenTxBlockHeight != null &&
1236
+ // Unseen in the DataLayer
1237
+ existingTx == null &&
1238
+ // The tx unconfirmed or confirmed after/at the last seenTxCheckpoint
1239
+ (tx.blockHeight === 0 || tx.blockHeight > seenTxBlockHeight)
1240
+
1241
+ common.emitter.emit(_EngineEmitter.EngineEvent.TRANSACTIONS, [
1242
+ { isNew, transaction: edgeTx }
1243
+ ])
1244
+
1245
+ if (edgeTx.blockHeight > common.maxSeenTxBlockHeight) {
1246
+ common.maxSeenTxBlockHeight = edgeTx.blockHeight
1247
+ }
1248
+
1204
1249
  if (needsTxSpecific(common)) {
1205
1250
  // Add task to grab transactionSpecific payload
1206
1251
  common.taskCache.transactionSpecificUpdateCache[tx.txid] = {
@@ -1209,6 +1254,9 @@ async function* processAddressForTransactions(
1209
1254
  }
1210
1255
  }
1211
1256
 
1257
+ // Make sure to update the seenTxCheckpoint after processing the transactions
1258
+ common.updateSeenTxCheckpoint()
1259
+
1212
1260
  // Halt on finishing the processing of address transaction until
1213
1261
  // we have progressed through all of the blockbook pages
1214
1262
  if (page < totalPages) {