@lifi/perps-sdk 0.0.0-preview-2edcdb1 → 0.0.0-preview-5111896

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 (66) hide show
  1. package/dist/cjs/services/resolveSubscribeQuote.d.ts.map +1 -1
  2. package/dist/cjs/services/resolveSubscribeQuote.js +33 -19
  3. package/dist/cjs/services/resolveSubscribeQuote.js.map +1 -1
  4. package/dist/cjs/transport/fetchWithRetry.d.ts +0 -1
  5. package/dist/cjs/transport/fetchWithRetry.d.ts.map +1 -1
  6. package/dist/cjs/transport/fetchWithRetry.js +1 -8
  7. package/dist/cjs/transport/fetchWithRetry.js.map +1 -1
  8. package/dist/cjs/transport/request.d.ts.map +1 -1
  9. package/dist/cjs/transport/request.js +0 -3
  10. package/dist/cjs/transport/request.js.map +1 -1
  11. package/dist/cjs/utils/sleep.d.ts +1 -1
  12. package/dist/cjs/utils/sleep.d.ts.map +1 -1
  13. package/dist/cjs/utils/sleep.js +1 -16
  14. package/dist/cjs/utils/sleep.js.map +1 -1
  15. package/dist/cjs/version.d.ts +1 -1
  16. package/dist/cjs/version.js +1 -1
  17. package/dist/cjs/websocket/PerpsWsClient.d.ts +2 -0
  18. package/dist/cjs/websocket/PerpsWsClient.d.ts.map +1 -1
  19. package/dist/cjs/websocket/PerpsWsClient.js +9 -0
  20. package/dist/cjs/websocket/PerpsWsClient.js.map +1 -1
  21. package/dist/cjs/websocket/WsProviderBase.d.ts.map +1 -1
  22. package/dist/cjs/websocket/WsProviderBase.js +4 -1
  23. package/dist/cjs/websocket/WsProviderBase.js.map +1 -1
  24. package/dist/esm/services/resolveSubscribeQuote.d.ts +9 -8
  25. package/dist/esm/services/resolveSubscribeQuote.d.ts.map +1 -1
  26. package/dist/esm/services/resolveSubscribeQuote.js +44 -27
  27. package/dist/esm/services/resolveSubscribeQuote.js.map +1 -1
  28. package/dist/esm/transport/fetchWithRetry.d.ts +1 -11
  29. package/dist/esm/transport/fetchWithRetry.d.ts.map +1 -1
  30. package/dist/esm/transport/fetchWithRetry.js +2 -17
  31. package/dist/esm/transport/fetchWithRetry.js.map +1 -1
  32. package/dist/esm/transport/request.d.ts.map +1 -1
  33. package/dist/esm/transport/request.js +1 -4
  34. package/dist/esm/transport/request.js.map +1 -1
  35. package/dist/esm/utils/sleep.d.ts +2 -3
  36. package/dist/esm/utils/sleep.d.ts.map +1 -1
  37. package/dist/esm/utils/sleep.js +2 -18
  38. package/dist/esm/utils/sleep.js.map +1 -1
  39. package/dist/esm/version.d.ts +1 -1
  40. package/dist/esm/version.js +1 -1
  41. package/dist/esm/websocket/PerpsWsClient.d.ts +5 -0
  42. package/dist/esm/websocket/PerpsWsClient.d.ts.map +1 -1
  43. package/dist/esm/websocket/PerpsWsClient.js +12 -0
  44. package/dist/esm/websocket/PerpsWsClient.js.map +1 -1
  45. package/dist/esm/websocket/WsProviderBase.d.ts.map +1 -1
  46. package/dist/esm/websocket/WsProviderBase.js +9 -1
  47. package/dist/esm/websocket/WsProviderBase.js.map +1 -1
  48. package/dist/types/services/resolveSubscribeQuote.d.ts +9 -8
  49. package/dist/types/services/resolveSubscribeQuote.d.ts.map +1 -1
  50. package/dist/types/transport/fetchWithRetry.d.ts +1 -11
  51. package/dist/types/transport/fetchWithRetry.d.ts.map +1 -1
  52. package/dist/types/transport/request.d.ts.map +1 -1
  53. package/dist/types/utils/sleep.d.ts +2 -3
  54. package/dist/types/utils/sleep.d.ts.map +1 -1
  55. package/dist/types/version.d.ts +1 -1
  56. package/dist/types/websocket/PerpsWsClient.d.ts +5 -0
  57. package/dist/types/websocket/PerpsWsClient.d.ts.map +1 -1
  58. package/dist/types/websocket/WsProviderBase.d.ts.map +1 -1
  59. package/package.json +2 -2
  60. package/src/services/resolveSubscribeQuote.ts +56 -28
  61. package/src/transport/fetchWithRetry.ts +2 -18
  62. package/src/transport/request.ts +1 -5
  63. package/src/utils/sleep.ts +3 -19
  64. package/src/version.ts +1 -1
  65. package/src/websocket/PerpsWsClient.ts +17 -0
  66. package/src/websocket/WsProviderBase.ts +9 -1
