@dhedge/v2-sdk 1.10.6 → 1.10.8

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.
@@ -21,6 +21,7 @@ import INonfungiblePositionManager from "../../abi/INonfungiblePositionManager.j
21
21
  import IVeldodromePositionManager from "../../abi/IVelodromeNonfungiblePositionManager.json";
22
22
  import IRamsesPositionManager from "../../abi/IRamsesNonfungiblePositionManager.json";
23
23
  import IArrakisV1RouterStaking from "../../abi/IArrakisV1RouterStaking.json";
24
+ import IPancakeMasterChef from "../../abi/IPancakeMasterChefV3.json";
24
25
  import { getDeadline } from "../../utils/deadline";
25
26
  import BigNumber from "bignumber.js";
26
27
 
@@ -71,7 +72,12 @@ export function tryParseTick(
71
72
  }
72
73
 
73
74
  export async function getUniswapV3MintTxData(
74
- dapp: Dapp.UNISWAPV3 | Dapp.VELODROMECL | Dapp.AERODROMECL | Dapp.RAMSESCL,
75
+ dapp:
76
+ | Dapp.UNISWAPV3
77
+ | Dapp.VELODROMECL
78
+ | Dapp.AERODROMECL
79
+ | Dapp.RAMSESCL
80
+ | Dapp.PANCAKECL,
75
81
  pool: Pool,
76
82
  assetA: string,
77
83
  assetB: string,
@@ -170,7 +176,12 @@ export async function getUniswapV3MintTxData(
170
176
  }
171
177
 
172
178
  export async function getUniswapV3Liquidity(
173
- dapp: Dapp.UNISWAPV3 | Dapp.VELODROMECL | Dapp.AERODROMECL | Dapp.RAMSESCL,
179
+ dapp:
180
+ | Dapp.UNISWAPV3
181
+ | Dapp.VELODROMECL
182
+ | Dapp.AERODROMECL
183
+ | Dapp.RAMSESCL
184
+ | Dapp,
174
185
  tokenId: string,
175
186
  pool: Pool
176
187
  ): Promise<BigNumber> {
@@ -196,7 +207,8 @@ export async function getIncreaseLiquidityTxData(
196
207
  dapp === Dapp.UNISWAPV3 ||
197
208
  dapp === Dapp.VELODROMECL ||
198
209
  dapp === Dapp.AERODROMECL ||
199
- dapp === Dapp.RAMSESCL
210
+ dapp === Dapp.RAMSESCL ||
211
+ dapp === Dapp.PANCAKECL
200
212
  ) {
201
213
  const abi = new ethers.utils.Interface(INonfungiblePositionManager.abi);
202
214
  txData = abi.encodeFunctionData(Transaction.INCREASE_LIQUIDITY, [
@@ -224,14 +236,16 @@ export async function getDecreaseLiquidityTxData(
224
236
  pool: Pool,
225
237
  dapp: Dapp,
226
238
  tokenId: string,
227
- amount = 100
239
+ amount = 100,
240
+ isStaked: boolean
228
241
  ): Promise<any> {
229
242
  let txData;
230
243
  if (
231
244
  dapp === Dapp.UNISWAPV3 ||
232
245
  dapp === Dapp.VELODROMECL ||
233
246
  dapp === Dapp.AERODROMECL ||
234
- dapp === Dapp.RAMSESCL
247
+ dapp === Dapp.RAMSESCL ||
248
+ dapp === Dapp.PANCAKECL
235
249
  ) {
236
250
  const abi = new ethers.utils.Interface(INonfungiblePositionManager.abi);
237
251
  const liquidity = (await getUniswapV3Liquidity(dapp, tokenId, pool))
@@ -248,6 +262,15 @@ export async function getDecreaseLiquidityTxData(
248
262
 
249
263
  const multicallParams = [decreaseLiquidityTxData, collectTxData];
250
264
 
265
+ if (isStaked && dapp === Dapp.PANCAKECL) {
266
+ const abi = new ethers.utils.Interface(IPancakeMasterChef);
267
+ const harvestTxData = abi.encodeFunctionData(Transaction.HARVEST, [
268
+ tokenId,
269
+ pool.address
270
+ ]);
271
+ multicallParams.unshift(harvestTxData);
272
+ }
273
+
251
274
  if (amount === 100) {
252
275
  const burnTxData = abi.encodeFunctionData(Transaction.BURN, [tokenId]);
253
276
  multicallParams.push(burnTxData);
@@ -49,9 +49,9 @@ export async function getVelodromeRemoveLiquidityTxData(
49
49
  ]);
50
50
  }
51
51
 
52
- export async function getVelodromeClOwner(
52
+ export async function getClOwner(
53
53
  pool: Pool,
54
- dapp: Dapp.VELODROMECL | Dapp.AERODROMECL,
54
+ dapp: Dapp.VELODROMECL | Dapp.AERODROMECL | Dapp.PANCAKECL,
55
55
  tokenId: string
56
56
  ): Promise<string> {
57
57
  const iNonfungiblePositionManager = new ethers.Contract(
@@ -81,6 +81,10 @@ const testCompoundV3 = ({ network, provider }: TestingRunParams) => {
81
81
  const wethBalance = await balanceDelta(pool.address, WETH, pool.signer);
82
82
  expect(wethBalance.gt(0));
83
83
  });
84
+
85
+ it("harvests rewards from CompundV3", async () => {
86
+ await pool.harvestCompoundV3Rewards(COMPOUNDV3_WETH);
87
+ });
84
88
  });
85
89
  };
86
90
 
@@ -0,0 +1,200 @@
1
+ import { Dhedge, Pool, ethers } from "..";
2
+
3
+ import { nonfungiblePositionManagerAddress, stakingAddress } from "../config";
4
+ import { AssetEnabled, Dapp, Network } from "../types";
5
+ import { CONTRACT_ADDRESS, MAX_AMOUNT, TEST_POOL } from "./constants";
6
+ import {
7
+ TestingRunParams,
8
+ beforeAfterReset,
9
+ setChainlinkTimeout,
10
+ testingHelper
11
+ } from "./utils/testingHelper";
12
+ import { allowanceDelta, balanceDelta } from "./utils/token";
13
+ import INonfungiblePositionManager from "../abi/INonfungiblePositionManager.json";
14
+
15
+ const testPancakeCL = ({ wallet, network, provider }: TestingRunParams) => {
16
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
17
+ const PANCAKE_POSITION_MANGER = nonfungiblePositionManagerAddress[network][
18
+ Dapp.PANCAKECL
19
+ ]!;
20
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
21
+ const GAUGE = stakingAddress[network][Dapp.PANCAKECL]!;
22
+
23
+ const USDC = CONTRACT_ADDRESS[network].USDC;
24
+ const USDT = CONTRACT_ADDRESS[network].USDT;
25
+
26
+ let dhedge: Dhedge;
27
+ let pool: Pool;
28
+ let positionManager: ethers.Contract;
29
+ let tokenId: string;
30
+ jest.setTimeout(100000);
31
+
32
+ describe(`[${network}] Pancake CL tests`, () => {
33
+ beforeAll(async () => {
34
+ await provider.send("evm_mine", []);
35
+ // top up ETH (gas)
36
+ await provider.send("hardhat_setBalance", [
37
+ wallet.address,
38
+ "0x100000000000000"
39
+ ]);
40
+ dhedge = new Dhedge(wallet, network);
41
+ pool = await dhedge.loadPool(TEST_POOL[network]);
42
+
43
+ // setChainlinkTimeout
44
+ await setChainlinkTimeout({ pool, provider }, 86400 * 365);
45
+
46
+ const newAssets: AssetEnabled[] = [
47
+ { asset: USDC, isDeposit: true },
48
+ { asset: USDT, isDeposit: true },
49
+ {
50
+ asset: PANCAKE_POSITION_MANGER,
51
+ isDeposit: false
52
+ }
53
+ ];
54
+ await pool.managerLogic.changeAssets(newAssets, []);
55
+
56
+ positionManager = new ethers.Contract(
57
+ PANCAKE_POSITION_MANGER,
58
+ INonfungiblePositionManager.abi,
59
+ pool.signer
60
+ );
61
+ });
62
+
63
+ beforeAfterReset({ beforeAll, afterAll, provider });
64
+
65
+ describe("Liquidity", () => {
66
+ it("approves unlimited USDC and USDT on for Aerodrome CL", async () => {
67
+ await pool.approveSpender(PANCAKE_POSITION_MANGER, USDC, MAX_AMOUNT);
68
+ await pool.approveSpender(PANCAKE_POSITION_MANGER, USDT, MAX_AMOUNT);
69
+ const UsdcAllowanceDelta = await allowanceDelta(
70
+ pool.address,
71
+ USDC,
72
+ PANCAKE_POSITION_MANGER,
73
+ pool.signer
74
+ );
75
+ await expect(UsdcAllowanceDelta.gt(0));
76
+ });
77
+
78
+ it("adds USDC and USDT to a CL (mint position)", async () => {
79
+ const usdcBalance = await pool.utils.getBalance(USDC, pool.address);
80
+ const usdtBalance = await pool.utils.getBalance(USDT, pool.address);
81
+ await pool.addLiquidityUniswapV3(
82
+ Dapp.PANCAKECL,
83
+ USDC,
84
+ USDT,
85
+ usdcBalance.div(2),
86
+ usdtBalance.div(2),
87
+ null,
88
+ null,
89
+ -73,
90
+ 127,
91
+ 100
92
+ );
93
+
94
+ tokenId = (
95
+ await positionManager.tokenOfOwnerByIndex(pool.address, 0)
96
+ ).toString();
97
+ expect(tokenId).not.toBe(null);
98
+ });
99
+
100
+ it("increases liquidity in a CL position", async () => {
101
+ const usdcBalance = await pool.utils.getBalance(USDC, pool.address);
102
+ const usdtBalance = await pool.utils.getBalance(USDT, pool.address);
103
+ const positionBefore = await positionManager.positions(tokenId);
104
+ await pool.increaseLiquidity(
105
+ Dapp.PANCAKECL,
106
+ tokenId,
107
+ usdcBalance.div(2),
108
+ usdtBalance.div(2)
109
+ );
110
+ const positionAfter = await positionManager.positions(tokenId);
111
+ expect(positionAfter.liquidity.gt(positionBefore.liquidity));
112
+ });
113
+
114
+ it("decreases liquidity from a CL position", async () => {
115
+ const positionBefore = await positionManager.positions(tokenId);
116
+ await pool.decreaseLiquidity(Dapp.PANCAKECL, tokenId, 50);
117
+ const positionAfter = await positionManager.positions(tokenId);
118
+ expect(positionAfter.liquidity.lt(positionBefore.liquidity));
119
+ });
120
+
121
+ it("collects fess of a CL position", async () => {
122
+ await provider.send("evm_increaseTime", [24 * 3600 * 3]); // 1 day
123
+ await provider.send("evm_mine", []);
124
+ await pool.claimFees(Dapp.PANCAKECL, tokenId);
125
+ expect((await balanceDelta(pool.address, USDC, pool.signer)).gt(0));
126
+ });
127
+ });
128
+ describe("Liquidity staking", () => {
129
+ it("stakes a CL position in gauge", async () => {
130
+ await pool.approveSpender(PANCAKE_POSITION_MANGER, USDC, MAX_AMOUNT);
131
+ await pool.approveSpender(PANCAKE_POSITION_MANGER, USDT, MAX_AMOUNT);
132
+ const usdcBalance = await pool.utils.getBalance(USDC, pool.address);
133
+ const usdtBalance = await pool.utils.getBalance(USDT, pool.address);
134
+ await pool.addLiquidityUniswapV3(
135
+ Dapp.PANCAKECL,
136
+ USDC,
137
+ USDT,
138
+ usdcBalance.div(2),
139
+ usdtBalance.div(2),
140
+ null,
141
+ null,
142
+ -73,
143
+ 127,
144
+ 100
145
+ );
146
+
147
+ tokenId = (
148
+ await positionManager.tokenOfOwnerByIndex(pool.address, 0)
149
+ ).toString();
150
+ await pool.stakeInGauge(Dapp.PANCAKECL, GAUGE, tokenId);
151
+ expect(await positionManager.ownerOf(tokenId)).toBe(GAUGE);
152
+ });
153
+
154
+ it("increases liquidity in a staked CL position", async () => {
155
+ await pool.approveSpender(GAUGE, USDC, MAX_AMOUNT);
156
+ await pool.approveSpender(GAUGE, USDT, MAX_AMOUNT);
157
+ const usdcBalance = await pool.utils.getBalance(USDC, pool.address);
158
+ const usdtBalance = await pool.utils.getBalance(USDT, pool.address);
159
+ const positionBefore = await positionManager.positions(tokenId);
160
+ await pool.increaseLiquidity(
161
+ Dapp.PANCAKECL,
162
+ tokenId,
163
+ usdcBalance.div(2),
164
+ usdtBalance.div(2)
165
+ );
166
+ const positionAfter = await positionManager.positions(tokenId);
167
+ expect(positionAfter.liquidity.gt(positionBefore.liquidity));
168
+ });
169
+
170
+ it("collects fess from a staked CL position", async () => {
171
+ await pool.claimFees(Dapp.PANCAKECL, tokenId);
172
+ });
173
+
174
+ it("decreases liquidity from a CL position", async () => {
175
+ const positionBefore = await positionManager.positions(tokenId);
176
+ await pool.decreaseLiquidity(Dapp.PANCAKECL, tokenId, 50);
177
+ const positionAfter = await positionManager.positions(tokenId);
178
+ expect(positionAfter.liquidity.lt(positionBefore.liquidity));
179
+ });
180
+
181
+ it("unstakes a CL position from a gauge", async () => {
182
+ await pool.unstakeFromGauge(GAUGE, tokenId);
183
+ expect((await positionManager.ownerOf(tokenId)).toLowerCase()).toBe(
184
+ pool.address.toLowerCase()
185
+ );
186
+ });
187
+
188
+ it("remove all liquidity from a staked CL position", async () => {
189
+ await pool.stakeInGauge(Dapp.PANCAKECL, GAUGE, tokenId);
190
+ await pool.decreaseLiquidity(Dapp.PANCAKECL, tokenId, 100);
191
+ expect((await positionManager.balanceOf(pool.address)).eq(0));
192
+ });
193
+ });
194
+ });
195
+ };
196
+
197
+ testingHelper({
198
+ network: Network.BASE,
199
+ testingRun: testPancakeCL
200
+ });
package/src/types.ts CHANGED
@@ -27,7 +27,9 @@ export enum Dapp {
27
27
  RAMSES = "ramses",
28
28
  AERODROME = "aerodrome",
29
29
  AERODROMECL = "aerodromeCL",
30
- RAMSESCL = "ramsesCL"
30
+ RAMSESCL = "ramsesCL",
31
+ PANCAKECL = "pancakeCL",
32
+ COMPOUNDV3 = "compoundV3"
31
33
  }
32
34
 
33
35
  export enum Transaction {