@metamask/smart-transactions-controller 6.2.2 → 7.0.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.
@@ -1,30 +1,43 @@
1
1
  "use strict";
2
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
3
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
4
+ 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");
5
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
6
+ };
2
7
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
8
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
9
  };
10
+ var _SmartTransactionsController_instances, _SmartTransactionsController_updateSmartTransaction, _SmartTransactionsController_confirmSmartTransaction, _SmartTransactionsController_getChainId, _SmartTransactionsController_getEthQuery;
5
11
  Object.defineProperty(exports, "__esModule", { value: true });
6
12
  exports.DEFAULT_INTERVAL = void 0;
7
- const base_controller_1 = require("@metamask/base-controller");
13
+ // eslint-disable-next-line import/no-nodejs-modules
14
+ const bytes_1 = require("@ethersproject/bytes");
8
15
  const controller_utils_1 = require("@metamask/controller-utils");
16
+ const eth_query_1 = __importDefault(require("@metamask/eth-query"));
17
+ const polling_controller_1 = require("@metamask/polling-controller");
9
18
  const bignumber_js_1 = require("bignumber.js");
10
- const bignumber_1 = require("@ethersproject/bignumber");
11
- const providers_1 = require("@ethersproject/providers");
12
- const bytes_1 = require("@ethersproject/bytes");
13
- const mapValues_1 = __importDefault(require("lodash/mapValues"));
19
+ // eslint-disable-next-line import/no-nodejs-modules
20
+ const events_1 = __importDefault(require("events"));
14
21
  const cloneDeep_1 = __importDefault(require("lodash/cloneDeep"));
22
+ const constants_1 = require("./constants");
15
23
  const types_1 = require("./types");
16
24
  const utils_1 = require("./utils");
17
- const constants_1 = require("./constants");
18
25
  const SECOND = 1000;
19
26
  exports.DEFAULT_INTERVAL = SECOND * 5;
