@dhedge/v2-sdk 2.1.5 → 2.1.7

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 (34) hide show
  1. package/README.md +180 -45
  2. package/dist/config.d.ts +2 -0
  3. package/dist/entities/pool.d.ts +121 -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/toros/limitOrder.d.ts +8 -0
  9. package/dist/test/constants.d.ts +7 -1
  10. package/dist/test/wallet.d.ts +1 -0
  11. package/dist/types.d.ts +12 -2
  12. package/dist/v2-sdk.cjs.development.js +1523 -32
  13. package/dist/v2-sdk.cjs.development.js.map +1 -1
  14. package/dist/v2-sdk.cjs.production.min.js +1 -1
  15. package/dist/v2-sdk.cjs.production.min.js.map +1 -1
  16. package/dist/v2-sdk.esm.js +1502 -12
  17. package/dist/v2-sdk.esm.js.map +1 -1
  18. package/package.json +3 -2
  19. package/src/abi/hyperliquid/ICoreDepositWallet.json +130 -0
  20. package/src/abi/hyperliquid/ICoreWriter.json +1 -0
  21. package/src/abi/toros/IPoolLimitOrderManager.json +78 -0
  22. package/src/config.ts +31 -9
  23. package/src/entities/pool.ts +382 -4
  24. package/src/services/hyperliquid/constants.ts +23 -0
  25. package/src/services/hyperliquid/index.ts +178 -0
  26. package/src/services/hyperliquid/marketData.ts +157 -0
  27. package/src/services/hyperliquid/positionData.ts +33 -0
  28. package/src/services/toros/limitOrder.ts +86 -0
  29. package/src/test/constants.ts +11 -5
  30. package/src/test/hyperliquid.test.ts +107 -0
  31. package/src/test/pool.test.ts +37 -45
  32. package/src/test/torosLimitOrder.test.ts +130 -0
  33. package/src/test/wallet.ts +2 -1
  34. package/src/types.ts +13 -2
@@ -19,7 +19,8 @@ import {
19
19
  nonfungiblePositionManagerAddress,
20
20
  routerAddress,
21
21
  stakingAddress,
22
- SYNTHETIX_TRACKING_CODE
22
+ SYNTHETIX_TRACKING_CODE,
23
+ limitOrderAddress
23
24
  } from "../config";
