@lifi/perps-sdk-provider-lighter 16.0.0 → 17.0.1

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 (50) hide show
  1. package/dist/cjs/LighterProvider.d.ts.map +1 -1
  2. package/dist/cjs/LighterProvider.js +6 -31
  3. package/dist/cjs/LighterProvider.js.map +1 -1
  4. package/dist/cjs/accountConfig.d.ts.map +1 -1
  5. package/dist/cjs/accountConfig.js +1 -0
  6. package/dist/cjs/accountConfig.js.map +1 -1
  7. package/dist/cjs/types/account.d.ts.map +1 -1
  8. package/dist/cjs/types/activity.d.ts.map +1 -1
  9. package/dist/cjs/types/fill.d.ts +2 -0
  10. package/dist/cjs/types/fill.d.ts.map +1 -1
  11. package/dist/cjs/types/order.d.ts.map +1 -1
  12. package/dist/cjs/utils/mapFill.d.ts.map +1 -1
  13. package/dist/cjs/utils/mapFill.js +14 -5
  14. package/dist/cjs/utils/mapFill.js.map +1 -1
  15. package/dist/esm/LighterProvider.d.ts.map +1 -1
  16. package/dist/esm/LighterProvider.js +10 -35
  17. package/dist/esm/LighterProvider.js.map +1 -1
  18. package/dist/esm/accountConfig.d.ts.map +1 -1
  19. package/dist/esm/accountConfig.js +1 -0
  20. package/dist/esm/accountConfig.js.map +1 -1
  21. package/dist/esm/types/account.d.ts +11 -0
  22. package/dist/esm/types/account.d.ts.map +1 -1
  23. package/dist/esm/types/activity.d.ts +9 -4
  24. package/dist/esm/types/activity.d.ts.map +1 -1
  25. package/dist/esm/types/fill.d.ts +9 -2
  26. package/dist/esm/types/fill.d.ts.map +1 -1
  27. package/dist/esm/types/order.d.ts +19 -5
  28. package/dist/esm/types/order.d.ts.map +1 -1
  29. package/dist/esm/utils/mapFill.d.ts.map +1 -1
  30. package/dist/esm/utils/mapFill.js +25 -5
  31. package/dist/esm/utils/mapFill.js.map +1 -1
  32. package/dist/types/LighterProvider.d.ts.map +1 -1
  33. package/dist/types/accountConfig.d.ts.map +1 -1
  34. package/dist/types/types/account.d.ts +11 -0
  35. package/dist/types/types/account.d.ts.map +1 -1
  36. package/dist/types/types/activity.d.ts +9 -4
  37. package/dist/types/types/activity.d.ts.map +1 -1
  38. package/dist/types/types/fill.d.ts +9 -2
  39. package/dist/types/types/fill.d.ts.map +1 -1
  40. package/dist/types/types/order.d.ts +19 -5
  41. package/dist/types/types/order.d.ts.map +1 -1
  42. package/dist/types/utils/mapFill.d.ts.map +1 -1
  43. package/package.json +3 -3
  44. package/src/LighterProvider.ts +20 -47
  45. package/src/accountConfig.ts +1 -0
  46. package/src/types/account.ts +11 -0
  47. package/src/types/activity.ts +9 -4
  48. package/src/types/fill.ts +11 -2
  49. package/src/types/order.ts +19 -5
  50. package/src/utils/mapFill.ts +35 -5
@@ -1,9 +1,10 @@
1
1
  /**
2
2
  * Order payload returned by Lighter's REST API. Amounts and prices are decimal
3
3
  * strings in market precision. `order_expiry` is an absolute Unix-millisecond
4
- * expiry; `created_at`, `updated_at`, and `transaction_time` are Unix seconds.
5
- * Enum-like side, type, time-in-force, status, and trigger fields retain
6
- * Lighter's wire strings.
4
+ * expiry; `created_at` and `updated_at` are Unix seconds. `timestamp` and
5
+ * `transaction_time` carry their unit on the member; `trigger_time` has no
6
+ * documented unit. Enum-like side, type, time-in-force, status, and trigger
7
+ * fields retain Lighter's wire strings.
7
8
  *
8
9
  * @public
9
10
  */
