@lifi/perps-sdk-provider-lighter 23.0.0 → 24.0.0

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 (63) hide show
  1. package/dist/cjs/LighterProvider.d.ts.map +1 -1
  2. package/dist/cjs/LighterProvider.js +43 -0
  3. package/dist/cjs/LighterProvider.js.map +1 -1
  4. package/dist/cjs/types/index.d.ts +1 -0
  5. package/dist/cjs/types/index.d.ts.map +1 -1
  6. package/dist/cjs/types/index.js +1 -0
  7. package/dist/cjs/types/index.js.map +1 -1
  8. package/dist/cjs/types/pnl.d.ts +25 -0
  9. package/dist/cjs/types/pnl.d.ts.map +1 -0
  10. package/dist/cjs/types/pnl.js +3 -0
  11. package/dist/cjs/types/pnl.js.map +1 -0
  12. package/dist/cjs/utils/index.d.ts +1 -0
  13. package/dist/cjs/utils/index.d.ts.map +1 -1
  14. package/dist/cjs/utils/index.js +3 -1
  15. package/dist/cjs/utils/index.js.map +1 -1
  16. package/dist/cjs/utils/mapPortfolioHistory.d.ts +5 -0
  17. package/dist/cjs/utils/mapPortfolioHistory.d.ts.map +1 -0
  18. package/dist/cjs/utils/mapPortfolioHistory.js +40 -0
  19. package/dist/cjs/utils/mapPortfolioHistory.js.map +1 -0
  20. package/dist/cjs/websocket/LighterWsProvider.d.ts.map +1 -1
  21. package/dist/cjs/websocket/LighterWsProvider.js +1 -5
  22. package/dist/cjs/websocket/LighterWsProvider.js.map +1 -1
  23. package/dist/esm/LighterProvider.d.ts.map +1 -1
  24. package/dist/esm/LighterProvider.js +52 -2
  25. package/dist/esm/LighterProvider.js.map +1 -1
  26. package/dist/esm/types/index.d.ts +1 -0
  27. package/dist/esm/types/index.d.ts.map +1 -1
  28. package/dist/esm/types/index.js +1 -0
  29. package/dist/esm/types/index.js.map +1 -1
  30. package/dist/esm/types/pnl.d.ts +33 -0
  31. package/dist/esm/types/pnl.d.ts.map +1 -0
  32. package/dist/esm/types/pnl.js +4 -0
  33. package/dist/esm/types/pnl.js.map +1 -0
  34. package/dist/esm/utils/index.d.ts +1 -0
  35. package/dist/esm/utils/index.d.ts.map +1 -1
  36. package/dist/esm/utils/index.js +1 -0
  37. package/dist/esm/utils/index.js.map +1 -1
  38. package/dist/esm/utils/mapPortfolioHistory.d.ts +12 -0
  39. package/dist/esm/utils/mapPortfolioHistory.d.ts.map +1 -0
  40. package/dist/esm/utils/mapPortfolioHistory.js +40 -0
  41. package/dist/esm/utils/mapPortfolioHistory.js.map +1 -0
  42. package/dist/esm/websocket/LighterWsProvider.d.ts +1 -1
  43. package/dist/esm/websocket/LighterWsProvider.d.ts.map +1 -1
  44. package/dist/esm/websocket/LighterWsProvider.js +2 -12
  45. package/dist/esm/websocket/LighterWsProvider.js.map +1 -1
  46. package/dist/types/LighterProvider.d.ts.map +1 -1
  47. package/dist/types/types/index.d.ts +1 -0
  48. package/dist/types/types/index.d.ts.map +1 -1
  49. package/dist/types/types/pnl.d.ts +33 -0
  50. package/dist/types/types/pnl.d.ts.map +1 -0
  51. package/dist/types/utils/index.d.ts +1 -0
  52. package/dist/types/utils/index.d.ts.map +1 -1
  53. package/dist/types/utils/mapPortfolioHistory.d.ts +12 -0
  54. package/dist/types/utils/mapPortfolioHistory.d.ts.map +1 -0
  55. package/dist/types/websocket/LighterWsProvider.d.ts +1 -1
  56. package/dist/types/websocket/LighterWsProvider.d.ts.map +1 -1
  57. package/package.json +3 -3
  58. package/src/LighterProvider.ts +89 -0
  59. package/src/types/index.ts +1 -0
  60. package/src/types/pnl.ts +36 -0
  61. package/src/utils/index.ts +1 -0
  62. package/src/utils/mapPortfolioHistory.ts +52 -0
  63. package/src/websocket/LighterWsProvider.ts +10 -16
