@dhedge/v2-sdk 1.1.1 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/README.md +60 -3
  2. package/dist/config.d.ts +7 -0
  3. package/dist/entities/pool.d.ts +101 -5
  4. package/dist/entities/utils.d.ts +10 -0
  5. package/dist/services/claim-balancer/claim.service.d.ts +17 -0
  6. package/dist/services/claim-balancer/claim.worker.d.ts +4 -0
  7. package/dist/services/claim-balancer/ipfs.service.d.ts +4 -0
  8. package/dist/services/claim-balancer/types.d.ts +54 -0
  9. package/dist/services/uniswap/V3Liquidity.d.ts +9 -0
  10. package/dist/services/uniswap/V3Trade.d.ts +4 -0
  11. package/dist/services/uniswap/types.d.ts +3 -0
  12. package/dist/test/constants.d.ts +12 -0
  13. package/dist/test/txOptions.d.ts +1 -0
  14. package/dist/types.d.ts +20 -6
  15. package/dist/utils/contract.d.ts +14 -0
  16. package/dist/utils/index.d.ts +7 -0
  17. package/dist/utils/merkle.d.ts +22 -0
  18. package/dist/v2-sdk.cjs.development.js +6086 -918
  19. package/dist/v2-sdk.cjs.development.js.map +1 -1
  20. package/dist/v2-sdk.cjs.production.min.js +1 -1
  21. package/dist/v2-sdk.cjs.production.min.js.map +1 -1
  22. package/dist/v2-sdk.esm.js +6090 -922
  23. package/dist/v2-sdk.esm.js.map +1 -1
  24. package/package.json +12 -2
  25. package/src/abi/IAaveIncentivesController.json +50 -0
  26. package/src/abi/IBalancerMerkleOrchard.json +353 -0
  27. package/src/abi/IBalancertV2Vault.json +938 -0
  28. package/src/abi/IERC20.json +15 -1
  29. package/src/abi/INonfungiblePositionManager.json +1221 -0
  30. package/src/abi/ISynthetix.json +139 -0
  31. package/src/abi/IUniswapV3Quoter.json +195 -0
  32. package/src/abi/IUniswapV3Router.json +221 -0
  33. package/src/config.ts +48 -8
  34. package/src/entities/dhedge.ts +4 -2
  35. package/src/entities/pool.ts +398 -27
  36. package/src/entities/utils.ts +147 -0
  37. package/src/services/claim-balancer/MultiTokenClaim.json +115 -0
  38. package/src/services/claim-balancer/claim.service.ts +262 -0
  39. package/src/services/claim-balancer/claim.worker.ts +32 -0
  40. package/src/services/claim-balancer/ipfs.service.ts +12 -0
  41. package/src/services/claim-balancer/types.ts +66 -0
  42. package/src/services/uniswap/V3Liquidity.ts +134 -0
  43. package/src/services/uniswap/V3Trade.ts +47 -0
  44. package/src/services/uniswap/types.ts +16 -0
  45. package/src/test/aave.test.ts +73 -0
  46. package/src/test/balancer.test.ts +109 -0
  47. package/src/test/constants.ts +17 -0
  48. package/src/test/oneInch.test.ts +56 -0
  49. package/src/test/pool.test.ts +6 -250
  50. package/src/test/sushi.test.ts +173 -0
  51. package/src/test/synthetix.test.ts +34 -0
  52. package/src/test/txOptions.ts +15 -0
  53. package/src/test/uniswap.test.ts +127 -0
  54. package/src/test/utils.test.ts +41 -26
  55. package/src/test/wallet.ts +5 -1
  56. package/src/types.ts +17 -3
  57. package/src/utils/contract.ts +95 -0
  58. package/src/utils/index.ts +38 -0
  59. package/src/utils/merkle.ts +172 -0
