@metamask/transaction-controller 24.0.0 → 25.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (278) hide show
  1. package/CHANGELOG.md +118 -1
  2. package/dist/TransactionController.js +38 -1816
  3. package/dist/TransactionController.js.map +1 -1
  4. package/dist/TransactionController.mjs +39 -0
  5. package/dist/TransactionController.mjs.map +1 -0
  6. package/dist/chunk-2K7J3EY3.mjs +170 -0
  7. package/dist/chunk-2K7J3EY3.mjs.map +1 -0
  8. package/dist/chunk-5XBULBP2.js +399 -0
  9. package/dist/chunk-5XBULBP2.js.map +1 -0
  10. package/dist/chunk-6MYNWYJK.mjs +158 -0
  11. package/dist/chunk-6MYNWYJK.mjs.map +1 -0
  12. package/dist/chunk-7APMBUKB.js +158 -0
  13. package/dist/chunk-7APMBUKB.js.map +1 -0
  14. package/dist/chunk-7LXE4KHV.js +40 -0
  15. package/dist/chunk-7LXE4KHV.js.map +1 -0
  16. package/dist/chunk-7MZ57ILQ.mjs +62 -0
  17. package/dist/chunk-7MZ57ILQ.mjs.map +1 -0
  18. package/dist/chunk-BJEESIBE.js +2313 -0
  19. package/dist/chunk-BJEESIBE.js.map +1 -0
  20. package/dist/chunk-C67QD5PV.mjs +320 -0
  21. package/dist/chunk-C67QD5PV.mjs.map +1 -0
  22. package/dist/chunk-DE3MZYVY.mjs +2313 -0
  23. package/dist/chunk-DE3MZYVY.mjs.map +1 -0
  24. package/dist/chunk-DEKM6PVG.mjs +46 -0
  25. package/dist/chunk-DEKM6PVG.mjs.map +1 -0
  26. package/dist/chunk-DQP6X25N.mjs +208 -0
  27. package/dist/chunk-DQP6X25N.mjs.map +1 -0
  28. package/dist/chunk-DTDTOMTB.js +238 -0
  29. package/dist/chunk-DTDTOMTB.js.map +1 -0
  30. package/dist/chunk-DTEDYRTL.js +242 -0
  31. package/dist/chunk-DTEDYRTL.js.map +1 -0
  32. package/dist/chunk-EQ3RRHB7.mjs +211 -0
  33. package/dist/chunk-EQ3RRHB7.mjs.map +1 -0
  34. package/dist/chunk-FDJPXQTF.js +46 -0
  35. package/dist/chunk-FDJPXQTF.js.map +1 -0
  36. package/dist/chunk-FRKQ3Z2L.mjs +40 -0
  37. package/dist/chunk-FRKQ3Z2L.mjs.map +1 -0
  38. package/dist/chunk-FS7FRO7B.mjs +90 -0
  39. package/dist/chunk-FS7FRO7B.mjs.map +1 -0
  40. package/dist/chunk-GKTIFXPN.js +170 -0
  41. package/dist/chunk-GKTIFXPN.js.map +1 -0
  42. package/dist/chunk-H4M66BA3.js +62 -0
  43. package/dist/chunk-H4M66BA3.js.map +1 -0
  44. package/dist/chunk-HPNXIKFY.js +76 -0
  45. package/dist/chunk-HPNXIKFY.js.map +1 -0
  46. package/dist/chunk-HS277C77.js +75 -0
  47. package/dist/chunk-HS277C77.js.map +1 -0
  48. package/dist/chunk-I5YZ7QUK.js +121 -0
  49. package/dist/chunk-I5YZ7QUK.js.map +1 -0
  50. package/dist/chunk-IC233ZQS.js +211 -0
  51. package/dist/chunk-IC233ZQS.js.map +1 -0
  52. package/dist/chunk-IUBAETUH.js +137 -0
  53. package/dist/chunk-IUBAETUH.js.map +1 -0
  54. package/dist/chunk-J56A7UCK.mjs +123 -0
  55. package/dist/chunk-J56A7UCK.mjs.map +1 -0
  56. package/dist/chunk-JR6HDRNV.mjs +242 -0
  57. package/dist/chunk-JR6HDRNV.mjs.map +1 -0
  58. package/dist/chunk-JRBREX22.mjs +75 -0
  59. package/dist/chunk-JRBREX22.mjs.map +1 -0
  60. package/dist/chunk-JRQHIBG5.mjs +399 -0
  61. package/dist/chunk-JRQHIBG5.mjs.map +1 -0
  62. package/dist/chunk-LM4NUNMT.mjs +76 -0
  63. package/dist/chunk-LM4NUNMT.mjs.map +1 -0
  64. package/dist/chunk-M7455RU7.js +320 -0
  65. package/dist/chunk-M7455RU7.js.map +1 -0
  66. package/dist/chunk-MHM5LRRF.mjs +122 -0
  67. package/dist/chunk-MHM5LRRF.mjs.map +1 -0
  68. package/dist/chunk-NHRBO3LU.mjs +50 -0
  69. package/dist/chunk-NHRBO3LU.mjs.map +1 -0
  70. package/dist/chunk-NM6OYEPP.mjs +182 -0
  71. package/dist/chunk-NM6OYEPP.mjs.map +1 -0
  72. package/dist/chunk-NUOBUW7C.js +85 -0
  73. package/dist/chunk-NUOBUW7C.js.map +1 -0
  74. package/dist/chunk-QP75SWIQ.js +53 -0
  75. package/dist/chunk-QP75SWIQ.js.map +1 -0
  76. package/dist/chunk-RI6MVJJN.js +122 -0
  77. package/dist/chunk-RI6MVJJN.js.map +1 -0
  78. package/dist/chunk-S6VGOPUY.js +14 -0
  79. package/dist/chunk-S6VGOPUY.js.map +1 -0
  80. package/dist/chunk-UGFBA4GV.js +123 -0
  81. package/dist/chunk-UGFBA4GV.js.map +1 -0
  82. package/dist/chunk-UKYY2RVS.mjs +137 -0
  83. package/dist/chunk-UKYY2RVS.mjs.map +1 -0
  84. package/dist/chunk-UM4ORJ5B.mjs +121 -0
  85. package/dist/chunk-UM4ORJ5B.mjs.map +1 -0
  86. package/dist/chunk-UQQWZT6C.mjs +14 -0
  87. package/dist/chunk-UQQWZT6C.mjs.map +1 -0
  88. package/dist/chunk-VH47Q6TS.js +182 -0
  89. package/dist/chunk-VH47Q6TS.js.map +1 -0
  90. package/dist/chunk-XGRAHX6T.mjs +53 -0
  91. package/dist/chunk-XGRAHX6T.mjs.map +1 -0
  92. package/dist/chunk-XUI43LEZ.mjs +30 -0
  93. package/dist/chunk-XUI43LEZ.mjs.map +1 -0
  94. package/dist/chunk-Y734U4V6.mjs +85 -0
  95. package/dist/chunk-Y734U4V6.mjs.map +1 -0
  96. package/dist/chunk-Y7ENNK7L.mjs +238 -0
  97. package/dist/chunk-Y7ENNK7L.mjs.map +1 -0
  98. package/dist/chunk-Z4BLTVTB.js +30 -0
  99. package/dist/chunk-Z4BLTVTB.js.map +1 -0
  100. package/dist/chunk-ZCQRDZ36.js +208 -0
  101. package/dist/chunk-ZCQRDZ36.js.map +1 -0
  102. package/dist/chunk-ZJLZSFOZ.js +90 -0
  103. package/dist/chunk-ZJLZSFOZ.js.map +1 -0
  104. package/dist/chunk-ZNZEJDOE.js +50 -0
  105. package/dist/chunk-ZNZEJDOE.js.map +1 -0
  106. package/dist/constants.js +15 -110
  107. package/dist/constants.js.map +1 -1
  108. package/dist/constants.mjs +16 -0
  109. package/dist/constants.mjs.map +1 -0
  110. package/dist/gas-flows/DefaultGasFeeFlow.js +14 -77
  111. package/dist/gas-flows/DefaultGasFeeFlow.js.map +1 -1
  112. package/dist/gas-flows/DefaultGasFeeFlow.mjs +15 -0
  113. package/dist/gas-flows/DefaultGasFeeFlow.mjs.map +1 -0
  114. package/dist/gas-flows/LineaGasFeeFlow.js +15 -110
  115. package/dist/gas-flows/LineaGasFeeFlow.js.map +1 -1
  116. package/dist/gas-flows/LineaGasFeeFlow.mjs +16 -0
  117. package/dist/gas-flows/LineaGasFeeFlow.mjs.map +1 -0
  118. package/dist/helpers/EtherscanRemoteTransactionSource.js +11 -145
  119. package/dist/helpers/EtherscanRemoteTransactionSource.js.map +1 -1
  120. package/dist/helpers/EtherscanRemoteTransactionSource.mjs +12 -0
  121. package/dist/helpers/EtherscanRemoteTransactionSource.mjs.map +1 -0
  122. package/dist/helpers/GasFeePoller.js +10 -143
  123. package/dist/helpers/GasFeePoller.js.map +1 -1
  124. package/dist/helpers/GasFeePoller.mjs +11 -0
  125. package/dist/helpers/GasFeePoller.mjs.map +1 -0
  126. package/dist/helpers/IncomingTransactionHelper.js +8 -205
  127. package/dist/helpers/IncomingTransactionHelper.js.map +1 -1
  128. package/dist/helpers/IncomingTransactionHelper.mjs +9 -0
  129. package/dist/helpers/IncomingTransactionHelper.mjs.map +1 -0
  130. package/dist/helpers/MultichainTrackingHelper.js +12 -291
  131. package/dist/helpers/MultichainTrackingHelper.js.map +1 -1
  132. package/dist/helpers/MultichainTrackingHelper.mjs +13 -0
  133. package/dist/helpers/MultichainTrackingHelper.mjs.map +1 -0
  134. package/dist/helpers/PendingTransactionTracker.js +9 -360
  135. package/dist/helpers/PendingTransactionTracker.js.map +1 -1
  136. package/dist/helpers/PendingTransactionTracker.mjs +10 -0
  137. package/dist/helpers/PendingTransactionTracker.mjs.map +1 -0
  138. package/dist/index.js +56 -26
  139. package/dist/index.js.map +1 -1
  140. package/dist/index.mjs +57 -0
  141. package/dist/index.mjs.map +1 -0
  142. package/dist/logger.js +11 -8
  143. package/dist/logger.js.map +1 -1
  144. package/dist/logger.mjs +12 -0
  145. package/dist/logger.mjs.map +1 -0
  146. package/dist/tsconfig.build.tsbuildinfo +1 -0
  147. package/dist/{TransactionController.d.ts → types/TransactionController.d.ts} +235 -46
  148. package/dist/types/TransactionController.d.ts.map +1 -0
  149. package/dist/{constants.d.ts → types/constants.d.ts} +5 -0
  150. package/dist/types/constants.d.ts.map +1 -0
  151. package/dist/types/gas-flows/DefaultGasFeeFlow.d.ts.map +1 -0
  152. package/dist/types/gas-flows/LineaGasFeeFlow.d.ts.map +1 -0
  153. package/dist/types/helpers/EtherscanRemoteTransactionSource.d.ts.map +1 -0
  154. package/dist/types/helpers/GasFeePoller.d.ts.map +1 -0
  155. package/dist/types/helpers/IncomingTransactionHelper.d.ts.map +1 -0
  156. package/dist/types/helpers/MultichainTrackingHelper.d.ts.map +1 -0
  157. package/dist/types/helpers/PendingTransactionTracker.d.ts.map +1 -0
  158. package/dist/types/index.d.ts +9 -0
  159. package/dist/types/index.d.ts.map +1 -0
  160. package/dist/types/logger.d.ts.map +1 -0
  161. package/dist/{types.d.ts → types/types.d.ts} +63 -65
  162. package/dist/types/types.d.ts.map +1 -0
  163. package/dist/types/utils/etherscan.d.ts.map +1 -0
  164. package/dist/types/utils/external-transactions.d.ts.map +1 -0
  165. package/dist/types/utils/gas-fees.d.ts.map +1 -0
  166. package/dist/types/utils/gas-flow.d.ts.map +1 -0
  167. package/dist/types/utils/gas.d.ts.map +1 -0
  168. package/dist/types/utils/history.d.ts +20 -0
  169. package/dist/types/utils/history.d.ts.map +1 -0
  170. package/dist/types/utils/nonce.d.ts.map +1 -0
  171. package/dist/types/utils/simulation-api.d.ts +99 -0
  172. package/dist/types/utils/simulation-api.d.ts.map +1 -0
  173. package/dist/types/utils/simulation.d.ts +21 -0
  174. package/dist/types/utils/simulation.d.ts.map +1 -0
  175. package/dist/{utils → types/utils}/swaps.d.ts +8 -5
  176. package/dist/types/utils/swaps.d.ts.map +1 -0
  177. package/dist/types/utils/transaction-type.d.ts.map +1 -0
  178. package/dist/types/utils/utils.d.ts.map +1 -0
  179. package/dist/types/utils/validation.d.ts.map +1 -0
  180. package/dist/types.js +19 -170
  181. package/dist/types.js.map +1 -1
  182. package/dist/types.mjs +20 -0
  183. package/dist/types.mjs.map +1 -0
  184. package/dist/utils/etherscan.js +13 -118
  185. package/dist/utils/etherscan.js.map +1 -1
  186. package/dist/utils/etherscan.mjs +14 -0
  187. package/dist/utils/etherscan.mjs.map +1 -0
  188. package/dist/utils/external-transactions.js +8 -35
  189. package/dist/utils/external-transactions.js.map +1 -1
  190. package/dist/utils/external-transactions.mjs +9 -0
  191. package/dist/utils/external-transactions.mjs.map +1 -0
  192. package/dist/utils/gas-fees.js +15 -200
  193. package/dist/utils/gas-fees.js.map +1 -1
  194. package/dist/utils/gas-fees.mjs +16 -0
  195. package/dist/utils/gas-fees.mjs.map +1 -0
  196. package/dist/utils/gas-flow.js +10 -52
  197. package/dist/utils/gas-flow.js.map +1 -1
  198. package/dist/utils/gas-flow.mjs +11 -0
  199. package/dist/utils/gas-flow.mjs.map +1 -0
  200. package/dist/utils/gas.js +19 -133
  201. package/dist/utils/gas.js.map +1 -1
  202. package/dist/utils/gas.mjs +20 -0
  203. package/dist/utils/gas.mjs.map +1 -0
  204. package/dist/utils/history.js +9 -83
  205. package/dist/utils/history.js.map +1 -1
  206. package/dist/utils/history.mjs +10 -0
  207. package/dist/utils/history.mjs.map +1 -0
  208. package/dist/utils/nonce.js +10 -76
  209. package/dist/utils/nonce.js.map +1 -1
  210. package/dist/utils/nonce.mjs +11 -0
  211. package/dist/utils/nonce.mjs.map +1 -0
  212. package/dist/utils/simulation-api.js +10 -0
  213. package/dist/utils/simulation-api.js.map +1 -0
  214. package/dist/utils/simulation-api.mjs +10 -0
  215. package/dist/utils/simulation-api.mjs.map +1 -0
  216. package/dist/utils/simulation.js +12 -0
  217. package/dist/utils/simulation.js.map +1 -0
  218. package/dist/utils/simulation.mjs +12 -0
  219. package/dist/utils/simulation.mjs.map +1 -0
  220. package/dist/utils/swaps.js +23 -256
  221. package/dist/utils/swaps.js.map +1 -1
  222. package/dist/utils/swaps.mjs +24 -0
  223. package/dist/utils/swaps.mjs.map +1 -0
  224. package/dist/utils/transaction-type.js +10 -120
  225. package/dist/utils/transaction-type.js.map +1 -1
  226. package/dist/utils/transaction-type.mjs +11 -0
  227. package/dist/utils/transaction-type.mjs.map +1 -0
  228. package/dist/utils/utils.js +32 -160
  229. package/dist/utils/utils.js.map +1 -1
  230. package/dist/utils/utils.mjs +33 -0
  231. package/dist/utils/utils.mjs.map +1 -0
  232. package/dist/utils/validation.js +11 -258
  233. package/dist/utils/validation.js.map +1 -1
  234. package/dist/utils/validation.mjs +12 -0
  235. package/dist/utils/validation.mjs.map +1 -0
  236. package/package.json +21 -9
  237. package/dist/TransactionController.d.ts.map +0 -1
  238. package/dist/constants.d.ts.map +0 -1
  239. package/dist/gas-flows/DefaultGasFeeFlow.d.ts.map +0 -1
  240. package/dist/gas-flows/LineaGasFeeFlow.d.ts.map +0 -1
  241. package/dist/helpers/EtherscanRemoteTransactionSource.d.ts.map +0 -1
  242. package/dist/helpers/GasFeePoller.d.ts.map +0 -1
  243. package/dist/helpers/IncomingTransactionHelper.d.ts.map +0 -1
  244. package/dist/helpers/MultichainTrackingHelper.d.ts.map +0 -1
  245. package/dist/helpers/PendingTransactionTracker.d.ts.map +0 -1
  246. package/dist/index.d.ts +0 -7
  247. package/dist/index.d.ts.map +0 -1
  248. package/dist/logger.d.ts.map +0 -1
  249. package/dist/types.d.ts.map +0 -1
  250. package/dist/utils/etherscan.d.ts.map +0 -1
  251. package/dist/utils/external-transactions.d.ts.map +0 -1
  252. package/dist/utils/gas-fees.d.ts.map +0 -1
  253. package/dist/utils/gas-flow.d.ts.map +0 -1
  254. package/dist/utils/gas.d.ts.map +0 -1
  255. package/dist/utils/history.d.ts +0 -15
  256. package/dist/utils/history.d.ts.map +0 -1
  257. package/dist/utils/nonce.d.ts.map +0 -1
  258. package/dist/utils/swaps.d.ts.map +0 -1
  259. package/dist/utils/transaction-type.d.ts.map +0 -1
  260. package/dist/utils/utils.d.ts.map +0 -1
  261. package/dist/utils/validation.d.ts.map +0 -1
  262. /package/dist/{gas-flows → types/gas-flows}/DefaultGasFeeFlow.d.ts +0 -0
  263. /package/dist/{gas-flows → types/gas-flows}/LineaGasFeeFlow.d.ts +0 -0
  264. /package/dist/{helpers → types/helpers}/EtherscanRemoteTransactionSource.d.ts +0 -0
  265. /package/dist/{helpers → types/helpers}/GasFeePoller.d.ts +0 -0
  266. /package/dist/{helpers → types/helpers}/IncomingTransactionHelper.d.ts +0 -0
  267. /package/dist/{helpers → types/helpers}/MultichainTrackingHelper.d.ts +0 -0
  268. /package/dist/{helpers → types/helpers}/PendingTransactionTracker.d.ts +0 -0
  269. /package/dist/{logger.d.ts → types/logger.d.ts} +0 -0
  270. /package/dist/{utils → types/utils}/etherscan.d.ts +0 -0
  271. /package/dist/{utils → types/utils}/external-transactions.d.ts +0 -0
  272. /package/dist/{utils → types/utils}/gas-fees.d.ts +0 -0
  273. /package/dist/{utils → types/utils}/gas-flow.d.ts +0 -0
  274. /package/dist/{utils → types/utils}/gas.d.ts +0 -0
  275. /package/dist/{utils → types/utils}/nonce.d.ts +0 -0
  276. /package/dist/{utils → types/utils}/transaction-type.d.ts +0 -0
  277. /package/dist/{utils → types/utils}/utils.d.ts +0 -0
  278. /package/dist/{utils → types/utils}/validation.d.ts +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/utils.ts"],"sourcesContent":["import { convertHexToDecimal } from '@metamask/controller-utils';\nimport {\n add0x,\n getKnownPropertyNames,\n isStrictHexString,\n} from '@metamask/utils';\nimport type { Json } from '@metamask/utils';\n\nimport type {\n GasPriceValue,\n FeeMarketEIP1559Values,\n} from '../TransactionController';\nimport { TransactionStatus } from '../types';\nimport type {\n TransactionParams,\n TransactionMeta,\n TransactionError,\n} from '../types';\n\nexport const ESTIMATE_GAS_ERROR = 'eth_estimateGas rpc method error';\n\n// TODO: Replace `any` with type\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst NORMALIZERS: { [param in keyof TransactionParams]: any } = {\n data: (data: string) => add0x(padHexToEvenLength(data)),\n from: (from: string) => add0x(from).toLowerCase(),\n gas: (gas: string) => add0x(gas),\n gasLimit: (gas: string) => add0x(gas),\n gasPrice: (gasPrice: string) => add0x(gasPrice),\n nonce: (nonce: string) => add0x(nonce),\n to: (to: string) => add0x(to).toLowerCase(),\n value: (value: string) => add0x(value),\n maxFeePerGas: (maxFeePerGas: string) => add0x(maxFeePerGas),\n maxPriorityFeePerGas: (maxPriorityFeePerGas: string) =>\n add0x(maxPriorityFeePerGas),\n estimatedBaseFee: (maxPriorityFeePerGas: string) =>\n add0x(maxPriorityFeePerGas),\n type: (type: string) => add0x(type),\n};\n\n/**\n * Normalizes properties on transaction params.\n *\n * @param txParams - The transaction params to normalize.\n * @returns Normalized transaction params.\n */\nexport function normalizeTransactionParams(txParams: TransactionParams) {\n const normalizedTxParams: TransactionParams = { from: '' };\n\n for (const key of getKnownPropertyNames(NORMALIZERS)) {\n if (txParams[key]) {\n normalizedTxParams[key] = NORMALIZERS[key](txParams[key]);\n }\n }\n\n if (!normalizedTxParams.value) {\n normalizedTxParams.value = '0x0';\n }\n\n return normalizedTxParams;\n}\n\n/**\n * Checks if a transaction is EIP-1559 by checking for the existence of\n * maxFeePerGas and maxPriorityFeePerGas within its parameters.\n *\n * @param txParams - Transaction params object to add.\n * @returns Boolean that is true if the transaction is EIP-1559 (has maxFeePerGas and maxPriorityFeePerGas), otherwise returns false.\n */\nexport function isEIP1559Transaction(txParams: TransactionParams): boolean {\n const hasOwnProp = (obj: TransactionParams, key: string) =>\n Object.prototype.hasOwnProperty.call(obj, key);\n return (\n hasOwnProp(txParams, 'maxFeePerGas') &&\n hasOwnProp(txParams, 'maxPriorityFeePerGas')\n );\n}\n\nexport const validateGasValues = (\n gasValues: GasPriceValue | FeeMarketEIP1559Values,\n) => {\n Object.keys(gasValues).forEach((key) => {\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const value = (gasValues as any)[key];\n if (typeof value !== 'string' || !isStrictHexString(value)) {\n throw new TypeError(\n `expected hex string for ${key} but received: ${value}`,\n );\n }\n });\n};\n\nexport const isFeeMarketEIP1559Values = (\n gasValues?: GasPriceValue | FeeMarketEIP1559Values,\n): gasValues is FeeMarketEIP1559Values =>\n (gasValues as FeeMarketEIP1559Values)?.maxFeePerGas !== undefined ||\n (gasValues as FeeMarketEIP1559Values)?.maxPriorityFeePerGas !== undefined;\n\nexport const isGasPriceValue = (\n gasValues?: GasPriceValue | FeeMarketEIP1559Values,\n): gasValues is GasPriceValue =>\n (gasValues as GasPriceValue)?.gasPrice !== undefined;\n\nexport const getIncreasedPriceHex = (value: number, rate: number): string =>\n add0x(`${parseInt(`${value * rate}`, 10).toString(16)}`);\n\nexport const getIncreasedPriceFromExisting = (\n value: string | undefined,\n rate: number,\n): string => {\n return getIncreasedPriceHex(convertHexToDecimal(value), rate);\n};\n\n/**\n * Validates that the proposed value is greater than or equal to the minimum value.\n *\n * @param proposed - The proposed value.\n * @param min - The minimum value.\n * @returns The proposed value.\n * @throws Will throw if the proposed value is too low.\n */\nexport function validateMinimumIncrease(proposed: string, min: string) {\n const proposedDecimal = convertHexToDecimal(proposed);\n const minDecimal = convertHexToDecimal(min);\n if (proposedDecimal >= minDecimal) {\n return proposed;\n }\n const errorMsg = `The proposed value: ${proposedDecimal} should meet or exceed the minimum value: ${minDecimal}`;\n throw new Error(errorMsg);\n}\n\n/**\n * Validates that a transaction is unapproved.\n * Throws if the transaction is not unapproved.\n *\n * @param transactionMeta - The transaction metadata to check.\n * @param fnName - The name of the function calling this helper.\n */\nexport function validateIfTransactionUnapproved(\n transactionMeta: TransactionMeta | undefined,\n fnName: string,\n) {\n if (transactionMeta?.status !== TransactionStatus.unapproved) {\n throw new Error(\n `TransactionsController: Can only call ${fnName} on an unapproved transaction.\n Current tx status: ${transactionMeta?.status}`,\n );\n }\n}\n\n/**\n * Normalizes properties on transaction params.\n *\n * @param error - The error to be normalize.\n * @returns Normalized transaction error.\n */\nexport function normalizeTxError(\n error: Error & { code?: string; value?: unknown },\n): TransactionError {\n return {\n name: error.name,\n message: error.message,\n stack: error.stack,\n code: error.code,\n rpc: isJsonCompatible(error.value) ? error.value : undefined,\n };\n}\n\n/**\n * Normalize an object containing gas fee values.\n *\n * @param gasFeeValues - An object containing gas fee values.\n * @returns An object containing normalized gas fee values.\n */\nexport function normalizeGasFeeValues(\n gasFeeValues: GasPriceValue | FeeMarketEIP1559Values,\n): GasPriceValue | FeeMarketEIP1559Values {\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const normalize = (value: any) =>\n typeof value === 'string' ? add0x(value) : value;\n\n if ('gasPrice' in gasFeeValues) {\n return {\n gasPrice: normalize(gasFeeValues.gasPrice),\n };\n }\n\n return {\n maxFeePerGas: normalize(gasFeeValues.maxFeePerGas),\n maxPriorityFeePerGas: normalize(gasFeeValues.maxPriorityFeePerGas),\n };\n}\n\n/**\n * Determines whether the given value can be encoded as JSON.\n *\n * @param value - The value.\n * @returns True if the value is JSON-encodable, false if not.\n */\nfunction isJsonCompatible(value: unknown): value is Json {\n try {\n JSON.parse(JSON.stringify(value));\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Ensure a hex string is of even length by adding a leading 0 if necessary.\n * Any existing `0x` prefix is preserved but is not added if missing.\n *\n * @param hex - The hex string to ensure is even.\n * @returns The hex string with an even length.\n */\nexport function padHexToEvenLength(hex: string) {\n const prefix = hex.toLowerCase().startsWith('0x') ? hex.slice(0, 2) : '';\n const data = prefix ? hex.slice(2) : hex;\n const evenData = data.length % 2 === 0 ? data : `0${data}`;\n\n return prefix + evenData;\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,242 @@