@@ -4,6 +4,7 @@ export * from './activity.js';
4
4
  export * from './asset.js';
5
5
  export * from './fill.js';
6
6
  export * from './order.js';
7
+ export * from './pnl.js';
7
8
  export * from './submit.js';
8
9
  export * from './ws.js';
9
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/types/index.ts"],"names":[],"mappings":"AAIA,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAC3B,cAAc,eAAe,CAAA;AAC7B,cAAc,YAAY,CAAA;AAC1B,cAAc,WAAW,CAAA;AACzB,cAAc,YAAY,CAAA;AAC1B,cAAc,aAAa,CAAA;AAC3B,cAAc,SAAS,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/types/index.ts"],"names":[],"mappings":"AAIA,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAC3B,cAAc,eAAe,CAAA;AAC7B,cAAc,YAAY,CAAA;AAC1B,cAAc,WAAW,CAAA;AACzB,cAAc,YAAY,CAAA;AAC1B,cAAc,UAAU,CAAA;AACxB,cAAc,aAAa,CAAA;AAC3B,cAAc,SAAS,CAAA"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * One PnL bucket. `timestamp` is Unix milliseconds. Every other field is a
3
+ * JSON number in USD for that bucket alone; the endpoint reports no account
4
+ * value.
5
+ *
6
+ * @public
7
+ */
8
+ export interface LtPnLEntry {
9
+ timestamp: number;
10
+ trade_pnl: number;
11
+ inflow: number;
12
+ outflow: number;
13
+ pool_pnl: number;
14
+ pool_inflow: number;
15
+ pool_outflow: number;
16
+ pool_total_shares: number;
17
+ spot_inflow: number;
18
+ spot_outflow: number;
19
+ staked_lit: number;
20
+ staking_inflow: number;
21
+ staking_outflow: number;
22
+ staking_pnl: number;
23
+ trade_spot_pnl: number;
24
+ volume: number;
25
+ }
26
+ /** `GET /api/v1/pnl` response envelope. @public */
27
+ export interface LtAccountPnL {
28
+ code: number;
29
+ message?: string;
30
+ resolution: string;
31
+ pnl: LtPnLEntry[] | null;
32
+ }
33
+ //# sourceMappingURL=pnl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pnl.d.ts","sourceRoot":"","sources":["../../../src/types/pnl.ts"],"names":[],"mappings":"AAGA;;;;;;GAMG;AACH,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,EAAE,MAAM,CAAA;IACpB,iBAAiB,EAAE,MAAM,CAAA;IACzB,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,EAAE,MAAM,CAAA;IACpB,UAAU,EAAE,MAAM,CAAA;IAClB,cAAc,EAAE,MAAM,CAAA;IACtB,eAAe,EAAE,MAAM,CAAA;IACvB,WAAW,EAAE,MAAM,CAAA;IACnB,cAAc,EAAE,MAAM,CAAA;IACtB,MAAM,EAAE,MAAM,CAAA;CACf;AAED,mDAAmD;AACnD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;IAClB,GAAG,EAAE,UAAU,EAAE,GAAG,IAAI,CAAA;CACzB"}
@@ -10,6 +10,7 @@ export { mapFill } from './mapFill.js';
10
10
  export { mapMarketContext } from './mapMarketContext.js';
11
11
  export { mapOpenPositions } from './mapOpenPositions.js';
12
12
  export { classifyAndMapOrders, isTriggerOrder, isTriggerType, mapOrder, mapOrderDetail, mapStatusReason, mapTriggerOrder, } from './mapOrder.js';
