@paraswap/dex-lib 3.11.5-cables.0 → 3.11.5-fluid-dex-changes.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.
- package/build/abi/fluid-dex/resolver.abi.json +731 -4
- package/build/dex/balancer-v2/balancer-v2.js +0 -1
- package/build/dex/balancer-v2/balancer-v2.js.map +1 -1
- package/build/dex/bebop/bebop.js +1 -1
- package/build/dex/bebop/bebop.js.map +1 -1
- package/build/dex/cables/cables.js +10 -2
- package/build/dex/cables/cables.js.map +1 -1
- package/build/dex/fluid-dex/config.js +1 -1
- package/build/dex/fluid-dex/fluid-dex-liquidity-proxy.js +28 -1
- package/build/dex/fluid-dex/fluid-dex-liquidity-proxy.js.map +1 -1
- package/build/dex/fluid-dex/fluid-dex.d.ts +17 -10
- package/build/dex/fluid-dex/fluid-dex.js +218 -67
- package/build/dex/fluid-dex/fluid-dex.js.map +1 -1
- package/build/dex/fluid-dex/types.d.ts +22 -2
- package/build/dex/index.js +0 -2
- package/build/dex/index.js.map +1 -1
- package/package.json +1 -1
- package/src/abi/fluid-dex/resolver.abi.json +731 -4
- package/src/dex/balancer-v2/balancer-v2-e2e.test.ts +0 -78
- package/src/dex/balancer-v2/balancer-v2.ts +0 -2
- package/src/dex/bebop/bebop.ts +1 -1
- package/src/dex/fluid-dex/config.ts +1 -1
- package/src/dex/fluid-dex/fluid-dex-e2e.test.ts +151 -3
- package/src/dex/fluid-dex/fluid-dex-events.test.ts +2 -4
- package/src/dex/fluid-dex/fluid-dex-integration.test.ts +79 -11
- package/src/dex/fluid-dex/fluid-dex-liquidity-proxy.ts +33 -0
- package/src/dex/fluid-dex/fluid-dex.ts +302 -104
- package/src/dex/fluid-dex/types.ts +25 -1
- package/src/dex/index.ts +0 -2
- package/tests/constants-e2e.ts +2 -2
- package/.env.example +0 -7
- package/src/abi/cables/CablesMainnetRFQ.json +0 -1083
- package/src/dex/cables/cables-e2e.test.ts +0 -171
- package/src/dex/cables/cables-integration.test.ts +0 -319
- package/src/dex/cables/cables.ts +0 -911
- package/src/dex/cables/config.ts +0 -13
- package/src/dex/cables/constants.ts +0 -35
- package/src/dex/cables/rate-fetcher.ts +0 -212
- package/src/dex/cables/types.ts +0 -128
- package/src/dex/cables/validators.test.ts +0 -151
- package/src/dex/cables/validators.ts +0 -61
|
@@ -20,6 +20,8 @@ import {
|
|
|
20
20
|
FluidDexData,
|
|
21
21
|
FluidDexPool,
|
|
22
22
|
Pool,
|
|
23
|
+
DexLimits,
|
|
24
|
+
TokenLimit,
|
|
23
25
|
} from './types';
|
|
24
26
|
import { SimpleExchange } from '../simple-exchange';
|
|
25
27
|
import FluidDexPoolABI from '../../abi/fluid-dex/fluid-dex.abi.json';
|
|
@@ -145,8 +147,6 @@ export class FluidDex extends SimpleExchange implements IDex<FluidDexData> {
|
|
|
145
147
|
side: SwapSide,
|
|
146
148
|
blockNumber: number,
|
|
147
149
|
): Promise<string[]> {
|
|
148
|
-
if (side === SwapSide.BUY) return [];
|
|
149
|
-
|
|
150
150
|
const pool = this.getPoolByTokenPair(srcToken.address, destToken.address);
|
|
151
151
|
return pool ? [pool.id] : [];
|
|
152
152
|
}
|
|
@@ -187,42 +187,53 @@ export class FluidDex extends SimpleExchange implements IDex<FluidDexData> {
|
|
|
187
187
|
try {
|
|
188
188
|
if (srcToken.address.toLowerCase() === destToken.address.toLowerCase())
|
|
189
189
|
return null;
|
|
190
|
-
|
|
191
|
-
if (side === SwapSide.BUY) return null;
|
|
192
190
|
// Get the pool to use.
|
|
193
191
|
const pool = this.getPoolByTokenPair(srcToken.address, destToken.address);
|
|
194
192
|
if (!pool) return null;
|
|
195
|
-
|
|
196
193
|
// Make sure the pool meets the optional limitPools filter.
|
|
197
194
|
if (limitPools && !limitPools.includes(pool.id)) return null;
|
|
198
195
|
|
|
199
196
|
const liquidityProxyState = await this.liquidityProxy.getStateOrGenerate(
|
|
200
197
|
blockNumber,
|
|
201
198
|
);
|
|
202
|
-
|
|
203
199
|
const currentPoolReserves = liquidityProxyState.poolsReserves.find(
|
|
204
200
|
poolReserve =>
|
|
205
201
|
poolReserve.pool.toLowerCase() === pool.address.toLowerCase(),
|
|
206
202
|
);
|
|
207
|
-
if (!currentPoolReserves)
|
|
208
|
-
|
|
203
|
+
if (!currentPoolReserves) {
|
|
204
|
+
return null;
|
|
205
|
+
}
|
|
209
206
|
const prices = amounts.map(amount => {
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
207
|
+
if (side == SwapSide.SELL) {
|
|
208
|
+
return this.swapIn(
|
|
209
|
+
srcToken.address.toLowerCase() === pool.token0.toLowerCase(),
|
|
210
|
+
amount,
|
|
211
|
+
currentPoolReserves.collateralReserves,
|
|
212
|
+
currentPoolReserves.debtReserves,
|
|
213
|
+
srcToken.decimals,
|
|
214
|
+
destToken.decimals,
|
|
215
|
+
BigInt(currentPoolReserves.fee),
|
|
216
|
+
currentPoolReserves.dexLimits,
|
|
217
|
+
Math.floor(Date.now() / 1000),
|
|
218
|
+
);
|
|
219
|
+
} else {
|
|
220
|
+
return this.swapOut(
|
|
221
|
+
srcToken.address.toLowerCase() === pool.token0.toLowerCase(),
|
|
222
|
+
amount,
|
|
223
|
+
currentPoolReserves.collateralReserves,
|
|
224
|
+
currentPoolReserves.debtReserves,
|
|
225
|
+
srcToken.decimals,
|
|
226
|
+
destToken.decimals,
|
|
227
|
+
BigInt(currentPoolReserves.fee),
|
|
228
|
+
currentPoolReserves.dexLimits,
|
|
229
|
+
Math.floor(Date.now() / 1000),
|
|
230
|
+
);
|
|
231
|
+
}
|
|
219
232
|
});
|
|
220
233
|
return [
|
|
221
234
|
{
|
|
222
235
|
prices: prices,
|
|
223
|
-
unit: getBigIntPow(
|
|
224
|
-
(side === SwapSide.SELL ? destToken : srcToken).decimals,
|
|
225
|
-
),
|
|
236
|
+
unit: getBigIntPow(destToken.decimals),
|
|
226
237
|
data: {},
|
|
227
238
|
exchange: this.dexKey,
|
|
228
239
|
poolIdentifier: pool.id,
|
|
@@ -237,7 +248,6 @@ export class FluidDex extends SimpleExchange implements IDex<FluidDexData> {
|
|
|
237
248
|
}, ${side}:`,
|
|
238
249
|
e,
|
|
239
250
|
);
|
|
240
|
-
|
|
241
251
|
return null;
|
|
242
252
|
}
|
|
243
253
|
}
|
|
@@ -259,8 +269,6 @@ export class FluidDex extends SimpleExchange implements IDex<FluidDexData> {
|
|
|
259
269
|
data: FluidDexData,
|
|
260
270
|
side: SwapSide,
|
|
261
271
|
): AdapterExchangeParam {
|
|
262
|
-
if (side === SwapSide.BUY) throw new Error(`Buy not supported`);
|
|
263
|
-
|
|
264
272
|
// Encode here the payload for adapter
|
|
265
273
|
const payload = '';
|
|
266
274
|
const pool = this.getPoolByTokenPair(srcToken, destToken);
|
|
@@ -293,29 +301,33 @@ export class FluidDex extends SimpleExchange implements IDex<FluidDexData> {
|
|
|
293
301
|
context: Context,
|
|
294
302
|
executorAddress: Address,
|
|
295
303
|
): Promise<DexExchangeParam> {
|
|
296
|
-
if (side === SwapSide.BUY) throw new Error(`Buy not supported`);
|
|
297
|
-
|
|
298
304
|
let args: any;
|
|
299
305
|
let returnAmountPos: number | undefined;
|
|
300
306
|
|
|
301
|
-
const method = 'swapIn';
|
|
307
|
+
const method = side == SwapSide.SELL ? 'swapIn' : 'swapOut';
|
|
302
308
|
|
|
303
309
|
returnAmountPos = extractReturnAmountPosition(
|
|
304
310
|
this.fluidDexPoolIface,
|
|
305
311
|
method,
|
|
306
|
-
'amountOut_',
|
|
312
|
+
side == SwapSide.SELL ? 'amountOut_' : 'amountIn_',
|
|
307
313
|
);
|
|
308
314
|
|
|
309
315
|
const pool = this.getPoolByTokenPair(srcToken, destToken);
|
|
310
316
|
|
|
311
|
-
if (
|
|
312
|
-
|
|
317
|
+
if (side == SwapSide.SELL) {
|
|
318
|
+
if (pool!.token0.toLowerCase() !== srcToken.toLowerCase()) {
|
|
319
|
+
args = [false, BigInt(srcAmount), BigInt(destAmount), recipient];
|
|
320
|
+
} else {
|
|
321
|
+
args = [true, BigInt(srcAmount), BigInt(destAmount), recipient];
|
|
322
|
+
}
|
|
313
323
|
} else {
|
|
314
|
-
|
|
324
|
+
if (pool!.token0.toLowerCase() !== srcToken.toLowerCase()) {
|
|
325
|
+
args = [false, BigInt(destAmount), BigInt(srcAmount), recipient];
|
|
326
|
+
} else {
|
|
327
|
+
args = [true, BigInt(destAmount), BigInt(srcAmount), recipient];
|
|
328
|
+
}
|
|
315
329
|
}
|
|
316
|
-
|
|
317
330
|
const swapData = this.fluidDexPoolIface.encodeFunctionData(method, args);
|
|
318
|
-
|
|
319
331
|
return {
|
|
320
332
|
needWrapNative: this.needWrapNative,
|
|
321
333
|
dexFuncHasRecipient: true,
|
|
@@ -335,7 +347,7 @@ export class FluidDex extends SimpleExchange implements IDex<FluidDexData> {
|
|
|
335
347
|
* @param outDecimals - The number of decimals for the output token.
|
|
336
348
|
* @returns The calculated output amount (as a BigInt).
|
|
337
349
|
*/
|
|
338
|
-
|
|
350
|
+
public swapIn(
|
|
339
351
|
swap0To1: boolean,
|
|
340
352
|
amountIn: bigint,
|
|
341
353
|
colReserves: CollateralReserves,
|
|
@@ -343,6 +355,8 @@ export class FluidDex extends SimpleExchange implements IDex<FluidDexData> {
|
|
|
343
355
|
inDecimals: number,
|
|
344
356
|
outDecimals: number,
|
|
345
357
|
fee: bigint,
|
|
358
|
+
currentLimits: DexLimits,
|
|
359
|
+
syncTime: number,
|
|
346
360
|
): bigint {
|
|
347
361
|
if (amountIn === 0n) {
|
|
348
362
|
return 0n; // Return 0 if input amount is 0
|
|
@@ -354,17 +368,19 @@ export class FluidDex extends SimpleExchange implements IDex<FluidDexData> {
|
|
|
354
368
|
return 0n;
|
|
355
369
|
}
|
|
356
370
|
const amountInAdjusted =
|
|
357
|
-
(amountIn *
|
|
358
|
-
|
|
371
|
+
(((amountIn * (this.FEE_100_PERCENT - fee)) / this.FEE_100_PERCENT) *
|
|
372
|
+
BigInt(10 ** 12)) /
|
|
373
|
+
BigInt(10 ** inDecimals);
|
|
359
374
|
const amountOut = this.swapInAdjusted(
|
|
360
375
|
swap0To1,
|
|
361
|
-
amountInAdjusted,
|
|
376
|
+
amountInAdjusted,
|
|
362
377
|
colReserves,
|
|
363
378
|
debtReserves,
|
|
364
|
-
|
|
379
|
+
outDecimals,
|
|
380
|
+
currentLimits,
|
|
381
|
+
syncTime,
|
|
365
382
|
);
|
|
366
|
-
|
|
367
|
-
return result;
|
|
383
|
+
return (amountOut * BigInt(10 ** outDecimals)) / BigInt(10 ** 12);
|
|
368
384
|
}
|
|
369
385
|
|
|
370
386
|
/**
|
|
@@ -375,12 +391,14 @@ export class FluidDex extends SimpleExchange implements IDex<FluidDexData> {
|
|
|
375
391
|
* @param debtReserves - The reserves of the debt pool.
|
|
376
392
|
* @returns The calculated output amount.
|
|
377
393
|
*/
|
|
378
|
-
|
|
394
|
+
public swapInAdjusted(
|
|
379
395
|
swap0To1: boolean,
|
|
380
396
|
amountToSwap: bigint,
|
|
381
397
|
colReserves: CollateralReserves,
|
|
382
398
|
debtReserves: DebtReserves,
|
|
383
|
-
|
|
399
|
+
outDecimals: number,
|
|
400
|
+
currentLimits: DexLimits,
|
|
401
|
+
syncTime: number,
|
|
384
402
|
): bigint {
|
|
385
403
|
const {
|
|
386
404
|
token0RealReserves,
|
|
@@ -388,7 +406,6 @@ export class FluidDex extends SimpleExchange implements IDex<FluidDexData> {
|
|
|
388
406
|
token0ImaginaryReserves,
|
|
389
407
|
token1ImaginaryReserves,
|
|
390
408
|
} = colReserves;
|
|
391
|
-
|
|
392
409
|
const {
|
|
393
410
|
token0RealReserves: debtToken0RealReserves,
|
|
394
411
|
token1RealReserves: debtToken1RealReserves,
|
|
@@ -398,26 +415,21 @@ export class FluidDex extends SimpleExchange implements IDex<FluidDexData> {
|
|
|
398
415
|
|
|
399
416
|
// Check if all reserves of collateral pool are greater than 0
|
|
400
417
|
const colPoolEnabled =
|
|
401
|
-
token0RealReserves >
|
|
402
|
-
token1RealReserves >
|
|
403
|
-
token0ImaginaryReserves >
|
|
404
|
-
token1ImaginaryReserves >
|
|
418
|
+
token0RealReserves > 0 &&
|
|
419
|
+
token1RealReserves > 0 &&
|
|
420
|
+
token0ImaginaryReserves > 0 &&
|
|
421
|
+
token1ImaginaryReserves > 0;
|
|
405
422
|
|
|
406
423
|
// Check if all reserves of debt pool are greater than 0
|
|
407
424
|
const debtPoolEnabled =
|
|
408
|
-
debtToken0RealReserves >
|
|
409
|
-
debtToken1RealReserves >
|
|
410
|
-
debtToken0ImaginaryReserves >
|
|
411
|
-
debtToken1ImaginaryReserves >
|
|
425
|
+
debtToken0RealReserves > 0 &&
|
|
426
|
+
debtToken1RealReserves > 0 &&
|
|
427
|
+
debtToken0ImaginaryReserves > 0 &&
|
|
428
|
+
debtToken1ImaginaryReserves > 0;
|
|
412
429
|
|
|
413
|
-
let colReserveIn
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
debtReserveOut: bigint;
|
|
417
|
-
let colIReserveIn: bigint,
|
|
418
|
-
colIReserveOut: bigint,
|
|
419
|
-
debtIReserveIn: bigint,
|
|
420
|
-
debtIReserveOut: bigint;
|
|
430
|
+
let colReserveIn, colReserveOut, debtReserveIn, debtReserveOut;
|
|
431
|
+
let colIReserveIn, colIReserveOut, debtIReserveIn, debtIReserveOut;
|
|
432
|
+
let borrowable, withdrawable;
|
|
421
433
|
|
|
422
434
|
if (swap0To1) {
|
|
423
435
|
colReserveIn = token0RealReserves;
|
|
@@ -428,6 +440,14 @@ export class FluidDex extends SimpleExchange implements IDex<FluidDexData> {
|
|
|
428
440
|
debtReserveOut = debtToken1RealReserves;
|
|
429
441
|
debtIReserveIn = debtToken0ImaginaryReserves;
|
|
430
442
|
debtIReserveOut = debtToken1ImaginaryReserves;
|
|
443
|
+
borrowable = this.getExpandedLimit(
|
|
444
|
+
syncTime,
|
|
445
|
+
currentLimits.borrowableToken1,
|
|
446
|
+
);
|
|
447
|
+
withdrawable = this.getExpandedLimit(
|
|
448
|
+
syncTime,
|
|
449
|
+
currentLimits.withdrawableToken1,
|
|
450
|
+
);
|
|
431
451
|
} else {
|
|
432
452
|
colReserveIn = token1RealReserves;
|
|
433
453
|
colReserveOut = token0RealReserves;
|
|
@@ -437,8 +457,21 @@ export class FluidDex extends SimpleExchange implements IDex<FluidDexData> {
|
|
|
437
457
|
debtReserveOut = debtToken0RealReserves;
|
|
438
458
|
debtIReserveIn = debtToken1ImaginaryReserves;
|
|
439
459
|
debtIReserveOut = debtToken0ImaginaryReserves;
|
|
460
|
+
borrowable = this.getExpandedLimit(
|
|
461
|
+
syncTime,
|
|
462
|
+
currentLimits.borrowableToken0,
|
|
463
|
+
);
|
|
464
|
+
withdrawable = this.getExpandedLimit(
|
|
465
|
+
syncTime,
|
|
466
|
+
currentLimits.withdrawableToken0,
|
|
467
|
+
);
|
|
440
468
|
}
|
|
441
469
|
|
|
470
|
+
// bring borrowable and withdrawable from token decimals to 1e12 decimals, same as amounts
|
|
471
|
+
borrowable = (borrowable * BigInt(10 ** 12)) / BigInt(10 ** outDecimals);
|
|
472
|
+
withdrawable =
|
|
473
|
+
(withdrawable * BigInt(10 ** 12)) / BigInt(10 ** outDecimals);
|
|
474
|
+
|
|
442
475
|
let a: bigint;
|
|
443
476
|
if (colPoolEnabled && debtPoolEnabled) {
|
|
444
477
|
a = this.swapRoutingIn(
|
|
@@ -449,39 +482,41 @@ export class FluidDex extends SimpleExchange implements IDex<FluidDexData> {
|
|
|
449
482
|
debtIReserveIn,
|
|
450
483
|
);
|
|
451
484
|
} else if (debtPoolEnabled) {
|
|
452
|
-
a =
|
|
485
|
+
a = -1n; // Route from debt pool
|
|
453
486
|
} else if (colPoolEnabled) {
|
|
454
|
-
a = amountToSwap +
|
|
487
|
+
a = amountToSwap + 1n; // Route from collateral pool
|
|
455
488
|
} else {
|
|
456
489
|
throw new Error('No pools are enabled');
|
|
457
490
|
}
|
|
458
491
|
|
|
459
|
-
let amountOutCollateral =
|
|
460
|
-
let amountOutDebt =
|
|
492
|
+
let amountOutCollateral = 0n;
|
|
493
|
+
let amountOutDebt = 0n;
|
|
494
|
+
let amountInCollateral = 0n;
|
|
495
|
+
let amountInDebt = 0n;
|
|
461
496
|
|
|
462
|
-
if (a <=
|
|
497
|
+
if (a <= 0n) {
|
|
463
498
|
// Entire trade routes through debt pool
|
|
499
|
+
amountInDebt = amountToSwap;
|
|
464
500
|
amountOutDebt = this.getAmountOut(
|
|
465
|
-
|
|
501
|
+
amountToSwap,
|
|
466
502
|
debtIReserveIn,
|
|
467
503
|
debtIReserveOut,
|
|
468
504
|
);
|
|
469
505
|
} else if (a >= amountToSwap) {
|
|
470
506
|
// Entire trade routes through collateral pool
|
|
507
|
+
amountInCollateral = amountToSwap;
|
|
471
508
|
amountOutCollateral = this.getAmountOut(
|
|
472
|
-
|
|
509
|
+
amountToSwap,
|
|
473
510
|
colIReserveIn,
|
|
474
511
|
colIReserveOut,
|
|
475
512
|
);
|
|
476
513
|
} else {
|
|
477
514
|
// Trade routes through both pools
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
colIReserveOut,
|
|
482
|
-
);
|
|
515
|
+
amountInCollateral = a;
|
|
516
|
+
amountOutCollateral = this.getAmountOut(a, colIReserveIn, colIReserveOut);
|
|
517
|
+
amountInDebt = amountToSwap - a;
|
|
483
518
|
amountOutDebt = this.getAmountOut(
|
|
484
|
-
|
|
519
|
+
amountInDebt,
|
|
485
520
|
debtIReserveIn,
|
|
486
521
|
debtIReserveOut,
|
|
487
522
|
);
|
|
@@ -490,17 +525,91 @@ export class FluidDex extends SimpleExchange implements IDex<FluidDexData> {
|
|
|
490
525
|
if (amountOutDebt > debtReserveOut) {
|
|
491
526
|
return 0n;
|
|
492
527
|
}
|
|
528
|
+
if (amountOutDebt > borrowable) {
|
|
529
|
+
return 0n;
|
|
530
|
+
}
|
|
493
531
|
|
|
494
532
|
if (amountOutCollateral > colReserveOut) {
|
|
495
533
|
return 0n;
|
|
496
534
|
}
|
|
535
|
+
|
|
536
|
+
if (amountOutCollateral > withdrawable) {
|
|
537
|
+
return 0n;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
// For price calculations, we'll use a precision factor for bigint division
|
|
541
|
+
const PRECISION = 1000000000000000000000000000n; // 1e27
|
|
542
|
+
|
|
543
|
+
let oldPrice: bigint;
|
|
544
|
+
let newPrice: bigint;
|
|
545
|
+
|
|
546
|
+
if (amountInCollateral > amountInDebt) {
|
|
547
|
+
// new pool price from col pool
|
|
548
|
+
oldPrice = swap0To1
|
|
549
|
+
? (colIReserveOut * PRECISION) / colIReserveIn
|
|
550
|
+
: (colIReserveIn * PRECISION) / colIReserveOut;
|
|
551
|
+
|
|
552
|
+
newPrice = swap0To1
|
|
553
|
+
? ((colIReserveOut - amountOutCollateral) * PRECISION) /
|
|
554
|
+
(colIReserveIn + amountInCollateral)
|
|
555
|
+
: ((colIReserveIn + amountInCollateral) * PRECISION) /
|
|
556
|
+
(colIReserveOut - amountOutCollateral);
|
|
557
|
+
} else {
|
|
558
|
+
// new pool price from debt pool
|
|
559
|
+
oldPrice = swap0To1
|
|
560
|
+
? (debtIReserveOut * PRECISION) / debtIReserveIn
|
|
561
|
+
: (debtIReserveIn * PRECISION) / debtIReserveOut;
|
|
562
|
+
|
|
563
|
+
newPrice = swap0To1
|
|
564
|
+
? ((debtIReserveOut - amountOutDebt) * PRECISION) /
|
|
565
|
+
(debtIReserveIn + amountInDebt)
|
|
566
|
+
: ((debtIReserveIn + amountInDebt) * PRECISION) /
|
|
567
|
+
(debtIReserveOut - amountOutDebt);
|
|
568
|
+
}
|
|
569
|
+
// Calculate price difference using bigint arithmetic
|
|
570
|
+
const MAX_PRICE_DIFF = 5n; // 5%
|
|
571
|
+
const priceDiff =
|
|
572
|
+
oldPrice > newPrice ? oldPrice - newPrice : newPrice - oldPrice;
|
|
573
|
+
const maxAllowedDiff = (oldPrice * MAX_PRICE_DIFF) / 100n;
|
|
574
|
+
|
|
575
|
+
if (priceDiff > maxAllowedDiff) {
|
|
576
|
+
return 0n;
|
|
577
|
+
}
|
|
497
578
|
const totalAmountOut = amountOutCollateral + amountOutDebt;
|
|
498
579
|
|
|
499
580
|
return totalAmountOut;
|
|
500
581
|
}
|
|
501
582
|
|
|
502
|
-
|
|
503
|
-
|
|
583
|
+
/**
|
|
584
|
+
* Calculates the currently available swappable amount for a token limit considering expansion since last syncTime.
|
|
585
|
+
* @param syncTime - timestamp in seconds when the limits were synced
|
|
586
|
+
* @param limit - token limit object containing available amount, expandsTo amount, and expandDuration
|
|
587
|
+
* @returns The calculated available swappable amount (borrowable or withdrawable)
|
|
588
|
+
*/
|
|
589
|
+
public getExpandedLimit(syncTime: number, limit: TokenLimit): bigint {
|
|
590
|
+
const currentTime = Math.floor(Date.now() / 1000); // convert milliseconds to seconds
|
|
591
|
+
const elapsedTime = currentTime - syncTime;
|
|
592
|
+
limit.expandsDuration = limit.expandsDuration || 0n;
|
|
593
|
+
if (elapsedTime < 10n) {
|
|
594
|
+
// if almost no time has elapsed, return available amount
|
|
595
|
+
return limit.available;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
if (elapsedTime >= limit.expandsDuration) {
|
|
599
|
+
// if duration has passed, return max amount
|
|
600
|
+
return limit.expandsTo;
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
// Calculate expansion ratio using bigint arithmetic
|
|
604
|
+
// Multiply by a large factor for precision in integer arithmetic
|
|
605
|
+
const PRECISION = 1000000;
|
|
606
|
+
const ratio = BigInt(elapsedTime * PRECISION) / limit.expandsDuration;
|
|
607
|
+
|
|
608
|
+
// Calculate expanded amount with precision factor
|
|
609
|
+
const expansion =
|
|
610
|
+
((limit.expandsTo - limit.available) * ratio) / BigInt(PRECISION);
|
|
611
|
+
const expandedAmount = limit.available + expansion;
|
|
612
|
+
return expandedAmount;
|
|
504
613
|
}
|
|
505
614
|
|
|
506
615
|
/**
|
|
@@ -510,7 +619,7 @@ export class FluidDex extends SimpleExchange implements IDex<FluidDexData> {
|
|
|
510
619
|
* @param iReserveOut - Imaginary token reserve of output amount.
|
|
511
620
|
* @returns The maximum output amount of the other asset.
|
|
512
621
|
*/
|
|
513
|
-
|
|
622
|
+
public getAmountOut(
|
|
514
623
|
amountIn: bigint,
|
|
515
624
|
iReserveIn: bigint,
|
|
516
625
|
iReserveOut: bigint,
|
|
@@ -532,7 +641,7 @@ export class FluidDex extends SimpleExchange implements IDex<FluidDexData> {
|
|
|
532
641
|
* @param iReserveOut - Imaginary token reserve of output amount.
|
|
533
642
|
* @returns The input amount of the other asset.
|
|
534
643
|
*/
|
|
535
|
-
|
|
644
|
+
public getAmountIn(
|
|
536
645
|
amountOut: bigint,
|
|
537
646
|
iReserveIn: bigint,
|
|
538
647
|
iReserveOut: bigint,
|
|
@@ -557,7 +666,7 @@ export class FluidDex extends SimpleExchange implements IDex<FluidDexData> {
|
|
|
557
666
|
* @note If a > t then entire trade route through col pool and col pool arbitrage with debt pool.
|
|
558
667
|
* @note If a > 0 & a < t then swap will route through both pools.
|
|
559
668
|
*/
|
|
560
|
-
|
|
669
|
+
public swapRoutingOut(
|
|
561
670
|
t: bigint,
|
|
562
671
|
x: bigint,
|
|
563
672
|
y: bigint,
|
|
@@ -594,7 +703,7 @@ export class FluidDex extends SimpleExchange implements IDex<FluidDexData> {
|
|
|
594
703
|
* @note If a > t then entire trade route through col pool and col pool arbitrage with debt pool.
|
|
595
704
|
* @note If a > 0 & a < t then swap will route through both pools.
|
|
596
705
|
*/
|
|
597
|
-
|
|
706
|
+
public swapRoutingIn(
|
|
598
707
|
t: bigint,
|
|
599
708
|
x: bigint,
|
|
600
709
|
y: bigint,
|
|
@@ -624,7 +733,7 @@ export class FluidDex extends SimpleExchange implements IDex<FluidDexData> {
|
|
|
624
733
|
* @param {number} fee - The fee for the swap. 1e4 = 1%
|
|
625
734
|
* @returns {bigint} amountIn - The calculated input amount required for the swap.
|
|
626
735
|
*/
|
|
627
|
-
|
|
736
|
+
public swapOut(
|
|
628
737
|
swap0to1: boolean,
|
|
629
738
|
amountOut: bigint,
|
|
630
739
|
colReserves: CollateralReserves,
|
|
@@ -632,6 +741,8 @@ export class FluidDex extends SimpleExchange implements IDex<FluidDexData> {
|
|
|
632
741
|
inDecimals: number,
|
|
633
742
|
outDecimals: number,
|
|
634
743
|
fee: bigint,
|
|
744
|
+
currentLimits: DexLimits,
|
|
745
|
+
syncTime: number,
|
|
635
746
|
): bigint {
|
|
636
747
|
const amountOutAdjusted =
|
|
637
748
|
(amountOut * BigInt(10 ** 12)) / BigInt(10 ** outDecimals);
|
|
@@ -640,15 +751,19 @@ export class FluidDex extends SimpleExchange implements IDex<FluidDexData> {
|
|
|
640
751
|
amountOutAdjusted,
|
|
641
752
|
colReserves,
|
|
642
753
|
debtReserves,
|
|
754
|
+
outDecimals,
|
|
755
|
+
currentLimits,
|
|
756
|
+
syncTime,
|
|
643
757
|
);
|
|
644
758
|
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
BigInt(10 **
|
|
650
|
-
|
|
651
|
-
|
|
759
|
+
if (amountIn == 2n ** 256n - 1n) {
|
|
760
|
+
return amountIn;
|
|
761
|
+
}
|
|
762
|
+
const ans =
|
|
763
|
+
(amountIn * this.FEE_100_PERCENT * BigInt(10 ** inDecimals)) /
|
|
764
|
+
BigInt(10 ** 12) /
|
|
765
|
+
(this.FEE_100_PERCENT - fee);
|
|
766
|
+
return ans;
|
|
652
767
|
}
|
|
653
768
|
|
|
654
769
|
/**
|
|
@@ -659,12 +774,18 @@ export class FluidDex extends SimpleExchange implements IDex<FluidDexData> {
|
|
|
659
774
|
* @param {DebtReserves} debtReserves - The reserves of the debt pool.
|
|
660
775
|
* @returns {bigint} The calculated input amount required for the swap.
|
|
661
776
|
*/
|
|
662
|
-
|
|
777
|
+
public swapOutAdjusted(
|
|
663
778
|
swap0to1: boolean,
|
|
664
779
|
amountOut: bigint,
|
|
665
780
|
colReserves: CollateralReserves,
|
|
666
781
|
debtReserves: DebtReserves,
|
|
782
|
+
outDecimals: number,
|
|
783
|
+
currentLimits: DexLimits,
|
|
784
|
+
syncTime: number,
|
|
667
785
|
): bigint {
|
|
786
|
+
if (amountOut === 0n) {
|
|
787
|
+
return 0n; // Return 0 if output amount is 0
|
|
788
|
+
}
|
|
668
789
|
const {
|
|
669
790
|
token0RealReserves,
|
|
670
791
|
token1RealReserves,
|
|
@@ -681,17 +802,17 @@ export class FluidDex extends SimpleExchange implements IDex<FluidDexData> {
|
|
|
681
802
|
|
|
682
803
|
// Check if all reserves of collateral pool are greater than 0
|
|
683
804
|
const colPoolEnabled =
|
|
684
|
-
token0RealReserves >
|
|
685
|
-
token1RealReserves >
|
|
686
|
-
token0ImaginaryReserves >
|
|
687
|
-
token1ImaginaryReserves >
|
|
805
|
+
token0RealReserves > BigInt(0) &&
|
|
806
|
+
token1RealReserves > BigInt(0) &&
|
|
807
|
+
token0ImaginaryReserves > BigInt(0) &&
|
|
808
|
+
token1ImaginaryReserves > BigInt(0);
|
|
688
809
|
|
|
689
810
|
// Check if all reserves of debt pool are greater than 0
|
|
690
811
|
const debtPoolEnabled =
|
|
691
|
-
debtToken0RealReserves >
|
|
692
|
-
debtToken1RealReserves >
|
|
693
|
-
debtToken0ImaginaryReserves >
|
|
694
|
-
debtToken1ImaginaryReserves >
|
|
812
|
+
debtToken0RealReserves > BigInt(0) &&
|
|
813
|
+
debtToken1RealReserves > BigInt(0) &&
|
|
814
|
+
debtToken0ImaginaryReserves > BigInt(0) &&
|
|
815
|
+
debtToken1ImaginaryReserves > BigInt(0);
|
|
695
816
|
|
|
696
817
|
let colReserveIn: bigint,
|
|
697
818
|
colReserveOut: bigint,
|
|
@@ -701,6 +822,7 @@ export class FluidDex extends SimpleExchange implements IDex<FluidDexData> {
|
|
|
701
822
|
colIReserveOut: bigint,
|
|
702
823
|
debtIReserveIn: bigint,
|
|
703
824
|
debtIReserveOut: bigint;
|
|
825
|
+
let borrowable: bigint, withdrawable: bigint;
|
|
704
826
|
|
|
705
827
|
if (swap0to1) {
|
|
706
828
|
colReserveIn = token0RealReserves;
|
|
@@ -711,6 +833,14 @@ export class FluidDex extends SimpleExchange implements IDex<FluidDexData> {
|
|
|
711
833
|
debtReserveOut = debtToken1RealReserves;
|
|
712
834
|
debtIReserveIn = debtToken0ImaginaryReserves;
|
|
713
835
|
debtIReserveOut = debtToken1ImaginaryReserves;
|
|
836
|
+
borrowable = this.getExpandedLimit(
|
|
837
|
+
syncTime,
|
|
838
|
+
currentLimits.borrowableToken1,
|
|
839
|
+
);
|
|
840
|
+
withdrawable = this.getExpandedLimit(
|
|
841
|
+
syncTime,
|
|
842
|
+
currentLimits.withdrawableToken1,
|
|
843
|
+
);
|
|
714
844
|
} else {
|
|
715
845
|
colReserveIn = token1RealReserves;
|
|
716
846
|
colReserveOut = token0RealReserves;
|
|
@@ -720,8 +850,21 @@ export class FluidDex extends SimpleExchange implements IDex<FluidDexData> {
|
|
|
720
850
|
debtReserveOut = debtToken0RealReserves;
|
|
721
851
|
debtIReserveIn = debtToken1ImaginaryReserves;
|
|
722
852
|
debtIReserveOut = debtToken0ImaginaryReserves;
|
|
853
|
+
borrowable = this.getExpandedLimit(
|
|
854
|
+
syncTime,
|
|
855
|
+
currentLimits.borrowableToken0,
|
|
856
|
+
);
|
|
857
|
+
withdrawable = this.getExpandedLimit(
|
|
858
|
+
syncTime,
|
|
859
|
+
currentLimits.withdrawableToken0,
|
|
860
|
+
);
|
|
723
861
|
}
|
|
724
862
|
|
|
863
|
+
// bring borrowable and withdrawable from token decimals to 1e12 decimals, same as amounts
|
|
864
|
+
borrowable = (borrowable * BigInt(10 ** 12)) / BigInt(10 ** outDecimals);
|
|
865
|
+
withdrawable =
|
|
866
|
+
(withdrawable * BigInt(10 ** 12)) / BigInt(10 ** outDecimals);
|
|
867
|
+
|
|
725
868
|
let a: bigint;
|
|
726
869
|
if (colPoolEnabled && debtPoolEnabled) {
|
|
727
870
|
a = this.swapRoutingOut(
|
|
@@ -732,51 +875,106 @@ export class FluidDex extends SimpleExchange implements IDex<FluidDexData> {
|
|
|
732
875
|
debtIReserveOut,
|
|
733
876
|
);
|
|
734
877
|
} else if (debtPoolEnabled) {
|
|
735
|
-
a = -
|
|
878
|
+
a = BigInt(-1); // Route from debt pool
|
|
736
879
|
} else if (colPoolEnabled) {
|
|
737
|
-
a = amountOut +
|
|
880
|
+
a = amountOut + BigInt(1); // Route from collateral pool
|
|
738
881
|
} else {
|
|
739
882
|
throw new Error('No pools are enabled');
|
|
740
883
|
}
|
|
741
884
|
|
|
742
|
-
let amountInCollateral =
|
|
743
|
-
let amountInDebt =
|
|
885
|
+
let amountInCollateral: bigint = BigInt(0);
|
|
886
|
+
let amountInDebt: bigint = BigInt(0);
|
|
887
|
+
let amountOutCollateral: bigint = BigInt(0);
|
|
888
|
+
let amountOutDebt: bigint = BigInt(0);
|
|
744
889
|
|
|
745
|
-
if (a <=
|
|
890
|
+
if (a <= BigInt(0)) {
|
|
746
891
|
// Entire trade routes through debt pool
|
|
892
|
+
amountOutDebt = amountOut;
|
|
747
893
|
amountInDebt = this.getAmountIn(
|
|
748
894
|
amountOut,
|
|
749
895
|
debtIReserveIn,
|
|
750
896
|
debtIReserveOut,
|
|
751
897
|
);
|
|
752
898
|
if (amountOut > debtReserveOut) {
|
|
753
|
-
return 2n **
|
|
899
|
+
return 2n ** 256n - 1n;
|
|
900
|
+
}
|
|
901
|
+
if (amountOut > borrowable) {
|
|
902
|
+
return 2n ** 256n - 1n;
|
|
754
903
|
}
|
|
755
904
|
} else if (a >= amountOut) {
|
|
756
905
|
// Entire trade routes through collateral pool
|
|
906
|
+
amountOutCollateral = amountOut;
|
|
757
907
|
amountInCollateral = this.getAmountIn(
|
|
758
908
|
amountOut,
|
|
759
909
|
colIReserveIn,
|
|
760
910
|
colIReserveOut,
|
|
761
911
|
);
|
|
762
912
|
if (amountOut > colReserveOut) {
|
|
763
|
-
return 2n **
|
|
913
|
+
return 2n ** 256n - 1n;
|
|
914
|
+
}
|
|
915
|
+
if (amountOut > withdrawable) {
|
|
916
|
+
return 2n ** 256n - 1n;
|
|
764
917
|
}
|
|
765
918
|
} else {
|
|
766
919
|
// Trade routes through both pools
|
|
920
|
+
amountOutCollateral = a;
|
|
767
921
|
amountInCollateral = this.getAmountIn(a, colIReserveIn, colIReserveOut);
|
|
922
|
+
amountOutDebt = amountOut - a;
|
|
768
923
|
amountInDebt = this.getAmountIn(
|
|
769
|
-
|
|
924
|
+
amountOutDebt,
|
|
770
925
|
debtIReserveIn,
|
|
771
926
|
debtIReserveOut,
|
|
772
927
|
);
|
|
773
|
-
if (
|
|
774
|
-
return 2n **
|
|
928
|
+
if (amountOutDebt > debtReserveOut || a > colReserveOut) {
|
|
929
|
+
return 2n ** 256n - 1n;
|
|
930
|
+
}
|
|
931
|
+
if (amountOutDebt > borrowable || a > withdrawable) {
|
|
932
|
+
return 2n ** 256n - 1n;
|
|
775
933
|
}
|
|
776
934
|
}
|
|
777
935
|
|
|
936
|
+
let oldPrice: bigint;
|
|
937
|
+
let newPrice: bigint;
|
|
938
|
+
const SCALE = BigInt(1e27);
|
|
939
|
+
|
|
940
|
+
// from whatever pool higher amount of swap is routing we are taking that as final price, does not matter much because both pools final price should be same
|
|
941
|
+
if (amountOutCollateral > amountOutDebt) {
|
|
942
|
+
// new pool price from col pool
|
|
943
|
+
oldPrice = swap0to1
|
|
944
|
+
? (colIReserveOut * SCALE) / colIReserveIn
|
|
945
|
+
: (colIReserveIn * SCALE) / colIReserveOut;
|
|
946
|
+
newPrice = swap0to1
|
|
947
|
+
? ((colIReserveOut - amountOutCollateral) * SCALE) /
|
|
948
|
+
(colIReserveIn + amountInCollateral)
|
|
949
|
+
: ((colIReserveIn + amountInCollateral) * SCALE) /
|
|
950
|
+
(colIReserveOut - amountOutCollateral);
|
|
951
|
+
} else {
|
|
952
|
+
// new pool price from debt pool
|
|
953
|
+
oldPrice = swap0to1
|
|
954
|
+
? (debtIReserveOut * SCALE) / debtIReserveIn
|
|
955
|
+
: (debtIReserveIn * SCALE) / debtIReserveOut;
|
|
956
|
+
newPrice = swap0to1
|
|
957
|
+
? ((debtIReserveOut - amountOutDebt) * SCALE) /
|
|
958
|
+
(debtIReserveIn + amountInDebt)
|
|
959
|
+
: ((debtIReserveIn + amountInDebt) * SCALE) /
|
|
960
|
+
(debtIReserveOut - amountOutDebt);
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
const MAX_PRICE_DIFF = BigInt(5); // 5%
|
|
964
|
+
if (
|
|
965
|
+
this.abs(oldPrice - newPrice) >
|
|
966
|
+
(oldPrice / BigInt(100)) * MAX_PRICE_DIFF
|
|
967
|
+
) {
|
|
968
|
+
// if price diff is > 5% then swap would revert.
|
|
969
|
+
return 2n ** 256n - 1n;
|
|
970
|
+
}
|
|
971
|
+
|
|
778
972
|
const totalAmountIn = amountInCollateral + amountInDebt;
|
|
779
973
|
|
|
780
974
|
return totalAmountIn;
|
|
781
975
|
}
|
|
976
|
+
|
|
977
|
+
private abs(value: bigint): bigint {
|
|
978
|
+
return value < 0 ? -value : value;
|
|
979
|
+
}
|
|
782
980
|
}
|