@metamask-previews/transaction-controller 52.0.0-preview-5a3453d → 52.0.0-preview-e3c959f

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 (122) hide show
  1. package/CHANGELOG.md +2 -3
  2. package/dist/TransactionController.cjs +15 -15
  3. package/dist/TransactionController.cjs.map +1 -1
  4. package/dist/TransactionController.d.cts.map +1 -1
  5. package/dist/TransactionController.d.mts.map +1 -1
  6. package/dist/TransactionController.mjs +15 -15
  7. package/dist/TransactionController.mjs.map +1 -1
  8. package/dist/gas-flows/DefaultGasFeeFlow.cjs +3 -1
  9. package/dist/gas-flows/DefaultGasFeeFlow.cjs.map +1 -1
  10. package/dist/gas-flows/DefaultGasFeeFlow.d.cts +2 -2
  11. package/dist/gas-flows/DefaultGasFeeFlow.d.cts.map +1 -1
  12. package/dist/gas-flows/DefaultGasFeeFlow.d.mts +2 -2
  13. package/dist/gas-flows/DefaultGasFeeFlow.d.mts.map +1 -1
  14. package/dist/gas-flows/DefaultGasFeeFlow.mjs +3 -1
  15. package/dist/gas-flows/DefaultGasFeeFlow.mjs.map +1 -1
  16. package/dist/gas-flows/LineaGasFeeFlow.cjs +1 -1
  17. package/dist/gas-flows/LineaGasFeeFlow.cjs.map +1 -1
  18. package/dist/gas-flows/LineaGasFeeFlow.d.cts +1 -5
  19. package/dist/gas-flows/LineaGasFeeFlow.d.cts.map +1 -1
  20. package/dist/gas-flows/LineaGasFeeFlow.d.mts +1 -5
  21. package/dist/gas-flows/LineaGasFeeFlow.d.mts.map +1 -1
  22. package/dist/gas-flows/LineaGasFeeFlow.mjs +1 -1
  23. package/dist/gas-flows/LineaGasFeeFlow.mjs.map +1 -1
  24. package/dist/gas-flows/OptimismLayer1GasFeeFlow.cjs +1 -1
  25. package/dist/gas-flows/OptimismLayer1GasFeeFlow.cjs.map +1 -1
  26. package/dist/gas-flows/OptimismLayer1GasFeeFlow.d.cts +1 -5
  27. package/dist/gas-flows/OptimismLayer1GasFeeFlow.d.cts.map +1 -1
  28. package/dist/gas-flows/OptimismLayer1GasFeeFlow.d.mts +1 -5
  29. package/dist/gas-flows/OptimismLayer1GasFeeFlow.d.mts.map +1 -1
  30. package/dist/gas-flows/OptimismLayer1GasFeeFlow.mjs +1 -1
  31. package/dist/gas-flows/OptimismLayer1GasFeeFlow.mjs.map +1 -1
  32. package/dist/gas-flows/OracleLayer1GasFeeFlow.cjs.map +1 -1
  33. package/dist/gas-flows/OracleLayer1GasFeeFlow.d.cts +1 -5
  34. package/dist/gas-flows/OracleLayer1GasFeeFlow.d.cts.map +1 -1
  35. package/dist/gas-flows/OracleLayer1GasFeeFlow.d.mts +1 -5
  36. package/dist/gas-flows/OracleLayer1GasFeeFlow.d.mts.map +1 -1
  37. package/dist/gas-flows/OracleLayer1GasFeeFlow.mjs.map +1 -1
  38. package/dist/gas-flows/ScrollLayer1GasFeeFlow.cjs +1 -1
  39. package/dist/gas-flows/ScrollLayer1GasFeeFlow.cjs.map +1 -1
  40. package/dist/gas-flows/ScrollLayer1GasFeeFlow.d.cts +1 -5
  41. package/dist/gas-flows/ScrollLayer1GasFeeFlow.d.cts.map +1 -1
  42. package/dist/gas-flows/ScrollLayer1GasFeeFlow.d.mts +1 -5
  43. package/dist/gas-flows/ScrollLayer1GasFeeFlow.d.mts.map +1 -1
  44. package/dist/gas-flows/ScrollLayer1GasFeeFlow.mjs +1 -1
  45. package/dist/gas-flows/ScrollLayer1GasFeeFlow.mjs.map +1 -1
  46. package/dist/gas-flows/TestGasFeeFlow.cjs +1 -1
  47. package/dist/gas-flows/TestGasFeeFlow.cjs.map +1 -1
  48. package/dist/gas-flows/TestGasFeeFlow.d.cts +2 -2
  49. package/dist/gas-flows/TestGasFeeFlow.d.cts.map +1 -1
  50. package/dist/gas-flows/TestGasFeeFlow.d.mts +2 -2
  51. package/dist/gas-flows/TestGasFeeFlow.d.mts.map +1 -1
  52. package/dist/gas-flows/TestGasFeeFlow.mjs +1 -1
  53. package/dist/gas-flows/TestGasFeeFlow.mjs.map +1 -1
  54. package/dist/helpers/GasFeePoller.cjs +4 -9
  55. package/dist/helpers/GasFeePoller.cjs.map +1 -1
  56. package/dist/helpers/GasFeePoller.d.cts +1 -4
  57. package/dist/helpers/GasFeePoller.d.cts.map +1 -1
  58. package/dist/helpers/GasFeePoller.d.mts +1 -4
  59. package/dist/helpers/GasFeePoller.d.mts.map +1 -1
  60. package/dist/helpers/GasFeePoller.mjs +4 -9
  61. package/dist/helpers/GasFeePoller.mjs.map +1 -1
  62. package/dist/types.cjs.map +1 -1
  63. package/dist/types.d.cts +3 -15
  64. package/dist/types.d.cts.map +1 -1
  65. package/dist/types.d.mts +3 -15
  66. package/dist/types.d.mts.map +1 -1
  67. package/dist/types.mjs.map +1 -1
  68. package/dist/utils/feature-flags.cjs +3 -16
  69. package/dist/utils/feature-flags.cjs.map +1 -1
  70. package/dist/utils/feature-flags.d.cts +2 -12
  71. package/dist/utils/feature-flags.d.cts.map +1 -1
  72. package/dist/utils/feature-flags.d.mts +2 -12
  73. package/dist/utils/feature-flags.d.mts.map +1 -1
  74. package/dist/utils/feature-flags.mjs +2 -14
  75. package/dist/utils/feature-flags.mjs.map +1 -1
  76. package/dist/utils/gas-fees.cjs +3 -21
  77. package/dist/utils/gas-fees.cjs.map +1 -1
  78. package/dist/utils/gas-fees.d.cts +0 -14
  79. package/dist/utils/gas-fees.d.cts.map +1 -1
  80. package/dist/utils/gas-fees.d.mts +0 -14
  81. package/dist/utils/gas-fees.d.mts.map +1 -1
  82. package/dist/utils/gas-fees.mjs +2 -19
  83. package/dist/utils/gas-fees.mjs.map +1 -1
  84. package/dist/utils/gas-flow.cjs +2 -3
  85. package/dist/utils/gas-flow.cjs.map +1 -1
  86. package/dist/utils/gas-flow.d.cts +1 -3
  87. package/dist/utils/gas-flow.d.cts.map +1 -1
  88. package/dist/utils/gas-flow.d.mts +1 -3
  89. package/dist/utils/gas-flow.d.mts.map +1 -1
  90. package/dist/utils/gas-flow.mjs +2 -3
  91. package/dist/utils/gas-flow.mjs.map +1 -1
  92. package/dist/utils/gas.cjs +108 -8
  93. package/dist/utils/gas.cjs.map +1 -1
  94. package/dist/utils/gas.d.cts +16 -5
  95. package/dist/utils/gas.d.cts.map +1 -1
  96. package/dist/utils/gas.d.mts +16 -5
  97. package/dist/utils/gas.d.mts.map +1 -1
  98. package/dist/utils/gas.mjs +108 -8
  99. package/dist/utils/gas.mjs.map +1 -1
  100. package/dist/utils/layer1-gas-fee-flow.cjs +4 -9
  101. package/dist/utils/layer1-gas-fee-flow.cjs.map +1 -1
  102. package/dist/utils/layer1-gas-fee-flow.d.cts +1 -4
  103. package/dist/utils/layer1-gas-fee-flow.d.cts.map +1 -1
  104. package/dist/utils/layer1-gas-fee-flow.d.mts +1 -4
  105. package/dist/utils/layer1-gas-fee-flow.d.mts.map +1 -1
  106. package/dist/utils/layer1-gas-fee-flow.mjs +4 -9
  107. package/dist/utils/layer1-gas-fee-flow.mjs.map +1 -1
  108. package/dist/utils/simulation-api.cjs.map +1 -1
  109. package/dist/utils/simulation-api.d.cts +9 -5
  110. package/dist/utils/simulation-api.d.cts.map +1 -1
  111. package/dist/utils/simulation-api.d.mts +9 -5
  112. package/dist/utils/simulation-api.d.mts.map +1 -1
  113. package/dist/utils/simulation-api.mjs.map +1 -1
  114. package/package.json +1 -1
  115. package/dist/gas-flows/RandomisedEstimationsGasFeeFlow.cjs +0 -145
  116. package/dist/gas-flows/RandomisedEstimationsGasFeeFlow.cjs.map +0 -1
  117. package/dist/gas-flows/RandomisedEstimationsGasFeeFlow.d.cts +0 -27
  118. package/dist/gas-flows/RandomisedEstimationsGasFeeFlow.d.cts.map +0 -1
  119. package/dist/gas-flows/RandomisedEstimationsGasFeeFlow.d.mts +0 -27
  120. package/dist/gas-flows/RandomisedEstimationsGasFeeFlow.d.mts.map +0 -1
  121. package/dist/gas-flows/RandomisedEstimationsGasFeeFlow.mjs +0 -140
  122. package/dist/gas-flows/RandomisedEstimationsGasFeeFlow.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"simulation-api.mjs","sourceRoot":"","sources":["../../src/utils/simulation-api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,mCAAmC;AACjE,OAAO,EAAE,kBAAkB,EAAY,wBAAwB;AAE/D,OAAO,EAAE,gCAAgC,EAAE,eAAe,EAAE,sBAAkB;AAC9E,OAAO,EAAE,aAAa,EAAE,sBAAkB;AAE1C,MAAM,GAAG,GAAG,kBAAkB,CAAC,aAAa,EAAE,gBAAgB,CAAC,CAAC;AAEhE,MAAM,UAAU,GAAG,6BAA6B,CAAC;AACjD,MAAM,QAAQ,GAAG,6CAA6C,CAAC;AAC/D,MAAM,iBAAiB,GAAG,UAAU,CAAC;AAgJrC,IAAI,gBAAgB,GAAG,CAAC,CAAC;AAEzB;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,OAAY,EACZ,OAA0B;IAE1B,MAAM,GAAG,GAAG,MAAM,gBAAgB,CAAC,OAAO,CAAC,CAAC;IAE5C,GAAG,CAAC,iBAAiB,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;IAErC,MAAM,SAAS,GAAG,gBAAgB,CAAC;IACnC,gBAAgB,IAAI,CAAC,CAAC;IAEtB,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAChC,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;YACnB,EAAE,EAAE,MAAM,CAAC,SAAS,CAAC;YACrB,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,UAAU;YAClB,MAAM,EAAE,CAAC,OAAO,CAAC;SAClB,CAAC;KACH,CAAC,CAAC;IAEH,MAAM,YAAY,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IAE3C,GAAG,CAAC,mBAAmB,EAAE,YAAY,CAAC,CAAC;IAEvC,IAAI,YAAY,CAAC,KAAK,EAAE;QACtB,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,YAAY,CAAC,KAAK,CAAC;QAC7C,MAAM,IAAI,eAAe,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;KAC1C;IAED,OAAO,YAAY,EAAE,MAAM,CAAC;AAC9B,CAAC;AAED;;;;;GAKG;AACH,KAAK,UAAU,gBAAgB,CAAC,OAAY;IAC1C,MAAM,WAAW,GAAG,MAAM,cAAc,EAAE,CAAC;IAC3C,MAAM,cAAc,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAC;IACpD,MAAM,OAAO,GAAG,WAAW,CAAC,cAAc,CAAC,CAAC;IAE5C,IAAI,CAAC,OAAO,EAAE,aAAa,EAAE;QAC3B,GAAG,CAAC,wBAAwB,EAAE,OAAO,CAAC,CAAC;QACvC,MAAM,IAAI,gCAAgC,CAAC,OAAO,CAAC,CAAC;KACrD;IAED,OAAO,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;AACjC,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,cAAc;IAC3B,MAAM,GAAG,GAAG,GAAG,MAAM,CAAC,kBAAkB,CAAC,GAAG,iBAAiB,EAAE,CAAC;IAChE,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;IAClC,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC;AACzB,CAAC;AAED;;;;;GAKG;AACH,SAAS,MAAM,CAAC,SAAiB;IAC/B,OAAO,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;AAC5C,CAAC","sourcesContent":["import { convertHexToDecimal } from '@metamask/controller-utils';\nimport { createModuleLogger, type Hex } from '@metamask/utils';\n\nimport { SimulationChainNotSupportedError, SimulationError } from '../errors';\nimport { projectLogger } from '../logger';\n\nconst log = createModuleLogger(projectLogger, 'simulation-api');\n\nconst RPC_METHOD = 'infura_simulateTransactions';\nconst BASE_URL = 'https://tx-sentinel-{0}.api.cx.metamask.io/';\nconst ENDPOINT_NETWORKS = 'networks';\n\n/** Single transaction to simulate in a simulation API request. */\nexport type SimulationRequestTransaction = {\n /** Data to send with the transaction. */\n data?: Hex;\n\n /** Sender of the transaction. */\n from: Hex;\n\n /** Gas limit for the transaction. */\n gas?: Hex;\n\n /** Maximum fee per gas for the transaction. */\n maxFeePerGas?: Hex;\n\n /** Maximum priority fee per gas for the transaction. */\n maxPriorityFeePerGas?: Hex;\n\n /** Recipient of the transaction. */\n to?: Hex;\n\n /** Value to send with the transaction. */\n value?: Hex;\n};\n\n/** Request to the simulation API to simulate transactions. */\nexport type SimulationRequest = {\n /**\n * Transactions to be sequentially simulated.\n * State changes impact subsequent transactions in the list.\n */\n transactions: SimulationRequestTransaction[];\n\n blockOverrides?: {\n time?: Hex;\n };\n\n /**\n * Overrides to the state of the blockchain, keyed by smart contract address.\n */\n overrides?: {\n [address: Hex]: {\n /** Overrides to the storage slots for a smart contract account. */\n stateDiff: {\n [slot: Hex]: Hex;\n };\n };\n };\n\n /**\n * Whether to include call traces in the response.\n * Defaults to false.\n */\n withCallTrace?: boolean;\n\n /**\n * Whether to include event logs in the response.\n * Defaults to false.\n */\n withLogs?: boolean;\n};\n\n/** Raw event log emitted by a simulated transaction. */\nexport type SimulationResponseLog = {\n /** Address of the account that created the event. */\n address: Hex;\n\n /** Raw data in the event that is not indexed. */\n data: Hex;\n\n /** Raw indexed data from the event. */\n topics: Hex[];\n};\n\n/** Call trace of a single simulated transaction. */\nexport type SimulationResponseCallTrace = {\n /** Nested calls. */\n calls: SimulationResponseCallTrace[];\n\n /** Raw event logs created by the call. */\n logs: SimulationResponseLog[];\n};\n\n/**\n * Changes to the blockchain state.\n * Keyed by account address.\n */\nexport type SimulationResponseStateDiff = {\n [address: Hex]: {\n /** Native balance of the account. */\n balance?: Hex;\n\n /** Nonce of the account. */\n nonce?: Hex;\n\n /** Storage values per slot. */\n storage?: {\n [slot: Hex]: Hex;\n };\n };\n};\n\n/** Response from the simulation API for a single transaction. */\nexport type SimulationResponseTransaction = {\n /** An error message indicating the transaction could not be simulated. */\n error?: string;\n\n /** Return value of the transaction, such as the balance if calling balanceOf. */\n return: Hex;\n\n /** Hierarchy of call data including nested calls and logs. */\n callTrace?: SimulationResponseCallTrace;\n\n /** Changes to the blockchain state. */\n stateDiff?: {\n /** Initial blockchain state before the transaction. */\n pre?: SimulationResponseStateDiff;\n\n /** Updated blockchain state after the transaction. */\n post?: SimulationResponseStateDiff;\n };\n};\n\n/** Response from the simulation API. */\nexport type SimulationResponse = {\n /** Simulation data for each transaction in the request. */\n transactions: SimulationResponseTransaction[];\n};\n\n/** Data for a network supported by the Simulation API. */\ntype SimulationNetwork = {\n /** Subdomain of the API for the network. */\n network: string;\n\n /** Whether the network supports confirmation simulations. */\n confirmations: boolean;\n};\n\n/** Response from the simulation API containing supported networks. */\ntype SimulationNetworkResponse = {\n [chainIdDecimal: string]: SimulationNetwork;\n};\n\nlet requestIdCounter = 0;\n\n/**\n * Simulate transactions using the transaction simulation API.\n *\n * @param chainId - The chain ID to simulate transactions on.\n * @param request - The request to simulate transactions.\n * @returns The response from the simulation API.\n */\nexport async function simulateTransactions(\n chainId: Hex,\n request: SimulationRequest,\n): Promise<SimulationResponse> {\n const url = await getSimulationUrl(chainId);\n\n log('Sending request', url, request);\n\n const requestId = requestIdCounter;\n requestIdCounter += 1;\n\n const response = await fetch(url, {\n method: 'POST',\n body: JSON.stringify({\n id: String(requestId),\n jsonrpc: '2.0',\n method: RPC_METHOD,\n params: [request],\n }),\n });\n\n const responseJson = await response.json();\n\n log('Received response', responseJson);\n\n if (responseJson.error) {\n const { code, message } = responseJson.error;\n throw new SimulationError(message, code);\n }\n\n return responseJson?.result;\n}\n\n/**\n * Get the URL for the transaction simulation API.\n *\n * @param chainId - The chain ID to get the URL for.\n * @returns The URL for the transaction simulation API.\n */\nasync function getSimulationUrl(chainId: Hex): Promise<string> {\n const networkData = await getNetworkData();\n const chainIdDecimal = convertHexToDecimal(chainId);\n const network = networkData[chainIdDecimal];\n\n if (!network?.confirmations) {\n log('Chain is not supported', chainId);\n throw new SimulationChainNotSupportedError(chainId);\n }\n\n return getUrl(network.network);\n}\n\n/**\n * Retrieve the supported network data from the simulation API.\n *\n * @returns The network data response from the simulation API.\n */\nasync function getNetworkData(): Promise<SimulationNetworkResponse> {\n const url = `${getUrl('ethereum-mainnet')}${ENDPOINT_NETWORKS}`;\n const response = await fetch(url);\n return response.json();\n}\n\n/**\n * Generate the URL for the specified subdomain in the simulation API.\n *\n * @param subdomain - The subdomain to generate the URL for.\n * @returns The URL for the transaction simulation API.\n */\nfunction getUrl(subdomain: string): string {\n return BASE_URL.replace('{0}', subdomain);\n}\n"]}