13
+ export { mapPortfolioHistory } from './mapPortfolioHistory.js';
13
14
  export { leverageFromImf, mapPosition } from './mapPosition.js';
14
15
  export { mapMarketOrderLimits } from './marketLimits.js';
15
16
  export { mapInterval } from './ohlcvInterval.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/index.ts"],"names":[],"mappings":"AAIA,YAAY,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAA;AAChE,OAAO,EACL,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AACjD,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAA;AAC/E,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAA;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAChD,OAAO,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAA;AAC3D,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AACxD,OAAO,EACL,oBAAoB,EACpB,cAAc,EACd,aAAa,EACb,QAAQ,EACR,cAAc,EACd,eAAe,EACf,eAAe,GAChB,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AACxE,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAA;AACzD,OAAO,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAA;AAC/D,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,EACnB,2BAA2B,EAC3B,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,2BAA2B,EAAE,MAAM,2BAA2B,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/index.ts"],"names":[],"mappings":"AAIA,YAAY,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAA;AAChE,OAAO,EACL,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AACjD,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAA;AAC/E,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAA;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAChD,OAAO,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAA;AAC3D,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AACxD,OAAO,EACL,oBAAoB,EACpB,cAAc,EACd,aAAa,EACb,QAAQ,EACR,cAAc,EACd,eAAe,EACf,eAAe,GAChB,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAC9D,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AACxE,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAA;AACzD,OAAO,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAA;AAC/D,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,EACnB,2BAA2B,EAC3B,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,2BAA2B,EAAE,MAAM,2BAA2B,CAAA"}
@@ -0,0 +1,12 @@
1
+ import type { PortfolioHistoryRange, PortfolioHistoryResponse } from '@lifi/perps-types';
2
+ import Big from 'big.js';
3
+ import type { LtPnLEntry } from '../types/pnl.js';
4
+ /**
5
+ * Build the portfolio series from Lighter PnL buckets and the account's
6
+ * current value. Lighter reports no historical account value, so each
7
+ * point's `accountValue` is `currentValue` with every later bucket's
8
+ * `trade_pnl + trade_spot_pnl + inflow - outflow` removed. `pnl` is the
9
+ * running `trade_pnl + trade_spot_pnl`, so both series unwind the same PnL.
10
+ */
11
+ export declare const mapPortfolioHistory: (range: PortfolioHistoryRange, entries: LtPnLEntry[], currentValue: Big) => PortfolioHistoryResponse;
12
+ //# sourceMappingURL=mapPortfolioHistory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mapPortfolioHistory.d.ts","sourceRoot":"","sources":["../../../src/utils/mapPortfolioHistory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,qBAAqB,EACrB,wBAAwB,EACzB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,GAAG,MAAM,QAAQ,CAAA;AACxB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAEjD;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,GAC9B,OAAO,qBAAqB,EAC5B,SAAS,UAAU,EAAE,EACrB,cAAc,GAAG,KAChB,wBAiCF,CAAA"}
@@ -41,7 +41,7 @@ export interface LighterWsProviderOptions {
41
41
  resolveAuthToken?: LighterAuthTokenResolver;
42
42
  }
