@metamask/transaction-controller 17.0.0 → 18.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +34 -1
- package/dist/TransactionController.d.ts +59 -14
- package/dist/TransactionController.d.ts.map +1 -1
- package/dist/TransactionController.js +280 -115
- package/dist/TransactionController.js.map +1 -1
- package/dist/constants.d.ts +4 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +5 -1
- package/dist/constants.js.map +1 -1
- package/dist/helpers/PendingTransactionTracker.d.ts +1 -1
- package/dist/helpers/PendingTransactionTracker.d.ts.map +1 -1
- package/dist/helpers/PendingTransactionTracker.js.map +1 -1
- package/dist/types.d.ts +8 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils/gas.d.ts.map +1 -1
- package/dist/utils/gas.js +4 -1
- package/dist/utils/gas.js.map +1 -1
- package/dist/utils/history.d.ts.map +1 -1
- package/dist/utils/history.js +3 -0
- package/dist/utils/history.js.map +1 -1
- package/dist/utils/swaps.d.ts.map +1 -1
- package/dist/utils/swaps.js +13 -0
- package/dist/utils/swaps.js.map +1 -1
- package/dist/utils/utils.d.ts +10 -2
- package/dist/utils/utils.d.ts.map +1 -1
- package/dist/utils/utils.js +28 -3
- package/dist/utils/utils.js.map +1 -1
- package/package.json +11 -11
|
@@ -24,7 +24,7 @@ const eth_method_registry_1 = __importDefault(require("eth-method-registry"));
|
|
|
24
24
|
const ethereumjs_util_1 = require("ethereumjs-util");
|
|
25
25
|
const events_1 = require("events");
|
|
26
26
|
const lodash_1 = require("lodash");
|
|
27
|
-
const nonce_tracker_1 =
|
|
27
|
+
const nonce_tracker_1 = require("nonce-tracker");
|
|
28
28
|
const uuid_1 = require("uuid");
|
|
29
29
|
const EtherscanRemoteTransactionSource_1 = require("./helpers/EtherscanRemoteTransactionSource");
|
|
30
30
|
const IncomingTransactionHelper_1 = require("./helpers/IncomingTransactionHelper");
|
|
@@ -55,12 +55,13 @@ const controllerName = 'TransactionController';
|
|
|
55
55
|
/**
|
|
56
56
|
* Controller responsible for submitting and managing transactions.
|
|
57
57
|
*/
|
|
58
|
-
class TransactionController extends base_controller_1.
|
|
58
|
+
class TransactionController extends base_controller_1.BaseControllerV1 {
|
|
59
59
|
/**
|
|
60
60
|
* Creates a TransactionController instance.
|
|
61
61
|
*
|
|
62
62
|
* @param options - The controller options.
|
|
63
63
|
* @param options.blockTracker - The block tracker used to poll for new blocks data.
|
|
64
|
+
* @param options.cancelMultiplier - Multiplier used to determine a transaction's increased gas fee during cancellation.
|
|
64
65
|
* @param options.disableHistory - Whether to disable storing history in transaction metadata.
|
|
65
66
|
* @param options.disableSendFlowHistory - Explicitly disable transaction metadata history.
|
|
66
67
|
* @param options.disableSwaps - Whether to disable additional processing on swaps transactions.
|
|
@@ -82,6 +83,7 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
82
83
|
* @param options.pendingTransactions.isResubmitEnabled - Whether transaction publishing is automatically retried.
|
|
83
84
|
* @param options.provider - The provider used to create the underlying EthQuery instance.
|
|
84
85
|
* @param options.securityProviderRequest - A function for verifying a transaction, whether it is malicious or not.
|
|
86
|
+
* @param options.speedUpMultiplier - Multiplier used to determine a transaction's increased gas fee during speed up.
|
|
85
87
|
* @param options.hooks - The controller hooks.
|
|
86
88
|
* @param options.hooks.afterSign - Additional logic to execute after signing a transaction. Return false to not change the status to signed.
|
|
87
89
|
* @param options.hooks.beforeApproveOnInit - Additional logic to execute before starting an approval flow for a transaction during initialization. Return false to skip the transaction.
|
|
@@ -91,7 +93,7 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
91
93
|
* @param config - Initial options used to configure this controller.
|
|
92
94
|
* @param state - Initial state to set on this controller.
|
|
93
95
|
*/
|
|
94
|
-
constructor({ blockTracker, disableHistory, disableSendFlowHistory, disableSwaps, getSavedGasFees, getCurrentAccountEIP1559Compatibility, getCurrentNetworkEIP1559Compatibility, getGasFeeEstimates, getNetworkState, getPermittedAccounts, getSelectedAddress, incomingTransactions = {}, messenger, onNetworkStateChange, pendingTransactions = {}, provider, securityProviderRequest, hooks = {}, }, config, state) {
|
|
96
|
+
constructor({ blockTracker, cancelMultiplier, disableHistory, disableSendFlowHistory, disableSwaps, getSavedGasFees, getCurrentAccountEIP1559Compatibility, getCurrentNetworkEIP1559Compatibility, getGasFeeEstimates, getNetworkState, getPermittedAccounts, getSelectedAddress, incomingTransactions = {}, messenger, onNetworkStateChange, pendingTransactions = {}, provider, securityProviderRequest, speedUpMultiplier, hooks = {}, }, config, state) {
|
|
95
97
|
var _a, _b, _c, _d, _e;
|
|
96
98
|
super(config, state);
|
|
97
99
|
this.inProcessOfSigning = new Set();
|
|
@@ -123,7 +125,7 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
123
125
|
this.registry = new eth_method_registry_1.default({ provider });
|
|
124
126
|
this.getSavedGasFees = getSavedGasFees !== null && getSavedGasFees !== void 0 ? getSavedGasFees : ((_chainId) => undefined);
|
|
125
127
|
this.getCurrentAccountEIP1559Compatibility =
|
|
126
|
-
getCurrentAccountEIP1559Compatibility;
|
|
128
|
+
getCurrentAccountEIP1559Compatibility !== null && getCurrentAccountEIP1559Compatibility !== void 0 ? getCurrentAccountEIP1559Compatibility : (() => Promise.resolve(true));
|
|
127
129
|
this.getCurrentNetworkEIP1559Compatibility =
|
|
128
130
|
getCurrentNetworkEIP1559Compatibility;
|
|
129
131
|
this.getGasFeeEstimates =
|
|
@@ -131,6 +133,8 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
131
133
|
this.getPermittedAccounts = getPermittedAccounts;
|
|
132
134
|
this.getSelectedAddress = getSelectedAddress;
|
|
133
135
|
this.securityProviderRequest = securityProviderRequest;
|
|
136
|
+
this.cancelMultiplier = cancelMultiplier !== null && cancelMultiplier !== void 0 ? cancelMultiplier : exports.CANCEL_RATE;
|
|
137
|
+
this.speedUpMultiplier = speedUpMultiplier !== null && speedUpMultiplier !== void 0 ? speedUpMultiplier : exports.SPEED_UP_RATE;
|
|
134
138
|
this.afterSign = (_a = hooks === null || hooks === void 0 ? void 0 : hooks.afterSign) !== null && _a !== void 0 ? _a : (() => true);
|
|
135
139
|
this.beforeApproveOnInit = (_b = hooks === null || hooks === void 0 ? void 0 : hooks.beforeApproveOnInit) !== null && _b !== void 0 ? _b : (() => true);
|
|
136
140
|
this.beforeCheckPendingTransaction =
|
|
@@ -140,11 +144,12 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
140
144
|
this.beforePublish = (_d = hooks === null || hooks === void 0 ? void 0 : hooks.beforePublish) !== null && _d !== void 0 ? _d : (() => true);
|
|
141
145
|
this.getAdditionalSignArguments =
|
|
142
146
|
(_e = hooks === null || hooks === void 0 ? void 0 : hooks.getAdditionalSignArguments) !== null && _e !== void 0 ? _e : (() => []);
|
|
143
|
-
this.nonceTracker = new nonce_tracker_1.
|
|
147
|
+
this.nonceTracker = new nonce_tracker_1.NonceTracker({
|
|
148
|
+
// @ts-expect-error provider types misaligned: SafeEventEmitterProvider vs Record<string,string>
|
|
144
149
|
provider,
|
|
145
150
|
blockTracker,
|
|
146
|
-
getPendingTransactions:
|
|
147
|
-
getConfirmedTransactions:
|
|
151
|
+
getPendingTransactions: this.getNonceTrackerTransactions.bind(this, types_1.TransactionStatus.submitted),
|
|
152
|
+
getConfirmedTransactions: this.getNonceTrackerTransactions.bind(this, types_1.TransactionStatus.confirmed),
|
|
148
153
|
});
|
|
149
154
|
this.incomingTransactionHelper = new IncomingTransactionHelper_1.IncomingTransactionHelper({
|
|
150
155
|
blockTracker,
|
|
@@ -192,6 +197,7 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
192
197
|
transactionMeta: newTransactionMeta,
|
|
193
198
|
});
|
|
194
199
|
this.updateTransaction(newTransactionMeta, 'TransactionController#failTransaction - Add error message and set status to failed');
|
|
200
|
+
this.onTransactionStatusChange(newTransactionMeta);
|
|
195
201
|
this.hub.emit(`${transactionMeta.id}:finished`, newTransactionMeta);
|
|
196
202
|
}
|
|
197
203
|
registryLookup(fourBytePrefix) {
|
|
@@ -249,7 +255,7 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
249
255
|
*/
|
|
250
256
|
addTransaction(txParams, { actionId, deviceConfirmedOn, method, origin, requireApproval, securityAlertResponse, sendFlowHistory, swaps = {}, type, } = {}) {
|
|
251
257
|
return __awaiter(this, void 0, void 0, function* () {
|
|
252
|
-
|
|
258
|
+
(0, logger_1.projectLogger)('Adding transaction', txParams);
|
|
253
259
|
txParams = (0, utils_1.normalizeTxParams)(txParams);
|
|
254
260
|
const isEIP1559Compatible = yield this.getEIP1559Compatibility();
|
|
255
261
|
(0, validation_1.validateTxParams)(txParams, isEIP1559Compatible);
|
|
@@ -259,6 +265,7 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
259
265
|
const dappSuggestedGasFees = this.generateDappSuggestedGasFees(txParams, origin);
|
|
260
266
|
const transactionType = type !== null && type !== void 0 ? type : (yield (0, transaction_type_1.determineTransactionType)(txParams, this.ethQuery)).type;
|
|
261
267
|
const existingTransactionMeta = this.getTransactionWithActionId(actionId);
|
|
268
|
+
const chainId = this.getChainId();
|
|
262
269
|
// If a request to add a transaction with the same actionId is submitted again, a new transaction will not be created for it.
|
|
263
270
|
const transactionMeta = existingTransactionMeta || {
|
|
264
271
|
// Add actionId to txMeta to check if same actionId is seen again
|
|
@@ -331,15 +338,18 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
331
338
|
* @param options.estimatedBaseFee - The estimated base fee of the transaction.
|
|
332
339
|
*/
|
|
333
340
|
stopTransaction(transactionId, gasValues, { estimatedBaseFee, actionId, } = {}) {
|
|
334
|
-
var _a, _b;
|
|
341
|
+
var _a, _b, _c;
|
|
335
342
|
return __awaiter(this, void 0, void 0, function* () {
|
|
336
343
|
// If transaction is found for same action id, do not create a cancel transaction.
|
|
337
344
|
if (this.getTransactionWithActionId(actionId)) {
|
|
338
345
|
return;
|
|
339
346
|
}
|
|
340
347
|
if (gasValues) {
|
|
348
|
+
// Not good practice to reassign a parameter but temporarily avoiding a larger refactor.
|
|
349
|
+
gasValues = (0, utils_1.normalizeGasFeeValues)(gasValues);
|
|
341
350
|
(0, utils_1.validateGasValues)(gasValues);
|
|
342
351
|
}
|
|
352
|
+
(0, logger_1.projectLogger)('Creating cancel transaction', transactionId, gasValues);
|
|
343
353
|
const transactionMeta = this.getTransaction(transactionId);
|
|
344
354
|
if (!transactionMeta) {
|
|
345
355
|
return;
|
|
@@ -348,21 +358,21 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
348
358
|
throw new Error('No sign method defined.');
|
|
349
359
|
}
|
|
350
360
|
// gasPrice (legacy non EIP1559)
|
|
351
|
-
const minGasPrice = (0, utils_1.getIncreasedPriceFromExisting)(transactionMeta.txParams.gasPrice,
|
|
361
|
+
const minGasPrice = (0, utils_1.getIncreasedPriceFromExisting)(transactionMeta.txParams.gasPrice, this.cancelMultiplier);
|
|
352
362
|
const gasPriceFromValues = (0, utils_1.isGasPriceValue)(gasValues) && gasValues.gasPrice;
|
|
353
363
|
const newGasPrice = (gasPriceFromValues &&
|
|
354
364
|
(0, utils_1.validateMinimumIncrease)(gasPriceFromValues, minGasPrice)) ||
|
|
355
365
|
minGasPrice;
|
|
356
366
|
// maxFeePerGas (EIP1559)
|
|
357
367
|
const existingMaxFeePerGas = (_a = transactionMeta.txParams) === null || _a === void 0 ? void 0 : _a.maxFeePerGas;
|
|
358
|
-
const minMaxFeePerGas = (0, utils_1.getIncreasedPriceFromExisting)(existingMaxFeePerGas,
|
|
368
|
+
const minMaxFeePerGas = (0, utils_1.getIncreasedPriceFromExisting)(existingMaxFeePerGas, this.cancelMultiplier);
|
|
359
369
|
const maxFeePerGasValues = (0, utils_1.isFeeMarketEIP1559Values)(gasValues) && gasValues.maxFeePerGas;
|
|
360
370
|
const newMaxFeePerGas = (maxFeePerGasValues &&
|
|
361
371
|
(0, utils_1.validateMinimumIncrease)(maxFeePerGasValues, minMaxFeePerGas)) ||
|
|
362
372
|
(existingMaxFeePerGas && minMaxFeePerGas);
|
|
363
373
|
// maxPriorityFeePerGas (EIP1559)
|
|
364
374
|
const existingMaxPriorityFeePerGas = (_b = transactionMeta.txParams) === null || _b === void 0 ? void 0 : _b.maxPriorityFeePerGas;
|
|
365
|
-
const minMaxPriorityFeePerGas = (0, utils_1.getIncreasedPriceFromExisting)(existingMaxPriorityFeePerGas,
|
|
375
|
+
const minMaxPriorityFeePerGas = (0, utils_1.getIncreasedPriceFromExisting)(existingMaxPriorityFeePerGas, this.cancelMultiplier);
|
|
366
376
|
const maxPriorityFeePerGasValues = (0, utils_1.isFeeMarketEIP1559Values)(gasValues) && gasValues.maxPriorityFeePerGas;
|
|
367
377
|
const newMaxPriorityFeePerGas = (maxPriorityFeePerGasValues &&
|
|
368
378
|
(0, utils_1.validateMinimumIncrease)(maxPriorityFeePerGasValues, minMaxPriorityFeePerGas)) ||
|
|
@@ -373,7 +383,7 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
373
383
|
gasLimit: transactionMeta.txParams.gas,
|
|
374
384
|
maxFeePerGas: newMaxFeePerGas,
|
|
375
385
|
maxPriorityFeePerGas: newMaxPriorityFeePerGas,
|
|
376
|
-
type:
|
|
386
|
+
type: types_1.TransactionEnvelopeType.feeMarket,
|
|
377
387
|
nonce: transactionMeta.txParams.nonce,
|
|
378
388
|
to: transactionMeta.txParams.from,
|
|
379
389
|
value: '0x0',
|
|
@@ -389,6 +399,15 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
389
399
|
const unsignedEthTx = this.prepareUnsignedEthTx(newTxParams);
|
|
390
400
|
const signedTx = yield this.sign(unsignedEthTx, transactionMeta.txParams.from);
|
|
391
401
|
const rawTx = (0, ethereumjs_util_1.bufferToHex)(signedTx.serialize());
|
|
402
|
+
const newFee = (_c = newTxParams.maxFeePerGas) !== null && _c !== void 0 ? _c : newTxParams.gasPrice;
|
|
403
|
+
const oldFee = newTxParams.maxFeePerGas
|
|
404
|
+
? transactionMeta.txParams.maxFeePerGas
|
|
405
|
+
: transactionMeta.txParams.gasPrice;
|
|
406
|
+
(0, logger_1.projectLogger)('Submitting cancel transaction', {
|
|
407
|
+
oldFee,
|
|
408
|
+
newFee,
|
|
409
|
+
txParams: newTxParams,
|
|
410
|
+
});
|
|
392
411
|
const hash = yield this.publishTransaction(rawTx);
|
|
393
412
|
const cancelTransactionMeta = {
|
|
394
413
|
actionId,
|
|
@@ -425,15 +444,18 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
425
444
|
* @param options.estimatedBaseFee - The estimated base fee of the transaction.
|
|
426
445
|
*/
|
|
427
446
|
speedUpTransaction(transactionId, gasValues, { actionId, estimatedBaseFee, } = {}) {
|
|
428
|
-
var _a, _b;
|
|
447
|
+
var _a, _b, _c;
|
|
429
448
|
return __awaiter(this, void 0, void 0, function* () {
|
|
430
449
|
// If transaction is found for same action id, do not create a new speed up transaction.
|
|
431
450
|
if (this.getTransactionWithActionId(actionId)) {
|
|
432
451
|
return;
|
|
433
452
|
}
|
|
434
453
|
if (gasValues) {
|
|
454
|
+
// Not good practice to reassign a parameter but temporarily avoiding a larger refactor.
|
|
455
|
+
gasValues = (0, utils_1.normalizeGasFeeValues)(gasValues);
|
|
435
456
|
(0, utils_1.validateGasValues)(gasValues);
|
|
436
457
|
}
|
|
458
|
+
(0, logger_1.projectLogger)('Creating speed up transaction', transactionId, gasValues);
|
|
437
459
|
const transactionMeta = this.state.transactions.find(({ id }) => id === transactionId);
|
|
438
460
|
/* istanbul ignore next */
|
|
439
461
|
if (!transactionMeta) {
|
|
@@ -444,31 +466,36 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
444
466
|
throw new Error('No sign method defined.');
|
|
445
467
|
}
|
|
446
468
|
// gasPrice (legacy non EIP1559)
|
|
447
|
-
const minGasPrice = (0, utils_1.getIncreasedPriceFromExisting)(transactionMeta.txParams.gasPrice,
|
|
469
|
+
const minGasPrice = (0, utils_1.getIncreasedPriceFromExisting)(transactionMeta.txParams.gasPrice, this.speedUpMultiplier);
|
|
448
470
|
const gasPriceFromValues = (0, utils_1.isGasPriceValue)(gasValues) && gasValues.gasPrice;
|
|
449
471
|
const newGasPrice = (gasPriceFromValues &&
|
|
450
472
|
(0, utils_1.validateMinimumIncrease)(gasPriceFromValues, minGasPrice)) ||
|
|
451
473
|
minGasPrice;
|
|
452
474
|
// maxFeePerGas (EIP1559)
|
|
453
475
|
const existingMaxFeePerGas = (_a = transactionMeta.txParams) === null || _a === void 0 ? void 0 : _a.maxFeePerGas;
|
|
454
|
-
const minMaxFeePerGas = (0, utils_1.getIncreasedPriceFromExisting)(existingMaxFeePerGas,
|
|
476
|
+
const minMaxFeePerGas = (0, utils_1.getIncreasedPriceFromExisting)(existingMaxFeePerGas, this.speedUpMultiplier);
|
|
455
477
|
const maxFeePerGasValues = (0, utils_1.isFeeMarketEIP1559Values)(gasValues) && gasValues.maxFeePerGas;
|
|
456
478
|
const newMaxFeePerGas = (maxFeePerGasValues &&
|
|
457
479
|
(0, utils_1.validateMinimumIncrease)(maxFeePerGasValues, minMaxFeePerGas)) ||
|
|
458
480
|
(existingMaxFeePerGas && minMaxFeePerGas);
|
|
459
481
|
// maxPriorityFeePerGas (EIP1559)
|
|
460
482
|
const existingMaxPriorityFeePerGas = (_b = transactionMeta.txParams) === null || _b === void 0 ? void 0 : _b.maxPriorityFeePerGas;
|
|
461
|
-
const minMaxPriorityFeePerGas = (0, utils_1.getIncreasedPriceFromExisting)(existingMaxPriorityFeePerGas,
|
|
483
|
+
const minMaxPriorityFeePerGas = (0, utils_1.getIncreasedPriceFromExisting)(existingMaxPriorityFeePerGas, this.speedUpMultiplier);
|
|
462
484
|
const maxPriorityFeePerGasValues = (0, utils_1.isFeeMarketEIP1559Values)(gasValues) && gasValues.maxPriorityFeePerGas;
|
|
463
485
|
const newMaxPriorityFeePerGas = (maxPriorityFeePerGasValues &&
|
|
464
486
|
(0, utils_1.validateMinimumIncrease)(maxPriorityFeePerGasValues, minMaxPriorityFeePerGas)) ||
|
|
465
487
|
(existingMaxPriorityFeePerGas && minMaxPriorityFeePerGas);
|
|
466
488
|
const txParams = newMaxFeePerGas && newMaxPriorityFeePerGas
|
|
467
|
-
? Object.assign(Object.assign({}, transactionMeta.txParams), { gasLimit: transactionMeta.txParams.gas, maxFeePerGas: newMaxFeePerGas, maxPriorityFeePerGas: newMaxPriorityFeePerGas, type:
|
|
489
|
+
? Object.assign(Object.assign({}, transactionMeta.txParams), { gasLimit: transactionMeta.txParams.gas, maxFeePerGas: newMaxFeePerGas, maxPriorityFeePerGas: newMaxPriorityFeePerGas, type: types_1.TransactionEnvelopeType.feeMarket }) : Object.assign(Object.assign({}, transactionMeta.txParams), { gasLimit: transactionMeta.txParams.gas, gasPrice: newGasPrice });
|
|
468
490
|
const unsignedEthTx = this.prepareUnsignedEthTx(txParams);
|
|
469
491
|
const signedTx = yield this.sign(unsignedEthTx, transactionMeta.txParams.from);
|
|
470
492
|
yield this.updateTransactionMetaRSV(transactionMeta, signedTx);
|
|
471
493
|
const rawTx = (0, ethereumjs_util_1.bufferToHex)(signedTx.serialize());
|
|
494
|
+
const newFee = (_c = txParams.maxFeePerGas) !== null && _c !== void 0 ? _c : txParams.gasPrice;
|
|
495
|
+
const oldFee = txParams.maxFeePerGas
|
|
496
|
+
? transactionMeta.txParams.maxFeePerGas
|
|
497
|
+
: transactionMeta.txParams.gasPrice;
|
|
498
|
+
(0, logger_1.projectLogger)('Submitting speed up transaction', { oldFee, newFee, txParams });
|
|
472
499
|
const hash = yield (0, controller_utils_1.query)(this.ethQuery, 'sendRawTransaction', [rawTx]);
|
|
473
500
|
const baseTransactionMeta = Object.assign(Object.assign({}, transactionMeta), { estimatedBaseFee, id: (0, uuid_1.v1)(), time: Date.now(), hash,
|
|
474
501
|
actionId, originalGasEstimate: transactionMeta.txParams.gas, type: types_1.TransactionType.retry, originalType: transactionMeta.type });
|
|
@@ -606,29 +633,16 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
606
633
|
this.markNonceDuplicatesDropped(transactionId);
|
|
607
634
|
// Update external provided transaction with updated gas values and confirmed status.
|
|
608
635
|
this.updateTransaction(transactionMeta, 'TransactionController:confirmExternalTransaction - Add external transaction');
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
updateTransaction: this.updateTransaction.bind(this),
|
|
614
|
-
})
|
|
615
|
-
.then(({ updatedTransactionMeta, approvalTransactionMeta }) => {
|
|
616
|
-
this.hub.emit('post-transaction-balance-updated', {
|
|
617
|
-
transactionMeta: updatedTransactionMeta,
|
|
618
|
-
approvalTransactionMeta,
|
|
619
|
-
});
|
|
620
|
-
})
|
|
621
|
-
.catch((error) => {
|
|
622
|
-
/* istanbul ignore next */
|
|
623
|
-
(0, logger_1.projectLogger)('Error while updating post transaction balance', error);
|
|
624
|
-
});
|
|
625
|
-
}
|
|
636
|
+
this.onTransactionStatusChange(transactionMeta);
|
|
637
|
+
// Intentional given potential duration of process.
|
|
638
|
+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
639
|
+
this.updatePostBalance(transactionMeta);
|
|
626
640
|
this.hub.emit('transaction-confirmed', {
|
|
627
641
|
transactionMeta,
|
|
628
642
|
});
|
|
629
643
|
}
|
|
630
644
|
catch (error) {
|
|
631
|
-
console.error(error);
|
|
645
|
+
console.error('Failed to confirm external transaction', error);
|
|
632
646
|
}
|
|
633
647
|
});
|
|
634
648
|
}
|
|
@@ -749,6 +763,44 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
749
763
|
return this.nonceTracker.getNonceLock(address);
|
|
750
764
|
});
|
|
751
765
|
}
|
|
766
|
+
/**
|
|
767
|
+
* Updates the editable parameters of a transaction.
|
|
768
|
+
*
|
|
769
|
+
* @param txId - The ID of the transaction to update.
|
|
770
|
+
* @param params - The editable parameters to update.
|
|
771
|
+
* @param params.data - Data to pass with the transaction.
|
|
772
|
+
* @param params.gas - Maximum number of units of gas to use for the transaction.
|
|
773
|
+
* @param params.gasPrice - Price per gas for legacy transactions.
|
|
774
|
+
* @param params.from - Address to send the transaction from.
|
|
775
|
+
* @param params.to - Address to send the transaction to.
|
|
776
|
+
* @param params.value - Value associated with the transaction.
|
|
777
|
+
* @returns The updated transaction metadata.
|
|
778
|
+
*/
|
|
779
|
+
updateEditableParams(txId, { data, gas, gasPrice, from, to, value, }) {
|
|
780
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
781
|
+
const transactionMeta = this.getTransaction(txId);
|
|
782
|
+
if (!transactionMeta) {
|
|
783
|
+
throw new Error(`Cannot update editable params as no transaction metadata found`);
|
|
784
|
+
}
|
|
785
|
+
(0, utils_1.validateIfTransactionUnapproved)(transactionMeta, 'updateEditableParams');
|
|
786
|
+
const editableParams = {
|
|
787
|
+
txParams: {
|
|
788
|
+
data,
|
|
789
|
+
from,
|
|
790
|
+
to,
|
|
791
|
+
value,
|
|
792
|
+
gas,
|
|
793
|
+
gasPrice,
|
|
794
|
+
},
|
|
795
|
+
};
|
|
796
|
+
editableParams.txParams = (0, lodash_1.pickBy)(editableParams.txParams);
|
|
797
|
+
const updatedTransaction = (0, lodash_1.merge)(transactionMeta, editableParams);
|
|
798
|
+
const { type } = yield (0, transaction_type_1.determineTransactionType)(updatedTransaction.txParams, this.ethQuery);
|
|
799
|
+
updatedTransaction.type = type;
|
|
800
|
+
this.updateTransaction(updatedTransaction, `Update Editable Params for ${txId}`);
|
|
801
|
+
return this.getTransaction(txId);
|
|
802
|
+
});
|
|
803
|
+
}
|
|
752
804
|
/**
|
|
753
805
|
* Signs and returns the raw transaction data for provided transaction params list.
|
|
754
806
|
*
|
|
@@ -801,14 +853,12 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
801
853
|
*
|
|
802
854
|
* @param transactionId - The ID of the transaction to update.
|
|
803
855
|
* @param options - The custodial transaction options to update.
|
|
804
|
-
* @param options.custodyStatus - The new custody status value to be assigned.
|
|
805
856
|
* @param options.errorMessage - The error message to be assigned in case transaction status update to failed.
|
|
806
857
|
* @param options.hash - The new hash value to be assigned.
|
|
807
858
|
* @param options.status - The new status value to be assigned.
|
|
808
859
|
*/
|
|
809
|
-
updateCustodialTransaction(transactionId, {
|
|
810
|
-
|
|
811
|
-
transactionMeta = this.getTransaction(transactionId);
|
|
860
|
+
updateCustodialTransaction(transactionId, { errorMessage, hash, status, }) {
|
|
861
|
+
const transactionMeta = this.getTransaction(transactionId);
|
|
812
862
|
if (!transactionMeta) {
|
|
813
863
|
throw new Error(`Cannot update custodial transaction as no transaction metadata found`);
|
|
814
864
|
}
|
|
@@ -823,23 +873,112 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
823
873
|
].includes(status)) {
|
|
824
874
|
throw new Error(`Cannot update custodial transaction with status: ${status}`);
|
|
825
875
|
}
|
|
826
|
-
|
|
827
|
-
transactionMeta.status = status;
|
|
828
|
-
}
|
|
876
|
+
const updatedTransactionMeta = (0, lodash_1.merge)(transactionMeta, (0, lodash_1.pickBy)({ hash, status }));
|
|
829
877
|
if (status === types_1.TransactionStatus.submitted) {
|
|
830
|
-
|
|
831
|
-
transactionMeta.status = status;
|
|
878
|
+
updatedTransactionMeta.submittedTime = new Date().getTime();
|
|
832
879
|
}
|
|
833
880
|
if (status === types_1.TransactionStatus.failed) {
|
|
834
|
-
|
|
881
|
+
updatedTransactionMeta.error = (0, utils_1.normalizeTxError)(new Error(errorMessage));
|
|
835
882
|
}
|
|
836
|
-
|
|
837
|
-
|
|
883
|
+
this.updateTransaction(updatedTransactionMeta, `TransactionController:updateCustodialTransaction - Custodial transaction updated`);
|
|
884
|
+
}
|
|
885
|
+
/**
|
|
886
|
+
* Creates approvals for all unapproved transactions persisted.
|
|
887
|
+
*/
|
|
888
|
+
initApprovals() {
|
|
889
|
+
const chainId = this.getChainId();
|
|
890
|
+
const unapprovedTxs = this.state.transactions.filter((transaction) => transaction.status === types_1.TransactionStatus.unapproved &&
|
|
891
|
+
transaction.chainId === chainId);
|
|
892
|
+
for (const txMeta of unapprovedTxs) {
|
|
893
|
+
this.processApproval(txMeta, {
|
|
894
|
+
shouldShowRequest: false,
|
|
895
|
+
}).catch((error) => {
|
|
896
|
+
if ((error === null || error === void 0 ? void 0 : error.code) === rpc_errors_1.errorCodes.provider.userRejectedRequest) {
|
|
897
|
+
return;
|
|
898
|
+
}
|
|
899
|
+
console.error('Error during persisted transaction approval', error);
|
|
900
|
+
});
|
|
838
901
|
}
|
|
839
|
-
|
|
840
|
-
|
|
902
|
+
}
|
|
903
|
+
/**
|
|
904
|
+
* Search transaction metadata for matching entries.
|
|
905
|
+
*
|
|
906
|
+
* @param opts - Options bag.
|
|
907
|
+
* @param opts.searchCriteria - An object containing values or functions for transaction properties to filter transactions with.
|
|
908
|
+
* @param opts.initialList - The transactions to search. Defaults to the current state.
|
|
909
|
+
* @param opts.filterToCurrentNetwork - Whether to filter the results to the current network. Defaults to true.
|
|
910
|
+
* @param opts.limit - The maximum number of transactions to return. No limit by default.
|
|
911
|
+
* @returns An array of transactions matching the provided options.
|
|
912
|
+
*/
|
|
913
|
+
getTransactions({ searchCriteria = {}, initialList, filterToCurrentNetwork = true, limit, } = {}) {
|
|
914
|
+
const chainId = this.getChainId();
|
|
915
|
+
// searchCriteria is an object that might have values that aren't predicate
|
|
916
|
+
// methods. When providing any other value type (string, number, etc), we
|
|
917
|
+
// consider this shorthand for "check the value at key for strict equality
|
|
918
|
+
// with the provided value". To conform this object to be only methods, we
|
|
919
|
+
// mapValues (lodash) such that every value on the object is a method that
|
|
920
|
+
// returns a boolean.
|
|
921
|
+
const predicateMethods = (0, lodash_1.mapValues)(searchCriteria, (predicate) => {
|
|
922
|
+
return typeof predicate === 'function'
|
|
923
|
+
? predicate
|
|
924
|
+
: (v) => v === predicate;
|
|
925
|
+
});
|
|
926
|
+
const transactionsToFilter = initialList !== null && initialList !== void 0 ? initialList : this.state.transactions;
|
|
927
|
+
// Combine sortBy and pickBy to transform our state object into an array of
|
|
928
|
+
// matching transactions that are sorted by time.
|
|
929
|
+
const filteredTransactions = (0, lodash_1.sortBy)((0, lodash_1.pickBy)(transactionsToFilter, (transaction) => {
|
|
930
|
+
if (filterToCurrentNetwork && transaction.chainId !== chainId) {
|
|
931
|
+
return false;
|
|
932
|
+
}
|
|
933
|
+
// iterate over the predicateMethods keys to check if the transaction
|
|
934
|
+
// matches the searchCriteria
|
|
935
|
+
for (const [key, predicate] of Object.entries(predicateMethods)) {
|
|
936
|
+
// We return false early as soon as we know that one of the specified
|
|
937
|
+
// search criteria do not match the transaction. This prevents
|
|
938
|
+
// needlessly checking all criteria when we already know the criteria
|
|
939
|
+
// are not fully satisfied. We check both txParams and the base
|
|
940
|
+
// object as predicate keys can be either.
|
|
941
|
+
if (key in transaction.txParams) {
|
|
942
|
+
if (predicate(transaction.txParams[key]) === false) {
|
|
943
|
+
return false;
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
else if (predicate(transaction[key]) === false) {
|
|
947
|
+
return false;
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
return true;
|
|
951
|
+
}), 'time');
|
|
952
|
+
if (limit !== undefined) {
|
|
953
|
+
// We need to have all transactions of a given nonce in order to display
|
|
954
|
+
// necessary details in the UI. We use the size of this set to determine
|
|
955
|
+
// whether we have reached the limit provided, thus ensuring that all
|
|
956
|
+
// transactions of nonces we include will be sent to the UI.
|
|
957
|
+
const nonces = new Set();
|
|
958
|
+
const txs = [];
|
|
959
|
+
// By default, the transaction list we filter from is sorted by time ASC.
|
|
960
|
+
// To ensure that filtered results prefers the newest transactions we
|
|
961
|
+
// iterate from right to left, inserting transactions into front of a new
|
|
962
|
+
// array. The original order is preserved, but we ensure that newest txs
|
|
963
|
+
// are preferred.
|
|
964
|
+
for (let i = filteredTransactions.length - 1; i > -1; i--) {
|
|
965
|
+
const txMeta = filteredTransactions[i];
|
|
966
|
+
const { nonce } = txMeta.txParams;
|
|
967
|
+
if (!nonces.has(nonce)) {
|
|
968
|
+
if (nonces.size < limit) {
|
|
969
|
+
nonces.add(nonce);
|
|
970
|
+
}
|
|
971
|
+
else {
|
|
972
|
+
continue;
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
// Push transaction into the beginning of our array to ensure the
|
|
976
|
+
// original order is preserved.
|
|
977
|
+
txs.unshift(txMeta);
|
|
978
|
+
}
|
|
979
|
+
return txs;
|
|
841
980
|
}
|
|
842
|
-
|
|
981
|
+
return filteredTransactions;
|
|
843
982
|
}
|
|
844
983
|
signExternalTransaction(transactionParams) {
|
|
845
984
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -874,7 +1013,8 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
874
1013
|
}
|
|
875
1014
|
updateGasProperties(transactionMeta) {
|
|
876
1015
|
return __awaiter(this, void 0, void 0, function* () {
|
|
877
|
-
const isEIP1559Compatible = yield this.getEIP1559Compatibility()
|
|
1016
|
+
const isEIP1559Compatible = (yield this.getEIP1559Compatibility()) &&
|
|
1017
|
+
transactionMeta.txParams.type !== types_1.TransactionEnvelopeType.legacy;
|
|
878
1018
|
const chainId = this.getChainId();
|
|
879
1019
|
yield (0, gas_1.updateGas)({
|
|
880
1020
|
ethQuery: this.ethQuery,
|
|
@@ -895,8 +1035,6 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
895
1035
|
return this.state.transactions.filter((transaction) => transaction.status === status && transaction.chainId === chainId);
|
|
896
1036
|
}
|
|
897
1037
|
onBootCleanup() {
|
|
898
|
-
this.createApprovalsForUnapprovedTransactions();
|
|
899
|
-
this.loadGasValuesForUnapprovedTransactions();
|
|
900
1038
|
this.submitApprovedTransactions();
|
|
901
1039
|
}
|
|
902
1040
|
/**
|
|
@@ -916,26 +1054,6 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
916
1054
|
});
|
|
917
1055
|
}
|
|
918
1056
|
}
|
|
919
|
-
/**
|
|
920
|
-
* Update the gas values of all unapproved transactions on current chain.
|
|
921
|
-
*/
|
|
922
|
-
loadGasValuesForUnapprovedTransactions() {
|
|
923
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
924
|
-
const unapprovedTransactions = this.getCurrentChainTransactionsByStatus(types_1.TransactionStatus.unapproved);
|
|
925
|
-
const results = yield Promise.allSettled(unapprovedTransactions.map((transactionMeta) => __awaiter(this, void 0, void 0, function* () {
|
|
926
|
-
yield this.updateGasProperties(transactionMeta);
|
|
927
|
-
this.updateTransaction(transactionMeta, 'TransactionController:loadGasValuesForUnapprovedTransactions - Gas values updated');
|
|
928
|
-
})));
|
|
929
|
-
for (const [index, result] of results.entries()) {
|
|
930
|
-
if (result.status === 'rejected') {
|
|
931
|
-
const transactionMeta = unapprovedTransactions[index];
|
|
932
|
-
this.failTransaction(transactionMeta, result.reason);
|
|
933
|
-
/* istanbul ignore next */
|
|
934
|
-
console.error('Error while loading gas values for persisted transaction id: ', transactionMeta.id, result.reason);
|
|
935
|
-
}
|
|
936
|
-
}
|
|
937
|
-
});
|
|
938
|
-
}
|
|
939
1057
|
/**
|
|
940
1058
|
* Force to submit approved transactions on current chain.
|
|
941
1059
|
*/
|
|
@@ -965,6 +1083,13 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
965
1083
|
shouldShowRequest,
|
|
966
1084
|
});
|
|
967
1085
|
resultCallbacks = acceptResult.resultCallbacks;
|
|
1086
|
+
if (resultCallbacks) {
|
|
1087
|
+
this.hub.once(`${transactionId}:publish-skip`, () => {
|
|
1088
|
+
resultCallbacks === null || resultCallbacks === void 0 ? void 0 : resultCallbacks.success();
|
|
1089
|
+
// Remove the reference to prevent additional reports once submitted.
|
|
1090
|
+
resultCallbacks = undefined;
|
|
1091
|
+
});
|
|
1092
|
+
}
|
|
968
1093
|
}
|
|
969
1094
|
const { isCompleted: isTxCompleted } = this.isTransactionCompleted(transactionId);
|
|
970
1095
|
if (!isTxCompleted) {
|
|
@@ -1036,7 +1161,6 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
1036
1161
|
(0, logger_1.projectLogger)('Skipping approval as signing in progress', transactionId);
|
|
1037
1162
|
return;
|
|
1038
1163
|
}
|
|
1039
|
-
const { approved: status } = types_1.TransactionStatus;
|
|
1040
1164
|
let nonceToUse = nonce;
|
|
1041
1165
|
// if a nonce already exists on the transactionMeta it means this is a speedup or cancel transaction
|
|
1042
1166
|
// so we want to reuse that nonce and hope that it beats the previous attempt to chain. Otherwise use a new locked nonce
|
|
@@ -1044,37 +1168,42 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
1044
1168
|
nonceLock = yield this.nonceTracker.getNonceLock(from);
|
|
1045
1169
|
nonceToUse = (0, ethereumjs_util_1.addHexPrefix)(nonceLock.nextNonce.toString(16));
|
|
1046
1170
|
}
|
|
1047
|
-
transactionMeta.status =
|
|
1171
|
+
transactionMeta.status = types_1.TransactionStatus.approved;
|
|
1048
1172
|
transactionMeta.txParams.nonce = nonceToUse;
|
|
1049
1173
|
transactionMeta.txParams.chainId = chainId;
|
|
1050
1174
|
const baseTxParams = Object.assign(Object.assign({}, transactionMeta.txParams), { gasLimit: transactionMeta.txParams.gas });
|
|
1051
1175
|
this.updateTransaction(transactionMeta, 'TransactionController#approveTransaction - Transaction approved');
|
|
1176
|
+
this.onTransactionStatusChange(transactionMeta);
|
|
1052
1177
|
const isEIP1559 = (0, utils_1.isEIP1559Transaction)(transactionMeta.txParams);
|
|
1053
1178
|
const txParams = isEIP1559
|
|
1054
|
-
? Object.assign(Object.assign({}, baseTxParams), {
|
|
1055
|
-
|
|
1056
|
-
type: '2' }) : baseTxParams;
|
|
1057
|
-
// delete gasPrice if maxFeePerGas and maxPriorityFeePerGas are set
|
|
1058
|
-
if (isEIP1559) {
|
|
1059
|
-
delete txParams.gasPrice;
|
|
1060
|
-
}
|
|
1061
|
-
const rawTx = yield this.signTransaction(transactionMeta);
|
|
1179
|
+
? Object.assign(Object.assign({}, baseTxParams), { estimatedBaseFee: transactionMeta.txParams.estimatedBaseFee, type: types_1.TransactionEnvelopeType.feeMarket }) : baseTxParams;
|
|
1180
|
+
const rawTx = yield this.signTransaction(transactionMeta, txParams);
|
|
1062
1181
|
if (!this.beforePublish(transactionMeta)) {
|
|
1063
1182
|
(0, logger_1.projectLogger)('Skipping publishing transaction based on hook');
|
|
1183
|
+
this.hub.emit(`${transactionMeta.id}:publish-skip`, transactionMeta);
|
|
1064
1184
|
return;
|
|
1065
1185
|
}
|
|
1066
1186
|
if (!rawTx) {
|
|
1067
1187
|
return;
|
|
1068
1188
|
}
|
|
1189
|
+
if (transactionMeta.type === types_1.TransactionType.swap) {
|
|
1190
|
+
(0, logger_1.projectLogger)('Determining pre-transaction balance');
|
|
1191
|
+
const preTxBalance = yield (0, controller_utils_1.query)(this.ethQuery, 'getBalance', [from]);
|
|
1192
|
+
transactionMeta.preTxBalance = preTxBalance;
|
|
1193
|
+
(0, logger_1.projectLogger)('Updated pre-transaction balance', transactionMeta.preTxBalance);
|
|
1194
|
+
}
|
|
1195
|
+
(0, logger_1.projectLogger)('Publishing transaction', txParams);
|
|
1069
1196
|
const hash = yield this.publishTransaction(rawTx);
|
|
1197
|
+
(0, logger_1.projectLogger)('Publish successful', hash);
|
|
1070
1198
|
transactionMeta.hash = hash;
|
|
1071
1199
|
transactionMeta.status = types_1.TransactionStatus.submitted;
|
|
1072
1200
|
transactionMeta.submittedTime = new Date().getTime();
|
|
1201
|
+
this.updateTransaction(transactionMeta, 'TransactionController#approveTransaction - Transaction submitted');
|
|
1073
1202
|
this.hub.emit('transaction-submitted', {
|
|
1074
1203
|
transactionMeta,
|
|
1075
1204
|
});
|
|
1076
|
-
this.updateTransaction(transactionMeta, 'TransactionController#approveTransaction - Transaction submitted');
|
|
1077
1205
|
this.hub.emit(`${transactionMeta.id}:finished`, transactionMeta);
|
|
1206
|
+
this.onTransactionStatusChange(transactionMeta);
|
|
1078
1207
|
}
|
|
1079
1208
|
catch (error) {
|
|
1080
1209
|
this.failTransaction(transactionMeta, error);
|
|
@@ -1107,13 +1236,14 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
1107
1236
|
return;
|
|
1108
1237
|
}
|
|
1109
1238
|
transactionMeta.status = types_1.TransactionStatus.rejected;
|
|
1239
|
+
const transactions = this.state.transactions.filter(({ id }) => id !== transactionId);
|
|
1240
|
+
this.update({ transactions: this.trimTransactionsForState(transactions) });
|
|
1110
1241
|
this.hub.emit(`${transactionMeta.id}:finished`, transactionMeta);
|
|
1111
1242
|
this.hub.emit('transaction-rejected', {
|
|
1112
1243
|
transactionMeta,
|
|
1113
1244
|
actionId,
|
|
1114
1245
|
});
|
|
1115
|
-
|
|
1116
|
-
this.update({ transactions: this.trimTransactionsForState(transactions) });
|
|
1246
|
+
this.onTransactionStatusChange(transactionMeta);
|
|
1117
1247
|
}
|
|
1118
1248
|
/**
|
|
1119
1249
|
* Trim the amount of transactions that are set on the state. Checks
|
|
@@ -1124,7 +1254,7 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
1124
1254
|
* representation, this function will not break apart transactions with the
|
|
1125
1255
|
* same nonce, created on the same day, per network. Not accounting for transactions of the same
|
|
1126
1256
|
* nonce, same day and network combo can result in confusing or broken experiences
|
|
1127
|
-
* in the UI. The transactions are then updated using the
|
|
1257
|
+
* in the UI. The transactions are then updated using the BaseControllerV1 update.
|
|
1128
1258
|
*
|
|
1129
1259
|
* @param transactions - The transactions to be applied to the state.
|
|
1130
1260
|
* @returns The trimmed list of transactions.
|
|
@@ -1288,25 +1418,23 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
1288
1418
|
*/
|
|
1289
1419
|
addExternalTransaction(transactionMeta) {
|
|
1290
1420
|
var _a, _b;
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
if (!
|
|
1302
|
-
|
|
1303
|
-
(0, history_1.addInitialHistorySnapshot)(transactionMeta);
|
|
1304
|
-
}
|
|
1421
|
+
const chainId = this.getChainId();
|
|
1422
|
+
const { transactions } = this.state;
|
|
1423
|
+
const fromAddress = (_a = transactionMeta === null || transactionMeta === void 0 ? void 0 : transactionMeta.txParams) === null || _a === void 0 ? void 0 : _a.from;
|
|
1424
|
+
const sameFromAndNetworkTransactions = transactions.filter((transaction) => transaction.txParams.from === fromAddress &&
|
|
1425
|
+
transaction.chainId === chainId);
|
|
1426
|
+
const confirmedTxs = sameFromAndNetworkTransactions.filter((transaction) => transaction.status === types_1.TransactionStatus.confirmed);
|
|
1427
|
+
const pendingTxs = sameFromAndNetworkTransactions.filter((transaction) => transaction.status === types_1.TransactionStatus.submitted);
|
|
1428
|
+
(0, external_transactions_1.validateConfirmedExternalTransaction)(transactionMeta, confirmedTxs, pendingTxs);
|
|
1429
|
+
// Make sure provided external transaction has non empty history array
|
|
1430
|
+
if (!((_b = transactionMeta.history) !== null && _b !== void 0 ? _b : []).length) {
|
|
1431
|
+
if (!this.isHistoryDisabled) {
|
|
1432
|
+
(0, history_1.addInitialHistorySnapshot)(transactionMeta);
|
|
1305
1433
|
}
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1434
|
+
}
|
|
1435
|
+
const updatedTransactions = [...transactions, transactionMeta];
|
|
1436
|
+
this.update({
|
|
1437
|
+
transactions: this.trimTransactionsForState(updatedTransactions),
|
|
1310
1438
|
});
|
|
1311
1439
|
}
|
|
1312
1440
|
/**
|
|
@@ -1351,6 +1479,7 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
1351
1479
|
transactionMeta,
|
|
1352
1480
|
});
|
|
1353
1481
|
this.updateTransaction(transactionMeta, 'TransactionController#setTransactionStatusDropped - Transaction dropped');
|
|
1482
|
+
this.onTransactionStatusChange(transactionMeta);
|
|
1354
1483
|
}
|
|
1355
1484
|
/**
|
|
1356
1485
|
* Get transaction with provided actionId.
|
|
@@ -1391,26 +1520,22 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
1391
1520
|
});
|
|
1392
1521
|
}
|
|
1393
1522
|
getEIP1559Compatibility() {
|
|
1394
|
-
var _a, _b;
|
|
1395
1523
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1396
1524
|
const currentNetworkIsEIP1559Compatible = yield this.getCurrentNetworkEIP1559Compatibility();
|
|
1397
|
-
const currentAccountIsEIP1559Compatible =
|
|
1525
|
+
const currentAccountIsEIP1559Compatible = yield this.getCurrentAccountEIP1559Compatibility();
|
|
1398
1526
|
return (currentNetworkIsEIP1559Compatible && currentAccountIsEIP1559Compatible);
|
|
1399
1527
|
});
|
|
1400
1528
|
}
|
|
1401
1529
|
addPendingTransactionTrackerListeners() {
|
|
1402
|
-
this.pendingTransactionTracker.hub.on('transaction-confirmed', (
|
|
1403
|
-
this.hub.emit('transaction-confirmed', { transactionMeta });
|
|
1404
|
-
this.hub.emit(`${transactionMeta.id}:confirmed`, transactionMeta);
|
|
1405
|
-
});
|
|
1530
|
+
this.pendingTransactionTracker.hub.on('transaction-confirmed', this.onConfirmedTransaction.bind(this));
|
|
1406
1531
|
this.pendingTransactionTracker.hub.on('transaction-dropped', this.setTransactionStatusDropped.bind(this));
|
|
1407
1532
|
this.pendingTransactionTracker.hub.on('transaction-failed', this.failTransaction.bind(this));
|
|
1408
1533
|
this.pendingTransactionTracker.hub.on('transaction-updated', this.updateTransaction.bind(this));
|
|
1409
1534
|
}
|
|
1410
|
-
signTransaction(transactionMeta) {
|
|
1535
|
+
signTransaction(transactionMeta, txParams) {
|
|
1411
1536
|
var _a;
|
|
1412
1537
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1413
|
-
|
|
1538
|
+
(0, logger_1.projectLogger)('Signing transaction', txParams);
|
|
1414
1539
|
const unsignedEthTx = this.prepareUnsignedEthTx(txParams);
|
|
1415
1540
|
this.inProcessOfSigning.add(transactionMeta.id);
|
|
1416
1541
|
const signedTx = yield ((_a = this.sign) === null || _a === void 0 ? void 0 : _a.call(this, unsignedEthTx, txParams.from, ...this.getAdditionalSignArguments(transactionMeta)));
|
|
@@ -1419,19 +1544,59 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
1419
1544
|
return undefined;
|
|
1420
1545
|
}
|
|
1421
1546
|
if (!this.afterSign(transactionMeta, signedTx)) {
|
|
1547
|
+
this.updateTransaction(transactionMeta, 'TransactionController#signTransaction - Update after sign');
|
|
1422
1548
|
(0, logger_1.projectLogger)('Skipping signed status based on hook');
|
|
1423
1549
|
return undefined;
|
|
1424
1550
|
}
|
|
1425
1551
|
yield this.updateTransactionMetaRSV(transactionMeta, signedTx);
|
|
1426
1552
|
transactionMeta.status = types_1.TransactionStatus.signed;
|
|
1427
1553
|
this.updateTransaction(transactionMeta, 'TransactionController#approveTransaction - Transaction signed');
|
|
1554
|
+
this.onTransactionStatusChange(transactionMeta);
|
|
1428
1555
|
const rawTx = (0, ethereumjs_util_1.bufferToHex)(signedTx.serialize());
|
|
1429
1556
|
transactionMeta.rawTx = rawTx;
|
|
1430
1557
|
this.updateTransaction(transactionMeta, 'TransactionController#approveTransaction - RawTransaction added');
|
|
1431
1558
|
return rawTx;
|
|
1432
1559
|
});
|
|
1433
1560
|
}
|
|
1561
|
+
onTransactionStatusChange(transactionMeta) {
|
|
1562
|
+
this.hub.emit('transaction-status-update', { transactionMeta });
|
|
1563
|
+
}
|
|
1564
|
+
getNonceTrackerTransactions(status, address) {
|
|
1565
|
+
const currentChainId = this.getChainId();
|
|
1566
|
+
return (0, utils_1.getAndFormatTransactionsForNonceTracker)(currentChainId, address, status, this.state.transactions);
|
|
1567
|
+
}
|
|
1568
|
+
onConfirmedTransaction(transactionMeta) {
|
|
1569
|
+
(0, logger_1.projectLogger)('Processing confirmed transaction', transactionMeta.id);
|
|
1570
|
+
this.markNonceDuplicatesDropped(transactionMeta.id);
|
|
1571
|
+
this.hub.emit('transaction-confirmed', { transactionMeta });
|
|
1572
|
+
this.hub.emit(`${transactionMeta.id}:confirmed`, transactionMeta);
|
|
1573
|
+
this.onTransactionStatusChange(transactionMeta);
|
|
1574
|
+
// Intentional given potential duration of process.
|
|
1575
|
+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
1576
|
+
this.updatePostBalance(transactionMeta);
|
|
1577
|
+
}
|
|
1578
|
+
updatePostBalance(transactionMeta) {
|
|
1579
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1580
|
+
try {
|
|
1581
|
+
if (transactionMeta.type !== types_1.TransactionType.swap) {
|
|
1582
|
+
return;
|
|
1583
|
+
}
|
|
1584
|
+
const { updatedTransactionMeta, approvalTransactionMeta } = yield (0, swaps_1.updatePostTransactionBalance)(transactionMeta, {
|
|
1585
|
+
ethQuery: this.ethQuery,
|
|
1586
|
+
getTransaction: this.getTransaction.bind(this),
|
|
1587
|
+
updateTransaction: this.updateTransaction.bind(this),
|
|
1588
|
+
});
|
|
1589
|
+
this.hub.emit('post-transaction-balance-updated', {
|
|
1590
|
+
transactionMeta: updatedTransactionMeta,
|
|
1591
|
+
approvalTransactionMeta,
|
|
1592
|
+
});
|
|
1593
|
+
}
|
|
1594
|
+
catch (error) {
|
|
1595
|
+
/* istanbul ignore next */
|
|
1596
|
+
(0, logger_1.projectLogger)('Error while updating post transaction balance', error);
|
|
1597
|
+
}
|
|
1598
|
+
});
|
|
1599
|
+
}
|
|
1434
1600
|
}
|
|
1435
1601
|
exports.TransactionController = TransactionController;
|
|
1436
|
-
exports.default = TransactionController;
|
|
1437
1602
|
//# sourceMappingURL=TransactionController.js.map
|