@dhedge/v2-sdk 1.9.0 → 1.9.1

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.9.0",
3
+ "version": "1.9.1",
4
4
  "license": "MIT",
5
5
  "description": "🛠 An SDK for building applications on top of dHEDGE V2",
6
6
  "main": "dist/index.js",
@@ -0,0 +1,191 @@
1
+ {
2
+ "abi": [
3
+ {
4
+ "inputs": [
5
+ {
6
+ "internalType": "address",
7
+ "name": "user",
8
+ "type": "address"
9
+ }
10
+ ],
11
+ "name": "balanceOf",
12
+ "outputs": [
13
+ {
14
+ "internalType": "uint256",
15
+ "name": "",
16
+ "type": "uint256"
17
+ }
18
+ ],
19
+ "stateMutability": "view",
20
+ "type": "function"
21
+ },
22
+ {
23
+ "inputs": [
24
+ {
25
+ "internalType": "uint256",
26
+ "name": "_amount",
27
+ "type": "uint256"
28
+ },
29
+ {
30
+ "internalType": "address",
31
+ "name": "_recipient",
32
+ "type": "address"
33
+ }
34
+ ],
35
+ "name": "deposit",
36
+ "outputs": [],
37
+ "stateMutability": "nonpayable",
38
+ "type": "function"
39
+ },
40
+ {
41
+ "inputs": [
42
+ {
43
+ "internalType": "uint256",
44
+ "name": "_amount",
45
+ "type": "uint256"
46
+ }
47
+ ],
48
+ "name": "deposit",
49
+ "outputs": [],
50
+ "stateMutability": "nonpayable",
51
+ "type": "function"
52
+ },
53
+ {
54
+ "inputs": [
55
+ {
56
+ "internalType": "address",
57
+ "name": "_account",
58
+ "type": "address"
59
+ }
60
+ ],
61
+ "name": "earned",
62
+ "outputs": [
63
+ {
64
+ "internalType": "uint256",
65
+ "name": "_earned",
66
+ "type": "uint256"
67
+ }
68
+ ],
69
+ "stateMutability": "view",
70
+ "type": "function"
71
+ },
72
+ {
73
+ "inputs": [
74
+ {
75
+ "internalType": "address",
76
+ "name": "_account",
77
+ "type": "address"
78
+ }
79
+ ],
80
+ "name": "getReward",
81
+ "outputs": [],
82
+ "stateMutability": "nonpayable",
83
+ "type": "function"
84
+ },
85
+ {
86
+ "inputs": [],
87
+ "name": "isPool",
88
+ "outputs": [
89
+ {
90
+ "internalType": "bool",
91
+ "name": "_isPool",
92
+ "type": "bool"
93
+ }
94
+ ],
95
+ "stateMutability": "view",
96
+ "type": "function"
97
+ },
98
+ {
99
+ "inputs": [],
100
+ "name": "lastTimeRewardApplicable",
101
+ "outputs": [
102
+ {
103
+ "internalType": "uint256",
104
+ "name": "_time",
105
+ "type": "uint256"
106
+ }
107
+ ],
108
+ "stateMutability": "view",
109
+ "type": "function"
110
+ },
111
+ {
112
+ "inputs": [],
113
+ "name": "left",
114
+ "outputs": [
115
+ {
116
+ "internalType": "uint256",
117
+ "name": "_left",
118
+ "type": "uint256"
119
+ }
120
+ ],
121
+ "stateMutability": "view",
122
+ "type": "function"
123
+ },
124
+ {
125
+ "inputs": [
126
+ {
127
+ "internalType": "uint256",
128
+ "name": "amount",
129
+ "type": "uint256"
130
+ }
131
+ ],
132
+ "name": "notifyRewardAmount",
133
+ "outputs": [],
134
+ "stateMutability": "nonpayable",
135
+ "type": "function"
136
+ },
137
+ {
138
+ "inputs": [],
139
+ "name": "rewardPerToken",
140
+ "outputs": [
141
+ {
142
+ "internalType": "uint256",
143
+ "name": "_rewardPerToken",
144
+ "type": "uint256"
145
+ }
146
+ ],
147
+ "stateMutability": "view",
148
+ "type": "function"
149
+ },
150
+ {
151
+ "inputs": [],
152
+ "name": "rewardToken",
153
+ "outputs": [
154
+ {
155
+ "internalType": "address",
156
+ "name": "_token",
157
+ "type": "address"
158
+ }
159
+ ],
160
+ "stateMutability": "view",
161
+ "type": "function"
162
+ },
163
+ {
164
+ "inputs": [],
165
+ "name": "stakingToken",
166
+ "outputs": [
167
+ {
168
+ "internalType": "address",
169
+ "name": "_pool",
170
+ "type": "address"
171
+ }
172
+ ],
173
+ "stateMutability": "view",
174
+ "type": "function"
175
+ },
176
+ {
177
+ "inputs": [
178
+ {
179
+ "internalType": "uint256",
180
+ "name": "_amount",
181
+ "type": "uint256"
182
+ }
183
+ ],
184
+ "name": "withdraw",
185
+ "outputs": [],
186
+ "stateMutability": "nonpayable",
187
+ "type": "function"
188
+ }
189
+ ]
190
+
191
+ }
package/src/config.ts CHANGED
@@ -29,7 +29,8 @@ export const routerAddress: AddressDappNetworkMap = {
29
29
  [Dapp.BALANCER]: "0xBA12222222228d8Ba445958a75a0704d566BF2C8",
30
30
  [Dapp.UNISWAPV3]: "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45",
31
31
  [Dapp.ARRAKIS]: "0xc73fb100a995b33f9fa181d420f4c8d74506df66",
32
- [Dapp.TOROS]: "0xB2F1498983bf9c9442c35F772e6C1AdE66a8DeDE"
32
+ [Dapp.TOROS]: "0xB2F1498983bf9c9442c35F772e6C1AdE66a8DeDE",
33
+ [Dapp.ZEROEX]: "0xdef1c0ded9bec7f1a1670819833240f027b25eff"
33
34
  },
