smoldot 2.0.5 → 2.0.7

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.
@@ -7,6 +7,9 @@ export interface PlatformBindings {
7
7
  /**
8
8
  * Tries to open a new connection using the given configuration.
9
9
  *
10
+ * In case of a multistream connection, `onMultistreamHandshakeInfo` should be called as soon
11
+ * as possible.
12
+ *
10
13
  * @see Connection
11
14
  */
12
15
  connect(config: ConnectionConfig): Connection;
@@ -22,19 +25,14 @@ export interface PlatformBindings {
22
25
  /**
23
26
  * Connection to a remote node.
24
27
  *
25
- * At any time, a connection can be in one of the three following states:
28
+ * At any time, a connection can be in one of the following states:
26
29
  *
27
- * - `Opening` (initial state)
28
- * - `Open`
30
+ * - `Open` (initial state)
29
31
  * - `Reset`
30
32
  *
31
- * When in the `Opening` or `Open` state, the connection can transition to the `Reset` state
32
- * if the remote closes the connection or refuses the connection altogether. When that
33
- * happens, `config.onReset` is called. Once in the `Reset` state, the connection cannot
34
- * transition back to another state.
35
- *
36
- * Initially in the `Opening` state, the connection can transition to the `Open` state if the
37
- * remote accepts the connection. When that happens, `config.onOpen` is called.
33
+ * When in the `Open` state, the connection can transition to the `Reset` state if the remote
34
+ * closes the connection or refuses the connection altogether. When that happens, `config.onReset`
35
+ * is called. Once in the `Reset` state, the connection cannot transition back to `Open`.
38
36
  *
39
37
  * When in the `Open` state, the connection can receive messages. When a message is received,
40
38
  * `config.onMessage` is called.
@@ -112,16 +110,14 @@ export interface ConnectionConfig {
112
110
  */
113
111
  address: instance.ParsedMultiaddr;
114
112
  /**
115
- * Callback called when the connection transitions from the `Opening` to the `Open` state.
113
+ * Callback called when a multistream connection knows information about its handshake. Should
114
+ * be called as soon as possible.
115
+ *
116
+ * Can only happen while the connection is in the `Open` state.
116
117
  *
117
118
  * Must only be called once per connection.
118
119
  */
119
- onOpen: (info: {
120
- type: 'single-stream';
121
- handshake: 'multistream-select-noise-yamux';
122
- initialWritableBytes: number;
123
- } | {
124
- type: 'multi-stream';
120
+ onMultistreamHandshakeInfo: (info: {
125
121
  handshake: 'webrtc';
126
122
  localTlsCertificateSha256: Uint8Array;
127
123
  remoteTlsCertificateSha256: Uint8Array;
@@ -137,7 +133,7 @@ export interface ConnectionConfig {
137
133
  *
138
134
  * This function must only be called for connections of type "multi-stream".
139
135
  */
140
- onStreamOpened: (streamId: number, direction: 'inbound' | 'outbound', initialWritableBytes: number) => void;
136
+ onStreamOpened: (streamId: number, direction: 'inbound' | 'outbound') => void;
141
137
  /**
142
138
  * Callback called when a stream transitions to the `Reset` state.
143
139
  *
@@ -151,14 +147,14 @@ export interface ConnectionConfig {
151
147
  * written on the stream, meaning that some buffer space is now free.
152
148
  *
153
149
  * Can only happen while the connection is in the `Open` state.
154
- *
155
150
  * This callback must not be called after `closeSend` has been called.
156
151
  *
152
+ * The total of writable bytes must not go beyond reasonable values (e.g. a few megabytes). It
153
+ * is not legal to provide a dummy implementation that simply passes an exceedingly large
154
+ * value.
155
+ *
157
156
  * The `streamId` parameter must be provided if and only if the connection is of type
158
157
  * "multi-stream".
159
- *
160
- * Only a number of bytes equal to the size of the data provided to {@link Connection.send}
161
- * must be reported. In other words, the `initialWritableBytes` must never be exceeded.
162
158
  */
163
159
  onWritableBytes: (numExtra: number, streamId?: number) => void;
164
160
  /**
@@ -138,15 +138,15 @@ function start(options, wasmModule, platformBindings) {
138
138
  throw new Error();
139
139
  state.instance.instance.streamMessage(connectionId, message, streamId);
140
140
  },
141
- onStreamOpened(streamId, direction, initialWritableBytes) {
141
+ onStreamOpened(streamId, direction) {
142
142
  if (state.instance.status !== "ready")
143
143
  throw new Error();
144
- state.instance.instance.streamOpened(connectionId, streamId, direction, initialWritableBytes);
144
+ state.instance.instance.streamOpened(connectionId, streamId, direction);
145
145
  },
146
- onOpen(info) {
146
+ onMultistreamHandshakeInfo(info) {
147
147
  if (state.instance.status !== "ready")
148
148
  throw new Error();
149
- state.instance.instance.connectionOpened(connectionId, info);
149
+ state.instance.instance.connectionMultiStreamSetHandshakeInfo(connectionId, info);
150
150
  },
151
151
  onWritableBytes(numExtra, streamId) {
152
152
  if (state.instance.status !== "ready")
@@ -103,12 +103,7 @@ export interface Instance {
103
103
  * all connections.
104
104
  */
105
105
  shutdownExecutor: () => void;
106
- connectionOpened: (connectionId: number, info: {
107
- type: 'single-stream';
108
- handshake: 'multistream-select-noise-yamux';
109
- initialWritableBytes: number;
110
- } | {
111
- type: 'multi-stream';
106
+ connectionMultiStreamSetHandshakeInfo: (connectionId: number, info: {
112
107
  handshake: 'webrtc';
113
108
  localTlsCertificateSha256: Uint8Array;
114
109
  remoteTlsCertificateSha256: Uint8Array;
@@ -116,7 +111,7 @@ export interface Instance {
116
111
  connectionReset: (connectionId: number, message: string) => void;
117
112
  streamWritableBytes: (connectionId: number, numExtra: number, streamId?: number) => void;
118
113
  streamMessage: (connectionId: number, message: Uint8Array, streamId?: number) => void;
119
- streamOpened: (connectionId: number, streamId: number, direction: 'inbound' | 'outbound', initialWritableBytes: number) => void;
114
+ streamOpened: (connectionId: number, streamId: number, direction: 'inbound' | 'outbound') => void;
120
115
  streamReset: (connectionId: number, streamId: number) => void;
121
116
  }
122
117
  /**
@@ -404,25 +404,16 @@ function startLocalInstance(config, wasmModule, eventCallback) {
404
404
  state.onShutdownExecutorOrWasmPanic = () => { };
405
405
  cb();
406
406
  },
407
- connectionOpened: (connectionId, info) => {
407
+ connectionMultiStreamSetHandshakeInfo: (connectionId, info) => {
408
408
  if (!state.instance)
409
409
  return;
410
- switch (info.type) {
411
- case 'single-stream': {
412
- state.instance.exports.connection_open_single_stream(connectionId, info.initialWritableBytes);
413
- break;
414
- }
415
- case 'multi-stream': {
416
- const handshakeTy = new Uint8Array(1 + info.localTlsCertificateSha256.length + info.remoteTlsCertificateSha256.length);
417
- buffer.writeUInt8(handshakeTy, 0, 0);
418
- handshakeTy.set(info.localTlsCertificateSha256, 1);
419
- handshakeTy.set(info.remoteTlsCertificateSha256, 1 + info.localTlsCertificateSha256.length);
420
- state.bufferIndices[0] = handshakeTy;
421
- state.instance.exports.connection_open_multi_stream(connectionId, 0);
422
- delete state.bufferIndices[0];
423
- break;
424
- }
425
- }
410
+ const handshakeTy = new Uint8Array(1 + info.localTlsCertificateSha256.length + info.remoteTlsCertificateSha256.length);
411
+ buffer.writeUInt8(handshakeTy, 0, 0);
412
+ handshakeTy.set(info.localTlsCertificateSha256, 1);
413
+ handshakeTy.set(info.remoteTlsCertificateSha256, 1 + info.localTlsCertificateSha256.length);
414
+ state.bufferIndices[0] = handshakeTy;
415
+ state.instance.exports.connection_multi_stream_set_handshake_info(connectionId, 0);
416
+ delete state.bufferIndices[0];
426
417
  },
427
418
  connectionReset: (connectionId, message) => {
428
419
  if (!state.instance)
@@ -443,10 +434,10 @@ function startLocalInstance(config, wasmModule, eventCallback) {
443
434
  state.instance.exports.stream_message(connectionId, streamId || 0, 0);
444
435
  delete state.bufferIndices[0];
445
436
  },
446
- streamOpened: (connectionId, streamId, direction, initialWritableBytes) => {
437
+ streamOpened: (connectionId, streamId, direction) => {
447
438
  if (!state.instance)
448
439
  return;
449
- state.instance.exports.connection_stream_opened(connectionId, streamId, direction === 'outbound' ? 1 : 0, initialWritableBytes);
440
+ state.instance.exports.connection_stream_opened(connectionId, streamId, direction === 'outbound' ? 1 : 0);
450
441
  },
451
442
  streamReset: (connectionId, streamId) => {
452
443
  if (!state.instance)
@@ -179,17 +179,17 @@ function connectToInstanceServer(config) {
179
179
  const msg = { ty: "connection-reset", connectionId, message };
180
180
  portToServer.postMessage(msg);
181
181
  },
182
- connectionOpened(connectionId, info) {
183
- const msg = { ty: "connection-opened", connectionId, info };
182
+ connectionMultiStreamSetHandshakeInfo(connectionId, info) {
183
+ const msg = { ty: "connection-multistream-set-info", connectionId, info };
184
184
  portToServer.postMessage(msg);
185
185
  },
186
186
  streamMessage(connectionId, message, streamId) {
187
187
  const msg = { ty: "stream-message", connectionId, message, streamId };
188
188
  portToServer.postMessage(msg);
189
189
  },
190
- streamOpened(connectionId, streamId, direction, initialWritableBytes) {
190
+ streamOpened(connectionId, streamId, direction) {
191
191
  state.connections.get(connectionId).add(streamId);
192
- const msg = { ty: "stream-opened", connectionId, streamId, direction, initialWritableBytes };
192
+ const msg = { ty: "stream-opened", connectionId, streamId, direction };
193
193
  portToServer.postMessage(msg);
194
194
  },
195
195
  streamWritableBytes(connectionId, numExtra, streamId) {
@@ -321,11 +321,11 @@ function startInstanceServer(config, initPortToClient) {
321
321
  state.instance.connectionReset(message.connectionId, message.message);
322
322
  break;
323
323
  }
324
- case "connection-opened": {
324
+ case "connection-multistream-set-info": {
325
325
  // The connection might have been reset locally in the past.
326
326
  if (!state.connections.has(message.connectionId))
327
327
  return;
328
- state.instance.connectionOpened(message.connectionId, message.info);
328
+ state.instance.connectionMultiStreamSetHandshakeInfo(message.connectionId, message.info);
329
329
  break;
330
330
  }
331
331
  case "stream-message": {
@@ -343,7 +343,7 @@ function startInstanceServer(config, initPortToClient) {
343
343
  if (!state.connections.has(message.connectionId))
344
344
  return;
345
345
  state.connections.get(message.connectionId).add(message.streamId);
346
- state.instance.streamOpened(message.connectionId, message.streamId, message.direction, message.initialWritableBytes);
346
+ state.instance.streamOpened(message.connectionId, message.streamId, message.direction);
347
347
  break;
348
348
  }
349
349
  case "stream-writable-bytes": {
@@ -58,7 +58,7 @@ exports.startWithBytecode = startWithBytecode;
58
58
  * Tries to open a new connection using the given configuration.
59
59
  *
60
60
  * @see Connection
61
- * @throws {@link ConnectionError} If the multiaddress couldn't be parsed or contains an invalid protocol.
61
+ * @throws any If the multiaddress couldn't be parsed or contains an invalid protocol.
62
62
  */
63
63
  function connect(config) {
64
64
  if (config.address.ty === "websocket") {
@@ -103,10 +103,7 @@ function connect(config) {
103
103
  if (connection instanceof WebSocket) {
104
104
  connection.binaryType = 'arraybuffer';
105
105
  connection.onopen = () => {
106
- config.onOpen({
107
- type: 'single-stream', handshake: 'multistream-select-noise-yamux',
108
- initialWritableBytes: 1024 * 1024
109
- });
106
+ config.onWritableBytes(1024 * 1024);
110
107
  };
111
108
  connection.onclose = (event) => {
112
109
  const message = "Error code " + event.code + (!!event.reason ? (": " + event.reason) : "");
@@ -167,10 +164,6 @@ function connect(config) {
167
164
  let pc = undefined;
168
165
  // Contains the data channels that are open and have been reported to smoldot.
169
166
  const dataChannels = new Map();
170
- // For various reasons explained below, we open a data channel in advance without reporting it
171
- // to smoldot. This data channel is stored in this variable. Once it is reported to smoldot,
172
- // it is inserted in `dataChannels`.
173
- let handshakeDataChannel;
174
167
  // SHA256 hash of the DTLS certificate of the local node. Unknown as long as it hasn't been
175
168
  // generated.
176
169
  // TODO: could be merged with `pc` in one variable, and maybe even the other fields as well
@@ -182,7 +175,7 @@ function connect(config) {
182
175
  // The `RTCPeerConnection` is created pretty quickly. It is however still possible for
183
176
  // smoldot to cancel the opening, in which case `pc` will still be undefined.
184
177
  if (!pc) {
185
- console.assert(dataChannels.size === 0 && !handshakeDataChannel, "substreams exist while pc is undef");
178
+ console.assert(dataChannels.size === 0, "substreams exist while pc is undef");
186
179
  pc = null;
187
180
  return;
188
181
  }
@@ -197,14 +190,6 @@ function connect(config) {
197
190
  channel.channel.onmessage = null;
198
191
  }
199
192
  dataChannels.clear();
200
- if (handshakeDataChannel) {
201
- handshakeDataChannel.onopen = null;
202
- handshakeDataChannel.onerror = null;
203
- handshakeDataChannel.onclose = null;
204
- handshakeDataChannel.onbufferedamountlow = null;
205
- handshakeDataChannel.onmessage = null;
206
- }
207
- handshakeDataChannel = undefined;
208
193
  pc.close(); // Not necessarily necessary, but it doesn't hurt to do so.
209
194
  };
210
195
  // Function that configures a newly-opened channel and adds it to the map. Used for both
@@ -212,54 +197,19 @@ function connect(config) {
212
197
  const addChannel = (dataChannel, direction) => {
213
198
  const dataChannelId = dataChannel.id;
214
199
  dataChannel.binaryType = 'arraybuffer';
215
- let isOpen = false;
200
+ let isOpen = { value: false };
216
201
  dataChannel.onopen = () => {
217
- console.assert(!isOpen, "substream opened twice");
218
- isOpen = true;
219
- if (direction === 'first-outbound') {
220
- console.assert(dataChannels.size === 0, "dataChannels not empty when opening");
221
- console.assert(handshakeDataChannel === dataChannel, "handshake substream mismatch");
222
- config.onOpen({
223
- type: 'multi-stream',
224
- handshake: 'webrtc',
225
- // `addChannel` can never be called before the local certificate is generated, so this
226
- // value is always defined.
227
- localTlsCertificateSha256: localTlsCertificateSha256,
228
- remoteTlsCertificateSha256,
229
- });
230
- }
231
- else {
232
- console.assert(direction !== 'outbound' || !handshakeDataChannel, "handshakeDataChannel still defined");
233
- config.onStreamOpened(dataChannelId, direction, 65536);
234
- }
202
+ console.assert(!isOpen.value, "substream opened twice");
203
+ isOpen.value = true;
204
+ config.onStreamOpened(dataChannelId, direction);
205
+ config.onWritableBytes(65536, dataChannelId);
235
206
  };
236
207
  dataChannel.onerror = dataChannel.onclose = (_error) => {
237
- // A couple of different things could be happening here.
238
- if (handshakeDataChannel === dataChannel && !isOpen) {
239
- // The handshake data channel that we have opened ahead of time failed to open. As this
240
- // happens before we have reported the WebRTC connection as a whole as being open, we
241
- // need to report that the connection has failed to open.
242
- killAllJs();
243
- // Note that the event doesn't give any additional reason for the failure.
244
- config.onConnectionReset("handshake data channel failed to open");
245
- }
246
- else if (handshakeDataChannel === dataChannel) {
247
- // The handshake data channel has been closed before we reported it to smoldot. This
248
- // isn't really a problem. We just update the state and continue running. If smoldot
249
- // requests a substream, another one will be opened. It could be a valid implementation
250
- // to also just kill the entire connection, however doing so is a bit too intrusive and
251
- // punches through abstraction layers.
252
- handshakeDataChannel.onopen = null;
253
- handshakeDataChannel.onerror = null;
254
- handshakeDataChannel.onclose = null;
255
- handshakeDataChannel.onbufferedamountlow = null;
256
- handshakeDataChannel.onmessage = null;
257
- handshakeDataChannel = undefined;
258
- }
259
- else if (!isOpen) {
260
- // Substream wasn't opened yet and thus has failed to open. The API has no mechanism to
261
- // report substream openings failures. We could try opening it again, but given that
262
- // it's unlikely to succeed, we simply opt to kill the entire connection.
208
+ if (!isOpen.value) {
209
+ // Substream wasn't opened yet and thus has failed to open. The API has no
210
+ // mechanism to report substream openings failures. We could try opening it
211
+ // again, but given that it's unlikely to succeed, we simply opt to kill the
212
+ // entire connection.
263
213
  killAllJs();
264
214
  // Note that the event doesn't give any additional reason for the failure.
265
215
  config.onConnectionReset("data channel failed to open");
@@ -279,10 +229,7 @@ function connect(config) {
279
229
  // The `data` field is an `ArrayBuffer`.
280
230
  config.onMessage(new Uint8Array(m.data), dataChannelId);
281
231
  };
282
- if (direction !== 'first-outbound')
283
- dataChannels.set(dataChannelId, { channel: dataChannel, bufferedBytes: 0 });
284
- else
285
- handshakeDataChannel = dataChannel;
232
+ dataChannels.set(dataChannelId, { channel: dataChannel, bufferedBytes: 0 });
286
233
  };
287
234
  // It is possible for the browser to use multiple different certificates.
288
235
  // In order for our local certificate to be deterministic, we need to generate it manually and
@@ -432,16 +379,11 @@ function connect(config) {
432
379
  // TODO: is the substream maybe already open? according to the Internet it seems that no but it's unclear
433
380
  addChannel(channel, 'inbound');
434
381
  };
435
- // Creating a `RTCPeerConnection` doesn't actually do anything before `createDataChannel` is
436
- // called. Smoldot's API, however, requires you to treat entire connections as open or
437
- // closed. We know, according to the libp2p WebRTC specification, that every connection
438
- // always starts with a substream where a handshake is performed. After we've reported that
439
- // the connection is open, smoldot will open a substream in order to perform the handshake.
440
- // Instead of following this API, we open this substream in advance, and will notify smoldot
441
- // that the connection is open when the substream is open.
442
- // Note that the label passed to `createDataChannel` is required to be empty as per the
443
- // libp2p WebRTC specification.
444
- addChannel(pc.createDataChannel("", { id: 0, negotiated: true }), 'first-outbound');
382
+ config.onMultistreamHandshakeInfo({
383
+ handshake: 'webrtc',
384
+ localTlsCertificateSha256,
385
+ remoteTlsCertificateSha256,
386
+ });
445
387
  }));
446
388
  return {
447
389
  reset: (streamId) => {
@@ -467,27 +409,11 @@ function connect(config) {
467
409
  },
468
410
  closeSend: () => { throw new Error('Wrong connection type'); },
469
411
  openOutSubstream: () => {
470
- // `openOutSubstream` can only be called after we have called `config.onOpen`, therefore
471
- // `pc` is guaranteed to be non-null.
472
- // As explained above, we open a data channel ahead of time. If this data channel is still
473
- // there, we report it.
474
- if (handshakeDataChannel) {
475
- // Do this asynchronously because calling callbacks within callbacks is error-prone.
476
- (() => __awaiter(this, void 0, void 0, function* () {
477
- // We need to check again if `handshakeDataChannel` is still defined, as the
478
- // connection might have been closed.
479
- if (handshakeDataChannel) {
480
- config.onStreamOpened(handshakeDataChannel.id, 'outbound', 1024 * 1024);
481
- dataChannels.set(handshakeDataChannel.id, { channel: handshakeDataChannel, bufferedBytes: 0 });
482
- handshakeDataChannel = undefined;
483
- }
484
- }))();
485
- }
486
- else {
487
- // Note that the label passed to `createDataChannel` is required to be empty as per the
488
- // libp2p WebRTC specification.
489
- addChannel(pc.createDataChannel(""), 'outbound');
490
- }
412
+ // `openOutSubstream` can only be called after we have called `config.onOpen`,
413
+ // therefore `pc` is guaranteed to be non-null.
414
+ // Note that the label passed to `createDataChannel` is required to be empty as
415
+ // per the libp2p WebRTC specification.
416
+ addChannel(pc.createDataChannel(""), 'outbound');
491
417
  }
492
418
  };
493
419
  }
@@ -79,7 +79,7 @@ function connect(config) {
79
79
  config.onWritableBytes(wasSent);
80
80
  };
81
81
  socket.onopen = () => {
82
- config.onOpen({ type: 'single-stream', handshake: 'multistream-select-noise-yamux', initialWritableBytes: 1024 * 1024 });
82
+ config.onWritableBytes(1024 * 1024);
83
83
  };
84
84
  socket.onclose = (event) => {
85
85
  const message = "Error code " + event.code + (!!event.reason ? (": " + event.reason) : "");
@@ -134,7 +134,7 @@ function connect(config) {
134
134
  if (socket.destroyed)
135
135
  return established;
136
136
  established === null || established === void 0 ? void 0 : established.setNoDelay();
137
- config.onOpen({ type: 'single-stream', handshake: 'multistream-select-noise-yamux', initialWritableBytes: 1024 * 1024 });
137
+ config.onWritableBytes(1024 * 1024);
138
138
  // Spawns an asynchronous task that continuously reads from the socket.
139
139
  // Every time data is read, the task re-executes itself in order to continue reading.
140
140
  // The task ends automatically if an EOF or error is detected, which should also happen
@@ -75,7 +75,7 @@ function connect(config) {
75
75
  config.onWritableBytes(wasSent);
76
76
  };
77
77
  socket.onopen = () => {
78
- config.onOpen({ type: 'single-stream', handshake: 'multistream-select-noise-yamux', initialWritableBytes: 1024 * 1024 });
78
+ config.onWritableBytes(1024 * 1024);
79
79
  };
80
80
  socket.onclose = (event) => {
81
81
  const message = "Error code " + event.code + (!!event.reason ? (": " + event.reason) : "");
@@ -128,10 +128,7 @@ function connect(config) {
128
128
  socket.on('connect', () => {
129
129
  if (socket.destroyed)
130
130
  return;
131
- config.onOpen({
132
- type: 'single-stream', handshake: 'multistream-select-noise-yamux',
133
- initialWritableBytes: socket.writableHighWaterMark
134
- });
131
+ config.onWritableBytes(socket.writableHighWaterMark);
135
132
  });
136
133
  socket.on('close', (hasError) => {
137
134
  if (socket.destroyed)
@@ -90,19 +90,19 @@ export interface Chain {
90
90
  /**
91
91
  * Enqueues a JSON-RPC request that the client will process as soon as possible.
92
92
  *
93
- * The response will be sent back using the callback passed when adding the chain.
93
+ * The response can be pulled by calling {@link Chain.nextJsonRpcResponse}.
94
94
  *
95
95
  * See <https://www.jsonrpc.org/specification> for a specification of the JSON-RPC format. Only
96
96
  * version 2 is supported.
97
- * Be aware that some requests will cause notifications to be sent back using the same callback
98
- * as the responses.
97
+ * Be aware that some requests will cause notifications to be sent back through
98
+ * {@link Chain.nextJsonRpcResponse}.
99
99
  *
100
100
  * If the request is not a valid JSON-RPC request, then a JSON-RPC error response is later
101
101
  * generated with an `id` equal to `null`, in accordance with the JSON-RPC 2.0 specification.
102
102
  *
103
103
  * If, however, the request is a valid JSON-RPC request but that concerns an unknown method, or
104
104
  * if for example some parameters are missing, an error response is properly generated and
105
- * yielded through the JSON-RPC callback.
105
+ * yielded through {@link Chain.nextJsonRpcResponse}.
106
106
  *
107
107
  * Two JSON-RPC APIs are supported by smoldot:
108
108
  *
@@ -121,9 +121,10 @@ export interface Chain {
121
121
  * Waits for a JSON-RPC response or notification to be generated.
122
122
  *
123
123
  * Each chain contains a buffer of the responses waiting to be sent out. Calling this function
124
- * pulls one element from the buffer. If this function is called at a slower rate than responses
125
- * are generated, then the buffer will eventually become full, at which point calling
126
- * {@link Chain.sendJsonRpc} will throw an exception.
124
+ * pulls one element from the buffer. If this function is called at a slower rate than
125
+ * responses are generated, then the buffer will eventually become full, at which point calling
126
+ * {@link Chain.sendJsonRpc} will throw an exception. The size of this buffer can be configured
127
+ * through {@link AddChainOptions.jsonRpcMaxPendingRequests}.
127
128
  *
128
129
  * If this function is called multiple times "simultaneously" (generating multiple different
129
130
  * `Promise`s), each `Promise` will return a different JSON-RPC response or notification. In
@@ -139,11 +140,11 @@ export interface Chain {
139
140
  /**
140
141
  * Disconnects from the blockchain.
141
142
  *
142
- * The JSON-RPC callback will no longer be called. This is the case immediately after this
143
- * function is called. Any on-going JSON-RPC request is instantaneously aborted.
143
+ * Any on-going call to {@link Chain.nextJsonRpcResponse} is instantaneously aborted and will
144
+ * throw a {@link AlreadyDestroyedError}.
144
145
  *
145
- * Trying to use the chain again will lead to a {@link AlreadyDestroyedError} exception
146
- * being thrown.
146
+ * Trying to use the chain again after this function has returned will lead to a
147
+ * {@link AlreadyDestroyedError} exception being thrown.
147
148
  *
148
149
  * While the chain instantaneously disappears from the public API as soon as this function is
149
150
  * called, its shutdown process actually happens asynchronously in the background. This means
@@ -369,7 +370,7 @@ export interface AddChainOptions {
369
370
  *
370
371
  * This field is ignored if {@link AddChainOptions.disableJsonRpc} is `true`.
371
372
  *
372
- * A zero, negative or NaN value is invalid.
373
+ * A zero, negative or NaN value is invalid and will generate a {@link AddChainError}.
373
374
  *
374
375
  * If this value is not set, it means that there is no maximum.
375
376
  */
@@ -379,7 +380,7 @@ export interface AddChainOptions {
379
380
  *
380
381
  * This field is ignored if {@link AddChainOptions.disableJsonRpc} is `true`.
381
382
  *
382
- * A negative or NaN value is invalid.
383
+ * A negative or NaN value is invalid and will generate a {@link AddChainError}.
383
384
  *
384
385
  * If this value is not set, it means that there is no maximum.
385
386
  */