@dhedge/v2-sdk 1.10.7 → 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.
- package/dist/entities/pool.d.ts +1 -1
- package/dist/services/pancake/staking.d.ts +4 -0
- package/dist/services/uniswap/V3Liquidity.d.ts +3 -3
- package/dist/services/velodrome/liquidity.d.ts +1 -1
- package/dist/types.d.ts +1 -0
- package/dist/v2-sdk.cjs.development.js +206 -78
- 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 +206 -78
- package/dist/v2-sdk.esm.js.map +1 -1
- package/package.json +2 -2
- package/src/abi/INonfungiblePositionManager.json +0 -28
- package/src/abi/IPancakeMasterChefV3.json +115 -0
- package/src/config.ts +5 -2
- package/src/entities/pool.ts +53 -14
- package/src/services/pancake/staking.ts +46 -0
- package/src/services/uniswap/V3Liquidity.ts +28 -5
- package/src/services/velodrome/liquidity.ts +2 -2
- package/src/test/pancakeCL.test.ts +200 -0
- package/src/types.ts +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dhedge/v2-sdk",
|
|
3
|
-
"version": "1.10.
|
|
3
|
+
"version": "1.10.8",
|
|
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.
|
|
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
|
@@ -87,7 +87,9 @@ export const stakingAddress: AddressDappNetworkMap = {
|
|
|
87
87
|
[Network.ARBITRUM]: {
|
|
88
88
|
[Dapp.COMPOUNDV3]: "0x88730d254a2f7e6ac8388c3198afd694ba9f7fae"
|
|
89
89
|
},
|
|
90
|
-
[Network.BASE]: {
|
|
90
|
+
[Network.BASE]: {
|
|
91
|
+
[Dapp.PANCAKECL]: "0xC6A2Db661D5a5690172d8eB0a7DEA2d3008665A3"
|
|
92
|
+
}
|
|
91
93
|
};
|
|
92
94
|
|
|
93
95
|
export const aaveAddressProvider: AddressDappNetworkMap = {
|
|
@@ -120,7 +122,8 @@ export const nonfungiblePositionManagerAddress: AddressDappNetworkMap = {
|
|
|
120
122
|
},
|
|
121
123
|
[Network.BASE]: {
|
|
122
124
|
[Dapp.UNISWAPV3]: "0x03a520b32C04BF3bEEf7BEb72E919cf822Ed34f1",
|
|
123
|
-
[Dapp.AERODROMECL]: "0x827922686190790b37229fd06084350e74485b72"
|
|
125
|
+
[Dapp.AERODROMECL]: "0x827922686190790b37229fd06084350e74485b72",
|
|
126
|
+
[Dapp.PANCAKECL]: "0x46A15B0b27311cedF172AB29E4f4766fbE7F4364"
|
|
124
127
|
}
|
|
125
128
|
};
|
|
126
129
|
|
package/src/entities/pool.ts
CHANGED
|
@@ -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
|
-
[
|
|
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
|
-
|
|
643
|
-
|
|
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:
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
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:
|
|
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
|
|
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
|
+
});
|