@metamask/transaction-controller 37.1.0 → 37.2.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 (32) hide show
  1. package/CHANGELOG.md +13 -1
  2. package/dist/TransactionController.cjs +1 -1
  3. package/dist/TransactionController.cjs.map +1 -1
  4. package/dist/TransactionController.d.cts +4 -1
  5. package/dist/TransactionController.d.cts.map +1 -1
  6. package/dist/TransactionController.d.mts +4 -1
  7. package/dist/TransactionController.d.mts.map +1 -1
  8. package/dist/TransactionController.mjs +1 -1
  9. package/dist/TransactionController.mjs.map +1 -1
  10. package/dist/gas-flows/LineaGasFeeFlow.cjs +0 -2
  11. package/dist/gas-flows/LineaGasFeeFlow.cjs.map +1 -1
  12. package/dist/gas-flows/LineaGasFeeFlow.d.cts.map +1 -1
  13. package/dist/gas-flows/LineaGasFeeFlow.d.mts.map +1 -1
  14. package/dist/gas-flows/LineaGasFeeFlow.mjs +0 -2
  15. package/dist/gas-flows/LineaGasFeeFlow.mjs.map +1 -1
  16. package/dist/helpers/EtherscanRemoteTransactionSource.cjs +12 -4
  17. package/dist/helpers/EtherscanRemoteTransactionSource.cjs.map +1 -1
  18. package/dist/helpers/EtherscanRemoteTransactionSource.d.cts +2 -1
  19. package/dist/helpers/EtherscanRemoteTransactionSource.d.cts.map +1 -1
  20. package/dist/helpers/EtherscanRemoteTransactionSource.d.mts +2 -1
  21. package/dist/helpers/EtherscanRemoteTransactionSource.d.mts.map +1 -1
  22. package/dist/helpers/EtherscanRemoteTransactionSource.mjs +12 -4
  23. package/dist/helpers/EtherscanRemoteTransactionSource.mjs.map +1 -1
  24. package/dist/utils/etherscan.cjs +9 -5
  25. package/dist/utils/etherscan.cjs.map +1 -1
  26. package/dist/utils/etherscan.d.cts +5 -2
  27. package/dist/utils/etherscan.d.cts.map +1 -1
  28. package/dist/utils/etherscan.d.mts +5 -2
  29. package/dist/utils/etherscan.d.mts.map +1 -1
  30. package/dist/utils/etherscan.mjs +9 -5
  31. package/dist/utils/etherscan.mjs.map +1 -1
  32. package/package.json +1 -1
@@ -76,8 +76,6 @@ _LineaGasFeeFlow_instances = new WeakSet(), _LineaGasFeeFlow_getLineaGasFees = a
76
76
  to: transactionMeta.txParams.to,
77
77
  value: transactionMeta.txParams.value,
78
78
  input: transactionMeta.txParams.data,
79
- // Required in request but no impact on response.
80
- gasPrice: '0x100000000',
81
79
  },
82
80
  ]);
