@metamask/transaction-controller 59.2.0 → 60.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/CHANGELOG.md +29 -1
  2. package/dist/TransactionController.cjs +33 -5
  3. package/dist/TransactionController.cjs.map +1 -1
  4. package/dist/TransactionController.d.cts +18 -1
  5. package/dist/TransactionController.d.cts.map +1 -1
  6. package/dist/TransactionController.d.mts +18 -1
  7. package/dist/TransactionController.d.mts.map +1 -1
  8. package/dist/TransactionController.mjs +33 -5
  9. package/dist/TransactionController.mjs.map +1 -1
  10. package/dist/api/simulation-api.cjs +13 -1
  11. package/dist/api/simulation-api.cjs.map +1 -1
  12. package/dist/api/simulation-api.d.cts +11 -0
  13. package/dist/api/simulation-api.d.cts.map +1 -1
  14. package/dist/api/simulation-api.d.mts +11 -0
  15. package/dist/api/simulation-api.d.mts.map +1 -1
  16. package/dist/api/simulation-api.mjs +13 -1
  17. package/dist/api/simulation-api.mjs.map +1 -1
  18. package/dist/hooks/ExtraTransactionsPublishHook.cjs +28 -14
  19. package/dist/hooks/ExtraTransactionsPublishHook.cjs.map +1 -1
  20. package/dist/hooks/ExtraTransactionsPublishHook.d.cts +2 -3
  21. package/dist/hooks/ExtraTransactionsPublishHook.d.cts.map +1 -1
  22. package/dist/hooks/ExtraTransactionsPublishHook.d.mts +2 -3
  23. package/dist/hooks/ExtraTransactionsPublishHook.d.mts.map +1 -1
  24. package/dist/hooks/ExtraTransactionsPublishHook.mjs +28 -14
  25. package/dist/hooks/ExtraTransactionsPublishHook.mjs.map +1 -1
  26. package/dist/index.cjs.map +1 -1
  27. package/dist/index.d.cts +1 -1
  28. package/dist/index.d.cts.map +1 -1
  29. package/dist/index.d.mts +1 -1
  30. package/dist/index.d.mts.map +1 -1
  31. package/dist/index.mjs.map +1 -1
  32. package/dist/types.cjs.map +1 -1
  33. package/dist/types.d.cts +64 -1
  34. package/dist/types.d.cts.map +1 -1
  35. package/dist/types.d.mts +64 -1
  36. package/dist/types.d.mts.map +1 -1
  37. package/dist/types.mjs.map +1 -1
  38. package/dist/utils/balance-changes.cjs +3 -1
  39. package/dist/utils/balance-changes.cjs.map +1 -1
  40. package/dist/utils/balance-changes.d.cts +3 -1
  41. package/dist/utils/balance-changes.d.cts.map +1 -1
  42. package/dist/utils/balance-changes.d.mts +3 -1
  43. package/dist/utils/balance-changes.d.mts.map +1 -1
  44. package/dist/utils/balance-changes.mjs +3 -1
  45. package/dist/utils/balance-changes.mjs.map +1 -1
  46. package/dist/utils/batch.cjs +13 -4
  47. package/dist/utils/batch.cjs.map +1 -1
  48. package/dist/utils/batch.d.cts +2 -1
  49. package/dist/utils/batch.d.cts.map +1 -1
  50. package/dist/utils/batch.d.mts +2 -1
  51. package/dist/utils/batch.d.mts.map +1 -1
  52. package/dist/utils/batch.mjs +13 -4
  53. package/dist/utils/batch.mjs.map +1 -1
  54. package/dist/utils/eip7702.cjs +0 -12
  55. package/dist/utils/eip7702.cjs.map +1 -1
  56. package/dist/utils/eip7702.d.cts.map +1 -1
  57. package/dist/utils/eip7702.d.mts.map +1 -1
  58. package/dist/utils/eip7702.mjs +0 -12
  59. package/dist/utils/eip7702.mjs.map +1 -1
  60. package/dist/utils/gas-fee-tokens.cjs +23 -17
  61. package/dist/utils/gas-fee-tokens.cjs.map +1 -1
  62. package/dist/utils/gas-fee-tokens.d.cts +7 -1
  63. package/dist/utils/gas-fee-tokens.d.cts.map +1 -1
  64. package/dist/utils/gas-fee-tokens.d.mts +7 -1
  65. package/dist/utils/gas-fee-tokens.d.mts.map +1 -1
  66. package/dist/utils/gas-fee-tokens.mjs +23 -17
  67. package/dist/utils/gas-fee-tokens.mjs.map +1 -1
  68. package/dist/utils/gas.cjs +16 -7
  69. package/dist/utils/gas.cjs.map +1 -1
  70. package/dist/utils/gas.d.cts +8 -3
  71. package/dist/utils/gas.d.cts.map +1 -1
  72. package/dist/utils/gas.d.mts +8 -3
  73. package/dist/utils/gas.d.mts.map +1 -1
  74. package/dist/utils/gas.mjs +16 -7
  75. package/dist/utils/gas.mjs.map +1 -1
  76. package/package.json +6 -6
