@metamask-previews/transaction-controller 41.1.0-preview-9cfbf21f → 41.1.0-preview-73fa7bfb

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 (80) hide show
  1. package/CHANGELOG.md +0 -23
  2. package/dist/TransactionController.cjs +51 -57
  3. package/dist/TransactionController.cjs.map +1 -1
  4. package/dist/TransactionController.d.cts +13 -72
  5. package/dist/TransactionController.d.cts.map +1 -1
  6. package/dist/TransactionController.d.mts +13 -72
  7. package/dist/TransactionController.d.mts.map +1 -1
  8. package/dist/TransactionController.mjs +51 -57
  9. package/dist/TransactionController.mjs.map +1 -1
  10. package/dist/api/accounts-api.cjs +3 -48
  11. package/dist/api/accounts-api.cjs.map +1 -1
  12. package/dist/api/accounts-api.d.cts +0 -49
  13. package/dist/api/accounts-api.d.cts.map +1 -1
  14. package/dist/api/accounts-api.d.mts +0 -49
  15. package/dist/api/accounts-api.d.mts.map +1 -1
  16. package/dist/api/accounts-api.mjs +2 -46
  17. package/dist/api/accounts-api.mjs.map +1 -1
  18. package/dist/constants.cjs +85 -1
  19. package/dist/constants.cjs.map +1 -1
  20. package/dist/constants.d.cts +84 -0
  21. package/dist/constants.d.cts.map +1 -1
  22. package/dist/constants.d.mts +84 -0
  23. package/dist/constants.d.mts.map +1 -1
  24. package/dist/constants.mjs +84 -0
  25. package/dist/constants.mjs.map +1 -1
  26. package/dist/helpers/EtherscanRemoteTransactionSource.cjs +158 -0
  27. package/dist/helpers/EtherscanRemoteTransactionSource.cjs.map +1 -0
  28. package/dist/helpers/EtherscanRemoteTransactionSource.d.cts +16 -0
  29. package/dist/helpers/EtherscanRemoteTransactionSource.d.cts.map +1 -0
  30. package/dist/helpers/EtherscanRemoteTransactionSource.d.mts +16 -0
  31. package/dist/helpers/EtherscanRemoteTransactionSource.d.mts.map +1 -0
  32. package/dist/helpers/EtherscanRemoteTransactionSource.mjs +158 -0
  33. package/dist/helpers/EtherscanRemoteTransactionSource.mjs.map +1 -0
  34. package/dist/helpers/IncomingTransactionHelper.cjs +142 -90
  35. package/dist/helpers/IncomingTransactionHelper.cjs.map +1 -1
  36. package/dist/helpers/IncomingTransactionHelper.d.cts +16 -10
  37. package/dist/helpers/IncomingTransactionHelper.d.cts.map +1 -1
  38. package/dist/helpers/IncomingTransactionHelper.d.mts +16 -10
  39. package/dist/helpers/IncomingTransactionHelper.d.mts.map +1 -1
  40. package/dist/helpers/IncomingTransactionHelper.mjs +143 -91
  41. package/dist/helpers/IncomingTransactionHelper.mjs.map +1 -1
  42. package/dist/helpers/MultichainTrackingHelper.cjs +70 -23
  43. package/dist/helpers/MultichainTrackingHelper.cjs.map +1 -1
  44. package/dist/helpers/MultichainTrackingHelper.d.cts +14 -1
  45. package/dist/helpers/MultichainTrackingHelper.d.cts.map +1 -1
  46. package/dist/helpers/MultichainTrackingHelper.d.mts +14 -1
  47. package/dist/helpers/MultichainTrackingHelper.d.mts.map +1 -1
  48. package/dist/helpers/MultichainTrackingHelper.mjs +70 -23
  49. package/dist/helpers/MultichainTrackingHelper.mjs.map +1 -1
  50. package/dist/index.cjs +2 -3
  51. package/dist/index.cjs.map +1 -1
  52. package/dist/index.d.cts +4 -4
  53. package/dist/index.d.cts.map +1 -1
  54. package/dist/index.d.mts +4 -4
  55. package/dist/index.d.mts.map +1 -1
  56. package/dist/index.mjs +1 -2
  57. package/dist/index.mjs.map +1 -1
  58. package/dist/types.cjs.map +1 -1
  59. package/dist/types.d.cts +14 -21
  60. package/dist/types.d.cts.map +1 -1
  61. package/dist/types.d.mts +14 -21
  62. package/dist/types.d.mts.map +1 -1
  63. package/dist/types.mjs.map +1 -1
  64. package/dist/utils/etherscan.cjs +116 -0
  65. package/dist/utils/etherscan.cjs.map +1 -0
  66. package/dist/utils/etherscan.d.cts +74 -0
  67. package/dist/utils/etherscan.d.cts.map +1 -0
  68. package/dist/utils/etherscan.d.mts +74 -0
  69. package/dist/utils/etherscan.d.mts.map +1 -0
  70. package/dist/utils/etherscan.mjs +110 -0
  71. package/dist/utils/etherscan.mjs.map +1 -0
  72. package/package.json +2 -2
  73. package/dist/helpers/AccountsApiRemoteTransactionSource.cjs +0 -183
  74. package/dist/helpers/AccountsApiRemoteTransactionSource.cjs.map +0 -1
  75. package/dist/helpers/AccountsApiRemoteTransactionSource.d.cts +0 -12
  76. package/dist/helpers/AccountsApiRemoteTransactionSource.d.cts.map +0 -1
  77. package/dist/helpers/AccountsApiRemoteTransactionSource.d.mts +0 -12
  78. package/dist/helpers/AccountsApiRemoteTransactionSource.d.mts.map +0 -1
  79. package/dist/helpers/AccountsApiRemoteTransactionSource.mjs +0 -183
  80. package/dist/helpers/AccountsApiRemoteTransactionSource.mjs.map +0 -1
@@ -9,41 +9,59 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
9
9
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
10
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
11
  };
12
- var _IncomingTransactionHelper_instances, _IncomingTransactionHelper_getCache, _IncomingTransactionHelper_getCurrentAccount, _IncomingTransactionHelper_getChainIds, _IncomingTransactionHelper_getLocalTransactions, _IncomingTransactionHelper_includeTokenTransfers, _IncomingTransactionHelper_isEnabled, _IncomingTransactionHelper_isRunning, _IncomingTransactionHelper_queryEntireHistory, _IncomingTransactionHelper_remoteTransactionSource, _IncomingTransactionHelper_timeoutId, _IncomingTransactionHelper_trimTransactions, _IncomingTransactionHelper_updateCache, _IncomingTransactionHelper_updateTransactions, _IncomingTransactionHelper_onInterval, _IncomingTransactionHelper_sortTransactionsByTime, _IncomingTransactionHelper_canStart;
12
+ var _IncomingTransactionHelper_instances, _IncomingTransactionHelper_blockTracker, _IncomingTransactionHelper_getCurrentAccount, _IncomingTransactionHelper_getLastFetchedBlockNumbers, _IncomingTransactionHelper_getLocalTransactions, _IncomingTransactionHelper_getChainId, _IncomingTransactionHelper_isEnabled, _IncomingTransactionHelper_isRunning, _IncomingTransactionHelper_log, _IncomingTransactionHelper_mutex, _IncomingTransactionHelper_onLatestBlock, _IncomingTransactionHelper_queryEntireHistory, _IncomingTransactionHelper_remoteTransactionSource, _IncomingTransactionHelper_transactionLimit, _IncomingTransactionHelper_updateTransactions, _IncomingTransactionHelper_sortTransactionsByTime, _IncomingTransactionHelper_getNewTransactions, _IncomingTransactionHelper_getUpdatedTransactions, _IncomingTransactionHelper_isTransactionOutdated, _IncomingTransactionHelper_getLastFetchedBlockNumberDec, _IncomingTransactionHelper_getFromBlock, _IncomingTransactionHelper_updateLastFetchedBlockNumber, _IncomingTransactionHelper_getBlockNumberKey, _IncomingTransactionHelper_canStart;
13
+ import { Mutex } from "async-mutex";
13
14
  // This package purposefully relies on Node's EventEmitter module.
14
15
  // eslint-disable-next-line import/no-nodejs-modules
15
16
  import EventEmitter from "events";
