@gala-chain/launchpad-sdk 9.0.0-rc.0 → 9.0.0-rc.2

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 (172) hide show
  1. package/CHANGELOG.md +500 -10
  2. package/EXAMPLES.md +1 -1
  3. package/MIGRATING-TO-9.0.md +43 -1
  4. package/README.md +1 -1
  5. package/dist/LaunchpadSDK.d.ts +414 -219
  6. package/dist/LaunchpadSDK.d.ts.map +1 -1
  7. package/dist/api/LaunchpadAPI.d.ts +2 -140
  8. package/dist/api/LaunchpadAPI.d.ts.map +1 -1
  9. package/dist/auth/SessionAuthService.d.ts +32 -2
  10. package/dist/auth/SessionAuthService.d.ts.map +1 -1
  11. package/dist/auth/session.d.ts +59 -0
  12. package/dist/auth/session.d.ts.map +1 -0
  13. package/dist/auth/types.d.ts +6 -1
  14. package/dist/auth/types.d.ts.map +1 -1
  15. package/dist/constants/endpoints.d.ts +19 -1
  16. package/dist/constants/endpoints.d.ts.map +1 -1
  17. package/dist/constants/enums.d.ts +19 -0
  18. package/dist/constants/enums.d.ts.map +1 -1
  19. package/dist/constants/version.generated.d.ts +1 -1
  20. package/dist/errors/LaunchpadSDKError.d.ts +18 -0
  21. package/dist/errors/LaunchpadSDKError.d.ts.map +1 -1
  22. package/dist/index.browser.d.ts +36 -27
  23. package/dist/index.browser.d.ts.map +1 -1
  24. package/dist/index.browser.esm.js +1 -1
  25. package/dist/index.cjs +1 -1
  26. package/dist/index.esm.js +1 -1
  27. package/dist/index.js +1 -1
  28. package/dist/launchpad/bundle-submission.d.ts +57 -2
  29. package/dist/launchpad/bundle-submission.d.ts.map +1 -1
  30. package/dist/launchpad/create-sale-validation.d.ts +19 -0
  31. package/dist/launchpad/create-sale-validation.d.ts.map +1 -0
  32. package/dist/launchpad/transport.d.ts +31 -1
  33. package/dist/launchpad/transport.d.ts.map +1 -1
  34. package/dist/launchpad/writes.d.ts +37 -11
  35. package/dist/launchpad/writes.d.ts.map +1 -1
  36. package/dist/native.cjs +1 -1
  37. package/dist/native.d.ts +1 -1
  38. package/dist/native.d.ts.map +1 -1
  39. package/dist/native.esm.js +1 -1
  40. package/dist/schemas/launchpad.d.ts +3 -2
  41. package/dist/schemas/launchpad.d.ts.map +1 -1
  42. package/dist/schemas/primitives.d.ts +12 -2
  43. package/dist/schemas/primitives.d.ts.map +1 -1
  44. package/dist/schemas/user.d.ts +3 -3
  45. package/dist/schemas/validators.d.ts +3 -3
  46. package/dist/services/ApiKeyService.d.ts +1 -1
  47. package/dist/services/BanService.d.ts +1 -1
  48. package/dist/services/ChartService.d.ts.map +1 -1
  49. package/dist/services/ContentReactionService.d.ts +6 -18
  50. package/dist/services/ContentReactionService.d.ts.map +1 -1
  51. package/dist/services/EventsQueryService.d.ts +47 -0
  52. package/dist/services/EventsQueryService.d.ts.map +1 -0
  53. package/dist/services/GalaChainLockService.d.ts.map +1 -1
  54. package/dist/services/GalaChainTransferService.d.ts.map +1 -1
  55. package/dist/services/HealthService.d.ts +33 -0
  56. package/dist/services/HealthService.d.ts.map +1 -0
  57. package/dist/services/ImageService.d.ts +3 -3
  58. package/dist/services/ImageService.d.ts.map +1 -1
  59. package/dist/services/LaunchpadPriceService.d.ts.map +1 -1
  60. package/dist/services/LaunchpadService.d.ts +34 -42
  61. package/dist/services/LaunchpadService.d.ts.map +1 -1
  62. package/dist/services/MessagesService.d.ts +12 -44
  63. package/dist/services/MessagesService.d.ts.map +1 -1
  64. package/dist/services/ModeratorService.d.ts +2 -2
  65. package/dist/services/ModeratorService.d.ts.map +1 -1
  66. package/dist/services/OverseerService.d.ts +3 -3
  67. package/dist/services/OverseerService.d.ts.map +1 -1
  68. package/dist/services/PlatformStatsService.d.ts +1 -2
  69. package/dist/services/PlatformStatsService.d.ts.map +1 -1
  70. package/dist/services/PoolService.d.ts +31 -65
  71. package/dist/services/PoolService.d.ts.map +1 -1
  72. package/dist/services/RestrictedNamesService.d.ts +1 -1
  73. package/dist/services/RestrictedNamesService.d.ts.map +1 -1
  74. package/dist/services/StreamChatService.d.ts +8 -19
  75. package/dist/services/StreamChatService.d.ts.map +1 -1
  76. package/dist/services/StreamTokenServiceBase.d.ts +2 -1
  77. package/dist/services/StreamTokenServiceBase.d.ts.map +1 -1
  78. package/dist/services/StreamWebSocketService.d.ts +423 -451
  79. package/dist/services/StreamWebSocketService.d.ts.map +1 -1
  80. package/dist/services/StreamingService.d.ts +14 -15
  81. package/dist/services/StreamingService.d.ts.map +1 -1
  82. package/dist/services/TokenBanService.d.ts +1 -1
  83. package/dist/services/TradeService.d.ts +13 -9
  84. package/dist/services/TradeService.d.ts.map +1 -1
  85. package/dist/services/TradingQuotesService.d.ts.map +1 -1
  86. package/dist/services/UserService.d.ts +64 -20
  87. package/dist/services/UserService.d.ts.map +1 -1
  88. package/dist/services/realtime/event-catalog.d.ts +456 -0
  89. package/dist/services/realtime/event-catalog.d.ts.map +1 -0
  90. package/dist/services/shared/pagination-helpers.d.ts +22 -5
  91. package/dist/services/shared/pagination-helpers.d.ts.map +1 -1
  92. package/dist/services/shared/service-validators.d.ts.map +1 -1
  93. package/dist/signing/signers.d.ts +57 -1
  94. package/dist/signing/signers.d.ts.map +1 -1
  95. package/dist/types/api-key.dto.d.ts +1 -1
  96. package/dist/types/ban.dto.d.ts +21 -16
  97. package/dist/types/ban.dto.d.ts.map +1 -1
  98. package/dist/types/chat-messages.dto.d.ts +10 -72
  99. package/dist/types/chat-messages.dto.d.ts.map +1 -1
  100. package/dist/types/comments.dto.d.ts +8 -78
  101. package/dist/types/comments.dto.d.ts.map +1 -1
  102. package/dist/types/common.d.ts +40 -62
  103. package/dist/types/common.d.ts.map +1 -1
  104. package/dist/types/constraints.d.ts +47 -23
  105. package/dist/types/constraints.d.ts.map +1 -1
  106. package/dist/types/content-flag.dto.d.ts +5 -1
  107. package/dist/types/content-flag.dto.d.ts.map +1 -1
  108. package/dist/types/content-reactions.dto.d.ts +0 -4
  109. package/dist/types/content-reactions.dto.d.ts.map +1 -1
  110. package/dist/types/engagement-stats.dto.d.ts +16 -27
  111. package/dist/types/engagement-stats.dto.d.ts.map +1 -1
  112. package/dist/types/events.dto.d.ts +89 -0
  113. package/dist/types/events.dto.d.ts.map +1 -1
  114. package/dist/types/global-feed.dto.d.ts +23 -164
  115. package/dist/types/global-feed.dto.d.ts.map +1 -1
  116. package/dist/types/health.dto.d.ts +32 -0
  117. package/dist/types/health.dto.d.ts.map +1 -0
  118. package/dist/types/launchpad.dto.d.ts +99 -66
  119. package/dist/types/launchpad.dto.d.ts.map +1 -1
  120. package/dist/types/messages.dto.d.ts +168 -118
  121. package/dist/types/messages.dto.d.ts.map +1 -1
  122. package/dist/types/moderator.dto.d.ts +1 -1
  123. package/dist/types/options.dto.d.ts +1 -3
  124. package/dist/types/options.dto.d.ts.map +1 -1
  125. package/dist/types/overseer.dto.d.ts +2 -1
  126. package/dist/types/overseer.dto.d.ts.map +1 -1
  127. package/dist/types/platform-stats.dto.d.ts +3 -3
  128. package/dist/types/realtime-events.dto.d.ts +340 -0
  129. package/dist/types/realtime-events.dto.d.ts.map +1 -0
  130. package/dist/types/restricted-names.dto.d.ts +2 -2
  131. package/dist/types/restricted-names.dto.d.ts.map +1 -1
  132. package/dist/types/stream-chat.dto.d.ts +15 -14
  133. package/dist/types/stream-chat.dto.d.ts.map +1 -1
  134. package/dist/types/streaming.dto.d.ts +73 -104
  135. package/dist/types/streaming.dto.d.ts.map +1 -1
  136. package/dist/types/token-ban.dto.d.ts.map +1 -1
  137. package/dist/types/token-config.dto.d.ts +34 -19
  138. package/dist/types/token-config.dto.d.ts.map +1 -1
  139. package/dist/types/trades-query.dto.d.ts +8 -24
  140. package/dist/types/trades-query.dto.d.ts.map +1 -1
  141. package/dist/types/user.dto.d.ts +126 -50
  142. package/dist/types/user.dto.d.ts.map +1 -1
  143. package/dist/types/websocket-events.dto.d.ts +5 -5
  144. package/dist/types/websocket-events.dto.d.ts.map +1 -1
  145. package/dist/utils/address-formatter.d.ts +15 -0
  146. package/dist/utils/address-formatter.d.ts.map +1 -1
  147. package/dist/utils/auto-pagination.d.ts +1 -1
  148. package/dist/utils/auto-pagination.d.ts.map +1 -1
  149. package/dist/utils/error-factories.d.ts +8 -7
  150. package/dist/utils/error-factories.d.ts.map +1 -1
  151. package/dist/utils/errors.d.ts +54 -11
  152. package/dist/utils/errors.d.ts.map +1 -1
  153. package/dist/utils/http.d.ts +24 -3
  154. package/dist/utils/http.d.ts.map +1 -1
  155. package/dist/utils/message-validators.d.ts.map +1 -1
  156. package/dist/utils/pagination-helpers.d.ts +17 -0
  157. package/dist/utils/pagination-helpers.d.ts.map +1 -1
  158. package/dist/utils/pagination-validation.d.ts +2 -2
  159. package/dist/utils/response-handlers.d.ts.map +1 -1
  160. package/dist/utils/service-validators.d.ts +6 -6
  161. package/dist/utils/service-validators.d.ts.map +1 -1
  162. package/dist/utils/validation-helpers.d.ts +18 -59
  163. package/dist/utils/validation-helpers.d.ts.map +1 -1
  164. package/dist/utils/validation.d.ts +4 -1
  165. package/dist/utils/validation.d.ts.map +1 -1
  166. package/package.json +3 -3
  167. package/dist/services/StreamingEventService.d.ts +0 -441
  168. package/dist/services/StreamingEventService.d.ts.map +0 -1
  169. package/dist/types/comment.dto.d.ts +0 -176
  170. package/dist/types/comment.dto.d.ts.map +0 -1
  171. package/dist/types/streaming-events.dto.d.ts +0 -605
  172. package/dist/types/streaming-events.dto.d.ts.map +0 -1