43
43
  /**
44
- * Lighter realtime WS provider (extends {@link WsProviderBase}): subscribes to
44
+ * Lighter WebSocket provider (extends {@link WsProviderBase}): subscribes to
45
45
  * Lighter's WS channels (orderbook, marketsContext, orders, positions), attaching auth
46
46
  * tokens to gated channels. Construct via {@link lighterWsProvider}.
47
47
  *
@@ -1 +1 @@
1
- {"version":3,"file":"LighterWsProvider.d.ts","sourceRoot":"","sources":["../../../src/websocket/LighterWsProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,cAAc,EACnB,KAAK,sBAAsB,EAC3B,KAAK,aAAa,EAKlB,cAAc,EACd,KAAK,iBAAiB,EAEvB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAKL,KAAK,YAAY,EAClB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AA4EnC;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,wBAAwB,GAAG,CACrC,OAAO,EAAE,OAAO,KACb,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAA;AAEhC,UAAU,QAAQ;IAChB,kFAAkF;IAClF,OAAO,EAAE,MAAM,CAAA;IACf,+DAA+D;IAC/D,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,yEAAyE;IACzE,SAAS,EAAE,OAAO,CAAA;CACnB;AAkBD;;;;GAIG;AACH,MAAM,WAAW,wBAAwB;IACvC,wEAAwE;IACxE,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,wBAAwB,CAAA;CAC5C;AAED;;;;;;GAMG;AACH,qBAAa,iBAAkB,SAAQ,cAAc,CAAC,QAAQ,CAAC;IAC7D,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAkB;IACtC,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAE5B;IACb,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA4B;IAEnD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAoC;IAC/D,OAAO,CAAC,cAAc,CAAoC;IAE1D;;;;OAIG;IACH,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAA2C;IAE9E,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA4B;IAErD,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAA4B;IAC9D,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAqC;gBAGxE,KAAK,GAAE,MAA+B,EACtC,WAAW,GAAE,MAA6B,EAC1C,OAAO,GAAE,wBAA6B,EACtC,MAAM,CAAC,EAAE,cAAc;IAsBzB;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;IAWzB;;;;;OAKG;IACG,cAAc,CAClB,MAAM,EAAE,sBAAsB,EAC9B,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,MAAM,IAAI,CAAC;cAkBN,WAAW,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC;cAqDhD,OAAO,IAAI,IAAI;cAMlB,aAAa,CAAC,EAC5B,OAAO,EACP,SAAS,EACT,OAAO,GACR,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAW3B;;;;;;OAMG;YACW,gBAAgB;IAsB9B,SAAS,CAAC,KAAK,CAAC,GAAG,EAAE,YAAY,GAAG,MAAM;YA2B5B,cAAc;YAsFd,mBAAmB;YAqBnB,iBAAiB;IAK/B,SAAS,CAAC,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAqB1C,OAAO,CAAC,QAAQ;IAkFhB,OAAO,CAAC,mBAAmB;IAgB3B,OAAO,CAAC,eAAe;IAuDvB,OAAO,CAAC,mBAAmB;IAiB3B,OAAO,CAAC,sBAAsB;IAiC9B;;;;;;OAMG;IACH,OAAO,CAAC,kBAAkB;IAuB1B,OAAO,CAAC,iBAAiB;IAuCzB,OAAO,CAAC,eAAe;IA+BvB,OAAO,CAAC,YAAY;IAwBpB,OAAO,CAAC,mBAAmB;CAc5B;AAkID;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,iBAAiB,GAC3B,UAAU,wBAAwB,KAAG,iBAEmB,CAAA"}
1
+ {"version":3,"file":"LighterWsProvider.d.ts","sourceRoot":"","sources":["../../../src/websocket/LighterWsProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,cAAc,EACnB,KAAK,sBAAsB,EAC3B,KAAK,aAAa,EAKlB,cAAc,EACd,KAAK,iBAAiB,EAGvB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAKL,KAAK,YAAY,EAClB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AA4EnC;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,wBAAwB,GAAG,CACrC,OAAO,EAAE,OAAO,KACb,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAA;AAEhC,UAAU,QAAQ;IAChB,kFAAkF;IAClF,OAAO,EAAE,MAAM,CAAA;IACf,+DAA+D;IAC/D,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,yEAAyE;IACzE,SAAS,EAAE,OAAO,CAAA;CACnB;AAkBD;;;;GAIG;AACH,MAAM,WAAW,wBAAwB;IACvC,wEAAwE;IACxE,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,wBAAwB,CAAA;CAC5C;AAED;;;;;;GAMG;AACH,qBAAa,iBAAkB,SAAQ,cAAc,CAAC,QAAQ,CAAC;IAC7D,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAkB;IACtC,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAE5B;IACb,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA4B;IAEnD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAoC;IAC/D,OAAO,CAAC,cAAc,CAAoC;IAE1D;;;;OAIG;IACH,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAA2C;IAE9E,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA4B;IAErD,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAA4B;IAC9D,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAqC;gBAGxE,KAAK,GAAE,MAA+B,EACtC,WAAW,GAAE,MAA6B,EAC1C,OAAO,GAAE,wBAA6B,EACtC,MAAM,CAAC,EAAE,cAAc;IAsBzB;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;IAWzB;;;;;OAKG;IACG,cAAc,CAClB,MAAM,EAAE,sBAAsB,EAC9B,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,MAAM,IAAI,CAAC;cAkBN,WAAW,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC;cA6ChD,OAAO,IAAI,IAAI;cAMlB,aAAa,CAAC,EAC5B,OAAO,EACP,SAAS,EACT,OAAO,GACR,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAW3B;;;;;;OAMG;YACW,gBAAgB;IAsB9B,SAAS,CAAC,KAAK,CAAC,GAAG,EAAE,YAAY,GAAG,MAAM;YAwB5B,cAAc;YAsFd,mBAAmB;YAqBnB,iBAAiB;IAK/B,SAAS,CAAC,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAqB1C,OAAO,CAAC,QAAQ;IAkFhB,OAAO,CAAC,mBAAmB;IAgB3B,OAAO,CAAC,eAAe;IAuDvB,OAAO,CAAC,mBAAmB;IAiB3B,OAAO,CAAC,sBAAsB;IAiC9B;;;;;;OAMG;IACH,OAAO,CAAC,kBAAkB;IAuB1B,OAAO,CAAC,iBAAiB;IAuCzB,OAAO,CAAC,eAAe;IA+BvB,OAAO,CAAC,YAAY;IAwBpB,OAAO,CAAC,mBAAmB;CAc5B;AAkID;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,iBAAiB,GAC5B,UAAU,wBAAwB,KACjC,iBAKA,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lifi/perps-sdk-provider-lighter",
3
- "version": "23.0.0",
3
+ "version": "24.0.0",
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": "^12.2.0"
47
+ "@lifi/perps-types": "^12.3.0"
48
48
  },
49
49
  "peerDependencies": {
50
- "@lifi/perps-sdk": "^12.1.0"
50
+ "@lifi/perps-sdk": "^13.0.0"
51
51
  },
52
52
  "publishConfig": {
53
53
  "access": "public"
@@ -17,6 +17,7 @@ import {
17
17
  type ProviderGetMarketSettingsParams,
18
18
  type ProviderGetOrderParams,
19
19
  type ProviderGetOrdersParams,
20
+ type ProviderGetPortfolioHistoryParams,
20
21
  type ProviderGetPositionsParams,
21
22
  type ProviderGetQuoteParams,
22
23
  type ProviderGetRunningTwapsParams,
@@ -46,6 +47,8 @@ import type {
46
47
  MarketSettings,
47
48
  Order,
48
49
  OrdersResponse,
50
+ PortfolioHistoryRange,
51
+ PortfolioHistoryResponse,
49
52
  Position,
50
53
  PositionsResponse,
51
54
  ProviderAction,
@@ -91,6 +94,7 @@ import type {
91
94
  LtAccount,
92
95
  LtAccountLimits,
93
96
  LtAccountOrdersResponse,
97
+ LtAccountPnL,
94
98
  LtDepositHistoryItem,
95
99
  LtDepositHistoryResponse,
96
100
  LtDetailedAccountPosition,
@@ -119,6 +123,7 @@ import {
119
123
  import {
120
124
  LIGHTER_RETRY_DEFAULTS,
121
125
  LighterApiClient,
126
+ LighterAuthRejectedError,
122
127
  LighterTokenRevokedError,
123
128
  } from './utils/apiClient.js'
124
129
  import { isAssetMarginEnabled } from './utils/assetCollateral.js'
@@ -134,6 +139,7 @@ import {
134
139
  mapFill,
135
140
  mapOpenPositions,
136
141
  mapOrderDetail,
142
+ mapPortfolioHistory,
137
143
  positionMarginConstraints,
138
144
  toBigOrNull,
139
145
  toIsoFromMs,
@@ -181,6 +187,24 @@ const CLIENT_ORDER_INDEX_PATTERN = /^\d+$/
181
187
 
182
188
  const INACTIVE_ORDERS_LOOKUP_LIMIT = 100
183
189
 
190
+ interface PnlWindow {
191
+ resolution: '1h' | '4h' | '1d'
192
+ bucketMs: number
193
+ countBack: number
194
+ }
195
+
196
+ const HOUR_MS = 60 * 60 * 1000
197
+ const DAY_MS = 24 * HOUR_MS
198
+
199
+ // `all` has no natural bucket count; 1000 daily buckets reach back past the
200
+ // venue's launch for every account.
201
+ const PNL_WINDOWS: Record<PortfolioHistoryRange, PnlWindow> = {
202
+ '24h': { resolution: '1h', bucketMs: HOUR_MS, countBack: 24 },
203
+ '7d': { resolution: '4h', bucketMs: 4 * HOUR_MS, countBack: 42 },
204
+ '30d': { resolution: '1d', bucketMs: DAY_MS, countBack: 30 },
205
+ all: { resolution: '1d', bucketMs: DAY_MS, countBack: 1000 },
206
+ }
207
+
184
208
  /** Activity surfaces whose rows name a market, so they need the market registry. */