@@ -1 +1 @@
1
- {"version":3,"file":"eip7702.mjs","sourceRoot":"","sources":["../../src/utils/eip7702.ts"],"names":[],"mappings":"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","sourcesContent":["import { defaultAbiCoder } from '@ethersproject/abi';\nimport { Contract } from '@ethersproject/contracts';\nimport { query, toHex } from '@metamask/controller-utils';\nimport type EthQuery from '@metamask/eth-query';\nimport { createModuleLogger, type Hex, add0x } from '@metamask/utils';\n\nimport {\n getEIP7702ContractAddresses,\n getEIP7702SupportedChains,\n} from './feature-flags';\nimport { ABI_IERC7821 } from '../constants';\nimport { projectLogger } from '../logger';\nimport type { TransactionControllerMessenger } from '../TransactionController';\nimport type {\n BatchTransactionParams,\n Authorization,\n AuthorizationList,\n TransactionMeta,\n} from '../types';\n\nexport const DELEGATION_PREFIX = '0xef0100';\nexport const BATCH_FUNCTION_NAME = 'execute';\nexport const CALLS_SIGNATURE = '(address,uint256,bytes)[]';\nexport const ERROR_MESSGE_PUBLIC_KEY = 'EIP-7702 public key not specified';\n\nconst UNSUPPORTED_PARAMS = [\n 'gas',\n 'maxFeePerGas',\n 'maxPriorityFeePerGas',\n] as const;\n\nconst log = createModuleLogger(projectLogger, 'eip-7702');\n\n/**\n * Determine if a chain supports EIP-7702 using LaunchDarkly feature flag.\n *\n * @param chainId - Hexadecimal ID of the chain.\n * @param messenger - Messenger instance.\n * @returns True if the chain supports EIP-7702.\n */\nexport function doesChainSupportEIP7702(\n chainId: Hex,\n messenger: TransactionControllerMessenger,\n) {\n const supportedChains = getEIP7702SupportedChains(messenger);\n\n return supportedChains.some(\n (supportedChainId) =>\n supportedChainId.toLowerCase() === chainId.toLowerCase(),\n );\n}\n\n/**\n * Retrieve the delegation address for an account.\n *\n * @param address - The address to check.\n * @param ethQuery - The EthQuery instance to communicate with the blockchain.\n * @returns The delegation address if it exists.\n */\nexport async function getDelegationAddress(\n address: Hex,\n ethQuery: EthQuery,\n): Promise<Hex | undefined> {\n const code = await query(ethQuery, 'eth_getCode', [address]);\n const normalizedCode = add0x(code?.toLowerCase?.() ?? '');\n\n const hasDelegation =\n code?.length === 48 && normalizedCode.startsWith(DELEGATION_PREFIX);\n\n return hasDelegation\n ? add0x(normalizedCode.slice(DELEGATION_PREFIX.length))\n : undefined;\n}\n\n/**\n * Determine if an account has been upgraded to a supported EIP-7702 contract.\n *\n * @param address - The EOA address to check.\n * @param chainId - The chain ID.\n * @param publicKey - Public key used to validate EIP-7702 contract signatures in feature flags.\n * @param messenger - The messenger instance.\n * @param ethQuery - The EthQuery instance to communicate with the blockchain.\n * @returns An object with the results of the check.\n */\nexport async function isAccountUpgradedToEIP7702(\n address: Hex,\n chainId: Hex,\n publicKey: Hex,\n messenger: TransactionControllerMessenger,\n ethQuery: EthQuery,\n) {\n const contractAddresses = getEIP7702ContractAddresses(\n chainId,\n messenger,\n publicKey,\n );\n\n const delegationAddress = await getDelegationAddress(address, ethQuery);\n\n const isSupported = Boolean(\n delegationAddress &&\n contractAddresses.some(\n (contract) =>\n contract.toLowerCase() === delegationAddress.toLowerCase(),\n ),\n );\n\n return {\n delegationAddress,\n isSupported,\n };\n}\n\n/**\n * Generate an EIP-7702 batch transaction.\n *\n * @param from - The sender address.\n * @param transactions - The transactions to batch.\n * @returns The batch transaction.\n */\nexport function generateEIP7702BatchTransaction(\n from: Hex,\n transactions: BatchTransactionParams[],\n): BatchTransactionParams {\n const erc7821Contract = Contract.getInterface(ABI_IERC7821);\n\n const calls = transactions.map((transaction) => {\n const { data, to, value } = transaction;\n\n const unsupported = UNSUPPORTED_PARAMS.filter(\n (param) => transaction[param] !== undefined,\n );\n\n if (unsupported.length) {\n const errorData = unsupported\n .map((param) => `${param}: ${transaction[param]}`)\n .join(', ');\n\n throw new Error(\n `EIP-7702 batch transactions do not support gas parameters per call - ${errorData}`,\n );\n }\n\n return [\n to ?? '0x0000000000000000000000000000000000000000',\n value ?? '0x0',\n data ?? '0x',\n ];\n });\n\n // Single batch mode, no opData.\n const mode = '0x01'.padEnd(66, '0');\n\n const callData = defaultAbiCoder.encode([CALLS_SIGNATURE], [calls]);\n\n const data = erc7821Contract.encodeFunctionData(BATCH_FUNCTION_NAME, [\n mode,\n callData,\n ]) as Hex;\n\n log('Transaction data', data);\n\n return {\n data,\n to: from,\n };\n}\n\n/**\n * Sign an authorization list.\n *\n * @param options - Options bag.\n * @param options.authorizationList - The authorization list to sign.\n * @param options.messenger - The controller messenger.\n * @param options.transactionMeta - The transaction metadata.\n * @returns The signed authorization list.\n */\nexport async function signAuthorizationList({\n authorizationList,\n messenger,\n transactionMeta,\n}: {\n authorizationList?: AuthorizationList;\n messenger: TransactionControllerMessenger;\n transactionMeta: TransactionMeta;\n}): Promise<Required<AuthorizationList | undefined>> {\n if (!authorizationList) {\n return undefined;\n }\n\n const signedAuthorizationList: Required<AuthorizationList> = [];\n let index = 0;\n\n for (const authorization of authorizationList) {\n const signedAuthorization = await signAuthorization(\n authorization,\n transactionMeta,\n messenger,\n index,\n );\n\n signedAuthorizationList.push(signedAuthorization);\n index += 1;\n }\n\n return signedAuthorizationList;\n}\n\n/**\n * Signs an authorization.\n *\n * @param authorization - The authorization to sign.\n * @param transactionMeta - The associated transaction metadata.\n * @param messenger - The messenger to use for signing.\n * @param index - The index of the authorization in the list.\n * @returns The signed authorization.\n */\nasync function signAuthorization(\n authorization: Authorization,\n transactionMeta: TransactionMeta,\n messenger: TransactionControllerMessenger,\n index: number,\n): Promise<Required<Authorization>> {\n const finalAuthorization = prepareAuthorization(\n authorization,\n transactionMeta,\n index,\n );\n\n const { txParams } = transactionMeta;\n const { from } = txParams;\n const { address, chainId, nonce } = finalAuthorization;\n const chainIdDecimal = parseInt(chainId, 16);\n const nonceDecimal = parseInt(nonce, 16);\n\n const signature = await messenger.call(\n 'KeyringController:signEip7702Authorization',\n {\n chainId: chainIdDecimal,\n contractAddress: address,\n from,\n nonce: nonceDecimal,\n },\n );\n\n const r = signature.slice(0, 66) as Hex;\n const s = add0x(signature.slice(66, 130));\n const v = parseInt(signature.slice(130, 132), 16);\n const yParity = toHex(v - 27 === 0 ? 0 : 1);\n\n const result: Required<Authorization> = {\n address,\n chainId,\n nonce,\n r,\n s,\n yParity,\n };\n\n log('Signed authorization', result);\n\n return result;\n}\n\n/**\n * Prepares an authorization for signing by populating the chainId and nonce.\n *\n * @param authorization - The authorization to prepare.\n * @param transactionMeta - The associated transaction metadata.\n * @param index - The index of the authorization in the list.\n * @returns The prepared authorization.\n */\nfunction prepareAuthorization(\n authorization: Authorization,\n transactionMeta: TransactionMeta,\n index: number,\n): Authorization & { chainId: Hex; nonce: Hex } {\n const { chainId: existingChainId, nonce: existingNonce } = authorization;\n const { txParams, chainId: transactionChainId } = transactionMeta;\n const { nonce: transactionNonce } = txParams;\n\n const chainId = existingChainId ?? transactionChainId;\n let nonce = existingNonce;\n\n if (nonce === undefined) {\n nonce = toHex(parseInt(transactionNonce as string, 16) + 1 + index);\n }\n\n const result = {\n ...authorization,\n chainId,\n nonce,\n };\n\n log('Prepared authorization', result);\n\n return result;\n}\n"]}
1
+ {"version":3,"file":"eip7702.mjs","sourceRoot":"","sources":["../../src/utils/eip7702.ts"],"names":[],"mappings":"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","sourcesContent":["import { defaultAbiCoder } from '@ethersproject/abi';\nimport { Contract } from '@ethersproject/contracts';\nimport { query, toHex } from '@metamask/controller-utils';\nimport type EthQuery from '@metamask/eth-query';\nimport { createModuleLogger, type Hex, add0x } from '@metamask/utils';\n\nimport {\n getEIP7702ContractAddresses,\n getEIP7702SupportedChains,\n} from './feature-flags';\nimport { ABI_IERC7821 } from '../constants';\nimport { projectLogger } from '../logger';\nimport type { TransactionControllerMessenger } from '../TransactionController';\nimport type {\n BatchTransactionParams,\n Authorization,\n AuthorizationList,\n TransactionMeta,\n} from '../types';\n\nexport const DELEGATION_PREFIX = '0xef0100';\nexport const BATCH_FUNCTION_NAME = 'execute';\nexport const CALLS_SIGNATURE = '(address,uint256,bytes)[]';\nexport const ERROR_MESSGE_PUBLIC_KEY = 'EIP-7702 public key not specified';\n\nconst log = createModuleLogger(projectLogger, 'eip-7702');\n\n/**\n * Determine if a chain supports EIP-7702 using LaunchDarkly feature flag.\n *\n * @param chainId - Hexadecimal ID of the chain.\n * @param messenger - Messenger instance.\n * @returns True if the chain supports EIP-7702.\n */\nexport function doesChainSupportEIP7702(\n chainId: Hex,\n messenger: TransactionControllerMessenger,\n) {\n const supportedChains = getEIP7702SupportedChains(messenger);\n\n return supportedChains.some(\n (supportedChainId) =>\n supportedChainId.toLowerCase() === chainId.toLowerCase(),\n );\n}\n\n/**\n * Retrieve the delegation address for an account.\n *\n * @param address - The address to check.\n * @param ethQuery - The EthQuery instance to communicate with the blockchain.\n * @returns The delegation address if it exists.\n */\nexport async function getDelegationAddress(\n address: Hex,\n ethQuery: EthQuery,\n): Promise<Hex | undefined> {\n const code = await query(ethQuery, 'eth_getCode', [address]);\n const normalizedCode = add0x(code?.toLowerCase?.() ?? '');\n\n const hasDelegation =\n code?.length === 48 && normalizedCode.startsWith(DELEGATION_PREFIX);\n\n return hasDelegation\n ? add0x(normalizedCode.slice(DELEGATION_PREFIX.length))\n : undefined;\n}\n\n/**\n * Determine if an account has been upgraded to a supported EIP-7702 contract.\n *\n * @param address - The EOA address to check.\n * @param chainId - The chain ID.\n * @param publicKey - Public key used to validate EIP-7702 contract signatures in feature flags.\n * @param messenger - The messenger instance.\n * @param ethQuery - The EthQuery instance to communicate with the blockchain.\n * @returns An object with the results of the check.\n */\nexport async function isAccountUpgradedToEIP7702(\n address: Hex,\n chainId: Hex,\n publicKey: Hex,\n messenger: TransactionControllerMessenger,\n ethQuery: EthQuery,\n) {\n const contractAddresses = getEIP7702ContractAddresses(\n chainId,\n messenger,\n publicKey,\n );\n\n const delegationAddress = await getDelegationAddress(address, ethQuery);\n\n const isSupported = Boolean(\n delegationAddress &&\n contractAddresses.some(\n (contract) =>\n contract.toLowerCase() === delegationAddress.toLowerCase(),\n ),\n );\n\n return {\n delegationAddress,\n isSupported,\n };\n}\n\n/**\n * Generate an EIP-7702 batch transaction.\n *\n * @param from - The sender address.\n * @param transactions - The transactions to batch.\n * @returns The batch transaction.\n */\nexport function generateEIP7702BatchTransaction(\n from: Hex,\n transactions: BatchTransactionParams[],\n): BatchTransactionParams {\n const erc7821Contract = Contract.getInterface(ABI_IERC7821);\n\n const calls = transactions.map((transaction) => {\n const { data, to, value } = transaction;\n\n return [\n to ?? '0x0000000000000000000000000000000000000000',\n value ?? '0x0',\n data ?? '0x',\n ];\n });\n\n // Single batch mode, no opData.\n const mode = '0x01'.padEnd(66, '0');\n\n const callData = defaultAbiCoder.encode([CALLS_SIGNATURE], [calls]);\n\n const data = erc7821Contract.encodeFunctionData(BATCH_FUNCTION_NAME, [\n mode,\n callData,\n ]) as Hex;\n\n log('Transaction data', data);\n\n return {\n data,\n to: from,\n };\n}\n\n/**\n * Sign an authorization list.\n *\n * @param options - Options bag.\n * @param options.authorizationList - The authorization list to sign.\n * @param options.messenger - The controller messenger.\n * @param options.transactionMeta - The transaction metadata.\n * @returns The signed authorization list.\n */\nexport async function signAuthorizationList({\n authorizationList,\n messenger,\n transactionMeta,\n}: {\n authorizationList?: AuthorizationList;\n messenger: TransactionControllerMessenger;\n transactionMeta: TransactionMeta;\n}): Promise<Required<AuthorizationList | undefined>> {\n if (!authorizationList) {\n return undefined;\n }\n\n const signedAuthorizationList: Required<AuthorizationList> = [];\n let index = 0;\n\n for (const authorization of authorizationList) {\n const signedAuthorization = await signAuthorization(\n authorization,\n transactionMeta,\n messenger,\n index,\n );\n\n signedAuthorizationList.push(signedAuthorization);\n index += 1;\n }\n\n return signedAuthorizationList;\n}\n\n/**\n * Signs an authorization.\n *\n * @param authorization - The authorization to sign.\n * @param transactionMeta - The associated transaction metadata.\n * @param messenger - The messenger to use for signing.\n * @param index - The index of the authorization in the list.\n * @returns The signed authorization.\n */\nasync function signAuthorization(\n authorization: Authorization,\n transactionMeta: TransactionMeta,\n messenger: TransactionControllerMessenger,\n index: number,\n): Promise<Required<Authorization>> {\n const finalAuthorization = prepareAuthorization(\n authorization,\n transactionMeta,\n index,\n );\n\n const { txParams } = transactionMeta;\n const { from } = txParams;\n const { address, chainId, nonce } = finalAuthorization;\n const chainIdDecimal = parseInt(chainId, 16);\n const nonceDecimal = parseInt(nonce, 16);\n\n const signature = await messenger.call(\n 'KeyringController:signEip7702Authorization',\n {\n chainId: chainIdDecimal,\n contractAddress: address,\n from,\n nonce: nonceDecimal,\n },\n );\n\n const r = signature.slice(0, 66) as Hex;\n const s = add0x(signature.slice(66, 130));\n const v = parseInt(signature.slice(130, 132), 16);\n const yParity = toHex(v - 27 === 0 ? 0 : 1);\n\n const result: Required<Authorization> = {\n address,\n chainId,\n nonce,\n r,\n s,\n yParity,\n };\n\n log('Signed authorization', result);\n\n return result;\n}\n\n/**\n * Prepares an authorization for signing by populating the chainId and nonce.\n *\n * @param authorization - The authorization to prepare.\n * @param transactionMeta - The associated transaction metadata.\n * @param index - The index of the authorization in the list.\n * @returns The prepared authorization.\n */\nfunction prepareAuthorization(\n authorization: Authorization,\n transactionMeta: TransactionMeta,\n index: number,\n): Authorization & { chainId: Hex; nonce: Hex } {\n const { chainId: existingChainId, nonce: existingNonce } = authorization;\n const { txParams, chainId: transactionChainId } = transactionMeta;\n const { nonce: transactionNonce } = txParams;\n\n const chainId = existingChainId ?? transactionChainId;\n let nonce = existingNonce;\n\n if (nonce === undefined) {\n nonce = toHex(parseInt(transactionNonce as string, 16) + 1 + index);\n }\n\n const result = {\n ...authorization,\n chainId,\n nonce,\n };\n\n log('Prepared authorization', result);\n\n return result;\n}\n"]}
@@ -18,9 +18,10 @@ const log = (0, utils_1.createModuleLogger)(logger_1.projectLogger, 'gas-fee-tok
18
18
  * @param request.messenger - The messenger instance.
19
19
  * @param request.publicKeyEIP7702 - Public key to validate EIP-7702 contract signatures.
20
20
  * @param request.transactionMeta - The transaction metadata.
21
+ * @param request.getSimulationConfig - Optional transaction simulation parameters.
21
22
  * @returns An array of gas fee tokens.
22
23
  */
23
- async function getGasFeeTokens({ chainId, isEIP7702GasFeeTokensEnabled, messenger, publicKeyEIP7702, transactionMeta, }) {
24
+ async function getGasFeeTokens({ chainId, isEIP7702GasFeeTokensEnabled, messenger, publicKeyEIP7702, transactionMeta, getSimulationConfig, }) {
24
25
  const { delegationAddress, txParams } = transactionMeta;
25
26
  const { authorizationList: authorizationListRequest } = txParams;
26
27
  const data = txParams.data;
@@ -44,6 +45,7 @@ async function getGasFeeTokens({ chainId, isEIP7702GasFeeTokensEnabled, messenge
44
45
  }
45
46
  try {
46
47
  const response = await (0, simulation_api_1.simulateTransactions)(chainId, {
48
+ getSimulationConfig,
47
49
  transactions: [
48
50
  {
49
51
  authorizationList,
@@ -66,7 +68,7 @@ async function getGasFeeTokens({ chainId, isEIP7702GasFeeTokensEnabled, messenge
66
68
  }
67
69
  catch (error) {
68
70
  log('Failed to gas fee tokens', error);
69
- return [];
71
+ return { gasFeeTokens: [], isGasFeeSponsored: false };
70
72
  }
71
73
  }
72
74
  exports.getGasFeeTokens = getGasFeeTokens;
@@ -74,26 +76,30 @@ exports.getGasFeeTokens = getGasFeeTokens;
74
76
  * Extract gas fee tokens from a simulation response.
75
77
  *
76
78
  * @param response - The simulation response.
77
- * @returns An array of gas fee tokens.
79
+ * @returns gasFeeTokens: An array of gas fee tokens. isGasFeeSponsored: Whether the transaction is sponsored
78
80
  */
79
81
  function parseGasFeeTokens(response) {
80
82
  const feeLevel = response.transactions?.[0]
81
83
  ?.fees?.[0];
84
+ const isGasFeeSponsored = response.sponsorship?.isSponsored ?? false;
82
85
  const tokenFees = feeLevel?.tokenFees ?? [];
83
- return tokenFees.map((tokenFee) => ({
84
- amount: tokenFee.balanceNeededToken,
85
- balance: tokenFee.currentBalanceToken,
86
- decimals: tokenFee.token.decimals,
87
- fee: tokenFee.serviceFee,
88
- gas: feeLevel.gas,
89
- gasTransfer: tokenFee.transferEstimate,
90
- maxFeePerGas: feeLevel.maxFeePerGas,
91
- maxPriorityFeePerGas: feeLevel.maxPriorityFeePerGas,
92
- rateWei: tokenFee.rateWei,
93
- recipient: tokenFee.feeRecipient,
94
- symbol: tokenFee.token.symbol,
95
- tokenAddress: tokenFee.token.address,
96
- }));
86
+ return {
87
+ gasFeeTokens: tokenFees.map((tokenFee) => ({
88
+ amount: tokenFee.balanceNeededToken,
89
+ balance: tokenFee.currentBalanceToken,
90
+ decimals: tokenFee.token.decimals,
91
+ fee: tokenFee.serviceFee,
92
+ gas: feeLevel.gas,
93
+ gasTransfer: tokenFee.transferEstimate,
94
+ maxFeePerGas: feeLevel.maxFeePerGas,
95
+ maxPriorityFeePerGas: feeLevel.maxPriorityFeePerGas,
96
+ rateWei: tokenFee.rateWei,
97
+ recipient: tokenFee.feeRecipient,
98
+ symbol: tokenFee.token.symbol,
99
+ tokenAddress: tokenFee.token.address,
100
+ })),
101
+ isGasFeeSponsored,
102
+ };
97
103
  }
98
104
  /**
99
105
  * Generate the authorization list for the request.
@@ -1 +1 @@
1
- {"version":3,"file":"gas-fee-tokens.cjs","sourceRoot":"","sources":["../../src/utils/gas-fee-tokens.ts"],"names":[],"mappings":"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","sourcesContent":["import { rpcErrors } from '@metamask/rpc-errors';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\n\nimport { ERROR_MESSAGE_NO_UPGRADE_CONTRACT } from './batch';\nimport { ERROR_MESSGE_PUBLIC_KEY, doesChainSupportEIP7702 } from './eip7702';\nimport { getEIP7702UpgradeContractAddress } from './feature-flags';\nimport type {\n GasFeeToken,\n TransactionControllerMessenger,\n TransactionMeta,\n} from '..';\nimport type { SimulationRequestTransaction } from '../api/simulation-api';\nimport {\n simulateTransactions,\n type SimulationResponse,\n type SimulationResponseTransaction,\n} from '../api/simulation-api';\nimport { projectLogger } from '../logger';\n\nconst log = createModuleLogger(projectLogger, 'gas-fee-tokens');\n\nexport type GetGasFeeTokensRequest = {\n chainId: Hex;\n isEIP7702GasFeeTokensEnabled: (\n transactionMeta: TransactionMeta,\n ) => Promise<boolean>;\n messenger: TransactionControllerMessenger;\n publicKeyEIP7702?: Hex;\n transactionMeta: TransactionMeta;\n};\n\n/**\n * Get gas fee tokens for a transaction.\n *\n * @param request - The request object.\n * @param request.chainId - The chain ID of the transaction.\n * @param request.isEIP7702GasFeeTokensEnabled - Callback to check if EIP-7702 gas fee tokens are enabled.\n * @param request.messenger - The messenger instance.\n * @param request.publicKeyEIP7702 - Public key to validate EIP-7702 contract signatures.\n * @param request.transactionMeta - The transaction metadata.\n * @returns An array of gas fee tokens.\n */\nexport async function getGasFeeTokens({\n chainId,\n isEIP7702GasFeeTokensEnabled,\n messenger,\n publicKeyEIP7702,\n transactionMeta,\n}: GetGasFeeTokensRequest) {\n const { delegationAddress, txParams } = transactionMeta;\n const { authorizationList: authorizationListRequest } = txParams;\n const data = txParams.data as Hex;\n const from = txParams.from as Hex;\n const to = txParams.to as Hex;\n const value = txParams.value as Hex;\n\n log('Request', { chainId, txParams });\n\n const is7702GasFeeTokensEnabled =\n await isEIP7702GasFeeTokensEnabled(transactionMeta);\n\n const with7702 =\n is7702GasFeeTokensEnabled && doesChainSupportEIP7702(chainId, messenger);\n\n let authorizationList:\n | SimulationRequestTransaction['authorizationList']\n | undefined = authorizationListRequest?.map((authorization) => ({\n address: authorization.address,\n from: from as Hex,\n }));\n\n if (with7702 && !delegationAddress && !authorizationList) {\n authorizationList = buildAuthorizationList({\n chainId,\n from: from as Hex,\n messenger,\n publicKeyEIP7702,\n });\n }\n\n try {\n const response = await simulateTransactions(chainId, {\n transactions: [\n {\n authorizationList,\n data,\n from,\n to,\n value,\n },\n ],\n suggestFees: {\n withTransfer: true,\n withFeeTransfer: true,\n with7702,\n },\n });\n\n log('Response', response);\n\n const result = parseGasFeeTokens(response);\n\n log('Gas fee tokens', result);\n\n return result;\n } catch (error) {\n log('Failed to gas fee tokens', error);\n return [];\n }\n}\n\n/**\n * Extract gas fee tokens from a simulation response.\n *\n * @param response - The simulation response.\n * @returns An array of gas fee tokens.\n */\nfunction parseGasFeeTokens(response: SimulationResponse): GasFeeToken[] {\n const feeLevel = response.transactions?.[0]\n ?.fees?.[0] as Required<SimulationResponseTransaction>['fees'][0];\n\n const tokenFees = feeLevel?.tokenFees ?? [];\n\n return tokenFees.map((tokenFee) => ({\n amount: tokenFee.balanceNeededToken,\n balance: tokenFee.currentBalanceToken,\n decimals: tokenFee.token.decimals,\n fee: tokenFee.serviceFee,\n gas: feeLevel.gas,\n gasTransfer: tokenFee.transferEstimate,\n maxFeePerGas: feeLevel.maxFeePerGas,\n maxPriorityFeePerGas: feeLevel.maxPriorityFeePerGas,\n rateWei: tokenFee.rateWei,\n recipient: tokenFee.feeRecipient,\n symbol: tokenFee.token.symbol,\n tokenAddress: tokenFee.token.address,\n }));\n}\n\n/**\n * Generate the authorization list for the request.\n *\n * @param request - The request object.\n * @param request.chainId - The chain ID.\n * @param request.from - The sender's address.\n * @param request.messenger - The messenger instance.\n * @param request.publicKeyEIP7702 - The public key for EIP-7702.\n * @returns The authorization list.\n */\nfunction buildAuthorizationList({\n chainId,\n from,\n messenger,\n publicKeyEIP7702,\n}: {\n chainId: Hex;\n from: Hex;\n messenger: TransactionControllerMessenger;\n publicKeyEIP7702?: Hex;\n}): SimulationRequestTransaction['authorizationList'] | undefined {\n if (!publicKeyEIP7702) {\n throw rpcErrors.internal(ERROR_MESSGE_PUBLIC_KEY);\n }\n\n const upgradeAddress = getEIP7702UpgradeContractAddress(\n chainId,\n messenger,\n publicKeyEIP7702,\n );\n\n if (!upgradeAddress) {\n throw rpcErrors.internal(ERROR_MESSAGE_NO_UPGRADE_CONTRACT);\n }\n\n return [\n {\n address: upgradeAddress,\n from: from as Hex,\n },\n ];\n}\n"]}
1
+ {"version":3,"file":"gas-fee-tokens.cjs","sourceRoot":"","sources":["../../src/utils/gas-fee-tokens.ts"],"names":[],"mappings":"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","sourcesContent":["import { rpcErrors } from '@metamask/rpc-errors';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\n\nimport { ERROR_MESSAGE_NO_UPGRADE_CONTRACT } from './batch';\nimport { ERROR_MESSGE_PUBLIC_KEY, doesChainSupportEIP7702 } from './eip7702';\nimport { getEIP7702UpgradeContractAddress } from './feature-flags';\nimport type {\n GasFeeToken,\n TransactionControllerMessenger,\n TransactionMeta,\n} from '..';\nimport type { SimulationRequestTransaction } from '../api/simulation-api';\nimport {\n simulateTransactions,\n type SimulationResponse,\n type SimulationResponseTransaction,\n} from '../api/simulation-api';\nimport { projectLogger } from '../logger';\nimport type { GetSimulationConfig } from '../types';\n\nconst log = createModuleLogger(projectLogger, 'gas-fee-tokens');\n\nexport type GetGasFeeTokensRequest = {\n chainId: Hex;\n isEIP7702GasFeeTokensEnabled: (\n transactionMeta: TransactionMeta,\n ) => Promise<boolean>;\n getSimulationConfig: GetSimulationConfig;\n messenger: TransactionControllerMessenger;\n publicKeyEIP7702?: Hex;\n transactionMeta: TransactionMeta;\n};\n\n/**\n * Get gas fee tokens for a transaction.\n *\n * @param request - The request object.\n * @param request.chainId - The chain ID of the transaction.\n * @param request.isEIP7702GasFeeTokensEnabled - Callback to check if EIP-7702 gas fee tokens are enabled.\n * @param request.messenger - The messenger instance.\n * @param request.publicKeyEIP7702 - Public key to validate EIP-7702 contract signatures.\n * @param request.transactionMeta - The transaction metadata.\n * @param request.getSimulationConfig - Optional transaction simulation parameters.\n * @returns An array of gas fee tokens.\n */\nexport async function getGasFeeTokens({\n chainId,\n isEIP7702GasFeeTokensEnabled,\n messenger,\n publicKeyEIP7702,\n transactionMeta,\n getSimulationConfig,\n}: GetGasFeeTokensRequest) {\n const { delegationAddress, txParams } = transactionMeta;\n const { authorizationList: authorizationListRequest } = txParams;\n const data = txParams.data as Hex;\n const from = txParams.from as Hex;\n const to = txParams.to as Hex;\n const value = txParams.value as Hex;\n\n log('Request', { chainId, txParams });\n\n const is7702GasFeeTokensEnabled =\n await isEIP7702GasFeeTokensEnabled(transactionMeta);\n\n const with7702 =\n is7702GasFeeTokensEnabled && doesChainSupportEIP7702(chainId, messenger);\n\n let authorizationList:\n | SimulationRequestTransaction['authorizationList']\n | undefined = authorizationListRequest?.map((authorization) => ({\n address: authorization.address,\n from: from as Hex,\n }));\n\n if (with7702 && !delegationAddress && !authorizationList) {\n authorizationList = buildAuthorizationList({\n chainId,\n from: from as Hex,\n messenger,\n publicKeyEIP7702,\n });\n }\n\n try {\n const response = await simulateTransactions(chainId, {\n getSimulationConfig,\n transactions: [\n {\n authorizationList,\n data,\n from,\n to,\n value,\n },\n ],\n suggestFees: {\n withTransfer: true,\n withFeeTransfer: true,\n with7702,\n },\n });\n\n log('Response', response);\n\n const result = parseGasFeeTokens(response);\n\n log('Gas fee tokens', result);\n\n return result;\n } catch (error) {\n log('Failed to gas fee tokens', error);\n return { gasFeeTokens: [], isGasFeeSponsored: false };\n }\n}\n\n/**\n * Extract gas fee tokens from a simulation response.\n *\n * @param response - The simulation response.\n * @returns gasFeeTokens: An array of gas fee tokens. isGasFeeSponsored: Whether the transaction is sponsored\n */\nfunction parseGasFeeTokens(response: SimulationResponse): {\n gasFeeTokens: GasFeeToken[];\n isGasFeeSponsored: boolean;\n} {\n const feeLevel = response.transactions?.[0]\n ?.fees?.[0] as Required<SimulationResponseTransaction>['fees'][0];\n\n const isGasFeeSponsored = response.sponsorship?.isSponsored ?? false;\n\n const tokenFees = feeLevel?.tokenFees ?? [];\n\n return {\n gasFeeTokens: tokenFees.map((tokenFee) => ({\n amount: tokenFee.balanceNeededToken,\n balance: tokenFee.currentBalanceToken,\n decimals: tokenFee.token.decimals,\n fee: tokenFee.serviceFee,\n gas: feeLevel.gas,\n gasTransfer: tokenFee.transferEstimate,\n maxFeePerGas: feeLevel.maxFeePerGas,\n maxPriorityFeePerGas: feeLevel.maxPriorityFeePerGas,\n rateWei: tokenFee.rateWei,\n recipient: tokenFee.feeRecipient,\n symbol: tokenFee.token.symbol,\n tokenAddress: tokenFee.token.address,\n })),\n isGasFeeSponsored,\n };\n}\n\n/**\n * Generate the authorization list for the request.\n *\n * @param request - The request object.\n * @param request.chainId - The chain ID.\n * @param request.from - The sender's address.\n * @param request.messenger - The messenger instance.\n * @param request.publicKeyEIP7702 - The public key for EIP-7702.\n * @returns The authorization list.\n */\nfunction buildAuthorizationList({\n chainId,\n from,\n messenger,\n publicKeyEIP7702,\n}: {\n chainId: Hex;\n from: Hex;\n messenger: TransactionControllerMessenger;\n publicKeyEIP7702?: Hex;\n}): SimulationRequestTransaction['authorizationList'] | undefined {\n if (!publicKeyEIP7702) {\n throw rpcErrors.internal(ERROR_MESSGE_PUBLIC_KEY);\n }\n\n const upgradeAddress = getEIP7702UpgradeContractAddress(\n chainId,\n messenger,\n publicKeyEIP7702,\n );\n\n if (!upgradeAddress) {\n throw rpcErrors.internal(ERROR_MESSAGE_NO_UPGRADE_CONTRACT);\n }\n\n return [\n {\n address: upgradeAddress,\n from: from as Hex,\n },\n ];\n}\n"]}
@@ -1,8 +1,10 @@
1
1
  import type { Hex } from "@metamask/utils";
2
2
  import type { GasFeeToken, TransactionControllerMessenger, TransactionMeta } from "../index.cjs";
3
+ import type { GetSimulationConfig } from "../types.cjs";
3
4
  export type GetGasFeeTokensRequest = {
4
5
  chainId: Hex;
5
6
  isEIP7702GasFeeTokensEnabled: (transactionMeta: TransactionMeta) => Promise<boolean>;
7
+ getSimulationConfig: GetSimulationConfig;
6
8
  messenger: TransactionControllerMessenger;
7
9
  publicKeyEIP7702?: Hex;
8
10
  transactionMeta: TransactionMeta;
@@ -16,7 +18,11 @@ export type GetGasFeeTokensRequest = {
16
18
  * @param request.messenger - The messenger instance.
17
19
  * @param request.publicKeyEIP7702 - Public key to validate EIP-7702 contract signatures.
18
20
  * @param request.transactionMeta - The transaction metadata.
21
+ * @param request.getSimulationConfig - Optional transaction simulation parameters.
19
22
  * @returns An array of gas fee tokens.
20
23
  */
21
- export declare function getGasFeeTokens({ chainId, isEIP7702GasFeeTokensEnabled, messenger, publicKeyEIP7702, transactionMeta, }: GetGasFeeTokensRequest): Promise<GasFeeToken[]>;
24
+ export declare function getGasFeeTokens({ chainId, isEIP7702GasFeeTokensEnabled, messenger, publicKeyEIP7702, transactionMeta, getSimulationConfig, }: GetGasFeeTokensRequest): Promise<{
25
+ gasFeeTokens: GasFeeToken[];
26
+ isGasFeeSponsored: boolean;
27
+ }>;
22
28
  //# sourceMappingURL=gas-fee-tokens.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"gas-fee-tokens.d.cts","sourceRoot":"","sources":["../../src/utils/gas-fee-tokens.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAM3C,OAAO,KAAK,EACV,WAAW,EACX,8BAA8B,EAC9B,eAAe,EAChB,qBAAW;AAWZ,MAAM,MAAM,sBAAsB,GAAG;IACnC,OAAO,EAAE,GAAG,CAAC;IACb,4BAA4B,EAAE,CAC5B,eAAe,EAAE,eAAe,KAC7B,OAAO,CAAC,OAAO,CAAC,CAAC;IACtB,SAAS,EAAE,8BAA8B,CAAC;IAC1C,gBAAgB,CAAC,EAAE,GAAG,CAAC;IACvB,eAAe,EAAE,eAAe,CAAC;CAClC,CAAC;AAEF;;;;;;;;;;GAUG;AACH,wBAAsB,eAAe,CAAC,EACpC,OAAO,EACP,4BAA4B,EAC5B,SAAS,EACT,gBAAgB,EAChB,eAAe,GAChB,EAAE,sBAAsB,0BA6DxB"}
1
+ {"version":3,"file":"gas-fee-tokens.d.cts","sourceRoot":"","sources":["../../src/utils/gas-fee-tokens.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAM3C,OAAO,KAAK,EACV,WAAW,EACX,8BAA8B,EAC9B,eAAe,EAChB,qBAAW;AAQZ,OAAO,KAAK,EAAE,mBAAmB,EAAE,qBAAiB;AAIpD,MAAM,MAAM,sBAAsB,GAAG;IACnC,OAAO,EAAE,GAAG,CAAC;IACb,4BAA4B,EAAE,CAC5B,eAAe,EAAE,eAAe,KAC7B,OAAO,CAAC,OAAO,CAAC,CAAC;IACtB,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,SAAS,EAAE,8BAA8B,CAAC;IAC1C,gBAAgB,CAAC,EAAE,GAAG,CAAC;IACvB,eAAe,EAAE,eAAe,CAAC;CAClC,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,wBAAsB,eAAe,CAAC,EACpC,OAAO,EACP,4BAA4B,EAC5B,SAAS,EACT,gBAAgB,EAChB,eAAe,EACf,mBAAmB,GACpB,EAAE,sBAAsB;;;GA8DxB"}
@@ -1,8 +1,10 @@
1
1
  import type { Hex } from "@metamask/utils";
2
2
  import type { GasFeeToken, TransactionControllerMessenger, TransactionMeta } from "../index.mjs";
3
+ import type { GetSimulationConfig } from "../types.mjs";
3
4
  export type GetGasFeeTokensRequest = {
4
5
  chainId: Hex;
5
6
  isEIP7702GasFeeTokensEnabled: (transactionMeta: TransactionMeta) => Promise<boolean>;
7
+ getSimulationConfig: GetSimulationConfig;
6
8
  messenger: TransactionControllerMessenger;
7
9
  publicKeyEIP7702?: Hex;
8
10
  transactionMeta: TransactionMeta;
@@ -16,7 +18,11 @@ export type GetGasFeeTokensRequest = {
16
18
  * @param request.messenger - The messenger instance.
17
19
  * @param request.publicKeyEIP7702 - Public key to validate EIP-7702 contract signatures.
18
20
  * @param request.transactionMeta - The transaction metadata.
21
+ * @param request.getSimulationConfig - Optional transaction simulation parameters.
19
22
  * @returns An array of gas fee tokens.
20
23
  */
21
- export declare function getGasFeeTokens({ chainId, isEIP7702GasFeeTokensEnabled, messenger, publicKeyEIP7702, transactionMeta, }: GetGasFeeTokensRequest): Promise<GasFeeToken[]>;
24
+ export declare function getGasFeeTokens({ chainId, isEIP7702GasFeeTokensEnabled, messenger, publicKeyEIP7702, transactionMeta, getSimulationConfig, }: GetGasFeeTokensRequest): Promise<{
25
+ gasFeeTokens: GasFeeToken[];
26
+ isGasFeeSponsored: boolean;
27
+ }>;
22
28
  //# sourceMappingURL=gas-fee-tokens.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"gas-fee-tokens.d.mts","sourceRoot":"","sources":["../../src/utils/gas-fee-tokens.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAM3C,OAAO,KAAK,EACV,WAAW,EACX,8BAA8B,EAC9B,eAAe,EAChB,qBAAW;AAWZ,MAAM,MAAM,sBAAsB,GAAG;IACnC,OAAO,EAAE,GAAG,CAAC;IACb,4BAA4B,EAAE,CAC5B,eAAe,EAAE,eAAe,KAC7B,OAAO,CAAC,OAAO,CAAC,CAAC;IACtB,SAAS,EAAE,8BAA8B,CAAC;IAC1C,gBAAgB,CAAC,EAAE,GAAG,CAAC;IACvB,eAAe,EAAE,eAAe,CAAC;CAClC,CAAC;AAEF;;;;;;;;;;GAUG;AACH,wBAAsB,eAAe,CAAC,EACpC,OAAO,EACP,4BAA4B,EAC5B,SAAS,EACT,gBAAgB,EAChB,eAAe,GAChB,EAAE,sBAAsB,0BA6DxB"}
1
+ {"version":3,"file":"gas-fee-tokens.d.mts","sourceRoot":"","sources":["../../src/utils/gas-fee-tokens.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAM3C,OAAO,KAAK,EACV,WAAW,EACX,8BAA8B,EAC9B,eAAe,EAChB,qBAAW;AAQZ,OAAO,KAAK,EAAE,mBAAmB,EAAE,qBAAiB;AAIpD,MAAM,MAAM,sBAAsB,GAAG;IACnC,OAAO,EAAE,GAAG,CAAC;IACb,4BAA4B,EAAE,CAC5B,eAAe,EAAE,eAAe,KAC7B,OAAO,CAAC,OAAO,CAAC,CAAC;IACtB,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,SAAS,EAAE,8BAA8B,CAAC;IAC1C,gBAAgB,CAAC,EAAE,GAAG,CAAC;IACvB,eAAe,EAAE,eAAe,CAAC;CAClC,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,wBAAsB,eAAe,CAAC,EACpC,OAAO,EACP,4BAA4B,EAC5B,SAAS,EACT,gBAAgB,EAChB,eAAe,EACf,mBAAmB,GACpB,EAAE,sBAAsB;;;GA8DxB"}
@@ -15,9 +15,10 @@ const log = createModuleLogger(projectLogger, 'gas-fee-tokens');
15
15
  * @param request.messenger - The messenger instance.
16
16
  * @param request.publicKeyEIP7702 - Public key to validate EIP-7702 contract signatures.
17
17
  * @param request.transactionMeta - The transaction metadata.
18
+ * @param request.getSimulationConfig - Optional transaction simulation parameters.
18
19
  * @returns An array of gas fee tokens.
19
20
  */
20
- export async function getGasFeeTokens({ chainId, isEIP7702GasFeeTokensEnabled, messenger, publicKeyEIP7702, transactionMeta, }) {
21
+ export async function getGasFeeTokens({ chainId, isEIP7702GasFeeTokensEnabled, messenger, publicKeyEIP7702, transactionMeta, getSimulationConfig, }) {
21
22
  const { delegationAddress, txParams } = transactionMeta;
22
23
  const { authorizationList: authorizationListRequest } = txParams;
23
24
  const data = txParams.data;
@@ -41,6 +42,7 @@ export async function getGasFeeTokens({ chainId, isEIP7702GasFeeTokensEnabled, m
41
42
  }
42
43
  try {
43
44
  const response = await simulateTransactions(chainId, {
45
+ getSimulationConfig,
44
46
  transactions: [
45
47
  {
46
48
  authorizationList,
@@ -63,33 +65,37 @@ export async function getGasFeeTokens({ chainId, isEIP7702GasFeeTokensEnabled, m
63
65
  }
64
66
  catch (error) {
65
67
  log('Failed to gas fee tokens', error);
66
- return [];
68
+ return { gasFeeTokens: [], isGasFeeSponsored: false };
67
69
  }
68
70
  }
69
71
  /**
70
72
  * Extract gas fee tokens from a simulation response.
71
73
  *
72
74
  * @param response - The simulation response.
73
- * @returns An array of gas fee tokens.
75
+ * @returns gasFeeTokens: An array of gas fee tokens. isGasFeeSponsored: Whether the transaction is sponsored
74
76
  */
75
77
  function parseGasFeeTokens(response) {
76
78
  const feeLevel = response.transactions?.[0]
77
79
  ?.fees?.[0];
80
+ const isGasFeeSponsored = response.sponsorship?.isSponsored ?? false;
78
81
  const tokenFees = feeLevel?.tokenFees ?? [];
79
- return tokenFees.map((tokenFee) => ({
80
- amount: tokenFee.balanceNeededToken,
81
- balance: tokenFee.currentBalanceToken,
82
- decimals: tokenFee.token.decimals,
83
- fee: tokenFee.serviceFee,
84
- gas: feeLevel.gas,
85
- gasTransfer: tokenFee.transferEstimate,
86
- maxFeePerGas: feeLevel.maxFeePerGas,
87
- maxPriorityFeePerGas: feeLevel.maxPriorityFeePerGas,
88
- rateWei: tokenFee.rateWei,
89
- recipient: tokenFee.feeRecipient,
90
- symbol: tokenFee.token.symbol,
91
- tokenAddress: tokenFee.token.address,
92
- }));
82
+ return {
83
+ gasFeeTokens: tokenFees.map((tokenFee) => ({
84
+ amount: tokenFee.balanceNeededToken,
85
+ balance: tokenFee.currentBalanceToken,
86
+ decimals: tokenFee.token.decimals,
87
+ fee: tokenFee.serviceFee,
88
+ gas: feeLevel.gas,
89
+ gasTransfer: tokenFee.transferEstimate,
90
+ maxFeePerGas: feeLevel.maxFeePerGas,
91
+ maxPriorityFeePerGas: feeLevel.maxPriorityFeePerGas,
92
+ rateWei: tokenFee.rateWei,
93
+ recipient: tokenFee.feeRecipient,
94
+ symbol: tokenFee.token.symbol,
95
+ tokenAddress: tokenFee.token.address,
96
+ })),
97
+ isGasFeeSponsored,
98
+ };
93
99
  }
94
100
  /**
95
101
  * Generate the authorization list for the request.
@@ -1 +1 @@
1
- {"version":3,"file":"gas-fee-tokens.mjs","sourceRoot":"","sources":["../../src/utils/gas-fee-tokens.ts"],"names":[],"mappings":"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","sourcesContent":["import { rpcErrors } from '@metamask/rpc-errors';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\n\nimport { ERROR_MESSAGE_NO_UPGRADE_CONTRACT } from './batch';\nimport { ERROR_MESSGE_PUBLIC_KEY, doesChainSupportEIP7702 } from './eip7702';\nimport { getEIP7702UpgradeContractAddress } from './feature-flags';\nimport type {\n GasFeeToken,\n TransactionControllerMessenger,\n TransactionMeta,\n} from '..';\nimport type { SimulationRequestTransaction } from '../api/simulation-api';\nimport {\n simulateTransactions,\n type SimulationResponse,\n type SimulationResponseTransaction,\n} from '../api/simulation-api';\nimport { projectLogger } from '../logger';\n\nconst log = createModuleLogger(projectLogger, 'gas-fee-tokens');\n\nexport type GetGasFeeTokensRequest = {\n chainId: Hex;\n isEIP7702GasFeeTokensEnabled: (\n transactionMeta: TransactionMeta,\n ) => Promise<boolean>;\n messenger: TransactionControllerMessenger;\n publicKeyEIP7702?: Hex;\n transactionMeta: TransactionMeta;\n};\n\n/**\n * Get gas fee tokens for a transaction.\n *\n * @param request - The request object.\n * @param request.chainId - The chain ID of the transaction.\n * @param request.isEIP7702GasFeeTokensEnabled - Callback to check if EIP-7702 gas fee tokens are enabled.\n * @param request.messenger - The messenger instance.\n * @param request.publicKeyEIP7702 - Public key to validate EIP-7702 contract signatures.\n * @param request.transactionMeta - The transaction metadata.\n * @returns An array of gas fee tokens.\n */\nexport async function getGasFeeTokens({\n chainId,\n isEIP7702GasFeeTokensEnabled,\n messenger,\n publicKeyEIP7702,\n transactionMeta,\n}: GetGasFeeTokensRequest) {\n const { delegationAddress, txParams } = transactionMeta;\n const { authorizationList: authorizationListRequest } = txParams;\n const data = txParams.data as Hex;\n const from = txParams.from as Hex;\n const to = txParams.to as Hex;\n const value = txParams.value as Hex;\n\n log('Request', { chainId, txParams });\n\n const is7702GasFeeTokensEnabled =\n await isEIP7702GasFeeTokensEnabled(transactionMeta);\n\n const with7702 =\n is7702GasFeeTokensEnabled && doesChainSupportEIP7702(chainId, messenger);\n\n let authorizationList:\n | SimulationRequestTransaction['authorizationList']\n | undefined = authorizationListRequest?.map((authorization) => ({\n address: authorization.address,\n from: from as Hex,\n }));\n\n if (with7702 && !delegationAddress && !authorizationList) {\n authorizationList = buildAuthorizationList({\n chainId,\n from: from as Hex,\n messenger,\n publicKeyEIP7702,\n });\n }\n\n try {\n const response = await simulateTransactions(chainId, {\n transactions: [\n {\n authorizationList,\n data,\n from,\n to,\n value,\n },\n ],\n suggestFees: {\n withTransfer: true,\n withFeeTransfer: true,\n with7702,\n },\n });\n\n log('Response', response);\n\n const result = parseGasFeeTokens(response);\n\n log('Gas fee tokens', result);\n\n return result;\n } catch (error) {\n log('Failed to gas fee tokens', error);\n return [];\n }\n}\n\n/**\n * Extract gas fee tokens from a simulation response.\n *\n * @param response - The simulation response.\n * @returns An array of gas fee tokens.\n */\nfunction parseGasFeeTokens(response: SimulationResponse): GasFeeToken[] {\n const feeLevel = response.transactions?.[0]\n ?.fees?.[0] as Required<SimulationResponseTransaction>['fees'][0];\n\n const tokenFees = feeLevel?.tokenFees ?? [];\n\n return tokenFees.map((tokenFee) => ({\n amount: tokenFee.balanceNeededToken,\n balance: tokenFee.currentBalanceToken,\n decimals: tokenFee.token.decimals,\n fee: tokenFee.serviceFee,\n gas: feeLevel.gas,\n gasTransfer: tokenFee.transferEstimate,\n maxFeePerGas: feeLevel.maxFeePerGas,\n maxPriorityFeePerGas: feeLevel.maxPriorityFeePerGas,\n rateWei: tokenFee.rateWei,\n recipient: tokenFee.feeRecipient,\n symbol: tokenFee.token.symbol,\n tokenAddress: tokenFee.token.address,\n }));\n}\n\n/**\n * Generate the authorization list for the request.\n *\n * @param request - The request object.\n * @param request.chainId - The chain ID.\n * @param request.from - The sender's address.\n * @param request.messenger - The messenger instance.\n * @param request.publicKeyEIP7702 - The public key for EIP-7702.\n * @returns The authorization list.\n */\nfunction buildAuthorizationList({\n chainId,\n from,\n messenger,\n publicKeyEIP7702,\n}: {\n chainId: Hex;\n from: Hex;\n messenger: TransactionControllerMessenger;\n publicKeyEIP7702?: Hex;\n}): SimulationRequestTransaction['authorizationList'] | undefined {\n if (!publicKeyEIP7702) {\n throw rpcErrors.internal(ERROR_MESSGE_PUBLIC_KEY);\n }\n\n const upgradeAddress = getEIP7702UpgradeContractAddress(\n chainId,\n messenger,\n publicKeyEIP7702,\n );\n\n if (!upgradeAddress) {\n throw rpcErrors.internal(ERROR_MESSAGE_NO_UPGRADE_CONTRACT);\n }\n\n return [\n {\n address: upgradeAddress,\n from: from as Hex,\n },\n ];\n}\n"]}
1
+ {"version":3,"file":"gas-fee-tokens.mjs","sourceRoot":"","sources":["../../src/utils/gas-fee-tokens.ts"],"names":[],"mappings":"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","sourcesContent":["import { rpcErrors } from '@metamask/rpc-errors';\nimport type { Hex } from '@metamask/utils';\nimport { createModuleLogger } from '@metamask/utils';\n\nimport { ERROR_MESSAGE_NO_UPGRADE_CONTRACT } from './batch';\nimport { ERROR_MESSGE_PUBLIC_KEY, doesChainSupportEIP7702 } from './eip7702';\nimport { getEIP7702UpgradeContractAddress } from './feature-flags';\nimport type {\n GasFeeToken,\n TransactionControllerMessenger,\n TransactionMeta,\n} from '..';\nimport type { SimulationRequestTransaction } from '../api/simulation-api';\nimport {\n simulateTransactions,\n type SimulationResponse,\n type SimulationResponseTransaction,\n} from '../api/simulation-api';\nimport { projectLogger } from '../logger';\nimport type { GetSimulationConfig } from '../types';\n\nconst log = createModuleLogger(projectLogger, 'gas-fee-tokens');\n\nexport type GetGasFeeTokensRequest = {\n chainId: Hex;\n isEIP7702GasFeeTokensEnabled: (\n transactionMeta: TransactionMeta,\n ) => Promise<boolean>;\n getSimulationConfig: GetSimulationConfig;\n messenger: TransactionControllerMessenger;\n publicKeyEIP7702?: Hex;\n transactionMeta: TransactionMeta;\n};\n\n/**\n * Get gas fee tokens for a transaction.\n *\n * @param request - The request object.\n * @param request.chainId - The chain ID of the transaction.\n * @param request.isEIP7702GasFeeTokensEnabled - Callback to check if EIP-7702 gas fee tokens are enabled.\n * @param request.messenger - The messenger instance.\n * @param request.publicKeyEIP7702 - Public key to validate EIP-7702 contract signatures.\n * @param request.transactionMeta - The transaction metadata.\n * @param request.getSimulationConfig - Optional transaction simulation parameters.\n * @returns An array of gas fee tokens.\n */\nexport async function getGasFeeTokens({\n chainId,\n isEIP7702GasFeeTokensEnabled,\n messenger,\n publicKeyEIP7702,\n transactionMeta,\n getSimulationConfig,\n}: GetGasFeeTokensRequest) {\n const { delegationAddress, txParams } = transactionMeta;\n const { authorizationList: authorizationListRequest } = txParams;\n const data = txParams.data as Hex;\n const from = txParams.from as Hex;\n const to = txParams.to as Hex;\n const value = txParams.value as Hex;\n\n log('Request', { chainId, txParams });\n\n const is7702GasFeeTokensEnabled =\n await isEIP7702GasFeeTokensEnabled(transactionMeta);\n\n const with7702 =\n is7702GasFeeTokensEnabled && doesChainSupportEIP7702(chainId, messenger);\n\n let authorizationList:\n | SimulationRequestTransaction['authorizationList']\n | undefined = authorizationListRequest?.map((authorization) => ({\n address: authorization.address,\n from: from as Hex,\n }));\n\n if (with7702 && !delegationAddress && !authorizationList) {\n authorizationList = buildAuthorizationList({\n chainId,\n from: from as Hex,\n messenger,\n publicKeyEIP7702,\n });\n }\n\n try {\n const response = await simulateTransactions(chainId, {\n getSimulationConfig,\n transactions: [\n {\n authorizationList,\n data,\n from,\n to,\n value,\n },\n ],\n suggestFees: {\n withTransfer: true,\n withFeeTransfer: true,\n with7702,\n },\n });\n\n log('Response', response);\n\n const result = parseGasFeeTokens(response);\n\n log('Gas fee tokens', result);\n\n return result;\n } catch (error) {\n log('Failed to gas fee tokens', error);\n return { gasFeeTokens: [], isGasFeeSponsored: false };\n }\n}\n\n/**\n * Extract gas fee tokens from a simulation response.\n *\n * @param response - The simulation response.\n * @returns gasFeeTokens: An array of gas fee tokens. isGasFeeSponsored: Whether the transaction is sponsored\n */\nfunction parseGasFeeTokens(response: SimulationResponse): {\n gasFeeTokens: GasFeeToken[];\n isGasFeeSponsored: boolean;\n} {\n const feeLevel = response.transactions?.[0]\n ?.fees?.[0] as Required<SimulationResponseTransaction>['fees'][0];\n\n const isGasFeeSponsored = response.sponsorship?.isSponsored ?? false;\n\n const tokenFees = feeLevel?.tokenFees ?? [];\n\n return {\n gasFeeTokens: tokenFees.map((tokenFee) => ({\n amount: tokenFee.balanceNeededToken,\n balance: tokenFee.currentBalanceToken,\n decimals: tokenFee.token.decimals,\n fee: tokenFee.serviceFee,\n gas: feeLevel.gas,\n gasTransfer: tokenFee.transferEstimate,\n maxFeePerGas: feeLevel.maxFeePerGas,\n maxPriorityFeePerGas: feeLevel.maxPriorityFeePerGas,\n rateWei: tokenFee.rateWei,\n recipient: tokenFee.feeRecipient,\n symbol: tokenFee.token.symbol,\n tokenAddress: tokenFee.token.address,\n })),\n isGasFeeSponsored,\n };\n}\n\n/**\n * Generate the authorization list for the request.\n *\n * @param request - The request object.\n * @param request.chainId - The chain ID.\n * @param request.from - The sender's address.\n * @param request.messenger - The messenger instance.\n * @param request.publicKeyEIP7702 - The public key for EIP-7702.\n * @returns The authorization list.\n */\nfunction buildAuthorizationList({\n chainId,\n from,\n messenger,\n publicKeyEIP7702,\n}: {\n chainId: Hex;\n from: Hex;\n messenger: TransactionControllerMessenger;\n publicKeyEIP7702?: Hex;\n}): SimulationRequestTransaction['authorizationList'] | undefined {\n if (!publicKeyEIP7702) {\n throw rpcErrors.internal(ERROR_MESSGE_PUBLIC_KEY);\n }\n\n const upgradeAddress = getEIP7702UpgradeContractAddress(\n chainId,\n messenger,\n publicKeyEIP7702,\n );\n\n if (!upgradeAddress) {\n throw rpcErrors.internal(ERROR_MESSAGE_NO_UPGRADE_CONTRACT);\n }\n\n return [\n {\n address: upgradeAddress,\n from: from as Hex,\n },\n ];\n}\n"]}
@@ -45,11 +45,12 @@ exports.updateGas = updateGas;
45
45
  * @param options.ethQuery - The EthQuery instance to interact with the network.
46
46
  * @param options.ignoreDelegationSignatures - Ignore signature errors if submitting delegations to the DelegationManager.
47
47
  * @param options.isSimulationEnabled - Whether the simulation is enabled.
48
+ * @param options.getSimulationConfig - The function to get the simulation configuration.
48
49
  * @param options.messenger - The messenger instance for communication.
49
50
  * @param options.txParams - The transaction parameters.
50
51
  * @returns The estimated gas and related info.
51
52
  */
52
- async function estimateGas({ chainId, ethQuery, ignoreDelegationSignatures, isSimulationEnabled, messenger, txParams, }) {
53
+ async function estimateGas({ chainId, ethQuery, ignoreDelegationSignatures, isSimulationEnabled, getSimulationConfig, messenger, txParams, }) {
53
54
  const request = { ...txParams };
54
55
  const { authorizationList, data, from, value, to } = request;
55
56
  if (ignoreDelegationSignatures && !isSimulationEnabled) {
@@ -77,11 +78,12 @@ async function estimateGas({ chainId, ethQuery, ignoreDelegationSignatures, isSi
77
78
  from?.toLowerCase() === to?.toLowerCase();
78
79
  try {
79
80
  if (isSimulationEnabled && isUpgradeWithDataToSelf) {
80
- estimatedGas = await estimateGasUpgradeWithDataToSelf(request, ethQuery, chainId);
81
+ estimatedGas = await estimateGasUpgradeWithDataToSelf(request, ethQuery, chainId, getSimulationConfig);
81
82
  }
82
83
  else if (ignoreDelegationSignatures && isSimulationEnabled) {
83
84
  estimatedGas = await simulateGas({
84
85
  chainId,
86
+ getSimulationConfig,
85
87
  transaction: request,
86
88
  });
87
89
  }
@@ -143,12 +145,14 @@ exports.addGasBuffer = addGasBuffer;
143
145
  * @param options - The options object.
144
146
  * @param options.chainId - The chain ID of the transactions.
145
147
  * @param options.from - The address of the sender.
148
+ * @param options.getSimulationConfig - The function to get the simulation configuration.
146
149
  * @param options.transactions - The array of transactions within a batch request.
147
150
  * @returns An object containing the transactions with their gas limits and the total gas limit.
148
151
  */
149
- async function simulateGasBatch({ chainId, from, transactions, }) {
152
+ async function simulateGasBatch({ chainId, from, getSimulationConfig, transactions, }) {
150
153
  try {
151
154
  const response = await (0, simulation_api_1.simulateTransactions)(chainId, {
155
+ getSimulationConfig,
152
156
  transactions: transactions.map((transaction) => ({
153
157
  ...transaction.params,
154
158
  from,
@@ -182,7 +186,7 @@ exports.simulateGasBatch = simulateGasBatch;
182
186
  * @returns The final gas value and the estimate used.
183
187
  */
184
188
  async function getGas(request) {
185
- const { chainId, isCustomNetwork, isSimulationEnabled, messenger, txMeta } = request;
189
+ const { chainId, isCustomNetwork, isSimulationEnabled, getSimulationConfig, messenger, txMeta, } = request;
186
190
  const { disableGasBuffer } = txMeta;
187
191
  if (txMeta.txParams.gas) {
188
192
  (0, exports.log)('Using value from request', txMeta.txParams.gas);
@@ -193,9 +197,10 @@ async function getGas(request) {
193
197
  return [exports.FIXED_GAS, undefined, exports.FIXED_GAS];
194
198
  }
195
199
  const { blockGasLimit, estimatedGas, isUpgradeWithDataToSelf, simulationFails, } = await estimateGas({
196
- chainId: request.chainId,
200
+ chainId,
197
201
  ethQuery: request.ethQuery,
198
202
  isSimulationEnabled,
203
+ getSimulationConfig,
199
204
  messenger,
200
205
  txParams: txMeta.txParams,
201
206
  });
@@ -265,9 +270,10 @@ async function getLatestBlock(ethQuery) {
265
270
  * @param txParams - The transaction parameters.
266
271
  * @param ethQuery - The EthQuery instance to interact with the network.
267
272
  * @param chainId - The chain ID of the transaction.
273
+ * @param getSimulationConfig - The function to get the simulation configuration.
268
274
  * @returns The estimated gas.
269
275
  */
270
- async function estimateGasUpgradeWithDataToSelf(txParams, ethQuery, chainId) {
276
+ async function estimateGasUpgradeWithDataToSelf(txParams, ethQuery, chainId, getSimulationConfig) {
271
277
  const upgradeGas = await (0, controller_utils_1.query)(ethQuery, 'estimateGas', [
272
278
  {
273
279
  ...txParams,
@@ -281,6 +287,7 @@ async function estimateGasUpgradeWithDataToSelf(txParams, ethQuery, chainId) {
281
287
  executeGas = await simulateGas({
282
288
  chainId: chainId,
283
289
  delegationAddress,
290
+ getSimulationConfig,
284
291
  transaction: txParams,
285
292
  });
286
293
  }
@@ -310,11 +317,13 @@ async function estimateGasUpgradeWithDataToSelf(txParams, ethQuery, chainId) {
310
317
  * @param options - The options object.
311
318
  * @param options.chainId - The chain ID of the transaction.
312
319
  * @param options.delegationAddress - The delegation address of the sender to mock.
320
+ * @param options.getSimulationConfig - The function to get the simulation configuration.
313
321
  * @param options.transaction - The transaction parameters.
314
322
  * @returns The simulated gas.
315
323
  */
316
- async function simulateGas({ chainId, delegationAddress, transaction, }) {
324
+ async function simulateGas({ chainId, delegationAddress, getSimulationConfig, transaction, }) {
317
325
  const response = await (0, simulation_api_1.simulateTransactions)(chainId, {
326
+ getSimulationConfig,
318
327
  transactions: [
319
328
  {
320
329
  to: transaction.to,
@@ -1 +1 @@
1
- {"version":3,"file":"gas.cjs","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, Json } from '@metamask/utils';\nimport { add0x, createModuleLogger, remove0x } from '@metamask/utils';\nimport { BN } from 'bn.js';\n\nimport { DELEGATION_PREFIX } from './eip7702';\nimport { getGasEstimateBuffer, getGasEstimateFallback } from './feature-flags';\nimport { simulateTransactions } from '../api/simulation-api';\nimport { projectLogger } from '../logger';\nimport type { TransactionControllerMessenger } from '../TransactionController';\nimport type { TransactionBatchSingleRequest } from '../types';\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.ignoreDelegationSignatures - Ignore signature errors if submitting delegations to the DelegationManager.\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 ignoreDelegationSignatures,\n isSimulationEnabled,\n messenger,\n txParams,\n}: {\n chainId: Hex;\n ethQuery: EthQuery;\n ignoreDelegationSignatures?: boolean;\n isSimulationEnabled: boolean;\n messenger: TransactionControllerMessenger;\n txParams: TransactionParams;\n}) {\n const request = { ...txParams };\n const { authorizationList, data, from, value, to } = request;\n\n if (ignoreDelegationSignatures && !isSimulationEnabled) {\n throw new Error(\n 'Gas estimation with ignored delegation signatures is not supported as simulation disabled',\n );\n }\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 Boolean(authorizationList?.length) &&\n Boolean(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 if (ignoreDelegationSignatures && isSimulationEnabled) {\n estimatedGas = await simulateGas({\n chainId,\n transaction: request,\n });\n } else {\n estimatedGas = await estimateGasNode(ethQuery, 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 isUpgradeWithDataToSelf,\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 * Simulate the required gas for a batch of transactions using the simulation API.\n *\n * @param options - The options object.\n * @param options.chainId - The chain ID of the transactions.\n * @param options.from - The address of the sender.\n * @param options.transactions - The array of transactions within a batch request.\n * @returns An object containing the transactions with their gas limits and the total gas limit.\n */\nexport async function simulateGasBatch({\n chainId,\n from,\n transactions,\n}: {\n chainId: Hex;\n from: Hex;\n transactions: TransactionBatchSingleRequest[];\n}): Promise<{ gasLimit: Hex }> {\n try {\n const response = await simulateTransactions(chainId, {\n transactions: transactions.map((transaction) => ({\n ...transaction.params,\n from,\n })),\n });\n\n if (\n !response?.transactions ||\n response.transactions.length !== transactions.length\n ) {\n throw new Error('Simulation response does not match transaction count');\n }\n\n const totalGasLimit = response.transactions.reduce((acc, transaction) => {\n const gasLimit = transaction?.gasLimit;\n\n if (!gasLimit) {\n throw new Error(\n 'No simulated gas returned for one of the transactions',\n );\n }\n\n return acc.add(hexToBN(gasLimit));\n }, new BN(0));\n\n return {\n gasLimit: BNToHex(totalGasLimit), // Return the total gas limit as a hex string\n };\n } catch (error: unknown) {\n log('Error while simulating gas batch', error);\n throw new Error(\n 'Cannot estimate transaction batch total gas as simulation failed',\n );\n }\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, messenger, txMeta } =\n 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 {\n blockGasLimit,\n estimatedGas,\n isUpgradeWithDataToSelf,\n simulationFails,\n } = await estimateGas({\n chainId: request.chainId,\n ethQuery: request.ethQuery,\n isSimulationEnabled,\n messenger,\n txParams: txMeta.txParams,\n });\n\n log('Original estimated gas', estimatedGas);\n\n if (simulationFails) {\n log('Using original fallback estimate as simulation failed');\n }\n\n if (disableGasBuffer) {\n log('Gas buffer disabled');\n }\n\n if (simulationFails || disableGasBuffer) {\n return [estimatedGas, simulationFails, estimatedGas];\n }\n\n const bufferMultiplier = getGasEstimateBuffer({\n chainId,\n isCustomRPC: isCustomNetwork,\n isUpgradeWithDataToSelf,\n messenger,\n });\n\n log('Buffer', bufferMultiplier);\n\n const bufferedGas = addGasBuffer(\n estimatedGas,\n blockGasLimit,\n bufferMultiplier,\n );\n\n log('Buffered gas', bufferedGas);\n\n return [bufferedGas, 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, type },\n } = txMeta;\n\n if (\n isCustomNetwork ||\n !to ||\n data ||\n type === TransactionEnvelopeType.setCode\n ) {\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 let executeGas: Hex | undefined;\n\n try {\n executeGas = await simulateGas({\n chainId: chainId as Hex,\n delegationAddress,\n transaction: txParams,\n });\n } catch (error: unknown) {\n log('Error while simulating data portion of upgrade', error);\n }\n\n if (executeGas === undefined) {\n try {\n executeGas = await estimateGasNode(\n ethQuery,\n { ...txParams, authorizationList: undefined, type: undefined },\n delegationAddress,\n );\n } catch (error: unknown) {\n log('Error while estimating data portion of upgrade', error);\n throw error;\n }\n\n log('Success estimating data portion of upgrade', executeGas);\n }\n\n log('Execute gas', executeGas);\n\n const total = BNToHex(\n hexToBN(upgradeGas)\n .add(hexToBN(executeGas as Hex))\n .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 gasLimit = response?.transactions?.[0].gasLimit;\n\n if (!gasLimit) {\n throw new Error('No simulated gas returned');\n }\n\n return gasLimit;\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\n/**\n * Estimate the gas for a transaction using the `eth_estimateGas` method.\n *\n * @param ethQuery - The EthQuery instance to interact with the network.\n * @param txParams - The transaction parameters.\n * @param delegationAddress - The delegation address of the sender to mock.\n * @returns The estimated gas as a hex string.\n */\nfunction estimateGasNode(\n ethQuery: EthQuery,\n txParams: TransactionParams,\n delegationAddress?: Hex,\n) {\n const { from } = txParams;\n const params = [txParams] as Json[];\n\n if (delegationAddress) {\n params.push('latest');\n\n params.push({\n [from as string]: {\n code: DELEGATION_PREFIX + remove0x(delegationAddress),\n },\n });\n }\n\n return query(ethQuery, 'estimateGas', params);\n}\n"]}
1
+ {"version":3,"file":"gas.cjs","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, Json } from '@metamask/utils';\nimport { add0x, createModuleLogger, remove0x } from '@metamask/utils';\nimport { BN } from 'bn.js';\n\nimport { DELEGATION_PREFIX } from './eip7702';\nimport { getGasEstimateBuffer, getGasEstimateFallback } from './feature-flags';\nimport { simulateTransactions } from '../api/simulation-api';\nimport { projectLogger } from '../logger';\nimport type { TransactionControllerMessenger } from '../TransactionController';\nimport type {\n GetSimulationConfig,\n TransactionBatchSingleRequest,\n} from '../types';\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 getSimulationConfig: GetSimulationConfig;\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.ignoreDelegationSignatures - Ignore signature errors if submitting delegations to the DelegationManager.\n * @param options.isSimulationEnabled - Whether the simulation is enabled.\n * @param options.getSimulationConfig - The function to get the simulation configuration.\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 ignoreDelegationSignatures,\n isSimulationEnabled,\n getSimulationConfig,\n messenger,\n txParams,\n}: {\n chainId: Hex;\n ethQuery: EthQuery;\n ignoreDelegationSignatures?: boolean;\n isSimulationEnabled: boolean;\n getSimulationConfig: GetSimulationConfig;\n messenger: TransactionControllerMessenger;\n txParams: TransactionParams;\n}) {\n const request = { ...txParams };\n const { authorizationList, data, from, value, to } = request;\n\n if (ignoreDelegationSignatures && !isSimulationEnabled) {\n throw new Error(\n 'Gas estimation with ignored delegation signatures is not supported as simulation disabled',\n );\n }\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 Boolean(authorizationList?.length) &&\n Boolean(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 getSimulationConfig,\n );\n } else if (ignoreDelegationSignatures && isSimulationEnabled) {\n estimatedGas = await simulateGas({\n chainId,\n getSimulationConfig,\n transaction: request,\n });\n } else {\n estimatedGas = await estimateGasNode(ethQuery, 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 isUpgradeWithDataToSelf,\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 * Simulate the required gas for a batch of transactions using the simulation API.\n *\n * @param options - The options object.\n * @param options.chainId - The chain ID of the transactions.\n * @param options.from - The address of the sender.\n * @param options.getSimulationConfig - The function to get the simulation configuration.\n * @param options.transactions - The array of transactions within a batch request.\n * @returns An object containing the transactions with their gas limits and the total gas limit.\n */\nexport async function simulateGasBatch({\n chainId,\n from,\n getSimulationConfig,\n transactions,\n}: {\n chainId: Hex;\n from: Hex;\n getSimulationConfig: GetSimulationConfig;\n transactions: TransactionBatchSingleRequest[];\n}): Promise<{ gasLimit: Hex }> {\n try {\n const response = await simulateTransactions(chainId, {\n getSimulationConfig,\n transactions: transactions.map((transaction) => ({\n ...transaction.params,\n from,\n })),\n });\n\n if (\n !response?.transactions ||\n response.transactions.length !== transactions.length\n ) {\n throw new Error('Simulation response does not match transaction count');\n }\n\n const totalGasLimit = response.transactions.reduce((acc, transaction) => {\n const gasLimit = transaction?.gasLimit;\n\n if (!gasLimit) {\n throw new Error(\n 'No simulated gas returned for one of the transactions',\n );\n }\n\n return acc.add(hexToBN(gasLimit));\n }, new BN(0));\n\n return {\n gasLimit: BNToHex(totalGasLimit), // Return the total gas limit as a hex string\n };\n } catch (error: unknown) {\n log('Error while simulating gas batch', error);\n throw new Error(\n 'Cannot estimate transaction batch total gas as simulation failed',\n );\n }\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 {\n chainId,\n isCustomNetwork,\n isSimulationEnabled,\n getSimulationConfig,\n messenger,\n txMeta,\n } = 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 {\n blockGasLimit,\n estimatedGas,\n isUpgradeWithDataToSelf,\n simulationFails,\n } = await estimateGas({\n chainId,\n ethQuery: request.ethQuery,\n isSimulationEnabled,\n getSimulationConfig,\n messenger,\n txParams: txMeta.txParams,\n });\n\n log('Original estimated gas', estimatedGas);\n\n if (simulationFails) {\n log('Using original fallback estimate as simulation failed');\n }\n\n if (disableGasBuffer) {\n log('Gas buffer disabled');\n }\n\n if (simulationFails || disableGasBuffer) {\n return [estimatedGas, simulationFails, estimatedGas];\n }\n\n const bufferMultiplier = getGasEstimateBuffer({\n chainId,\n isCustomRPC: isCustomNetwork,\n isUpgradeWithDataToSelf,\n messenger,\n });\n\n log('Buffer', bufferMultiplier);\n\n const bufferedGas = addGasBuffer(\n estimatedGas,\n blockGasLimit,\n bufferMultiplier,\n );\n\n log('Buffered gas', bufferedGas);\n\n return [bufferedGas, 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, type },\n } = txMeta;\n\n if (\n isCustomNetwork ||\n !to ||\n data ||\n type === TransactionEnvelopeType.setCode\n ) {\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 * @param getSimulationConfig - The function to get the simulation configuration.\n * @returns The estimated gas.\n */\nasync function estimateGasUpgradeWithDataToSelf(\n txParams: TransactionParams,\n ethQuery: EthQuery,\n chainId: Hex,\n getSimulationConfig: GetSimulationConfig,\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 let executeGas: Hex | undefined;\n\n try {\n executeGas = await simulateGas({\n chainId: chainId as Hex,\n delegationAddress,\n getSimulationConfig,\n transaction: txParams,\n });\n } catch (error: unknown) {\n log('Error while simulating data portion of upgrade', error);\n }\n\n if (executeGas === undefined) {\n try {\n executeGas = await estimateGasNode(\n ethQuery,\n { ...txParams, authorizationList: undefined, type: undefined },\n delegationAddress,\n );\n } catch (error: unknown) {\n log('Error while estimating data portion of upgrade', error);\n throw error;\n }\n\n log('Success estimating data portion of upgrade', executeGas);\n }\n\n log('Execute gas', executeGas);\n\n const total = BNToHex(\n hexToBN(upgradeGas)\n .add(hexToBN(executeGas as Hex))\n .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.getSimulationConfig - The function to get the simulation configuration.\n * @param options.transaction - The transaction parameters.\n * @returns The simulated gas.\n */\nasync function simulateGas({\n chainId,\n delegationAddress,\n getSimulationConfig,\n transaction,\n}: {\n chainId: Hex;\n delegationAddress?: Hex;\n getSimulationConfig: GetSimulationConfig;\n transaction: TransactionParams;\n}): Promise<Hex> {\n const response = await simulateTransactions(chainId, {\n getSimulationConfig,\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 gasLimit = response?.transactions?.[0].gasLimit;\n\n if (!gasLimit) {\n throw new Error('No simulated gas returned');\n }\n\n return gasLimit;\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\n/**\n * Estimate the gas for a transaction using the `eth_estimateGas` method.\n *\n * @param ethQuery - The EthQuery instance to interact with the network.\n * @param txParams - The transaction parameters.\n * @param delegationAddress - The delegation address of the sender to mock.\n * @returns The estimated gas as a hex string.\n */\nfunction estimateGasNode(\n ethQuery: EthQuery,\n txParams: TransactionParams,\n delegationAddress?: Hex,\n) {\n const { from } = txParams;\n const params = [txParams] as Json[];\n\n if (delegationAddress) {\n params.push('latest');\n\n params.push({\n [from as string]: {\n code: DELEGATION_PREFIX + remove0x(delegationAddress),\n },\n });\n }\n\n return query(ethQuery, 'estimateGas', params);\n}\n"]}