@@ -1,283 +1,252 @@
1
1
  /**
2
2
  * Stream WebSocket Service
3
3
  *
4
- * Handles real-time streaming and chat events via Socket.IO including:
5
- * - Stream status updates (IDLE/ACTIVE/DISABLED)
6
- * - Viewer count updates
7
- * - Chat messages
8
- * - Subscription management
4
+ * The launchpad backend's realtime socket: stream status, viewer counts, chat, comments, trades,
5
+ * moderation, the global feed and the overseers' events firehose.
6
+ *
7
+ * ## One registry
8
+ *
9
+ * Every subscription is an entry in one registry:
10
+ *
11
+ * - Any number of subscribers per event, per token and per room. A subscribe method returns that
12
+ * subscriber's own unsubscribe; releasing one never touches another. A subscriber that throws (or
13
+ * rejects) is logged and skipped: it never stops the others.
14
+ * - A room (a token room, a comment room, the global feed, the firehose) is joined when its FIRST
15
+ * subscriber arrives and left when its LAST subscriber is released: never two server subscriptions for
16
+ * one room, however many subscribers share it. A leave waits for the join's acknowledgement, so a
17
+ * subscribe followed at once by an unsubscribe cannot leave the server holding a room nobody wants.
18
+ * - A subscribe method is synchronous and never fails for want of a connection: it registers, and the
19
+ * room is joined once the socket is connected (and, for the firehose, authenticated). With
20
+ * `autoConnect` (the default) a subscription also opens the socket.
21
+ * - Socket listeners are registered once per socket, when it is created, and removed when it is closed.
22
+ *
23
+ * ## Reconnecting
24
+ *
25
+ * socket.io reconnects by itself. On every connection after the first the service re-authenticates FIRST
26
+ * (with the token its `tokenProvider` hands out at that moment, never a remembered one) if the socket was
27
+ * authenticated, THEN re-joins every room that still has a subscriber, THEN tells `onReconnect` listeners
28
+ * so they can refetch what they missed.
9
29
  *
10
30
  * @category Services
11
31
  * @since 5.1.0
12
32
  */
13
33
  import type { Socket } from 'socket.io-client';
14
- import type { GlobalFeedEventCallbacks, GlobalFeedSubscribedEvent } from '../types/global-feed.dto';
15
- import type { StreamChatAuthenticatedEvent, StreamChatAuthErrorEvent, StreamChatErrorEvent, StreamChatGlobalStatusEvent, StreamChatMessageEvent, StreamChatPinnedEvent, StreamChatSentEvent, StreamChatStatusEvent, StreamChatUnpinnedEvent, StreamReactionErrorEvent, StreamReactionEvent, TypingIndicatorEvent } from '../types/stream-chat.dto';
16
- import type { StreamCountdownEvent, StreamGlobalStatusEvent, StreamLanguageEvent, StreamStatusEvent, StreamSubscribedEvent, StreamUnsubscribedEvent, ViewerCountEvent } from '../types/streaming.dto';
17
- import type { ApiKeyCreatedEvent, ApiKeyRevokedEvent, ApiKeyUpdatedEvent, BalanceUpdatedEvent, CommentCreatedEvent, EngagementStatsUpdatedEvent, HolderCountUpdatedEvent, ModeratorAddedEvent, ModeratorInviteCreatedEvent, ModeratorRemovedEvent, ModeratorRoleUpdatedEvent, OverseerAddedEvent, OverseerRemovedEvent, PoolBadgeAssignedEvent, PoolMetadataUpdatedEvent, PoolSocialLinksUpdatedEvent, StatsUpdatedEvent, TokenBannedEvent, TokenConfigUpdatedEvent, TokenUnbannedEvent, TradeExecutedEvent, UserProfileUpdatedEvent } from '../types/websocket-events.dto';
34
+ import type { SiteConfigState } from '../types/global-feed.dto';
35
+ import type { RealtimeEventName, RealtimeEventPayloads } from '../types/realtime-events.dto';
36
+ import type { StreamSubscribedEvent } from '../types/streaming.dto';
18
37
  import { LoggerBase } from './BaseService';
19
- import type { StreamingEventService } from './StreamingEventService';
38
+ import { type CommentRoomEventName, type FeedEventName, type FeedTokenEvent, type GlobalFeedEventCallbacks, type StreamEventCallbacks, type TokenRoomEventName } from './realtime/event-catalog';
20
39
  /**
21
40
  * Stream WebSocket configuration
22
41
  */
23
42
  export interface StreamWebSocketConfig {
24
43
  /** Stream WebSocket server URL (SEPARATE from bundleBaseUrl) */
25
44
  url: string;
26
- /** JWT token for authentication (optional - required for chat) */
27
- authToken?: string;
28
- /** Maximum reconnection attempts (default: 5) */
45
+ /** Maximum reconnection attempts (default: 5; `Infinity` never gives up) */
29
46
  reconnectAttempts?: number;
30
- /** Delay between reconnection attempts in ms (default: 2000) */
47
+ /** Delay before the first reconnection attempt in ms (default: 2000) */
31
48
  reconnectDelay?: number;
32
- /** Subscription timeout in ms (default: 10000) */
49
+ /** Longest delay between reconnection attempts in ms (socket.io's default: 5000) */
50
+ reconnectDelayMax?: number;
51
+ /** How long a room join or an authentication may wait for the server's answer in ms (default: 10000) */
33
52
  subscriptionTimeout?: number;
53
+ /**
54
+ * The JWT to authenticate with, asked for whenever the service authenticates without being handed a token
55
+ * (and on every reconnect). It must answer with the token current at that moment. `null`: none.
56
+ */
57
+ tokenProvider?: () => Promise<string | null>;
58
+ /** Open the socket when a subscription is registered and none is open (default: true). */
59
+ autoConnect?: boolean;
34
60
  }