@@ -12,25 +12,12 @@ export interface FetchWithRetryOptions {
12
12
  signal?: AbortSignal
13
13
  }
14
14
 
15
- /**
16
- * True when `error` is an `AbortSignal` cancellation (the native `fetch` abort
17
- * rejection) rather than a genuine network failure. An abort is a deliberate
18
- * caller action, so it is rethrown untouched instead of being retried.
19
- *
20
- * @internal
21
- */
22
- export function isAbortError(error: unknown): boolean {
23
- return error instanceof Error && error.name === 'AbortError'
24
- }
25
-
26
15
  /**
27
16
  * Wrap `fetch` with policy-driven retry. Honors `Retry-After` (when present
28
17
  * and `respectRetryAfter` is true), otherwise falls back to exponential
29
18
  * backoff with full jitter, capped by `maxDelayMs`. Network errors (thrown
30
19
  * `fetch` rejections) are treated as `retry-network` — same retry budget as
31
- * 5xx. Aborts (a pre-aborted signal, a mid-flight abort rejection, or a signal
32
- * that fires during a between-retries backoff) reject with the abort reason
33
- * without any further attempt.
20
+ * 5xx. An aborted signal short-circuits without further attempts.
34
21
  *
35
22
  * @public
36
23
  */
@@ -53,9 +40,6 @@ export async function fetchWithRetry(
53
40
  try {
54
41
  response = await fetchImpl(input, mergedInit)
55
42
  } catch (error) {
56
- if (isAbortError(error)) {
57
- throw error
58
- }
59
43
  networkError = error
60
44
  }
61
45
 
@@ -94,7 +78,7 @@ export async function fetchWithRetry(
94
78
 
95
79
  const delayMs = computeDelay(policy, attempt, response)
96
80
  if (delayMs > 0) {
97
- await sleep(delayMs, signal)
81
+ await sleep(delayMs)
98
82
  }
99
83
  attempt++
100
84
  }
@@ -3,7 +3,7 @@ import { PerpsErrorCode } from '@lifi/perps-types'
3
3
  import { PerpsError } from '../errors/PerpsError.js'
4
4
  import type { PerpsBaseConfig, SDKRequestOptions } from '../types/config.js'
5
5
  import { version } from '../version.js'
6
- import { fetchWithRetry, isAbortError } from './fetchWithRetry.js'
6
+ import { fetchWithRetry } from './fetchWithRetry.js'
7
7
  import {
8
8
  LIFI_REQUEST_KEY,
9
9
  LIFI_RETRY_DEFAULTS,
@@ -94,10 +94,6 @@ export async function request<T>(
94
94
  throw error
95
95
  }
96
96
 
97
- if (isAbortError(error)) {
98
- throw error
99
- }
100
-
101
97
  throw new PerpsError(
102
98
  PerpsErrorCode.ServerError,
103
99
  error instanceof Error ? error.message : 'Request failed'
@@ -1,23 +1,7 @@
1
1
  /**
2
- * Resolve after `ms` milliseconds, or reject with the signal's abort reason if
3
- * `signal` aborts first. Without a `signal` it always resolves.
2
+ * Resolve after `ms` milliseconds.
4
3
  *
5
4
  * @internal
6
5
  */
7
- export const sleep = (ms: number, signal?: AbortSignal): Promise<void> =>
8
- new Promise((resolve, reject) => {
9
- if (signal?.aborted) {
10
- reject(signal.reason ?? new DOMException('Aborted', 'AbortError'))
11
- return
12
- }
13
- let timer: ReturnType<typeof setTimeout>
14
- const onAbort = () => {
15
- clearTimeout(timer)
16
- reject(signal?.reason ?? new DOMException('Aborted', 'AbortError'))
17
- }
18
- timer = setTimeout(() => {
19
- signal?.removeEventListener('abort', onAbort)
20
- resolve()
21
- }, ms)
22
- signal?.addEventListener('abort', onAbort, { once: true })
23
- })
6
+ export const sleep = (ms: number): Promise<void> =>
7
+ new Promise((resolve) => setTimeout(resolve, ms))
package/src/version.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  export const name = '@lifi/perps-sdk'
2
- export const version = '0.0.0-preview-2edcdb1'
2
+ export const version = '0.0.0-preview-5111896'
@@ -65,6 +65,7 @@ export class PerpsWsClient {
65
65
  private readonly options: PerpsWsClientOptions
66
66
  private providers = new Map<string, WsProvider>()
67
67
  private initPromises = new Map<string, Promise<WsProvider>>()
68
+ private closed = false
68
69
 
69
70
  constructor(client: PerpsSDKClient, options: PerpsWsClientOptions = {}) {
70
71
  this.client = client
@@ -124,10 +125,14 @@ export class PerpsWsClient {
124
125
 
125
126
  /**
126
127
  * Close every open provider WS connection and drop all cached providers.
128
+ * Terminal: after `close()` the client is dead — `subscribe` and
129
+ * `subscribeQuote` reject, and any provider init still suspended mid-flight
130
+ * aborts without opening a socket. Create a new instance to subscribe again.
127
131
  *
128
132
  * @public
129
133
  */
130
134
  close() {
135
+ this.closed = true
131
136
  for (const p of this.providers.values()) {
132
137
  p.close()
133
138
  }
@@ -145,7 +150,18 @@ export class PerpsWsClient {
145
150
  this.providers.get(provider)?.reconnect()
146
151
  }
147
152
 
153
+ private assertOpen(): void {
154
+ if (this.closed) {
155
+ throw new PerpsError(
156
+ PerpsErrorCode.SDKError,
157
+ 'PerpsWsClient is closed. Create a new instance to subscribe again.'
158
+ )
159
+ }
160
+ }
161
+
148
162
  private async getOrCreateProvider(provider: string): Promise<WsProvider> {
163
+ this.assertOpen()
164
+
149
165
  const existing = this.providers.get(provider)
150
166
  if (existing) {
151
167
  return existing
@@ -175,6 +191,7 @@ export class PerpsWsClient {
175
191
  }
176
192
 
177
193
  const { providers } = await getProviders(this.client)
194
+ this.assertOpen()
178
195
 
179
196
  const providerInfo = providers.find((d) => d.key === provider)
180
197
  if (!providerInfo?.wsUrl) {
@@ -188,7 +188,15 @@ export abstract class WsProviderBase<TSub = unknown> implements WsProvider {
188
188
  }
189
189
 
190
190
  private async replaySubs(): Promise<void> {
191
- for (const [key, state] of this.wireSubs) {
191
+ // Snapshot at replay start, and re-check the live registry before each
192
+ // send. An async sendSubscribe (e.g. Lighter's auth-token fetch) suspends
193
+ // the loop; status is already 'connected' while open listeners run, so a
194
+ // subscribe landing mid-replay is sent inline by registerSub — it must not
195
+ // be revisited here, and an entry unregistered mid-replay must be skipped.
196
+ for (const [key, state] of [...this.wireSubs]) {
197
+ if (this.wireSubs.get(key) !== state) {
198
+ continue
199
+ }
192
200
  // Isolate each resubscribe: a send can reject (e.g. an auth-token fetch
193
201
  // after reconnect), and one sub's failure must not abort the rest of
194
202
  // the loop or escape as an unhandled rejection.