@metamask/transaction-controller 14.0.0 → 16.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.
Files changed (76) hide show
  1. package/CHANGELOG.md +14 -1
  2. package/dist/TransactionController.d.ts +22 -7
  3. package/dist/TransactionController.d.ts.map +1 -1
  4. package/dist/TransactionController.js +42 -80
  5. package/dist/TransactionController.js.map +1 -1
  6. package/dist/{EtherscanRemoteTransactionSource.d.ts → helpers/EtherscanRemoteTransactionSource.d.ts} +1 -1
  7. package/dist/helpers/EtherscanRemoteTransactionSource.d.ts.map +1 -0
  8. package/dist/{EtherscanRemoteTransactionSource.js → helpers/EtherscanRemoteTransactionSource.js} +4 -4
  9. package/dist/helpers/EtherscanRemoteTransactionSource.js.map +1 -0
  10. package/dist/{IncomingTransactionHelper.d.ts → helpers/IncomingTransactionHelper.d.ts} +1 -1
  11. package/dist/helpers/IncomingTransactionHelper.d.ts.map +1 -0
  12. package/dist/{IncomingTransactionHelper.js → helpers/IncomingTransactionHelper.js} +1 -1
  13. package/dist/helpers/IncomingTransactionHelper.js.map +1 -0
  14. package/dist/{PendingTransactionTracker.d.ts → helpers/PendingTransactionTracker.d.ts} +4 -2
  15. package/dist/helpers/PendingTransactionTracker.d.ts.map +1 -0
  16. package/dist/{PendingTransactionTracker.js → helpers/PendingTransactionTracker.js} +47 -17
  17. package/dist/helpers/PendingTransactionTracker.js.map +1 -0
  18. package/dist/index.d.ts +2 -2
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +1 -1
  21. package/dist/index.js.map +1 -1
  22. package/dist/types.d.ts +71 -2
  23. package/dist/types.d.ts.map +1 -1
  24. package/dist/types.js +36 -1
  25. package/dist/types.js.map +1 -1
  26. package/dist/utils/etherscan.d.ts.map +1 -0
  27. package/dist/{etherscan.js → utils/etherscan.js} +3 -4
  28. package/dist/utils/etherscan.js.map +1 -0
  29. package/dist/{external-transactions.d.ts → utils/external-transactions.d.ts} +1 -1
  30. package/dist/utils/external-transactions.d.ts.map +1 -0
  31. package/dist/{external-transactions.js → utils/external-transactions.js} +1 -1
  32. package/dist/utils/external-transactions.js.map +1 -0
  33. package/dist/utils/gas-fees.d.ts +30 -0
  34. package/dist/utils/gas-fees.d.ts.map +1 -0
  35. package/dist/utils/gas-fees.js +194 -0
  36. package/dist/utils/gas-fees.js.map +1 -0
  37. package/dist/utils/gas.d.ts +25 -0
  38. package/dist/utils/gas.d.ts.map +1 -0
  39. package/dist/utils/gas.js +125 -0
  40. package/dist/utils/gas.js.map +1 -0
  41. package/dist/{history.d.ts → utils/history.d.ts} +1 -1
  42. package/dist/utils/history.d.ts.map +1 -0
  43. package/dist/utils/history.js.map +1 -0
  44. package/dist/{transaction-type.d.ts → utils/transaction-type.d.ts} +1 -1
  45. package/dist/utils/transaction-type.d.ts.map +1 -0
  46. package/dist/{transaction-type.js → utils/transaction-type.js} +1 -1
  47. package/dist/utils/transaction-type.js.map +1 -0
  48. package/dist/{utils.d.ts → utils/utils.d.ts} +3 -3
  49. package/dist/utils/utils.d.ts.map +1 -0
  50. package/dist/{utils.js → utils/utils.js} +3 -3
  51. package/dist/utils/utils.js.map +1 -0
  52. package/dist/{validation.d.ts → utils/validation.d.ts} +1 -1
  53. package/dist/utils/validation.d.ts.map +1 -0
  54. package/dist/utils/validation.js.map +1 -0
  55. package/package.json +9 -7
  56. package/dist/EtherscanRemoteTransactionSource.d.ts.map +0 -1
  57. package/dist/EtherscanRemoteTransactionSource.js.map +0 -1
  58. package/dist/IncomingTransactionHelper.d.ts.map +0 -1
  59. package/dist/IncomingTransactionHelper.js.map +0 -1
  60. package/dist/PendingTransactionTracker.d.ts.map +0 -1
  61. package/dist/PendingTransactionTracker.js.map +0 -1
  62. package/dist/etherscan.d.ts.map +0 -1
  63. package/dist/etherscan.js.map +0 -1
  64. package/dist/external-transactions.d.ts.map +0 -1
  65. package/dist/external-transactions.js.map +0 -1
  66. package/dist/history.d.ts.map +0 -1
  67. package/dist/history.js.map +0 -1
  68. package/dist/transaction-type.d.ts.map +0 -1
  69. package/dist/transaction-type.js.map +0 -1
  70. package/dist/utils.d.ts.map +0 -1
  71. package/dist/utils.js.map +0 -1
  72. package/dist/validation.d.ts.map +0 -1
  73. package/dist/validation.js.map +0 -1
  74. /package/dist/{etherscan.d.ts → utils/etherscan.d.ts} +0 -0
  75. /package/dist/{history.js → utils/history.js} +0 -0
  76. /package/dist/{validation.js → utils/validation.js} +0 -0
