@mixerx/oracles 1.0.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/README.md +90 -111
  2. package/dist/application/ports/ILogger.d.ts +0 -1
  3. package/dist/application/ports/ILogger.js +0 -1
  4. package/dist/domain/config/TokenDefaults.d.ts +0 -32
  5. package/dist/domain/config/TokenDefaults.js +7 -73
  6. package/dist/domain/exceptions.d.ts +8 -4
  7. package/dist/domain/exceptions.js +12 -4
  8. package/dist/domain/repositories.d.ts +3 -2
  9. package/dist/domain/repositories.js +10 -1
  10. package/dist/factory.d.ts +15 -46
  11. package/dist/factory.js +18 -28
  12. package/dist/index.d.ts +6 -1
  13. package/dist/index.js +4 -1
  14. package/dist/infrastructure/blockchain/staticProvider.d.ts +3 -0
  15. package/dist/infrastructure/blockchain/staticProvider.js +36 -0
  16. package/dist/infrastructure/config/ProtocolTokenConfig.d.ts +0 -1
  17. package/dist/infrastructure/config/ProtocolTokenConfig.js +7 -5
  18. package/dist/infrastructure/config/gasOracleConfigs.d.ts +2 -13
  19. package/dist/infrastructure/config/gasOracleConfigs.js +7 -34
  20. package/dist/infrastructure/gas/GasPriceOracle.d.ts +14 -17
  21. package/dist/infrastructure/gas/GasPriceOracle.js +89 -44
  22. package/dist/infrastructure/mixerx/MixerXFeeOracle.d.ts +99 -0
  23. package/dist/infrastructure/mixerx/MixerXFeeOracle.js +292 -0
  24. package/dist/infrastructure/multicall/MulticallProvider.d.ts +9 -3
  25. package/dist/infrastructure/multicall/MulticallProvider.js +48 -10
  26. package/dist/infrastructure/token-price/TokenPriceOracle.d.ts +10 -47
  27. package/dist/infrastructure/token-price/TokenPriceOracle.js +75 -107
  28. package/dist/types.d.ts +11 -2
  29. package/dist/types.js +0 -1
  30. package/package.json +37 -15
  31. package/dist/application/ports/ILogger.d.ts.map +0 -1
  32. package/dist/application/ports/ILogger.js.map +0 -1
  33. package/dist/application/ports/index.d.ts +0 -6
  34. package/dist/application/ports/index.d.ts.map +0 -1
  35. package/dist/application/ports/index.js +0 -18
  36. package/dist/application/ports/index.js.map +0 -1
  37. package/dist/application/services/TokenPriceService.d.ts +0 -61
  38. package/dist/application/services/TokenPriceService.d.ts.map +0 -1
  39. package/dist/application/services/TokenPriceService.js +0 -137
  40. package/dist/application/services/TokenPriceService.js.map +0 -1
  41. package/dist/domain/config/TokenDefaults.d.ts.map +0 -1
  42. package/dist/domain/config/TokenDefaults.js.map +0 -1
  43. package/dist/domain/config/index.d.ts +0 -2
  44. package/dist/domain/config/index.d.ts.map +0 -1
  45. package/dist/domain/config/index.js +0 -20
  46. package/dist/domain/config/index.js.map +0 -1
  47. package/dist/domain/exceptions.d.ts.map +0 -1
  48. package/dist/domain/exceptions.js.map +0 -1
  49. package/dist/domain/repositories.d.ts.map +0 -1
  50. package/dist/domain/repositories.js.map +0 -1
  51. package/dist/factory.d.ts.map +0 -1
  52. package/dist/factory.js.map +0 -1
  53. package/dist/index.d.ts.map +0 -1
  54. package/dist/index.js.map +0 -1
  55. package/dist/infrastructure/blockchain/contracts.d.ts +0 -20
  56. package/dist/infrastructure/blockchain/contracts.d.ts.map +0 -1
  57. package/dist/infrastructure/blockchain/contracts.js +0 -10
  58. package/dist/infrastructure/blockchain/contracts.js.map +0 -1
  59. package/dist/infrastructure/config/ProtocolTokenConfig.d.ts.map +0 -1
  60. package/dist/infrastructure/config/ProtocolTokenConfig.js.map +0 -1
  61. package/dist/infrastructure/config/gasOracleConfigs.d.ts.map +0 -1
  62. package/dist/infrastructure/config/gasOracleConfigs.js.map +0 -1
  63. package/dist/infrastructure/config/index.d.ts +0 -5
  64. package/dist/infrastructure/config/index.d.ts.map +0 -1
  65. package/dist/infrastructure/config/index.js +0 -11
  66. package/dist/infrastructure/config/index.js.map +0 -1
  67. package/dist/infrastructure/gas/GasPriceOracle.d.ts.map +0 -1
  68. package/dist/infrastructure/gas/GasPriceOracle.js.map +0 -1
  69. package/dist/infrastructure/multicall/MulticallProvider.d.ts.map +0 -1
  70. package/dist/infrastructure/multicall/MulticallProvider.js.map +0 -1
  71. package/dist/infrastructure/token-price/TokenPriceOracle.d.ts.map +0 -1
  72. package/dist/infrastructure/token-price/TokenPriceOracle.js.map +0 -1
  73. package/dist/infrastructure/token-price/index.d.ts +0 -3
  74. package/dist/infrastructure/token-price/index.d.ts.map +0 -1
  75. package/dist/infrastructure/token-price/index.js +0 -6
  76. package/dist/infrastructure/token-price/index.js.map +0 -1
  77. package/dist/infrastructure/tornado/TornadoFeeOracle.d.ts +0 -90
  78. package/dist/infrastructure/tornado/TornadoFeeOracle.d.ts.map +0 -1
  79. package/dist/infrastructure/tornado/TornadoFeeOracle.js +0 -230
  80. package/dist/infrastructure/tornado/TornadoFeeOracle.js.map +0 -1
  81. package/dist/types.d.ts.map +0 -1
  82. package/dist/types.js.map +0 -1
