@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.
Files changed (41) hide show
  1. package/dist/config.d.ts +5 -0
  2. package/dist/entities/pool.d.ts +98 -7
  3. package/dist/entities/utils.d.ts +7 -1
  4. package/dist/services/uniswap/V3Liquidity.d.ts +9 -0
  5. package/dist/services/uniswap/V3Trade.d.ts +4 -0
  6. package/dist/services/uniswap/types.d.ts +3 -0
  7. package/dist/test/constants.d.ts +5 -2
  8. package/dist/test/txOptions.d.ts +1 -0
  9. package/dist/types.d.ts +19 -10
  10. package/dist/v2-sdk.cjs.development.js +3796 -679
  11. package/dist/v2-sdk.cjs.development.js.map +1 -1
  12. package/dist/v2-sdk.cjs.production.min.js +1 -1
  13. package/dist/v2-sdk.cjs.production.min.js.map +1 -1
  14. package/dist/v2-sdk.esm.js +3797 -680
  15. package/dist/v2-sdk.esm.js.map +1 -1
  16. package/package.json +4 -1
  17. package/src/abi/IArrakisV1RouterStaking.json +107 -0
  18. package/src/abi/IBalancerRewardsGauge.json +239 -0
  19. package/src/abi/IERC20.json +15 -1
  20. package/src/abi/ILiquidityGaugeV4.json +153 -0
  21. package/src/abi/INonfungiblePositionManager.json +1221 -0
  22. package/src/abi/ISynthetix.json +139 -0
  23. package/src/abi/IUniswapV3Quoter.json +195 -0
  24. package/src/abi/IUniswapV3Router.json +221 -0
  25. package/src/config.ts +35 -8
  26. package/src/entities/dhedge.ts +4 -2
  27. package/src/entities/pool.ts +394 -33
  28. package/src/entities/utils.ts +25 -9
  29. package/src/services/uniswap/V3Liquidity.ts +134 -0
  30. package/src/services/uniswap/V3Trade.ts +47 -0
  31. package/src/services/uniswap/types.ts +16 -0
  32. package/src/test/aave.test.ts +53 -25
  33. package/src/test/arrakis.test.ts +89 -0
  34. package/src/test/balancer.test.ts +115 -10
  35. package/src/test/constants.ts +12 -2
  36. package/src/test/oneInch.test.ts +13 -20
  37. package/src/test/synthetix.test.ts +34 -0
  38. package/src/test/txOptions.ts +15 -0
  39. package/src/test/uniswap.test.ts +125 -0
  40. package/src/test/wallet.ts +4 -0
  41. package/src/types.ts +19 -10
@@ -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 { routerAddress, stakingAddress } from "../config";
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 {BigNumber | string} minAmountOut Minumum amount to receive
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 apiUrl = `https://api.1inch.exchange/v4.0/137/swap?fromTokenAddress=${assetFrom}&toTokenAddress=${assetTo}&amount=${amountIn.toString()}&fromAddress=${
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
- Math.floor(Date.now() / 1000) + 60 * 20 // 20 minutes from the current Unix time
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} referrralCode Code from Aave referral program
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
- referrralCode = 0,
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
- referrralCode
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} referrralCode Code from Aave referral program
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
- referrralCode = 0,
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
- referrralCode,
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
  }
@@ -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;