@paraswap/dex-lib 3.9.6 → 3.9.7-fluid-dex.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 (155) hide show
  1. package/.idea/aws.xml +17 -0
  2. package/.idea/codeStyles/Project.xml +19 -0
  3. package/.idea/codeStyles/codeStyleConfig.xml +5 -0
  4. package/.idea/misc.xml +6 -0
  5. package/.idea/modules.xml +8 -0
  6. package/.idea/paraswap-dex-lib.iml +9 -0
  7. package/.idea/prettier.xml +7 -0
  8. package/.idea/vcs.xml +6 -0
  9. package/build/abi/fluid-dex/dexFactory.abi.json +506 -0
  10. package/build/abi/fluid-dex/fluid-dex.abi.json +922 -0
  11. package/build/abi/fluid-dex/liquidityUserModule.abi.json +145 -0
  12. package/build/abi/fluid-dex/resolver.abi.json +999 -0
  13. package/build/abi/integral/factory.json +333 -0
  14. package/build/abi/integral/oracle.json +501 -0
  15. package/build/abi/{inception/inception-ineth-pool.json → integral/pool.json} +522 -543
  16. package/build/abi/{wombat/pool.json → integral/relayer.json} +720 -473
  17. package/build/dex/aave-v1/aave-v1.d.ts +1 -2
  18. package/build/dex/aave-v1/aave-v1.js +0 -23
  19. package/build/dex/aave-v1/aave-v1.js.map +1 -1
  20. package/build/dex/fluid-dex/config.d.ts +4 -0
  21. package/build/dex/fluid-dex/config.js +21 -0
  22. package/build/dex/fluid-dex/config.js.map +1 -0
  23. package/build/dex/fluid-dex/fluid-dex-generate-pool.d.ts +49 -0
  24. package/build/dex/fluid-dex/fluid-dex-generate-pool.js +104 -0
  25. package/build/dex/fluid-dex/fluid-dex-generate-pool.js.map +1 -0
  26. package/build/dex/fluid-dex/fluid-dex-pool.d.ts +47 -0
  27. package/build/dex/fluid-dex/fluid-dex-pool.js +119 -0
  28. package/build/dex/fluid-dex/fluid-dex-pool.js.map +1 -0
  29. package/build/dex/fluid-dex/fluid-dex.d.ts +128 -0
  30. package/build/dex/fluid-dex/fluid-dex.js +578 -0
  31. package/build/dex/fluid-dex/fluid-dex.js.map +1 -0
  32. package/build/dex/fluid-dex/types.d.ts +53 -0
  33. package/build/dex/{inception → fluid-dex}/types.js.map +1 -1
  34. package/build/dex/index.js +2 -0
  35. package/build/dex/index.js.map +1 -1
  36. package/build/dex/integral/config.d.ts +4 -0
  37. package/build/dex/integral/config.js +20 -0
  38. package/build/dex/integral/config.js.map +1 -0
  39. package/build/dex/integral/context.d.ts +40 -0
  40. package/build/dex/integral/context.js +158 -0
  41. package/build/dex/integral/context.js.map +1 -0
  42. package/build/dex/integral/integral-factory.d.ts +24 -0
  43. package/build/dex/integral/integral-factory.js +95 -0
  44. package/build/dex/integral/integral-factory.js.map +1 -0
  45. package/build/dex/integral/integral-pool.d.ts +50 -0
  46. package/build/dex/integral/integral-pool.js +149 -0
  47. package/build/dex/integral/integral-pool.js.map +1 -0
  48. package/build/dex/integral/integral-pricing.d.ts +18 -0
  49. package/build/dex/integral/integral-pricing.js +114 -0
  50. package/build/dex/integral/integral-pricing.js.map +1 -0
  51. package/build/dex/integral/integral-relayer.d.ts +42 -0
  52. package/build/dex/integral/integral-relayer.js +192 -0
  53. package/build/dex/integral/integral-relayer.js.map +1 -0
  54. package/build/dex/integral/integral-token.d.ts +27 -0
  55. package/build/dex/integral/integral-token.js +59 -0
  56. package/build/dex/integral/integral-token.js.map +1 -0
  57. package/build/dex/integral/integral.d.ts +41 -0
  58. package/build/dex/integral/integral.js +376 -0
  59. package/build/dex/integral/integral.js.map +1 -0
  60. package/build/dex/integral/types.d.ts +85 -0
  61. package/build/dex/integral/types.js +9 -0
  62. package/build/dex/integral/types.js.map +1 -0
  63. package/build/dex/integral/utils-e2e.d.ts +9 -0
  64. package/build/dex/integral/utils-e2e.js +131 -0
  65. package/build/dex/integral/utils-e2e.js.map +1 -0
  66. package/build/dex/integral/utils.d.ts +17 -0
  67. package/build/dex/integral/utils.js +94 -0
  68. package/build/dex/integral/utils.js.map +1 -0
  69. package/build/dex/jarvis.d.ts +1 -2
  70. package/build/dex/jarvis.js +0 -58
  71. package/build/dex/jarvis.js.map +1 -1
  72. package/build/dex/platypus/platypus.d.ts +1 -2
  73. package/build/dex/platypus/platypus.js +0 -45
  74. package/build/dex/platypus/platypus.js.map +1 -1
  75. package/build/dex/stable-pool.js +8 -1
  76. package/build/dex/stable-pool.js.map +1 -1
  77. package/build/dex/swaap-v1/swaap-v1.d.ts +1 -2
  78. package/build/dex/swaap-v1/swaap-v1.js +0 -14
  79. package/build/dex/swaap-v1/swaap-v1.js.map +1 -1
  80. package/build/dex/trader-joe-v2.1/optimizer.d.ts +2 -0
  81. package/build/dex/trader-joe-v2.1/optimizer.js +47 -0
  82. package/build/dex/trader-joe-v2.1/optimizer.js.map +1 -0
  83. package/build/dex/zerox/index.d.ts +26 -4
  84. package/build/dex/zerox/index.js +42 -50
  85. package/build/dex/zerox/index.js.map +1 -1
  86. package/build/dex/zerox/types.d.ts +0 -29
  87. package/build/dex/zerox/types.js +1 -8
  88. package/build/dex/zerox/types.js.map +1 -1
  89. package/package.json +1 -1
  90. package/src/abi/fluid-dex/dexFactory.abi.json +506 -0
  91. package/src/abi/fluid-dex/fluid-dex.abi.json +922 -0
  92. package/src/abi/fluid-dex/liquidityUserModule.abi.json +145 -0
  93. package/src/abi/fluid-dex/resolver.abi.json +999 -0
  94. package/src/dex/fluid-dex/config.ts +21 -0
  95. package/src/dex/fluid-dex/fluid-dex-e2e.test.ts +138 -0
  96. package/src/dex/fluid-dex/fluid-dex-events.test.ts +294 -0
  97. package/src/dex/fluid-dex/fluid-dex-generate-pool.ts +143 -0
  98. package/src/dex/fluid-dex/fluid-dex-integration.test.ts +225 -0
  99. package/src/dex/fluid-dex/fluid-dex-pool.ts +178 -0
  100. package/src/dex/fluid-dex/fluid-dex.ts +878 -0
  101. package/src/dex/fluid-dex/types.ts +63 -0
  102. package/src/dex/index.ts +2 -0
  103. package/tests/constants-e2e.d.ts +22 -0
  104. package/tests/constants-e2e.js +1942 -0
  105. package/tests/constants-e2e.js.map +1 -0
  106. package/tests/constants-e2e.ts +3 -2
  107. package/tests/smart-tokens.d.ts +36 -0
  108. package/tests/smart-tokens.js +64 -0
  109. package/tests/smart-tokens.js.map +1 -0
  110. package/.vscode/launch.json +0 -53
  111. package/.vscode/settings.json +0 -2
  112. package/.vscode/tasks.json +0 -15
  113. package/build/abi/inception/inception-ratio-feed.json +0 -329
  114. package/build/abi/inception/inception-vault.json +0 -991
  115. package/build/abi/uniswap-v3/AlienBaseV3Router.abi.json +0 -52
  116. package/build/dex/aave-v2/tokens-avalanche.json +0 -44
  117. package/build/dex/aave-v2/tokens-mainnet.json +0 -188
  118. package/build/dex/aave-v2/tokens-polygon.json +0 -44
  119. package/build/dex/inception/config.d.ts +0 -4
  120. package/build/dex/inception/config.js +0 -109
  121. package/build/dex/inception/config.js.map +0 -1
  122. package/build/dex/inception/inception-event-pool.d.ts +0 -16
  123. package/build/dex/inception/inception-event-pool.js +0 -49
  124. package/build/dex/inception/inception-event-pool.js.map +0 -1
  125. package/build/dex/inception/inception.d.ts +0 -43
  126. package/build/dex/inception/inception.js +0 -180
  127. package/build/dex/inception/inception.js.map +0 -1
  128. package/build/dex/inception/tokens.d.ts +0 -9
  129. package/build/dex/inception/tokens.js +0 -28
  130. package/build/dex/inception/tokens.js.map +0 -1
  131. package/build/dex/inception/types.d.ts +0 -22
  132. package/build/dex/inception/utils.d.ts +0 -7
  133. package/build/dex/inception/utils.js +0 -58
  134. package/build/dex/inception/utils.js.map +0 -1
  135. package/build/dex/maker-psm/scripts/gem.abi.json +0 -136
  136. package/build/dex/maker-psm/scripts/validate-state.d.ts +0 -0
  137. package/build/dex/maker-psm/scripts/validate-state.js +0 -185
  138. package/build/dex/maker-psm/scripts/validate-state.js.map +0 -1
  139. package/build/dex/maker-psm/scripts/vat.abi.json +0 -243
  140. package/build/dex/solidly-v3/scripts/check-event-pool-event.d.ts +0 -1
  141. package/build/dex/solidly-v3/scripts/check-event-pool-event.js +0 -53
  142. package/build/dex/solidly-v3/scripts/check-event-pool-event.js.map +0 -1
  143. package/build/dex/uniswap-v3/forks/alien-base-v3/alien-base-v3.d.ts +0 -17
  144. package/build/dex/uniswap-v3/forks/alien-base-v3/alien-base-v3.js +0 -64
  145. package/build/dex/uniswap-v3/forks/alien-base-v3/alien-base-v3.js.map +0 -1
  146. package/build/dex/uniswap-v3/forks/alien-v3/alien-v3.d.ts +0 -17
  147. package/build/dex/uniswap-v3/forks/alien-v3/alien-v3.js +0 -79
  148. package/build/dex/uniswap-v3/forks/alien-v3/alien-v3.js.map +0 -1
  149. package/build/dex/uniswap-v3/uniswap-v3-pricing.d.ts +0 -4
  150. package/build/dex/uniswap-v3/uniswap-v3-pricing.js +0 -43
  151. package/build/dex/uniswap-v3/uniswap-v3-pricing.js.map +0 -1
  152. package/build/dex/uniswap-v3/uniswap-v3-worker.d.ts +0 -1
  153. package/build/dex/uniswap-v3/uniswap-v3-worker.js +0 -10
  154. package/build/dex/uniswap-v3/uniswap-v3-worker.js.map +0 -1
  155. /package/build/dex/{inception → fluid-dex}/types.js +0 -0
