@dhedge/v2-sdk 1.10.7 → 1.10.9

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dhedge/v2-sdk",
3
- "version": "1.10.7",
3
+ "version": "1.10.9",
4
4
  "license": "MIT",
5
5
  "description": "🛠 An SDK for building applications on top of dHEDGE V2",
6
6
  "main": "dist/index.js",
@@ -34,7 +34,7 @@
34
34
  "@size-limit/preset-small-lib": "^5.0.1",
35
35
  "@types/jest": "^28.1.7",
36
36
  "@types/lodash": "^4.14.178",
37
- "hardhat": "2.19.3",
37
+ "hardhat": "2.22.18",
38
38
  "husky": "^7.0.1",
39
39
  "jest": "^28.1.3",
40
40
  "size-limit": "^5.0.1",
@@ -822,34 +822,6 @@
822
822
  "stateMutability": "nonpayable",
823
823
  "type": "function"
824
824
  },
825
- {
826
- "inputs": [
827
- {
828
- "internalType": "address",
829
- "name": "from",
830
- "type": "address"
831
- },
832
- {
833
- "internalType": "address",
834
- "name": "to",
835
- "type": "address"
836
- },
837
- {
838
- "internalType": "uint256",
839
- "name": "tokenId",
840
- "type": "uint256"
841
- },
842
- {
843
- "internalType": "bytes",
844
- "name": "_data",
845
- "type": "bytes"
846
- }
847
- ],
848
- "name": "safeTransferFrom",
849
- "outputs": [],
850
- "stateMutability": "nonpayable",
851
- "type": "function"
852
- },
853
825
  {
854
826
  "inputs": [
855
827
  {
@@ -0,0 +1,115 @@
1
+ [
2
+ {
3
+ "inputs": [
4
+ {
5
+ "internalType": "uint256",
6
+ "name": "tokenId",
7
+ "type": "uint256"
8
+ },
9
+ {
10
+ "internalType": "address",
11
+ "name": "to",
12
+ "type": "address"
13
+ }
14
+ ],
15
+ "name": "harvest",
16
+ "outputs": [
17
+ {
18
+ "internalType": "uint256",
19
+ "name": "reward",
20
+ "type": "uint256"
21
+ }
22
+ ],
23
+ "stateMutability": "nonpayable",
24
+ "type": "function"
25
+ },
26
+ {
27
+ "inputs": [
28
+ {
29
+ "internalType": "uint256",
30
+ "name": "_tokenId",
31
+ "type": "uint256"
32
+ },
33
+ {
34
+ "internalType": "address",
35
+ "name": "_to",
36
+ "type": "address"
37
+ }
38
+ ],
39
+ "name": "withdraw",
40
+ "outputs": [
41
+ {
42
+ "internalType": "uint256",
43
+ "name": "reward",
44
+ "type": "uint256"
45
+ }
46
+ ],
47
+ "stateMutability": "nonpayable",
48
+ "type": "function"
49
+ },
50
+ {
51
+ "inputs": [
52
+ {
53
+ "internalType": "bytes[]",
54
+ "name": "data",
55
+ "type": "bytes[]"
56
+ }
57
+ ],
58
+ "name": "multicall",
59
+ "outputs": [
60
+ {
61
+ "internalType": "bytes[]",
62
+ "name": "results",
63
+ "type": "bytes[]"
64
+ }
65
+ ],
66
+ "stateMutability": "payable",
67
+ "type": "function"
68
+ },
69
+ {
70
+ "inputs": [
71
+ {
72
+ "components": [
73
+ {
74
+ "internalType": "uint256",
75
+ "name": "tokenId",
76
+ "type": "uint256"
77
+ },
78
+ {
79
+ "internalType": "address",
80
+ "name": "recipient",
81
+ "type": "address"
82
+ },
83
+ {
84
+ "internalType": "uint128",
85
+ "name": "amount0Max",
86
+ "type": "uint128"
87
+ },
88
+ {
89
+ "internalType": "uint128",
90
+ "name": "amount1Max",
91
+ "type": "uint128"
92
+ }
93
+ ],
94
+ "internalType": "struct INonfungiblePositionManager.CollectParams",
95
+ "name": "params",
96
+ "type": "tuple"
97
+ }
98
+ ],
99
+ "name": "collect",
100
+ "outputs": [
101
+ {
102
+ "internalType": "uint256",
103
+ "name": "amount0",
104
+ "type": "uint256"
105
+ },
106
+ {
107
+ "internalType": "uint256",
108
+ "name": "amount1",
109
+ "type": "uint256"
110
+ }
111
+ ],
112
+ "stateMutability": "payable",
113
+ "type": "function"
114
+ }
115
+ ]
package/src/config.ts CHANGED
@@ -85,9 +85,12 @@ export const stakingAddress: AddressDappNetworkMap = {
85
85
  [Dapp.COMPOUNDV3]: "0x443ea0340cb75a160f31a440722dec7b5bc3c2e9"
86
86
  },
87
87
  [Network.ARBITRUM]: {
88
- [Dapp.COMPOUNDV3]: "0x88730d254a2f7e6ac8388c3198afd694ba9f7fae"
88
+ [Dapp.COMPOUNDV3]: "0x88730d254a2f7e6ac8388c3198afd694ba9f7fae",
89
+ [Dapp.PANCAKECL]: "0x5e09ACf80C0296740eC5d6F643005a4ef8DaA694"
89
90
  },
90
- [Network.BASE]: {}
91
+ [Network.BASE]: {
92
+ [Dapp.PANCAKECL]: "0xC6A2Db661D5a5690172d8eB0a7DEA2d3008665A3"
93
+ }
91
94
  };
92
95
 
93
96
  export const aaveAddressProvider: AddressDappNetworkMap = {
@@ -116,11 +119,13 @@ export const nonfungiblePositionManagerAddress: AddressDappNetworkMap = {
116
119
  },
117
120
  [Network.ARBITRUM]: {
118
121
  [Dapp.UNISWAPV3]: "0xC36442b4a4522E871399CD717aBDD847Ab11FE88",
119
- [Dapp.RAMSESCL]: "0xAA277CB7914b7e5514946Da92cb9De332Ce610EF"
122
+ [Dapp.RAMSESCL]: "0xAA277CB7914b7e5514946Da92cb9De332Ce610EF",
123
+ [Dapp.PANCAKECL]: "0x46a15b0b27311cedf172ab29e4f4766fbe7f4364"
120
124
  },
121
125
  [Network.BASE]: {
122
126
  [Dapp.UNISWAPV3]: "0x03a520b32C04BF3bEEf7BEb72E919cf822Ed34f1",
123
- [Dapp.AERODROMECL]: "0x827922686190790b37229fd06084350e74485b72"
127
+ [Dapp.AERODROMECL]: "0x827922686190790b37229fd06084350e74485b72",
128
+ [Dapp.PANCAKECL]: "0x46A15B0b27311cedF172AB29E4f4766fbE7F4364"
124
129
  }
125
130
  };
126
131
 
@@ -46,8 +46,8 @@ import {
46
46
  } from "../services/toros/easySwapper";
47
47
  import { getAaveV3ClaimTxData } from "../services/aave/incentives";
48
48
  import {
49
+ getClOwner,
49
50
  getVelodromeAddLiquidityTxData,
50
- getVelodromeClOwner,
51
51
  getVelodromeRemoveLiquidityTxData
52
52
  } from "../services/velodrome/liquidity";
53
53
  import {
@@ -81,6 +81,11 @@ import {
81
81
  getCompoundV3WithdrawTxData
82
82
  } from "../services/compound/lending";
83
83
  import { getCompoundV3ClaimTxData } from "../services/compound/rewards";
84
+ import {
85
+ getPancakeHarvestClaimTxData,
86
+ getPancakeStakeTxData,
87
+ getPancakeUnStakeTxData
88
+ } from "../services/pancake/staking";
84
89
 
85
90
  export class Pool {
86
91
  public readonly poolLogic: Contract;
@@ -582,12 +587,19 @@ export class Pool {
582
587
  case Dapp.AERODROMECL:
583
588
  stakeTxData = getVelodromeStakeTxData(amount, true);
584
589
  break;
590
+ case Dapp.PANCAKECL:
591
+ stakeTxData = getPancakeStakeTxData(this, amount.toString(), gauge);
592
+ break;
585
593
  default:
586
594
  throw new Error("dapp not supported");
587
595
  }
596
+ const txTo =
597
+ dapp !== Dapp.PANCAKECL
598
+ ? gauge
599
+ : nonfungiblePositionManagerAddress[this.network][dapp];
588
600
  const tx = await getPoolTxOrGasEstimate(
589
601
  this,
590
- [gauge, stakeTxData, options],
602
+ [txTo, stakeTxData, options],
591
603
  estimateGas
592
604
  );
593
605
  return tx;
@@ -638,10 +650,18 @@ export class Pool {
638
650
  options: any = null,
639
651
  estimateGas = false
640
652
  ): Promise<any> {
653
+ let unstakeTxData;
641
654
  const rewardsGauge = new ethers.utils.Interface(IBalancerRewardsGauge.abi);
642
- const unstakeTxData = rewardsGauge.encodeFunctionData("withdraw(uint256)", [
643
- amount
644
- ]);
655
+ if (
656
+ gauge.toLowerCase() ===
657
+ stakingAddress[this.network][Dapp.PANCAKECL]?.toLowerCase()
658
+ ) {
659
+ unstakeTxData = getPancakeUnStakeTxData(this, amount.toString());
660
+ } else {
661
+ unstakeTxData = rewardsGauge.encodeFunctionData("withdraw(uint256)", [
662
+ amount
663
+ ]);
664
+ }
645
665
  const tx = await getPoolTxOrGasEstimate(
646
666
  this,
647
667
  [gauge, unstakeTxData, options],
@@ -1083,7 +1103,12 @@ export class Pool {
1083
1103
  * @returns {Promise<any>} Transaction
1084
1104
  */
1085
1105
  async addLiquidityUniswapV3(
1086
- dapp: Dapp.UNISWAPV3 | Dapp.VELODROMECL | Dapp.AERODROMECL | Dapp.RAMSESCL,
1106
+ dapp:
1107
+ | Dapp.UNISWAPV3
1108
+ | Dapp.VELODROMECL
1109
+ | Dapp.AERODROMECL
1110
+ | Dapp.RAMSESCL
1111
+ | Dapp.PANCAKECL,
1087
1112
  assetA: string,
1088
1113
  assetB: string,
1089
1114
  amountA: BigNumber | string,
@@ -1156,7 +1181,8 @@ export class Pool {
1156
1181
  break;
1157
1182
  case Dapp.VELODROMECL:
1158
1183
  case Dapp.AERODROMECL:
1159
- const tokenIdOwner = await getVelodromeClOwner(this, dapp, tokenId);
1184
+ case Dapp.PANCAKECL:
1185
+ const tokenIdOwner = await getClOwner(this, dapp, tokenId);
1160
1186
  if (tokenIdOwner.toLowerCase() === this.address.toLowerCase()) {
1161
1187
  dappAddress = nonfungiblePositionManagerAddress[this.network][dapp];
1162
1188
  } else {
@@ -1171,8 +1197,14 @@ export class Pool {
1171
1197
  default:
1172
1198
  throw new Error("dapp not supported");
1173
1199
  }
1174
- if (!isStaked) {
1175
- txData = await getDecreaseLiquidityTxData(this, dapp, tokenId, amount);
1200
+ if (!isStaked || dapp === Dapp.PANCAKECL) {
1201
+ txData = await getDecreaseLiquidityTxData(
1202
+ this,
1203
+ dapp,
1204
+ tokenId,
1205
+ amount,
1206
+ isStaked
1207
+ );
1176
1208
  } else {
1177
1209
  throw new Error(
1178
1210
  "unsupported decreaseStakedLiquidity: unstake first to decrease lp"
@@ -1214,7 +1246,8 @@ export class Pool {
1214
1246
  break;
1215
1247
  case Dapp.VELODROMECL:
1216
1248
  case Dapp.AERODROMECL:
1217
- const tokenIdOwner = await getVelodromeClOwner(this, dapp, tokenId);
1249
+ case Dapp.PANCAKECL:
1250
+ const tokenIdOwner = await getClOwner(this, dapp, tokenId);
1218
1251
  if (tokenIdOwner.toLowerCase() === this.address.toLowerCase()) {
1219
1252
  dappAddress = nonfungiblePositionManagerAddress[this.network][dapp];
1220
1253
  } else {
@@ -1229,7 +1262,8 @@ export class Pool {
1229
1262
  default:
1230
1263
  throw new Error("dapp not supported");
1231
1264
  }
1232
- if (!isStaked) {
1265
+ //PancakeCL supports increase liquidity to staked position
1266
+ if (!isStaked || dapp === Dapp.PANCAKECL) {
1233
1267
  txData = await getIncreaseLiquidityTxData(
1234
1268
  this,
1235
1269
  dapp,
@@ -1296,7 +1330,8 @@ export class Pool {
1296
1330
  break;
1297
1331
  case Dapp.VELODROMECL:
1298
1332
  case Dapp.AERODROMECL:
1299
- const tokenIdOwner = await getVelodromeClOwner(this, dapp, tokenId);
1333
+ case Dapp.PANCAKECL:
1334
+ const tokenIdOwner = await getClOwner(this, dapp, tokenId);
1300
1335
  if (tokenIdOwner.toLowerCase() === this.address.toLowerCase()) {
1301
1336
  contractAddress =
1302
1337
  nonfungiblePositionManagerAddress[this.network][dapp];
@@ -1305,9 +1340,13 @@ export class Pool {
1305
1340
  [[tokenId, this.address, MaxUint128, MaxUint128]]
1306
1341
  );
1307
1342
  } else {
1308
- //staked in gauge
1343
+ //staked in gauge or pancake masterchef
1309
1344
  contractAddress = tokenIdOwner;
1310
- txData = getVelodromeCLClaimTxData(tokenId);
1345
+ if (dapp === Dapp.PANCAKECL) {
1346
+ txData = getPancakeHarvestClaimTxData(this, tokenId);
1347
+ } else {
1348
+ txData = getVelodromeCLClaimTxData(tokenId);
1349
+ }
1311
1350
  }
1312
1351
  break;
1313
1352
  default:
@@ -0,0 +1,46 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import { ethers } from "ethers";
3
+ import INonfungiblePositionManager from "../../abi/INonfungiblePositionManager.json";
4
+ import IPanncakeMasterChef from "../../abi/IPancakeMasterChefV3.json";
5
+ import { Pool } from "../../entities";
6
+ import { Transaction } from "../../types";
7
+ import { MaxUint128 } from "../../config";
8
+ const iNonfungiblePositionManager = new ethers.utils.Interface(
9
+ INonfungiblePositionManager.abi
10
+ );
11
+ const iMasterChef = new ethers.utils.Interface(IPanncakeMasterChef);
12
+
13
+ export function getPancakeStakeTxData(
14
+ pool: Pool,
15
+ tokenId: string,
16
+ stakingAddress: string
17
+ ): string {
18
+ return iNonfungiblePositionManager.encodeFunctionData("safeTransferFrom", [
19
+ pool.address,
20
+ stakingAddress,
21
+ tokenId
22
+ ]);
23
+ }
24
+
25
+ export function getPancakeUnStakeTxData(pool: Pool, tokenId: string): string {
26
+ return iMasterChef.encodeFunctionData("withdraw", [tokenId, pool.address]);
27
+ }
28
+
29
+ export function getPancakeHarvestClaimTxData(
30
+ pool: Pool,
31
+ tokenId: string
32
+ ): string {
33
+ const harvestTxData = iMasterChef.encodeFunctionData(Transaction.HARVEST, [
34
+ tokenId,
35
+ pool.address
36
+ ]);
37
+ const collectTxData = iMasterChef.encodeFunctionData(Transaction.COLLECT, [
38
+ [tokenId, pool.address, MaxUint128, MaxUint128]
39
+ ]);
40
+
41
+ const multicallParams = [harvestTxData, collectTxData];
42
+
43
+ return iMasterChef.encodeFunctionData(Transaction.MULTI_CALL, [
44
+ multicallParams
45
+ ]);
46
+ }
@@ -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(
@@ -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
@@ -28,6 +28,7 @@ export enum Dapp {
28
28
  AERODROME = "aerodrome",
29
29
  AERODROMECL = "aerodromeCL",
30
30
  RAMSESCL = "ramsesCL",
31
+ PANCAKECL = "pancakeCL",
31
32
  COMPOUNDV3 = "compoundV3"
32
33
  }
33
34