61
+ /** A subscriber's unsubscribe. Calling it twice is harmless. */
62
+ export type Unsubscribe = () => void;
63
+ /** A subscriber: it may be async; a rejection is logged, never thrown. */
64
+ export type RealtimeListener<E extends RealtimeEventName> = (event: RealtimeEventPayloads[E]) => void | Promise<void>;
35
65
  /**
36
- * Stream event names used by the backend.
37
- *
38
- * BREAKING CHANGE (v7.2.0): Event values changed from snake_case to SCREAMING_CASE
39
- * to match backend websocket-events.constant.ts. Frontend and SDK consumers must
40
- * update their event listeners to use these new names.
41
- *
42
- * Migration: 'stream_status' → 'STREAM_STATUS', 'token_banned' → 'TOKEN_BANNED', etc.
43
- */
44
- export declare const STREAM_EVENTS: {
45
- readonly SUBSCRIBE: "subscribe_token";
46
- readonly UNSUBSCRIBE: "unsubscribe_token";
47
- readonly AUTHENTICATE: "authenticate";
48
- readonly SEND_CHAT: "send_stream_chat";
49
- readonly SEND_REACTION: "SEND_STREAM_REACTION";
50
- readonly TYPING_START: "typing_start";
51
- readonly TYPING_STOP: "typing_stop";
52
- readonly STREAM_STATUS: "STREAM_STATUS";
53
- readonly RECORDING_STATUS: "RECORDING_STATUS";
54
- readonly RECORDINGS_COUNT_UPDATED: "RECORDINGS_COUNT_UPDATED";
55
- readonly SIMULCAST_STATUS: "SIMULCAST_STATUS";
56
- readonly DOWNLOAD_READY: "DOWNLOAD_READY";
57
- readonly STREAM_COUNTDOWN_UPDATED: "STREAM_COUNTDOWN_UPDATED";
58
- readonly STREAM_LANGUAGE_UPDATED: "STREAM_LANGUAGE_UPDATED";
59
- readonly VIEWER_COUNT: "VIEWER_COUNT";
60
- readonly STREAM_SUBSCRIBED: "token_subscribed";
61
- readonly STREAM_UNSUBSCRIBED: "token_unsubscribed";
62
- readonly STREAM_GLOBAL_STATUS: "STREAM_GLOBAL_STATUS";
63
- readonly ENGAGEMENT_STATS_UPDATED: "ENGAGEMENT_STATS_UPDATED";
64
- readonly CHAT_MESSAGE: "STREAM_CHAT_MESSAGE";
65
- readonly CHAT_SENT: "STREAM_CHAT_SENT";
66
- readonly CHAT_UPDATED: "STREAM_CHAT_UPDATED";
67
- readonly CHAT_DELETED: "STREAM_CHAT_DELETED";
68
- readonly CHAT_ERROR: "stream_chat_error";
69
- readonly CHAT_STATUS: "CHAT_STATUS_CHANGED";
70
- readonly CHAT_GLOBAL_STATUS: "STREAM_CHAT_GLOBAL_STATUS";
71
- readonly CHAT_AUTHENTICATED: "authenticated";
72
- readonly CHAT_AUTH_ERROR: "stream_chat_auth_error";
73
- readonly STREAM_CONTROL_STATUS_CHANGED: "STREAM_CONTROL_STATUS_CHANGED";
74
- readonly REACTION: "STREAM_REACTION";
75
- readonly CONTENT_REACTION_ADDED: "CONTENT_REACTION_ADDED";
76
- readonly CONTENT_REACTION_REMOVED: "CONTENT_REACTION_REMOVED";
77
- readonly REACTION_ERROR: "stream_reaction_error";
78
- readonly USER_TYPING: "USER_TYPING";
79
- readonly CHAT_PINNED: "STREAM_CHAT_PINNED";
80
- readonly CHAT_UNPINNED: "STREAM_CHAT_UNPINNED";
81
- readonly COMMENT_CREATED: "COMMENT_CREATED";
82
- readonly COMMENT_UPDATED: "COMMENT_UPDATED";
83
- readonly COMMENT_DELETED: "COMMENT_DELETED";
84
- readonly USER_BANNED: "USER_BANNED";
85
- readonly USER_UNBANNED: "USER_UNBANNED";
86
- readonly BAN_ENFORCEMENT: "BAN_ENFORCEMENT";
87
- readonly TOKEN_BANNED: "TOKEN_BANNED";
88
- readonly TOKEN_UNBANNED: "TOKEN_UNBANNED";
89
- readonly CONTENT_FLAGGED: "CONTENT_FLAGGED";
90
- readonly FLAG_RESOLVED: "FLAG_RESOLVED";
91
- readonly MODERATOR_INVITE_CREATED: "MODERATOR_INVITE_CREATED";
92
- readonly MODERATOR_ADDED: "MODERATOR_ADDED";
93
- readonly MODERATOR_REMOVED: "MODERATOR_REMOVED";
94
- readonly MODERATOR_ROLE_UPDATED: "MODERATOR_ROLE_UPDATED";
95
- readonly OVERSEER_ADDED: "OVERSEER_ADDED";
96
- readonly OVERSEER_REMOVED: "OVERSEER_REMOVED";
97
- readonly TRADE_EXECUTED: "TRADE_EXECUTED";
98
- readonly BALANCE_UPDATED: "BALANCE_UPDATED";
99
- readonly STATS_UPDATED: "STATS_UPDATED";
100
- readonly POOL_METADATA_UPDATED: "POOL_METADATA_UPDATED";
101
- readonly POOL_SOCIAL_LINKS_UPDATED: "POOL_SOCIAL_LINKS_UPDATED";
102
- readonly POOL_BADGE_ASSIGNED: "POOL_BADGE_ASSIGNED";
103
- readonly HOLDER_COUNT_UPDATED: "HOLDER_COUNT_UPDATED";
104
- readonly USER_PROFILE_UPDATED: "USER_PROFILE_UPDATED";
105
- readonly API_KEY_CREATED: "API_KEY_CREATED";
106
- readonly API_KEY_UPDATED: "API_KEY_UPDATED";
107
- readonly API_KEY_REVOKED: "API_KEY_REVOKED";
108
- readonly TOKEN_CONFIG_UPDATED: "TOKEN_CONFIG_UPDATED";
109
- readonly SITE_CONFIG_CHANGED: "SITE_CONFIG_CHANGED";
110
- readonly COMMENTS_GLOBAL_STATUS: "COMMENTS_GLOBAL_STATUS";
111
- readonly WEBHOOKS_GLOBAL_STATUS: "WEBHOOKS_GLOBAL_STATUS";
112
- readonly SUBSCRIBE_GLOBAL_FEED: "subscribe_global_feed";
113
- readonly UNSUBSCRIBE_GLOBAL_FEED: "unsubscribe_global_feed";
114
- readonly GLOBAL_FEED_SUBSCRIBED: "global_feed_subscribed";
115
- readonly GLOBAL_FEED_UNSUBSCRIBED: "global_feed_unsubscribed";
116
- };
117
- /**
118
- * Callback types for stream events
66
+ * Client-side filters of a firehose subscriber. The backend's firehose takes no filters (every overseer
67
+ * socket in the room receives every event), so each subscriber's filters are applied here.
119
68
  */
