@dhedge/v2-sdk 1.10.2 → 1.10.3

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.2",
3
+ "version": "1.10.3",
4
4
  "license": "MIT",
5
5
  "description": "🛠 An SDK for building applications on top of dHEDGE V2",
6
6
  "main": "dist/index.js",
package/src/config.ts CHANGED
@@ -113,7 +113,8 @@ export const nonfungiblePositionManagerAddress: AddressDappNetworkMap = {
113
113
  [Dapp.UNISWAPV3]: "0xC36442b4a4522E871399CD717aBDD847Ab11FE88"
114
114
  },
115
115
  [Network.BASE]: {
116
- [Dapp.UNISWAPV3]: "0x03a520b32C04BF3bEEf7BEb72E919cf822Ed34f1"
116
+ [Dapp.UNISWAPV3]: "0x03a520b32C04BF3bEEf7BEb72E919cf822Ed34f1",
117
+ [Dapp.AERODROMECL]: "0x827922686190790b37229fd06084350e74485b72"
117
118
  }
118
119
  };
119
120
 
@@ -570,6 +570,7 @@ export class Pool {
570
570
  case Dapp.VELODROMEV2:
571
571
  case Dapp.AERODROME:
572
572
  case Dapp.VELODROMECL:
573
+ case Dapp.AERODROMECL:
573
574
  stakeTxData = getVelodromeStakeTxData(amount, true);
574
575
  break;
575
576
  default:
@@ -979,7 +980,7 @@ export class Pool {
979
980
 
980
981
  /**
981
982
  * Create UniswapV3 liquidity pool
982
- * @param {dapp} Platform either UniswapV3 or VelodromeCL
983
+ * @param {dapp} Platform UniswapV3, VelodromeCL or AerodromeCL
983
984
  * @param {string} assetA First asset
984
985
  * @param {string} assetB Second asset
985
986
  * @param {BigNumber | string} amountA Amount first asset
@@ -994,7 +995,7 @@ export class Pool {
994
995
  * @returns {Promise<any>} Transaction
995
996
  */
996
997
  async addLiquidityUniswapV3(
997
- dapp: Dapp.UNISWAPV3 | Dapp.VELODROMECL,
998
+ dapp: Dapp.UNISWAPV3 | Dapp.VELODROMECL | Dapp.AERODROMECL,
998
999
  assetA: string,
999
1000
  assetB: string,
1000
1001
  amountA: BigNumber | string,
@@ -1012,8 +1013,8 @@ export class Pool {
1012
1013
  (minTick === null || maxTick === null)
1013
1014
  )
1014
1015
  throw new Error("Need to provide price or tick range");
1015
- if ((minPrice || maxPrice) && dapp === Dapp.VELODROMECL)
1016
- throw new Error("no price conversion for Velodrome CL");
1016
+ if ((minPrice || maxPrice) && dapp !== Dapp.UNISWAPV3)
1017
+ throw new Error("no price conversion for Aerodrome/Velodrome CL");
1017
1018
 
1018
1019
  const mintTxData = await getUniswapV3MintTxData(
1019
1020
  dapp,
@@ -1065,7 +1066,8 @@ export class Pool {
1065
1066
  dappAddress = nonfungiblePositionManagerAddress[this.network][dapp];
1066
1067
  break;
1067
1068
  case Dapp.VELODROMECL:
1068
- const tokenIdOwner = await getVelodromeClOwner(this, tokenId);
1069
+ case Dapp.AERODROMECL:
1070
+ const tokenIdOwner = await getVelodromeClOwner(this, dapp, tokenId);
1069
1071
  if (tokenIdOwner.toLowerCase() === this.address.toLowerCase()) {
1070
1072
  dappAddress = nonfungiblePositionManagerAddress[this.network][dapp];
1071
1073
  } else {
@@ -1121,7 +1123,8 @@ export class Pool {
1121
1123
  dappAddress = nonfungiblePositionManagerAddress[this.network][dapp];
1122
1124
  break;
1123
1125
  case Dapp.VELODROMECL:
1124
- const tokenIdOwner = await getVelodromeClOwner(this, tokenId);
1126
+ case Dapp.AERODROMECL:
1127
+ const tokenIdOwner = await getVelodromeClOwner(this, dapp, tokenId);
1125
1128
  if (tokenIdOwner.toLowerCase() === this.address.toLowerCase()) {
1126
1129
  dappAddress = nonfungiblePositionManagerAddress[this.network][dapp];
1127
1130
  } else {
@@ -1201,7 +1204,8 @@ export class Pool {
1201
1204
  txData = getVelodromeClaimTxData(this, tokenId, true);
1202
1205
  break;
1203
1206
  case Dapp.VELODROMECL:
1204
- const tokenIdOwner = await getVelodromeClOwner(this, tokenId);
1207
+ case Dapp.AERODROMECL:
1208
+ const tokenIdOwner = await getVelodromeClOwner(this, dapp, tokenId);
1205
1209
  if (tokenIdOwner.toLowerCase() === this.address.toLowerCase()) {
1206
1210
  contractAddress =
1207
1211
  nonfungiblePositionManagerAddress[this.network][dapp];
@@ -70,7 +70,7 @@ export function tryParseTick(
70
70
  }
71
71
 
72
72
  export async function getUniswapV3MintTxData(
73
- dapp: Dapp.UNISWAPV3 | Dapp.VELODROMECL,
73
+ dapp: Dapp.UNISWAPV3 | Dapp.VELODROMECL | Dapp.AERODROMECL,
74
74
  pool: Pool,
75
75
  assetA: string,
76
76
  assetB: string,
@@ -147,7 +147,7 @@ export async function getUniswapV3MintTxData(
147
147
  INonfungiblePositionManager.abi
148
148
  );
149
149
 
150
- if (dapp === Dapp.VELODROMECL) {
150
+ if (dapp === Dapp.VELODROMECL || dapp === Dapp.AERODROMECL) {
151
151
  iNonfungiblePositionManager = new ethers.utils.Interface(
152
152
  IVeldodromePositionManager.abi
153
153
  );
@@ -162,7 +162,7 @@ export async function getUniswapV3MintTxData(
162
162
  }
163
163
 
164
164
  export async function getUniswapV3Liquidity(
165
- dapp: Dapp.UNISWAPV3 | Dapp.VELODROMECL,
165
+ dapp: Dapp.UNISWAPV3 | Dapp.VELODROMECL | Dapp.AERODROMECL,
166
166
  tokenId: string,
167
167
  pool: Pool
168
168
  ): Promise<BigNumber> {
@@ -184,7 +184,11 @@ export async function getIncreaseLiquidityTxData(
184
184
  amountB: ethers.BigNumber | string
185
185
  ): Promise<any> {
186
186
  let txData;
187
- if (dapp === Dapp.UNISWAPV3 || dapp === Dapp.VELODROMECL) {
187
+ if (
188
+ dapp === Dapp.UNISWAPV3 ||
189
+ dapp === Dapp.VELODROMECL ||
190
+ dapp === Dapp.AERODROMECL
191
+ ) {
188
192
  const abi = new ethers.utils.Interface(INonfungiblePositionManager.abi);
189
193
  txData = abi.encodeFunctionData(Transaction.INCREASE_LIQUIDITY, [
190
194
  [tokenId, amountA, amountB, 0, 0, await getDeadline(pool)]
@@ -214,7 +218,11 @@ export async function getDecreaseLiquidityTxData(
214
218
  amount = 100
215
219
  ): Promise<any> {
216
220
  let txData;
217
- if (dapp === Dapp.UNISWAPV3 || dapp === Dapp.VELODROMECL) {
221
+ if (
222
+ dapp === Dapp.UNISWAPV3 ||
223
+ dapp === Dapp.VELODROMECL ||
224
+ dapp === Dapp.AERODROMECL
225
+ ) {
218
226
  const abi = new ethers.utils.Interface(INonfungiblePositionManager.abi);
219
227
  const liquidity = (await getUniswapV3Liquidity(dapp, tokenId, pool))
220
228
  .times(amount)
@@ -51,11 +51,12 @@ export async function getVelodromeRemoveLiquidityTxData(
51
51
 
52
52
  export async function getVelodromeClOwner(
53
53
  pool: Pool,
54
+ dapp: Dapp.VELODROMECL | Dapp.AERODROMECL,
54
55
  tokenId: string
55
56
  ): Promise<string> {
56
57
  const iNonfungiblePositionManager = new ethers.Contract(
57
58
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
58
- nonfungiblePositionManagerAddress[pool.network][Dapp.VELODROMECL]!,
59
+ nonfungiblePositionManagerAddress[pool.network][dapp]!,
59
60
  INonfungiblePositionManager.abi,
60
61
  pool.signer
61
62
  );
@@ -0,0 +1,188 @@
1
+ import { Dhedge, Pool, ethers } from "..";
2
+
3
+ import { nonfungiblePositionManagerAddress } 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 testAerodromeCL = ({ wallet, network, provider }: TestingRunParams) => {
16
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
17
+ const AERODROME_POSITION_MANGER = nonfungiblePositionManagerAddress[network][
18
+ Dapp.AERODROMECL
19
+ ]!;
20
+
21
+ const USDC = CONTRACT_ADDRESS[network].USDC;
22
+ const USDT = CONTRACT_ADDRESS[network].USDT;
23
+ const USDC_USDT_CL_GAUGE = "0xBd85D45f1636fCEB2359d9Dcf839f12b3cF5AF3F";
24
+ const AERO = CONTRACT_ADDRESS[network].VELO;
25
+
26
+ let dhedge: Dhedge;
27
+ let pool: Pool;
28
+ let velodromePositionManager: ethers.Contract;
29
+ let tokenId: string;
30
+ jest.setTimeout(100000);
31
+
32
+ describe(`[${network}] Aerodrome CL tests`, () => {
33
+ beforeAll(async () => {
34
+ // top up ETH (gas)
35
+ await provider.send("hardhat_setBalance", [
36
+ wallet.address,
37
+ "0x100000000000000"
38
+ ]);
39
+ dhedge = new Dhedge(wallet, network);
40
+ pool = await dhedge.loadPool(TEST_POOL[network]);
41
+
42
+ // setChainlinkTimeout
43
+ await setChainlinkTimeout({ pool, provider }, 86400 * 365);
44
+
45
+ const newAssets: AssetEnabled[] = [
46
+ { asset: USDC, isDeposit: true },
47
+ { asset: USDT, isDeposit: true },
48
+ {
49
+ asset: AERODROME_POSITION_MANGER,
50
+ isDeposit: false
51
+ },
52
+ {
53
+ asset: AERO,
54
+ isDeposit: false
55
+ }
56
+ ];
57
+ await pool.managerLogic.changeAssets(newAssets, []);
58
+
59
+ velodromePositionManager = new ethers.Contract(
60
+ AERODROME_POSITION_MANGER,
61
+ INonfungiblePositionManager.abi,
62
+ pool.signer
63
+ );
64
+ });
65
+
66
+ beforeAfterReset({ beforeAll, afterAll, provider });
67
+
68
+ describe("Liquidity", () => {
69
+ it("approves unlimited USDC and USDT on for Aerodrome CL", async () => {
70
+ await pool.approveSpender(AERODROME_POSITION_MANGER, USDC, MAX_AMOUNT);
71
+ await pool.approveSpender(AERODROME_POSITION_MANGER, USDT, MAX_AMOUNT);
72
+ const UsdcAllowanceDelta = await allowanceDelta(
73
+ pool.address,
74
+ USDC,
75
+ AERODROME_POSITION_MANGER,
76
+ pool.signer
77
+ );
78
+ await expect(UsdcAllowanceDelta.gt(0));
79
+ });
80
+
81
+ it("adds USDC and WETH to a CL (mint position)", async () => {
82
+ const usdcBalance = await pool.utils.getBalance(USDC, pool.address);
83
+ const usdtBalance = await pool.utils.getBalance(USDT, pool.address);
84
+ await pool.addLiquidityUniswapV3(
85
+ Dapp.AERODROMECL,
86
+ USDC,
87
+ USDT,
88
+ usdcBalance.div(2),
89
+ usdtBalance.div(2),
90
+ null,
91
+ null,
92
+ -2,
93
+ 4,
94
+ 1
95
+ );
96
+
97
+ tokenId = (
98
+ await velodromePositionManager.tokenOfOwnerByIndex(pool.address, 0)
99
+ ).toString();
100
+ expect(tokenId).not.toBe(null);
101
+ });
102
+
103
+ it("increases liquidity in a CL position", async () => {
104
+ const usdcBalance = await pool.utils.getBalance(USDC, pool.address);
105
+ const usdtBalance = await pool.utils.getBalance(USDT, pool.address);
106
+ const positionBefore = await velodromePositionManager.positions(
107
+ tokenId
108
+ );
109
+ await pool.increaseLiquidity(
110
+ Dapp.AERODROMECL,
111
+ tokenId,
112
+ usdcBalance.div(2),
113
+ usdtBalance.div(2)
114
+ );
115
+ const positionAfter = await velodromePositionManager.positions(tokenId);
116
+ expect(positionAfter.liquidity.gt(positionBefore.liquidity));
117
+ });
118
+
119
+ it("decreases liquidity from a CL position", async () => {
120
+ const positionBefore = await velodromePositionManager.positions(
121
+ tokenId
122
+ );
123
+ await pool.decreaseLiquidity(Dapp.AERODROMECL, tokenId, 50);
124
+ const positionAfter = await velodromePositionManager.positions(tokenId);
125
+ expect(positionAfter.liquidity.lt(positionBefore.liquidity));
126
+ });
127
+
128
+ it("collects fess of a CL position", async () => {
129
+ await provider.send("evm_increaseTime", [24 * 3600 * 3]); // 1 day
130
+ await provider.send("evm_mine", []);
131
+ await pool.claimFees(Dapp.AERODROMECL, tokenId);
132
+ expect((await balanceDelta(pool.address, USDC, pool.signer)).gt(0));
133
+ });
134
+ });
135
+ describe("Liquidity staking", () => {
136
+ it("stakes a CL position in gauge", async () => {
137
+ await pool.approveSpender(AERODROME_POSITION_MANGER, USDC, MAX_AMOUNT);
138
+ await pool.approveSpender(AERODROME_POSITION_MANGER, USDT, MAX_AMOUNT);
139
+ const usdcBalance = await pool.utils.getBalance(USDC, pool.address);
140
+ const usdtBalance = await pool.utils.getBalance(USDT, pool.address);
141
+ await pool.addLiquidityUniswapV3(
142
+ Dapp.AERODROMECL,
143
+ USDC,
144
+ USDT,
145
+ usdcBalance.div(2),
146
+ usdtBalance.div(2),
147
+ null,
148
+ null,
149
+ -2,
150
+ 4,
151
+ 1
152
+ );
153
+
154
+ tokenId = (
155
+ await velodromePositionManager.tokenOfOwnerByIndex(pool.address, 0)
156
+ ).toString();
157
+ await pool.approveSpenderNFT(
158
+ USDC_USDT_CL_GAUGE,
159
+ AERODROME_POSITION_MANGER,
160
+ tokenId
161
+ );
162
+ await pool.stakeInGauge(Dapp.AERODROMECL, USDC_USDT_CL_GAUGE, tokenId);
163
+ expect(await velodromePositionManager.ownerOf(tokenId)).toBe(
164
+ USDC_USDT_CL_GAUGE
165
+ );
166
+ });
167
+
168
+ it("collects fess of a staked CL position", async () => {
169
+ await provider.send("evm_increaseTime", [24 * 3600]); // 1 day
170
+ await provider.send("evm_mine", []);
171
+ await pool.claimFees(Dapp.AERODROMECL, tokenId);
172
+ expect((await balanceDelta(pool.address, AERO, pool.signer)).gt(0));
173
+ });
174
+
175
+ it("unstakes a CL position from a gauge", async () => {
176
+ await pool.unstakeFromGauge(USDC_USDT_CL_GAUGE, tokenId);
177
+ expect(
178
+ (await velodromePositionManager.ownerOf(tokenId)).toLowerCase()
179
+ ).toBe(pool.address.toLowerCase());
180
+ });
181
+ });
182
+ });
183
+ };
184
+
185
+ testingHelper({
186
+ network: Network.BASE,
187
+ testingRun: testAerodromeCL
188
+ });
@@ -48,6 +48,7 @@ export const TEST_POOL = {
48
48
  export const CONTRACT_ADDRESS = {
49
49
  [Network.POLYGON]: {
50
50
  USDC: "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174",
51
+ USDT: "",
51
52
  SWETH: "",
52
53
  WETH: "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619",
53
54
  WBTC: "0x1BFD67037B42Cf73acF2047067bd4F2C47D9BfD6",
@@ -63,8 +64,9 @@ export const CONTRACT_ADDRESS = {
63
64
 
64
65
  [Network.OPTIMISM]: {
65
66
  USDC: "0x0b2c639c533813f4aa9d7837caf62653d097ff85",
66
- SUSD: "0x8c6f28f2f1a3c87f0f938b96d27520d9751ec8d9",
67
+ USDT: "",
67
68
  SWETH: "",
69
+ SUSD: "0x8c6f28f2f1a3c87f0f938b96d27520d9751ec8d9",
68
70
  WETH: "0x4200000000000000000000000000000000000006",
69
71
  WBTC: "0x68f180fcCe6836688e9084f035309E29Bf0A2095",
70
72
  KWENTA_ETH_PERP_V2: "0x2b3bb4c683bfc5239b029131eef3b1d214478d93",
@@ -81,6 +83,7 @@ export const CONTRACT_ADDRESS = {
81
83
  },
82
84
  [Network.ARBITRUM]: {
83
85
  USDC: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
86
+ USDT: "",
84
87
  SWETH: "0xbc011A12Da28e8F0f528d9eE5E7039E22F91cf18",
85
88
  WETH: "0x82af49447d8a07e3bd95bd0d56f35241523fbab1",
86
89
  WBTC: "0x2f2a2543b76a4166549f7aab2e75bef0aefc5b0f",
@@ -101,6 +104,7 @@ export const CONTRACT_ADDRESS = {
101
104
  },
102
105
  [Network.BASE]: {
103
106
  USDC: "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
107
+ USDT: "0xfde4c96c8593536e31f229ea8f37b2ada2699bb2",
104
108
  WETH: "0x4200000000000000000000000000000000000006",
105
109
  WBTC: "",
106
110
  SWETH: "",
@@ -111,8 +115,8 @@ export const CONTRACT_ADDRESS = {
111
115
  ARRAKIS_USDC_WETH_GAUGE: "",
112
116
  ARRAKIS_USDC_WETH_LP: "",
113
117
  WMATIC: "",
114
- VELODROME_CL_USDC_WETH_GAUGE: "",
115
- VELO: ""
118
+ VELODROME_CL_USDC_WETH_GAUGE: "0xF33a96b5932D9E9B9A0eDA447AbD8C9d48d2e0c8",
119
+ VELO: "0x940181a94A35A4569E4529A3CDfB74e38FD98631"
116
120
  }
117
121
  };
118
122
 
package/src/types.ts CHANGED
@@ -25,7 +25,8 @@ export enum Dapp {
25
25
  LYRA = "lyra",
26
26
  ZEROEX = "0x",
27
27
  RAMSES = "ramses",
28
- AERODROME = "aerodrome"
28
+ AERODROME = "aerodrome",
29
+ AERODROMECL = "aerodromeCL"
29
30
  }
30
31
 
31
32
  export enum Transaction {