1
+ import {
2
+ simulateTransactions
3
+ } from "./chunk-DEKM6PVG.mjs";
4
+ import {
5
+ projectLogger
6
+ } from "./chunk-UQQWZT6C.mjs";
7
+
8
+ // src/utils/simulation.ts
9
+ import { Interface } from "@ethersproject/abi";
10
+ import { hexToBN, toHex } from "@metamask/controller-utils";
11
+ import { abiERC20, abiERC721, abiERC1155 } from "@metamask/metamask-eth-abis";
12
+ import { createModuleLogger } from "@metamask/utils";
13
+ var log = createModuleLogger(projectLogger, "simulation");
14
+ async function getSimulationData(request) {
15
+ const { chainId, from, to, value, data } = request;
16
+ log("Getting simulation data", request);
17
+ try {
18
+ const response = await simulateTransactions(chainId, {
19
+ transactions: [{ from, to, value, data }],
20
+ withCallTrace: true,
21
+ withLogs: true
22
+ });
23
+ const nativeBalanceChange = getNativeBalanceChange(request.from, response);
24
+ const events = getEvents(response);
25
+ log("Parsed events", events);
26
+ const tokenBalanceChanges = await getTokenBalanceChanges(request, events);
27
+ return {
28
+ nativeBalanceChange,
29
+ tokenBalanceChanges
30
+ };
31
+ } catch (error) {
32
+ log("Failed to get simulation data", error, request);
33
+ return void 0;
34
+ }
35
+ }
36
+ function getNativeBalanceChange(userAddress, response) {
37
+ const transactionResponse = response.transactions[0];
38
+ if (!transactionResponse) {
39
+ return void 0;
40
+ }
41
+ const { stateDiff } = transactionResponse;
42
+ const previousBalance = stateDiff.pre[userAddress]?.balance;
43
+ const newBalance = stateDiff.post[userAddress]?.balance;
44
+ if (!previousBalance || !newBalance) {
45
+ return void 0;
46
+ }
47
+ return getSimulationBalanceChange(previousBalance, newBalance);
48
+ }
49
+ function getEvents(response) {
50
+ const logs = extractLogs(response.transactions[0]?.callTrace ?? {});
51
+ log("Extracted logs", logs);
52
+ const erc20Interface = new Interface(abiERC20);
53
+ const erc721Interface = new Interface(abiERC721);
54
+ const erc1155Interface = new Interface(abiERC1155);
55
+ return logs.map((currentLog) => {
56
+ const event = parseLog(
57
+ currentLog,
58
+ erc20Interface,
59
+ erc721Interface,
60
+ erc1155Interface
61
+ );
62
+ if (!event) {
63
+ log("Failed to parse log", currentLog);
64
+ return void 0;
65
+ }
66
+ const inputs = event.abi.find((e) => e.name === event.name)?.inputs;
67
+ if (!inputs) {
68
+ log("Failed to find inputs for event", event);
69
+ return void 0;
70
+ }
71
+ const args = parseEventArgs(event.args, inputs);
72
+ return {
73
+ contractAddress: currentLog.address,
74
+ tokenStandard: event.standard,
75
+ name: event.name,
76
+ args,
77
+ abi: event.abi
78
+ };
79
+ }).filter((e) => e !== void 0);
80
+ }
81
+ function parseEventArgs(args, abiInputs) {
82
+ return args.reduce((result, arg, index) => {
83
+ const name = abiInputs[index].name.replace("_", "");
84
+ const value = parseEventArgValue(arg);
85
+ result[name] = value;
86
+ return result;
87
+ }, {});
88
+ }
89
+ function parseEventArgValue(value) {
90
+ if (Array.isArray(value)) {
91
+ return value.map(parseEventArgValue);
92
+ }
93
+ return (value.toHexString?.() ?? value).toLowerCase();
94
+ }
95
+ async function getTokenBalanceChanges(request, events) {
96
+ const balanceTransactionsByToken = getTokenBalanceTransactions(
97
+ request,
98
+ events
99
+ );
100
+ const balanceTransactions = [...balanceTransactionsByToken.values()];
101
+ log("Generated balance transactions", balanceTransactions);
102
+ if (!balanceTransactions.length) {
103
+ return [];
104
+ }
105
+ const response = await simulateTransactions(request.chainId, {
106
+ transactions: [...balanceTransactions, request, ...balanceTransactions]
107
+ });
108
+ log("Balance simulation response", response);
109
+ if (response.transactions.length !== balanceTransactions.length * 2 + 1) {
110
+ throw new Error("Invalid response from simulation API");
111
+ }
112
+ return [...balanceTransactionsByToken.keys()].map((token, index) => {
113
+ const previousBalance = normalizeReturnValue(
114
+ response.transactions[index].return
115
+ );
116
+ const newBalance = normalizeReturnValue(
117
+ response.transactions[index + balanceTransactions.length + 1].return
118
+ );
119
+ const balanceChange = getSimulationBalanceChange(
120
+ previousBalance,
121
+ newBalance
122
+ );
123
+ if (!balanceChange) {
124
+ return void 0;
125
+ }
126
+ return {
127
+ ...token,
128
+ ...balanceChange
129
+ };
130
+ }).filter((change) => change !== void 0);
131
+ }
132
+ function getTokenBalanceTransactions(request, events) {
133
+ const tokenKeys = /* @__PURE__ */ new Set();
134
+ return events.reduce((result, event) => {
135
+ if (!["Transfer", "TransferSingle", "TransferBatch"].includes(event.name) || ![event.args.from, event.args.to].includes(request.from)) {
136
+ log("Ignoring event", event);
137
+ return result;
138
+ }
139
+ let tokenIds = [void 0];
140
+ if (event.tokenStandard === "erc721" /* erc721 */) {
141
+ tokenIds = [event.args.tokenId];
142
+ }
143
+ if (event.tokenStandard === "erc1155" /* erc1155 */ && event.name === "TransferSingle") {
144
+ tokenIds = [event.args.id];
145
+ }
146
+ if (event.tokenStandard === "erc1155" /* erc1155 */ && event.name === "TransferBatch") {
147
+ tokenIds = event.args.ids;
148
+ }
149
+ log("Extracted token ids", tokenIds);
150
+ for (const tokenId of tokenIds) {
151
+ const simulationToken = {
152
+ address: event.contractAddress,
153
+ standard: event.tokenStandard,
154
+ id: tokenId
155
+ };
156
+ const tokenKey = JSON.stringify(simulationToken);
157
+ if (tokenKeys.has(tokenKey)) {
158
+ log(
159
+ "Ignoring additional event with same contract and token ID",
160
+ simulationToken
161
+ );
162
+ continue;
163
+ }
164
+ tokenKeys.add(tokenKey);
165
+ const parameters = [request.from];
166
+ if (event.tokenStandard === "erc1155" /* erc1155 */) {
167
+ parameters.push(tokenId);
168
+ }
169
+ result.set(simulationToken, {
170
+ from: request.from,
171
+ to: event.contractAddress,
172
+ data: new Interface(event.abi).encodeFunctionData(
173
+ "balanceOf",
174
+ parameters
175
+ )
176
+ });
177
+ }
178
+ return result;
179
+ }, /* @__PURE__ */ new Map());
180
+ }
181
+ function parseLog(eventLog, erc20, erc721, erc1155) {
182
+ const abisByStandard = [
183
+ {
184
+ abi: abiERC20,
185
+ contractInterface: erc20,
186
+ standard: "erc20" /* erc20 */
187
+ },
188
+ {
189
+ abi: abiERC721,
190
+ contractInterface: erc721,
191
+ standard: "erc721" /* erc721 */
192
+ },
193
+ {
194
+ abi: abiERC1155,
195
+ contractInterface: erc1155,
196
+ standard: "erc1155" /* erc1155 */
197
+ }
198
+ ];
199
+ for (const { abi, contractInterface, standard } of abisByStandard) {
200
+ try {
201
+ return {
202
+ ...contractInterface.parseLog(eventLog),
203
+ abi,
204
+ standard
205
+ };
206
+ } catch (e) {
207
+ continue;
208
+ }
209
+ }
210
+ return void 0;
211
+ }
212
+ function extractLogs(call) {
213
+ const logs = call.logs ?? [];
214
+ const nestedCalls = call.calls ?? [];
215
+ return [
216
+ ...logs,
217
+ ...nestedCalls.map((nestedCall) => extractLogs(nestedCall)).flat()
218
+ ];
219
+ }
220
+ function getSimulationBalanceChange(previousBalance, newBalance) {
221
+ const differenceBN = hexToBN(newBalance).sub(hexToBN(previousBalance));
222
+ const isDecrease = differenceBN.isNeg();
223
+ const difference = toHex(differenceBN.abs());
224
+ if (differenceBN.isZero()) {
225
+ log("Balance change is zero");
226
+ return void 0;
227
+ }
228
+ return {
229
+ previousBalance,
230
+ newBalance,
231
+ difference,
232
+ isDecrease
233
+ };
234
+ }
235
+ function normalizeReturnValue(value) {
236
+ return toHex(hexToBN(value));
237
+ }
238
+
239
+ export {
240
+ getSimulationData
241
+ };
242
+ //# sourceMappingURL=chunk-JR6HDRNV.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/simulation.ts"],"sourcesContent":["import type { Fragment, LogDescription, Result } from '@ethersproject/abi';\nimport { Interface } from '@ethersproject/abi';\nimport { hexToBN, toHex } from '@metamask/controller-utils';\nimport { abiERC20, abiERC721, abiERC1155 } from '@metamask/metamask-eth-abis';\nimport { createModuleLogger, type Hex } from '@metamask/utils';\n\nimport { projectLogger } from '../logger';\nimport type {\n SimulationBalanceChange,\n SimulationData,\n SimulationTokenBalanceChange,\n SimulationToken,\n} from '../types';\nimport { SimulationTokenStandard } from '../types';\nimport type {\n SimulationResponseLog,\n SimulationRequestTransaction,\n SimulationResponse,\n SimulationResponseCallTrace,\n} from './simulation-api';\nimport { simulateTransactions } from './simulation-api';\n\nconst log = createModuleLogger(projectLogger, 'simulation');\n\ntype ABI = Fragment[];\n\nexport type GetSimulationDataRequest = {\n chainId: Hex;\n from: Hex;\n to?: Hex;\n value?: Hex;\n data?: Hex;\n};\n\ntype ParsedEvent = {\n contractAddress: Hex;\n tokenStandard: SimulationTokenStandard;\n name: string;\n args: Record<string, Hex | Hex[]>;\n abi: ABI;\n};\n\n/**\n * Generate simulation data for a transaction.\n * @param request - The transaction to simulate.\n * @param request.chainId - The chain ID of the transaction.\n * @param request.from - The sender of the transaction.\n * @param request.to - The recipient of the transaction.\n * @param request.value - The value of the transaction.\n * @param request.data - The data of the transaction.\n * @returns The simulation data.\n */\nexport async function getSimulationData(\n request: GetSimulationDataRequest,\n): Promise<SimulationData | undefined> {\n const { chainId, from, to, value, data } = request;\n\n log('Getting simulation data', request);\n\n try {\n const response = await simulateTransactions(chainId, {\n transactions: [{ from, to, value, data }],\n withCallTrace: true,\n withLogs: true,\n });\n\n const nativeBalanceChange = getNativeBalanceChange(request.from, response);\n const events = getEvents(response);\n\n log('Parsed events', events);\n\n const tokenBalanceChanges = await getTokenBalanceChanges(request, events);\n\n return {\n nativeBalanceChange,\n tokenBalanceChanges,\n };\n } catch (error) {\n log('Failed to get simulation data', error, request);\n return undefined;\n }\n}\n\n/**\n * Extract the native balance change from a simulation response.\n * @param userAddress - The user's account address.\n * @param response - The simulation response.\n * @returns The native balance change or undefined if unchanged.\n */\nfunction getNativeBalanceChange(\n userAddress: Hex,\n response: SimulationResponse,\n): SimulationBalanceChange | undefined {\n const transactionResponse = response.transactions[0];\n\n /* istanbul ignore next */\n if (!transactionResponse) {\n return undefined;\n }\n\n const { stateDiff } = transactionResponse;\n const previousBalance = stateDiff.pre[userAddress]?.balance;\n const newBalance = stateDiff.post[userAddress]?.balance;\n\n if (!previousBalance || !newBalance) {\n return undefined;\n }\n\n return getSimulationBalanceChange(previousBalance, newBalance);\n}\n\n/**\n * Extract events from a simulation response.\n * @param response - The simulation response.\n * @returns The parsed events.\n */\nfunction getEvents(response: SimulationResponse): ParsedEvent[] {\n /* istanbul ignore next */\n const logs = extractLogs(response.transactions[0]?.callTrace ?? {});\n\n log('Extracted logs', logs);\n\n const erc20Interface = new Interface(abiERC20);\n const erc721Interface = new Interface(abiERC721);\n const erc1155Interface = new Interface(abiERC1155);\n\n return logs\n .map((currentLog) => {\n const event = parseLog(\n currentLog,\n erc20Interface,\n erc721Interface,\n erc1155Interface,\n );\n\n if (!event) {\n log('Failed to parse log', currentLog);\n return undefined;\n }\n\n /* istanbul ignore next */\n const inputs = event.abi.find((e) => e.name === event.name)?.inputs;\n\n /* istanbul ignore if */\n if (!inputs) {\n log('Failed to find inputs for event', event);\n return undefined;\n }\n\n const args = parseEventArgs(event.args, inputs);\n\n return {\n contractAddress: currentLog.address,\n tokenStandard: event.standard,\n name: event.name,\n args,\n abi: event.abi,\n };\n })\n .filter((e) => e !== undefined) as ParsedEvent[];\n}\n\n/**\n * Parse event arguments using ABI input definitions.\n * @param args - The raw event arguments.\n * @param abiInputs - The ABI input definitions.\n * @returns The parsed event arguments.\n */\nfunction parseEventArgs(\n args: Result,\n abiInputs: { name: string }[],\n): Record<string, Hex | Hex[]> {\n return args.reduce((result, arg, index) => {\n const name = abiInputs[index].name.replace('_', '');\n const value = parseEventArgValue(arg);\n\n result[name] = value;\n\n return result;\n }, {});\n}\n\n/**\n * Parse an event argument value.\n * @param value - The event argument value.\n * @returns The parsed event argument value.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction parseEventArgValue(value: any): Hex | Hex[] {\n if (Array.isArray(value)) {\n return value.map(parseEventArgValue) as Hex[];\n }\n\n return (value.toHexString?.() ?? value).toLowerCase();\n}\n\n/**\n * Generate token balance changes from parsed events.\n * @param request - The transaction that was simulated.\n * @param events - The parsed events.\n * @returns An array of token balance changes.\n */\nasync function getTokenBalanceChanges(\n request: GetSimulationDataRequest,\n events: ParsedEvent[],\n): Promise<SimulationTokenBalanceChange[]> {\n const balanceTransactionsByToken = getTokenBalanceTransactions(\n request,\n events,\n );\n\n const balanceTransactions = [...balanceTransactionsByToken.values()];\n\n log('Generated balance transactions', balanceTransactions);\n\n if (!balanceTransactions.length) {\n return [];\n }\n\n const response = await simulateTransactions(request.chainId as Hex, {\n transactions: [...balanceTransactions, request, ...balanceTransactions],\n });\n\n log('Balance simulation response', response);\n\n if (response.transactions.length !== balanceTransactions.length * 2 + 1) {\n throw new Error('Invalid response from simulation API');\n }\n\n return [...balanceTransactionsByToken.keys()]\n .map((token, index) => {\n const previousBalance = normalizeReturnValue(\n response.transactions[index].return,\n );\n\n const newBalance = normalizeReturnValue(\n response.transactions[index + balanceTransactions.length + 1].return,\n );\n\n const balanceChange = getSimulationBalanceChange(\n previousBalance,\n newBalance,\n );\n\n if (!balanceChange) {\n return undefined;\n }\n\n return {\n ...token,\n ...balanceChange,\n };\n })\n .filter((change) => change !== undefined) as SimulationTokenBalanceChange[];\n}\n\n/**\n * Generate transactions to check token balances.\n * @param request - The transaction that was simulated.\n * @param events - The parsed events.\n * @returns A map of token balance transactions keyed by token.\n */\nfunction getTokenBalanceTransactions(\n request: GetSimulationDataRequest,\n events: ParsedEvent[],\n): Map<SimulationToken, SimulationRequestTransaction> {\n const tokenKeys = new Set();\n\n return events.reduce((result, event) => {\n if (\n !['Transfer', 'TransferSingle', 'TransferBatch'].includes(event.name) ||\n ![event.args.from, event.args.to].includes(request.from)\n ) {\n log('Ignoring event', event);\n return result;\n }\n\n // ERC-20 does not have a token ID so default to undefined.\n let tokenIds: (Hex | undefined)[] = [undefined];\n\n if (event.tokenStandard === SimulationTokenStandard.erc721) {\n tokenIds = [event.args.tokenId as Hex];\n }\n\n if (\n event.tokenStandard === SimulationTokenStandard.erc1155 &&\n event.name === 'TransferSingle'\n ) {\n tokenIds = [event.args.id as Hex];\n }\n\n if (\n event.tokenStandard === SimulationTokenStandard.erc1155 &&\n event.name === 'TransferBatch'\n ) {\n tokenIds = event.args.ids as Hex[];\n }\n\n log('Extracted token ids', tokenIds);\n\n for (const tokenId of tokenIds) {\n const simulationToken: SimulationToken = {\n address: event.contractAddress,\n standard: event.tokenStandard,\n id: tokenId,\n };\n\n const tokenKey = JSON.stringify(simulationToken);\n\n if (tokenKeys.has(tokenKey)) {\n log(\n 'Ignoring additional event with same contract and token ID',\n simulationToken,\n );\n continue;\n }\n\n tokenKeys.add(tokenKey);\n\n const parameters = [request.from];\n\n if (event.tokenStandard === SimulationTokenStandard.erc1155) {\n parameters.push(tokenId as Hex);\n }\n\n result.set(simulationToken, {\n from: request.from,\n to: event.contractAddress,\n data: new Interface(event.abi).encodeFunctionData(\n 'balanceOf',\n parameters,\n ) as Hex,\n });\n }\n\n return result;\n }, new Map<SimulationToken, SimulationRequestTransaction>());\n}\n\n/**\n * Parse a raw event log using known ABIs.\n * @param eventLog - The raw event log.\n * @param erc20 - The ERC-20 ABI interface.\n * @param erc721 - The ERC-721 ABI interface.\n * @param erc1155 - The ERC-1155 ABI interface.\n * @returns The parsed event log or undefined if it could not be parsed.\n */\nfunction parseLog(\n eventLog: SimulationResponseLog,\n erc20: Interface,\n erc721: Interface,\n erc1155: Interface,\n):\n | (LogDescription & { abi: ABI; standard: SimulationTokenStandard })\n | undefined {\n const abisByStandard = [\n {\n abi: abiERC20,\n contractInterface: erc20,\n standard: SimulationTokenStandard.erc20,\n },\n {\n abi: abiERC721,\n contractInterface: erc721,\n standard: SimulationTokenStandard.erc721,\n },\n {\n abi: abiERC1155,\n contractInterface: erc1155,\n standard: SimulationTokenStandard.erc1155,\n },\n ];\n\n for (const { abi, contractInterface, standard } of abisByStandard) {\n try {\n return {\n ...contractInterface.parseLog(eventLog),\n abi,\n standard,\n };\n } catch (e) {\n continue;\n }\n }\n\n return undefined;\n}\n\n/**\n * Extract all logs from a call trace tree.\n * @param call - The root call trace.\n * @returns An array of logs.\n */\nfunction extractLogs(\n call: SimulationResponseCallTrace,\n): SimulationResponseLog[] {\n /* istanbul ignore next */\n const logs = call.logs ?? [];\n\n /* istanbul ignore next */\n const nestedCalls = call.calls ?? [];\n\n return [\n ...logs,\n ...nestedCalls.map((nestedCall) => extractLogs(nestedCall)).flat(),\n ];\n}\n\n/**\n * Generate balance change data from previous and new balances.\n * @param previousBalance - The previous balance.\n * @param newBalance - The new balance.\n * @returns The balance change data or undefined if unchanged.\n */\nfunction getSimulationBalanceChange(\n previousBalance: Hex,\n newBalance: Hex,\n): SimulationBalanceChange | undefined {\n const differenceBN = hexToBN(newBalance).sub(hexToBN(previousBalance));\n const isDecrease = differenceBN.isNeg();\n const difference = toHex(differenceBN.abs());\n\n if (differenceBN.isZero()) {\n log('Balance change is zero');\n return undefined;\n }\n\n return {\n previousBalance,\n newBalance,\n difference,\n isDecrease,\n };\n}\n\n/**\n * Normalize a return value.\n * @param value - The return value to normalize.\n * @returns The normalized return value.\n */\nfunction normalizeReturnValue(value: Hex): Hex {\n return toHex(hexToBN(value));\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,75 @@
1
+ // src/utils/transaction-type.ts
2
+ import { Interface } from "@ethersproject/abi";
3
+ import { query } from "@metamask/controller-utils";
4
+ import { abiERC721, abiERC20, abiERC1155 } from "@metamask/metamask-eth-abis";
5
+ var ESTIMATE_GAS_ERROR = "eth_estimateGas rpc method error";
6
+ var ERC20Interface = new Interface(abiERC20);
7
+ var ERC721Interface = new Interface(abiERC721);
8
+ var ERC1155Interface = new Interface(abiERC1155);
9
+ async function determineTransactionType(txParams, ethQuery) {
10
+ const { data, to } = txParams;
11
+ if (data && !to) {
12
+ return { type: "contractDeployment" /* deployContract */, getCodeResponse: void 0 };
13
+ }
14
+ const { contractCode: getCodeResponse, isContractAddress } = await readAddressAsContract(ethQuery, to);
15
+ if (!isContractAddress) {
16
+ return { type: "simpleSend" /* simpleSend */, getCodeResponse };
17
+ }
18
+ const hasValue = Number(txParams.value ?? "0") !== 0;
19
+ const contractInteractionResult = {
20
+ type: "contractInteraction" /* contractInteraction */,
21
+ getCodeResponse
22
+ };
23
+ if (!data || hasValue) {
24
+ return contractInteractionResult;
25
+ }
26
+ const name = parseStandardTokenTransactionData(data)?.name;
27
+ if (!name) {
28
+ return contractInteractionResult;
29
+ }
30
+ const tokenMethodName = [
31
+ "approve" /* tokenMethodApprove */,
32
+ "setapprovalforall" /* tokenMethodSetApprovalForAll */,
33
+ "transfer" /* tokenMethodTransfer */,
34
+ "transferfrom" /* tokenMethodTransferFrom */,
35
+ "safetransferfrom" /* tokenMethodSafeTransferFrom */
36
+ ].find((methodName) => methodName.toLowerCase() === name.toLowerCase());
37
+ if (tokenMethodName) {
38
+ return { type: tokenMethodName, getCodeResponse };
39
+ }
40
+ return contractInteractionResult;
41
+ }
42
+ function parseStandardTokenTransactionData(data) {
43
+ if (!data) {
44
+ return void 0;
45
+ }
46
+ try {
47
+ return ERC20Interface.parseTransaction({ data });
48
+ } catch {
49
+ }
50
+ try {
51
+ return ERC721Interface.parseTransaction({ data });
52
+ } catch {
53
+ }
54
+ try {
55
+ return ERC1155Interface.parseTransaction({ data });
56
+ } catch {
57
+ }
58
+ return void 0;
59
+ }
60
+ async function readAddressAsContract(ethQuery, address) {
61
+ let contractCode;
62
+ try {
63
+ contractCode = await query(ethQuery, "getCode", [address]);
64
+ } catch (e) {
65
+ contractCode = null;
66
+ }
67
+ const isContractAddress = contractCode ? contractCode !== "0x" && contractCode !== "0x0" : false;
68
+ return { contractCode, isContractAddress };
69
+ }
70
+
71
+ export {
72
+ ESTIMATE_GAS_ERROR,
73
+ determineTransactionType
74
+ };
75
+ //# sourceMappingURL=chunk-JRBREX22.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/transaction-type.ts"],"sourcesContent":["import type { TransactionDescription } from '@ethersproject/abi';\nimport { Interface } from '@ethersproject/abi';\nimport { query } from '@metamask/controller-utils';\nimport type EthQuery from '@metamask/eth-query';\nimport { abiERC721, abiERC20, abiERC1155 } from '@metamask/metamask-eth-abis';\n\nimport type { InferTransactionTypeResult, TransactionParams } from '../types';\nimport { TransactionType } from '../types';\n\nexport const ESTIMATE_GAS_ERROR = 'eth_estimateGas rpc method error';\n\nconst ERC20Interface = new Interface(abiERC20);\nconst ERC721Interface = new Interface(abiERC721);\nconst ERC1155Interface = new Interface(abiERC1155);\n\n/**\n * Determines the type of the transaction by analyzing the txParams.\n * It will never return TRANSACTION_TYPE_CANCEL or TRANSACTION_TYPE_RETRY as these\n * represent specific events that we specify manually at transaction creation.\n *\n * @param txParams - Parameters for the transaction.\n * @param ethQuery - EthQuery instance.\n * @returns A object with the transaction type and the contract code response in Hex.\n */\nexport async function determineTransactionType(\n txParams: TransactionParams,\n ethQuery: EthQuery,\n): Promise<InferTransactionTypeResult> {\n const { data, to } = txParams;\n\n if (data && !to) {\n return { type: TransactionType.deployContract, getCodeResponse: undefined };\n }\n\n const { contractCode: getCodeResponse, isContractAddress } =\n await readAddressAsContract(ethQuery, to);\n\n if (!isContractAddress) {\n return { type: TransactionType.simpleSend, getCodeResponse };\n }\n\n const hasValue = Number(txParams.value ?? '0') !== 0;\n\n const contractInteractionResult = {\n type: TransactionType.contractInteraction,\n getCodeResponse,\n };\n\n if (!data || hasValue) {\n return contractInteractionResult;\n }\n\n const name = parseStandardTokenTransactionData(data)?.name;\n\n if (!name) {\n return contractInteractionResult;\n }\n\n const tokenMethodName = [\n TransactionType.tokenMethodApprove,\n TransactionType.tokenMethodSetApprovalForAll,\n TransactionType.tokenMethodTransfer,\n TransactionType.tokenMethodTransferFrom,\n TransactionType.tokenMethodSafeTransferFrom,\n ].find((methodName) => methodName.toLowerCase() === name.toLowerCase());\n\n if (tokenMethodName) {\n return { type: tokenMethodName, getCodeResponse };\n }\n\n return contractInteractionResult;\n}\n\n/**\n * Attempts to decode transaction data using ABIs for three different token standards: ERC20, ERC721, ERC1155.\n * The data will decode correctly if the transaction is an interaction with a contract that matches one of these\n * contract standards\n *\n * @param data - Encoded transaction data.\n * @returns A representation of an ethereum contract call.\n */\nfunction parseStandardTokenTransactionData(\n data?: string,\n): TransactionDescription | undefined {\n if (!data) {\n return undefined;\n }\n\n try {\n return ERC20Interface.parseTransaction({ data });\n } catch {\n // ignore and next try to parse with erc721 ABI\n }\n\n try {\n return ERC721Interface.parseTransaction({ data });\n } catch {\n // ignore and next try to parse with erc1155 ABI\n }\n\n try {\n return ERC1155Interface.parseTransaction({ data });\n } catch {\n // ignore and return undefined\n }\n\n return undefined;\n}\n\n/**\n * Reads an Ethereum address and determines if it is a contract address.\n *\n * @param ethQuery - The Ethereum query object used to interact with the Ethereum blockchain.\n * @param address - The Ethereum address.\n * @returns An object containing the contract code and a boolean indicating if it is a contract address.\n */\nasync function readAddressAsContract(\n ethQuery: EthQuery,\n address?: string,\n): Promise<{\n contractCode: string | null;\n isContractAddress: boolean;\n}> {\n let contractCode;\n try {\n contractCode = await query(ethQuery, 'getCode', [address]);\n } catch (e) {\n contractCode = null;\n }\n\n const isContractAddress = contractCode\n ? contractCode !== '0x' && contractCode !== '0x0'\n : false;\n return { contractCode, isContractAddress };\n}\n"],"mappings":";AACA,SAAS,iBAAiB;AAC1B,SAAS,aAAa;AAEtB,SAAS,WAAW,UAAU,kBAAkB;AAKzC,IAAM,qBAAqB;AAElC,IAAM,iBAAiB,IAAI,UAAU,QAAQ;AAC7C,IAAM,kBAAkB,IAAI,UAAU,SAAS;AAC/C,IAAM,mBAAmB,IAAI,UAAU,UAAU;AAWjD,eAAsB,yBACpB,UACA,UACqC;AACrC,QAAM,EAAE,MAAM,GAAG,IAAI;AAErB,MAAI,QAAQ,CAAC,IAAI;AACf,WAAO,EAAE,iDAAsC,iBAAiB,OAAU;AAAA,EAC5E;AAEA,QAAM,EAAE,cAAc,iBAAiB,kBAAkB,IACvD,MAAM,sBAAsB,UAAU,EAAE;AAE1C,MAAI,CAAC,mBAAmB;AACtB,WAAO,EAAE,qCAAkC,gBAAgB;AAAA,EAC7D;AAEA,QAAM,WAAW,OAAO,SAAS,SAAS,GAAG,MAAM;AAEnD,QAAM,4BAA4B;AAAA,IAChC;AAAA,IACA;AAAA,EACF;AAEA,MAAI,CAAC,QAAQ,UAAU;AACrB,WAAO;AAAA,EACT;AAEA,QAAM,OAAO,kCAAkC,IAAI,GAAG;AAEtD,MAAI,CAAC,MAAM;AACT,WAAO;AAAA,EACT;AAEA,QAAM,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMxB,EAAE,KAAK,CAAC,eAAe,WAAW,YAAY,MAAM,KAAK,YAAY,CAAC;AAEtE,MAAI,iBAAiB;AACnB,WAAO,EAAE,MAAM,iBAAiB,gBAAgB;AAAA,EAClD;AAEA,SAAO;AACT;AAUA,SAAS,kCACP,MACoC;AACpC,MAAI,CAAC,MAAM;AACT,WAAO;AAAA,EACT;AAEA,MAAI;AACF,WAAO,eAAe,iBAAiB,EAAE,KAAK,CAAC;AAAA,EACjD,QAAQ;AAAA,EAER;AAEA,MAAI;AACF,WAAO,gBAAgB,iBAAiB,EAAE,KAAK,CAAC;AAAA,EAClD,QAAQ;AAAA,EAER;AAEA,MAAI;AACF,WAAO,iBAAiB,iBAAiB,EAAE,KAAK,CAAC;AAAA,EACnD,QAAQ;AAAA,EAER;AAEA,SAAO;AACT;AASA,eAAe,sBACb,UACA,SAIC;AACD,MAAI;AACJ,MAAI;AACF,mBAAe,MAAM,MAAM,UAAU,WAAW,CAAC,OAAO,CAAC;AAAA,EAC3D,SAAS,GAAG;AACV,mBAAe;AAAA,EACjB;AAEA,QAAM,oBAAoB,eACtB,iBAAiB,QAAQ,iBAAiB,QAC1C;AACJ,SAAO,EAAE,cAAc,kBAAkB;AAC3C;","names":[]}