24
25
  import {
25
26
  Dapp,
@@ -31,7 +32,8 @@ import {
31
32
  LyraOptionType,
32
33
  LyraTradeType,
33
34
  LyraPosition,
34
- SDKOptions
35
+ SDKOptions,
36
+ LimitOrderInfo
35
37
  } from "../types";
36
38
 
37
39
  import { Utils } from "./utils";
@@ -57,8 +59,8 @@ import { getLyraOptionTxData } from "../services/lyra/trade";
57
59
  import { getOptionPositions } from "../services/lyra/positions";
58
60
  import { getDeadline } from "../utils/deadline";
59
61
  import {
60
- getFuturesChangePositionTxData,
61
- getFuturesChangeMarginTxData
62
+ getFuturesChangeMarginTxData,
63
+ getFuturesChangePositionTxData
62
64
  } from "../services/futures";
63
65
  import { getFuturesCancelOrderTxData } from "../services/futures/trade";
64
66
  import { getOneInchSwapTxData } from "../services/oneInch";
@@ -86,7 +88,25 @@ import {
86
88
  import { getOdosSwapTxData } from "../services/odos";
87
89
  import { getPendleMintTxData, getPendleSwapTxData } from "../services/pendle";
88
90
  import { getCompleteWithdrawalTxData } from "../services/toros/completeWithdrawal";
91
+ import {
92
+ getCreateLimitOrderTxData,
93
+ getModifyLimitOrderTxData,
94
+ getDeleteLimitOrderTxData,
95
+ getTorosLimitOrder,
96
+ hasActiveTorosLimitOrder
97
+ } from "../services/toros/limitOrder";
89
98
  import { getKyberSwapTxData } from "../services/kyberSwap";
99
+ import {
100
+ getClosePositionHyperliquidTxData,
101
+ getDepositHyperliquidTxData,
102
+ getLimitOrderHyperliquidTxData,
103
+ getSendAssetHyperliquidTxData,
104
+ getWithdrawSpotHyperliquidTxData
105
+ } from "../services/hyperliquid";
106
+ import {
107
+ CORE_WRITER_ADDRESS,
108
+ SPOT_DEX_ID
109
+ } from "../services/hyperliquid/constants";
90
110
 
91
111
  export class Pool {
92
112
  public readonly poolLogic: Contract;
@@ -2147,4 +2167,362 @@ export class Pool {
2147
2167
  );
2148
2168
  return tx;
2149
2169
  }
2170
+
2171
+ /** Deposit USDC from EVM to a HyperCore trading dex via the CoreDepositWallet.
2172
+ * This bridges USDC on-chain to Hyperliquid for perp/spot trading.
2173
+ *
2174
+ * @param {BigNumber | string} amount USDC amount to deposit (6 decimals, e.g. "1000000" = 1 USDC)
2175
+ * @param {number} dexId Destination dex ID where USDC will be available (default 0)
2176
+ * - 0: Core Perp dex (standard perps like BTC, ETH)
2177
+ * - 1: xyz HIP-3 dex (builder perps like TSLA, GOLD)
2178
+ * @param {any} options Transaction options
2179
+ * @param {SDKOptions} sdkOptions SDK options including estimateGas
2180
+ * @returns {Promise<any>} Transaction
2181
+ */
2182
+ async depositHyperliquid(
2183
+ amount: BigNumber | string,
2184
+ dexId = 0,
2185
+ options: any = null,
2186
+ sdkOptions: SDKOptions = {
2187
+ estimateGas: false
2188
+ }
2189
+ ): Promise<any> {
2190
+ const tx = await getPoolTxOrGasEstimate(
2191
+ this,
2192
+ [
2193
+ routerAddress[this.network][Dapp.HYPERLIQUID],
2194
+ getDepositHyperliquidTxData(dexId, amount),
2195
+ options
2196
+ ],
2197
+ sdkOptions
2198
+ );
2199
+ return tx;
2200
+ }
2201
+
2202
+ /** Move USDC from a HyperCore trading dex to the Spot wallet.
2203
+ * Required before calling withdrawHyperliquid() to bridge USDC back to EVM.
2204
+ *
2205
+ * @param {number} dexId Source dex ID where USDC currently sits
2206
+ * - 0: Core Perp dex (standard perps like BTC, ETH)
2207
+ * - 1: xyz HIP-3 dex (builder perps like TSLA, GOLD)
2208
+ * @param {BigNumber | string} amount USDC amount to transfer (6 decimals, e.g. "1000000" = 1 USDC)
2209
+ * @param {any} options Transaction options
2210
+ * @param {SDKOptions} sdkOptions SDK options including estimateGas
2211
+ * @returns {Promise<any>} Transaction
2212
+ */
2213
+
2214
+ async perpToSpotHyperliquid(
2215
+ dexId: number,
2216
+ amount: BigNumber | string,
2217
+ options: any = null,
2218
+ sdkOptions: SDKOptions = {
2219
+ estimateGas: false
2220
+ }
2221
+ ): Promise<any> {
2222
+ const tx = await getPoolTxOrGasEstimate(
2223
+ this,
2224
+ [
2225
+ CORE_WRITER_ADDRESS,
2226
+ getSendAssetHyperliquidTxData(dexId, SPOT_DEX_ID, this.address, amount),
2227
+ options
2228
+ ],
2229
+ sdkOptions
2230
+ );
2231
+ return tx;
2232
+ }
2233
+
2234
+ /** Move USDC from HyperCore spot wallet to a trading dex.
2235
+ *
2236
+ * @param {number} dexId Destination dex ID where USDC will be moved to
2237
+ * - 0: Core Perp dex (standard perps like BTC, ETH)
2238
+ * - 1: xyz HIP-3 dex (builder perps like TSLA, GOLD)
2239
+ * @param {BigNumber | string} amount USDC amount to transfer (6 decimals, e.g. "1000000" = 1 USDC)
2240
+ * @param {any} options Transaction options
2241
+ * @param {SDKOptions} sdkOptions SDK options including estimateGas
2242
+ * @returns {Promise<any>} Transaction
2243
+ */
2244
+
2245
+ async spotToPerpHyperliquid(
2246
+ dexId: number,
2247
+ amount: BigNumber | string,
2248
+ options: any = null,
2249
+ sdkOptions: SDKOptions = {
2250
+ estimateGas: false
2251
+ }
2252
+ ): Promise<any> {
2253
+ const tx = await getPoolTxOrGasEstimate(
2254
+ this,
2255
+ [
2256
+ CORE_WRITER_ADDRESS,
2257
+ getSendAssetHyperliquidTxData(SPOT_DEX_ID, dexId, this.address, amount),
2258
+ options
2259
+ ],
2260
+ sdkOptions
2261
+ );
2262
+ return tx;
2263
+ }
2264
+
2265
+ /** Withdraw USDC from Hyperliquid Spot wallet back to EVM.
2266
+ * USDC must be in the Spot wallet first — use perpToSpotHyperliquid() to move it from a trading dex.
2267
+ *
2268
+ * @param {BigNumber | string} amount USDC amount to withdraw (6 decimals, e.g. "1000000" = 1 USDC)
2269
+ * @param {any} options Transaction options
2270
+ * @param {SDKOptions} sdkOptions SDK options including estimateGas
2271
+ * @returns {Promise<any>} Transaction
2272
+ */
2273
+
2274
+ async withdrawHyperliquid(
2275
+ amount: BigNumber | string,
2276
+ options: any = null,
2277
+ sdkOptions: SDKOptions = {
2278
+ estimateGas: false
2279
+ }
2280
+ ): Promise<any> {
2281
+ const tx = await getPoolTxOrGasEstimate(
2282
+ this,
2283
+ [CORE_WRITER_ADDRESS, getWithdrawSpotHyperliquidTxData(amount), options],
2284
+ sdkOptions
2285
+ );
2286
+ return tx;
2287
+ }
2288
+
2289
+ /** Open a market order on Hyperliquid
2290
+ * @param {number} assetId Asset id
2291
+ * @param {boolean} isLong Long or short (Note: Spot assets only support long positions)
2292
+ * @param {number} value Order value in base asset units (positive for opening/increasing,
2293
+ * negative for closing/reducing or selling spot)
2294
+ * @param {number } slippage Slippage tolerance in %
2295
+ * @param {any} options Transaction options
2296
+ * @param {SDKOptions} sdkOptions SDK options including estimateGas
2297
+ * @returns {Promise<any>} Transaction
2298
+ */
2299
+ async openMarketOrderHyperliquid(
2300
+ assetId: number,
2301
+ isLong: boolean,
2302
+ value: number,
2303
+ slippage = 0.5,
2304
+ options: any = null,
2305
+ sdkOptions: SDKOptions = {
2306
+ estimateGas: false
2307
+ }
2308
+ ): Promise<any> {
2309
+ const tx = await getPoolTxOrGasEstimate(
2310
+ this,
2311
+ [
2312
+ CORE_WRITER_ADDRESS,
2313
+ await getLimitOrderHyperliquidTxData(assetId, isLong, value, slippage),
2314
+ options
2315
+ ],
2316
+ sdkOptions
2317
+ );
2318
+ return tx;
2319
+ }
2320
+
2321
+ /** Close a position on Hyperliquid
2322
+ * @param {number} assetId Asset id
2323
+ * @param {number} percentageToClose Percentage of position to close (0-100)
2324
+ * @param {number } slippage Slippage tolerance in %
2325
+ * @param {any} options Transaction options
2326
+ * @param {SDKOptions} sdkOptions SDK options including estimateGas
2327
+ * @returns {Promise<any>} Transaction
2328
+ */
2329
+ async closePositionHyperliquid(
2330
+ assetId: number,
2331
+ percentageToClose = 100,
2332
+ slippage = 0.5,
2333
+ options: any = null,
2334
+ sdkOptions: SDKOptions = {
2335
+ estimateGas: false
2336
+ }
2337
+ ): Promise<any> {
2338
+ const tx = await getPoolTxOrGasEstimate(
2339
+ this,
2340
+ [
2341
+ CORE_WRITER_ADDRESS,
2342
+ await getClosePositionHyperliquidTxData(
2343
+ assetId,
2344
+ percentageToClose,
2345
+ slippage,
2346
+ this.address
2347
+ ),
2348
+ options
2349
+ ],
2350
+ sdkOptions
2351
+ );
2352
+ return tx;
2353
+ }
2354
+
2355
+ /**
2356
+ * Approve the Toros vault token for the PoolLimitOrderManager
2357
+ * Must be called before createTorosLimitOrder
2358
+ * @param {string} vaultAddress Address of the Toros vault token to approve
2359
+ * @param {BigNumber | string} amount Amount to approve
2360
+ * @param {any} options Transaction options
2361
+ * @param {SDKOptions} sdkOptions SDK options including estimateGas
2362
+ * @returns {Promise<any>} Transaction
2363
+ */
2364
+ async approveTorosLimitOrder(
2365
+ vaultAddress: string,
2366
+ amount: BigNumber | string,
2367
+ options: any = null,
2368
+ sdkOptions: SDKOptions = { estimateGas: false }
2369
+ ): Promise<any> {
2370
+ const managerAddress = limitOrderAddress[this.network];
2371
+ const iERC20 = new ethers.utils.Interface(IERC20.abi);
2372
+ const approveTxData = iERC20.encodeFunctionData("approve", [
2373
+ managerAddress,
2374
+ amount
2375
+ ]);
2376
+ return getPoolTxOrGasEstimate(
2377
+ this,
2378
+ [vaultAddress, approveTxData, options],
2379
+ sdkOptions
2380
+ );
2381
+ }
2382
+
2383
+ /**
2384
+ * Create a Toros limit order (stop-loss / take-profit)
2385
+ * @param {string} vaultAddress Address of the Toros vault token
2386
+ * @param {BigNumber | string} amount Vault token amount (18 decimals)
2387
+ * @param {BigNumber | string | null | undefined} stopLossPriceD18 Stop-loss price in D18 (0 or null/undefined = disabled)
2388
+ * @param {BigNumber | string | null | undefined} takeProfitPriceD18 Take-profit price in D18 (MaxUint256 or null/undefined = disabled)
2389
+ * @param {string} pricingAsset Address of the pricing asset (e.g. USDC)
2390
+ * @param {any} options Transaction options
2391
+ * @param {SDKOptions} sdkOptions SDK options including estimateGas
2392
+ * @returns {Promise<any>} Transaction
2393
+ */
2394
+ async createTorosLimitOrder(
2395
+ vaultAddress: string,
2396
+ amount: BigNumber | string,
2397
+ stopLossPriceD18: BigNumber | string | null | undefined,
2398
+ takeProfitPriceD18: BigNumber | string | null | undefined,
2399
+ pricingAsset: string,
2400
+ options: any = null,
2401
+ sdkOptions: SDKOptions = { estimateGas: false }
2402
+ ): Promise<any> {
2403
+ const managerAddress = limitOrderAddress[this.network];
2404
+ if (!managerAddress) {
2405
+ throw new Error(`Limit orders not supported on ${this.network}`);
2406
+ }
2407
+ const resolvedStopLoss =
2408
+ stopLossPriceD18 == null
2409
+ ? BigNumber.from(0)
2410
+ : BigNumber.from(stopLossPriceD18);
2411
+ const resolvedTakeProfit =
2412
+ takeProfitPriceD18 == null
2413
+ ? ethers.constants.MaxUint256
2414
+ : BigNumber.from(takeProfitPriceD18);
2415
+ const info: LimitOrderInfo = {
2416
+ amount: BigNumber.from(amount),
2417
+ stopLossPriceD18: resolvedStopLoss,
2418
+ takeProfitPriceD18: resolvedTakeProfit,
2419
+ user: this.address,
2420
+ pool: vaultAddress,
2421
+ pricingAsset
2422
+ };
2423
+ const txData = getCreateLimitOrderTxData(info);
2424
+ return getPoolTxOrGasEstimate(
2425
+ this,
2426
+ [managerAddress, txData, options],
2427
+ sdkOptions
2428
+ );
2429
+ }
2430
+
2431
+ /**
2432
+ * Modify an existing Toros limit order
2433
+ * @param {string} vaultAddress Address of the Toros vault token
2434
+ * @param {BigNumber | string} amount New vault token amount (18 decimals)
2435
+ * @param {BigNumber | string | null | undefined} stopLossPriceD18 New stop-loss price in D18 (0 or null/undefined = disabled)
2436
+ * @param {BigNumber | string | null | undefined} takeProfitPriceD18 New take-profit price in D18 (MaxUint256 or null/undefined = disabled)
2437
+ * @param {string} pricingAsset Address of the pricing asset
2438
+ * @param {any} options Transaction options
2439
+ * @param {SDKOptions} sdkOptions SDK options including estimateGas
2440
+ * @returns {Promise<any>} Transaction
2441
+ */
2442
+ async modifyTorosLimitOrder(
2443
+ vaultAddress: string,
2444
+ amount: BigNumber | string,
2445
+ stopLossPriceD18: BigNumber | string | null | undefined,
2446
+ takeProfitPriceD18: BigNumber | string | null | undefined,
2447
+ pricingAsset: string,
2448
+ options: any = null,
2449
+ sdkOptions: SDKOptions = { estimateGas: false }
2450
+ ): Promise<any> {
2451
+ const managerAddress = limitOrderAddress[this.network];
2452
+ if (!managerAddress) {
2453
+ throw new Error(`Limit orders not supported on ${this.network}`);
2454
+ }
2455
+ const resolvedStopLoss =
2456
+ stopLossPriceD18 == null
2457
+ ? BigNumber.from(0)
2458
+ : BigNumber.from(stopLossPriceD18);
2459
+ const resolvedTakeProfit =
2460
+ takeProfitPriceD18 == null
2461
+ ? ethers.constants.MaxUint256
2462
+ : BigNumber.from(takeProfitPriceD18);
2463
+ const info: LimitOrderInfo = {
2464
+ amount: BigNumber.from(amount),
2465
+ stopLossPriceD18: resolvedStopLoss,
2466
+ takeProfitPriceD18: resolvedTakeProfit,
2467
+ user: this.address,
2468
+ pool: vaultAddress,
2469
+ pricingAsset
2470
+ };
2471
+ const txData = getModifyLimitOrderTxData(info);
2472
+ return getPoolTxOrGasEstimate(
2473
+ this,
2474
+ [managerAddress, txData, options],
2475
+ sdkOptions
2476
+ );
2477
+ }
2478
+
2479
+ /**
2480
+ * Delete an existing Toros limit order
2481
+ * @param {string} vaultAddress Address of the Toros vault token
2482
+ * @param {any} options Transaction options
2483
+ * @param {SDKOptions} sdkOptions SDK options including estimateGas
2484
+ * @returns {Promise<any>} Transaction
2485
+ */
2486
+ async deleteTorosLimitOrder(
2487
+ vaultAddress: string,
2488
+ options: any = null,
2489
+ sdkOptions: SDKOptions = { estimateGas: false }
2490
+ ): Promise<any> {
2491
+ const managerAddress = limitOrderAddress[this.network];
2492
+ if (!managerAddress) {
2493
+ throw new Error(`Limit orders not supported on ${this.network}`);
2494
+ }
2495
+ const txData = getDeleteLimitOrderTxData(vaultAddress);
2496
+ return getPoolTxOrGasEstimate(
2497
+ this,
2498
+ [managerAddress, txData, options],
2499
+ sdkOptions
2500
+ );
2501
+ }
2502
+
2503
+ /**
2504
+ * Fetch a Toros limit order for a given user and vault
2505
+ * @param {string} userAddress Address of the order owner (the dHEDGE pool)
2506
+ * @param {string} vaultAddress Address of the Toros vault token
2507
+ * @returns {Promise<LimitOrderInfo | null>} Order info, or null if none exists
2508
+ */
2509
+ async getTorosLimitOrder(
2510
+ userAddress: string,
2511
+ vaultAddress: string
2512
+ ): Promise<LimitOrderInfo | null> {
2513
+ return getTorosLimitOrder(this, userAddress, vaultAddress);
2514
+ }
2515
+
2516
+ /**
2517
+ * Check whether an active Toros limit order exists for a given user and vault
2518
+ * @param {string} userAddress Address of the order owner (the dHEDGE pool)
2519
+ * @param {string} vaultAddress Address of the Toros vault token
2520
+ * @returns {Promise<boolean>}
2521
+ */
2522
+ async hasActiveTorosLimitOrder(
2523
+ userAddress: string,
2524
+ vaultAddress: string
2525
+ ): Promise<boolean> {
2526
+ return hasActiveTorosLimitOrder(this, userAddress, vaultAddress);
2527
+ }
2150
2528
  }
@@ -0,0 +1,23 @@
1
+ export const USDC_TOKEN_ID = 0;
2
+ export const USDC_CORE_ADDRESS = "0x2000000000000000000000000000000000000000";
3
+ export const CORE_WRITER_ADDRESS = "0x3333333333333333333333333333333333333333";
4
+ export const PERP_DEX_ID = 0;
5
+ export const SPOT_DEX_ID = 4294967295; // max uint32;
6
+ export const HYPERLIQUID_VERSION = 1;
7
+
8
+ //Action IDs
9
+ export const SPOT_SEND_ACTION = 6;
10
+ export const SEND_ASSET_ACTION = 13;
11
+ export const LIMIT_ORDER_ACTION = 1;
12
+
13
+ //Order Time In Force options
14
+ export const LIMIT_ORDER_TIF_ALO = 1;
15
+ export const LIMIT_ORDER_TIF_GTC = 2;
16
+ export const LIMIT_ORDER_TIF_IOC = 3;
17
+
18
+ export const dexIdNameMap: { [key: number]: string } = {
19
+ 0: "",
20
+ 1: "xyz"
21
+ };
22
+
23
+ export const API_URL = "https://api.hyperliquid.xyz/info";
@@ -0,0 +1,178 @@
1
+ import { ethers } from "ethers";
2
+ import ICoreDepositWalletAbi from "../../abi/hyperliquid/ICoreDepositWallet.json";
3
+ import ICoreWriterAbi from "../../abi/hyperliquid/ICoreWriter.json";
4
+ import {
5
+ HYPERLIQUID_VERSION,
6
+ LIMIT_ORDER_ACTION,
7
+ LIMIT_ORDER_TIF_IOC,
8
+ SEND_ASSET_ACTION,
9
+ SPOT_SEND_ACTION,
10
+ USDC_CORE_ADDRESS,
11
+ USDC_TOKEN_ID
12
+ } from "./constants";
13
+
14
+ import {
15
+ calculatePrice,
16
+ calculateSize,
17
+ getAssetInfo,
18
+ getMidPrice,
19
+ isSpotAsset,
20
+ scaleSize
21
+ } from "./marketData";
22
+ import { getPositionSize } from "./positionData";
23
+
24
+ const depositWallet = new ethers.utils.Interface(ICoreDepositWalletAbi);
25
+ const coreWriter = new ethers.utils.Interface(ICoreWriterAbi);
26
+
27
+ export const getDepositHyperliquidTxData = (
28
+ dexId: number,
29
+ amount: ethers.BigNumber | string
30
+ ): string => {
31
+ return depositWallet.encodeFunctionData("deposit", [amount, dexId]);
32
+ };
33
+
34
+ export const getWithdrawSpotHyperliquidTxData = (
35
+ amount: ethers.BigNumber | string
36
+ ): string => {
37
+ const coreAmount = ethers.BigNumber.from(amount).mul(100); //USDC on Core has two more decimals
38
+ //Hardcoded to USDC address and id on Hyperliquid Core
39
+ //From Spot to EVM
40
+ const innerEncoded = ethers.utils.defaultAbiCoder.encode(
41
+ //to, token, amount
42
+ ["address", "uint64", "uint64"],
43
+ [USDC_CORE_ADDRESS, USDC_TOKEN_ID, coreAmount]
44
+ );
45
+
46
+ const rawTXData = ethers.utils.solidityPack(
47
+ ["uint8", "uint24", "bytes"],
48
+ [HYPERLIQUID_VERSION, SPOT_SEND_ACTION, innerEncoded]
49
+ );
50
+ return coreWriter.encodeFunctionData("sendRawAction", [rawTXData]);
51
+ };
52
+ export const getSendAssetHyperliquidTxData = (
53
+ sourceDex: number,
54
+ destinationDex: number,
55
+ receiver: string,
56
+ amount: ethers.BigNumber | string
57
+ ): string => {
58
+ // Convert 6-decimal EVM USDC to 8-decimal HyperCore USDC (spot, main perp, and xyz)
59
+ // Transfer USDC between dexes (perp, spot, xyz)
60
+ const coreAmount = ethers.BigNumber.from(amount).mul(100);
61
+ //From Perp to Spot
62
+ const innerEncoded = ethers.utils.defaultAbiCoder.encode(
63
+ //destination, subAccount, sourceDex, destinationDex, token, amount
64
+ ["address", "address", "uint32", "uint32", "uint64", "uint64"],
65
+ [
66
+ receiver,
67
+ ethers.constants.AddressZero,
68
+ sourceDex,
69
+ destinationDex,
70
+ USDC_TOKEN_ID,
71
+ coreAmount
72
+ ]
73
+ );
74
+
75
+ const rawTXData = ethers.utils.solidityPack(
76
+ ["uint8", "uint24", "bytes"],
77
+ [HYPERLIQUID_VERSION, SEND_ASSET_ACTION, innerEncoded]
78
+ );
79
+
80
+ return coreWriter.encodeFunctionData("sendRawAction", [rawTXData]);
81
+ };
82
+
83
+ export const getLimitOrderHyperliquidTxData = async (
84
+ assetId: number,
85
+ isLong: boolean,
86
+ changeAmount: number,
87
+ slippage: number
88
+ ): Promise<string> => {
89
+ let isBuy = isLong;
90
+ let reduceOnly = false;
91
+ if (changeAmount < 0) {
92
+ changeAmount = changeAmount * -1;
93
+ isBuy = !isLong;
94
+ reduceOnly = !isSpotAsset(assetId);
95
+ }
96
+
97
+ //Calculate price with slippage
98
+ const { assetName, szDecimals } = await getAssetInfo(assetId);
99
+ const midPrice = await getMidPrice(assetId, assetName);
100
+ const price = calculatePrice(
101
+ isSpotAsset(assetId),
102
+ szDecimals,
103
+ midPrice,
104
+ isBuy,
105
+ slippage
106
+ );
107
+ const size = calculateSize(szDecimals, changeAmount, midPrice);
108
+
109
+ const innerEncoded = ethers.utils.defaultAbiCoder.encode(
110
+ //assetIndex, isBuy, price, size, reduceOnly, tif, clientOrderId
111
+ ["uint32", "bool", "uint64", "uint64", "bool", "uint8", "uint128"],
112
+ [
113
+ assetId,
114
+ isBuy,
115
+ price,
116
+ size,
117
+ reduceOnly,
118
+ LIMIT_ORDER_TIF_IOC, // immediate or cancel
119
+ ethers.BigNumber.from(0) //client order id
120
+ ]
121
+ );
122
+
123
+ const rawTXData = ethers.utils.solidityPack(
124
+ ["uint8", "uint24", "bytes"],
125
+ [HYPERLIQUID_VERSION, LIMIT_ORDER_ACTION, innerEncoded]
126
+ );
127
+
128
+ return coreWriter.encodeFunctionData("sendRawAction", [rawTXData]);
129
+ };
130
+
131
+ export const getClosePositionHyperliquidTxData = async (
132
+ assetId: number,
133
+ percentageToClose: number,
134
+ slippage: number,
135
+ poolAddress: string
136
+ ): Promise<string> => {
137
+ const isSpot = isSpotAsset(assetId);
138
+ const { assetName, szDecimals, baseTokenName } = await getAssetInfo(assetId);
139
+ const positionSize = await getPositionSize(
140
+ assetId,
141
+ isSpot,
142
+ baseTokenName ?? assetName,
143
+ poolAddress
144
+ );
145
+ const isBuy = positionSize < 0; // if position size is negative, we need to buy to close, otherwise sell
146
+ const sizeRaw = scaleSize(szDecimals, positionSize, percentageToClose);
147
+
148
+ //Calculate price with slippage
149
+ const midPrice = await getMidPrice(assetId, assetName);
150
+ const price = calculatePrice(
151
+ isSpotAsset(assetId),
152
+ szDecimals,
153
+ midPrice,
154
+ isBuy,
155
+ slippage
156
+ );
157
+
158
+ const innerEncoded = ethers.utils.defaultAbiCoder.encode(
159
+ //assetIndex, isBuy, price, size, reduceOnly, tif, clientOrderId
160
+ ["uint32", "bool", "uint64", "uint64", "bool", "uint8", "uint128"],
161
+ [
162
+ assetId,
163
+ positionSize < 0, // if position size is negative, we need to buy to close, otherwise sell
164
+ price,
165
+ sizeRaw,
166
+ !isSpot,
167
+ LIMIT_ORDER_TIF_IOC, // immediate or cancel
168
+ ethers.BigNumber.from(0) //client order id
169
+ ]
170
+ );
171
+
172
+ const rawTXData = ethers.utils.solidityPack(
173
+ ["uint8", "uint24", "bytes"],
174
+ [HYPERLIQUID_VERSION, LIMIT_ORDER_ACTION, innerEncoded]
175
+ );
176
+
177
+ return coreWriter.encodeFunctionData("sendRawAction", [rawTXData]);
178
+ };