@lifi/perps-sdk 12.1.0 → 14.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 (130) hide show
  1. package/README.md +7 -5
  2. package/dist/cjs/client/PerpsClient.d.ts +8 -3
  3. package/dist/cjs/client/PerpsClient.d.ts.map +1 -1
  4. package/dist/cjs/client/PerpsClient.js +15 -0
  5. package/dist/cjs/client/PerpsClient.js.map +1 -1
  6. package/dist/cjs/index.d.ts +6 -5
  7. package/dist/cjs/index.d.ts.map +1 -1
  8. package/dist/cjs/index.js +10 -3
  9. package/dist/cjs/index.js.map +1 -1
  10. package/dist/cjs/registry/assetRegistry.d.ts +2 -0
  11. package/dist/cjs/registry/assetRegistry.d.ts.map +1 -1
  12. package/dist/cjs/registry/assetRegistry.js +18 -1
  13. package/dist/cjs/registry/assetRegistry.js.map +1 -1
  14. package/dist/cjs/registry/referenceDataRegistry.d.ts +5 -2
  15. package/dist/cjs/registry/referenceDataRegistry.d.ts.map +1 -1
  16. package/dist/cjs/registry/referenceDataRegistry.js +37 -7
  17. package/dist/cjs/registry/referenceDataRegistry.js.map +1 -1
  18. package/dist/cjs/services/getOrders.d.ts +2 -1
  19. package/dist/cjs/services/getOrders.d.ts.map +1 -1
  20. package/dist/cjs/services/getOrders.js +2 -0
  21. package/dist/cjs/services/getOrders.js.map +1 -1
  22. package/dist/cjs/transport/fetchWithRetry.d.ts.map +1 -1
  23. package/dist/cjs/transport/fetchWithRetry.js.map +1 -1
  24. package/dist/cjs/types/api.d.ts +6 -1
  25. package/dist/cjs/types/api.d.ts.map +1 -1
  26. package/dist/cjs/types/provider.d.ts +7 -6
  27. package/dist/cjs/types/provider.d.ts.map +1 -1
  28. package/dist/cjs/utils/orderClassification.d.ts +9 -5
  29. package/dist/cjs/utils/orderClassification.d.ts.map +1 -1
  30. package/dist/cjs/utils/orderClassification.js +19 -0
  31. package/dist/cjs/utils/orderClassification.js.map +1 -1
  32. package/dist/cjs/utils/orderMath.d.ts +2 -2
  33. package/dist/cjs/utils/orderMath.d.ts.map +1 -1
  34. package/dist/cjs/utils/orderMath.js +15 -4
  35. package/dist/cjs/utils/orderMath.js.map +1 -1
  36. package/dist/cjs/utils/warnOnce.d.ts +2 -0
  37. package/dist/cjs/utils/warnOnce.d.ts.map +1 -0
  38. package/dist/cjs/utils/warnOnce.js +22 -0
  39. package/dist/cjs/utils/warnOnce.js.map +1 -0
  40. package/dist/cjs/version.d.ts +1 -1
  41. package/dist/cjs/version.js +1 -1
  42. package/dist/cjs/websocket/PerpsWsClient.d.ts +7 -2
  43. package/dist/cjs/websocket/PerpsWsClient.d.ts.map +1 -1
  44. package/dist/cjs/websocket/PerpsWsClient.js +3 -0
  45. package/dist/cjs/websocket/PerpsWsClient.js.map +1 -1
  46. package/dist/esm/client/PerpsClient.d.ts +18 -3
  47. package/dist/esm/client/PerpsClient.d.ts.map +1 -1
  48. package/dist/esm/client/PerpsClient.js +25 -0
  49. package/dist/esm/client/PerpsClient.js.map +1 -1
  50. package/dist/esm/index.d.ts +6 -5
  51. package/dist/esm/index.d.ts.map +1 -1
  52. package/dist/esm/index.js +3 -2
  53. package/dist/esm/index.js.map +1 -1
  54. package/dist/esm/registry/assetRegistry.d.ts +5 -8
  55. package/dist/esm/registry/assetRegistry.d.ts.map +1 -1
  56. package/dist/esm/registry/assetRegistry.js +21 -9
  57. package/dist/esm/registry/assetRegistry.js.map +1 -1
  58. package/dist/esm/registry/referenceDataRegistry.d.ts +6 -14
  59. package/dist/esm/registry/referenceDataRegistry.d.ts.map +1 -1
  60. package/dist/esm/registry/referenceDataRegistry.js +38 -19
  61. package/dist/esm/registry/referenceDataRegistry.js.map +1 -1
  62. package/dist/esm/services/getOrders.d.ts +3 -17
  63. package/dist/esm/services/getOrders.d.ts.map +1 -1
  64. package/dist/esm/services/getOrders.js +3 -16
  65. package/dist/esm/services/getOrders.js.map +1 -1
  66. package/dist/esm/transport/fetchWithRetry.d.ts +3 -2
  67. package/dist/esm/transport/fetchWithRetry.d.ts.map +1 -1
  68. package/dist/esm/transport/fetchWithRetry.js +3 -2
  69. package/dist/esm/transport/fetchWithRetry.js.map +1 -1
  70. package/dist/esm/types/api.d.ts +13 -3
  71. package/dist/esm/types/api.d.ts.map +1 -1
  72. package/dist/esm/types/provider.d.ts +16 -16
  73. package/dist/esm/types/provider.d.ts.map +1 -1
  74. package/dist/esm/utils/orderClassification.d.ts +14 -19
  75. package/dist/esm/utils/orderClassification.d.ts.map +1 -1
  76. package/dist/esm/utils/orderClassification.js +21 -15
  77. package/dist/esm/utils/orderClassification.js.map +1 -1
  78. package/dist/esm/utils/orderMath.d.ts +3 -13
  79. package/dist/esm/utils/orderMath.d.ts.map +1 -1
  80. package/dist/esm/utils/orderMath.js +17 -16
  81. package/dist/esm/utils/orderMath.js.map +1 -1
  82. package/dist/esm/utils/warnOnce.d.ts +9 -0
  83. package/dist/esm/utils/warnOnce.d.ts.map +1 -0
  84. package/dist/esm/utils/warnOnce.js +29 -0
  85. package/dist/esm/utils/warnOnce.js.map +1 -0
  86. package/dist/esm/version.d.ts +1 -1
  87. package/dist/esm/version.js +1 -1
  88. package/dist/esm/websocket/PerpsWsClient.d.ts +25 -6
  89. package/dist/esm/websocket/PerpsWsClient.d.ts.map +1 -1
  90. package/dist/esm/websocket/PerpsWsClient.js +13 -2
  91. package/dist/esm/websocket/PerpsWsClient.js.map +1 -1
  92. package/dist/types/client/PerpsClient.d.ts +18 -3
  93. package/dist/types/client/PerpsClient.d.ts.map +1 -1
  94. package/dist/types/index.d.ts +6 -5
  95. package/dist/types/index.d.ts.map +1 -1
  96. package/dist/types/registry/assetRegistry.d.ts +5 -8
  97. package/dist/types/registry/assetRegistry.d.ts.map +1 -1
  98. package/dist/types/registry/referenceDataRegistry.d.ts +6 -14
  99. package/dist/types/registry/referenceDataRegistry.d.ts.map +1 -1
  100. package/dist/types/services/getOrders.d.ts +3 -17
  101. package/dist/types/services/getOrders.d.ts.map +1 -1
  102. package/dist/types/transport/fetchWithRetry.d.ts +3 -2
  103. package/dist/types/transport/fetchWithRetry.d.ts.map +1 -1
  104. package/dist/types/types/api.d.ts +13 -3
  105. package/dist/types/types/api.d.ts.map +1 -1
  106. package/dist/types/types/provider.d.ts +16 -16
  107. package/dist/types/types/provider.d.ts.map +1 -1
  108. package/dist/types/utils/orderClassification.d.ts +14 -19
  109. package/dist/types/utils/orderClassification.d.ts.map +1 -1
  110. package/dist/types/utils/orderMath.d.ts +3 -13
  111. package/dist/types/utils/orderMath.d.ts.map +1 -1
  112. package/dist/types/utils/warnOnce.d.ts +9 -0
  113. package/dist/types/utils/warnOnce.d.ts.map +1 -0
  114. package/dist/types/version.d.ts +1 -1
  115. package/dist/types/websocket/PerpsWsClient.d.ts +25 -6
  116. package/dist/types/websocket/PerpsWsClient.d.ts.map +1 -1
  117. package/package.json +2 -2
  118. package/src/client/PerpsClient.ts +58 -1
  119. package/src/index.ts +9 -2
  120. package/src/registry/assetRegistry.ts +29 -9
  121. package/src/registry/referenceDataRegistry.ts +46 -19
  122. package/src/services/getOrders.ts +5 -17
  123. package/src/transport/fetchWithRetry.ts +3 -2
  124. package/src/types/api.ts +14 -2
  125. package/src/types/provider.ts +23 -21
  126. package/src/utils/orderClassification.ts +37 -19
  127. package/src/utils/orderMath.ts +25 -17
  128. package/src/utils/warnOnce.ts +29 -0
  129. package/src/version.ts +1 -1
  130. package/src/websocket/PerpsWsClient.ts +29 -6