120
- export interface StreamEventCallbacks {
121
- onStreamStatus?: (event: StreamStatusEvent) => void;
122
- onStreamSubscribed?: (event: StreamSubscribedEvent) => void;
123
- onStreamUnsubscribed?: (event: StreamUnsubscribedEvent) => void;
124
- onViewerCount?: (event: ViewerCountEvent) => void;
125
- onStreamGlobalStatus?: (event: StreamGlobalStatusEvent) => void;
126
- onChatMessage?: (event: StreamChatMessageEvent) => void;
127
- onChatSent?: (event: StreamChatSentEvent) => void;
128
- onChatError?: (event: StreamChatErrorEvent) => void;
129
- onChatStatus?: (event: StreamChatStatusEvent) => void;
130
- onChatGlobalStatus?: (event: StreamChatGlobalStatusEvent) => void;
131
- onChatAuthenticated?: (event: StreamChatAuthenticatedEvent) => void;
132
- onChatAuthError?: (event: StreamChatAuthErrorEvent) => void;
133
- onReaction?: (event: StreamReactionEvent) => void;
134
- onReactionError?: (event: StreamReactionErrorEvent) => void;
135
- onTypingIndicator?: (event: TypingIndicatorEvent) => void;
136
- onChatPinned?: (event: StreamChatPinnedEvent) => void;
137
- onChatUnpinned?: (event: StreamChatUnpinnedEvent) => void;
138
- onCountdownUpdated?: (event: StreamCountdownEvent) => void;
139
- onLanguageUpdated?: (event: StreamLanguageEvent) => void;
140
- onTokenBanned?: (event: TokenBannedEvent) => void;
141
- onTokenUnbanned?: (event: TokenUnbannedEvent) => void;
142
- onModeratorInviteCreated?: (event: ModeratorInviteCreatedEvent) => void;
143
- onModeratorAdded?: (event: ModeratorAddedEvent) => void;
144
- onModeratorRemoved?: (event: ModeratorRemovedEvent) => void;
145
- onModeratorRoleUpdated?: (event: ModeratorRoleUpdatedEvent) => void;
146
- onOverseerAdded?: (event: OverseerAddedEvent) => void;
147
- onOverseerRemoved?: (event: OverseerRemovedEvent) => void;
148
- onTradeExecuted?: (event: TradeExecutedEvent) => void;
149
- onBalanceUpdated?: (event: BalanceUpdatedEvent) => void;
150
- onPoolMetadataUpdated?: (event: PoolMetadataUpdatedEvent) => void;
151
- onPoolSocialLinksUpdated?: (event: PoolSocialLinksUpdatedEvent) => void;
152
- onPoolBadgeAssigned?: (event: PoolBadgeAssignedEvent) => void;
153
- onHolderCountUpdated?: (event: HolderCountUpdatedEvent) => void;
154
- onCommentCreated?: (event: CommentCreatedEvent) => void;
155
- onUserProfileUpdated?: (event: UserProfileUpdatedEvent) => void;
156
- onApiKeyCreated?: (event: ApiKeyCreatedEvent) => void;
157
- onApiKeyUpdated?: (event: ApiKeyUpdatedEvent) => void;
158
- onApiKeyRevoked?: (event: ApiKeyRevokedEvent) => void;
159
- onTokenConfigUpdated?: (event: TokenConfigUpdatedEvent) => void;
160
- onStatsUpdated?: (event: StatsUpdatedEvent) => void;
161
- onEngagementStatsUpdated?: (event: EngagementStatsUpdatedEvent) => void;
69
+ export interface EventsFirehoseFilters {
70
+ /** Only events of these `eventType`s (compared case-insensitively). */
71
+ eventTypes?: string[];
72
+ /** Only events about this token. */
73
+ tokenName?: string;
74
+ /** Only events caused by this user address (compared case-insensitively). */
75
+ userAddress?: string;
162
76
  }
163
77
  /**
164
78
  * Stream WebSocket Service
165
79
  *
166
- * Manages real-time connections for streaming and chat functionality.
167
- * Uses a SEPARATE WebSocket endpoint from the bundle backend.
168
- *
169
- * Key features:
170
- * - Event buffering to prevent race conditions
171
- * - Room-based subscriptions per token
172
- * - Automatic reconnection with re-subscription
173
- * - Memory-safe listener cleanup
174
- *
175
80
  * @example
176
81
  * ```typescript
177
- * import { getEnvironmentConfig } from '../config/environments';
178
- *
179
- * const wsService = new StreamWebSocketService({
180
- * url: getEnvironmentConfig('stage').webSocketUrl,
181
- * authToken: 'jwt-token-here'
182
- * });
82
+ * const ws = new StreamWebSocketService({ url: getEnvironmentConfig('stage').launchpadBaseUrl });
183
83
  *
184
- * await wsService.connect();
84
+ * // Two components watch the same token: both are served, the room is joined once.
85
+ * const offStatus = ws.subscribeStreamStatus('mytoken', (event) => console.log(event.status));
86
+ * const offTrades = ws.subscribeTradeExecuted('mytoken', (event) => console.log(event.tradeType));
185
87
  *
186
- * // Subscribe to a stream
187
- * await wsService.subscribeToStream('mytoken', {
188
- * onStreamStatus: (event) => console.log('Status:', event.status),
189
- * onViewerCount: (event) => console.log('Viewers:', event.count),
190
- * onChatMessage: (event) => console.log('Chat:', event.message.content)
191
- * });
88
+ * // Leaving the last subscriber leaves the room.
89
+ * offStatus();
90
+ * offTrades();
192
91
  *
193
- * // Send a chat message
194
- * wsService.sendChatMessage('mytoken', 'Hello everyone!');
195
- *
196
- * // Cleanup
197
- * wsService.unsubscribeFromStream('mytoken');
198
- * wsService.disconnect();
92
+ * ws.disconnect();
199
93
  * ```
200
94
  */
201
95
  export declare class StreamWebSocketService extends LoggerBase {
202
96
  private socket;
203
- private config;
204
- private isSocketIOAvailable;
205
- private reconnectionManager;
206
- private isAuthenticated;
207
- private streamingEventService;
208
- private subscribedRooms;
209
- private roomCallbacks;
210
- private pendingSubscriptions;
211
- private eventBuffer;
212
- private eventBufferTimeouts;
213
- private readonly MAX_BUFFER_SIZE;
214
- private readonly BUFFER_CLEANUP_MS;
215
- private globalCallbacks;
216
- private isGlobalFeedSubscribed;
217
- private globalFeedCallbacks;
218
- private pendingGlobalFeedSubscription;
97
+ private readonly config;
98
+ private readonly isSocketIOAvailable;
99
+ private disposed;
100
+ /** Bumped by every `disconnect()`: an async call that started before it must not register after it. */
101
+ private epoch;
102
+ private connectionGeneration;
103
+ private hasConnected;
104
+ private connectAttempt;
105
+ /** socket.io gave up reconnecting (`reconnect_failed`); it does not try again by itself. */
106
+ private reconnectExhausted;
107
+ private managerCleanups;
108
+ private readonly connectionStateListeners;
109
+ private readonly reconnectListeners;
110
+ private readonly subscribers;
111
+ private readonly roomRefs;
112
+ private readonly roomStates;
113
+ private readonly roomWaiters;
114
+ private readonly explicitHolds;
115
+ private readonly recentOccurrences;
116
+ private siteConfig;
117
+ private authenticated;
118
+ private authenticatedToken;
119
+ private authenticatedGeneration;
120
+ private wantsAuthentication;
121
+ private lastExplicitToken;
122
+ private authSequence;
123
+ private inFlight;
124
+ private lastEmitted;
125
+ private pendingAuthenticate;
219
126
  constructor(config: StreamWebSocketConfig, debug?: boolean);
220
127
  /**
221
- * Check if Socket.IO is available
128
+ * Register a subscriber. Every public subscribe method ends here.
222
129
  */
223
- private checkSocketIOAvailability;
130
+ private register;
131
+ private release;
132
+ /** A room reference with no event subscriber behind it (an explicit `subscribeToStream`). */
133
+ private hold;
134
+ private openIfNeeded;
135
+ private acquireRoom;
136
+ private releaseRoom;
224
137
  /**
225
- * Get room name for token
138
+ * Bring one room to what the registry wants: joined when it has a subscriber, left when it has none.
139
+ * Idempotent; called on every change and on every (re)connect.
226
140
  */
227
- private getRoomName;
141
+ private syncRoom;
142
+ private syncAllRooms;
143
+ private joinRoom;
144
+ private onRoomAcknowledged;
145
+ private rejectWaiters;
146
+ private clearRoomStates;
228
147
  /**
229
- * Buffer an event for potential late listeners
148
+ * One incoming occurrence: what it changes in the service, then every subscriber it is for.
230
149
  */
231
- private bufferEvent;
150
+ private onServerEvent;
151
+ private isDuplicate;
152
+ private deliver;
153
+ private passes;
154
+ private invoke;
155
+ /** What an incoming event changes in the service itself. */
156
+ private applyEffects;
232
157
  /**
233
- * Process buffered events for a newly subscribed token
158
+ * The socket, if it is connected right now.
234
159
  */
235
- private processBufferedEvents;
160
+ private liveSocket;
236
161
  /**
237
- * Setup global event listeners
162
+ * Connect to the stream WebSocket server.
163
+ *
164
+ * Idempotent and safe to call concurrently: there is one socket however many callers wait for it. Calling
165
+ * it while connected resolves at once; while socket.io is retrying it waits for the next connection.
166
+ *
167
+ * @returns Promise that resolves when connected, rejects when the next connection attempt fails
168
+ * @throws ConfigurationError if Socket.IO is not available (the promise rejects)
238
169
  */
239
- private setupGlobalListeners;
170
+ connect(): Promise<void>;
171
+ private createSocket;
240
172
  /**
241
- * Re-subscribe to all active rooms after reconnection
173
+ * Every socket listener the service has, registered here and nowhere else, once per socket.
242
174
  */
243
- private resubscribeAll;
175
+ private attachListeners;
176
+ private onSocketConnect;
244
177
  /**
245
- * Attach the StreamingEventService instance this connection forwards raw
246
- * USER_BANNED/USER_UNBANNED/BAN_ENFORCEMENT socket events into, so LaunchpadSDK's
247
- * onUserBanned()/onUserUnbanned()/onBanEnforcement() subscribers actually receive events.
248
- *
249
- * @internal
178
+ * Re-authenticate with the token current now, then re-join the rooms, then tell the reconnect listeners.
179
+ * Aborts if the connection changed again while it waited.
250
180
  */
251
- setStreamingEventService(service: StreamingEventService): void;
181
+ private restoreAfterReconnect;
182
+ private onSocketDisconnect;
183
+ private settleConnectWaiters;
184
+ private notifyConnectionState;
185
+ private notifyReconnect;
252
186
  /**
253
- * Connect to the stream WebSocket server
187
+ * Listen for the connection coming up (`true`) and going down (`false`).
254
188
  *
255
- * @returns Promise that resolves when connected
256
- * @throws ConfigurationError if Socket.IO is not available
189
+ * @returns Function to stop listening
190
+ * @since 9.0.0
257
191
  */
258
- connect(): Promise<void>;
192
+ onConnectionStateChange(listener: (connected: boolean) => void): Unsubscribe;
259
193
  /**
260
- * Authenticate with the stream server for chat operations
194
+ * Listen for the socket coming back after a drop. Fires after the service has re-authenticated and
195
+ * re-joined its rooms, never for the first connection. Use it to refetch what was missed.
261
196
  *
262
- * @param token JWT token for authentication
197
+ * @returns Function to stop listening
198
+ * @since 9.0.0
263
199
  */
264
- authenticate(token: string): void;
200
+ onReconnect(listener: () => void): Unsubscribe;
201
+ private resolveToken;
265
202
  /**
266
- * Subscribe to a token's stream events
203
+ * Authenticate the connection (opening it first if needed).
267
204
  *
268
- * @param tokenName Token name to subscribe to
269
- * @param callbacks Event callbacks for this subscription
270
- * @returns Promise that resolves when subscription is confirmed
271
- * @throws ValidationError if WebSocket is not connected
272
- * @throws Error if subscription times out
205
+ * Resolves `true` when the server answers `authenticated`; `false` when it answers `exception` or
206
+ * `stream_chat_auth_error`, when the answer does not come within `subscriptionTimeout`, when the
207
+ * connection drops meanwhile, when there is no token, or when a newer `authenticate` / `deauthenticate`
208
+ * replaced this call.
209
+ *
210
+ * - The same token on the same connection resolves `true` without sending anything.
211
+ * - The same token while that token is being authenticated shares the pending call.
212
+ * - A different token replaces the pending one (that call resolves `false`); the new token is sent after
213
+ * the server has answered the one in flight, so the server's final identity is the newest token.
214
+ * - Without a token argument the service asks its `tokenProvider` (so a refreshed token is used).
215
+ *
216
+ * @param token JWT to authenticate with (default: the token provider's current token)
217
+ * @since 5.1.0
273
218
  */
274
- subscribeToStream(tokenName: string, callbacks?: StreamEventCallbacks): Promise<StreamSubscribedEvent>;
219
+ authenticate(token?: string): Promise<boolean>;
220
+ private runAuthenticate;
221
+ private beginAuthentication;
222
+ private finishAuthentication;
223
+ private markAuthenticated;
275
224
  /**
276
- * Unsubscribe from a token's stream events
225
+ * The server answered `authenticated` after the service had stopped waiting (the 10 seconds ran out, or
226
+ * an unrelated `exception` was read as the failure): when that answer is to the newest authenticate sent
227
+ * on this connection, the socket IS authenticated, whatever the caller was told.
228
+ */
229
+ private adoptLateAuthentication;
230
+ /**
231
+ * Forget the authenticated identity.
277
232
  *
278
- * @param tokenName Token name to unsubscribe from
233
+ * Cancels a pending `authenticate`, stops re-authenticating on reconnect, and: the server has no message
234
+ * that drops a socket's identity (its user room, and the overseer room, stay joined until the connection
235
+ * closes), so when the socket was authenticated it is closed and opened again. The registry survives; the
236
+ * new connection joins the public rooms again and `onReconnect` listeners fire.
237
+ *
238
+ * @since 9.0.0
279
239
  */
280
- unsubscribeFromStream(tokenName: string): void;
240
+ deauthenticate(): void;
241
+ /**
242
+ * Check if authenticated for chat operations
243
+ */
244
+ isAuthenticatedForChat(): boolean;
245
+ /**
246
+ * Check if connected to the WebSocket server
247
+ */
248
+ isConnected(): boolean;
249
+ private requireReady;
281
250
  /**
282
251
  * Send a chat message via WebSocket (faster than REST)
283
252
  *
@@ -300,13 +269,7 @@ export declare class StreamWebSocketService extends LoggerBase {
300
269
  */
301
270
  sendReaction(tokenName: string, emoji: string, streamTime?: number): void;
302
271
  /**
303
- * Send typing indicator start event
304
- *
305
- * Indicates user has started typing in chat. Server broadcasts typing
306
- * status to all viewers in the room except the sender.
307
- *
308
- * Auto-expires after 5 seconds if no typing activity.
309
- * Use sendTypingStop() to explicitly stop the indicator.
272
+ * Send typing indicator start event (the server auto-expires it after 5 seconds)
310
273
  *
311
274
  * @param tokenName Token name for the chat room
312
275
  * @throws ValidationError if not authenticated or not connected
@@ -316,9 +279,6 @@ export declare class StreamWebSocketService extends LoggerBase {
316
279
  /**
317
280
  * Send typing indicator stop event
318
281
  *
319
- * Indicates user has stopped typing (e.g., message sent, input cleared, blur).
320
- * Call this when user sends message, clears input, or loses focus.
321
- *
322
282
  * @param tokenName Token name for the chat room
323
283
  * @throws ValidationError if not authenticated or not connected
324
284
  * @since 5.11.0
@@ -326,274 +286,286 @@ export declare class StreamWebSocketService extends LoggerBase {
326
286
  sendTypingStop(tokenName: string): void;
327
287
  private sendTypingEvent;
328
288
  /**
329
- * Subscribe to token banned events for a specific token
289
+ * Subscribe to a token room event. The token's room is joined for as long as any subscriber of the
290
+ * token (any event) is registered.
330
291
  *
331
- * @param tokenName Token name to listen for
332
- * @param callback Callback function
333
- * @returns Function to unsubscribe
334
- * @since 6.0.0
292
+ * @param event A token room event
293
+ * @param tokenName Token name
294
+ * @param listener Called for every occurrence about that token
295
+ * @returns This subscriber's own unsubscribe
296
+ * @since 9.0.0
335
297
  */
336
- subscribeTokenBanned(tokenName: string, callback: (event: TokenBannedEvent) => void): () => void;
298
+ subscribeToken<E extends TokenRoomEventName>(event: E, tokenName: string, listener: RealtimeListener<E>): Unsubscribe;
337
299
  /**
338
- * Subscribe to token unbanned events for a specific token
300
+ * Hold a token's room without listening to any event of it: the room is joined for as long as this (or
301
+ * any other subscriber of the token) is registered. For a caller that wants the room to stay joined while
302
+ * its listeners come and go.
339
303
  *
340
- * @param tokenName Token name to listen for
341
- * @param callback Callback function
342
- * @returns Function to unsubscribe
343
- * @since 6.0.0
304
+ * @returns This hold's own release
305
+ * @since 9.0.0
344
306
  */
345
- subscribeTokenUnbanned(tokenName: string, callback: (event: TokenUnbannedEvent) => void): () => void;
307
+ joinTokenRoom(tokenName: string): Unsubscribe;
346
308
  /**
347
- * Subscribe to moderator invite created events for a specific token
309
+ * Subscribe to a comment room event. The token's comment room (not its token room) is joined for as
310
+ * long as any comment subscriber of the token is registered.
348
311
  *
349
- * @param tokenName Token name to listen for
350
- * @param callback Callback function
351
- * @returns Function to unsubscribe
352
- * @since 8.5.0
312
+ * @since 9.0.0
353
313
  */
354
- subscribeModeratorInviteCreated(tokenName: string, callback: (event: ModeratorInviteCreatedEvent) => void): () => void;
314
+ subscribeComment<E extends CommentRoomEventName>(event: E, tokenName: string, listener: RealtimeListener<E>): Unsubscribe;
355
315
  /**
356
- * Subscribe to moderator added events for a specific token
316
+ * Subscribe to a global feed event, for every token. The feed room is joined for as long as any feed
317
+ * subscriber is registered. Feed subscribers are served whether or not the token's own room is joined.
357
318
  *
358
- * @param tokenName Token name to listen for
359
- * @param callback Callback function
360
- * @returns Function to unsubscribe
361
- * @since 6.0.0
319
+ * @since 9.0.0
362
320
  */
363
- subscribeModeratorAdded(tokenName: string, callback: (event: ModeratorAddedEvent) => void): () => void;
321
+ subscribeFeed<E extends FeedEventName>(event: E, listener: RealtimeListener<E>): Unsubscribe;
364
322
  /**
365
- * Subscribe to moderator removed events for a specific token
323
+ * Subscribe to every occurrence of an event the socket receives, for any token, joining no room. For the
324
+ * events the server sends to the connection's own rooms (the user room and the overseer room, joined by
325
+ * authenticating) and the broadcasts.
366
326
  *
367
- * @param tokenName Token name to listen for
368
- * @param callback Callback function
369
- * @returns Function to unsubscribe
370
- * @since 6.0.0
327
+ * @since 9.0.0
371
328
  */
372
- subscribeModeratorRemoved(tokenName: string, callback: (event: ModeratorRemovedEvent) => void): () => void;
329
+ subscribeEvent<E extends RealtimeEventName>(event: E, listener: RealtimeListener<E>): Unsubscribe;
373
330
  /**
374
- * Subscribe to moderator role updated events for a specific token
331
+ * Subscribe to the overseers' events firehose. ONE server subscription serves every subscriber; each
332
+ * subscriber's `filters` are applied here (the server filters nothing). The server admits overseers
333
+ * only, so the room is joined once the socket is authenticated (and re-joined, after
334
+ * re-authenticating, on every reconnect).
375
335
  *
376
- * @param tokenName Token name to listen for
377
- * @param callback Callback function
378
- * @returns Function to unsubscribe
379
- * @since 6.0.0
336
+ * @param listener Called for each event that passes `filters`
337
+ * @param filters Optional client-side filters
338
+ * @since 9.0.0
380
339
  */
381
- subscribeModeratorRoleUpdated(tokenName: string, callback: (event: ModeratorRoleUpdatedEvent) => void): () => void;
340
+ subscribeEventsFirehose(listener: RealtimeListener<'EVENT'>, filters?: EventsFirehoseFilters): Unsubscribe;
382
341
  /**
383
- * Subscribe to overseer added events (global)
342
+ * Subscribe to every global feed token event through one callback. Each occurrence is handed over with
343
+ * the event's name, so a caller tells them apart by `event`.
384
344
  *
385
- * @param callback Callback function
386
- * @returns Function to unsubscribe
387
- * @since 6.0.0
345
+ * @since 9.0.0
388
346
  */
389
- subscribeOverseerAdded(callback: (event: OverseerAddedEvent) => void): () => void;
347
+ subscribeFeedTokenEvents(listener: (event: FeedTokenEvent) => void | Promise<void>): Unsubscribe;
390
348
  /**
391
- * Subscribe to overseer removed events (global)
349
+ * Subscribe to the global feed with a callback object: each `onX` becomes its own subscriber.
392
350
  *
393
- * @param callback Callback function
394
- * @returns Function to unsubscribe
395
- * @since 6.0.0
396
- */
397
- subscribeOverseerRemoved(callback: (event: OverseerRemovedEvent) => void): () => void;
398
- /**
399
- * Subscribe to trade executed events for a specific token
400
- *
401
- * @param tokenName Token name to listen for
402
- * @param callback Callback function
403
- * @returns Function to unsubscribe
404
- * @since 6.0.0
405
- */
406
- subscribeTradeExecuted(tokenName: string, callback: (event: TradeExecutedEvent) => void): () => void;
407
- /**
408
- * Subscribe to pool metadata updated events for a specific token
409
- *
410
- * @param tokenName Token name to listen for
411
- * @param callback Callback function
412
- * @returns Function to unsubscribe
413
- * @since 6.0.0
414
- */
415
- subscribePoolMetadataUpdated(tokenName: string, callback: (event: PoolMetadataUpdatedEvent) => void): () => void;
416
- /**
417
- * Subscribe to pool social links updated events for a specific token
418
- *
419
- * @param tokenName Token name to listen for
420
- * @param callback Callback function
421
- * @returns Function to unsubscribe
422
- * @since 6.0.0
423
- */
424
- subscribePoolSocialLinksUpdated(tokenName: string, callback: (event: PoolSocialLinksUpdatedEvent) => void): () => void;
425
- /**
426
- * Subscribe to pool badge assigned events for a specific token
427
- *
428
- * @param tokenName Token name to listen for
429
- * @param callback Callback function
430
- * @returns Function to unsubscribe
431
- * @since 6.0.0
432
- */
433
- subscribePoolBadgeAssigned(tokenName: string, callback: (event: PoolBadgeAssignedEvent) => void): () => void;
434
- /**
435
- * Subscribe to holder count updated events for a specific token
436
- *
437
- * @param tokenName Token name to listen for
438
- * @param callback Callback function
439
- * @returns Function to unsubscribe
440
- * @since 6.0.0
441
- */
442
- subscribeHolderCountUpdated(tokenName: string, callback: (event: HolderCountUpdatedEvent) => void): () => void;
443
- /**
444
- * Subscribe to comment created events for a specific token
445
- *
446
- * @param tokenName Token name to listen for
447
- * @param callback Callback function
448
- * @returns Function to unsubscribe
449
- * @since 6.0.0
450
- */
451
- subscribeCommentCreated(tokenName: string, callback: (event: CommentCreatedEvent) => void): () => void;
452
- /**
453
- * Subscribe to user profile updated events (global)
454
- *
455
- * @param callback Callback function
456
- * @returns Function to unsubscribe
457
- * @since 6.0.0
351
+ * @returns Function that removes every callback this call registered (and leaves the feed room if
352
+ * nothing else needs it)
353
+ * @since 7.0.0
458
354
  */
459
- subscribeUserProfileUpdated(callback: (event: UserProfileUpdatedEvent) => void): () => void;
355
+ subscribeToGlobalFeed(callbacks?: GlobalFeedEventCallbacks): Unsubscribe;
460
356
  /**
461
- * Subscribe to API key created events (global)
357
+ * Add a callback object's callbacks as subscribers of their events on every token, joining no room.
358
+ * Each callback is its own subscriber; none replaces another.
462
359
  *
463
- * @param callback Callback function
464
- * @returns Function to unsubscribe
465
- * @since 6.0.0
360
+ * @returns Function that removes the callbacks this call added
361
+ * @since 9.0.0
466
362
  */
467
- subscribeApiKeyCreated(callback: (event: ApiKeyCreatedEvent) => void): () => void;
363
+ addCallbacks(callbacks: StreamEventCallbacks): Unsubscribe;
364
+ private registerCallbacks;
468
365
  /**
469
- * Subscribe to API key updated events (global)
366
+ * Subscribe to a token's events with a callback object, and wait for the server to confirm the room.
470
367
  *
471
- * @param callback Callback function
472
- * @returns Function to unsubscribe
473
- * @since 6.0.0
474
- */
475
- subscribeApiKeyUpdated(callback: (event: ApiKeyUpdatedEvent) => void): () => void;
476
- /**
477
- * Subscribe to API key revoked events (global)
368
+ * Each callback in `callbacks` is a subscriber of that token; the room is joined while at least one
369
+ * `subscribeToStream` call for it, or any other subscriber, is registered. Calling it again for a token
370
+ * ADDS callbacks: it never replaces the ones already registered.
371
+ * {@link StreamWebSocketService.unsubscribeFromStream} removes what `subscribeToStream` registered.
478
372
  *
479
- * @param callback Callback function
480
- * @returns Function to unsubscribe
481
- * @since 6.0.0
482
- */
483
- subscribeApiKeyRevoked(callback: (event: ApiKeyRevokedEvent) => void): () => void;
484
- /**
485
- * Subscribe to platform stats updated events (global).
486
- * Emitted after every trade with enriched token price, market cap, and supply data.
487
- *
488
- * @param callback Callback function receiving StatsUpdatedEvent
489
- * @returns Function to unsubscribe
490
- * @since 8.3.0
491
- */
492
- subscribeStatsUpdated(callback: (event: StatsUpdatedEvent) => void): () => void;
493
- /**
494
- * Subscribe to engagement stats updated events (global).
495
- * Emitted by the chat flush job every ~15 seconds when chat activity occurs.
496
- * Contains updated chat/comment counts for the token.
497
- *
498
- * @param callback Callback function receiving EngagementStatsUpdatedEvent
499
- * @returns Function to unsubscribe
500
- * @since 8.5.0
373
+ * @param tokenName Token name to subscribe to
374
+ * @param callbacks Event callbacks for this token
375
+ * @returns Promise that resolves when the server confirms the room
376
+ * @throws ValidationError if the token name is empty
377
+ * @throws Error if the connection fails or the confirmation times out (what this call registered is then released)
501
378
  */
502
- subscribeEngagementStatsUpdated(callback: (event: EngagementStatsUpdatedEvent) => void): () => void;
379
+ subscribeToStream(tokenName: string, callbacks?: StreamEventCallbacks): Promise<StreamSubscribedEvent>;
380
+ private waitForRoom;
381
+ private dropExplicitHold;
503
382
  /**
504
- * Set global event callbacks (not per-room)
383
+ * Remove everything `subscribeToStream` registered for a token. Other subscribers of the token (from the
384
+ * `subscribe*` methods) are untouched, and the room is left only when none remains.
505
385
  *
506
- * @param callbacks Global event callbacks
386
+ * @param tokenName Token name to unsubscribe from
507
387
  */
508
- setGlobalCallbacks(callbacks: StreamEventCallbacks): void;
509
- /**
510
- * Get list of currently subscribed tokens
388
+ unsubscribeFromStream(tokenName: string): void;
389
+ /** Stream status changes (`STREAM_STATUS`) of a token. @since 9.0.0 */
390
+ subscribeStreamStatus(tokenName: string, listener: RealtimeListener<'STREAM_STATUS'>): Unsubscribe;
391
+ /** Viewer count changes (`VIEWER_COUNT`) of a token. @since 9.0.0 */
392
+ subscribeViewerCount(tokenName: string, listener: RealtimeListener<'VIEWER_COUNT'>): Unsubscribe;
393
+ /** Recording changes (`RECORDING_STATUS`) of a token. @since 9.0.0 */
394
+ subscribeRecordingStatus(tokenName: string, listener: RealtimeListener<'RECORDING_STATUS'>): Unsubscribe;
395
+ /** Recording count changes (`RECORDINGS_COUNT_UPDATED`) of a token. @since 9.0.0 */
396
+ subscribeRecordingsCountUpdated(tokenName: string, listener: RealtimeListener<'RECORDINGS_COUNT_UPDATED'>): Unsubscribe;
397
+ /** Simulcast target changes (`SIMULCAST_STATUS`) of a token. @since 9.0.0 */
398
+ subscribeSimulcastStatus(tokenName: string, listener: RealtimeListener<'SIMULCAST_STATUS'>): Unsubscribe;
399
+ /** A recording's download is ready (`DOWNLOAD_READY`, sent to the stream owner). @since 9.0.0 */
400
+ subscribeDownloadReady(tokenName: string, listener: RealtimeListener<'DOWNLOAD_READY'>): Unsubscribe;
401
+ /**
402
+ * The next live stream's countdown changed (`STREAM_COUNTDOWN_UPDATED`). Fed from `TOKEN_CONFIG_UPDATED`
403
+ * (the backend folds the countdown into the config delta). @since 9.0.0
404
+ */
405
+ subscribeCountdownUpdated(tokenName: string, listener: RealtimeListener<'STREAM_COUNTDOWN_UPDATED'>): Unsubscribe;
406
+ /**
407
+ * The stream language changed (`STREAM_LANGUAGE_UPDATED`). Fed from `TOKEN_CONFIG_UPDATED`.
408
+ * @since 9.0.0
409
+ */
410
+ subscribeLanguageUpdated(tokenName: string, listener: RealtimeListener<'STREAM_LANGUAGE_UPDATED'>): Unsubscribe;
411
+ /** Stream control changes (`STREAM_CONTROL_STATUS_CHANGED`) of a token. @since 9.0.0 */
412
+ subscribeStreamControlStatusChanged(tokenName: string, listener: RealtimeListener<'STREAM_CONTROL_STATUS_CHANGED'>): Unsubscribe;
413
+ /** Chat and comment counts (`ENGAGEMENT_STATS_UPDATED`) of a token, about every 15 seconds. @since 8.5.0 */
414
+ subscribeEngagementStatsUpdated(tokenName: string, listener: RealtimeListener<'ENGAGEMENT_STATS_UPDATED'>): Unsubscribe;
415
+ /** New chat messages (`STREAM_CHAT_MESSAGE`) of a token. @since 9.0.0 */
416
+ subscribeChatMessages(tokenName: string, listener: RealtimeListener<'STREAM_CHAT_MESSAGE'>): Unsubscribe;
417
+ /** Confirmation that this socket's chat message was stored (`STREAM_CHAT_SENT`). @since 9.0.0 */
418
+ subscribeChatSent(tokenName: string, listener: RealtimeListener<'STREAM_CHAT_SENT'>): Unsubscribe;
419
+ /** Edited chat messages (`STREAM_CHAT_UPDATED`) of a token. @since 9.0.0 */
420
+ subscribeChatUpdated(tokenName: string, listener: RealtimeListener<'STREAM_CHAT_UPDATED'>): Unsubscribe;
421
+ /** Deleted chat messages (`STREAM_CHAT_DELETED`) of a token. @since 9.0.0 */
422
+ subscribeChatDeleted(tokenName: string, listener: RealtimeListener<'STREAM_CHAT_DELETED'>): Unsubscribe;
423
+ /** Pinned chat messages (`STREAM_CHAT_PINNED`) of a token. @since 9.0.0 */
424
+ subscribeChatPinned(tokenName: string, listener: RealtimeListener<'STREAM_CHAT_PINNED'>): Unsubscribe;
425
+ /** Unpinned chat messages (`STREAM_CHAT_UNPINNED`) of a token. @since 9.0.0 */
426
+ subscribeChatUnpinned(tokenName: string, listener: RealtimeListener<'STREAM_CHAT_UNPINNED'>): Unsubscribe;
427
+ /** A token's chat was enabled or disabled (`CHAT_STATUS_CHANGED`). @since 9.0.0 */
428
+ subscribeChatStatus(tokenName: string, listener: RealtimeListener<'CHAT_STATUS_CHANGED'>): Unsubscribe;
429
+ /** A token's chat slow mode changed (`SLOW_MODE_CHANGED`). @since 9.0.0 */
430
+ subscribeChatSlowMode(tokenName: string, listener: RealtimeListener<'SLOW_MODE_CHANGED'>): Unsubscribe;
431
+ /** Who is typing in a token's chat (`USER_TYPING`). @since 9.0.0 */
432
+ subscribeTypingIndicator(tokenName: string, listener: RealtimeListener<'USER_TYPING'>): Unsubscribe;
433
+ /** Ephemeral emoji reactions (`STREAM_REACTION`) of a token. @since 9.0.0 */
434
+ subscribeReactions(tokenName: string, listener: RealtimeListener<'STREAM_REACTION'>): Unsubscribe;
435
+ /** A reaction was added to a message (`CONTENT_REACTION_ADDED`) of a token. @since 9.0.0 */
436
+ subscribeContentReactionAdded(tokenName: string, listener: RealtimeListener<'CONTENT_REACTION_ADDED'>): Unsubscribe;
437
+ /** A reaction was removed from a message (`CONTENT_REACTION_REMOVED`) of a token. @since 9.0.0 */
438
+ subscribeContentReactionRemoved(tokenName: string, listener: RealtimeListener<'CONTENT_REACTION_REMOVED'>): Unsubscribe;
439
+ /** Trades (`TRADE_EXECUTED`) of a token. @since 6.0.0 */
440
+ subscribeTradeExecuted(tokenName: string, listener: RealtimeListener<'TRADE_EXECUTED'>): Unsubscribe;
441
+ /** The authenticated user's balance change after a trade (`BALANCE_UPDATED`) of a token. @since 9.0.0 */
442
+ subscribeBalanceUpdated(tokenName: string, listener: RealtimeListener<'BALANCE_UPDATED'>): Unsubscribe;
443
+ /** A token was banned (`TOKEN_BANNED`). @since 6.0.0 */
444
+ subscribeTokenBanned(tokenName: string, listener: RealtimeListener<'TOKEN_BANNED'>): Unsubscribe;
445
+ /** A token ban was lifted (`TOKEN_UNBANNED`). @since 6.0.0 */
446
+ subscribeTokenUnbanned(tokenName: string, listener: RealtimeListener<'TOKEN_UNBANNED'>): Unsubscribe;
447
+ /** A moderator invite was created (`MODERATOR_INVITE_CREATED`) for a token. @since 8.5.0 */
448
+ subscribeModeratorInviteCreated(tokenName: string, listener: RealtimeListener<'MODERATOR_INVITE_CREATED'>): Unsubscribe;
449
+ /** A moderator was added (`MODERATOR_ADDED`) to a token. @since 6.0.0 */
450
+ subscribeModeratorAdded(tokenName: string, listener: RealtimeListener<'MODERATOR_ADDED'>): Unsubscribe;
451
+ /** A moderator was removed (`MODERATOR_REMOVED`) from a token. @since 6.0.0 */
452
+ subscribeModeratorRemoved(tokenName: string, listener: RealtimeListener<'MODERATOR_REMOVED'>): Unsubscribe;
453
+ /** A moderator's role changed (`MODERATOR_ROLE_UPDATED`) on a token. @since 6.0.0 */
454
+ subscribeModeratorRoleUpdated(tokenName: string, listener: RealtimeListener<'MODERATOR_ROLE_UPDATED'>): Unsubscribe;
455
+ /** A token's metadata changed (`POOL_METADATA_UPDATED`). @since 6.0.0 */
456
+ subscribePoolMetadataUpdated(tokenName: string, listener: RealtimeListener<'POOL_METADATA_UPDATED'>): Unsubscribe;
457
+ /** A token's social links changed (`POOL_SOCIAL_LINKS_UPDATED`). @since 6.0.0 */
458
+ subscribePoolSocialLinksUpdated(tokenName: string, listener: RealtimeListener<'POOL_SOCIAL_LINKS_UPDATED'>): Unsubscribe;
459
+ /** A badge was assigned to a token (`POOL_BADGE_ASSIGNED`). @since 6.0.0 */
460
+ subscribePoolBadgeAssigned(tokenName: string, listener: RealtimeListener<'POOL_BADGE_ASSIGNED'>): Unsubscribe;
461
+ /** A token's holder count changed (`HOLDER_COUNT_UPDATED`). @since 6.0.0 */
462
+ subscribeHolderCountUpdated(tokenName: string, listener: RealtimeListener<'HOLDER_COUNT_UPDATED'>): Unsubscribe;
463
+ /** A token's configuration changed (`TOKEN_CONFIG_UPDATED`, a delta of the changed fields). @since 8.4.0 */
464
+ subscribeTokenConfigUpdated(tokenName: string, listener: RealtimeListener<'TOKEN_CONFIG_UPDATED'>): Unsubscribe;
465
+ /** New comments (`COMMENT_CREATED`) on a token. Joins the token's comment room. @since 6.0.0 */
466
+ subscribeCommentCreated(tokenName: string, listener: RealtimeListener<'COMMENT_CREATED'>): Unsubscribe;
467
+ /** Edited comments (`COMMENT_UPDATED`) on a token. Joins the token's comment room. @since 9.0.0 */
468
+ subscribeCommentUpdated(tokenName: string, listener: RealtimeListener<'COMMENT_UPDATED'>): Unsubscribe;
469
+ /** Deleted comments (`COMMENT_DELETED`) on a token. Joins the token's comment room. @since 9.0.0 */
470
+ subscribeCommentDeleted(tokenName: string, listener: RealtimeListener<'COMMENT_DELETED'>): Unsubscribe;
471
+ /** Price, market cap and supply after a trade (`STATS_UPDATED`), every token. Joins the global feed. @since 8.3.0 */
472
+ subscribeStatsUpdated(listener: RealtimeListener<'STATS_UPDATED'>): Unsubscribe;
473
+ /** A token pool was created (`POOL_CREATED`). Joins the global feed. @since 9.0.0 */
474
+ subscribePoolCreated(listener: RealtimeListener<'POOL_CREATED'>): Unsubscribe;
475
+ /** Streaming was switched on or off site-wide (`STREAM_GLOBAL_STATUS`). Joins the global feed. @since 9.0.0 */
476
+ subscribeStreamGlobalStatus(listener: RealtimeListener<'STREAM_GLOBAL_STATUS'>): Unsubscribe;
477
+ /** Chat was switched on or off site-wide (`STREAM_CHAT_GLOBAL_STATUS`). Joins the global feed. @since 9.0.0 */
478
+ subscribeChatGlobalStatus(listener: RealtimeListener<'STREAM_CHAT_GLOBAL_STATUS'>): Unsubscribe;
479
+ /** Comments were switched on or off site-wide (`COMMENTS_GLOBAL_STATUS`). Joins the global feed. @since 9.0.0 */
480
+ subscribeCommentsGlobalStatus(listener: RealtimeListener<'COMMENTS_GLOBAL_STATUS'>): Unsubscribe;
481
+ /** Webhooks were switched on or off site-wide (`WEBHOOKS_GLOBAL_STATUS`). Joins the global feed. @since 9.0.0 */
482
+ subscribeWebhooksGlobalStatus(listener: RealtimeListener<'WEBHOOKS_GLOBAL_STATUS'>): Unsubscribe;
483
+ /** AI moderation was switched on or off site-wide (`AI_MODERATION_GLOBAL_STATUS`). Joins the global feed. @since 9.0.0 */
484
+ subscribeAIModerationGlobalStatus(listener: RealtimeListener<'AI_MODERATION_GLOBAL_STATUS'>): Unsubscribe;
485
+ /** A site-wide switch changed (`SITE_CONFIG_CHANGED`). Joins the global feed. @since 9.0.0 */
486
+ subscribeSiteConfigChanged(listener: RealtimeListener<'SITE_CONFIG_CHANGED'>): Unsubscribe;
487
+ /**
488
+ * The site-wide switches announced since the feed was joined (`undefined`: none announced yet).
489
+ *
490
+ * @since 9.0.0
491
+ */
492
+ getSiteConfigState(): SiteConfigState;
493
+ /** An overseer was added (`OVERSEER_ADDED`). @since 6.0.0 */
494
+ subscribeOverseerAdded(listener: RealtimeListener<'OVERSEER_ADDED'>): Unsubscribe;
495
+ /** An overseer was removed (`OVERSEER_REMOVED`). @since 6.0.0 */
496
+ subscribeOverseerRemoved(listener: RealtimeListener<'OVERSEER_REMOVED'>): Unsubscribe;
497
+ /** The authenticated user's profile changed (`USER_PROFILE_UPDATED`). @since 6.0.0 */
498
+ subscribeUserProfileUpdated(listener: RealtimeListener<'USER_PROFILE_UPDATED'>): Unsubscribe;
499
+ /** An API key was created (`API_KEY_CREATED`). @since 6.0.0 */
500
+ subscribeApiKeyCreated(listener: RealtimeListener<'API_KEY_CREATED'>): Unsubscribe;
501
+ /** An API key was updated (`API_KEY_UPDATED`). @since 6.0.0 */
502
+ subscribeApiKeyUpdated(listener: RealtimeListener<'API_KEY_UPDATED'>): Unsubscribe;
503
+ /** An API key was revoked (`API_KEY_REVOKED`). @since 6.0.0 */
504
+ subscribeApiKeyRevoked(listener: RealtimeListener<'API_KEY_REVOKED'>): Unsubscribe;
505
+ /** A token was banned, any token (`TOKEN_BANNED`, the overseer room). @since 9.0.0 */
506
+ subscribeGlobalTokenBanned(listener: RealtimeListener<'TOKEN_BANNED'>): Unsubscribe;
507
+ /** A token ban was lifted, any token (`TOKEN_UNBANNED`, the overseer room). @since 9.0.0 */
508
+ subscribeGlobalTokenUnbanned(listener: RealtimeListener<'TOKEN_UNBANNED'>): Unsubscribe;
509
+ /** The authenticated user was added as a moderator, any token (`MODERATOR_ADDED`, the user room). @since 9.0.0 */
510
+ subscribeGlobalModeratorAdded(listener: RealtimeListener<'MODERATOR_ADDED'>): Unsubscribe;
511
+ /** The authenticated user was removed as a moderator, any token (`MODERATOR_REMOVED`). @since 9.0.0 */
512
+ subscribeGlobalModeratorRemoved(listener: RealtimeListener<'MODERATOR_REMOVED'>): Unsubscribe;
513
+ /** The authenticated user's moderator role changed, any token (`MODERATOR_ROLE_UPDATED`). @since 9.0.0 */
514
+ subscribeGlobalModeratorRoleUpdated(listener: RealtimeListener<'MODERATOR_ROLE_UPDATED'>): Unsubscribe;
515
+ /** A moderator invite the authenticated user made, any token (`MODERATOR_INVITE_CREATED`). @since 9.0.0 */
516
+ subscribeGlobalModeratorInviteCreated(listener: RealtimeListener<'MODERATOR_INVITE_CREATED'>): Unsubscribe;
517
+ /** Content was flagged, any token (`CONTENT_FLAGGED`, the overseer room). @since 9.0.0 */
518
+ subscribeContentFlagged(listener: RealtimeListener<'CONTENT_FLAGGED'>): Unsubscribe;
519
+ /** A flag was resolved, any token (`FLAG_RESOLVED`, the overseer room). @since 9.0.0 */
520
+ subscribeFlagResolved(listener: RealtimeListener<'FLAG_RESOLVED'>): Unsubscribe;
521
+ /** An AI analysis of a flag finished (`AI_MODERATION_COMPLETE`, the overseer room). @since 9.0.0 */
522
+ subscribeAIModerationComplete(listener: RealtimeListener<'AI_MODERATION_COMPLETE'>): Unsubscribe;
523
+ /** An AI analysis of a flag failed (`AI_MODERATION_FAILED`, the overseer room). @since 9.0.0 */
524
+ subscribeAIModerationFailed(listener: RealtimeListener<'AI_MODERATION_FAILED'>): Unsubscribe;
525
+ /** The authenticated user was banned (`USER_BANNED`; overseers see every ban). @since 9.0.0 */
526
+ subscribeUserBanned(listener: RealtimeListener<'USER_BANNED'>): Unsubscribe;
527
+ /** The authenticated user was unbanned (`USER_UNBANNED`; overseers see every unban). @since 9.0.0 */
528
+ subscribeUserUnbanned(listener: RealtimeListener<'USER_UNBANNED'>): Unsubscribe;
529
+ /** A banned user's action was refused (`BAN_ENFORCEMENT`). @since 9.0.0 */
530
+ subscribeBanEnforcement(listener: RealtimeListener<'BAN_ENFORCEMENT'>): Unsubscribe;
531
+ /** The most recent trades, broadcast to every client (`TRADE_UPDATE_NOTIFY`). @since 9.0.0 */
532
+ subscribeTradeUpdateNotify(listener: RealtimeListener<'TRADE_UPDATE_NOTIFY'>): Unsubscribe;
533
+ /** A reaction was refused (`stream_reaction_error`), any token. @since 9.0.0 */
534
+ subscribeReactionErrors(listener: RealtimeListener<'stream_reaction_error'>): Unsubscribe;
535
+ /** A chat message was refused (`stream_chat_error`), any token. @since 9.0.0 */
536
+ subscribeChatErrors(listener: RealtimeListener<'stream_chat_error'>): Unsubscribe;
537
+ /**
538
+ * A server handler failed (`exception`): an unauthenticated call, an invalid token. Authentication
539
+ * failures also resolve the pending {@link StreamWebSocketService.authenticate} with `false`.
540
+ *
541
+ * @since 9.0.0
542
+ */
543
+ subscribeException(listener: RealtimeListener<'exception'>): Unsubscribe;
544
+ /**
545
+ * Get list of tokens whose room has a subscriber
511
546
  */
512
547
  getSubscribedTokens(): string[];
513
548
  /**
514
- * Check if connected to the WebSocket server
515
- */
516
- isConnected(): boolean;
517
- /**
518
- * Check if authenticated for chat operations
519
- */
520
- isAuthenticatedForChat(): boolean;
521
- /**
522
- * Subscribe to the global feed for unified real-time updates
523
- *
524
- * Provides homepage/listing views with token summary events and site config events.
525
- * Automatically reconnects on disconnect if configured.
526
- *
527
- * Feed token events routed through global feed:
528
- * - STREAM_STATUS, TRADE_EXECUTED, HOLDER_COUNT_UPDATED, POOL_BADGE_ASSIGNED,
529
- * VIEWER_COUNT, TOKEN_CONFIG_UPDATED, STATS_UPDATED
530
- *
531
- * Dedup behavior: When a client is subscribed to both a token room AND the global
532
- * feed, overlapping events are delivered only via the token room callbacks (the backend
533
- * uses `.except()` to prevent double delivery). Global feed callbacks fire only for
534
- * tokens the client has NOT individually subscribed to.
535
- *
536
- * @param callbacks Optional callbacks for feed events
537
- * @returns Promise resolving to subscription confirmation
538
- * @throws ValidationError if WebSocket not connected
539
- *
540
- * @example
541
- * ```typescript
542
- * const subscription = await service.subscribeToGlobalFeed({
543
- * onStreamStatus: (event) => updateCard(event.tokenName, event),
544
- * onTradeExecuted: (event) => addTradeNotification(event),
545
- * onStatsUpdated: (event) => updatePriceCard(event.tokenName, event),
546
- * onTokenConfigUpdated: (event) => updateConfigCard(event.tokenName, event),
547
- * onStreamGlobalStatus: (event) => setStreamingEnabled(event.enabled),
548
- * });
549
- *
550
- * // Later: unsubscribe
551
- * service.unsubscribeFromGlobalFeed();
552
- * ```
553
- *
554
- * @since 7.0.0
555
- */
556
- subscribeToGlobalFeed(callbacks?: GlobalFeedEventCallbacks): Promise<GlobalFeedSubscribedEvent>;
557
- /**
558
- * Unsubscribe from the global feed
559
- *
560
- * Stops receiving feed events and cleans up subscriptions.
561
- *
562
- * @example
563
- * ```typescript
564
- * service.unsubscribeFromGlobalFeed();
565
- * ```
549
+ * Check if the global feed has a subscriber
566
550
  *
567
551
  * @since 7.0.0
568
552
  */
569
- unsubscribeFromGlobalFeed(): void;
570
- /**
571
- * Check if currently subscribed to global feed
572
- *
573
- * @returns True if subscribed to global feed
574
- * @since 7.0.0
575
- */
576
553
  isSubscribedToGlobalFeed(): boolean;
577
- /**
578
- * Update global feed event callbacks
579
- *
580
- * Allows updating which events you want to receive after subscription.
581
- *
582
- * @param callbacks Callbacks for feed events
583
- * @since 7.0.0
584
- */
585
- setGlobalFeedCallbacks(callbacks: GlobalFeedEventCallbacks): void;
586
554
  /**
587
555
  * Get the underlying Socket.IO instance
588
556
  */
589
557
  getSocket(): Socket | null;
590
558
  /**
591
- * Disconnect from the stream WebSocket server
592
- *
593
- * Cleans up all listeners, subscriptions, and buffers.
594
- * All cleanup operations are wrapped in try-catch to ensure
595
- * complete cleanup even if individual steps fail.
559
+ * Close the socket and release everything the service holds: every socket listener (the Socket's and
560
+ * the Manager's), every timer, every subscriber, every pending connect / authenticate / subscribe (they
561
+ * settle: connects reject, authenticates resolve `false`, subscribes reject). An unsubscribe handed out
562
+ * earlier stays harmless. The service can connect and subscribe again afterwards.
596
563
  */
597
564
  disconnect(): void;
565
+ /**
566
+ * {@link StreamWebSocketService.disconnect}, and the service refuses everything afterwards (a
567
+ * subscribe returns an inert unsubscribe, a connect rejects). Called when the owning SDK is disposed.
568
+ */
569
+ dispose(): void;
598
570
  }
599
571
  //# sourceMappingURL=StreamWebSocketService.d.ts.map