@rabby-wallet/hyperliquid-sdk 1.0.8-beta1 → 1.0.8-beta4

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.
@@ -21,7 +21,7 @@ export declare class ExchangeClient {
21
21
  updateExchangeAgent(agentPrivateKey: string, agentPublicKey: string, agentName?: string): void;
22
22
  private getAgentPrivateKey;
23
23
  /**
24
- * deprecated 50 = 0.05%
24
+ * @deprecated This method is deprecated. Use the new builder configuration in constructor instead.
25
25
  */
26
26
  updateBuilder(address: string, fee: number): Promise<any>;
27
27
  updateLeverage(params: UpdateLeverageParams): Promise<any>;
@@ -29,7 +29,25 @@ export declare class ExchangeClient {
29
29
  * Place a single order
30
30
  */
31
31
  placeOrder(params: PlaceOrderParams): Promise<OrderResponse>;
32
+ /**
33
+ * Calculate slippage price for market orders following Hyperliquid price rules
34
+ * Based on official Python SDK logic
35
+ *
36
+ * Rules:
37
+ * - Round to 5 significant figures
38
+ * - Round to (6 - szDecimals) decimal places for perps
39
+ *
40
+ * @param midPx - Middle price as string
41
+ * @param slippage - Slippage rate (e.g., 0.08 for 8%)
42
+ * @param isBuy - True for buy orders, false for sell orders
43
+ * @param szDecimals - Size decimals from meta endpoint (default 0)
44
+ * @param isSpot - Whether this is a spot asset (default false for perps)
45
+ */
32
46
  private getSlippagePx;
47
+ /**
48
+ * Round a number to specified decimal places
49
+ */
50
+ private roundToDecimals;
33
51
  /**
34
52
  * Place a market order
35
53
  * default slippage is 0.08
@@ -104,7 +104,7 @@ class ExchangeClient {
104
104
  return this.agentPrivateKey;
105
105
  }
106
106
  /**
107
- * deprecated 50 = 0.05%
107
+ * @deprecated This method is deprecated. Use the new builder configuration in constructor instead.
108
108
  */
109
109
  updateBuilder(address, fee) {
110
110
  return __awaiter(this, void 0, void 0, function* () {
@@ -167,12 +167,40 @@ class ExchangeClient {
167
167
  });
168
168
  });
169
169
  }
170
- getSlippagePx(midPx, slippage, isBuy) {
171
- var _a;
172
- const decimals = ((_a = midPx.toString().split('.')[1]) === null || _a === void 0 ? void 0 : _a.length) || 0;
173
- const prepDecimals = Math.max(0, decimals - 1);
174
- const px = isBuy ? (Number(midPx) * (1 + slippage)).toFixed(prepDecimals) : (Number(midPx) * (1 - slippage)).toFixed(prepDecimals);
175
- return (0, number_1.removeTrailingZeros)(px);
170
+ /**
171
+ * Calculate slippage price for market orders following Hyperliquid price rules
172
+ * Based on official Python SDK logic
173
+ *
174
+ * Rules:
175
+ * - Round to 5 significant figures
176
+ * - Round to (6 - szDecimals) decimal places for perps
177
+ *
178
+ * @param midPx - Middle price as string
179
+ * @param slippage - Slippage rate (e.g., 0.08 for 8%)
180
+ * @param isBuy - True for buy orders, false for sell orders
181
+ * @param szDecimals - Size decimals from meta endpoint (default 0)
182
+ * @param isSpot - Whether this is a spot asset (default false for perps)
183
+ */
184
+ getSlippagePx(midPx, slippage, isBuy, szDecimals = 0) {
185
+ let px = parseFloat(midPx);
186
+ if (isNaN(px) || px <= 0) {
187
+ throw new Error('Invalid midPx: must be a positive number');
188
+ }
189
+ // Calculate slippage price
190
+ px *= isBuy ? (1 + slippage) : (1 - slippage);
191
+ // Round to 5 significant figures
192
+ const sigFigRounded = parseFloat(px.toPrecision(5));
193
+ // Round to (6 - szDecimals) decimals for perps
194
+ const maxDecimals = 6 - szDecimals;
195
+ const decimalRounded = this.roundToDecimals(sigFigRounded, maxDecimals);
196
+ return (0, number_1.removeTrailingZeros)(decimalRounded.toFixed(maxDecimals));
197
+ }
198
+ /**
199
+ * Round a number to specified decimal places
200
+ */
201
+ roundToDecimals(value, decimals) {
202
+ const multiplier = Math.pow(10, decimals);
203
+ return Math.round(value * multiplier) / multiplier;
176
204
  }
177
205
  /**
178
206
  * Place a market order
@@ -183,7 +211,8 @@ class ExchangeClient {
183
211
  return __awaiter(this, void 0, void 0, function* () {
184
212
  try {
185
213
  const slippage = params.slippage || constants_1.SLIPPAGE;
186
- const px = this.getSlippagePx((0, number_1.removeTrailingZeros)(params.midPx), slippage, params.isBuy);
214
+ const szDecimals = yield this.symbolConversion.getAssetSzDecimals(params.coin);
215
+ const px = this.getSlippagePx((0, number_1.removeTrailingZeros)(params.midPx), slippage, params.isBuy, szDecimals);
187
216
  const orders = [{
188
217
  coin: params.coin,
189
218
  isBuy: params.isBuy,
@@ -241,7 +270,8 @@ class ExchangeClient {
241
270
  return __awaiter(this, void 0, void 0, function* () {
242
271
  try {
243
272
  const slippage = params.slippage || constants_1.SLIPPAGE;
244
- const px = this.getSlippagePx(params.midPx, slippage, params.isBuy);
273
+ const szDecimals = yield this.symbolConversion.getAssetSzDecimals(params.coin);
274
+ const px = this.getSlippagePx(params.midPx, slippage, params.isBuy, szDecimals);
245
275
  const orders = [{
246
276
  coin: params.coin,
247
277
  isBuy: params.isBuy,
@@ -266,6 +296,7 @@ class ExchangeClient {
266
296
  */
267
297
  multiOrder(params) {
268
298
  return __awaiter(this, void 0, void 0, function* () {
299
+ var _a, _b, _c;
269
300
  const nonce = Date.now();
270
301
  const assetIndexCache = new Map();
271
302
  const orderWires = yield Promise.all(params.orders.map((order) => __awaiter(this, void 0, void 0, function* () {
@@ -295,22 +326,29 @@ class ExchangeClient {
295
326
  };
296
327
  }
297
328
  const signature = (0, signer_1.signL1AgentAction)(this.getAgentPrivateKey(), action, this.isTestnet, nonce);
298
- return this.httpClient.exchange({
329
+ const res = yield this.httpClient.exchange({
299
330
  action,
300
331
  nonce,
301
332
  signature,
302
333
  });
334
+ (_c = (_b = (_a = res === null || res === void 0 ? void 0 : res.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.statuses) === null || _c === void 0 ? void 0 : _c.forEach((status, index) => {
335
+ if (status.error) {
336
+ throw new Error(status.error);
337
+ }
338
+ });
339
+ return res;
303
340
  });
304
341
  }
305
342
  bindTpslByOrderId(params) {
306
343
  return __awaiter(this, void 0, void 0, function* () {
307
344
  let orders = [];
345
+ const szDecimals = yield this.symbolConversion.getAssetSzDecimals(params.coin);
308
346
  if (params.tpTriggerPx) {
309
347
  orders.push({
310
348
  coin: params.coin,
311
349
  isBuy: !params.isBuy,
312
350
  sz: '0',
313
- limitPx: this.getSlippagePx((0, number_1.removeTrailingZeros)(params.tpTriggerPx), constants_1.SLIPPAGE, !params.isBuy),
351
+ limitPx: this.getSlippagePx((0, number_1.removeTrailingZeros)(params.tpTriggerPx), constants_1.SLIPPAGE, !params.isBuy, szDecimals),
314
352
  reduceOnly: true,
315
353
  orderType: {
316
354
  trigger: {
@@ -326,7 +364,7 @@ class ExchangeClient {
326
364
  coin: params.coin,
327
365
  isBuy: !params.isBuy,
328
366
  sz: '0',
329
- limitPx: this.getSlippagePx((0, number_1.removeTrailingZeros)(params.slTriggerPx), constants_1.SLIPPAGE, !params.isBuy),
367
+ limitPx: this.getSlippagePx((0, number_1.removeTrailingZeros)(params.slTriggerPx), constants_1.SLIPPAGE, !params.isBuy, szDecimals),
330
368
  reduceOnly: true,
331
369
  orderType: {
332
370
  trigger: {
@@ -2,6 +2,7 @@ import { HttpClientConfig } from "./http-client";
2
2
  import { InfoClient } from "./info-client";
3
3
  export declare class SymbolConversion {
4
4
  private assetToIndexMap;
5
+ private assetSzDecimalsMap;
5
6
  private httpClient;
6
7
  private initialized;
7
8
  private infoClient?;
@@ -10,6 +11,7 @@ export declare class SymbolConversion {
10
11
  private ensureInitialized;
11
12
  private refreshAssetMaps;
12
13
  getAssetIndex(assetSymbol: string): Promise<number>;
14
+ getAssetSzDecimals(assetSymbol: string): Promise<number>;
13
15
  getAllAssets(): Promise<{
14
16
  perp: string[];
15
17
  }>;
@@ -15,6 +15,7 @@ const http_client_1 = require("./http-client");
15
15
  class SymbolConversion {
16
16
  constructor(config, infoClient) {
17
17
  this.assetToIndexMap = new Map();
18
+ this.assetSzDecimalsMap = new Map();
18
19
  this.initialized = false;
19
20
  this.infoClient = infoClient;
20
21
  this.httpClient = new http_client_1.HttpClient({
@@ -64,9 +65,11 @@ class SymbolConversion {
64
65
  throw new Error('Invalid perpetual metadata response');
65
66
  }
66
67
  this.assetToIndexMap.clear();
68
+ this.assetSzDecimalsMap.clear();
67
69
  // Handle perpetual assets
68
70
  perpMeta[0].universe.forEach((asset, index) => {
69
71
  this.assetToIndexMap.set(asset.name, index);
72
+ this.assetSzDecimalsMap.set(asset.name, asset.szDecimals);
70
73
  });
71
74
  }
72
75
  catch (error) {
@@ -84,6 +87,16 @@ class SymbolConversion {
84
87
  return index;
85
88
  });
86
89
  }
90
+ getAssetSzDecimals(assetSymbol) {
91
+ return __awaiter(this, void 0, void 0, function* () {
92
+ yield this.ensureInitialized();
93
+ const szDecimals = this.assetSzDecimalsMap.get(assetSymbol);
94
+ if (szDecimals === undefined) {
95
+ throw new Error(`Unknown asset index: ${assetSymbol}`);
96
+ }
97
+ return szDecimals;
98
+ });
99
+ }
87
100
  getAllAssets() {
88
101
  return __awaiter(this, void 0, void 0, function* () {
89
102
  yield this.ensureInitialized();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rabby-wallet/hyperliquid-sdk",
3
- "version": "1.0.8-beta1",
3
+ "version": "1.0.8-beta4",
4
4
  "description": "Simplified Hyperliquid Perpetuals Trading SDK for Frontend Applications",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",