1
+ {"version":3,"file":"simulation-api.mjs","sourceRoot":"","sources":["../../src/utils/simulation-api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,mCAAmC;AACjE,OAAO,EAAE,kBAAkB,EAAY,wBAAwB;AAE/D,OAAO,EAAE,gCAAgC,EAAE,eAAe,EAAE,sBAAkB;AAC9E,OAAO,EAAE,aAAa,EAAE,sBAAkB;AAE1C,MAAM,GAAG,GAAG,kBAAkB,CAAC,aAAa,EAAE,gBAAgB,CAAC,CAAC;AAEhE,MAAM,UAAU,GAAG,6BAA6B,CAAC;AACjD,MAAM,QAAQ,GAAG,6CAA6C,CAAC;AAC/D,MAAM,iBAAiB,GAAG,UAAU,CAAC;AAsJrC,IAAI,gBAAgB,GAAG,CAAC,CAAC;AAEzB;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,OAAY,EACZ,OAA0B;IAE1B,MAAM,GAAG,GAAG,MAAM,gBAAgB,CAAC,OAAO,CAAC,CAAC;IAE5C,GAAG,CAAC,iBAAiB,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;IAErC,MAAM,SAAS,GAAG,gBAAgB,CAAC;IACnC,gBAAgB,IAAI,CAAC,CAAC;IAEtB,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAChC,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;YACnB,EAAE,EAAE,MAAM,CAAC,SAAS,CAAC;YACrB,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,UAAU;YAClB,MAAM,EAAE,CAAC,OAAO,CAAC;SAClB,CAAC;KACH,CAAC,CAAC;IAEH,MAAM,YAAY,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IAE3C,GAAG,CAAC,mBAAmB,EAAE,YAAY,CAAC,CAAC;IAEvC,IAAI,YAAY,CAAC,KAAK,EAAE;QACtB,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,YAAY,CAAC,KAAK,CAAC;QAC7C,MAAM,IAAI,eAAe,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;KAC1C;IAED,OAAO,YAAY,EAAE,MAAM,CAAC;AAC9B,CAAC;AAED;;;;;GAKG;AACH,KAAK,UAAU,gBAAgB,CAAC,OAAY;IAC1C,MAAM,WAAW,GAAG,MAAM,cAAc,EAAE,CAAC;IAC3C,MAAM,cAAc,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAC;IACpD,MAAM,OAAO,GAAG,WAAW,CAAC,cAAc,CAAC,CAAC;IAE5C,IAAI,CAAC,OAAO,EAAE,aAAa,EAAE;QAC3B,GAAG,CAAC,wBAAwB,EAAE,OAAO,CAAC,CAAC;QACvC,MAAM,IAAI,gCAAgC,CAAC,OAAO,CAAC,CAAC;KACrD;IAED,OAAO,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;AACjC,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,cAAc;IAC3B,MAAM,GAAG,GAAG,GAAG,MAAM,CAAC,kBAAkB,CAAC,GAAG,iBAAiB,EAAE,CAAC;IAChE,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;IAClC,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC;AACzB,CAAC;AAED;;;;;GAKG;AACH,SAAS,MAAM,CAAC,SAAiB;IAC/B,OAAO,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;AAC5C,CAAC","sourcesContent":["import { convertHexToDecimal } from '@metamask/controller-utils';\nimport { createModuleLogger, type Hex } from '@metamask/utils';\n\nimport { SimulationChainNotSupportedError, SimulationError } from '../errors';\nimport { projectLogger } from '../logger';\n\nconst log = createModuleLogger(projectLogger, 'simulation-api');\n\nconst RPC_METHOD = 'infura_simulateTransactions';\nconst BASE_URL = 'https://tx-sentinel-{0}.api.cx.metamask.io/';\nconst ENDPOINT_NETWORKS = 'networks';\n\n/** Single transaction to simulate in a simulation API request. */\nexport type SimulationRequestTransaction = {\n /** Data to send with the transaction. */\n data?: Hex;\n\n /** Sender of the transaction. */\n from: Hex;\n\n /** Gas limit for the transaction. */\n gas?: Hex;\n\n /** Maximum fee per gas for the transaction. */\n maxFeePerGas?: Hex;\n\n /** Maximum priority fee per gas for the transaction. */\n maxPriorityFeePerGas?: Hex;\n\n /** Recipient of the transaction. */\n to?: Hex;\n\n /** Value to send with the transaction. */\n value?: Hex;\n};\n\n/** Request to the simulation API to simulate transactions. */\nexport type SimulationRequest = {\n /**\n * Transactions to be sequentially simulated.\n * State changes impact subsequent transactions in the list.\n */\n transactions: SimulationRequestTransaction[];\n\n blockOverrides?: {\n time?: Hex;\n };\n\n /**\n * Overrides to the state of the blockchain, keyed by address.\n */\n overrides?: {\n [address: Hex]: {\n /** Override the code for an address. */\n code?: Hex;\n\n /** Overrides to the storage slots for an address. */\n stateDiff?: {\n [slot: Hex]: Hex;\n };\n };\n };\n\n /**\n * Whether to include call traces in the response.\n * Defaults to false.\n */\n withCallTrace?: boolean;\n\n /**\n * Whether to include event logs in the response.\n * Defaults to false.\n */\n withLogs?: boolean;\n};\n\n/** Raw event log emitted by a simulated transaction. */\nexport type SimulationResponseLog = {\n /** Address of the account that created the event. */\n address: Hex;\n\n /** Raw data in the event that is not indexed. */\n data: Hex;\n\n /** Raw indexed data from the event. */\n topics: Hex[];\n};\n\n/** Call trace of a single simulated transaction. */\nexport type SimulationResponseCallTrace = {\n /** Nested calls. */\n calls: SimulationResponseCallTrace[];\n\n /** Raw event logs created by the call. */\n logs: SimulationResponseLog[];\n};\n\n/**\n * Changes to the blockchain state.\n * Keyed by account address.\n */\nexport type SimulationResponseStateDiff = {\n [address: Hex]: {\n /** Native balance of the account. */\n balance?: Hex;\n\n /** Nonce of the account. */\n nonce?: Hex;\n\n /** Storage values per slot. */\n storage?: {\n [slot: Hex]: Hex;\n };\n };\n};\n\n/** Response from the simulation API for a single transaction. */\nexport type SimulationResponseTransaction = {\n /** Hierarchy of call data including nested calls and logs. */\n callTrace?: SimulationResponseCallTrace;\n\n /** An error message indicating the transaction could not be simulated. */\n error?: string;\n\n /** The total gas used by the transaction. */\n gasUsed?: Hex;\n\n /** Return value of the transaction, such as the balance if calling balanceOf. */\n return: Hex;\n\n /** Changes to the blockchain state. */\n stateDiff?: {\n /** Initial blockchain state before the transaction. */\n pre?: SimulationResponseStateDiff;\n\n /** Updated blockchain state after the transaction. */\n post?: SimulationResponseStateDiff;\n };\n};\n\n/** Response from the simulation API. */\nexport type SimulationResponse = {\n /** Simulation data for each transaction in the request. */\n transactions: SimulationResponseTransaction[];\n};\n\n/** Data for a network supported by the Simulation API. */\ntype SimulationNetwork = {\n /** Subdomain of the API for the network. */\n network: string;\n\n /** Whether the network supports confirmation simulations. */\n confirmations: boolean;\n};\n\n/** Response from the simulation API containing supported networks. */\ntype SimulationNetworkResponse = {\n [chainIdDecimal: string]: SimulationNetwork;\n};\n\nlet requestIdCounter = 0;\n\n/**\n * Simulate transactions using the transaction simulation API.\n *\n * @param chainId - The chain ID to simulate transactions on.\n * @param request - The request to simulate transactions.\n * @returns The response from the simulation API.\n */\nexport async function simulateTransactions(\n chainId: Hex,\n request: SimulationRequest,\n): Promise<SimulationResponse> {\n const url = await getSimulationUrl(chainId);\n\n log('Sending request', url, request);\n\n const requestId = requestIdCounter;\n requestIdCounter += 1;\n\n const response = await fetch(url, {\n method: 'POST',\n body: JSON.stringify({\n id: String(requestId),\n jsonrpc: '2.0',\n method: RPC_METHOD,\n params: [request],\n }),\n });\n\n const responseJson = await response.json();\n\n log('Received response', responseJson);\n\n if (responseJson.error) {\n const { code, message } = responseJson.error;\n throw new SimulationError(message, code);\n }\n\n return responseJson?.result;\n}\n\n/**\n * Get the URL for the transaction simulation API.\n *\n * @param chainId - The chain ID to get the URL for.\n * @returns The URL for the transaction simulation API.\n */\nasync function getSimulationUrl(chainId: Hex): Promise<string> {\n const networkData = await getNetworkData();\n const chainIdDecimal = convertHexToDecimal(chainId);\n const network = networkData[chainIdDecimal];\n\n if (!network?.confirmations) {\n log('Chain is not supported', chainId);\n throw new SimulationChainNotSupportedError(chainId);\n }\n\n return getUrl(network.network);\n}\n\n/**\n * Retrieve the supported network data from the simulation API.\n *\n * @returns The network data response from the simulation API.\n */\nasync function getNetworkData(): Promise<SimulationNetworkResponse> {\n const url = `${getUrl('ethereum-mainnet')}${ENDPOINT_NETWORKS}`;\n const response = await fetch(url);\n return response.json();\n}\n\n/**\n * Generate the URL for the specified subdomain in the simulation API.\n *\n * @param subdomain - The subdomain to generate the URL for.\n * @returns The URL for the transaction simulation API.\n */\nfunction getUrl(subdomain: string): string {\n return BASE_URL.replace('{0}', subdomain);\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask-previews/transaction-controller",
3
- "version": "52.0.0-preview-5a3453d",
3
+ "version": "52.0.0-preview-e3c959f",
4
4
  "description": "Stores transactions alongside their periodically updated statuses and manages interactions such as approval and cancellation",
5
5
  "keywords": [
6
6
  "MetaMask",
@@ -1,145 +0,0 @@
1
- "use strict";
2
- var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
3
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
4
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
5
- return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
6
- };
7
- var _RandomisedEstimationsGasFeeFlow_instances, _RandomisedEstimationsGasFeeFlow_getDefaultGasFees, _RandomisedEstimationsGasFeeFlow_getRandomisedGasFees, _RandomisedEstimationsGasFeeFlow_randomiseFeeMarketEstimates, _RandomisedEstimationsGasFeeFlow_getRandomisedFeeMarketLevel, _RandomisedEstimationsGasFeeFlow_randomiseLegacyEstimates, _RandomisedEstimationsGasFeeFlow_getRandomisedLegacyLevel, _RandomisedEstimationsGasFeeFlow_getRandomisedGasPriceEstimate;
8
- Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.randomiseDecimalGWEIAndConvertToHex = exports.RandomisedEstimationsGasFeeFlow = void 0;
10
- const gas_fee_controller_1 = require("@metamask/gas-fee-controller");
11
- const utils_1 = require("@metamask/utils");
12
- const DefaultGasFeeFlow_1 = require("./DefaultGasFeeFlow.cjs");
13
- const logger_1 = require("../logger.cjs");
14
- const types_1 = require("../types.cjs");
15
- const feature_flags_1 = require("../utils/feature-flags.cjs");
16
- const gas_fees_1 = require("../utils/gas-fees.cjs");
17
- const log = (0, utils_1.createModuleLogger)(logger_1.projectLogger, 'randomised-estimation-gas-fee-flow');
18
- const PRESERVE_NUMBER_OF_DIGITS = 2;
19
- /**
20
- * Implementation of a gas fee flow that randomises the last digits of gas fee estimations
21
- */
22
- class RandomisedEstimationsGasFeeFlow {
23
- constructor() {
24
- _RandomisedEstimationsGasFeeFlow_instances.add(this);
25
- }
26
- matchesTransaction({ transactionMeta, messenger, }) {
27
- const { chainId } = transactionMeta;
28
- const randomisedGasFeeDigits = (0, feature_flags_1.getRandomisedGasFeeDigits)(chainId, messenger);
29
- return randomisedGasFeeDigits !== undefined;
30
- }
31
- async getGasFees(request) {
32
- try {
33
- return await __classPrivateFieldGet(this, _RandomisedEstimationsGasFeeFlow_instances, "m", _RandomisedEstimationsGasFeeFlow_getRandomisedGasFees).call(this, request);
34
- }
35
- catch (error) {
36
- log('Using default flow as fallback due to error', error);
37
- return await __classPrivateFieldGet(this, _RandomisedEstimationsGasFeeFlow_instances, "m", _RandomisedEstimationsGasFeeFlow_getDefaultGasFees).call(this, request);
38
- }
39
- }
40
- }
41
- exports.RandomisedEstimationsGasFeeFlow = RandomisedEstimationsGasFeeFlow;
42
- _RandomisedEstimationsGasFeeFlow_instances = new WeakSet(), _RandomisedEstimationsGasFeeFlow_getDefaultGasFees = async function _RandomisedEstimationsGasFeeFlow_getDefaultGasFees(request) {
43
- return new DefaultGasFeeFlow_1.DefaultGasFeeFlow().getGasFees(request);
44
- }, _RandomisedEstimationsGasFeeFlow_getRandomisedGasFees = async function _RandomisedEstimationsGasFeeFlow_getRandomisedGasFees(request) {
45
- const { messenger, gasFeeControllerData, transactionMeta } = request;
46
- const { gasEstimateType, gasFeeEstimates } = gasFeeControllerData;
47
- const randomisedGasFeeDigits = (0, feature_flags_1.getRandomisedGasFeeDigits)(transactionMeta.chainId, messenger);
48
- let response;
49
- if (gasEstimateType === gas_fee_controller_1.GAS_ESTIMATE_TYPES.FEE_MARKET) {
50
- log('Using fee market estimates', gasFeeEstimates);
51
- response = __classPrivateFieldGet(this, _RandomisedEstimationsGasFeeFlow_instances, "m", _RandomisedEstimationsGasFeeFlow_randomiseFeeMarketEstimates).call(this, gasFeeEstimates, randomisedGasFeeDigits);
52
- log('Randomised fee market estimates', response);
53
- }
54
- else if (gasEstimateType === gas_fee_controller_1.GAS_ESTIMATE_TYPES.LEGACY) {
55
- log('Using legacy estimates', gasFeeEstimates);
56
- response = __classPrivateFieldGet(this, _RandomisedEstimationsGasFeeFlow_instances, "m", _RandomisedEstimationsGasFeeFlow_randomiseLegacyEstimates).call(this, gasFeeEstimates, randomisedGasFeeDigits);
57
- log('Randomised legacy estimates', response);
58
- }
59
- else if (gasEstimateType === gas_fee_controller_1.GAS_ESTIMATE_TYPES.ETH_GASPRICE) {
60
- log('Using eth_gasPrice estimates', gasFeeEstimates);
61
- response = __classPrivateFieldGet(this, _RandomisedEstimationsGasFeeFlow_instances, "m", _RandomisedEstimationsGasFeeFlow_getRandomisedGasPriceEstimate).call(this, gasFeeEstimates, randomisedGasFeeDigits);
62
- log('Randomised eth_gasPrice estimates', response);
63
- }
64
- else {
65
- throw new Error(`Unsupported gas estimate type: ${gasEstimateType}`);
66
- }
67
- return {
68
- estimates: response,
69
- };
70
- }, _RandomisedEstimationsGasFeeFlow_randomiseFeeMarketEstimates = function _RandomisedEstimationsGasFeeFlow_randomiseFeeMarketEstimates(gasFeeEstimates, lastNDigits) {
71
- const levels = Object.values(types_1.GasFeeEstimateLevel).reduce((result, level) => ({
72
- ...result,
73
- [level]: __classPrivateFieldGet(this, _RandomisedEstimationsGasFeeFlow_instances, "m", _RandomisedEstimationsGasFeeFlow_getRandomisedFeeMarketLevel).call(this, gasFeeEstimates, level, lastNDigits),
74
- }), {});
75
- return {
76
- type: types_1.GasFeeEstimateType.FeeMarket,
77
- ...levels,
78
- };
79
- }, _RandomisedEstimationsGasFeeFlow_getRandomisedFeeMarketLevel = function _RandomisedEstimationsGasFeeFlow_getRandomisedFeeMarketLevel(gasFeeEstimates, level, lastNDigits) {
80
- return {
81
- maxFeePerGas: randomiseDecimalGWEIAndConvertToHex(gasFeeEstimates[level].suggestedMaxFeePerGas, lastNDigits),
82
- maxPriorityFeePerGas: randomiseDecimalGWEIAndConvertToHex(gasFeeEstimates[level].suggestedMaxPriorityFeePerGas, lastNDigits),
83
- };
84
- }, _RandomisedEstimationsGasFeeFlow_randomiseLegacyEstimates = function _RandomisedEstimationsGasFeeFlow_randomiseLegacyEstimates(gasFeeEstimates, lastNDigits) {
85
- const levels = Object.values(types_1.GasFeeEstimateLevel).reduce((result, level) => ({
86
- ...result,
87
- [level]: __classPrivateFieldGet(this, _RandomisedEstimationsGasFeeFlow_instances, "m", _RandomisedEstimationsGasFeeFlow_getRandomisedLegacyLevel).call(this, gasFeeEstimates, level, lastNDigits),
88
- }), {});
89
- return {
90
- type: types_1.GasFeeEstimateType.Legacy,
91
- ...levels,
92
- };
93
- }, _RandomisedEstimationsGasFeeFlow_getRandomisedLegacyLevel = function _RandomisedEstimationsGasFeeFlow_getRandomisedLegacyLevel(gasFeeEstimates, level, lastNDigits) {
94
- return randomiseDecimalGWEIAndConvertToHex(gasFeeEstimates[level], lastNDigits);
95
- }, _RandomisedEstimationsGasFeeFlow_getRandomisedGasPriceEstimate = function _RandomisedEstimationsGasFeeFlow_getRandomisedGasPriceEstimate(gasFeeEstimates, lastNDigits) {
96
- return {
97
- type: types_1.GasFeeEstimateType.GasPrice,
98
- gasPrice: randomiseDecimalGWEIAndConvertToHex(gasFeeEstimates.gasPrice, lastNDigits),
99
- };
100
- };
101
- /**
102
- * Generates a random number with the specified number of digits that is greater than or equal to the given minimum value.
103
- *
104
- * @param digitCount - The number of digits the random number should have
105
- * @param minValue - The minimum value the random number should have
106
- * @returns A random number with the specified number of digits
107
- */
108
- function generateRandomDigits(digitCount, minValue) {
109
- const multiplier = 10 ** digitCount;
110
- return minValue + Math.floor(Math.random() * (multiplier - minValue));
111
- }
112
- /**
113
- * Randomises the least significant digits of a decimal gas fee value and converts it to a hexadecimal Wei value.
114
- *
115
- * This function preserves the more significant digits while randomizing only the least significant ones,
116
- * ensuring that fees remain close to the original estimation while providing randomisation.
117
- * The randomisation is performed in Wei units for more precision.
118
- *
119
- * @param gweiDecimalValue - The original gas fee value in Gwei (decimal)
120
- * @param [numberOfDigitsToRandomizeAtTheEnd] - The number of least significant digits to randomise
121
- * @returns The randomised value converted to Wei in hexadecimal format
122
- */
123
- function randomiseDecimalGWEIAndConvertToHex(gweiDecimalValue, numberOfDigitsToRandomizeAtTheEnd) {
124
- const weiDecimalValue = (0, gas_fees_1.gweiDecimalToWeiDecimal)(gweiDecimalValue);
125
- const decimalLength = weiDecimalValue.length;
126
- // Determine how many digits to randomise while preserving the PRESERVE_NUMBER_OF_DIGITS
127
- const effectiveDigitsToRandomise = Math.min(numberOfDigitsToRandomizeAtTheEnd, decimalLength - PRESERVE_NUMBER_OF_DIGITS);
128
- // Handle the case when the value is 0 or too small
129
- if (Number(weiDecimalValue) === 0 || effectiveDigitsToRandomise <= 0) {
130
- return `0x${Number(weiDecimalValue).toString(16)}`;
131
- }
132
- // Use string manipulation to get the base part (significant digits)
133
- const significantDigitsCount = decimalLength - effectiveDigitsToRandomise;
134
- const significantDigits = weiDecimalValue.slice(0, significantDigitsCount);
135
- // Get the original ending digits using string manipulation
136
- const endingDigits = weiDecimalValue.slice(-effectiveDigitsToRandomise);
137
- const originalEndingDigits = Number(endingDigits);
138
- // Generate random digits that are greater than or equal to the original ending digits
139
- const randomEndingDigits = generateRandomDigits(effectiveDigitsToRandomise, originalEndingDigits);
140
- const basePart = BigInt(significantDigits + '0'.repeat(effectiveDigitsToRandomise));
141
- const randomisedWeiDecimal = basePart + BigInt(randomEndingDigits);
142
- return `0x${randomisedWeiDecimal.toString(16)}`;
143
- }
144
- exports.randomiseDecimalGWEIAndConvertToHex = randomiseDecimalGWEIAndConvertToHex;
145
- //# sourceMappingURL=RandomisedEstimationsGasFeeFlow.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"RandomisedEstimationsGasFeeFlow.cjs","sourceRoot":"","sources":["../../src/gas-flows/RandomisedEstimationsGasFeeFlow.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n LegacyGasPriceEstimate,\n GasFeeEstimates as FeeMarketGasPriceEstimate,\n EthGasPriceEstimate,\n} from '@metamask/gas-fee-controller';\nimport { GAS_ESTIMATE_TYPES } from '@metamask/gas-fee-controller';\nimport { createModuleLogger, type Hex } from '@metamask/utils';\n\nimport { DefaultGasFeeFlow } from './DefaultGasFeeFlow';\nimport { projectLogger } from '../logger';\nimport type { TransactionControllerMessenger } from '../TransactionController';\nimport type {\n FeeMarketGasFeeEstimateForLevel,\n FeeMarketGasFeeEstimates,\n GasFeeEstimates,\n GasFeeFlow,\n GasFeeFlowRequest,\n GasFeeFlowResponse,\n GasPriceGasFeeEstimates,\n LegacyGasFeeEstimates,\n TransactionMeta,\n} from '../types';\nimport { GasFeeEstimateLevel, GasFeeEstimateType } from '../types';\nimport { getRandomisedGasFeeDigits } from '../utils/feature-flags';\nimport { gweiDecimalToWeiDecimal } from '../utils/gas-fees';\n\nconst log = createModuleLogger(\n projectLogger,\n 'randomised-estimation-gas-fee-flow',\n);\n\nconst PRESERVE_NUMBER_OF_DIGITS = 2;\n\n/**\n * Implementation of a gas fee flow that randomises the last digits of gas fee estimations\n */\nexport class RandomisedEstimationsGasFeeFlow implements GasFeeFlow {\n matchesTransaction({\n transactionMeta,\n messenger,\n }: {\n transactionMeta: TransactionMeta;\n messenger: TransactionControllerMessenger;\n }): boolean {\n const { chainId } = transactionMeta;\n\n const randomisedGasFeeDigits = getRandomisedGasFeeDigits(\n chainId,\n messenger,\n );\n\n return randomisedGasFeeDigits !== undefined;\n }\n\n async getGasFees(request: GasFeeFlowRequest): Promise<GasFeeFlowResponse> {\n try {\n return await this.#getRandomisedGasFees(request);\n } catch (error) {\n log('Using default flow as fallback due to error', error);\n return await this.#getDefaultGasFees(request);\n }\n }\n\n async #getDefaultGasFees(\n request: GasFeeFlowRequest,\n ): Promise<GasFeeFlowResponse> {\n return new DefaultGasFeeFlow().getGasFees(request);\n }\n\n async #getRandomisedGasFees(\n request: GasFeeFlowRequest,\n ): Promise<GasFeeFlowResponse> {\n const { messenger, gasFeeControllerData, transactionMeta } = request;\n const { gasEstimateType, gasFeeEstimates } = gasFeeControllerData;\n\n const randomisedGasFeeDigits = getRandomisedGasFeeDigits(\n transactionMeta.chainId,\n messenger,\n ) as number;\n\n let response: GasFeeEstimates;\n\n if (gasEstimateType === GAS_ESTIMATE_TYPES.FEE_MARKET) {\n log('Using fee market estimates', gasFeeEstimates);\n response = this.#randomiseFeeMarketEstimates(\n gasFeeEstimates,\n randomisedGasFeeDigits,\n );\n log('Randomised fee market estimates', response);\n } else if (gasEstimateType === GAS_ESTIMATE_TYPES.LEGACY) {\n log('Using legacy estimates', gasFeeEstimates);\n response = this.#randomiseLegacyEstimates(\n gasFeeEstimates,\n randomisedGasFeeDigits,\n );\n log('Randomised legacy estimates', response);\n } else if (gasEstimateType === GAS_ESTIMATE_TYPES.ETH_GASPRICE) {\n log('Using eth_gasPrice estimates', gasFeeEstimates);\n response = this.#getRandomisedGasPriceEstimate(\n gasFeeEstimates,\n randomisedGasFeeDigits,\n );\n log('Randomised eth_gasPrice estimates', response);\n } else {\n throw new Error(`Unsupported gas estimate type: ${gasEstimateType}`);\n }\n\n return {\n estimates: response,\n };\n }\n\n #randomiseFeeMarketEstimates(\n gasFeeEstimates: FeeMarketGasPriceEstimate,\n lastNDigits: number,\n ): FeeMarketGasFeeEstimates {\n const levels = Object.values(GasFeeEstimateLevel).reduce(\n (result, level) => ({\n ...result,\n [level]: this.#getRandomisedFeeMarketLevel(\n gasFeeEstimates,\n level,\n lastNDigits,\n ),\n }),\n {} as Omit<FeeMarketGasFeeEstimates, 'type'>,\n );\n\n return {\n type: GasFeeEstimateType.FeeMarket,\n ...levels,\n };\n }\n\n #getRandomisedFeeMarketLevel(\n gasFeeEstimates: FeeMarketGasPriceEstimate,\n level: GasFeeEstimateLevel,\n lastNDigits: number,\n ): FeeMarketGasFeeEstimateForLevel {\n return {\n maxFeePerGas: randomiseDecimalGWEIAndConvertToHex(\n gasFeeEstimates[level].suggestedMaxFeePerGas,\n lastNDigits,\n ),\n maxPriorityFeePerGas: randomiseDecimalGWEIAndConvertToHex(\n gasFeeEstimates[level].suggestedMaxPriorityFeePerGas,\n lastNDigits,\n ),\n };\n }\n\n #randomiseLegacyEstimates(\n gasFeeEstimates: LegacyGasPriceEstimate,\n lastNDigits: number,\n ): LegacyGasFeeEstimates {\n const levels = Object.values(GasFeeEstimateLevel).reduce(\n (result, level) => ({\n ...result,\n [level]: this.#getRandomisedLegacyLevel(\n gasFeeEstimates,\n level,\n lastNDigits,\n ),\n }),\n {} as Omit<LegacyGasFeeEstimates, 'type'>,\n );\n\n return {\n type: GasFeeEstimateType.Legacy,\n ...levels,\n };\n }\n\n #getRandomisedLegacyLevel(\n gasFeeEstimates: LegacyGasPriceEstimate,\n level: GasFeeEstimateLevel,\n lastNDigits: number,\n ): Hex {\n return randomiseDecimalGWEIAndConvertToHex(\n gasFeeEstimates[level],\n lastNDigits,\n );\n }\n\n #getRandomisedGasPriceEstimate(\n gasFeeEstimates: EthGasPriceEstimate,\n lastNDigits: number,\n ): GasPriceGasFeeEstimates {\n return {\n type: GasFeeEstimateType.GasPrice,\n gasPrice: randomiseDecimalGWEIAndConvertToHex(\n gasFeeEstimates.gasPrice,\n lastNDigits,\n ),\n };\n }\n}\n\n/**\n * Generates a random number with the specified number of digits that is greater than or equal to the given minimum value.\n *\n * @param digitCount - The number of digits the random number should have\n * @param minValue - The minimum value the random number should have\n * @returns A random number with the specified number of digits\n */\nfunction generateRandomDigits(digitCount: number, minValue: number): number {\n const multiplier = 10 ** digitCount;\n return minValue + Math.floor(Math.random() * (multiplier - minValue));\n}\n\n/**\n * Randomises the least significant digits of a decimal gas fee value and converts it to a hexadecimal Wei value.\n *\n * This function preserves the more significant digits while randomizing only the least significant ones,\n * ensuring that fees remain close to the original estimation while providing randomisation.\n * The randomisation is performed in Wei units for more precision.\n *\n * @param gweiDecimalValue - The original gas fee value in Gwei (decimal)\n * @param [numberOfDigitsToRandomizeAtTheEnd] - The number of least significant digits to randomise\n * @returns The randomised value converted to Wei in hexadecimal format\n */\nexport function randomiseDecimalGWEIAndConvertToHex(\n gweiDecimalValue: string | number,\n numberOfDigitsToRandomizeAtTheEnd: number,\n): Hex {\n const weiDecimalValue = gweiDecimalToWeiDecimal(gweiDecimalValue);\n const decimalLength = weiDecimalValue.length;\n\n // Determine how many digits to randomise while preserving the PRESERVE_NUMBER_OF_DIGITS\n const effectiveDigitsToRandomise = Math.min(\n numberOfDigitsToRandomizeAtTheEnd,\n decimalLength - PRESERVE_NUMBER_OF_DIGITS,\n );\n\n // Handle the case when the value is 0 or too small\n if (Number(weiDecimalValue) === 0 || effectiveDigitsToRandomise <= 0) {\n return `0x${Number(weiDecimalValue).toString(16)}` as Hex;\n }\n\n // Use string manipulation to get the base part (significant digits)\n const significantDigitsCount = decimalLength - effectiveDigitsToRandomise;\n const significantDigits = weiDecimalValue.slice(0, significantDigitsCount);\n\n // Get the original ending digits using string manipulation\n const endingDigits = weiDecimalValue.slice(-effectiveDigitsToRandomise);\n const originalEndingDigits = Number(endingDigits);\n\n // Generate random digits that are greater than or equal to the original ending digits\n const randomEndingDigits = generateRandomDigits(\n effectiveDigitsToRandomise,\n originalEndingDigits,\n );\n\n const basePart = BigInt(\n significantDigits + '0'.repeat(effectiveDigitsToRandomise),\n );\n const randomisedWeiDecimal = basePart + BigInt(randomEndingDigits);\n\n return `0x${randomisedWeiDecimal.toString(16)}` as Hex;\n}\n"]}
@@ -1,27 +0,0 @@
1
- import { type Hex } from "@metamask/utils";
2
- import type { TransactionControllerMessenger } from "../TransactionController.cjs";
3
- import type { GasFeeFlow, GasFeeFlowRequest, GasFeeFlowResponse, TransactionMeta } from "../types.cjs";
4
- /**
5
- * Implementation of a gas fee flow that randomises the last digits of gas fee estimations
6
- */
7
- export declare class RandomisedEstimationsGasFeeFlow implements GasFeeFlow {
8
- #private;
9
- matchesTransaction({ transactionMeta, messenger, }: {
10
- transactionMeta: TransactionMeta;
11
- messenger: TransactionControllerMessenger;
12
- }): boolean;
13
- getGasFees(request: GasFeeFlowRequest): Promise<GasFeeFlowResponse>;
14
- }
15
- /**
16
- * Randomises the least significant digits of a decimal gas fee value and converts it to a hexadecimal Wei value.
17
- *
18
- * This function preserves the more significant digits while randomizing only the least significant ones,
19
- * ensuring that fees remain close to the original estimation while providing randomisation.
20
- * The randomisation is performed in Wei units for more precision.
21
- *
22
- * @param gweiDecimalValue - The original gas fee value in Gwei (decimal)
23
- * @param [numberOfDigitsToRandomizeAtTheEnd] - The number of least significant digits to randomise
24
- * @returns The randomised value converted to Wei in hexadecimal format
25
- */
26
- export declare function randomiseDecimalGWEIAndConvertToHex(gweiDecimalValue: string | number, numberOfDigitsToRandomizeAtTheEnd: number): Hex;
27
- //# sourceMappingURL=RandomisedEstimationsGasFeeFlow.d.cts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"RandomisedEstimationsGasFeeFlow.d.cts","sourceRoot":"","sources":["../../src/gas-flows/RandomisedEstimationsGasFeeFlow.ts"],"names":[],"mappings":"AAMA,OAAO,EAAsB,KAAK,GAAG,EAAE,wBAAwB;AAI/D,OAAO,KAAK,EAAE,8BAA8B,EAAE,qCAAiC;AAC/E,OAAO,KAAK,EAIV,UAAU,EACV,iBAAiB,EACjB,kBAAkB,EAGlB,eAAe,EAChB,qBAAiB;AAYlB;;GAEG;AACH,qBAAa,+BAAgC,YAAW,UAAU;;IAChE,kBAAkB,CAAC,EACjB,eAAe,EACf,SAAS,GACV,EAAE;QACD,eAAe,EAAE,eAAe,CAAC;QACjC,SAAS,EAAE,8BAA8B,CAAC;KAC3C,GAAG,OAAO;IAWL,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;CA8I1E;AAcD;;;;;;;;;;GAUG;AACH,wBAAgB,mCAAmC,CACjD,gBAAgB,EAAE,MAAM,GAAG,MAAM,EACjC,iCAAiC,EAAE,MAAM,GACxC,GAAG,CAmCL"}
@@ -1,27 +0,0 @@
1
- import { type Hex } from "@metamask/utils";
2
- import type { TransactionControllerMessenger } from "../TransactionController.mjs";
3
- import type { GasFeeFlow, GasFeeFlowRequest, GasFeeFlowResponse, TransactionMeta } from "../types.mjs";
4
- /**
5
- * Implementation of a gas fee flow that randomises the last digits of gas fee estimations
6
- */
7
- export declare class RandomisedEstimationsGasFeeFlow implements GasFeeFlow {
8
- #private;
9
- matchesTransaction({ transactionMeta, messenger, }: {
10
- transactionMeta: TransactionMeta;
11
- messenger: TransactionControllerMessenger;
12
- }): boolean;
13
- getGasFees(request: GasFeeFlowRequest): Promise<GasFeeFlowResponse>;
14
- }
15
- /**
16
- * Randomises the least significant digits of a decimal gas fee value and converts it to a hexadecimal Wei value.
17
- *
18
- * This function preserves the more significant digits while randomizing only the least significant ones,
19
- * ensuring that fees remain close to the original estimation while providing randomisation.
20
- * The randomisation is performed in Wei units for more precision.
21
- *
22
- * @param gweiDecimalValue - The original gas fee value in Gwei (decimal)
23
- * @param [numberOfDigitsToRandomizeAtTheEnd] - The number of least significant digits to randomise
24
- * @returns The randomised value converted to Wei in hexadecimal format
25
- */
26
- export declare function randomiseDecimalGWEIAndConvertToHex(gweiDecimalValue: string | number, numberOfDigitsToRandomizeAtTheEnd: number): Hex;
27
- //# sourceMappingURL=RandomisedEstimationsGasFeeFlow.d.mts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"RandomisedEstimationsGasFeeFlow.d.mts","sourceRoot":"","sources":["../../src/gas-flows/RandomisedEstimationsGasFeeFlow.ts"],"names":[],"mappings":"AAMA,OAAO,EAAsB,KAAK,GAAG,EAAE,wBAAwB;AAI/D,OAAO,KAAK,EAAE,8BAA8B,EAAE,qCAAiC;AAC/E,OAAO,KAAK,EAIV,UAAU,EACV,iBAAiB,EACjB,kBAAkB,EAGlB,eAAe,EAChB,qBAAiB;AAYlB;;GAEG;AACH,qBAAa,+BAAgC,YAAW,UAAU;;IAChE,kBAAkB,CAAC,EACjB,eAAe,EACf,SAAS,GACV,EAAE;QACD,eAAe,EAAE,eAAe,CAAC;QACjC,SAAS,EAAE,8BAA8B,CAAC;KAC3C,GAAG,OAAO;IAWL,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;CA8I1E;AAcD;;;;;;;;;;GAUG;AACH,wBAAgB,mCAAmC,CACjD,gBAAgB,EAAE,MAAM,GAAG,MAAM,EACjC,iCAAiC,EAAE,MAAM,GACxC,GAAG,CAmCL"}
@@ -1,140 +0,0 @@
1
- var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
2
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
3
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
4
- return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
5
- };
6
- var _RandomisedEstimationsGasFeeFlow_instances, _RandomisedEstimationsGasFeeFlow_getDefaultGasFees, _RandomisedEstimationsGasFeeFlow_getRandomisedGasFees, _RandomisedEstimationsGasFeeFlow_randomiseFeeMarketEstimates, _RandomisedEstimationsGasFeeFlow_getRandomisedFeeMarketLevel, _RandomisedEstimationsGasFeeFlow_randomiseLegacyEstimates, _RandomisedEstimationsGasFeeFlow_getRandomisedLegacyLevel, _RandomisedEstimationsGasFeeFlow_getRandomisedGasPriceEstimate;
7
- import { GAS_ESTIMATE_TYPES } from "@metamask/gas-fee-controller";
8
- import { createModuleLogger } from "@metamask/utils";
9
- import { DefaultGasFeeFlow } from "./DefaultGasFeeFlow.mjs";
10
- import { projectLogger } from "../logger.mjs";
11
- import { GasFeeEstimateLevel, GasFeeEstimateType } from "../types.mjs";
12
- import { getRandomisedGasFeeDigits } from "../utils/feature-flags.mjs";
13
- import { gweiDecimalToWeiDecimal } from "../utils/gas-fees.mjs";
14
- const log = createModuleLogger(projectLogger, 'randomised-estimation-gas-fee-flow');
15
- const PRESERVE_NUMBER_OF_DIGITS = 2;
16
- /**
17
- * Implementation of a gas fee flow that randomises the last digits of gas fee estimations
18
- */
19
- export class RandomisedEstimationsGasFeeFlow {
20
- constructor() {
21
- _RandomisedEstimationsGasFeeFlow_instances.add(this);
22
- }
23
- matchesTransaction({ transactionMeta, messenger, }) {
24
- const { chainId } = transactionMeta;
25
- const randomisedGasFeeDigits = getRandomisedGasFeeDigits(chainId, messenger);
26
- return randomisedGasFeeDigits !== undefined;
27
- }
28
- async getGasFees(request) {
29
- try {
30
- return await __classPrivateFieldGet(this, _RandomisedEstimationsGasFeeFlow_instances, "m", _RandomisedEstimationsGasFeeFlow_getRandomisedGasFees).call(this, request);
31
- }
32
- catch (error) {
33
- log('Using default flow as fallback due to error', error);
34
- return await __classPrivateFieldGet(this, _RandomisedEstimationsGasFeeFlow_instances, "m", _RandomisedEstimationsGasFeeFlow_getDefaultGasFees).call(this, request);
35
- }
36
- }
37
- }
38
- _RandomisedEstimationsGasFeeFlow_instances = new WeakSet(), _RandomisedEstimationsGasFeeFlow_getDefaultGasFees = async function _RandomisedEstimationsGasFeeFlow_getDefaultGasFees(request) {
39
- return new DefaultGasFeeFlow().getGasFees(request);
40
- }, _RandomisedEstimationsGasFeeFlow_getRandomisedGasFees = async function _RandomisedEstimationsGasFeeFlow_getRandomisedGasFees(request) {
41
- const { messenger, gasFeeControllerData, transactionMeta } = request;
42
- const { gasEstimateType, gasFeeEstimates } = gasFeeControllerData;
43
- const randomisedGasFeeDigits = getRandomisedGasFeeDigits(transactionMeta.chainId, messenger);
44
- let response;
45
- if (gasEstimateType === GAS_ESTIMATE_TYPES.FEE_MARKET) {
46
- log('Using fee market estimates', gasFeeEstimates);
47
- response = __classPrivateFieldGet(this, _RandomisedEstimationsGasFeeFlow_instances, "m", _RandomisedEstimationsGasFeeFlow_randomiseFeeMarketEstimates).call(this, gasFeeEstimates, randomisedGasFeeDigits);
48
- log('Randomised fee market estimates', response);
49
- }
50
- else if (gasEstimateType === GAS_ESTIMATE_TYPES.LEGACY) {
51
- log('Using legacy estimates', gasFeeEstimates);
52
- response = __classPrivateFieldGet(this, _RandomisedEstimationsGasFeeFlow_instances, "m", _RandomisedEstimationsGasFeeFlow_randomiseLegacyEstimates).call(this, gasFeeEstimates, randomisedGasFeeDigits);
53
- log('Randomised legacy estimates', response);
54
- }
55
- else if (gasEstimateType === GAS_ESTIMATE_TYPES.ETH_GASPRICE) {
56
- log('Using eth_gasPrice estimates', gasFeeEstimates);
57
- response = __classPrivateFieldGet(this, _RandomisedEstimationsGasFeeFlow_instances, "m", _RandomisedEstimationsGasFeeFlow_getRandomisedGasPriceEstimate).call(this, gasFeeEstimates, randomisedGasFeeDigits);
58
- log('Randomised eth_gasPrice estimates', response);
59
- }
60
- else {
61
- throw new Error(`Unsupported gas estimate type: ${gasEstimateType}`);
62
- }
63
- return {
64
- estimates: response,
65
- };
66
- }, _RandomisedEstimationsGasFeeFlow_randomiseFeeMarketEstimates = function _RandomisedEstimationsGasFeeFlow_randomiseFeeMarketEstimates(gasFeeEstimates, lastNDigits) {
67
- const levels = Object.values(GasFeeEstimateLevel).reduce((result, level) => ({
68
- ...result,
69
- [level]: __classPrivateFieldGet(this, _RandomisedEstimationsGasFeeFlow_instances, "m", _RandomisedEstimationsGasFeeFlow_getRandomisedFeeMarketLevel).call(this, gasFeeEstimates, level, lastNDigits),
70
- }), {});
71
- return {
72
- type: GasFeeEstimateType.FeeMarket,
73
- ...levels,
74
- };
75
- }, _RandomisedEstimationsGasFeeFlow_getRandomisedFeeMarketLevel = function _RandomisedEstimationsGasFeeFlow_getRandomisedFeeMarketLevel(gasFeeEstimates, level, lastNDigits) {
76
- return {
77
- maxFeePerGas: randomiseDecimalGWEIAndConvertToHex(gasFeeEstimates[level].suggestedMaxFeePerGas, lastNDigits),
78
- maxPriorityFeePerGas: randomiseDecimalGWEIAndConvertToHex(gasFeeEstimates[level].suggestedMaxPriorityFeePerGas, lastNDigits),
79
- };
80
- }, _RandomisedEstimationsGasFeeFlow_randomiseLegacyEstimates = function _RandomisedEstimationsGasFeeFlow_randomiseLegacyEstimates(gasFeeEstimates, lastNDigits) {
81
- const levels = Object.values(GasFeeEstimateLevel).reduce((result, level) => ({
82
- ...result,
83
- [level]: __classPrivateFieldGet(this, _RandomisedEstimationsGasFeeFlow_instances, "m", _RandomisedEstimationsGasFeeFlow_getRandomisedLegacyLevel).call(this, gasFeeEstimates, level, lastNDigits),
84
- }), {});
85
- return {
86
- type: GasFeeEstimateType.Legacy,
87
- ...levels,
88
- };
89
- }, _RandomisedEstimationsGasFeeFlow_getRandomisedLegacyLevel = function _RandomisedEstimationsGasFeeFlow_getRandomisedLegacyLevel(gasFeeEstimates, level, lastNDigits) {
90
- return randomiseDecimalGWEIAndConvertToHex(gasFeeEstimates[level], lastNDigits);
91
- }, _RandomisedEstimationsGasFeeFlow_getRandomisedGasPriceEstimate = function _RandomisedEstimationsGasFeeFlow_getRandomisedGasPriceEstimate(gasFeeEstimates, lastNDigits) {
92
- return {
93
- type: GasFeeEstimateType.GasPrice,
94
- gasPrice: randomiseDecimalGWEIAndConvertToHex(gasFeeEstimates.gasPrice, lastNDigits),
95
- };
96
- };
97
- /**
98
- * Generates a random number with the specified number of digits that is greater than or equal to the given minimum value.
99
- *
100
- * @param digitCount - The number of digits the random number should have
101
- * @param minValue - The minimum value the random number should have
102
- * @returns A random number with the specified number of digits
103
- */
104
- function generateRandomDigits(digitCount, minValue) {
105
- const multiplier = 10 ** digitCount;
106
- return minValue + Math.floor(Math.random() * (multiplier - minValue));
107
- }
108
- /**
109
- * Randomises the least significant digits of a decimal gas fee value and converts it to a hexadecimal Wei value.
110
- *
111
- * This function preserves the more significant digits while randomizing only the least significant ones,
112
- * ensuring that fees remain close to the original estimation while providing randomisation.
113
- * The randomisation is performed in Wei units for more precision.
114
- *
115
- * @param gweiDecimalValue - The original gas fee value in Gwei (decimal)
116
- * @param [numberOfDigitsToRandomizeAtTheEnd] - The number of least significant digits to randomise
117
- * @returns The randomised value converted to Wei in hexadecimal format
118
- */
119
- export function randomiseDecimalGWEIAndConvertToHex(gweiDecimalValue, numberOfDigitsToRandomizeAtTheEnd) {
120
- const weiDecimalValue = gweiDecimalToWeiDecimal(gweiDecimalValue);
121
- const decimalLength = weiDecimalValue.length;
122
- // Determine how many digits to randomise while preserving the PRESERVE_NUMBER_OF_DIGITS
123
- const effectiveDigitsToRandomise = Math.min(numberOfDigitsToRandomizeAtTheEnd, decimalLength - PRESERVE_NUMBER_OF_DIGITS);
124
- // Handle the case when the value is 0 or too small
125
- if (Number(weiDecimalValue) === 0 || effectiveDigitsToRandomise <= 0) {
126
- return `0x${Number(weiDecimalValue).toString(16)}`;
127
- }
128
- // Use string manipulation to get the base part (significant digits)
129
- const significantDigitsCount = decimalLength - effectiveDigitsToRandomise;
130
- const significantDigits = weiDecimalValue.slice(0, significantDigitsCount);
131
- // Get the original ending digits using string manipulation
132
- const endingDigits = weiDecimalValue.slice(-effectiveDigitsToRandomise);
133
- const originalEndingDigits = Number(endingDigits);
134
- // Generate random digits that are greater than or equal to the original ending digits
135
- const randomEndingDigits = generateRandomDigits(effectiveDigitsToRandomise, originalEndingDigits);
136
- const basePart = BigInt(significantDigits + '0'.repeat(effectiveDigitsToRandomise));
137
- const randomisedWeiDecimal = basePart + BigInt(randomEndingDigits);
138
- return `0x${randomisedWeiDecimal.toString(16)}`;
139
- }
140
- //# sourceMappingURL=RandomisedEstimationsGasFeeFlow.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"RandomisedEstimationsGasFeeFlow.mjs","sourceRoot":"","sources":["../../src/gas-flows/RandomisedEstimationsGasFeeFlow.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n LegacyGasPriceEstimate,\n GasFeeEstimates as FeeMarketGasPriceEstimate,\n EthGasPriceEstimate,\n} from '@metamask/gas-fee-controller';\nimport { GAS_ESTIMATE_TYPES } from '@metamask/gas-fee-controller';\nimport { createModuleLogger, type Hex } from '@metamask/utils';\n\nimport { DefaultGasFeeFlow } from './DefaultGasFeeFlow';\nimport { projectLogger } from '../logger';\nimport type { TransactionControllerMessenger } from '../TransactionController';\nimport type {\n FeeMarketGasFeeEstimateForLevel,\n FeeMarketGasFeeEstimates,\n GasFeeEstimates,\n GasFeeFlow,\n GasFeeFlowRequest,\n GasFeeFlowResponse,\n GasPriceGasFeeEstimates,\n LegacyGasFeeEstimates,\n TransactionMeta,\n} from '../types';\nimport { GasFeeEstimateLevel, GasFeeEstimateType } from '../types';\nimport { getRandomisedGasFeeDigits } from '../utils/feature-flags';\nimport { gweiDecimalToWeiDecimal } from '../utils/gas-fees';\n\nconst log = createModuleLogger(\n projectLogger,\n 'randomised-estimation-gas-fee-flow',\n);\n\nconst PRESERVE_NUMBER_OF_DIGITS = 2;\n\n/**\n * Implementation of a gas fee flow that randomises the last digits of gas fee estimations\n */\nexport class RandomisedEstimationsGasFeeFlow implements GasFeeFlow {\n matchesTransaction({\n transactionMeta,\n messenger,\n }: {\n transactionMeta: TransactionMeta;\n messenger: TransactionControllerMessenger;\n }): boolean {\n const { chainId } = transactionMeta;\n\n const randomisedGasFeeDigits = getRandomisedGasFeeDigits(\n chainId,\n messenger,\n );\n\n return randomisedGasFeeDigits !== undefined;\n }\n\n async getGasFees(request: GasFeeFlowRequest): Promise<GasFeeFlowResponse> {\n try {\n return await this.#getRandomisedGasFees(request);\n } catch (error) {\n log('Using default flow as fallback due to error', error);\n return await this.#getDefaultGasFees(request);\n }\n }\n\n async #getDefaultGasFees(\n request: GasFeeFlowRequest,\n ): Promise<GasFeeFlowResponse> {\n return new DefaultGasFeeFlow().getGasFees(request);\n }\n\n async #getRandomisedGasFees(\n request: GasFeeFlowRequest,\n ): Promise<GasFeeFlowResponse> {\n const { messenger, gasFeeControllerData, transactionMeta } = request;\n const { gasEstimateType, gasFeeEstimates } = gasFeeControllerData;\n\n const randomisedGasFeeDigits = getRandomisedGasFeeDigits(\n transactionMeta.chainId,\n messenger,\n ) as number;\n\n let response: GasFeeEstimates;\n\n if (gasEstimateType === GAS_ESTIMATE_TYPES.FEE_MARKET) {\n log('Using fee market estimates', gasFeeEstimates);\n response = this.#randomiseFeeMarketEstimates(\n gasFeeEstimates,\n randomisedGasFeeDigits,\n );\n log('Randomised fee market estimates', response);\n } else if (gasEstimateType === GAS_ESTIMATE_TYPES.LEGACY) {\n log('Using legacy estimates', gasFeeEstimates);\n response = this.#randomiseLegacyEstimates(\n gasFeeEstimates,\n randomisedGasFeeDigits,\n );\n log('Randomised legacy estimates', response);\n } else if (gasEstimateType === GAS_ESTIMATE_TYPES.ETH_GASPRICE) {\n log('Using eth_gasPrice estimates', gasFeeEstimates);\n response = this.#getRandomisedGasPriceEstimate(\n gasFeeEstimates,\n randomisedGasFeeDigits,\n );\n log('Randomised eth_gasPrice estimates', response);\n } else {\n throw new Error(`Unsupported gas estimate type: ${gasEstimateType}`);\n }\n\n return {\n estimates: response,\n };\n }\n\n #randomiseFeeMarketEstimates(\n gasFeeEstimates: FeeMarketGasPriceEstimate,\n lastNDigits: number,\n ): FeeMarketGasFeeEstimates {\n const levels = Object.values(GasFeeEstimateLevel).reduce(\n (result, level) => ({\n ...result,\n [level]: this.#getRandomisedFeeMarketLevel(\n gasFeeEstimates,\n level,\n lastNDigits,\n ),\n }),\n {} as Omit<FeeMarketGasFeeEstimates, 'type'>,\n );\n\n return {\n type: GasFeeEstimateType.FeeMarket,\n ...levels,\n };\n }\n\n #getRandomisedFeeMarketLevel(\n gasFeeEstimates: FeeMarketGasPriceEstimate,\n level: GasFeeEstimateLevel,\n lastNDigits: number,\n ): FeeMarketGasFeeEstimateForLevel {\n return {\n maxFeePerGas: randomiseDecimalGWEIAndConvertToHex(\n gasFeeEstimates[level].suggestedMaxFeePerGas,\n lastNDigits,\n ),\n maxPriorityFeePerGas: randomiseDecimalGWEIAndConvertToHex(\n gasFeeEstimates[level].suggestedMaxPriorityFeePerGas,\n lastNDigits,\n ),\n };\n }\n\n #randomiseLegacyEstimates(\n gasFeeEstimates: LegacyGasPriceEstimate,\n lastNDigits: number,\n ): LegacyGasFeeEstimates {\n const levels = Object.values(GasFeeEstimateLevel).reduce(\n (result, level) => ({\n ...result,\n [level]: this.#getRandomisedLegacyLevel(\n gasFeeEstimates,\n level,\n lastNDigits,\n ),\n }),\n {} as Omit<LegacyGasFeeEstimates, 'type'>,\n );\n\n return {\n type: GasFeeEstimateType.Legacy,\n ...levels,\n };\n }\n\n #getRandomisedLegacyLevel(\n gasFeeEstimates: LegacyGasPriceEstimate,\n level: GasFeeEstimateLevel,\n lastNDigits: number,\n ): Hex {\n return randomiseDecimalGWEIAndConvertToHex(\n gasFeeEstimates[level],\n lastNDigits,\n );\n }\n\n #getRandomisedGasPriceEstimate(\n gasFeeEstimates: EthGasPriceEstimate,\n lastNDigits: number,\n ): GasPriceGasFeeEstimates {\n return {\n type: GasFeeEstimateType.GasPrice,\n gasPrice: randomiseDecimalGWEIAndConvertToHex(\n gasFeeEstimates.gasPrice,\n lastNDigits,\n ),\n };\n }\n}\n\n/**\n * Generates a random number with the specified number of digits that is greater than or equal to the given minimum value.\n *\n * @param digitCount - The number of digits the random number should have\n * @param minValue - The minimum value the random number should have\n * @returns A random number with the specified number of digits\n */\nfunction generateRandomDigits(digitCount: number, minValue: number): number {\n const multiplier = 10 ** digitCount;\n return minValue + Math.floor(Math.random() * (multiplier - minValue));\n}\n\n/**\n * Randomises the least significant digits of a decimal gas fee value and converts it to a hexadecimal Wei value.\n *\n * This function preserves the more significant digits while randomizing only the least significant ones,\n * ensuring that fees remain close to the original estimation while providing randomisation.\n * The randomisation is performed in Wei units for more precision.\n *\n * @param gweiDecimalValue - The original gas fee value in Gwei (decimal)\n * @param [numberOfDigitsToRandomizeAtTheEnd] - The number of least significant digits to randomise\n * @returns The randomised value converted to Wei in hexadecimal format\n */\nexport function randomiseDecimalGWEIAndConvertToHex(\n gweiDecimalValue: string | number,\n numberOfDigitsToRandomizeAtTheEnd: number,\n): Hex {\n const weiDecimalValue = gweiDecimalToWeiDecimal(gweiDecimalValue);\n const decimalLength = weiDecimalValue.length;\n\n // Determine how many digits to randomise while preserving the PRESERVE_NUMBER_OF_DIGITS\n const effectiveDigitsToRandomise = Math.min(\n numberOfDigitsToRandomizeAtTheEnd,\n decimalLength - PRESERVE_NUMBER_OF_DIGITS,\n );\n\n // Handle the case when the value is 0 or too small\n if (Number(weiDecimalValue) === 0 || effectiveDigitsToRandomise <= 0) {\n return `0x${Number(weiDecimalValue).toString(16)}` as Hex;\n }\n\n // Use string manipulation to get the base part (significant digits)\n const significantDigitsCount = decimalLength - effectiveDigitsToRandomise;\n const significantDigits = weiDecimalValue.slice(0, significantDigitsCount);\n\n // Get the original ending digits using string manipulation\n const endingDigits = weiDecimalValue.slice(-effectiveDigitsToRandomise);\n const originalEndingDigits = Number(endingDigits);\n\n // Generate random digits that are greater than or equal to the original ending digits\n const randomEndingDigits = generateRandomDigits(\n effectiveDigitsToRandomise,\n originalEndingDigits,\n );\n\n const basePart = BigInt(\n significantDigits + '0'.repeat(effectiveDigitsToRandomise),\n );\n const randomisedWeiDecimal = basePart + BigInt(randomEndingDigits);\n\n return `0x${randomisedWeiDecimal.toString(16)}` as Hex;\n}\n"]}