@@ -3,10 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.resolveOffchainOracleAddress = resolveOffchainOracleAddress;
4
4
  exports.resolveDefaultTokens = resolveDefaultTokens;
5
5
  const config_1 = require("@mixerx/config");
6
+ const exceptions_1 = require("../../domain/exceptions");
7
+ const gasOracleConfigs_1 = require("./gasOracleConfigs");
6
8
  function toSupportedChainId(chainId) {
7
9
  const numericChainId = Number(chainId);
10
+ (0, gasOracleConfigs_1.assertSepoliaChainId)(numericChainId);
8
11
  if (!(0, config_1.isSupportedNetId)(numericChainId)) {
9
- throw new Error(`Unsupported chainId ${chainId} for @mixerx/config`);
12
+ throw new exceptions_1.OracleError('INVALID_CONFIG', `Unsupported chainId ${chainId} for @mixerx/config`);
10
13
  }
11
14
  return numericChainId;
12
15
  }
@@ -15,7 +18,7 @@ function resolveOffchainOracleAddress(chainId) {
15
18
  const network = (0, config_1.getNetworkConfig)(validatedChainId);
16
19
  const address = network?.contracts.offchainOracleAddress;
17
20
  if (!address) {
18
- throw new Error(`Missing offchainOracleAddress in @mixerx/config for chainId ${chainId}`);
21
+ throw new exceptions_1.OracleError('INVALID_CONFIG', `Missing offchainOracleAddress in @mixerx/config for chainId ${chainId}`);
19
22
  }
20
23
  return address;
21
24
  }
@@ -34,7 +37,7 @@ function resolveDefaultTokens(chainId) {
34
37
  }