20
- class SmartTransactionsController extends base_controller_1.BaseController {
21
- constructor({ onNetworkStateChange, getNonceLock, provider, confirmExternalTransaction, trackMetaMetricsEvent, }, config, state) {
27
+ const ETH_QUERY_ERROR_MSG = '`ethQuery` is not defined on SmartTransactionsController';
28
+ class SmartTransactionsController extends polling_controller_1.StaticIntervalPollingControllerV1 {
29
+ constructor({ onNetworkStateChange, getNonceLock, provider, confirmExternalTransaction, trackMetaMetricsEvent, getNetworkClientById, }, config, state) {
22
30
  super(config, state);
31
+ _SmartTransactionsController_instances.add(this);
32
+ /**
33
+ * Name of this controller used during composition
34
+ */
35
+ this.name = 'SmartTransactionsController';
23
36
  this.defaultConfig = {
24
37
  interval: exports.DEFAULT_INTERVAL,
25
38
  chainId: constants_1.CHAIN_IDS.ETHEREUM,
26
39
  clientId: 'default',
27
- supportedChainIds: [constants_1.CHAIN_IDS.ETHEREUM, constants_1.CHAIN_IDS.RINKEBY],
40
+ supportedChainIds: [constants_1.CHAIN_IDS.ETHEREUM, constants_1.CHAIN_IDS.GOERLI],
28
41
  };
29
42
  this.defaultState = {
30
43
  smartTransactionsState: {
@@ -36,22 +49,39 @@ class SmartTransactionsController extends base_controller_1.BaseController {
36
49
  tradeTxFees: undefined,
37
50
  },
38
51
  liveness: true,
52
+ livenessByChainId: {
53
+ [constants_1.CHAIN_IDS.ETHEREUM]: true,
54
+ [constants_1.CHAIN_IDS.GOERLI]: true,
55
+ },
56
+ feesByChainId: {
57
+ [constants_1.CHAIN_IDS.ETHEREUM]: {
58
+ approvalTxFees: undefined,
59
+ tradeTxFees: undefined,
60
+ },
61
+ [constants_1.CHAIN_IDS.GOERLI]: {
62
+ approvalTxFees: undefined,
63
+ tradeTxFees: undefined,
64
+ },
65
+ },
39
66
  },
40
67
  };
68
+ this.initialize();
69
+ this.setIntervalLength(this.config.interval);
41
70
  this.getNonceLock = getNonceLock;
42
- this.ethersProvider = new providers_1.Web3Provider(provider);
71
+ this.ethQuery = undefined;
43
72
  this.confirmExternalTransaction = confirmExternalTransaction;
44
73
  this.trackMetaMetricsEvent = trackMetaMetricsEvent;
45
- this.initialize();
74
+ this.getNetworkClientById = getNetworkClientById;
46
75
  this.initializeSmartTransactionsForChainId();
47
76
  onNetworkStateChange(({ providerConfig: newProvider }) => {
48
77
  const { chainId } = newProvider;
49
78
  this.configure({ chainId });
50
79
  this.initializeSmartTransactionsForChainId();
51
80
  this.checkPoll(this.state);
52
- this.ethersProvider = new providers_1.Web3Provider(provider);
81
+ this.ethQuery = new eth_query_1.default(provider);
53
82
  });
54
83
  this.subscribe((currentState) => this.checkPoll(currentState));
84
+ this.eventEmitter = new events_1.default();
55
85
  }
56
86
  /* istanbul ignore next */
57
87
  async fetch(request, options) {
@@ -59,6 +89,17 @@ class SmartTransactionsController extends base_controller_1.BaseController {
59
89
  const fetchOptions = Object.assign(Object.assign({}, options), { headers: Object.assign({ 'Content-Type': 'application/json' }, (clientId && { 'X-Client-Id': clientId })) });
60
90
  return (0, utils_1.handleFetch)(request, fetchOptions);
61
91
  }
92
+ async _executePoll(networkClientId) {
93
+ // if this is going to be truly UI driven polling we shouldn't really reach here
94
+ // with a networkClientId that is not supported, but for now I'll add a check in case
95
+ // wondering if we should add some kind of predicate to the polling controller to check whether
96
+ // we should poll or not
97
+ const chainId = __classPrivateFieldGet(this, _SmartTransactionsController_instances, "m", _SmartTransactionsController_getChainId).call(this, { networkClientId });
98
+ if (!this.config.supportedChainIds.includes(chainId)) {
99
+ return Promise.resolve();
100
+ }
101
+ return this.updateSmartTransactions({ networkClientId });
102
+ }
62
103
  checkPoll(state) {
63
104
  const { smartTransactions } = state.smartTransactionsState;
64
105
  const currentSmartTransactions = smartTransactions[this.config.chainId];
@@ -86,9 +127,9 @@ class SmartTransactionsController extends base_controller_1.BaseController {
86
127
  if (!supportedChainIds.includes(chainId)) {
87
128
  return;
88
129
  }
89
- await (0, controller_utils_1.safelyExecute)(() => this.updateSmartTransactions());
130
+ await (0, controller_utils_1.safelyExecute)(async () => this.updateSmartTransactions());
90
131
  this.timeoutHandle = setInterval(() => {
91
- (0, controller_utils_1.safelyExecute)(() => this.updateSmartTransactions());
132
+ (0, controller_utils_1.safelyExecute)(async () => this.updateSmartTransactions());
92
133
  }, this.config.interval);
93
134
  }
94
135
  async stop() {
@@ -121,8 +162,8 @@ class SmartTransactionsController extends base_controller_1.BaseController {
121
162
  stx_user_opt_in: true,
122
163
  };
123
164
  this.trackMetaMetricsEvent({
124
- event: 'STX Status Updated',
125
- category: 'swaps',
165
+ event: constants_1.MetaMetricsEventName.StxStatusUpdated,
166
+ category: constants_1.MetaMetricsEventCategory.Transactions,
126
167
  sensitiveProperties,
127
168
  });
128
169
  }
@@ -134,123 +175,48 @@ class SmartTransactionsController extends base_controller_1.BaseController {
134
175
  const currentIndex = currentSmartTransactions === null || currentSmartTransactions === void 0 ? void 0 : currentSmartTransactions.findIndex((stx) => stx.uuid === smartTransactionUuid);
135
176
  return currentIndex === -1 || currentIndex === undefined;
136
177
  }
137
- updateSmartTransaction(smartTransaction) {
138
- const { chainId } = this.config;
139
- const { smartTransactionsState } = this.state;
140
- const { smartTransactions } = smartTransactionsState;
141
- const currentSmartTransactions = smartTransactions[chainId];
142
- const currentIndex = currentSmartTransactions === null || currentSmartTransactions === void 0 ? void 0 : currentSmartTransactions.findIndex((stx) => stx.uuid === smartTransaction.uuid);
143
- const isNewSmartTransaction = this.isNewSmartTransaction(smartTransaction.uuid);
144
- this.trackStxStatusChange(smartTransaction, isNewSmartTransaction
145
- ? undefined
146
- : currentSmartTransactions[currentIndex]);
147
- if (isNewSmartTransaction) {
148
- // add smart transaction
149
- const cancelledNonceIndex = currentSmartTransactions.findIndex((stx) => {
150
- var _a, _b, _c;
151
- return ((_a = stx.txParams) === null || _a === void 0 ? void 0 : _a.nonce) === ((_b = smartTransaction.txParams) === null || _b === void 0 ? void 0 : _b.nonce) &&
152
- ((_c = stx.status) === null || _c === void 0 ? void 0 : _c.startsWith('cancelled'));
153
- });
154
- const snapshot = (0, cloneDeep_1.default)(smartTransaction);
155
- const history = [snapshot];
156
- const historifiedSmartTransaction = Object.assign(Object.assign({}, smartTransaction), { history });
157
- const nextSmartTransactions = cancelledNonceIndex > -1
158
- ? currentSmartTransactions
159
- .slice(0, cancelledNonceIndex)
160
- .concat(currentSmartTransactions.slice(cancelledNonceIndex + 1))
161
- .concat(historifiedSmartTransaction)
162
- : currentSmartTransactions.concat(historifiedSmartTransaction);
163
- this.update({
164
- smartTransactionsState: Object.assign(Object.assign({}, smartTransactionsState), { smartTransactions: Object.assign(Object.assign({}, smartTransactionsState.smartTransactions), { [chainId]: nextSmartTransactions }) }),
165
- });
166
- return;
178
+ updateSmartTransaction(smartTransaction, { networkClientId } = {}) {
179
+ let { ethQuery, config: { chainId }, } = this;
180
+ if (networkClientId) {
181
+ const networkClient = this.getNetworkClientById(networkClientId);
182
+ chainId = networkClient.configuration.chainId;
183
+ ethQuery = new eth_query_1.default(networkClient.provider);
167
184
  }
168
- if ((smartTransaction.status === types_1.SmartTransactionStatuses.SUCCESS ||
169
- smartTransaction.status === types_1.SmartTransactionStatuses.REVERTED) &&
170
- !smartTransaction.confirmed) {
171
- // confirm smart transaction
172
- const currentSmartTransaction = currentSmartTransactions[currentIndex];
173
- const nextSmartTransaction = Object.assign(Object.assign({}, currentSmartTransaction), smartTransaction);
174
- this.confirmSmartTransaction(nextSmartTransaction);
175
- }
176
- this.update({
177
- smartTransactionsState: Object.assign(Object.assign({}, smartTransactionsState), { smartTransactions: Object.assign(Object.assign({}, smartTransactionsState.smartTransactions), { [chainId]: smartTransactionsState.smartTransactions[chainId].map((item, index) => {
178
- return index === currentIndex
179
- ? Object.assign(Object.assign({}, item), smartTransaction) : item;
180
- }) }) }),
185
+ __classPrivateFieldGet(this, _SmartTransactionsController_instances, "m", _SmartTransactionsController_updateSmartTransaction).call(this, smartTransaction, {
186
+ chainId,
187
+ ethQuery,
181
188
  });
182
189
  }
183
- async updateSmartTransactions() {
190
+ async updateSmartTransactions({ networkClientId, } = {}) {
184
191
  const { smartTransactions } = this.state.smartTransactionsState;
185
- const { chainId } = this.config;
186
- const currentSmartTransactions = smartTransactions === null || smartTransactions === void 0 ? void 0 : smartTransactions[chainId];
187
- const transactionsToUpdate = currentSmartTransactions
192
+ const chainId = __classPrivateFieldGet(this, _SmartTransactionsController_instances, "m", _SmartTransactionsController_getChainId).call(this, { networkClientId });
193
+ const smartTransactionsForChainId = smartTransactions[chainId];
194
+ const transactionsToUpdate = smartTransactionsForChainId
188
195
  .filter(utils_1.isSmartTransactionPending)
189
196
  .map((smartTransaction) => smartTransaction.uuid);
190
197
  if (transactionsToUpdate.length > 0) {
191
- this.fetchSmartTransactionsStatus(transactionsToUpdate);
192
- }
193
- }
194
- async confirmSmartTransaction(smartTransaction) {
195
- var _a, _b, _c;
196
- const txHash = (_a = smartTransaction.statusMetadata) === null || _a === void 0 ? void 0 : _a.minedHash;
197
- try {
198
- const transactionReceipt = await this.ethersProvider.getTransactionReceipt(txHash);
199
- const transaction = await this.ethersProvider.getTransaction(txHash);
200
- const maxFeePerGas = (_b = transaction.maxFeePerGas) === null || _b === void 0 ? void 0 : _b.toHexString();
201
- const maxPriorityFeePerGas = (_c = transaction.maxPriorityFeePerGas) === null || _c === void 0 ? void 0 : _c.toHexString();
202
- if (transactionReceipt === null || transactionReceipt === void 0 ? void 0 : transactionReceipt.blockNumber) {
203
- const blockData = await this.ethersProvider.getBlock(transactionReceipt === null || transactionReceipt === void 0 ? void 0 : transactionReceipt.blockNumber, false);
204
- const baseFeePerGas = blockData === null || blockData === void 0 ? void 0 : blockData.baseFeePerGas.toHexString();
205
- const txReceipt = (0, mapValues_1.default)(transactionReceipt, (value) => {
206
- if (value instanceof bignumber_1.BigNumber) {
207
- return value.toHexString();
208
- }
209
- return value;
210
- });
211
- const updatedTxParams = Object.assign(Object.assign({}, smartTransaction.txParams), { maxFeePerGas,
212
- maxPriorityFeePerGas });
213
- // call confirmExternalTransaction
214
- const originalTxMeta = Object.assign(Object.assign({}, smartTransaction), { id: smartTransaction.uuid, status: 'confirmed', hash: txHash, txParams: updatedTxParams });
215
- // create txMeta snapshot for history
216
- const snapshot = (0, utils_1.snapshotFromTxMeta)(originalTxMeta);
217
- // recover previous tx state obj
218
- const previousState = (0, utils_1.replayHistory)(originalTxMeta.history);
219
- // generate history entry and add to history
220
- const entry = (0, utils_1.generateHistoryEntry)(previousState, snapshot, 'txStateManager: setting status to confirmed');
221
- const txMeta = entry.length > 0
222
- ? Object.assign(Object.assign({}, originalTxMeta), { history: originalTxMeta.history.concat(entry) }) : originalTxMeta;
223
- this.confirmExternalTransaction(txMeta, txReceipt, baseFeePerGas);
224
- this.trackMetaMetricsEvent({
225
- event: 'STX Confirmed',
226
- category: 'swaps',
227
- });
228
- this.updateSmartTransaction(Object.assign(Object.assign({}, smartTransaction), { confirmed: true }));
229
- }
230
- }
231
- catch (e) {
232
- this.trackMetaMetricsEvent({
233
- event: 'STX Confirmation Failed',
234
- category: 'swaps',
198
+ this.fetchSmartTransactionsStatus(transactionsToUpdate, {
199
+ networkClientId,
235
200
  });
236
- console.error('confirm error', e);
237
201
  }
238
202
  }
239
203
  // ! Ask backend API to accept list of uuids as params
240
- async fetchSmartTransactionsStatus(uuids) {
241
- const { chainId } = this.config;
204
+ async fetchSmartTransactionsStatus(uuids, { networkClientId } = {}) {
242
205
  const params = new URLSearchParams({
243
206
  uuids: uuids.join(','),
244
207
  });
208
+ const chainId = __classPrivateFieldGet(this, _SmartTransactionsController_instances, "m", _SmartTransactionsController_getChainId).call(this, { networkClientId });
209
+ const ethQuery = __classPrivateFieldGet(this, _SmartTransactionsController_instances, "m", _SmartTransactionsController_getEthQuery).call(this, { networkClientId });
245
210
  const url = `${(0, utils_1.getAPIRequestURL)(types_1.APIType.BATCH_STATUS, chainId)}?${params.toString()}`;
246
- const data = await this.fetch(url);
211
+ const data = (await this.fetch(url));
247
212
  Object.entries(data).forEach(([uuid, stxStatus]) => {
248
- this.updateSmartTransaction({
213
+ const smartTransaction = {
249
214
  statusMetadata: stxStatus,
250
215
  status: (0, utils_1.calculateStatus)(stxStatus),
251
216
  cancellable: (0, utils_1.isSmartTransactionCancellable)(stxStatus),
252
217
  uuid,
253
- });
218
+ };
219
+ __classPrivateFieldGet(this, _SmartTransactionsController_instances, "m", _SmartTransactionsController_updateSmartTransaction).call(this, smartTransaction, { chainId, ethQuery });
254
220
  });
255
221
  return data;
256
222
  }
@@ -270,8 +236,8 @@ class SmartTransactionsController extends base_controller_1.BaseController {
270
236
  });
271
237
  return fees;
272
238
  }
273
- async getFees(tradeTx, approvalTx) {
274
- const { chainId } = this.config;
239
+ async getFees(tradeTx, approvalTx, { networkClientId } = {}) {
240
+ const chainId = __classPrivateFieldGet(this, _SmartTransactionsController_instances, "m", _SmartTransactionsController_getChainId).call(this, { networkClientId });
275
241
  const transactions = [];
276
242
  let unsignedTradeTransactionWithNonce;
277
243
  if (approvalTx) {
@@ -281,6 +247,9 @@ class SmartTransactionsController extends base_controller_1.BaseController {
281
247
  // If there is an approval tx, the trade tx's nonce is increased by 1.
282
248
  nonce: (0, utils_1.incrementNonceInHex)(unsignedApprovalTransactionWithNonce.nonce) });
283
249
  }
250
+ else if (tradeTx.nonce) {
251
+ unsignedTradeTransactionWithNonce = tradeTx;
252
+ }
284
253
  else {
285
254
  unsignedTradeTransactionWithNonce = await this.addNonceToTransaction(tradeTx);
286
255
  }
@@ -301,10 +270,15 @@ class SmartTransactionsController extends base_controller_1.BaseController {
301
270
  tradeTxFees = data === null || data === void 0 ? void 0 : data.txs[0];
302
271
  }
303
272
  this.update({
304
- smartTransactionsState: Object.assign(Object.assign({}, this.state.smartTransactionsState), { fees: {
273
+ smartTransactionsState: Object.assign(Object.assign(Object.assign({}, this.state.smartTransactionsState), (chainId === this.config.chainId && {
274
+ fees: {
305
275
  approvalTxFees,
306
276
  tradeTxFees,
307
- } }),
277
+ },
278
+ })), { feesByChainId: Object.assign(Object.assign({}, this.state.smartTransactionsState.feesByChainId), { [chainId]: {
279
+ approvalTxFees,
280
+ tradeTxFees,
281
+ } }) }),
308
282
  });
309
283
  return {
310
284
  approvalTxFees,
@@ -313,8 +287,10 @@ class SmartTransactionsController extends base_controller_1.BaseController {
313
287
  }
314
288
  // * After this successful call client must add a nonce representative to
315
289
  // * transaction controller external transactions list
316
- async submitSignedTransactions({ txParams, signedTransactions, signedCanceledTransactions, }) {
317
- const { chainId } = this.config;
290
+ async submitSignedTransactions({ transactionMeta, txParams, signedTransactions, signedCanceledTransactions, networkClientId, }) {
291
+ var _a;
292
+ const chainId = __classPrivateFieldGet(this, _SmartTransactionsController_instances, "m", _SmartTransactionsController_getChainId).call(this, { networkClientId });
293
+ const ethQuery = __classPrivateFieldGet(this, _SmartTransactionsController_instances, "m", _SmartTransactionsController_getEthQuery).call(this, { networkClientId });
318
294
  const data = await this.fetch((0, utils_1.getAPIRequestURL)(types_1.APIType.SUBMIT_TRANSACTIONS, chainId), {
319
295
  method: 'POST',
320
296
  body: JSON.stringify({
@@ -325,57 +301,68 @@ class SmartTransactionsController extends base_controller_1.BaseController {
325
301
  const time = Date.now();
326
302
  let preTxBalance;
327
303
  try {
328
- const preTxBalanceBN = await this.ethersProvider.getBalance(txParams === null || txParams === void 0 ? void 0 : txParams.from);
329
- preTxBalance = new bignumber_js_1.BigNumber(preTxBalanceBN.toHexString()).toString(16);
304
+ const preTxBalanceBN = await (0, controller_utils_1.query)(ethQuery, 'getBalance', [
305
+ txParams === null || txParams === void 0 ? void 0 : txParams.from,
306
+ ]);
307
+ preTxBalance = new bignumber_js_1.BigNumber(preTxBalanceBN).toString(16);
330
308
  }
331
- catch (e) {
332
- console.error('ethers error', e);
309
+ catch (error) {
310
+ console.error('provider error', error);
333
311
  }
334
- const nonceLock = await this.getNonceLock(txParams === null || txParams === void 0 ? void 0 : txParams.from);
335
- try {
336
- const nonce = (0, bytes_1.hexlify)(nonceLock.nextNonce);
337
- if (txParams && !(txParams === null || txParams === void 0 ? void 0 : txParams.nonce)) {
338
- txParams.nonce = nonce;
312
+ const requiresNonce = !txParams.nonce;
313
+ let nonce;
314
+ let nonceLock;
315
+ let nonceDetails = {};
316
+ if (requiresNonce) {
317
+ nonceLock = await this.getNonceLock(txParams === null || txParams === void 0 ? void 0 : txParams.from);
318
+ nonce = (0, bytes_1.hexlify)(nonceLock.nextNonce);
319
+ nonceDetails = nonceLock.nonceDetails;
320
+ if (txParams) {
321
+ (_a = txParams.nonce) !== null && _a !== void 0 ? _a : (txParams.nonce = nonce);
339
322
  }
340
- const { nonceDetails } = nonceLock;
341
- this.updateSmartTransaction({
323
+ }
324
+ const submitTransactionResponse = Object.assign(Object.assign({}, data), { txHash: (0, utils_1.getTxHash)(signedTransactions[0]) });
325
+ try {
326
+ __classPrivateFieldGet(this, _SmartTransactionsController_instances, "m", _SmartTransactionsController_updateSmartTransaction).call(this, {
342
327
  chainId,
343
328
  nonceDetails,
344
329
  preTxBalance,
345
330
  status: types_1.SmartTransactionStatuses.PENDING,
346
331
  time,
347
332
  txParams,
348
- uuid: data.uuid,
333
+ uuid: submitTransactionResponse.uuid,
334
+ txHash: submitTransactionResponse.txHash,
349
335
  cancellable: true,
350
- });
336
+ type: (transactionMeta === null || transactionMeta === void 0 ? void 0 : transactionMeta.type) || 'swap',
337
+ }, { chainId, ethQuery });
351
338
  }
352
339
  finally {
353
- nonceLock.releaseLock();
340
+ nonceLock === null || nonceLock === void 0 ? void 0 : nonceLock.releaseLock();
354
341
  }
355
- return data;
342
+ return submitTransactionResponse;
356
343
  }
357
344
  // TODO: This should return if the cancellation was on chain or not (for nonce management)
358
345
  // After this successful call client must update nonce representative
359
346
  // in transaction controller external transactions list
360
- async cancelSmartTransaction(uuid) {
361
- const { chainId } = this.config;
347
+ async cancelSmartTransaction(uuid, { networkClientId, } = {}) {
348
+ const chainId = __classPrivateFieldGet(this, _SmartTransactionsController_instances, "m", _SmartTransactionsController_getChainId).call(this, { networkClientId });
362
349
  await this.fetch((0, utils_1.getAPIRequestURL)(types_1.APIType.CANCEL, chainId), {
363
350
  method: 'POST',
364
351
  body: JSON.stringify({ uuid }),
365
352
  });
366
353
  }
367
- async fetchLiveness() {
368
- const { chainId } = this.config;
354
+ async fetchLiveness({ networkClientId, } = {}) {
355
+ const chainId = __classPrivateFieldGet(this, _SmartTransactionsController_instances, "m", _SmartTransactionsController_getChainId).call(this, { networkClientId });
369
356
  let liveness = false;
370
357
  try {
371
358
  const response = await this.fetch((0, utils_1.getAPIRequestURL)(types_1.APIType.LIVENESS, chainId));
372
359
  liveness = Boolean(response.lastBlock);
373
360
  }
374
- catch (e) {
361
+ catch (error) {
375
362
  console.log('"fetchLiveness" API call failed');
376
363
  }
377
364
  this.update({
378
- smartTransactionsState: Object.assign(Object.assign({}, this.state.smartTransactionsState), { liveness }),
365
+ smartTransactionsState: Object.assign(Object.assign(Object.assign({}, this.state.smartTransactionsState), (chainId === this.config.chainId && { liveness })), { livenessByChainId: Object.assign(Object.assign({}, this.state.smartTransactionsState.livenessByChainId), { [chainId]: liveness }) }),
379
366
  });
380
367
  return liveness;
381
368
  }
@@ -398,4 +385,112 @@ class SmartTransactionsController extends base_controller_1.BaseController {
398
385
  }
399
386
  }
400
387
  exports.default = SmartTransactionsController;
388
+ _SmartTransactionsController_instances = new WeakSet(), _SmartTransactionsController_updateSmartTransaction = async function _SmartTransactionsController_updateSmartTransaction(smartTransaction, { chainId = this.config.chainId, ethQuery = this.ethQuery, }) {
389
+ var _a;
390
+ const { smartTransactionsState } = this.state;
391
+ const { smartTransactions } = smartTransactionsState;
392
+ const currentSmartTransactions = (_a = smartTransactions[chainId]) !== null && _a !== void 0 ? _a : [];
393
+ const currentIndex = currentSmartTransactions === null || currentSmartTransactions === void 0 ? void 0 : currentSmartTransactions.findIndex((stx) => stx.uuid === smartTransaction.uuid);
394
+ const isNewSmartTransaction = this.isNewSmartTransaction(smartTransaction.uuid);
395
+ if (this.ethQuery === undefined) {
396
+ throw new Error(ETH_QUERY_ERROR_MSG);
397
+ }
398
+ this.trackStxStatusChange(smartTransaction, isNewSmartTransaction
399
+ ? undefined
400
+ : currentSmartTransactions[currentIndex]);
401
+ if (isNewSmartTransaction) {
402
+ // add smart transaction
403
+ const cancelledNonceIndex = currentSmartTransactions === null || currentSmartTransactions === void 0 ? void 0 : currentSmartTransactions.findIndex((stx) => {
404
+ var _a, _b, _c;
405
+ return ((_a = stx.txParams) === null || _a === void 0 ? void 0 : _a.nonce) === ((_b = smartTransaction.txParams) === null || _b === void 0 ? void 0 : _b.nonce) &&
406
+ ((_c = stx.status) === null || _c === void 0 ? void 0 : _c.startsWith('cancelled'));
407
+ });
408
+ const snapshot = (0, cloneDeep_1.default)(smartTransaction);
409
+ const history = [snapshot];
410
+ const historifiedSmartTransaction = Object.assign(Object.assign({}, smartTransaction), { history });
411
+ const nextSmartTransactions = cancelledNonceIndex > -1
412
+ ? currentSmartTransactions
413
+ .slice(0, cancelledNonceIndex)
414
+ .concat(currentSmartTransactions.slice(cancelledNonceIndex + 1))
415
+ .concat(historifiedSmartTransaction)
416
+ : currentSmartTransactions.concat(historifiedSmartTransaction);
417
+ this.update({
418
+ smartTransactionsState: Object.assign(Object.assign({}, smartTransactionsState), { smartTransactions: Object.assign(Object.assign({}, smartTransactionsState.smartTransactions), { [chainId]: nextSmartTransactions }) }),
419
+ });
420
+ return;
421
+ }
422
+ if ((smartTransaction.status === types_1.SmartTransactionStatuses.SUCCESS ||
423
+ smartTransaction.status === types_1.SmartTransactionStatuses.REVERTED) &&
424
+ !smartTransaction.confirmed) {
425
+ // confirm smart transaction
426
+ const currentSmartTransaction = currentSmartTransactions[currentIndex];
427
+ const nextSmartTransaction = Object.assign(Object.assign({}, currentSmartTransaction), smartTransaction);
428
+ await __classPrivateFieldGet(this, _SmartTransactionsController_instances, "m", _SmartTransactionsController_confirmSmartTransaction).call(this, nextSmartTransaction, {
429
+ chainId,
430
+ ethQuery,
431
+ });
432
+ }
433
+ else {
434
+ this.update({
435
+ smartTransactionsState: Object.assign(Object.assign({}, smartTransactionsState), { smartTransactions: Object.assign(Object.assign({}, smartTransactionsState.smartTransactions), { [chainId]: smartTransactionsState.smartTransactions[chainId].map((item, index) => {
436
+ return index === currentIndex
437
+ ? Object.assign(Object.assign({}, item), smartTransaction) : item;
438
+ }) }) }),
439
+ });
440
+ }
441
+ this.eventEmitter.emit(`${smartTransaction.uuid}:smartTransaction`, smartTransaction);
442
+ }, _SmartTransactionsController_confirmSmartTransaction = async function _SmartTransactionsController_confirmSmartTransaction(smartTransaction, { chainId = this.config.chainId, ethQuery = this.ethQuery, }) {
443
+ var _a;
444
+ if (ethQuery === undefined) {
445
+ throw new Error(ETH_QUERY_ERROR_MSG);
446
+ }
447
+ const txHash = (_a = smartTransaction.statusMetadata) === null || _a === void 0 ? void 0 : _a.minedHash;
448
+ try {
449
+ const transactionReceipt = await (0, controller_utils_1.query)(ethQuery, 'getTransactionReceipt', [txHash]);
450
+ const transaction = await (0, controller_utils_1.query)(ethQuery, 'getTransactionByHash', [txHash]);
451
+ const maxFeePerGas = transaction === null || transaction === void 0 ? void 0 : transaction.maxFeePerGas;
452
+ const maxPriorityFeePerGas = transaction === null || transaction === void 0 ? void 0 : transaction.maxPriorityFeePerGas;
453
+ if (transactionReceipt === null || transactionReceipt === void 0 ? void 0 : transactionReceipt.blockNumber) {
454
+ const blockData = await (0, controller_utils_1.query)(ethQuery, 'getBlockByNumber', [transactionReceipt === null || transactionReceipt === void 0 ? void 0 : transactionReceipt.blockNumber, false]);
455
+ const baseFeePerGas = blockData === null || blockData === void 0 ? void 0 : blockData.baseFeePerGas;
456
+ const updatedTxParams = Object.assign(Object.assign({}, smartTransaction.txParams), { maxFeePerGas,
457
+ maxPriorityFeePerGas });
458
+ // call confirmExternalTransaction
459
+ const originalTxMeta = Object.assign(Object.assign({}, smartTransaction), { id: smartTransaction.uuid, status: 'confirmed', hash: txHash, txParams: updatedTxParams });
460
+ // create txMeta snapshot for history
461
+ const snapshot = (0, utils_1.snapshotFromTxMeta)(originalTxMeta);
462
+ // recover previous tx state obj
463
+ const previousState = (0, utils_1.replayHistory)(originalTxMeta.history);
464
+ // generate history entry and add to history
465
+ const entry = (0, utils_1.generateHistoryEntry)(previousState, snapshot, 'txStateManager: setting status to confirmed');
466
+ const txMeta = entry.length > 0
467
+ ? Object.assign(Object.assign({}, originalTxMeta), { history: originalTxMeta.history.concat(entry) }) : originalTxMeta;
468
+ this.confirmExternalTransaction(txMeta, transactionReceipt, baseFeePerGas);
469
+ this.trackMetaMetricsEvent({
470
+ event: constants_1.MetaMetricsEventName.StxConfirmed,
471
+ category: constants_1.MetaMetricsEventCategory.Transactions,
472
+ });
473
+ __classPrivateFieldGet(this, _SmartTransactionsController_instances, "m", _SmartTransactionsController_updateSmartTransaction).call(this, Object.assign(Object.assign({}, smartTransaction), { confirmed: true }), { chainId, ethQuery });
474
+ }
475
+ }
476
+ catch (error) {
477
+ this.trackMetaMetricsEvent({
478
+ event: constants_1.MetaMetricsEventName.StxConfirmationFailed,
479
+ category: constants_1.MetaMetricsEventCategory.Transactions,
480
+ });
481
+ console.error('confirm error', error);
482
+ }
483
+ }, _SmartTransactionsController_getChainId = function _SmartTransactionsController_getChainId({ networkClientId, } = {}) {
484
+ return networkClientId
485
+ ? this.getNetworkClientById(networkClientId).configuration.chainId
486
+ : this.config.chainId;
487
+ }, _SmartTransactionsController_getEthQuery = function _SmartTransactionsController_getEthQuery({ networkClientId, } = {}) {
488
+ if (networkClientId) {
489
+ return new eth_query_1.default(this.getNetworkClientById(networkClientId).provider);
490
+ }
491
+ if (this.ethQuery === undefined) {
492
+ throw new Error(ETH_QUERY_ERROR_MSG);
493
+ }
494
+ return this.ethQuery;
495
+ };
401
496
  //# sourceMappingURL=SmartTransactionsController.js.map