aftermath-ts-sdk 1.3.23-perps.26 → 1.3.23-perps.27

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.
@@ -13,15 +13,78 @@ exports.PerpetualsMarket = void 0;
13
13
  const __1 = require("../..");
14
14
  const caller_1 = require("../../general/utils/caller");
15
15
  const perpetuals_1 = require("./perpetuals");
16
+ /**
17
+ * High-level wrapper around a single perpetuals market.
18
+ *
19
+ * This class provides:
20
+ *
21
+ * - Lightweight accessors for immutable market properties:
22
+ * - `marketId`, `indexPrice`, `collateralPrice`, `collateralCoinType`
23
+ * - `marketParams`, `marketState`
24
+ * - Read endpoints for:
25
+ * - Orderbook snapshots
26
+ * - 24h stats and trade history
27
+ * - Market prices and derived funding metrics
28
+ * - Helpers for:
29
+ * - Order sizing (max size, lot/tick rounding)
30
+ * - Margin and collateral calculations
31
+ * - Constructing an “empty” position for a market
32
+ *
33
+ * Typical usage:
34
+ *
35
+ * ```ts
36
+ * const perps = new Perpetuals(config);
37
+ * const markets = await perps.getMarkets({ marketIds: ["0x..."] });
38
+ * const btcPerp = new PerpetualsMarket(markets[0], config);
39
+ *
40
+ * const ob = await btcPerp.getOrderbook();
41
+ * const stats = await btcPerp.get24hrStats();
42
+ * const prices = await btcPerp.getPrices();
43
+ * ```
44
+ */
16
45
  class PerpetualsMarket extends caller_1.Caller {
17
46
  // =========================================================================
18
47
  // Constructor
19
48
  // =========================================================================
49
+ /**
50
+ * Create a new {@link PerpetualsMarket} wrapper from raw market data.
51
+ *
52
+ * @param marketData - Snapshot of market configuration and state.
53
+ * @param config - Optional {@link CallerConfig} (network, base URL, etc.).
54
+ */
20
55
  constructor(marketData, config
21
56
  // public readonly Provider?: AftermathApi
22
57
  ) {
23
58
  super(config, "perpetuals");
24
59
  this.marketData = marketData;
60
+ /**
61
+ * Compute the maximum order size that can be placed by a given account
62
+ * in this market, under optional leverage and price assumptions.
63
+ *
64
+ * This is useful for frontends to:
65
+ * - Drive "max" buttons.
66
+ * - Validate order inputs against risk limits.
67
+ *
68
+ * **Note:** This lives on the `account` namespace since it depends on
69
+ * account state.
70
+ *
71
+ * @param inputs.accountId - Perpetuals account ID.
72
+ * @param inputs.side - Order side (Bid/Ask).
73
+ * @param inputs.leverage - Optional leverage to assume (defaults to account-level).
74
+ * @param inputs.price - Optional limit price; if omitted, a default or index-based
75
+ * assumption may be used by the backend.
76
+ *
77
+ * @returns An object containing `maxOrderSize` (as `bigint` in base units).
78
+ *
79
+ * @example
80
+ * ```ts
81
+ * const { maxOrderSize } = await market.getMaxOrderSize({
82
+ * accountId,
83
+ * side: PerpetualsOrderSide.Bid,
84
+ * leverage: 5,
85
+ * });
86
+ * ```
87
+ */
25
88
  // TODO: move/add to account ?
26
89
  this.getMaxOrderSize = (inputs) => __awaiter(this, void 0, void 0, function* () {
27
90
  const { side, price, accountId, leverage } = inputs;
@@ -35,22 +98,75 @@ class PerpetualsMarket extends caller_1.Caller {
35
98
  });
36
99
  // =========================================================================
37
100
  // Calculations
38
- // =========================================================================
101
+ // =========================================================================`
102
+ /**
103
+ * Compute the remaining time until the next funding event, in milliseconds.
104
+ *
105
+ * - If the on-chain `nextFundingTimestampMs` exceeds `Number.MAX_SAFE_INTEGER`,
106
+ * this uses `Number.MAX_SAFE_INTEGER` as a cap via {@link nextFundingTimeMs}.
107
+ *
108
+ * @returns `nextFundingTimeMs() - Date.now()`.
109
+ */
39
110
  this.timeUntilNextFundingMs = () => {
40
111
  return this.nextFundingTimeMs() - Date.now();
41
112
  };
113
+ /**
114
+ * Get the scheduled timestamp for the next funding event, in milliseconds.
115
+ *
116
+ * - If `nextFundingTimestampMs` doesn't fit in JS `number` safely
117
+ * (i.e. `> Number.MAX_SAFE_INTEGER`), this method returns
118
+ * `Number.MAX_SAFE_INTEGER` as a safeguard.
119
+ *
120
+ * @returns Next funding timestamp (ms) as a JS `number`.
121
+ */
42
122
  this.nextFundingTimeMs = () => {
43
123
  return this.marketData.nextFundingTimestampMs >
44
124
  BigInt(Number.MAX_SAFE_INTEGER)
45
125
  ? Number.MAX_SAFE_INTEGER
46
126
  : Number(this.marketData.nextFundingTimestampMs);
47
127
  };
128
+ /**
129
+ * Estimated funding rate per period for this market.
130
+ *
131
+ * Conceptually defined as:
132
+ *
133
+ * ```text
134
+ * (bookTwap - indexTwap) / indexPrice * (fundingFrequency / fundingPeriod)
135
+ * ```
136
+ *
137
+ * but here it's read directly from `marketData.estimatedFundingRate`.
138
+ *
139
+ * @returns Estimated funding rate as a fraction (e.g. 0.01 = 1%).
140
+ */
48
141
  // The funding rate as the difference between book and index TWAPs relative to the index price,
49
142
  // scaled by the funding period adjustment:
50
143
  // (bookTwap - indexTwap) / indexPrice * (fundingFrequency / fundingPeriod)
51
144
  this.estimatedFundingRate = () => {
52
145
  return this.marketData.estimatedFundingRate;
53
146
  };
147
+ /**
148
+ * Calculate the collateral required to support an order given leverage
149
+ * and prices.
150
+ *
151
+ * The formula is (in USD):
152
+ *
153
+ * ```text
154
+ * remainingSizeBase * indexPrice * initialMarginRatio
155
+ * ```
156
+ *
157
+ * where:
158
+ * - `remainingSizeBase` = `(initialSize - filledSize) / fixedOneN9`
159
+ * - `initialMarginRatio` = `1 / leverage` (or 1 if leverage is falsy).
160
+ *
161
+ * @param inputs.leverage - Target leverage for the order.
162
+ * @param inputs.orderData - Order data containing `initialSize` and `filledSize`.
163
+ * @param inputs.indexPrice - Current index price of the underlying.
164
+ * @param inputs.collateralPrice - Price of the collateral asset in USD.
165
+ *
166
+ * @returns Object with:
167
+ * - `collateralUsd`: required collateral in USD.
168
+ * - `collateral`: required collateral in collateral coins.
169
+ */
54
170
  this.calcCollateralUsedForOrder = (inputs) => {
55
171
  const { leverage, orderData, indexPrice, collateralPrice } = inputs;
56
172
  const imr = 1 / (leverage || 1);
@@ -70,6 +186,22 @@ class PerpetualsMarket extends caller_1.Caller {
70
186
  // =========================================================================
71
187
  // Helpers
72
188
  // =========================================================================
189
+ /**
190
+ * Round a price to the nearest valid tick for this market.
191
+ *
192
+ * @param inputs.price - Raw price to round.
193
+ * @param inputs.floor - If `true`, always round down to the previous tick.
194
+ * @param inputs.ceil - If `true`, always round up to the next tick.
195
+ *
196
+ * If neither `floor` nor `ceil` are set, this uses `Math.round`.
197
+ *
198
+ * @returns Price snapped to a valid tick.
199
+ *
200
+ * @example
201
+ * ```ts
202
+ * const validPrice = market.roundToValidPrice({ price: 27123.45 });
203
+ * ```
204
+ */
73
205
  this.roundToValidPrice = (inputs) => {
74
206
  const ticks = inputs.price / this.tickSize();
75
207
  return ((inputs.floor
@@ -78,6 +210,18 @@ class PerpetualsMarket extends caller_1.Caller {
78
210
  ? Math.ceil(ticks)
79
211
  : Math.round(ticks)) * this.tickSize());
80
212
  };
213
+ /**
214
+ * Round a price to the nearest valid tick for this market, expressed as
215
+ * a `bigint` scaled by `Fixed.fixedOneN9`.
216
+ *
217
+ * This is useful when you need the on-chain representation directly.
218
+ *
219
+ * @param inputs.price - Raw price as a JS number.
220
+ * @param inputs.floor - If `true`, always round down.
221
+ * @param inputs.ceil - If `true`, always round up.
222
+ *
223
+ * @returns Price scaled by `1e9` and snapped to a valid tick as a `bigint`.
224
+ */
81
225
  this.roundToValidPriceBigInt = (inputs) => {
82
226
  const scaledPrice = Number(inputs.price * __1.Casting.Fixed.fixedOneN9);
83
227
  // TODO: make sure this calc is safe
@@ -89,6 +233,15 @@ class PerpetualsMarket extends caller_1.Caller {
89
233
  this.marketParams.tickSize) *
90
234
  this.marketParams.tickSize);
91
235
  };
236
+ /**
237
+ * Round a base-asset size to the nearest valid lot size for this market.
238
+ *
239
+ * @param inputs.size - Raw size in base asset units.
240
+ * @param inputs.floor - If `true`, always round down.
241
+ * @param inputs.ceil - If `true`, always round up.
242
+ *
243
+ * @returns Size snapped to a valid lot boundary.
244
+ */
92
245
  this.roundToValidSize = (inputs) => {
93
246
  const lots = inputs.size / this.lotSize();
94
247
  return ((inputs.floor
@@ -97,6 +250,16 @@ class PerpetualsMarket extends caller_1.Caller {
97
250
  ? Math.ceil(lots)
98
251
  : Math.round(lots)) * this.lotSize());
99
252
  };
253
+ /**
254
+ * Round a base-asset size to the nearest valid lot size for this market,
255
+ * as a scaled `bigint` (`Fixed.fixedOneN9`).
256
+ *
257
+ * @param inputs.size - Raw size in base units.
258
+ * @param inputs.floor - If `true`, always round down.
259
+ * @param inputs.ceil - If `true`, always round up.
260
+ *
261
+ * @returns Size scaled by `1e9` and snapped to valid lot as a `bigint`.
262
+ */
100
263
  this.roundToValidSizeBigInt = (inputs) => {
101
264
  const scaledSize = Number(inputs.size * __1.Casting.Fixed.fixedOneN9);
102
265
  // TODO: make sure this calc is safe
@@ -108,6 +271,15 @@ class PerpetualsMarket extends caller_1.Caller {
108
271
  this.marketParams.lotSize) *
109
272
  this.marketParams.lotSize);
110
273
  };
274
+ /**
275
+ * Construct an "empty" position object for this market.
276
+ *
277
+ * This is useful for UI and calculations when an account has no open
278
+ * position but you still want a full {@link PerpetualsPosition}-shaped
279
+ * object with defaulted values.
280
+ *
281
+ * @returns A zeroed-out {@link PerpetualsPosition} for `this.marketId`.
282
+ */
111
283
  this.emptyPosition = () => {
112
284
  return {
113
285
  marketId: this.marketId,
@@ -143,12 +315,41 @@ class PerpetualsMarket extends caller_1.Caller {
143
315
  // =========================================================================
144
316
  // Inspections
145
317
  // =========================================================================
318
+ /**
319
+ * Fetch the mid price for this market’s orderbook.
320
+ *
321
+ * This is a convenience endpoint that returns only:
322
+ *
323
+ * - `midPrice`: The midpoint between best bid and best ask, or `undefined`
324
+ * if the orderbook is empty or malformed.
325
+ *
326
+ * @returns A promise resolving to `{ midPrice }`.
327
+ *
328
+ * @example
329
+ * ```ts
330
+ * const { midPrice } = await market.getOrderbookMidPrice();
331
+ * ```
332
+ */
146
333
  // NOTE: should this be entirely removed since data already in orderbook function ?
147
334
  getOrderbookMidPrice() {
148
335
  return this.fetchApi("market/orderbook-price", {
149
336
  marketId: this.marketId,
150
337
  });
151
338
  }
339
+ /**
340
+ * Fetch the 24-hour statistics for this specific market.
341
+ *
342
+ * Under the hood, this calls {@link Perpetuals.getMarkets24hrStats} and
343
+ * returns the first (and only) entry for this market.
344
+ *
345
+ * @returns {@link PerpetualsMarket24hrStats} with volume, high/low, and other metrics.
346
+ *
347
+ * @example
348
+ * ```ts
349
+ * const stats = await market.get24hrStats();
350
+ * console.log(stats.volumeUsd, stats.priceChangePct);
351
+ * ```
352
+ */
152
353
  get24hrStats() {
153
354
  return __awaiter(this, void 0, void 0, function* () {
154
355
  const stats = yield new perpetuals_1.Perpetuals(this.config).getMarkets24hrStats({
@@ -157,6 +358,21 @@ class PerpetualsMarket extends caller_1.Caller {
157
358
  return stats[0];
158
359
  });
159
360
  }
361
+ /**
362
+ * Fetch the full orderbook snapshot for this market.
363
+ *
364
+ * Currently implemented via the generic `markets` endpoint with:
365
+ * - `marketIds: [this.marketId]`
366
+ * - `withOrderbook: true`
367
+ *
368
+ * @returns {@link PerpetualsOrderbook} for this market.
369
+ *
370
+ * @example
371
+ * ```ts
372
+ * const ob = await market.getOrderbook();
373
+ * console.log(ob.bids[0], ob.asks[0]);
374
+ * ```
375
+ */
160
376
  getOrderbook() {
161
377
  return __awaiter(this, void 0, void 0, function* () {
162
378
  // TODO: create own endpoint for just orderbook
@@ -168,11 +384,47 @@ class PerpetualsMarket extends caller_1.Caller {
168
384
  return marketDatas[0].orderbook;
169
385
  });
170
386
  }
387
+ /**
388
+ * Market-level preview of placing a market order.
389
+ *
390
+ * Unlike the account-specific preview on {@link PerpetualsAccount},
391
+ * this version:
392
+ * - Calls `account/previews/place-market-order`.
393
+ * - Explicitly sets `accountId: undefined`, allowing the backend to use
394
+ * generic or hypothetical assumptions about account state.
395
+ *
396
+ * @param inputs - See {@link SdkPerpetualsPlaceMarketOrderPreviewInputs}.
397
+ * @param abortSignal - Optional `AbortSignal` to cancel the HTTP request.
398
+ *
399
+ * @returns Either:
400
+ * - `{ error }`, or
401
+ * - A preview with:
402
+ * - `updatedPosition`
403
+ * - `priceSlippage` / `percentSlippage`
404
+ * - `filledSize` / `filledSizeUsd`
405
+ * - `postedSize` / `postedSizeUsd`
406
+ * - `collateralChange`
407
+ * - `executionPrice`
408
+ */
171
409
  getPlaceMarketOrderPreview(inputs, abortSignal) {
172
410
  return __awaiter(this, void 0, void 0, function* () {
173
411
  return this.fetchApi("account/previews/place-market-order", Object.assign(Object.assign({}, inputs), { accountId: undefined }), abortSignal);
174
412
  });
175
413
  }
414
+ /**
415
+ * Market-level preview of placing a limit order.
416
+ *
417
+ * Similar to {@link getPlaceMarketOrderPreview}, this uses:
418
+ * - `account/previews/place-limit-order`
419
+ * - `accountId: undefined`
420
+ *
421
+ * @param inputs - See {@link SdkPerpetualsPlaceLimitOrderPreviewInputs}.
422
+ * @param abortSignal - Optional `AbortSignal` to cancel the request.
423
+ *
424
+ * @returns Either:
425
+ * - `{ error }`, or
426
+ * - A preview object with post-order position, slippage, and collateral changes.
427
+ */
176
428
  getPlaceLimitOrderPreview(inputs, abortSignal) {
177
429
  return __awaiter(this, void 0, void 0, function* () {
178
430
  return this.fetchApi("account/previews/place-limit-order", Object.assign(Object.assign({}, inputs), { accountId: undefined }), abortSignal);
@@ -181,6 +433,24 @@ class PerpetualsMarket extends caller_1.Caller {
181
433
  // =========================================================================
182
434
  // Trade History
183
435
  // =========================================================================
436
+ /**
437
+ * Fetch paginated trade history for this market.
438
+ *
439
+ * This returns *market-level* trade history (not account-specific), useful
440
+ * for charting, recent trades lists, etc.
441
+ *
442
+ * @param inputs.cursor - Optional pagination cursor.
443
+ * @param inputs.limit - Optional number of trades per page.
444
+ *
445
+ * @returns {@link PerpetualsTradeHistoryWithCursor} including a list of
446
+ * trades and a `nextCursor`.
447
+ *
448
+ * @example
449
+ * ```ts
450
+ * const result = await market.getTradeHistory({ limit: 100 });
451
+ * console.log(result.trades.length, result.nextCursor);
452
+ * ```
453
+ */
184
454
  getTradeHistory(inputs) {
185
455
  return __awaiter(this, void 0, void 0, function* () {
186
456
  return this.fetchApi("market/trade-history", Object.assign(Object.assign({}, inputs), { marketId: this.marketId }));
@@ -189,6 +459,19 @@ class PerpetualsMarket extends caller_1.Caller {
189
459
  // =========================================================================
190
460
  // Prices
191
461
  // =========================================================================
462
+ /**
463
+ * Fetch the current base and collateral prices for this market.
464
+ *
465
+ * Internally calls {@link Perpetuals.getPrices} and returns the first
466
+ * element corresponding to `this.marketId`.
467
+ *
468
+ * @returns `{ basePrice, collateralPrice }` for this market.
469
+ *
470
+ * @example
471
+ * ```ts
472
+ * const { basePrice, collateralPrice } = await market.getPrices();
473
+ * ```
474
+ */
192
475
  getPrices() {
193
476
  return __awaiter(this, void 0, void 0, function* () {
194
477
  return (yield new perpetuals_1.Perpetuals(this.config
@@ -201,18 +484,55 @@ class PerpetualsMarket extends caller_1.Caller {
201
484
  // =========================================================================
202
485
  // Value Conversions
203
486
  // =========================================================================
487
+ /**
488
+ * Get the base asset lot size for this market as a `number`.
489
+ *
490
+ * Order sizes must be a multiple of this lot size.
491
+ *
492
+ * @returns Lot size in base asset units.
493
+ */
204
494
  lotSize() {
205
495
  return perpetuals_1.Perpetuals.lotOrTickSizeToNumber(this.marketParams.lotSize);
206
496
  }
497
+ /**
498
+ * Get the minimal price tick for this market as a `number`.
499
+ *
500
+ * Limit prices must be a multiple of this tick size.
501
+ *
502
+ * @returns Tick size in quote units (e.g. USD).
503
+ */
207
504
  tickSize() {
208
505
  return perpetuals_1.Perpetuals.lotOrTickSizeToNumber(this.marketParams.tickSize);
209
506
  }
507
+ /**
508
+ * Get the maximum theoretical leverage for this market, computed as:
509
+ *
510
+ * ```ts
511
+ * 1 / marginRatioInitial
512
+ * ```
513
+ *
514
+ * @returns Maximum leverage value for opening positions.
515
+ */
210
516
  maxLeverage() {
211
517
  return 1 / this.marketParams.marginRatioInitial;
212
518
  }
519
+ /**
520
+ * Get the initial margin ratio for this market.
521
+ *
522
+ * This is the minimum margin required when opening a position.
523
+ *
524
+ * @returns Initial margin ratio as a fraction (e.g. 0.05 = 20x).
525
+ */
213
526
  initialMarginRatio() {
214
527
  return this.marketParams.marginRatioInitial;
215
528
  }
529
+ /**
530
+ * Get the maintenance margin ratio for this market.
531
+ *
532
+ * Falling below this ratio may result in liquidation.
533
+ *
534
+ * @returns Maintenance margin ratio as a fraction.
535
+ */
216
536
  maintenanceMarginRatio() {
217
537
  return this.marketParams.marginRatioMaintenance;
218
538
  }