83
81
  }, _LineaGasFeeFlow_getValuesFromMultipliers = function _LineaGasFeeFlow_getValuesFromMultipliers(value, multipliers) {
@@ -1 +1 @@
1
- {"version":3,"file":"LineaGasFeeFlow.cjs","sourceRoot":"","sources":["../../src/gas-flows/LineaGasFeeFlow.ts"],"names":[],"mappings":"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","sourcesContent":["import { ChainId, hexToBN, query, toHex } from '@metamask/controller-utils';\nimport type EthQuery from '@metamask/eth-query';\nimport { createModuleLogger, type Hex } from '@metamask/utils';\nimport type BN from 'bn.js';\n\nimport { projectLogger } from '../logger';\nimport type {\n GasFeeEstimates,\n GasFeeFlow,\n GasFeeFlowRequest,\n GasFeeFlowResponse,\n TransactionMeta,\n} from '../types';\nimport { GasFeeEstimateLevel, GasFeeEstimateType } from '../types';\nimport { DefaultGasFeeFlow } from './DefaultGasFeeFlow';\n\ntype LineaEstimateGasResponse = {\n baseFeePerGas: Hex;\n priorityFeePerGas: Hex;\n};\n\ntype FeesByLevel = {\n [key in GasFeeEstimateLevel]: BN;\n};\n\nconst log = createModuleLogger(projectLogger, 'linea-gas-fee-flow');\n\nconst LINEA_CHAIN_IDS: Hex[] = [\n ChainId['linea-mainnet'],\n ChainId['linea-goerli'],\n ChainId['linea-sepolia'],\n];\n\nconst BASE_FEE_MULTIPLIERS = {\n low: 1,\n medium: 1.35,\n high: 1.7,\n};\n\nconst PRIORITY_FEE_MULTIPLIERS = {\n low: 1,\n medium: 1.05,\n high: 1.1,\n};\n\n/**\n * Implementation of a gas fee flow specific to Linea networks that obtains gas fee estimates using:\n * - The `linea_estimateGas` RPC method to obtain the base fee and lowest priority fee.\n * - Static multipliers to increase the base and priority fees.\n */\nexport class LineaGasFeeFlow implements GasFeeFlow {\n matchesTransaction(transactionMeta: TransactionMeta): boolean {\n return LINEA_CHAIN_IDS.includes(transactionMeta.chainId);\n }\n\n async getGasFees(request: GasFeeFlowRequest): Promise<GasFeeFlowResponse> {\n try {\n return await this.#getLineaGasFees(request);\n } catch (error) {\n log('Using default flow as fallback due to error', error);\n return new DefaultGasFeeFlow().getGasFees(request);\n }\n }\n\n async #getLineaGasFees(\n request: GasFeeFlowRequest,\n ): Promise<GasFeeFlowResponse> {\n const { ethQuery, transactionMeta } = request;\n\n const lineaResponse = await this.#getLineaResponse(\n transactionMeta,\n ethQuery,\n );\n\n log('Received Linea response', lineaResponse);\n\n const baseFees = this.#getValuesFromMultipliers(\n lineaResponse.baseFeePerGas,\n BASE_FEE_MULTIPLIERS,\n );\n\n log('Generated base fees', this.#feesToString(baseFees));\n\n const priorityFees = this.#getValuesFromMultipliers(\n lineaResponse.priorityFeePerGas,\n PRIORITY_FEE_MULTIPLIERS,\n );\n\n log('Generated priority fees', this.#feesToString(priorityFees));\n\n const maxFees = this.#getMaxFees(baseFees, priorityFees);\n\n log('Generated max fees', this.#feesToString(maxFees));\n\n const estimates = Object.values(GasFeeEstimateLevel).reduce(\n (result, level) => ({\n ...result,\n [level]: {\n maxFeePerGas: toHex(maxFees[level]),\n maxPriorityFeePerGas: toHex(priorityFees[level]),\n },\n }),\n { type: GasFeeEstimateType.FeeMarket } as GasFeeEstimates,\n );\n\n return { estimates };\n }\n\n #getLineaResponse(\n transactionMeta: TransactionMeta,\n ethQuery: EthQuery,\n ): Promise<LineaEstimateGasResponse> {\n return query(ethQuery, 'linea_estimateGas', [\n {\n from: transactionMeta.txParams.from,\n to: transactionMeta.txParams.to,\n value: transactionMeta.txParams.value,\n input: transactionMeta.txParams.data,\n // Required in request but no impact on response.\n gasPrice: '0x100000000',\n },\n ]);\n }\n\n #getValuesFromMultipliers(\n value: Hex,\n multipliers: { low: number; medium: number; high: number },\n ): FeesByLevel {\n const base = hexToBN(value);\n const low = base.muln(multipliers.low);\n const medium = base.muln(multipliers.medium);\n const high = base.muln(multipliers.high);\n\n return {\n low,\n medium,\n high,\n };\n }\n\n #getMaxFees(\n baseFees: Record<GasFeeEstimateLevel, BN>,\n priorityFees: Record<GasFeeEstimateLevel, BN>,\n ): FeesByLevel {\n return {\n low: baseFees.low.add(priorityFees.low),\n medium: baseFees.medium.add(priorityFees.medium),\n high: baseFees.high.add(priorityFees.high),\n };\n }\n\n #feesToString(fees: FeesByLevel) {\n return Object.values(GasFeeEstimateLevel).map((level) =>\n fees[level].toString(10),\n );\n }\n}\n"]}
1
+ {"version":3,"file":"LineaGasFeeFlow.cjs","sourceRoot":"","sources":["../../src/gas-flows/LineaGasFeeFlow.ts"],"names":[],"mappings":"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","sourcesContent":["import { ChainId, hexToBN, query, toHex } from '@metamask/controller-utils';\nimport type EthQuery from '@metamask/eth-query';\nimport { createModuleLogger, type Hex } from '@metamask/utils';\nimport type BN from 'bn.js';\n\nimport { projectLogger } from '../logger';\nimport type {\n GasFeeEstimates,\n GasFeeFlow,\n GasFeeFlowRequest,\n GasFeeFlowResponse,\n TransactionMeta,\n} from '../types';\nimport { GasFeeEstimateLevel, GasFeeEstimateType } from '../types';\nimport { DefaultGasFeeFlow } from './DefaultGasFeeFlow';\n\ntype LineaEstimateGasResponse = {\n baseFeePerGas: Hex;\n priorityFeePerGas: Hex;\n};\n\ntype FeesByLevel = {\n [key in GasFeeEstimateLevel]: BN;\n};\n\nconst log = createModuleLogger(projectLogger, 'linea-gas-fee-flow');\n\nconst LINEA_CHAIN_IDS: Hex[] = [\n ChainId['linea-mainnet'],\n ChainId['linea-goerli'],\n ChainId['linea-sepolia'],\n];\n\nconst BASE_FEE_MULTIPLIERS = {\n low: 1,\n medium: 1.35,\n high: 1.7,\n};\n\nconst PRIORITY_FEE_MULTIPLIERS = {\n low: 1,\n medium: 1.05,\n high: 1.1,\n};\n\n/**\n * Implementation of a gas fee flow specific to Linea networks that obtains gas fee estimates using:\n * - The `linea_estimateGas` RPC method to obtain the base fee and lowest priority fee.\n * - Static multipliers to increase the base and priority fees.\n */\nexport class LineaGasFeeFlow implements GasFeeFlow {\n matchesTransaction(transactionMeta: TransactionMeta): boolean {\n return LINEA_CHAIN_IDS.includes(transactionMeta.chainId);\n }\n\n async getGasFees(request: GasFeeFlowRequest): Promise<GasFeeFlowResponse> {\n try {\n return await this.#getLineaGasFees(request);\n } catch (error) {\n log('Using default flow as fallback due to error', error);\n return new DefaultGasFeeFlow().getGasFees(request);\n }\n }\n\n async #getLineaGasFees(\n request: GasFeeFlowRequest,\n ): Promise<GasFeeFlowResponse> {\n const { ethQuery, transactionMeta } = request;\n\n const lineaResponse = await this.#getLineaResponse(\n transactionMeta,\n ethQuery,\n );\n\n log('Received Linea response', lineaResponse);\n\n const baseFees = this.#getValuesFromMultipliers(\n lineaResponse.baseFeePerGas,\n BASE_FEE_MULTIPLIERS,\n );\n\n log('Generated base fees', this.#feesToString(baseFees));\n\n const priorityFees = this.#getValuesFromMultipliers(\n lineaResponse.priorityFeePerGas,\n PRIORITY_FEE_MULTIPLIERS,\n );\n\n log('Generated priority fees', this.#feesToString(priorityFees));\n\n const maxFees = this.#getMaxFees(baseFees, priorityFees);\n\n log('Generated max fees', this.#feesToString(maxFees));\n\n const estimates = Object.values(GasFeeEstimateLevel).reduce(\n (result, level) => ({\n ...result,\n [level]: {\n maxFeePerGas: toHex(maxFees[level]),\n maxPriorityFeePerGas: toHex(priorityFees[level]),\n },\n }),\n { type: GasFeeEstimateType.FeeMarket } as GasFeeEstimates,\n );\n\n return { estimates };\n }\n\n #getLineaResponse(\n transactionMeta: TransactionMeta,\n ethQuery: EthQuery,\n ): Promise<LineaEstimateGasResponse> {\n return query(ethQuery, 'linea_estimateGas', [\n {\n from: transactionMeta.txParams.from,\n to: transactionMeta.txParams.to,\n value: transactionMeta.txParams.value,\n input: transactionMeta.txParams.data,\n },\n ]);\n }\n\n #getValuesFromMultipliers(\n value: Hex,\n multipliers: { low: number; medium: number; high: number },\n ): FeesByLevel {\n const base = hexToBN(value);\n const low = base.muln(multipliers.low);\n const medium = base.muln(multipliers.medium);\n const high = base.muln(multipliers.high);\n\n return {\n low,\n medium,\n high,\n };\n }\n\n #getMaxFees(\n baseFees: Record<GasFeeEstimateLevel, BN>,\n priorityFees: Record<GasFeeEstimateLevel, BN>,\n ): FeesByLevel {\n return {\n low: baseFees.low.add(priorityFees.low),\n medium: baseFees.medium.add(priorityFees.medium),\n high: baseFees.high.add(priorityFees.high),\n };\n }\n\n #feesToString(fees: FeesByLevel) {\n return Object.values(GasFeeEstimateLevel).map((level) =>\n fees[level].toString(10),\n );\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"LineaGasFeeFlow.d.cts","sourceRoot":"","sources":["../../src/gas-flows/LineaGasFeeFlow.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAEV,UAAU,EACV,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,EAChB,qBAAiB;AAiClB;;;;GAIG;AACH,qBAAa,eAAgB,YAAW,UAAU;;IAChD,kBAAkB,CAAC,eAAe,EAAE,eAAe,GAAG,OAAO;IAIvD,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;CAqG1E"}
1
+ {"version":3,"file":"LineaGasFeeFlow.d.cts","sourceRoot":"","sources":["../../src/gas-flows/LineaGasFeeFlow.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAEV,UAAU,EACV,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,EAChB,qBAAiB;AAiClB;;;;GAIG;AACH,qBAAa,eAAgB,YAAW,UAAU;;IAChD,kBAAkB,CAAC,eAAe,EAAE,eAAe,GAAG,OAAO;IAIvD,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;CAmG1E"}
@@ -1 +1 @@
1
- {"version":3,"file":"LineaGasFeeFlow.d.mts","sourceRoot":"","sources":["../../src/gas-flows/LineaGasFeeFlow.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAEV,UAAU,EACV,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,EAChB,qBAAiB;AAiClB;;;;GAIG;AACH,qBAAa,eAAgB,YAAW,UAAU;;IAChD,kBAAkB,CAAC,eAAe,EAAE,eAAe,GAAG,OAAO;IAIvD,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;CAqG1E"}
1
+ {"version":3,"file":"LineaGasFeeFlow.d.mts","sourceRoot":"","sources":["../../src/gas-flows/LineaGasFeeFlow.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAEV,UAAU,EACV,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,EAChB,qBAAiB;AAiClB;;;;GAIG;AACH,qBAAa,eAAgB,YAAW,UAAU;;IAChD,kBAAkB,CAAC,eAAe,EAAE,eAAe,GAAG,OAAO;IAIvD,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;CAmG1E"}
@@ -72,8 +72,6 @@ _LineaGasFeeFlow_instances = new WeakSet(), _LineaGasFeeFlow_getLineaGasFees = a
72
72
  to: transactionMeta.txParams.to,
73
73
  value: transactionMeta.txParams.value,
74
74
  input: transactionMeta.txParams.data,
75
- // Required in request but no impact on response.
76
- gasPrice: '0x100000000',
77
75
  },
78
76
  ]);
79
77
  }, _LineaGasFeeFlow_getValuesFromMultipliers = function _LineaGasFeeFlow_getValuesFromMultipliers(value, multipliers) {
@@ -1 +1 @@
1
- {"version":3,"file":"LineaGasFeeFlow.mjs","sourceRoot":"","sources":["../../src/gas-flows/LineaGasFeeFlow.ts"],"names":[],"mappings":"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","sourcesContent":["import { ChainId, hexToBN, query, toHex } from '@metamask/controller-utils';\nimport type EthQuery from '@metamask/eth-query';\nimport { createModuleLogger, type Hex } from '@metamask/utils';\nimport type BN from 'bn.js';\n\nimport { projectLogger } from '../logger';\nimport type {\n GasFeeEstimates,\n GasFeeFlow,\n GasFeeFlowRequest,\n GasFeeFlowResponse,\n TransactionMeta,\n} from '../types';\nimport { GasFeeEstimateLevel, GasFeeEstimateType } from '../types';\nimport { DefaultGasFeeFlow } from './DefaultGasFeeFlow';\n\ntype LineaEstimateGasResponse = {\n baseFeePerGas: Hex;\n priorityFeePerGas: Hex;\n};\n\ntype FeesByLevel = {\n [key in GasFeeEstimateLevel]: BN;\n};\n\nconst log = createModuleLogger(projectLogger, 'linea-gas-fee-flow');\n\nconst LINEA_CHAIN_IDS: Hex[] = [\n ChainId['linea-mainnet'],\n ChainId['linea-goerli'],\n ChainId['linea-sepolia'],\n];\n\nconst BASE_FEE_MULTIPLIERS = {\n low: 1,\n medium: 1.35,\n high: 1.7,\n};\n\nconst PRIORITY_FEE_MULTIPLIERS = {\n low: 1,\n medium: 1.05,\n high: 1.1,\n};\n\n/**\n * Implementation of a gas fee flow specific to Linea networks that obtains gas fee estimates using:\n * - The `linea_estimateGas` RPC method to obtain the base fee and lowest priority fee.\n * - Static multipliers to increase the base and priority fees.\n */\nexport class LineaGasFeeFlow implements GasFeeFlow {\n matchesTransaction(transactionMeta: TransactionMeta): boolean {\n return LINEA_CHAIN_IDS.includes(transactionMeta.chainId);\n }\n\n async getGasFees(request: GasFeeFlowRequest): Promise<GasFeeFlowResponse> {\n try {\n return await this.#getLineaGasFees(request);\n } catch (error) {\n log('Using default flow as fallback due to error', error);\n return new DefaultGasFeeFlow().getGasFees(request);\n }\n }\n\n async #getLineaGasFees(\n request: GasFeeFlowRequest,\n ): Promise<GasFeeFlowResponse> {\n const { ethQuery, transactionMeta } = request;\n\n const lineaResponse = await this.#getLineaResponse(\n transactionMeta,\n ethQuery,\n );\n\n log('Received Linea response', lineaResponse);\n\n const baseFees = this.#getValuesFromMultipliers(\n lineaResponse.baseFeePerGas,\n BASE_FEE_MULTIPLIERS,\n );\n\n log('Generated base fees', this.#feesToString(baseFees));\n\n const priorityFees = this.#getValuesFromMultipliers(\n lineaResponse.priorityFeePerGas,\n PRIORITY_FEE_MULTIPLIERS,\n );\n\n log('Generated priority fees', this.#feesToString(priorityFees));\n\n const maxFees = this.#getMaxFees(baseFees, priorityFees);\n\n log('Generated max fees', this.#feesToString(maxFees));\n\n const estimates = Object.values(GasFeeEstimateLevel).reduce(\n (result, level) => ({\n ...result,\n [level]: {\n maxFeePerGas: toHex(maxFees[level]),\n maxPriorityFeePerGas: toHex(priorityFees[level]),\n },\n }),\n { type: GasFeeEstimateType.FeeMarket } as GasFeeEstimates,\n );\n\n return { estimates };\n }\n\n #getLineaResponse(\n transactionMeta: TransactionMeta,\n ethQuery: EthQuery,\n ): Promise<LineaEstimateGasResponse> {\n return query(ethQuery, 'linea_estimateGas', [\n {\n from: transactionMeta.txParams.from,\n to: transactionMeta.txParams.to,\n value: transactionMeta.txParams.value,\n input: transactionMeta.txParams.data,\n // Required in request but no impact on response.\n gasPrice: '0x100000000',\n },\n ]);\n }\n\n #getValuesFromMultipliers(\n value: Hex,\n multipliers: { low: number; medium: number; high: number },\n ): FeesByLevel {\n const base = hexToBN(value);\n const low = base.muln(multipliers.low);\n const medium = base.muln(multipliers.medium);\n const high = base.muln(multipliers.high);\n\n return {\n low,\n medium,\n high,\n };\n }\n\n #getMaxFees(\n baseFees: Record<GasFeeEstimateLevel, BN>,\n priorityFees: Record<GasFeeEstimateLevel, BN>,\n ): FeesByLevel {\n return {\n low: baseFees.low.add(priorityFees.low),\n medium: baseFees.medium.add(priorityFees.medium),\n high: baseFees.high.add(priorityFees.high),\n };\n }\n\n #feesToString(fees: FeesByLevel) {\n return Object.values(GasFeeEstimateLevel).map((level) =>\n fees[level].toString(10),\n );\n }\n}\n"]}
1
+ {"version":3,"file":"LineaGasFeeFlow.mjs","sourceRoot":"","sources":["../../src/gas-flows/LineaGasFeeFlow.ts"],"names":[],"mappings":"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","sourcesContent":["import { ChainId, hexToBN, query, toHex } from '@metamask/controller-utils';\nimport type EthQuery from '@metamask/eth-query';\nimport { createModuleLogger, type Hex } from '@metamask/utils';\nimport type BN from 'bn.js';\n\nimport { projectLogger } from '../logger';\nimport type {\n GasFeeEstimates,\n GasFeeFlow,\n GasFeeFlowRequest,\n GasFeeFlowResponse,\n TransactionMeta,\n} from '../types';\nimport { GasFeeEstimateLevel, GasFeeEstimateType } from '../types';\nimport { DefaultGasFeeFlow } from './DefaultGasFeeFlow';\n\ntype LineaEstimateGasResponse = {\n baseFeePerGas: Hex;\n priorityFeePerGas: Hex;\n};\n\ntype FeesByLevel = {\n [key in GasFeeEstimateLevel]: BN;\n};\n\nconst log = createModuleLogger(projectLogger, 'linea-gas-fee-flow');\n\nconst LINEA_CHAIN_IDS: Hex[] = [\n ChainId['linea-mainnet'],\n ChainId['linea-goerli'],\n ChainId['linea-sepolia'],\n];\n\nconst BASE_FEE_MULTIPLIERS = {\n low: 1,\n medium: 1.35,\n high: 1.7,\n};\n\nconst PRIORITY_FEE_MULTIPLIERS = {\n low: 1,\n medium: 1.05,\n high: 1.1,\n};\n\n/**\n * Implementation of a gas fee flow specific to Linea networks that obtains gas fee estimates using:\n * - The `linea_estimateGas` RPC method to obtain the base fee and lowest priority fee.\n * - Static multipliers to increase the base and priority fees.\n */\nexport class LineaGasFeeFlow implements GasFeeFlow {\n matchesTransaction(transactionMeta: TransactionMeta): boolean {\n return LINEA_CHAIN_IDS.includes(transactionMeta.chainId);\n }\n\n async getGasFees(request: GasFeeFlowRequest): Promise<GasFeeFlowResponse> {\n try {\n return await this.#getLineaGasFees(request);\n } catch (error) {\n log('Using default flow as fallback due to error', error);\n return new DefaultGasFeeFlow().getGasFees(request);\n }\n }\n\n async #getLineaGasFees(\n request: GasFeeFlowRequest,\n ): Promise<GasFeeFlowResponse> {\n const { ethQuery, transactionMeta } = request;\n\n const lineaResponse = await this.#getLineaResponse(\n transactionMeta,\n ethQuery,\n );\n\n log('Received Linea response', lineaResponse);\n\n const baseFees = this.#getValuesFromMultipliers(\n lineaResponse.baseFeePerGas,\n BASE_FEE_MULTIPLIERS,\n );\n\n log('Generated base fees', this.#feesToString(baseFees));\n\n const priorityFees = this.#getValuesFromMultipliers(\n lineaResponse.priorityFeePerGas,\n PRIORITY_FEE_MULTIPLIERS,\n );\n\n log('Generated priority fees', this.#feesToString(priorityFees));\n\n const maxFees = this.#getMaxFees(baseFees, priorityFees);\n\n log('Generated max fees', this.#feesToString(maxFees));\n\n const estimates = Object.values(GasFeeEstimateLevel).reduce(\n (result, level) => ({\n ...result,\n [level]: {\n maxFeePerGas: toHex(maxFees[level]),\n maxPriorityFeePerGas: toHex(priorityFees[level]),\n },\n }),\n { type: GasFeeEstimateType.FeeMarket } as GasFeeEstimates,\n );\n\n return { estimates };\n }\n\n #getLineaResponse(\n transactionMeta: TransactionMeta,\n ethQuery: EthQuery,\n ): Promise<LineaEstimateGasResponse> {\n return query(ethQuery, 'linea_estimateGas', [\n {\n from: transactionMeta.txParams.from,\n to: transactionMeta.txParams.to,\n value: transactionMeta.txParams.value,\n input: transactionMeta.txParams.data,\n },\n ]);\n }\n\n #getValuesFromMultipliers(\n value: Hex,\n multipliers: { low: number; medium: number; high: number },\n ): FeesByLevel {\n const base = hexToBN(value);\n const low = base.muln(multipliers.low);\n const medium = base.muln(multipliers.medium);\n const high = base.muln(multipliers.high);\n\n return {\n low,\n medium,\n high,\n };\n }\n\n #getMaxFees(\n baseFees: Record<GasFeeEstimateLevel, BN>,\n priorityFees: Record<GasFeeEstimateLevel, BN>,\n ): FeesByLevel {\n return {\n low: baseFees.low.add(priorityFees.low),\n medium: baseFees.medium.add(priorityFees.medium),\n high: baseFees.high.add(priorityFees.high),\n };\n }\n\n #feesToString(fees: FeesByLevel) {\n return Object.values(GasFeeEstimateLevel).map((level) =>\n fees[level].toString(10),\n );\n }\n}\n"]}
@@ -13,7 +13,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
13
13
  var __importDefault = (this && this.__importDefault) || function (mod) {
14
14
  return (mod && mod.__esModule) ? mod : { "default": mod };
15
15
  };
16
- var _EtherscanRemoteTransactionSource_instances, _EtherscanRemoteTransactionSource_includeTokenTransfers, _EtherscanRemoteTransactionSource_isTokenRequestPending, _EtherscanRemoteTransactionSource_mutex, _EtherscanRemoteTransactionSource_releaseLockAfterInterval, _EtherscanRemoteTransactionSource_fetchNormalTransactions, _EtherscanRemoteTransactionSource_fetchTokenTransactions, _EtherscanRemoteTransactionSource_getResponseTransactions, _EtherscanRemoteTransactionSource_normalizeTransaction, _EtherscanRemoteTransactionSource_normalizeTokenTransaction, _EtherscanRemoteTransactionSource_normalizeTransactionBase;
16
+ var _EtherscanRemoteTransactionSource_instances, _EtherscanRemoteTransactionSource_apiKeysByChainId, _EtherscanRemoteTransactionSource_includeTokenTransfers, _EtherscanRemoteTransactionSource_isTokenRequestPending, _EtherscanRemoteTransactionSource_mutex, _EtherscanRemoteTransactionSource_releaseLockAfterInterval, _EtherscanRemoteTransactionSource_fetchNormalTransactions, _EtherscanRemoteTransactionSource_fetchTokenTransactions, _EtherscanRemoteTransactionSource_getResponseTransactions, _EtherscanRemoteTransactionSource_normalizeTransaction, _EtherscanRemoteTransactionSource_normalizeTokenTransaction, _EtherscanRemoteTransactionSource_normalizeTransactionBase;
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
18
  exports.EtherscanRemoteTransactionSource = void 0;
19
19
  const controller_utils_1 = require("@metamask/controller-utils");
@@ -29,8 +29,9 @@ const ETHERSCAN_RATE_LIMIT_INTERVAL = 5000;
29
29
  * A RemoteTransactionSource that fetches transaction data from Etherscan.
30
30
  */
31
31
  class EtherscanRemoteTransactionSource {
32
- constructor({ includeTokenTransfers, } = {}) {
32
+ constructor({ apiKeysByChainId, includeTokenTransfers, } = {}) {
33
33
  _EtherscanRemoteTransactionSource_instances.add(this);
34
+ _EtherscanRemoteTransactionSource_apiKeysByChainId.set(this, void 0);
34
35
  _EtherscanRemoteTransactionSource_includeTokenTransfers.set(this, void 0);
35
36
  _EtherscanRemoteTransactionSource_isTokenRequestPending.set(this, void 0);
36
37
  _EtherscanRemoteTransactionSource_mutex.set(this, new async_mutex_1.Mutex());
@@ -44,6 +45,7 @@ class EtherscanRemoteTransactionSource {
44
45
  const etherscanTransactions = await (0, etherscan_1.fetchEtherscanTokenTransactions)(etherscanRequest);
45
46
  return __classPrivateFieldGet(this, _EtherscanRemoteTransactionSource_instances, "m", _EtherscanRemoteTransactionSource_getResponseTransactions).call(this, etherscanTransactions).map((tx) => __classPrivateFieldGet(this, _EtherscanRemoteTransactionSource_instances, "m", _EtherscanRemoteTransactionSource_normalizeTokenTransaction).call(this, tx, currentChainId));
46
47
  });
48
+ __classPrivateFieldSet(this, _EtherscanRemoteTransactionSource_apiKeysByChainId, apiKeysByChainId, "f");
47
49
  __classPrivateFieldSet(this, _EtherscanRemoteTransactionSource_includeTokenTransfers, includeTokenTransfers ?? true, "f");
48
50
  __classPrivateFieldSet(this, _EtherscanRemoteTransactionSource_isTokenRequestPending, false, "f");
49
51
  }
@@ -56,9 +58,15 @@ class EtherscanRemoteTransactionSource {
56
58
  async fetchTransactions(request) {
57
59
  const releaseLock = await __classPrivateFieldGet(this, _EtherscanRemoteTransactionSource_mutex, "f").acquire();
58
60
  const acquiredTime = Date.now();
61
+ const { currentChainId: chainId } = request;
62
+ const apiKey = __classPrivateFieldGet(this, _EtherscanRemoteTransactionSource_apiKeysByChainId, "f")?.[chainId];
63
+ if (apiKey) {
64
+ (0, logger_1.incomingTransactionsLogger)('Etherscan API key found for chain', chainId);
65
+ }
59
66
  const etherscanRequest = {
60
67
  ...request,
61
- chainId: request.currentChainId,
68
+ apiKey,
69
+ chainId,
62
70
  };
63
71
  try {
64
72
  const transactions = __classPrivateFieldGet(this, _EtherscanRemoteTransactionSource_isTokenRequestPending, "f")
@@ -75,7 +83,7 @@ class EtherscanRemoteTransactionSource {
75
83
  }
76
84
  }
77
85
  exports.EtherscanRemoteTransactionSource = EtherscanRemoteTransactionSource;
78
- _EtherscanRemoteTransactionSource_includeTokenTransfers = new WeakMap(), _EtherscanRemoteTransactionSource_isTokenRequestPending = new WeakMap(), _EtherscanRemoteTransactionSource_mutex = new WeakMap(), _EtherscanRemoteTransactionSource_fetchNormalTransactions = new WeakMap(), _EtherscanRemoteTransactionSource_fetchTokenTransactions = new WeakMap(), _EtherscanRemoteTransactionSource_instances = new WeakSet(), _EtherscanRemoteTransactionSource_releaseLockAfterInterval = function _EtherscanRemoteTransactionSource_releaseLockAfterInterval(acquireTime, releaseLock) {
86
+ _EtherscanRemoteTransactionSource_apiKeysByChainId = new WeakMap(), _EtherscanRemoteTransactionSource_includeTokenTransfers = new WeakMap(), _EtherscanRemoteTransactionSource_isTokenRequestPending = new WeakMap(), _EtherscanRemoteTransactionSource_mutex = new WeakMap(), _EtherscanRemoteTransactionSource_fetchNormalTransactions = new WeakMap(), _EtherscanRemoteTransactionSource_fetchTokenTransactions = new WeakMap(), _EtherscanRemoteTransactionSource_instances = new WeakSet(), _EtherscanRemoteTransactionSource_releaseLockAfterInterval = function _EtherscanRemoteTransactionSource_releaseLockAfterInterval(acquireTime, releaseLock) {
79
87
  const elapsedTime = Date.now() - acquireTime;
80
88
  const remainingTime = Math.max(0, ETHERSCAN_RATE_LIMIT_INTERVAL - elapsedTime);
81
89
  // Wait for the remaining time if it hasn't been 5 seconds yet
@@ -1 +1 @@
1
- {"version":3,"file":"EtherscanRemoteTransactionSource.cjs","sourceRoot":"","sources":["../../src/helpers/EtherscanRemoteTransactionSource.ts"],"names":[],"mappings":"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","sourcesContent":["import { BNToHex } from '@metamask/controller-utils';\nimport type { Hex } from '@metamask/utils';\nimport { Mutex } from 'async-mutex';\nimport BN from 'bn.js';\nimport { v1 as random } from 'uuid';\n\nimport { ETHERSCAN_SUPPORTED_NETWORKS } from '../constants';\nimport { incomingTransactionsLogger as log } from '../logger';\nimport type {\n RemoteTransactionSource,\n RemoteTransactionSourceRequest,\n TransactionMeta,\n} from '../types';\nimport { TransactionStatus, TransactionType } from '../types';\nimport {\n fetchEtherscanTokenTransactions,\n fetchEtherscanTransactions,\n} from '../utils/etherscan';\nimport type {\n EtherscanTokenTransactionMeta,\n EtherscanTransactionMeta,\n EtherscanTransactionMetaBase,\n EtherscanTransactionRequest,\n EtherscanTransactionResponse,\n} from '../utils/etherscan';\n\nconst ETHERSCAN_RATE_LIMIT_INTERVAL = 5000;\n/**\n * A RemoteTransactionSource that fetches transaction data from Etherscan.\n */\nexport class EtherscanRemoteTransactionSource\n implements RemoteTransactionSource\n{\n #includeTokenTransfers: boolean;\n\n #isTokenRequestPending: boolean;\n\n #mutex = new Mutex();\n\n constructor({\n includeTokenTransfers,\n }: { includeTokenTransfers?: boolean } = {}) {\n this.#includeTokenTransfers = includeTokenTransfers ?? true;\n this.#isTokenRequestPending = false;\n }\n\n isSupportedNetwork(chainId: Hex): boolean {\n return Object.keys(ETHERSCAN_SUPPORTED_NETWORKS).includes(chainId);\n }\n\n getLastBlockVariations(): string[] {\n return [this.#isTokenRequestPending ? 'token' : 'normal'];\n }\n\n async fetchTransactions(\n request: RemoteTransactionSourceRequest,\n ): Promise<TransactionMeta[]> {\n const releaseLock = await this.#mutex.acquire();\n const acquiredTime = Date.now();\n\n const etherscanRequest: EtherscanTransactionRequest = {\n ...request,\n chainId: request.currentChainId,\n };\n\n try {\n const transactions = this.#isTokenRequestPending\n ? await this.#fetchTokenTransactions(request, etherscanRequest)\n : await this.#fetchNormalTransactions(request, etherscanRequest);\n\n if (this.#includeTokenTransfers) {\n this.#isTokenRequestPending = !this.#isTokenRequestPending;\n }\n\n return transactions;\n } finally {\n this.#releaseLockAfterInterval(acquiredTime, releaseLock);\n }\n }\n\n #releaseLockAfterInterval(acquireTime: number, releaseLock: () => void) {\n const elapsedTime = Date.now() - acquireTime;\n const remainingTime = Math.max(\n 0,\n ETHERSCAN_RATE_LIMIT_INTERVAL - elapsedTime,\n );\n // Wait for the remaining time if it hasn't been 5 seconds yet\n if (remainingTime > 0) {\n setTimeout(releaseLock, remainingTime);\n } else {\n releaseLock();\n }\n }\n\n #fetchNormalTransactions = async (\n request: RemoteTransactionSourceRequest,\n etherscanRequest: EtherscanTransactionRequest,\n ) => {\n const { currentChainId } = request;\n\n const etherscanTransactions = await fetchEtherscanTransactions(\n etherscanRequest,\n );\n\n return this.#getResponseTransactions(etherscanTransactions).map((tx) =>\n this.#normalizeTransaction(tx, currentChainId),\n );\n };\n\n #fetchTokenTransactions = async (\n request: RemoteTransactionSourceRequest,\n etherscanRequest: EtherscanTransactionRequest,\n ) => {\n const { currentChainId } = request;\n\n const etherscanTransactions = await fetchEtherscanTokenTransactions(\n etherscanRequest,\n );\n\n return this.#getResponseTransactions(etherscanTransactions).map((tx) =>\n this.#normalizeTokenTransaction(tx, currentChainId),\n );\n };\n\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n #getResponseTransactions<T extends EtherscanTransactionMetaBase>(\n response: EtherscanTransactionResponse<T>,\n ): T[] {\n let result = response.result as T[];\n\n if (response.status === '0') {\n result = [];\n\n if (response.result.length) {\n log('Ignored Etherscan request error', {\n message: response.result,\n type: this.#isTokenRequestPending ? 'token' : 'normal',\n });\n }\n }\n\n return result;\n }\n\n #normalizeTransaction(\n txMeta: EtherscanTransactionMeta,\n currentChainId: Hex,\n ): TransactionMeta {\n const base = this.#normalizeTransactionBase(txMeta, currentChainId);\n\n return {\n ...base,\n txParams: {\n ...base.txParams,\n data: txMeta.input,\n },\n ...(txMeta.isError === '0'\n ? { status: TransactionStatus.confirmed }\n : {\n error: new Error('Transaction failed'),\n status: TransactionStatus.failed,\n }),\n };\n }\n\n #normalizeTokenTransaction(\n txMeta: EtherscanTokenTransactionMeta,\n currentChainId: Hex,\n ): TransactionMeta {\n const base = this.#normalizeTransactionBase(txMeta, currentChainId);\n\n return {\n ...base,\n isTransfer: true,\n transferInformation: {\n contractAddress: txMeta.contractAddress,\n decimals: Number(txMeta.tokenDecimal),\n symbol: txMeta.tokenSymbol,\n },\n };\n }\n\n #normalizeTransactionBase(\n txMeta: EtherscanTransactionMetaBase,\n currentChainId: Hex,\n ): TransactionMeta {\n const time = parseInt(txMeta.timeStamp, 10) * 1000;\n\n return {\n blockNumber: txMeta.blockNumber,\n chainId: currentChainId,\n hash: txMeta.hash,\n id: random({ msecs: time }),\n status: TransactionStatus.confirmed,\n time,\n txParams: {\n chainId: currentChainId,\n from: txMeta.from,\n gas: BNToHex(new BN(txMeta.gas)),\n gasPrice: BNToHex(new BN(txMeta.gasPrice)),\n gasUsed: BNToHex(new BN(txMeta.gasUsed)),\n nonce: BNToHex(new BN(txMeta.nonce)),\n to: txMeta.to,\n value: BNToHex(new BN(txMeta.value)),\n },\n type: TransactionType.incoming,\n verifiedOnBlockchain: false,\n };\n }\n}\n"]}
1
+ {"version":3,"file":"EtherscanRemoteTransactionSource.cjs","sourceRoot":"","sources":["../../src/helpers/EtherscanRemoteTransactionSource.ts"],"names":[],"mappings":"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","sourcesContent":["import { BNToHex } from '@metamask/controller-utils';\nimport type { Hex } from '@metamask/utils';\nimport { Mutex } from 'async-mutex';\nimport BN from 'bn.js';\nimport { v1 as random } from 'uuid';\n\nimport { ETHERSCAN_SUPPORTED_NETWORKS } from '../constants';\nimport { incomingTransactionsLogger as log } from '../logger';\nimport type {\n RemoteTransactionSource,\n RemoteTransactionSourceRequest,\n TransactionMeta,\n} from '../types';\nimport { TransactionStatus, TransactionType } from '../types';\nimport {\n fetchEtherscanTokenTransactions,\n fetchEtherscanTransactions,\n} from '../utils/etherscan';\nimport type {\n EtherscanTokenTransactionMeta,\n EtherscanTransactionMeta,\n EtherscanTransactionMetaBase,\n EtherscanTransactionRequest,\n EtherscanTransactionResponse,\n} from '../utils/etherscan';\n\nconst ETHERSCAN_RATE_LIMIT_INTERVAL = 5000;\n\n/**\n * A RemoteTransactionSource that fetches transaction data from Etherscan.\n */\nexport class EtherscanRemoteTransactionSource\n implements RemoteTransactionSource\n{\n #apiKeysByChainId?: Record<Hex, string>;\n\n #includeTokenTransfers: boolean;\n\n #isTokenRequestPending: boolean;\n\n #mutex = new Mutex();\n\n constructor({\n apiKeysByChainId,\n includeTokenTransfers,\n }: {\n apiKeysByChainId?: Record<Hex, string>;\n includeTokenTransfers?: boolean;\n } = {}) {\n this.#apiKeysByChainId = apiKeysByChainId;\n this.#includeTokenTransfers = includeTokenTransfers ?? true;\n this.#isTokenRequestPending = false;\n }\n\n isSupportedNetwork(chainId: Hex): boolean {\n return Object.keys(ETHERSCAN_SUPPORTED_NETWORKS).includes(chainId);\n }\n\n getLastBlockVariations(): string[] {\n return [this.#isTokenRequestPending ? 'token' : 'normal'];\n }\n\n async fetchTransactions(\n request: RemoteTransactionSourceRequest,\n ): Promise<TransactionMeta[]> {\n const releaseLock = await this.#mutex.acquire();\n const acquiredTime = Date.now();\n const { currentChainId: chainId } = request;\n const apiKey = this.#apiKeysByChainId?.[chainId];\n\n if (apiKey) {\n log('Etherscan API key found for chain', chainId);\n }\n\n const etherscanRequest: EtherscanTransactionRequest = {\n ...request,\n apiKey,\n chainId,\n };\n\n try {\n const transactions = this.#isTokenRequestPending\n ? await this.#fetchTokenTransactions(request, etherscanRequest)\n : await this.#fetchNormalTransactions(request, etherscanRequest);\n\n if (this.#includeTokenTransfers) {\n this.#isTokenRequestPending = !this.#isTokenRequestPending;\n }\n\n return transactions;\n } finally {\n this.#releaseLockAfterInterval(acquiredTime, releaseLock);\n }\n }\n\n #releaseLockAfterInterval(acquireTime: number, releaseLock: () => void) {\n const elapsedTime = Date.now() - acquireTime;\n const remainingTime = Math.max(\n 0,\n ETHERSCAN_RATE_LIMIT_INTERVAL - elapsedTime,\n );\n // Wait for the remaining time if it hasn't been 5 seconds yet\n if (remainingTime > 0) {\n setTimeout(releaseLock, remainingTime);\n } else {\n releaseLock();\n }\n }\n\n #fetchNormalTransactions = async (\n request: RemoteTransactionSourceRequest,\n etherscanRequest: EtherscanTransactionRequest,\n ) => {\n const { currentChainId } = request;\n\n const etherscanTransactions = await fetchEtherscanTransactions(\n etherscanRequest,\n );\n\n return this.#getResponseTransactions(etherscanTransactions).map((tx) =>\n this.#normalizeTransaction(tx, currentChainId),\n );\n };\n\n #fetchTokenTransactions = async (\n request: RemoteTransactionSourceRequest,\n etherscanRequest: EtherscanTransactionRequest,\n ) => {\n const { currentChainId } = request;\n\n const etherscanTransactions = await fetchEtherscanTokenTransactions(\n etherscanRequest,\n );\n\n return this.#getResponseTransactions(etherscanTransactions).map((tx) =>\n this.#normalizeTokenTransaction(tx, currentChainId),\n );\n };\n\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n #getResponseTransactions<T extends EtherscanTransactionMetaBase>(\n response: EtherscanTransactionResponse<T>,\n ): T[] {\n let result = response.result as T[];\n\n if (response.status === '0') {\n result = [];\n\n if (response.result.length) {\n log('Ignored Etherscan request error', {\n message: response.result,\n type: this.#isTokenRequestPending ? 'token' : 'normal',\n });\n }\n }\n\n return result;\n }\n\n #normalizeTransaction(\n txMeta: EtherscanTransactionMeta,\n currentChainId: Hex,\n ): TransactionMeta {\n const base = this.#normalizeTransactionBase(txMeta, currentChainId);\n\n return {\n ...base,\n txParams: {\n ...base.txParams,\n data: txMeta.input,\n },\n ...(txMeta.isError === '0'\n ? { status: TransactionStatus.confirmed }\n : {\n error: new Error('Transaction failed'),\n status: TransactionStatus.failed,\n }),\n };\n }\n\n #normalizeTokenTransaction(\n txMeta: EtherscanTokenTransactionMeta,\n currentChainId: Hex,\n ): TransactionMeta {\n const base = this.#normalizeTransactionBase(txMeta, currentChainId);\n\n return {\n ...base,\n isTransfer: true,\n transferInformation: {\n contractAddress: txMeta.contractAddress,\n decimals: Number(txMeta.tokenDecimal),\n symbol: txMeta.tokenSymbol,\n },\n };\n }\n\n #normalizeTransactionBase(\n txMeta: EtherscanTransactionMetaBase,\n currentChainId: Hex,\n ): TransactionMeta {\n const time = parseInt(txMeta.timeStamp, 10) * 1000;\n\n return {\n blockNumber: txMeta.blockNumber,\n chainId: currentChainId,\n hash: txMeta.hash,\n id: random({ msecs: time }),\n status: TransactionStatus.confirmed,\n time,\n txParams: {\n chainId: currentChainId,\n from: txMeta.from,\n gas: BNToHex(new BN(txMeta.gas)),\n gasPrice: BNToHex(new BN(txMeta.gasPrice)),\n gasUsed: BNToHex(new BN(txMeta.gasUsed)),\n nonce: BNToHex(new BN(txMeta.nonce)),\n to: txMeta.to,\n value: BNToHex(new BN(txMeta.value)),\n },\n type: TransactionType.incoming,\n verifiedOnBlockchain: false,\n };\n }\n}\n"]}
@@ -5,7 +5,8 @@ import type { RemoteTransactionSource, RemoteTransactionSourceRequest, Transacti
5
5
  */
6
6
  export declare class EtherscanRemoteTransactionSource implements RemoteTransactionSource {
7
7
  #private;
8
- constructor({ includeTokenTransfers, }?: {
8
+ constructor({ apiKeysByChainId, includeTokenTransfers, }?: {
9
+ apiKeysByChainId?: Record<Hex, string>;
9
10
  includeTokenTransfers?: boolean;
10
11
  });
11
12
  isSupportedNetwork(chainId: Hex): boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"EtherscanRemoteTransactionSource.d.cts","sourceRoot":"","sources":["../../src/helpers/EtherscanRemoteTransactionSource.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAO3C,OAAO,KAAK,EACV,uBAAuB,EACvB,8BAA8B,EAC9B,eAAe,EAChB,qBAAiB;AAelB;;GAEG;AACH,qBAAa,gCACX,YAAW,uBAAuB;;gBAQtB,EACV,qBAAqB,GACtB,GAAE;QAAE,qBAAqB,CAAC,EAAE,OAAO,CAAA;KAAO;IAK3C,kBAAkB,CAAC,OAAO,EAAE,GAAG,GAAG,OAAO;IAIzC,sBAAsB,IAAI,MAAM,EAAE;IAI5B,iBAAiB,CACrB,OAAO,EAAE,8BAA8B,GACtC,OAAO,CAAC,eAAe,EAAE,CAAC;CA0J9B"}
1
+ {"version":3,"file":"EtherscanRemoteTransactionSource.d.cts","sourceRoot":"","sources":["../../src/helpers/EtherscanRemoteTransactionSource.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAO3C,OAAO,KAAK,EACV,uBAAuB,EACvB,8BAA8B,EAC9B,eAAe,EAChB,qBAAiB;AAgBlB;;GAEG;AACH,qBAAa,gCACX,YAAW,uBAAuB;;gBAUtB,EACV,gBAAgB,EAChB,qBAAqB,GACtB,GAAE;QACD,gBAAgB,CAAC,EAAE,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QACvC,qBAAqB,CAAC,EAAE,OAAO,CAAC;KAC5B;IAMN,kBAAkB,CAAC,OAAO,EAAE,GAAG,GAAG,OAAO;IAIzC,sBAAsB,IAAI,MAAM,EAAE;IAI5B,iBAAiB,CACrB,OAAO,EAAE,8BAA8B,GACtC,OAAO,CAAC,eAAe,EAAE,CAAC;CAiK9B"}
@@ -5,7 +5,8 @@ import type { RemoteTransactionSource, RemoteTransactionSourceRequest, Transacti
5
5
  */
6
6
  export declare class EtherscanRemoteTransactionSource implements RemoteTransactionSource {
7
7
  #private;
8
- constructor({ includeTokenTransfers, }?: {
8
+ constructor({ apiKeysByChainId, includeTokenTransfers, }?: {
9
+ apiKeysByChainId?: Record<Hex, string>;
9
10
  includeTokenTransfers?: boolean;
10
11
  });
11
12
  isSupportedNetwork(chainId: Hex): boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"EtherscanRemoteTransactionSource.d.mts","sourceRoot":"","sources":["../../src/helpers/EtherscanRemoteTransactionSource.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAO3C,OAAO,KAAK,EACV,uBAAuB,EACvB,8BAA8B,EAC9B,eAAe,EAChB,qBAAiB;AAelB;;GAEG;AACH,qBAAa,gCACX,YAAW,uBAAuB;;gBAQtB,EACV,qBAAqB,GACtB,GAAE;QAAE,qBAAqB,CAAC,EAAE,OAAO,CAAA;KAAO;IAK3C,kBAAkB,CAAC,OAAO,EAAE,GAAG,GAAG,OAAO;IAIzC,sBAAsB,IAAI,MAAM,EAAE;IAI5B,iBAAiB,CACrB,OAAO,EAAE,8BAA8B,GACtC,OAAO,CAAC,eAAe,EAAE,CAAC;CA0J9B"}
1
+ {"version":3,"file":"EtherscanRemoteTransactionSource.d.mts","sourceRoot":"","sources":["../../src/helpers/EtherscanRemoteTransactionSource.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAO3C,OAAO,KAAK,EACV,uBAAuB,EACvB,8BAA8B,EAC9B,eAAe,EAChB,qBAAiB;AAgBlB;;GAEG;AACH,qBAAa,gCACX,YAAW,uBAAuB;;gBAUtB,EACV,gBAAgB,EAChB,qBAAqB,GACtB,GAAE;QACD,gBAAgB,CAAC,EAAE,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QACvC,qBAAqB,CAAC,EAAE,OAAO,CAAC;KAC5B;IAMN,kBAAkB,CAAC,OAAO,EAAE,GAAG,GAAG,OAAO;IAIzC,sBAAsB,IAAI,MAAM,EAAE;IAI5B,iBAAiB,CACrB,OAAO,EAAE,8BAA8B,GACtC,OAAO,CAAC,eAAe,EAAE,CAAC;CAiK9B"}
@@ -9,7 +9,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
9
9
  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");
10
10
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
11
  };
12
- var _EtherscanRemoteTransactionSource_instances, _EtherscanRemoteTransactionSource_includeTokenTransfers, _EtherscanRemoteTransactionSource_isTokenRequestPending, _EtherscanRemoteTransactionSource_mutex, _EtherscanRemoteTransactionSource_releaseLockAfterInterval, _EtherscanRemoteTransactionSource_fetchNormalTransactions, _EtherscanRemoteTransactionSource_fetchTokenTransactions, _EtherscanRemoteTransactionSource_getResponseTransactions, _EtherscanRemoteTransactionSource_normalizeTransaction, _EtherscanRemoteTransactionSource_normalizeTokenTransaction, _EtherscanRemoteTransactionSource_normalizeTransactionBase;
12
+ var _EtherscanRemoteTransactionSource_instances, _EtherscanRemoteTransactionSource_apiKeysByChainId, _EtherscanRemoteTransactionSource_includeTokenTransfers, _EtherscanRemoteTransactionSource_isTokenRequestPending, _EtherscanRemoteTransactionSource_mutex, _EtherscanRemoteTransactionSource_releaseLockAfterInterval, _EtherscanRemoteTransactionSource_fetchNormalTransactions, _EtherscanRemoteTransactionSource_fetchTokenTransactions, _EtherscanRemoteTransactionSource_getResponseTransactions, _EtherscanRemoteTransactionSource_normalizeTransaction, _EtherscanRemoteTransactionSource_normalizeTokenTransaction, _EtherscanRemoteTransactionSource_normalizeTransactionBase;
13
13
  function $importDefault(module) {
14
14
  if (module?.__esModule) {
15
15
  return module.default;
@@ -30,8 +30,9 @@ const ETHERSCAN_RATE_LIMIT_INTERVAL = 5000;
30
30
  * A RemoteTransactionSource that fetches transaction data from Etherscan.
31
31
  */
32
32
  export class EtherscanRemoteTransactionSource {
33
- constructor({ includeTokenTransfers, } = {}) {
33
+ constructor({ apiKeysByChainId, includeTokenTransfers, } = {}) {
34
34
  _EtherscanRemoteTransactionSource_instances.add(this);
35
+ _EtherscanRemoteTransactionSource_apiKeysByChainId.set(this, void 0);
35
36
  _EtherscanRemoteTransactionSource_includeTokenTransfers.set(this, void 0);
36
37
  _EtherscanRemoteTransactionSource_isTokenRequestPending.set(this, void 0);
37
38
  _EtherscanRemoteTransactionSource_mutex.set(this, new Mutex());
@@ -45,6 +46,7 @@ export class EtherscanRemoteTransactionSource {
45
46
  const etherscanTransactions = await fetchEtherscanTokenTransactions(etherscanRequest);
46
47
  return __classPrivateFieldGet(this, _EtherscanRemoteTransactionSource_instances, "m", _EtherscanRemoteTransactionSource_getResponseTransactions).call(this, etherscanTransactions).map((tx) => __classPrivateFieldGet(this, _EtherscanRemoteTransactionSource_instances, "m", _EtherscanRemoteTransactionSource_normalizeTokenTransaction).call(this, tx, currentChainId));
47
48
  });
49
+ __classPrivateFieldSet(this, _EtherscanRemoteTransactionSource_apiKeysByChainId, apiKeysByChainId, "f");
48
50
  __classPrivateFieldSet(this, _EtherscanRemoteTransactionSource_includeTokenTransfers, includeTokenTransfers ?? true, "f");
49
51
  __classPrivateFieldSet(this, _EtherscanRemoteTransactionSource_isTokenRequestPending, false, "f");
50
52
  }
@@ -57,9 +59,15 @@ export class EtherscanRemoteTransactionSource {
57
59
  async fetchTransactions(request) {
58
60
  const releaseLock = await __classPrivateFieldGet(this, _EtherscanRemoteTransactionSource_mutex, "f").acquire();
59
61
  const acquiredTime = Date.now();
62
+ const { currentChainId: chainId } = request;
63
+ const apiKey = __classPrivateFieldGet(this, _EtherscanRemoteTransactionSource_apiKeysByChainId, "f")?.[chainId];
64
+ if (apiKey) {
65
+ log('Etherscan API key found for chain', chainId);
66
+ }
60
67
  const etherscanRequest = {
61
68
  ...request,
62
- chainId: request.currentChainId,
69
+ apiKey,
70
+ chainId,
63
71
  };
64
72
  try {
65
73
  const transactions = __classPrivateFieldGet(this, _EtherscanRemoteTransactionSource_isTokenRequestPending, "f")
@@ -75,7 +83,7 @@ export class EtherscanRemoteTransactionSource {
75
83
  }
76
84
  }
77
85
  }
78
- _EtherscanRemoteTransactionSource_includeTokenTransfers = new WeakMap(), _EtherscanRemoteTransactionSource_isTokenRequestPending = new WeakMap(), _EtherscanRemoteTransactionSource_mutex = new WeakMap(), _EtherscanRemoteTransactionSource_fetchNormalTransactions = new WeakMap(), _EtherscanRemoteTransactionSource_fetchTokenTransactions = new WeakMap(), _EtherscanRemoteTransactionSource_instances = new WeakSet(), _EtherscanRemoteTransactionSource_releaseLockAfterInterval = function _EtherscanRemoteTransactionSource_releaseLockAfterInterval(acquireTime, releaseLock) {
86
+ _EtherscanRemoteTransactionSource_apiKeysByChainId = new WeakMap(), _EtherscanRemoteTransactionSource_includeTokenTransfers = new WeakMap(), _EtherscanRemoteTransactionSource_isTokenRequestPending = new WeakMap(), _EtherscanRemoteTransactionSource_mutex = new WeakMap(), _EtherscanRemoteTransactionSource_fetchNormalTransactions = new WeakMap(), _EtherscanRemoteTransactionSource_fetchTokenTransactions = new WeakMap(), _EtherscanRemoteTransactionSource_instances = new WeakSet(), _EtherscanRemoteTransactionSource_releaseLockAfterInterval = function _EtherscanRemoteTransactionSource_releaseLockAfterInterval(acquireTime, releaseLock) {
79
87
  const elapsedTime = Date.now() - acquireTime;
80
88
  const remainingTime = Math.max(0, ETHERSCAN_RATE_LIMIT_INTERVAL - elapsedTime);
81
89
  // Wait for the remaining time if it hasn't been 5 seconds yet
@@ -1 +1 @@
1
- {"version":3,"file":"EtherscanRemoteTransactionSource.mjs","sourceRoot":"","sources":["../../src/helpers/EtherscanRemoteTransactionSource.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AAAA,OAAO,EAAE,OAAO,EAAE,mCAAmC;AAErD,OAAO,EAAE,KAAK,EAAE,oBAAoB;AACpC,OAAO,GAAE,cAAc;;AACvB,OAAO,EAAE,EAAE,IAAI,MAAM,EAAE,aAAa;AAEpC,OAAO,EAAE,4BAA4B,EAAE,yBAAqB;AAC5D,OAAO,EAAE,0BAA0B,IAAI,GAAG,EAAE,sBAAkB;AAM9D,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,qBAAiB;AAC9D,OAAO,EACL,+BAA+B,EAC/B,0BAA0B,EAC3B,+BAA2B;AAS5B,MAAM,6BAA6B,GAAG,IAAI,CAAC;AAC3C;;GAEG;AACH,MAAM,OAAO,gCAAgC;IAS3C,YAAY,EACV,qBAAqB,MACkB,EAAE;;QAR3C,0EAAgC;QAEhC,0EAAgC;QAEhC,kDAAS,IAAI,KAAK,EAAE,EAAC;QAyDrB,oEAA2B,KAAK,EAC9B,OAAuC,EACvC,gBAA6C,EAC7C,EAAE;YACF,MAAM,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC;YAEnC,MAAM,qBAAqB,GAAG,MAAM,0BAA0B,CAC5D,gBAAgB,CACjB,CAAC;YAEF,OAAO,uBAAA,IAAI,8GAAyB,MAA7B,IAAI,EAA0B,qBAAqB,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CACrE,uBAAA,IAAI,2GAAsB,MAA1B,IAAI,EAAuB,EAAE,EAAE,cAAc,CAAC,CAC/C,CAAC;QACJ,CAAC,EAAC;QAEF,mEAA0B,KAAK,EAC7B,OAAuC,EACvC,gBAA6C,EAC7C,EAAE;YACF,MAAM,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC;YAEnC,MAAM,qBAAqB,GAAG,MAAM,+BAA+B,CACjE,gBAAgB,CACjB,CAAC;YAEF,OAAO,uBAAA,IAAI,8GAAyB,MAA7B,IAAI,EAA0B,qBAAqB,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CACrE,uBAAA,IAAI,gHAA2B,MAA/B,IAAI,EAA4B,EAAE,EAAE,cAAc,CAAC,CACpD,CAAC;QACJ,CAAC,EAAC;QAhFA,uBAAA,IAAI,2DAA0B,qBAAqB,IAAI,IAAI,MAAA,CAAC;QAC5D,uBAAA,IAAI,2DAA0B,KAAK,MAAA,CAAC;IACtC,CAAC;IAED,kBAAkB,CAAC,OAAY;QAC7B,OAAO,MAAM,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IACrE,CAAC;IAED,sBAAsB;QACpB,OAAO,CAAC,uBAAA,IAAI,+DAAuB,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IAC5D,CAAC;IAED,KAAK,CAAC,iBAAiB,CACrB,OAAuC;QAEvC,MAAM,WAAW,GAAG,MAAM,uBAAA,IAAI,+CAAO,CAAC,OAAO,EAAE,CAAC;QAChD,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAEhC,MAAM,gBAAgB,GAAgC;YACpD,GAAG,OAAO;YACV,OAAO,EAAE,OAAO,CAAC,cAAc;SAChC,CAAC;QAEF,IAAI;YACF,MAAM,YAAY,GAAG,uBAAA,IAAI,+DAAuB;gBAC9C,CAAC,CAAC,MAAM,uBAAA,IAAI,gEAAwB,MAA5B,IAAI,EAAyB,OAAO,EAAE,gBAAgB,CAAC;gBAC/D,CAAC,CAAC,MAAM,uBAAA,IAAI,iEAAyB,MAA7B,IAAI,EAA0B,OAAO,EAAE,gBAAgB,CAAC,CAAC;YAEnE,IAAI,uBAAA,IAAI,+DAAuB,EAAE;gBAC/B,uBAAA,IAAI,2DAA0B,CAAC,uBAAA,IAAI,+DAAuB,MAAA,CAAC;aAC5D;YAED,OAAO,YAAY,CAAC;SACrB;gBAAS;YACR,uBAAA,IAAI,+GAA0B,MAA9B,IAAI,EAA2B,YAAY,EAAE,WAAW,CAAC,CAAC;SAC3D;IACH,CAAC;CAoIF;8hBAlI2B,WAAmB,EAAE,WAAuB;IACpE,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,WAAW,CAAC;IAC7C,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAC5B,CAAC,EACD,6BAA6B,GAAG,WAAW,CAC5C,CAAC;IACF,8DAA8D;IAC9D,IAAI,aAAa,GAAG,CAAC,EAAE;QACrB,UAAU,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;KACxC;SAAM;QACL,WAAW,EAAE,CAAC;KACf;AACH,CAAC,iIAmCC,QAAyC;IAEzC,IAAI,MAAM,GAAG,QAAQ,CAAC,MAAa,CAAC;IAEpC,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE;QAC3B,MAAM,GAAG,EAAE,CAAC;QAEZ,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE;YAC1B,GAAG,CAAC,iCAAiC,EAAE;gBACrC,OAAO,EAAE,QAAQ,CAAC,MAAM;gBACxB,IAAI,EAAE,uBAAA,IAAI,+DAAuB,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ;aACvD,CAAC,CAAC;SACJ;KACF;IAED,OAAO,MAAM,CAAC;AAChB,CAAC,2HAGC,MAAgC,EAChC,cAAmB;IAEnB,MAAM,IAAI,GAAG,uBAAA,IAAI,+GAA0B,MAA9B,IAAI,EAA2B,MAAM,EAAE,cAAc,CAAC,CAAC;IAEpE,OAAO;QACL,GAAG,IAAI;QACP,QAAQ,EAAE;YACR,GAAG,IAAI,CAAC,QAAQ;YAChB,IAAI,EAAE,MAAM,CAAC,KAAK;SACnB;QACD,GAAG,CAAC,MAAM,CAAC,OAAO,KAAK,GAAG;YACxB,CAAC,CAAC,EAAE,MAAM,EAAE,iBAAiB,CAAC,SAAS,EAAE;YACzC,CAAC,CAAC;gBACE,KAAK,EAAE,IAAI,KAAK,CAAC,oBAAoB,CAAC;gBACtC,MAAM,EAAE,iBAAiB,CAAC,MAAM;aACjC,CAAC;KACP,CAAC;AACJ,CAAC,qIAGC,MAAqC,EACrC,cAAmB;IAEnB,MAAM,IAAI,GAAG,uBAAA,IAAI,+GAA0B,MAA9B,IAAI,EAA2B,MAAM,EAAE,cAAc,CAAC,CAAC;IAEpE,OAAO;QACL,GAAG,IAAI;QACP,UAAU,EAAE,IAAI;QAChB,mBAAmB,EAAE;YACnB,eAAe,EAAE,MAAM,CAAC,eAAe;YACvC,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC;YACrC,MAAM,EAAE,MAAM,CAAC,WAAW;SAC3B;KACF,CAAC;AACJ,CAAC,mIAGC,MAAoC,EACpC,cAAmB;IAEnB,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC;IAEnD,OAAO;QACL,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,OAAO,EAAE,cAAc;QACvB,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,EAAE,EAAE,MAAM,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;QAC3B,MAAM,EAAE,iBAAiB,CAAC,SAAS;QACnC,IAAI;QACJ,QAAQ,EAAE;YACR,OAAO,EAAE,cAAc;YACvB,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,GAAG,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAChC,QAAQ,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAC1C,OAAO,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YACxC,KAAK,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACpC,EAAE,EAAE,MAAM,CAAC,EAAE;YACb,KAAK,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;SACrC;QACD,IAAI,EAAE,eAAe,CAAC,QAAQ;QAC9B,oBAAoB,EAAE,KAAK;KAC5B,CAAC;AACJ,CAAC","sourcesContent":["import { BNToHex } from '@metamask/controller-utils';\nimport type { Hex } from '@metamask/utils';\nimport { Mutex } from 'async-mutex';\nimport BN from 'bn.js';\nimport { v1 as random } from 'uuid';\n\nimport { ETHERSCAN_SUPPORTED_NETWORKS } from '../constants';\nimport { incomingTransactionsLogger as log } from '../logger';\nimport type {\n RemoteTransactionSource,\n RemoteTransactionSourceRequest,\n TransactionMeta,\n} from '../types';\nimport { TransactionStatus, TransactionType } from '../types';\nimport {\n fetchEtherscanTokenTransactions,\n fetchEtherscanTransactions,\n} from '../utils/etherscan';\nimport type {\n EtherscanTokenTransactionMeta,\n EtherscanTransactionMeta,\n EtherscanTransactionMetaBase,\n EtherscanTransactionRequest,\n EtherscanTransactionResponse,\n} from '../utils/etherscan';\n\nconst ETHERSCAN_RATE_LIMIT_INTERVAL = 5000;\n/**\n * A RemoteTransactionSource that fetches transaction data from Etherscan.\n */\nexport class EtherscanRemoteTransactionSource\n implements RemoteTransactionSource\n{\n #includeTokenTransfers: boolean;\n\n #isTokenRequestPending: boolean;\n\n #mutex = new Mutex();\n\n constructor({\n includeTokenTransfers,\n }: { includeTokenTransfers?: boolean } = {}) {\n this.#includeTokenTransfers = includeTokenTransfers ?? true;\n this.#isTokenRequestPending = false;\n }\n\n isSupportedNetwork(chainId: Hex): boolean {\n return Object.keys(ETHERSCAN_SUPPORTED_NETWORKS).includes(chainId);\n }\n\n getLastBlockVariations(): string[] {\n return [this.#isTokenRequestPending ? 'token' : 'normal'];\n }\n\n async fetchTransactions(\n request: RemoteTransactionSourceRequest,\n ): Promise<TransactionMeta[]> {\n const releaseLock = await this.#mutex.acquire();\n const acquiredTime = Date.now();\n\n const etherscanRequest: EtherscanTransactionRequest = {\n ...request,\n chainId: request.currentChainId,\n };\n\n try {\n const transactions = this.#isTokenRequestPending\n ? await this.#fetchTokenTransactions(request, etherscanRequest)\n : await this.#fetchNormalTransactions(request, etherscanRequest);\n\n if (this.#includeTokenTransfers) {\n this.#isTokenRequestPending = !this.#isTokenRequestPending;\n }\n\n return transactions;\n } finally {\n this.#releaseLockAfterInterval(acquiredTime, releaseLock);\n }\n }\n\n #releaseLockAfterInterval(acquireTime: number, releaseLock: () => void) {\n const elapsedTime = Date.now() - acquireTime;\n const remainingTime = Math.max(\n 0,\n ETHERSCAN_RATE_LIMIT_INTERVAL - elapsedTime,\n );\n // Wait for the remaining time if it hasn't been 5 seconds yet\n if (remainingTime > 0) {\n setTimeout(releaseLock, remainingTime);\n } else {\n releaseLock();\n }\n }\n\n #fetchNormalTransactions = async (\n request: RemoteTransactionSourceRequest,\n etherscanRequest: EtherscanTransactionRequest,\n ) => {\n const { currentChainId } = request;\n\n const etherscanTransactions = await fetchEtherscanTransactions(\n etherscanRequest,\n );\n\n return this.#getResponseTransactions(etherscanTransactions).map((tx) =>\n this.#normalizeTransaction(tx, currentChainId),\n );\n };\n\n #fetchTokenTransactions = async (\n request: RemoteTransactionSourceRequest,\n etherscanRequest: EtherscanTransactionRequest,\n ) => {\n const { currentChainId } = request;\n\n const etherscanTransactions = await fetchEtherscanTokenTransactions(\n etherscanRequest,\n );\n\n return this.#getResponseTransactions(etherscanTransactions).map((tx) =>\n this.#normalizeTokenTransaction(tx, currentChainId),\n );\n };\n\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n #getResponseTransactions<T extends EtherscanTransactionMetaBase>(\n response: EtherscanTransactionResponse<T>,\n ): T[] {\n let result = response.result as T[];\n\n if (response.status === '0') {\n result = [];\n\n if (response.result.length) {\n log('Ignored Etherscan request error', {\n message: response.result,\n type: this.#isTokenRequestPending ? 'token' : 'normal',\n });\n }\n }\n\n return result;\n }\n\n #normalizeTransaction(\n txMeta: EtherscanTransactionMeta,\n currentChainId: Hex,\n ): TransactionMeta {\n const base = this.#normalizeTransactionBase(txMeta, currentChainId);\n\n return {\n ...base,\n txParams: {\n ...base.txParams,\n data: txMeta.input,\n },\n ...(txMeta.isError === '0'\n ? { status: TransactionStatus.confirmed }\n : {\n error: new Error('Transaction failed'),\n status: TransactionStatus.failed,\n }),\n };\n }\n\n #normalizeTokenTransaction(\n txMeta: EtherscanTokenTransactionMeta,\n currentChainId: Hex,\n ): TransactionMeta {\n const base = this.#normalizeTransactionBase(txMeta, currentChainId);\n\n return {\n ...base,\n isTransfer: true,\n transferInformation: {\n contractAddress: txMeta.contractAddress,\n decimals: Number(txMeta.tokenDecimal),\n symbol: txMeta.tokenSymbol,\n },\n };\n }\n\n #normalizeTransactionBase(\n txMeta: EtherscanTransactionMetaBase,\n currentChainId: Hex,\n ): TransactionMeta {\n const time = parseInt(txMeta.timeStamp, 10) * 1000;\n\n return {\n blockNumber: txMeta.blockNumber,\n chainId: currentChainId,\n hash: txMeta.hash,\n id: random({ msecs: time }),\n status: TransactionStatus.confirmed,\n time,\n txParams: {\n chainId: currentChainId,\n from: txMeta.from,\n gas: BNToHex(new BN(txMeta.gas)),\n gasPrice: BNToHex(new BN(txMeta.gasPrice)),\n gasUsed: BNToHex(new BN(txMeta.gasUsed)),\n nonce: BNToHex(new BN(txMeta.nonce)),\n to: txMeta.to,\n value: BNToHex(new BN(txMeta.value)),\n },\n type: TransactionType.incoming,\n verifiedOnBlockchain: false,\n };\n }\n}\n"]}
1
+ {"version":3,"file":"EtherscanRemoteTransactionSource.mjs","sourceRoot":"","sources":["../../src/helpers/EtherscanRemoteTransactionSource.ts"],"names":[],"mappings":"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","sourcesContent":["import { BNToHex } from '@metamask/controller-utils';\nimport type { Hex } from '@metamask/utils';\nimport { Mutex } from 'async-mutex';\nimport BN from 'bn.js';\nimport { v1 as random } from 'uuid';\n\nimport { ETHERSCAN_SUPPORTED_NETWORKS } from '../constants';\nimport { incomingTransactionsLogger as log } from '../logger';\nimport type {\n RemoteTransactionSource,\n RemoteTransactionSourceRequest,\n TransactionMeta,\n} from '../types';\nimport { TransactionStatus, TransactionType } from '../types';\nimport {\n fetchEtherscanTokenTransactions,\n fetchEtherscanTransactions,\n} from '../utils/etherscan';\nimport type {\n EtherscanTokenTransactionMeta,\n EtherscanTransactionMeta,\n EtherscanTransactionMetaBase,\n EtherscanTransactionRequest,\n EtherscanTransactionResponse,\n} from '../utils/etherscan';\n\nconst ETHERSCAN_RATE_LIMIT_INTERVAL = 5000;\n\n/**\n * A RemoteTransactionSource that fetches transaction data from Etherscan.\n */\nexport class EtherscanRemoteTransactionSource\n implements RemoteTransactionSource\n{\n #apiKeysByChainId?: Record<Hex, string>;\n\n #includeTokenTransfers: boolean;\n\n #isTokenRequestPending: boolean;\n\n #mutex = new Mutex();\n\n constructor({\n apiKeysByChainId,\n includeTokenTransfers,\n }: {\n apiKeysByChainId?: Record<Hex, string>;\n includeTokenTransfers?: boolean;\n } = {}) {\n this.#apiKeysByChainId = apiKeysByChainId;\n this.#includeTokenTransfers = includeTokenTransfers ?? true;\n this.#isTokenRequestPending = false;\n }\n\n isSupportedNetwork(chainId: Hex): boolean {\n return Object.keys(ETHERSCAN_SUPPORTED_NETWORKS).includes(chainId);\n }\n\n getLastBlockVariations(): string[] {\n return [this.#isTokenRequestPending ? 'token' : 'normal'];\n }\n\n async fetchTransactions(\n request: RemoteTransactionSourceRequest,\n ): Promise<TransactionMeta[]> {\n const releaseLock = await this.#mutex.acquire();\n const acquiredTime = Date.now();\n const { currentChainId: chainId } = request;\n const apiKey = this.#apiKeysByChainId?.[chainId];\n\n if (apiKey) {\n log('Etherscan API key found for chain', chainId);\n }\n\n const etherscanRequest: EtherscanTransactionRequest = {\n ...request,\n apiKey,\n chainId,\n };\n\n try {\n const transactions = this.#isTokenRequestPending\n ? await this.#fetchTokenTransactions(request, etherscanRequest)\n : await this.#fetchNormalTransactions(request, etherscanRequest);\n\n if (this.#includeTokenTransfers) {\n this.#isTokenRequestPending = !this.#isTokenRequestPending;\n }\n\n return transactions;\n } finally {\n this.#releaseLockAfterInterval(acquiredTime, releaseLock);\n }\n }\n\n #releaseLockAfterInterval(acquireTime: number, releaseLock: () => void) {\n const elapsedTime = Date.now() - acquireTime;\n const remainingTime = Math.max(\n 0,\n ETHERSCAN_RATE_LIMIT_INTERVAL - elapsedTime,\n );\n // Wait for the remaining time if it hasn't been 5 seconds yet\n if (remainingTime > 0) {\n setTimeout(releaseLock, remainingTime);\n } else {\n releaseLock();\n }\n }\n\n #fetchNormalTransactions = async (\n request: RemoteTransactionSourceRequest,\n etherscanRequest: EtherscanTransactionRequest,\n ) => {\n const { currentChainId } = request;\n\n const etherscanTransactions = await fetchEtherscanTransactions(\n etherscanRequest,\n );\n\n return this.#getResponseTransactions(etherscanTransactions).map((tx) =>\n this.#normalizeTransaction(tx, currentChainId),\n );\n };\n\n #fetchTokenTransactions = async (\n request: RemoteTransactionSourceRequest,\n etherscanRequest: EtherscanTransactionRequest,\n ) => {\n const { currentChainId } = request;\n\n const etherscanTransactions = await fetchEtherscanTokenTransactions(\n etherscanRequest,\n );\n\n return this.#getResponseTransactions(etherscanTransactions).map((tx) =>\n this.#normalizeTokenTransaction(tx, currentChainId),\n );\n };\n\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n #getResponseTransactions<T extends EtherscanTransactionMetaBase>(\n response: EtherscanTransactionResponse<T>,\n ): T[] {\n let result = response.result as T[];\n\n if (response.status === '0') {\n result = [];\n\n if (response.result.length) {\n log('Ignored Etherscan request error', {\n message: response.result,\n type: this.#isTokenRequestPending ? 'token' : 'normal',\n });\n }\n }\n\n return result;\n }\n\n #normalizeTransaction(\n txMeta: EtherscanTransactionMeta,\n currentChainId: Hex,\n ): TransactionMeta {\n const base = this.#normalizeTransactionBase(txMeta, currentChainId);\n\n return {\n ...base,\n txParams: {\n ...base.txParams,\n data: txMeta.input,\n },\n ...(txMeta.isError === '0'\n ? { status: TransactionStatus.confirmed }\n : {\n error: new Error('Transaction failed'),\n status: TransactionStatus.failed,\n }),\n };\n }\n\n #normalizeTokenTransaction(\n txMeta: EtherscanTokenTransactionMeta,\n currentChainId: Hex,\n ): TransactionMeta {\n const base = this.#normalizeTransactionBase(txMeta, currentChainId);\n\n return {\n ...base,\n isTransfer: true,\n transferInformation: {\n contractAddress: txMeta.contractAddress,\n decimals: Number(txMeta.tokenDecimal),\n symbol: txMeta.tokenSymbol,\n },\n };\n }\n\n #normalizeTransactionBase(\n txMeta: EtherscanTransactionMetaBase,\n currentChainId: Hex,\n ): TransactionMeta {\n const time = parseInt(txMeta.timeStamp, 10) * 1000;\n\n return {\n blockNumber: txMeta.blockNumber,\n chainId: currentChainId,\n hash: txMeta.hash,\n id: random({ msecs: time }),\n status: TransactionStatus.confirmed,\n time,\n txParams: {\n chainId: currentChainId,\n from: txMeta.from,\n gas: BNToHex(new BN(txMeta.gas)),\n gasPrice: BNToHex(new BN(txMeta.gasPrice)),\n gasUsed: BNToHex(new BN(txMeta.gasUsed)),\n nonce: BNToHex(new BN(txMeta.nonce)),\n to: txMeta.to,\n value: BNToHex(new BN(txMeta.value)),\n },\n type: TransactionType.incoming,\n verifiedOnBlockchain: false,\n };\n }\n}\n"]}
@@ -9,14 +9,16 @@ const logger_1 = require("../logger.cjs");
9
9
  *
10
10
  * @param request - Configuration required to fetch transactions.
11
11
  * @param request.address - Address to retrieve transactions for.
12
+ * @param request.apiKey - Etherscan API key to prevent rate limiting.
12
13
  * @param request.chainId - Current chain ID used to determine subdomain and domain.
13
14
  * @param request.fromBlock - Block number to start fetching transactions from.
14
15
  * @param request.limit - Number of transactions to retrieve.
15
16
  * @returns An Etherscan response object containing the request status and an array of token transaction data.
16
17
  */
17
- async function fetchEtherscanTransactions({ address, chainId, fromBlock, limit, }) {
18
+ async function fetchEtherscanTransactions({ address, apiKey, chainId, fromBlock, limit, }) {
18
19
  return await fetchTransactions('txlist', {
19
20
  address,
21
+ apiKey,
20
22
  chainId,
21
23
  fromBlock,
22
24
  limit,
@@ -28,14 +30,16 @@ exports.fetchEtherscanTransactions = fetchEtherscanTransactions;
28
30
  *
29
31
  * @param request - Configuration required to fetch token transactions.
30
32
  * @param request.address - Address to retrieve token transactions for.
33
+ * @param request.apiKey - Etherscan API key to prevent rate limiting.
31
34
  * @param request.chainId - Current chain ID used to determine subdomain and domain.
32
35
  * @param request.fromBlock - Block number to start fetching token transactions from.
33
36
  * @param request.limit - Number of token transactions to retrieve.
34
37
  * @returns An Etherscan response object containing the request status and an array of token transaction data.
35
38
  */
36
- async function fetchEtherscanTokenTransactions({ address, chainId, fromBlock, limit, }) {
39
+ async function fetchEtherscanTokenTransactions({ address, apiKey, chainId, fromBlock, limit, }) {
37
40
  return await fetchTransactions('tokentx', {
38
41
  address,
42
+ apiKey,
39
43
  chainId,
40
44
  fromBlock,
41
45
  limit,
@@ -48,14 +52,13 @@ exports.fetchEtherscanTokenTransactions = fetchEtherscanTokenTransactions;
48
52
  * @param action - The Etherscan endpoint to use.
49
53
  * @param options - Options bag.
50
54
  * @param options.address - Address to retrieve transactions for.
55
+ * @param options.apiKey - Etherscan API key to prevent rate limiting.
51
56
  * @param options.chainId - Current chain ID used to determine subdomain and domain.
52
57
  * @param options.fromBlock - Block number to start fetching transactions from.
53
58
  * @param options.limit - Number of transactions to retrieve.
54
59
  * @returns An object containing the request status and an array of transaction data.
55
60
  */
56
- // TODO: Either fix this lint violation or explain why it's necessary to ignore.
57
- // eslint-disable-next-line @typescript-eslint/naming-convention
58
- async function fetchTransactions(action, { address, chainId, fromBlock, limit, }) {
61
+ async function fetchTransactions(action, { address, apiKey, chainId, fromBlock, limit, }) {
59
62
  const urlParams = {
60
63
  module: 'account',
61
64
  address,
@@ -66,6 +69,7 @@ async function fetchTransactions(action, { address, chainId, fromBlock, limit, }
66
69
  const etherscanTxUrl = getEtherscanApiUrl(chainId, {
67
70
  ...urlParams,
68
71
  action,
72
+ apikey: apiKey,
69
73
  });
70
74
  (0, logger_1.incomingTransactionsLogger)('Sending Etherscan request', etherscanTxUrl);
71
75
  const response = (await (0, controller_utils_1.handleFetch)(etherscanTxUrl));
@@ -1 +1 @@
1
- {"version":3,"file":"etherscan.cjs","sourceRoot":"","sources":["../../src/utils/etherscan.ts"],"names":[],"mappings":";;;AAAA,iEAAyD;AAGzD,gDAA4D;AAC5D,0CAA8D;AAqE9D;;;;;;;;;GASG;AACI,KAAK,UAAU,0BAA0B,CAAC,EAC/C,OAAO,EACP,OAAO,EACP,SAAS,EACT,KAAK,GACuB;IAG5B,OAAO,MAAM,iBAAiB,CAAC,QAAQ,EAAE;QACvC,OAAO;QACP,OAAO;QACP,SAAS;QACT,KAAK;KACN,CAAC,CAAC;AACL,CAAC;AAdD,gEAcC;AAED;;;;;;;;;GASG;AACI,KAAK,UAAU,+BAA+B,CAAC,EACpD,OAAO,EACP,OAAO,EACP,SAAS,EACT,KAAK,GACuB;IAG5B,OAAO,MAAM,iBAAiB,CAAC,SAAS,EAAE;QACxC,OAAO;QACP,OAAO;QACP,SAAS;QACT,KAAK;KACN,CAAC,CAAC;AACL,CAAC;AAdD,0EAcC;AAED;;;;;;;;;;GAUG;AACH,gFAAgF;AAChF,gEAAgE;AAChE,KAAK,UAAU,iBAAiB,CAC9B,MAAc,EACd,EACE,OAAO,EACP,OAAO,EACP,SAAS,EACT,KAAK,GAMN;IAED,MAAM,SAAS,GAAG;QAChB,MAAM,EAAE,SAAS;QACjB,OAAO;QACP,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE;QACjC,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE;QACzB,IAAI,EAAE,MAAM;KACb,CAAC;IAEF,MAAM,cAAc,GAAG,kBAAkB,CAAC,OAAO,EAAE;QACjD,GAAG,SAAS;QACZ,MAAM;KACP,CAAC,CAAC;IAEH,IAAA,mCAAG,EAAC,2BAA2B,EAAE,cAAc,CAAC,CAAC;IAEjD,MAAM,QAAQ,GAAG,CAAC,MAAM,IAAA,8BAAW,EACjC,cAAc,CACf,CAAoC,CAAC;IAEtC,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;;;GAMG;AACH,SAAS,kBAAkB,CACzB,OAAY,EACZ,SAA6C;IAE7C,MAAM,MAAM,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAC;IAC5C,IAAI,GAAG,GAAG,GAAG,MAAM,OAAO,CAAC;IAE3B,KAAK,MAAM,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE;QAC7C,MAAM,KAAK,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;QAElC,IAAI,CAAC,KAAK,EAAE;YACV,SAAS;SACV;QAED,GAAG,IAAI,GAAG,QAAQ,IAAI,KAAK,GAAG,CAAC;KAChC;IAED,GAAG,IAAI,mBAAmB,CAAC;IAE3B,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;GAKG;AACH,SAAgB,mBAAmB,CAAC,OAAY;IAC9C,uEAAuE;IACvE,MAAM,WAAW,GAAG,wCAA4B,CAAC,OAAO,CAAC,CAAC;IAE1D,IAAI,CAAC,WAAW,EAAE;QAChB,MAAM,IAAI,KAAK,CAAC,6CAA6C,OAAO,EAAE,CAAC,CAAC;KACzE;IAED,gFAAgF;IAChF,4EAA4E;IAC5E,OAAO,WAAW,WAAW,CAAC,SAAS,IAAI,WAAW,CAAC,MAAM,EAAE,CAAC;AAClE,CAAC;AAXD,kDAWC","sourcesContent":["import { handleFetch } from '@metamask/controller-utils';\nimport type { Hex } from '@metamask/utils';\n\nimport { ETHERSCAN_SUPPORTED_NETWORKS } from '../constants';\nimport { incomingTransactionsLogger as log } from '../logger';\n\n// This interface was created before this ESLint rule was added.\n// Convert to a `type` in a future major version.\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\nexport interface EtherscanTransactionMetaBase {\n blockNumber: string;\n blockHash: string;\n confirmations: string;\n contractAddress: string;\n cumulativeGasUsed: string;\n from: string;\n gas: string;\n gasPrice: string;\n gasUsed: string;\n hash: string;\n nonce: string;\n timeStamp: string;\n to: string;\n transactionIndex: string;\n value: string;\n}\n\n// This interface was created before this ESLint rule was added.\n// Convert to a `type` in a future major version.\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\nexport interface EtherscanTransactionMeta extends EtherscanTransactionMetaBase {\n functionName: string;\n input: string;\n isError: string;\n methodId: string;\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n txreceipt_status: string;\n}\n\n// This interface was created before this ESLint rule was added.\n// Convert to a `type` in a future major version.\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\nexport interface EtherscanTokenTransactionMeta\n extends EtherscanTransactionMetaBase {\n tokenDecimal: string;\n tokenName: string;\n tokenSymbol: string;\n}\n\n// This interface was created before this ESLint rule was added.\n// Convert to a `type` in a future major version.\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\nexport interface EtherscanTransactionResponse<\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n T extends EtherscanTransactionMetaBase,\n> {\n status: '0' | '1';\n message?: string;\n result: string | T[];\n}\n\n// This interface was created before this ESLint rule was added.\n// Convert to a `type` in a future major version.\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\nexport interface EtherscanTransactionRequest {\n address: string;\n chainId: Hex;\n fromBlock?: number;\n limit?: number;\n}\n\n/**\n * Retrieves transaction data from Etherscan.\n *\n * @param request - Configuration required to fetch transactions.\n * @param request.address - Address to retrieve transactions for.\n * @param request.chainId - Current chain ID used to determine subdomain and domain.\n * @param request.fromBlock - Block number to start fetching transactions from.\n * @param request.limit - Number of transactions to retrieve.\n * @returns An Etherscan response object containing the request status and an array of token transaction data.\n */\nexport async function fetchEtherscanTransactions({\n address,\n chainId,\n fromBlock,\n limit,\n}: EtherscanTransactionRequest): Promise<\n EtherscanTransactionResponse<EtherscanTransactionMeta>\n> {\n return await fetchTransactions('txlist', {\n address,\n chainId,\n fromBlock,\n limit,\n });\n}\n\n/**\n * Retrieves token transaction data from Etherscan.\n *\n * @param request - Configuration required to fetch token transactions.\n * @param request.address - Address to retrieve token transactions for.\n * @param request.chainId - Current chain ID used to determine subdomain and domain.\n * @param request.fromBlock - Block number to start fetching token transactions from.\n * @param request.limit - Number of token transactions to retrieve.\n * @returns An Etherscan response object containing the request status and an array of token transaction data.\n */\nexport async function fetchEtherscanTokenTransactions({\n address,\n chainId,\n fromBlock,\n limit,\n}: EtherscanTransactionRequest): Promise<\n EtherscanTransactionResponse<EtherscanTokenTransactionMeta>\n> {\n return await fetchTransactions('tokentx', {\n address,\n chainId,\n fromBlock,\n limit,\n });\n}\n\n/**\n * Retrieves transaction data from Etherscan from a specific endpoint.\n *\n * @param action - The Etherscan endpoint to use.\n * @param options - Options bag.\n * @param options.address - Address to retrieve transactions for.\n * @param options.chainId - Current chain ID used to determine subdomain and domain.\n * @param options.fromBlock - Block number to start fetching transactions from.\n * @param options.limit - Number of transactions to retrieve.\n * @returns An object containing the request status and an array of transaction data.\n */\n// TODO: Either fix this lint violation or explain why it's necessary to ignore.\n// eslint-disable-next-line @typescript-eslint/naming-convention\nasync function fetchTransactions<T extends EtherscanTransactionMetaBase>(\n action: string,\n {\n address,\n chainId,\n fromBlock,\n limit,\n }: {\n address: string;\n chainId: Hex;\n fromBlock?: number;\n limit?: number;\n },\n): Promise<EtherscanTransactionResponse<T>> {\n const urlParams = {\n module: 'account',\n address,\n startBlock: fromBlock?.toString(),\n offset: limit?.toString(),\n sort: 'desc',\n };\n\n const etherscanTxUrl = getEtherscanApiUrl(chainId, {\n ...urlParams,\n action,\n });\n\n log('Sending Etherscan request', etherscanTxUrl);\n\n const response = (await handleFetch(\n etherscanTxUrl,\n )) as EtherscanTransactionResponse<T>;\n\n return response;\n}\n\n/**\n * Return a URL that can be used to fetch data from Etherscan.\n *\n * @param chainId - Current chain ID used to determine subdomain and domain.\n * @param urlParams - The parameters used to construct the URL.\n * @returns URL to access Etherscan data.\n */\nfunction getEtherscanApiUrl(\n chainId: Hex,\n urlParams: Record<string, string | undefined>,\n): string {\n const apiUrl = getEtherscanApiHost(chainId);\n let url = `${apiUrl}/api?`;\n\n for (const paramKey of Object.keys(urlParams)) {\n const value = urlParams[paramKey];\n\n if (!value) {\n continue;\n }\n\n url += `${paramKey}=${value}&`;\n }\n\n url += 'tag=latest&page=1';\n\n return url;\n}\n\n/**\n * Return the host url used to fetch data from Etherscan.\n *\n * @param chainId - Current chain ID used to determine subdomain and domain.\n * @returns host URL to access Etherscan data.\n */\nexport function getEtherscanApiHost(chainId: Hex) {\n // @ts-expect-error We account for `chainId` not being a property below\n const networkInfo = ETHERSCAN_SUPPORTED_NETWORKS[chainId];\n\n if (!networkInfo) {\n throw new Error(`Etherscan does not support chain with ID: ${chainId}`);\n }\n\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n return `https://${networkInfo.subdomain}.${networkInfo.domain}`;\n}\n"]}
1
+ {"version":3,"file":"etherscan.cjs","sourceRoot":"","sources":["../../src/utils/etherscan.ts"],"names":[],"mappings":";;;AAAA,iEAAyD;AAGzD,gDAA4D;AAC5D,0CAA8D;AAsE9D;;;;;;;;;;GAUG;AACI,KAAK,UAAU,0BAA0B,CAAC,EAC/C,OAAO,EACP,MAAM,EACN,OAAO,EACP,SAAS,EACT,KAAK,GACuB;IAG5B,OAAO,MAAM,iBAAiB,CAAC,QAAQ,EAAE;QACvC,OAAO;QACP,MAAM;QACN,OAAO;QACP,SAAS;QACT,KAAK;KACN,CAAC,CAAC;AACL,CAAC;AAhBD,gEAgBC;AAED;;;;;;;;;;GAUG;AACI,KAAK,UAAU,+BAA+B,CAAC,EACpD,OAAO,EACP,MAAM,EACN,OAAO,EACP,SAAS,EACT,KAAK,GACuB;IAG5B,OAAO,MAAM,iBAAiB,CAAC,SAAS,EAAE;QACxC,OAAO;QACP,MAAM;QACN,OAAO;QACP,SAAS;QACT,KAAK;KACN,CAAC,CAAC;AACL,CAAC;AAhBD,0EAgBC;AAED;;;;;;;;;;;GAWG;AACH,KAAK,UAAU,iBAAiB,CAG9B,MAAc,EACd,EACE,OAAO,EACP,MAAM,EACN,OAAO,EACP,SAAS,EACT,KAAK,GAON;IAED,MAAM,SAAS,GAAG;QAChB,MAAM,EAAE,SAAS;QACjB,OAAO;QACP,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE;QACjC,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE;QACzB,IAAI,EAAE,MAAM;KACb,CAAC;IAEF,MAAM,cAAc,GAAG,kBAAkB,CAAC,OAAO,EAAE;QACjD,GAAG,SAAS;QACZ,MAAM;QACN,MAAM,EAAE,MAAM;KACf,CAAC,CAAC;IAEH,IAAA,mCAAG,EAAC,2BAA2B,EAAE,cAAc,CAAC,CAAC;IAEjD,MAAM,QAAQ,GAAG,CAAC,MAAM,IAAA,8BAAW,EACjC,cAAc,CACf,CAA+C,CAAC;IAEjD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;;;GAMG;AACH,SAAS,kBAAkB,CACzB,OAAY,EACZ,SAA6C;IAE7C,MAAM,MAAM,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAC;IAC5C,IAAI,GAAG,GAAG,GAAG,MAAM,OAAO,CAAC;IAE3B,KAAK,MAAM,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE;QAC7C,MAAM,KAAK,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;QAElC,IAAI,CAAC,KAAK,EAAE;YACV,SAAS;SACV;QAED,GAAG,IAAI,GAAG,QAAQ,IAAI,KAAK,GAAG,CAAC;KAChC;IAED,GAAG,IAAI,mBAAmB,CAAC;IAE3B,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;GAKG;AACH,SAAgB,mBAAmB,CAAC,OAAY;IAC9C,uEAAuE;IACvE,MAAM,WAAW,GAAG,wCAA4B,CAAC,OAAO,CAAC,CAAC;IAE1D,IAAI,CAAC,WAAW,EAAE;QAChB,MAAM,IAAI,KAAK,CAAC,6CAA6C,OAAO,EAAE,CAAC,CAAC;KACzE;IAED,gFAAgF;IAChF,4EAA4E;IAC5E,OAAO,WAAW,WAAW,CAAC,SAAS,IAAI,WAAW,CAAC,MAAM,EAAE,CAAC;AAClE,CAAC;AAXD,kDAWC","sourcesContent":["import { handleFetch } from '@metamask/controller-utils';\nimport type { Hex } from '@metamask/utils';\n\nimport { ETHERSCAN_SUPPORTED_NETWORKS } from '../constants';\nimport { incomingTransactionsLogger as log } from '../logger';\n\n// This interface was created before this ESLint rule was added.\n// Convert to a `type` in a future major version.\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\nexport interface EtherscanTransactionMetaBase {\n blockNumber: string;\n blockHash: string;\n confirmations: string;\n contractAddress: string;\n cumulativeGasUsed: string;\n from: string;\n gas: string;\n gasPrice: string;\n gasUsed: string;\n hash: string;\n nonce: string;\n timeStamp: string;\n to: string;\n transactionIndex: string;\n value: string;\n}\n\n// This interface was created before this ESLint rule was added.\n// Convert to a `type` in a future major version.\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\nexport interface EtherscanTransactionMeta extends EtherscanTransactionMetaBase {\n functionName: string;\n input: string;\n isError: string;\n methodId: string;\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n txreceipt_status: string;\n}\n\n// This interface was created before this ESLint rule was added.\n// Convert to a `type` in a future major version.\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\nexport interface EtherscanTokenTransactionMeta\n extends EtherscanTransactionMetaBase {\n tokenDecimal: string;\n tokenName: string;\n tokenSymbol: string;\n}\n\n// This interface was created before this ESLint rule was added.\n// Convert to a `type` in a future major version.\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\nexport interface EtherscanTransactionResponse<\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n T extends EtherscanTransactionMetaBase,\n> {\n status: '0' | '1';\n message?: string;\n result: string | T[];\n}\n\n// This interface was created before this ESLint rule was added.\n// Convert to a `type` in a future major version.\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\nexport interface EtherscanTransactionRequest {\n address: string;\n apiKey?: string;\n chainId: Hex;\n fromBlock?: number;\n limit?: number;\n}\n\n/**\n * Retrieves transaction data from Etherscan.\n *\n * @param request - Configuration required to fetch transactions.\n * @param request.address - Address to retrieve transactions for.\n * @param request.apiKey - Etherscan API key to prevent rate limiting.\n * @param request.chainId - Current chain ID used to determine subdomain and domain.\n * @param request.fromBlock - Block number to start fetching transactions from.\n * @param request.limit - Number of transactions to retrieve.\n * @returns An Etherscan response object containing the request status and an array of token transaction data.\n */\nexport async function fetchEtherscanTransactions({\n address,\n apiKey,\n chainId,\n fromBlock,\n limit,\n}: EtherscanTransactionRequest): Promise<\n EtherscanTransactionResponse<EtherscanTransactionMeta>\n> {\n return await fetchTransactions('txlist', {\n address,\n apiKey,\n chainId,\n fromBlock,\n limit,\n });\n}\n\n/**\n * Retrieves token transaction data from Etherscan.\n *\n * @param request - Configuration required to fetch token transactions.\n * @param request.address - Address to retrieve token transactions for.\n * @param request.apiKey - Etherscan API key to prevent rate limiting.\n * @param request.chainId - Current chain ID used to determine subdomain and domain.\n * @param request.fromBlock - Block number to start fetching token transactions from.\n * @param request.limit - Number of token transactions to retrieve.\n * @returns An Etherscan response object containing the request status and an array of token transaction data.\n */\nexport async function fetchEtherscanTokenTransactions({\n address,\n apiKey,\n chainId,\n fromBlock,\n limit,\n}: EtherscanTransactionRequest): Promise<\n EtherscanTransactionResponse<EtherscanTokenTransactionMeta>\n> {\n return await fetchTransactions('tokentx', {\n address,\n apiKey,\n chainId,\n fromBlock,\n limit,\n });\n}\n\n/**\n * Retrieves transaction data from Etherscan from a specific endpoint.\n *\n * @param action - The Etherscan endpoint to use.\n * @param options - Options bag.\n * @param options.address - Address to retrieve transactions for.\n * @param options.apiKey - Etherscan API key to prevent rate limiting.\n * @param options.chainId - Current chain ID used to determine subdomain and domain.\n * @param options.fromBlock - Block number to start fetching transactions from.\n * @param options.limit - Number of transactions to retrieve.\n * @returns An object containing the request status and an array of transaction data.\n */\nasync function fetchTransactions<\n ResponseData extends EtherscanTransactionMetaBase,\n>(\n action: string,\n {\n address,\n apiKey,\n chainId,\n fromBlock,\n limit,\n }: {\n address: string;\n apiKey?: string;\n chainId: Hex;\n fromBlock?: number;\n limit?: number;\n },\n): Promise<EtherscanTransactionResponse<ResponseData>> {\n const urlParams = {\n module: 'account',\n address,\n startBlock: fromBlock?.toString(),\n offset: limit?.toString(),\n sort: 'desc',\n };\n\n const etherscanTxUrl = getEtherscanApiUrl(chainId, {\n ...urlParams,\n action,\n apikey: apiKey,\n });\n\n log('Sending Etherscan request', etherscanTxUrl);\n\n const response = (await handleFetch(\n etherscanTxUrl,\n )) as EtherscanTransactionResponse<ResponseData>;\n\n return response;\n}\n\n/**\n * Return a URL that can be used to fetch data from Etherscan.\n *\n * @param chainId - Current chain ID used to determine subdomain and domain.\n * @param urlParams - The parameters used to construct the URL.\n * @returns URL to access Etherscan data.\n */\nfunction getEtherscanApiUrl(\n chainId: Hex,\n urlParams: Record<string, string | undefined>,\n): string {\n const apiUrl = getEtherscanApiHost(chainId);\n let url = `${apiUrl}/api?`;\n\n for (const paramKey of Object.keys(urlParams)) {\n const value = urlParams[paramKey];\n\n if (!value) {\n continue;\n }\n\n url += `${paramKey}=${value}&`;\n }\n\n url += 'tag=latest&page=1';\n\n return url;\n}\n\n/**\n * Return the host url used to fetch data from Etherscan.\n *\n * @param chainId - Current chain ID used to determine subdomain and domain.\n * @returns host URL to access Etherscan data.\n */\nexport function getEtherscanApiHost(chainId: Hex) {\n // @ts-expect-error We account for `chainId` not being a property below\n const networkInfo = ETHERSCAN_SUPPORTED_NETWORKS[chainId];\n\n if (!networkInfo) {\n throw new Error(`Etherscan does not support chain with ID: ${chainId}`);\n }\n\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n return `https://${networkInfo.subdomain}.${networkInfo.domain}`;\n}\n"]}
@@ -35,6 +35,7 @@ export interface EtherscanTransactionResponse<T extends EtherscanTransactionMeta
35
35
  }
36
36
  export interface EtherscanTransactionRequest {
37
37
  address: string;
38
+ apiKey?: string;
38
39
  chainId: Hex;
39
40
  fromBlock?: number;
40
41
  limit?: number;
@@ -44,23 +45,25 @@ export interface EtherscanTransactionRequest {
44
45
  *
45
46
  * @param request - Configuration required to fetch transactions.
46
47
  * @param request.address - Address to retrieve transactions for.
48
+ * @param request.apiKey - Etherscan API key to prevent rate limiting.
47
49
  * @param request.chainId - Current chain ID used to determine subdomain and domain.
48
50
  * @param request.fromBlock - Block number to start fetching transactions from.
49
51
  * @param request.limit - Number of transactions to retrieve.
50
52
  * @returns An Etherscan response object containing the request status and an array of token transaction data.
51
53
  */
52
- export declare function fetchEtherscanTransactions({ address, chainId, fromBlock, limit, }: EtherscanTransactionRequest): Promise<EtherscanTransactionResponse<EtherscanTransactionMeta>>;
54
+ export declare function fetchEtherscanTransactions({ address, apiKey, chainId, fromBlock, limit, }: EtherscanTransactionRequest): Promise<EtherscanTransactionResponse<EtherscanTransactionMeta>>;
53
55
  /**
54
56
  * Retrieves token transaction data from Etherscan.
55
57
  *
56
58
  * @param request - Configuration required to fetch token transactions.
57
59
  * @param request.address - Address to retrieve token transactions for.
60
+ * @param request.apiKey - Etherscan API key to prevent rate limiting.
58
61
  * @param request.chainId - Current chain ID used to determine subdomain and domain.
59
62
  * @param request.fromBlock - Block number to start fetching token transactions from.
60
63
  * @param request.limit - Number of token transactions to retrieve.
61
64
  * @returns An Etherscan response object containing the request status and an array of token transaction data.
62
65
  */
63
- export declare function fetchEtherscanTokenTransactions({ address, chainId, fromBlock, limit, }: EtherscanTransactionRequest): Promise<EtherscanTransactionResponse<EtherscanTokenTransactionMeta>>;
66
+ export declare function fetchEtherscanTokenTransactions({ address, apiKey, chainId, fromBlock, limit, }: EtherscanTransactionRequest): Promise<EtherscanTransactionResponse<EtherscanTokenTransactionMeta>>;
64
67
  /**
65
68
  * Return the host url used to fetch data from Etherscan.
66
69
  *
@@ -1 +1 @@
1
- {"version":3,"file":"etherscan.d.cts","sourceRoot":"","sources":["../../src/utils/etherscan.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAQ3C,MAAM,WAAW,4BAA4B;IAC3C,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,gBAAgB,EAAE,MAAM,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;CACf;AAKD,MAAM,WAAW,wBAAyB,SAAQ,4BAA4B;IAC5E,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IAGjB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAKD,MAAM,WAAW,6BACf,SAAQ,4BAA4B;IACpC,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB;AAKD,MAAM,WAAW,4BAA4B,CAG3C,CAAC,SAAS,4BAA4B;IAEtC,MAAM,EAAE,GAAG,GAAG,GAAG,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,GAAG,CAAC,EAAE,CAAC;CACtB;AAKD,MAAM,WAAW,2BAA2B;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,GAAG,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;GASG;AACH,wBAAsB,0BAA0B,CAAC,EAC/C,OAAO,EACP,OAAO,EACP,SAAS,EACT,KAAK,GACN,EAAE,2BAA2B,GAAG,OAAO,CACtC,4BAA4B,CAAC,wBAAwB,CAAC,CACvD,CAOA;AAED;;;;;;;;;GASG;AACH,wBAAsB,+BAA+B,CAAC,EACpD,OAAO,EACP,OAAO,EACP,SAAS,EACT,KAAK,GACN,EAAE,2BAA2B,GAAG,OAAO,CACtC,4BAA4B,CAAC,6BAA6B,CAAC,CAC5D,CAOA;AAgFD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,GAAG,UAW/C"}
1
+ {"version":3,"file":"etherscan.d.cts","sourceRoot":"","sources":["../../src/utils/etherscan.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAQ3C,MAAM,WAAW,4BAA4B;IAC3C,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,gBAAgB,EAAE,MAAM,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;CACf;AAKD,MAAM,WAAW,wBAAyB,SAAQ,4BAA4B;IAC5E,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IAGjB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAKD,MAAM,WAAW,6BACf,SAAQ,4BAA4B;IACpC,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB;AAKD,MAAM,WAAW,4BAA4B,CAG3C,CAAC,SAAS,4BAA4B;IAEtC,MAAM,EAAE,GAAG,GAAG,GAAG,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,GAAG,CAAC,EAAE,CAAC;CACtB;AAKD,MAAM,WAAW,2BAA2B;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,GAAG,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,0BAA0B,CAAC,EAC/C,OAAO,EACP,MAAM,EACN,OAAO,EACP,SAAS,EACT,KAAK,GACN,EAAE,2BAA2B,GAAG,OAAO,CACtC,4BAA4B,CAAC,wBAAwB,CAAC,CACvD,CAQA;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,+BAA+B,CAAC,EACpD,OAAO,EACP,MAAM,EACN,OAAO,EACP,SAAS,EACT,KAAK,GACN,EAAE,2BAA2B,GAAG,OAAO,CACtC,4BAA4B,CAAC,6BAA6B,CAAC,CAC5D,CAQA;AAoFD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,GAAG,UAW/C"}
@@ -35,6 +35,7 @@ export interface EtherscanTransactionResponse<T extends EtherscanTransactionMeta
35
35
  }
36
36
  export interface EtherscanTransactionRequest {
37
37
  address: string;
38
+ apiKey?: string;
38
39
  chainId: Hex;
39
40
  fromBlock?: number;
40
41
  limit?: number;
@@ -44,23 +45,25 @@ export interface EtherscanTransactionRequest {
44
45
  *
45
46
  * @param request - Configuration required to fetch transactions.
46
47
  * @param request.address - Address to retrieve transactions for.
48
+ * @param request.apiKey - Etherscan API key to prevent rate limiting.
47
49
  * @param request.chainId - Current chain ID used to determine subdomain and domain.
48
50
  * @param request.fromBlock - Block number to start fetching transactions from.
49
51
  * @param request.limit - Number of transactions to retrieve.
50
52
  * @returns An Etherscan response object containing the request status and an array of token transaction data.
51
53
  */
52
- export declare function fetchEtherscanTransactions({ address, chainId, fromBlock, limit, }: EtherscanTransactionRequest): Promise<EtherscanTransactionResponse<EtherscanTransactionMeta>>;
54
+ export declare function fetchEtherscanTransactions({ address, apiKey, chainId, fromBlock, limit, }: EtherscanTransactionRequest): Promise<EtherscanTransactionResponse<EtherscanTransactionMeta>>;
53
55
  /**
54
56
  * Retrieves token transaction data from Etherscan.
55
57
  *
56
58
  * @param request - Configuration required to fetch token transactions.
57
59
  * @param request.address - Address to retrieve token transactions for.
60
+ * @param request.apiKey - Etherscan API key to prevent rate limiting.
58
61
  * @param request.chainId - Current chain ID used to determine subdomain and domain.
59
62
  * @param request.fromBlock - Block number to start fetching token transactions from.
60
63
  * @param request.limit - Number of token transactions to retrieve.
61
64
  * @returns An Etherscan response object containing the request status and an array of token transaction data.
62
65
  */
63
- export declare function fetchEtherscanTokenTransactions({ address, chainId, fromBlock, limit, }: EtherscanTransactionRequest): Promise<EtherscanTransactionResponse<EtherscanTokenTransactionMeta>>;
66
+ export declare function fetchEtherscanTokenTransactions({ address, apiKey, chainId, fromBlock, limit, }: EtherscanTransactionRequest): Promise<EtherscanTransactionResponse<EtherscanTokenTransactionMeta>>;
64
67
  /**
65
68
  * Return the host url used to fetch data from Etherscan.
66
69
  *
@@ -1 +1 @@
1
- {"version":3,"file":"etherscan.d.mts","sourceRoot":"","sources":["../../src/utils/etherscan.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAQ3C,MAAM,WAAW,4BAA4B;IAC3C,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,gBAAgB,EAAE,MAAM,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;CACf;AAKD,MAAM,WAAW,wBAAyB,SAAQ,4BAA4B;IAC5E,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IAGjB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAKD,MAAM,WAAW,6BACf,SAAQ,4BAA4B;IACpC,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB;AAKD,MAAM,WAAW,4BAA4B,CAG3C,CAAC,SAAS,4BAA4B;IAEtC,MAAM,EAAE,GAAG,GAAG,GAAG,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,GAAG,CAAC,EAAE,CAAC;CACtB;AAKD,MAAM,WAAW,2BAA2B;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,GAAG,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;GASG;AACH,wBAAsB,0BAA0B,CAAC,EAC/C,OAAO,EACP,OAAO,EACP,SAAS,EACT,KAAK,GACN,EAAE,2BAA2B,GAAG,OAAO,CACtC,4BAA4B,CAAC,wBAAwB,CAAC,CACvD,CAOA;AAED;;;;;;;;;GASG;AACH,wBAAsB,+BAA+B,CAAC,EACpD,OAAO,EACP,OAAO,EACP,SAAS,EACT,KAAK,GACN,EAAE,2BAA2B,GAAG,OAAO,CACtC,4BAA4B,CAAC,6BAA6B,CAAC,CAC5D,CAOA;AAgFD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,GAAG,UAW/C"}
1
+ {"version":3,"file":"etherscan.d.mts","sourceRoot":"","sources":["../../src/utils/etherscan.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAQ3C,MAAM,WAAW,4BAA4B;IAC3C,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,gBAAgB,EAAE,MAAM,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;CACf;AAKD,MAAM,WAAW,wBAAyB,SAAQ,4BAA4B;IAC5E,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IAGjB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAKD,MAAM,WAAW,6BACf,SAAQ,4BAA4B;IACpC,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB;AAKD,MAAM,WAAW,4BAA4B,CAG3C,CAAC,SAAS,4BAA4B;IAEtC,MAAM,EAAE,GAAG,GAAG,GAAG,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,GAAG,CAAC,EAAE,CAAC;CACtB;AAKD,MAAM,WAAW,2BAA2B;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,GAAG,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,0BAA0B,CAAC,EAC/C,OAAO,EACP,MAAM,EACN,OAAO,EACP,SAAS,EACT,KAAK,GACN,EAAE,2BAA2B,GAAG,OAAO,CACtC,4BAA4B,CAAC,wBAAwB,CAAC,CACvD,CAQA;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,+BAA+B,CAAC,EACpD,OAAO,EACP,MAAM,EACN,OAAO,EACP,SAAS,EACT,KAAK,GACN,EAAE,2BAA2B,GAAG,OAAO,CACtC,4BAA4B,CAAC,6BAA6B,CAAC,CAC5D,CAQA;AAoFD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,GAAG,UAW/C"}