@solana/rpc-subscriptions-channel-websocket 5.1.0-canary-20251202173352 → 5.1.0-canary-20251203213248

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../event-target-impl/src/index.browser.ts","../../ws-impl/src/index.browser.ts","../src/websocket-channel.ts"],"names":["EventTarget","index_browser_default","SolanaError","SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED","SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_FAILED_TO_CONNECT","getDataPublisherFromEventEmitter","SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CLOSED_BEFORE_MESSAGE_BUFFERED"],"mappings":"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","file":"index.browser.cjs","sourcesContent":["export const AbortController = globalThis.AbortController;\nexport const EventTarget = globalThis.EventTarget;\n","export default globalThis.WebSocket;\n","import {\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CLOSED_BEFORE_MESSAGE_BUFFERED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_FAILED_TO_CONNECT,\n SolanaError,\n} from '@solana/errors';\nimport { EventTarget } from '@solana/event-target-impl';\nimport { RpcSubscriptionsChannel } from '@solana/rpc-subscriptions-spec';\nimport { getDataPublisherFromEventEmitter } from '@solana/subscribable';\nimport WebSocket from '@solana/ws-impl';\n\nexport type Config = Readonly<{\n /**\n * The number of bytes to admit into the WebSocket's send buffer before queueing messages on the\n * client.\n *\n * When you call {@link RpcSubscriptionsChannel.send | `send()`} on a `WebSocket` the runtime\n * might add the message to a buffer rather than send it right away. In the event that\n * `socket.bufferedAmount` exceeds the value configured here, messages will be added to a queue\n * in your application code instead of being sent to the WebSocket, until such time as the\n * `bufferedAmount` falls back below the high watermark.\n */\n sendBufferHighWatermark: number;\n /**\n * An `AbortSignal` to fire when you want to explicitly close the `WebSocket`.\n *\n * If the channel is open it will be closed with a normal closure code\n * (https://www.rfc-editor.org/rfc/rfc6455.html#section-7.4.1) If the channel has not been\n * established yet, firing this signal will result in the `AbortError` being thrown to the\n * caller who was trying to open the channel.\n */\n signal: AbortSignal;\n /**\n * A string representing the target endpoint.\n *\n * In Node, it must be an absolute URL using the `ws` or `wss` protocol.\n */\n url: string;\n}>;\n\ntype WebSocketMessage = ArrayBufferLike | ArrayBufferView | Blob | string;\n\nconst NORMAL_CLOSURE_CODE = 1000; // https://www.rfc-editor.org/rfc/rfc6455.html#section-7.4.1\n\n/**\n * Creates an object that represents an open channel to a `WebSocket` server.\n *\n * You can use it to send messages by calling its\n * {@link RpcSubscriptionsChannel.send | `send()`} function and you can receive them by subscribing\n * to the {@link RpcSubscriptionChannelEvents} it emits.\n */\nexport function createWebSocketChannel({\n sendBufferHighWatermark,\n signal,\n url,\n}: Config): Promise<RpcSubscriptionsChannel<WebSocketMessage, string>> {\n if (signal.aborted) {\n // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\n return Promise.reject(signal.reason);\n }\n let bufferDrainWatcher: Readonly<{ onCancel(): void; promise: Promise<void> }> | undefined;\n let hasConnected = false;\n const listenerRemovers = new Set<() => void>();\n function cleanupListeners() {\n listenerRemovers.forEach(r => {\n r();\n });\n listenerRemovers.clear();\n }\n function handleAbort() {\n cleanupListeners();\n if (!hasConnected) {\n rejectOpen(signal.reason);\n }\n if (webSocket.readyState !== WebSocket.CLOSED && webSocket.readyState !== WebSocket.CLOSING) {\n webSocket.close(NORMAL_CLOSURE_CODE);\n }\n }\n function handleClose(ev: CloseEvent) {\n cleanupListeners();\n bufferDrainWatcher?.onCancel();\n signal.removeEventListener('abort', handleAbort);\n webSocket.removeEventListener('close', handleClose);\n webSocket.removeEventListener('error', handleError);\n webSocket.removeEventListener('message', handleMessage);\n webSocket.removeEventListener('open', handleOpen);\n if (!signal.aborted && !(ev.wasClean && ev.code === NORMAL_CLOSURE_CODE)) {\n eventTarget.dispatchEvent(\n new CustomEvent('error', {\n detail: new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED, {\n cause: ev,\n }),\n }),\n );\n }\n }\n function handleError(ev: Event) {\n if (signal.aborted) {\n return;\n }\n if (!hasConnected) {\n const failedToConnectError = new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_FAILED_TO_CONNECT, {\n errorEvent: ev,\n });\n rejectOpen(failedToConnectError);\n eventTarget.dispatchEvent(\n new CustomEvent('error', {\n detail: failedToConnectError,\n }),\n );\n }\n }\n function handleMessage(ev: MessageEvent) {\n if (signal.aborted) {\n return;\n }\n eventTarget.dispatchEvent(new CustomEvent('message', { detail: ev.data }));\n }\n const eventTarget = new EventTarget();\n const dataPublisher = getDataPublisherFromEventEmitter(eventTarget);\n function handleOpen() {\n hasConnected = true;\n resolveOpen({\n ...dataPublisher,\n async send(message) {\n if (webSocket.readyState !== WebSocket.OPEN) {\n throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED);\n }\n if (!bufferDrainWatcher && webSocket.bufferedAmount > sendBufferHighWatermark) {\n let onCancel!: () => void;\n const promise = new Promise<void>((resolve, reject) => {\n const intervalId = setInterval(() => {\n if (\n webSocket.readyState !== WebSocket.OPEN ||\n !(webSocket.bufferedAmount > sendBufferHighWatermark)\n ) {\n clearInterval(intervalId);\n bufferDrainWatcher = undefined;\n resolve();\n }\n }, 16);\n onCancel = () => {\n bufferDrainWatcher = undefined;\n clearInterval(intervalId);\n reject(\n new SolanaError(\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CLOSED_BEFORE_MESSAGE_BUFFERED,\n ),\n );\n };\n });\n bufferDrainWatcher = {\n onCancel,\n promise,\n };\n }\n if (bufferDrainWatcher) {\n if (ArrayBuffer.isView(message) && !(message instanceof DataView)) {\n const TypedArrayConstructor = message.constructor as {\n new (...args: [typeof message]): typeof message;\n };\n // Clone the message to prevent mutation while queued.\n message = new TypedArrayConstructor(message);\n }\n await bufferDrainWatcher.promise;\n }\n webSocket.send(message);\n },\n });\n }\n const webSocket = new WebSocket(url);\n signal.addEventListener('abort', handleAbort);\n webSocket.addEventListener('close', handleClose);\n webSocket.addEventListener('error', handleError);\n webSocket.addEventListener('message', handleMessage);\n webSocket.addEventListener('open', handleOpen);\n let rejectOpen!: (e: SolanaError) => void;\n let resolveOpen!: (value: RpcSubscriptionsChannel<WebSocketMessage, string>) => void;\n return new Promise<RpcSubscriptionsChannel<WebSocketMessage, string>>((resolve, reject) => {\n rejectOpen = reject;\n resolveOpen = resolve;\n });\n}\n"]}
1
+ {"version":3,"sources":["../../event-target-impl/src/index.browser.ts","../../ws-impl/src/index.browser.ts","../src/websocket-channel.ts"],"names":["EventTarget","index_browser_default","SolanaError","SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED","SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_FAILED_TO_CONNECT","getDataPublisherFromEventEmitter","SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CLOSED_BEFORE_MESSAGE_BUFFERED"],"mappings":"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","file":"index.browser.cjs","sourcesContent":["export const AbortController = globalThis.AbortController;\nexport const EventTarget = globalThis.EventTarget;\n","export default globalThis.WebSocket;\n","import {\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CLOSED_BEFORE_MESSAGE_BUFFERED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_FAILED_TO_CONNECT,\n SolanaError,\n} from '@solana/errors';\nimport { EventTarget } from '@solana/event-target-impl';\nimport { RpcSubscriptionsChannel } from '@solana/rpc-subscriptions-spec';\nimport { getDataPublisherFromEventEmitter } from '@solana/subscribable';\nimport WebSocket from '@solana/ws-impl';\n\nexport type Config = Readonly<{\n /**\n * The number of bytes to admit into the WebSocket's send buffer before queueing messages on the\n * client.\n *\n * When you call {@link RpcSubscriptionsChannel.send | `send()`} on a `WebSocket` the runtime\n * might add the message to a buffer rather than send it right away. In the event that\n * `socket.bufferedAmount` exceeds the value configured here, messages will be added to a queue\n * in your application code instead of being sent to the WebSocket, until such time as the\n * `bufferedAmount` falls back below the high watermark.\n */\n sendBufferHighWatermark: number;\n /**\n * An `AbortSignal` to fire when you want to explicitly close the `WebSocket`.\n *\n * If the channel is open it will be closed with a normal closure code\n * (https://www.rfc-editor.org/rfc/rfc6455.html#section-7.4.1) If the channel has not been\n * established yet, firing this signal will result in the `AbortError` being thrown to the\n * caller who was trying to open the channel.\n */\n signal: AbortSignal;\n /**\n * A string representing the target endpoint.\n *\n * In Node, it must be an absolute URL using the `ws` or `wss` protocol.\n */\n url: string;\n}>;\n\ntype WebSocketMessage = ArrayBufferLike | ArrayBufferView | Blob | string;\n\nconst NORMAL_CLOSURE_CODE = 1000; // https://www.rfc-editor.org/rfc/rfc6455.html#section-7.4.1\n\n/**\n * Creates an object that represents an open channel to a `WebSocket` server.\n *\n * You can use it to send messages by calling its\n * {@link RpcSubscriptionsChannel.send | `send()`} function and you can receive them by subscribing\n * to the {@link RpcSubscriptionChannelEvents} it emits.\n */\nexport function createWebSocketChannel({\n sendBufferHighWatermark,\n signal,\n url,\n}: Config): Promise<RpcSubscriptionsChannel<WebSocketMessage, string>> {\n if (signal.aborted) {\n // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\n return Promise.reject(signal.reason);\n }\n let bufferDrainWatcher: Readonly<{ onCancel(): void; promise: Promise<void> }> | undefined;\n let hasConnected = false;\n const listenerRemovers = new Set<() => void>();\n function cleanupListeners() {\n listenerRemovers.forEach(r => {\n r();\n });\n listenerRemovers.clear();\n }\n function handleAbort() {\n cleanupListeners();\n if (!hasConnected) {\n rejectOpen(signal.reason);\n }\n if (webSocket.readyState !== WebSocket.CLOSED && webSocket.readyState !== WebSocket.CLOSING) {\n webSocket.close(NORMAL_CLOSURE_CODE);\n }\n }\n function handleClose(ev: CloseEvent) {\n cleanupListeners();\n bufferDrainWatcher?.onCancel();\n signal.removeEventListener('abort', handleAbort);\n webSocket.removeEventListener('close', handleClose);\n webSocket.removeEventListener('error', handleError);\n webSocket.removeEventListener('message', handleMessage);\n webSocket.removeEventListener('open', handleOpen);\n if (!signal.aborted && !(ev.wasClean && ev.code === NORMAL_CLOSURE_CODE)) {\n eventTarget.dispatchEvent(\n new CustomEvent('error', {\n detail: new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED, {\n cause: ev,\n }),\n }),\n );\n }\n }\n function handleError(ev: Event) {\n if (signal.aborted) {\n return;\n }\n if (!hasConnected) {\n const failedToConnectError = new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_FAILED_TO_CONNECT, {\n errorEvent: ev,\n });\n rejectOpen(failedToConnectError);\n eventTarget.dispatchEvent(\n new CustomEvent('error', {\n detail: failedToConnectError,\n }),\n );\n }\n }\n function handleMessage(ev: MessageEvent) {\n if (signal.aborted) {\n return;\n }\n eventTarget.dispatchEvent(new CustomEvent('message', { detail: ev.data }));\n }\n const eventTarget = new EventTarget();\n const dataPublisher = getDataPublisherFromEventEmitter(eventTarget);\n function handleOpen() {\n hasConnected = true;\n resolveOpen({\n ...dataPublisher,\n async send(message) {\n if (webSocket.readyState !== WebSocket.OPEN) {\n throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED);\n }\n if (!bufferDrainWatcher && webSocket.bufferedAmount > sendBufferHighWatermark) {\n let onCancel!: () => void;\n const promise = new Promise<void>((resolve, reject) => {\n const intervalId = setInterval(() => {\n if (\n webSocket.readyState !== WebSocket.OPEN ||\n !(webSocket.bufferedAmount > sendBufferHighWatermark)\n ) {\n clearInterval(intervalId);\n bufferDrainWatcher = undefined;\n resolve();\n }\n }, 16);\n onCancel = () => {\n bufferDrainWatcher = undefined;\n clearInterval(intervalId);\n reject(\n new SolanaError(\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CLOSED_BEFORE_MESSAGE_BUFFERED,\n ),\n );\n };\n });\n bufferDrainWatcher = {\n onCancel,\n promise,\n };\n }\n if (bufferDrainWatcher) {\n if (ArrayBuffer.isView(message) && !(message instanceof DataView)) {\n const TypedArrayConstructor = message.constructor as {\n new (...args: [typeof message]): typeof message;\n };\n // Clone the message to prevent mutation while queued.\n message = new TypedArrayConstructor(message);\n }\n await bufferDrainWatcher.promise;\n }\n webSocket.send(message);\n },\n });\n }\n const webSocket = new WebSocket(url);\n signal.addEventListener('abort', handleAbort);\n webSocket.addEventListener('close', handleClose);\n webSocket.addEventListener('error', handleError);\n webSocket.addEventListener('message', handleMessage);\n webSocket.addEventListener('open', handleOpen);\n let rejectOpen!: (e: SolanaError) => void;\n let resolveOpen!: (value: RpcSubscriptionsChannel<WebSocketMessage, string>) => void;\n return new Promise<RpcSubscriptionsChannel<WebSocketMessage, string>>((resolve, reject) => {\n rejectOpen = reject;\n resolveOpen = resolve;\n });\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../event-target-impl/src/index.browser.ts","../../ws-impl/src/index.browser.ts","../src/websocket-channel.ts"],"names":["EventTarget","index_browser_default"],"mappings":";;;;AAAO,IACMA,IAAc,UAAW,CAAA,WAAA;;;ACDtC,IAAOC,IAAQ,UAAW,CAAA,SAAA;;;AC0C1B,IAAM,mBAAsB,GAAA,GAAA;AASrB,SAAS,sBAAuB,CAAA;AAAA,EACnC,uBAAA;AAAA,EACA,MAAA;AAAA,EACA;AACJ,CAAuE,EAAA;AACnE,EAAA,IAAI,OAAO,OAAS,EAAA;AAEhB,IAAO,OAAA,OAAA,CAAQ,MAAO,CAAA,MAAA,CAAO,MAAM,CAAA;AAAA;AAEvC,EAAI,IAAA,kBAAA;AACJ,EAAA,IAAI,YAAe,GAAA,KAAA;AACnB,EAAM,MAAA,gBAAA,uBAAuB,GAAgB,EAAA;AAC7C,EAAA,SAAS,gBAAmB,GAAA;AACxB,IAAA,gBAAA,CAAiB,QAAQ,CAAK,CAAA,KAAA;AAC1B,MAAE,CAAA,EAAA;AAAA,KACL,CAAA;AACD,IAAA,gBAAA,CAAiB,KAAM,EAAA;AAAA;AAE3B,EAAA,SAAS,WAAc,GAAA;AACnB,IAAiB,gBAAA,EAAA;AACjB,IAAA,IAAI,CAAC,YAAc,EAAA;AACf,MAAA,UAAA,CAAW,OAAO,MAAM,CAAA;AAAA;AAE5B,IAAA,IAAI,UAAU,UAAe,KAAA,CAAA,CAAU,UAAU,SAAU,CAAA,UAAA,KAAe,EAAU,OAAS,EAAA;AACzF,MAAA,SAAA,CAAU,MAAM,mBAAmB,CAAA;AAAA;AACvC;AAEJ,EAAA,SAAS,YAAY,EAAgB,EAAA;AACjC,IAAiB,gBAAA,EAAA;AACjB,IAAA,kBAAA,EAAoB,QAAS,EAAA;AAC7B,IAAO,MAAA,CAAA,mBAAA,CAAoB,SAAS,WAAW,CAAA;AAC/C,IAAU,SAAA,CAAA,mBAAA,CAAoB,SAAS,WAAW,CAAA;AAClD,IAAU,SAAA,CAAA,mBAAA,CAAoB,SAAS,WAAW,CAAA;AAClD,IAAU,SAAA,CAAA,mBAAA,CAAoB,WAAW,aAAa,CAAA;AACtD,IAAU,SAAA,CAAA,mBAAA,CAAoB,QAAQ,UAAU,CAAA;AAChD,IAAI,IAAA,CAAC,OAAO,OAAW,IAAA,EAAE,GAAG,QAAY,IAAA,EAAA,CAAG,SAAS,mBAAsB,CAAA,EAAA;AACtE,MAAY,WAAA,CAAA,aAAA;AAAA,QACR,IAAI,YAAY,OAAS,EAAA;AAAA,UACrB,MAAA,EAAQ,IAAI,WAAA,CAAY,0DAA4D,EAAA;AAAA,YAChF,KAAO,EAAA;AAAA,WACV;AAAA,SACJ;AAAA,OACL;AAAA;AACJ;AAEJ,EAAA,SAAS,YAAY,EAAW,EAAA;AAC5B,IAAA,IAAI,OAAO,OAAS,EAAA;AAChB,MAAA;AAAA;AAEJ,IAAA,IAAI,CAAC,YAAc,EAAA;AACf,MAAM,MAAA,oBAAA,GAAuB,IAAI,WAAA,CAAY,0DAA4D,EAAA;AAAA,QACrG,UAAY,EAAA;AAAA,OACf,CAAA;AACD,MAAA,UAAA,CAAW,oBAAoB,CAAA;AAC/B,MAAY,WAAA,CAAA,aAAA;AAAA,QACR,IAAI,YAAY,OAAS,EAAA;AAAA,UACrB,MAAQ,EAAA;AAAA,SACX;AAAA,OACL;AAAA;AACJ;AAEJ,EAAA,SAAS,cAAc,EAAkB,EAAA;AACrC,IAAA,IAAI,OAAO,OAAS,EAAA;AAChB,MAAA;AAAA;AAEJ,IAAY,WAAA,CAAA,aAAA,CAAc,IAAI,WAAY,CAAA,SAAA,EAAW,EAAE,MAAQ,EAAA,EAAA,CAAG,IAAK,EAAC,CAAC,CAAA;AAAA;AAE7E,EAAM,MAAA,WAAA,GAAc,IAAI,CAAY,EAAA;AACpC,EAAM,MAAA,aAAA,GAAgB,iCAAiC,WAAW,CAAA;AAClE,EAAA,SAAS,UAAa,GAAA;AAClB,IAAe,YAAA,GAAA,IAAA;AACf,IAAY,WAAA,CAAA;AAAA,MACR,GAAG,aAAA;AAAA,MACH,MAAM,KAAK,OAAS,EAAA;AAChB,QAAI,IAAA,SAAA,CAAU,UAAe,KAAA,CAAA,CAAU,IAAM,EAAA;AACzC,UAAM,MAAA,IAAI,YAAY,0DAA0D,CAAA;AAAA;AAEpF,QAAA,IAAI,CAAC,kBAAA,IAAsB,SAAU,CAAA,cAAA,GAAiB,uBAAyB,EAAA;AAC3E,UAAI,IAAA,QAAA;AACJ,UAAA,MAAM,OAAU,GAAA,IAAI,OAAc,CAAA,CAAC,SAAS,MAAW,KAAA;AACnD,YAAM,MAAA,UAAA,GAAa,YAAY,MAAM;AACjC,cAAA,IACI,UAAU,UAAe,KAAA,CAAA,CAAU,QACnC,EAAE,SAAA,CAAU,iBAAiB,uBAC/B,CAAA,EAAA;AACE,gBAAA,aAAA,CAAc,UAAU,CAAA;AACxB,gBAAqB,kBAAA,GAAA,MAAA;AACrB,gBAAQ,OAAA,EAAA;AAAA;AACZ,eACD,EAAE,CAAA;AACL,YAAA,QAAA,GAAW,MAAM;AACb,cAAqB,kBAAA,GAAA,MAAA;AACrB,cAAA,aAAA,CAAc,UAAU,CAAA;AACxB,cAAA,MAAA;AAAA,gBACI,IAAI,WAAA;AAAA,kBACA;AAAA;AACJ,eACJ;AAAA,aACJ;AAAA,WACH,CAAA;AACD,UAAqB,kBAAA,GAAA;AAAA,YACjB,QAAA;AAAA,YACA;AAAA,WACJ;AAAA;AAEJ,QAAA,IAAI,kBAAoB,EAAA;AACpB,UAAA,IAAI,YAAY,MAAO,CAAA,OAAO,CAAK,IAAA,EAAE,mBAAmB,QAAW,CAAA,EAAA;AAC/D,YAAA,MAAM,wBAAwB,OAAQ,CAAA,WAAA;AAItC,YAAU,OAAA,GAAA,IAAI,sBAAsB,OAAO,CAAA;AAAA;AAE/C,UAAA,MAAM,kBAAmB,CAAA,OAAA;AAAA;AAE7B,QAAA,SAAA,CAAU,KAAK,OAAO,CAAA;AAAA;AAC1B,KACH,CAAA;AAAA;AAEL,EAAM,MAAA,SAAA,GAAY,IAAI,CAAA,CAAU,GAAG,CAAA;AACnC,EAAO,MAAA,CAAA,gBAAA,CAAiB,SAAS,WAAW,CAAA;AAC5C,EAAU,SAAA,CAAA,gBAAA,CAAiB,SAAS,WAAW,CAAA;AAC/C,EAAU,SAAA,CAAA,gBAAA,CAAiB,SAAS,WAAW,CAAA;AAC/C,EAAU,SAAA,CAAA,gBAAA,CAAiB,WAAW,aAAa,CAAA;AACnD,EAAU,SAAA,CAAA,gBAAA,CAAiB,QAAQ,UAAU,CAAA;AAC7C,EAAI,IAAA,UAAA;AACJ,EAAI,IAAA,WAAA;AACJ,EAAA,OAAO,IAAI,OAAA,CAA2D,CAAC,OAAA,EAAS,MAAW,KAAA;AACvF,IAAa,UAAA,GAAA,MAAA;AACb,IAAc,WAAA,GAAA,OAAA;AAAA,GACjB,CAAA;AACL","file":"index.browser.mjs","sourcesContent":["export const AbortController = globalThis.AbortController;\nexport const EventTarget = globalThis.EventTarget;\n","export default globalThis.WebSocket;\n","import {\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CLOSED_BEFORE_MESSAGE_BUFFERED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_FAILED_TO_CONNECT,\n SolanaError,\n} from '@solana/errors';\nimport { EventTarget } from '@solana/event-target-impl';\nimport { RpcSubscriptionsChannel } from '@solana/rpc-subscriptions-spec';\nimport { getDataPublisherFromEventEmitter } from '@solana/subscribable';\nimport WebSocket from '@solana/ws-impl';\n\nexport type Config = Readonly<{\n /**\n * The number of bytes to admit into the WebSocket's send buffer before queueing messages on the\n * client.\n *\n * When you call {@link RpcSubscriptionsChannel.send | `send()`} on a `WebSocket` the runtime\n * might add the message to a buffer rather than send it right away. In the event that\n * `socket.bufferedAmount` exceeds the value configured here, messages will be added to a queue\n * in your application code instead of being sent to the WebSocket, until such time as the\n * `bufferedAmount` falls back below the high watermark.\n */\n sendBufferHighWatermark: number;\n /**\n * An `AbortSignal` to fire when you want to explicitly close the `WebSocket`.\n *\n * If the channel is open it will be closed with a normal closure code\n * (https://www.rfc-editor.org/rfc/rfc6455.html#section-7.4.1) If the channel has not been\n * established yet, firing this signal will result in the `AbortError` being thrown to the\n * caller who was trying to open the channel.\n */\n signal: AbortSignal;\n /**\n * A string representing the target endpoint.\n *\n * In Node, it must be an absolute URL using the `ws` or `wss` protocol.\n */\n url: string;\n}>;\n\ntype WebSocketMessage = ArrayBufferLike | ArrayBufferView | Blob | string;\n\nconst NORMAL_CLOSURE_CODE = 1000; // https://www.rfc-editor.org/rfc/rfc6455.html#section-7.4.1\n\n/**\n * Creates an object that represents an open channel to a `WebSocket` server.\n *\n * You can use it to send messages by calling its\n * {@link RpcSubscriptionsChannel.send | `send()`} function and you can receive them by subscribing\n * to the {@link RpcSubscriptionChannelEvents} it emits.\n */\nexport function createWebSocketChannel({\n sendBufferHighWatermark,\n signal,\n url,\n}: Config): Promise<RpcSubscriptionsChannel<WebSocketMessage, string>> {\n if (signal.aborted) {\n // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\n return Promise.reject(signal.reason);\n }\n let bufferDrainWatcher: Readonly<{ onCancel(): void; promise: Promise<void> }> | undefined;\n let hasConnected = false;\n const listenerRemovers = new Set<() => void>();\n function cleanupListeners() {\n listenerRemovers.forEach(r => {\n r();\n });\n listenerRemovers.clear();\n }\n function handleAbort() {\n cleanupListeners();\n if (!hasConnected) {\n rejectOpen(signal.reason);\n }\n if (webSocket.readyState !== WebSocket.CLOSED && webSocket.readyState !== WebSocket.CLOSING) {\n webSocket.close(NORMAL_CLOSURE_CODE);\n }\n }\n function handleClose(ev: CloseEvent) {\n cleanupListeners();\n bufferDrainWatcher?.onCancel();\n signal.removeEventListener('abort', handleAbort);\n webSocket.removeEventListener('close', handleClose);\n webSocket.removeEventListener('error', handleError);\n webSocket.removeEventListener('message', handleMessage);\n webSocket.removeEventListener('open', handleOpen);\n if (!signal.aborted && !(ev.wasClean && ev.code === NORMAL_CLOSURE_CODE)) {\n eventTarget.dispatchEvent(\n new CustomEvent('error', {\n detail: new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED, {\n cause: ev,\n }),\n }),\n );\n }\n }\n function handleError(ev: Event) {\n if (signal.aborted) {\n return;\n }\n if (!hasConnected) {\n const failedToConnectError = new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_FAILED_TO_CONNECT, {\n errorEvent: ev,\n });\n rejectOpen(failedToConnectError);\n eventTarget.dispatchEvent(\n new CustomEvent('error', {\n detail: failedToConnectError,\n }),\n );\n }\n }\n function handleMessage(ev: MessageEvent) {\n if (signal.aborted) {\n return;\n }\n eventTarget.dispatchEvent(new CustomEvent('message', { detail: ev.data }));\n }\n const eventTarget = new EventTarget();\n const dataPublisher = getDataPublisherFromEventEmitter(eventTarget);\n function handleOpen() {\n hasConnected = true;\n resolveOpen({\n ...dataPublisher,\n async send(message) {\n if (webSocket.readyState !== WebSocket.OPEN) {\n throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED);\n }\n if (!bufferDrainWatcher && webSocket.bufferedAmount > sendBufferHighWatermark) {\n let onCancel!: () => void;\n const promise = new Promise<void>((resolve, reject) => {\n const intervalId = setInterval(() => {\n if (\n webSocket.readyState !== WebSocket.OPEN ||\n !(webSocket.bufferedAmount > sendBufferHighWatermark)\n ) {\n clearInterval(intervalId);\n bufferDrainWatcher = undefined;\n resolve();\n }\n }, 16);\n onCancel = () => {\n bufferDrainWatcher = undefined;\n clearInterval(intervalId);\n reject(\n new SolanaError(\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CLOSED_BEFORE_MESSAGE_BUFFERED,\n ),\n );\n };\n });\n bufferDrainWatcher = {\n onCancel,\n promise,\n };\n }\n if (bufferDrainWatcher) {\n if (ArrayBuffer.isView(message) && !(message instanceof DataView)) {\n const TypedArrayConstructor = message.constructor as {\n new (...args: [typeof message]): typeof message;\n };\n // Clone the message to prevent mutation while queued.\n message = new TypedArrayConstructor(message);\n }\n await bufferDrainWatcher.promise;\n }\n webSocket.send(message);\n },\n });\n }\n const webSocket = new WebSocket(url);\n signal.addEventListener('abort', handleAbort);\n webSocket.addEventListener('close', handleClose);\n webSocket.addEventListener('error', handleError);\n webSocket.addEventListener('message', handleMessage);\n webSocket.addEventListener('open', handleOpen);\n let rejectOpen!: (e: SolanaError) => void;\n let resolveOpen!: (value: RpcSubscriptionsChannel<WebSocketMessage, string>) => void;\n return new Promise<RpcSubscriptionsChannel<WebSocketMessage, string>>((resolve, reject) => {\n rejectOpen = reject;\n resolveOpen = resolve;\n });\n}\n"]}
1
+ {"version":3,"sources":["../../event-target-impl/src/index.browser.ts","../../ws-impl/src/index.browser.ts","../src/websocket-channel.ts"],"names":["EventTarget","index_browser_default"],"mappings":"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","file":"index.browser.mjs","sourcesContent":["export const AbortController = globalThis.AbortController;\nexport const EventTarget = globalThis.EventTarget;\n","export default globalThis.WebSocket;\n","import {\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CLOSED_BEFORE_MESSAGE_BUFFERED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_FAILED_TO_CONNECT,\n SolanaError,\n} from '@solana/errors';\nimport { EventTarget } from '@solana/event-target-impl';\nimport { RpcSubscriptionsChannel } from '@solana/rpc-subscriptions-spec';\nimport { getDataPublisherFromEventEmitter } from '@solana/subscribable';\nimport WebSocket from '@solana/ws-impl';\n\nexport type Config = Readonly<{\n /**\n * The number of bytes to admit into the WebSocket's send buffer before queueing messages on the\n * client.\n *\n * When you call {@link RpcSubscriptionsChannel.send | `send()`} on a `WebSocket` the runtime\n * might add the message to a buffer rather than send it right away. In the event that\n * `socket.bufferedAmount` exceeds the value configured here, messages will be added to a queue\n * in your application code instead of being sent to the WebSocket, until such time as the\n * `bufferedAmount` falls back below the high watermark.\n */\n sendBufferHighWatermark: number;\n /**\n * An `AbortSignal` to fire when you want to explicitly close the `WebSocket`.\n *\n * If the channel is open it will be closed with a normal closure code\n * (https://www.rfc-editor.org/rfc/rfc6455.html#section-7.4.1) If the channel has not been\n * established yet, firing this signal will result in the `AbortError` being thrown to the\n * caller who was trying to open the channel.\n */\n signal: AbortSignal;\n /**\n * A string representing the target endpoint.\n *\n * In Node, it must be an absolute URL using the `ws` or `wss` protocol.\n */\n url: string;\n}>;\n\ntype WebSocketMessage = ArrayBufferLike | ArrayBufferView | Blob | string;\n\nconst NORMAL_CLOSURE_CODE = 1000; // https://www.rfc-editor.org/rfc/rfc6455.html#section-7.4.1\n\n/**\n * Creates an object that represents an open channel to a `WebSocket` server.\n *\n * You can use it to send messages by calling its\n * {@link RpcSubscriptionsChannel.send | `send()`} function and you can receive them by subscribing\n * to the {@link RpcSubscriptionChannelEvents} it emits.\n */\nexport function createWebSocketChannel({\n sendBufferHighWatermark,\n signal,\n url,\n}: Config): Promise<RpcSubscriptionsChannel<WebSocketMessage, string>> {\n if (signal.aborted) {\n // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\n return Promise.reject(signal.reason);\n }\n let bufferDrainWatcher: Readonly<{ onCancel(): void; promise: Promise<void> }> | undefined;\n let hasConnected = false;\n const listenerRemovers = new Set<() => void>();\n function cleanupListeners() {\n listenerRemovers.forEach(r => {\n r();\n });\n listenerRemovers.clear();\n }\n function handleAbort() {\n cleanupListeners();\n if (!hasConnected) {\n rejectOpen(signal.reason);\n }\n if (webSocket.readyState !== WebSocket.CLOSED && webSocket.readyState !== WebSocket.CLOSING) {\n webSocket.close(NORMAL_CLOSURE_CODE);\n }\n }\n function handleClose(ev: CloseEvent) {\n cleanupListeners();\n bufferDrainWatcher?.onCancel();\n signal.removeEventListener('abort', handleAbort);\n webSocket.removeEventListener('close', handleClose);\n webSocket.removeEventListener('error', handleError);\n webSocket.removeEventListener('message', handleMessage);\n webSocket.removeEventListener('open', handleOpen);\n if (!signal.aborted && !(ev.wasClean && ev.code === NORMAL_CLOSURE_CODE)) {\n eventTarget.dispatchEvent(\n new CustomEvent('error', {\n detail: new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED, {\n cause: ev,\n }),\n }),\n );\n }\n }\n function handleError(ev: Event) {\n if (signal.aborted) {\n return;\n }\n if (!hasConnected) {\n const failedToConnectError = new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_FAILED_TO_CONNECT, {\n errorEvent: ev,\n });\n rejectOpen(failedToConnectError);\n eventTarget.dispatchEvent(\n new CustomEvent('error', {\n detail: failedToConnectError,\n }),\n );\n }\n }\n function handleMessage(ev: MessageEvent) {\n if (signal.aborted) {\n return;\n }\n eventTarget.dispatchEvent(new CustomEvent('message', { detail: ev.data }));\n }\n const eventTarget = new EventTarget();\n const dataPublisher = getDataPublisherFromEventEmitter(eventTarget);\n function handleOpen() {\n hasConnected = true;\n resolveOpen({\n ...dataPublisher,\n async send(message) {\n if (webSocket.readyState !== WebSocket.OPEN) {\n throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED);\n }\n if (!bufferDrainWatcher && webSocket.bufferedAmount > sendBufferHighWatermark) {\n let onCancel!: () => void;\n const promise = new Promise<void>((resolve, reject) => {\n const intervalId = setInterval(() => {\n if (\n webSocket.readyState !== WebSocket.OPEN ||\n !(webSocket.bufferedAmount > sendBufferHighWatermark)\n ) {\n clearInterval(intervalId);\n bufferDrainWatcher = undefined;\n resolve();\n }\n }, 16);\n onCancel = () => {\n bufferDrainWatcher = undefined;\n clearInterval(intervalId);\n reject(\n new SolanaError(\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CLOSED_BEFORE_MESSAGE_BUFFERED,\n ),\n );\n };\n });\n bufferDrainWatcher = {\n onCancel,\n promise,\n };\n }\n if (bufferDrainWatcher) {\n if (ArrayBuffer.isView(message) && !(message instanceof DataView)) {\n const TypedArrayConstructor = message.constructor as {\n new (...args: [typeof message]): typeof message;\n };\n // Clone the message to prevent mutation while queued.\n message = new TypedArrayConstructor(message);\n }\n await bufferDrainWatcher.promise;\n }\n webSocket.send(message);\n },\n });\n }\n const webSocket = new WebSocket(url);\n signal.addEventListener('abort', handleAbort);\n webSocket.addEventListener('close', handleClose);\n webSocket.addEventListener('error', handleError);\n webSocket.addEventListener('message', handleMessage);\n webSocket.addEventListener('open', handleOpen);\n let rejectOpen!: (e: SolanaError) => void;\n let resolveOpen!: (value: RpcSubscriptionsChannel<WebSocketMessage, string>) => void;\n return new Promise<RpcSubscriptionsChannel<WebSocketMessage, string>>((resolve, reject) => {\n rejectOpen = reject;\n resolveOpen = resolve;\n });\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../event-target-impl/src/index.browser.ts","../../ws-impl/src/index.browser.ts","../src/websocket-channel.ts"],"names":["EventTarget","index_browser_default"],"mappings":"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","file":"index.native.mjs","sourcesContent":["export const AbortController = globalThis.AbortController;\nexport const EventTarget = globalThis.EventTarget;\n","export default globalThis.WebSocket;\n","import {\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CLOSED_BEFORE_MESSAGE_BUFFERED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_FAILED_TO_CONNECT,\n SolanaError,\n} from '@solana/errors';\nimport { EventTarget } from '@solana/event-target-impl';\nimport { RpcSubscriptionsChannel } from '@solana/rpc-subscriptions-spec';\nimport { getDataPublisherFromEventEmitter } from '@solana/subscribable';\nimport WebSocket from '@solana/ws-impl';\n\nexport type Config = Readonly<{\n /**\n * The number of bytes to admit into the WebSocket's send buffer before queueing messages on the\n * client.\n *\n * When you call {@link RpcSubscriptionsChannel.send | `send()`} on a `WebSocket` the runtime\n * might add the message to a buffer rather than send it right away. In the event that\n * `socket.bufferedAmount` exceeds the value configured here, messages will be added to a queue\n * in your application code instead of being sent to the WebSocket, until such time as the\n * `bufferedAmount` falls back below the high watermark.\n */\n sendBufferHighWatermark: number;\n /**\n * An `AbortSignal` to fire when you want to explicitly close the `WebSocket`.\n *\n * If the channel is open it will be closed with a normal closure code\n * (https://www.rfc-editor.org/rfc/rfc6455.html#section-7.4.1) If the channel has not been\n * established yet, firing this signal will result in the `AbortError` being thrown to the\n * caller who was trying to open the channel.\n */\n signal: AbortSignal;\n /**\n * A string representing the target endpoint.\n *\n * In Node, it must be an absolute URL using the `ws` or `wss` protocol.\n */\n url: string;\n}>;\n\ntype WebSocketMessage = ArrayBufferLike | ArrayBufferView | Blob | string;\n\nconst NORMAL_CLOSURE_CODE = 1000; // https://www.rfc-editor.org/rfc/rfc6455.html#section-7.4.1\n\n/**\n * Creates an object that represents an open channel to a `WebSocket` server.\n *\n * You can use it to send messages by calling its\n * {@link RpcSubscriptionsChannel.send | `send()`} function and you can receive them by subscribing\n * to the {@link RpcSubscriptionChannelEvents} it emits.\n */\nexport function createWebSocketChannel({\n sendBufferHighWatermark,\n signal,\n url,\n}: Config): Promise<RpcSubscriptionsChannel<WebSocketMessage, string>> {\n if (signal.aborted) {\n // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\n return Promise.reject(signal.reason);\n }\n let bufferDrainWatcher: Readonly<{ onCancel(): void; promise: Promise<void> }> | undefined;\n let hasConnected = false;\n const listenerRemovers = new Set<() => void>();\n function cleanupListeners() {\n listenerRemovers.forEach(r => {\n r();\n });\n listenerRemovers.clear();\n }\n function handleAbort() {\n cleanupListeners();\n if (!hasConnected) {\n rejectOpen(signal.reason);\n }\n if (webSocket.readyState !== WebSocket.CLOSED && webSocket.readyState !== WebSocket.CLOSING) {\n webSocket.close(NORMAL_CLOSURE_CODE);\n }\n }\n function handleClose(ev: CloseEvent) {\n cleanupListeners();\n bufferDrainWatcher?.onCancel();\n signal.removeEventListener('abort', handleAbort);\n webSocket.removeEventListener('close', handleClose);\n webSocket.removeEventListener('error', handleError);\n webSocket.removeEventListener('message', handleMessage);\n webSocket.removeEventListener('open', handleOpen);\n if (!signal.aborted && !(ev.wasClean && ev.code === NORMAL_CLOSURE_CODE)) {\n eventTarget.dispatchEvent(\n new CustomEvent('error', {\n detail: new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED, {\n cause: ev,\n }),\n }),\n );\n }\n }\n function handleError(ev: Event) {\n if (signal.aborted) {\n return;\n }\n if (!hasConnected) {\n const failedToConnectError = new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_FAILED_TO_CONNECT, {\n errorEvent: ev,\n });\n rejectOpen(failedToConnectError);\n eventTarget.dispatchEvent(\n new CustomEvent('error', {\n detail: failedToConnectError,\n }),\n );\n }\n }\n function handleMessage(ev: MessageEvent) {\n if (signal.aborted) {\n return;\n }\n eventTarget.dispatchEvent(new CustomEvent('message', { detail: ev.data }));\n }\n const eventTarget = new EventTarget();\n const dataPublisher = getDataPublisherFromEventEmitter(eventTarget);\n function handleOpen() {\n hasConnected = true;\n resolveOpen({\n ...dataPublisher,\n async send(message) {\n if (webSocket.readyState !== WebSocket.OPEN) {\n throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED);\n }\n if (!bufferDrainWatcher && webSocket.bufferedAmount > sendBufferHighWatermark) {\n let onCancel!: () => void;\n const promise = new Promise<void>((resolve, reject) => {\n const intervalId = setInterval(() => {\n if (\n webSocket.readyState !== WebSocket.OPEN ||\n !(webSocket.bufferedAmount > sendBufferHighWatermark)\n ) {\n clearInterval(intervalId);\n bufferDrainWatcher = undefined;\n resolve();\n }\n }, 16);\n onCancel = () => {\n bufferDrainWatcher = undefined;\n clearInterval(intervalId);\n reject(\n new SolanaError(\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CLOSED_BEFORE_MESSAGE_BUFFERED,\n ),\n );\n };\n });\n bufferDrainWatcher = {\n onCancel,\n promise,\n };\n }\n if (bufferDrainWatcher) {\n if (ArrayBuffer.isView(message) && !(message instanceof DataView)) {\n const TypedArrayConstructor = message.constructor as {\n new (...args: [typeof message]): typeof message;\n };\n // Clone the message to prevent mutation while queued.\n message = new TypedArrayConstructor(message);\n }\n await bufferDrainWatcher.promise;\n }\n webSocket.send(message);\n },\n });\n }\n const webSocket = new WebSocket(url);\n signal.addEventListener('abort', handleAbort);\n webSocket.addEventListener('close', handleClose);\n webSocket.addEventListener('error', handleError);\n webSocket.addEventListener('message', handleMessage);\n webSocket.addEventListener('open', handleOpen);\n let rejectOpen!: (e: SolanaError) => void;\n let resolveOpen!: (value: RpcSubscriptionsChannel<WebSocketMessage, string>) => void;\n return new Promise<RpcSubscriptionsChannel<WebSocketMessage, string>>((resolve, reject) => {\n rejectOpen = reject;\n resolveOpen = resolve;\n });\n}\n"]}
1
+ {"version":3,"sources":["../../event-target-impl/src/index.browser.ts","../../ws-impl/src/index.browser.ts","../src/websocket-channel.ts"],"names":["EventTarget","index_browser_default"],"mappings":"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","file":"index.native.mjs","sourcesContent":["export const AbortController = globalThis.AbortController;\nexport const EventTarget = globalThis.EventTarget;\n","export default globalThis.WebSocket;\n","import {\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CLOSED_BEFORE_MESSAGE_BUFFERED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_FAILED_TO_CONNECT,\n SolanaError,\n} from '@solana/errors';\nimport { EventTarget } from '@solana/event-target-impl';\nimport { RpcSubscriptionsChannel } from '@solana/rpc-subscriptions-spec';\nimport { getDataPublisherFromEventEmitter } from '@solana/subscribable';\nimport WebSocket from '@solana/ws-impl';\n\nexport type Config = Readonly<{\n /**\n * The number of bytes to admit into the WebSocket's send buffer before queueing messages on the\n * client.\n *\n * When you call {@link RpcSubscriptionsChannel.send | `send()`} on a `WebSocket` the runtime\n * might add the message to a buffer rather than send it right away. In the event that\n * `socket.bufferedAmount` exceeds the value configured here, messages will be added to a queue\n * in your application code instead of being sent to the WebSocket, until such time as the\n * `bufferedAmount` falls back below the high watermark.\n */\n sendBufferHighWatermark: number;\n /**\n * An `AbortSignal` to fire when you want to explicitly close the `WebSocket`.\n *\n * If the channel is open it will be closed with a normal closure code\n * (https://www.rfc-editor.org/rfc/rfc6455.html#section-7.4.1) If the channel has not been\n * established yet, firing this signal will result in the `AbortError` being thrown to the\n * caller who was trying to open the channel.\n */\n signal: AbortSignal;\n /**\n * A string representing the target endpoint.\n *\n * In Node, it must be an absolute URL using the `ws` or `wss` protocol.\n */\n url: string;\n}>;\n\ntype WebSocketMessage = ArrayBufferLike | ArrayBufferView | Blob | string;\n\nconst NORMAL_CLOSURE_CODE = 1000; // https://www.rfc-editor.org/rfc/rfc6455.html#section-7.4.1\n\n/**\n * Creates an object that represents an open channel to a `WebSocket` server.\n *\n * You can use it to send messages by calling its\n * {@link RpcSubscriptionsChannel.send | `send()`} function and you can receive them by subscribing\n * to the {@link RpcSubscriptionChannelEvents} it emits.\n */\nexport function createWebSocketChannel({\n sendBufferHighWatermark,\n signal,\n url,\n}: Config): Promise<RpcSubscriptionsChannel<WebSocketMessage, string>> {\n if (signal.aborted) {\n // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\n return Promise.reject(signal.reason);\n }\n let bufferDrainWatcher: Readonly<{ onCancel(): void; promise: Promise<void> }> | undefined;\n let hasConnected = false;\n const listenerRemovers = new Set<() => void>();\n function cleanupListeners() {\n listenerRemovers.forEach(r => {\n r();\n });\n listenerRemovers.clear();\n }\n function handleAbort() {\n cleanupListeners();\n if (!hasConnected) {\n rejectOpen(signal.reason);\n }\n if (webSocket.readyState !== WebSocket.CLOSED && webSocket.readyState !== WebSocket.CLOSING) {\n webSocket.close(NORMAL_CLOSURE_CODE);\n }\n }\n function handleClose(ev: CloseEvent) {\n cleanupListeners();\n bufferDrainWatcher?.onCancel();\n signal.removeEventListener('abort', handleAbort);\n webSocket.removeEventListener('close', handleClose);\n webSocket.removeEventListener('error', handleError);\n webSocket.removeEventListener('message', handleMessage);\n webSocket.removeEventListener('open', handleOpen);\n if (!signal.aborted && !(ev.wasClean && ev.code === NORMAL_CLOSURE_CODE)) {\n eventTarget.dispatchEvent(\n new CustomEvent('error', {\n detail: new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED, {\n cause: ev,\n }),\n }),\n );\n }\n }\n function handleError(ev: Event) {\n if (signal.aborted) {\n return;\n }\n if (!hasConnected) {\n const failedToConnectError = new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_FAILED_TO_CONNECT, {\n errorEvent: ev,\n });\n rejectOpen(failedToConnectError);\n eventTarget.dispatchEvent(\n new CustomEvent('error', {\n detail: failedToConnectError,\n }),\n );\n }\n }\n function handleMessage(ev: MessageEvent) {\n if (signal.aborted) {\n return;\n }\n eventTarget.dispatchEvent(new CustomEvent('message', { detail: ev.data }));\n }\n const eventTarget = new EventTarget();\n const dataPublisher = getDataPublisherFromEventEmitter(eventTarget);\n function handleOpen() {\n hasConnected = true;\n resolveOpen({\n ...dataPublisher,\n async send(message) {\n if (webSocket.readyState !== WebSocket.OPEN) {\n throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED);\n }\n if (!bufferDrainWatcher && webSocket.bufferedAmount > sendBufferHighWatermark) {\n let onCancel!: () => void;\n const promise = new Promise<void>((resolve, reject) => {\n const intervalId = setInterval(() => {\n if (\n webSocket.readyState !== WebSocket.OPEN ||\n !(webSocket.bufferedAmount > sendBufferHighWatermark)\n ) {\n clearInterval(intervalId);\n bufferDrainWatcher = undefined;\n resolve();\n }\n }, 16);\n onCancel = () => {\n bufferDrainWatcher = undefined;\n clearInterval(intervalId);\n reject(\n new SolanaError(\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CLOSED_BEFORE_MESSAGE_BUFFERED,\n ),\n );\n };\n });\n bufferDrainWatcher = {\n onCancel,\n promise,\n };\n }\n if (bufferDrainWatcher) {\n if (ArrayBuffer.isView(message) && !(message instanceof DataView)) {\n const TypedArrayConstructor = message.constructor as {\n new (...args: [typeof message]): typeof message;\n };\n // Clone the message to prevent mutation while queued.\n message = new TypedArrayConstructor(message);\n }\n await bufferDrainWatcher.promise;\n }\n webSocket.send(message);\n },\n });\n }\n const webSocket = new WebSocket(url);\n signal.addEventListener('abort', handleAbort);\n webSocket.addEventListener('close', handleClose);\n webSocket.addEventListener('error', handleError);\n webSocket.addEventListener('message', handleMessage);\n webSocket.addEventListener('open', handleOpen);\n let rejectOpen!: (e: SolanaError) => void;\n let resolveOpen!: (value: RpcSubscriptionsChannel<WebSocketMessage, string>) => void;\n return new Promise<RpcSubscriptionsChannel<WebSocketMessage, string>>((resolve, reject) => {\n rejectOpen = reject;\n resolveOpen = resolve;\n });\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../event-target-impl/src/index.node.ts","../../ws-impl/src/index.node.ts","../src/websocket-channel.ts"],"names":["EventTarget","args","setMaxListeners","index_node_default","WebSocketImpl","SolanaError","SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED","SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_FAILED_TO_CONNECT","getDataPublisherFromEventEmitter","SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CLOSED_BEFORE_MESSAGE_BUFFERED"],"mappings":"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","file":"index.node.cjs","sourcesContent":["import { setMaxListeners } from 'node:events';\n\nexport const AbortController = class extends globalThis.AbortController {\n constructor(...args: ConstructorParameters<typeof globalThis.AbortController>) {\n super(...args);\n setMaxListeners(Number.MAX_SAFE_INTEGER, this.signal);\n }\n};\n\nexport const EventTarget = class extends globalThis.EventTarget {\n constructor(...args: ConstructorParameters<typeof globalThis.EventTarget>) {\n super(...args);\n setMaxListeners(Number.MAX_SAFE_INTEGER, this);\n }\n};\n","// When building the browser bundle, this import gets replaced by `globalThis.WebSocket`.\nimport WebSocketImpl from 'ws';\n\nexport default globalThis.WebSocket\n ? globalThis.WebSocket // Use native `WebSocket` in runtimes that support it (eg. Deno)\n : WebSocketImpl;\n","import {\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CLOSED_BEFORE_MESSAGE_BUFFERED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_FAILED_TO_CONNECT,\n SolanaError,\n} from '@solana/errors';\nimport { EventTarget } from '@solana/event-target-impl';\nimport { RpcSubscriptionsChannel } from '@solana/rpc-subscriptions-spec';\nimport { getDataPublisherFromEventEmitter } from '@solana/subscribable';\nimport WebSocket from '@solana/ws-impl';\n\nexport type Config = Readonly<{\n /**\n * The number of bytes to admit into the WebSocket's send buffer before queueing messages on the\n * client.\n *\n * When you call {@link RpcSubscriptionsChannel.send | `send()`} on a `WebSocket` the runtime\n * might add the message to a buffer rather than send it right away. In the event that\n * `socket.bufferedAmount` exceeds the value configured here, messages will be added to a queue\n * in your application code instead of being sent to the WebSocket, until such time as the\n * `bufferedAmount` falls back below the high watermark.\n */\n sendBufferHighWatermark: number;\n /**\n * An `AbortSignal` to fire when you want to explicitly close the `WebSocket`.\n *\n * If the channel is open it will be closed with a normal closure code\n * (https://www.rfc-editor.org/rfc/rfc6455.html#section-7.4.1) If the channel has not been\n * established yet, firing this signal will result in the `AbortError` being thrown to the\n * caller who was trying to open the channel.\n */\n signal: AbortSignal;\n /**\n * A string representing the target endpoint.\n *\n * In Node, it must be an absolute URL using the `ws` or `wss` protocol.\n */\n url: string;\n}>;\n\ntype WebSocketMessage = ArrayBufferLike | ArrayBufferView | Blob | string;\n\nconst NORMAL_CLOSURE_CODE = 1000; // https://www.rfc-editor.org/rfc/rfc6455.html#section-7.4.1\n\n/**\n * Creates an object that represents an open channel to a `WebSocket` server.\n *\n * You can use it to send messages by calling its\n * {@link RpcSubscriptionsChannel.send | `send()`} function and you can receive them by subscribing\n * to the {@link RpcSubscriptionChannelEvents} it emits.\n */\nexport function createWebSocketChannel({\n sendBufferHighWatermark,\n signal,\n url,\n}: Config): Promise<RpcSubscriptionsChannel<WebSocketMessage, string>> {\n if (signal.aborted) {\n // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\n return Promise.reject(signal.reason);\n }\n let bufferDrainWatcher: Readonly<{ onCancel(): void; promise: Promise<void> }> | undefined;\n let hasConnected = false;\n const listenerRemovers = new Set<() => void>();\n function cleanupListeners() {\n listenerRemovers.forEach(r => {\n r();\n });\n listenerRemovers.clear();\n }\n function handleAbort() {\n cleanupListeners();\n if (!hasConnected) {\n rejectOpen(signal.reason);\n }\n if (webSocket.readyState !== WebSocket.CLOSED && webSocket.readyState !== WebSocket.CLOSING) {\n webSocket.close(NORMAL_CLOSURE_CODE);\n }\n }\n function handleClose(ev: CloseEvent) {\n cleanupListeners();\n bufferDrainWatcher?.onCancel();\n signal.removeEventListener('abort', handleAbort);\n webSocket.removeEventListener('close', handleClose);\n webSocket.removeEventListener('error', handleError);\n webSocket.removeEventListener('message', handleMessage);\n webSocket.removeEventListener('open', handleOpen);\n if (!signal.aborted && !(ev.wasClean && ev.code === NORMAL_CLOSURE_CODE)) {\n eventTarget.dispatchEvent(\n new CustomEvent('error', {\n detail: new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED, {\n cause: ev,\n }),\n }),\n );\n }\n }\n function handleError(ev: Event) {\n if (signal.aborted) {\n return;\n }\n if (!hasConnected) {\n const failedToConnectError = new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_FAILED_TO_CONNECT, {\n errorEvent: ev,\n });\n rejectOpen(failedToConnectError);\n eventTarget.dispatchEvent(\n new CustomEvent('error', {\n detail: failedToConnectError,\n }),\n );\n }\n }\n function handleMessage(ev: MessageEvent) {\n if (signal.aborted) {\n return;\n }\n eventTarget.dispatchEvent(new CustomEvent('message', { detail: ev.data }));\n }\n const eventTarget = new EventTarget();\n const dataPublisher = getDataPublisherFromEventEmitter(eventTarget);\n function handleOpen() {\n hasConnected = true;\n resolveOpen({\n ...dataPublisher,\n async send(message) {\n if (webSocket.readyState !== WebSocket.OPEN) {\n throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED);\n }\n if (!bufferDrainWatcher && webSocket.bufferedAmount > sendBufferHighWatermark) {\n let onCancel!: () => void;\n const promise = new Promise<void>((resolve, reject) => {\n const intervalId = setInterval(() => {\n if (\n webSocket.readyState !== WebSocket.OPEN ||\n !(webSocket.bufferedAmount > sendBufferHighWatermark)\n ) {\n clearInterval(intervalId);\n bufferDrainWatcher = undefined;\n resolve();\n }\n }, 16);\n onCancel = () => {\n bufferDrainWatcher = undefined;\n clearInterval(intervalId);\n reject(\n new SolanaError(\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CLOSED_BEFORE_MESSAGE_BUFFERED,\n ),\n );\n };\n });\n bufferDrainWatcher = {\n onCancel,\n promise,\n };\n }\n if (bufferDrainWatcher) {\n if (ArrayBuffer.isView(message) && !(message instanceof DataView)) {\n const TypedArrayConstructor = message.constructor as {\n new (...args: [typeof message]): typeof message;\n };\n // Clone the message to prevent mutation while queued.\n message = new TypedArrayConstructor(message);\n }\n await bufferDrainWatcher.promise;\n }\n webSocket.send(message);\n },\n });\n }\n const webSocket = new WebSocket(url);\n signal.addEventListener('abort', handleAbort);\n webSocket.addEventListener('close', handleClose);\n webSocket.addEventListener('error', handleError);\n webSocket.addEventListener('message', handleMessage);\n webSocket.addEventListener('open', handleOpen);\n let rejectOpen!: (e: SolanaError) => void;\n let resolveOpen!: (value: RpcSubscriptionsChannel<WebSocketMessage, string>) => void;\n return new Promise<RpcSubscriptionsChannel<WebSocketMessage, string>>((resolve, reject) => {\n rejectOpen = reject;\n resolveOpen = resolve;\n });\n}\n"]}
1
+ {"version":3,"sources":["../../event-target-impl/src/index.node.ts","../../ws-impl/src/index.node.ts","../src/websocket-channel.ts"],"names":["EventTarget","args","setMaxListeners","index_node_default","WebSocketImpl","SolanaError","SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED","SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_FAILED_TO_CONNECT","getDataPublisherFromEventEmitter","SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CLOSED_BEFORE_MESSAGE_BUFFERED"],"mappings":";;;;;;;;;;;;IASaA,CAAAA,GAAc,cAAc,WAAW,WAAA,CAAY;AAC5D,EAAA,WAAA,CAAA,GAAeC,CAAAA,EAA4D;AACvE,IAAA,KAAA,CAAM,GAAGA,CAAI,CAAA,EACbC,sBAAAA,CAAgB,MAAA,CAAO,kBAAkB,IAAI,CAAA;AACjD,EAAA;AACJ,CAAA;ACXA,IAAOC,CAAAA,GAAQ,UAAA,CAAW,SAAA,GACpB,UAAA,CAAW,SAAA,GACXC,mBAAAA;;;ACqCN,IAAM,mBAAA,GAAsB,GAAA;AASrB,SAAS,sBAAA,CAAuB;AAAA,EACnC,uBAAA;AAAA,EACA,MAAA;AAAA,EACA;AACJ,CAAA,EAAuE;AACnE,EAAA,IAAI,OAAO,OAAA,EAAS;AAEhB,IAAA,OAAO,OAAA,CAAQ,MAAA,CAAO,MAAA,CAAO,MAAM,CAAA;AAAA,EACvC;AACA,EAAA,IAAI,kBAAA;AACJ,EAAA,IAAI,YAAA,GAAe,KAAA;AACnB,EAAA,MAAM,gBAAA,uBAAuB,GAAA,EAAgB;AAC7C,EAAA,SAAS,gBAAA,GAAmB;AACxB,IAAA,gBAAA,CAAiB,QAAQ,CAAA,CAAA,KAAK;AAC1B,MAAA,CAAA,EAAE;AAAA,IACN,CAAC,CAAA;AACD,IAAA,gBAAA,CAAiB,KAAA,EAAM;AAAA,EAC3B;AACA,EAAA,SAAS,WAAA,GAAc;AACnB,IAAA,gBAAA,EAAiB;AACjB,IAAA,IAAI,CAAC,YAAA,EAAc;AACf,MAAA,UAAA,CAAW,OAAO,MAAM,CAAA;AAAA,IAC5B;AACA,IAAA,IAAI,UAAU,UAAA,KAAe,CAAA,CAAU,UAAU,SAAA,CAAU,UAAA,KAAe,EAAU,OAAA,EAAS;AACzF,MAAA,SAAA,CAAU,MAAM,mBAAmB,CAAA;AAAA,IACvC;AAAA,EACJ;AACA,EAAA,SAAS,YAAY,EAAA,EAAgB;AACjC,IAAA,gBAAA,EAAiB;AACjB,IAAA,kBAAA,EAAoB,QAAA,EAAS;AAC7B,IAAA,MAAA,CAAO,mBAAA,CAAoB,SAAS,WAAW,CAAA;AAC/C,IAAA,SAAA,CAAU,mBAAA,CAAoB,SAAS,WAAW,CAAA;AAClD,IAAA,SAAA,CAAU,mBAAA,CAAoB,SAAS,WAAW,CAAA;AAClD,IAAA,SAAA,CAAU,mBAAA,CAAoB,WAAW,aAAa,CAAA;AACtD,IAAA,SAAA,CAAU,mBAAA,CAAoB,QAAQ,UAAU,CAAA;AAChD,IAAA,IAAI,CAAC,OAAO,OAAA,IAAW,EAAE,GAAG,QAAA,IAAY,EAAA,CAAG,SAAS,mBAAA,CAAA,EAAsB;AACtE,MAAA,WAAA,CAAY,aAAA;AAAA,QACR,IAAI,YAAY,OAAA,EAAS;AAAA,UACrB,MAAA,EAAQ,IAAIC,kBAAA,CAAYC,iEAAA,EAA4D;AAAA,YAChF,KAAA,EAAO;AAAA,WACV;AAAA,SACJ;AAAA,OACL;AAAA,IACJ;AAAA,EACJ;AACA,EAAA,SAAS,YAAY,EAAA,EAAW;AAC5B,IAAA,IAAI,OAAO,OAAA,EAAS;AAChB,MAAA;AAAA,IACJ;AACA,IAAA,IAAI,CAAC,YAAA,EAAc;AACf,MAAA,MAAM,oBAAA,GAAuB,IAAID,kBAAA,CAAYE,iEAAA,EAA4D;AAAA,QACrG,UAAA,EAAY;AAAA,OACf,CAAA;AACD,MAAA,UAAA,CAAW,oBAAoB,CAAA;AAC/B,MAAA,WAAA,CAAY,aAAA;AAAA,QACR,IAAI,YAAY,OAAA,EAAS;AAAA,UACrB,MAAA,EAAQ;AAAA,SACX;AAAA,OACL;AAAA,IACJ;AAAA,EACJ;AACA,EAAA,SAAS,cAAc,EAAA,EAAkB;AACrC,IAAA,IAAI,OAAO,OAAA,EAAS;AAChB,MAAA;AAAA,IACJ;AACA,IAAA,WAAA,CAAY,aAAA,CAAc,IAAI,WAAA,CAAY,SAAA,EAAW,EAAE,MAAA,EAAQ,EAAA,CAAG,IAAA,EAAM,CAAC,CAAA;AAAA,EAC7E;AACA,EAAA,MAAM,WAAA,GAAc,IAAI,CAAA,EAAY;AACpC,EAAA,MAAM,aAAA,GAAgBC,8CAAiC,WAAW,CAAA;AAClE,EAAA,SAAS,UAAA,GAAa;AAClB,IAAA,YAAA,GAAe,IAAA;AACf,IAAA,WAAA,CAAY;AAAA,MACR,GAAG,aAAA;AAAA,MACH,MAAM,KAAK,OAAA,EAAS;AAChB,QAAA,IAAI,SAAA,CAAU,UAAA,KAAe,CAAA,CAAU,IAAA,EAAM;AACzC,UAAA,MAAM,IAAIH,mBAAYC,iEAA0D,CAAA;AAAA,QACpF;AACA,QAAA,IAAI,CAAC,kBAAA,IAAsB,SAAA,CAAU,cAAA,GAAiB,uBAAA,EAAyB;AAC3E,UAAA,IAAI,QAAA;AACJ,UAAA,MAAM,OAAA,GAAU,IAAI,OAAA,CAAc,CAAC,SAAS,MAAA,KAAW;AACnD,YAAA,MAAM,UAAA,GAAa,YAAY,MAAM;AACjC,cAAA,IACI,UAAU,UAAA,KAAe,CAAA,CAAU,QACnC,EAAE,SAAA,CAAU,iBAAiB,uBAAA,CAAA,EAC/B;AACE,gBAAA,aAAA,CAAc,UAAU,CAAA;AACxB,gBAAA,kBAAA,GAAqB,MAAA;AACrB,gBAAA,OAAA,EAAQ;AAAA,cACZ;AAAA,YACJ,GAAG,EAAE,CAAA;AACL,YAAA,QAAA,GAAW,MAAM;AACb,cAAA,kBAAA,GAAqB,MAAA;AACrB,cAAA,aAAA,CAAc,UAAU,CAAA;AACxB,cAAA,MAAA;AAAA,gBACI,IAAID,kBAAA;AAAA,kBACAI;AAAA;AACJ,eACJ;AAAA,YACJ,CAAA;AAAA,UACJ,CAAC,CAAA;AACD,UAAA,kBAAA,GAAqB;AAAA,YACjB,QAAA;AAAA,YACA;AAAA,WACJ;AAAA,QACJ;AACA,QAAA,IAAI,kBAAA,EAAoB;AACpB,UAAA,IAAI,YAAY,MAAA,CAAO,OAAO,CAAA,IAAK,EAAE,mBAAmB,QAAA,CAAA,EAAW;AAC/D,YAAA,MAAM,wBAAwB,OAAA,CAAQ,WAAA;AAItC,YAAA,OAAA,GAAU,IAAI,sBAAsB,OAAO,CAAA;AAAA,UAC/C;AACA,UAAA,MAAM,kBAAA,CAAmB,OAAA;AAAA,QAC7B;AACA,QAAA,SAAA,CAAU,KAAK,OAAO,CAAA;AAAA,MAC1B;AAAA,KACH,CAAA;AAAA,EACL;AACA,EAAA,MAAM,SAAA,GAAY,IAAI,CAAA,CAAU,GAAG,CAAA;AACnC,EAAA,MAAA,CAAO,gBAAA,CAAiB,SAAS,WAAW,CAAA;AAC5C,EAAA,SAAA,CAAU,gBAAA,CAAiB,SAAS,WAAW,CAAA;AAC/C,EAAA,SAAA,CAAU,gBAAA,CAAiB,SAAS,WAAW,CAAA;AAC/C,EAAA,SAAA,CAAU,gBAAA,CAAiB,WAAW,aAAa,CAAA;AACnD,EAAA,SAAA,CAAU,gBAAA,CAAiB,QAAQ,UAAU,CAAA;AAC7C,EAAA,IAAI,UAAA;AACJ,EAAA,IAAI,WAAA;AACJ,EAAA,OAAO,IAAI,OAAA,CAA2D,CAAC,OAAA,EAAS,MAAA,KAAW;AACvF,IAAA,UAAA,GAAa,MAAA;AACb,IAAA,WAAA,GAAc,OAAA;AAAA,EAClB,CAAC,CAAA;AACL","file":"index.node.cjs","sourcesContent":["import { setMaxListeners } from 'node:events';\n\nexport const AbortController = class extends globalThis.AbortController {\n constructor(...args: ConstructorParameters<typeof globalThis.AbortController>) {\n super(...args);\n setMaxListeners(Number.MAX_SAFE_INTEGER, this.signal);\n }\n};\n\nexport const EventTarget = class extends globalThis.EventTarget {\n constructor(...args: ConstructorParameters<typeof globalThis.EventTarget>) {\n super(...args);\n setMaxListeners(Number.MAX_SAFE_INTEGER, this);\n }\n};\n","// When building the browser bundle, this import gets replaced by `globalThis.WebSocket`.\nimport WebSocketImpl from 'ws';\n\nexport default globalThis.WebSocket\n ? globalThis.WebSocket // Use native `WebSocket` in runtimes that support it (eg. Deno)\n : WebSocketImpl;\n","import {\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CLOSED_BEFORE_MESSAGE_BUFFERED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_FAILED_TO_CONNECT,\n SolanaError,\n} from '@solana/errors';\nimport { EventTarget } from '@solana/event-target-impl';\nimport { RpcSubscriptionsChannel } from '@solana/rpc-subscriptions-spec';\nimport { getDataPublisherFromEventEmitter } from '@solana/subscribable';\nimport WebSocket from '@solana/ws-impl';\n\nexport type Config = Readonly<{\n /**\n * The number of bytes to admit into the WebSocket's send buffer before queueing messages on the\n * client.\n *\n * When you call {@link RpcSubscriptionsChannel.send | `send()`} on a `WebSocket` the runtime\n * might add the message to a buffer rather than send it right away. In the event that\n * `socket.bufferedAmount` exceeds the value configured here, messages will be added to a queue\n * in your application code instead of being sent to the WebSocket, until such time as the\n * `bufferedAmount` falls back below the high watermark.\n */\n sendBufferHighWatermark: number;\n /**\n * An `AbortSignal` to fire when you want to explicitly close the `WebSocket`.\n *\n * If the channel is open it will be closed with a normal closure code\n * (https://www.rfc-editor.org/rfc/rfc6455.html#section-7.4.1) If the channel has not been\n * established yet, firing this signal will result in the `AbortError` being thrown to the\n * caller who was trying to open the channel.\n */\n signal: AbortSignal;\n /**\n * A string representing the target endpoint.\n *\n * In Node, it must be an absolute URL using the `ws` or `wss` protocol.\n */\n url: string;\n}>;\n\ntype WebSocketMessage = ArrayBufferLike | ArrayBufferView | Blob | string;\n\nconst NORMAL_CLOSURE_CODE = 1000; // https://www.rfc-editor.org/rfc/rfc6455.html#section-7.4.1\n\n/**\n * Creates an object that represents an open channel to a `WebSocket` server.\n *\n * You can use it to send messages by calling its\n * {@link RpcSubscriptionsChannel.send | `send()`} function and you can receive them by subscribing\n * to the {@link RpcSubscriptionChannelEvents} it emits.\n */\nexport function createWebSocketChannel({\n sendBufferHighWatermark,\n signal,\n url,\n}: Config): Promise<RpcSubscriptionsChannel<WebSocketMessage, string>> {\n if (signal.aborted) {\n // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\n return Promise.reject(signal.reason);\n }\n let bufferDrainWatcher: Readonly<{ onCancel(): void; promise: Promise<void> }> | undefined;\n let hasConnected = false;\n const listenerRemovers = new Set<() => void>();\n function cleanupListeners() {\n listenerRemovers.forEach(r => {\n r();\n });\n listenerRemovers.clear();\n }\n function handleAbort() {\n cleanupListeners();\n if (!hasConnected) {\n rejectOpen(signal.reason);\n }\n if (webSocket.readyState !== WebSocket.CLOSED && webSocket.readyState !== WebSocket.CLOSING) {\n webSocket.close(NORMAL_CLOSURE_CODE);\n }\n }\n function handleClose(ev: CloseEvent) {\n cleanupListeners();\n bufferDrainWatcher?.onCancel();\n signal.removeEventListener('abort', handleAbort);\n webSocket.removeEventListener('close', handleClose);\n webSocket.removeEventListener('error', handleError);\n webSocket.removeEventListener('message', handleMessage);\n webSocket.removeEventListener('open', handleOpen);\n if (!signal.aborted && !(ev.wasClean && ev.code === NORMAL_CLOSURE_CODE)) {\n eventTarget.dispatchEvent(\n new CustomEvent('error', {\n detail: new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED, {\n cause: ev,\n }),\n }),\n );\n }\n }\n function handleError(ev: Event) {\n if (signal.aborted) {\n return;\n }\n if (!hasConnected) {\n const failedToConnectError = new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_FAILED_TO_CONNECT, {\n errorEvent: ev,\n });\n rejectOpen(failedToConnectError);\n eventTarget.dispatchEvent(\n new CustomEvent('error', {\n detail: failedToConnectError,\n }),\n );\n }\n }\n function handleMessage(ev: MessageEvent) {\n if (signal.aborted) {\n return;\n }\n eventTarget.dispatchEvent(new CustomEvent('message', { detail: ev.data }));\n }\n const eventTarget = new EventTarget();\n const dataPublisher = getDataPublisherFromEventEmitter(eventTarget);\n function handleOpen() {\n hasConnected = true;\n resolveOpen({\n ...dataPublisher,\n async send(message) {\n if (webSocket.readyState !== WebSocket.OPEN) {\n throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED);\n }\n if (!bufferDrainWatcher && webSocket.bufferedAmount > sendBufferHighWatermark) {\n let onCancel!: () => void;\n const promise = new Promise<void>((resolve, reject) => {\n const intervalId = setInterval(() => {\n if (\n webSocket.readyState !== WebSocket.OPEN ||\n !(webSocket.bufferedAmount > sendBufferHighWatermark)\n ) {\n clearInterval(intervalId);\n bufferDrainWatcher = undefined;\n resolve();\n }\n }, 16);\n onCancel = () => {\n bufferDrainWatcher = undefined;\n clearInterval(intervalId);\n reject(\n new SolanaError(\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CLOSED_BEFORE_MESSAGE_BUFFERED,\n ),\n );\n };\n });\n bufferDrainWatcher = {\n onCancel,\n promise,\n };\n }\n if (bufferDrainWatcher) {\n if (ArrayBuffer.isView(message) && !(message instanceof DataView)) {\n const TypedArrayConstructor = message.constructor as {\n new (...args: [typeof message]): typeof message;\n };\n // Clone the message to prevent mutation while queued.\n message = new TypedArrayConstructor(message);\n }\n await bufferDrainWatcher.promise;\n }\n webSocket.send(message);\n },\n });\n }\n const webSocket = new WebSocket(url);\n signal.addEventListener('abort', handleAbort);\n webSocket.addEventListener('close', handleClose);\n webSocket.addEventListener('error', handleError);\n webSocket.addEventListener('message', handleMessage);\n webSocket.addEventListener('open', handleOpen);\n let rejectOpen!: (e: SolanaError) => void;\n let resolveOpen!: (value: RpcSubscriptionsChannel<WebSocketMessage, string>) => void;\n return new Promise<RpcSubscriptionsChannel<WebSocketMessage, string>>((resolve, reject) => {\n rejectOpen = reject;\n resolveOpen = resolve;\n });\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../event-target-impl/src/index.node.ts","../../ws-impl/src/index.node.ts","../src/websocket-channel.ts"],"names":["EventTarget","args","setMaxListeners","index_node_default","WebSocketImpl"],"mappings":"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","file":"index.node.mjs","sourcesContent":["import { setMaxListeners } from 'node:events';\n\nexport const AbortController = class extends globalThis.AbortController {\n constructor(...args: ConstructorParameters<typeof globalThis.AbortController>) {\n super(...args);\n setMaxListeners(Number.MAX_SAFE_INTEGER, this.signal);\n }\n};\n\nexport const EventTarget = class extends globalThis.EventTarget {\n constructor(...args: ConstructorParameters<typeof globalThis.EventTarget>) {\n super(...args);\n setMaxListeners(Number.MAX_SAFE_INTEGER, this);\n }\n};\n","// When building the browser bundle, this import gets replaced by `globalThis.WebSocket`.\nimport WebSocketImpl from 'ws';\n\nexport default globalThis.WebSocket\n ? globalThis.WebSocket // Use native `WebSocket` in runtimes that support it (eg. Deno)\n : WebSocketImpl;\n","import {\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CLOSED_BEFORE_MESSAGE_BUFFERED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_FAILED_TO_CONNECT,\n SolanaError,\n} from '@solana/errors';\nimport { EventTarget } from '@solana/event-target-impl';\nimport { RpcSubscriptionsChannel } from '@solana/rpc-subscriptions-spec';\nimport { getDataPublisherFromEventEmitter } from '@solana/subscribable';\nimport WebSocket from '@solana/ws-impl';\n\nexport type Config = Readonly<{\n /**\n * The number of bytes to admit into the WebSocket's send buffer before queueing messages on the\n * client.\n *\n * When you call {@link RpcSubscriptionsChannel.send | `send()`} on a `WebSocket` the runtime\n * might add the message to a buffer rather than send it right away. In the event that\n * `socket.bufferedAmount` exceeds the value configured here, messages will be added to a queue\n * in your application code instead of being sent to the WebSocket, until such time as the\n * `bufferedAmount` falls back below the high watermark.\n */\n sendBufferHighWatermark: number;\n /**\n * An `AbortSignal` to fire when you want to explicitly close the `WebSocket`.\n *\n * If the channel is open it will be closed with a normal closure code\n * (https://www.rfc-editor.org/rfc/rfc6455.html#section-7.4.1) If the channel has not been\n * established yet, firing this signal will result in the `AbortError` being thrown to the\n * caller who was trying to open the channel.\n */\n signal: AbortSignal;\n /**\n * A string representing the target endpoint.\n *\n * In Node, it must be an absolute URL using the `ws` or `wss` protocol.\n */\n url: string;\n}>;\n\ntype WebSocketMessage = ArrayBufferLike | ArrayBufferView | Blob | string;\n\nconst NORMAL_CLOSURE_CODE = 1000; // https://www.rfc-editor.org/rfc/rfc6455.html#section-7.4.1\n\n/**\n * Creates an object that represents an open channel to a `WebSocket` server.\n *\n * You can use it to send messages by calling its\n * {@link RpcSubscriptionsChannel.send | `send()`} function and you can receive them by subscribing\n * to the {@link RpcSubscriptionChannelEvents} it emits.\n */\nexport function createWebSocketChannel({\n sendBufferHighWatermark,\n signal,\n url,\n}: Config): Promise<RpcSubscriptionsChannel<WebSocketMessage, string>> {\n if (signal.aborted) {\n // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\n return Promise.reject(signal.reason);\n }\n let bufferDrainWatcher: Readonly<{ onCancel(): void; promise: Promise<void> }> | undefined;\n let hasConnected = false;\n const listenerRemovers = new Set<() => void>();\n function cleanupListeners() {\n listenerRemovers.forEach(r => {\n r();\n });\n listenerRemovers.clear();\n }\n function handleAbort() {\n cleanupListeners();\n if (!hasConnected) {\n rejectOpen(signal.reason);\n }\n if (webSocket.readyState !== WebSocket.CLOSED && webSocket.readyState !== WebSocket.CLOSING) {\n webSocket.close(NORMAL_CLOSURE_CODE);\n }\n }\n function handleClose(ev: CloseEvent) {\n cleanupListeners();\n bufferDrainWatcher?.onCancel();\n signal.removeEventListener('abort', handleAbort);\n webSocket.removeEventListener('close', handleClose);\n webSocket.removeEventListener('error', handleError);\n webSocket.removeEventListener('message', handleMessage);\n webSocket.removeEventListener('open', handleOpen);\n if (!signal.aborted && !(ev.wasClean && ev.code === NORMAL_CLOSURE_CODE)) {\n eventTarget.dispatchEvent(\n new CustomEvent('error', {\n detail: new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED, {\n cause: ev,\n }),\n }),\n );\n }\n }\n function handleError(ev: Event) {\n if (signal.aborted) {\n return;\n }\n if (!hasConnected) {\n const failedToConnectError = new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_FAILED_TO_CONNECT, {\n errorEvent: ev,\n });\n rejectOpen(failedToConnectError);\n eventTarget.dispatchEvent(\n new CustomEvent('error', {\n detail: failedToConnectError,\n }),\n );\n }\n }\n function handleMessage(ev: MessageEvent) {\n if (signal.aborted) {\n return;\n }\n eventTarget.dispatchEvent(new CustomEvent('message', { detail: ev.data }));\n }\n const eventTarget = new EventTarget();\n const dataPublisher = getDataPublisherFromEventEmitter(eventTarget);\n function handleOpen() {\n hasConnected = true;\n resolveOpen({\n ...dataPublisher,\n async send(message) {\n if (webSocket.readyState !== WebSocket.OPEN) {\n throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED);\n }\n if (!bufferDrainWatcher && webSocket.bufferedAmount > sendBufferHighWatermark) {\n let onCancel!: () => void;\n const promise = new Promise<void>((resolve, reject) => {\n const intervalId = setInterval(() => {\n if (\n webSocket.readyState !== WebSocket.OPEN ||\n !(webSocket.bufferedAmount > sendBufferHighWatermark)\n ) {\n clearInterval(intervalId);\n bufferDrainWatcher = undefined;\n resolve();\n }\n }, 16);\n onCancel = () => {\n bufferDrainWatcher = undefined;\n clearInterval(intervalId);\n reject(\n new SolanaError(\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CLOSED_BEFORE_MESSAGE_BUFFERED,\n ),\n );\n };\n });\n bufferDrainWatcher = {\n onCancel,\n promise,\n };\n }\n if (bufferDrainWatcher) {\n if (ArrayBuffer.isView(message) && !(message instanceof DataView)) {\n const TypedArrayConstructor = message.constructor as {\n new (...args: [typeof message]): typeof message;\n };\n // Clone the message to prevent mutation while queued.\n message = new TypedArrayConstructor(message);\n }\n await bufferDrainWatcher.promise;\n }\n webSocket.send(message);\n },\n });\n }\n const webSocket = new WebSocket(url);\n signal.addEventListener('abort', handleAbort);\n webSocket.addEventListener('close', handleClose);\n webSocket.addEventListener('error', handleError);\n webSocket.addEventListener('message', handleMessage);\n webSocket.addEventListener('open', handleOpen);\n let rejectOpen!: (e: SolanaError) => void;\n let resolveOpen!: (value: RpcSubscriptionsChannel<WebSocketMessage, string>) => void;\n return new Promise<RpcSubscriptionsChannel<WebSocketMessage, string>>((resolve, reject) => {\n rejectOpen = reject;\n resolveOpen = resolve;\n });\n}\n"]}
1
+ {"version":3,"sources":["../../event-target-impl/src/index.node.ts","../../ws-impl/src/index.node.ts","../src/websocket-channel.ts"],"names":["EventTarget","args","setMaxListeners","index_node_default","WebSocketImpl"],"mappings":"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","file":"index.node.mjs","sourcesContent":["import { setMaxListeners } from 'node:events';\n\nexport const AbortController = class extends globalThis.AbortController {\n constructor(...args: ConstructorParameters<typeof globalThis.AbortController>) {\n super(...args);\n setMaxListeners(Number.MAX_SAFE_INTEGER, this.signal);\n }\n};\n\nexport const EventTarget = class extends globalThis.EventTarget {\n constructor(...args: ConstructorParameters<typeof globalThis.EventTarget>) {\n super(...args);\n setMaxListeners(Number.MAX_SAFE_INTEGER, this);\n }\n};\n","// When building the browser bundle, this import gets replaced by `globalThis.WebSocket`.\nimport WebSocketImpl from 'ws';\n\nexport default globalThis.WebSocket\n ? globalThis.WebSocket // Use native `WebSocket` in runtimes that support it (eg. Deno)\n : WebSocketImpl;\n","import {\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CLOSED_BEFORE_MESSAGE_BUFFERED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED,\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_FAILED_TO_CONNECT,\n SolanaError,\n} from '@solana/errors';\nimport { EventTarget } from '@solana/event-target-impl';\nimport { RpcSubscriptionsChannel } from '@solana/rpc-subscriptions-spec';\nimport { getDataPublisherFromEventEmitter } from '@solana/subscribable';\nimport WebSocket from '@solana/ws-impl';\n\nexport type Config = Readonly<{\n /**\n * The number of bytes to admit into the WebSocket's send buffer before queueing messages on the\n * client.\n *\n * When you call {@link RpcSubscriptionsChannel.send | `send()`} on a `WebSocket` the runtime\n * might add the message to a buffer rather than send it right away. In the event that\n * `socket.bufferedAmount` exceeds the value configured here, messages will be added to a queue\n * in your application code instead of being sent to the WebSocket, until such time as the\n * `bufferedAmount` falls back below the high watermark.\n */\n sendBufferHighWatermark: number;\n /**\n * An `AbortSignal` to fire when you want to explicitly close the `WebSocket`.\n *\n * If the channel is open it will be closed with a normal closure code\n * (https://www.rfc-editor.org/rfc/rfc6455.html#section-7.4.1) If the channel has not been\n * established yet, firing this signal will result in the `AbortError` being thrown to the\n * caller who was trying to open the channel.\n */\n signal: AbortSignal;\n /**\n * A string representing the target endpoint.\n *\n * In Node, it must be an absolute URL using the `ws` or `wss` protocol.\n */\n url: string;\n}>;\n\ntype WebSocketMessage = ArrayBufferLike | ArrayBufferView | Blob | string;\n\nconst NORMAL_CLOSURE_CODE = 1000; // https://www.rfc-editor.org/rfc/rfc6455.html#section-7.4.1\n\n/**\n * Creates an object that represents an open channel to a `WebSocket` server.\n *\n * You can use it to send messages by calling its\n * {@link RpcSubscriptionsChannel.send | `send()`} function and you can receive them by subscribing\n * to the {@link RpcSubscriptionChannelEvents} it emits.\n */\nexport function createWebSocketChannel({\n sendBufferHighWatermark,\n signal,\n url,\n}: Config): Promise<RpcSubscriptionsChannel<WebSocketMessage, string>> {\n if (signal.aborted) {\n // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\n return Promise.reject(signal.reason);\n }\n let bufferDrainWatcher: Readonly<{ onCancel(): void; promise: Promise<void> }> | undefined;\n let hasConnected = false;\n const listenerRemovers = new Set<() => void>();\n function cleanupListeners() {\n listenerRemovers.forEach(r => {\n r();\n });\n listenerRemovers.clear();\n }\n function handleAbort() {\n cleanupListeners();\n if (!hasConnected) {\n rejectOpen(signal.reason);\n }\n if (webSocket.readyState !== WebSocket.CLOSED && webSocket.readyState !== WebSocket.CLOSING) {\n webSocket.close(NORMAL_CLOSURE_CODE);\n }\n }\n function handleClose(ev: CloseEvent) {\n cleanupListeners();\n bufferDrainWatcher?.onCancel();\n signal.removeEventListener('abort', handleAbort);\n webSocket.removeEventListener('close', handleClose);\n webSocket.removeEventListener('error', handleError);\n webSocket.removeEventListener('message', handleMessage);\n webSocket.removeEventListener('open', handleOpen);\n if (!signal.aborted && !(ev.wasClean && ev.code === NORMAL_CLOSURE_CODE)) {\n eventTarget.dispatchEvent(\n new CustomEvent('error', {\n detail: new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED, {\n cause: ev,\n }),\n }),\n );\n }\n }\n function handleError(ev: Event) {\n if (signal.aborted) {\n return;\n }\n if (!hasConnected) {\n const failedToConnectError = new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_FAILED_TO_CONNECT, {\n errorEvent: ev,\n });\n rejectOpen(failedToConnectError);\n eventTarget.dispatchEvent(\n new CustomEvent('error', {\n detail: failedToConnectError,\n }),\n );\n }\n }\n function handleMessage(ev: MessageEvent) {\n if (signal.aborted) {\n return;\n }\n eventTarget.dispatchEvent(new CustomEvent('message', { detail: ev.data }));\n }\n const eventTarget = new EventTarget();\n const dataPublisher = getDataPublisherFromEventEmitter(eventTarget);\n function handleOpen() {\n hasConnected = true;\n resolveOpen({\n ...dataPublisher,\n async send(message) {\n if (webSocket.readyState !== WebSocket.OPEN) {\n throw new SolanaError(SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CONNECTION_CLOSED);\n }\n if (!bufferDrainWatcher && webSocket.bufferedAmount > sendBufferHighWatermark) {\n let onCancel!: () => void;\n const promise = new Promise<void>((resolve, reject) => {\n const intervalId = setInterval(() => {\n if (\n webSocket.readyState !== WebSocket.OPEN ||\n !(webSocket.bufferedAmount > sendBufferHighWatermark)\n ) {\n clearInterval(intervalId);\n bufferDrainWatcher = undefined;\n resolve();\n }\n }, 16);\n onCancel = () => {\n bufferDrainWatcher = undefined;\n clearInterval(intervalId);\n reject(\n new SolanaError(\n SOLANA_ERROR__RPC_SUBSCRIPTIONS__CHANNEL_CLOSED_BEFORE_MESSAGE_BUFFERED,\n ),\n );\n };\n });\n bufferDrainWatcher = {\n onCancel,\n promise,\n };\n }\n if (bufferDrainWatcher) {\n if (ArrayBuffer.isView(message) && !(message instanceof DataView)) {\n const TypedArrayConstructor = message.constructor as {\n new (...args: [typeof message]): typeof message;\n };\n // Clone the message to prevent mutation while queued.\n message = new TypedArrayConstructor(message);\n }\n await bufferDrainWatcher.promise;\n }\n webSocket.send(message);\n },\n });\n }\n const webSocket = new WebSocket(url);\n signal.addEventListener('abort', handleAbort);\n webSocket.addEventListener('close', handleClose);\n webSocket.addEventListener('error', handleError);\n webSocket.addEventListener('message', handleMessage);\n webSocket.addEventListener('open', handleOpen);\n let rejectOpen!: (e: SolanaError) => void;\n let resolveOpen!: (value: RpcSubscriptionsChannel<WebSocketMessage, string>) => void;\n return new Promise<RpcSubscriptionsChannel<WebSocketMessage, string>>((resolve, reject) => {\n rejectOpen = reject;\n resolveOpen = resolve;\n });\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solana/rpc-subscriptions-channel-websocket",
3
- "version": "5.1.0-canary-20251202173352",
3
+ "version": "5.1.0-canary-20251203213248",
4
4
  "description": "An RPC Subscriptions transport that uses WebSockets",
5
5
  "homepage": "https://www.solanakit.com/api#solanarpc-subscriptions-channel-websocket",
6
6
  "exports": {
@@ -55,10 +55,10 @@
55
55
  "maintained node versions"
56
56
  ],
57
57
  "dependencies": {
58
- "@solana/errors": "5.1.0-canary-20251202173352",
59
- "@solana/functional": "5.1.0-canary-20251202173352",
60
- "@solana/rpc-subscriptions-spec": "5.1.0-canary-20251202173352",
61
- "@solana/subscribable": "5.1.0-canary-20251202173352"
58
+ "@solana/errors": "5.1.0-canary-20251203213248",
59
+ "@solana/functional": "5.1.0-canary-20251203213248",
60
+ "@solana/rpc-subscriptions-spec": "5.1.0-canary-20251203213248",
61
+ "@solana/subscribable": "5.1.0-canary-20251203213248"
62
62
  },
63
63
  "peerDependencies": {
64
64
  "typescript": ">=5.3.3",