@@ -3,12 +3,11 @@ import type { GetQuoteParams } from '../services/getQuote.js';
3
3
  import type { PerpsSDKClient, QuoteListener } from '../types/provider.js';
4
4
  import type { EventForSubscription, WsProvider, WsStatusListener } from './types.js';
5
5
  /**
6
- * Factory for a per-provider WS plugin. Invoked once per provider key the
7
- * first time `subscribe(...)` is called against it.
6
+ * Call parameters of a {@link WsProviderFactory}.
8
7
  *
9
8
  * @public
10
9
  */
11
- export type WsProviderFactory = (params: {
10
+ export interface WsProviderFactoryParams {
12
11
  provider: string;
13
12
  /** WS URL discovered from `/providers`. */
14
13
  wsUrl: string;
@@ -25,7 +24,18 @@ export type WsProviderFactory = (params: {
25
24
  * duplicating backend orchestration in the WS layer.
26
25
  */
27
26
  client: PerpsSDKClient;
28
- }) => WsProvider;
27
+ }
28
+ /**
29
+ * Factory for a per-provider WS plugin. Invoked once per provider key the
30
+ * first time `subscribe(...)` is called against it.
31
+ *
32
+ * @public
33
+ */
34
+ export interface WsProviderFactory {
35
+ (params: WsProviderFactoryParams): WsProvider;
36
+ /** `true` when the venue socket serves the `candle` channel. */
37
+ readonly streamsCandles: boolean;
38
+ }
29
39
  /**
30
40
  * Options for {@link PerpsWsClient}.
31
41
  *
@@ -43,7 +53,7 @@ export interface PerpsWsClientOptions {
43
53
  wsProviders?: Record<string, WsProviderFactory>;
44
54
  }
45
55
  /**
46
- * Realtime client: lazily instantiates a per-provider {@link WsProvider} on
56
+ * WebSocket client: lazily instantiates a per-provider {@link WsProvider} on
47
57
  * first subscription and fans subscriptions out to it.
48
58
  *
49
59
  * @public
@@ -56,7 +66,16 @@ export declare class PerpsWsClient {
56
66
  private closed;
57
67
  constructor(client: PerpsSDKClient, options?: PerpsWsClientOptions);
58
68
  /**
59
- * Subscribe to a realtime channel, lazily creating the provider's WS
69
+ * Whether `provider`'s socket serves the `candle` channel, as reported by
70
+ * its registered factory. Returns `false` when no factory is registered.
71
+ * Synchronous: it reads the factory without instantiating the provider and
72
+ * makes no network call, so a caller can branch before the first subscribe.
73
+ *
74
+ * @public
75
+ */
76
+ streamsCandles(provider: string): boolean;
77
+ /**
78
+ * Subscribe to a WebSocket channel, lazily creating the provider's WS
60
79
  * connection. Returns an unsubscribe function.
61
80
  *
62
81
  * @param onStatus - Optional listener for the underlying connection's
@@ -1 +1 @@
1
- {"version":3,"file":"PerpsWsClient.d.ts","sourceRoot":"","sources":["../../../src/websocket/PerpsWsClient.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAGrE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAEzE,OAAO,KAAK,EACV,oBAAoB,EAEpB,UAAU,EACV,gBAAgB,EACjB,MAAM,YAAY,CAAA;AAEnB;;;;;GAKG;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,MAAM,EAAE;IACvC,QAAQ,EAAE,MAAM,CAAA;IAChB,2CAA2C;IAC3C,KAAK,EAAE,MAAM,CAAA;IACb;;;;;OAKG;IACH,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB;;;;OAIG;IACH,MAAM,EAAE,cAAc,CAAA;CACvB,KAAK,UAAU,CAAA;AAEhB;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACnC;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAA;CAChD;AAED;;;;;GAKG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsB;IAC9C,OAAO,CAAC,SAAS,CAAgC;IACjD,OAAO,CAAC,YAAY,CAAyC;IAC7D,OAAO,CAAC,MAAM,CAAQ;gBAEV,MAAM,EAAE,cAAc,EAAE,OAAO,GAAE,oBAAyB;IAKtE;;;;;;;;;;;;OAYG;IACG,SAAS,CAAC,CAAC,SAAS,YAAY,EACpC,GAAG,EAAE,CAAC,EACN,QAAQ,EAAE,CAAC,KAAK,EAAE,oBAAoB,CAAC,CAAC,CAAC,KAAK,IAAI,EAClD,QAAQ,CAAC,EAAE,gBAAgB,GAC1B,OAAO,CAAC,MAAM,IAAI,CAAC;IAOtB;;;;;;;;;;OAUG;IACG,cAAc,CAClB,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,MAAM,IAAI,CAAC;IAatB;;;;;;;OAOG;IACH,KAAK;IASL;;;;;OAKG;IACH,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAIjC,OAAO,CAAC,UAAU;YASJ,mBAAmB;YAqBnB,YAAY;CAsC3B"}
1
+ {"version":3,"file":"PerpsWsClient.d.ts","sourceRoot":"","sources":["../../../src/websocket/PerpsWsClient.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAGrE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAEzE,OAAO,KAAK,EACV,oBAAoB,EAEpB,UAAU,EACV,gBAAgB,EACjB,MAAM,YAAY,CAAA;AAEnB;;;;GAIG;AACH,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,MAAM,CAAA;IAChB,2CAA2C;IAC3C,KAAK,EAAE,MAAM,CAAA;IACb;;;;;OAKG;IACH,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB;;;;OAIG;IACH,MAAM,EAAE,cAAc,CAAA;CACvB;AAED;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,CAAC,MAAM,EAAE,uBAAuB,GAAG,UAAU,CAAA;IAC7C,gEAAgE;IAChE,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAA;CACjC;AAED;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACnC;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAA;CAChD;AAED;;;;;GAKG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsB;IAC9C,OAAO,CAAC,SAAS,CAAgC;IACjD,OAAO,CAAC,YAAY,CAAyC;IAC7D,OAAO,CAAC,MAAM,CAAQ;gBAEV,MAAM,EAAE,cAAc,EAAE,OAAO,GAAE,oBAAyB;IAKtE;;;;;;;OAOG;IACH,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAIzC;;;;;;;;;;;;OAYG;IACG,SAAS,CAAC,CAAC,SAAS,YAAY,EACpC,GAAG,EAAE,CAAC,EACN,QAAQ,EAAE,CAAC,KAAK,EAAE,oBAAoB,CAAC,CAAC,CAAC,KAAK,IAAI,EAClD,QAAQ,CAAC,EAAE,gBAAgB,GAC1B,OAAO,CAAC,MAAM,IAAI,CAAC;IAOtB;;;;;;;;;;OAUG;IACG,cAAc,CAClB,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,MAAM,IAAI,CAAC;IAatB;;;;;;;OAOG;IACH,KAAK;IASL;;;;;OAKG;IACH,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAIjC,OAAO,CAAC,UAAU;YASJ,mBAAmB;YAqBnB,YAAY;CAsC3B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lifi/perps-sdk",
3
- "version": "12.1.0",
3
+ "version": "14.0.0",
4
4
  "description": "LI.FI Perps SDK for perpetuals trading",
5
5
  "homepage": "https://github.com/lifinance/perps-sdk",
6
6
  "bugs": {
@@ -46,7 +46,7 @@
46
46
  "big.js": "^7.0.1",
47
47
  "partysocket": "^1.1.19",
48
48
  "viem": "^2.55.18",
49
- "@lifi/perps-types": "^12.0.1"
49
+ "@lifi/perps-types": "^13.0.0"
50
50
  },
51
51
  "publishConfig": {
52
52
  "access": "public"
@@ -9,6 +9,9 @@ import type {
9
9
  MarketRef,
10
10
  MarketSettings,
11
11
  MetaActionType,
12
+ Order,
13
+ OrdersResponse,
14
+ PortfolioHistoryResponse,
12
15
  Position,
13
16
  PositionMarginConstraints,
14
17
  Provider,
@@ -29,6 +32,14 @@ import { getAssetRegistry } from '../registry/assetRegistry.js'
29
32
  import { createAction } from '../services/createAction.js'
30
33
  import { executeAction } from '../services/executeAction.js'
31
34
  import { getAccount as fetchAccount } from '../services/getAccount.js'
35
+ import {
36
+ getOrder as fetchOrder,
37
+ type GetOrderParams,
38
+ } from '../services/getOrder.js'
39
+ import {
40
+ getOrders as fetchOrders,
41
+ type GetOrdersParams,
42
+ } from '../services/getOrders.js'
32
43
  import { getProviders } from '../services/getProviders.js'
33
44
  import type {
34
45
  BuildProviderSetupParams,
@@ -40,6 +51,7 @@ import type {
40
51
  ExecuteProviderSetupResult,
41
52
  GetAccountResult,
42
53
  GetDepositFlowParams,
54
+ GetPortfolioHistoryParams,
43
55
  GetSetupParams,
44
56
  GetWithdrawableBalancesParams,
45
57
  ModifyOrdersParams,
@@ -52,7 +64,11 @@ import type {
52
64
  SubmitOnboardingParams,
53
65
  WithdrawParams,
54
66
  } from '../types/api.js'
55
- import type { PerpsClientSigner, SwitchChainHook } from '../types/config.js'
67
+ import type {
68
+ PerpsClientSigner,
69
+ SDKRequestOptions,
70
+ SwitchChainHook,
71
+ } from '../types/config.js'
56
72
  import type { DepositFlow } from '../types/deposit.js'
57
73
  import type {
58
74
  ActionSignerContribution,
@@ -184,6 +200,22 @@ export class PerpsClient {
184
200
  return resolveProvider(this.sdkClient, provider)
185
201
  }
186
202
 
203
+ /** Read active or historical orders from the selected venue. */
204
+ async getOrders(
205
+ params: GetOrdersParams,
206
+ options?: SDKRequestOptions
207
+ ): Promise<OrdersResponse> {
208
+ return fetchOrders(this.sdkClient, params, options)
209
+ }
210
+
211
+ /** Read one venue order through the provider's unified mapper. */
212
+ async getOrder(
213
+ params: GetOrderParams,
214
+ options?: SDKRequestOptions
215
+ ): Promise<Order> {
216
+ return fetchOrder(this.sdkClient, params, options)
217
+ }
218
+
187
219
  /**
188
220
  * Ask the provider plugin for the signer-bearing wire fields of `action` —
189
221
  * the on-wire `signerAddress` and any signer-derived params (e.g.
@@ -579,6 +611,31 @@ export class PerpsClient {
579
611
  })
580
612
  }
581
613
 
614
+ /**
615
+ * The account's portfolio value and cumulative PnL over `params.range` at
616
+ * `params.provider`, read directly from the venue.
617
+ *
618
+ * @throws {PerpsError} When the provider plugin is not registered, when it
619
+ * declares no portfolio history read, or when the venue read fails.
620
+ * @public
621
+ */
622
+ async getPortfolioHistory(
623
+ params: GetPortfolioHistoryParams,
624
+ options?: SDKRequestOptions
625
+ ): Promise<PortfolioHistoryResponse> {
626
+ const plugin = this.requireProvider(params.provider)
627
+ if (typeof plugin.getPortfolioHistory !== 'function') {
628
+ throw new PerpsError(
629
+ PerpsErrorCode.SDKError,
630
+ `Provider '${params.provider}' does not implement getPortfolioHistory.`
631
+ )
632
+ }
633
+ return plugin.getPortfolioHistory(
634
+ { address: params.address, range: params.range },
635
+ options
636
+ )
637
+ }
638
+
582
639
  /**
583
640
  * Return the unsatisfied entries on `Provider.setup` for this account as a
584
641
  * flat, self-describing list. Trading is gated on `isReady === true`.
package/src/index.ts CHANGED
@@ -87,7 +87,7 @@ export { createMemoryStorage } from './storage/storage.js'
87
87
  export type { StorageAdapter } from './storage/types.js'
88
88
  export { errorCodeFromStatus } from './transport/errorCodeFromStatus.js'
89
89
  export type { FetchWithRetryOptions } from './transport/fetchWithRetry.js'
90
- export { fetchWithRetry } from './transport/fetchWithRetry.js'
90
+ export { fetchWithRetry, isAbortError } from './transport/fetchWithRetry.js'
91
91
  export type {
92
92
  ProviderRetryConfig,
93
93
  ResolvedRetryPolicy,
@@ -111,6 +111,7 @@ export type {
111
111
  ExecuteMetaActionParams,
112
112
  GetAccountResult,
113
113
  GetDepositFlowParams,
114
+ GetPortfolioHistoryParams,
114
115
  GetSetupParams,
115
116
  GetWithdrawableBalancesParams,
116
117
  ModifyOrdersParams,
@@ -156,9 +157,9 @@ export type {
156
157
  ProviderGetMarketSettingsParams,
157
158
  ProviderGetOrderParams,
158
159
  ProviderGetOrdersParams,
160
+ ProviderGetPortfolioHistoryParams,
159
161
  ProviderGetPositionsParams,
160
162
  ProviderGetQuoteParams,
161
- ProviderGetRunningTwapsParams,
162
163
  ProviderGetWithdrawableBalancesParams,
163
164
  QuoteListener,
164
165
  SignActionProgress,
@@ -220,9 +221,13 @@ export {
220
221
  classifyFill,
221
222
  FillClassification,
222
223
  isActiveOrderStatus,
224
+ isRegularOrder,
223
225
  isStopLossOrder,
224
226
  isTakeProfitOrder,
225
227
  isTpSlOrder,
228
+ isTriggerOrder,
229
+ isTwapOrder,
230
+ triggerConditionFor,
226
231
  } from './utils/orderClassification.js'
227
232
  export {
228
233
  expectedRealizedPnlForOpenOrder,
@@ -250,12 +255,14 @@ export type { RemovableIsolatedMarginParams } from './utils/transferMargin.js'
250
255
  export { removableIsolatedMargin } from './utils/transferMargin.js'
251
256
  export { fromBaseUnits, fromBaseUnitsNumber } from './utils/units.js'
252
257
  export { validateMargin } from './utils/validation.js'
258
+ export { createWarnOnce } from './utils/warnOnce.js'
253
259
  // Version
254
260
  export { name, version } from './version.js'
255
261
  export { cachePromise } from './websocket/cachePromise.js'
256
262
  export type {
257
263
  PerpsWsClientOptions,
258
264
  WsProviderFactory,
265
+ WsProviderFactoryParams,
259
266
  } from './websocket/PerpsWsClient.js'
260
267
  export { PerpsWsClient } from './websocket/PerpsWsClient.js'
261
268
  export type { ReconnectingWebSocketOptions } from './websocket/ReconnectingWebSocket.js'
@@ -1,19 +1,39 @@
1
1
  import type { Asset, AssetsResponse } from '@lifi/perps-types'
2
+ import { PerpsErrorCode } from '@lifi/perps-types'
3
+ import { PerpsError } from '../errors/PerpsError.js'
2
4
  import { buildUrl, request } from '../transport/request.js'
3
5
  import type { PerpsSDKClient } from '../types/provider.js'
4
6
  import { ReferenceDataRegistry } from './referenceDataRegistry.js'
5
7
 
6
- /**
7
- * Per-provider index over the backend's `/assets` token registry, keyed by
8
- * `Asset.id` — the provider-native asset id (Lighter: the stringified
9
- * `asset_id`, Hyperliquid spot: the venue token index). Obtain via
10
- * {@link getAssetRegistry}.
11
- *
12
- * @public
13
- */
8
+ const addressKey = (address: string): string =>
9
+ /^0x[0-9a-f]{40}$/i.test(address) ? address.toLowerCase() : address
10
+
11
+ /** Provider `/assets` index by native `id` and by L1 contract address. @public */
14
12
  export class AssetRegistry extends ReferenceDataRegistry<Asset> {
15
13
  constructor(client: PerpsSDKClient, provider: string) {
16
- super(client, provider, 'asset')
14
+ super(client, provider, 'asset', {
15
+ l1Address: (asset) =>
16
+ asset.l1Address === undefined ? undefined : addressKey(asset.l1Address),
17
+ })
18
+ }
19
+
20
+ /** Lookup by provider identity; hexadecimal L1 addresses are case-insensitive. */
21
+ override get(id: string, key: 'id' | 'l1Address' = 'id'): Asset | undefined {
22
+ return key === 'id' ? super.get(id) : this.getByIndex(addressKey(id), key)
23
+ }
24
+
25
+ /** Resolve registry membership or report a stale or mis-keyed asset registry. */
26
+ require(id: string, key: 'id' | 'l1Address' = 'id'): Asset {
27
+ const asset = this.get(id, key)
28
+ if (asset === undefined) {
29
+ const error = new PerpsError(
30
+ PerpsErrorCode.ValidationError,
31
+ `[${this.provider}] stale or mis-keyed asset registry: unknown ${key} '${id}'`
32
+ )
33
+ error.tool = this.provider
34
+ throw error
35
+ }
36
+ return asset
17
37
  }
18
38
 
19
39
  /**
@@ -1,27 +1,23 @@
1
+ import { PerpsErrorCode } from '@lifi/perps-types'
2
+ import { PerpsError } from '../errors/PerpsError.js'
1
3
  import type { PerpsSDKClient } from '../types/provider.js'
4
+ import { createWarnOnce } from '../utils/warnOnce.js'
2
5
 
3
- /**
4
- * Per-provider hash index over one of the provider's reference-data lists
5
- * (`/markets`, `/assets`), keyed by the list's own primary key.
6
- *
7
- * NOT a cache: it holds no freshness policy of its own. Every {@link sync}
8
- * refetches through the HTTP layer, whose `cache-control` headers decide
9
- * whether the response comes from disk or the network. A lookup miss warns
10
- * once per id and returns `undefined`; subsequent syncs reconcile the index
11
- * without replaying the warning for an id that remains absent.
12
- *
13
- * @internal
14
- */
6
+ /** Atomic provider reference indexes; HTTP cache headers govern freshness. @internal */
15
7
  export abstract class ReferenceDataRegistry<T> {
16
8
  private index = new Map<string, T>()
9
+ private secondaryIndexes = new Map<string, Map<string, T>>()
17
10
  private current: readonly T[] = []
18
11
  private inflight: Promise<readonly T[]> | undefined
19
- private warnedIds = new Set<string>()
12
+ private readonly warnOnce = createWarnOnce()
20
13
 
21
14
  protected constructor(
22
15
  protected readonly client: PerpsSDKClient,
23
16
  readonly provider: string,
24
- private readonly kind: string
17
+ private readonly kind: string,
18
+ private readonly secondaryKeys: Readonly<
19
+ Record<string, (item: T) => string | undefined>
20
+ > = {}
25
21
  ) {}
26
22
 
27
23
  /** Fetch the provider's full list through the HTTP layer. */
@@ -55,16 +51,47 @@ export abstract class ReferenceDataRegistry<T> {
55
51
  if (item !== undefined) {
56
52
  return item
57
53
  }
58
- if (!this.warnedIds.has(id)) {
59
- this.warnedIds.add(id)
60
- console.warn(`[${this.provider}] unknown ${this.kind} id '${id}'`)
61
- }
54
+ this.warnOnce(id, `[${this.provider}] unknown ${this.kind} id '${id}'`)
62
55
  return undefined
63
56
  }
64
57
 
58
+ protected getByIndex(id: string, key: string): T | undefined {
59
+ return this.secondaryIndexes.get(key)?.get(id)
60
+ }
61
+
65
62
  private async load(): Promise<readonly T[]> {
66
63
  const items = await this.fetchItems()
67
- this.index = new Map(items.map((item) => [this.keyOf(item), item]))
64
+ const index = new Map<string, T>()
65
+ for (const item of items) {
66
+ const key = this.keyOf(item)
67
+ if (index.has(key)) {
68
+ throw new PerpsError(
69
+ PerpsErrorCode.ValidationError,
70
+ `[${this.provider}] stale or mis-keyed ${this.kind} registry: duplicate id '${key}'`
71
+ )
72
+ }
73
+ index.set(key, item)
74
+ }
75
+ const secondaryIndexes = new Map<string, Map<string, T>>()
76
+ for (const [name, keyOf] of Object.entries(this.secondaryKeys)) {
77
+ const secondary = new Map<string, T>()
78
+ for (const item of items) {
79
+ const key = keyOf(item)
80
+ if (key === undefined) {
81
+ continue
82
+ }
83
+ if (secondary.has(key)) {
84
+ throw new PerpsError(
85
+ PerpsErrorCode.ValidationError,
86
+ `[${this.provider}] stale or mis-keyed ${this.kind} registry: duplicate ${name} '${key}'`
87
+ )
88
+ }
89
+ secondary.set(key, item)
90
+ }
91
+ secondaryIndexes.set(name, secondary)
92
+ }
93
+ this.index = index
94
+ this.secondaryIndexes = secondaryIndexes
68
95
  this.current = items
69
96
  return items
70
97
  }
@@ -1,8 +1,9 @@
1
- import type { OrdersResponse } from '@lifi/perps-types'
1
+ import type { OrderStatus, OrdersResponse } from '@lifi/perps-types'
2
2
  import type { Address } from 'viem'
3
3
  import { requireProvider } from '../client/requireProvider.js'
4
4
  import type { SDKRequestOptions } from '../types/config.js'
5
5
  import type { PerpsSDKClient } from '../types/provider.js'
6
+ import { ACTIVE_ORDER_STATUSES } from '../utils/orderClassification.js'
6
7
 
7
8
  /**
8
9
  * Parameters for {@link getOrders}.
@@ -12,6 +13,7 @@ import type { PerpsSDKClient } from '../types/provider.js'
12
13
  export interface GetOrdersParams {
13
14
  provider: string
14
15
  address: Address
16
+ statuses?: OrderStatus[]
15
17
  /** Optional opaque `Market.id` filter, not a display symbol. */
16
18
  marketId?: string
17
19
  /** Maximum items returned; provider defaults and caps apply. */
@@ -20,22 +22,7 @@ export interface GetOrdersParams {
20
22
  cursor?: string
21
23
  }
22
24
 
23
- /**
24
- * Get open orders and trigger orders for an account. Delegates to the
25
- * registered venue plugin (direct-to-venue); requires the provider plugin to be
26
- * registered on the client.
27
- *
28
- * @throws {PerpsError} When the provider plugin is not registered, or on
29
- * backend / network / parsing errors.
30
- * @example
31
- * ```ts
32
- * const { openOrders, triggerOrders } = await getOrders(client, {
33
- * provider: 'hyperliquid',
34
- * address: '0x1234...',
35
- * })
36
- * ```
37
- * @public
38
- */
25
+ /** Read account orders with active lifecycle statuses as the default filter. */
39
26
  export async function getOrders(
40
27
  client: PerpsSDKClient,
41
28
  params: GetOrdersParams,
@@ -44,6 +31,7 @@ export async function getOrders(
44
31
  return requireProvider(client, params.provider).getOrders(
45
32
  {
46
33
  address: params.address,
34
+ statuses: params.statuses ?? [...ACTIVE_ORDER_STATUSES],
47
35
  marketId: params.marketId,
48
36
  limit: params.limit,
49
37
  cursor: params.cursor,
@@ -18,9 +18,10 @@ export interface FetchWithRetryOptions {
18
18
  /**
19
19
  * True when `error` is an `AbortSignal` cancellation (the native `fetch` abort
20
20
  * rejection) rather than a genuine network failure. An abort is a deliberate
21
- * caller action, so it is rethrown untouched instead of being retried.
21
+ * caller action, so every transport rethrows it untouched instead of retrying
22
+ * it or wrapping it in a provider error.
22
23
  *
23
- * @internal
24
+ * @public
24
25
  */
25
26
  export function isAbortError(error: unknown): boolean {
26
27
  return error instanceof Error && error.name === 'AbortError'
package/src/types/api.ts CHANGED
@@ -14,6 +14,7 @@ import type {
14
14
  OnboardParams,
15
15
  OrderSide,
16
16
  OrderType,
17
+ PortfolioHistoryRange,
17
18
  ProviderAction,
18
19
  SignedActionStep,
19
20
  TimeInForce,
@@ -175,8 +176,8 @@ export interface PlaceOrderParams {
175
176
  }
176
177
 
177
178
  /**
178
- * Parameters for placing trigger-only orders (TP/SL on existing positions).
179
- * Sends a TRIGGER_ONLY order that skips the main order wire.
179
+ * Sends `ActionType.PLACE_TRIGGER_ORDER` with
180
+ * `{ market, side, takeProfit?, stopLoss? }`.
180
181
  *
181
182
  * @public
182
183
  */
@@ -298,6 +299,17 @@ export interface GetWithdrawableBalancesParams {
298
299
  address: Address
299
300
  }
300
301
 
302
+ /**
303
+ * Parameters for {@link PerpsClient.getPortfolioHistory}.
304
+ *
305
+ * @public
306
+ */
307
+ export interface GetPortfolioHistoryParams {
308
+ provider: string
309
+ address: Address
310
+ range: PortfolioHistoryRange
311
+ }
312
+
301
313
  /**
302
314
  * One entry on {@link ProviderSetup.checklist}: a user-facing setup
303
315
  * descriptor plus its satisfied state for the queried account.
@@ -13,9 +13,12 @@ import type {
13
13
  MarketRef,
14
14
  MarketSettings,
15
15
  Order,
16
+ OrderStatus,
16
17
  OrdersResponse,
17
18
  PerpsMarket,
18
19
  PerpsSigner,
20
+ PortfolioHistoryRange,
21
+ PortfolioHistoryResponse,
19
22
  Position,
20
23
  PositionMarginConstraints,
21
24
  PositionsResponse,
@@ -25,7 +28,6 @@ import type {
25
28
  SignedActionStep,
26
29
  SigningMethod,
27
30
  TradeType,
28
- TwapOrder,
29
31
  } from '@lifi/perps-types'
30
32
  import type { Address } from 'viem'
31
33
  import type {
@@ -221,6 +223,7 @@ export interface ProviderGetMarketSettingsParams {
221
223
  */
222
224
  export interface ProviderGetOrdersParams {
223
225
  address: Address
226
+ statuses?: OrderStatus[]
224
227
  /** Optional opaque `Market.id` filter (not a display symbol). */
225
228
  marketId?: string
226
229
  /** Maximum items returned; provider defaults and caps apply. */
@@ -229,17 +232,6 @@ export interface ProviderGetOrdersParams {
229
232
  cursor?: string
230
233
  }
231
234
 
232
- /**
233
- * Read params for {@link PerpsProvider.getRunningTwaps}.
234
- *
235
- * @public
236
- */
237
- export interface ProviderGetRunningTwapsParams {
238
- address: Address
239
- /** Optional opaque `Market.id` filter (not a display symbol). */
240
- marketId?: string
241
- }
242
-
243
235
  /**
244
236
  * Read params for {@link PerpsProvider.getOrder}.
245
237
  *
@@ -287,6 +279,16 @@ export interface ProviderGetActivityParams {
287
279
  type?: ActivityType[]
288
280
  }
289
281
 
282
+ /**
283
+ * Read params for {@link PerpsProvider.getPortfolioHistory}.
284
+ *
285
+ * @public
286
+ */
287
+ export interface ProviderGetPortfolioHistoryParams {
288
+ address: Address
289
+ range: PortfolioHistoryRange
290
+ }
291
+
290
292
  /**
291
293
  * Read params for {@link PerpsProviderPlugin.getQuote}. `provider` is implicit
292
294
  * in the provider instance and so is not duplicated here.
@@ -445,15 +447,6 @@ export interface PerpsProviderPlugin {
445
447
  options?: SDKRequestOptions
446
448
  ): Promise<OrdersResponse>
447
449
 
448
- /**
449
- * Fetch the account's currently running TWAP parent orders directly from the
450
- * venue. Child slice orders are excluded.
451
- */
452
- getRunningTwaps?(
453
- params: ProviderGetRunningTwapsParams,
454
- options?: SDKRequestOptions
455
- ): Promise<TwapOrder[]>
456
-
457
450
  getOrder(
458
451
  params: ProviderGetOrderParams,
459
452
  options?: SDKRequestOptions
@@ -469,6 +462,15 @@ export interface PerpsProviderPlugin {
469
462
  options?: SDKRequestOptions
470
463
  ): Promise<ActivitiesResponse>
471
464
 
465
+ /**
466
+ * Read the account's portfolio value and cumulative PnL over
467
+ * `params.range`, oldest point first, directly from the venue.
468
+ */
469
+ getPortfolioHistory?(
470
+ params: ProviderGetPortfolioHistoryParams,
471
+ options?: SDKRequestOptions
472
+ ): Promise<PortfolioHistoryResponse>
473
+
472
474
  /**
473
475
  * Produce a one-shot fill {@link Quote} for `params.symbol` at `params.size`
474
476
  * USD notional on this venue. The provider resolves the symbol against its
@@ -1,17 +1,15 @@
1
- /**
2
- * Order classification utilities.
3
- *
4
- * Type guards and classifiers that operate on SDK types to determine
5
- * order categories (TP/SL, open/close). These use the OrderType enum
6
- * for classification — no string matching.
7
- */
8
-
9
- import type { OpenOrder } from '@lifi/perps-types'
1
+ import type {
2
+ Order,
3
+ RegularOrder,
4
+ TriggerOrder,
5
+ TwapOrder,
6
+ } from '@lifi/perps-types'
10
7
  import {
11
8
  FillClassification,
12
9
  OrderSide,
13
10
  OrderStatus,
14
11
  OrderType,
12
+ TriggerCondition,
15
13
  } from '@lifi/perps-types'
16
14
  import { stringToFloat } from './parse.js'
17
15
 
@@ -36,7 +34,7 @@ const SL_TYPES = new Set<OrderType>([
36
34
  * Check if an open order is a Take Profit trigger order.
37
35
  * @public
38
36
  */
39
- export function isTakeProfitOrder(order: Pick<OpenOrder, 'type'>): boolean {
37
+ export function isTakeProfitOrder(order: Pick<Order, 'type'>): boolean {
40
38
  return TP_TYPES.has(order.type)
41
39
  }
42
40
 
@@ -44,7 +42,7 @@ export function isTakeProfitOrder(order: Pick<OpenOrder, 'type'>): boolean {
44
42
  * Check if an open order is a Stop Loss trigger order.
45
43
  * @public
46
44
  */
47
- export function isStopLossOrder(order: Pick<OpenOrder, 'type'>): boolean {
45
+ export function isStopLossOrder(order: Pick<Order, 'type'>): boolean {
48
46
  return SL_TYPES.has(order.type)
49
47
  }
50
48
 
@@ -52,17 +50,37 @@ export function isStopLossOrder(order: Pick<OpenOrder, 'type'>): boolean {
52
50
  * Check if an open order is a TP or SL trigger order.
53
51
  * @public
54
52
  */
55
- export function isTpSlOrder(order: Pick<OpenOrder, 'type'>): boolean {
53
+ export function isTpSlOrder(order: Pick<Order, 'type'>): boolean {
56
54
  return TP_TYPES.has(order.type) || SL_TYPES.has(order.type)
57
55
  }
58
56
 
59
- /**
60
- * Order statuses representing an order still resting on the book (visible
61
- * in `openOrders` / `triggerOrders`). Anything not in this set is terminal —
62
- * filled, cancelled, rejected, expired — and should be evicted from the
63
- * cached orders list when seen in a WS update.
64
- * @public
65
- */
57
+ /** Narrow an order to a price-activated order. */
58
+ export function isTriggerOrder(order: Order): order is TriggerOrder {
59
+ return isTpSlOrder(order)
60
+ }
61
+
62
+ /** Narrow an order to a market or limit order. */
63
+ export function isRegularOrder(order: Order): order is RegularOrder {
64
+ return order.type === OrderType.MARKET || order.type === OrderType.LIMIT
65
+ }
66
+
67
+ /** Narrow an order to a time-weighted execution parent. */
68
+ export function isTwapOrder(order: Order): order is TwapOrder {
69
+ return order.type === OrderType.TWAP
70
+ }
71
+
72
+ /** Derive the trigger price relation from the trigger type and execution side. */
73
+ export function triggerConditionFor(
74
+ type: TriggerOrder['type'],
75
+ side: OrderSide
76
+ ): TriggerCondition {
77
+ const takeProfit = TP_TYPES.has(type)
78
+ return takeProfit === (side === OrderSide.SELL)
79
+ ? TriggerCondition.ABOVE
80
+ : TriggerCondition.BELOW
81
+ }
82
+
83
+ /** Lifecycle statuses included in order reads by default. */
66
84
  export const ACTIVE_ORDER_STATUSES: ReadonlySet<OrderStatus> = new Set([
67
85
  OrderStatus.OPEN,
68
86
  OrderStatus.PENDING,