@paraswap/dex-lib 3.9.7-fluid-dex.1 → 3.9.7-fluid-dex.3

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.
@@ -3,7 +3,7 @@ import dotenv from 'dotenv';
3
3
  dotenv.config();
4
4
 
5
5
  import { FluidDexEventPool } from './fluid-dex-pool';
6
- import { FluidDexCommonAddresses } from './fluid-dex-generate-pool';
6
+ import { FluidDexFactory } from './fluid-dex-factory';
7
7
  import { FluidDex } from './fluid-dex';
8
8
  import { Network } from '../../constants';
9
9
  import { Address } from '../../types';
@@ -57,10 +57,10 @@ async function fetchPoolState(
57
57
  }
58
58
 
59
59
  async function fetchTotalPools(
60
- fluidCommonAddresses: FluidDexCommonAddresses,
60
+ factory: FluidDexFactory,
61
61
  blockNumber: number,
62
62
  ): Promise<DeepReadonly<Pool[]>> {
63
- return await fluidCommonAddresses.generateState(blockNumber);
63
+ return await factory.generateState(blockNumber);
64
64
  }
65
65
 
66
66
  async function delay(seconds: number): Promise<void> {
@@ -122,7 +122,7 @@ describe('FluidDex EventPool Mainnet', function () {
122
122
  };
123
123
 
124
124
  let fluidDexEventPool: FluidDexEventPool;
125
- let fluidDexCommonAddress: FluidDexCommonAddresses;
125
+ let factory: FluidDexFactory;
126
126
 
127
127
  Object.entries(poolUpdateEventsToTest).forEach(
128
128
  ([poolAddress, events]: [string, EventMappings]) => {
@@ -150,8 +150,7 @@ describe('FluidDex EventPool Mainnet', function () {
150
150
 
151
151
  console.log(forkId);
152
152
 
153
- const pools =
154
- fluidDex.fluidCommonAddresses.getState(blockNumber);
153
+ const pools = fluidDex.factory.getState(blockNumber);
155
154
  let pool: string | undefined;
156
155
 
157
156
  if (pools) {
@@ -266,7 +265,7 @@ describe('FluidDex EventPool Mainnet', function () {
266
265
  describe(`${eventName}`, () => {
267
266
  blockNumbers.forEach((blockNumber: number) => {
268
267
  it(`State after ${blockNumber}`, async function () {
269
- fluidDexCommonAddress = new FluidDexCommonAddresses(
268
+ factory = new FluidDexFactory(
270
269
  'FluidDex',
271
270
  fluidDexCommonAddressStruct,
272
271
  network,
@@ -275,10 +274,10 @@ describe('FluidDex EventPool Mainnet', function () {
275
274
  );
276
275
 
277
276
  await testEventSubscriber(
278
- fluidDexCommonAddress,
279
- fluidDexCommonAddress.addressesSubscribed,
277
+ factory,
278
+ factory.addressesSubscribed,
280
279
  (_blockNumber: number) =>
281
- fetchTotalPools(fluidDexCommonAddress, _blockNumber),
280
+ fetchTotalPools(factory, _blockNumber),
282
281
  blockNumber,
283
282
  `${dexKey}_${poolAddress}`,
284
283
  dexHelper.provider,
@@ -13,7 +13,7 @@ import { Address } from '../../types';
13
13
  import { generalDecoder } from '../../lib/decoders';
14
14
  import { Contract } from 'ethers';
15
15
 
16
- export class FluidDexCommonAddresses extends StatefulEventSubscriber<Pool[]> {
16
+ export class FluidDexFactory extends StatefulEventSubscriber<Pool[]> {
17
17
  handlers: {
18
18
  [event: string]: (
19
19
  event: any,
@@ -133,11 +133,6 @@ async function testPricingOnNetwork(
133
133
  pools,
134
134
  );
135
135
  expect(poolPrices).not.toBeNull();
136
- if (fluidDex.hasConstantPriceLargeAmounts) {
137
- checkConstantPoolPrices(poolPrices!, amounts, dexKey);
138
- } else {
139
- checkPoolPrices(poolPrices!, amounts, side, dexKey);
140
- }
141
136
 
142
137
  // Check if onchain pricing equals to calculated ones
143
138
  await checkOnChainPricing(
@@ -160,24 +155,6 @@ describe('FluidDex', function () {
160
155
 
161
156
  const tokens = Tokens[network];
162
157
 
163
- // Don't forget to update relevant tokens in constant-e2e.ts
164
- const srcTokenSymbol = 'wstETH';
165
- const destTokenSymbol = 'ETH';
166
-
167
- const amountsForSell = [
168
- 0n,
169
- 1n * BI_POWS[tokens[srcTokenSymbol].decimals - 10],
170
- 2n * BI_POWS[tokens[srcTokenSymbol].decimals - 10],
171
- 3n * BI_POWS[tokens[srcTokenSymbol].decimals - 10],
172
- 4n * BI_POWS[tokens[srcTokenSymbol].decimals - 10],
173
- 5n * BI_POWS[tokens[srcTokenSymbol].decimals - 10],
174
- 6n * BI_POWS[tokens[srcTokenSymbol].decimals - 10],
175
- 7n * BI_POWS[tokens[srcTokenSymbol].decimals - 10],
176
- 8n * BI_POWS[tokens[srcTokenSymbol].decimals - 10],
177
- 9n * BI_POWS[tokens[srcTokenSymbol].decimals - 10],
178
- 10n * BI_POWS[tokens[srcTokenSymbol].decimals - 10],
179
- ];
180
-
181
158
  beforeAll(async () => {
182
159
  blockNumber = await dexHelper.provider.getBlockNumber();
183
160
  fluidDex = new FluidDex(network, dexKey, dexHelper);
@@ -186,40 +163,98 @@ describe('FluidDex', function () {
186
163
  }
187
164
  });
188
165
 
189
- it('getPoolIdentifiers and getPricesVolume SELL', async function () {
190
- await testPricingOnNetwork(
191
- fluidDex,
192
- network,
193
- dexKey,
194
- blockNumber,
195
- srcTokenSymbol,
196
- destTokenSymbol,
197
- SwapSide.SELL,
198
- amountsForSell,
199
- 'estimateSwapIn',
200
- );
166
+ describe('wstETH -> ETH', () => {
167
+ const tokenASymbol = 'wstETH';
168
+ const tokenBSymbol = 'ETH';
169
+
170
+ const amountsForSell = [
171
+ 0n,
172
+ 1n * BI_POWS[8],
173
+ 2n * BI_POWS[8],
174
+ 3n * BI_POWS[8],
175
+ 4n * BI_POWS[8],
176
+ 5n * BI_POWS[8],
177
+ 6n * BI_POWS[8],
178
+ 7n * BI_POWS[8],
179
+ 8n * BI_POWS[8],
180
+ 9n * BI_POWS[8],
181
+ 10n * BI_POWS[8],
182
+ ];
183
+
184
+ it('wstETH -> ETH, getPoolIdentifiers and getPricesVolume SELL', async function () {
185
+ await testPricingOnNetwork(
186
+ fluidDex,
187
+ network,
188
+ dexKey,
189
+ blockNumber,
190
+ tokenASymbol,
191
+ tokenBSymbol,
192
+ SwapSide.SELL,
193
+ amountsForSell,
194
+ 'estimateSwapIn',
195
+ );
196
+ });
197
+
198
+ it('ETH -> wstETH, getPoolIdentifiers and getPricesVolume SELL', async function () {
199
+ await testPricingOnNetwork(
200
+ fluidDex,
201
+ network,
202
+ dexKey,
203
+ blockNumber,
204
+ tokenBSymbol,
205
+ tokenASymbol,
206
+ SwapSide.SELL,
207
+ amountsForSell,
208
+ 'estimateSwapIn',
209
+ );
210
+ });
201
211
  });
202
212
 
203
- it('getTopPoolsForToken', async function () {
204
- // We have to check without calling initializePricing, because
205
- // pool-tracker is not calling that function
206
- const newFluidDex = new FluidDex(network, dexKey, dexHelper);
207
- await newFluidDex.initializePricing(blockNumber);
208
- if (newFluidDex.updatePoolState) {
209
- await newFluidDex.updatePoolState();
210
- }
211
- const poolLiquidity = await newFluidDex.getTopPoolsForToken(
212
- tokens[srcTokenSymbol].address,
213
- 1,
214
- );
215
-
216
- if (!newFluidDex.hasConstantPriceLargeAmounts) {
217
- checkPoolsLiquidity(
218
- poolLiquidity,
219
- Tokens[network][srcTokenSymbol].address,
213
+ describe('USDC -> USDT', () => {
214
+ const tokenASymbol = 'USDC';
215
+ const tokenBSymbol = 'USDT';
216
+
217
+ const amountsForSell = [
218
+ 0n,
219
+ 1n * BI_POWS[6],
220
+ 2n * BI_POWS[6],
221
+ 3n * BI_POWS[6],
222
+ 4n * BI_POWS[6],
223
+ 5n * BI_POWS[6],
224
+ 6n * BI_POWS[6],
225
+ 7n * BI_POWS[6],
226
+ 8n * BI_POWS[6],
227
+ 9n * BI_POWS[6],
228
+ 10n * BI_POWS[6],
229
+ ];
230
+
231
+ it('USDC -> USDT getPoolIdentifiers and getPricesVolume SELL', async function () {
232
+ await testPricingOnNetwork(
233
+ fluidDex,
234
+ network,
220
235
  dexKey,
236
+ blockNumber,
237
+ tokenASymbol,
238
+ tokenBSymbol,
239
+ SwapSide.SELL,
240
+ amountsForSell,
241
+ 'estimateSwapIn',
221
242
  );
222
- }
243
+ });
244
+
245
+ it('USDT -> USDC getPoolIdentifiers and getPricesVolume SELL', async function () {
246
+ await testPricingOnNetwork(
247
+ fluidDex,
248
+ network,
249
+ dexKey,
250
+ blockNumber,
251
+ tokenBSymbol,
252
+ tokenASymbol,
253
+ SwapSide.SELL,
254
+ amountsForSell,
255
+ 'estimateSwapIn',
256
+ );
257
+ });
223
258
  });
224
259
  });
225
260
  });
@@ -26,7 +26,7 @@ import { SimpleExchange } from '../simple-exchange';
26
26
  import FluidDexPoolABI from '../../abi/fluid-dex/fluid-dex.abi.json';
27
27
  import { FluidDexConfig, FLUID_DEX_GAS_COST } from './config';
28
28
  import { FluidDexEventPool } from './fluid-dex-pool';
29
- import { FluidDexCommonAddresses } from './fluid-dex-generate-pool';
29
+ import { FluidDexFactory } from './fluid-dex-factory';
30
30
  import { getDexKeysWithNetwork, getBigIntPow } from '../../utils';
31
31
  import { extractReturnAmountPosition } from '../../executor/utils';
32
32
  import { MultiResult } from '../../lib/multi-wrapper';
@@ -42,9 +42,9 @@ export class FluidDex extends SimpleExchange implements IDex<FluidDexData> {
42
42
 
43
43
  logger: Logger;
44
44
 
45
- pools: FluidDexPool[];
45
+ pools: FluidDexPool[] = [];
46
46
 
47
- readonly fluidCommonAddresses: FluidDexCommonAddresses;
47
+ readonly factory: FluidDexFactory;
48
48
 
49
49
  readonly fluidDexPoolIface: Interface;
50
50
 
@@ -57,22 +57,23 @@ export class FluidDex extends SimpleExchange implements IDex<FluidDexData> {
57
57
  ) {
58
58
  super(dexHelper, dexKey);
59
59
  this.logger = dexHelper.getLogger(dexKey);
60
- this.fluidCommonAddresses = new FluidDexCommonAddresses(
60
+ this.factory = new FluidDexFactory(
61
61
  'FluidDex',
62
62
  FluidDexConfig['FluidDex'][network].commonAddresses,
63
63
  network,
64
64
  dexHelper,
65
65
  this.logger,
66
66
  );
67
- this.pools = FluidDexConfig['FluidDex'][network].pools;
68
67
  this.fluidDexPoolIface = new Interface(FluidDexPoolABI);
69
68
  }
70
69
 
71
70
  private async fetchFluidDexPools(
72
71
  blockNumber: number,
73
72
  ): Promise<FluidDexPool[]> {
74
- const poolsFromResolver =
75
- await this.fluidCommonAddresses.getStateOrGenerate(blockNumber, false);
73
+ const poolsFromResolver = await this.factory.getStateOrGenerate(
74
+ blockNumber,
75
+ false,
76
+ );
76
77
  return poolsFromResolver.map(pool => ({
77
78
  id: `FluidDex_${pool.address.toLowerCase()}`,
78
79
  address: pool.address.toLowerCase(),
@@ -81,28 +82,32 @@ export class FluidDex extends SimpleExchange implements IDex<FluidDexData> {
81
82
  }));
82
83
  }
83
84
 
84
- async updatePoolAndEventPool(blockNumber: number) {
85
+ // Initialize pricing is called once in the start of
86
+ // pricing service. It is intended to setup the integration
87
+ // for pricing requests. It is optional for a DEX to
88
+ // implement this function
89
+ async initializePricing(blockNumber: number) {
90
+ await this.factory.initialize(blockNumber);
85
91
  this.pools = await this.fetchFluidDexPools(blockNumber);
92
+
86
93
  for (const pool of this.pools) {
87
94
  if (!this.eventPools[pool.id]) {
88
95
  this.eventPools[pool.id] = new FluidDexEventPool(
89
96
  'FluidDex',
90
97
  pool.address,
91
- this.fluidCommonAddresses.commonAddresses,
98
+ this.factory.commonAddresses,
92
99
  this.network,
93
100
  this.dexHelper,
94
101
  this.logger,
95
102
  );
96
103
  }
97
104
  }
98
- }
99
105
 
100
- // Initialize pricing is called once in the start of
101
- // pricing service. It is intended to setup the integration
102
- // for pricing requests. It is optional for a DEX to
103
- // implement this function
104
- async initializePricing(blockNumber: number) {
105
- await this.updatePoolAndEventPool(blockNumber);
106
+ await Promise.all(
107
+ Object.values(this.eventPools).map(async eventPool => {
108
+ return eventPool.initialize(blockNumber);
109
+ }),
110
+ );
106
111
  }
107
112
 
108
113
  getAdapters(side: SwapSide) {
@@ -134,7 +139,6 @@ export class FluidDex extends SimpleExchange implements IDex<FluidDexData> {
134
139
  side: SwapSide,
135
140
  blockNumber: number,
136
141
  ): Promise<string[]> {
137
- await this.updatePoolAndEventPool(blockNumber);
138
142
  const pool = await this.getPoolByTokenPair(
139
143
  srcToken.address,
140
144
  destToken.address,
@@ -175,8 +179,10 @@ export class FluidDex extends SimpleExchange implements IDex<FluidDexData> {
175
179
  blockNumber: number,
176
180
  limitPools?: string[],
177
181
  ): Promise<null | ExchangePrices<FluidDexData>> {
178
- await this.updatePoolAndEventPool(blockNumber);
179
182
  try {
183
+ if (srcToken.address.toLowerCase() === destToken.address.toLowerCase())
184
+ return null;
185
+
180
186
  if (side === SwapSide.BUY) throw new Error(`Buy not supported`);
181
187
  // Get the pool to use.
182
188
  const pool = await this.getPoolByTokenPair(
@@ -196,7 +202,8 @@ export class FluidDex extends SimpleExchange implements IDex<FluidDexData> {
196
202
  return null;
197
203
  }
198
204
 
199
- const state = await eventPool.getStateOrGenerate(blockNumber);
205
+ const state = await eventPool.getState(blockNumber);
206
+ if (!state) return null;
200
207
 
201
208
  const prices = amounts.map(amount => {
202
209
  return this.swapIn(
@@ -268,113 +275,13 @@ export class FluidDex extends SimpleExchange implements IDex<FluidDexData> {
268
275
  };
269
276
  }
270
277
 
271
- // This is called once before getTopPoolsForToken is
272
- // called for multiple tokens. This can be helpful to
273
- // update common state required for calculating
274
- // getTopPoolsForToken. It is optional for a DEX
275
- // to implement this
276
- async updatePoolState(): Promise<void> {
277
- this.initializePricing(await this.dexHelper.provider.getBlockNumber());
278
- }
279
-
280
278
  // Returns list of top pools based on liquidity. Max
281
279
  // limit number pools should be returned.
282
280
  async getTopPoolsForToken(
283
281
  tokenAddress: Address,
284
282
  limit: number,
285
283
  ): Promise<PoolLiquidity[]> {
286
- // const latestBlockNumber_ = await this.dexHelper.provider.getBlockNumber();
287
- // let liquidityAmounts: { [id: string]: bigint } = {};
288
- // for (const pool of this.pools) {
289
- // if (
290
- // pool.token0 === tokenAddress.toLowerCase() ||
291
- // pool.token1 === tokenAddress.toLowerCase()
292
- // ) {
293
- // const state: FluidDexPoolState = await this.eventPools[
294
- // pool.id
295
- // ].getStateOrGenerate(latestBlockNumber_, false);
296
- //
297
- // liquidityAmounts[pool.id] =
298
- // pool.token0 === tokenAddress
299
- // ? state.collateralReserves.token0RealReserves +
300
- // state.debtReserves.token0RealReserves
301
- // : state.collateralReserves.token1RealReserves +
302
- // state.debtReserves.token1RealReserves;
303
- // }
304
- // }
305
- //
306
- // const entries = Object.entries(liquidityAmounts);
307
- //
308
- // // Sort the entries based on the values in descending order
309
- // entries.sort((a, b) => {
310
- // if (b[1] > a[1]) return 1;
311
- // if (b[1] < a[1]) return -1;
312
- // return 0;
313
- // });
314
- //
315
- // // Take the top k entries
316
- // const topKEntries = entries.slice(0, limit);
317
- //
318
- // // Convert the array back to an object
319
- // const sortedAmounts = Object.fromEntries(topKEntries);
320
- //
321
- // const poolLiquidities: PoolLiquidity[] = [];
322
- //
323
- // for (const [id, amount] of Object.entries(sortedAmounts)) {
324
- // const pool = this.pools.find(p => p.id === id);
325
- // if (!pool) continue; // Skip if pool not found
326
- //
327
- // const state: FluidDexPoolState = await this.eventPools[
328
- // pool.id
329
- // ].getStateOrGenerate(latestBlockNumber_, false);
330
- //
331
- // // let token0decimals: number;
332
- // // for (const [networkStr, symbolMapping] of Object.entries(Tokens)) {
333
- // // let found = false;
334
- // // for (const [symbol, tokenParams] of Object.entries(symbolMapping)) {
335
- // // if (tokenParams.address.toLowerCase() === pool.token0.toLowerCase()) {
336
- // // token0decimals = tokenParams.decimals;
337
- // // found = true;
338
- // // break;
339
- // // }
340
- // // if (found) break;
341
- // // }
342
- // // }
343
- // //
344
- // // let token1decimals: number;
345
- // // for (const [networkStr, symbolMapping] of Object.entries(Tokens)) {
346
- // // let found = false;
347
- // // for (const [symbol, tokenParams] of Object.entries(symbolMapping)) {
348
- // // if (tokenParams.address.toLowerCase() === pool.token1.toLowerCase()) {
349
- // // token1decimals = tokenParams.decimals;
350
- // // found = true;
351
- // // break;
352
- // // }
353
- // // if (found) break;
354
- // // }
355
- // // }
356
- //
357
- // const usd0 = await this.dexHelper.getTokenUSDPrice(
358
- // { address: pool.token0, decimals: token0decimals! },
359
- // state.collateralReserves.token0RealReserves +
360
- // state.debtReserves.token0RealReserves,
361
- // );
362
- //
363
- // const usd1 = await this.dexHelper.getTokenUSDPrice(
364
- // { address: pool.token1, decimals: token1decimals! },
365
- // state.collateralReserves.token1RealReserves +
366
- // state.debtReserves.token1RealReserves,
367
- // );
368
- //
369
- // poolLiquidities.push({
370
- // exchange: 'FluidDex',
371
- // address: pool.address,
372
- // connectorTokens: [],
373
- // liquidityUSD: Number(usd0 + usd1), // converted to number
374
- // });
375
- // }
376
- // return poolLiquidities;
377
-
284
+ //@TODO
378
285
  return [];
379
286
  }
380
287
 
@@ -389,13 +296,10 @@ export class FluidDex extends SimpleExchange implements IDex<FluidDexData> {
389
296
  context: Context,
390
297
  executorAddress: Address,
391
298
  ): Promise<DexExchangeParam> {
392
- const latestBlockNumber_ = await this.dexHelper.provider.getBlockNumber();
393
- await this.updatePoolAndEventPool(latestBlockNumber_);
394
-
395
299
  if (side === SwapSide.BUY) throw new Error(`Buy not supported`);
396
300
 
397
301
  let args: any;
398
- let returnAmountPos: number | undefined = undefined;
302
+ let returnAmountPos: number | undefined;
399
303
 
400
304
  const method = 'swapIn';
401
305
 
@@ -408,7 +312,7 @@ export class FluidDex extends SimpleExchange implements IDex<FluidDexData> {
408
312
 
409
313
  const pool = await this.getPoolByTokenPair(srcToken, destToken);
410
314
 
411
- if (pool!.token0.toLowerCase() != srcToken.toLowerCase()) {
315
+ if (pool!.token0.toLowerCase() !== srcToken.toLowerCase()) {
412
316
  args = [false, BigInt(srcAmount), BigInt(destAmount), recipient];
413
317
  } else {
414
318
  args = [true, BigInt(srcAmount), BigInt(destAmount), recipient];
@@ -47,7 +47,6 @@ export type FluidDexPool = {
47
47
 
48
48
  export type DexParams = {
49
49
  commonAddresses: CommonAddresses;
50
- pools: FluidDexPool[];
51
50
  };
52
51
 
53
52
  export type CommonAddresses = {
@@ -1,22 +0,0 @@
1
- import { SmartTokenParams, SmartToken } from '../tests/smart-tokens';
2
- import { Address } from '../src/types';
3
- export declare const GIFTER_ADDRESS = "0xb22fC4eC94D555A5049593ca4552c810Fb8a6d00";
4
- export declare const GENERIC_ADDR1 = "0xbe9317f6711e2da074fe1f168fd9c402bc0a9d1b";
5
- export declare const GENERIC_ADDR2 = "0x230a1ac45690b9ae1176389434610b9526d2f21b";
6
- export declare const Tokens: {
7
- [network: number]: {
8
- [symbol: string]: SmartTokenParams;
9
- };
10
- };
11
- export declare const Holders: {
12
- [network: number]: {
13
- [tokenAddress: string]: Address;
14
- };
15
- };
16
- export declare const SmartTokens: Record<number, Record<string, SmartToken>>;
17
- export declare const NativeTokenSymbols: {
18
- [network: number]: string;
19
- };
20
- export declare const WrappedNativeTokenSymbols: {
21
- [network: number]: string;
22
- };