@@ -0,0 +1,134 @@
1
+ import { Price, Token } from "@uniswap/sdk-core";
2
+ import {
3
+ encodeSqrtRatioX96,
4
+ FeeAmount,
5
+ nearestUsableTick,
6
+ priceToClosestTick,
7
+ TICK_SPACINGS,
8
+ TickMath
9
+ } from "@uniswap/v3-sdk";
10
+ import { ethers } from "ethers";
11
+ import JSBI from "jsbi";
12
+ import { Pool } from "../..";
13
+ import {
14
+ networkChainIdMap,
15
+ nonfungiblePositionManagerAddress
16
+ } from "../../config";
17
+ import { UniswapV3MintParams } from "./types";
18
+ import INonfungiblePositionManager from "../../abi/INonfungiblePositionManager.json";
19
+
20
+ export function tryParsePrice(
21
+ baseToken: Token,
22
+ quoteToken: Token,
23
+ value: string
24
+ ): Price<Token, Token> {
25
+ const [whole, fraction] = value.split(".");
26
+
27
+ const decimals = fraction?.length ?? 0;
28
+ const withoutDecimals = JSBI.BigInt((whole ?? "") + (fraction ?? ""));
29
+
30
+ return new Price(
31
+ baseToken,
32
+ quoteToken,
33
+ JSBI.multiply(
34
+ JSBI.BigInt(10 ** decimals),
35
+ JSBI.BigInt(10 ** baseToken.decimals)
36
+ ),
37
+ JSBI.multiply(withoutDecimals, JSBI.BigInt(10 ** quoteToken.decimals))
38
+ );
39
+ }
40
+
41
+ export function tryParseTick(
42
+ baseToken: Token,
43
+ quoteToken: Token,
44
+ feeAmount: FeeAmount,
45
+ value: string
46
+ ): number {
47
+ const price = tryParsePrice(baseToken, quoteToken, value);
48
+
49
+ let tick: number;
50
+
51
+ // check price is within min/max bounds, if outside return min/max
52
+ const sqrtRatioX96 = encodeSqrtRatioX96(price.numerator, price.denominator);
53
+
54
+ if (JSBI.greaterThanOrEqual(sqrtRatioX96, TickMath.MAX_SQRT_RATIO)) {
55
+ tick = TickMath.MAX_TICK;
56
+ } else if (JSBI.lessThanOrEqual(sqrtRatioX96, TickMath.MIN_SQRT_RATIO)) {
57
+ tick = TickMath.MIN_TICK;
58
+ } else {
59
+ // this function is agnostic to the base, will always return the correct tick
60
+ tick = priceToClosestTick(price);
61
+ }
62
+
63
+ return nearestUsableTick(tick, TICK_SPACINGS[feeAmount]);
64
+ }
65
+
66
+ export async function getUniswapV3MintParams(
67
+ pool: Pool,
68
+ assetA: string,
69
+ assetB: string,
70
+ amountA: string | ethers.BigNumber,
71
+ amountB: string | ethers.BigNumber,
72
+ minPrice: number | null,
73
+ maxPrice: number | null,
74
+ minTick: number | null,
75
+ maxTick: number | null,
76
+ feeAmount: FeeAmount
77
+ ): Promise<UniswapV3MintParams> {
78
+ let tickLower = 0;
79
+ let tickUpper = 0;
80
+ const chainId = networkChainIdMap[pool.network];
81
+ const decimals = await Promise.all(
82
+ [assetA, assetB].map(asset => pool.utils.getDecimals(asset))
83
+ );
84
+ const tokenA = new Token(chainId, assetA, decimals[0]);
85
+ const tokenB = new Token(chainId, assetB, decimals[1]);
86
+ const [token0, token1] = tokenA.sortsBefore(tokenB)
87
+ ? [tokenA, tokenB]
88
+ : [tokenB, tokenA];
89
+ const invertPrice = !tokenA.equals(token0);
90
+
91
+ if (minPrice && maxPrice) {
92
+ tickLower = invertPrice
93
+ ? tryParseTick(token1, token0, feeAmount, maxPrice.toString())
94
+ : tryParseTick(token0, token1, feeAmount, minPrice.toString());
95
+ tickUpper = invertPrice
96
+ ? tryParseTick(token1, token0, feeAmount, minPrice.toString())
97
+ : tryParseTick(token0, token1, feeAmount, maxPrice.toString());
98
+ } else if (minTick && maxTick) {
99
+ tickLower = minTick;
100
+ tickUpper = maxTick;
101
+ }
102
+ const [amount0, amount1] = invertPrice
103
+ ? [amountB, amountA]
104
+ : [amountA, amountB];
105
+
106
+ const deadline = Math.floor(Date.now() / 1000) + 60 * 20;
107
+
108
+ return [
109
+ token0.address,
110
+ token1.address,
111
+ feeAmount,
112
+ tickLower,
113
+ tickUpper,
114
+ amount0,
115
+ amount1,
116
+ "0",
117
+ "0",
118
+ pool.address,
119
+ deadline
120
+ ];
121
+ }
122
+
123
+ export async function getUniswapV3Liquidity(
124
+ tokenId: string,
125
+ pool: Pool
126
+ ): Promise<ethers.BigNumber> {
127
+ const iNonfungiblePositionManager = new ethers.Contract(
128
+ nonfungiblePositionManagerAddress[pool.network],
129
+ INonfungiblePositionManager.abi,
130
+ pool.signer
131
+ );
132
+ const result = await iNonfungiblePositionManager.positions(tokenId);
133
+ return result.liquidity;
134
+ }
@@ -0,0 +1,47 @@
1
+ import { FeeAmount } from "@uniswap/v3-sdk";
2
+ import { ethers } from "ethers";
3
+ import { Pool } from "../..";
4
+
5
+ import IUniswapV3Router from "../../abi/IUniswapV3Router.json";
6
+ import IUniswapV3Quoter from "../../abi/IUniswapV3Quoter.json";
7
+ import { UNISWAPV3_QUOTER_ADDRESS } from "../../config";
8
+
9
+ export async function getUniswapV3SwapTxData(
10
+ pool: Pool,
11
+ assetA: string,
12
+ assetB: string,
13
+ amountIn: string | ethers.BigNumber,
14
+ slippage: number,
15
+ feeAmount: FeeAmount
16
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
17
+ ): Promise<any> {
18
+ const quoterContract = new ethers.Contract(
19
+ UNISWAPV3_QUOTER_ADDRESS,
20
+ IUniswapV3Quoter.abi,
21
+ pool.signer
22
+ );
23
+
24
+ const quotedAmountOut: ethers.BigNumber = await quoterContract.callStatic.quoteExactInputSingle(
25
+ assetA,
26
+ assetB,
27
+ feeAmount,
28
+ amountIn.toString(),
29
+ 0
30
+ );
31
+
32
+ const minAmountOut = quotedAmountOut.mul((100 - slippage) * 100).div(10000);
33
+
34
+ const iUniswapV3Router = new ethers.utils.Interface(IUniswapV3Router.abi);
35
+ const swapTx = iUniswapV3Router.encodeFunctionData("exactInputSingle", [
36
+ [
37
+ assetA,
38
+ assetB,
39
+ feeAmount,
40
+ pool.address,
41
+ amountIn.toString(),
42
+ minAmountOut.toString(),
43
+ 0
44
+ ]
45
+ ]);
46
+ return swapTx;
47
+ }
@@ -0,0 +1,16 @@
1
+ import { FeeAmount } from "@uniswap/v3-sdk";
2
+ import { ethers } from "ethers";
3
+
4
+ export type UniswapV3MintParams = [
5
+ string,
6
+ string,
7
+ FeeAmount,
8
+ number,
9
+ number,
10
+ ethers.BigNumber | string,
11
+ ethers.BigNumber | string,
12
+ ethers.BigNumber | string,
13
+ ethers.BigNumber | string,
14
+ string,
15
+ number
16
+ ];
@@ -0,0 +1,73 @@
1
+ import { Dhedge, ethers } from "..";
2
+ import { Network } from "../types";
3
+ import { AMUSDC, TEST_POOL, VDEBTWETH } from "./constants";
4
+
5
+ import { wallet } from "./wallet";
6
+
7
+ let dhedge: Dhedge;
8
+
9
+ jest.setTimeout(100000);
10
+
11
+ const options = {
12
+ gasLimit: 5000000,
13
+ gasPrice: ethers.utils.parseUnits("100", "gwei")
14
+ };
15
+
16
+ describe("pool", () => {
17
+ beforeAll(() => {
18
+ dhedge = new Dhedge(wallet, Network.POLYGON);
19
+ });
20
+
21
+ // it("withdraws 1 USDC from Aave lending pool", async () => {
22
+ // let result;
23
+ // const pool = await dhedge.loadPool(myPool);
24
+ // try {
25
+ // result = await pool.withdrawDeposit(
26
+ // Dapp.AAVE,
27
+ // weth,
28
+ // "86567951006165",
29
+ // options
30
+ // );
31
+ // console.log(result);
32
+ // } catch (e) {
33
+ // console.log(e);
34
+ // }
35
+ // expect(result).not.toBe(null);
36
+ // });
37
+
38
+ // it("borrows 0.0001 WETH from Aave lending pool", async () => {
39
+ // let result;
40
+ // const pool = await dhedge.loadPool(myPool);
41
+ // try {
42
+ // result = await pool.borrow(Dapp.AAVE, weth, "100000000000000");
43
+ // console.log(result);
44
+ // } catch (e) {
45
+ // console.log(e);
46
+ // }
47
+ // expect(result).not.toBe(null);
48
+ // });
49
+
50
+ // it("reapys 0.0001 WETH to Aave lending pool", async () => {
51
+ // let result;
52
+ // const pool = await dhedge.loadPool(myPool);
53
+ // try {
54
+ // result = await pool.repay(Dapp.AAVE, weth, "100000000000000", options);
55
+ // console.log(result);
56
+ // } catch (e) {
57
+ // console.log(e);
58
+ // }
59
+ // expect(result).not.toBe(null);
60
+ // });
61
+
62
+ it("claims rewards from Aave", async () => {
63
+ let result;
64
+ const pool = await dhedge.loadPool(TEST_POOL);
65
+ try {
66
+ result = await pool.harvestAaveRewards([AMUSDC, VDEBTWETH], options);
67
+ console.log(result);
68
+ } catch (e) {
69
+ console.log(e);
70
+ }
71
+ expect(result).not.toBe(null);
72
+ });
73
+ });
@@ -0,0 +1,109 @@
1
+ import { Dhedge, ethers } from "..";
2
+ import { Network } from "../types";
3
+ import { TEST_POOL } from "./constants";
4
+
5
+ import { wallet } from "./wallet";
6
+
7
+ let dhedge: Dhedge;
8
+
9
+ jest.setTimeout(100000);
10
+
11
+ const options = {
12
+ gasLimit: 2000000,
13
+ gasPrice: ethers.utils.parseUnits("1000", "gwei")
14
+ };
15
+
16
+ describe("pool", () => {
17
+ beforeAll(() => {
18
+ dhedge = new Dhedge(wallet, Network.POLYGON);
19
+ });
20
+
21
+ // it("approves unlimited USDC on Balancer", async () => {
22
+ // let result;
23
+ // const pool = await dhedge.loadPool(TEST_POOL);
24
+ // try {
25
+ // result = await pool.approve(
26
+ // Dapp.BALANCER,
27
+ // USDC,
28
+ // ethers.constants.MaxInt256,
29
+ // options
30
+ // );
31
+ // console.log(result);
32
+ // } catch (e) {
33
+ // console.log(e);
34
+ // }
35
+ // expect(result).not.toBe(null);
36
+ // });
37
+
38
+ // it("trades 2 USDC into SUSHI on Balancer", async () => {
39
+ // let result;
40
+ // const pool = await dhedge.loadPool(myPool);
41
+ // try {
42
+ // result = await pool.trade(
43
+ // Dapp.BALANCER,
44
+ // usdc,
45
+ // sushi,
46
+ // "2000000",
47
+ // 0.5,
48
+ // options
49
+ // );
50
+ // console.log(result);
51
+ // } catch (e) {
52
+ // console.log(e);
53
+ // }
54
+ // expect(result).not.toBe(null);
55
+ // });
56
+
57
+ // it("adds 1 USDC to a USDC/TUSD/DAI/USDT balancer pool", async () => {
58
+ // let result;
59
+ // const pool = await dhedge.loadPool(TEST_POOL);
60
+ // const assets = [USDC, TUSD, DAI, USDT];
61
+ // const amounts = ["1000000", "0", "0", "0"];
62
+ // try {
63
+ // result = await pool.joinBalancerPool(
64
+ // "0x0d34e5dd4d8f043557145598e4e2dc286b35fd4f000000000000000000000068",
65
+ // assets,
66
+ // amounts,
67
+ // options
68
+ // );
69
+ // console.log("result", result);
70
+ // } catch (e) {
71
+ // console.log(e);
72
+ // }
73
+ // expect(result).not.toBe(null);
74
+ // });
75
+
76
+ // it("exits entire balance of WBTC/USDC/WETH balancer pool", async () => {
77
+ // let result;
78
+ // const pool = await dhedge.loadPool(myPool);
79
+ // const assets = [wbtc, usdc, weth];
80
+ // const amount = await dhedge.utils.getBalance(
81
+ // "0x03cd191f589d12b0582a99808cf19851e468e6b5",
82
+ // pool.address
83
+ // );
84
+ // try {
85
+ // result = await pool.exitBalancerPool(
86
+ // "0x03cd191f589d12b0582a99808cf19851e468e6b500010000000000000000000a",
87
+ // assets,
88
+ // amount,
89
+ // options
90
+ // );
91
+ // console.log("result", result);
92
+ // } catch (e) {
93
+ // console.log(e);
94
+ // }
95
+ // expect(result).not.toBe(null);
96
+ // });
97
+
98
+ it("claims balancer rewards", async () => {
99
+ let result;
100
+ const pool = await dhedge.loadPool(TEST_POOL);
101
+ try {
102
+ result = await pool.harvestBalancerRewards(options);
103
+ console.log("result", result);
104
+ } catch (e) {
105
+ console.log(e);
106
+ }
107
+ expect(result).not.toBe(null);
108
+ });
109
+ });
@@ -0,0 +1,17 @@
1
+ //export const USDC = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174";
2
+ //Optimism
3
+ export const USDC = "0x7F5c764cBc14f9669B88837ca1490cCa17c31607";
4
+ export const USDT = "0xc2132D05D31c914a87C6611C10748AEb04B58e8F";
5
+ export const DAI = "0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063";
6
+ export const TUSD = "0x2e1ad108ff1d8c782fcbbb89aad783ac49586756";
7
+ //export const WETH = "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619";
8
+ //Optimism
9
+ export const WETH = "0x4200000000000000000000000000000000000006";
10
+ export const WBTC = "0x1BFD67037B42Cf73acF2047067bd4F2C47D9BfD6";
11
+ export const SUSHI = "0x0b3f868e0be5597d5db7feb59e1cadbb0fdda50a";
12
+ export const WMATIC = "0x0d500b1d8e8ef31e21c99d1db9a6444d3adf1270";
13
+ export const BAL = "0x9a71012B13CA4d3D0Cdc72A177DF3ef03b0E76A3";
14
+ export const AMUSDC = "0x1a13f4ca1d028320a707d99520abfefca3998b7f";
15
+ export const VDEBTWETH = "0xede17e9d79fc6f9ff9250d9eefbdb88cc18038b5";
16
+
17
+ export const TEST_POOL = "0xf36f550907872faaa02477f791df3ce33fe38854";
@@ -0,0 +1,56 @@
1
+ import { Dhedge, ethers } from "..";
2
+ import { Dapp, Network } from "../types";
3
+ import { TEST_POOL, USDC, WETH } from "./constants";
4
+
5
+ import { wallet } from "./wallet";
6
+
7
+ let dhedge: Dhedge;
8
+
9
+ jest.setTimeout(100000);
10
+
11
+ const options = {
12
+ gasLimit: 5000000,
13
+ gasPrice: ethers.utils.parseUnits("35", "gwei")
14
+ };
15
+
16
+ describe("pool", () => {
17
+ beforeAll(() => {
18
+ dhedge = new Dhedge(wallet, Network.POLYGON);
19
+ });
20
+
21
+ // it("approves unlimited USDC on 1Inch", async () => {
22
+ // let result;
23
+ // const pool = await dhedge.loadPool(TEST_POOL);
24
+ // try {
25
+ // result = await pool.approve(
26
+ // Dapp.ONEINCH,
27
+ // USDC,
28
+ // ethers.constants.MaxInt256,
29
+ // options
30
+ // );
31
+ // console.log(result);
32
+ // } catch (e) {
33
+ // console.log(e);
34
+ // }
35
+ // expect(result).not.toBe(null);
36
+ // });
37
+
38
+ it("trades 1 USDC into WETH on 1Inch", async () => {
39
+ let result;
40
+ const pool = await dhedge.loadPool(TEST_POOL);
41
+ try {
42
+ result = await pool.trade(
43
+ Dapp.ONEINCH,
44
+ USDC,
45
+ WETH,
46
+ "1000000",
47
+ 0.5,
48
+ options
49
+ );
50
+ console.log("1inch trade", result);
51
+ } catch (e) {
52
+ console.log(e);
53
+ }
54
+ expect(result).not.toBe(null);
55
+ });
56
+ });