@dhedge/v2-sdk 2.1.4 → 2.1.6

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.
Files changed (41) hide show
  1. package/README.md +180 -45
  2. package/dist/config.d.ts +10 -0
  3. package/dist/entities/pool.d.ts +110 -1
  4. package/dist/services/hyperliquid/constants.d.ts +16 -0
  5. package/dist/services/hyperliquid/index.d.ts +6 -0
  6. package/dist/services/hyperliquid/marketData.d.ts +12 -0
  7. package/dist/services/hyperliquid/positionData.d.ts +1 -0
  8. package/dist/services/odos/index.d.ts +15 -1
  9. package/dist/services/toros/limitOrder.d.ts +8 -0
  10. package/dist/test/constants.d.ts +7 -0
  11. package/dist/test/wallet.d.ts +1 -0
  12. package/dist/types.d.ts +12 -2
  13. package/dist/v2-sdk.cjs.development.js +4256 -1335
  14. package/dist/v2-sdk.cjs.development.js.map +1 -1
  15. package/dist/v2-sdk.cjs.production.min.js +1 -1
  16. package/dist/v2-sdk.cjs.production.min.js.map +1 -1
  17. package/dist/v2-sdk.esm.js +5007 -2087
  18. package/dist/v2-sdk.esm.js.map +1 -1
  19. package/package.json +3 -2
  20. package/src/abi/hyperliquid/ICoreDepositWallet.json +130 -0
  21. package/src/abi/hyperliquid/ICoreWriter.json +1 -0
  22. package/src/abi/odos/OdosRouterV3.json +1351 -0
  23. package/src/abi/toros/IPoolLimitOrderManager.json +78 -0
  24. package/src/config.ts +44 -13
  25. package/src/entities/pool.ts +348 -4
  26. package/src/services/hyperliquid/constants.ts +23 -0
  27. package/src/services/hyperliquid/index.ts +176 -0
  28. package/src/services/hyperliquid/marketData.ts +157 -0
  29. package/src/services/hyperliquid/positionData.ts +33 -0
  30. package/src/services/odos/index.ts +97 -13
  31. package/src/services/toros/completeWithdrawal.ts +1 -1
  32. package/src/services/toros/initWithdrawal.ts +1 -1
  33. package/src/services/toros/limitOrder.ts +86 -0
  34. package/src/services/toros/swapData.ts +83 -12
  35. package/src/test/constants.ts +10 -3
  36. package/src/test/hyperliquid.test.ts +107 -0
  37. package/src/test/odos.test.ts +43 -12
  38. package/src/test/pool.test.ts +37 -45
  39. package/src/test/torosLimitOrder.test.ts +130 -0
  40. package/src/test/wallet.ts +2 -1
  41. package/src/types.ts +13 -2
@@ -1,6 +1,9 @@
1
1
  import axios from "axios";
2
2
  import BigNumber from "bignumber.js";
3
- import { odosBaseUrl } from "../odos";
3
+ import { ethers } from "ethers";
4
+ import { odosBaseUrl, SwapReferralInfo, SwapTokenInfo } from "../odos";
5
+ import { networkChainIdMap, OdosSwapFeeRecipient } from "../../config";
6
+ import OdosRouterV3Abi from "../../abi/odos/OdosRouterV3.json";
4
7
 
5
8
  export const SWAPPER_ADDERSS = "0x4F754e0F0924afD74980886b0B479Fa1D7C58D0D";
6
9
 