35
38
  if (networkInstances) {
36
39
  for (const currencyData of Object.values(networkInstances)) {
37
- if (!currencyData.tokenAddress) {
40
+ if (currencyData.assetType !== 'erc20') {
38
41
  continue;
39
42
  }
40
43
  const tokenAddress = currencyData.tokenAddress.toLowerCase();
@@ -47,8 +50,7 @@ function resolveDefaultTokens(chainId) {
47
50
  }
48
51
  const tokens = Array.from(tokenMap.values());
49
52
  if (tokens.length === 0) {
50
- throw new Error(`No default tokens resolved from @mixerx/config for chainId ${chainId}`);
53
+ throw new exceptions_1.OracleError('INVALID_CONFIG', `No default tokens resolved from @mixerx/config for chainId ${chainId}`);
51
54
  }
52
55
  return tokens;
53
56
  }
54
- //# sourceMappingURL=ProtocolTokenConfig.js.map
@@ -1,14 +1,3 @@
1
- import { getNetworkConfig as getProtocolNetworkConfig } from '@mixerx/config';
2
1
  export type ChainId = number;
3
- export interface NetworkConfig {
4
- chainId: number;
5
- rpcUrl?: string;
6
- }
7
- export declare const NETWORKS: Record<number, NetworkConfig>;
8
- export declare function getNetworkConfig(chainId: ChainId): ReturnType<typeof getProtocolNetworkConfig>;
9
- export declare function isSupportedChain(chainId: number): boolean;
10
- export declare function getSupportedChainIds(): number[];
11
- export declare function getDefaultGasPrice(): number;
12
- export declare function getMaxGasPrice(): number;
13
- export declare function getRpcUrl(chainId: number): string | undefined;
14
- //# sourceMappingURL=gasOracleConfigs.d.ts.map
2
+ export declare const SEPOLIA_CHAIN_ID = 11155111;
3
+ export declare function assertSepoliaChainId(chainId: number): void;
@@ -1,38 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.NETWORKS = void 0;
4
- exports.getNetworkConfig = getNetworkConfig;
5
- exports.isSupportedChain = isSupportedChain;
6
- exports.getSupportedChainIds = getSupportedChainIds;
7
- exports.getDefaultGasPrice = getDefaultGasPrice;
8
- exports.getMaxGasPrice = getMaxGasPrice;
9
- exports.getRpcUrl = getRpcUrl;
10
- const config_1 = require("@mixerx/config");
11
- const SUPPORTED_CHAIN_IDS = [...config_1.SUPPORTED_NET_IDS];
12
- exports.NETWORKS = Object.fromEntries(SUPPORTED_CHAIN_IDS.map((chainId) => [chainId, { chainId }]));
13
- function getNetworkConfig(chainId) {
14
- if (!(0, config_1.isSupportedNetId)(chainId)) {
15
- return undefined;
3
+ exports.SEPOLIA_CHAIN_ID = void 0;
4
+ exports.assertSepoliaChainId = assertSepoliaChainId;
5
+ const exceptions_1 = require("../../domain/exceptions");
6
+ exports.SEPOLIA_CHAIN_ID = 11_155_111;
7
+ function assertSepoliaChainId(chainId) {
8
+ if (chainId !== exports.SEPOLIA_CHAIN_ID) {
9
+ throw new exceptions_1.OracleError('INVALID_CONFIG', `Unsupported chainId ${String(chainId)}; @mixerx/oracles is Sepolia-only`);
16
10
  }
17
- return (0, config_1.getNetworkConfig)(chainId);
18
11
  }
19
- function isSupportedChain(chainId) {
20
- return (0, config_1.isSupportedNetId)(chainId);
21
- }
22
- function getSupportedChainIds() {
23
- return [...SUPPORTED_CHAIN_IDS];
24
- }
25
- function getDefaultGasPrice() {
26
- return 20;
27
- }
28
- function getMaxGasPrice() {
29
- return 500;
30
- }
31
- function getRpcUrl(chainId) {
32
- const network = getNetworkConfig(chainId);
33
- if (!network || !('rpcUrl' in network) || typeof network.rpcUrl !== 'string') {
34
- return undefined;
35
- }
36
- return network.rpcUrl;
37
- }
38
- //# sourceMappingURL=gasOracleConfigs.js.map
@@ -1,41 +1,38 @@
1
1
  import type { ILogger } from '../../application/ports/ILogger';
2
2
  import type { ChainId } from '../config/gasOracleConfigs';
3
3
  export interface GasPriceParams {
4
+ effectiveGasPriceWei: string;
5
+ gasSource: 'rpc';
4
6
  gasPrice?: string;
7
+ baseFeePerGas?: string;
5
8
  maxFeePerGas?: string;
6
9
  maxPriorityFeePerGas?: string;
7
10
  }
8
11
  export interface GetTxGasParamsInput {
9
12
  isLegacy?: boolean;
10
13
  bumpPercent?: number;
11
- legacySpeed?: 'instant' | 'fast' | 'standard' | 'low';
12
14
  }
13
15
  export interface GasPriceOracleOptions {
14
16
  chainId: ChainId;
15
17
  rpcUrl: string;
16
18
  logger?: ILogger;
17
- fallbackGasPrices?: {
18
- legacy?: {
19
- instant: number;
20
- fast: number;
21
- standard: number;
22
- low: number;
23
- };
24
- eip1559?: {
25
- baseFee: number;
26
- maxFeePerGas: number;
27
- maxPriorityFeePerGas: number;
28
- };
29
- };
19
+ rpcTimeoutMs?: number;
20
+ maxGasPriceGwei?: number;
30
21
  }
31
22
  export declare class GasPriceOracle {
32
23
  private readonly provider;
33
24
  private readonly logger;
34
- private readonly fallback;
25
+ private readonly chainId;
26
+ private readonly maxGasPriceWei;
35
27
  constructor(options: GasPriceOracleOptions);
36
28
  getTxGasParams(input?: GetTxGasParamsInput): Promise<GasPriceParams>;
29
+ private validateGwei;
30
+ private validateBump;
37
31
  private bump;
38
32
  private toWeiGwei;
39
- private bumpGwei;
33
+ private cap;
34
+ private assertWithinMaximum;
35
+ private assertPositiveGasPrice;
36
+ private assertValidEip1559FeeData;
37
+ private min;
40
38
  }
41
- //# sourceMappingURL=GasPriceOracle.d.ts.map
@@ -1,77 +1,122 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.GasPriceOracle = void 0;
4
- const ethers_1 = require("ethers");
5
4
  const ILogger_1 = require("../../application/ports/ILogger");
5
+ const exceptions_1 = require("../../domain/exceptions");
6
+ const staticProvider_1 = require("../blockchain/staticProvider");
7
+ const DEFAULT_MAX_GAS_PRICE_GWEI = 500;
6
8
  class GasPriceOracle {
7
9
  provider;
8
10
  logger;
9
- fallback;
11
+ chainId;
12
+ maxGasPriceWei;
10
13
  constructor(options) {
11
- this.provider = new ethers_1.ethers.JsonRpcProvider(options.rpcUrl);
14
+ this.chainId = options.chainId;
15
+ this.provider = (0, staticProvider_1.createVerifiedJsonRpcProvider)(options.rpcUrl, options.chainId, { batchMaxCount: 1 }, options.rpcTimeoutMs);
12
16
  this.logger = options.logger ?? new ILogger_1.NullLogger();
13
- this.fallback = {
14
- legacy: options.fallbackGasPrices?.legacy ?? { instant: 35, fast: 25, standard: 20, low: 15 },
15
- eip1559: options.fallbackGasPrices?.eip1559 ?? { baseFee: 15, maxFeePerGas: 30, maxPriorityFeePerGas: 2 },
16
- };
17
+ const maxGasPriceGwei = options.maxGasPriceGwei ?? DEFAULT_MAX_GAS_PRICE_GWEI;
18
+ const validatedMaxGasPriceGwei = this.validateGwei(maxGasPriceGwei, 'maxGasPriceGwei');
19
+ if (validatedMaxGasPriceGwei === 0) {
20
+ throw new exceptions_1.OracleError('INVALID_CONFIG', 'maxGasPriceGwei must be greater than 0');
21
+ }
22
+ this.maxGasPriceWei = this.toWeiGwei(validatedMaxGasPriceGwei);
17
23
  }
18
24
  async getTxGasParams(input = {}) {
19
- const rawBumpPercent = Number(input.bumpPercent);
20
- const bumpPercent = Number.isFinite(rawBumpPercent)
21
- ? Math.max(0, Math.floor(rawBumpPercent))
22
- : 0;
25
+ const bumpPercent = this.validateBump(input.bumpPercent ?? 0);
23
26
  try {
24
- const feeData = await this.provider.getFeeData();
25
- if (!input.isLegacy && feeData.maxFeePerGas && feeData.maxPriorityFeePerGas) {
26
- const maxFeePerGas = this.bump(feeData.maxFeePerGas, bumpPercent);
27
- const maxPriorityFeePerGas = this.bump(feeData.maxPriorityFeePerGas, bumpPercent);
27
+ await (0, staticProvider_1.assertProviderNetwork)(this.provider, this.chainId);
28
+ const [feeData, block] = await Promise.all([
29
+ this.provider.getFeeData(),
30
+ this.provider.getBlock('latest'),
31
+ ]);
32
+ if (!input.isLegacy &&
33
+ feeData.maxFeePerGas !== null &&
34
+ feeData.maxPriorityFeePerGas !== null &&
35
+ block?.baseFeePerGas !== null &&
36
+ block?.baseFeePerGas !== undefined) {
37
+ this.assertValidEip1559FeeData(block.baseFeePerGas, feeData.maxFeePerGas, feeData.maxPriorityFeePerGas);
38
+ this.assertWithinMaximum(block.baseFeePerGas, 'base fee');
39
+ const baseFeePerGas = block.baseFeePerGas;
40
+ const maxPriorityFeePerGas = this.cap(this.bump(feeData.maxPriorityFeePerGas, bumpPercent));
41
+ const maxFeePerGas = this.cap(this.bump(feeData.maxFeePerGas, bumpPercent));
42
+ if (maxFeePerGas < baseFeePerGas) {
43
+ throw new exceptions_1.OracleError('RPC_REQUEST_FAILED', 'EIP-1559 fee cap is below the current base fee');
44
+ }
45
+ const cappedPriorityFeePerGas = this.min(maxPriorityFeePerGas, maxFeePerGas);
46
+ const effectiveGasPriceWei = this.min(baseFeePerGas + cappedPriorityFeePerGas, maxFeePerGas);
47
+ this.assertPositiveGasPrice(effectiveGasPriceWei);
28
48
  return {
49
+ baseFeePerGas: baseFeePerGas.toString(),
50
+ effectiveGasPriceWei: effectiveGasPriceWei.toString(),
51
+ gasSource: 'rpc',
29
52
  maxFeePerGas: maxFeePerGas.toString(),
30
- maxPriorityFeePerGas: maxPriorityFeePerGas.toString(),
53
+ maxPriorityFeePerGas: cappedPriorityFeePerGas.toString(),
31
54
  };
32
55
  }
33
- if (feeData.gasPrice) {
56
+ if (feeData.gasPrice !== null) {
57
+ this.assertWithinMaximum(feeData.gasPrice, 'legacy gas price');
58
+ const gasPrice = this.cap(this.bump(feeData.gasPrice, bumpPercent));
59
+ this.assertPositiveGasPrice(gasPrice);
34
60
  return {
35
- gasPrice: this.bump(feeData.gasPrice, bumpPercent).toString(),
61
+ effectiveGasPriceWei: gasPrice.toString(),
62
+ gasPrice: gasPrice.toString(),
63
+ gasSource: 'rpc',
36
64
  };
37
65
  }
66
+ throw new exceptions_1.OracleError('RPC_REQUEST_FAILED', 'Gas RPC response is incomplete');
38
67
  }
39
68
  catch (error) {
40
- this.logger.warn('GasPriceOracle failed to fetch gas price; using fallback', error);
69
+ if (error instanceof exceptions_1.OracleError &&
70
+ (error.code === 'NETWORK_MISMATCH' ||
71
+ error.code === 'RPC_REQUEST_FAILED' ||
72
+ error.code === 'ECONOMIC_LIMIT_EXCEEDED')) {
73
+ throw error;
74
+ }
75
+ this.logger.warn('Gas RPC request failed', { code: 'RPC_REQUEST_FAILED' });
76
+ throw new exceptions_1.OracleError('RPC_REQUEST_FAILED', 'Gas RPC request failed');
41
77
  }
42
- if (input.isLegacy) {
43
- const requestedSpeed = input.legacySpeed;
44
- const speed = requestedSpeed && Object.prototype.hasOwnProperty.call(this.fallback.legacy, requestedSpeed)
45
- ? requestedSpeed
46
- : 'fast';
47
- const bumpedLegacyGwei = this.bumpGwei(this.fallback.legacy[speed], bumpPercent);
48
- return { gasPrice: this.toWeiGwei(bumpedLegacyGwei).toString() };
78
+ }
79
+ validateGwei(value, name) {
80
+ if (!Number.isFinite(value) || value < 0 || value > DEFAULT_MAX_GAS_PRICE_GWEI) {
81
+ throw new exceptions_1.OracleError('INVALID_CONFIG', `${name} must be a finite number between 0 and ${String(DEFAULT_MAX_GAS_PRICE_GWEI)} gwei`);
49
82
  }
50
- const bumpedMaxFeePerGasGwei = this.bumpGwei(this.fallback.eip1559.maxFeePerGas, bumpPercent);
51
- const bumpedMaxPriorityFeePerGasGwei = this.bumpGwei(this.fallback.eip1559.maxPriorityFeePerGas, bumpPercent);
52
- return {
53
- maxFeePerGas: this.toWeiGwei(bumpedMaxFeePerGasGwei).toString(),
54
- maxPriorityFeePerGas: this.toWeiGwei(bumpedMaxPriorityFeePerGasGwei).toString(),
55
- };
83
+ return value;
56
84
  }
57
- bump(value, percent) {
58
- if (!percent) {
59
- return value;
85
+ validateBump(value) {
86
+ if (!Number.isFinite(value) || value < 0 || value > 100) {
87
+ throw new exceptions_1.OracleError('INVALID_INPUT', 'bumpPercent must be a finite number between 0 and 100');
60
88
  }
61
- return (value * BigInt(100 + percent)) / 100n;
89
+ return Math.floor(value);
90
+ }
91
+ bump(value, percent) {
92
+ return percent === 0 ? value : (value * BigInt(100 + percent)) / 100n;
62
93
  }
63
94
  toWeiGwei(gwei) {
64
- if (!Number.isFinite(gwei) || gwei < 0) {
65
- throw new Error(`Invalid fallbackGasPrices gwei value: ${String(gwei)}. Expected a finite non-negative number.`);
66
- }
67
95
  return BigInt(Math.round(gwei * 1e9));
68
96
  }
69
- bumpGwei(gwei, percent) {
70
- if (!percent) {
71
- return gwei;
97
+ cap(value) {
98
+ return this.min(value, this.maxGasPriceWei);
99
+ }
100
+ assertWithinMaximum(value, label) {
101
+ if (value > this.maxGasPriceWei) {
102
+ throw new exceptions_1.OracleError('ECONOMIC_LIMIT_EXCEEDED', `${label} exceeds maxGasPriceGwei`);
103
+ }
104
+ }
105
+ assertPositiveGasPrice(value) {
106
+ if (value <= 0n) {
107
+ throw new exceptions_1.OracleError('RPC_REQUEST_FAILED', 'Gas RPC response has no positive economic value');
72
108
  }
73
- return (gwei * (100 + percent)) / 100;
109
+ }
110
+ assertValidEip1559FeeData(baseFeePerGas, maxFeePerGas, maxPriorityFeePerGas) {
111
+ if (baseFeePerGas < 0n ||
112
+ maxFeePerGas <= 0n ||
113
+ maxPriorityFeePerGas < 0n ||
114
+ maxFeePerGas < maxPriorityFeePerGas) {
115
+ throw new exceptions_1.OracleError('RPC_REQUEST_FAILED', 'EIP-1559 RPC fee data is internally inconsistent');
116
+ }
117
+ }
118
+ min(left, right) {
119
+ return left < right ? left : right;
74
120
  }
75
121
  }
76
122
  exports.GasPriceOracle = GasPriceOracle;
77
- //# sourceMappingURL=GasPriceOracle.js.map
@@ -0,0 +1,99 @@
1
+ import type { ILogger } from '../../application/ports/ILogger';
2
+ import { type ITokenPriceRepository } from '../../domain/repositories';
3
+ import { GasPriceOracle, type GasPriceParams } from '../gas/GasPriceOracle';
4
+ import { type ChainId } from '../config/gasOracleConfigs';
5
+ import { TokenPriceOracle } from '../token-price/TokenPriceOracle';
6
+ export type MixerXTxType = 'relayer_withdrawal' | 'user_withdrawal' | 'relayer_withdrawal_check_v4';
7
+ export type MixerXGasPurpose = 'fee' | 'send' | 'replacement';
8
+ export type LegacyFeePurpose = 'fee_quote' | 'fee_validation';
9
+ export interface MixerXFeeOracleOptions {
10
+ chainId: ChainId;
11
+ rpcUrl: string;
12
+ relayerFeePercent: number;
13
+ gasPriceOracle?: GasPriceOracle;
14
+ tokenPriceOracle?: TokenPriceOracle;
15
+ priceRepository?: ITokenPriceRepository;
16
+ logger?: ILogger;
17
+ multicallAddress?: string;
18
+ offchainOracleAddress?: string;
19
+ rpcTimeoutMs?: number;
20
+ maxGasPriceGwei?: number;
21
+ maxPriceAgeMs?: number;
22
+ maxRefundWei?: bigint;
23
+ maxTotalFeeBps?: number;
24
+ priceBounds?: Readonly<Record<string, TokenPriceBounds>>;
25
+ }
26
+ export interface TokenPriceBounds {
27
+ minimumWeiPerToken: bigint;
28
+ maximumWeiPerToken: bigint;
29
+ }
30
+ export interface MixerXWithdrawalFeeInput {
31
+ currency: string;
32
+ amount: bigint;
33
+ decimals: number;
34
+ /** Gas limit obtained from a simulation or eth_estimateGas for this exact transaction. */
35
+ gasLimit: number;
36
+ refund?: string;
37
+ refundGasMultiplier?: number;
38
+ txType?: MixerXTxType;
39
+ purpose?: 'fee' | LegacyFeePurpose;
40
+ }
41
+ export interface MixerXGasParametersForTxInput {
42
+ txType?: MixerXTxType;
43
+ purpose?: MixerXGasPurpose | LegacyFeePurpose;
44
+ isLegacy?: boolean;
45
+ }
46
+ export interface MixerXGasParametersForTxResult extends GasPriceParams {
47
+ txType: MixerXTxType;
48
+ purpose: MixerXGasPurpose;
49
+ bumpPercent: number;
50
+ }
51
+ export interface MixerXFeeCalculationResult {
52
+ gasCost: bigint;
53
+ relayerFee: bigint;
54
+ refundAmount: bigint;
55
+ refundWei: bigint;
56
+ totalFee: bigint;
57
+ currency: string;
58
+ gasLimit: number;
59
+ gasPriceWei: bigint;
60
+ gasSource: 'rpc';
61
+ baseFeePerGas?: string;
62
+ maxFeePerGas?: string;
63
+ maxPriorityFeePerGas?: string;
64
+ gasPrice?: string;
65
+ tokenPriceInEth?: bigint;
66
+ priceSource: 'native' | 'repository';
67
+ priceObservedAtMs?: number;
68
+ bumpPercent: number;
69
+ txType: MixerXTxType;
70
+ gasPurpose: 'fee';
71
+ }
72
+ export type WithdrawalFeeInput = MixerXWithdrawalFeeInput;
73
+ export type FeeCalculationResult = MixerXFeeCalculationResult;
74
+ export declare class MixerXFeeOracle {
75
+ private readonly relayerFeePartsPerMillion;
76
+ private readonly gasPriceOracle;
77
+ private readonly tokenPriceOracle;
78
+ private readonly priceRepository?;
79
+ private readonly logger;
80
+ private readonly maxPriceAgeMs;
81
+ private readonly maxRefundWei;
82
+ private readonly maxTotalFeeBps;
83
+ private readonly currencyDecimals;
84
+ private readonly priceBounds;
85
+ constructor(options: MixerXFeeOracleOptions);
86
+ calculateWithdrawalFee(input: MixerXWithdrawalFeeInput): Promise<MixerXFeeCalculationResult>;
87
+ getGasParametersForTx(input?: MixerXGasParametersForTxInput): Promise<MixerXGasParametersForTxResult>;
88
+ assertReady(): Promise<void>;
89
+ private validateFeeInput;
90
+ private parseRefund;
91
+ private resolveRefundWei;
92
+ private getFreshPrice;
93
+ private validatePriceBounds;
94
+ private effectiveGasPrice;
95
+ private assertTotalFee;
96
+ private normalizePurpose;
97
+ private validateTxType;
98
+ private result;
99
+ }