@@ -0,0 +1,194 @@
1
+ "use strict";
2
+ /* eslint-disable jsdoc/require-jsdoc */
3
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
4
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
5
+ return new (P || (P = Promise))(function (resolve, reject) {
6
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
7
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
8
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
9
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
10
+ });
11
+ };
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.updateGasFees = void 0;
14
+ const controller_utils_1 = require("@metamask/controller-utils");
15
+ const gas_fee_controller_1 = require("@metamask/gas-fee-controller");
16
+ const utils_1 = require("@metamask/utils");
17
+ const ethereumjs_util_1 = require("ethereumjs-util");
18
+ const logger_1 = require("../logger");
19
+ const types_1 = require("../types");
20
+ const log = (0, utils_1.createModuleLogger)(logger_1.projectLogger, 'gas-fees');
21
+ function updateGasFees(request) {
22
+ return __awaiter(this, void 0, void 0, function* () {
23
+ const { txMeta } = request;
24
+ const initialParams = Object.assign({}, txMeta.txParams);
25
+ const suggestedGasFees = yield getSuggestedGasFees(request);
26
+ log('Suggested gas fees', suggestedGasFees);
27
+ const getGasFeeRequest = Object.assign(Object.assign({}, request), { initialParams, suggestedGasFees });
28
+ txMeta.txParams.maxFeePerGas = getMaxFeePerGas(getGasFeeRequest);
29
+ txMeta.txParams.maxPriorityFeePerGas =
30
+ getMaxPriorityFeePerGas(getGasFeeRequest);
31
+ txMeta.txParams.gasPrice = getGasPrice(getGasFeeRequest);
32
+ txMeta.userFeeLevel = getUserFeeLevel(getGasFeeRequest);
33
+ log('Updated gas fee properties', {
34
+ maxFeePerGas: txMeta.txParams.maxFeePerGas,
35
+ maxPriorityFeePerGas: txMeta.txParams.maxPriorityFeePerGas,
36
+ gasPrice: txMeta.txParams.gasPrice,
37
+ });
38
+ if (txMeta.txParams.maxFeePerGas || txMeta.txParams.maxPriorityFeePerGas) {
39
+ delete txMeta.txParams.gasPrice;
40
+ }
41
+ if (txMeta.txParams.gasPrice) {
42
+ delete txMeta.txParams.maxFeePerGas;
43
+ delete txMeta.txParams.maxPriorityFeePerGas;
44
+ }
45
+ updateDefaultGasEstimates(txMeta);
46
+ });
47
+ }
48
+ exports.updateGasFees = updateGasFees;
49
+ function getMaxFeePerGas(request) {
50
+ const { eip1559, initialParams, suggestedGasFees } = request;
51
+ if (!eip1559) {
52
+ return undefined;
53
+ }
54
+ if (initialParams.maxFeePerGas) {
55
+ log('Using maxFeePerGas from request', initialParams.maxFeePerGas);
56
+ return initialParams.maxFeePerGas;
57
+ }
58
+ if (initialParams.gasPrice && !initialParams.maxPriorityFeePerGas) {
59
+ log('Setting maxFeePerGas to gasPrice from request', initialParams.gasPrice);
60
+ return initialParams.gasPrice;
61
+ }
62
+ if (suggestedGasFees.maxFeePerGas) {
63
+ log('Using suggested maxFeePerGas', suggestedGasFees.maxFeePerGas);
64
+ return suggestedGasFees.maxFeePerGas;
65
+ }
66
+ if (suggestedGasFees.gasPrice) {
67
+ log('Setting maxFeePerGas to suggested gasPrice', suggestedGasFees.gasPrice);
68
+ return suggestedGasFees.gasPrice;
69
+ }
70
+ log('maxFeePerGas not set');
71
+ return undefined;
72
+ }
73
+ function getMaxPriorityFeePerGas(request) {
74
+ const { eip1559, initialParams, suggestedGasFees, txMeta } = request;
75
+ if (!eip1559) {
76
+ return undefined;
77
+ }
78
+ if (initialParams.maxPriorityFeePerGas) {
79
+ log('Using maxPriorityFeePerGas from request', initialParams.maxPriorityFeePerGas);
80
+ return initialParams.maxPriorityFeePerGas;
81
+ }
82
+ if (initialParams.gasPrice && !initialParams.maxFeePerGas) {
83
+ log('Setting maxPriorityFeePerGas to gasPrice from request', initialParams.gasPrice);
84
+ return initialParams.gasPrice;
85
+ }
86
+ if (suggestedGasFees.maxPriorityFeePerGas) {
87
+ log('Using suggested maxPriorityFeePerGas', suggestedGasFees.maxPriorityFeePerGas);
88
+ return suggestedGasFees.maxPriorityFeePerGas;
89
+ }
90
+ if (txMeta.txParams.maxFeePerGas) {
91
+ log('Setting maxPriorityFeePerGas to maxFeePerGas', txMeta.txParams.maxFeePerGas);
92
+ return txMeta.txParams.maxFeePerGas;
93
+ }
94
+ log('maxPriorityFeePerGas not set');
95
+ return undefined;
96
+ }
97
+ function getGasPrice(request) {
98
+ const { eip1559, initialParams, suggestedGasFees } = request;
99
+ if (eip1559) {
100
+ return undefined;
101
+ }
102
+ if (initialParams.gasPrice) {
103
+ log('Using gasPrice from request', initialParams.gasPrice);
104
+ return initialParams.gasPrice;
105
+ }
106
+ if (suggestedGasFees.gasPrice) {
107
+ log('Using suggested gasPrice', suggestedGasFees.gasPrice);
108
+ return suggestedGasFees.gasPrice;
109
+ }
110
+ log('gasPrice not set');
111
+ return undefined;
112
+ }
113
+ function getUserFeeLevel(request) {
114
+ const { eip1559, initialParams, suggestedGasFees, txMeta } = request;
115
+ if (!eip1559) {
116
+ return undefined;
117
+ }
118
+ if (!initialParams.maxFeePerGas &&
119
+ !initialParams.maxPriorityFeePerGas &&
120
+ initialParams.gasPrice) {
121
+ return txMeta.origin === controller_utils_1.ORIGIN_METAMASK
122
+ ? types_1.UserFeeLevel.CUSTOM
123
+ : types_1.UserFeeLevel.DAPP_SUGGESTED;
124
+ }
125
+ if (!initialParams.maxFeePerGas &&
126
+ !initialParams.maxPriorityFeePerGas &&
127
+ suggestedGasFees.maxFeePerGas &&
128
+ suggestedGasFees.maxPriorityFeePerGas) {
129
+ return types_1.UserFeeLevel.MEDIUM;
130
+ }
131
+ if (txMeta.origin === controller_utils_1.ORIGIN_METAMASK) {
132
+ return types_1.UserFeeLevel.MEDIUM;
133
+ }
134
+ return types_1.UserFeeLevel.DAPP_SUGGESTED;
135
+ }
136
+ function updateDefaultGasEstimates(txMeta) {
137
+ if (!txMeta.defaultGasEstimates) {
138
+ txMeta.defaultGasEstimates = {};
139
+ }
140
+ txMeta.defaultGasEstimates.maxFeePerGas = txMeta.txParams.maxFeePerGas;
141
+ txMeta.defaultGasEstimates.maxPriorityFeePerGas =
142
+ txMeta.txParams.maxPriorityFeePerGas;
143
+ txMeta.defaultGasEstimates.gasPrice = txMeta.txParams.gasPrice;
144
+ txMeta.defaultGasEstimates.estimateType = txMeta.userFeeLevel;
145
+ }
146
+ function getSuggestedGasFees(request) {
147
+ return __awaiter(this, void 0, void 0, function* () {
148
+ const { eip1559, ethQuery, getGasFeeEstimates, txMeta } = request;
149
+ if ((!eip1559 && txMeta.txParams.gasPrice) ||
150
+ (eip1559 &&
151
+ txMeta.txParams.maxFeePerGas &&
152
+ txMeta.txParams.maxPriorityFeePerGas)) {
153
+ return {};
154
+ }
155
+ try {
156
+ const { gasFeeEstimates, gasEstimateType } = yield getGasFeeEstimates();
157
+ if (eip1559 && gasEstimateType === gas_fee_controller_1.GAS_ESTIMATE_TYPES.FEE_MARKET) {
158
+ const { medium: { suggestedMaxPriorityFeePerGas, suggestedMaxFeePerGas } = {}, } = gasFeeEstimates;
159
+ if (suggestedMaxPriorityFeePerGas && suggestedMaxFeePerGas) {
160
+ return {
161
+ maxFeePerGas: gweiDecimalToWeiHex(suggestedMaxFeePerGas),
162
+ maxPriorityFeePerGas: gweiDecimalToWeiHex(suggestedMaxPriorityFeePerGas),
163
+ };
164
+ }
165
+ }
166
+ if (gasEstimateType === gas_fee_controller_1.GAS_ESTIMATE_TYPES.LEGACY) {
167
+ // The LEGACY type includes low, medium and high estimates of
168
+ // gas price values.
169
+ return {
170
+ gasPrice: gweiDecimalToWeiHex(gasFeeEstimates.medium),
171
+ };
172
+ }
173
+ if (gasEstimateType === gas_fee_controller_1.GAS_ESTIMATE_TYPES.ETH_GASPRICE) {
174
+ // The ETH_GASPRICE type just includes a single gas price property,
175
+ // which we can assume was retrieved from eth_gasPrice
176
+ return {
177
+ gasPrice: gweiDecimalToWeiHex(gasFeeEstimates.gasPrice),
178
+ };
179
+ }
180
+ }
181
+ catch (error) {
182
+ log('Failed to get suggested gas fees', error);
183
+ }
184
+ const gasPriceDecimal = (yield (0, controller_utils_1.query)(ethQuery, 'gasPrice'));
185
+ const gasPrice = gasPriceDecimal
186
+ ? (0, ethereumjs_util_1.addHexPrefix)(gasPriceDecimal.toString(16))
187
+ : undefined;
188
+ return { gasPrice };
189
+ });
190
+ }
191
+ function gweiDecimalToWeiHex(value) {
192
+ return (0, controller_utils_1.toHex)((0, controller_utils_1.gweiDecToWEIBN)(value));
193
+ }
194
+ //# sourceMappingURL=gas-fees.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gas-fees.js","sourceRoot":"","sources":["../../src/utils/gas-fees.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable jsdoc/require-jsdoc */\n\nimport {\n ORIGIN_METAMASK,\n gweiDecToWEIBN,\n query,\n toHex,\n} from '@metamask/controller-utils';\nimport type EthQuery from '@metamask/eth-query';\nimport type { GasFeeState } from '@metamask/gas-fee-controller';\nimport { GAS_ESTIMATE_TYPES } from '@metamask/gas-fee-controller';\nimport { createModuleLogger } from '@metamask/utils';\nimport { addHexPrefix } from 'ethereumjs-util';\n\nimport { projectLogger } from '../logger';\nimport type { TransactionParams } from '../types';\nimport { UserFeeLevel, type TransactionMeta } from '../types';\n\nexport type UpdateGasFeesRequest = {\n eip1559: boolean;\n ethQuery: EthQuery;\n getGasFeeEstimates: () => Promise<GasFeeState>;\n txMeta: TransactionMeta;\n};\n\nexport type GetGasFeeRequest = UpdateGasFeesRequest & {\n initialParams: TransactionParams;\n suggestedGasFees: Awaited<ReturnType<typeof getSuggestedGasFees>>;\n};\n\nconst log = createModuleLogger(projectLogger, 'gas-fees');\n\nexport async function updateGasFees(request: UpdateGasFeesRequest) {\n const { txMeta } = request;\n const initialParams = { ...txMeta.txParams };\n\n const suggestedGasFees = await getSuggestedGasFees(request);\n\n log('Suggested gas fees', suggestedGasFees);\n\n const getGasFeeRequest = { ...request, initialParams, suggestedGasFees };\n\n txMeta.txParams.maxFeePerGas = getMaxFeePerGas(getGasFeeRequest);\n\n txMeta.txParams.maxPriorityFeePerGas =\n getMaxPriorityFeePerGas(getGasFeeRequest);\n\n txMeta.txParams.gasPrice = getGasPrice(getGasFeeRequest);\n txMeta.userFeeLevel = getUserFeeLevel(getGasFeeRequest);\n\n log('Updated gas fee properties', {\n maxFeePerGas: txMeta.txParams.maxFeePerGas,\n maxPriorityFeePerGas: txMeta.txParams.maxPriorityFeePerGas,\n gasPrice: txMeta.txParams.gasPrice,\n });\n\n if (txMeta.txParams.maxFeePerGas || txMeta.txParams.maxPriorityFeePerGas) {\n delete txMeta.txParams.gasPrice;\n }\n\n if (txMeta.txParams.gasPrice) {\n delete txMeta.txParams.maxFeePerGas;\n delete txMeta.txParams.maxPriorityFeePerGas;\n }\n\n updateDefaultGasEstimates(txMeta);\n}\n\nfunction getMaxFeePerGas(request: GetGasFeeRequest): string | undefined {\n const { eip1559, initialParams, suggestedGasFees } = request;\n\n if (!eip1559) {\n return undefined;\n }\n\n if (initialParams.maxFeePerGas) {\n log('Using maxFeePerGas from request', initialParams.maxFeePerGas);\n return initialParams.maxFeePerGas;\n }\n\n if (initialParams.gasPrice && !initialParams.maxPriorityFeePerGas) {\n log(\n 'Setting maxFeePerGas to gasPrice from request',\n initialParams.gasPrice,\n );\n return initialParams.gasPrice;\n }\n\n if (suggestedGasFees.maxFeePerGas) {\n log('Using suggested maxFeePerGas', suggestedGasFees.maxFeePerGas);\n return suggestedGasFees.maxFeePerGas;\n }\n\n if (suggestedGasFees.gasPrice) {\n log(\n 'Setting maxFeePerGas to suggested gasPrice',\n suggestedGasFees.gasPrice,\n );\n return suggestedGasFees.gasPrice;\n }\n\n log('maxFeePerGas not set');\n return undefined;\n}\n\nfunction getMaxPriorityFeePerGas(\n request: GetGasFeeRequest,\n): string | undefined {\n const { eip1559, initialParams, suggestedGasFees, txMeta } = request;\n\n if (!eip1559) {\n return undefined;\n }\n\n if (initialParams.maxPriorityFeePerGas) {\n log(\n 'Using maxPriorityFeePerGas from request',\n initialParams.maxPriorityFeePerGas,\n );\n return initialParams.maxPriorityFeePerGas;\n }\n\n if (initialParams.gasPrice && !initialParams.maxFeePerGas) {\n log(\n 'Setting maxPriorityFeePerGas to gasPrice from request',\n initialParams.gasPrice,\n );\n return initialParams.gasPrice;\n }\n\n if (suggestedGasFees.maxPriorityFeePerGas) {\n log(\n 'Using suggested maxPriorityFeePerGas',\n suggestedGasFees.maxPriorityFeePerGas,\n );\n return suggestedGasFees.maxPriorityFeePerGas;\n }\n\n if (txMeta.txParams.maxFeePerGas) {\n log(\n 'Setting maxPriorityFeePerGas to maxFeePerGas',\n txMeta.txParams.maxFeePerGas,\n );\n return txMeta.txParams.maxFeePerGas;\n }\n\n log('maxPriorityFeePerGas not set');\n return undefined;\n}\n\nfunction getGasPrice(request: GetGasFeeRequest): string | undefined {\n const { eip1559, initialParams, suggestedGasFees } = request;\n\n if (eip1559) {\n return undefined;\n }\n\n if (initialParams.gasPrice) {\n log('Using gasPrice from request', initialParams.gasPrice);\n return initialParams.gasPrice;\n }\n\n if (suggestedGasFees.gasPrice) {\n log('Using suggested gasPrice', suggestedGasFees.gasPrice);\n return suggestedGasFees.gasPrice;\n }\n\n log('gasPrice not set');\n return undefined;\n}\n\nfunction getUserFeeLevel(request: GetGasFeeRequest): UserFeeLevel | undefined {\n const { eip1559, initialParams, suggestedGasFees, txMeta } = request;\n\n if (!eip1559) {\n return undefined;\n }\n\n if (\n !initialParams.maxFeePerGas &&\n !initialParams.maxPriorityFeePerGas &&\n initialParams.gasPrice\n ) {\n return txMeta.origin === ORIGIN_METAMASK\n ? UserFeeLevel.CUSTOM\n : UserFeeLevel.DAPP_SUGGESTED;\n }\n\n if (\n !initialParams.maxFeePerGas &&\n !initialParams.maxPriorityFeePerGas &&\n suggestedGasFees.maxFeePerGas &&\n suggestedGasFees.maxPriorityFeePerGas\n ) {\n return UserFeeLevel.MEDIUM;\n }\n\n if (txMeta.origin === ORIGIN_METAMASK) {\n return UserFeeLevel.MEDIUM;\n }\n\n return UserFeeLevel.DAPP_SUGGESTED;\n}\n\nfunction updateDefaultGasEstimates(txMeta: TransactionMeta) {\n if (!txMeta.defaultGasEstimates) {\n txMeta.defaultGasEstimates = {};\n }\n\n txMeta.defaultGasEstimates.maxFeePerGas = txMeta.txParams.maxFeePerGas;\n\n txMeta.defaultGasEstimates.maxPriorityFeePerGas =\n txMeta.txParams.maxPriorityFeePerGas;\n\n txMeta.defaultGasEstimates.gasPrice = txMeta.txParams.gasPrice;\n txMeta.defaultGasEstimates.estimateType = txMeta.userFeeLevel;\n}\n\nasync function getSuggestedGasFees(request: UpdateGasFeesRequest) {\n const { eip1559, ethQuery, getGasFeeEstimates, txMeta } = request;\n\n if (\n (!eip1559 && txMeta.txParams.gasPrice) ||\n (eip1559 &&\n txMeta.txParams.maxFeePerGas &&\n txMeta.txParams.maxPriorityFeePerGas)\n ) {\n return {};\n }\n\n try {\n const { gasFeeEstimates, gasEstimateType } = await getGasFeeEstimates();\n\n if (eip1559 && gasEstimateType === GAS_ESTIMATE_TYPES.FEE_MARKET) {\n const {\n medium: { suggestedMaxPriorityFeePerGas, suggestedMaxFeePerGas } = {},\n } = gasFeeEstimates;\n\n if (suggestedMaxPriorityFeePerGas && suggestedMaxFeePerGas) {\n return {\n maxFeePerGas: gweiDecimalToWeiHex(suggestedMaxFeePerGas),\n maxPriorityFeePerGas: gweiDecimalToWeiHex(\n suggestedMaxPriorityFeePerGas,\n ),\n };\n }\n }\n\n if (gasEstimateType === GAS_ESTIMATE_TYPES.LEGACY) {\n // The LEGACY type includes low, medium and high estimates of\n // gas price values.\n return {\n gasPrice: gweiDecimalToWeiHex(gasFeeEstimates.medium),\n };\n }\n\n if (gasEstimateType === GAS_ESTIMATE_TYPES.ETH_GASPRICE) {\n // The ETH_GASPRICE type just includes a single gas price property,\n // which we can assume was retrieved from eth_gasPrice\n return {\n gasPrice: gweiDecimalToWeiHex(gasFeeEstimates.gasPrice),\n };\n }\n } catch (error) {\n log('Failed to get suggested gas fees', error);\n }\n\n const gasPriceDecimal = (await query(ethQuery, 'gasPrice')) as number;\n\n const gasPrice = gasPriceDecimal\n ? addHexPrefix(gasPriceDecimal.toString(16))\n : undefined;\n\n return { gasPrice };\n}\n\nfunction gweiDecimalToWeiHex(value: string) {\n return toHex(gweiDecToWEIBN(value));\n}\n"]}
@@ -0,0 +1,25 @@
1
+ /// <reference types="debug" />
2
+ import type EthQuery from '@metamask/eth-query';
3
+ import type { ProviderConfig } from '@metamask/network-controller';
4
+ import type { TransactionMeta, TransactionParams } from '../types';
5
+ export declare type UpdateGasRequest = {
6
+ ethQuery: EthQuery;
7
+ providerConfig: ProviderConfig;
8
+ txMeta: TransactionMeta;
9
+ };
10
+ export declare const log: import("debug").Debugger;
11
+ export declare const FIXED_GAS = "0x5208";
12
+ export declare function updateGas(request: UpdateGasRequest): Promise<void>;
13
+ export declare function estimateGas(txParams: TransactionParams, ethQuery: EthQuery): Promise<{
14
+ blockGasLimit: string;
15
+ estimatedGas: string;
16
+ simulationFails: {
17
+ reason: any;
18
+ errorKey: any;
19
+ debug: {
20
+ blockNumber: string;
21
+ blockGasLimit: string;
22
+ };
23
+ } | undefined;
24
+ }>;
25
+ //# sourceMappingURL=gas.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gas.d.ts","sourceRoot":"","sources":["../../src/utils/gas.ts"],"names":[],"mappings":";AASA,OAAO,KAAK,QAAQ,MAAM,qBAAqB,CAAC;AAChD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAKnE,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAEnE,oBAAY,gBAAgB,GAAG;IAC7B,QAAQ,EAAE,QAAQ,CAAC;IACnB,cAAc,EAAE,cAAc,CAAC;IAC/B,MAAM,EAAE,eAAe,CAAC;CACzB,CAAC;AAEF,eAAO,MAAM,GAAG,0BAA2C,CAAC;AAE5D,eAAO,MAAM,SAAS,WAAW,CAAC;AAElC,wBAAsB,SAAS,CAAC,OAAO,EAAE,gBAAgB,iBAkBxD;AAED,wBAAsB,WAAW,CAC/B,QAAQ,EAAE,iBAAiB,EAC3B,QAAQ,EAAE,QAAQ;;;;;;;;;;;GAsCnB"}
@@ -0,0 +1,125 @@
1
+ "use strict";
2
+ /* eslint-disable jsdoc/require-jsdoc */
3
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
4
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
5
+ return new (P || (P = Promise))(function (resolve, reject) {
6
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
7
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
8
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
9
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
10
+ });
11
+ };
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.estimateGas = exports.updateGas = exports.FIXED_GAS = exports.log = void 0;
14
+ const controller_utils_1 = require("@metamask/controller-utils");
15
+ const utils_1 = require("@metamask/utils");
16
+ const ethereumjs_util_1 = require("ethereumjs-util");
17
+ const logger_1 = require("../logger");
18
+ exports.log = (0, utils_1.createModuleLogger)(logger_1.projectLogger, 'gas');
19
+ exports.FIXED_GAS = '0x5208';
20
+ function updateGas(request) {
21
+ return __awaiter(this, void 0, void 0, function* () {
22
+ const { txMeta } = request;
23
+ const initialParams = Object.assign({}, txMeta.txParams);
24
+ const [gas, simulationFails] = yield getGas(request);
25
+ txMeta.txParams.gas = gas;
26
+ txMeta.simulationFails = simulationFails;
27
+ if (!initialParams.gas) {
28
+ txMeta.originalGasEstimate = txMeta.txParams.gas;
29
+ }
30
+ if (!txMeta.defaultGasEstimates) {
31
+ txMeta.defaultGasEstimates = {};
32
+ }
33
+ txMeta.defaultGasEstimates.gas = txMeta.txParams.gas;
34
+ });
35
+ }
36
+ exports.updateGas = updateGas;
37
+ function estimateGas(txParams, ethQuery) {
38
+ return __awaiter(this, void 0, void 0, function* () {
39
+ const request = Object.assign({}, txParams);
40
+ const { data, value } = request;
41
+ const { gasLimit: gasLimitHex, number: blockNumber } = yield getLatestBlock(ethQuery);
42
+ const gasLimitBN = (0, controller_utils_1.hexToBN)(gasLimitHex);
43
+ request.data = data ? (0, ethereumjs_util_1.addHexPrefix)(data) : data;
44
+ request.gas = (0, controller_utils_1.BNToHex)((0, controller_utils_1.fractionBN)(gasLimitBN, 19, 20));
45
+ request.value = value || '0x0';
46
+ let estimatedGas = request.gas;
47
+ let simulationFails;
48
+ try {
49
+ estimatedGas = yield (0, controller_utils_1.query)(ethQuery, 'estimateGas', [request]);
50
+ }
51
+ catch (error) {
52
+ simulationFails = {
53
+ reason: error.message,
54
+ errorKey: error.errorKey,
55
+ debug: {
56
+ blockNumber,
57
+ blockGasLimit: gasLimitHex,
58
+ },
59
+ };
60
+ (0, exports.log)('Estimation failed', Object.assign(Object.assign({}, simulationFails), { fallback: estimateGas }));
61
+ }
62
+ return {
63
+ blockGasLimit: gasLimitHex,
64
+ estimatedGas,
65
+ simulationFails,
66
+ };
67
+ });
68
+ }
69
+ exports.estimateGas = estimateGas;
70
+ function getGas(request) {
71
+ return __awaiter(this, void 0, void 0, function* () {
72
+ const { providerConfig, txMeta } = request;
73
+ if (txMeta.txParams.gas) {
74
+ (0, exports.log)('Using value from request', txMeta.txParams.gas);
75
+ return [txMeta.txParams.gas];
76
+ }
77
+ if (yield requiresFixedGas(request)) {
78
+ (0, exports.log)('Using fixed value', exports.FIXED_GAS);
79
+ return [exports.FIXED_GAS];
80
+ }
81
+ const { blockGasLimit, estimatedGas, simulationFails } = yield estimateGas(txMeta.txParams, request.ethQuery);
82
+ const estimatedGasBN = (0, controller_utils_1.hexToBN)(estimatedGas);
83
+ const maxGasBN = (0, controller_utils_1.hexToBN)(blockGasLimit).muln(0.9);
84
+ const paddedGasBN = estimatedGasBN.muln(1.5);
85
+ const isCustomNetwork = providerConfig.type === controller_utils_1.NetworkType.rpc;
86
+ if (estimatedGasBN.gt(maxGasBN) || isCustomNetwork) {
87
+ const estimatedGasHex = (0, ethereumjs_util_1.addHexPrefix)(estimatedGas);
88
+ (0, exports.log)('Using estimated value', estimatedGasHex);
89
+ return [estimatedGasHex, simulationFails];
90
+ }
91
+ if (paddedGasBN.lt(maxGasBN)) {
92
+ const paddedHex = (0, ethereumjs_util_1.addHexPrefix)((0, controller_utils_1.BNToHex)(paddedGasBN));
93
+ (0, exports.log)('Using 150% of estimated value', paddedHex);
94
+ return [paddedHex, simulationFails];
95
+ }
96
+ const maxHex = (0, ethereumjs_util_1.addHexPrefix)((0, controller_utils_1.BNToHex)(maxGasBN));
97
+ (0, exports.log)('Using 90% of block gas limit', maxHex);
98
+ return [maxHex, simulationFails];
99
+ });
100
+ }
101
+ function requiresFixedGas({ ethQuery, txMeta, providerConfig, }) {
102
+ return __awaiter(this, void 0, void 0, function* () {
103
+ const isCustomNetwork = providerConfig.type === controller_utils_1.NetworkType.rpc;
104
+ const { txParams: { to, data }, } = txMeta;
105
+ if (isCustomNetwork) {
106
+ return false;
107
+ }
108
+ if (!to) {
109
+ return true;
110
+ }
111
+ const code = yield getCode(ethQuery, to);
112
+ return !data && (!code || code === '0x');
113
+ });
114
+ }
115
+ function getCode(ethQuery, address) {
116
+ return __awaiter(this, void 0, void 0, function* () {
117
+ return yield (0, controller_utils_1.query)(ethQuery, 'getCode', [address]);
118
+ });
119
+ }
120
+ function getLatestBlock(ethQuery) {
121
+ return __awaiter(this, void 0, void 0, function* () {
122
+ return yield (0, controller_utils_1.query)(ethQuery, 'getBlockByNumber', ['latest', false]);
123
+ });
124
+ }
125
+ //# sourceMappingURL=gas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gas.js","sourceRoot":"","sources":["../../src/utils/gas.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable jsdoc/require-jsdoc */\n\nimport {\n BNToHex,\n NetworkType,\n fractionBN,\n hexToBN,\n query,\n} from '@metamask/controller-utils';\nimport type EthQuery from '@metamask/eth-query';\nimport type { ProviderConfig } from '@metamask/network-controller';\nimport { createModuleLogger } from '@metamask/utils';\nimport { addHexPrefix } from 'ethereumjs-util';\n\nimport { projectLogger } from '../logger';\nimport type { TransactionMeta, TransactionParams } from '../types';\n\nexport type UpdateGasRequest = {\n ethQuery: EthQuery;\n providerConfig: ProviderConfig;\n txMeta: TransactionMeta;\n};\n\nexport const log = createModuleLogger(projectLogger, 'gas');\n\nexport const FIXED_GAS = '0x5208';\n\nexport async function updateGas(request: UpdateGasRequest) {\n const { txMeta } = request;\n const initialParams = { ...txMeta.txParams };\n\n const [gas, simulationFails] = await getGas(request);\n\n txMeta.txParams.gas = gas;\n txMeta.simulationFails = simulationFails;\n\n if (!initialParams.gas) {\n txMeta.originalGasEstimate = txMeta.txParams.gas;\n }\n\n if (!txMeta.defaultGasEstimates) {\n txMeta.defaultGasEstimates = {};\n }\n\n txMeta.defaultGasEstimates.gas = txMeta.txParams.gas;\n}\n\nexport async function estimateGas(\n txParams: TransactionParams,\n ethQuery: EthQuery,\n) {\n const request = { ...txParams };\n const { data, value } = request;\n\n const { gasLimit: gasLimitHex, number: blockNumber } = await getLatestBlock(\n ethQuery,\n );\n\n const gasLimitBN = hexToBN(gasLimitHex);\n\n request.data = data ? addHexPrefix(data) : data;\n request.gas = BNToHex(fractionBN(gasLimitBN, 19, 20));\n request.value = value || '0x0';\n\n let estimatedGas = request.gas;\n let simulationFails;\n\n try {\n estimatedGas = await query(ethQuery, 'estimateGas', [request]);\n } catch (error: any) {\n simulationFails = {\n reason: error.message,\n errorKey: error.errorKey,\n debug: {\n blockNumber,\n blockGasLimit: gasLimitHex,\n },\n };\n\n log('Estimation failed', { ...simulationFails, fallback: estimateGas });\n }\n\n return {\n blockGasLimit: gasLimitHex,\n estimatedGas,\n simulationFails,\n };\n}\n\nasync function getGas(\n request: UpdateGasRequest,\n): Promise<[string, TransactionMeta['simulationFails']?]> {\n const { providerConfig, txMeta } = request;\n\n if (txMeta.txParams.gas) {\n log('Using value from request', txMeta.txParams.gas);\n return [txMeta.txParams.gas];\n }\n\n if (await requiresFixedGas(request)) {\n log('Using fixed value', FIXED_GAS);\n return [FIXED_GAS];\n }\n\n const { blockGasLimit, estimatedGas, simulationFails } = await estimateGas(\n txMeta.txParams,\n request.ethQuery,\n );\n\n const estimatedGasBN = hexToBN(estimatedGas);\n const maxGasBN = hexToBN(blockGasLimit).muln(0.9);\n const paddedGasBN = estimatedGasBN.muln(1.5);\n const isCustomNetwork = providerConfig.type === NetworkType.rpc;\n\n if (estimatedGasBN.gt(maxGasBN) || isCustomNetwork) {\n const estimatedGasHex = addHexPrefix(estimatedGas);\n log('Using estimated value', estimatedGasHex);\n return [estimatedGasHex, simulationFails];\n }\n\n if (paddedGasBN.lt(maxGasBN)) {\n const paddedHex = addHexPrefix(BNToHex(paddedGasBN));\n log('Using 150% of estimated value', paddedHex);\n return [paddedHex, simulationFails];\n }\n\n const maxHex = addHexPrefix(BNToHex(maxGasBN));\n log('Using 90% of block gas limit', maxHex);\n return [maxHex, simulationFails];\n}\n\nasync function requiresFixedGas({\n ethQuery,\n txMeta,\n providerConfig,\n}: UpdateGasRequest): Promise<boolean> {\n const isCustomNetwork = providerConfig.type === NetworkType.rpc;\n\n const {\n txParams: { to, data },\n } = txMeta;\n\n if (isCustomNetwork) {\n return false;\n }\n\n if (!to) {\n return true;\n }\n\n const code = await getCode(ethQuery, to);\n\n return !data && (!code || code === '0x');\n}\n\nasync function getCode(\n ethQuery: EthQuery,\n address: string,\n): Promise<string | undefined> {\n return await query(ethQuery, 'getCode', [address]);\n}\n\nasync function getLatestBlock(\n ethQuery: EthQuery,\n): Promise<{ gasLimit: string; number: string }> {\n return await query(ethQuery, 'getBlockByNumber', ['latest', false]);\n}\n"]}
@@ -1,4 +1,4 @@
1
- import type { TransactionMeta } from './types';
1
+ import type { TransactionMeta } from '../types';
2
2
  /**
3
3
  * Add initial history snapshot to the provided transactionMeta history.
4
4
  *
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../../src/utils/history.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAGV,eAAe,EAChB,MAAM,UAAU,CAAC;AAElB;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,eAAe,EAAE,eAAe,QAGzE;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,eAAe,EAAE,eAAe,EAChC,IAAI,EAAE,MAAM,GACX,IAAI,CAWN"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history.js","sourceRoot":"","sources":["../../src/utils/history.ts"],"names":[],"mappings":";;;;;;AAAA,sEAAyC;AACzC,mCAAmC;AAQnC;;;;GAIG;AACH,SAAgB,yBAAyB,CAAC,eAAgC;IACxE,MAAM,QAAQ,GAAG,2BAA2B,CAAC,eAAe,CAAC,CAAC;IAC9D,eAAe,CAAC,OAAO,GAAG,CAAC,QAAQ,CAAC,CAAC;AACvC,CAAC;AAHD,8DAGC;AAED;;;;;GAKG;AACH,SAAgB,wBAAwB,CACtC,eAAgC,EAChC,IAAY;;IAEZ,MAAM,YAAY,GAAG,2BAA2B,CAAC,eAAe,CAAC,CAAC;IAClE,MAAM,aAAa,GAAG,aAAa,CACjC,eAAe,CAAC,OAA6B,CAC9C,CAAC;IAEF,MAAM,YAAY,GAAG,oBAAoB,CAAC,aAAa,EAAE,YAAY,EAAE,IAAI,CAAC,CAAC;IAE7E,IAAI,YAAY,CAAC,MAAM,EAAE;QACvB,MAAA,eAAe,aAAf,eAAe,uBAAf,eAAe,CAAE,OAAO,0CAAE,IAAI,CAAC,YAAY,CAAC,CAAC;KAC9C;AACH,CAAC;AAdD,4DAcC;AAED;;;;;;;GAOG;AACH,SAAS,oBAAoB,CAC3B,aAAkB,EAClB,YAA6B,EAC7B,IAAY;IAEZ,MAAM,sBAAsB,GAAG,yBAAU,CAAC,OAAO,CAC/C,aAAa,EACb,YAAY,CACc,CAAC;IAC7B,kFAAkF;IAClF,IAAI,sBAAsB,CAAC,CAAC,CAAC,EAAE;QAC7B,IAAI,IAAI,EAAE;YACR,sBAAsB,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,IAAI,CAAC;SACvC;QACD,sBAAsB,CAAC,CAAC,CAAC,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;KAClD;IACD,OAAO,sBAAsB,CAAC;AAChC,CAAC;AAED;;;;;GAKG;AACH,SAAS,aAAa,CACpB,kBAAsC;IAEtC,MAAM,YAAY,GAAG,IAAA,kBAAS,EAAC,kBAAkB,CAAC,CAAC;IACnD,OAAO,YAAY,CAAC,MAAM,CACxB,CAAC,GAAG,EAAE,KAAU,EAAE,EAAE,CAAC,yBAAU,CAAC,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,WAAW,CAChD,CAAC;AACvB,CAAC;AAED;;;;;GAKG;AACH,SAAS,2BAA2B,CAClC,eAAgC;IAEhC,MAAM,QAAQ,qBAAQ,eAAe,CAAE,CAAC;IACxC,OAAO,QAAQ,CAAC,OAAO,CAAC;IACxB,OAAO,IAAA,kBAAS,EAAC,QAAQ,CAAC,CAAC;AAC7B,CAAC","sourcesContent":["import jsonDiffer from 'fast-json-patch';\nimport { cloneDeep } from 'lodash';\n\nimport type {\n TransactionHistory,\n TransactionHistoryEntry,\n TransactionMeta,\n} from '../types';\n\n/**\n * Add initial history snapshot to the provided transactionMeta history.\n *\n * @param transactionMeta - TransactionMeta to add initial history snapshot to.\n */\nexport function addInitialHistorySnapshot(transactionMeta: TransactionMeta) {\n const snapshot = snapshotFromTransactionMeta(transactionMeta);\n transactionMeta.history = [snapshot];\n}\n\n/**\n * Compares and adds history entry to the provided transactionMeta history.\n *\n * @param transactionMeta - TransactionMeta to add history entry to.\n * @param note - Note to add to history entry.\n */\nexport function updateTransactionHistory(\n transactionMeta: TransactionMeta,\n note: string,\n): void {\n const currentState = snapshotFromTransactionMeta(transactionMeta);\n const previousState = replayHistory(\n transactionMeta.history as TransactionHistory,\n );\n\n const historyEntry = generateHistoryEntry(previousState, currentState, note);\n\n if (historyEntry.length) {\n transactionMeta?.history?.push(historyEntry);\n }\n}\n\n/**\n * Generates a history entry from the previous and new transaction metadata.\n *\n * @param previousState - The previous transaction metadata.\n * @param currentState - The new transaction metadata.\n * @param note - A note for the transaction metada update.\n * @returns An array of history operation.\n */\nfunction generateHistoryEntry(\n previousState: any,\n currentState: TransactionMeta,\n note: string,\n): TransactionHistoryEntry {\n const historyOperationsEntry = jsonDiffer.compare(\n previousState,\n currentState,\n ) as TransactionHistoryEntry;\n // Add a note to the first operation, since it breaks if we append it to the entry\n if (historyOperationsEntry[0]) {\n if (note) {\n historyOperationsEntry[0].note = note;\n }\n historyOperationsEntry[0].timestamp = Date.now();\n }\n return historyOperationsEntry;\n}\n\n/**\n * Recovers previous transactionMeta from passed history array.\n *\n * @param transactionHistory - The transaction metadata to replay.\n * @returns The transaction metadata.\n */\nfunction replayHistory(\n transactionHistory: TransactionHistory,\n): TransactionMeta {\n const shortHistory = cloneDeep(transactionHistory);\n return shortHistory.reduce(\n (val, entry: any) => jsonDiffer.applyPatch(val, entry).newDocument,\n ) as TransactionMeta;\n}\n\n/**\n * Clone the transaction meta data without the history property.\n *\n * @param transactionMeta - The transaction metadata to snapshot.\n * @returns A deep clone of transaction metadata without history property.\n */\nfunction snapshotFromTransactionMeta(\n transactionMeta: TransactionMeta,\n): TransactionMeta {\n const snapshot = { ...transactionMeta };\n delete snapshot.history;\n return cloneDeep(snapshot);\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import type EthQuery from '@metamask/eth-query';
2
- import type { InferTransactionTypeResult, TransactionParams } from './types';
2
+ import type { InferTransactionTypeResult, TransactionParams } from '../types';
3
3
  export declare const ESTIMATE_GAS_ERROR = "eth_estimateGas rpc method error";
4
4
  /**
5
5
  * Determines the type of the transaction by analyzing the txParams.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transaction-type.d.ts","sourceRoot":"","sources":["../../src/utils/transaction-type.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,QAAQ,MAAM,qBAAqB,CAAC;AAGhD,OAAO,KAAK,EAAE,0BAA0B,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAG9E,eAAO,MAAM,kBAAkB,qCAAqC,CAAC;AAMrE;;;;;;;;GAQG;AACH,wBAAsB,wBAAwB,CAC5C,QAAQ,EAAE,iBAAiB,EAC3B,QAAQ,EAAE,QAAQ,GACjB,OAAO,CAAC,0BAA0B,CAAC,CAiCrC"}
@@ -13,7 +13,7 @@ exports.determineTransactionType = exports.ESTIMATE_GAS_ERROR = void 0;
13
13
  const abi_1 = require("@ethersproject/abi");
14
14
  const controller_utils_1 = require("@metamask/controller-utils");
15
15
  const metamask_eth_abis_1 = require("@metamask/metamask-eth-abis");
16
- const types_1 = require("./types");
16
+ const types_1 = require("../types");
17
17
  exports.ESTIMATE_GAS_ERROR = 'eth_estimateGas rpc method error';
18
18
  const ERC20Interface = new abi_1.Interface(metamask_eth_abis_1.abiERC20);
19
19
  const ERC721Interface = new abi_1.Interface(metamask_eth_abis_1.abiERC721);
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transaction-type.js","sourceRoot":"","sources":["../../src/utils/transaction-type.ts"],"names":[],"mappings":"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","sourcesContent":["import type { TransactionDescription } from '@ethersproject/abi';\nimport { Interface } from '@ethersproject/abi';\nimport { query } from '@metamask/controller-utils';\nimport type EthQuery from '@metamask/eth-query';\nimport { abiERC721, abiERC20, abiERC1155 } from '@metamask/metamask-eth-abis';\n\nimport type { InferTransactionTypeResult, TransactionParams } from '../types';\nimport { TransactionType } from '../types';\n\nexport const ESTIMATE_GAS_ERROR = 'eth_estimateGas rpc method error';\n\nconst ERC20Interface = new Interface(abiERC20);\nconst ERC721Interface = new Interface(abiERC721);\nconst ERC1155Interface = new Interface(abiERC1155);\n\n/**\n * Determines the type of the transaction by analyzing the txParams.\n * It will never return TRANSACTION_TYPE_CANCEL or TRANSACTION_TYPE_RETRY as these\n * represent specific events that we specify manually at transaction creation.\n *\n * @param txParams - Parameters for the transaction.\n * @param ethQuery - EthQuery instance.\n * @returns A object with the transaction type and the contract code response in Hex.\n */\nexport async function determineTransactionType(\n txParams: TransactionParams,\n ethQuery: EthQuery,\n): Promise<InferTransactionTypeResult> {\n const { data, to } = txParams;\n const name = parseStandardTokenTransactionData(data)?.name;\n\n if (data && !to) {\n return { type: TransactionType.deployContract, getCodeResponse: undefined };\n }\n\n const { contractCode: resultCode, isContractAddress } =\n await readAddressAsContract(ethQuery, to);\n\n if (!isContractAddress) {\n return { type: TransactionType.simpleSend, getCodeResponse: resultCode };\n }\n\n const hasValue = txParams.value && Number(txParams.value) !== 0;\n\n const tokenMethodName = [\n TransactionType.tokenMethodApprove,\n TransactionType.tokenMethodSetApprovalForAll,\n TransactionType.tokenMethodTransfer,\n TransactionType.tokenMethodTransferFrom,\n TransactionType.tokenMethodSafeTransferFrom,\n ].find((methodName) => methodName.toLowerCase() === name?.toLowerCase());\n\n if (data && tokenMethodName && !hasValue) {\n return { type: tokenMethodName, getCodeResponse: resultCode };\n }\n\n return {\n type: TransactionType.contractInteraction,\n getCodeResponse: resultCode,\n };\n}\n\n/**\n * Attempts to decode transaction data using ABIs for three different token standards: ERC20, ERC721, ERC1155.\n * The data will decode correctly if the transaction is an interaction with a contract that matches one of these\n * contract standards\n *\n * @param data - Encoded transaction data.\n * @returns A representation of an ethereum contract call.\n */\nfunction parseStandardTokenTransactionData(\n data?: string,\n): TransactionDescription | undefined {\n if (!data) {\n return undefined;\n }\n\n try {\n return ERC20Interface.parseTransaction({ data });\n } catch {\n // ignore and next try to parse with erc721 ABI\n }\n\n try {\n return ERC721Interface.parseTransaction({ data });\n } catch {\n // ignore and next try to parse with erc1155 ABI\n }\n\n try {\n return ERC1155Interface.parseTransaction({ data });\n } catch {\n // ignore and return undefined\n }\n\n return undefined;\n}\n\n/**\n * Reads an Ethereum address and determines if it is a contract address.\n *\n * @param ethQuery - The Ethereum query object used to interact with the Ethereum blockchain.\n * @param address - The Ethereum address.\n * @returns An object containing the contract code and a boolean indicating if it is a contract address.\n */\nasync function readAddressAsContract(\n ethQuery: EthQuery,\n address?: string,\n): Promise<{\n contractCode: string | null;\n isContractAddress: boolean;\n}> {\n let contractCode;\n try {\n contractCode = await query(ethQuery, 'getCode', [address]);\n } catch (e) {\n contractCode = null;\n }\n\n const isContractAddress = contractCode\n ? contractCode !== '0x' && contractCode !== '0x0'\n : false;\n return { contractCode, isContractAddress };\n}\n"]}
@@ -1,7 +1,7 @@
1
1
  import type { Transaction as NonceTrackerTransaction } from 'nonce-tracker/dist/NonceTracker';
2
- import type { GasPriceValue, FeeMarketEIP1559Values } from './TransactionController';
3
- import { TransactionStatus } from './types';
4
- import type { TransactionParams, TransactionMeta } from './types';
2
+ import type { GasPriceValue, FeeMarketEIP1559Values } from '../TransactionController';
3
+ import { TransactionStatus } from '../types';
4
+ import type { TransactionParams, TransactionMeta } from '../types';
5
5
  export declare const ESTIMATE_GAS_ERROR = "eth_estimateGas rpc method error";
6
6
  /**
7
7
  * Normalizes properties on transaction params.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils/utils.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,IAAI,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AAE9F,OAAO,KAAK,EACV,aAAa,EACb,sBAAsB,EACvB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAEnE,eAAO,MAAM,kBAAkB,qCAAqC,CAAC;AAmBrE;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,iBAAiB,qBAQ5D;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,iBAAiB,GAAG,OAAO,CAOzE;AAED,eAAO,MAAM,iBAAiB,cACjB,aAAa,GAAG,sBAAsB,SAUlD,CAAC;AAEF,eAAO,MAAM,wBAAwB,eACvB,aAAa,GAAG,sBAAsB,wCAGuB,CAAC;AAE5E,eAAO,MAAM,eAAe,eACd,aAAa,GAAG,sBAAsB,+BAEE,CAAC;AAEvD,eAAO,MAAM,oBAAoB,UAAW,MAAM,QAAQ,MAAM,KAAG,MACF,CAAC;AAElE,eAAO,MAAM,6BAA6B,UACjC,MAAM,GAAG,SAAS,QACnB,MAAM,KACX,MAEF,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,UAQpE;AAED;;;;;;;GAOG;AACH,wBAAgB,uCAAuC,CACrD,WAAW,EAAE,MAAM,EACnB,iBAAiB,EAAE,iBAAiB,EACpC,YAAY,EAAE,eAAe,EAAE,GAC9B,uBAAuB,EAAE,CAsB3B;AAED;;;;;;GAMG;AACH,wBAAgB,+BAA+B,CAC7C,eAAe,EAAE,eAAe,GAAG,SAAS,EAC5C,MAAM,EAAE,MAAM,QAQf"}
@@ -2,8 +2,9 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.validateIfTransactionUnapproved = exports.getAndFormatTransactionsForNonceTracker = exports.validateMinimumIncrease = exports.getIncreasedPriceFromExisting = exports.getIncreasedPriceHex = exports.isGasPriceValue = exports.isFeeMarketEIP1559Values = exports.validateGasValues = exports.isEIP1559Transaction = exports.normalizeTxParams = exports.ESTIMATE_GAS_ERROR = void 0;
4
4
  const controller_utils_1 = require("@metamask/controller-utils");
5
+ const utils_1 = require("@metamask/utils");
5
6
  const ethereumjs_util_1 = require("ethereumjs-util");
6
- const types_1 = require("./types");
7
+ const types_1 = require("../types");
7
8
  exports.ESTIMATE_GAS_ERROR = 'eth_estimateGas rpc method error';
8
9
  const NORMALIZERS = {
9
10
  data: (data) => (0, ethereumjs_util_1.addHexPrefix)(data),
@@ -27,8 +28,7 @@ const NORMALIZERS = {
27
28
  */
28
29
  function normalizeTxParams(txParams) {
29
30
  const normalizedTxParams = { from: '' };
30
- let key;
31
- for (key in NORMALIZERS) {
31
+ for (const key of (0, utils_1.getKnownPropertyNames)(NORMALIZERS)) {
32
32
  if (txParams[key]) {
33
33
  normalizedTxParams[key] = NORMALIZERS[key](txParams[key]);
34
34
  }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/utils/utils.ts"],"names":[],"mappings":"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","sourcesContent":["import { convertHexToDecimal } from '@metamask/controller-utils';\nimport { getKnownPropertyNames } from '@metamask/utils';\nimport { addHexPrefix, isHexString } from 'ethereumjs-util';\nimport type { Transaction as NonceTrackerTransaction } from 'nonce-tracker/dist/NonceTracker';\n\nimport type {\n GasPriceValue,\n FeeMarketEIP1559Values,\n} from '../TransactionController';\nimport { TransactionStatus } from '../types';\nimport type { TransactionParams, TransactionMeta } from '../types';\n\nexport const ESTIMATE_GAS_ERROR = 'eth_estimateGas rpc method error';\n\nconst NORMALIZERS: { [param in keyof TransactionParams]: any } = {\n data: (data: string) => addHexPrefix(data),\n from: (from: string) => addHexPrefix(from).toLowerCase(),\n gas: (gas: string) => addHexPrefix(gas),\n gasLimit: (gas: string) => addHexPrefix(gas),\n gasPrice: (gasPrice: string) => addHexPrefix(gasPrice),\n nonce: (nonce: string) => addHexPrefix(nonce),\n to: (to: string) => addHexPrefix(to).toLowerCase(),\n value: (value: string) => addHexPrefix(value),\n maxFeePerGas: (maxFeePerGas: string) => addHexPrefix(maxFeePerGas),\n maxPriorityFeePerGas: (maxPriorityFeePerGas: string) =>\n addHexPrefix(maxPriorityFeePerGas),\n estimatedBaseFee: (maxPriorityFeePerGas: string) =>\n addHexPrefix(maxPriorityFeePerGas),\n type: (type: string) => (type === '0x0' ? '0x0' : undefined),\n};\n\n/**\n * Normalizes properties on transaction params.\n *\n * @param txParams - The transaction params to normalize.\n * @returns Normalized transaction params.\n */\nexport function normalizeTxParams(txParams: TransactionParams) {\n const normalizedTxParams: TransactionParams = { from: '' };\n for (const key of getKnownPropertyNames(NORMALIZERS)) {\n if (txParams[key]) {\n normalizedTxParams[key] = NORMALIZERS[key](txParams[key]);\n }\n }\n return normalizedTxParams;\n}\n\n/**\n * Checks if a transaction is EIP-1559 by checking for the existence of\n * maxFeePerGas and maxPriorityFeePerGas within its parameters.\n *\n * @param txParams - Transaction params object to add.\n * @returns Boolean that is true if the transaction is EIP-1559 (has maxFeePerGas and maxPriorityFeePerGas), otherwise returns false.\n */\nexport function isEIP1559Transaction(txParams: TransactionParams): boolean {\n const hasOwnProp = (obj: TransactionParams, key: string) =>\n Object.prototype.hasOwnProperty.call(obj, key);\n return (\n hasOwnProp(txParams, 'maxFeePerGas') &&\n hasOwnProp(txParams, 'maxPriorityFeePerGas')\n );\n}\n\nexport const validateGasValues = (\n gasValues: GasPriceValue | FeeMarketEIP1559Values,\n) => {\n Object.keys(gasValues).forEach((key) => {\n const value = (gasValues as any)[key];\n if (typeof value !== 'string' || !isHexString(value)) {\n throw new TypeError(\n `expected hex string for ${key} but received: ${value}`,\n );\n }\n });\n};\n\nexport const isFeeMarketEIP1559Values = (\n gasValues?: GasPriceValue | FeeMarketEIP1559Values,\n): gasValues is FeeMarketEIP1559Values =>\n (gasValues as FeeMarketEIP1559Values)?.maxFeePerGas !== undefined ||\n (gasValues as FeeMarketEIP1559Values)?.maxPriorityFeePerGas !== undefined;\n\nexport const isGasPriceValue = (\n gasValues?: GasPriceValue | FeeMarketEIP1559Values,\n): gasValues is GasPriceValue =>\n (gasValues as GasPriceValue)?.gasPrice !== undefined;\n\nexport const getIncreasedPriceHex = (value: number, rate: number): string =>\n addHexPrefix(`${parseInt(`${value * rate}`, 10).toString(16)}`);\n\nexport const getIncreasedPriceFromExisting = (\n value: string | undefined,\n rate: number,\n): string => {\n return getIncreasedPriceHex(convertHexToDecimal(value), rate);\n};\n\n/**\n * Validates that the proposed value is greater than or equal to the minimum value.\n *\n * @param proposed - The proposed value.\n * @param min - The minimum value.\n * @returns The proposed value.\n * @throws Will throw if the proposed value is too low.\n */\nexport function validateMinimumIncrease(proposed: string, min: string) {\n const proposedDecimal = convertHexToDecimal(proposed);\n const minDecimal = convertHexToDecimal(min);\n if (proposedDecimal >= minDecimal) {\n return proposed;\n }\n const errorMsg = `The proposed value: ${proposedDecimal} should meet or exceed the minimum value: ${minDecimal}`;\n throw new Error(errorMsg);\n}\n\n/**\n * Helper function to filter and format transactions for the nonce tracker.\n *\n * @param fromAddress - Address of the account from which the transactions to filter from are sent.\n * @param transactionStatus - Status of the transactions for which to filter.\n * @param transactions - Array of transactionMeta objects that have been prefiltered.\n * @returns Array of transactions formatted for the nonce tracker.\n */\nexport function getAndFormatTransactionsForNonceTracker(\n fromAddress: string,\n transactionStatus: TransactionStatus,\n transactions: TransactionMeta[],\n): NonceTrackerTransaction[] {\n return transactions\n .filter(\n ({ status, txParams: { from } }) =>\n status === transactionStatus &&\n from.toLowerCase() === fromAddress.toLowerCase(),\n )\n .map(({ status, txParams: { from, gas, value, nonce } }) => {\n // the only value we care about is the nonce\n // but we need to return the other values to satisfy the type\n // TODO: refactor nonceTracker to not require this\n return {\n status,\n history: [{}],\n txParams: {\n from: from ?? '',\n gas: gas ?? '',\n value: value ?? '',\n nonce: nonce ?? '',\n },\n };\n });\n}\n\n/**\n * Validates that a transaction is unapproved.\n * Throws if the transaction is not unapproved.\n *\n * @param transactionMeta - The transaction metadata to check.\n * @param fnName - The name of the function calling this helper.\n */\nexport function validateIfTransactionUnapproved(\n transactionMeta: TransactionMeta | undefined,\n fnName: string,\n) {\n if (transactionMeta?.status !== TransactionStatus.unapproved) {\n throw new Error(\n `Can only call ${fnName} on an unapproved transaction.\n Current tx status: ${transactionMeta?.status}`,\n );\n }\n}\n"]}
@@ -1,4 +1,4 @@
1
- import type { TransactionParams } from './types';
1
+ import type { TransactionParams } from '../types';
2
2
  /**
3
3
  * Validates whether a transaction initiated by a specific 'from' address is permitted by the origin.
4
4
  *
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAGlD;;;;;;;;GAQG;AACH,wBAAsB,yBAAyB,CAC7C,kBAAkB,EAAE,MAAM,EAAE,EAC5B,eAAe,EAAE,MAAM,EACvB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,iBAqBf;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,iBAAiB,EAC3B,mBAAmB,UAAO,QAQ3B"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"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","sourcesContent":["import { Interface } from '@ethersproject/abi';\nimport { ORIGIN_METAMASK, isValidHexAddress } from '@metamask/controller-utils';\nimport { abiERC20 } from '@metamask/metamask-eth-abis';\nimport { providerErrors, rpcErrors } from '@metamask/rpc-errors';\n\nimport type { TransactionParams } from '../types';\nimport { isEIP1559Transaction } from './utils';\n\n/**\n * Validates whether a transaction initiated by a specific 'from' address is permitted by the origin.\n *\n * @param permittedAddresses - The permitted accounts for the given origin.\n * @param selectedAddress - The currently selected Ethereum address in the wallet.\n * @param from - The address from which the transaction is initiated.\n * @param origin - The origin or source of the transaction.\n * @throws Throws an error if the transaction is not permitted.\n */\nexport async function validateTransactionOrigin(\n permittedAddresses: string[],\n selectedAddress: string,\n from: string,\n origin: string,\n) {\n if (origin === ORIGIN_METAMASK) {\n // Ensure the 'from' address matches the currently selected address\n if (from !== selectedAddress) {\n throw rpcErrors.internal({\n message: `Internally initiated transaction is using invalid account.`,\n data: {\n origin,\n fromAddress: from,\n selectedAddress,\n },\n });\n }\n return;\n }\n\n // Check if the origin has permissions to initiate transactions from the specified address\n if (!permittedAddresses.includes(from)) {\n throw providerErrors.unauthorized({ data: { origin } });\n }\n}\n\n/**\n * Validates the transaction params for required properties and throws in\n * the event of any validation error.\n *\n * @param txParams - Transaction params object to validate.\n * @param isEIP1559Compatible - whether or not the current network supports EIP-1559 transactions.\n */\nexport function validateTxParams(\n txParams: TransactionParams,\n isEIP1559Compatible = true,\n) {\n validateEIP1559Compatibility(txParams, isEIP1559Compatible);\n validateParamFrom(txParams.from);\n validateParamRecipient(txParams);\n validateParamValue(txParams.value);\n validateParamData(txParams.data);\n validateParamChainId(txParams.chainId);\n}\n\n/**\n * Validates EIP-1559 compatibility for transaction creation.\n *\n * @param txParams - The transaction parameters to validate.\n * @param isEIP1559Compatible - Indicates if the current network supports EIP-1559.\n * @throws Throws invalid params if the transaction specifies EIP-1559 but the network does not support it.\n */\nfunction validateEIP1559Compatibility(\n txParams: TransactionParams,\n isEIP1559Compatible: boolean,\n) {\n if (isEIP1559Transaction(txParams) && !isEIP1559Compatible) {\n throw rpcErrors.invalidParams(\n 'Invalid transaction params: params specify an EIP-1559 transaction but the current network does not support EIP-1559',\n );\n }\n}\n\n/**\n * Validates value property, ensuring it is a valid positive integer number\n * denominated in wei.\n *\n * @param value - The value to validate, expressed as a string.\n * @throws Throws an error if the value is not a valid positive integer\n * number denominated in wei.\n * - If the value contains a hyphen (-), it is considered invalid.\n * - If the value contains a decimal point (.), it is considered invalid.\n * - If the value is not a finite number, is NaN, or is not a safe integer, it is considered invalid.\n */\nfunction validateParamValue(value?: string) {\n if (value !== undefined) {\n if (value.includes('-')) {\n throw rpcErrors.invalidParams(\n `Invalid \"value\": ${value} is not a positive number.`,\n );\n }\n\n if (value.includes('.')) {\n throw rpcErrors.invalidParams(\n `Invalid \"value\": ${value} number must be denominated in wei.`,\n );\n }\n const intValue = parseInt(value, 10);\n const isValid =\n Number.isFinite(intValue) &&\n !Number.isNaN(intValue) &&\n !isNaN(Number(value)) &&\n Number.isSafeInteger(intValue);\n if (!isValid) {\n throw rpcErrors.invalidParams(\n `Invalid \"value\": ${value} number must be a valid number.`,\n );\n }\n }\n}\n\n/**\n * Validates the recipient address in a transaction's parameters.\n *\n * @param txParams - The transaction parameters object to validate.\n * @throws Throws an error if the recipient address is invalid:\n * - If the recipient address is an empty string ('0x') or undefined and the transaction contains data,\n * the \"to\" field is removed from the transaction parameters.\n * - If the recipient address is not a valid hexadecimal Ethereum address, an error is thrown.\n */\nfunction validateParamRecipient(txParams: TransactionParams) {\n if (txParams.to === '0x' || txParams.to === undefined) {\n if (txParams.data) {\n delete txParams.to;\n } else {\n throw new Error(\n `Invalid \"to\" address: ${txParams.to} must be a valid string.`,\n );\n }\n } else if (txParams.to !== undefined && !isValidHexAddress(txParams.to)) {\n throw new Error(\n `Invalid \"to\" address: ${txParams.to} must be a valid string.`,\n );\n }\n}\n\n/**\n * Validates the recipient address in a transaction's parameters.\n *\n * @param from - The from property to validate.\n * @throws Throws an error if the recipient address is invalid:\n * - If the recipient address is an empty string ('0x') or undefined and the transaction contains data,\n * the \"to\" field is removed from the transaction parameters.\n * - If the recipient address is not a valid hexadecimal Ethereum address, an error is thrown.\n */\nfunction validateParamFrom(from: string) {\n if (!from || typeof from !== 'string' || !isValidHexAddress(from)) {\n throw new Error(`Invalid \"from\" address: ${from} must be a valid string.`);\n }\n}\n\n/**\n * Validates input data for transactions.\n *\n * @param value - The input data to validate.\n * @throws Throws invalid params if the input data is invalid.\n */\nfunction validateParamData(value?: string) {\n if (value) {\n const ERC20Interface = new Interface(abiERC20);\n try {\n ERC20Interface.parseTransaction({ data: value });\n } catch (error: any) {\n if (error.message.match(/BUFFER_OVERRUN/u)) {\n throw rpcErrors.invalidParams(\n 'Invalid transaction params: data out-of-bounds, BUFFER_OVERRUN.',\n );\n }\n }\n }\n}\n\n/**\n * Validates chainId type.\n *\n * @param chainId - The chainId to validate.\n */\nfunction validateParamChainId(chainId: number | string | undefined) {\n if (\n chainId !== undefined &&\n typeof chainId !== 'number' &&\n typeof chainId !== 'string'\n ) {\n throw rpcErrors.invalidParams(\n `Invalid transaction params: chainId is not a Number or hex string. got: (${chainId})`,\n );\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask/transaction-controller",
3
- "version": "14.0.0",
3
+ "version": "16.0.0",
4
4
  "description": "Stores transactions alongside their periodically updated statuses and manages interactions such as approval and cancellation",
5
5
  "keywords": [
6
6
  "MetaMask",
@@ -32,13 +32,14 @@
32
32
  "@ethereumjs/common": "^3.2.0",
33
33
  "@ethereumjs/tx": "^4.2.0",
34
34
  "@ethersproject/abi": "^5.7.0",
35
- "@metamask/approval-controller": "^4.0.0",
35
+ "@metamask/approval-controller": "^4.1.0",
36
36
  "@metamask/base-controller": "^3.2.3",
37
37
  "@metamask/controller-utils": "^5.0.2",
38
38
  "@metamask/eth-query": "^3.0.1",
39
+ "@metamask/gas-fee-controller": "^10.0.0",
39
40
  "@metamask/metamask-eth-abis": "^3.0.0",
40
- "@metamask/network-controller": "^14.0.0",
41
- "@metamask/rpc-errors": "^6.0.0",
41
+ "@metamask/network-controller": "^15.1.0",
42
+ "@metamask/rpc-errors": "^6.1.0",
42
43
  "@metamask/utils": "^8.1.0",
43
44
  "async-mutex": "^0.2.6",
44
45
  "eth-method-registry": "1.1.0",
@@ -49,7 +50,7 @@
49
50
  "uuid": "^8.3.2"
50
51
  },
51
52
  "devDependencies": {
52
- "@metamask/auto-changelog": "^3.1.0",
53
+ "@metamask/auto-changelog": "^3.4.2",
53
54
  "@types/jest": "^27.4.1",
54
55
  "@types/node": "^16.18.54",
55
56
  "babel-runtime": "^6.26.0",
@@ -63,8 +64,9 @@
63
64
  "typescript": "~4.8.4"
64
65
  },
65
66
  "peerDependencies": {
66
- "@metamask/approval-controller": "^4.0.0",
67
- "@metamask/network-controller": "^14.0.0",
67
+ "@metamask/approval-controller": "^4.1.0",
68
+ "@metamask/gas-fee-controller": "^10.0.0",
69
+ "@metamask/network-controller": "^15.1.0",
68
70
  "babel-runtime": "^6.26.0"
69
71
  },
70
72
  "engines": {
@@ -1 +0,0 @@
1
- {"version":3,"file":"EtherscanRemoteTransactionSource.d.ts","sourceRoot":"","sources":["../src/EtherscanRemoteTransactionSource.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAiB3C,OAAO,KAAK,EACV,uBAAuB,EACvB,8BAA8B,EAC9B,eAAe,EAChB,MAAM,SAAS,CAAC;AAGjB;;GAEG;AACH,qBAAa,gCACX,YAAW,uBAAuB;;gBAMtB,EACV,qBAAqB,GACtB,GAAE;QAAE,qBAAqB,CAAC,EAAE,OAAO,CAAA;KAAO;IAK3C,kBAAkB,CAAC,OAAO,EAAE,GAAG,GAAG,OAAO;IAIzC,sBAAsB,IAAI,MAAM,EAAE;IAI5B,iBAAiB,CACrB,OAAO,EAAE,8BAA8B,GACtC,OAAO,CAAC,eAAe,EAAE,CAAC;CAkI9B"}