@@ -36,9 +37,18 @@ export type LtOrder = {
36
37
  to_trigger_order_id_1: string;
37
38
  to_cancel_order_id_0: string;
38
39
  block_height: number;
40
+ /**
41
+ * Unit unproven. Lighter documents no unit, and every endpoint that returns
42
+ * this row is auth-gated, so no public probe can observe a value.
43
+ */
39
44
  timestamp: number;
40
45
  created_at: number;
41
46
  updated_at: number;
47
+ /**
48
+ * Unix timestamp in microseconds. Lighter documents no unit, and its public
49
+ * trade rows report this member in microseconds while the sibling
50
+ * `created_at` and `updated_at` stay in seconds.
51
+ */
42
52
  transaction_time: number;
43
53
  };
44
54
  /**
@@ -54,8 +64,8 @@ export interface LtOrdersResponse {
54
64
  }
55
65
  /**
56
66
  * Single order-book level returned by Lighter. Amounts and prices are decimal
57
- * strings in the market's native precision; expiry and transaction time are
58
- * Unix milliseconds.
67
+ * strings in the market's native precision; `order_expiry` is an absolute
68
+ * Unix-millisecond expiry.
59
69
  *
60
70
  * @public
61
71
  */
@@ -67,6 +77,10 @@ export interface LtOrderBookOrder {
67
77
  remaining_base_amount: string;
68
78
  price: string;
69
79
  order_expiry: number;
80
+ /**
81
+ * Unit unproven. Lighter documents no unit, and every resting order this
82
+ * endpoint returns reports the member as zero.
83
+ */
70
84
  transaction_time: number;
71
85
  }
