@metamask-previews/transaction-controller 17.0.0-preview.eb58a59 → 18.3.0-preview.3fbb6b41
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 +48 -1
- package/dist/TransactionController.d.ts +65 -16
- package/dist/TransactionController.d.ts.map +1 -1
- package/dist/TransactionController.js +309 -129
- 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/EtherscanRemoteTransactionSource.d.ts.map +1 -1
- package/dist/helpers/EtherscanRemoteTransactionSource.js +1 -0
- package/dist/helpers/EtherscanRemoteTransactionSource.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 +10 -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/nonce.d.ts +21 -0
- package/dist/utils/nonce.d.ts.map +1 -0
- package/dist/utils/nonce.js +76 -0
- package/dist/utils/nonce.js.map +1 -0
- 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/transaction-type.d.ts.map +1 -1
- package/dist/utils/transaction-type.js +19 -12
- package/dist/utils/transaction-type.js.map +1 -1
- package/dist/utils/utils.d.ts +7 -11
- package/dist/utils/utils.d.ts.map +1 -1
- package/dist/utils/utils.js +23 -30
- 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");
|
|
@@ -35,6 +35,7 @@ const external_transactions_1 = require("./utils/external-transactions");
|
|
|
35
35
|
const gas_1 = require("./utils/gas");
|
|
36
36
|
const gas_fees_1 = require("./utils/gas-fees");
|
|
37
37
|
const history_1 = require("./utils/history");
|
|
38
|
+
const nonce_1 = require("./utils/nonce");
|
|
38
39
|
const swaps_1 = require("./utils/swaps");
|
|
39
40
|
const transaction_type_1 = require("./utils/transaction-type");
|
|
40
41
|
const utils_1 = require("./utils/utils");
|
|
@@ -55,21 +56,23 @@ const controllerName = 'TransactionController';
|
|
|
55
56
|
/**
|
|
56
57
|
* Controller responsible for submitting and managing transactions.
|
|
57
58
|
*/
|
|
58
|
-
class TransactionController extends base_controller_1.
|
|
59
|
+
class TransactionController extends base_controller_1.BaseControllerV1 {
|
|
59
60
|
/**
|
|
60
61
|
* Creates a TransactionController instance.
|
|
61
62
|
*
|
|
62
63
|
* @param options - The controller options.
|
|
63
64
|
* @param options.blockTracker - The block tracker used to poll for new blocks data.
|
|
65
|
+
* @param options.cancelMultiplier - Multiplier used to determine a transaction's increased gas fee during cancellation.
|
|
64
66
|
* @param options.disableHistory - Whether to disable storing history in transaction metadata.
|
|
65
67
|
* @param options.disableSendFlowHistory - Explicitly disable transaction metadata history.
|
|
66
68
|
* @param options.disableSwaps - Whether to disable additional processing on swaps transactions.
|
|
67
|
-
* @param options.getSavedGasFees - Gets the saved gas fee config.
|
|
68
69
|
* @param options.getCurrentAccountEIP1559Compatibility - Whether or not the account supports EIP-1559.
|
|
69
70
|
* @param options.getCurrentNetworkEIP1559Compatibility - Whether or not the network supports EIP-1559.
|
|
71
|
+
* @param options.getExternalPendingTransactions - Callback to retrieve pending transactions from external sources.
|
|
70
72
|
* @param options.getGasFeeEstimates - Callback to retrieve gas fee estimates.
|
|
71
73
|
* @param options.getNetworkState - Gets the state of the network controller.
|
|
72
74
|
* @param options.getPermittedAccounts - Get accounts that a given origin has permissions for.
|
|
75
|
+
* @param options.getSavedGasFees - Gets the saved gas fee config.
|
|
73
76
|
* @param options.getSelectedAddress - Gets the address of the currently selected account.
|
|
74
77
|
* @param options.incomingTransactions - Configuration options for incoming transaction support.
|
|
75
78
|
* @param options.incomingTransactions.includeTokenTransfers - Whether or not to include ERC20 token transfers.
|
|
@@ -82,6 +85,7 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
82
85
|
* @param options.pendingTransactions.isResubmitEnabled - Whether transaction publishing is automatically retried.
|
|
83
86
|
* @param options.provider - The provider used to create the underlying EthQuery instance.
|
|
84
87
|
* @param options.securityProviderRequest - A function for verifying a transaction, whether it is malicious or not.
|
|
88
|
+
* @param options.speedUpMultiplier - Multiplier used to determine a transaction's increased gas fee during speed up.
|
|
85
89
|
* @param options.hooks - The controller hooks.
|
|
86
90
|
* @param options.hooks.afterSign - Additional logic to execute after signing a transaction. Return false to not change the status to signed.
|
|
87
91
|
* @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 +95,7 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
91
95
|
* @param config - Initial options used to configure this controller.
|
|
92
96
|
* @param state - Initial state to set on this controller.
|
|
93
97
|
*/
|
|
94
|
-
constructor({ blockTracker, disableHistory, disableSendFlowHistory, disableSwaps,
|
|
98
|
+
constructor({ blockTracker, cancelMultiplier, disableHistory, disableSendFlowHistory, disableSwaps, getCurrentAccountEIP1559Compatibility, getCurrentNetworkEIP1559Compatibility, getExternalPendingTransactions, getGasFeeEstimates, getNetworkState, getPermittedAccounts, getSavedGasFees, getSelectedAddress, incomingTransactions = {}, messenger, onNetworkStateChange, pendingTransactions = {}, provider, securityProviderRequest, speedUpMultiplier, hooks = {}, }, config, state) {
|
|
95
99
|
var _a, _b, _c, _d, _e;
|
|
96
100
|
super(config, state);
|
|
97
101
|
this.inProcessOfSigning = new Set();
|
|
@@ -123,14 +127,18 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
123
127
|
this.registry = new eth_method_registry_1.default({ provider });
|
|
124
128
|
this.getSavedGasFees = getSavedGasFees !== null && getSavedGasFees !== void 0 ? getSavedGasFees : ((_chainId) => undefined);
|
|
125
129
|
this.getCurrentAccountEIP1559Compatibility =
|
|
126
|
-
getCurrentAccountEIP1559Compatibility;
|
|
130
|
+
getCurrentAccountEIP1559Compatibility !== null && getCurrentAccountEIP1559Compatibility !== void 0 ? getCurrentAccountEIP1559Compatibility : (() => Promise.resolve(true));
|
|
127
131
|
this.getCurrentNetworkEIP1559Compatibility =
|
|
128
132
|
getCurrentNetworkEIP1559Compatibility;
|
|
129
133
|
this.getGasFeeEstimates =
|
|
130
134
|
getGasFeeEstimates || (() => Promise.resolve({}));
|
|
131
135
|
this.getPermittedAccounts = getPermittedAccounts;
|
|
132
136
|
this.getSelectedAddress = getSelectedAddress;
|
|
137
|
+
this.getExternalPendingTransactions =
|
|
138
|
+
getExternalPendingTransactions !== null && getExternalPendingTransactions !== void 0 ? getExternalPendingTransactions : (() => []);
|
|
133
139
|
this.securityProviderRequest = securityProviderRequest;
|
|
140
|
+
this.cancelMultiplier = cancelMultiplier !== null && cancelMultiplier !== void 0 ? cancelMultiplier : exports.CANCEL_RATE;
|
|
141
|
+
this.speedUpMultiplier = speedUpMultiplier !== null && speedUpMultiplier !== void 0 ? speedUpMultiplier : exports.SPEED_UP_RATE;
|
|
134
142
|
this.afterSign = (_a = hooks === null || hooks === void 0 ? void 0 : hooks.afterSign) !== null && _a !== void 0 ? _a : (() => true);
|
|
135
143
|
this.beforeApproveOnInit = (_b = hooks === null || hooks === void 0 ? void 0 : hooks.beforeApproveOnInit) !== null && _b !== void 0 ? _b : (() => true);
|
|
136
144
|
this.beforeCheckPendingTransaction =
|
|
@@ -140,11 +148,12 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
140
148
|
this.beforePublish = (_d = hooks === null || hooks === void 0 ? void 0 : hooks.beforePublish) !== null && _d !== void 0 ? _d : (() => true);
|
|
141
149
|
this.getAdditionalSignArguments =
|
|
142
150
|
(_e = hooks === null || hooks === void 0 ? void 0 : hooks.getAdditionalSignArguments) !== null && _e !== void 0 ? _e : (() => []);
|
|
143
|
-
this.nonceTracker = new nonce_tracker_1.
|
|
151
|
+
this.nonceTracker = new nonce_tracker_1.NonceTracker({
|
|
152
|
+
// @ts-expect-error provider types misaligned: SafeEventEmitterProvider vs Record<string,string>
|
|
144
153
|
provider,
|
|
145
154
|
blockTracker,
|
|
146
|
-
getPendingTransactions:
|
|
147
|
-
getConfirmedTransactions:
|
|
155
|
+
getPendingTransactions: this.getNonceTrackerPendingTransactions.bind(this),
|
|
156
|
+
getConfirmedTransactions: this.getNonceTrackerTransactions.bind(this, types_1.TransactionStatus.confirmed),
|
|
148
157
|
});
|
|
149
158
|
this.incomingTransactionHelper = new IncomingTransactionHelper_1.IncomingTransactionHelper({
|
|
150
159
|
blockTracker,
|
|
@@ -192,6 +201,7 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
192
201
|
transactionMeta: newTransactionMeta,
|
|
193
202
|
});
|
|
194
203
|
this.updateTransaction(newTransactionMeta, 'TransactionController#failTransaction - Add error message and set status to failed');
|
|
204
|
+
this.onTransactionStatusChange(newTransactionMeta);
|
|
195
205
|
this.hub.emit(`${transactionMeta.id}:finished`, newTransactionMeta);
|
|
196
206
|
}
|
|
197
207
|
registryLookup(fourBytePrefix) {
|
|
@@ -249,7 +259,7 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
249
259
|
*/
|
|
250
260
|
addTransaction(txParams, { actionId, deviceConfirmedOn, method, origin, requireApproval, securityAlertResponse, sendFlowHistory, swaps = {}, type, } = {}) {
|
|
251
261
|
return __awaiter(this, void 0, void 0, function* () {
|
|
252
|
-
|
|
262
|
+
(0, logger_1.projectLogger)('Adding transaction', txParams);
|
|
253
263
|
txParams = (0, utils_1.normalizeTxParams)(txParams);
|
|
254
264
|
const isEIP1559Compatible = yield this.getEIP1559Compatibility();
|
|
255
265
|
(0, validation_1.validateTxParams)(txParams, isEIP1559Compatible);
|
|
@@ -259,6 +269,7 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
259
269
|
const dappSuggestedGasFees = this.generateDappSuggestedGasFees(txParams, origin);
|
|
260
270
|
const transactionType = type !== null && type !== void 0 ? type : (yield (0, transaction_type_1.determineTransactionType)(txParams, this.ethQuery)).type;
|
|
261
271
|
const existingTransactionMeta = this.getTransactionWithActionId(actionId);
|
|
272
|
+
const chainId = this.getChainId();
|
|
262
273
|
// If a request to add a transaction with the same actionId is submitted again, a new transaction will not be created for it.
|
|
263
274
|
const transactionMeta = existingTransactionMeta || {
|
|
264
275
|
// Add actionId to txMeta to check if same actionId is seen again
|
|
@@ -331,15 +342,18 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
331
342
|
* @param options.estimatedBaseFee - The estimated base fee of the transaction.
|
|
332
343
|
*/
|
|
333
344
|
stopTransaction(transactionId, gasValues, { estimatedBaseFee, actionId, } = {}) {
|
|
334
|
-
var _a, _b;
|
|
345
|
+
var _a, _b, _c;
|
|
335
346
|
return __awaiter(this, void 0, void 0, function* () {
|
|
336
347
|
// If transaction is found for same action id, do not create a cancel transaction.
|
|
337
348
|
if (this.getTransactionWithActionId(actionId)) {
|
|
338
349
|
return;
|
|
339
350
|
}
|
|
340
351
|
if (gasValues) {
|
|
352
|
+
// Not good practice to reassign a parameter but temporarily avoiding a larger refactor.
|
|
353
|
+
gasValues = (0, utils_1.normalizeGasFeeValues)(gasValues);
|
|
341
354
|
(0, utils_1.validateGasValues)(gasValues);
|
|
342
355
|
}
|
|
356
|
+
(0, logger_1.projectLogger)('Creating cancel transaction', transactionId, gasValues);
|
|
343
357
|
const transactionMeta = this.getTransaction(transactionId);
|
|
344
358
|
if (!transactionMeta) {
|
|
345
359
|
return;
|
|
@@ -348,21 +362,21 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
348
362
|
throw new Error('No sign method defined.');
|
|
349
363
|
}
|
|
350
364
|
// gasPrice (legacy non EIP1559)
|
|
351
|
-
const minGasPrice = (0, utils_1.getIncreasedPriceFromExisting)(transactionMeta.txParams.gasPrice,
|
|
365
|
+
const minGasPrice = (0, utils_1.getIncreasedPriceFromExisting)(transactionMeta.txParams.gasPrice, this.cancelMultiplier);
|
|
352
366
|
const gasPriceFromValues = (0, utils_1.isGasPriceValue)(gasValues) && gasValues.gasPrice;
|
|
353
367
|
const newGasPrice = (gasPriceFromValues &&
|
|
354
368
|
(0, utils_1.validateMinimumIncrease)(gasPriceFromValues, minGasPrice)) ||
|
|
355
369
|
minGasPrice;
|
|
356
370
|
// maxFeePerGas (EIP1559)
|
|
357
371
|
const existingMaxFeePerGas = (_a = transactionMeta.txParams) === null || _a === void 0 ? void 0 : _a.maxFeePerGas;
|
|
358
|
-
const minMaxFeePerGas = (0, utils_1.getIncreasedPriceFromExisting)(existingMaxFeePerGas,
|
|
372
|
+
const minMaxFeePerGas = (0, utils_1.getIncreasedPriceFromExisting)(existingMaxFeePerGas, this.cancelMultiplier);
|
|
359
373
|
const maxFeePerGasValues = (0, utils_1.isFeeMarketEIP1559Values)(gasValues) && gasValues.maxFeePerGas;
|
|
360
374
|
const newMaxFeePerGas = (maxFeePerGasValues &&
|
|
361
375
|
(0, utils_1.validateMinimumIncrease)(maxFeePerGasValues, minMaxFeePerGas)) ||
|
|
362
376
|
(existingMaxFeePerGas && minMaxFeePerGas);
|
|
363
377
|
// maxPriorityFeePerGas (EIP1559)
|
|
364
378
|
const existingMaxPriorityFeePerGas = (_b = transactionMeta.txParams) === null || _b === void 0 ? void 0 : _b.maxPriorityFeePerGas;
|
|
365
|
-
const minMaxPriorityFeePerGas = (0, utils_1.getIncreasedPriceFromExisting)(existingMaxPriorityFeePerGas,
|
|
379
|
+
const minMaxPriorityFeePerGas = (0, utils_1.getIncreasedPriceFromExisting)(existingMaxPriorityFeePerGas, this.cancelMultiplier);
|
|
366
380
|
const maxPriorityFeePerGasValues = (0, utils_1.isFeeMarketEIP1559Values)(gasValues) && gasValues.maxPriorityFeePerGas;
|
|
367
381
|
const newMaxPriorityFeePerGas = (maxPriorityFeePerGasValues &&
|
|
368
382
|
(0, utils_1.validateMinimumIncrease)(maxPriorityFeePerGasValues, minMaxPriorityFeePerGas)) ||
|
|
@@ -373,7 +387,7 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
373
387
|
gasLimit: transactionMeta.txParams.gas,
|
|
374
388
|
maxFeePerGas: newMaxFeePerGas,
|
|
375
389
|
maxPriorityFeePerGas: newMaxPriorityFeePerGas,
|
|
376
|
-
type:
|
|
390
|
+
type: types_1.TransactionEnvelopeType.feeMarket,
|
|
377
391
|
nonce: transactionMeta.txParams.nonce,
|
|
378
392
|
to: transactionMeta.txParams.from,
|
|
379
393
|
value: '0x0',
|
|
@@ -389,6 +403,15 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
389
403
|
const unsignedEthTx = this.prepareUnsignedEthTx(newTxParams);
|
|
390
404
|
const signedTx = yield this.sign(unsignedEthTx, transactionMeta.txParams.from);
|
|
391
405
|
const rawTx = (0, ethereumjs_util_1.bufferToHex)(signedTx.serialize());
|
|
406
|
+
const newFee = (_c = newTxParams.maxFeePerGas) !== null && _c !== void 0 ? _c : newTxParams.gasPrice;
|
|
407
|
+
const oldFee = newTxParams.maxFeePerGas
|
|
408
|
+
? transactionMeta.txParams.maxFeePerGas
|
|
409
|
+
: transactionMeta.txParams.gasPrice;
|
|
410
|
+
(0, logger_1.projectLogger)('Submitting cancel transaction', {
|
|
411
|
+
oldFee,
|
|
412
|
+
newFee,
|
|
413
|
+
txParams: newTxParams,
|
|
414
|
+
});
|
|
392
415
|
const hash = yield this.publishTransaction(rawTx);
|
|
393
416
|
const cancelTransactionMeta = {
|
|
394
417
|
actionId,
|
|
@@ -425,15 +448,18 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
425
448
|
* @param options.estimatedBaseFee - The estimated base fee of the transaction.
|
|
426
449
|
*/
|
|
427
450
|
speedUpTransaction(transactionId, gasValues, { actionId, estimatedBaseFee, } = {}) {
|
|
428
|
-
var _a, _b;
|
|
451
|
+
var _a, _b, _c;
|
|
429
452
|
return __awaiter(this, void 0, void 0, function* () {
|
|
430
453
|
// If transaction is found for same action id, do not create a new speed up transaction.
|
|
431
454
|
if (this.getTransactionWithActionId(actionId)) {
|
|
432
455
|
return;
|
|
433
456
|
}
|
|
434
457
|
if (gasValues) {
|
|
458
|
+
// Not good practice to reassign a parameter but temporarily avoiding a larger refactor.
|
|
459
|
+
gasValues = (0, utils_1.normalizeGasFeeValues)(gasValues);
|
|
435
460
|
(0, utils_1.validateGasValues)(gasValues);
|
|
436
461
|
}
|
|
462
|
+
(0, logger_1.projectLogger)('Creating speed up transaction', transactionId, gasValues);
|
|
437
463
|
const transactionMeta = this.state.transactions.find(({ id }) => id === transactionId);
|
|
438
464
|
/* istanbul ignore next */
|
|
439
465
|
if (!transactionMeta) {
|
|
@@ -444,31 +470,36 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
444
470
|
throw new Error('No sign method defined.');
|
|
445
471
|
}
|
|
446
472
|
// gasPrice (legacy non EIP1559)
|
|
447
|
-
const minGasPrice = (0, utils_1.getIncreasedPriceFromExisting)(transactionMeta.txParams.gasPrice,
|
|
473
|
+
const minGasPrice = (0, utils_1.getIncreasedPriceFromExisting)(transactionMeta.txParams.gasPrice, this.speedUpMultiplier);
|
|
448
474
|
const gasPriceFromValues = (0, utils_1.isGasPriceValue)(gasValues) && gasValues.gasPrice;
|
|
449
475
|
const newGasPrice = (gasPriceFromValues &&
|
|
450
476
|
(0, utils_1.validateMinimumIncrease)(gasPriceFromValues, minGasPrice)) ||
|
|
451
477
|
minGasPrice;
|
|
452
478
|
// maxFeePerGas (EIP1559)
|
|
453
479
|
const existingMaxFeePerGas = (_a = transactionMeta.txParams) === null || _a === void 0 ? void 0 : _a.maxFeePerGas;
|
|
454
|
-
const minMaxFeePerGas = (0, utils_1.getIncreasedPriceFromExisting)(existingMaxFeePerGas,
|
|
480
|
+
const minMaxFeePerGas = (0, utils_1.getIncreasedPriceFromExisting)(existingMaxFeePerGas, this.speedUpMultiplier);
|
|
455
481
|
const maxFeePerGasValues = (0, utils_1.isFeeMarketEIP1559Values)(gasValues) && gasValues.maxFeePerGas;
|
|
456
482
|
const newMaxFeePerGas = (maxFeePerGasValues &&
|
|
457
483
|
(0, utils_1.validateMinimumIncrease)(maxFeePerGasValues, minMaxFeePerGas)) ||
|
|
458
484
|
(existingMaxFeePerGas && minMaxFeePerGas);
|
|
459
485
|
// maxPriorityFeePerGas (EIP1559)
|
|
460
486
|
const existingMaxPriorityFeePerGas = (_b = transactionMeta.txParams) === null || _b === void 0 ? void 0 : _b.maxPriorityFeePerGas;
|
|
461
|
-
const minMaxPriorityFeePerGas = (0, utils_1.getIncreasedPriceFromExisting)(existingMaxPriorityFeePerGas,
|
|
487
|
+
const minMaxPriorityFeePerGas = (0, utils_1.getIncreasedPriceFromExisting)(existingMaxPriorityFeePerGas, this.speedUpMultiplier);
|
|
462
488
|
const maxPriorityFeePerGasValues = (0, utils_1.isFeeMarketEIP1559Values)(gasValues) && gasValues.maxPriorityFeePerGas;
|
|
463
489
|
const newMaxPriorityFeePerGas = (maxPriorityFeePerGasValues &&
|
|
464
490
|
(0, utils_1.validateMinimumIncrease)(maxPriorityFeePerGasValues, minMaxPriorityFeePerGas)) ||
|
|
465
491
|
(existingMaxPriorityFeePerGas && minMaxPriorityFeePerGas);
|
|
466
492
|
const txParams = newMaxFeePerGas && newMaxPriorityFeePerGas
|
|
467
|
-
? Object.assign(Object.assign({}, transactionMeta.txParams), { gasLimit: transactionMeta.txParams.gas, maxFeePerGas: newMaxFeePerGas, maxPriorityFeePerGas: newMaxPriorityFeePerGas, type:
|
|
493
|
+
? 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
494
|
const unsignedEthTx = this.prepareUnsignedEthTx(txParams);
|
|
469
495
|
const signedTx = yield this.sign(unsignedEthTx, transactionMeta.txParams.from);
|
|
470
496
|
yield this.updateTransactionMetaRSV(transactionMeta, signedTx);
|
|
471
497
|
const rawTx = (0, ethereumjs_util_1.bufferToHex)(signedTx.serialize());
|
|
498
|
+
const newFee = (_c = txParams.maxFeePerGas) !== null && _c !== void 0 ? _c : txParams.gasPrice;
|
|
499
|
+
const oldFee = txParams.maxFeePerGas
|
|
500
|
+
? transactionMeta.txParams.maxFeePerGas
|
|
501
|
+
: transactionMeta.txParams.gasPrice;
|
|
502
|
+
(0, logger_1.projectLogger)('Submitting speed up transaction', { oldFee, newFee, txParams });
|
|
472
503
|
const hash = yield (0, controller_utils_1.query)(this.ethQuery, 'sendRawTransaction', [rawTx]);
|
|
473
504
|
const baseTransactionMeta = Object.assign(Object.assign({}, transactionMeta), { estimatedBaseFee, id: (0, uuid_1.v1)(), time: Date.now(), hash,
|
|
474
505
|
actionId, originalGasEstimate: transactionMeta.txParams.gas, type: types_1.TransactionType.retry, originalType: transactionMeta.type });
|
|
@@ -606,29 +637,16 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
606
637
|
this.markNonceDuplicatesDropped(transactionId);
|
|
607
638
|
// Update external provided transaction with updated gas values and confirmed status.
|
|
608
639
|
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
|
-
}
|
|
640
|
+
this.onTransactionStatusChange(transactionMeta);
|
|
641
|
+
// Intentional given potential duration of process.
|
|
642
|
+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
643
|
+
this.updatePostBalance(transactionMeta);
|
|
626
644
|
this.hub.emit('transaction-confirmed', {
|
|
627
645
|
transactionMeta,
|
|
628
646
|
});
|
|
629
647
|
}
|
|
630
648
|
catch (error) {
|
|
631
|
-
console.error(error);
|
|
649
|
+
console.error('Failed to confirm external transaction', error);
|
|
632
650
|
}
|
|
633
651
|
});
|
|
634
652
|
}
|
|
@@ -749,6 +767,44 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
749
767
|
return this.nonceTracker.getNonceLock(address);
|
|
750
768
|
});
|
|
751
769
|
}
|
|
770
|
+
/**
|
|
771
|
+
* Updates the editable parameters of a transaction.
|
|
772
|
+
*
|
|
773
|
+
* @param txId - The ID of the transaction to update.
|
|
774
|
+
* @param params - The editable parameters to update.
|
|
775
|
+
* @param params.data - Data to pass with the transaction.
|
|
776
|
+
* @param params.gas - Maximum number of units of gas to use for the transaction.
|
|
777
|
+
* @param params.gasPrice - Price per gas for legacy transactions.
|
|
778
|
+
* @param params.from - Address to send the transaction from.
|
|
779
|
+
* @param params.to - Address to send the transaction to.
|
|
780
|
+
* @param params.value - Value associated with the transaction.
|
|
781
|
+
* @returns The updated transaction metadata.
|
|
782
|
+
*/
|
|
783
|
+
updateEditableParams(txId, { data, gas, gasPrice, from, to, value, }) {
|
|
784
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
785
|
+
const transactionMeta = this.getTransaction(txId);
|
|
786
|
+
if (!transactionMeta) {
|
|
787
|
+
throw new Error(`Cannot update editable params as no transaction metadata found`);
|
|
788
|
+
}
|
|
789
|
+
(0, utils_1.validateIfTransactionUnapproved)(transactionMeta, 'updateEditableParams');
|
|
790
|
+
const editableParams = {
|
|
791
|
+
txParams: {
|
|
792
|
+
data,
|
|
793
|
+
from,
|
|
794
|
+
to,
|
|
795
|
+
value,
|
|
796
|
+
gas,
|
|
797
|
+
gasPrice,
|
|
798
|
+
},
|
|
799
|
+
};
|
|
800
|
+
editableParams.txParams = (0, lodash_1.pickBy)(editableParams.txParams);
|
|
801
|
+
const updatedTransaction = (0, lodash_1.merge)(transactionMeta, editableParams);
|
|
802
|
+
const { type } = yield (0, transaction_type_1.determineTransactionType)(updatedTransaction.txParams, this.ethQuery);
|
|
803
|
+
updatedTransaction.type = type;
|
|
804
|
+
this.updateTransaction(updatedTransaction, `Update Editable Params for ${txId}`);
|
|
805
|
+
return this.getTransaction(txId);
|
|
806
|
+
});
|
|
807
|
+
}
|
|
752
808
|
/**
|
|
753
809
|
* Signs and returns the raw transaction data for provided transaction params list.
|
|
754
810
|
*
|
|
@@ -757,6 +813,9 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
757
813
|
*/
|
|
758
814
|
approveTransactionsWithSameNonce(listOfTxParams = []) {
|
|
759
815
|
return __awaiter(this, void 0, void 0, function* () {
|
|
816
|
+
(0, logger_1.projectLogger)('Approving transactions with same nonce', {
|
|
817
|
+
transactions: listOfTxParams,
|
|
818
|
+
});
|
|
760
819
|
if (listOfTxParams.length === 0) {
|
|
761
820
|
return '';
|
|
762
821
|
}
|
|
@@ -776,6 +835,7 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
776
835
|
const fromAddress = initialTx.from;
|
|
777
836
|
nonceLock = yield this.nonceTracker.getNonceLock(fromAddress);
|
|
778
837
|
const nonce = nonceLock.nextNonce;
|
|
838
|
+
(0, logger_1.projectLogger)('Using nonce from nonce tracker', nonce, nonceLock.nonceDetails);
|
|
779
839
|
rawTransactions = yield Promise.all(listOfTxParams.map((txParams) => {
|
|
780
840
|
txParams.nonce = (0, ethereumjs_util_1.addHexPrefix)(nonce.toString(16));
|
|
781
841
|
return this.signExternalTransaction(txParams);
|
|
@@ -801,14 +861,12 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
801
861
|
*
|
|
802
862
|
* @param transactionId - The ID of the transaction to update.
|
|
803
863
|
* @param options - The custodial transaction options to update.
|
|
804
|
-
* @param options.custodyStatus - The new custody status value to be assigned.
|
|
805
864
|
* @param options.errorMessage - The error message to be assigned in case transaction status update to failed.
|
|
806
865
|
* @param options.hash - The new hash value to be assigned.
|
|
807
866
|
* @param options.status - The new status value to be assigned.
|
|
808
867
|
*/
|
|
809
|
-
updateCustodialTransaction(transactionId, {
|
|
810
|
-
|
|
811
|
-
transactionMeta = this.getTransaction(transactionId);
|
|
868
|
+
updateCustodialTransaction(transactionId, { errorMessage, hash, status, }) {
|
|
869
|
+
const transactionMeta = this.getTransaction(transactionId);
|
|
812
870
|
if (!transactionMeta) {
|
|
813
871
|
throw new Error(`Cannot update custodial transaction as no transaction metadata found`);
|
|
814
872
|
}
|
|
@@ -823,23 +881,112 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
823
881
|
].includes(status)) {
|
|
824
882
|
throw new Error(`Cannot update custodial transaction with status: ${status}`);
|
|
825
883
|
}
|
|
826
|
-
|
|
827
|
-
transactionMeta.status = status;
|
|
828
|
-
}
|
|
884
|
+
const updatedTransactionMeta = (0, lodash_1.merge)(transactionMeta, (0, lodash_1.pickBy)({ hash, status }));
|
|
829
885
|
if (status === types_1.TransactionStatus.submitted) {
|
|
830
|
-
|
|
831
|
-
transactionMeta.status = status;
|
|
886
|
+
updatedTransactionMeta.submittedTime = new Date().getTime();
|
|
832
887
|
}
|
|
833
888
|
if (status === types_1.TransactionStatus.failed) {
|
|
834
|
-
|
|
889
|
+
updatedTransactionMeta.error = (0, utils_1.normalizeTxError)(new Error(errorMessage));
|
|
835
890
|
}
|
|
836
|
-
|
|
837
|
-
|
|
891
|
+
this.updateTransaction(updatedTransactionMeta, `TransactionController:updateCustodialTransaction - Custodial transaction updated`);
|
|
892
|
+
}
|
|
893
|
+
/**
|
|
894
|
+
* Creates approvals for all unapproved transactions persisted.
|
|
895
|
+
*/
|
|
896
|
+
initApprovals() {
|
|
897
|
+
const chainId = this.getChainId();
|
|
898
|
+
const unapprovedTxs = this.state.transactions.filter((transaction) => transaction.status === types_1.TransactionStatus.unapproved &&
|
|
899
|
+
transaction.chainId === chainId);
|
|
900
|
+
for (const txMeta of unapprovedTxs) {
|
|
901
|
+
this.processApproval(txMeta, {
|
|
902
|
+
shouldShowRequest: false,
|
|
903
|
+
}).catch((error) => {
|
|
904
|
+
if ((error === null || error === void 0 ? void 0 : error.code) === rpc_errors_1.errorCodes.provider.userRejectedRequest) {
|
|
905
|
+
return;
|
|
906
|
+
}
|
|
907
|
+
console.error('Error during persisted transaction approval', error);
|
|
908
|
+
});
|
|
838
909
|
}
|
|
839
|
-
|
|
840
|
-
|
|
910
|
+
}
|
|
911
|
+
/**
|
|
912
|
+
* Search transaction metadata for matching entries.
|
|
913
|
+
*
|
|
914
|
+
* @param opts - Options bag.
|
|
915
|
+
* @param opts.searchCriteria - An object containing values or functions for transaction properties to filter transactions with.
|
|
916
|
+
* @param opts.initialList - The transactions to search. Defaults to the current state.
|
|
917
|
+
* @param opts.filterToCurrentNetwork - Whether to filter the results to the current network. Defaults to true.
|
|
918
|
+
* @param opts.limit - The maximum number of transactions to return. No limit by default.
|
|
919
|
+
* @returns An array of transactions matching the provided options.
|
|
920
|
+
*/
|
|
921
|
+
getTransactions({ searchCriteria = {}, initialList, filterToCurrentNetwork = true, limit, } = {}) {
|
|
922
|
+
const chainId = this.getChainId();
|
|
923
|
+
// searchCriteria is an object that might have values that aren't predicate
|
|
924
|
+
// methods. When providing any other value type (string, number, etc), we
|
|
925
|
+
// consider this shorthand for "check the value at key for strict equality
|
|
926
|
+
// with the provided value". To conform this object to be only methods, we
|
|
927
|
+
// mapValues (lodash) such that every value on the object is a method that
|
|
928
|
+
// returns a boolean.
|
|
929
|
+
const predicateMethods = (0, lodash_1.mapValues)(searchCriteria, (predicate) => {
|
|
930
|
+
return typeof predicate === 'function'
|
|
931
|
+
? predicate
|
|
932
|
+
: (v) => v === predicate;
|
|
933
|
+
});
|
|
934
|
+
const transactionsToFilter = initialList !== null && initialList !== void 0 ? initialList : this.state.transactions;
|
|
935
|
+
// Combine sortBy and pickBy to transform our state object into an array of
|
|
936
|
+
// matching transactions that are sorted by time.
|
|
937
|
+
const filteredTransactions = (0, lodash_1.sortBy)((0, lodash_1.pickBy)(transactionsToFilter, (transaction) => {
|
|
938
|
+
if (filterToCurrentNetwork && transaction.chainId !== chainId) {
|
|
939
|
+
return false;
|
|
940
|
+
}
|
|
941
|
+
// iterate over the predicateMethods keys to check if the transaction
|
|
942
|
+
// matches the searchCriteria
|
|
943
|
+
for (const [key, predicate] of Object.entries(predicateMethods)) {
|
|
944
|
+
// We return false early as soon as we know that one of the specified
|
|
945
|
+
// search criteria do not match the transaction. This prevents
|
|
946
|
+
// needlessly checking all criteria when we already know the criteria
|
|
947
|
+
// are not fully satisfied. We check both txParams and the base
|
|
948
|
+
// object as predicate keys can be either.
|
|
949
|
+
if (key in transaction.txParams) {
|
|
950
|
+
if (predicate(transaction.txParams[key]) === false) {
|
|
951
|
+
return false;
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
else if (predicate(transaction[key]) === false) {
|
|
955
|
+
return false;
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
return true;
|
|
959
|
+
}), 'time');
|
|
960
|
+
if (limit !== undefined) {
|
|
961
|
+
// We need to have all transactions of a given nonce in order to display
|
|
962
|
+
// necessary details in the UI. We use the size of this set to determine
|
|
963
|
+
// whether we have reached the limit provided, thus ensuring that all
|
|
964
|
+
// transactions of nonces we include will be sent to the UI.
|
|
965
|
+
const nonces = new Set();
|
|
966
|
+
const txs = [];
|
|
967
|
+
// By default, the transaction list we filter from is sorted by time ASC.
|
|
968
|
+
// To ensure that filtered results prefers the newest transactions we
|
|
969
|
+
// iterate from right to left, inserting transactions into front of a new
|
|
970
|
+
// array. The original order is preserved, but we ensure that newest txs
|
|
971
|
+
// are preferred.
|
|
972
|
+
for (let i = filteredTransactions.length - 1; i > -1; i--) {
|
|
973
|
+
const txMeta = filteredTransactions[i];
|
|
974
|
+
const { nonce } = txMeta.txParams;
|
|
975
|
+
if (!nonces.has(nonce)) {
|
|
976
|
+
if (nonces.size < limit) {
|
|
977
|
+
nonces.add(nonce);
|
|
978
|
+
}
|
|
979
|
+
else {
|
|
980
|
+
continue;
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
// Push transaction into the beginning of our array to ensure the
|
|
984
|
+
// original order is preserved.
|
|
985
|
+
txs.unshift(txMeta);
|
|
986
|
+
}
|
|
987
|
+
return txs;
|
|
841
988
|
}
|
|
842
|
-
|
|
989
|
+
return filteredTransactions;
|
|
843
990
|
}
|
|
844
991
|
signExternalTransaction(transactionParams) {
|
|
845
992
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -874,7 +1021,8 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
874
1021
|
}
|
|
875
1022
|
updateGasProperties(transactionMeta) {
|
|
876
1023
|
return __awaiter(this, void 0, void 0, function* () {
|
|
877
|
-
const isEIP1559Compatible = yield this.getEIP1559Compatibility()
|
|
1024
|
+
const isEIP1559Compatible = (yield this.getEIP1559Compatibility()) &&
|
|
1025
|
+
transactionMeta.txParams.type !== types_1.TransactionEnvelopeType.legacy;
|
|
878
1026
|
const chainId = this.getChainId();
|
|
879
1027
|
yield (0, gas_1.updateGas)({
|
|
880
1028
|
ethQuery: this.ethQuery,
|
|
@@ -895,8 +1043,6 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
895
1043
|
return this.state.transactions.filter((transaction) => transaction.status === status && transaction.chainId === chainId);
|
|
896
1044
|
}
|
|
897
1045
|
onBootCleanup() {
|
|
898
|
-
this.createApprovalsForUnapprovedTransactions();
|
|
899
|
-
this.loadGasValuesForUnapprovedTransactions();
|
|
900
1046
|
this.submitApprovedTransactions();
|
|
901
1047
|
}
|
|
902
1048
|
/**
|
|
@@ -916,26 +1062,6 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
916
1062
|
});
|
|
917
1063
|
}
|
|
918
1064
|
}
|
|
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
1065
|
/**
|
|
940
1066
|
* Force to submit approved transactions on current chain.
|
|
941
1067
|
*/
|
|
@@ -965,6 +1091,22 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
965
1091
|
shouldShowRequest,
|
|
966
1092
|
});
|
|
967
1093
|
resultCallbacks = acceptResult.resultCallbacks;
|
|
1094
|
+
if (resultCallbacks) {
|
|
1095
|
+
this.hub.once(`${transactionId}:publish-skip`, () => {
|
|
1096
|
+
resultCallbacks === null || resultCallbacks === void 0 ? void 0 : resultCallbacks.success();
|
|
1097
|
+
// Remove the reference to prevent additional reports once submitted.
|
|
1098
|
+
resultCallbacks = undefined;
|
|
1099
|
+
});
|
|
1100
|
+
}
|
|
1101
|
+
const approvalValue = acceptResult.value;
|
|
1102
|
+
const updatedTransaction = approvalValue === null || approvalValue === void 0 ? void 0 : approvalValue.txMeta;
|
|
1103
|
+
if (updatedTransaction) {
|
|
1104
|
+
(0, logger_1.projectLogger)('Updating transaction with approval data', {
|
|
1105
|
+
customNonce: updatedTransaction.customNonceValue,
|
|
1106
|
+
params: updatedTransaction.txParams,
|
|
1107
|
+
});
|
|
1108
|
+
this.updateTransaction(updatedTransaction, 'TransactionController#processApproval - Updated with approval data');
|
|
1109
|
+
}
|
|
968
1110
|
}
|
|
969
1111
|
const { isCompleted: isTxCompleted } = this.isTransactionCompleted(transactionId);
|
|
970
1112
|
if (!isTxCompleted) {
|
|
@@ -1019,8 +1161,8 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
1019
1161
|
const chainId = this.getChainId();
|
|
1020
1162
|
const index = transactions.findIndex(({ id }) => transactionId === id);
|
|
1021
1163
|
const transactionMeta = transactions[index];
|
|
1022
|
-
const { txParams: {
|
|
1023
|
-
let
|
|
1164
|
+
const { txParams: { from }, } = transactionMeta;
|
|
1165
|
+
let releaseNonceLock;
|
|
1024
1166
|
try {
|
|
1025
1167
|
if (!this.sign) {
|
|
1026
1168
|
releaseLock();
|
|
@@ -1036,45 +1178,44 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
1036
1178
|
(0, logger_1.projectLogger)('Skipping approval as signing in progress', transactionId);
|
|
1037
1179
|
return;
|
|
1038
1180
|
}
|
|
1039
|
-
const
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
if (!nonceToUse) {
|
|
1044
|
-
nonceLock = yield this.nonceTracker.getNonceLock(from);
|
|
1045
|
-
nonceToUse = (0, ethereumjs_util_1.addHexPrefix)(nonceLock.nextNonce.toString(16));
|
|
1046
|
-
}
|
|
1047
|
-
transactionMeta.status = status;
|
|
1048
|
-
transactionMeta.txParams.nonce = nonceToUse;
|
|
1181
|
+
const [nonce, releaseNonce] = yield (0, nonce_1.getNextNonce)(transactionMeta, this.nonceTracker);
|
|
1182
|
+
releaseNonceLock = releaseNonce;
|
|
1183
|
+
transactionMeta.status = types_1.TransactionStatus.approved;
|
|
1184
|
+
transactionMeta.txParams.nonce = nonce;
|
|
1049
1185
|
transactionMeta.txParams.chainId = chainId;
|
|
1050
1186
|
const baseTxParams = Object.assign(Object.assign({}, transactionMeta.txParams), { gasLimit: transactionMeta.txParams.gas });
|
|
1051
1187
|
this.updateTransaction(transactionMeta, 'TransactionController#approveTransaction - Transaction approved');
|
|
1188
|
+
this.onTransactionStatusChange(transactionMeta);
|
|
1052
1189
|
const isEIP1559 = (0, utils_1.isEIP1559Transaction)(transactionMeta.txParams);
|
|
1053
1190
|
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);
|
|
1191
|
+
? Object.assign(Object.assign({}, baseTxParams), { estimatedBaseFee: transactionMeta.txParams.estimatedBaseFee, type: types_1.TransactionEnvelopeType.feeMarket }) : baseTxParams;
|
|
1192
|
+
const rawTx = yield this.signTransaction(transactionMeta, txParams);
|
|
1062
1193
|
if (!this.beforePublish(transactionMeta)) {
|
|
1063
1194
|
(0, logger_1.projectLogger)('Skipping publishing transaction based on hook');
|
|
1195
|
+
this.hub.emit(`${transactionMeta.id}:publish-skip`, transactionMeta);
|
|
1064
1196
|
return;
|
|
1065
1197
|
}
|
|
1066
1198
|
if (!rawTx) {
|
|
1067
1199
|
return;
|
|
1068
1200
|
}
|
|
1201
|
+
if (transactionMeta.type === types_1.TransactionType.swap) {
|
|
1202
|
+
(0, logger_1.projectLogger)('Determining pre-transaction balance');
|
|
1203
|
+
const preTxBalance = yield (0, controller_utils_1.query)(this.ethQuery, 'getBalance', [from]);
|
|
1204
|
+
transactionMeta.preTxBalance = preTxBalance;
|
|
1205
|
+
(0, logger_1.projectLogger)('Updated pre-transaction balance', transactionMeta.preTxBalance);
|
|
1206
|
+
}
|
|
1207
|
+
(0, logger_1.projectLogger)('Publishing transaction', txParams);
|
|
1069
1208
|
const hash = yield this.publishTransaction(rawTx);
|
|
1209
|
+
(0, logger_1.projectLogger)('Publish successful', hash);
|
|
1070
1210
|
transactionMeta.hash = hash;
|
|
1071
1211
|
transactionMeta.status = types_1.TransactionStatus.submitted;
|
|
1072
1212
|
transactionMeta.submittedTime = new Date().getTime();
|
|
1213
|
+
this.updateTransaction(transactionMeta, 'TransactionController#approveTransaction - Transaction submitted');
|
|
1073
1214
|
this.hub.emit('transaction-submitted', {
|
|
1074
1215
|
transactionMeta,
|
|
1075
1216
|
});
|
|
1076
|
-
this.updateTransaction(transactionMeta, 'TransactionController#approveTransaction - Transaction submitted');
|
|
1077
1217
|
this.hub.emit(`${transactionMeta.id}:finished`, transactionMeta);
|
|
1218
|
+
this.onTransactionStatusChange(transactionMeta);
|
|
1078
1219
|
}
|
|
1079
1220
|
catch (error) {
|
|
1080
1221
|
this.failTransaction(transactionMeta, error);
|
|
@@ -1082,9 +1223,7 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
1082
1223
|
finally {
|
|
1083
1224
|
this.inProcessOfSigning.delete(transactionId);
|
|
1084
1225
|
// must set transaction to submitted/failed before releasing lock
|
|
1085
|
-
|
|
1086
|
-
nonceLock.releaseLock();
|
|
1087
|
-
}
|
|
1226
|
+
releaseNonceLock === null || releaseNonceLock === void 0 ? void 0 : releaseNonceLock();
|
|
1088
1227
|
releaseLock();
|
|
1089
1228
|
}
|
|
1090
1229
|
});
|
|
@@ -1107,13 +1246,14 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
1107
1246
|
return;
|
|
1108
1247
|
}
|
|
1109
1248
|
transactionMeta.status = types_1.TransactionStatus.rejected;
|
|
1249
|
+
const transactions = this.state.transactions.filter(({ id }) => id !== transactionId);
|
|
1250
|
+
this.update({ transactions: this.trimTransactionsForState(transactions) });
|
|
1110
1251
|
this.hub.emit(`${transactionMeta.id}:finished`, transactionMeta);
|
|
1111
1252
|
this.hub.emit('transaction-rejected', {
|
|
1112
1253
|
transactionMeta,
|
|
1113
1254
|
actionId,
|
|
1114
1255
|
});
|
|
1115
|
-
|
|
1116
|
-
this.update({ transactions: this.trimTransactionsForState(transactions) });
|
|
1256
|
+
this.onTransactionStatusChange(transactionMeta);
|
|
1117
1257
|
}
|
|
1118
1258
|
/**
|
|
1119
1259
|
* Trim the amount of transactions that are set on the state. Checks
|
|
@@ -1124,7 +1264,7 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
1124
1264
|
* representation, this function will not break apart transactions with the
|
|
1125
1265
|
* same nonce, created on the same day, per network. Not accounting for transactions of the same
|
|
1126
1266
|
* nonce, same day and network combo can result in confusing or broken experiences
|
|
1127
|
-
* in the UI. The transactions are then updated using the
|
|
1267
|
+
* in the UI. The transactions are then updated using the BaseControllerV1 update.
|
|
1128
1268
|
*
|
|
1129
1269
|
* @param transactions - The transactions to be applied to the state.
|
|
1130
1270
|
* @returns The trimmed list of transactions.
|
|
@@ -1288,25 +1428,23 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
1288
1428
|
*/
|
|
1289
1429
|
addExternalTransaction(transactionMeta) {
|
|
1290
1430
|
var _a, _b;
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
if (!
|
|
1302
|
-
|
|
1303
|
-
(0, history_1.addInitialHistorySnapshot)(transactionMeta);
|
|
1304
|
-
}
|
|
1431
|
+
const chainId = this.getChainId();
|
|
1432
|
+
const { transactions } = this.state;
|
|
1433
|
+
const fromAddress = (_a = transactionMeta === null || transactionMeta === void 0 ? void 0 : transactionMeta.txParams) === null || _a === void 0 ? void 0 : _a.from;
|
|
1434
|
+
const sameFromAndNetworkTransactions = transactions.filter((transaction) => transaction.txParams.from === fromAddress &&
|
|
1435
|
+
transaction.chainId === chainId);
|
|
1436
|
+
const confirmedTxs = sameFromAndNetworkTransactions.filter((transaction) => transaction.status === types_1.TransactionStatus.confirmed);
|
|
1437
|
+
const pendingTxs = sameFromAndNetworkTransactions.filter((transaction) => transaction.status === types_1.TransactionStatus.submitted);
|
|
1438
|
+
(0, external_transactions_1.validateConfirmedExternalTransaction)(transactionMeta, confirmedTxs, pendingTxs);
|
|
1439
|
+
// Make sure provided external transaction has non empty history array
|
|
1440
|
+
if (!((_b = transactionMeta.history) !== null && _b !== void 0 ? _b : []).length) {
|
|
1441
|
+
if (!this.isHistoryDisabled) {
|
|
1442
|
+
(0, history_1.addInitialHistorySnapshot)(transactionMeta);
|
|
1305
1443
|
}
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1444
|
+
}
|
|
1445
|
+
const updatedTransactions = [...transactions, transactionMeta];
|
|
1446
|
+
this.update({
|
|
1447
|
+
transactions: this.trimTransactionsForState(updatedTransactions),
|
|
1310
1448
|
});
|
|
1311
1449
|
}
|
|
1312
1450
|
/**
|
|
@@ -1351,6 +1489,7 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
1351
1489
|
transactionMeta,
|
|
1352
1490
|
});
|
|
1353
1491
|
this.updateTransaction(transactionMeta, 'TransactionController#setTransactionStatusDropped - Transaction dropped');
|
|
1492
|
+
this.onTransactionStatusChange(transactionMeta);
|
|
1354
1493
|
}
|
|
1355
1494
|
/**
|
|
1356
1495
|
* Get transaction with provided actionId.
|
|
@@ -1391,26 +1530,22 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
1391
1530
|
});
|
|
1392
1531
|
}
|
|
1393
1532
|
getEIP1559Compatibility() {
|
|
1394
|
-
var _a, _b;
|
|
1395
1533
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1396
1534
|
const currentNetworkIsEIP1559Compatible = yield this.getCurrentNetworkEIP1559Compatibility();
|
|
1397
|
-
const currentAccountIsEIP1559Compatible =
|
|
1535
|
+
const currentAccountIsEIP1559Compatible = yield this.getCurrentAccountEIP1559Compatibility();
|
|
1398
1536
|
return (currentNetworkIsEIP1559Compatible && currentAccountIsEIP1559Compatible);
|
|
1399
1537
|
});
|
|
1400
1538
|
}
|
|
1401
1539
|
addPendingTransactionTrackerListeners() {
|
|
1402
|
-
this.pendingTransactionTracker.hub.on('transaction-confirmed', (
|
|
1403
|
-
this.hub.emit('transaction-confirmed', { transactionMeta });
|
|
1404
|
-
this.hub.emit(`${transactionMeta.id}:confirmed`, transactionMeta);
|
|
1405
|
-
});
|
|
1540
|
+
this.pendingTransactionTracker.hub.on('transaction-confirmed', this.onConfirmedTransaction.bind(this));
|
|
1406
1541
|
this.pendingTransactionTracker.hub.on('transaction-dropped', this.setTransactionStatusDropped.bind(this));
|
|
1407
1542
|
this.pendingTransactionTracker.hub.on('transaction-failed', this.failTransaction.bind(this));
|
|
1408
1543
|
this.pendingTransactionTracker.hub.on('transaction-updated', this.updateTransaction.bind(this));
|
|
1409
1544
|
}
|
|
1410
|
-
signTransaction(transactionMeta) {
|
|
1545
|
+
signTransaction(transactionMeta, txParams) {
|
|
1411
1546
|
var _a;
|
|
1412
1547
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1413
|
-
|
|
1548
|
+
(0, logger_1.projectLogger)('Signing transaction', txParams);
|
|
1414
1549
|
const unsignedEthTx = this.prepareUnsignedEthTx(txParams);
|
|
1415
1550
|
this.inProcessOfSigning.add(transactionMeta.id);
|
|
1416
1551
|
const signedTx = yield ((_a = this.sign) === null || _a === void 0 ? void 0 : _a.call(this, unsignedEthTx, txParams.from, ...this.getAdditionalSignArguments(transactionMeta)));
|
|
@@ -1419,19 +1554,64 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
1419
1554
|
return undefined;
|
|
1420
1555
|
}
|
|
1421
1556
|
if (!this.afterSign(transactionMeta, signedTx)) {
|
|
1557
|
+
this.updateTransaction(transactionMeta, 'TransactionController#signTransaction - Update after sign');
|
|
1422
1558
|
(0, logger_1.projectLogger)('Skipping signed status based on hook');
|
|
1423
1559
|
return undefined;
|
|
1424
1560
|
}
|
|
1425
1561
|
yield this.updateTransactionMetaRSV(transactionMeta, signedTx);
|
|
1426
1562
|
transactionMeta.status = types_1.TransactionStatus.signed;
|
|
1427
1563
|
this.updateTransaction(transactionMeta, 'TransactionController#approveTransaction - Transaction signed');
|
|
1564
|
+
this.onTransactionStatusChange(transactionMeta);
|
|
1428
1565
|
const rawTx = (0, ethereumjs_util_1.bufferToHex)(signedTx.serialize());
|
|
1429
1566
|
transactionMeta.rawTx = rawTx;
|
|
1430
1567
|
this.updateTransaction(transactionMeta, 'TransactionController#approveTransaction - RawTransaction added');
|
|
1431
1568
|
return rawTx;
|
|
1432
1569
|
});
|
|
1433
1570
|
}
|
|
1571
|
+
onTransactionStatusChange(transactionMeta) {
|
|
1572
|
+
this.hub.emit('transaction-status-update', { transactionMeta });
|
|
1573
|
+
}
|
|
1574
|
+
getNonceTrackerPendingTransactions(address) {
|
|
1575
|
+
const standardPendingTransactions = this.getNonceTrackerTransactions(types_1.TransactionStatus.submitted, address);
|
|
1576
|
+
const externalPendingTransactions = this.getExternalPendingTransactions(address);
|
|
1577
|
+
return [...standardPendingTransactions, ...externalPendingTransactions];
|
|
1578
|
+
}
|
|
1579
|
+
getNonceTrackerTransactions(status, address) {
|
|
1580
|
+
const currentChainId = this.getChainId();
|
|
1581
|
+
return (0, nonce_1.getAndFormatTransactionsForNonceTracker)(currentChainId, address, status, this.state.transactions);
|
|
1582
|
+
}
|
|
1583
|
+
onConfirmedTransaction(transactionMeta) {
|
|
1584
|
+
(0, logger_1.projectLogger)('Processing confirmed transaction', transactionMeta.id);
|
|
1585
|
+
this.markNonceDuplicatesDropped(transactionMeta.id);
|
|
1586
|
+
this.hub.emit('transaction-confirmed', { transactionMeta });
|
|
1587
|
+
this.hub.emit(`${transactionMeta.id}:confirmed`, transactionMeta);
|
|
1588
|
+
this.onTransactionStatusChange(transactionMeta);
|
|
1589
|
+
// Intentional given potential duration of process.
|
|
1590
|
+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
1591
|
+
this.updatePostBalance(transactionMeta);
|
|
1592
|
+
}
|
|
1593
|
+
updatePostBalance(transactionMeta) {
|
|
1594
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1595
|
+
try {
|
|
1596
|
+
if (transactionMeta.type !== types_1.TransactionType.swap) {
|
|
1597
|
+
return;
|
|
1598
|
+
}
|
|
1599
|
+
const { updatedTransactionMeta, approvalTransactionMeta } = yield (0, swaps_1.updatePostTransactionBalance)(transactionMeta, {
|
|
1600
|
+
ethQuery: this.ethQuery,
|
|
1601
|
+
getTransaction: this.getTransaction.bind(this),
|
|
1602
|
+
updateTransaction: this.updateTransaction.bind(this),
|
|
1603
|
+
});
|
|
1604
|
+
this.hub.emit('post-transaction-balance-updated', {
|
|
1605
|
+
transactionMeta: updatedTransactionMeta,
|
|
1606
|
+
approvalTransactionMeta,
|
|
1607
|
+
});
|
|
1608
|
+
}
|
|
1609
|
+
catch (error) {
|
|
1610
|
+
/* istanbul ignore next */
|
|
1611
|
+
(0, logger_1.projectLogger)('Error while updating post transaction balance', error);
|
|
1612
|
+
}
|
|
1613
|
+
});
|
|
1614
|
+
}
|
|
1434
1615
|
}
|
|
1435
1616
|
exports.TransactionController = TransactionController;
|
|
1436
|
-
exports.default = TransactionController;
|
|
1437
1617
|
//# sourceMappingURL=TransactionController.js.map
|