@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.
- package/README.md +180 -45
- package/dist/config.d.ts +10 -0
- package/dist/entities/pool.d.ts +110 -1
- package/dist/services/hyperliquid/constants.d.ts +16 -0
- package/dist/services/hyperliquid/index.d.ts +6 -0
- package/dist/services/hyperliquid/marketData.d.ts +12 -0
- package/dist/services/hyperliquid/positionData.d.ts +1 -0
- package/dist/services/odos/index.d.ts +15 -1
- package/dist/services/toros/limitOrder.d.ts +8 -0
- package/dist/test/constants.d.ts +7 -0
- package/dist/test/wallet.d.ts +1 -0
- package/dist/types.d.ts +12 -2
- package/dist/v2-sdk.cjs.development.js +4256 -1335
- 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 +5007 -2087
- package/dist/v2-sdk.esm.js.map +1 -1
- package/package.json +3 -2
- package/src/abi/hyperliquid/ICoreDepositWallet.json +130 -0
- package/src/abi/hyperliquid/ICoreWriter.json +1 -0
- package/src/abi/odos/OdosRouterV3.json +1351 -0
- package/src/abi/toros/IPoolLimitOrderManager.json +78 -0
- package/src/config.ts +44 -13
- package/src/entities/pool.ts +348 -4
- package/src/services/hyperliquid/constants.ts +23 -0
- package/src/services/hyperliquid/index.ts +176 -0
- package/src/services/hyperliquid/marketData.ts +157 -0
- package/src/services/hyperliquid/positionData.ts +33 -0
- package/src/services/odos/index.ts +97 -13
- package/src/services/toros/completeWithdrawal.ts +1 -1
- package/src/services/toros/initWithdrawal.ts +1 -1
- package/src/services/toros/limitOrder.ts +86 -0
- package/src/services/toros/swapData.ts +83 -12
- package/src/test/constants.ts +10 -3
- package/src/test/hyperliquid.test.ts +107 -0
- package/src/test/odos.test.ts +43 -12
- package/src/test/pool.test.ts +37 -45
- package/src/test/torosLimitOrder.test.ts +130 -0
- package/src/test/wallet.ts +2 -1
- 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 {
|
|
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
|
-
|
|
26
|
-
|
|
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
|
-
|
|
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/
|
|
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
|
-
|
|
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");
|
package/src/test/constants.ts
CHANGED
|
@@ -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
|
|
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
|
+
});
|
package/src/test/odos.test.ts
CHANGED
|
@@ -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(
|
|
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
|
|
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
|
-
"
|
|
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
|
|
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
|
-
"
|
|
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.
|
|
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,
|
package/src/test/pool.test.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
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
|
|
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
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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].
|
|
55
|
-
// { asset: CONTRACT_ADDRESS[network].USDE, isDeposit: true },
|
|
49
|
+
// { asset: CONTRACT_ADDRESS[network].USDC, isDeposit: true },
|
|
56
50
|
// {
|
|
57
|
-
// asset: "
|
|
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].
|
|
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
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
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.
|
|
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
|
+
});
|
package/src/test/wallet.ts
CHANGED
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
|
+
};
|