@@ -22,13 +25,19 @@ export const getSwapDataViaOdos = async ({
22
25
  from,
23
26
  slippage
24
27
  }: SwapParams): Promise<string> => {
25
- let referralCode = 0; // Defaults to 0 for unregistered activity.
26
- if (
27
- process.env.ODOS_REFERAL_CODE &&
28
- Number(process.env.ODOS_REFERAL_CODE) > 0
29
- ) {
30
- referralCode = Number(process.env.ODOS_REFERAL_CODE);
28
+ if (!process.env.ODOS_API_KEY) {
29
+ throw new Error("ODOS_API_KEY is not set");
31
30
  }
31
+ const ODOS_API_KEY = process.env.ODOS_API_KEY;
32
+ const network = (Object.keys(networkChainIdMap) as Array<
33
+ keyof typeof networkChainIdMap
34
+ >).find(key => networkChainIdMap[key] === chainId);
35
+ if (!network) {
36
+ throw new Error(`Unsupported chainId: ${chainId}`);
37
+ }
38
+
39
+ const referralFeeBips = 2; // 2 basis points = 0.02%
40
+
32
41
  const quoteParams = {
33
42
  chainId: chainId,
34
43
  inputTokens: [
@@ -45,12 +54,20 @@ export const getSwapDataViaOdos = async ({
45
54
  ],
46
55
  slippageLimitPercent: new BigNumber(slippage).div(100).toString(), // Convert basis points to percentage
47
56
  userAddr: from,
48
- referralCode
57
+ referralFee: referralFeeBips, // 0.02% fee
58
+ referralFeeRecipient: OdosSwapFeeRecipient[network],
59
+ compact: false
49
60
  };
50
61
  try {
51
62
  const quoteResult = await axios.post(
52
- `${odosBaseUrl}/quote/v2`,
53
- quoteParams
63
+ `${odosBaseUrl}/quote/v3`,
64
+ quoteParams,
65
+ {
66
+ headers: {
67
+ "Content-Type": "application/json",
68
+ "x-api-key": ODOS_API_KEY
69
+ }
70
+ }
54
71
  );
55
72
 
56
73
  const assembleParams = {
@@ -60,9 +77,63 @@ export const getSwapDataViaOdos = async ({
60
77
 
61
78
  const assembleResult = await axios.post(
62
79
  `${odosBaseUrl}/assemble`,
63
- assembleParams
80
+ assembleParams,
81
+ {
82
+ headers: {
83
+ "Content-Type": "application/json",
84
+ "x-api-key": ODOS_API_KEY
85
+ }
86
+ }
64
87
  );
65
- return assembleResult.data.transaction.data;
88
+
89
+ const txData = assembleResult.data.transaction.data;
90
+
91
+ // Decode the transaction data
92
+ const iface = new ethers.utils.Interface(OdosRouterV3Abi.abi);
93
+ const decodedData = iface.parseTransaction({ data: txData });
94
+
95
+ const tokenInfo = decodedData.args[0] as SwapTokenInfo;
96
+ const pathDefinition = decodedData.args[1] as string;
97
+ const executor = decodedData.args[2] as string;
98
+ const referralInfo = decodedData.args[3] as SwapReferralInfo;
99
+
100
+ if (
101
+ referralInfo.fee.lte(
102
+ ethers.BigNumber.from((referralFeeBips * 1e18) / 10000)
103
+ )
104
+ ) {
105
+ // Referral fee is already correct, return original txData
106
+ return txData;
107
+ }
108
+
109
+ const FEE_DENOM = new BigNumber(1e18);
110
+ const correctedFee = new BigNumber((referralFeeBips * 1e18) / 10000);
111
+ const factor = 1.1;
112
+ const correctedOutputQuote = new BigNumber(tokenInfo.outputQuote.toString())
113
+ .times(
114
+ FEE_DENOM.minus(correctedFee).div(
115
+ FEE_DENOM.minus(referralInfo.fee.toString())
116
+ )
117
+ )
118
+ .times(factor);
119
+
120
+ // example referralInfo.fee could be 0.0005 * 1e18 = 500000000000000, which is 0.05%
121
+ // Create corrected referral info
122
+ const correctedTxData = iface.encodeFunctionData(decodedData.name, [
123
+ {
124
+ ...tokenInfo,
125
+ outputQuote: correctedOutputQuote.toFixed(0)
126
+ },
127
+ pathDefinition,
128
+ executor,
129
+ {
130
+ code: referralInfo.code,
131
+ fee: correctedFee.toFixed(0), // align with referralFeeBips
132
+ feeRecipient: referralInfo.feeRecipient
133
+ }
134
+ ]);
135
+
136
+ return correctedTxData;
66
137
  } catch (e) {
67
138
  console.error("Error in Odos API request:", e);
68
139
  throw new Error("Swap api request of Odos failed");
@@ -44,7 +44,8 @@ export const TEST_POOL = {
44
44
  [Network.ARBITRUM]: "0x0b5f6591c8eb23e5a68102d3d39ebbb464ee5c14",
45
45
  [Network.BASE]: "0x4842b42F68524383F609aa46eAfc18c1459cE3cD",
46
46
  [Network.ETHEREUM]: "0xe8e74f664d2d6a919a18b911990db0979789b6f7",
47
- [Network.PLASMA]: "0xdad21646ebb0997eb59de1f6a68a67059daf4c31"
47
+ [Network.PLASMA]: "0xdad21646ebb0997eb59de1f6a68a67059daf4c31",
48
+ [Network.HYPERLIQUID]: "0x3b4427283148c30b13b33a564264c73443ed12d1"
48
49
  };
49
50
 
50
51
  export const CONTRACT_ADDRESS = {
@@ -171,6 +172,10 @@ export const CONTRACT_ADDRESS = {
171
172
  WETH: "0x9895d81bb462a195b4922ed7de0e3acd007c32cb",
172
173
  USDT: "0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb",
173
174
  USDE: "0x5d3a1ff2b6bab83b63cd9ad0787074081a52ef34"
175
+ },
176
+ [Network.HYPERLIQUID]: {
177
+ USDC: "0xb88339cb7199b77e23db6e890353e22632ba630f",
178
+ WETH: ""
174
179
  }
175
180
  };
176
181
 
@@ -182,7 +187,8 @@ export const USDC_BALANCEOF_SLOT = {
182
187
  [Network.POLYGON]: 0,
183
188
  [Network.BASE]: 9,
184
189
  [Network.ETHEREUM]: 9,
185
- [Network.PLASMA]: 9 //Currently no USDC on Plasma
190
+ [Network.PLASMA]: 9,
191
+ [Network.HYPERLIQUID]: 9
186
192
  };
187
193
 
188
194
  export const WETH_BALANCEOF_SLOT = {
@@ -191,5 +197,6 @@ export const WETH_BALANCEOF_SLOT = {
191
197
  [Network.POLYGON]: 0,
192
198
  [Network.BASE]: 0,
193
199
  [Network.ETHEREUM]: 3,
194
- [Network.PLASMA]: 1
200
+ [Network.PLASMA]: 1,
201
+ [Network.HYPERLIQUID]: 1
195
202
  };
@@ -0,0 +1,107 @@
1
+ /* eslint-disable @typescript-eslint/no-non-null-assertion */
2
+
3
+ import { Dhedge, Pool } from "..";
4
+
5
+ import { Network } from "../types";
6
+ import { TEST_POOL } from "./constants";
7
+
8
+ import { TestingRunParams, testingHelper } from "./utils/testingHelper";
9
+
10
+ // import { balanceDelta } from "./utils/token";
11
+
12
+ const testHyperliquid = ({ wallet, network }: TestingRunParams) => {
13
+ let dhedge: Dhedge;
14
+ let pool: Pool;
15
+ jest.setTimeout(100000);
16
+
17
+ describe(`pool on ${network}`, () => {
18
+ beforeAll(async () => {
19
+ dhedge = new Dhedge(wallet, network);
20
+ pool = await dhedge.loadPool(TEST_POOL[network]);
21
+ // // top up gas
22
+ // await provider.send("hardhat_setBalance", [
23
+ // wallet.address,
24
+ // "0x10000000000000000"
25
+ // ]);
26
+ // await provider.send("evm
27
+ // _mine", []);
28
+ // // top up USDC
29
+ // await setUSDCAmount({
30
+ // amount: new BigNumber(2).times(1e6).toFixed(0),
31
+ // userAddress: pool.address,
32
+ // network,
33
+ // provider
34
+ // });
35
+ });
36
+
37
+ // it("approves unlimited USDC on Hyperliquid Core Wallet", async () => {
38
+ // await pool.approve(
39
+ // Dapp.HYPERLIQUID,
40
+ // USDC,
41
+ // MAX_AMOUNT,
42
+ // await getTxOptions(network)
43
+ // );
44
+ // const usdcAllowanceDelta = await allowanceDelta(
45
+ // pool.address,
46
+ // USDC,
47
+ // routerAddress[network][Dapp.HYPERLIQUID]!,
48
+ // pool.signer
49
+ // );
50
+ // await expect(usdcAllowanceDelta.gt(0));
51
+ // });
52
+
53
+ // it("deposits USDC into Hyperliquid Core Wallet", async () => {
54
+ // await pool.depositHyperliquid(
55
+ // "30000000", // 5 USDC with 6 decimals,
56
+ // 4294967295
57
+ // );
58
+ // expect(
59
+ // (await balanceDelta(pool.address, USDC, pool.signer)).eq("-20000000")
60
+ // ).toBe(true);
61
+ // });
62
+
63
+ // it("move 5 USDC from Perp to Spot Wallet", async () => {
64
+ // const tx = await pool.perpToSpotHyperliquid(
65
+ // 0,
66
+ // "5000000" // 5 USDC with 6 decimals
67
+ // );
68
+ // expect(tx).toBeDefined();
69
+ // });
70
+
71
+ // it("withdraws USDC from Hyperliquid Spot Wallet", async () => {
72
+ // const tx = await pool.withdrawHyperliquid(
73
+ // "784577548" // 5 USDC with 6 decimals
74
+ // );
75
+ // expect(tx).toBeDefined();
76
+ // });
77
+
78
+ // it("sets up a BTC_USDC buy order", async () => {
79
+ // const tx = await pool.openMarketOrderHyperliquid(
80
+ // 10182, // HYPE SPOT
81
+ // true, // is long
82
+ // 25, // 25 USD value of BTC,
83
+ // 1, // 0.5% slippage,
84
+ // null,
85
+ // true
86
+ // );
87
+ // expect(tx).toBeDefined();
88
+ // });
89
+
90
+ it("closes a position on Hyperliquid", async () => {
91
+ const tx = await pool.closePositionHyperliquid(
92
+ 1, // ETH Perp,
93
+ 50, // percentage to close
94
+ 1, // 0.5% slippage,
95
+ null,
96
+ true
97
+ );
98
+ expect(tx).toBeDefined();
99
+ });
100
+ });
101
+ };
102
+
103
+ testingHelper({
104
+ network: Network.HYPERLIQUID,
105
+ testingRun: testHyperliquid,
106
+ onFork: false
107
+ });
@@ -13,7 +13,7 @@ import {
13
13
  import { allowanceDelta, balanceDelta } from "./utils/token";
14
14
  import { getTxOptions } from "./txOptions";
15
15
  import BigNumber from "bignumber.js";
16
- import { routerAddress } from "../config";
16
+ import { OdosSwapFeeRecipient, routerAddress } from "../config";
17
17
 
18
18
  const testOdos = ({ wallet, network, provider }: TestingRunParams) => {
19
19
  const USDC = CONTRACT_ADDRESS[network].USDC;
@@ -35,7 +35,7 @@ const testOdos = ({ wallet, network, provider }: TestingRunParams) => {
35
35
  await provider.send("evm_mine", []);
36
36
  // top up USDC
37
37
  await setUSDCAmount({
38
- amount: new BigNumber(2).times(1e6).toFixed(0),
38
+ amount: new BigNumber(20).times(1e6).toFixed(0),
39
39
  userAddress: pool.address,
40
40
  network,
41
41
  provider
@@ -53,12 +53,12 @@ const testOdos = ({ wallet, network, provider }: TestingRunParams) => {
53
53
  await expect(usdcAllowanceDelta.gt(0));
54
54
  });
55
55
 
56
- it("gets gas estimation for 2 USDC into WETH on Odos", async () => {
56
+ it("gets gas estimation for 10 USDC into WETH on Odos", async () => {
57
57
  const gasEstimate = await pool.trade(
58
58
  Dapp.ODOS,
59
59
  USDC,
60
60
  WETH,
61
- "2000000",
61
+ "10000000",
62
62
  1,
63
63
  await getTxOptions(network),
64
64
  true
@@ -67,13 +67,13 @@ const testOdos = ({ wallet, network, provider }: TestingRunParams) => {
67
67
  expect(gasEstimate.minAmountOut).not.toBeNull();
68
68
  });
69
69
 
70
- it("trades 2 USDC into WETH on Odos", async () => {
70
+ it("trades 10 USDC into WETH on Odos", async () => {
71
71
  await wait(1);
72
72
  await pool.trade(
73
73
  Dapp.ODOS,
74
74
  USDC,
75
75
  WETH,
76
- "2000000",
76
+ "10000000",
77
77
  0.5,
78
78
  await getTxOptions(network)
79
79
  );
@@ -83,20 +83,51 @@ const testOdos = ({ wallet, network, provider }: TestingRunParams) => {
83
83
  pool.signer
84
84
  );
85
85
  expect(wethBalanceDelta.gt(0));
86
+ const wethBalanceDeltaForFeeRecipient = await balanceDelta(
87
+ OdosSwapFeeRecipient[network],
88
+ WETH,
89
+ pool.signer
90
+ );
91
+
92
+ // diffRatio = (1 - fee) / (0.8 * fee)
93
+ // 0.8 is the split percentage for fee recipient
94
+ // e.g. for 0.02% fee, diffRatio = 0.9998 / 0.00016 = 6248.75
95
+ // e.g. for 0.03% fee, diffRatio = 0.9997 / 0.00024 = 4165.42
96
+ // e.g. for 0.04% fee, diffRatio = 0.9996 / 0.00032 = 3123.75
97
+ // e.g. for 0.05% fee, diffRatio = 0.9995 / 0.00040 = 2498.75
98
+ const diffRatio = wethBalanceDelta.div(wethBalanceDeltaForFeeRecipient);
99
+ console.log("diff ratio:", diffRatio.toString());
100
+ expect(diffRatio.gt(6200)).toBe(true);
101
+ expect(diffRatio.lt(6260)).toBe(true);
102
+ const wethBalanceDeltaForRouter = await balanceDelta(
103
+ routerAddress[network]["odos"]!,
104
+ WETH,
105
+ pool.signer
106
+ );
107
+ // diffRatio = (1 - fee) / (0.2 * fee)
108
+ // 0.2 is the split percentage for router
109
+ // e.g. for 0.02% fee, diffRatio = 0.9998 / 0.00004 = 24995
110
+ // e.g. for 0.03% fee, diffRatio = 0.9997 / 0.00006 = 16661.67
111
+ // e.g. for 0.04% fee, diffRatio = 0.9996 / 0.00008 = 12495
112
+ // e.g. for 0.05% fee, diffRatio = 0.9995 / 0.00010 = 9995
113
+ const diffRatioRouter = wethBalanceDelta.div(wethBalanceDeltaForRouter);
114
+ console.log("diff ratio router:", diffRatioRouter.toString());
115
+ expect(diffRatioRouter.gt(24000)).toBe(true);
116
+ expect(diffRatioRouter.lt(26000)).toBe(true);
86
117
  });
87
118
  });
88
119
  };
89
120
 
90
- testingHelper({
91
- network: Network.OPTIMISM,
92
- testingRun: testOdos
93
- });
94
-
95
121
  // testingHelper({
96
- // network: Network.ARBITRUM,
122
+ // network: Network.OPTIMISM,
97
123
  // testingRun: testOdos
98
124
  // });
99
125
 
126
+ testingHelper({
127
+ network: Network.ARBITRUM,
128
+ testingRun: testOdos
129
+ });
130
+
100
131
  // testingHelper({
101
132
  // network: Network.POLYGON,
102
133
  // onFork: false,
@@ -1,12 +1,12 @@
1
- import { BigNumber } from "ethers";
2
- import { Dhedge, Pool } from "..";
3
- import { Network } from "../types";
4
- import { TEST_POOL } from "./constants";
1
+ import { Dhedge, Network, Pool } from "..";
2
+ import { CONTRACT_ADDRESS, TEST_POOL } from "./constants";
5
3
 
6
4
  import { testingHelper, TestingRunParams } from "./utils/testingHelper";
5
+ import { balanceDelta } from "./utils/token";
6
+ // import { allowanceDelta } from "./utils/token";
7
7
  // import { balanceDelta } from "./utils/token";
8
8
 
9
- const testPool = ({ wallet, network, provider }: TestingRunParams) => {
9
+ const testPool = ({ wallet, network }: TestingRunParams) => {
10
10
  let dhedge: Dhedge;
11
11
  let pool: Pool;
12
12
 
@@ -16,31 +16,26 @@ const testPool = ({ wallet, network, provider }: TestingRunParams) => {
16
16
  beforeAll(async () => {
17
17
  dhedge = new Dhedge(wallet, network);
18
18
  pool = await dhedge.loadPool(TEST_POOL[network]);
19
-
20
- await provider.send("hardhat_setBalance", [
21
- wallet.address,
22
- "0x10000000000000000"
23
- ]);
24
19
  });
25
20
 
26
- it("checks fund composition", async () => {
27
- const result = await pool.getComposition();
28
- // console.log(result);
29
- expect(result.length).toBeGreaterThan(0);
30
- });
21
+ // it("checks fund composition", async () => {
22
+ // const result = await pool.getComposition();
23
+ // console.log(result);
24
+ // expect(result.length).toBeGreaterThan(0);
25
+ // });
31
26
 
32
- it("sets max supply cap", async () => {
33
- const totalSupply: BigNumber = await pool.poolLogic.totalSupply();
34
- let initCap = totalSupply;
35
- if (totalSupply.eq(0)) {
36
- initCap = BigNumber.from(1000).mul(BigNumber.from(10).pow(18));
37
- }
38
- await pool.setMaxCap(initCap.mul(2), null, true);
39
- const tx = await pool.setMaxCap(initCap.mul(2));
40
- await tx.wait(1);
41
- const maxCapAfter: BigNumber = await pool.managerLogic.maxSupplyCap();
42
- expect(maxCapAfter).toEqual(initCap.mul(2));
43
- });
27
+ // it("sets max supply cap", async () => {
28
+ // const totalSupply: BigNumber = await pool.poolLogic.totalSupply();
29
+ // let initCap = totalSupply;
30
+ // if (totalSupply.eq(0)) {
31
+ // initCap = BigNumber.from(1000).mul(BigNumber.from(10).pow(18));
32
+ // }
33
+ // await pool.setMaxCap(initCap.mul(2), null, true);
34
+ // const tx = await pool.setMaxCap(initCap.mul(2));
35
+ // await tx.wait(1);
36
+ // const maxCapAfter: BigNumber = await pool.managerLogic.maxSupplyCap();
37
+ // expect(maxCapAfter).toEqual(initCap.mul(2));
38
+ // });
44
39
 
45
40
  // it("sets pool private", async () => {
46
41
  // const result = await pool.setPrivate(true);
@@ -51,10 +46,9 @@ const testPool = ({ wallet, network, provider }: TestingRunParams) => {
51
46
  // const assetsBefore = await pool.getComposition();
52
47
 
53
48
  // const newAssets: AssetEnabled[] = [
54
- // { asset: CONTRACT_ADDRESS[network].USDT, isDeposit: true },
55
- // { asset: CONTRACT_ADDRESS[network].USDE, isDeposit: true },
49
+ // { asset: CONTRACT_ADDRESS[network].USDC, isDeposit: true },
56
50
  // {
57
- // asset: "0x925a2A7214Ed92428B5b1B090F80b25700095e12",
51
+ // asset: "0x3333333333333333333333333333333333333333",
58
52
  // isDeposit: false
59
53
  // }
60
54
  // ];
@@ -65,7 +59,7 @@ const testPool = ({ wallet, network, provider }: TestingRunParams) => {
65
59
 
66
60
  // it("approves USDT balance of User for Deposit", async () => {
67
61
  // await pool.approveDeposit(
68
- // CONTRACT_ADDRESS[network].USDT,
62
+ // CONTRACT_ADDRESS[network].USDC,
69
63
  // ethers.constants.MaxUint256
70
64
  // );
71
65
  // const usdtAllowanceDelta = await allowanceDelta(
@@ -77,18 +71,15 @@ const testPool = ({ wallet, network, provider }: TestingRunParams) => {
77
71
  // expect(usdtAllowanceDelta.gt(0));
78
72
  // });
79
73
 
80
- // it("deposits 200 USDT into Pool", async () => {
81
- // await pool.deposit(
82
- // CONTRACT_ADDRESS[network].USDT,
83
- // (200000000).toString()
84
- // );
85
- // const poolTokenDelta = await balanceDelta(
86
- // pool.address,
87
- // USDT,
88
- // pool.signer
89
- // );
90
- // expect(poolTokenDelta.gt(0));
91
- // });
74
+ it("deposits 200 USDT into Pool", async () => {
75
+ await pool.deposit(CONTRACT_ADDRESS[network].USDC, (30000000).toString());
76
+ const poolTokenDelta = await balanceDelta(
77
+ pool.address,
78
+ CONTRACT_ADDRESS[network].USDC,
79
+ pool.signer
80
+ );
81
+ expect(poolTokenDelta.gt(0));
82
+ });
92
83
 
93
84
  // it("get available Manager Fee", async () => {
94
85
  // const result = await pool.getAvailableManagerFee();
@@ -120,6 +111,7 @@ const testPool = ({ wallet, network, provider }: TestingRunParams) => {
120
111
  // });
121
112
 
122
113
  testingHelper({
123
- network: Network.ARBITRUM,
124
- testingRun: testPool
114
+ network: Network.HYPERLIQUID,
115
+ testingRun: testPool,
116
+ onFork: false
125
117
  });
@@ -0,0 +1,130 @@
1
+ /* eslint-disable @typescript-eslint/no-non-null-assertion */
2
+
3
+ // import { ethers } from "ethers";
4
+ import { Dhedge, Pool } from "..";
5
+ // import { limitOrderAddress } from "../config";
6
+
7
+ import { Network } from "../types";
8
+ // import { MAX_AMOUNT } from "./constants";
9
+ import { testingHelper, TestingRunParams } from "./utils/testingHelper";
10
+
11
+ // import { allowanceDelta } from "./utils/token";
12
+
13
+ // cspell:ignore goldbull
14
+ const TOROS_GOLDBULL2X = "0xc8e7e840ca82804c14061a27aaca1b97a5a592ab";
15
+ // const GOLD_PRICING_ASSET = "0x7624cccCc59361D583F28BEC40D37e7771d2ef5D";
16
+
17
+ const testTorosLimitOrder = ({ wallet, network }: TestingRunParams) => {
18
+ // const ORDER_AMOUNT = ethers.utils.parseEther("0.001");
19
+ // const STOP_LOSS = ethers.utils.parseEther("3000");
20
+ // const TAKE_PROFIT = ethers.utils.parseEther("6000");
21
+
22
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
23
+ let dhedge: Dhedge;
24
+ let pool: Pool;
25
+ jest.setTimeout(100000);
26
+
27
+ describe(`toros limit order on ${network}`, () => {
28
+ beforeAll(async () => {
29
+ dhedge = new Dhedge(wallet, network);
30
+ pool = await dhedge.loadPool(
31
+ "0xdd3d575fae102a12aaa086d97c7a8814eff42ebc" // MCP test pool (with GOLDBULL2X)
32
+ );
33
+ });
34
+
35
+ it("approves Toros vault token for LimitOrderManager", async () => {
36
+ const tx = await pool.approveTorosLimitOrder(
37
+ TOROS_GOLDBULL2X,
38
+ MAX_AMOUNT
39
+ );
40
+ await tx.wait(1);
41
+ const delta = await allowanceDelta(
42
+ pool.address,
43
+ TOROS_GOLDBULL2X,
44
+ limitOrderAddress[network],
45
+ pool.signer
46
+ );
47
+ expect(delta.gt(0)).toBe(true);
48
+ });
49
+
50
+ it("creates a limit order", async () => {
51
+ const tx = await pool.createTorosLimitOrder(
52
+ TOROS_GOLDBULL2X,
53
+ ORDER_AMOUNT,
54
+ STOP_LOSS,
55
+ TAKE_PROFIT,
56
+ GOLD_PRICING_ASSET
57
+ );
58
+ await tx.wait(1);
59
+ const order = await pool.getTorosLimitOrder(
60
+ pool.address,
61
+ TOROS_GOLDBULL2X
62
+ );
63
+ expect(order).not.toBeNull();
64
+ expect(order!.amount.eq(ORDER_AMOUNT)).toBe(true);
65
+ expect(order!.stopLossPriceD18.eq(STOP_LOSS)).toBe(true);
66
+ expect(order!.takeProfitPriceD18.eq(TAKE_PROFIT)).toBe(true);
67
+ expect(order!.pool.toLowerCase()).toBe(TOROS_GOLDBULL2X.toLowerCase());
68
+ expect(order!.pricingAsset.toLowerCase()).toBe(
69
+ GOLD_PRICING_ASSET.toLowerCase()
70
+ );
71
+ });
72
+
73
+ it("modifies a toros limit order", async () => {
74
+ const order = await pool.getTorosLimitOrder(
75
+ pool.address,
76
+ TOROS_GOLDBULL2X
77
+ );
78
+ if (!order) throw new Error("No existing order found");
79
+
80
+ const newStopLoss = order.stopLossPriceD18
81
+ .mul(90)
82
+ .div(100)
83
+ .toString();
84
+ const newTakeProfit = order.takeProfitPriceD18
85
+ .mul(110)
86
+ .div(100)
87
+ .toString();
88
+
89
+ const tx = await pool.modifyTorosLimitOrder(
90
+ TOROS_GOLDBULL2X,
91
+ order.amount,
92
+ newStopLoss,
93
+ newTakeProfit,
94
+ order.pricingAsset
95
+ );
96
+ await tx.wait(1);
97
+
98
+ const modifiedOrder = await pool.getTorosLimitOrder(
99
+ pool.address,
100
+ TOROS_GOLDBULL2X
101
+ );
102
+ expect(modifiedOrder).not.toBeNull();
103
+ expect(modifiedOrder!.stopLossPriceD18.toString()).toBe(newStopLoss);
104
+ expect(modifiedOrder!.takeProfitPriceD18.toString()).toBe(newTakeProfit);
105
+ });
106
+
107
+ it("deletes a toros limit order", async () => {
108
+ const order = await pool.getTorosLimitOrder(
109
+ pool.address,
110
+ TOROS_GOLDBULL2X
111
+ );
112
+ if (!order) throw new Error("No existing order found");
113
+
114
+ const tx = await pool.deleteTorosLimitOrder(TOROS_GOLDBULL2X);
115
+ await tx.wait(1);
116
+
117
+ const deletedOrder = await pool.getTorosLimitOrder(
118
+ pool.address,
119
+ TOROS_GOLDBULL2X
120
+ );
121
+ expect(deletedOrder).toBeNull();
122
+ });
123
+ });
124
+ };
125
+
126
+ testingHelper({
127
+ network: Network.ARBITRUM,
128
+ testingRun: testTorosLimitOrder,
129
+ onFork: false
130
+ });
@@ -9,7 +9,8 @@ export const networkPortMap = {
9
9
  [Network.ARBITRUM]: 8540,
10
10
  [Network.BASE]: 8546,
11
11
  [Network.ETHEREUM]: 8547,
12
- [Network.PLASMA]: 8548
12
+ [Network.PLASMA]: 8548,
13
+ [Network.HYPERLIQUID]: 8549
13
14
  };
14
15
 
15
16
  export const getWalletData = (
package/src/types.ts CHANGED
@@ -7,7 +7,8 @@ export enum Network {
7
7
  ARBITRUM = "arbitrum",
8
8
  BASE = "base",
9
9
  ETHEREUM = "ethereum",
10
- PLASMA = "plasma"
10
+ PLASMA = "plasma",
11
+ HYPERLIQUID = "hyperliquid"
11
12
  }
12
13
 
13
14
  export enum Dapp {
@@ -33,7 +34,8 @@ export enum Dapp {
33
34
  COMPOUNDV3 = "compoundV3",
34
35
  ODOS = "odos",
35
36
  PENDLE = "pendle",
36
- KYBERSWAP = "kyberswap"
37
+ KYBERSWAP = "kyberswap",
38
+ HYPERLIQUID = "hyperliquid"
37
39
  }
38
40
 
39
41
  export enum Transaction {
@@ -111,3 +113,12 @@ export type SDKOptions =
111
113
  useTraderAddressAsFrom?: boolean;
112
114
  }
113
115
  | boolean; // shorthand for { estimateGas: true/false }; for backward compatibility
116
+
117
+ export type LimitOrderInfo = {
118
+ amount: BigNumber;
119
+ stopLossPriceD18: BigNumber;
120
+ takeProfitPriceD18: BigNumber;
121
+ user: string;
122
+ pool: string;
123
+ pricingAsset: string;
124
+ };