@metamask/transaction-controller 52.3.0 → 54.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 +52 -1
- package/dist/TransactionController.cjs +133 -119
- package/dist/TransactionController.cjs.map +1 -1
- package/dist/TransactionController.d.cts +25 -30
- package/dist/TransactionController.d.cts.map +1 -1
- package/dist/TransactionController.d.mts +25 -30
- package/dist/TransactionController.d.mts.map +1 -1
- package/dist/TransactionController.mjs +133 -119
- package/dist/TransactionController.mjs.map +1 -1
- package/dist/helpers/GasFeePoller.cjs +2 -1
- package/dist/helpers/GasFeePoller.cjs.map +1 -1
- package/dist/helpers/GasFeePoller.d.cts +1 -1
- package/dist/helpers/GasFeePoller.d.cts.map +1 -1
- package/dist/helpers/GasFeePoller.d.mts +1 -1
- package/dist/helpers/GasFeePoller.d.mts.map +1 -1
- package/dist/helpers/GasFeePoller.mjs +2 -1
- package/dist/helpers/GasFeePoller.mjs.map +1 -1
- package/dist/helpers/PendingTransactionTracker.cjs +8 -7
- package/dist/helpers/PendingTransactionTracker.cjs.map +1 -1
- package/dist/helpers/PendingTransactionTracker.d.cts +1 -2
- package/dist/helpers/PendingTransactionTracker.d.cts.map +1 -1
- package/dist/helpers/PendingTransactionTracker.d.mts +1 -2
- package/dist/helpers/PendingTransactionTracker.d.mts.map +1 -1
- package/dist/helpers/PendingTransactionTracker.mjs +8 -7
- package/dist/helpers/PendingTransactionTracker.mjs.map +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/types.cjs +4 -0
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +60 -8
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.mts +60 -8
- package/dist/types.d.mts.map +1 -1
- package/dist/types.mjs +4 -0
- package/dist/types.mjs.map +1 -1
- package/dist/utils/batch.cjs +16 -8
- package/dist/utils/batch.cjs.map +1 -1
- package/dist/utils/batch.d.cts +4 -3
- package/dist/utils/batch.d.cts.map +1 -1
- package/dist/utils/batch.d.mts +4 -3
- package/dist/utils/batch.d.mts.map +1 -1
- package/dist/utils/batch.mjs +16 -8
- package/dist/utils/batch.mjs.map +1 -1
- package/dist/utils/feature-flags.cjs +21 -1
- package/dist/utils/feature-flags.cjs.map +1 -1
- package/dist/utils/feature-flags.d.cts +35 -0
- package/dist/utils/feature-flags.d.cts.map +1 -1
- package/dist/utils/feature-flags.d.mts +35 -0
- package/dist/utils/feature-flags.d.mts.map +1 -1
- package/dist/utils/feature-flags.mjs +19 -0
- package/dist/utils/feature-flags.mjs.map +1 -1
- package/dist/utils/gas.cjs +10 -4
- package/dist/utils/gas.cjs.map +1 -1
- package/dist/utils/gas.d.cts +5 -2
- package/dist/utils/gas.d.cts.map +1 -1
- package/dist/utils/gas.d.mts +5 -2
- package/dist/utils/gas.d.mts.map +1 -1
- package/dist/utils/gas.mjs +10 -4
- package/dist/utils/gas.mjs.map +1 -1
- package/dist/utils/nonce.cjs +4 -1
- package/dist/utils/nonce.cjs.map +1 -1
- package/dist/utils/nonce.d.cts +1 -1
- package/dist/utils/nonce.d.cts.map +1 -1
- package/dist/utils/nonce.d.mts +1 -1
- package/dist/utils/nonce.d.mts.map +1 -1
- package/dist/utils/nonce.mjs +4 -1
- package/dist/utils/nonce.mjs.map +1 -1
- package/dist/utils/validation.cjs +14 -13
- package/dist/utils/validation.cjs.map +1 -1
- package/dist/utils/validation.d.cts +3 -1
- package/dist/utils/validation.d.cts.map +1 -1
- package/dist/utils/validation.d.mts +3 -1
- package/dist/utils/validation.d.mts.map +1 -1
- package/dist/utils/validation.mjs +14 -13
- package/dist/utils/validation.mjs.map +1 -1
- package/package.json +3 -3
package/dist/utils/gas.d.mts
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
/// <reference types="debug" />
|
|
2
2
|
import type EthQuery from "@metamask/eth-query";
|
|
3
3
|
import type { Hex } from "@metamask/utils";
|
|
4
|
+
import type { TransactionControllerMessenger } from "../TransactionController.mjs";
|
|
4
5
|
import { type TransactionMeta, type TransactionParams } from "../types.mjs";
|
|
5
6
|
export type UpdateGasRequest = {
|
|
6
7
|
chainId: Hex;
|
|
7
8
|
ethQuery: EthQuery;
|
|
8
9
|
isCustomNetwork: boolean;
|
|
9
10
|
isSimulationEnabled: boolean;
|
|
11
|
+
messenger: TransactionControllerMessenger;
|
|
10
12
|
txMeta: TransactionMeta;
|
|
11
13
|
};
|
|
12
14
|
export declare const log: import("debug").Debugger;
|
|
13
15
|
export declare const FIXED_GAS = "0x5208";
|
|
14
16
|
export declare const DEFAULT_GAS_MULTIPLIER = 1.5;
|
|
15
|
-
export declare const GAS_ESTIMATE_FALLBACK_BLOCK_PERCENT = 35;
|
|
16
17
|
export declare const MAX_GAS_BLOCK_PERCENT = 90;
|
|
17
18
|
export declare const INTRINSIC_GAS = 21000;
|
|
18
19
|
export declare const DUMMY_AUTHORIZATION_SIGNATURE = "0x1111111111111111111111111111111111111111111111111111111111111111";
|
|
@@ -30,13 +31,15 @@ export declare function updateGas(request: UpdateGasRequest): Promise<void>;
|
|
|
30
31
|
* @param options.chainId - The chain ID of the transaction.
|
|
31
32
|
* @param options.ethQuery - The EthQuery instance to interact with the network.
|
|
32
33
|
* @param options.isSimulationEnabled - Whether the simulation is enabled.
|
|
34
|
+
* @param options.messenger - The messenger instance for communication.
|
|
33
35
|
* @param options.txParams - The transaction parameters.
|
|
34
36
|
* @returns The estimated gas and related info.
|
|
35
37
|
*/
|
|
36
|
-
export declare function estimateGas({ chainId, ethQuery, isSimulationEnabled, txParams, }: {
|
|
38
|
+
export declare function estimateGas({ chainId, ethQuery, isSimulationEnabled, messenger, txParams, }: {
|
|
37
39
|
chainId: Hex;
|
|
38
40
|
ethQuery: EthQuery;
|
|
39
41
|
isSimulationEnabled: boolean;
|
|
42
|
+
messenger: TransactionControllerMessenger;
|
|
40
43
|
txParams: TransactionParams;
|
|
41
44
|
}): Promise<{
|
|
42
45
|
blockGasLimit: string;
|
package/dist/utils/gas.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gas.d.mts","sourceRoot":"","sources":["../../src/utils/gas.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"gas.d.mts","sourceRoot":"","sources":["../../src/utils/gas.ts"],"names":[],"mappings":";AAOA,OAAO,KAAK,QAAQ,4BAA4B;AAChD,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAQ3C,OAAO,KAAK,EAAE,8BAA8B,EAAE,qCAAiC;AAC/E,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACvB,qBAAiB;AAElB,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,GAAG,CAAC;IACb,QAAQ,EAAE,QAAQ,CAAC;IACnB,eAAe,EAAE,OAAO,CAAC;IACzB,mBAAmB,EAAE,OAAO,CAAC;IAC7B,SAAS,EAAE,8BAA8B,CAAC;IAC1C,MAAM,EAAE,eAAe,CAAC;CACzB,CAAC;AAEF,eAAO,MAAM,GAAG,0BAA2C,CAAC;AAE5D,eAAO,MAAM,SAAS,WAAW,CAAC;AAClC,eAAO,MAAM,sBAAsB,MAAM,CAAC;AAC1C,eAAO,MAAM,qBAAqB,KAAK,CAAC;AACxC,eAAO,MAAM,aAAa,QAAQ,CAAC;AAEnC,eAAO,MAAM,6BAA6B,uEAC4B,CAAC;AAEvE;;;;GAIG;AACH,wBAAsB,SAAS,CAAC,OAAO,EAAE,gBAAgB,iBAmBxD;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,WAAW,CAAC,EAChC,OAAO,EACP,QAAQ,EACR,mBAAmB,EACnB,SAAS,EACT,QAAQ,GACT,EAAE;IACD,OAAO,EAAE,GAAG,CAAC;IACb,QAAQ,EAAE,QAAQ,CAAC;IACnB,mBAAmB,EAAE,OAAO,CAAC;IAC7B,SAAS,EAAE,8BAA8B,CAAC;IAC1C,QAAQ,EAAE,iBAAiB,CAAC;CAC7B;;;;;;;;;;;GAmEA;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAC1B,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,MAAM,iBA2BnB"}
|
package/dist/utils/gas.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { BNToHex, fractionBN, hexToBN, query } from "@metamask/controller-utils";
|
|
1
|
+
import { BNToHex, fractionBN, hexToBN, query, toHex } from "@metamask/controller-utils";
|
|
2
2
|
import { add0x, createModuleLogger, remove0x } from "@metamask/utils";
|
|
3
3
|
import { DELEGATION_PREFIX } from "./eip7702.mjs";
|
|
4
|
+
import { getGasEstimateFallback } from "./feature-flags.mjs";
|
|
4
5
|
import { simulateTransactions } from "./simulation-api.mjs";
|
|
5
6
|
import { GAS_BUFFER_CHAIN_OVERRIDES } from "../constants.mjs";
|
|
6
7
|
import { projectLogger } from "../logger.mjs";
|
|
@@ -8,7 +9,6 @@ import { TransactionEnvelopeType } from "../types.mjs";
|
|
|
8
9
|
export const log = createModuleLogger(projectLogger, 'gas');
|
|
9
10
|
export const FIXED_GAS = '0x5208';
|
|
10
11
|
export const DEFAULT_GAS_MULTIPLIER = 1.5;
|
|
11
|
-
export const GAS_ESTIMATE_FALLBACK_BLOCK_PERCENT = 35;
|
|
12
12
|
export const MAX_GAS_BLOCK_PERCENT = 90;
|
|
13
13
|
export const INTRINSIC_GAS = 21000;
|
|
14
14
|
export const DUMMY_AUTHORIZATION_SIGNATURE = '0x1111111111111111111111111111111111111111111111111111111111111111';
|
|
@@ -40,15 +40,20 @@ export async function updateGas(request) {
|
|
|
40
40
|
* @param options.chainId - The chain ID of the transaction.
|
|
41
41
|
* @param options.ethQuery - The EthQuery instance to interact with the network.
|
|
42
42
|
* @param options.isSimulationEnabled - Whether the simulation is enabled.
|
|
43
|
+
* @param options.messenger - The messenger instance for communication.
|
|
43
44
|
* @param options.txParams - The transaction parameters.
|
|
44
45
|
* @returns The estimated gas and related info.
|
|
45
46
|
*/
|
|
46
|
-
export async function estimateGas({ chainId, ethQuery, isSimulationEnabled, txParams, }) {
|
|
47
|
+
export async function estimateGas({ chainId, ethQuery, isSimulationEnabled, messenger, txParams, }) {
|
|
47
48
|
const request = { ...txParams };
|
|
48
49
|
const { authorizationList, data, from, value, to } = request;
|
|
49
50
|
const { gasLimit: blockGasLimit, number: blockNumber } = await getLatestBlock(ethQuery);
|
|
50
51
|
const blockGasLimitBN = hexToBN(blockGasLimit);
|
|
51
|
-
const
|
|
52
|
+
const { percentage, fixed } = getGasEstimateFallback(chainId, messenger);
|
|
53
|
+
const fallback = fixed
|
|
54
|
+
? toHex(fixed)
|
|
55
|
+
: BNToHex(fractionBN(blockGasLimitBN, percentage, 100));
|
|
56
|
+
log('Estimation fallback values', fallback);
|
|
52
57
|
request.data = data ? add0x(data) : data;
|
|
53
58
|
request.value = value || '0x0';
|
|
54
59
|
request.authorizationList = normalizeAuthorizationList(request.authorizationList, chainId);
|
|
@@ -136,6 +141,7 @@ async function getGas(request) {
|
|
|
136
141
|
chainId: request.chainId,
|
|
137
142
|
ethQuery: request.ethQuery,
|
|
138
143
|
isSimulationEnabled,
|
|
144
|
+
messenger: request.messenger,
|
|
139
145
|
txParams: txMeta.txParams,
|
|
140
146
|
});
|
|
141
147
|
if (isCustomNetwork || simulationFails) {
|
package/dist/utils/gas.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gas.mjs","sourceRoot":"","sources":["../../src/utils/gas.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n BNToHex,\n fractionBN,\n hexToBN,\n query,\n} from '@metamask/controller-utils';\nimport type EthQuery from '@metamask/eth-query';\nimport type { Hex } from '@metamask/utils';\nimport { add0x, createModuleLogger, remove0x } from '@metamask/utils';\n\nimport { DELEGATION_PREFIX } from './eip7702';\nimport { simulateTransactions } from './simulation-api';\nimport { GAS_BUFFER_CHAIN_OVERRIDES } from '../constants';\nimport { projectLogger } from '../logger';\nimport {\n TransactionEnvelopeType,\n type TransactionMeta,\n type TransactionParams,\n} from '../types';\n\nexport type UpdateGasRequest = {\n chainId: Hex;\n ethQuery: EthQuery;\n isCustomNetwork: boolean;\n isSimulationEnabled: boolean;\n txMeta: TransactionMeta;\n};\n\nexport const log = createModuleLogger(projectLogger, 'gas');\n\nexport const FIXED_GAS = '0x5208';\nexport const DEFAULT_GAS_MULTIPLIER = 1.5;\nexport const GAS_ESTIMATE_FALLBACK_BLOCK_PERCENT = 35;\nexport const MAX_GAS_BLOCK_PERCENT = 90;\nexport const INTRINSIC_GAS = 21000;\n\nexport const DUMMY_AUTHORIZATION_SIGNATURE =\n '0x1111111111111111111111111111111111111111111111111111111111111111';\n\n/**\n * Populate the gas properties of the provided transaction meta.\n *\n * @param request - The request object including the necessary parameters.\n */\nexport async function updateGas(request: UpdateGasRequest) {\n const { txMeta } = request;\n const initialParams = { ...txMeta.txParams };\n\n const [gas, simulationFails, gasLimitNoBuffer] = await getGas(request);\n\n txMeta.txParams.gas = gas;\n txMeta.simulationFails = simulationFails;\n txMeta.gasLimitNoBuffer = gasLimitNoBuffer;\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\n/**\n * Estimate the gas for the provided transaction parameters.\n * If the gas estimate fails, the fallback value is returned.\n *\n * @param options - The options object.\n * @param options.chainId - The chain ID of the transaction.\n * @param options.ethQuery - The EthQuery instance to interact with the network.\n * @param options.isSimulationEnabled - Whether the simulation is enabled.\n * @param options.txParams - The transaction parameters.\n * @returns The estimated gas and related info.\n */\nexport async function estimateGas({\n chainId,\n ethQuery,\n isSimulationEnabled,\n txParams,\n}: {\n chainId: Hex;\n ethQuery: EthQuery;\n isSimulationEnabled: boolean;\n txParams: TransactionParams;\n}) {\n const request = { ...txParams };\n const { authorizationList, data, from, value, to } = request;\n\n const { gasLimit: blockGasLimit, number: blockNumber } =\n await getLatestBlock(ethQuery);\n\n const blockGasLimitBN = hexToBN(blockGasLimit);\n\n const fallback = BNToHex(\n fractionBN(blockGasLimitBN, GAS_ESTIMATE_FALLBACK_BLOCK_PERCENT, 100),\n );\n\n request.data = data ? add0x(data) : data;\n request.value = value || '0x0';\n\n request.authorizationList = normalizeAuthorizationList(\n request.authorizationList,\n chainId,\n );\n\n delete request.gasPrice;\n delete request.maxFeePerGas;\n delete request.maxPriorityFeePerGas;\n\n let estimatedGas = fallback;\n let simulationFails: TransactionMeta['simulationFails'];\n\n const isUpgradeWithDataToSelf =\n txParams.type === TransactionEnvelopeType.setCode &&\n authorizationList?.length &&\n data &&\n data !== '0x' &&\n from?.toLowerCase() === to?.toLowerCase();\n\n try {\n if (isSimulationEnabled && isUpgradeWithDataToSelf) {\n estimatedGas = await estimateGasUpgradeWithDataToSelf(\n request,\n ethQuery,\n chainId,\n );\n } else {\n estimatedGas = await query(ethQuery, 'estimateGas', [request]);\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (error: any) {\n simulationFails = {\n reason: error.message,\n errorKey: error.errorKey,\n debug: {\n blockNumber,\n blockGasLimit,\n },\n };\n\n log('Estimation failed', { ...simulationFails, fallback });\n }\n\n return {\n blockGasLimit,\n estimatedGas,\n simulationFails,\n };\n}\n\n/**\n * Add a buffer to the provided estimated gas.\n * The buffer is calculated based on the block gas limit and a multiplier.\n *\n * @param estimatedGas - The estimated gas.\n * @param blockGasLimit - The block gas limit.\n * @param multiplier - The multiplier to apply to the estimated gas.\n * @returns The gas with the buffer applied.\n */\nexport function addGasBuffer(\n estimatedGas: string,\n blockGasLimit: string,\n multiplier: number,\n) {\n const estimatedGasBN = hexToBN(estimatedGas);\n\n const maxGasBN = fractionBN(\n hexToBN(blockGasLimit),\n MAX_GAS_BLOCK_PERCENT,\n 100,\n );\n\n const paddedGasBN = fractionBN(estimatedGasBN, multiplier * 100, 100);\n\n if (estimatedGasBN.gt(maxGasBN)) {\n const estimatedGasHex = add0x(estimatedGas);\n log('Using estimated value', estimatedGasHex);\n return estimatedGasHex;\n }\n\n if (paddedGasBN.lt(maxGasBN)) {\n const paddedHex = add0x(BNToHex(paddedGasBN));\n log('Using padded estimate', paddedHex, multiplier);\n return paddedHex;\n }\n\n const maxHex = add0x(BNToHex(maxGasBN));\n log('Using 90% of block gas limit', maxHex);\n return maxHex;\n}\n\n/**\n * Determine the gas for the provided request.\n *\n * @param request - The request object including the necessary parameters.\n * @returns The final gas value and the estimate used.\n */\nasync function getGas(\n request: UpdateGasRequest,\n): Promise<[string, TransactionMeta['simulationFails']?, string?]> {\n const { chainId, isCustomNetwork, isSimulationEnabled, txMeta } = request;\n const { disableGasBuffer } = txMeta;\n\n if (txMeta.txParams.gas) {\n log('Using value from request', txMeta.txParams.gas);\n return [txMeta.txParams.gas, undefined, txMeta.txParams.gas];\n }\n\n if (await requiresFixedGas(request)) {\n log('Using fixed value', FIXED_GAS);\n return [FIXED_GAS, undefined, FIXED_GAS];\n }\n\n const { blockGasLimit, estimatedGas, simulationFails } = await estimateGas({\n chainId: request.chainId,\n ethQuery: request.ethQuery,\n isSimulationEnabled,\n txParams: txMeta.txParams,\n });\n\n if (isCustomNetwork || simulationFails) {\n log(\n isCustomNetwork\n ? 'Using original estimate as custom network'\n : 'Using original fallback estimate as simulation failed',\n );\n return [estimatedGas, simulationFails, estimatedGas];\n }\n\n let finalGas = estimatedGas;\n\n if (!disableGasBuffer) {\n const bufferMultiplier =\n GAS_BUFFER_CHAIN_OVERRIDES[\n chainId as keyof typeof GAS_BUFFER_CHAIN_OVERRIDES\n ] ?? DEFAULT_GAS_MULTIPLIER;\n\n finalGas = addGasBuffer(estimatedGas, blockGasLimit, bufferMultiplier);\n }\n\n return [finalGas, simulationFails, estimatedGas];\n}\n\n/**\n * Determine if the gas for the provided request should be fixed.\n *\n * @param options - The options object.\n * @param options.ethQuery - The EthQuery instance to interact with the network.\n * @param options.txMeta - The transaction meta object.\n * @param options.isCustomNetwork - Whether the network is a custom network.\n * @returns Whether the gas should be fixed.\n */\nasync function requiresFixedGas({\n ethQuery,\n txMeta,\n isCustomNetwork,\n}: UpdateGasRequest): Promise<boolean> {\n const {\n txParams: { to, data },\n } = txMeta;\n\n if (isCustomNetwork || !to || data) {\n return false;\n }\n\n const code = await getCode(ethQuery, to);\n\n return !code || code === '0x';\n}\n\n/**\n * Get the contract code for the provided address.\n *\n * @param ethQuery - The EthQuery instance to interact with the network.\n * @param address - The address to get the code for.\n * @returns The contract code.\n */\nasync function getCode(\n ethQuery: EthQuery,\n address: string,\n): Promise<string | undefined> {\n return await query(ethQuery, 'getCode', [address]);\n}\n\n/**\n * Get the latest block from the network.\n *\n * @param ethQuery - The EthQuery instance to interact with the network.\n * @returns The latest block number.\n */\nasync function getLatestBlock(\n ethQuery: EthQuery,\n): Promise<{ gasLimit: string; number: string }> {\n return await query(ethQuery, 'getBlockByNumber', ['latest', false]);\n}\n\n/**\n * Estimate the gas for a type 4 transaction.\n *\n * @param txParams - The transaction parameters.\n * @param ethQuery - The EthQuery instance to interact with the network.\n * @param chainId - The chain ID of the transaction.\n * @returns The estimated gas.\n */\nasync function estimateGasUpgradeWithDataToSelf(\n txParams: TransactionParams,\n ethQuery: EthQuery,\n chainId: Hex,\n) {\n const upgradeGas = await query(ethQuery, 'estimateGas', [\n {\n ...txParams,\n data: '0x',\n },\n ]);\n\n log('Upgrade only gas', upgradeGas);\n\n const delegationAddress = txParams.authorizationList?.[0].address as Hex;\n\n const executeGas = await simulateGas({\n chainId: chainId as Hex,\n delegationAddress,\n transaction: txParams,\n });\n\n log('Execute gas', executeGas);\n\n const total = BNToHex(\n hexToBN(upgradeGas).add(hexToBN(executeGas)).subn(INTRINSIC_GAS),\n );\n\n log('Total type 4 gas', total);\n\n return total;\n}\n\n/**\n * Simulate the required gas using the simulation API.\n *\n * @param options - The options object.\n * @param options.chainId - The chain ID of the transaction.\n * @param options.delegationAddress - The delegation address of the sender to mock.\n * @param options.transaction - The transaction parameters.\n * @returns The simulated gas.\n */\nasync function simulateGas({\n chainId,\n delegationAddress,\n transaction,\n}: {\n chainId: Hex;\n delegationAddress?: Hex;\n transaction: TransactionParams;\n}): Promise<Hex> {\n const response = await simulateTransactions(chainId, {\n transactions: [\n {\n to: transaction.to as Hex,\n from: transaction.from as Hex,\n data: transaction.data as Hex,\n value: transaction.value as Hex,\n },\n ],\n overrides: {\n [transaction.from as string]: {\n code:\n delegationAddress &&\n ((DELEGATION_PREFIX + remove0x(delegationAddress)) as Hex),\n },\n },\n });\n\n const gasUsed = response?.transactions?.[0].gasUsed;\n\n if (!gasUsed) {\n throw new Error('No simulated gas returned');\n }\n\n return gasUsed;\n}\n\n/**\n * Populate the authorization list with dummy values.\n *\n * @param authorizationList - The authorization list to prepare.\n * @param chainId - The chain ID to use.\n * @returns The authorization list with dummy values.\n */\nfunction normalizeAuthorizationList(\n authorizationList: TransactionParams['authorizationList'],\n chainId: Hex,\n) {\n return authorizationList?.map((authorization) => ({\n ...authorization,\n chainId: authorization.chainId ?? chainId,\n nonce: authorization.nonce ?? '0x1',\n r: authorization.r ?? DUMMY_AUTHORIZATION_SIGNATURE,\n s: authorization.s ?? DUMMY_AUTHORIZATION_SIGNATURE,\n yParity: authorization.yParity ?? '0x1',\n }));\n}\n"]}
|
|
1
|
+
{"version":3,"file":"gas.mjs","sourceRoot":"","sources":["../../src/utils/gas.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n BNToHex,\n fractionBN,\n hexToBN,\n query,\n toHex,\n} from '@metamask/controller-utils';\nimport type EthQuery from '@metamask/eth-query';\nimport type { Hex } from '@metamask/utils';\nimport { add0x, createModuleLogger, remove0x } from '@metamask/utils';\n\nimport { DELEGATION_PREFIX } from './eip7702';\nimport { getGasEstimateFallback } from './feature-flags';\nimport { simulateTransactions } from './simulation-api';\nimport { GAS_BUFFER_CHAIN_OVERRIDES } from '../constants';\nimport { projectLogger } from '../logger';\nimport type { TransactionControllerMessenger } from '../TransactionController';\nimport {\n TransactionEnvelopeType,\n type TransactionMeta,\n type TransactionParams,\n} from '../types';\n\nexport type UpdateGasRequest = {\n chainId: Hex;\n ethQuery: EthQuery;\n isCustomNetwork: boolean;\n isSimulationEnabled: boolean;\n messenger: TransactionControllerMessenger;\n txMeta: TransactionMeta;\n};\n\nexport const log = createModuleLogger(projectLogger, 'gas');\n\nexport const FIXED_GAS = '0x5208';\nexport const DEFAULT_GAS_MULTIPLIER = 1.5;\nexport const MAX_GAS_BLOCK_PERCENT = 90;\nexport const INTRINSIC_GAS = 21000;\n\nexport const DUMMY_AUTHORIZATION_SIGNATURE =\n '0x1111111111111111111111111111111111111111111111111111111111111111';\n\n/**\n * Populate the gas properties of the provided transaction meta.\n *\n * @param request - The request object including the necessary parameters.\n */\nexport async function updateGas(request: UpdateGasRequest) {\n const { txMeta } = request;\n const initialParams = { ...txMeta.txParams };\n\n const [gas, simulationFails, gasLimitNoBuffer] = await getGas(request);\n\n txMeta.txParams.gas = gas;\n txMeta.simulationFails = simulationFails;\n txMeta.gasLimitNoBuffer = gasLimitNoBuffer;\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\n/**\n * Estimate the gas for the provided transaction parameters.\n * If the gas estimate fails, the fallback value is returned.\n *\n * @param options - The options object.\n * @param options.chainId - The chain ID of the transaction.\n * @param options.ethQuery - The EthQuery instance to interact with the network.\n * @param options.isSimulationEnabled - Whether the simulation is enabled.\n * @param options.messenger - The messenger instance for communication.\n * @param options.txParams - The transaction parameters.\n * @returns The estimated gas and related info.\n */\nexport async function estimateGas({\n chainId,\n ethQuery,\n isSimulationEnabled,\n messenger,\n txParams,\n}: {\n chainId: Hex;\n ethQuery: EthQuery;\n isSimulationEnabled: boolean;\n messenger: TransactionControllerMessenger;\n txParams: TransactionParams;\n}) {\n const request = { ...txParams };\n const { authorizationList, data, from, value, to } = request;\n\n const { gasLimit: blockGasLimit, number: blockNumber } =\n await getLatestBlock(ethQuery);\n\n const blockGasLimitBN = hexToBN(blockGasLimit);\n const { percentage, fixed } = getGasEstimateFallback(chainId, messenger);\n\n const fallback = fixed\n ? toHex(fixed)\n : BNToHex(fractionBN(blockGasLimitBN, percentage, 100));\n\n log('Estimation fallback values', fallback);\n\n request.data = data ? add0x(data) : data;\n request.value = value || '0x0';\n\n request.authorizationList = normalizeAuthorizationList(\n request.authorizationList,\n chainId,\n );\n\n delete request.gasPrice;\n delete request.maxFeePerGas;\n delete request.maxPriorityFeePerGas;\n\n let estimatedGas = fallback;\n let simulationFails: TransactionMeta['simulationFails'];\n\n const isUpgradeWithDataToSelf =\n txParams.type === TransactionEnvelopeType.setCode &&\n authorizationList?.length &&\n data &&\n data !== '0x' &&\n from?.toLowerCase() === to?.toLowerCase();\n\n try {\n if (isSimulationEnabled && isUpgradeWithDataToSelf) {\n estimatedGas = await estimateGasUpgradeWithDataToSelf(\n request,\n ethQuery,\n chainId,\n );\n } else {\n estimatedGas = await query(ethQuery, 'estimateGas', [request]);\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (error: any) {\n simulationFails = {\n reason: error.message,\n errorKey: error.errorKey,\n debug: {\n blockNumber,\n blockGasLimit,\n },\n };\n\n log('Estimation failed', { ...simulationFails, fallback });\n }\n\n return {\n blockGasLimit,\n estimatedGas,\n simulationFails,\n };\n}\n\n/**\n * Add a buffer to the provided estimated gas.\n * The buffer is calculated based on the block gas limit and a multiplier.\n *\n * @param estimatedGas - The estimated gas.\n * @param blockGasLimit - The block gas limit.\n * @param multiplier - The multiplier to apply to the estimated gas.\n * @returns The gas with the buffer applied.\n */\nexport function addGasBuffer(\n estimatedGas: string,\n blockGasLimit: string,\n multiplier: number,\n) {\n const estimatedGasBN = hexToBN(estimatedGas);\n\n const maxGasBN = fractionBN(\n hexToBN(blockGasLimit),\n MAX_GAS_BLOCK_PERCENT,\n 100,\n );\n\n const paddedGasBN = fractionBN(estimatedGasBN, multiplier * 100, 100);\n\n if (estimatedGasBN.gt(maxGasBN)) {\n const estimatedGasHex = add0x(estimatedGas);\n log('Using estimated value', estimatedGasHex);\n return estimatedGasHex;\n }\n\n if (paddedGasBN.lt(maxGasBN)) {\n const paddedHex = add0x(BNToHex(paddedGasBN));\n log('Using padded estimate', paddedHex, multiplier);\n return paddedHex;\n }\n\n const maxHex = add0x(BNToHex(maxGasBN));\n log('Using 90% of block gas limit', maxHex);\n return maxHex;\n}\n\n/**\n * Determine the gas for the provided request.\n *\n * @param request - The request object including the necessary parameters.\n * @returns The final gas value and the estimate used.\n */\nasync function getGas(\n request: UpdateGasRequest,\n): Promise<[string, TransactionMeta['simulationFails']?, string?]> {\n const { chainId, isCustomNetwork, isSimulationEnabled, txMeta } = request;\n const { disableGasBuffer } = txMeta;\n\n if (txMeta.txParams.gas) {\n log('Using value from request', txMeta.txParams.gas);\n return [txMeta.txParams.gas, undefined, txMeta.txParams.gas];\n }\n\n if (await requiresFixedGas(request)) {\n log('Using fixed value', FIXED_GAS);\n return [FIXED_GAS, undefined, FIXED_GAS];\n }\n\n const { blockGasLimit, estimatedGas, simulationFails } = await estimateGas({\n chainId: request.chainId,\n ethQuery: request.ethQuery,\n isSimulationEnabled,\n messenger: request.messenger,\n txParams: txMeta.txParams,\n });\n\n if (isCustomNetwork || simulationFails) {\n log(\n isCustomNetwork\n ? 'Using original estimate as custom network'\n : 'Using original fallback estimate as simulation failed',\n );\n return [estimatedGas, simulationFails, estimatedGas];\n }\n\n let finalGas = estimatedGas;\n\n if (!disableGasBuffer) {\n const bufferMultiplier =\n GAS_BUFFER_CHAIN_OVERRIDES[\n chainId as keyof typeof GAS_BUFFER_CHAIN_OVERRIDES\n ] ?? DEFAULT_GAS_MULTIPLIER;\n\n finalGas = addGasBuffer(estimatedGas, blockGasLimit, bufferMultiplier);\n }\n\n return [finalGas, simulationFails, estimatedGas];\n}\n\n/**\n * Determine if the gas for the provided request should be fixed.\n *\n * @param options - The options object.\n * @param options.ethQuery - The EthQuery instance to interact with the network.\n * @param options.txMeta - The transaction meta object.\n * @param options.isCustomNetwork - Whether the network is a custom network.\n * @returns Whether the gas should be fixed.\n */\nasync function requiresFixedGas({\n ethQuery,\n txMeta,\n isCustomNetwork,\n}: UpdateGasRequest): Promise<boolean> {\n const {\n txParams: { to, data },\n } = txMeta;\n\n if (isCustomNetwork || !to || data) {\n return false;\n }\n\n const code = await getCode(ethQuery, to);\n\n return !code || code === '0x';\n}\n\n/**\n * Get the contract code for the provided address.\n *\n * @param ethQuery - The EthQuery instance to interact with the network.\n * @param address - The address to get the code for.\n * @returns The contract code.\n */\nasync function getCode(\n ethQuery: EthQuery,\n address: string,\n): Promise<string | undefined> {\n return await query(ethQuery, 'getCode', [address]);\n}\n\n/**\n * Get the latest block from the network.\n *\n * @param ethQuery - The EthQuery instance to interact with the network.\n * @returns The latest block number.\n */\nasync function getLatestBlock(\n ethQuery: EthQuery,\n): Promise<{ gasLimit: string; number: string }> {\n return await query(ethQuery, 'getBlockByNumber', ['latest', false]);\n}\n\n/**\n * Estimate the gas for a type 4 transaction.\n *\n * @param txParams - The transaction parameters.\n * @param ethQuery - The EthQuery instance to interact with the network.\n * @param chainId - The chain ID of the transaction.\n * @returns The estimated gas.\n */\nasync function estimateGasUpgradeWithDataToSelf(\n txParams: TransactionParams,\n ethQuery: EthQuery,\n chainId: Hex,\n) {\n const upgradeGas = await query(ethQuery, 'estimateGas', [\n {\n ...txParams,\n data: '0x',\n },\n ]);\n\n log('Upgrade only gas', upgradeGas);\n\n const delegationAddress = txParams.authorizationList?.[0].address as Hex;\n\n const executeGas = await simulateGas({\n chainId: chainId as Hex,\n delegationAddress,\n transaction: txParams,\n });\n\n log('Execute gas', executeGas);\n\n const total = BNToHex(\n hexToBN(upgradeGas).add(hexToBN(executeGas)).subn(INTRINSIC_GAS),\n );\n\n log('Total type 4 gas', total);\n\n return total;\n}\n\n/**\n * Simulate the required gas using the simulation API.\n *\n * @param options - The options object.\n * @param options.chainId - The chain ID of the transaction.\n * @param options.delegationAddress - The delegation address of the sender to mock.\n * @param options.transaction - The transaction parameters.\n * @returns The simulated gas.\n */\nasync function simulateGas({\n chainId,\n delegationAddress,\n transaction,\n}: {\n chainId: Hex;\n delegationAddress?: Hex;\n transaction: TransactionParams;\n}): Promise<Hex> {\n const response = await simulateTransactions(chainId, {\n transactions: [\n {\n to: transaction.to as Hex,\n from: transaction.from as Hex,\n data: transaction.data as Hex,\n value: transaction.value as Hex,\n },\n ],\n overrides: {\n [transaction.from as string]: {\n code:\n delegationAddress &&\n ((DELEGATION_PREFIX + remove0x(delegationAddress)) as Hex),\n },\n },\n });\n\n const gasUsed = response?.transactions?.[0].gasUsed;\n\n if (!gasUsed) {\n throw new Error('No simulated gas returned');\n }\n\n return gasUsed;\n}\n\n/**\n * Populate the authorization list with dummy values.\n *\n * @param authorizationList - The authorization list to prepare.\n * @param chainId - The chain ID to use.\n * @returns The authorization list with dummy values.\n */\nfunction normalizeAuthorizationList(\n authorizationList: TransactionParams['authorizationList'],\n chainId: Hex,\n) {\n return authorizationList?.map((authorization) => ({\n ...authorization,\n chainId: authorization.chainId ?? chainId,\n nonce: authorization.nonce ?? '0x1',\n r: authorization.r ?? DUMMY_AUTHORIZATION_SIGNATURE,\n s: authorization.s ?? DUMMY_AUTHORIZATION_SIGNATURE,\n yParity: authorization.yParity ?? '0x1',\n }));\n}\n"]}
|
package/dist/utils/nonce.cjs
CHANGED
|
@@ -12,7 +12,10 @@ const log = (0, logger_1.createModuleLogger)(logger_1.projectLogger, 'nonce');
|
|
|
12
12
|
* @returns The next hexadecimal nonce to be used for the given transaction, and optionally a function to release the nonce lock.
|
|
13
13
|
*/
|
|
14
14
|
async function getNextNonce(txMeta, getNonceLock) {
|
|
15
|
-
const { customNonceValue, txParams: { from, nonce: existingNonce }, } = txMeta;
|
|
15
|
+
const { customNonceValue, isExternalSign, txParams: { from, nonce: existingNonce }, } = txMeta;
|
|
16
|
+
if (isExternalSign) {
|
|
17
|
+
return [undefined, undefined];
|
|
18
|
+
}
|
|
16
19
|
const customNonce = customNonceValue ? (0, controller_utils_1.toHex)(customNonceValue) : undefined;
|
|
17
20
|
if (customNonce) {
|
|
18
21
|
log('Using custom nonce', customNonce);
|
package/dist/utils/nonce.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nonce.cjs","sourceRoot":"","sources":["../../src/utils/nonce.ts"],"names":[],"mappings":";;;AAAA,iEAAmD;AAMnD,0CAA8D;AAG9D,MAAM,GAAG,GAAG,IAAA,2BAAkB,EAAC,sBAAa,EAAE,OAAO,CAAC,CAAC;AAEvD;;;;;;GAMG;AACI,KAAK,UAAU,YAAY,CAChC,MAAuB,EACvB,YAAqD;IAErD,MAAM,EACJ,gBAAgB,EAChB,QAAQ,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,aAAa,EAAE,GACzC,GAAG,MAAM,CAAC;IAEX,MAAM,WAAW,GAAG,gBAAgB,CAAC,CAAC,CAAC,IAAA,wBAAK,EAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAE3E,IAAI,WAAW,EAAE;QACf,GAAG,CAAC,oBAAoB,EAAE,WAAW,CAAC,CAAC;QACvC,OAAO,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;KACjC;IAED,IAAI,aAAa,EAAE;QACjB,GAAG,CAAC,sBAAsB,EAAE,aAAa,CAAC,CAAC;QAC3C,OAAO,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC;KACnC;IAED,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,CAAC;IAC3C,MAAM,KAAK,GAAG,IAAA,wBAAK,EAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IACzC,MAAM,WAAW,GAAG,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAE1D,GAAG,CAAC,gCAAgC,EAAE,KAAK,EAAE,SAAS,CAAC,YAAY,CAAC,CAAC;IAErE,OAAO,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;AAC9B,CAAC;
|
|
1
|
+
{"version":3,"file":"nonce.cjs","sourceRoot":"","sources":["../../src/utils/nonce.ts"],"names":[],"mappings":";;;AAAA,iEAAmD;AAMnD,0CAA8D;AAG9D,MAAM,GAAG,GAAG,IAAA,2BAAkB,EAAC,sBAAa,EAAE,OAAO,CAAC,CAAC;AAEvD;;;;;;GAMG;AACI,KAAK,UAAU,YAAY,CAChC,MAAuB,EACvB,YAAqD;IAErD,MAAM,EACJ,gBAAgB,EAChB,cAAc,EACd,QAAQ,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,aAAa,EAAE,GACzC,GAAG,MAAM,CAAC;IAEX,IAAI,cAAc,EAAE;QAClB,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;KAC/B;IAED,MAAM,WAAW,GAAG,gBAAgB,CAAC,CAAC,CAAC,IAAA,wBAAK,EAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAE3E,IAAI,WAAW,EAAE;QACf,GAAG,CAAC,oBAAoB,EAAE,WAAW,CAAC,CAAC;QACvC,OAAO,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;KACjC;IAED,IAAI,aAAa,EAAE;QACjB,GAAG,CAAC,sBAAsB,EAAE,aAAa,CAAC,CAAC;QAC3C,OAAO,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC;KACnC;IAED,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,CAAC;IAC3C,MAAM,KAAK,GAAG,IAAA,wBAAK,EAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IACzC,MAAM,WAAW,GAAG,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAE1D,GAAG,CAAC,gCAAgC,EAAE,KAAK,EAAE,SAAS,CAAC,YAAY,CAAC,CAAC;IAErE,OAAO,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;AAC9B,CAAC;AAjCD,oCAiCC;AAED;;;;;;;;GAQG;AACH,SAAgB,uCAAuC,CACrD,cAAsB,EACtB,WAAmB,EACnB,mBAAwC,EACxC,YAA+B;IAE/B,OAAO,YAAY;SAChB,MAAM,CACL,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,CACvE,CAAC,UAAU;QACX,CAAC,eAAe;QAChB,OAAO,KAAK,cAAc;QAC1B,mBAAmB,CAAC,QAAQ,CAAC,MAAM,CAAC;QACpC,IAAI,CAAC,WAAW,EAAE,KAAK,WAAW,CAAC,WAAW,EAAE,CACnD;SACA,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE;QACzD,4CAA4C;QAC5C,6DAA6D;QAC7D,kDAAkD;QAClD,0BAA0B;QAC1B,OAAO;YACL,MAAM;YACN,OAAO,EAAE,CAAC,EAAE,CAAC;YACb,QAAQ,EAAE;gBACR,IAAI,EAAE,IAAI,IAAI,EAAE;gBAChB,GAAG,EAAE,GAAG,IAAI,EAAE;gBACd,KAAK,EAAE,KAAK,IAAI,EAAE;gBAClB,KAAK,EAAE,KAAK,IAAI,EAAE;aACnB;SACF,CAAC;IACJ,CAAC,CAAC,CAAC;AACP,CAAC;AA/BD,0FA+BC","sourcesContent":["import { toHex } from '@metamask/controller-utils';\nimport type {\n NonceLock,\n Transaction as NonceTrackerTransaction,\n} from '@metamask/nonce-tracker';\n\nimport { createModuleLogger, projectLogger } from '../logger';\nimport type { TransactionMeta, TransactionStatus } from '../types';\n\nconst log = createModuleLogger(projectLogger, 'nonce');\n\n/**\n * Determine the next nonce to be used for a transaction.\n *\n * @param txMeta - The transaction metadata.\n * @param getNonceLock - An anonymous function that acquires the nonce lock for an address\n * @returns The next hexadecimal nonce to be used for the given transaction, and optionally a function to release the nonce lock.\n */\nexport async function getNextNonce(\n txMeta: TransactionMeta,\n getNonceLock: (address: string) => Promise<NonceLock>,\n): Promise<[string | undefined, (() => void) | undefined]> {\n const {\n customNonceValue,\n isExternalSign,\n txParams: { from, nonce: existingNonce },\n } = txMeta;\n\n if (isExternalSign) {\n return [undefined, undefined];\n }\n\n const customNonce = customNonceValue ? toHex(customNonceValue) : undefined;\n\n if (customNonce) {\n log('Using custom nonce', customNonce);\n return [customNonce, undefined];\n }\n\n if (existingNonce) {\n log('Using existing nonce', existingNonce);\n return [existingNonce, undefined];\n }\n\n const nonceLock = await getNonceLock(from);\n const nonce = toHex(nonceLock.nextNonce);\n const releaseLock = nonceLock.releaseLock.bind(nonceLock);\n\n log('Using nonce from nonce tracker', nonce, nonceLock.nonceDetails);\n\n return [nonce, releaseLock];\n}\n\n/**\n * Filter and format transactions for the nonce tracker.\n *\n * @param currentChainId - Chain ID of the current network.\n * @param fromAddress - Address of the account from which the transactions to filter from are sent.\n * @param transactionStatuses - 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 currentChainId: string,\n fromAddress: string,\n transactionStatuses: TransactionStatus[],\n transactions: TransactionMeta[],\n): NonceTrackerTransaction[] {\n return transactions\n .filter(\n ({ chainId, isTransfer, isUserOperation, status, txParams: { from } }) =>\n !isTransfer &&\n !isUserOperation &&\n chainId === currentChainId &&\n transactionStatuses.includes(status) &&\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 /* istanbul ignore next */\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"]}
|
package/dist/utils/nonce.d.cts
CHANGED
|
@@ -7,7 +7,7 @@ import type { TransactionMeta, TransactionStatus } from "../types.cjs";
|
|
|
7
7
|
* @param getNonceLock - An anonymous function that acquires the nonce lock for an address
|
|
8
8
|
* @returns The next hexadecimal nonce to be used for the given transaction, and optionally a function to release the nonce lock.
|
|
9
9
|
*/
|
|
10
|
-
export declare function getNextNonce(txMeta: TransactionMeta, getNonceLock: (address: string) => Promise<NonceLock>): Promise<[string, (() => void) | undefined]>;
|
|
10
|
+
export declare function getNextNonce(txMeta: TransactionMeta, getNonceLock: (address: string) => Promise<NonceLock>): Promise<[string | undefined, (() => void) | undefined]>;
|
|
11
11
|
/**
|
|
12
12
|
* Filter and format transactions for the nonce tracker.
|
|
13
13
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nonce.d.cts","sourceRoot":"","sources":["../../src/utils/nonce.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,SAAS,EACT,WAAW,IAAI,uBAAuB,EACvC,gCAAgC;AAGjC,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,qBAAiB;AAInE;;;;;;GAMG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,eAAe,EACvB,YAAY,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAAC,GACpD,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"nonce.d.cts","sourceRoot":"","sources":["../../src/utils/nonce.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,SAAS,EACT,WAAW,IAAI,uBAAuB,EACvC,gCAAgC;AAGjC,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,qBAAiB;AAInE;;;;;;GAMG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,eAAe,EACvB,YAAY,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAAC,GACpD,OAAO,CAAC,CAAC,MAAM,GAAG,SAAS,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC,CAAC,CA8BzD;AAED;;;;;;;;GAQG;AACH,wBAAgB,uCAAuC,CACrD,cAAc,EAAE,MAAM,EACtB,WAAW,EAAE,MAAM,EACnB,mBAAmB,EAAE,iBAAiB,EAAE,EACxC,YAAY,EAAE,eAAe,EAAE,GAC9B,uBAAuB,EAAE,CA0B3B"}
|
package/dist/utils/nonce.d.mts
CHANGED
|
@@ -7,7 +7,7 @@ import type { TransactionMeta, TransactionStatus } from "../types.mjs";
|
|
|
7
7
|
* @param getNonceLock - An anonymous function that acquires the nonce lock for an address
|
|
8
8
|
* @returns The next hexadecimal nonce to be used for the given transaction, and optionally a function to release the nonce lock.
|
|
9
9
|
*/
|
|
10
|
-
export declare function getNextNonce(txMeta: TransactionMeta, getNonceLock: (address: string) => Promise<NonceLock>): Promise<[string, (() => void) | undefined]>;
|
|
10
|
+
export declare function getNextNonce(txMeta: TransactionMeta, getNonceLock: (address: string) => Promise<NonceLock>): Promise<[string | undefined, (() => void) | undefined]>;
|
|
11
11
|
/**
|
|
12
12
|
* Filter and format transactions for the nonce tracker.
|
|
13
13
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nonce.d.mts","sourceRoot":"","sources":["../../src/utils/nonce.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,SAAS,EACT,WAAW,IAAI,uBAAuB,EACvC,gCAAgC;AAGjC,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,qBAAiB;AAInE;;;;;;GAMG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,eAAe,EACvB,YAAY,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAAC,GACpD,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"nonce.d.mts","sourceRoot":"","sources":["../../src/utils/nonce.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,SAAS,EACT,WAAW,IAAI,uBAAuB,EACvC,gCAAgC;AAGjC,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,qBAAiB;AAInE;;;;;;GAMG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,eAAe,EACvB,YAAY,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAAC,GACpD,OAAO,CAAC,CAAC,MAAM,GAAG,SAAS,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC,CAAC,CA8BzD;AAED;;;;;;;;GAQG;AACH,wBAAgB,uCAAuC,CACrD,cAAc,EAAE,MAAM,EACtB,WAAW,EAAE,MAAM,EACnB,mBAAmB,EAAE,iBAAiB,EAAE,EACxC,YAAY,EAAE,eAAe,EAAE,GAC9B,uBAAuB,EAAE,CA0B3B"}
|
package/dist/utils/nonce.mjs
CHANGED
|
@@ -9,7 +9,10 @@ const log = createModuleLogger(projectLogger, 'nonce');
|
|
|
9
9
|
* @returns The next hexadecimal nonce to be used for the given transaction, and optionally a function to release the nonce lock.
|
|
10
10
|
*/
|
|
11
11
|
export async function getNextNonce(txMeta, getNonceLock) {
|
|
12
|
-
const { customNonceValue, txParams: { from, nonce: existingNonce }, } = txMeta;
|
|
12
|
+
const { customNonceValue, isExternalSign, txParams: { from, nonce: existingNonce }, } = txMeta;
|
|
13
|
+
if (isExternalSign) {
|
|
14
|
+
return [undefined, undefined];
|
|
15
|
+
}
|
|
13
16
|
const customNonce = customNonceValue ? toHex(customNonceValue) : undefined;
|
|
14
17
|
if (customNonce) {
|
|
15
18
|
log('Using custom nonce', customNonce);
|
package/dist/utils/nonce.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nonce.mjs","sourceRoot":"","sources":["../../src/utils/nonce.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,mCAAmC;AAMnD,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,sBAAkB;AAG9D,MAAM,GAAG,GAAG,kBAAkB,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;AAEvD;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,MAAuB,EACvB,YAAqD;IAErD,MAAM,EACJ,gBAAgB,EAChB,QAAQ,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,aAAa,EAAE,GACzC,GAAG,MAAM,CAAC;IAEX,MAAM,WAAW,GAAG,gBAAgB,CAAC,CAAC,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAE3E,IAAI,WAAW,EAAE;QACf,GAAG,CAAC,oBAAoB,EAAE,WAAW,CAAC,CAAC;QACvC,OAAO,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;KACjC;IAED,IAAI,aAAa,EAAE;QACjB,GAAG,CAAC,sBAAsB,EAAE,aAAa,CAAC,CAAC;QAC3C,OAAO,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC;KACnC;IAED,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,CAAC;IAC3C,MAAM,KAAK,GAAG,KAAK,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IACzC,MAAM,WAAW,GAAG,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAE1D,GAAG,CAAC,gCAAgC,EAAE,KAAK,EAAE,SAAS,CAAC,YAAY,CAAC,CAAC;IAErE,OAAO,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;AAC9B,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,uCAAuC,CACrD,cAAsB,EACtB,WAAmB,EACnB,mBAAwC,EACxC,YAA+B;IAE/B,OAAO,YAAY;SAChB,MAAM,CACL,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,CACvE,CAAC,UAAU;QACX,CAAC,eAAe;QAChB,OAAO,KAAK,cAAc;QAC1B,mBAAmB,CAAC,QAAQ,CAAC,MAAM,CAAC;QACpC,IAAI,CAAC,WAAW,EAAE,KAAK,WAAW,CAAC,WAAW,EAAE,CACnD;SACA,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE;QACzD,4CAA4C;QAC5C,6DAA6D;QAC7D,kDAAkD;QAClD,0BAA0B;QAC1B,OAAO;YACL,MAAM;YACN,OAAO,EAAE,CAAC,EAAE,CAAC;YACb,QAAQ,EAAE;gBACR,IAAI,EAAE,IAAI,IAAI,EAAE;gBAChB,GAAG,EAAE,GAAG,IAAI,EAAE;gBACd,KAAK,EAAE,KAAK,IAAI,EAAE;gBAClB,KAAK,EAAE,KAAK,IAAI,EAAE;aACnB;SACF,CAAC;IACJ,CAAC,CAAC,CAAC;AACP,CAAC","sourcesContent":["import { toHex } from '@metamask/controller-utils';\nimport type {\n NonceLock,\n Transaction as NonceTrackerTransaction,\n} from '@metamask/nonce-tracker';\n\nimport { createModuleLogger, projectLogger } from '../logger';\nimport type { TransactionMeta, TransactionStatus } from '../types';\n\nconst log = createModuleLogger(projectLogger, 'nonce');\n\n/**\n * Determine the next nonce to be used for a transaction.\n *\n * @param txMeta - The transaction metadata.\n * @param getNonceLock - An anonymous function that acquires the nonce lock for an address\n * @returns The next hexadecimal nonce to be used for the given transaction, and optionally a function to release the nonce lock.\n */\nexport async function getNextNonce(\n txMeta: TransactionMeta,\n getNonceLock: (address: string) => Promise<NonceLock>,\n): Promise<[string, (() => void) | undefined]> {\n const {\n customNonceValue,\n txParams: { from, nonce: existingNonce },\n } = txMeta;\n\n const customNonce = customNonceValue ? toHex(customNonceValue) : undefined;\n\n if (customNonce) {\n log('Using custom nonce', customNonce);\n return [customNonce, undefined];\n }\n\n if (existingNonce) {\n log('Using existing nonce', existingNonce);\n return [existingNonce, undefined];\n }\n\n const nonceLock = await getNonceLock(from);\n const nonce = toHex(nonceLock.nextNonce);\n const releaseLock = nonceLock.releaseLock.bind(nonceLock);\n\n log('Using nonce from nonce tracker', nonce, nonceLock.nonceDetails);\n\n return [nonce, releaseLock];\n}\n\n/**\n * Filter and format transactions for the nonce tracker.\n *\n * @param currentChainId - Chain ID of the current network.\n * @param fromAddress - Address of the account from which the transactions to filter from are sent.\n * @param transactionStatuses - 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 currentChainId: string,\n fromAddress: string,\n transactionStatuses: TransactionStatus[],\n transactions: TransactionMeta[],\n): NonceTrackerTransaction[] {\n return transactions\n .filter(\n ({ chainId, isTransfer, isUserOperation, status, txParams: { from } }) =>\n !isTransfer &&\n !isUserOperation &&\n chainId === currentChainId &&\n transactionStatuses.includes(status) &&\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 /* istanbul ignore next */\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"]}
|
|
1
|
+
{"version":3,"file":"nonce.mjs","sourceRoot":"","sources":["../../src/utils/nonce.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,mCAAmC;AAMnD,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,sBAAkB;AAG9D,MAAM,GAAG,GAAG,kBAAkB,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;AAEvD;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,MAAuB,EACvB,YAAqD;IAErD,MAAM,EACJ,gBAAgB,EAChB,cAAc,EACd,QAAQ,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,aAAa,EAAE,GACzC,GAAG,MAAM,CAAC;IAEX,IAAI,cAAc,EAAE;QAClB,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;KAC/B;IAED,MAAM,WAAW,GAAG,gBAAgB,CAAC,CAAC,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAE3E,IAAI,WAAW,EAAE;QACf,GAAG,CAAC,oBAAoB,EAAE,WAAW,CAAC,CAAC;QACvC,OAAO,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;KACjC;IAED,IAAI,aAAa,EAAE;QACjB,GAAG,CAAC,sBAAsB,EAAE,aAAa,CAAC,CAAC;QAC3C,OAAO,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC;KACnC;IAED,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,CAAC;IAC3C,MAAM,KAAK,GAAG,KAAK,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IACzC,MAAM,WAAW,GAAG,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAE1D,GAAG,CAAC,gCAAgC,EAAE,KAAK,EAAE,SAAS,CAAC,YAAY,CAAC,CAAC;IAErE,OAAO,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;AAC9B,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,uCAAuC,CACrD,cAAsB,EACtB,WAAmB,EACnB,mBAAwC,EACxC,YAA+B;IAE/B,OAAO,YAAY;SAChB,MAAM,CACL,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,CACvE,CAAC,UAAU;QACX,CAAC,eAAe;QAChB,OAAO,KAAK,cAAc;QAC1B,mBAAmB,CAAC,QAAQ,CAAC,MAAM,CAAC;QACpC,IAAI,CAAC,WAAW,EAAE,KAAK,WAAW,CAAC,WAAW,EAAE,CACnD;SACA,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE;QACzD,4CAA4C;QAC5C,6DAA6D;QAC7D,kDAAkD;QAClD,0BAA0B;QAC1B,OAAO;YACL,MAAM;YACN,OAAO,EAAE,CAAC,EAAE,CAAC;YACb,QAAQ,EAAE;gBACR,IAAI,EAAE,IAAI,IAAI,EAAE;gBAChB,GAAG,EAAE,GAAG,IAAI,EAAE;gBACd,KAAK,EAAE,KAAK,IAAI,EAAE;gBAClB,KAAK,EAAE,KAAK,IAAI,EAAE;aACnB;SACF,CAAC;IACJ,CAAC,CAAC,CAAC;AACP,CAAC","sourcesContent":["import { toHex } from '@metamask/controller-utils';\nimport type {\n NonceLock,\n Transaction as NonceTrackerTransaction,\n} from '@metamask/nonce-tracker';\n\nimport { createModuleLogger, projectLogger } from '../logger';\nimport type { TransactionMeta, TransactionStatus } from '../types';\n\nconst log = createModuleLogger(projectLogger, 'nonce');\n\n/**\n * Determine the next nonce to be used for a transaction.\n *\n * @param txMeta - The transaction metadata.\n * @param getNonceLock - An anonymous function that acquires the nonce lock for an address\n * @returns The next hexadecimal nonce to be used for the given transaction, and optionally a function to release the nonce lock.\n */\nexport async function getNextNonce(\n txMeta: TransactionMeta,\n getNonceLock: (address: string) => Promise<NonceLock>,\n): Promise<[string | undefined, (() => void) | undefined]> {\n const {\n customNonceValue,\n isExternalSign,\n txParams: { from, nonce: existingNonce },\n } = txMeta;\n\n if (isExternalSign) {\n return [undefined, undefined];\n }\n\n const customNonce = customNonceValue ? toHex(customNonceValue) : undefined;\n\n if (customNonce) {\n log('Using custom nonce', customNonce);\n return [customNonce, undefined];\n }\n\n if (existingNonce) {\n log('Using existing nonce', existingNonce);\n return [existingNonce, undefined];\n }\n\n const nonceLock = await getNonceLock(from);\n const nonce = toHex(nonceLock.nextNonce);\n const releaseLock = nonceLock.releaseLock.bind(nonceLock);\n\n log('Using nonce from nonce tracker', nonce, nonceLock.nonceDetails);\n\n return [nonce, releaseLock];\n}\n\n/**\n * Filter and format transactions for the nonce tracker.\n *\n * @param currentChainId - Chain ID of the current network.\n * @param fromAddress - Address of the account from which the transactions to filter from are sent.\n * @param transactionStatuses - 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 currentChainId: string,\n fromAddress: string,\n transactionStatuses: TransactionStatus[],\n transactions: TransactionMeta[],\n): NonceTrackerTransaction[] {\n return transactions\n .filter(\n ({ chainId, isTransfer, isUserOperation, status, txParams: { from } }) =>\n !isTransfer &&\n !isUserOperation &&\n chainId === currentChainId &&\n transactionStatuses.includes(status) &&\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 /* istanbul ignore next */\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"]}
|
|
@@ -43,6 +43,9 @@ async function validateTransactionOrigin({ data, from, internalAccounts, origin,
|
|
|
43
43
|
if (isExternal && permittedAddresses && !permittedAddresses.includes(from)) {
|
|
44
44
|
throw rpc_errors_1.providerErrors.unauthorized({ data: { origin } });
|
|
45
45
|
}
|
|
46
|
+
if (type === types_1.TransactionType.batch) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
46
49
|
if (isExternal &&
|
|
47
50
|
(authorizationList || envelopeType === types_1.TransactionEnvelopeType.setCode)) {
|
|
48
51
|
throw rpc_errors_1.rpcErrors.invalidParams('External EIP-7702 transactions are not supported');
|
|
@@ -50,8 +53,7 @@ async function validateTransactionOrigin({ data, from, internalAccounts, origin,
|
|
|
50
53
|
const hasData = Boolean(data && data !== '0x');
|
|
51
54
|
if (isExternal &&
|
|
52
55
|
hasData &&
|
|
53
|
-
internalAccounts?.some((account) => account.toLowerCase() === to?.toLowerCase())
|
|
54
|
-
type !== types_1.TransactionType.batch) {
|
|
56
|
+
internalAccounts?.some((account) => account.toLowerCase() === to?.toLowerCase())) {
|
|
55
57
|
throw rpc_errors_1.rpcErrors.invalidParams('External transactions to internal accounts cannot include data');
|
|
56
58
|
}
|
|
57
59
|
}
|
|
@@ -62,15 +64,16 @@ exports.validateTransactionOrigin = validateTransactionOrigin;
|
|
|
62
64
|
*
|
|
63
65
|
* @param txParams - Transaction params object to validate.
|
|
64
66
|
* @param isEIP1559Compatible - whether or not the current network supports EIP-1559 transactions.
|
|
67
|
+
* @param chainId - The chain ID of the transaction.
|
|
65
68
|
*/
|
|
66
|
-
function validateTxParams(txParams, isEIP1559Compatible = true) {
|
|
69
|
+
function validateTxParams(txParams, isEIP1559Compatible = true, chainId) {
|
|
67
70
|
validateEnvelopeType(txParams.type);
|
|
68
71
|
validateEIP1559Compatibility(txParams, isEIP1559Compatible);
|
|
69
72
|
validateParamFrom(txParams.from);
|
|
70
73
|
validateParamRecipient(txParams);
|
|
71
74
|
validateParamValue(txParams.value);
|
|
72
75
|
validateParamData(txParams.data);
|
|
73
|
-
validateParamChainId(txParams.chainId);
|
|
76
|
+
validateParamChainId(txParams.chainId, chainId);
|
|
74
77
|
validateGasFeeParams(txParams);
|
|
75
78
|
validateAuthorizationList(txParams);
|
|
76
79
|
}
|
|
@@ -225,16 +228,14 @@ function validateParamData(value) {
|
|
|
225
228
|
/**
|
|
226
229
|
* Validates chainId type.
|
|
227
230
|
*
|
|
228
|
-
* @param
|
|
231
|
+
* @param chainIdParams - The chain ID to validate.
|
|
232
|
+
* @param chainIdNetworkClient - The chain ID of the network client.
|
|
229
233
|
*/
|
|
230
|
-
function validateParamChainId(
|
|
231
|
-
if (
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
throw rpc_errors_1.rpcErrors.invalidParams(
|
|
235
|
-
// TODO: Either fix this lint violation or explain why it's necessary to ignore.
|
|
236
|
-
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
237
|
-
`Invalid transaction params: chainId is not a Number or hex string. got: (${chainId})`);
|
|
234
|
+
function validateParamChainId(chainIdParams, chainIdNetworkClient) {
|
|
235
|
+
if (chainIdParams &&
|
|
236
|
+
chainIdNetworkClient &&
|
|
237
|
+
chainIdParams.toLowerCase?.() !== chainIdNetworkClient.toLowerCase()) {
|
|
238
|
+
throw rpc_errors_1.rpcErrors.invalidParams(`Invalid transaction params: chainId must match the network client, got: ${chainIdParams}, expected: ${chainIdNetworkClient}`);
|
|
238
239
|
}
|
|
239
240
|
}
|
|
240
241
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.cjs","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';\nimport { isStrictHexString, remove0x } from '@metamask/utils';\n\nimport { isEIP1559Transaction } from './utils';\nimport type { Authorization, TransactionBatchRequest } from '../types';\nimport {\n TransactionEnvelopeType,\n TransactionType,\n type TransactionParams,\n} from '../types';\n\nconst TRANSACTION_ENVELOPE_TYPES_FEE_MARKET = [\n TransactionEnvelopeType.feeMarket,\n TransactionEnvelopeType.setCode,\n];\n\ntype GasFieldsToValidate =\n | 'gasPrice'\n | 'maxFeePerGas'\n | 'maxPriorityFeePerGas'\n | 'gas'\n | 'gasLimit';\n\n/**\n * Validates whether a transaction initiated by a specific 'from' address is permitted by the origin.\n *\n * @param options - Options bag.\n * @param options.data - The data included in the transaction.\n * @param options.from - The address from which the transaction is initiated.\n * @param options.internalAccounts - The internal accounts added to the wallet.\n * @param options.origin - The origin or source of the transaction.\n * @param options.permittedAddresses - The permitted accounts for the given origin.\n * @param options.selectedAddress - The currently selected Ethereum address in the wallet.\n * @param options.txParams - The transaction parameters.\n * @param options.type - The transaction type.\n * @throws Throws an error if the transaction is not permitted.\n */\nexport async function validateTransactionOrigin({\n data,\n from,\n internalAccounts,\n origin,\n permittedAddresses,\n selectedAddress,\n txParams,\n type,\n}: {\n data?: string;\n from: string;\n internalAccounts?: string[];\n origin?: string;\n permittedAddresses?: string[];\n selectedAddress?: string;\n txParams: TransactionParams;\n type?: TransactionType;\n}) {\n const isInternal = origin === ORIGIN_METAMASK;\n const isExternal = origin && origin !== ORIGIN_METAMASK;\n const { authorizationList, to, type: envelopeType } = txParams;\n\n if (isInternal && 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\n if (isExternal && permittedAddresses && !permittedAddresses.includes(from)) {\n throw providerErrors.unauthorized({ data: { origin } });\n }\n\n if (\n isExternal &&\n (authorizationList || envelopeType === TransactionEnvelopeType.setCode)\n ) {\n throw rpcErrors.invalidParams(\n 'External EIP-7702 transactions are not supported',\n );\n }\n\n const hasData = Boolean(data && data !== '0x');\n\n if (\n isExternal &&\n hasData &&\n internalAccounts?.some(\n (account) => account.toLowerCase() === to?.toLowerCase(),\n ) &&\n type !== TransactionType.batch\n ) {\n throw rpcErrors.invalidParams(\n 'External transactions to internal accounts cannot include data',\n );\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 validateEnvelopeType(txParams.type);\n validateEIP1559Compatibility(txParams, isEIP1559Compatible);\n validateParamFrom(txParams.from);\n validateParamRecipient(txParams);\n validateParamValue(txParams.value);\n validateParamData(txParams.data);\n validateParamChainId(txParams.chainId);\n validateGasFeeParams(txParams);\n validateAuthorizationList(txParams);\n}\n\n/**\n * Validates the `type` property, ensuring that if it is specified, it is a valid transaction envelope type.\n *\n * @param type - The transaction envelope type to validate.\n * @throws Throws invalid params if the type is not a valid transaction envelope type.\n */\nfunction validateEnvelopeType(type: string | undefined) {\n if (\n type &&\n !Object.values(TransactionEnvelopeType).includes(\n type as TransactionEnvelopeType,\n )\n ) {\n throw rpcErrors.invalidParams(\n `Invalid transaction envelope type: \"${type}\". Must be one of: ${Object.values(\n TransactionEnvelopeType,\n ).join(', ')}`,\n );\n }\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 transaction value \"${value}\": not a positive number.`,\n );\n }\n\n if (value.includes('.')) {\n throw rpcErrors.invalidParams(\n `Invalid transaction value \"${value}\": number must be 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 transaction 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 rpcErrors.invalidParams(`Invalid \"to\" address.`);\n }\n } else if (txParams.to !== undefined && !isValidHexAddress(txParams.to)) {\n throw rpcErrors.invalidParams(`Invalid \"to\" address.`);\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') {\n throw rpcErrors.invalidParams(\n `Invalid \"from\" address ${from}: not a string.`,\n );\n }\n if (!isValidHexAddress(from)) {\n throw rpcErrors.invalidParams('Invalid \"from\" address.');\n }\n}\n\n/**\n * Validates the recipient address in a transaction's parameters.\n *\n * @param to - The to property to validate.\n * @throws Throws an error if the recipient address is invalid.\n */\nexport function validateParamTo(to?: string) {\n if (!to || typeof to !== 'string') {\n throw rpcErrors.invalidParams(`Invalid \"to\" address`);\n }\n}\n\n/**\n * Validates a transaction batch request.\n *\n * @param options - Options bag.\n * @param options.internalAccounts - The internal accounts added to the wallet.\n * @param options.request - The batch request object.\n * @param options.sizeLimit - The maximum number of calls allowed in a batch request.\n */\nexport function validateBatchRequest({\n internalAccounts,\n request,\n sizeLimit,\n}: {\n internalAccounts: string[];\n request: TransactionBatchRequest;\n sizeLimit: number;\n}) {\n const { origin } = request;\n const isExternal = origin && origin !== ORIGIN_METAMASK;\n\n const transactionTargetsNormalized = request.transactions.map((tx) =>\n tx.params.to?.toLowerCase(),\n );\n\n const internalAccountsNormalized = internalAccounts.map((account) =>\n account.toLowerCase(),\n );\n\n if (\n isExternal &&\n transactionTargetsNormalized.some((target) =>\n internalAccountsNormalized.includes(target as string),\n )\n ) {\n throw rpcErrors.invalidParams(\n 'Calls to internal accounts are not supported',\n );\n }\n\n if (isExternal && request.transactions.length > sizeLimit) {\n throw rpcErrors.invalidParams(\n `Batch size cannot exceed ${sizeLimit}. got: ${request.transactions.length}`,\n );\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 // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\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 // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n `Invalid transaction params: chainId is not a Number or hex string. got: (${chainId})`,\n );\n }\n}\n\n/**\n * Validates gas values.\n *\n * @param txParams - The transaction parameters to validate.\n */\nfunction validateGasFeeParams(txParams: TransactionParams) {\n if (txParams.gasPrice) {\n ensureProperTransactionEnvelopeTypeProvided(txParams, 'gasPrice');\n ensureMutuallyExclusiveFieldsNotProvided(\n txParams,\n 'gasPrice',\n 'maxFeePerGas',\n );\n ensureMutuallyExclusiveFieldsNotProvided(\n txParams,\n 'gasPrice',\n 'maxPriorityFeePerGas',\n );\n ensureFieldIsValidHex(txParams, 'gasPrice');\n }\n\n if (txParams.maxFeePerGas) {\n ensureProperTransactionEnvelopeTypeProvided(txParams, 'maxFeePerGas');\n ensureMutuallyExclusiveFieldsNotProvided(\n txParams,\n 'maxFeePerGas',\n 'gasPrice',\n );\n ensureFieldIsValidHex(txParams, 'maxFeePerGas');\n }\n\n if (txParams.maxPriorityFeePerGas) {\n ensureProperTransactionEnvelopeTypeProvided(\n txParams,\n 'maxPriorityFeePerGas',\n );\n ensureMutuallyExclusiveFieldsNotProvided(\n txParams,\n 'maxPriorityFeePerGas',\n 'gasPrice',\n );\n ensureFieldIsValidHex(txParams, 'maxPriorityFeePerGas');\n }\n\n if (txParams.gasLimit) {\n ensureFieldIsValidHex(txParams, 'gasLimit');\n }\n\n if (txParams.gas) {\n ensureFieldIsValidHex(txParams, 'gas');\n }\n}\n\n/**\n * Ensures that the provided txParams has the proper 'type' specified for the\n * given field, if it is provided. If types do not match throws an\n * invalidParams error.\n *\n * @param txParams - The transaction parameters object\n * @param field - The current field being validated\n * @throws {ethErrors.rpc.invalidParams} Throws if type does not match the\n * expectations for provided field.\n */\nfunction ensureProperTransactionEnvelopeTypeProvided(\n txParams: TransactionParams,\n field: keyof TransactionParams,\n) {\n const type = txParams.type as TransactionEnvelopeType | undefined;\n\n switch (field) {\n case 'authorizationList':\n if (type && type !== TransactionEnvelopeType.setCode) {\n throw rpcErrors.invalidParams(\n `Invalid transaction envelope type: specified type \"${type}\" but including authorizationList requires type: \"${TransactionEnvelopeType.setCode}\"`,\n );\n }\n break;\n case 'maxFeePerGas':\n case 'maxPriorityFeePerGas':\n if (\n type &&\n !TRANSACTION_ENVELOPE_TYPES_FEE_MARKET.includes(\n type as TransactionEnvelopeType,\n )\n ) {\n throw rpcErrors.invalidParams(\n `Invalid transaction envelope type: specified type \"${type}\" but including maxFeePerGas and maxPriorityFeePerGas requires type: \"${TRANSACTION_ENVELOPE_TYPES_FEE_MARKET.join(', ')}\"`,\n );\n }\n break;\n case 'gasPrice':\n default:\n if (\n type &&\n TRANSACTION_ENVELOPE_TYPES_FEE_MARKET.includes(\n type as TransactionEnvelopeType,\n )\n ) {\n throw rpcErrors.invalidParams(\n `Invalid transaction envelope type: specified type \"${type}\" but included a gasPrice instead of maxFeePerGas and maxPriorityFeePerGas`,\n );\n }\n }\n}\n\n/**\n * Given two fields, ensure that the second field is not included in txParams,\n * and if it is throw an invalidParams error.\n *\n * @param txParams - The transaction parameters object\n * @param fieldBeingValidated - The current field being validated\n * @param mutuallyExclusiveField - The field to ensure is not provided\n * @throws {ethErrors.rpc.invalidParams} Throws if mutuallyExclusiveField is\n * present in txParams.\n */\nfunction ensureMutuallyExclusiveFieldsNotProvided(\n txParams: TransactionParams,\n fieldBeingValidated: GasFieldsToValidate,\n mutuallyExclusiveField: GasFieldsToValidate,\n) {\n if (typeof txParams[mutuallyExclusiveField] !== 'undefined') {\n throw rpcErrors.invalidParams(\n `Invalid transaction params: specified ${fieldBeingValidated} but also included ${mutuallyExclusiveField}, these cannot be mixed`,\n );\n }\n}\n\n/**\n * Ensures that the provided value for field is a valid hexadecimal.\n * Throws an invalidParams error if field is not a valid hexadecimal.\n *\n * @param data - The object containing the field\n * @param field - The current field being validated\n * @throws {rpcErrors.invalidParams} Throws if field is not a valid hexadecimal\n */\nfunction ensureFieldIsValidHex<T>(data: T, field: keyof T) {\n const value = data[field];\n if (typeof value !== 'string' || !isStrictHexString(value)) {\n throw rpcErrors.invalidParams(\n `Invalid transaction params: ${String(field)} is not a valid hexadecimal string. got: (${String(\n value,\n )})`,\n );\n }\n}\n\n/**\n * Validate the authorization list property in the transaction parameters.\n *\n * @param txParams - The transaction parameters containing the authorization list to validate.\n */\nfunction validateAuthorizationList(txParams: TransactionParams) {\n const { authorizationList } = txParams;\n\n if (!authorizationList) {\n return;\n }\n\n ensureProperTransactionEnvelopeTypeProvided(txParams, 'authorizationList');\n\n if (!Array.isArray(authorizationList)) {\n throw rpcErrors.invalidParams(\n `Invalid transaction params: authorizationList must be an array`,\n );\n }\n\n for (const authorization of authorizationList) {\n validateAuthorization(authorization);\n }\n}\n\n/**\n * Validate an authorization object.\n *\n * @param authorization - The authorization object to validate.\n */\nfunction validateAuthorization(authorization: Authorization) {\n ensureFieldIsValidHex(authorization, 'address');\n validateHexLength(authorization.address, 20, 'address');\n\n for (const field of ['chainId', 'nonce', 'r', 's'] as const) {\n if (authorization[field]) {\n ensureFieldIsValidHex(authorization, field);\n }\n }\n\n const { yParity } = authorization;\n\n if (yParity && !['0x', '0x1'].includes(yParity)) {\n throw rpcErrors.invalidParams(\n `Invalid transaction params: yParity must be '0x' or '0x1'. got: ${yParity}`,\n );\n }\n}\n\n/**\n * Validate the number of bytes in a hex string.\n *\n * @param value - The hex string to validate.\n * @param lengthBytes - The expected length in bytes.\n * @param fieldName - The name of the field being validated.\n */\nfunction validateHexLength(\n value: string,\n lengthBytes: number,\n fieldName: string,\n) {\n const actualLengthBytes = remove0x(value).length / 2;\n\n if (actualLengthBytes !== lengthBytes) {\n throw rpcErrors.invalidParams(\n `Invalid transaction params: ${fieldName} must be ${lengthBytes} bytes. got: ${actualLengthBytes} bytes`,\n );\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"validation.cjs","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';\nimport type { Hex } from '@metamask/utils';\nimport { isStrictHexString, remove0x } from '@metamask/utils';\n\nimport { isEIP1559Transaction } from './utils';\nimport type { Authorization, TransactionBatchRequest } from '../types';\nimport {\n TransactionEnvelopeType,\n TransactionType,\n type TransactionParams,\n} from '../types';\n\nconst TRANSACTION_ENVELOPE_TYPES_FEE_MARKET = [\n TransactionEnvelopeType.feeMarket,\n TransactionEnvelopeType.setCode,\n];\n\ntype GasFieldsToValidate =\n | 'gasPrice'\n | 'maxFeePerGas'\n | 'maxPriorityFeePerGas'\n | 'gas'\n | 'gasLimit';\n\n/**\n * Validates whether a transaction initiated by a specific 'from' address is permitted by the origin.\n *\n * @param options - Options bag.\n * @param options.data - The data included in the transaction.\n * @param options.from - The address from which the transaction is initiated.\n * @param options.internalAccounts - The internal accounts added to the wallet.\n * @param options.origin - The origin or source of the transaction.\n * @param options.permittedAddresses - The permitted accounts for the given origin.\n * @param options.selectedAddress - The currently selected Ethereum address in the wallet.\n * @param options.txParams - The transaction parameters.\n * @param options.type - The transaction type.\n * @throws Throws an error if the transaction is not permitted.\n */\nexport async function validateTransactionOrigin({\n data,\n from,\n internalAccounts,\n origin,\n permittedAddresses,\n selectedAddress,\n txParams,\n type,\n}: {\n data?: string;\n from: string;\n internalAccounts?: string[];\n origin?: string;\n permittedAddresses?: string[];\n selectedAddress?: string;\n txParams: TransactionParams;\n type?: TransactionType;\n}) {\n const isInternal = origin === ORIGIN_METAMASK;\n const isExternal = origin && origin !== ORIGIN_METAMASK;\n const { authorizationList, to, type: envelopeType } = txParams;\n\n if (isInternal && 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\n if (isExternal && permittedAddresses && !permittedAddresses.includes(from)) {\n throw providerErrors.unauthorized({ data: { origin } });\n }\n\n if (type === TransactionType.batch) {\n return;\n }\n\n if (\n isExternal &&\n (authorizationList || envelopeType === TransactionEnvelopeType.setCode)\n ) {\n throw rpcErrors.invalidParams(\n 'External EIP-7702 transactions are not supported',\n );\n }\n\n const hasData = Boolean(data && data !== '0x');\n\n if (\n isExternal &&\n hasData &&\n internalAccounts?.some(\n (account) => account.toLowerCase() === to?.toLowerCase(),\n )\n ) {\n throw rpcErrors.invalidParams(\n 'External transactions to internal accounts cannot include data',\n );\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 * @param chainId - The chain ID of the transaction.\n */\nexport function validateTxParams(\n txParams: TransactionParams,\n isEIP1559Compatible = true,\n chainId?: Hex,\n) {\n validateEnvelopeType(txParams.type);\n validateEIP1559Compatibility(txParams, isEIP1559Compatible);\n validateParamFrom(txParams.from);\n validateParamRecipient(txParams);\n validateParamValue(txParams.value);\n validateParamData(txParams.data);\n validateParamChainId(txParams.chainId, chainId);\n validateGasFeeParams(txParams);\n validateAuthorizationList(txParams);\n}\n\n/**\n * Validates the `type` property, ensuring that if it is specified, it is a valid transaction envelope type.\n *\n * @param type - The transaction envelope type to validate.\n * @throws Throws invalid params if the type is not a valid transaction envelope type.\n */\nfunction validateEnvelopeType(type: string | undefined) {\n if (\n type &&\n !Object.values(TransactionEnvelopeType).includes(\n type as TransactionEnvelopeType,\n )\n ) {\n throw rpcErrors.invalidParams(\n `Invalid transaction envelope type: \"${type}\". Must be one of: ${Object.values(\n TransactionEnvelopeType,\n ).join(', ')}`,\n );\n }\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 transaction value \"${value}\": not a positive number.`,\n );\n }\n\n if (value.includes('.')) {\n throw rpcErrors.invalidParams(\n `Invalid transaction value \"${value}\": number must be 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 transaction 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 rpcErrors.invalidParams(`Invalid \"to\" address.`);\n }\n } else if (txParams.to !== undefined && !isValidHexAddress(txParams.to)) {\n throw rpcErrors.invalidParams(`Invalid \"to\" address.`);\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') {\n throw rpcErrors.invalidParams(\n `Invalid \"from\" address ${from}: not a string.`,\n );\n }\n if (!isValidHexAddress(from)) {\n throw rpcErrors.invalidParams('Invalid \"from\" address.');\n }\n}\n\n/**\n * Validates the recipient address in a transaction's parameters.\n *\n * @param to - The to property to validate.\n * @throws Throws an error if the recipient address is invalid.\n */\nexport function validateParamTo(to?: string) {\n if (!to || typeof to !== 'string') {\n throw rpcErrors.invalidParams(`Invalid \"to\" address`);\n }\n}\n\n/**\n * Validates a transaction batch request.\n *\n * @param options - Options bag.\n * @param options.internalAccounts - The internal accounts added to the wallet.\n * @param options.request - The batch request object.\n * @param options.sizeLimit - The maximum number of calls allowed in a batch request.\n */\nexport function validateBatchRequest({\n internalAccounts,\n request,\n sizeLimit,\n}: {\n internalAccounts: string[];\n request: TransactionBatchRequest;\n sizeLimit: number;\n}) {\n const { origin } = request;\n const isExternal = origin && origin !== ORIGIN_METAMASK;\n\n const transactionTargetsNormalized = request.transactions.map((tx) =>\n tx.params.to?.toLowerCase(),\n );\n\n const internalAccountsNormalized = internalAccounts.map((account) =>\n account.toLowerCase(),\n );\n\n if (\n isExternal &&\n transactionTargetsNormalized.some((target) =>\n internalAccountsNormalized.includes(target as string),\n )\n ) {\n throw rpcErrors.invalidParams(\n 'Calls to internal accounts are not supported',\n );\n }\n\n if (isExternal && request.transactions.length > sizeLimit) {\n throw rpcErrors.invalidParams(\n `Batch size cannot exceed ${sizeLimit}. got: ${request.transactions.length}`,\n );\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 // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\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 chainIdParams - The chain ID to validate.\n * @param chainIdNetworkClient - The chain ID of the network client.\n */\nfunction validateParamChainId(chainIdParams?: Hex, chainIdNetworkClient?: Hex) {\n if (\n chainIdParams &&\n chainIdNetworkClient &&\n chainIdParams.toLowerCase?.() !== chainIdNetworkClient.toLowerCase()\n ) {\n throw rpcErrors.invalidParams(\n `Invalid transaction params: chainId must match the network client, got: ${chainIdParams}, expected: ${chainIdNetworkClient}`,\n );\n }\n}\n\n/**\n * Validates gas values.\n *\n * @param txParams - The transaction parameters to validate.\n */\nfunction validateGasFeeParams(txParams: TransactionParams) {\n if (txParams.gasPrice) {\n ensureProperTransactionEnvelopeTypeProvided(txParams, 'gasPrice');\n ensureMutuallyExclusiveFieldsNotProvided(\n txParams,\n 'gasPrice',\n 'maxFeePerGas',\n );\n ensureMutuallyExclusiveFieldsNotProvided(\n txParams,\n 'gasPrice',\n 'maxPriorityFeePerGas',\n );\n ensureFieldIsValidHex(txParams, 'gasPrice');\n }\n\n if (txParams.maxFeePerGas) {\n ensureProperTransactionEnvelopeTypeProvided(txParams, 'maxFeePerGas');\n ensureMutuallyExclusiveFieldsNotProvided(\n txParams,\n 'maxFeePerGas',\n 'gasPrice',\n );\n ensureFieldIsValidHex(txParams, 'maxFeePerGas');\n }\n\n if (txParams.maxPriorityFeePerGas) {\n ensureProperTransactionEnvelopeTypeProvided(\n txParams,\n 'maxPriorityFeePerGas',\n );\n ensureMutuallyExclusiveFieldsNotProvided(\n txParams,\n 'maxPriorityFeePerGas',\n 'gasPrice',\n );\n ensureFieldIsValidHex(txParams, 'maxPriorityFeePerGas');\n }\n\n if (txParams.gasLimit) {\n ensureFieldIsValidHex(txParams, 'gasLimit');\n }\n\n if (txParams.gas) {\n ensureFieldIsValidHex(txParams, 'gas');\n }\n}\n\n/**\n * Ensures that the provided txParams has the proper 'type' specified for the\n * given field, if it is provided. If types do not match throws an\n * invalidParams error.\n *\n * @param txParams - The transaction parameters object\n * @param field - The current field being validated\n * @throws {ethErrors.rpc.invalidParams} Throws if type does not match the\n * expectations for provided field.\n */\nfunction ensureProperTransactionEnvelopeTypeProvided(\n txParams: TransactionParams,\n field: keyof TransactionParams,\n) {\n const type = txParams.type as TransactionEnvelopeType | undefined;\n\n switch (field) {\n case 'authorizationList':\n if (type && type !== TransactionEnvelopeType.setCode) {\n throw rpcErrors.invalidParams(\n `Invalid transaction envelope type: specified type \"${type}\" but including authorizationList requires type: \"${TransactionEnvelopeType.setCode}\"`,\n );\n }\n break;\n case 'maxFeePerGas':\n case 'maxPriorityFeePerGas':\n if (\n type &&\n !TRANSACTION_ENVELOPE_TYPES_FEE_MARKET.includes(\n type as TransactionEnvelopeType,\n )\n ) {\n throw rpcErrors.invalidParams(\n `Invalid transaction envelope type: specified type \"${type}\" but including maxFeePerGas and maxPriorityFeePerGas requires type: \"${TRANSACTION_ENVELOPE_TYPES_FEE_MARKET.join(', ')}\"`,\n );\n }\n break;\n case 'gasPrice':\n default:\n if (\n type &&\n TRANSACTION_ENVELOPE_TYPES_FEE_MARKET.includes(\n type as TransactionEnvelopeType,\n )\n ) {\n throw rpcErrors.invalidParams(\n `Invalid transaction envelope type: specified type \"${type}\" but included a gasPrice instead of maxFeePerGas and maxPriorityFeePerGas`,\n );\n }\n }\n}\n\n/**\n * Given two fields, ensure that the second field is not included in txParams,\n * and if it is throw an invalidParams error.\n *\n * @param txParams - The transaction parameters object\n * @param fieldBeingValidated - The current field being validated\n * @param mutuallyExclusiveField - The field to ensure is not provided\n * @throws {ethErrors.rpc.invalidParams} Throws if mutuallyExclusiveField is\n * present in txParams.\n */\nfunction ensureMutuallyExclusiveFieldsNotProvided(\n txParams: TransactionParams,\n fieldBeingValidated: GasFieldsToValidate,\n mutuallyExclusiveField: GasFieldsToValidate,\n) {\n if (typeof txParams[mutuallyExclusiveField] !== 'undefined') {\n throw rpcErrors.invalidParams(\n `Invalid transaction params: specified ${fieldBeingValidated} but also included ${mutuallyExclusiveField}, these cannot be mixed`,\n );\n }\n}\n\n/**\n * Ensures that the provided value for field is a valid hexadecimal.\n * Throws an invalidParams error if field is not a valid hexadecimal.\n *\n * @param data - The object containing the field\n * @param field - The current field being validated\n * @throws {rpcErrors.invalidParams} Throws if field is not a valid hexadecimal\n */\nfunction ensureFieldIsValidHex<T>(data: T, field: keyof T) {\n const value = data[field];\n if (typeof value !== 'string' || !isStrictHexString(value)) {\n throw rpcErrors.invalidParams(\n `Invalid transaction params: ${String(field)} is not a valid hexadecimal string. got: (${String(\n value,\n )})`,\n );\n }\n}\n\n/**\n * Validate the authorization list property in the transaction parameters.\n *\n * @param txParams - The transaction parameters containing the authorization list to validate.\n */\nfunction validateAuthorizationList(txParams: TransactionParams) {\n const { authorizationList } = txParams;\n\n if (!authorizationList) {\n return;\n }\n\n ensureProperTransactionEnvelopeTypeProvided(txParams, 'authorizationList');\n\n if (!Array.isArray(authorizationList)) {\n throw rpcErrors.invalidParams(\n `Invalid transaction params: authorizationList must be an array`,\n );\n }\n\n for (const authorization of authorizationList) {\n validateAuthorization(authorization);\n }\n}\n\n/**\n * Validate an authorization object.\n *\n * @param authorization - The authorization object to validate.\n */\nfunction validateAuthorization(authorization: Authorization) {\n ensureFieldIsValidHex(authorization, 'address');\n validateHexLength(authorization.address, 20, 'address');\n\n for (const field of ['chainId', 'nonce', 'r', 's'] as const) {\n if (authorization[field]) {\n ensureFieldIsValidHex(authorization, field);\n }\n }\n\n const { yParity } = authorization;\n\n if (yParity && !['0x', '0x1'].includes(yParity)) {\n throw rpcErrors.invalidParams(\n `Invalid transaction params: yParity must be '0x' or '0x1'. got: ${yParity}`,\n );\n }\n}\n\n/**\n * Validate the number of bytes in a hex string.\n *\n * @param value - The hex string to validate.\n * @param lengthBytes - The expected length in bytes.\n * @param fieldName - The name of the field being validated.\n */\nfunction validateHexLength(\n value: string,\n lengthBytes: number,\n fieldName: string,\n) {\n const actualLengthBytes = remove0x(value).length / 2;\n\n if (actualLengthBytes !== lengthBytes) {\n throw rpcErrors.invalidParams(\n `Invalid transaction params: ${fieldName} must be ${lengthBytes} bytes. got: ${actualLengthBytes} bytes`,\n );\n }\n}\n"]}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Hex } from "@metamask/utils";
|
|
1
2
|
import type { TransactionBatchRequest } from "../types.cjs";
|
|
2
3
|
import { TransactionType, type TransactionParams } from "../types.cjs";
|
|
3
4
|
/**
|
|
@@ -30,8 +31,9 @@ export declare function validateTransactionOrigin({ data, from, internalAccounts
|
|
|
30
31
|
*
|
|
31
32
|
* @param txParams - Transaction params object to validate.
|
|
32
33
|
* @param isEIP1559Compatible - whether or not the current network supports EIP-1559 transactions.
|
|
34
|
+
* @param chainId - The chain ID of the transaction.
|
|
33
35
|
*/
|
|
34
|
-
export declare function validateTxParams(txParams: TransactionParams, isEIP1559Compatible?: boolean): void;
|
|
36
|
+
export declare function validateTxParams(txParams: TransactionParams, isEIP1559Compatible?: boolean, chainId?: Hex): void;
|
|
35
37
|
/**
|
|
36
38
|
* Validates the recipient address in a transaction's parameters.
|
|
37
39
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.d.cts","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"validation.d.cts","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAI3C,OAAO,KAAK,EAAiB,uBAAuB,EAAE,qBAAiB;AACvE,OAAO,EAEL,eAAe,EACf,KAAK,iBAAiB,EACvB,qBAAiB;AAclB;;;;;;;;;;;;;GAaG;AACH,wBAAsB,yBAAyB,CAAC,EAC9C,IAAI,EACJ,IAAI,EACJ,gBAAgB,EAChB,MAAM,EACN,kBAAkB,EAClB,eAAe,EACf,QAAQ,EACR,IAAI,GACL,EAAE;IACD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,IAAI,CAAC,EAAE,eAAe,CAAC;CACxB,iBA8CA;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,iBAAiB,EAC3B,mBAAmB,UAAO,EAC1B,OAAO,CAAC,EAAE,GAAG,QAWd;AAwHD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,EAAE,CAAC,EAAE,MAAM,QAI1C;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,EACnC,gBAAgB,EAChB,OAAO,EACP,SAAS,GACV,EAAE;IACD,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,OAAO,EAAE,uBAAuB,CAAC;IACjC,SAAS,EAAE,MAAM,CAAC;CACnB,QA4BA"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Hex } from "@metamask/utils";
|
|
1
2
|
import type { TransactionBatchRequest } from "../types.mjs";
|
|
2
3
|
import { TransactionType, type TransactionParams } from "../types.mjs";
|
|
3
4
|
/**
|
|
@@ -30,8 +31,9 @@ export declare function validateTransactionOrigin({ data, from, internalAccounts
|
|
|
30
31
|
*
|
|
31
32
|
* @param txParams - Transaction params object to validate.
|
|
32
33
|
* @param isEIP1559Compatible - whether or not the current network supports EIP-1559 transactions.
|
|
34
|
+
* @param chainId - The chain ID of the transaction.
|
|
33
35
|
*/
|
|
34
|
-
export declare function validateTxParams(txParams: TransactionParams, isEIP1559Compatible?: boolean): void;
|
|
36
|
+
export declare function validateTxParams(txParams: TransactionParams, isEIP1559Compatible?: boolean, chainId?: Hex): void;
|
|
35
37
|
/**
|
|
36
38
|
* Validates the recipient address in a transaction's parameters.
|
|
37
39
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.d.mts","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"validation.d.mts","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAI3C,OAAO,KAAK,EAAiB,uBAAuB,EAAE,qBAAiB;AACvE,OAAO,EAEL,eAAe,EACf,KAAK,iBAAiB,EACvB,qBAAiB;AAclB;;;;;;;;;;;;;GAaG;AACH,wBAAsB,yBAAyB,CAAC,EAC9C,IAAI,EACJ,IAAI,EACJ,gBAAgB,EAChB,MAAM,EACN,kBAAkB,EAClB,eAAe,EACf,QAAQ,EACR,IAAI,GACL,EAAE;IACD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,IAAI,CAAC,EAAE,eAAe,CAAC;CACxB,iBA8CA;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,iBAAiB,EAC3B,mBAAmB,UAAO,EAC1B,OAAO,CAAC,EAAE,GAAG,QAWd;AAwHD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,EAAE,CAAC,EAAE,MAAM,QAI1C;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,EACnC,gBAAgB,EAChB,OAAO,EACP,SAAS,GACV,EAAE;IACD,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,OAAO,EAAE,uBAAuB,CAAC;IACjC,SAAS,EAAE,MAAM,CAAC;CACnB,QA4BA"}
|
|
@@ -40,6 +40,9 @@ export async function validateTransactionOrigin({ data, from, internalAccounts,
|
|
|
40
40
|
if (isExternal && permittedAddresses && !permittedAddresses.includes(from)) {
|
|
41
41
|
throw providerErrors.unauthorized({ data: { origin } });
|
|
42
42
|
}
|
|
43
|
+
if (type === TransactionType.batch) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
43
46
|
if (isExternal &&
|
|
44
47
|
(authorizationList || envelopeType === TransactionEnvelopeType.setCode)) {
|
|
45
48
|
throw rpcErrors.invalidParams('External EIP-7702 transactions are not supported');
|
|
@@ -47,8 +50,7 @@ export async function validateTransactionOrigin({ data, from, internalAccounts,
|
|
|
47
50
|
const hasData = Boolean(data && data !== '0x');
|
|
48
51
|
if (isExternal &&
|
|
49
52
|
hasData &&
|
|
50
|
-
internalAccounts?.some((account) => account.toLowerCase() === to?.toLowerCase())
|
|
51
|
-
type !== TransactionType.batch) {
|
|
53
|
+
internalAccounts?.some((account) => account.toLowerCase() === to?.toLowerCase())) {
|
|
52
54
|
throw rpcErrors.invalidParams('External transactions to internal accounts cannot include data');
|
|
53
55
|
}
|
|
54
56
|
}
|
|
@@ -58,15 +60,16 @@ export async function validateTransactionOrigin({ data, from, internalAccounts,
|
|
|
58
60
|
*
|
|
59
61
|
* @param txParams - Transaction params object to validate.
|
|
60
62
|
* @param isEIP1559Compatible - whether or not the current network supports EIP-1559 transactions.
|
|
63
|
+
* @param chainId - The chain ID of the transaction.
|
|
61
64
|
*/
|
|
62
|
-
export function validateTxParams(txParams, isEIP1559Compatible = true) {
|
|
65
|
+
export function validateTxParams(txParams, isEIP1559Compatible = true, chainId) {
|
|
63
66
|
validateEnvelopeType(txParams.type);
|
|
64
67
|
validateEIP1559Compatibility(txParams, isEIP1559Compatible);
|
|
65
68
|
validateParamFrom(txParams.from);
|
|
66
69
|
validateParamRecipient(txParams);
|
|
67
70
|
validateParamValue(txParams.value);
|
|
68
71
|
validateParamData(txParams.data);
|
|
69
|
-
validateParamChainId(txParams.chainId);
|
|
72
|
+
validateParamChainId(txParams.chainId, chainId);
|
|
70
73
|
validateGasFeeParams(txParams);
|
|
71
74
|
validateAuthorizationList(txParams);
|
|
72
75
|
}
|
|
@@ -218,16 +221,14 @@ function validateParamData(value) {
|
|
|
218
221
|
/**
|
|
219
222
|
* Validates chainId type.
|
|
220
223
|
*
|
|
221
|
-
* @param
|
|
224
|
+
* @param chainIdParams - The chain ID to validate.
|
|
225
|
+
* @param chainIdNetworkClient - The chain ID of the network client.
|
|
222
226
|
*/
|
|
223
|
-
function validateParamChainId(
|
|
224
|
-
if (
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
throw rpcErrors.invalidParams(
|
|
228
|
-
// TODO: Either fix this lint violation or explain why it's necessary to ignore.
|
|
229
|
-
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
230
|
-
`Invalid transaction params: chainId is not a Number or hex string. got: (${chainId})`);
|
|
227
|
+
function validateParamChainId(chainIdParams, chainIdNetworkClient) {
|
|
228
|
+
if (chainIdParams &&
|
|
229
|
+
chainIdNetworkClient &&
|
|
230
|
+
chainIdParams.toLowerCase?.() !== chainIdNetworkClient.toLowerCase()) {
|
|
231
|
+
throw rpcErrors.invalidParams(`Invalid transaction params: chainId must match the network client, got: ${chainIdParams}, expected: ${chainIdNetworkClient}`);
|
|
231
232
|
}
|
|
232
233
|
}
|
|
233
234
|
/**
|