34
35
  [Network.OPTIMISM]: {
35
36
  [Dapp.UNISWAPV3]: "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45",
@@ -38,8 +39,10 @@ export const routerAddress: AddressDappNetworkMap = {
38
39
  [Dapp.ONEINCH]: "0x1111111254EEB25477B68fb85Ed929f73A960582",
39
40
  [Dapp.TOROS]: "0x3988513793bCE39f0167064A9F7fC3617FaF35AB",
40
41
  [Dapp.VELODROME]: "0x9c12939390052919aF3155f41Bf4160Fd3666A6f",
42
+ [Dapp.VELODROMEV2]: "0xa062ae8a9c5e11aaa026fc2670b0d65ccc8b2858",
41
43
  [Dapp.LYRA]: "0xCCE7819d65f348c64B7Beb205BA367b3fE33763B",
42
- [Dapp.ARRAKIS]: "0x9ce88a56d120300061593eF7AD074A1B710094d5"
44
+ [Dapp.ARRAKIS]: "0x9ce88a56d120300061593eF7AD074A1B710094d5",
45
+ [Dapp.ZEROEX]: "0xdef1abe32c034e558cdd535791643c58a13acc10"
43
46
  },
44
47
  [Network.ARBITRUM]: {
45
48
  [Dapp.ONEINCH]: "0x1111111254EEB25477B68fb85Ed929f73A960582",
@@ -60,6 +60,8 @@ import {
60
60
  getFuturesChangeMarginTxData
61
61
  } from "../services/futures";
62
62
  import { getFuturesCancelOrderTxData } from "../services/futures/trade";
63
+ import { getZeroExTradeTxData } from "../services/zeroEx/zeroExTrade";
64
+ import { ApiError } from "../errors";
63
65
 
64
66
  export class Pool {
65
67
  public readonly poolLogic: Contract;
@@ -286,6 +288,16 @@ export class Pool {
286
288
  ): Promise<any> {
287
289
  let swapTxData: string;
288
290
  switch (dapp) {
291
+ case Dapp.ZEROEX:
292
+ swapTxData = await getZeroExTradeTxData(
293
+ this.network,
294
+ assetFrom,
295
+ assetTo,
296
+ amountIn,
297
+ slippage,
298
+ this.address
299
+ );
300
+ break;
289
301
  case Dapp.ONEINCH:
290
302
  const chainId = networkChainIdMap[this.network];
291
303
  const protocols = await getOneInchProtocols(chainId);
@@ -298,8 +310,13 @@ export class Pool {
298
310
  }&destReceiver=${
299
311
  this.address
300
312
  }&slippage=${slippage.toString()}&disableEstimate=true${protocols}`;
301
- const response = await axios.get(apiUrl);
302
- swapTxData = response.data.tx.data;
313
+ try {
314
+ const response = await axios.get(apiUrl);
315
+ swapTxData = response.data.tx.data;
316
+ } catch (e) {
317
+ throw new ApiError("Swap api request of 1inch failed");
318
+ }
319
+
303
320
  break;
304
321
  case Dapp.BALANCER:
305
322
  swapTxData = await this.utils.getBalancerSwapTx(
@@ -483,7 +500,10 @@ export class Pool {
483
500
  ]);
484
501
  break;
485
502
  case Dapp.VELODROME:
486
- stakeTxData = getVelodromeStakeTxData(amount);
503
+ stakeTxData = getVelodromeStakeTxData(amount, false);
504
+ break;
505
+ case Dapp.VELODROMEV2:
506
+ stakeTxData = getVelodromeStakeTxData(amount, true);
487
507
  break;
488
508
  default:
489
509
  throw new Error("dapp not supported");
@@ -526,7 +546,7 @@ export class Pool {
526
546
  }
527
547
 
528
548
  /**
529
- * Unstake liquidity pool tokens from gauge contract
549
+ * Unstake liquidity pool tokens from Velodrome or Balancer gauge
530
550
  * @param {string} gauge Gauge contract address
531
551
  * @param {BigNumber | string} amount Amount of liquidity pool tokens
532
552
  * @param {any} options Transaction options
@@ -1051,7 +1071,11 @@ export class Pool {
1051
1071
  break;
1052
1072
  case Dapp.VELODROME:
1053
1073
  contractAddress = tokenId;
1054
- txData = getVelodromeClaimTxData(this, tokenId);
1074
+ txData = getVelodromeClaimTxData(this, tokenId, false);
1075
+ break;
1076
+ case Dapp.VELODROMEV2:
1077
+ contractAddress = tokenId;
1078
+ txData = getVelodromeClaimTxData(this, tokenId, true);
1055
1079
  break;
1056
1080
  default:
1057
1081
  throw new Error("dapp not supported");
@@ -1162,6 +1186,69 @@ export class Pool {
1162
1186
  return tx;
1163
1187
  }
1164
1188
 
1189
+ /**
1190
+ * Add liquidity to Velodrome V2 pool
1191
+ * @param {string} assetA First asset
1192
+ * @param {string} assetB Second asset
1193
+ * @param {BigNumber | string} amountA Amount first asset
1194
+ * @param {BigNumber | string} amountB Amount second asset
1195
+ * @param { boolean } isStable Is stable pool
1196
+ * @param {any} options Transaction options
1197
+ * @returns {Promise<any>} Transaction
1198
+ */
1199
+ async addLiquidityVelodromeV2(
1200
+ assetA: string,
1201
+ assetB: string,
1202
+ amountA: BigNumber | string,
1203
+ amountB: BigNumber | string,
1204
+ isStable: boolean,
1205
+ options: any = null
1206
+ ): Promise<any> {
1207
+ const tx = await this.poolLogic.execTransaction(
1208
+ routerAddress[this.network][Dapp.VELODROMEV2],
1209
+ await getVelodromeAddLiquidityTxData(
1210
+ this,
1211
+ assetA,
1212
+ assetB,
1213
+ amountA,
1214
+ amountB,
1215
+ isStable
1216
+ ),
1217
+ options
1218
+ );
1219
+ return tx;
1220
+ }
1221
+
1222
+ /**
1223
+ * Remove liquidity from Velodrome V2 pool
1224
+ * @param {string} assetA First asset
1225
+ * @param {string} assetB Second asset
1226
+ * @param {BigNumber | string} amount Amount of LP tokens
1227
+ * @param { boolean } isStable Is stable pool
1228
+ * @param {any} options Transaction options
1229
+ * @returns {Promise<any>} Transaction
1230
+ */
1231
+ async removeLiquidityVelodromeV2(
1232
+ assetA: string,
1233
+ assetB: string,
1234
+ amount: BigNumber | string,
1235
+ isStable: boolean,
1236
+ options: any = null
1237
+ ): Promise<any> {
1238
+ const tx = await this.poolLogic.execTransaction(
1239
+ routerAddress[this.network][Dapp.VELODROMEV2],
1240
+ await getVelodromeRemoveLiquidityTxData(
1241
+ this,
1242
+ assetA,
1243
+ assetB,
1244
+ amount,
1245
+ isStable
1246
+ ),
1247
+ options
1248
+ );
1249
+ return tx;
1250
+ }
1251
+
1165
1252
  /**
1166
1253
  * Trade options on lyra
1167
1254
  * @param {LyraOptionMarket} market Underlying market e.g. eth
package/src/errors.ts ADDED
@@ -0,0 +1,10 @@
1
+ // see https://stackoverflow.com/a/41102306
2
+ const CAN_SET_PROTOTYPE = "setPrototypeOf" in Object;
3
+
4
+ export class ApiError extends Error {
5
+ public constructor(message?: string) {
6
+ super(message ?? "Api request failed");
7
+ this.name = this.constructor.name;
8
+ if (CAN_SET_PROTOTYPE) Object.setPrototypeOf(this, new.target.prototype);
9
+ }
10
+ }
package/src/index.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export * from "./entities";
2
2
  export * from "./types";
3
+ export * from "./errors";
3
4
  export { ethers } from "ethers";
@@ -1,31 +1,44 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
2
  import { BigNumber, ethers } from "ethers";
3
- import IVelodromeGauge from "../../abi/IVelodromeGauge.json";
3
+ import IVelodromeGaugeV1 from "../../abi/IVelodromeGauge.json";
4
+ import IVelodromeGaugeV2 from "../../abi/IVelodromeGaugeV2.json";
4
5
  import { Pool } from "../../entities";
5
- import { Transaction } from "../../types";
6
6
  import { call } from "../../utils/contract";
7
- const iVelodromeGauge = new ethers.utils.Interface(IVelodromeGauge.abi);
7
+ const iVelodromeGaugeV1 = new ethers.utils.Interface(IVelodromeGaugeV1.abi);
8
+ const iVelodromeGaugeV2 = new ethers.utils.Interface(IVelodromeGaugeV2.abi);
8
9
 
9
- export function getVelodromeStakeTxData(amount: BigNumber | string): any {
10
- return iVelodromeGauge.encodeFunctionData(Transaction.DEPOSIT, [amount, "0"]);
10
+ export function getVelodromeStakeTxData(
11
+ amount: BigNumber | string,
12
+ v2: boolean
13
+ ): any {
14
+ const depositParams: [string, unknown[]] = v2
15
+ ? ["deposit(uint256)", [amount]]
16
+ : ["deposit", [amount, 0]];
17
+ const iVelodromeGauge = v2 ? iVelodromeGaugeV2 : iVelodromeGaugeV1;
18
+ return iVelodromeGauge.encodeFunctionData(...depositParams);
11
19
  }
12
20
 
13
21
  export async function getVelodromeClaimTxData(
14
22
  pool: Pool,
15
- gauge: string
23
+ gauge: string,
24
+ v2: boolean
16
25
  ): Promise<any> {
17
- const rewardAssetCount = await call(pool.signer, IVelodromeGauge.abi, [
18
- gauge,
19
- "rewardsListLength",
20
- []
21
- ]);
22
- const rewardAssets = await Promise.all(
23
- Array.from(Array(rewardAssetCount.toNumber()).keys()).map(e =>
24
- call(pool.signer, IVelodromeGauge.abi, [gauge, "rewards", [e]])
25
- )
26
- );
27
- return iVelodromeGauge.encodeFunctionData("getReward", [
28
- pool.address,
29
- rewardAssets
30
- ]);
26
+ if (v2) {
27
+ return iVelodromeGaugeV2.encodeFunctionData("getReward", [pool.address]);
28
+ } else {
29
+ const rewardAssetCount = await call(pool.signer, IVelodromeGaugeV1.abi, [
30
+ gauge,
31
+ "rewardsListLength",
32
+ []
33
+ ]);
34
+ const rewardAssets = await Promise.all(
35
+ Array.from(Array(rewardAssetCount.toNumber()).keys()).map(e =>
36
+ call(pool.signer, IVelodromeGaugeV1.abi, [gauge, "rewards", [e]])
37
+ )
38
+ );
39
+ return iVelodromeGaugeV1.encodeFunctionData("getReward", [
40
+ pool.address,
41
+ rewardAssets
42
+ ]);
43
+ }
31
44
  }
@@ -0,0 +1,52 @@
1
+ import axios from "axios";
2
+ import { BigNumber } from "ethers";
3
+ import { Network } from "../../types";
4
+ import { ApiError } from "../../errors";
5
+
6
+ // slippage of 0x is different from that of 1Inch
7
+ // in 0x, e.g. 0.03 for 3% slippage allowed
8
+ // 1inch slippage 0.5% represented by 0.5
9
+ // 0x slippage 0.5% represented by 0.005
10
+ const getZeroExSlippage = (slippage: number): number => {
11
+ return Number(slippage) / 100;
12
+ };
13
+
14
+ export const getZeroExTradeTxData = async (
15
+ network: Network,
16
+ assetFrom: string,
17
+ assetTo: string,
18
+ amountIn: BigNumber | string,
19
+ slippage = 0.5,
20
+ takerAddress: string
21
+ ): Promise<string> => {
22
+ if (!process.env.ZEROEX_API_KEY)
23
+ throw new Error("ZEROEX_API_KEY not configured in .env file");
24
+ try {
25
+ const slippagePercentage = getZeroExSlippage(slippage);
26
+ const params = {
27
+ buyToken: assetTo,
28
+ sellToken: assetFrom,
29
+ sellAmount: amountIn.toString(),
30
+ // necessary to skip quote validation is that in which the takerAddress refers to a smart contract
31
+ skipValidation: true,
32
+ // Used to enable RFQ-T liquidity
33
+ intentOnFilling: true,
34
+ takerAddress,
35
+ slippagePercentage
36
+ // excludedSourcesParam
37
+ };
38
+ const response = await axios.get(
39
+ `https://${network}.api.0x.org/swap/v1/quote`,
40
+ {
41
+ params,
42
+ headers: {
43
+ "0x-api-key": process.env.ZEROEX_API_KEY
44
+ }
45
+ }
46
+ );
47
+
48
+ return response.data.data;
49
+ } catch (e) {
50
+ throw new ApiError("Swap api request of 0x failed");
51
+ }
52
+ };
@@ -5,7 +5,7 @@ import { Network } from "../types";
5
5
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
6
6
  export const getTxOptions = async (network: Network): Promise<any> => {
7
7
  if (network === Network.POLYGON) {
8
- const result = await axios("https://gasstation-mainnet.matic.network/v2");
8
+ const result = await axios("https://gasstation.polygon.technology/v2");
9
9
  return {
10
10
  gasLimit: "3000000",
11
11
  maxPriorityFeePerGas: new BigNumber(result.data.fast.maxPriorityFee)
@@ -0,0 +1,114 @@
1
+ /* eslint-disable @typescript-eslint/no-non-null-assertion */
2
+ /* eslint-disable @typescript-eslint/no-explicit-any */
3
+ import { Dhedge, Pool } from "..";
4
+ import { routerAddress } from "../config";
5
+ import { Dapp, Network } from "../types";
6
+ import { CONTRACT_ADDRESS, MAX_AMOUNT, TEST_POOL } from "./constants";
7
+ import { allowanceDelta, balanceDelta } from "./utils/token";
8
+
9
+ import { wallet } from "./wallet";
10
+
11
+ const USDC_SUSD_Lp = "0x6d5BA400640226e24b50214d2bBb3D4Db8e6e15a";
12
+ const USDC_SUSD_Gauge = "0x55a272304456355242f6690863b5c8d5c512ff71";
13
+ const network = Network.OPTIMISM;
14
+ const SUSD = CONTRACT_ADDRESS[network].SUSD;
15
+ const USDC = CONTRACT_ADDRESS[network].USDC;
16
+
17
+ let dhedge: Dhedge;
18
+ let pool: Pool;
19
+ jest.setTimeout(100000);
20
+
21
+ describe("pool", () => {
22
+ beforeAll(async () => {
23
+ dhedge = new Dhedge(wallet, network);
24
+ pool = await dhedge.loadPool(TEST_POOL[network]);
25
+ });
26
+
27
+ it("approves unlimited sUSD and USDC on for Velodrome", async () => {
28
+ await pool.approve(Dapp.VELODROMEV2, SUSD, MAX_AMOUNT);
29
+ await pool.approve(Dapp.VELODROMEV2, USDC, MAX_AMOUNT);
30
+ const UsdcAllowanceDelta = await allowanceDelta(
31
+ pool.address,
32
+ USDC,
33
+ routerAddress[network].velodromeV2!,
34
+ pool.signer
35
+ );
36
+ await expect(UsdcAllowanceDelta.gt(0));
37
+ });
38
+
39
+ it("adds USDC and SUSD to a Velodrome stable pool", async () => {
40
+ await pool.addLiquidityVelodromeV2(
41
+ USDC,
42
+ SUSD,
43
+ (5 * 1e6).toString(),
44
+ (5 * 1e18).toString(),
45
+ true
46
+ );
47
+
48
+ const lpTokenDelta = await balanceDelta(
49
+ pool.address,
50
+ USDC_SUSD_Lp,
51
+ pool.signer
52
+ );
53
+ expect(lpTokenDelta.gt(0));
54
+ });
55
+
56
+ it("should stake USDC-sUSD LP in a gauge", async () => {
57
+ const balance = await dhedge.utils.getBalance(USDC_SUSD_Lp, pool.address);
58
+ await pool.approveSpender(USDC_SUSD_Gauge, USDC_SUSD_Lp, MAX_AMOUNT);
59
+ await pool.stakeInGauge(Dapp.VELODROMEV2, USDC_SUSD_Gauge, balance);
60
+ const gaugeBalance = await balanceDelta(
61
+ pool.address,
62
+ USDC_SUSD_Lp,
63
+ pool.signer
64
+ );
65
+ expect(gaugeBalance.gt(0));
66
+ });
67
+
68
+ it("should claim rewards from Gauge", async () => {
69
+ const tx = await pool.claimFees(Dapp.VELODROMEV2, USDC_SUSD_Gauge);
70
+ expect(tx).not.toBe(null);
71
+ });
72
+
73
+ it("should unStake USDC-sUSD LP from a gauge", async () => {
74
+ const gaugeBalance = await dhedge.utils.getBalance(
75
+ USDC_SUSD_Gauge,
76
+ pool.address
77
+ );
78
+ await pool.unstakeFromGauge(USDC_SUSD_Gauge, gaugeBalance);
79
+ const lpTokenDelta = await balanceDelta(
80
+ pool.address,
81
+ USDC_SUSD_Lp,
82
+ pool.signer
83
+ );
84
+ expect(lpTokenDelta.gt(0));
85
+ });
86
+
87
+ it("approves unlimited wETH/stwETH LP for Velodrome", async () => {
88
+ await pool.approve(Dapp.VELODROMEV2, USDC_SUSD_Lp, MAX_AMOUNT);
89
+ const lpAllowanceDelta = await allowanceDelta(
90
+ pool.address,
91
+ USDC_SUSD_Lp,
92
+ routerAddress[network].velodrome!,
93
+ pool.signer
94
+ );
95
+ expect(lpAllowanceDelta.gt(0));
96
+ });
97
+
98
+ it("should remove all liquidity from an existing pool ", async () => {
99
+ const balance = await dhedge.utils.getBalance(USDC_SUSD_Lp, pool.address);
100
+ await pool.removeLiquidityVelodromeV2(USDC, SUSD, balance, true);
101
+ const usdcBalanceDelta = await balanceDelta(
102
+ pool.address,
103
+ USDC,
104
+ pool.signer
105
+ );
106
+ const susdBalanceDelta = await balanceDelta(
107
+ pool.address,
108
+ SUSD,
109
+ pool.signer
110
+ );
111
+ expect(usdcBalanceDelta.gt(0));
112
+ expect(susdBalanceDelta.gt(0));
113
+ });
114
+ });
@@ -0,0 +1,46 @@
1
+ /* eslint-disable @typescript-eslint/no-non-null-assertion */
2
+ import { Dhedge, Pool } from "..";
3
+ import { routerAddress } from "../config";
4
+ import { Dapp, Network } from "../types";
5
+ import { CONTRACT_ADDRESS, MAX_AMOUNT, TEST_POOL } from "./constants";
6
+ import { allowanceDelta, balanceDelta } from "./utils/token";
7
+
8
+ import { wallet } from "./wallet";
9
+
10
+ //const network = Network.OPTIMISM;
11
+ const network = Network.POLYGON;
12
+ // const network = Network.ARBITRUM;
13
+ const USDC = CONTRACT_ADDRESS[network].USDC;
14
+ const WETH = CONTRACT_ADDRESS[network].WETH;
15
+
16
+ let dhedge: Dhedge;
17
+ let pool: Pool;
18
+ jest.setTimeout(100000);
19
+
20
+ describe("pool", () => {
21
+ beforeAll(async () => {
22
+ dhedge = new Dhedge(wallet, network);
23
+ pool = await dhedge.loadPool(TEST_POOL[network]);
24
+ });
25
+
26
+ it("approves unlimited USDC on 0x", async () => {
27
+ await pool.approve(Dapp.ZEROEX, USDC, MAX_AMOUNT);
28
+ const usdcAllowanceDelta = await allowanceDelta(
29
+ pool.address,
30
+ USDC,
31
+ routerAddress[network]["0x"]!,
32
+ pool.signer
33
+ );
34
+ await expect(usdcAllowanceDelta.gt(0));
35
+ });
36
+
37
+ it("trades 2 USDC into WETH on 0x", async () => {
38
+ await pool.trade(Dapp.ZEROEX, USDC, WETH, "2000000", 0.5);
39
+ const wethBalanceDelta = await balanceDelta(
40
+ pool.address,
41
+ WETH,
42
+ pool.signer
43
+ );
44
+ expect(wethBalanceDelta.gt(0));
45
+ });
46
+ });
package/src/types.ts CHANGED
@@ -19,7 +19,9 @@ export enum Dapp {
19
19
  ARRAKIS = "arrakis",
20
20
  TOROS = "toros",
21
21
  VELODROME = "velodrome",
22
- LYRA = "lyra"
22
+ VELODROMEV2 = "velodromeV2",
23
+ LYRA = "lyra",
24
+ ZEROEX = "0x"
23
25
  }
24
26
 
25
27
  export enum Transaction {