16
- import { incomingTransactionsLogger as log } from "../logger.mjs";
17
- const INTERVAL = 1000 * 30; // 30 Seconds
17
+ import { createModuleLogger, incomingTransactionsLogger as log } from "../logger.mjs";
18
+ const RECENT_HISTORY_BLOCK_RANGE = 10;
19
+ // TODO: Replace `any` with type
20
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
21
+ const UPDATE_CHECKS = [
22
+ (txMeta) => txMeta.status,
23
+ (txMeta) => txMeta.txParams.gasUsed,
24
+ ];
18
25
  export class IncomingTransactionHelper {
19
- constructor({ getCache, getCurrentAccount, getChainIds, getLocalTransactions, includeTokenTransfers, isEnabled, queryEntireHistory, remoteTransactionSource, trimTransactions, updateCache, updateTransactions, }) {
26
+ constructor({ blockTracker, getCurrentAccount, getLastFetchedBlockNumbers, getLocalTransactions, getChainId, isEnabled, queryEntireHistory, remoteTransactionSource, transactionLimit, updateTransactions, }) {
20
27
  _IncomingTransactionHelper_instances.add(this);
21
- _IncomingTransactionHelper_getCache.set(this, void 0);
28
+ _IncomingTransactionHelper_blockTracker.set(this, void 0);
22
29
  _IncomingTransactionHelper_getCurrentAccount.set(this, void 0);
23
- _IncomingTransactionHelper_getChainIds.set(this, void 0);
30
+ _IncomingTransactionHelper_getLastFetchedBlockNumbers.set(this, void 0);
24
31
  _IncomingTransactionHelper_getLocalTransactions.set(this, void 0);
25
- _IncomingTransactionHelper_includeTokenTransfers.set(this, void 0);
32
+ _IncomingTransactionHelper_getChainId.set(this, void 0);
26
33
  _IncomingTransactionHelper_isEnabled.set(this, void 0);
27
34
  _IncomingTransactionHelper_isRunning.set(this, void 0);
35
+ _IncomingTransactionHelper_log.set(this, void 0);
36
+ _IncomingTransactionHelper_mutex.set(this, new Mutex());
37
+ _IncomingTransactionHelper_onLatestBlock.set(this, void 0);
28
38
  _IncomingTransactionHelper_queryEntireHistory.set(this, void 0);
29
39
  _IncomingTransactionHelper_remoteTransactionSource.set(this, void 0);
30
- _IncomingTransactionHelper_timeoutId.set(this, void 0);
31
- _IncomingTransactionHelper_trimTransactions.set(this, void 0);
32
- _IncomingTransactionHelper_updateCache.set(this, void 0);
40
+ _IncomingTransactionHelper_transactionLimit.set(this, void 0);
33
41
  _IncomingTransactionHelper_updateTransactions.set(this, void 0);
34
42
  this.hub = new EventEmitter();
35
- __classPrivateFieldSet(this, _IncomingTransactionHelper_getCache, getCache, "f");
43
+ __classPrivateFieldSet(this, _IncomingTransactionHelper_blockTracker, blockTracker, "f");
36
44
  __classPrivateFieldSet(this, _IncomingTransactionHelper_getCurrentAccount, getCurrentAccount, "f");
37
- __classPrivateFieldSet(this, _IncomingTransactionHelper_getChainIds, getChainIds, "f");
38
- __classPrivateFieldSet(this, _IncomingTransactionHelper_getLocalTransactions, getLocalTransactions, "f");
39
- __classPrivateFieldSet(this, _IncomingTransactionHelper_includeTokenTransfers, includeTokenTransfers, "f");
45
+ __classPrivateFieldSet(this, _IncomingTransactionHelper_getLastFetchedBlockNumbers, getLastFetchedBlockNumbers, "f");
46
+ __classPrivateFieldSet(this, _IncomingTransactionHelper_getLocalTransactions, getLocalTransactions || (() => []), "f");
47
+ __classPrivateFieldSet(this, _IncomingTransactionHelper_getChainId, getChainId, "f");
40
48
  __classPrivateFieldSet(this, _IncomingTransactionHelper_isEnabled, isEnabled ?? (() => true), "f");
41
49
  __classPrivateFieldSet(this, _IncomingTransactionHelper_isRunning, false, "f");
42
- __classPrivateFieldSet(this, _IncomingTransactionHelper_queryEntireHistory, queryEntireHistory, "f");
50
+ __classPrivateFieldSet(this, _IncomingTransactionHelper_log, createModuleLogger(log, getChainId()), "f");
51
+ __classPrivateFieldSet(this, _IncomingTransactionHelper_queryEntireHistory, queryEntireHistory ?? true, "f");
43
52
  __classPrivateFieldSet(this, _IncomingTransactionHelper_remoteTransactionSource, remoteTransactionSource, "f");
44
- __classPrivateFieldSet(this, _IncomingTransactionHelper_trimTransactions, trimTransactions, "f");
45
- __classPrivateFieldSet(this, _IncomingTransactionHelper_updateCache, updateCache, "f");
46
- __classPrivateFieldSet(this, _IncomingTransactionHelper_updateTransactions, updateTransactions, "f");
53
+ __classPrivateFieldSet(this, _IncomingTransactionHelper_transactionLimit, transactionLimit, "f");
54
+ __classPrivateFieldSet(this, _IncomingTransactionHelper_updateTransactions, updateTransactions ?? false, "f");
55
+ // Using a property instead of a method to provide a listener reference
56
+ // with the correct scope that we can remove later if stopped.
57
+ __classPrivateFieldSet(this, _IncomingTransactionHelper_onLatestBlock, async (blockNumberHex) => {
58
+ try {
59
+ await this.update(blockNumberHex);
60
+ }
61
+ catch (error) {
62
+ console.error('Error while checking incoming transactions', error);
63
+ }
64
+ }, "f");
47
65
  }
48
66
  start() {
49
67
  if (__classPrivateFieldGet(this, _IncomingTransactionHelper_isRunning, "f")) {
@@ -52,98 +70,132 @@ export class IncomingTransactionHelper {
52
70
  if (!__classPrivateFieldGet(this, _IncomingTransactionHelper_instances, "m", _IncomingTransactionHelper_canStart).call(this)) {
53
71
  return;
54
72
  }
55
- log('Starting polling');
73
+ __classPrivateFieldGet(this, _IncomingTransactionHelper_log, "f").call(this, 'Starting polling');
74
+ // TODO: Either fix this lint violation or explain why it's necessary to ignore.
56
75
  // eslint-disable-next-line @typescript-eslint/no-misused-promises
57
- __classPrivateFieldSet(this, _IncomingTransactionHelper_timeoutId, setTimeout(() => __classPrivateFieldGet(this, _IncomingTransactionHelper_instances, "m", _IncomingTransactionHelper_onInterval).call(this), INTERVAL), "f");
76
+ __classPrivateFieldGet(this, _IncomingTransactionHelper_blockTracker, "f").addListener('latest', __classPrivateFieldGet(this, _IncomingTransactionHelper_onLatestBlock, "f"));
58
77
  __classPrivateFieldSet(this, _IncomingTransactionHelper_isRunning, true, "f");
59
- log('Started polling');
60
78
  }
61
79
  stop() {
62
- if (__classPrivateFieldGet(this, _IncomingTransactionHelper_timeoutId, "f")) {
63
- clearTimeout(__classPrivateFieldGet(this, _IncomingTransactionHelper_timeoutId, "f"));
64
- }
65
80
  if (!__classPrivateFieldGet(this, _IncomingTransactionHelper_isRunning, "f")) {
66
81
  return;
67
82
  }
83
+ // TODO: Either fix this lint violation or explain why it's necessary to ignore.
84
+ // eslint-disable-next-line @typescript-eslint/no-misused-promises
85
+ __classPrivateFieldGet(this, _IncomingTransactionHelper_blockTracker, "f").removeListener('latest', __classPrivateFieldGet(this, _IncomingTransactionHelper_onLatestBlock, "f"));
68
86
  __classPrivateFieldSet(this, _IncomingTransactionHelper_isRunning, false, "f");
69
- log('Stopped polling');
87
+ __classPrivateFieldGet(this, _IncomingTransactionHelper_log, "f").call(this, 'Stopped polling');
70
88
  }
71
- async update({ isInterval } = {}) {
72
- log('Checking for incoming transactions', {
73
- isInterval: Boolean(isInterval),
74
- });
75
- if (!__classPrivateFieldGet(this, _IncomingTransactionHelper_instances, "m", _IncomingTransactionHelper_canStart).call(this)) {
76
- return;
77
- }
78
- const account = __classPrivateFieldGet(this, _IncomingTransactionHelper_getCurrentAccount, "f").call(this);
79
- const chainIds = __classPrivateFieldGet(this, _IncomingTransactionHelper_getChainIds, "f").call(this);
80
- const cache = __classPrivateFieldGet(this, _IncomingTransactionHelper_getCache, "f").call(this);
81
- const includeTokenTransfers = __classPrivateFieldGet(this, _IncomingTransactionHelper_includeTokenTransfers, "f") ?? true;
82
- const queryEntireHistory = __classPrivateFieldGet(this, _IncomingTransactionHelper_queryEntireHistory, "f") ?? true;
83
- const updateTransactions = __classPrivateFieldGet(this, _IncomingTransactionHelper_updateTransactions, "f") ?? false;
84
- let remoteTransactions = [];
89
+ async update(latestBlockNumberHex) {
90
+ const releaseLock = await __classPrivateFieldGet(this, _IncomingTransactionHelper_mutex, "f").acquire();
91
+ __classPrivateFieldGet(this, _IncomingTransactionHelper_log, "f").call(this, 'Checking');
85
92
  try {
86
- remoteTransactions =
87
- await __classPrivateFieldGet(this, _IncomingTransactionHelper_remoteTransactionSource, "f").fetchTransactions({
88
- address: account.address,
89
- cache,
90
- chainIds,
91
- includeTokenTransfers,
92
- queryEntireHistory,
93
- updateCache: __classPrivateFieldGet(this, _IncomingTransactionHelper_updateCache, "f"),
94
- updateTransactions,
93
+ if (!__classPrivateFieldGet(this, _IncomingTransactionHelper_instances, "m", _IncomingTransactionHelper_canStart).call(this)) {
94
+ return;
95
+ }
96
+ const latestBlockNumber = parseInt(latestBlockNumberHex || (await __classPrivateFieldGet(this, _IncomingTransactionHelper_blockTracker, "f").getLatestBlock()), 16);
97
+ const additionalLastFetchedKeys = __classPrivateFieldGet(this, _IncomingTransactionHelper_remoteTransactionSource, "f").getLastBlockVariations?.() ?? [];
98
+ const fromBlock = __classPrivateFieldGet(this, _IncomingTransactionHelper_instances, "m", _IncomingTransactionHelper_getFromBlock).call(this, latestBlockNumber);
99
+ const account = __classPrivateFieldGet(this, _IncomingTransactionHelper_getCurrentAccount, "f").call(this);
100
+ const chainId = __classPrivateFieldGet(this, _IncomingTransactionHelper_getChainId, "f").call(this);
101
+ let remoteTransactions = [];
102
+ try {
103
+ remoteTransactions =
104
+ await __classPrivateFieldGet(this, _IncomingTransactionHelper_remoteTransactionSource, "f").fetchTransactions({
105
+ address: account.address,
106
+ chainId,
107
+ fromBlock,
108
+ limit: __classPrivateFieldGet(this, _IncomingTransactionHelper_transactionLimit, "f"),
109
+ });
110
+ // TODO: Replace `any` with type
111
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
112
+ }
113
+ catch (error) {
114
+ __classPrivateFieldGet(this, _IncomingTransactionHelper_log, "f").call(this, 'Error while fetching remote transactions', error);
115
+ return;
116
+ }
117
+ if (!__classPrivateFieldGet(this, _IncomingTransactionHelper_updateTransactions, "f")) {
118
+ const address = account.address.toLowerCase();
119
+ remoteTransactions = remoteTransactions.filter((tx) => tx.txParams.to?.toLowerCase() === address);
120
+ }
121
+ const localTransactions = !__classPrivateFieldGet(this, _IncomingTransactionHelper_updateTransactions, "f")
122
+ ? []
123
+ : __classPrivateFieldGet(this, _IncomingTransactionHelper_getLocalTransactions, "f").call(this);
124
+ const newTransactions = __classPrivateFieldGet(this, _IncomingTransactionHelper_instances, "m", _IncomingTransactionHelper_getNewTransactions).call(this, remoteTransactions, localTransactions);
125
+ const updatedTransactions = __classPrivateFieldGet(this, _IncomingTransactionHelper_instances, "m", _IncomingTransactionHelper_getUpdatedTransactions).call(this, remoteTransactions, localTransactions);
126
+ if (newTransactions.length > 0 || updatedTransactions.length > 0) {
127
+ __classPrivateFieldGet(this, _IncomingTransactionHelper_instances, "m", _IncomingTransactionHelper_sortTransactionsByTime).call(this, newTransactions);
128
+ __classPrivateFieldGet(this, _IncomingTransactionHelper_instances, "m", _IncomingTransactionHelper_sortTransactionsByTime).call(this, updatedTransactions);
129
+ __classPrivateFieldGet(this, _IncomingTransactionHelper_log, "f").call(this, 'Found incoming transactions', {
130
+ new: newTransactions,
131
+ updated: updatedTransactions,
95
132
  });
133
+ this.hub.emit('transactions', {
134
+ added: newTransactions,
135
+ updated: updatedTransactions,
136
+ });
137
+ }
138
+ __classPrivateFieldGet(this, _IncomingTransactionHelper_instances, "m", _IncomingTransactionHelper_updateLastFetchedBlockNumber).call(this, remoteTransactions, additionalLastFetchedKeys);
96
139
  }
97
- catch (error) {
98
- log('Error while fetching remote transactions', error);
99
- return;
100
- }
101
- if (!remoteTransactions.length) {
102
- return;
103
- }
104
- __classPrivateFieldGet(this, _IncomingTransactionHelper_instances, "m", _IncomingTransactionHelper_sortTransactionsByTime).call(this, remoteTransactions);
105
- log('Found potential transactions', remoteTransactions.length, remoteTransactions);
106
- const localTransactions = __classPrivateFieldGet(this, _IncomingTransactionHelper_getLocalTransactions, "f").call(this);
107
- const uniqueTransactions = remoteTransactions.filter((tx) => !localTransactions.some((currentTx) => currentTx.hash?.toLowerCase() === tx.hash?.toLowerCase() &&
108
- currentTx.txParams.from?.toLowerCase() ===
109
- tx.txParams.from?.toLowerCase()));
110
- if (!uniqueTransactions.length) {
111
- log('All transactions are already known');
112
- return;
113
- }
114
- log('Found unique transactions', uniqueTransactions.length, uniqueTransactions);
115
- const trimmedTransactions = __classPrivateFieldGet(this, _IncomingTransactionHelper_trimTransactions, "f").call(this, [
116
- ...uniqueTransactions,
117
- ...localTransactions,
118
- ]);
119
- const uniqueTransactionIds = uniqueTransactions.map((tx) => tx.id);
120
- const newTransactions = trimmedTransactions.filter((tx) => uniqueTransactionIds.includes(tx.id));
121
- if (!newTransactions.length) {
122
- log('All unique transactions truncated due to limit');
123
- return;
140
+ finally {
141
+ releaseLock();
124
142
  }
125
- log('Adding new transactions', newTransactions.length, newTransactions);
126
- this.hub.emit('transactions', newTransactions);
127
143
  }
128
144
  }
129
- _IncomingTransactionHelper_getCache = new WeakMap(), _IncomingTransactionHelper_getCurrentAccount = new WeakMap(), _IncomingTransactionHelper_getChainIds = new WeakMap(), _IncomingTransactionHelper_getLocalTransactions = new WeakMap(), _IncomingTransactionHelper_includeTokenTransfers = new WeakMap(), _IncomingTransactionHelper_isEnabled = new WeakMap(), _IncomingTransactionHelper_isRunning = new WeakMap(), _IncomingTransactionHelper_queryEntireHistory = new WeakMap(), _IncomingTransactionHelper_remoteTransactionSource = new WeakMap(), _IncomingTransactionHelper_timeoutId = new WeakMap(), _IncomingTransactionHelper_trimTransactions = new WeakMap(), _IncomingTransactionHelper_updateCache = new WeakMap(), _IncomingTransactionHelper_updateTransactions = new WeakMap(), _IncomingTransactionHelper_instances = new WeakSet(), _IncomingTransactionHelper_onInterval = async function _IncomingTransactionHelper_onInterval() {
130
- try {
131
- await this.update({ isInterval: true });
145
+ _IncomingTransactionHelper_blockTracker = new WeakMap(), _IncomingTransactionHelper_getCurrentAccount = new WeakMap(), _IncomingTransactionHelper_getLastFetchedBlockNumbers = new WeakMap(), _IncomingTransactionHelper_getLocalTransactions = new WeakMap(), _IncomingTransactionHelper_getChainId = new WeakMap(), _IncomingTransactionHelper_isEnabled = new WeakMap(), _IncomingTransactionHelper_isRunning = new WeakMap(), _IncomingTransactionHelper_log = new WeakMap(), _IncomingTransactionHelper_mutex = new WeakMap(), _IncomingTransactionHelper_onLatestBlock = new WeakMap(), _IncomingTransactionHelper_queryEntireHistory = new WeakMap(), _IncomingTransactionHelper_remoteTransactionSource = new WeakMap(), _IncomingTransactionHelper_transactionLimit = new WeakMap(), _IncomingTransactionHelper_updateTransactions = new WeakMap(), _IncomingTransactionHelper_instances = new WeakSet(), _IncomingTransactionHelper_sortTransactionsByTime = function _IncomingTransactionHelper_sortTransactionsByTime(transactions) {
146
+ transactions.sort((a, b) => (a.time < b.time ? -1 : 1));
147
+ }, _IncomingTransactionHelper_getNewTransactions = function _IncomingTransactionHelper_getNewTransactions(remoteTxs, localTxs) {
148
+ return remoteTxs.filter((tx) => !localTxs.some(({ hash }) => hash === tx.hash));
149
+ }, _IncomingTransactionHelper_getUpdatedTransactions = function _IncomingTransactionHelper_getUpdatedTransactions(remoteTxs, localTxs) {
150
+ return remoteTxs.filter((remoteTx) => localTxs.some((localTx) => remoteTx.hash === localTx.hash &&
151
+ __classPrivateFieldGet(this, _IncomingTransactionHelper_instances, "m", _IncomingTransactionHelper_isTransactionOutdated).call(this, remoteTx, localTx)));
152
+ }, _IncomingTransactionHelper_isTransactionOutdated = function _IncomingTransactionHelper_isTransactionOutdated(remoteTx, localTx) {
153
+ return UPDATE_CHECKS.some((getValue) => getValue(remoteTx) !== getValue(localTx));
154
+ }, _IncomingTransactionHelper_getLastFetchedBlockNumberDec = function _IncomingTransactionHelper_getLastFetchedBlockNumberDec() {
155
+ const additionalLastFetchedKeys = __classPrivateFieldGet(this, _IncomingTransactionHelper_remoteTransactionSource, "f").getLastBlockVariations?.() ?? [];
156
+ const lastFetchedKey = __classPrivateFieldGet(this, _IncomingTransactionHelper_instances, "m", _IncomingTransactionHelper_getBlockNumberKey).call(this, additionalLastFetchedKeys);
157
+ const lastFetchedBlockNumbers = __classPrivateFieldGet(this, _IncomingTransactionHelper_getLastFetchedBlockNumbers, "f").call(this);
158
+ return lastFetchedBlockNumbers[lastFetchedKey];
159
+ }, _IncomingTransactionHelper_getFromBlock = function _IncomingTransactionHelper_getFromBlock(latestBlockNumber) {
160
+ const lastFetchedBlockNumber = __classPrivateFieldGet(this, _IncomingTransactionHelper_instances, "m", _IncomingTransactionHelper_getLastFetchedBlockNumberDec).call(this);
161
+ if (lastFetchedBlockNumber) {
162
+ return lastFetchedBlockNumber + 1;
132
163
  }
133
- catch (error) {
134
- console.error('Error while checking incoming transactions', error);
164
+ return __classPrivateFieldGet(this, _IncomingTransactionHelper_queryEntireHistory, "f")
165
+ ? undefined
166
+ : latestBlockNumber - RECENT_HISTORY_BLOCK_RANGE;
167
+ }, _IncomingTransactionHelper_updateLastFetchedBlockNumber = function _IncomingTransactionHelper_updateLastFetchedBlockNumber(remoteTxs, additionalKeys) {
168
+ let lastFetchedBlockNumber = -1;
169
+ for (const tx of remoteTxs) {
170
+ const currentBlockNumberValue = tx.blockNumber
171
+ ? parseInt(tx.blockNumber, 10)
172
+ : -1;
173
+ lastFetchedBlockNumber = Math.max(lastFetchedBlockNumber, currentBlockNumberValue);
135
174
  }
136
- if (__classPrivateFieldGet(this, _IncomingTransactionHelper_isRunning, "f")) {
137
- // eslint-disable-next-line @typescript-eslint/no-misused-promises
138
- __classPrivateFieldSet(this, _IncomingTransactionHelper_timeoutId, setTimeout(() => __classPrivateFieldGet(this, _IncomingTransactionHelper_instances, "m", _IncomingTransactionHelper_onInterval).call(this), INTERVAL), "f");
175
+ if (lastFetchedBlockNumber === -1) {
176
+ return;
139
177
  }
140
- }, _IncomingTransactionHelper_sortTransactionsByTime = function _IncomingTransactionHelper_sortTransactionsByTime(transactions) {
141
- transactions.sort((a, b) => (a.time < b.time ? -1 : 1));
178
+ const lastFetchedKey = __classPrivateFieldGet(this, _IncomingTransactionHelper_instances, "m", _IncomingTransactionHelper_getBlockNumberKey).call(this, additionalKeys);
179
+ const lastFetchedBlockNumbers = __classPrivateFieldGet(this, _IncomingTransactionHelper_getLastFetchedBlockNumbers, "f").call(this);
180
+ const previousValue = lastFetchedBlockNumbers[lastFetchedKey];
181
+ if (previousValue >= lastFetchedBlockNumber) {
182
+ return;
183
+ }
184
+ this.hub.emit('updatedLastFetchedBlockNumbers', {
185
+ lastFetchedBlockNumbers: {
186
+ ...lastFetchedBlockNumbers,
187
+ [lastFetchedKey]: lastFetchedBlockNumber,
188
+ },
189
+ blockNumber: lastFetchedBlockNumber,
190
+ });
191
+ }, _IncomingTransactionHelper_getBlockNumberKey = function _IncomingTransactionHelper_getBlockNumberKey(additionalKeys) {
192
+ const chainId = __classPrivateFieldGet(this, _IncomingTransactionHelper_getChainId, "f").call(this);
193
+ const currentAccount = __classPrivateFieldGet(this, _IncomingTransactionHelper_getCurrentAccount, "f").call(this)?.address.toLowerCase();
194
+ return [chainId, currentAccount, ...additionalKeys].join('#');
142
195
  }, _IncomingTransactionHelper_canStart = function _IncomingTransactionHelper_canStart() {
143
196
  const isEnabled = __classPrivateFieldGet(this, _IncomingTransactionHelper_isEnabled, "f").call(this);
144
- const chainIds = __classPrivateFieldGet(this, _IncomingTransactionHelper_getChainIds, "f").call(this);
145
- const supportedChainIds = __classPrivateFieldGet(this, _IncomingTransactionHelper_remoteTransactionSource, "f").getSupportedChains();
146
- const isAnyChainSupported = chainIds.some((chainId) => supportedChainIds.includes(chainId));
147
- return isEnabled && isAnyChainSupported;
197
+ const chainId = __classPrivateFieldGet(this, _IncomingTransactionHelper_getChainId, "f").call(this);
198
+ const isSupportedNetwork = __classPrivateFieldGet(this, _IncomingTransactionHelper_remoteTransactionSource, "f").isSupportedNetwork(chainId);
199
+ return isEnabled && isSupportedNetwork;
148
200
  };
149
201
  //# sourceMappingURL=IncomingTransactionHelper.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"IncomingTransactionHelper.mjs","sourceRoot":"","sources":["../../src/helpers/IncomingTransactionHelper.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AccountsController } from '@metamask/accounts-controller';\nimport type { Hex } from '@metamask/utils';\n// This package purposefully relies on Node's EventEmitter module.\n// eslint-disable-next-line import/no-nodejs-modules\nimport EventEmitter from 'events';\n\nimport { incomingTransactionsLogger as log } from '../logger';\nimport type { RemoteTransactionSource, TransactionMeta } from '../types';\n\nexport type IncomingTransactionOptions = {\n includeTokenTransfers?: boolean;\n isEnabled?: () => boolean;\n queryEntireHistory?: boolean;\n updateTransactions?: boolean;\n};\n\nconst INTERVAL = 1000 * 30; // 30 Seconds\n\nexport class IncomingTransactionHelper {\n hub: EventEmitter;\n\n #getCache: () => Record<string, unknown>;\n\n #getCurrentAccount: () => ReturnType<\n AccountsController['getSelectedAccount']\n >;\n\n #getChainIds: () => Hex[];\n\n #getLocalTransactions: () => TransactionMeta[];\n\n #includeTokenTransfers?: boolean;\n\n #isEnabled: () => boolean;\n\n #isRunning: boolean;\n\n #queryEntireHistory?: boolean;\n\n #remoteTransactionSource: RemoteTransactionSource;\n\n #timeoutId?: unknown;\n\n #trimTransactions: (transactions: TransactionMeta[]) => TransactionMeta[];\n\n #updateCache: (fn: (cache: Record<string, unknown>) => void) => void;\n\n #updateTransactions?: boolean;\n\n constructor({\n getCache,\n getCurrentAccount,\n getChainIds,\n getLocalTransactions,\n includeTokenTransfers,\n isEnabled,\n queryEntireHistory,\n remoteTransactionSource,\n trimTransactions,\n updateCache,\n updateTransactions,\n }: {\n getCache: () => Record<string, unknown>;\n getCurrentAccount: () => ReturnType<\n AccountsController['getSelectedAccount']\n >;\n getChainIds: () => Hex[];\n getLocalTransactions: () => TransactionMeta[];\n includeTokenTransfers?: boolean;\n isEnabled?: () => boolean;\n queryEntireHistory?: boolean;\n remoteTransactionSource: RemoteTransactionSource;\n trimTransactions: (transactions: TransactionMeta[]) => TransactionMeta[];\n updateCache: (fn: (cache: Record<string, unknown>) => void) => void;\n updateTransactions?: boolean;\n }) {\n this.hub = new EventEmitter();\n\n this.#getCache = getCache;\n this.#getCurrentAccount = getCurrentAccount;\n this.#getChainIds = getChainIds;\n this.#getLocalTransactions = getLocalTransactions;\n this.#includeTokenTransfers = includeTokenTransfers;\n this.#isEnabled = isEnabled ?? (() => true);\n this.#isRunning = false;\n this.#queryEntireHistory = queryEntireHistory;\n this.#remoteTransactionSource = remoteTransactionSource;\n this.#trimTransactions = trimTransactions;\n this.#updateCache = updateCache;\n this.#updateTransactions = updateTransactions;\n }\n\n start() {\n if (this.#isRunning) {\n return;\n }\n\n if (!this.#canStart()) {\n return;\n }\n\n log('Starting polling');\n\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n this.#timeoutId = setTimeout(() => this.#onInterval(), INTERVAL);\n this.#isRunning = true;\n\n log('Started polling');\n }\n\n stop() {\n if (this.#timeoutId) {\n clearTimeout(this.#timeoutId as number);\n }\n\n if (!this.#isRunning) {\n return;\n }\n\n this.#isRunning = false;\n\n log('Stopped polling');\n }\n\n async #onInterval() {\n try {\n await this.update({ isInterval: true });\n } catch (error) {\n console.error('Error while checking incoming transactions', error);\n }\n\n if (this.#isRunning) {\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n this.#timeoutId = setTimeout(() => this.#onInterval(), INTERVAL);\n }\n }\n\n async update({ isInterval }: { isInterval?: boolean } = {}): Promise<void> {\n log('Checking for incoming transactions', {\n isInterval: Boolean(isInterval),\n });\n\n if (!this.#canStart()) {\n return;\n }\n\n const account = this.#getCurrentAccount();\n const chainIds = this.#getChainIds();\n const cache = this.#getCache();\n const includeTokenTransfers = this.#includeTokenTransfers ?? true;\n const queryEntireHistory = this.#queryEntireHistory ?? true;\n const updateTransactions = this.#updateTransactions ?? false;\n\n let remoteTransactions: TransactionMeta[] = [];\n\n try {\n remoteTransactions =\n await this.#remoteTransactionSource.fetchTransactions({\n address: account.address as Hex,\n cache,\n chainIds,\n includeTokenTransfers,\n queryEntireHistory,\n updateCache: this.#updateCache,\n updateTransactions,\n });\n } catch (error: unknown) {\n log('Error while fetching remote transactions', error);\n return;\n }\n\n if (!remoteTransactions.length) {\n return;\n }\n\n this.#sortTransactionsByTime(remoteTransactions);\n\n log(\n 'Found potential transactions',\n remoteTransactions.length,\n remoteTransactions,\n );\n\n const localTransactions = this.#getLocalTransactions();\n\n const uniqueTransactions = remoteTransactions.filter(\n (tx) =>\n !localTransactions.some(\n (currentTx) =>\n currentTx.hash?.toLowerCase() === tx.hash?.toLowerCase() &&\n currentTx.txParams.from?.toLowerCase() ===\n tx.txParams.from?.toLowerCase(),\n ),\n );\n\n if (!uniqueTransactions.length) {\n log('All transactions are already known');\n return;\n }\n\n log(\n 'Found unique transactions',\n uniqueTransactions.length,\n uniqueTransactions,\n );\n\n const trimmedTransactions = this.#trimTransactions([\n ...uniqueTransactions,\n ...localTransactions,\n ]);\n\n const uniqueTransactionIds = uniqueTransactions.map((tx) => tx.id);\n\n const newTransactions = trimmedTransactions.filter((tx) =>\n uniqueTransactionIds.includes(tx.id),\n );\n\n if (!newTransactions.length) {\n log('All unique transactions truncated due to limit');\n return;\n }\n\n log('Adding new transactions', newTransactions.length, newTransactions);\n\n this.hub.emit('transactions', newTransactions);\n }\n\n #sortTransactionsByTime(transactions: TransactionMeta[]) {\n transactions.sort((a, b) => (a.time < b.time ? -1 : 1));\n }\n\n #canStart(): boolean {\n const isEnabled = this.#isEnabled();\n const chainIds = this.#getChainIds();\n\n const supportedChainIds =\n this.#remoteTransactionSource.getSupportedChains();\n\n const isAnyChainSupported = chainIds.some((chainId) =>\n supportedChainIds.includes(chainId),\n );\n\n return isEnabled && isAnyChainSupported;\n }\n}\n"]}
1
+ {"version":3,"file":"IncomingTransactionHelper.mjs","sourceRoot":"","sources":["../../src/helpers/IncomingTransactionHelper.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AccountsController } from '@metamask/accounts-controller';\nimport type { BlockTracker } from '@metamask/network-controller';\nimport type { Hex } from '@metamask/utils';\nimport { Mutex } from 'async-mutex';\n// This package purposefully relies on Node's EventEmitter module.\n// eslint-disable-next-line import/no-nodejs-modules\nimport EventEmitter from 'events';\n\nimport {\n createModuleLogger,\n incomingTransactionsLogger as log,\n} from '../logger';\nimport type { RemoteTransactionSource, TransactionMeta } from '../types';\n\nconst RECENT_HISTORY_BLOCK_RANGE = 10;\n\n// TODO: Replace `any` with type\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst UPDATE_CHECKS: ((txMeta: TransactionMeta) => any)[] = [\n (txMeta) => txMeta.status,\n (txMeta) => txMeta.txParams.gasUsed,\n];\n\n/**\n * Configuration options for the IncomingTransactionHelper\n *\n * @property includeTokenTransfers - Whether or not to include ERC20 token transfers.\n * @property isEnabled - Whether or not incoming transaction retrieval is enabled.\n * @property queryEntireHistory - Whether to initially query the entire transaction history or only recent blocks.\n * @property updateTransactions - Whether to update local transactions using remote transaction data.\n */\nexport type IncomingTransactionOptions = {\n includeTokenTransfers?: boolean;\n isEnabled?: () => boolean;\n queryEntireHistory?: boolean;\n updateTransactions?: boolean;\n};\n\nexport class IncomingTransactionHelper {\n hub: EventEmitter;\n\n #blockTracker: BlockTracker;\n\n #getCurrentAccount: () => ReturnType<\n AccountsController['getSelectedAccount']\n >;\n\n #getLastFetchedBlockNumbers: () => Record<string, number>;\n\n #getLocalTransactions: () => TransactionMeta[];\n\n #getChainId: () => Hex;\n\n #isEnabled: () => boolean;\n\n #isRunning: boolean;\n\n #log: debug.Debugger;\n\n #mutex = new Mutex();\n\n #onLatestBlock: (blockNumberHex: Hex) => Promise<void>;\n\n #queryEntireHistory: boolean;\n\n #remoteTransactionSource: RemoteTransactionSource;\n\n #transactionLimit?: number;\n\n #updateTransactions: boolean;\n\n constructor({\n blockTracker,\n getCurrentAccount,\n getLastFetchedBlockNumbers,\n getLocalTransactions,\n getChainId,\n isEnabled,\n queryEntireHistory,\n remoteTransactionSource,\n transactionLimit,\n updateTransactions,\n }: {\n blockTracker: BlockTracker;\n getCurrentAccount: () => ReturnType<\n AccountsController['getSelectedAccount']\n >;\n getLastFetchedBlockNumbers: () => Record<string, number>;\n getLocalTransactions?: () => TransactionMeta[];\n getChainId: () => Hex;\n isEnabled?: () => boolean;\n queryEntireHistory?: boolean;\n remoteTransactionSource: RemoteTransactionSource;\n transactionLimit?: number;\n updateTransactions?: boolean;\n }) {\n this.hub = new EventEmitter();\n\n this.#blockTracker = blockTracker;\n this.#getCurrentAccount = getCurrentAccount;\n this.#getLastFetchedBlockNumbers = getLastFetchedBlockNumbers;\n this.#getLocalTransactions = getLocalTransactions || (() => []);\n this.#getChainId = getChainId;\n this.#isEnabled = isEnabled ?? (() => true);\n this.#isRunning = false;\n this.#log = createModuleLogger(log, getChainId());\n this.#queryEntireHistory = queryEntireHistory ?? true;\n this.#remoteTransactionSource = remoteTransactionSource;\n this.#transactionLimit = transactionLimit;\n this.#updateTransactions = updateTransactions ?? false;\n\n // Using a property instead of a method to provide a listener reference\n // with the correct scope that we can remove later if stopped.\n this.#onLatestBlock = async (blockNumberHex: Hex) => {\n try {\n await this.update(blockNumberHex);\n } catch (error) {\n console.error('Error while checking incoming transactions', error);\n }\n };\n }\n\n start() {\n if (this.#isRunning) {\n return;\n }\n\n if (!this.#canStart()) {\n return;\n }\n\n this.#log('Starting polling');\n\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n this.#blockTracker.addListener('latest', this.#onLatestBlock);\n this.#isRunning = true;\n }\n\n stop() {\n if (!this.#isRunning) {\n return;\n }\n\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n this.#blockTracker.removeListener('latest', this.#onLatestBlock);\n this.#isRunning = false;\n\n this.#log('Stopped polling');\n }\n\n async update(latestBlockNumberHex?: Hex): Promise<void> {\n const releaseLock = await this.#mutex.acquire();\n\n this.#log('Checking');\n\n try {\n if (!this.#canStart()) {\n return;\n }\n\n const latestBlockNumber = parseInt(\n latestBlockNumberHex || (await this.#blockTracker.getLatestBlock()),\n 16,\n );\n\n const additionalLastFetchedKeys =\n this.#remoteTransactionSource.getLastBlockVariations?.() ?? [];\n\n const fromBlock = this.#getFromBlock(latestBlockNumber);\n const account = this.#getCurrentAccount();\n const chainId = this.#getChainId();\n\n let remoteTransactions = [];\n\n try {\n remoteTransactions =\n await this.#remoteTransactionSource.fetchTransactions({\n address: account.address,\n chainId,\n fromBlock,\n limit: this.#transactionLimit,\n });\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (error: any) {\n this.#log('Error while fetching remote transactions', error);\n return;\n }\n\n if (!this.#updateTransactions) {\n const address = account.address.toLowerCase();\n remoteTransactions = remoteTransactions.filter(\n (tx) => tx.txParams.to?.toLowerCase() === address,\n );\n }\n\n const localTransactions = !this.#updateTransactions\n ? []\n : this.#getLocalTransactions();\n\n const newTransactions = this.#getNewTransactions(\n remoteTransactions,\n localTransactions,\n );\n\n const updatedTransactions = this.#getUpdatedTransactions(\n remoteTransactions,\n localTransactions,\n );\n\n if (newTransactions.length > 0 || updatedTransactions.length > 0) {\n this.#sortTransactionsByTime(newTransactions);\n this.#sortTransactionsByTime(updatedTransactions);\n\n this.#log('Found incoming transactions', {\n new: newTransactions,\n updated: updatedTransactions,\n });\n\n this.hub.emit('transactions', {\n added: newTransactions,\n updated: updatedTransactions,\n });\n }\n this.#updateLastFetchedBlockNumber(\n remoteTransactions,\n additionalLastFetchedKeys,\n );\n } finally {\n releaseLock();\n }\n }\n\n #sortTransactionsByTime(transactions: TransactionMeta[]) {\n transactions.sort((a, b) => (a.time < b.time ? -1 : 1));\n }\n\n #getNewTransactions(\n remoteTxs: TransactionMeta[],\n localTxs: TransactionMeta[],\n ): TransactionMeta[] {\n return remoteTxs.filter(\n (tx) => !localTxs.some(({ hash }) => hash === tx.hash),\n );\n }\n\n #getUpdatedTransactions(\n remoteTxs: TransactionMeta[],\n localTxs: TransactionMeta[],\n ): TransactionMeta[] {\n return remoteTxs.filter((remoteTx) =>\n localTxs.some(\n (localTx) =>\n remoteTx.hash === localTx.hash &&\n this.#isTransactionOutdated(remoteTx, localTx),\n ),\n );\n }\n\n #isTransactionOutdated(\n remoteTx: TransactionMeta,\n localTx: TransactionMeta,\n ): boolean {\n return UPDATE_CHECKS.some(\n (getValue) => getValue(remoteTx) !== getValue(localTx),\n );\n }\n\n #getLastFetchedBlockNumberDec(): number {\n const additionalLastFetchedKeys =\n this.#remoteTransactionSource.getLastBlockVariations?.() ?? [];\n const lastFetchedKey = this.#getBlockNumberKey(additionalLastFetchedKeys);\n const lastFetchedBlockNumbers = this.#getLastFetchedBlockNumbers();\n return lastFetchedBlockNumbers[lastFetchedKey];\n }\n\n #getFromBlock(latestBlockNumber: number): number | undefined {\n const lastFetchedBlockNumber = this.#getLastFetchedBlockNumberDec();\n\n if (lastFetchedBlockNumber) {\n return lastFetchedBlockNumber + 1;\n }\n\n return this.#queryEntireHistory\n ? undefined\n : latestBlockNumber - RECENT_HISTORY_BLOCK_RANGE;\n }\n\n #updateLastFetchedBlockNumber(\n remoteTxs: TransactionMeta[],\n additionalKeys: string[],\n ) {\n let lastFetchedBlockNumber = -1;\n\n for (const tx of remoteTxs) {\n const currentBlockNumberValue = tx.blockNumber\n ? parseInt(tx.blockNumber, 10)\n : -1;\n\n lastFetchedBlockNumber = Math.max(\n lastFetchedBlockNumber,\n currentBlockNumberValue,\n );\n }\n\n if (lastFetchedBlockNumber === -1) {\n return;\n }\n\n const lastFetchedKey = this.#getBlockNumberKey(additionalKeys);\n const lastFetchedBlockNumbers = this.#getLastFetchedBlockNumbers();\n const previousValue = lastFetchedBlockNumbers[lastFetchedKey];\n\n if (previousValue >= lastFetchedBlockNumber) {\n return;\n }\n\n this.hub.emit('updatedLastFetchedBlockNumbers', {\n lastFetchedBlockNumbers: {\n ...lastFetchedBlockNumbers,\n [lastFetchedKey]: lastFetchedBlockNumber,\n },\n blockNumber: lastFetchedBlockNumber,\n });\n }\n\n #getBlockNumberKey(additionalKeys: string[]): string {\n const chainId = this.#getChainId();\n const currentAccount = this.#getCurrentAccount()?.address.toLowerCase();\n\n return [chainId, currentAccount, ...additionalKeys].join('#');\n }\n\n #canStart(): boolean {\n const isEnabled = this.#isEnabled();\n const chainId = this.#getChainId();\n\n const isSupportedNetwork =\n this.#remoteTransactionSource.isSupportedNetwork(chainId);\n\n return isEnabled && isSupportedNetwork;\n }\n}\n"]}
@@ -10,29 +10,34 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
10
10
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
11
11
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
12
12
  };
13
- var _MultichainTrackingHelper_instances, _MultichainTrackingHelper_findNetworkClientIdByChainId, _MultichainTrackingHelper_getNetworkClientById, _MultichainTrackingHelper_getNetworkClientRegistry, _MultichainTrackingHelper_removePendingTransactionTrackerListeners, _MultichainTrackingHelper_createNonceTracker, _MultichainTrackingHelper_createPendingTransactionTracker, _MultichainTrackingHelper_nonceMutexesByChainId, _MultichainTrackingHelper_trackingMap, _MultichainTrackingHelper_refreshTrackingMap, _MultichainTrackingHelper_stopTrackingByNetworkClientId, _MultichainTrackingHelper_startTrackingByNetworkClientId, _MultichainTrackingHelper_getNetworkClient;
13
+ var _MultichainTrackingHelper_instances, _MultichainTrackingHelper_findNetworkClientIdByChainId, _MultichainTrackingHelper_getNetworkClientById, _MultichainTrackingHelper_getNetworkClientRegistry, _MultichainTrackingHelper_removeIncomingTransactionHelperListeners, _MultichainTrackingHelper_removePendingTransactionTrackerListeners, _MultichainTrackingHelper_createNonceTracker, _MultichainTrackingHelper_createIncomingTransactionHelper, _MultichainTrackingHelper_createPendingTransactionTracker, _MultichainTrackingHelper_createRemoteTransactionSource, _MultichainTrackingHelper_nonceMutexesByChainId, _MultichainTrackingHelper_trackingMap, _MultichainTrackingHelper_remoteTransactionSourcesMap, _MultichainTrackingHelper_refreshTrackingMap, _MultichainTrackingHelper_stopTrackingByNetworkClientId, _MultichainTrackingHelper_startTrackingByNetworkClientId, _MultichainTrackingHelper_refreshRemoteTransactionSources;
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.MultichainTrackingHelper = void 0;
16
16
  const async_mutex_1 = require("async-mutex");
17
17
  const logger_1 = require("../logger.cjs");
18
18
  const log = (0, logger_1.createModuleLogger)(logger_1.projectLogger, 'multichain-tracking');
19
19
  class MultichainTrackingHelper {
20
- constructor({ findNetworkClientIdByChainId, getNetworkClientById, getNetworkClientRegistry, removePendingTransactionTrackerListeners, createNonceTracker, createPendingTransactionTracker, onNetworkStateChange, }) {
20
+ constructor({ findNetworkClientIdByChainId, getNetworkClientById, getNetworkClientRegistry, removeIncomingTransactionHelperListeners, removePendingTransactionTrackerListeners, createNonceTracker, createIncomingTransactionHelper, createPendingTransactionTracker, createRemoteTransactionSource, onNetworkStateChange, }) {
21
21
  _MultichainTrackingHelper_instances.add(this);
22
22
  _MultichainTrackingHelper_findNetworkClientIdByChainId.set(this, void 0);
23
23
  _MultichainTrackingHelper_getNetworkClientById.set(this, void 0);
24
24
  _MultichainTrackingHelper_getNetworkClientRegistry.set(this, void 0);
25
+ _MultichainTrackingHelper_removeIncomingTransactionHelperListeners.set(this, void 0);
25
26
  _MultichainTrackingHelper_removePendingTransactionTrackerListeners.set(this, void 0);
26
27
  _MultichainTrackingHelper_createNonceTracker.set(this, void 0);
28
+ _MultichainTrackingHelper_createIncomingTransactionHelper.set(this, void 0);
27
29
  _MultichainTrackingHelper_createPendingTransactionTracker.set(this, void 0);
30
+ _MultichainTrackingHelper_createRemoteTransactionSource.set(this, void 0);
28
31
  _MultichainTrackingHelper_nonceMutexesByChainId.set(this, new Map());
29
32
  _MultichainTrackingHelper_trackingMap.set(this, new Map());
33
+ _MultichainTrackingHelper_remoteTransactionSourcesMap.set(this, new Map());
30
34
  this.checkForPendingTransactionAndStartPolling = () => {
31
35
  for (const [, trackers] of __classPrivateFieldGet(this, _MultichainTrackingHelper_trackingMap, "f")) {
32
36
  trackers.pendingTransactionTracker.startIfPendingTransactions();
33
37
  }
34
38
  };
35
39
  _MultichainTrackingHelper_refreshTrackingMap.set(this, (networkClients) => {
40
+ __classPrivateFieldGet(this, _MultichainTrackingHelper_refreshRemoteTransactionSources, "f").call(this, networkClients);
36
41
  const networkClientIds = Object.keys(networkClients);
37
42
  const existingNetworkClientIds = Array.from(__classPrivateFieldGet(this, _MultichainTrackingHelper_trackingMap, "f").keys());
38
43
  // Remove tracking for NetworkClientIds that no longer exist
@@ -52,12 +57,24 @@ class MultichainTrackingHelper {
52
57
  log('Removed trackers', networkClientIdsToRemove);
53
58
  }
54
59
  });
60
+ _MultichainTrackingHelper_refreshRemoteTransactionSources.set(this, (networkClients) => {
61
+ const chainIdsInRegistry = new Set();
62
+ Object.values(networkClients).forEach((networkClient) => chainIdsInRegistry.add(networkClient.configuration.chainId));
63
+ const existingChainIds = Array.from(__classPrivateFieldGet(this, _MultichainTrackingHelper_remoteTransactionSourcesMap, "f").keys());
64
+ const chainIdsToRemove = existingChainIds.filter((chainId) => !chainIdsInRegistry.has(chainId));
65
+ chainIdsToRemove.forEach((chainId) => {
66
+ __classPrivateFieldGet(this, _MultichainTrackingHelper_remoteTransactionSourcesMap, "f").delete(chainId);
67
+ });
68
+ });
55
69
  __classPrivateFieldSet(this, _MultichainTrackingHelper_findNetworkClientIdByChainId, findNetworkClientIdByChainId, "f");
56
70
  __classPrivateFieldSet(this, _MultichainTrackingHelper_getNetworkClientById, getNetworkClientById, "f");
57
71
  __classPrivateFieldSet(this, _MultichainTrackingHelper_getNetworkClientRegistry, getNetworkClientRegistry, "f");
72
+ __classPrivateFieldSet(this, _MultichainTrackingHelper_removeIncomingTransactionHelperListeners, removeIncomingTransactionHelperListeners, "f");
58
73
  __classPrivateFieldSet(this, _MultichainTrackingHelper_removePendingTransactionTrackerListeners, removePendingTransactionTrackerListeners, "f");
59
74
  __classPrivateFieldSet(this, _MultichainTrackingHelper_createNonceTracker, createNonceTracker, "f");
75
+ __classPrivateFieldSet(this, _MultichainTrackingHelper_createIncomingTransactionHelper, createIncomingTransactionHelper, "f");
60
76
  __classPrivateFieldSet(this, _MultichainTrackingHelper_createPendingTransactionTracker, createPendingTransactionTracker, "f");
77
+ __classPrivateFieldSet(this, _MultichainTrackingHelper_createRemoteTransactionSource, createRemoteTransactionSource, "f");
61
78
  onNetworkStateChange((_, patches) => {
62
79
  const networkClients = __classPrivateFieldGet(this, _MultichainTrackingHelper_getNetworkClientRegistry, "f").call(this);
63
80
  patches.forEach(({ op, path }) => {
@@ -136,6 +153,42 @@ class MultichainTrackingHelper {
136
153
  throw err;
137
154
  }
138
155
  }
156
+ startIncomingTransactionPolling(networkClientIds) {
157
+ const finalNetworkClientIds = networkClientIds ?? [
158
+ ...__classPrivateFieldGet(this, _MultichainTrackingHelper_trackingMap, "f").keys(),
159
+ ];
160
+ finalNetworkClientIds.forEach((networkClientId) => {
161
+ __classPrivateFieldGet(this, _MultichainTrackingHelper_trackingMap, "f").get(networkClientId)?.incomingTransactionHelper.start();
162
+ });
163
+ }
164
+ stopIncomingTransactionPolling(networkClientIds) {
165
+ const finalNetworkClientIds = networkClientIds ?? [
166
+ ...__classPrivateFieldGet(this, _MultichainTrackingHelper_trackingMap, "f").keys(),
167
+ ];
168
+ finalNetworkClientIds.forEach((networkClientId) => {
169
+ __classPrivateFieldGet(this, _MultichainTrackingHelper_trackingMap, "f").get(networkClientId)?.incomingTransactionHelper.stop();
170
+ });
171
+ }
172
+ stopAllIncomingTransactionPolling() {
173
+ for (const [, trackers] of __classPrivateFieldGet(this, _MultichainTrackingHelper_trackingMap, "f")) {
174
+ trackers.incomingTransactionHelper.stop();
175
+ }
176
+ }
177
+ async updateIncomingTransactions(networkClientIds) {
178
+ const finalNetworkClientIds = networkClientIds ?? [
179
+ ...__classPrivateFieldGet(this, _MultichainTrackingHelper_trackingMap, "f").keys(),
180
+ ];
181
+ const promises = await Promise.allSettled(finalNetworkClientIds.map(async (networkClientId) => {
182
+ return await __classPrivateFieldGet(this, _MultichainTrackingHelper_trackingMap, "f")
183
+ .get(networkClientId)
184
+ ?.incomingTransactionHelper.update();
185
+ }));
186
+ promises
187
+ .filter((result) => result.status === 'rejected')
188
+ .forEach((result) => {
189
+ log('Failed to update incoming transactions', result.reason);
190
+ });
191
+ }
139
192
  stopAllTracking() {
140
193
  for (const [networkClientId] of __classPrivateFieldGet(this, _MultichainTrackingHelper_trackingMap, "f")) {
141
194
  __classPrivateFieldGet(this, _MultichainTrackingHelper_instances, "m", _MultichainTrackingHelper_stopTrackingByNetworkClientId).call(this, networkClientId);
@@ -169,11 +222,13 @@ class MultichainTrackingHelper {
169
222
  }
170
223
  }
171
224
  exports.MultichainTrackingHelper = MultichainTrackingHelper;
172
- _MultichainTrackingHelper_findNetworkClientIdByChainId = new WeakMap(), _MultichainTrackingHelper_getNetworkClientById = new WeakMap(), _MultichainTrackingHelper_getNetworkClientRegistry = new WeakMap(), _MultichainTrackingHelper_removePendingTransactionTrackerListeners = new WeakMap(), _MultichainTrackingHelper_createNonceTracker = new WeakMap(), _MultichainTrackingHelper_createPendingTransactionTracker = new WeakMap(), _MultichainTrackingHelper_nonceMutexesByChainId = new WeakMap(), _MultichainTrackingHelper_trackingMap = new WeakMap(), _MultichainTrackingHelper_refreshTrackingMap = new WeakMap(), _MultichainTrackingHelper_instances = new WeakSet(), _MultichainTrackingHelper_stopTrackingByNetworkClientId = function _MultichainTrackingHelper_stopTrackingByNetworkClientId(networkClientId) {
225
+ _MultichainTrackingHelper_findNetworkClientIdByChainId = new WeakMap(), _MultichainTrackingHelper_getNetworkClientById = new WeakMap(), _MultichainTrackingHelper_getNetworkClientRegistry = new WeakMap(), _MultichainTrackingHelper_removeIncomingTransactionHelperListeners = new WeakMap(), _MultichainTrackingHelper_removePendingTransactionTrackerListeners = new WeakMap(), _MultichainTrackingHelper_createNonceTracker = new WeakMap(), _MultichainTrackingHelper_createIncomingTransactionHelper = new WeakMap(), _MultichainTrackingHelper_createPendingTransactionTracker = new WeakMap(), _MultichainTrackingHelper_createRemoteTransactionSource = new WeakMap(), _MultichainTrackingHelper_nonceMutexesByChainId = new WeakMap(), _MultichainTrackingHelper_trackingMap = new WeakMap(), _MultichainTrackingHelper_remoteTransactionSourcesMap = new WeakMap(), _MultichainTrackingHelper_refreshTrackingMap = new WeakMap(), _MultichainTrackingHelper_refreshRemoteTransactionSources = new WeakMap(), _MultichainTrackingHelper_instances = new WeakSet(), _MultichainTrackingHelper_stopTrackingByNetworkClientId = function _MultichainTrackingHelper_stopTrackingByNetworkClientId(networkClientId) {
173
226
  const trackers = __classPrivateFieldGet(this, _MultichainTrackingHelper_trackingMap, "f").get(networkClientId);
174
227
  if (trackers) {
175
228
  trackers.pendingTransactionTracker.stop();
176
229
  __classPrivateFieldGet(this, _MultichainTrackingHelper_removePendingTransactionTrackerListeners, "f").call(this, trackers.pendingTransactionTracker);
230
+ trackers.incomingTransactionHelper.stop();
231
+ __classPrivateFieldGet(this, _MultichainTrackingHelper_removeIncomingTransactionHelperListeners, "f").call(this, trackers.incomingTransactionHelper);
177
232
  __classPrivateFieldGet(this, _MultichainTrackingHelper_trackingMap, "f").delete(networkClientId);
178
233
  }
179
234
  }, _MultichainTrackingHelper_startTrackingByNetworkClientId = function _MultichainTrackingHelper_startTrackingByNetworkClientId(networkClientId) {
@@ -182,11 +237,22 @@ _MultichainTrackingHelper_findNetworkClientIdByChainId = new WeakMap(), _Multich
182
237
  return;
183
238
  }
184
239
  const { provider, blockTracker, configuration: { chainId }, } = __classPrivateFieldGet(this, _MultichainTrackingHelper_getNetworkClientById, "f").call(this, networkClientId);
240
+ let remoteTransactionSource = __classPrivateFieldGet(this, _MultichainTrackingHelper_remoteTransactionSourcesMap, "f").get(chainId);
241
+ if (!remoteTransactionSource) {
242
+ remoteTransactionSource = __classPrivateFieldGet(this, _MultichainTrackingHelper_createRemoteTransactionSource, "f").call(this);
243
+ __classPrivateFieldGet(this, _MultichainTrackingHelper_remoteTransactionSourcesMap, "f").set(chainId, remoteTransactionSource);
244
+ log('Created remote transaction source', chainId);
245
+ }
185
246
  const nonceTracker = __classPrivateFieldGet(this, _MultichainTrackingHelper_createNonceTracker, "f").call(this, {
186
247
  provider,
187
248
  blockTracker,
188
249
  chainId,
189
250
  });
251
+ const incomingTransactionHelper = __classPrivateFieldGet(this, _MultichainTrackingHelper_createIncomingTransactionHelper, "f").call(this, {
252
+ blockTracker,
253
+ remoteTransactionSource,
254
+ chainId,
255
+ });
190
256
  const pendingTransactionTracker = __classPrivateFieldGet(this, _MultichainTrackingHelper_createPendingTransactionTracker, "f").call(this, {
191
257
  provider,
192
258
  blockTracker,
@@ -194,27 +260,8 @@ _MultichainTrackingHelper_findNetworkClientIdByChainId = new WeakMap(), _Multich
194
260
  });
195
261
  __classPrivateFieldGet(this, _MultichainTrackingHelper_trackingMap, "f").set(networkClientId, {
196
262
  nonceTracker,
263
+ incomingTransactionHelper,
197
264
  pendingTransactionTracker,
198
265
  });
199
- }, _MultichainTrackingHelper_getNetworkClient = function _MultichainTrackingHelper_getNetworkClient({ networkClientId, chainId, } = {}) {
200
- let networkClient;
201
- if (networkClientId) {
202
- try {
203
- networkClient = __classPrivateFieldGet(this, _MultichainTrackingHelper_getNetworkClientById, "f").call(this, networkClientId);
204
- }
205
- catch (err) {
206
- log('failed to get network client by networkClientId');
207
- }
208
- }
209
- if (!networkClient && chainId) {
210
- try {
211
- const networkClientIdForChainId = __classPrivateFieldGet(this, _MultichainTrackingHelper_findNetworkClientIdByChainId, "f").call(this, chainId);
212
- networkClient = __classPrivateFieldGet(this, _MultichainTrackingHelper_getNetworkClientById, "f").call(this, networkClientIdForChainId);
213
- }
214
- catch (err) {
215
- log('failed to get network client by chainId');
216
- }
217
- }
218
- return networkClient;
219
266
  };
220
267
  //# sourceMappingURL=MultichainTrackingHelper.cjs.map