@metamask/transaction-controller 11.0.0 → 13.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +33 -4
- package/dist/EtherscanRemoteTransactionSource.d.ts +1 -1
- package/dist/EtherscanRemoteTransactionSource.d.ts.map +1 -1
- package/dist/EtherscanRemoteTransactionSource.js +11 -11
- package/dist/EtherscanRemoteTransactionSource.js.map +1 -1
- package/dist/IncomingTransactionHelper.d.ts.map +1 -1
- package/dist/IncomingTransactionHelper.js +2 -7
- package/dist/IncomingTransactionHelper.js.map +1 -1
- package/dist/TransactionController.d.ts +13 -3
- package/dist/TransactionController.d.ts.map +1 -1
- package/dist/TransactionController.js +48 -39
- package/dist/TransactionController.js.map +1 -1
- package/dist/constants.d.ts +3 -19
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +15 -20
- package/dist/constants.js.map +1 -1
- package/dist/external-transactions.js +5 -5
- package/dist/external-transactions.js.map +1 -1
- package/dist/transaction-type.d.ts +14 -0
- package/dist/transaction-type.d.ts.map +1 -0
- package/dist/transaction-type.js +114 -0
- package/dist/transaction-type.js.map +1 -0
- package/dist/types.d.ts +128 -11
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +99 -1
- package/dist/types.js.map +1 -1
- package/dist/utils.d.ts +5 -15
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +16 -29
- package/dist/utils.js.map +1 -1
- package/package.json +13 -11
|
@@ -18,9 +18,9 @@ const tx_1 = require("@ethereumjs/tx");
|
|
|
18
18
|
const base_controller_1 = require("@metamask/base-controller");
|
|
19
19
|
const controller_utils_1 = require("@metamask/controller-utils");
|
|
20
20
|
const eth_query_1 = __importDefault(require("@metamask/eth-query"));
|
|
21
|
+
const rpc_errors_1 = require("@metamask/rpc-errors");
|
|
21
22
|
const async_mutex_1 = require("async-mutex");
|
|
22
23
|
const eth_method_registry_1 = __importDefault(require("eth-method-registry"));
|
|
23
|
-
const eth_rpc_errors_1 = require("eth-rpc-errors");
|
|
24
24
|
const ethereumjs_util_1 = require("ethereumjs-util");
|
|
25
25
|
const events_1 = require("events");
|
|
26
26
|
const lodash_1 = require("lodash");
|
|
@@ -30,6 +30,7 @@ const EtherscanRemoteTransactionSource_1 = require("./EtherscanRemoteTransaction
|
|
|
30
30
|
const external_transactions_1 = require("./external-transactions");
|
|
31
31
|
const history_1 = require("./history");
|
|
32
32
|
const IncomingTransactionHelper_1 = require("./IncomingTransactionHelper");
|
|
33
|
+
const transaction_type_1 = require("./transaction-type");
|
|
33
34
|
const types_1 = require("./types");
|
|
34
35
|
const utils_1 = require("./utils");
|
|
35
36
|
exports.HARDFORK = common_1.Hardfork.London;
|
|
@@ -56,6 +57,8 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
56
57
|
* @param options.blockTracker - The block tracker used to poll for new blocks data.
|
|
57
58
|
* @param options.disableHistory - Whether to disable storing history in transaction metadata.
|
|
58
59
|
* @param options.disableSendFlowHistory - Explicitly disable transaction metadata history.
|
|
60
|
+
* @param options.getCurrentAccountEIP1559Compatibility - Whether or not the account supports EIP-1559.
|
|
61
|
+
* @param options.getCurrentNetworkEIP1559Compatibility - Whether or not the network supports EIP-1559.
|
|
59
62
|
* @param options.getNetworkState - Gets the state of the network controller.
|
|
60
63
|
* @param options.getSelectedAddress - Gets the address of the currently selected account.
|
|
61
64
|
* @param options.incomingTransactions - Configuration options for incoming transaction support.
|
|
@@ -69,7 +72,7 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
69
72
|
* @param config - Initial options used to configure this controller.
|
|
70
73
|
* @param state - Initial state to set on this controller.
|
|
71
74
|
*/
|
|
72
|
-
constructor({ blockTracker, disableHistory, disableSendFlowHistory, getNetworkState, getSelectedAddress, incomingTransactions = {}, messenger, onNetworkStateChange, provider, }, config, state) {
|
|
75
|
+
constructor({ blockTracker, disableHistory, disableSendFlowHistory, getCurrentAccountEIP1559Compatibility, getCurrentNetworkEIP1559Compatibility, getNetworkState, getSelectedAddress, incomingTransactions = {}, messenger, onNetworkStateChange, provider, }, config, state) {
|
|
73
76
|
super(config, state);
|
|
74
77
|
this.mutex = new async_mutex_1.Mutex();
|
|
75
78
|
/**
|
|
@@ -97,6 +100,10 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
97
100
|
this.isSendFlowHistoryDisabled = disableSendFlowHistory !== null && disableSendFlowHistory !== void 0 ? disableSendFlowHistory : false;
|
|
98
101
|
this.isHistoryDisabled = disableHistory !== null && disableHistory !== void 0 ? disableHistory : false;
|
|
99
102
|
this.registry = new eth_method_registry_1.default({ provider });
|
|
103
|
+
this.getCurrentAccountEIP1559Compatibility =
|
|
104
|
+
getCurrentAccountEIP1559Compatibility;
|
|
105
|
+
this.getCurrentNetworkEIP1559Compatibility =
|
|
106
|
+
getCurrentNetworkEIP1559Compatibility;
|
|
100
107
|
this.nonceTracker = new nonce_tracker_1.default({
|
|
101
108
|
provider,
|
|
102
109
|
blockTracker,
|
|
@@ -190,15 +197,18 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
190
197
|
* @param opts.requireApproval - Whether the transaction requires approval by the user, defaults to true unless explicitly disabled.
|
|
191
198
|
* @param opts.securityAlertResponse - Response from security validator.
|
|
192
199
|
* @param opts.sendFlowHistory - The sendFlowHistory entries to add.
|
|
200
|
+
* @param opts.type - Type of transaction to add, such as 'cancel' or 'swap'.
|
|
193
201
|
* @returns Object containing a promise resolving to the transaction hash if approved.
|
|
194
202
|
*/
|
|
195
|
-
addTransaction(txParams, { actionId, deviceConfirmedOn, origin, requireApproval, securityAlertResponse, sendFlowHistory, } = {}) {
|
|
203
|
+
addTransaction(txParams, { actionId, deviceConfirmedOn, origin, requireApproval, securityAlertResponse, sendFlowHistory, type, } = {}) {
|
|
196
204
|
return __awaiter(this, void 0, void 0, function* () {
|
|
197
|
-
const
|
|
205
|
+
const chainId = this.getChainId();
|
|
198
206
|
const { transactions } = this.state;
|
|
199
207
|
txParams = (0, utils_1.normalizeTxParams)(txParams);
|
|
200
|
-
|
|
208
|
+
const isEIP1559Compatible = yield this.getEIP1559Compatibility();
|
|
209
|
+
(0, utils_1.validateTxParams)(txParams, isEIP1559Compatible);
|
|
201
210
|
const dappSuggestedGasFees = this.generateDappSuggestedGasFees(txParams, origin);
|
|
211
|
+
const transactionType = type !== null && type !== void 0 ? type : (yield (0, transaction_type_1.determineTransactionType)(txParams, this.ethQuery)).type;
|
|
202
212
|
const existingTransactionMeta = this.getTransactionWithActionId(actionId);
|
|
203
213
|
// If a request to add a transaction with the same actionId is submitted again, a new transaction will not be created for it.
|
|
204
214
|
const transactionMeta = existingTransactionMeta || {
|
|
@@ -208,7 +218,6 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
208
218
|
dappSuggestedGasFees,
|
|
209
219
|
deviceConfirmedOn,
|
|
210
220
|
id: (0, uuid_1.v1)(),
|
|
211
|
-
networkID: networkId !== null && networkId !== void 0 ? networkId : undefined,
|
|
212
221
|
origin,
|
|
213
222
|
securityAlertResponse,
|
|
214
223
|
status: types_1.TransactionStatus.unapproved,
|
|
@@ -216,6 +225,7 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
216
225
|
txParams,
|
|
217
226
|
userEditedGasLimit: false,
|
|
218
227
|
verifiedOnBlockchain: false,
|
|
228
|
+
type: transactionType,
|
|
219
229
|
};
|
|
220
230
|
try {
|
|
221
231
|
const { gas, estimateGasError } = yield this.estimateGas(txParams);
|
|
@@ -266,9 +276,9 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
266
276
|
* Creates approvals for all unapproved transactions persisted.
|
|
267
277
|
*/
|
|
268
278
|
initApprovals() {
|
|
269
|
-
const
|
|
279
|
+
const chainId = this.getChainId();
|
|
270
280
|
const unapprovedTxs = this.state.transactions.filter((transaction) => transaction.status === types_1.TransactionStatus.unapproved &&
|
|
271
|
-
|
|
281
|
+
transaction.chainId === chainId);
|
|
272
282
|
for (const txMeta of unapprovedTxs) {
|
|
273
283
|
this.processApproval(txMeta, {
|
|
274
284
|
shouldShowRequest: false,
|
|
@@ -406,7 +416,7 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
406
416
|
const rawTx = (0, ethereumjs_util_1.bufferToHex)(signedTx.serialize());
|
|
407
417
|
const hash = yield (0, controller_utils_1.query)(this.ethQuery, 'sendRawTransaction', [rawTx]);
|
|
408
418
|
const baseTransactionMeta = Object.assign(Object.assign({}, transactionMeta), { estimatedBaseFee, id: (0, uuid_1.v1)(), time: Date.now(), hash,
|
|
409
|
-
actionId, originalGasEstimate: transactionMeta.txParams.gas });
|
|
419
|
+
actionId, originalGasEstimate: transactionMeta.txParams.gas, type: types_1.TransactionType.retry });
|
|
410
420
|
const newTransactionMeta = newMaxFeePerGas && newMaxPriorityFeePerGas
|
|
411
421
|
? Object.assign(Object.assign({}, baseTransactionMeta), { txParams: Object.assign(Object.assign({}, transactionMeta.txParams), { maxFeePerGas: newMaxFeePerGas, maxPriorityFeePerGas: newMaxPriorityFeePerGas }) }) : Object.assign(Object.assign({}, baseTransactionMeta), { txParams: Object.assign(Object.assign({}, transactionMeta.txParams), { gasPrice: newGasPrice }) });
|
|
412
422
|
transactions.push(newTransactionMeta);
|
|
@@ -492,14 +502,10 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
492
502
|
queryTransactionStatuses() {
|
|
493
503
|
return __awaiter(this, void 0, void 0, function* () {
|
|
494
504
|
const { transactions } = this.state;
|
|
495
|
-
const
|
|
505
|
+
const currentChainId = this.getChainId();
|
|
496
506
|
let gotUpdates = false;
|
|
497
507
|
yield (0, controller_utils_1.safelyExecute)(() => Promise.all(transactions.map((meta, index) => __awaiter(this, void 0, void 0, function* () {
|
|
498
|
-
|
|
499
|
-
// Should be removed when networkID is completely removed.
|
|
500
|
-
const txBelongsToCurrentChain = meta.chainId === currentChainId ||
|
|
501
|
-
(!meta.chainId && meta.networkID === currentNetworkID);
|
|
502
|
-
if (!meta.verifiedOnBlockchain && txBelongsToCurrentChain) {
|
|
508
|
+
if (!meta.verifiedOnBlockchain && meta.chainId === currentChainId) {
|
|
503
509
|
const [reconciledTx, updateRequired] = yield this.blockchainTransactionStateReconciler(meta);
|
|
504
510
|
if (updateRequired) {
|
|
505
511
|
transactions[index] = reconciledTx;
|
|
@@ -546,13 +552,10 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
546
552
|
this.update({ transactions: [] });
|
|
547
553
|
return;
|
|
548
554
|
}
|
|
549
|
-
const
|
|
550
|
-
const newTransactions = this.state.transactions.filter(({
|
|
555
|
+
const currentChainId = this.getChainId();
|
|
556
|
+
const newTransactions = this.state.transactions.filter(({ chainId, txParams }) => {
|
|
551
557
|
var _a;
|
|
552
|
-
|
|
553
|
-
const isMatchingNetwork = ignoreNetwork ||
|
|
554
|
-
chainId === currentChainId ||
|
|
555
|
-
(!chainId && networkID === currentNetworkID);
|
|
558
|
+
const isMatchingNetwork = ignoreNetwork || chainId === currentChainId;
|
|
556
559
|
if (!isMatchingNetwork) {
|
|
557
560
|
return true;
|
|
558
561
|
}
|
|
@@ -697,9 +700,9 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
697
700
|
catch (error) {
|
|
698
701
|
const { isCompleted: isTxCompleted } = this.isTransactionCompleted(transactionId);
|
|
699
702
|
if (!isTxCompleted) {
|
|
700
|
-
if (error.code ===
|
|
703
|
+
if (error.code === rpc_errors_1.errorCodes.provider.userRejectedRequest) {
|
|
701
704
|
this.cancelTransaction(transactionId);
|
|
702
|
-
throw
|
|
705
|
+
throw rpc_errors_1.providerErrors.userRejectedRequest('User rejected the transaction');
|
|
703
706
|
}
|
|
704
707
|
else {
|
|
705
708
|
this.failTransaction(meta, error);
|
|
@@ -711,16 +714,16 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
711
714
|
switch (finalMeta === null || finalMeta === void 0 ? void 0 : finalMeta.status) {
|
|
712
715
|
case types_1.TransactionStatus.failed:
|
|
713
716
|
resultCallbacks === null || resultCallbacks === void 0 ? void 0 : resultCallbacks.error(finalMeta.error);
|
|
714
|
-
throw
|
|
717
|
+
throw rpc_errors_1.rpcErrors.internal(finalMeta.error.message);
|
|
715
718
|
case types_1.TransactionStatus.cancelled:
|
|
716
|
-
const cancelError =
|
|
719
|
+
const cancelError = rpc_errors_1.rpcErrors.internal('User cancelled the transaction');
|
|
717
720
|
resultCallbacks === null || resultCallbacks === void 0 ? void 0 : resultCallbacks.error(cancelError);
|
|
718
721
|
throw cancelError;
|
|
719
722
|
case types_1.TransactionStatus.submitted:
|
|
720
723
|
resultCallbacks === null || resultCallbacks === void 0 ? void 0 : resultCallbacks.success();
|
|
721
724
|
return finalMeta.hash;
|
|
722
725
|
default:
|
|
723
|
-
const internalError =
|
|
726
|
+
const internalError = rpc_errors_1.rpcErrors.internal(`MetaMask Tx Signature: Unknown problem: ${JSON.stringify(finalMeta || transactionId)}`);
|
|
724
727
|
resultCallbacks === null || resultCallbacks === void 0 ? void 0 : resultCallbacks.error(internalError);
|
|
725
728
|
throw internalError;
|
|
726
729
|
}
|
|
@@ -738,7 +741,7 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
738
741
|
return __awaiter(this, void 0, void 0, function* () {
|
|
739
742
|
const { transactions } = this.state;
|
|
740
743
|
const releaseLock = yield this.mutex.acquire();
|
|
741
|
-
const
|
|
744
|
+
const chainId = this.getChainId();
|
|
742
745
|
const index = transactions.findIndex(({ id }) => transactionId === id);
|
|
743
746
|
const transactionMeta = transactions[index];
|
|
744
747
|
const { txParams: { nonce, from }, } = transactionMeta;
|
|
@@ -837,9 +840,9 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
837
840
|
const txsToKeep = transactions
|
|
838
841
|
.sort((a, b) => (a.time > b.time ? -1 : 1)) // Descending time order
|
|
839
842
|
.filter((tx) => {
|
|
840
|
-
const { chainId,
|
|
843
|
+
const { chainId, status, txParams, time } = tx;
|
|
841
844
|
if (txParams) {
|
|
842
|
-
const key = `${txParams.nonce}-${
|
|
845
|
+
const key = `${txParams.nonce}-${(0, controller_utils_1.convertHexToDecimal)(chainId)}-${new Date(time).toDateString()}`;
|
|
843
846
|
if (nonceNetworkSet.has(key)) {
|
|
844
847
|
return true;
|
|
845
848
|
}
|
|
@@ -990,10 +993,9 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
990
993
|
const isCompleted = this.isLocalFinalState(transaction.status);
|
|
991
994
|
return { meta: transaction, isCompleted };
|
|
992
995
|
}
|
|
993
|
-
|
|
994
|
-
const {
|
|
995
|
-
|
|
996
|
-
return { networkId, chainId };
|
|
996
|
+
getChainId() {
|
|
997
|
+
const { providerConfig } = this.getNetworkState();
|
|
998
|
+
return providerConfig.chainId;
|
|
997
999
|
}
|
|
998
1000
|
prepareUnsignedEthTx(txParams) {
|
|
999
1001
|
return tx_1.TransactionFactory.fromTxData(txParams, {
|
|
@@ -1011,7 +1013,7 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
1011
1013
|
* @returns common configuration object
|
|
1012
1014
|
*/
|
|
1013
1015
|
getCommonConfiguration() {
|
|
1014
|
-
const {
|
|
1016
|
+
const { providerConfig: { type: chain, chainId, nickname: name }, } = this.getNetworkState();
|
|
1015
1017
|
if (chain !== controller_utils_1.RPC &&
|
|
1016
1018
|
chain !== controller_utils_1.NetworkType['linea-goerli'] &&
|
|
1017
1019
|
chain !== controller_utils_1.NetworkType['linea-mainnet']) {
|
|
@@ -1020,7 +1022,6 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
1020
1022
|
const customChainParams = {
|
|
1021
1023
|
name,
|
|
1022
1024
|
chainId: parseInt(chainId, 16),
|
|
1023
|
-
networkId: networkId === null ? NaN : parseInt(networkId, undefined),
|
|
1024
1025
|
defaultHardfork: exports.HARDFORK,
|
|
1025
1026
|
};
|
|
1026
1027
|
return common_1.Common.custom(customChainParams);
|
|
@@ -1075,11 +1076,11 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
1075
1076
|
addExternalTransaction(transactionMeta) {
|
|
1076
1077
|
var _a, _b;
|
|
1077
1078
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1078
|
-
const
|
|
1079
|
+
const chainId = this.getChainId();
|
|
1079
1080
|
const { transactions } = this.state;
|
|
1080
1081
|
const fromAddress = (_a = transactionMeta === null || transactionMeta === void 0 ? void 0 : transactionMeta.txParams) === null || _a === void 0 ? void 0 : _a.from;
|
|
1081
1082
|
const sameFromAndNetworkTransactions = transactions.filter((transaction) => transaction.txParams.from === fromAddress &&
|
|
1082
|
-
|
|
1083
|
+
transaction.chainId === chainId);
|
|
1083
1084
|
const confirmedTxs = sameFromAndNetworkTransactions.filter((transaction) => transaction.status === types_1.TransactionStatus.confirmed);
|
|
1084
1085
|
const pendingTxs = sameFromAndNetworkTransactions.filter((transaction) => transaction.status === types_1.TransactionStatus.submitted);
|
|
1085
1086
|
(0, external_transactions_1.validateConfirmedExternalTransaction)(transactionMeta, confirmedTxs, pendingTxs);
|
|
@@ -1103,13 +1104,13 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
1103
1104
|
*/
|
|
1104
1105
|
markNonceDuplicatesDropped(transactionId) {
|
|
1105
1106
|
var _a, _b;
|
|
1106
|
-
const
|
|
1107
|
+
const chainId = this.getChainId();
|
|
1107
1108
|
const transactionMeta = this.getTransaction(transactionId);
|
|
1108
1109
|
const nonce = (_a = transactionMeta === null || transactionMeta === void 0 ? void 0 : transactionMeta.txParams) === null || _a === void 0 ? void 0 : _a.nonce;
|
|
1109
1110
|
const from = (_b = transactionMeta === null || transactionMeta === void 0 ? void 0 : transactionMeta.txParams) === null || _b === void 0 ? void 0 : _b.from;
|
|
1110
1111
|
const sameNonceTxs = this.state.transactions.filter((transaction) => transaction.txParams.from === from &&
|
|
1111
1112
|
transaction.txParams.nonce === nonce &&
|
|
1112
|
-
|
|
1113
|
+
transaction.chainId === chainId);
|
|
1113
1114
|
if (!sameNonceTxs.length) {
|
|
1114
1115
|
return;
|
|
1115
1116
|
}
|
|
@@ -1173,6 +1174,14 @@ class TransactionController extends base_controller_1.BaseController {
|
|
|
1173
1174
|
}
|
|
1174
1175
|
});
|
|
1175
1176
|
}
|
|
1177
|
+
getEIP1559Compatibility() {
|
|
1178
|
+
var _a, _b;
|
|
1179
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1180
|
+
const currentNetworkIsEIP1559Compatible = yield this.getCurrentNetworkEIP1559Compatibility();
|
|
1181
|
+
const currentAccountIsEIP1559Compatible = (_b = (_a = this.getCurrentAccountEIP1559Compatibility) === null || _a === void 0 ? void 0 : _a.call(this)) !== null && _b !== void 0 ? _b : true;
|
|
1182
|
+
return (currentNetworkIsEIP1559Compatible && currentAccountIsEIP1559Compatible);
|
|
1183
|
+
});
|
|
1184
|
+
}
|
|
1176
1185
|
}
|
|
1177
1186
|
exports.TransactionController = TransactionController;
|
|
1178
1187
|
exports.default = TransactionController;
|