@@ -0,0 +1,878 @@
1
+ import { BytesLike } from 'ethers/lib/utils';
2
+ import { Interface } from '@ethersproject/abi';
3
+ import {
4
+ Token,
5
+ Address,
6
+ ExchangePrices,
7
+ PoolPrices,
8
+ AdapterExchangeParam,
9
+ PoolLiquidity,
10
+ DexExchangeParam,
11
+ Logger,
12
+ } from '../../types';
13
+ import { SwapSide, Network } from '../../constants';
14
+ import * as CALLDATA_GAS_COST from '../../calldata-gas-cost';
15
+ import { Context, IDex } from '../../dex/idex';
16
+ import { IDexHelper } from '../../dex-helper/idex-helper';
17
+ import {
18
+ CollateralReserves,
19
+ DebtReserves,
20
+ FluidDexData,
21
+ FluidDexPool,
22
+ FluidDexPoolState,
23
+ Pool,
24
+ } from './types';
25
+ import { SimpleExchange } from '../simple-exchange';
26
+ import FluidDexPoolABI from '../../abi/fluid-dex/fluid-dex.abi.json';
27
+ import { FluidDexConfig, FLUID_DEX_GAS_COST } from './config';
28
+ import { FluidDexEventPool } from './fluid-dex-pool';
29
+ import { FluidDexCommonAddresses } from './fluid-dex-generate-pool';
30
+ import { getDexKeysWithNetwork, getBigIntPow } from '../../utils';
31
+ import { extractReturnAmountPosition } from '../../executor/utils';
32
+ import { MultiResult } from '../../lib/multi-wrapper';
33
+ import { generalDecoder } from '../../lib/decoders';
34
+ // @ts-ignore
35
+ import { Tokens } from '../../../tests/constants-e2e';
36
+
37
+ export class FluidDex extends SimpleExchange implements IDex<FluidDexData> {
38
+ eventPools: { [id: string]: FluidDexEventPool } = {};
39
+ readonly hasConstantPriceLargeAmounts = false;
40
+ readonly needWrapNative = false;
41
+ readonly isFeeOnTransferSupported = false;
42
+ public static dexKeysWithNetwork: { key: string; networks: Network[] }[] =
43
+ getDexKeysWithNetwork(FluidDexConfig);
44
+
45
+ logger: Logger;
46
+
47
+ pools: FluidDexPool[];
48
+
49
+ readonly fluidCommonAddresses: FluidDexCommonAddresses;
50
+
51
+ readonly fluidDexPoolIface: Interface;
52
+
53
+ FEE_100_PERCENT = BigInt(1000000);
54
+
55
+ constructor(
56
+ readonly network: Network,
57
+ readonly dexKey: string,
58
+ readonly dexHelper: IDexHelper,
59
+ ) {
60
+ super(dexHelper, dexKey);
61
+ this.logger = dexHelper.getLogger(dexKey);
62
+ this.fluidCommonAddresses = new FluidDexCommonAddresses(
63
+ 'FluidDex',
64
+ FluidDexConfig['FluidDex'][network].commonAddresses,
65
+ network,
66
+ dexHelper,
67
+ this.logger,
68
+ );
69
+ this.pools = FluidDexConfig['FluidDex'][network].pools;
70
+ this.fluidDexPoolIface = new Interface(FluidDexPoolABI);
71
+ }
72
+
73
+ private async fetchFluidDexPools(
74
+ blockNumber: number,
75
+ ): Promise<FluidDexPool[]> {
76
+ const poolsFromResolver =
77
+ await this.fluidCommonAddresses.getStateOrGenerate(blockNumber, false);
78
+ return poolsFromResolver.map(pool => ({
79
+ id: `FluidDex_${pool.address.toLowerCase()}`,
80
+ address: pool.address.toLowerCase(),
81
+ token0: pool.token0.toLowerCase(),
82
+ token1: pool.token1.toLowerCase(),
83
+ }));
84
+ }
85
+
86
+ async updatePoolAndEventPool(blockNumber: number) {
87
+ this.pools = await this.fetchFluidDexPools(blockNumber);
88
+ for (const pool of this.pools) {
89
+ if (!this.eventPools[pool.id]) {
90
+ this.eventPools[pool.id] = new FluidDexEventPool(
91
+ 'FluidDex',
92
+ pool.address,
93
+ this.fluidCommonAddresses.commonAddresses,
94
+ this.network,
95
+ this.dexHelper,
96
+ this.logger,
97
+ );
98
+ }
99
+ }
100
+ }
101
+
102
+ // Initialize pricing is called once in the start of
103
+ // pricing service. It is intended to setup the integration
104
+ // for pricing requests. It is optional for a DEX to
105
+ // implement this function
106
+ async initializePricing(blockNumber: number) {
107
+ await this.updatePoolAndEventPool(blockNumber);
108
+ }
109
+
110
+ getAdapters(side: SwapSide) {
111
+ return null;
112
+ }
113
+
114
+ decodePools = (result: MultiResult<BytesLike> | BytesLike): Pool[] => {
115
+ return generalDecoder(
116
+ result,
117
+ ['tuple(address pool, address token0, address token1)[]'],
118
+ undefined,
119
+ decoded => {
120
+ return decoded.map((decodedPool: any) => ({
121
+ address: decodedPool[0][0].toLowerCase(),
122
+ token0: decodedPool[0][1].toLowerCase(),
123
+ token1: decodedPool[0][2].toLowerCase(),
124
+ }));
125
+ },
126
+ );
127
+ };
128
+
129
+ // Returns list of pool identifiers that can be used
130
+ // for a given swap. poolIdentifiers must be unique
131
+ // across DEXes. It is recommended to use
132
+ // ${dexKey}_${poolAddress} as a poolIdentifier
133
+ async getPoolIdentifiers(
134
+ srcToken: Token,
135
+ destToken: Token,
136
+ side: SwapSide,
137
+ blockNumber: number,
138
+ ): Promise<string[]> {
139
+ await this.updatePoolAndEventPool(blockNumber);
140
+ const pool = await this.getPoolByTokenPair(
141
+ srcToken.address,
142
+ destToken.address,
143
+ );
144
+ return pool ? [pool.id] : [];
145
+ }
146
+
147
+ async getPoolByTokenPair(
148
+ srcToken: Address,
149
+ destToken: Address,
150
+ ): Promise<FluidDexPool | null> {
151
+ const srcAddress = srcToken.toLowerCase();
152
+ const destAddress = destToken.toLowerCase();
153
+
154
+ // A pair must have 2 different tokens.
155
+ if (srcAddress === destAddress) return null;
156
+
157
+ for (const pool of this.pools) {
158
+ if (
159
+ (srcAddress === pool.token0 && destAddress === pool.token1) ||
160
+ (srcAddress === pool.token1 && destAddress === pool.token0)
161
+ ) {
162
+ return pool;
163
+ }
164
+ }
165
+ return null;
166
+ }
167
+
168
+ // Returns pool prices for amounts.
169
+ // If limitPools is defined only pools in limitPools
170
+ // should be used. If limitPools is undefined then
171
+ // any pools can be used.
172
+ async getPricesVolume(
173
+ srcToken: Token,
174
+ destToken: Token,
175
+ amounts: bigint[],
176
+ side: SwapSide,
177
+ blockNumber: number,
178
+ limitPools?: string[],
179
+ ): Promise<null | ExchangePrices<FluidDexData>> {
180
+ await this.updatePoolAndEventPool(blockNumber);
181
+ try {
182
+ if (side === SwapSide.BUY) throw new Error(`Buy not supported`);
183
+ // Get the pool to use.
184
+ const pool = await this.getPoolByTokenPair(
185
+ srcToken.address,
186
+ destToken.address,
187
+ );
188
+ if (!pool) return null;
189
+
190
+ // Make sure the pool meets the optional limitPools filter.
191
+ if (limitPools && !limitPools.includes(pool.id)) return null;
192
+
193
+ const eventPool = this.eventPools[pool.id];
194
+
195
+ if (!eventPool) {
196
+ this.logger.error(`fluid-dex pool ${pool.id}: No EventPool found.`);
197
+
198
+ return null;
199
+ }
200
+
201
+ const state = await eventPool.getStateOrGenerate(blockNumber);
202
+
203
+ const prices = amounts.map(amount => {
204
+ return this.swapIn(
205
+ srcToken.address.toLowerCase() === pool.token0.toLowerCase(),
206
+ amount,
207
+ state.collateralReserves,
208
+ state.debtReserves,
209
+ srcToken.decimals,
210
+ destToken.decimals,
211
+ BigInt(state.fee),
212
+ );
213
+ });
214
+ return [
215
+ {
216
+ prices: prices,
217
+ unit: getBigIntPow(
218
+ (side === SwapSide.SELL ? destToken : srcToken).decimals,
219
+ ),
220
+ data: {
221
+ colReserves: state.collateralReserves,
222
+ debtReserves: state.debtReserves,
223
+ exchange: this.dexKey,
224
+ },
225
+ exchange: this.dexKey,
226
+ poolIdentifier: pool.id,
227
+ gasCost: FLUID_DEX_GAS_COST,
228
+ poolAddresses: [pool.address],
229
+ },
230
+ ];
231
+ } catch (e) {
232
+ this.logger.error(
233
+ `Error_getPricesVolume ${srcToken.address || srcToken.symbol}, ${
234
+ destToken.address || destToken.symbol
235
+ }, ${side}:`,
236
+ e,
237
+ );
238
+
239
+ return null;
240
+ }
241
+ }
242
+
243
+ // Returns estimated gas cost of calldata for this DEX in multiSwap
244
+ getCalldataGasCost(poolPrices: PoolPrices<FluidDexData>): number | number[] {
245
+ return CALLDATA_GAS_COST.DEX_NO_PAYLOAD;
246
+ }
247
+
248
+ // Encode params required by the exchange adapter
249
+ // V5: Used for multiSwap, buy & megaSwap
250
+ // V6: Not used, can be left blank
251
+ // Hint: abiCoder.encodeParameter() could be useful
252
+ getAdapterParam(
253
+ srcToken: string,
254
+ destToken: string,
255
+ srcAmount: string,
256
+ destAmount: string,
257
+ data: FluidDexData,
258
+ side: SwapSide,
259
+ ): AdapterExchangeParam {
260
+ if (side === SwapSide.BUY) throw new Error(`Buy not supported`);
261
+ const { exchange } = data;
262
+
263
+ // Encode here the payload for adapter
264
+ const payload = '';
265
+
266
+ return {
267
+ targetExchange: exchange,
268
+ payload,
269
+ networkFee: '0',
270
+ };
271
+ }
272
+
273
+ // This is called once before getTopPoolsForToken is
274
+ // called for multiple tokens. This can be helpful to
275
+ // update common state required for calculating
276
+ // getTopPoolsForToken. It is optional for a DEX
277
+ // to implement this
278
+ async updatePoolState(): Promise<void> {
279
+ this.initializePricing(await this.dexHelper.provider.getBlockNumber());
280
+ }
281
+
282
+ // Returns list of top pools based on liquidity. Max
283
+ // limit number pools should be returned.
284
+ async getTopPoolsForToken(
285
+ tokenAddress: Address,
286
+ limit: number,
287
+ ): Promise<PoolLiquidity[]> {
288
+ const latestBlockNumber_ = await this.dexHelper.provider.getBlockNumber();
289
+ let liquidityAmounts: { [id: string]: bigint } = {};
290
+ for (const pool of this.pools) {
291
+ if (
292
+ pool.token0 === tokenAddress.toLowerCase() ||
293
+ pool.token1 === tokenAddress.toLowerCase()
294
+ ) {
295
+ const state: FluidDexPoolState = await this.eventPools[
296
+ pool.id
297
+ ].getStateOrGenerate(latestBlockNumber_, false);
298
+
299
+ liquidityAmounts[pool.id] =
300
+ pool.token0 === tokenAddress
301
+ ? state.collateralReserves.token0RealReserves +
302
+ state.debtReserves.token0RealReserves
303
+ : state.collateralReserves.token1RealReserves +
304
+ state.debtReserves.token1RealReserves;
305
+ }
306
+ }
307
+
308
+ const entries = Object.entries(liquidityAmounts);
309
+
310
+ // Sort the entries based on the values in descending order
311
+ entries.sort((a, b) => {
312
+ if (b[1] > a[1]) return 1;
313
+ if (b[1] < a[1]) return -1;
314
+ return 0;
315
+ });
316
+
317
+ // Take the top k entries
318
+ const topKEntries = entries.slice(0, limit);
319
+
320
+ // Convert the array back to an object
321
+ const sortedAmounts = Object.fromEntries(topKEntries);
322
+
323
+ const poolLiquidities: PoolLiquidity[] = [];
324
+
325
+ for (const [id, amount] of Object.entries(sortedAmounts)) {
326
+ const pool = this.pools.find(p => p.id === id);
327
+ if (!pool) continue; // Skip if pool not found
328
+
329
+ const state: FluidDexPoolState = await this.eventPools[
330
+ pool.id
331
+ ].getStateOrGenerate(latestBlockNumber_, false);
332
+
333
+ let token0decimals: number;
334
+ for (const [networkStr, symbolMapping] of Object.entries(Tokens)) {
335
+ let found = false;
336
+ for (const [symbol, tokenParams] of Object.entries(symbolMapping)) {
337
+ if (tokenParams.address.toLowerCase() === pool.token0.toLowerCase()) {
338
+ token0decimals = tokenParams.decimals;
339
+ found = true;
340
+ break;
341
+ }
342
+ if (found) break;
343
+ }
344
+ }
345
+
346
+ let token1decimals: number;
347
+ for (const [networkStr, symbolMapping] of Object.entries(Tokens)) {
348
+ let found = false;
349
+ for (const [symbol, tokenParams] of Object.entries(symbolMapping)) {
350
+ if (tokenParams.address.toLowerCase() === pool.token1.toLowerCase()) {
351
+ token1decimals = tokenParams.decimals;
352
+ found = true;
353
+ break;
354
+ }
355
+ if (found) break;
356
+ }
357
+ }
358
+
359
+ const usd0 = await this.dexHelper.getTokenUSDPrice(
360
+ { address: pool.token0, decimals: token0decimals! },
361
+ state.collateralReserves.token0RealReserves +
362
+ state.debtReserves.token0RealReserves,
363
+ );
364
+
365
+ const usd1 = await this.dexHelper.getTokenUSDPrice(
366
+ { address: pool.token1, decimals: token1decimals! },
367
+ state.collateralReserves.token1RealReserves +
368
+ state.debtReserves.token1RealReserves,
369
+ );
370
+
371
+ poolLiquidities.push({
372
+ exchange: 'FluidDex',
373
+ address: pool.address,
374
+ connectorTokens: [],
375
+ liquidityUSD: Number(usd0 + usd1), // converted to number
376
+ });
377
+ }
378
+ return poolLiquidities;
379
+ }
380
+
381
+ async getDexParam(
382
+ srcToken: Address,
383
+ destToken: Address,
384
+ srcAmount: string,
385
+ destAmount: string,
386
+ recipient: Address,
387
+ data: FluidDexData,
388
+ side: SwapSide,
389
+ context: Context,
390
+ executorAddress: Address,
391
+ ): Promise<DexExchangeParam> {
392
+ const latestBlockNumber_ = await this.dexHelper.provider.getBlockNumber();
393
+ await this.updatePoolAndEventPool(latestBlockNumber_);
394
+
395
+ if (side === SwapSide.BUY) throw new Error(`Buy not supported`);
396
+
397
+ let args: any;
398
+ let returnAmountPos: number | undefined = undefined;
399
+
400
+ const method = 'swapIn';
401
+
402
+ returnAmountPos = extractReturnAmountPosition(
403
+ this.fluidDexPoolIface,
404
+ method,
405
+ 'amountOut_',
406
+ 1,
407
+ );
408
+
409
+ const pool = await this.getPoolByTokenPair(srcToken, destToken);
410
+
411
+ if (pool!.token0.toLowerCase() != srcToken.toLowerCase()) {
412
+ args = [false, BigInt(srcAmount), BigInt(destAmount), recipient];
413
+ } else {
414
+ args = [true, BigInt(srcAmount), BigInt(destAmount), recipient];
415
+ }
416
+
417
+ const swapData = this.fluidDexPoolIface.encodeFunctionData(method, args);
418
+
419
+ return {
420
+ needWrapNative: this.needWrapNative,
421
+ dexFuncHasRecipient: true,
422
+ exchangeData: swapData,
423
+ targetExchange: pool!.address,
424
+ returnAmountPos,
425
+ };
426
+ }
427
+
428
+ /**
429
+ * Calculates the output amount for a given input amount in a swap operation.
430
+ * @param swap0To1 - Direction of the swap. True if swapping token0 for token1, false otherwise.
431
+ * @param amountIn - The amount of input token to be swapped (as a BigInt).
432
+ * @param colReserves - The reserves of the collateral pool.
433
+ * @param debtReserves - The reserves of the debt pool.
434
+ * @param inDecimals - The number of decimals for the input token.
435
+ * @param outDecimals - The number of decimals for the output token.
436
+ * @returns The calculated output amount (as a BigInt).
437
+ */
438
+ private swapIn(
439
+ swap0To1: boolean,
440
+ amountIn: bigint,
441
+ colReserves: CollateralReserves,
442
+ debtReserves: DebtReserves,
443
+ inDecimals: number,
444
+ outDecimals: number,
445
+ fee: bigint,
446
+ ): bigint {
447
+ if (amountIn === 0n) {
448
+ return 0n; // Return 0 if input amount is 0
449
+ }
450
+ if (
451
+ colReserves.token0RealReserves + debtReserves.token0RealReserves == 0n &&
452
+ colReserves.token1RealReserves + debtReserves.token1RealReserves == 0n
453
+ ) {
454
+ return 0n;
455
+ }
456
+ const amountInAdjusted =
457
+ (((amountIn * (this.FEE_100_PERCENT - fee)) / this.FEE_100_PERCENT) *
458
+ BigInt(10 ** 12)) /
459
+ BigInt(10 ** inDecimals);
460
+
461
+ const amountOut = this.swapInAdjusted(
462
+ swap0To1,
463
+ amountInAdjusted, // Convert back to number for internal calculations
464
+ colReserves,
465
+ debtReserves,
466
+ );
467
+ const result = (amountOut * BigInt(10 ** outDecimals)) / BigInt(10 ** 12);
468
+ return result;
469
+ }
470
+
471
+ /**
472
+ * Calculates the output amount for a given input amount in a swap operation.
473
+ * @param swap0To1 - Direction of the swap. True if swapping token0 for token1, false otherwise.
474
+ * @param amountToSwap - The amount of input token to be swapped.
475
+ * @param colReserves - The reserves of the collateral pool.
476
+ * @param debtReserves - The reserves of the debt pool.
477
+ * @returns The calculated output amount.
478
+ */
479
+ private swapInAdjusted(
480
+ swap0To1: boolean,
481
+ amountToSwap: bigint,
482
+ colReserves: CollateralReserves,
483
+ debtReserves: DebtReserves,
484
+ ): bigint {
485
+ const {
486
+ token0RealReserves,
487
+ token1RealReserves,
488
+ token0ImaginaryReserves,
489
+ token1ImaginaryReserves,
490
+ } = colReserves;
491
+
492
+ const {
493
+ token0RealReserves: debtToken0RealReserves,
494
+ token1RealReserves: debtToken1RealReserves,
495
+ token0ImaginaryReserves: debtToken0ImaginaryReserves,
496
+ token1ImaginaryReserves: debtToken1ImaginaryReserves,
497
+ } = debtReserves;
498
+
499
+ // Check if all reserves of collateral pool are greater than 0
500
+ const colPoolEnabled =
501
+ token0RealReserves > BigInt(0) &&
502
+ token1RealReserves > BigInt(0) &&
503
+ token0ImaginaryReserves > BigInt(0) &&
504
+ token1ImaginaryReserves > BigInt(0);
505
+
506
+ // Check if all reserves of debt pool are greater than 0
507
+ const debtPoolEnabled =
508
+ debtToken0RealReserves > BigInt(0) &&
509
+ debtToken1RealReserves > BigInt(0) &&
510
+ debtToken0ImaginaryReserves > BigInt(0) &&
511
+ debtToken1ImaginaryReserves > BigInt(0);
512
+
513
+ let colReserveIn: bigint,
514
+ colReserveOut: bigint,
515
+ debtReserveIn: bigint,
516
+ debtReserveOut: bigint;
517
+ let colIReserveIn: bigint,
518
+ colIReserveOut: bigint,
519
+ debtIReserveIn: bigint,
520
+ debtIReserveOut: bigint;
521
+
522
+ if (swap0To1) {
523
+ colReserveIn = token0RealReserves;
524
+ colReserveOut = token1RealReserves;
525
+ colIReserveIn = token0ImaginaryReserves;
526
+ colIReserveOut = token1ImaginaryReserves;
527
+ debtReserveIn = debtToken0RealReserves;
528
+ debtReserveOut = debtToken1RealReserves;
529
+ debtIReserveIn = debtToken0ImaginaryReserves;
530
+ debtIReserveOut = debtToken1ImaginaryReserves;
531
+ } else {
532
+ colReserveIn = token1RealReserves;
533
+ colReserveOut = token0RealReserves;
534
+ colIReserveIn = token1ImaginaryReserves;
535
+ colIReserveOut = token0ImaginaryReserves;
536
+ debtReserveIn = debtToken1RealReserves;
537
+ debtReserveOut = debtToken0RealReserves;
538
+ debtIReserveIn = debtToken1ImaginaryReserves;
539
+ debtIReserveOut = debtToken0ImaginaryReserves;
540
+ }
541
+
542
+ let a: bigint;
543
+ if (colPoolEnabled && debtPoolEnabled) {
544
+ a = this.swapRoutingIn(
545
+ amountToSwap,
546
+ colIReserveOut,
547
+ colIReserveIn,
548
+ debtIReserveOut,
549
+ debtIReserveIn,
550
+ );
551
+ } else if (debtPoolEnabled) {
552
+ a = BigInt(-1); // Route from debt pool
553
+ } else if (colPoolEnabled) {
554
+ a = amountToSwap + BigInt(1); // Route from collateral pool
555
+ } else {
556
+ throw new Error('No pools are enabled');
557
+ }
558
+
559
+ let amountOutCollateral = BigInt(0);
560
+ let amountOutDebt = BigInt(0);
561
+
562
+ if (a <= BigInt(0)) {
563
+ // Entire trade routes through debt pool
564
+ amountOutDebt = this.getAmountOut(
565
+ amountToSwap,
566
+ debtIReserveIn,
567
+ debtIReserveOut,
568
+ );
569
+ } else if (a >= amountToSwap) {
570
+ // Entire trade routes through collateral pool
571
+ amountOutCollateral = this.getAmountOut(
572
+ amountToSwap,
573
+ colIReserveIn,
574
+ colIReserveOut,
575
+ );
576
+ } else {
577
+ // Trade routes through both pools
578
+ amountOutCollateral = this.getAmountOut(a, colIReserveIn, colIReserveOut);
579
+ amountOutDebt = this.getAmountOut(
580
+ amountToSwap - a,
581
+ debtIReserveIn,
582
+ debtIReserveOut,
583
+ );
584
+ }
585
+
586
+ if (amountOutDebt > debtReserveOut) {
587
+ return 0n;
588
+ }
589
+
590
+ if (amountOutCollateral > colReserveOut) {
591
+ return 0n;
592
+ }
593
+ const totalAmountOut = amountOutCollateral + amountOutDebt;
594
+
595
+ return totalAmountOut;
596
+ }
597
+
598
+ /**
599
+ * Given an input amount of asset and pair reserves, returns the maximum output amount of the other asset.
600
+ * @param amountIn - The amount of input asset.
601
+ * @param iReserveIn - Imaginary token reserve with input amount.
602
+ * @param iReserveOut - Imaginary token reserve of output amount.
603
+ * @returns The maximum output amount of the other asset.
604
+ */
605
+ private getAmountOut(
606
+ amountIn: bigint,
607
+ iReserveIn: bigint,
608
+ iReserveOut: bigint,
609
+ ): bigint {
610
+ // Both numerator and denominator are scaled to 1e6 to factor in fee scaling.
611
+ const numerator = amountIn * iReserveOut;
612
+ const denominator = iReserveIn + amountIn;
613
+
614
+ // Using the swap formula: (AmountIn * iReserveY) / (iReserveX + AmountIn)
615
+ // We use division with rounding down, which is the default for bigint division
616
+
617
+ return numerator / denominator;
618
+ }
619
+
620
+ /**
621
+ * Given an output amount of asset and pair reserves, returns the input amount of the other asset
622
+ * @param amountOut - Desired output amount of the asset.
623
+ * @param iReserveIn - Imaginary token reserve of input amount.
624
+ * @param iReserveOut - Imaginary token reserve of output amount.
625
+ * @returns The input amount of the other asset.
626
+ */
627
+ private getAmountIn(
628
+ amountOut: bigint,
629
+ iReserveIn: bigint,
630
+ iReserveOut: bigint,
631
+ ): bigint {
632
+ // Both numerator and denominator are scaled to 1e6 to factor in fee scaling.
633
+ const numerator = amountOut * iReserveIn;
634
+ const denominator = iReserveOut - amountOut;
635
+
636
+ // Using the swap formula: (AmountOut * iReserveX) / (iReserveY - AmountOut)
637
+ return numerator / denominator;
638
+ }
639
+
640
+ /**
641
+ * Calculates how much of a swap should go through the collateral pool for output amount.
642
+ * @param t - Total amount out.
643
+ * @param x - Imaginary reserves of token in of collateral.
644
+ * @param y - Imaginary reserves of token out of collateral.
645
+ * @param x2 - Imaginary reserves of token in of debt.
646
+ * @param y2 - Imaginary reserves of token out of debt.
647
+ * @returns How much swap should go through collateral pool. Remaining will go from debt.
648
+ * @note If a < 0 then entire trade route through debt pool and debt pool arbitrage with col pool.
649
+ * @note If a > t then entire trade route through col pool and col pool arbitrage with debt pool.
650
+ * @note If a > 0 & a < t then swap will route through both pools.
651
+ */
652
+ private swapRoutingOut(
653
+ t: bigint,
654
+ x: bigint,
655
+ y: bigint,
656
+ x2: bigint,
657
+ y2: bigint,
658
+ ): bigint {
659
+ // Adding 1e18 precision
660
+ const xyRoot = BigInt(
661
+ Math.floor(Math.sqrt(Number(x * y * BigInt(10n ** 18n)))),
662
+ );
663
+ const x2y2Root = BigInt(
664
+ Math.floor(Math.sqrt(Number(x2 * y2 * BigInt(10n ** 18n)))),
665
+ );
666
+
667
+ // 1e18 precision gets cancelled out in division
668
+ const numerator = t * xyRoot + y * x2y2Root - y2 * xyRoot;
669
+ const denominator = xyRoot + x2y2Root;
670
+
671
+ // Use integer division (rounds down)
672
+ const a = numerator / denominator;
673
+
674
+ return a;
675
+ }
676
+
677
+ /**
678
+ * Calculates how much of a swap should go through the collateral pool.
679
+ * @param t - Total amount in.
680
+ * @param x - Imaginary reserves of token out of collateral.
681
+ * @param y - Imaginary reserves of token in of collateral.
682
+ * @param x2 - Imaginary reserves of token out of debt.
683
+ * @param y2 - Imaginary reserves of token in of debt.
684
+ * @returns How much swap should go through collateral pool. Remaining will go from debt.
685
+ * @note If a < 0 then entire trade route through debt pool and debt pool arbitrage with col pool.
686
+ * @note If a > t then entire trade route through col pool and col pool arbitrage with debt pool.
687
+ * @note If a > 0 & a < t then swap will route through both pools.
688
+ */
689
+ private swapRoutingIn(
690
+ t: bigint,
691
+ x: bigint,
692
+ y: bigint,
693
+ x2: bigint,
694
+ y2: bigint,
695
+ ): bigint {
696
+ // Adding 1e18 precision
697
+
698
+ const xyRoot = BigInt(Math.floor(Math.sqrt(Number(x * y * BigInt(1e18)))));
699
+ const x2y2Root = BigInt(
700
+ Math.floor(Math.sqrt(Number(x2 * y2 * BigInt(1e18)))),
701
+ );
702
+
703
+ // Calculating 'a' using the given formula
704
+ const a =
705
+ (Number(y2) * Number(xyRoot) +
706
+ Number(t) * Number(xyRoot) -
707
+ Number(y) * Number(x2y2Root)) /
708
+ (Number(xyRoot) + Number(x2y2Root));
709
+ return BigInt(Math.floor(a));
710
+ }
711
+
712
+ /**
713
+ * Calculates the input amount for a given output amount in a swap operation.
714
+ * @param {boolean} swap0to1 - Direction of the swap. True if swapping token0 for token1, false otherwise.
715
+ * @param {bigint} amountOut - The amount of output token to be swapped.
716
+ * @param {Reserves} colReserves - The reserves of the collateral pool.
717
+ * @param {Reserves} debtReserves - The reserves of the debt pool.
718
+ * @param {number} inDecimals - The number of decimals for the input token.
719
+ * @param {number} outDecimals - The number of decimals for the output token.
720
+ * @param {number} fee - The fee for the swap. 1e4 = 1%
721
+ * @returns {bigint} amountIn - The calculated input amount required for the swap.
722
+ */
723
+ private swapOut(
724
+ swap0to1: boolean,
725
+ amountOut: bigint,
726
+ colReserves: CollateralReserves,
727
+ debtReserves: DebtReserves,
728
+ inDecimals: number,
729
+ outDecimals: number,
730
+ fee: bigint,
731
+ ): bigint {
732
+ const amountOutAdjusted =
733
+ (amountOut * BigInt(10 ** 12)) / BigInt(10 ** outDecimals);
734
+ const amountIn = this.swapOutAdjusted(
735
+ swap0to1,
736
+ amountOutAdjusted,
737
+ colReserves,
738
+ debtReserves,
739
+ );
740
+
741
+ const FEE_100_PERCENT = BigInt(1e6); // Assuming this constant is defined elsewhere
742
+
743
+ const result =
744
+ ((amountIn * FEE_100_PERCENT) / (FEE_100_PERCENT - fee)) *
745
+ BigInt(10 ** (inDecimals - 12));
746
+
747
+ return result;
748
+ }
749
+
750
+ /**
751
+ * Calculates the input amount for a given output amount in a swap operation.
752
+ * @param {boolean} swap0to1 - Direction of the swap. True if swapping token0 for token1, false otherwise.
753
+ * @param {bigint} amountOut - The amount of output token to be swapped.
754
+ * @param {CollateralReserves} colReserves - The reserves of the collateral pool.
755
+ * @param {DebtReserves} debtReserves - The reserves of the debt pool.
756
+ * @returns {bigint} The calculated input amount required for the swap.
757
+ */
758
+ private swapOutAdjusted(
759
+ swap0to1: boolean,
760
+ amountOut: bigint,
761
+ colReserves: CollateralReserves,
762
+ debtReserves: DebtReserves,
763
+ ): bigint {
764
+ const {
765
+ token0RealReserves,
766
+ token1RealReserves,
767
+ token0ImaginaryReserves,
768
+ token1ImaginaryReserves,
769
+ } = colReserves;
770
+
771
+ const {
772
+ token0RealReserves: debtToken0RealReserves,
773
+ token1RealReserves: debtToken1RealReserves,
774
+ token0ImaginaryReserves: debtToken0ImaginaryReserves,
775
+ token1ImaginaryReserves: debtToken1ImaginaryReserves,
776
+ } = debtReserves;
777
+
778
+ // Check if all reserves of collateral pool are greater than 0
779
+ const colPoolEnabled =
780
+ token0RealReserves > 0n &&
781
+ token1RealReserves > 0n &&
782
+ token0ImaginaryReserves > 0n &&
783
+ token1ImaginaryReserves > 0n;
784
+
785
+ // Check if all reserves of debt pool are greater than 0
786
+ const debtPoolEnabled =
787
+ debtToken0RealReserves > 0n &&
788
+ debtToken1RealReserves > 0n &&
789
+ debtToken0ImaginaryReserves > 0n &&
790
+ debtToken1ImaginaryReserves > 0n;
791
+
792
+ let colReserveIn: bigint,
793
+ colReserveOut: bigint,
794
+ debtReserveIn: bigint,
795
+ debtReserveOut: bigint;
796
+ let colIReserveIn: bigint,
797
+ colIReserveOut: bigint,
798
+ debtIReserveIn: bigint,
799
+ debtIReserveOut: bigint;
800
+
801
+ if (swap0to1) {
802
+ colReserveIn = token0RealReserves;
803
+ colReserveOut = token1RealReserves;
804
+ colIReserveIn = token0ImaginaryReserves;
805
+ colIReserveOut = token1ImaginaryReserves;
806
+ debtReserveIn = debtToken0RealReserves;
807
+ debtReserveOut = debtToken1RealReserves;
808
+ debtIReserveIn = debtToken0ImaginaryReserves;
809
+ debtIReserveOut = debtToken1ImaginaryReserves;
810
+ } else {
811
+ colReserveIn = token1RealReserves;
812
+ colReserveOut = token0RealReserves;
813
+ colIReserveIn = token1ImaginaryReserves;
814
+ colIReserveOut = token0ImaginaryReserves;
815
+ debtReserveIn = debtToken1RealReserves;
816
+ debtReserveOut = debtToken0RealReserves;
817
+ debtIReserveIn = debtToken1ImaginaryReserves;
818
+ debtIReserveOut = debtToken0ImaginaryReserves;
819
+ }
820
+
821
+ let a: bigint;
822
+ if (colPoolEnabled && debtPoolEnabled) {
823
+ a = this.swapRoutingOut(
824
+ amountOut,
825
+ colIReserveIn,
826
+ colIReserveOut,
827
+ debtIReserveIn,
828
+ debtIReserveOut,
829
+ );
830
+ } else if (debtPoolEnabled) {
831
+ a = -1n; // Route from debt pool
832
+ } else if (colPoolEnabled) {
833
+ a = amountOut + 1n; // Route from collateral pool
834
+ } else {
835
+ throw new Error('No pools are enabled');
836
+ }
837
+
838
+ let amountInCollateral = 0n;
839
+ let amountInDebt = 0n;
840
+
841
+ if (a <= 0n) {
842
+ // Entire trade routes through debt pool
843
+ amountInDebt = this.getAmountIn(
844
+ amountOut,
845
+ debtIReserveIn,
846
+ debtIReserveOut,
847
+ );
848
+ if (amountOut > debtReserveOut) {
849
+ return 2n ** 64n - 1n; // BigInt max value
850
+ }
851
+ } else if (a >= amountOut) {
852
+ // Entire trade routes through collateral pool
853
+ amountInCollateral = this.getAmountIn(
854
+ amountOut,
855
+ colIReserveIn,
856
+ colIReserveOut,
857
+ );
858
+ if (amountOut > colReserveOut) {
859
+ return 2n ** 64n - 1n; // BigInt max value
860
+ }
861
+ } else {
862
+ // Trade routes through both pools
863
+ amountInCollateral = this.getAmountIn(a, colIReserveIn, colIReserveOut);
864
+ amountInDebt = this.getAmountIn(
865
+ amountOut - a,
866
+ debtIReserveIn,
867
+ debtIReserveOut,
868
+ );
869
+ if (amountOut - a > debtReserveOut || a > debtReserveOut) {
870
+ return 2n ** 64n - 1n; // BigInt max value
871
+ }
872
+ }
873
+
874
+ const totalAmountIn = amountInCollateral + amountInDebt;
875
+
876
+ return totalAmountIn;
877
+ }
878
+ }