Skip to main content
Version: 11.x

Class: WsTransport

Defined in: src/channel/transport/ws.ts:88

Carries JSON-RPC envelopes over a single WebSocket.

It owns the socket and nothing else: it does not know what starknet_getBlockWithTxs means, and it does not know that subscriptions exist. That is what lets one socket serve several versioned channels at once, and lets it survive the probe channel that RpcProvider.create() builds and throws away.

This transport connects once. When the connection goes away it settles everything waiting on it and reports 'closed'; it does not reconnect.

Batches depend on the node. Pathfinder accepts an array and answers with a single array frame (measured 2026-08-10 with a raw socket), and so does starknet-devnet from 0.9.2 — wsTransport.ws.test.ts exercises it against a real node. Devnet before 0.9.2 refuses it on its /ws endpoint with -32700 Parse error.

A refusal is answered with id: null, which belongs to no request, so every call in the batch runs out its requestTimeout instead of failing fast — worth checking on an unfamiliar node.

Prefer ReconnectingWsTransport for anything long-lived: a shared gateway drops idle connections, and this one does not come back.

Example

const transport = new WsTransport({ nodeUrl: 'wss://your-starknet-node/rpc/v0_10' });
const myProvider = new WebSocketProvider({ transport });
// ... later
transport.close();

Extended by

Implements

Constructors

Constructor

new WsTransport(options): WsTransport

Defined in: src/channel/transport/ws.ts:146

Parameters

options

WsTransportOptions

Returns

WsTransport

Properties

nodeUrl

readonly nodeUrl: string

Defined in: src/channel/transport/ws.ts:90

The URL of the WebSocket RPC node.


socket

socket: WebSocket

Defined in: src/channel/transport/ws.ts:98

The underlying socket. Owned by this transport — close it through close().

Not readonly because a subclass may replace it on a reconnection. This class never does: one WsTransport is one socket, which is what its own tests rely on.


WsImplementation

protected readonly WsImplementation: WebSocketModule

Defined in: src/channel/transport/ws.ts:101

Kept so a subclass can build a replacement socket the same way this one was built.

Methods

swapSocket()

protected swapSocket(next): void

Defined in: src/channel/transport/ws.ts:180

Adopts a replacement socket.

The readiness latch is discarded with the old socket: it records that that connection came up, and reusing it would let a request be written to a socket still handshaking.

Requests already on the wire are not settled here — handleClose has done that for the socket that went away, since nothing on a dead socket can still be answered.

Parameters

next

WebSocket

Returns

void


onOpened()

protected onOpened(): void

Defined in: src/channel/transport/ws.ts:203

What happens once a socket is open. Overridden by a reconnecting subclass, which also has a retry counter to reset and a queue to flush.

Returns

void


onClosed()

protected onClosed(_event): void

Defined in: src/channel/transport/ws.ts:211

What happens once a socket is gone. This class stays closed; a reconnecting subclass starts an attempt instead.

Parameters

_event

Event

Returns

void


onError()

protected onError(_event): void

Defined in: src/channel/transport/ws.ts:282

What happens on a socket error. This class only logs; a reconnecting subclass treats it as a failed attempt, because a refused connection may produce an error with no close behind it.

Parameters

_event

Event

Returns

void


setState()

protected setState(next): void

Defined in: src/channel/transport/ws.ts:284

Parameters

next

WsTransportState

Returns

void


getState()

getState(): WsTransportState

Defined in: src/channel/transport/ws.ts:295

The current connection state. The getSnapshot half of the useSyncExternalStore pair.

Returns

WsTransportState


isConnected()

isConnected(): boolean

Defined in: src/channel/transport/ws.ts:300

Whether the socket is open right now.

Returns

boolean


allocateRequestId()

allocateRequestId(): number

Defined in: src/channel/transport/ws.ts:312

Allocates the next wire id, starting at 0.

Exposed because a caller may write to the socket itself rather than through requestWebSocketChannel.send() is fire-and-forget and correlates nothing. Drawing from this same sequence is what stops such a write from colliding with a request this transport is tracking, which would hand one caller the other's reply.

Returns

number


on()

on<K>(event, listener): () => void

Defined in: src/channel/transport/ws.ts:327

Subscribes to one of the transport's two streams.

'statechange' fires on every connection state transition; 'notification' fires for every frame the node pushes on its own.

Type Parameters

K

K extends keyof WsTransportEvents

Parameters

event

K

listener

(payload) => void

Returns

the unsubscribe function, which is what useSyncExternalStore requires of its subscribe argument.

() => void


request()

Call Signature

request(body): Promise<ResponseBody>

Defined in: src/channel/transport/ws.ts:405

Sends the envelope over the socket and resolves with the node's answer. See RpcTransport.request for the contract every transport honours.

Waits for the socket to be usable when it is not yet, and rejects with a TimeoutError after requestTimeout, or with a WebSocketNotConnectedError if the connection is lost meanwhile.

Parameters
body

RequestBody

A request envelope, or an array of them for a batch — read the note on batch portability in the class description first.

Returns

Promise<ResponseBody>

The response envelope, or an array of them.

Implementation of

RpcTransport.request

Call Signature

request(body): Promise<ResponseBody[]>

Defined in: src/channel/transport/ws.ts:406

Sends the envelope over the socket and resolves with the node's answer. See RpcTransport.request for the contract every transport honours.

Waits for the socket to be usable when it is not yet, and rejects with a TimeoutError after requestTimeout, or with a WebSocketNotConnectedError if the connection is lost meanwhile.

Parameters
body

RequestBody[]

A request envelope, or an array of them for a batch — read the note on batch portability in the class description first.

Returns

Promise<ResponseBody[]>

The response envelope, or an array of them.

Implementation of

RpcTransport.request


rejectPending()

protected rejectPending(reason): void

Defined in: src/channel/transport/ws.ts:482

Fails every request still on the wire.

Their only other exit is the requestTimeout timer, so without this the caller waits the whole timeout — 60s by default — for a reply that can no longer arrive, and that pending timer keeps the Node event loop alive for just as long.

Parameters

reason

string

Returns

void


close()

close(code?, reason?): void

Defined in: src/channel/transport/ws.ts:504

Closes the socket.

One object owns the socket and one object closes it. Dropping every reference to this transport does not close anything: an open socket is a libuv handle the Node event loop holds onto, so it must be closed explicitly.

Parameters

code?

number

reason?

string

Returns

void