72
86
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"order.d.ts","sourceRoot":"","sources":["../../../src/types/order.ts"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AACH,MAAM,MAAM,OAAO,GAAG;IACpB,WAAW,EAAE,MAAM,CAAA;IACnB,kBAAkB,EAAE,MAAM,CAAA;IAC1B,QAAQ,EAAE,MAAM,CAAA;IAChB,eAAe,EAAE,MAAM,CAAA;IACvB,YAAY,EAAE,MAAM,CAAA;IACpB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,mBAAmB,EAAE,MAAM,CAAA;IAC3B,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,qBAAqB,EAAE,MAAM,CAAA;IAC7B,MAAM,EAAE,OAAO,CAAA;IACf,kBAAkB,EAAE,MAAM,CAAA;IAC1B,mBAAmB,EAAE,MAAM,CAAA;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,aAAa,EAAE,MAAM,CAAA;IACrB,WAAW,EAAE,OAAO,CAAA;IACpB,aAAa,EAAE,MAAM,CAAA;IACrB,YAAY,EAAE,MAAM,CAAA;IACpB,MAAM,EAAE,MAAM,CAAA;IACd,cAAc,EAAE,MAAM,CAAA;IACtB,YAAY,EAAE,MAAM,CAAA;IACpB,kBAAkB,EAAE,MAAM,CAAA;IAC1B,eAAe,EAAE,MAAM,CAAA;IACvB,qBAAqB,EAAE,MAAM,CAAA;IAC7B,qBAAqB,EAAE,MAAM,CAAA;IAC7B,oBAAoB,EAAE,MAAM,CAAA;IAC5B,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,CAAA;IAClB,gBAAgB,EAAE,MAAM,CAAA;CACzB,CAAA;AAED;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,OAAO,EAAE,CAAA;CAClB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,MAAM,CAAA;IAChB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,mBAAmB,EAAE,MAAM,CAAA;IAC3B,qBAAqB,EAAE,MAAM,CAAA;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,YAAY,EAAE,MAAM,CAAA;IACpB,gBAAgB,EAAE,MAAM,CAAA;CACzB;AAED;;;;GAIG;AACH,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,gBAAgB,EAAE,CAAA;IACxB,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,gBAAgB,EAAE,CAAA;CACzB"}
1
+ {"version":3,"file":"order.d.ts","sourceRoot":"","sources":["../../../src/types/order.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AACH,MAAM,MAAM,OAAO,GAAG;IACpB,WAAW,EAAE,MAAM,CAAA;IACnB,kBAAkB,EAAE,MAAM,CAAA;IAC1B,QAAQ,EAAE,MAAM,CAAA;IAChB,eAAe,EAAE,MAAM,CAAA;IACvB,YAAY,EAAE,MAAM,CAAA;IACpB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,mBAAmB,EAAE,MAAM,CAAA;IAC3B,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,qBAAqB,EAAE,MAAM,CAAA;IAC7B,MAAM,EAAE,OAAO,CAAA;IACf,kBAAkB,EAAE,MAAM,CAAA;IAC1B,mBAAmB,EAAE,MAAM,CAAA;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,aAAa,EAAE,MAAM,CAAA;IACrB,WAAW,EAAE,OAAO,CAAA;IACpB,aAAa,EAAE,MAAM,CAAA;IACrB,YAAY,EAAE,MAAM,CAAA;IACpB,MAAM,EAAE,MAAM,CAAA;IACd,cAAc,EAAE,MAAM,CAAA;IACtB,YAAY,EAAE,MAAM,CAAA;IACpB,kBAAkB,EAAE,MAAM,CAAA;IAC1B,eAAe,EAAE,MAAM,CAAA;IACvB,qBAAqB,EAAE,MAAM,CAAA;IAC7B,qBAAqB,EAAE,MAAM,CAAA;IAC7B,oBAAoB,EAAE,MAAM,CAAA;IAC5B,YAAY,EAAE,MAAM,CAAA;IACpB;;;OAGG;IACH,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,CAAA;IAClB;;;;OAIG;IACH,gBAAgB,EAAE,MAAM,CAAA;CACzB,CAAA;AAED;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,OAAO,EAAE,CAAA;CAClB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,MAAM,CAAA;IAChB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,mBAAmB,EAAE,MAAM,CAAA;IAC3B,qBAAqB,EAAE,MAAM,CAAA;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,YAAY,EAAE,MAAM,CAAA;IACpB;;;OAGG;IACH,gBAAgB,EAAE,MAAM,CAAA;CACzB;AAED;;;;GAIG;AACH,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,gBAAgB,EAAE,CAAA;IACxB,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,gBAAgB,EAAE,CAAA;CACzB"}
@@ -1 +1 @@
1
- {"version":3,"file":"mapFill.d.ts","sourceRoot":"","sources":["../../../src/utils/mapFill.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAQ5D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAyChD;;;;;GAKG;AACH,eAAO,MAAM,OAAO,GAClB,OAAO,OAAO,EACd,cAAc,MAAM,EACpB,QAAQ,aAAa,KACpB,IAkDF,CAAA"}
1
+ {"version":3,"file":"mapFill.d.ts","sourceRoot":"","sources":["../../../src/utils/mapFill.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAS5D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAA;AA8DhD;;;;;GAKG;AACH,eAAO,MAAM,OAAO,GAClB,OAAO,OAAO,EACd,cAAc,MAAM,EACpB,QAAQ,aAAa,KACpB,IA0DF,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lifi/perps-sdk-provider-lighter",
3
- "version": "16.0.0",
3
+ "version": "17.0.1",
4
4
  "description": "Lighter provider plugin for @lifi/perps-sdk",
5
5
  "homepage": "https://github.com/lifinance/perps-sdk",
6
6
  "bugs": {
@@ -44,10 +44,10 @@
44
44
  "dependencies": {
45
45
  "big.js": "^7.0.1",
46
46
  "viem": "^2.55.18",
47
- "@lifi/perps-types": "^10.0.0"
47
+ "@lifi/perps-types": "^11.1.0"
48
48
  },
49
49
  "peerDependencies": {
50
- "@lifi/perps-sdk": "^9.0.0"
50
+ "@lifi/perps-sdk": "^10.0.1"
51
51
  },
52
52
  "publishConfig": {
53
53
  "access": "public"
@@ -21,6 +21,7 @@ import {
21
21
  type ProviderGetRunningTwapsParams,
22
22
  type ProviderGetWithdrawableBalancesParams,
23
23
  type ProviderWithdrawableBalance,
24
+ paginateActivity,
24
25
  resolveQuote,
25
26
  resolveRetryPolicy,
26
27
  type SDKRequestOptions,
@@ -1400,68 +1401,40 @@ export const createLighterProvider = (
1400
1401
  counterpartyAccountIndex,
1401
1402
  asset: assetSymbol(t.asset_id),
1402
1403
  amount: t.amount,
1404
+ // The venue charges the transfer fee in the deployment's
1405
+ // settlement asset, not in the asset the row moves, so a spot
1406
+ // token transfer still reports a collateral-denominated fee.
1407
+ fees: [{ amount: t.fee, asset: collateral.displaySymbol }],
1403
1408
  explorerLink: explorerTxUrlFromBase(explorerTxBaseUrl, t.tx_hash),
1404
1409
  meta: {
1405
1410
  transferType: t.type,
1406
1411
  txHash: t.tx_hash,
1407
1412
  fromRoute: t.from_route,
1408
1413
  toRoute: t.to_route,
1409
- fee: t.fee,
1410
1414
  },
1411
1415
  }
1412
1416
  }),
1413
1417
  ]
1414
1418
 
1415
- const merged = [...(inputCursor?.overflow ?? []), ...items]
1416
-
1417
- // The type filter also applies to replayed overflow rows: a cursor
1418
- // minted under one filter must never leak another surface's rows when
1419
- // the caller pages the two surfaces independently.
1420
- const requestedTypes =
1421
- params.type === undefined ? undefined : new Set(params.type)
1422
-
1423
- const filtered = merged.filter((it) => {
1424
- if (requestedTypes !== undefined && !requestedTypes.has(it.type)) {
1425
- return false
1426
- }
1427
- const ts = new Date(it.timestamp).getTime()
1428
- if (params.startTime !== undefined && ts < params.startTime) {
1429
- return false
1430
- }
1431
- if (params.endTime !== undefined && ts > params.endTime) {
1432
- return false
1433
- }
1434
- return true
1435
- })
1436
-
1437
- filtered.sort(
1438
- (a, b) =>
1439
- new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime()
1419
+ const page = paginateActivity(
1420
+ items,
1421
+ inputCursor?.overflow ?? [],
1422
+ params,
1423
+ (overflowTail) =>
1424
+ encodeActivityCursor({
1425
+ deposits: history.deposits.cursor,
1426
+ withdraws: history.withdraws.cursor,
1427
+ fundings: history.fundings.next_cursor,
1428
+ liquidations: history.liquidations.next_cursor,
1429
+ transfers: history.transfers.cursor,
1430
+ overflow: overflowTail,
1431
+ })
1440
1432
  )
1441
1433
 
1442
- const limit = params.limit ?? filtered.length
1443
- const emitted = filtered.slice(0, limit)
1444
- const overflow = filtered.slice(limit)
1445
-
1446
- const nextCursorEnvelope: LighterActivityCursor = {
1447
- deposits: history.deposits.cursor,
1448
- withdraws: history.withdraws.cursor,
1449
- fundings: history.fundings.next_cursor,
1450
- liquidations: history.liquidations.next_cursor,
1451
- transfers: history.transfers.cursor,
1452
- overflow,
1453
- }
1454
- const responseCursor = encodeActivityCursor(nextCursorEnvelope)
1455
- const hasMore = responseCursor !== undefined
1456
-
1457
1434
  return {
1458
1435
  provider: providerKey,
1459
- items: emitted,
1460
- pagination: {
1461
- limit,
1462
- hasMore,
1463
- ...(responseCursor === undefined ? {} : { cursor: responseCursor }),
1464
- },
1436
+ items: page.items,
1437
+ pagination: page.pagination,
1465
1438
  }
1466
1439
  },
1467
1440
 
@@ -149,6 +149,7 @@ function projectLighterDescriptor(
149
149
  case ActionType.UPDATE_ASSET_COLLATERAL:
150
150
  case ActionType.DEPOSIT:
151
151
  case ActionType.META_ACCEPT_TERMS:
152
+ case ActionType.SYNC_FEE_ATTRIBUTION:
152
153
  throw new PerpsError(
153
154
  PerpsErrorCode.SDKError,
154
155
  `Lighter account-config mapper has no projection for ` +
@@ -116,6 +116,11 @@ export interface LtDetailedAccount {
116
116
  available_balance: string
117
117
  status: number
118
118
  collateral: string
119
+ /**
120
+ * Unix timestamp in microseconds. Lighter documents no unit, and its
121
+ * account rows report 16-digit values. A dormant account reports `0`, so
122
+ * treat `0` as "no transaction" and not as the Unix epoch.
123
+ */
119
124
  transaction_time: number
120
125
  account_trading_mode: number
121
126
  account_index: number
@@ -183,6 +188,12 @@ export interface LtSubAccount {
183
188
  available_balance: string
184
189
  status: number
185
190
  collateral: string
191
+ /**
192
+ * Unix timestamp in microseconds, the same wire member as
193
+ * `LtDetailedAccount.transaction_time`. Lighter leaves it at `0` on the
194
+ * `accountsByL1Address` rows, so read the value from the account endpoint
195
+ * instead.
196
+ */
186
197
  transaction_time: number
187
198
  account_trading_mode: number
188
199
  }
@@ -113,7 +113,11 @@ export interface LtLiqTrade {
113
113
  size: string
114
114
  taker_fee: string
115
115
  maker_fee: string
116
- /** Unix timestamp in milliseconds. */
116
+ /**
117
+ * Unix timestamp in microseconds. The enclosing row's `executed_at` is
118
+ * milliseconds. Lighter documents no unit, and its public trade rows report
119
+ * this member in microseconds.
120
+ */
117
121
  transaction_time: number
118
122
  }
119
123
 
@@ -177,9 +181,10 @@ export interface LtLiquidationsResponse {
177
181
  }
178
182
 
179
183
  /**
180
- * Asset transfer-history row returned by Lighter. Amounts and fees are decimal
181
- * strings in the asset's precision; route literals identify the source and
182
- * destination account ledger (`spot` or `perps`).
184
+ * Asset transfer-history row returned by Lighter. `amount` is a decimal string
185
+ * in the precision of the asset the row moves; `fee` is a decimal string in the
186
+ * precision of the deployment's settlement asset. Route literals identify the
187
+ * source and destination account ledger (`spot` or `perps`).
183
188
  *
184
189
  * @public
185
190
  */
package/src/types/fill.ts CHANGED
@@ -3,8 +3,13 @@
3
3
  /**
4
4
  * Public trade/fill row returned by Lighter's `/api/v1/trades` endpoint.
5
5
  * Size, price, and notional fields are decimal strings in market precision;
6
- * `timestamp` and `transaction_time` are Unix millisecond timestamps. The
7
- * optional fee fields are integer fee ticks and may be absent on older rows.
6
+ * `timestamp` is a Unix millisecond timestamp; `transaction_time` is a Unix
7
+ * microsecond timestamp. The optional fee fields are the side's fee *rate* as
8
+ * an integer tick on `LIGHTER_FEE_TICK_SCALE` (1e6), not the amount charged,
9
+ * and may be absent on older rows. A row can also carry
10
+ * `integrator_maker_fee` or `integrator_taker_fee`: a second optional rate for
11
+ * the same side, on the same 1e6 tick scale. The mapper adds that second rate
12
+ * to the side's own rate.
8
13
  *
9
14
  * @public
10
15
  */
@@ -28,6 +33,10 @@ export type LtTrade = {
28
33
  // on older trades) — keep optional and let the mapper emit `undefined`.
29
34
  taker_fee?: number
30
35
  maker_fee?: number
36
+ // A second fee tick that a row can carry for the same side, on the same 1e6
37
+ // tick scale as `taker_fee` / `maker_fee`.
38
+ integrator_taker_fee?: number
39
+ integrator_maker_fee?: number
31
40
  transaction_time: number
32
41
  // Per-counterparty position snapshot BEFORE the trade is applied. Signed
33
42
  // strings: positive = long, negative = short, "0" / "0.00000" = flat.
@@ -3,9 +3,10 @@
3
3
  /**
4
4
  * Order payload returned by Lighter's REST API. Amounts and prices are decimal
5
5
  * strings in market precision. `order_expiry` is an absolute Unix-millisecond
6
- * expiry; `created_at`, `updated_at`, and `transaction_time` are Unix seconds.
7
- * Enum-like side, type, time-in-force, status, and trigger fields retain
8
- * Lighter's wire strings.
6
+ * expiry; `created_at` and `updated_at` are Unix seconds. `timestamp` and
7
+ * `transaction_time` carry their unit on the member; `trigger_time` has no
8
+ * documented unit. Enum-like side, type, time-in-force, status, and trigger
9
+ * fields retain Lighter's wire strings.
9
10
  *
10
11
  * @public
11
12
  */
@@ -38,9 +39,18 @@ export type LtOrder = {
38
39
  to_trigger_order_id_1: string
39
40
  to_cancel_order_id_0: string
40
41
  block_height: number
42
+ /**
43
+ * Unit unproven. Lighter documents no unit, and every endpoint that returns
44
+ * this row is auth-gated, so no public probe can observe a value.
45
+ */
41
46
  timestamp: number
42
47
  created_at: number
43
48
  updated_at: number
49
+ /**
50
+ * Unix timestamp in microseconds. Lighter documents no unit, and its public
51
+ * trade rows report this member in microseconds while the sibling
52
+ * `created_at` and `updated_at` stay in seconds.
53
+ */
44
54
  transaction_time: number
45
55
  }
46
56
 
@@ -58,8 +68,8 @@ export interface LtOrdersResponse {
58
68
 
59
69
  /**
60
70
  * Single order-book level returned by Lighter. Amounts and prices are decimal
61
- * strings in the market's native precision; expiry and transaction time are
62
- * Unix milliseconds.
71
+ * strings in the market's native precision; `order_expiry` is an absolute
72
+ * Unix-millisecond expiry.
63
73
  *
64
74
  * @public
65
75
  */
@@ -71,6 +81,10 @@ export interface LtOrderBookOrder {
71
81
  remaining_base_amount: string
72
82
  price: string
73
83
  order_expiry: number
84
+ /**
85
+ * Unit unproven. Lighter documents no unit, and every resting order this
86
+ * endpoint returns reports the member as zero.
87
+ */
74
88
  transaction_time: number
75
89
  }
76
90
 
@@ -11,8 +11,30 @@ import {
11
11
  OrderType,
12
12
  } from '@lifi/perps-types'
13
13
  import Big from 'big.js'
14
+ import { LIGHTER_FEE_TICK_SCALE } from '../constants.js'
14
15
  import type { LtTrade } from '../types/index.js'
15
16
 
17
+ /**
18
+ * Fee charged on a fill, in the market's quote asset. Lighter publishes the
19
+ * side's fee *rate* as an integer tick on `LIGHTER_FEE_TICK_SCALE` rather than
20
+ * the amount it charged. A row can carry more than one tick for the same side,
21
+ * so `amount = notional * sum(side ticks) / LIGHTER_FEE_TICK_SCALE`.
22
+ *
23
+ * The product keeps the sign of both inputs. A rebate tick therefore maps to a
24
+ * negative amount, which `Fee.amount` permits and the Ondo mapper already emits
25
+ * when a rebate exceeds the fee, so this helper never clamps the sign. A zero
26
+ * notional charges a zero fee at every tick.
27
+ */
28
+ const tickToFeeAmount = (
29
+ notional: string,
30
+ ownTick: number,
31
+ integratorTick: number | undefined
32
+ ): string =>
33
+ new Big(notional)
34
+ .times(new Big(ownTick).plus(integratorTick ?? 0))
35
+ .div(LIGHTER_FEE_TICK_SCALE)
36
+ .toFixed()
37
+
16
38
  /**
17
39
  * Realized PnL on a position-reducing fill, derived from the pre-trade entry
18
40
  * basis. Returns `undefined` for opens/increases (nothing closes) or when the
@@ -75,9 +97,10 @@ export const mapFill = (
75
97
  const entryQuoteBefore = isMaker
76
98
  ? trade.maker_entry_quote_before
77
99
  : trade.taker_entry_quote_before
78
- const feeAmount = isMaker
79
- ? trade.maker_fee?.toString()
80
- : trade.taker_fee?.toString()
100
+ const feeTick = isMaker ? trade.maker_fee : trade.taker_fee
101
+ const integratorFeeTick = isMaker
102
+ ? trade.integrator_maker_fee
103
+ : trade.integrator_taker_fee
81
104
 
82
105
  return {
83
106
  id: trade.trade_id.toString(),
@@ -91,9 +114,16 @@ export const mapFill = (
91
114
  liquidity: isMaker ? LiquidityRole.MAKER : LiquidityRole.TAKER,
92
115
  // Lighter charges the fill fee in the market's quote asset.
93
116
  fee:
94
- feeAmount === undefined
117
+ feeTick === undefined
95
118
  ? undefined
96
- : { amount: feeAmount, asset: market.quoteAsset.displaySymbol },
119
+ : {
120
+ amount: tickToFeeAmount(
121
+ trade.usd_amount,
122
+ feeTick,
123
+ integratorFeeTick
124
+ ),
125
+ asset: market.quoteAsset.displaySymbol,
126
+ },
97
127
  realizedPnl: deriveRealizedPnl(
98
128
  startPosition,
99
129
  entryQuoteBefore,