185
209
  const MARKET_BEARING_TYPES: ReadonlySet<ActivityType> = new Set([
186
210
  ActivityType.FUNDING,
@@ -1305,6 +1329,71 @@ export const createLighterProvider = (
1305
1329
  }
1306
1330
  },
1307
1331
 
1332
+ async getPortfolioHistory(
1333
+ params: ProviderGetPortfolioHistoryParams,
1334
+ opts?: SDKRequestOptions
1335
+ ): Promise<PortfolioHistoryResponse> {
1336
+ const sdkOwnsToken =
1337
+ opts?.lighterAuthToken === undefined && authTokenSource === undefined
1338
+ const apiKey = sdkOwnsToken ? await keyStore.get(params.address) : null
1339
+ const token = await resolveAuthToken(
1340
+ opts,
1341
+ params.address,
1342
+ apiKey ?? undefined
1343
+ )
1344
+ if (token === undefined) {
1345
+ return { range: params.range, points: [] }
1346
+ }
1347
+
1348
+ const client = apiClient(opts)
1349
+ const account = await fetchDetailedAccount(client, params.address)
1350
+ const window = PNL_WINDOWS[params.range]
1351
+ const endTimestamp = Date.now()
1352
+ const queryParams: Record<string, string | number | boolean> = {
1353
+ by: 'index',
1354
+ value: String(account.index),
1355
+ resolution: window.resolution,
1356
+ start_timestamp:
1357
+ params.range === 'all'
1358
+ ? 0
1359
+ : endTimestamp - window.countBack * window.bucketMs,
1360
+ end_timestamp: endTimestamp,
1361
+ count_back: window.countBack,
1362
+ ignore_transfers: false,
1363
+ }
1364
+ const read = (tok: string) =>
1365
+ client.getAuthed<LtAccountPnL>('/api/v1/pnl', tok, queryParams)
1366
+
1367
+ // The read-only token may not be accepted on `/pnl`; the standard token
1368
+ // is, so a read signed from the SDK's own key retries once with it. The
1369
+ // fallback sits outside `retryOnRevoked`, so a revocation the standard
1370
+ // token reports never replaces the read-only one. The key is re-read at
1371
+ // retry time because `REGISTER_API_KEY` can rotate it.
1372
+ const response = await retryOnRevoked(
1373
+ opts,
1374
+ params.address,
1375
+ token,
1376
+ read
1377
+ ).catch(async (err: unknown) => {
1378
+ if (!(err instanceof LighterAuthRejectedError) || apiKey === null) {
1379
+ throw err
1380
+ }
1381
+ const current = (await keyStore.get(params.address)) ?? apiKey
1382
+ return read(
1383
+ await getStandardAuthToken(params.address, current.apiKeyPrivateKey, {
1384
+ apiKeyIndex: current.apiKeyIndex,
1385
+ accountIndex: current.accountIndex,
1386
+ })
1387
+ )
1388
+ })
1389
+
1390
+ return mapPortfolioHistory(
1391
+ params.range,
1392
+ wireList(response.pnl),
1393
+ toRequiredBig(account.total_asset_value, 'total_asset_value')
1394
+ )
1395
+ },
1396
+
1308
1397
  async getActivity(
1309
1398
  params: ProviderGetActivityParams,
1310
1399
  opts?: SDKRequestOptions
@@ -8,5 +8,6 @@ export * from './activity.js'
8
8
  export * from './asset.js'
9
9
  export * from './fill.js'
10
10
  export * from './order.js'
11
+ export * from './pnl.js'
11
12
  export * from './submit.js'
12
13
  export * from './ws.js'
@@ -0,0 +1,36 @@
1
+ // Account PnL shapes returned by Lighter's `/api/v1/pnl` endpoint.
2
+ // Lighter serializes an empty list as JSON `null`, so list members are nullable.
3
+
4
+ /**
5
+ * One PnL bucket. `timestamp` is Unix milliseconds. Every other field is a
6
+ * JSON number in USD for that bucket alone; the endpoint reports no account
7
+ * value.
8
+ *
9
+ * @public
10
+ */
11
+ export interface LtPnLEntry {
12
+ timestamp: number
13
+ trade_pnl: number
14
+ inflow: number
15
+ outflow: number
16
+ pool_pnl: number
17
+ pool_inflow: number
18
+ pool_outflow: number
19
+ pool_total_shares: number
20
+ spot_inflow: number
21
+ spot_outflow: number
22
+ staked_lit: number
23
+ staking_inflow: number
24
+ staking_outflow: number
25
+ staking_pnl: number
26
+ trade_spot_pnl: number
27
+ volume: number
28
+ }
29
+
30
+ /** `GET /api/v1/pnl` response envelope. @public */
31
+ export interface LtAccountPnL {
32
+ code: number
33
+ message?: string
34
+ resolution: string
35
+ pnl: LtPnLEntry[] | null
36
+ }
@@ -25,6 +25,7 @@ export {
25
25
  mapStatusReason,
26
26
  mapTriggerOrder,
27
27
  } from './mapOrder.js'
28
+ export { mapPortfolioHistory } from './mapPortfolioHistory.js'
28
29
  export { leverageFromImf, mapPosition } from './mapPosition.js'
29
30
  export { mapMarketOrderLimits } from './marketLimits.js'
30
31
  export { mapInterval } from './ohlcvInterval.js'
@@ -0,0 +1,52 @@
1
+ import type {
2
+ PortfolioHistoryRange,
3
+ PortfolioHistoryResponse,
4
+ } from '@lifi/perps-types'
5
+ import Big from 'big.js'
6
+ import type { LtPnLEntry } from '../types/pnl.js'
7
+
8
+ /**
9
+ * Build the portfolio series from Lighter PnL buckets and the account's
10
+ * current value. Lighter reports no historical account value, so each
11
+ * point's `accountValue` is `currentValue` with every later bucket's
12
+ * `trade_pnl + trade_spot_pnl + inflow - outflow` removed. `pnl` is the
13
+ * running `trade_pnl + trade_spot_pnl`, so both series unwind the same PnL.
14
+ */
15
+ export const mapPortfolioHistory = (
16
+ range: PortfolioHistoryRange,
17
+ entries: LtPnLEntry[],
18
+ currentValue: Big
19
+ ): PortfolioHistoryResponse => {
20
+ const ordered = [...entries].sort((a, b) => a.timestamp - b.timestamp)
21
+
22
+ const accountValues: Big[] = []
23
+ let value = currentValue
24
+ for (let i = ordered.length - 1; i >= 0; i -= 1) {
25
+ accountValues[i] = value
26
+ const entry = ordered[i]
27
+ value = value
28
+ .minus(new Big(entry.trade_pnl))
29
+ .minus(new Big(entry.trade_spot_pnl))
30
+ .minus(new Big(entry.inflow))
31
+ .plus(new Big(entry.outflow))
32
+ }
33
+
34
+ let pnl = new Big(0)
35
+ let volume = new Big(0)
36
+ const points = ordered.map((entry, i) => {
37
+ pnl = pnl.plus(new Big(entry.trade_pnl)).plus(new Big(entry.trade_spot_pnl))
38
+ volume = volume.plus(new Big(entry.volume))
39
+ return {
40
+ timestamp: entry.timestamp,
41
+ accountValue: accountValues[i].toFixed(),
42
+ pnl: pnl.toFixed(),
43
+ }
44
+ })
45
+
46
+ return {
47
+ range,
48
+ points,
49
+ volume: volume.toFixed(),
50
+ totalPnl: points.at(-1)?.pnl,
51
+ }
52
+ }
@@ -13,6 +13,7 @@ import {
13
13
  toPerpsMarketDisplay,
14
14
  WsProviderBase,
15
15
  type WsProviderFactory,
16
+ type WsProviderFactoryParams,
16
17
  wsLog,
17
18
  } from '@lifi/perps-sdk'
18
19
  import {
@@ -159,7 +160,7 @@ export interface LighterWsProviderOptions {
159
160
  }
160
161
 
161
162
  /**
162
- * Lighter realtime WS provider (extends {@link WsProviderBase}): subscribes to
163
+ * Lighter WebSocket provider (extends {@link WsProviderBase}): subscribes to
163
164
  * Lighter's WS channels (orderbook, marketsContext, orders, positions), attaching auth
164
165
  * tokens to gated channels. Construct via {@link lighterWsProvider}.
165
166
  *
@@ -257,14 +258,6 @@ export class LighterWsProvider extends WsProviderBase<SubState> {
257
258
  }
258
259
 
259
260
  protected async openChannel(sub: Subscription): Promise<() => void> {
260
- // Lighter has no live OHLC channel — there's nothing to subscribe to.
261
- // Return a no-op unsubscribe so the caller's UX (chart still rendering
262
- // from REST history + price-tick mid line) is unaffected, instead of
263
- // throwing and surfacing a console error on every chart mount.
264
- if (sub.channel === 'candle') {
265
- return () => {}
266
- }
267
-
268
261
  // Only the auth channels (orders/fills/positions) resolve markets.
269
262
  // `marketsContext`/`orderbook` are keyed purely by `String(market_id)`, so
270
263
  // gating them on the registry sync would let a failed `/markets` fetch kill
@@ -377,10 +370,7 @@ export class LighterWsProvider extends WsProviderBase<SubState> {
377
370
  return `positions:${sub.address.toLowerCase()}`
378
371
  case 'accountSummary':
379
372
  return `accountSummary:${sub.address.toLowerCase()}`
380
- // No live wire sub (openChannel returns a no-op), but a stable key is
381
- // still needed so the base's fan-out registry can track/release it.
382
373
  case 'candle':
383
- return `candle:${sub.marketId}:${sub.interval}`
384
374
  case 'spotBalances':
385
375
  throw new Error(`Lighter WS does not support channel: ${sub.channel}.`)
386
376
  }
@@ -1006,7 +996,11 @@ function collectAuthChannelItems<T>(
1006
996
  *
1007
997
  * @public
1008
998
  */
1009
- export const lighterWsProvider =
1010
- (options?: LighterWsProviderOptions): WsProviderFactory =>
1011
- ({ provider, wsUrl, client }) =>
1012
- new LighterWsProvider(wsUrl, provider, options, client)
999
+ export const lighterWsProvider = (
1000
+ options?: LighterWsProviderOptions
1001
+ ): WsProviderFactory =>
1002
+ Object.assign(
1003
+ ({ provider, wsUrl, client }: WsProviderFactoryParams) =>
1004
+ new LighterWsProvider(wsUrl, provider, options, client),
1005
+ { streamsCandles: false }
1006
+ )