@dhedge/v2-sdk 1.2.1 → 1.4.1
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/dist/config.d.ts +5 -0
- package/dist/entities/pool.d.ts +98 -7
- package/dist/entities/utils.d.ts +7 -1
- package/dist/services/uniswap/V3Liquidity.d.ts +9 -0
- package/dist/services/uniswap/V3Trade.d.ts +4 -0
- package/dist/services/uniswap/types.d.ts +3 -0
- package/dist/test/constants.d.ts +5 -2
- package/dist/test/txOptions.d.ts +1 -0
- package/dist/types.d.ts +19 -10
- package/dist/v2-sdk.cjs.development.js +3796 -679
- package/dist/v2-sdk.cjs.development.js.map +1 -1
- package/dist/v2-sdk.cjs.production.min.js +1 -1
- package/dist/v2-sdk.cjs.production.min.js.map +1 -1
- package/dist/v2-sdk.esm.js +3797 -680
- package/dist/v2-sdk.esm.js.map +1 -1
- package/package.json +4 -1
- package/src/abi/IArrakisV1RouterStaking.json +107 -0
- package/src/abi/IBalancerRewardsGauge.json +239 -0
- package/src/abi/IERC20.json +15 -1
- package/src/abi/ILiquidityGaugeV4.json +153 -0
- package/src/abi/INonfungiblePositionManager.json +1221 -0
- package/src/abi/ISynthetix.json +139 -0
- package/src/abi/IUniswapV3Quoter.json +195 -0
- package/src/abi/IUniswapV3Router.json +221 -0
- package/src/config.ts +35 -8
- package/src/entities/dhedge.ts +4 -2
- package/src/entities/pool.ts +394 -33
- package/src/entities/utils.ts +25 -9
- package/src/services/uniswap/V3Liquidity.ts +134 -0
- package/src/services/uniswap/V3Trade.ts +47 -0
- package/src/services/uniswap/types.ts +16 -0
- package/src/test/aave.test.ts +53 -25
- package/src/test/arrakis.test.ts +89 -0
- package/src/test/balancer.test.ts +115 -10
- package/src/test/constants.ts +12 -2
- package/src/test/oneInch.test.ts +13 -20
- package/src/test/synthetix.test.ts +34 -0
- package/src/test/txOptions.ts +15 -0
- package/src/test/uniswap.test.ts +125 -0
- package/src/test/wallet.ts +4 -0
- package/src/types.ts +19 -10
package/src/entities/pool.ts
CHANGED
|
@@ -6,10 +6,24 @@ import { Contract, ethers, Wallet, BigNumber } from "ethers";
|
|
|
6
6
|
import IERC20 from "../abi/IERC20.json";
|
|
7
7
|
import IMiniChefV2 from "../abi/IMiniChefV2.json";
|
|
8
8
|
import ILendingPool from "../abi/ILendingPool.json";
|
|
9
|
+
import ISynthetix from "../abi/ISynthetix.json";
|
|
9
10
|
import IUniswapV2Router from "../abi/IUniswapV2Router.json";
|
|
11
|
+
import INonfungiblePositionManager from "../abi/INonfungiblePositionManager.json";
|
|
10
12
|
import IBalancerMerkleOrchard from "../abi/IBalancerMerkleOrchard.json";
|
|
11
13
|
import IAaveIncentivesController from "../abi/IAaveIncentivesController.json";
|
|
12
|
-
import
|
|
14
|
+
import IArrakisV1RouterStaking from "../abi/IArrakisV1RouterStaking.json";
|
|
15
|
+
import ILiquidityGaugeV4 from "../abi/ILiquidityGaugeV4.json";
|
|
16
|
+
import IBalancerRewardsGauge from "../abi/IBalancerRewardsGauge.json";
|
|
17
|
+
|
|
18
|
+
import {
|
|
19
|
+
deadline,
|
|
20
|
+
MaxUint128,
|
|
21
|
+
networkChainIdMap,
|
|
22
|
+
nonfungiblePositionManagerAddress,
|
|
23
|
+
routerAddress,
|
|
24
|
+
stakingAddress,
|
|
25
|
+
SYNTHETIX_TRACKING_CODE
|
|
26
|
+
} from "../config";
|
|
13
27
|
import {
|
|
14
28
|
Dapp,
|
|
15
29
|
Transaction,
|
|
@@ -20,10 +34,17 @@ import {
|
|
|
20
34
|
|
|
21
35
|
import { Utils } from "./utils";
|
|
22
36
|
import { ClaimService } from "../services/claim-balancer/claim.service";
|
|
37
|
+
import {
|
|
38
|
+
getUniswapV3Liquidity,
|
|
39
|
+
getUniswapV3MintParams
|
|
40
|
+
} from "../services/uniswap/V3Liquidity";
|
|
41
|
+
import { FeeAmount } from "@uniswap/v3-sdk";
|
|
42
|
+
import { getUniswapV3SwapTxData } from "../services/uniswap/V3Trade";
|
|
23
43
|
|
|
24
44
|
export class Pool {
|
|
25
45
|
public readonly poolLogic: Contract;
|
|
26
46
|
public readonly managerLogic: Contract;
|
|
47
|
+
public readonly factory: Contract;
|
|
27
48
|
public readonly signer: Wallet;
|
|
28
49
|
public readonly address: string;
|
|
29
50
|
public readonly utils: Utils;
|
|
@@ -34,7 +55,8 @@ export class Pool {
|
|
|
34
55
|
signer: Wallet,
|
|
35
56
|
poolLogic: Contract,
|
|
36
57
|
mangerLogic: Contract,
|
|
37
|
-
utils: Utils
|
|
58
|
+
utils: Utils,
|
|
59
|
+
factory: Contract
|
|
38
60
|
) {
|
|
39
61
|
this.network = network;
|
|
40
62
|
this.poolLogic = poolLogic;
|
|
@@ -42,6 +64,7 @@ export class Pool {
|
|
|
42
64
|
this.managerLogic = mangerLogic;
|
|
43
65
|
this.signer = signer;
|
|
44
66
|
this.utils = utils;
|
|
67
|
+
this.factory = factory;
|
|
45
68
|
}
|
|
46
69
|
|
|
47
70
|
/**
|
|
@@ -170,13 +193,66 @@ export class Pool {
|
|
|
170
193
|
return tx;
|
|
171
194
|
}
|
|
172
195
|
|
|
196
|
+
/**
|
|
197
|
+
* Approve the liquidity pool token for staking
|
|
198
|
+
* @param {Dapp} dapp Platform like Sushiswap or Uniswap
|
|
199
|
+
* @param {string} asset Address of liquidity pool token
|
|
200
|
+
* @param {BigNumber | string} amount Aamount to be approved
|
|
201
|
+
* @param {any} options Transaction options
|
|
202
|
+
* @returns {Promise<any>} Transaction
|
|
203
|
+
*/
|
|
204
|
+
async approveUniswapV3Liquidity(
|
|
205
|
+
asset: string,
|
|
206
|
+
amount: BigNumber | string,
|
|
207
|
+
options: any = null
|
|
208
|
+
): Promise<any> {
|
|
209
|
+
const iERC20 = new ethers.utils.Interface(IERC20.abi);
|
|
210
|
+
const approveTxData = iERC20.encodeFunctionData("approve", [
|
|
211
|
+
nonfungiblePositionManagerAddress[this.network],
|
|
212
|
+
amount
|
|
213
|
+
]);
|
|
214
|
+
const tx = await this.poolLogic.execTransaction(
|
|
215
|
+
asset,
|
|
216
|
+
approveTxData,
|
|
217
|
+
options
|
|
218
|
+
);
|
|
219
|
+
return tx;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Approve the asset for provided spender address
|
|
224
|
+
* @param {string} spender Spender address
|
|
225
|
+
* @param {string} asset Address of asset
|
|
226
|
+
* @param {BigNumber | string} amount to be approved
|
|
227
|
+
* @param {any} options Transaction options
|
|
228
|
+
* @returns {Promise<any>} Transaction
|
|
229
|
+
*/
|
|
230
|
+
async approveSpender(
|
|
231
|
+
spender: string,
|
|
232
|
+
asset: string,
|
|
233
|
+
amount: BigNumber | string,
|
|
234
|
+
options: any = null
|
|
235
|
+
): Promise<any> {
|
|
236
|
+
const iERC20 = new ethers.utils.Interface(IERC20.abi);
|
|
237
|
+
const approveTxData = iERC20.encodeFunctionData("approve", [
|
|
238
|
+
spender,
|
|
239
|
+
amount
|
|
240
|
+
]);
|
|
241
|
+
const tx = await this.poolLogic.execTransaction(
|
|
242
|
+
asset,
|
|
243
|
+
approveTxData,
|
|
244
|
+
options
|
|
245
|
+
);
|
|
246
|
+
return tx;
|
|
247
|
+
}
|
|
248
|
+
|
|
173
249
|
/**
|
|
174
250
|
* Trade an asset into another asset
|
|
175
251
|
* @param {Dapp} dapp Platform like Sushiswap or Uniswap
|
|
176
252
|
* @param {string} assetFrom Asset to trade from
|
|
177
253
|
* @param {string} assetTo Asset to trade into
|
|
178
254
|
* @param {BigNumber | string} amountIn Amount
|
|
179
|
-
* @param {
|
|
255
|
+
* @param {number} slippage Slippage tolerance in %
|
|
180
256
|
* @param {any} options Transaction options
|
|
181
257
|
* @returns {Promise<any>} Transaction
|
|
182
258
|
*/
|
|
@@ -190,7 +266,8 @@ export class Pool {
|
|
|
190
266
|
): Promise<any> {
|
|
191
267
|
let swapTxData: string;
|
|
192
268
|
if (dapp === Dapp.ONEINCH) {
|
|
193
|
-
const
|
|
269
|
+
const chainId = networkChainIdMap[this.network];
|
|
270
|
+
const apiUrl = `https://api.1inch.exchange/v4.0/${chainId}/swap?fromTokenAddress=${assetFrom}&toTokenAddress=${assetTo}&amount=${amountIn.toString()}&fromAddress=${
|
|
194
271
|
this.address
|
|
195
272
|
}&destReceiver=${
|
|
196
273
|
this.address
|
|
@@ -205,6 +282,19 @@ export class Pool {
|
|
|
205
282
|
amountIn,
|
|
206
283
|
slippage
|
|
207
284
|
);
|
|
285
|
+
} else if (dapp === Dapp.SYNTHETIX) {
|
|
286
|
+
const iSynthetix = new ethers.utils.Interface(ISynthetix.abi);
|
|
287
|
+
const assets = [assetFrom, assetTo].map(asset =>
|
|
288
|
+
ethers.utils.formatBytes32String(asset)
|
|
289
|
+
);
|
|
290
|
+
const daoAddress = await this.factory.owner();
|
|
291
|
+
swapTxData = iSynthetix.encodeFunctionData(Transaction.SWAP_SYNTHS, [
|
|
292
|
+
assets[0],
|
|
293
|
+
amountIn,
|
|
294
|
+
assets[1],
|
|
295
|
+
daoAddress,
|
|
296
|
+
SYNTHETIX_TRACKING_CODE
|
|
297
|
+
]);
|
|
208
298
|
} else {
|
|
209
299
|
const iUniswapV2Router = new ethers.utils.Interface(IUniswapV2Router.abi);
|
|
210
300
|
const minAmountOut = await this.utils.getMinAmountOut(
|
|
@@ -219,7 +309,7 @@ export class Pool {
|
|
|
219
309
|
minAmountOut,
|
|
220
310
|
[assetFrom, assetTo],
|
|
221
311
|
this.address,
|
|
222
|
-
|
|
312
|
+
deadline
|
|
223
313
|
]);
|
|
224
314
|
}
|
|
225
315
|
const tx = await this.poolLogic.execTransaction(
|
|
@@ -251,16 +341,7 @@ export class Pool {
|
|
|
251
341
|
const iUniswapV2Router = new ethers.utils.Interface(IUniswapV2Router.abi);
|
|
252
342
|
const addLiquidityTxData = iUniswapV2Router.encodeFunctionData(
|
|
253
343
|
Transaction.ADD_LIQUIDITY,
|
|
254
|
-
[
|
|
255
|
-
assetA,
|
|
256
|
-
assetB,
|
|
257
|
-
amountA,
|
|
258
|
-
amountB,
|
|
259
|
-
0,
|
|
260
|
-
0,
|
|
261
|
-
this.address,
|
|
262
|
-
Math.floor(Date.now() / 1000) + 60 * 20 // 20 minutes from the current Unix time
|
|
263
|
-
]
|
|
344
|
+
[assetA, assetB, amountA, amountB, 0, 0, this.address, deadline]
|
|
264
345
|
);
|
|
265
346
|
const tx = await this.poolLogic.execTransaction(
|
|
266
347
|
routerAddress[this.network][dapp],
|
|
@@ -289,15 +370,7 @@ export class Pool {
|
|
|
289
370
|
const iUniswapV2Router = new ethers.utils.Interface(IUniswapV2Router.abi);
|
|
290
371
|
const removeLiquidityTxData = iUniswapV2Router.encodeFunctionData(
|
|
291
372
|
Transaction.REMOVE_LIQUIDITY,
|
|
292
|
-
[
|
|
293
|
-
assetA,
|
|
294
|
-
assetB,
|
|
295
|
-
amount,
|
|
296
|
-
0,
|
|
297
|
-
0,
|
|
298
|
-
this.address,
|
|
299
|
-
Math.floor(Date.now() / 1000) + 60 * 20 // 20 minutes from the current Unix time
|
|
300
|
-
]
|
|
373
|
+
[assetA, assetB, amount, 0, 0, this.address, deadline]
|
|
301
374
|
);
|
|
302
375
|
const tx = await this.poolLogic.execTransaction(
|
|
303
376
|
routerAddress[this.network][dapp],
|
|
@@ -333,7 +406,30 @@ export class Pool {
|
|
|
333
406
|
stakeTxData,
|
|
334
407
|
options
|
|
335
408
|
);
|
|
409
|
+
return tx;
|
|
410
|
+
}
|
|
336
411
|
|
|
412
|
+
/**
|
|
413
|
+
* Stake liquidity pool tokens in gauge contract
|
|
414
|
+
* @param {string} gauge Gauge contract address
|
|
415
|
+
* @param {BigNumber | string} amount Amount of liquidity pool tokens
|
|
416
|
+
* @param {any} options Transaction options
|
|
417
|
+
* @returns {Promise<any>} Transaction
|
|
418
|
+
*/
|
|
419
|
+
async stakeInGauge(
|
|
420
|
+
gauge: string,
|
|
421
|
+
amount: BigNumber | string,
|
|
422
|
+
options: any = null
|
|
423
|
+
): Promise<any> {
|
|
424
|
+
const rewardsGauge = new ethers.utils.Interface(IBalancerRewardsGauge.abi);
|
|
425
|
+
const stakeTxData = rewardsGauge.encodeFunctionData("deposit(uint256)", [
|
|
426
|
+
amount
|
|
427
|
+
]);
|
|
428
|
+
const tx = await this.poolLogic.execTransaction(
|
|
429
|
+
gauge,
|
|
430
|
+
stakeTxData,
|
|
431
|
+
options
|
|
432
|
+
);
|
|
337
433
|
return tx;
|
|
338
434
|
}
|
|
339
435
|
|
|
@@ -366,12 +462,36 @@ export class Pool {
|
|
|
366
462
|
return tx;
|
|
367
463
|
}
|
|
368
464
|
|
|
465
|
+
/**
|
|
466
|
+
* Unstake liquidity pool tokens from gauge contract
|
|
467
|
+
* @param {string} gauge Gauge contract address
|
|
468
|
+
* @param {BigNumber | string} amount Amount of liquidity pool tokens
|
|
469
|
+
* @param {any} options Transaction options
|
|
470
|
+
* @returns {Promise<any>} Transaction
|
|
471
|
+
*/
|
|
472
|
+
async unstakeFromGauge(
|
|
473
|
+
gauge: string,
|
|
474
|
+
amount: BigNumber | string,
|
|
475
|
+
options: any = null
|
|
476
|
+
): Promise<any> {
|
|
477
|
+
const rewardsGauge = new ethers.utils.Interface(IBalancerRewardsGauge.abi);
|
|
478
|
+
const unstakeTxData = rewardsGauge.encodeFunctionData("withdraw(uint256)", [
|
|
479
|
+
amount
|
|
480
|
+
]);
|
|
481
|
+
const tx = await this.poolLogic.execTransaction(
|
|
482
|
+
gauge,
|
|
483
|
+
unstakeTxData,
|
|
484
|
+
options
|
|
485
|
+
);
|
|
486
|
+
return tx;
|
|
487
|
+
}
|
|
488
|
+
|
|
369
489
|
/**
|
|
370
490
|
* Lend asset to a lending pool
|
|
371
491
|
* @param {Dapp} dapp Platform like Aave
|
|
372
492
|
* @param {string} asset Asset
|
|
373
493
|
* @param {BigNumber | string} amount Amount of asset to lend
|
|
374
|
-
* @param {number}
|
|
494
|
+
* @param {number} referralCode Code from Aave referral program
|
|
375
495
|
* @param {any} options Transaction options
|
|
376
496
|
* @returns {Promise<any>} Transaction
|
|
377
497
|
*/
|
|
@@ -379,7 +499,7 @@ export class Pool {
|
|
|
379
499
|
dapp: Dapp,
|
|
380
500
|
asset: string,
|
|
381
501
|
amount: BigNumber | string,
|
|
382
|
-
|
|
502
|
+
referralCode = 0,
|
|
383
503
|
options: any = null
|
|
384
504
|
): Promise<any> {
|
|
385
505
|
const iLendingPool = new ethers.utils.Interface(ILendingPool.abi);
|
|
@@ -387,7 +507,7 @@ export class Pool {
|
|
|
387
507
|
asset,
|
|
388
508
|
amount,
|
|
389
509
|
this.address,
|
|
390
|
-
|
|
510
|
+
referralCode
|
|
391
511
|
]);
|
|
392
512
|
const tx = await this.poolLogic.execTransaction(
|
|
393
513
|
routerAddress[this.network][dapp],
|
|
@@ -429,7 +549,7 @@ export class Pool {
|
|
|
429
549
|
* @param {Dapp} dapp Platform like Aave
|
|
430
550
|
* @param {string} asset Asset
|
|
431
551
|
* @param {BigNumber | string} amount Amount of asset to lend
|
|
432
|
-
* @param {number}
|
|
552
|
+
* @param {number} referralCode Code from Aave referral program
|
|
433
553
|
* @param {any} options Transaction options
|
|
434
554
|
* @returns {Promise<any>} Transaction
|
|
435
555
|
*/
|
|
@@ -437,7 +557,7 @@ export class Pool {
|
|
|
437
557
|
dapp: Dapp,
|
|
438
558
|
asset: string,
|
|
439
559
|
amount: BigNumber | string,
|
|
440
|
-
|
|
560
|
+
referralCode = 0,
|
|
441
561
|
options: any = null
|
|
442
562
|
): Promise<any> {
|
|
443
563
|
const iLendingPool = new ethers.utils.Interface(ILendingPool.abi);
|
|
@@ -445,7 +565,7 @@ export class Pool {
|
|
|
445
565
|
asset,
|
|
446
566
|
amount,
|
|
447
567
|
2,
|
|
448
|
-
|
|
568
|
+
referralCode,
|
|
449
569
|
this.address
|
|
450
570
|
]);
|
|
451
571
|
const tx = await this.poolLogic.execTransaction(
|
|
@@ -580,6 +700,7 @@ export class Pool {
|
|
|
580
700
|
* @param {string} poolId Balancer pool id
|
|
581
701
|
* @param {string[] | } assets Array of balancer pool assets
|
|
582
702
|
* @param {BigNumber | string } amount Amount of pool tokens to withdraw
|
|
703
|
+
* @param { null | number } singleExitAssetIndex Index of asset to withdraw to
|
|
583
704
|
* @param {any} options Transaction options
|
|
584
705
|
* @returns {Promise<any>} Transaction
|
|
585
706
|
*/
|
|
@@ -587,12 +708,14 @@ export class Pool {
|
|
|
587
708
|
poolId: string,
|
|
588
709
|
assets: string[],
|
|
589
710
|
amount: string | BigNumber,
|
|
711
|
+
singleExitAssetIndex: number | null = null,
|
|
590
712
|
options: any = null
|
|
591
713
|
): Promise<any> {
|
|
592
714
|
const exitPoolTxData = this.utils.getBalancerExitPoolTx(
|
|
593
715
|
this,
|
|
594
716
|
poolId,
|
|
595
717
|
assets,
|
|
718
|
+
singleExitAssetIndex,
|
|
596
719
|
amount
|
|
597
720
|
);
|
|
598
721
|
const tx = await this.poolLogic.execTransaction(
|
|
@@ -657,16 +780,13 @@ export class Pool {
|
|
|
657
780
|
iAaveIncentivesController,
|
|
658
781
|
this.signer
|
|
659
782
|
);
|
|
660
|
-
|
|
661
783
|
const amount = await aaveIncentivesController.getUserUnclaimedRewards(
|
|
662
784
|
this.address
|
|
663
785
|
);
|
|
664
|
-
|
|
665
786
|
const claimTxData = iAaveIncentivesController.encodeFunctionData(
|
|
666
787
|
Transaction.CLAIM_REWARDS,
|
|
667
788
|
[assets, amount, this.address]
|
|
668
789
|
);
|
|
669
|
-
|
|
670
790
|
const tx = await this.poolLogic.execTransaction(
|
|
671
791
|
aaveIncentivesAddress,
|
|
672
792
|
claimTxData,
|
|
@@ -674,4 +794,245 @@ export class Pool {
|
|
|
674
794
|
);
|
|
675
795
|
return tx;
|
|
676
796
|
}
|
|
797
|
+
|
|
798
|
+
/**
|
|
799
|
+
* Create UniswapV3 liquidity pool
|
|
800
|
+
* @param {string} assetA First asset
|
|
801
|
+
* @param {string} assetB Second asset
|
|
802
|
+
* @param {BigNumber | string} amountA Amount first asset
|
|
803
|
+
* @param {BigNumber | string} amountB Amount second asset
|
|
804
|
+
* @param { number } minPrice Lower price range (assetB per assetA)
|
|
805
|
+
* @param { number } maxPrice Upper price range (assetB per assetA)
|
|
806
|
+
* @param { number } minTick Lower tick range
|
|
807
|
+
* @param { number } maxTick Upper tick range
|
|
808
|
+
* @param { FeeAmount } feeAmount Fee tier (Low 0.05%, Medium 0.3%, High 1%)
|
|
809
|
+
* @param {any} options Transaction options
|
|
810
|
+
* @returns {Promise<any>} Transaction
|
|
811
|
+
*/
|
|
812
|
+
async addLiquidityUniswapV3(
|
|
813
|
+
assetA: string,
|
|
814
|
+
assetB: string,
|
|
815
|
+
amountA: BigNumber | string,
|
|
816
|
+
amountB: BigNumber | string,
|
|
817
|
+
minPrice: number | null,
|
|
818
|
+
maxPrice: number | null,
|
|
819
|
+
minTick: number | null,
|
|
820
|
+
maxTick: number | null,
|
|
821
|
+
feeAmount: FeeAmount,
|
|
822
|
+
options: any = null
|
|
823
|
+
): Promise<any> {
|
|
824
|
+
if ((!minPrice || !maxPrice) && (!minTick || !maxTick))
|
|
825
|
+
throw new Error("Need to provide price or tick range");
|
|
826
|
+
|
|
827
|
+
const iNonfungiblePositionManager = new ethers.utils.Interface(
|
|
828
|
+
INonfungiblePositionManager.abi
|
|
829
|
+
);
|
|
830
|
+
|
|
831
|
+
const mintTxParams = await getUniswapV3MintParams(
|
|
832
|
+
this,
|
|
833
|
+
assetA,
|
|
834
|
+
assetB,
|
|
835
|
+
amountA,
|
|
836
|
+
amountB,
|
|
837
|
+
minPrice,
|
|
838
|
+
maxPrice,
|
|
839
|
+
minTick,
|
|
840
|
+
maxTick,
|
|
841
|
+
feeAmount
|
|
842
|
+
);
|
|
843
|
+
const mintTxData = iNonfungiblePositionManager.encodeFunctionData(
|
|
844
|
+
Transaction.MINT,
|
|
845
|
+
[mintTxParams]
|
|
846
|
+
);
|
|
847
|
+
const tx = await this.poolLogic.execTransaction(
|
|
848
|
+
nonfungiblePositionManagerAddress[this.network],
|
|
849
|
+
mintTxData,
|
|
850
|
+
options
|
|
851
|
+
);
|
|
852
|
+
return tx;
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
/**
|
|
856
|
+
* Remove liquidity from an UniswapV3 or Arrakis liquidity pool
|
|
857
|
+
* @param {Dapp} dapp Platform either UniswapV3 or Arrakis
|
|
858
|
+
* @param {string} tokenId Token Id of UniswapV3 position
|
|
859
|
+
* @param {number} amount Amount in percent of assets to be removed
|
|
860
|
+
* @param {any} options Transaction options
|
|
861
|
+
* @returns {Promise<any>} Transaction
|
|
862
|
+
*/
|
|
863
|
+
async decreaseLiquidity(
|
|
864
|
+
dapp: Dapp,
|
|
865
|
+
tokenId: string,
|
|
866
|
+
amount = 100,
|
|
867
|
+
options: any = null
|
|
868
|
+
): Promise<any> {
|
|
869
|
+
let txData;
|
|
870
|
+
let dappAddress;
|
|
871
|
+
if (dapp === Dapp.UNISWAPV3) {
|
|
872
|
+
dappAddress = nonfungiblePositionManagerAddress[this.network];
|
|
873
|
+
const abi = new ethers.utils.Interface(INonfungiblePositionManager.abi);
|
|
874
|
+
const liquidity = (await getUniswapV3Liquidity(tokenId, this))
|
|
875
|
+
.mul(amount)
|
|
876
|
+
.div(100);
|
|
877
|
+
const decreaseLiquidityTxData = abi.encodeFunctionData(
|
|
878
|
+
Transaction.DECREASE_LIQUIDITY,
|
|
879
|
+
[[tokenId, liquidity, 0, 0, deadline]]
|
|
880
|
+
);
|
|
881
|
+
const collectTxData = abi.encodeFunctionData(Transaction.COLLECT, [
|
|
882
|
+
[tokenId, this.address, MaxUint128, MaxUint128]
|
|
883
|
+
]);
|
|
884
|
+
|
|
885
|
+
const multicallParams = [decreaseLiquidityTxData, collectTxData];
|
|
886
|
+
|
|
887
|
+
if (amount === 100) {
|
|
888
|
+
const burnTxData = abi.encodeFunctionData(Transaction.BURN, [tokenId]);
|
|
889
|
+
multicallParams.push(burnTxData);
|
|
890
|
+
}
|
|
891
|
+
txData = abi.encodeFunctionData(Transaction.MULTI_CALL, [
|
|
892
|
+
multicallParams
|
|
893
|
+
]);
|
|
894
|
+
} else if (dapp === Dapp.ARRAKIS) {
|
|
895
|
+
dappAddress = routerAddress[this.network][dapp];
|
|
896
|
+
const abi = new ethers.utils.Interface(IArrakisV1RouterStaking.abi);
|
|
897
|
+
const liquidity = (await this.utils.getBalance(tokenId, this.address))
|
|
898
|
+
.mul(amount)
|
|
899
|
+
.div(100);
|
|
900
|
+
txData = abi.encodeFunctionData(Transaction.REMOVE_LIQUIDITY_UNSTAKE, [
|
|
901
|
+
tokenId,
|
|
902
|
+
liquidity,
|
|
903
|
+
0,
|
|
904
|
+
0,
|
|
905
|
+
this.address
|
|
906
|
+
]);
|
|
907
|
+
} else {
|
|
908
|
+
throw new Error("dapp not supported");
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
const tx = await this.poolLogic.execTransaction(
|
|
912
|
+
dappAddress,
|
|
913
|
+
txData,
|
|
914
|
+
options
|
|
915
|
+
);
|
|
916
|
+
return tx;
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
/**
|
|
920
|
+
* Increase liquidity of an UniswapV3 or Arrakis liquidity pool
|
|
921
|
+
* @param {Dapp} dapp Platform either UniswapV3 or Arrakis
|
|
922
|
+
* @param {string} tokenId Token Id of UniswapV3 position
|
|
923
|
+
* @param {BigNumber | string} amountA Amount first asset
|
|
924
|
+
* @param {BigNumber | string} amountB Amount second asset
|
|
925
|
+
* @param {any} options Transaction options
|
|
926
|
+
* @returns {Promise<any>} Transaction
|
|
927
|
+
*/
|
|
928
|
+
async increaseLiquidity(
|
|
929
|
+
dapp: Dapp,
|
|
930
|
+
tokenId: string,
|
|
931
|
+
amountA: BigNumber | string,
|
|
932
|
+
amountB: BigNumber | string,
|
|
933
|
+
options: any = null
|
|
934
|
+
): Promise<any> {
|
|
935
|
+
let txData;
|
|
936
|
+
let dappAddress;
|
|
937
|
+
if (dapp === Dapp.UNISWAPV3) {
|
|
938
|
+
dappAddress = nonfungiblePositionManagerAddress[this.network];
|
|
939
|
+
const abi = new ethers.utils.Interface(INonfungiblePositionManager.abi);
|
|
940
|
+
txData = abi.encodeFunctionData(Transaction.INCREASE_LIQUIDITY, [
|
|
941
|
+
[tokenId, amountA, amountB, 0, 0, deadline]
|
|
942
|
+
]);
|
|
943
|
+
} else if (dapp === Dapp.ARRAKIS) {
|
|
944
|
+
dappAddress = routerAddress[this.network][dapp];
|
|
945
|
+
const abi = new ethers.utils.Interface(IArrakisV1RouterStaking.abi);
|
|
946
|
+
txData = abi.encodeFunctionData(Transaction.ADD_LIQUIDITY_STAKE, [
|
|
947
|
+
tokenId,
|
|
948
|
+
amountA,
|
|
949
|
+
amountB,
|
|
950
|
+
0,
|
|
951
|
+
0,
|
|
952
|
+
this.address
|
|
953
|
+
]);
|
|
954
|
+
} else {
|
|
955
|
+
throw new Error("dapp not supported");
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
const tx = await this.poolLogic.execTransaction(
|
|
959
|
+
dappAddress,
|
|
960
|
+
txData,
|
|
961
|
+
options
|
|
962
|
+
);
|
|
963
|
+
return tx;
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
/**
|
|
967
|
+
* Claim fees of an UniswapV3 liquidity or Arrakis pool
|
|
968
|
+
* @param {Dapp} dapp Platform either UniswapV3 or Arrakis
|
|
969
|
+
* @param {string} tokenId Token Id of UniswapV3 or Gauge address
|
|
970
|
+
* @param {any} options Transaction option
|
|
971
|
+
* @returns {Promise<any>} Transaction
|
|
972
|
+
*/
|
|
973
|
+
async claimFees(
|
|
974
|
+
dapp: Dapp,
|
|
975
|
+
tokenId: string,
|
|
976
|
+
options: any = null
|
|
977
|
+
): Promise<any> {
|
|
978
|
+
let txData;
|
|
979
|
+
let contractAddress;
|
|
980
|
+
if (dapp === Dapp.UNISWAPV3) {
|
|
981
|
+
contractAddress = nonfungiblePositionManagerAddress[this.network];
|
|
982
|
+
const iNonfungiblePositionManager = new ethers.utils.Interface(
|
|
983
|
+
INonfungiblePositionManager.abi
|
|
984
|
+
);
|
|
985
|
+
txData = iNonfungiblePositionManager.encodeFunctionData(
|
|
986
|
+
Transaction.COLLECT,
|
|
987
|
+
[[tokenId, this.address, MaxUint128, MaxUint128]]
|
|
988
|
+
);
|
|
989
|
+
} else if (dapp === Dapp.ARRAKIS || dapp === Dapp.BALANCER) {
|
|
990
|
+
contractAddress = tokenId;
|
|
991
|
+
const abi = new ethers.utils.Interface(ILiquidityGaugeV4.abi);
|
|
992
|
+
txData = abi.encodeFunctionData("claim_rewards()", []);
|
|
993
|
+
} else {
|
|
994
|
+
throw new Error("dapp not supported");
|
|
995
|
+
}
|
|
996
|
+
const tx = await this.poolLogic.execTransaction(
|
|
997
|
+
contractAddress,
|
|
998
|
+
txData,
|
|
999
|
+
options
|
|
1000
|
+
);
|
|
1001
|
+
return tx;
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
/**
|
|
1005
|
+
* Trade an asset into another asset
|
|
1006
|
+
* @param {Dapp} dapp Platform like Sushiswap or Uniswap
|
|
1007
|
+
* @param {string} assetFrom Asset to trade from
|
|
1008
|
+
* @param {string} assetTo Asset to trade into
|
|
1009
|
+
* @param {BigNumber | string} amountIn Amount
|
|
1010
|
+
* @param { FeeAmount } feeAmount Fee tier (Low 0.05%, Medium 0.3%, High 1%)
|
|
1011
|
+
* @param {number} slippage Slippage tolerance in %
|
|
1012
|
+
* @param {any} options Transaction options
|
|
1013
|
+
* @returns {Promise<any>} Transaction
|
|
1014
|
+
*/
|
|
1015
|
+
async tradeUniswapV3(
|
|
1016
|
+
assetFrom: string,
|
|
1017
|
+
assetTo: string,
|
|
1018
|
+
amountIn: BigNumber | string,
|
|
1019
|
+
feeAmount: FeeAmount,
|
|
1020
|
+
slippage = 0.5,
|
|
1021
|
+
options: any = null
|
|
1022
|
+
): Promise<any> {
|
|
1023
|
+
const swapxData = await getUniswapV3SwapTxData(
|
|
1024
|
+
this,
|
|
1025
|
+
assetFrom,
|
|
1026
|
+
assetTo,
|
|
1027
|
+
amountIn,
|
|
1028
|
+
slippage,
|
|
1029
|
+
feeAmount
|
|
1030
|
+
);
|
|
1031
|
+
const tx = await this.poolLogic.execTransaction(
|
|
1032
|
+
routerAddress[this.network][Dapp.UNISWAPV3],
|
|
1033
|
+
swapxData,
|
|
1034
|
+
options
|
|
1035
|
+
);
|
|
1036
|
+
return tx;
|
|
1037
|
+
}
|
|
677
1038
|
}
|
package/src/entities/utils.ts
CHANGED
|
@@ -125,6 +125,18 @@ export class Utils {
|
|
|
125
125
|
return balance;
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
+
/**
|
|
129
|
+
* Returns the decimals of an asset (ERC20) token
|
|
130
|
+
* @param {string} asset string token address
|
|
131
|
+
* @returns { number } Balance of asset
|
|
132
|
+
*/
|
|
133
|
+
|
|
134
|
+
async getDecimals(asset: string): Promise<number> {
|
|
135
|
+
const iERC20 = new ethers.Contract(asset, IERC20.abi, this.signer);
|
|
136
|
+
const decimals = await iERC20.decimals();
|
|
137
|
+
return decimals;
|
|
138
|
+
}
|
|
139
|
+
|
|
128
140
|
/**
|
|
129
141
|
* Return the minimum amount out for a trade between two assets
|
|
130
142
|
* given the trade amount and slippage
|
|
@@ -283,25 +295,29 @@ export class Utils {
|
|
|
283
295
|
pool: Pool,
|
|
284
296
|
balancerPoolId: string,
|
|
285
297
|
assets: string[],
|
|
298
|
+
singleExitAssetIndex: null | number,
|
|
286
299
|
amount: string | ethers.BigNumber
|
|
287
300
|
|
|
288
301
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
289
302
|
): Promise<any> {
|
|
290
303
|
const minimumAmountOut = new Array(assets.length).fill(0);
|
|
291
304
|
const iBalancerV2Vault = new ethers.utils.Interface(IBalancerV2Vault.abi);
|
|
305
|
+
const userTxData =
|
|
306
|
+
singleExitAssetIndex === null
|
|
307
|
+
? ethers.utils.defaultAbiCoder.encode(
|
|
308
|
+
["uint256", "uint256"],
|
|
309
|
+
[1, amount]
|
|
310
|
+
)
|
|
311
|
+
: ethers.utils.defaultAbiCoder.encode(
|
|
312
|
+
["uint256", "uint256", "uint256"],
|
|
313
|
+
[0, amount, singleExitAssetIndex]
|
|
314
|
+
);
|
|
315
|
+
|
|
292
316
|
const txData = [
|
|
293
317
|
balancerPoolId,
|
|
294
318
|
pool.address,
|
|
295
319
|
pool.address,
|
|
296
|
-
[
|
|
297
|
-
assets,
|
|
298
|
-
minimumAmountOut,
|
|
299
|
-
ethers.utils.defaultAbiCoder.encode(
|
|
300
|
-
["uint256", "uint256"],
|
|
301
|
-
[1, amount]
|
|
302
|
-
),
|
|
303
|
-
false
|
|
304
|
-
]
|
|
320
|
+
[assets, minimumAmountOut, userTxData, false]
|
|
305
321
|
];
|
|
306
322
|
const exitPoolTx = iBalancerV2Vault.encodeFunctionData("exitPool", txData);
|
|
307
323
|
return exitPoolTx;
|