smoldot 1.0.3 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. package/README.md +58 -0
  2. package/dist/cjs/bytecode-browser.d.ts +5 -0
  3. package/dist/cjs/bytecode-browser.js +42 -0
  4. package/dist/cjs/bytecode-deno.d.ts +5 -0
  5. package/dist/cjs/bytecode-deno.js +87 -0
  6. package/dist/cjs/bytecode-nodejs.d.ts +5 -0
  7. package/dist/cjs/bytecode-nodejs.js +41 -0
  8. package/dist/cjs/index-browser.d.ts +2 -2
  9. package/dist/cjs/index-browser.js +10 -495
  10. package/dist/cjs/index-deno.d.ts +2 -2
  11. package/dist/cjs/index-deno.js +10 -273
  12. package/dist/cjs/index-nodejs.d.ts +2 -2
  13. package/dist/cjs/index-nodejs.js +10 -208
  14. package/dist/cjs/internals/bytecode/wasm0.js +4 -0
  15. package/dist/cjs/internals/bytecode/wasm1.js +4 -0
  16. package/dist/cjs/internals/bytecode/wasm2.js +4 -0
  17. package/dist/cjs/{instance/bindings-smoldot-light.d.ts → internals/client.d.ts} +15 -33
  18. package/dist/cjs/internals/client.js +364 -0
  19. package/dist/cjs/internals/local-instance.d.ts +140 -0
  20. package/dist/cjs/internals/local-instance.js +555 -0
  21. package/dist/cjs/internals/remote-instance.d.ts +38 -0
  22. package/dist/cjs/internals/remote-instance.js +381 -0
  23. package/dist/cjs/no-auto-bytecode-browser.d.ts +11 -0
  24. package/dist/cjs/no-auto-bytecode-browser.js +481 -0
  25. package/dist/cjs/no-auto-bytecode-deno.d.ts +10 -0
  26. package/dist/cjs/no-auto-bytecode-deno.js +220 -0
  27. package/dist/cjs/no-auto-bytecode-nodejs.d.ts +10 -0
  28. package/dist/cjs/no-auto-bytecode-nodejs.js +189 -0
  29. package/dist/{mjs/client.d.ts → cjs/public-types.d.ts} +51 -3
  30. package/dist/cjs/public-types.js +76 -0
  31. package/dist/cjs/worker-browser.d.ts +11 -0
  32. package/dist/cjs/worker-browser.js +63 -0
  33. package/dist/cjs/worker-deno.d.ts +11 -0
  34. package/dist/cjs/worker-deno.js +54 -0
  35. package/dist/cjs/worker-nodejs.d.ts +11 -0
  36. package/dist/cjs/worker-nodejs.js +55 -0
  37. package/dist/mjs/bytecode-browser.d.ts +5 -0
  38. package/dist/mjs/bytecode-browser.js +38 -0
  39. package/dist/mjs/bytecode-deno.d.ts +5 -0
  40. package/dist/mjs/bytecode-deno.js +83 -0
  41. package/dist/mjs/bytecode-nodejs.d.ts +5 -0
  42. package/dist/mjs/bytecode-nodejs.js +37 -0
  43. package/dist/mjs/index-browser.d.ts +2 -2
  44. package/dist/mjs/index-browser.js +4 -489
  45. package/dist/mjs/index-deno.d.ts +2 -2
  46. package/dist/mjs/index-deno.js +4 -267
  47. package/dist/mjs/index-nodejs.d.ts +2 -2
  48. package/dist/mjs/index-nodejs.js +4 -202
  49. package/dist/mjs/internals/bytecode/wasm0.js +1 -0
  50. package/dist/mjs/internals/bytecode/wasm1.js +1 -0
  51. package/dist/mjs/internals/bytecode/wasm2.js +1 -0
  52. package/dist/mjs/{instance/bindings-smoldot-light.d.ts → internals/client.d.ts} +15 -33
  53. package/dist/mjs/internals/client.js +360 -0
  54. package/dist/mjs/internals/local-instance.d.ts +140 -0
  55. package/dist/mjs/internals/local-instance.js +550 -0
  56. package/dist/mjs/internals/remote-instance.d.ts +38 -0
  57. package/dist/mjs/internals/remote-instance.js +376 -0
  58. package/dist/mjs/no-auto-bytecode-browser.d.ts +11 -0
  59. package/dist/mjs/no-auto-bytecode-browser.js +471 -0
  60. package/dist/mjs/no-auto-bytecode-deno.d.ts +10 -0
  61. package/dist/mjs/no-auto-bytecode-deno.js +210 -0
  62. package/dist/mjs/no-auto-bytecode-nodejs.d.ts +10 -0
  63. package/dist/mjs/no-auto-bytecode-nodejs.js +179 -0
  64. package/dist/{cjs/client.d.ts → mjs/public-types.d.ts} +51 -3
  65. package/dist/mjs/public-types.js +67 -0
  66. package/dist/mjs/worker-browser.d.ts +11 -0
  67. package/dist/mjs/worker-browser.js +59 -0
  68. package/dist/mjs/worker-deno.d.ts +11 -0
  69. package/dist/mjs/worker-deno.js +50 -0
  70. package/dist/mjs/worker-nodejs.d.ts +11 -0
  71. package/dist/mjs/worker-nodejs.js +51 -0
  72. package/package.json +39 -7
  73. package/dist/cjs/client.js +0 -175
  74. package/dist/cjs/instance/autogen/wasm0.js +0 -4
  75. package/dist/cjs/instance/autogen/wasm1.js +0 -4
  76. package/dist/cjs/instance/autogen/wasm2.js +0 -4
  77. package/dist/cjs/instance/bindings-smoldot-light.js +0 -282
  78. package/dist/cjs/instance/bindings-wasi.d.ts +0 -27
  79. package/dist/cjs/instance/bindings-wasi.js +0 -172
  80. package/dist/cjs/instance/bindings.d.ts +0 -31
  81. package/dist/cjs/instance/bindings.js +0 -5
  82. package/dist/cjs/instance/instance.d.ts +0 -45
  83. package/dist/cjs/instance/instance.js +0 -295
  84. package/dist/cjs/instance/raw-instance.d.ts +0 -65
  85. package/dist/cjs/instance/raw-instance.js +0 -74
  86. package/dist/mjs/client.js +0 -165
  87. package/dist/mjs/instance/autogen/wasm0.js +0 -1
  88. package/dist/mjs/instance/autogen/wasm1.js +0 -1
  89. package/dist/mjs/instance/autogen/wasm2.js +0 -1
  90. package/dist/mjs/instance/bindings-smoldot-light.js +0 -277
  91. package/dist/mjs/instance/bindings-wasi.d.ts +0 -27
  92. package/dist/mjs/instance/bindings-wasi.js +0 -170
  93. package/dist/mjs/instance/bindings.d.ts +0 -31
  94. package/dist/mjs/instance/bindings.js +0 -4
  95. package/dist/mjs/instance/instance.d.ts +0 -45
  96. package/dist/mjs/instance/instance.js +0 -287
  97. package/dist/mjs/instance/raw-instance.d.ts +0 -65
  98. package/dist/mjs/instance/raw-instance.js +0 -69
  99. /package/dist/cjs/{base64.d.ts → internals/base64.d.ts} +0 -0
  100. /package/dist/cjs/{base64.js → internals/base64.js} +0 -0
  101. /package/dist/cjs/{instance → internals}/buffer.d.ts +0 -0
  102. /package/dist/cjs/{instance → internals}/buffer.js +0 -0
  103. /package/dist/cjs/{instance/autogen → internals/bytecode}/wasm.d.ts +0 -0
  104. /package/dist/cjs/{instance/autogen → internals/bytecode}/wasm.js +0 -0
  105. /package/dist/cjs/{instance/autogen → internals/bytecode}/wasm0.d.ts +0 -0
  106. /package/dist/cjs/{instance/autogen → internals/bytecode}/wasm1.d.ts +0 -0
  107. /package/dist/cjs/{instance/autogen → internals/bytecode}/wasm2.d.ts +0 -0
  108. /package/dist/mjs/{base64.d.ts → internals/base64.d.ts} +0 -0
  109. /package/dist/mjs/{base64.js → internals/base64.js} +0 -0
  110. /package/dist/mjs/{instance → internals}/buffer.d.ts +0 -0
  111. /package/dist/mjs/{instance → internals}/buffer.js +0 -0
  112. /package/dist/mjs/{instance/autogen → internals/bytecode}/wasm.d.ts +0 -0
  113. /package/dist/mjs/{instance/autogen → internals/bytecode}/wasm.js +0 -0
  114. /package/dist/mjs/{instance/autogen → internals/bytecode}/wasm0.d.ts +0 -0
  115. /package/dist/mjs/{instance/autogen → internals/bytecode}/wasm1.d.ts +0 -0
  116. /package/dist/mjs/{instance/autogen → internals/bytecode}/wasm2.d.ts +0 -0
@@ -1,12 +1,9 @@
1
- import type { SmoldotWasmInstance } from './bindings.js';
2
- export interface Config {
3
- instance?: SmoldotWasmInstance;
4
- /**
5
- * Array used to store the buffers provided to the Rust code.
6
- *
7
- * When `buffer_size` or `buffer_index` are called, the buffer is found here.
8
- */
9
- bufferIndices: Array<Uint8Array>;
1
+ import { Client, ClientOptions, SmoldotBytecode } from '../public-types.js';
2
+ import * as instance from './local-instance.js';
3
+ /**
4
+ * Contains functions that the client will use when it needs to leverage the platform.
5
+ */
6
+ export interface PlatformBindings {
10
7
  /**
11
8
  * Tries to open a new connection using the given configuration.
12
9
  *
@@ -15,14 +12,13 @@ export interface Config {
15
12
  */
16
13
  connect(config: ConnectionConfig): Connection;
17
14
  /**
18
- * Closure to call when the Wasm instance calls `panic`.
19
- *
20
- * This callback will always be invoked from within a binding called the Wasm instance.
15
+ * Returns the number of milliseconds since an arbitrary epoch.
16
+ */
17
+ performanceNow: () => number;
18
+ /**
19
+ * Fills the given buffer with randomly-generated bytes.
21
20
  */
22
- onPanic: (message: string) => never;
23
- logCallback: (level: number, target: string, message: string) => void;
24
- jsonRpcResponsesNonEmptyCallback: (chainId: number) => void;
25
- currentTaskCallback?: (taskName: string | null) => void;
21
+ getRandomValues: (buffer: Uint8Array) => void;
26
22
  }
27
23
  /**
28
24
  * Connection to a remote node.
@@ -113,12 +109,9 @@ export interface Connection {
113
109
  */
114
110
  export interface ConnectionConfig {
115
111
  /**
116
- * Multiaddress in string format that describes which node to try to connect to.
117
- *
118
- * Note that this address shouldn't be trusted. The value in this field might have been chosen
119
- * by a potentially malicious peer.
112
+ * Parsed multiaddress, as returned by the `parseMultiaddr` function.
120
113
  */
121
- address: string;
114
+ address: instance.ParsedMultiaddr;
122
115
  /**
123
116
  * Callback called when the connection transitions from the `Opening` to the `Open` state.
124
117
  *
@@ -180,15 +173,4 @@ export interface ConnectionConfig {
180
173
  */
181
174
  onMessage: (message: Uint8Array, streamId?: number) => void;
182
175
  }
183
- /**
184
- * Emitted by `connect` if the multiaddress couldn't be parsed or contains an invalid protocol.
185
- *
186
- * @see connect
187
- */
188
- export declare class ConnectionError extends Error {
189
- constructor(message: string);
190
- }
191
- export default function (config: Config): {
192
- imports: WebAssembly.ModuleImports;
193
- killAll: () => void;
194
- };
176
+ export declare function start(options: ClientOptions, wasmModule: SmoldotBytecode | Promise<SmoldotBytecode>, platformBindings: PlatformBindings): Client;
@@ -0,0 +1,364 @@
1
+ "use strict";
2
+ // Smoldot
3
+ // Copyright (C) 2019-2022 Parity Technologies (UK) Ltd.
4
+ // SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
5
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
6
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
7
+ return new (P || (P = Promise))(function (resolve, reject) {
8
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
9
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
10
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
11
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
12
+ });
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.start = void 0;
16
+ // This program is free software: you can redistribute it and/or modify
17
+ // it under the terms of the GNU General Public License as published by
18
+ // the Free Software Foundation, either version 3 of the License, or
19
+ // (at your option) any later version.
20
+ // This program is distributed in the hope that it will be useful,
21
+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
22
+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23
+ // GNU General Public License for more details.
24
+ // You should have received a copy of the GNU General Public License
25
+ // along with this program. If not, see <http://www.gnu.org/licenses/>.
26
+ const public_types_js_1 = require("../public-types.js");
27
+ const instance = require("./local-instance.js");
28
+ const remote = require("./remote-instance.js");
29
+ // This function is similar to the `start` function found in `index.ts`, except with an extra
30
+ // parameter containing the platform-specific bindings.
31
+ // Contrary to the one within `index.js`, this function is not supposed to be directly used.
32
+ function start(options, wasmModule, platformBindings) {
33
+ const logCallback = options.logCallback || ((level, target, message) => {
34
+ // The first parameter of the methods of `console` has some printf-like substitution
35
+ // capabilities. We don't really need to use this, but not using it means that the logs might
36
+ // not get printed correctly if they contain `%`.
37
+ if (level <= 1) {
38
+ console.error("[%s] %s", target, message);
39
+ }
40
+ else if (level == 2) {
41
+ console.warn("[%s] %s", target, message);
42
+ }
43
+ else if (level == 3) {
44
+ console.info("[%s] %s", target, message);
45
+ }
46
+ else if (level == 4) {
47
+ console.debug("[%s] %s", target, message);
48
+ }
49
+ else {
50
+ console.trace("[%s] %s", target, message);
51
+ }
52
+ });
53
+ if (!(wasmModule instanceof Promise)) {
54
+ wasmModule = Promise.resolve(wasmModule);
55
+ }
56
+ // Extract (to make sure the value doesn't change) and sanitize `cpuRateLimit`.
57
+ let cpuRateLimit = options.cpuRateLimit || 1.0;
58
+ if (isNaN(cpuRateLimit))
59
+ cpuRateLimit = 1.0;
60
+ if (cpuRateLimit > 1.0)
61
+ cpuRateLimit = 1.0;
62
+ if (cpuRateLimit < 0.0)
63
+ cpuRateLimit = 0.0;
64
+ // This object holds the state of everything.
65
+ const state = {
66
+ instance: { status: "not-created" },
67
+ chainIds: new WeakMap(),
68
+ currentTaskName: null,
69
+ connections: new Map(),
70
+ addChainResults: [],
71
+ chains: new Map(),
72
+ };
73
+ // Callback called during the execution of the instance.
74
+ const eventCallback = (event) => {
75
+ switch (event.ty) {
76
+ case "wasm-panic": {
77
+ console.error("Smoldot has panicked" +
78
+ (state.currentTaskName ? (" while executing task `" + state.currentTaskName + "`") : "") +
79
+ ". This is a bug in smoldot. Please open an issue at " +
80
+ "https://github.com/smol-dot/smoldot/issues with the following message:\n" +
81
+ event.message);
82
+ state.instance = {
83
+ status: "destroyed",
84
+ error: new public_types_js_1.CrashError(event.message),
85
+ };
86
+ state.connections.forEach((connec) => connec.reset());
87
+ state.connections.clear();
88
+ for (const addChainResult of state.addChainResults) {
89
+ addChainResult({ success: false, error: "Smoldot has crashed" });
90
+ }
91
+ state.addChainResults = [];
92
+ for (const chain of Array.from(state.chains.values())) {
93
+ for (const callback of chain.jsonRpcResponsesPromises) {
94
+ callback();
95
+ }
96
+ chain.jsonRpcResponsesPromises = [];
97
+ }
98
+ state.chains.clear();
99
+ state.currentTaskName = null;
100
+ break;
101
+ }
102
+ case "log": {
103
+ logCallback(event.level, event.target, event.message);
104
+ break;
105
+ }
106
+ case "add-chain-result": {
107
+ (state.addChainResults.shift())(event);
108
+ break;
109
+ }
110
+ case "json-rpc-responses-non-empty": {
111
+ // Notify every single promise found in `jsonRpcResponsesPromises`.
112
+ const callbacks = state.chains.get(event.chainId).jsonRpcResponsesPromises;
113
+ while (callbacks.length !== 0) {
114
+ (callbacks.shift())();
115
+ }
116
+ break;
117
+ }
118
+ case "current-task": {
119
+ state.currentTaskName = event.taskName;
120
+ break;
121
+ }
122
+ case "new-connection": {
123
+ const connectionId = event.connectionId;
124
+ state.connections.set(connectionId, platformBindings.connect({
125
+ address: event.address,
126
+ onConnectionReset(message) {
127
+ if (state.instance.status !== "ready")
128
+ throw new Error();
129
+ state.connections.delete(connectionId);
130
+ state.instance.instance.connectionReset(connectionId, message);
131
+ },
132
+ onMessage(message, streamId) {
133
+ if (state.instance.status !== "ready")
134
+ throw new Error();
135
+ state.instance.instance.streamMessage(connectionId, message, streamId);
136
+ },
137
+ onStreamOpened(streamId, direction, initialWritableBytes) {
138
+ if (state.instance.status !== "ready")
139
+ throw new Error();
140
+ state.instance.instance.streamOpened(connectionId, streamId, direction, initialWritableBytes);
141
+ },
142
+ onOpen(info) {
143
+ if (state.instance.status !== "ready")
144
+ throw new Error();
145
+ state.instance.instance.connectionOpened(connectionId, info);
146
+ },
147
+ onWritableBytes(numExtra, streamId) {
148
+ if (state.instance.status !== "ready")
149
+ throw new Error();
150
+ state.instance.instance.streamWritableBytes(connectionId, numExtra, streamId);
151
+ },
152
+ onStreamReset(streamId) {
153
+ if (state.instance.status !== "ready")
154
+ throw new Error();
155
+ state.instance.instance.streamReset(connectionId, streamId);
156
+ },
157
+ }));
158
+ break;
159
+ }
160
+ case "connection-reset": {
161
+ const connection = state.connections.get(event.connectionId);
162
+ connection.reset();
163
+ state.connections.delete(event.connectionId);
164
+ break;
165
+ }
166
+ case "connection-stream-open": {
167
+ const connection = state.connections.get(event.connectionId);
168
+ connection.openOutSubstream();
169
+ break;
170
+ }
171
+ case "connection-stream-reset": {
172
+ const connection = state.connections.get(event.connectionId);
173
+ connection.reset(event.streamId);
174
+ break;
175
+ }
176
+ case "stream-send": {
177
+ const connection = state.connections.get(event.connectionId);
178
+ connection.send(event.data, event.streamId);
179
+ break;
180
+ }
181
+ case "stream-send-close": {
182
+ const connection = state.connections.get(event.connectionId);
183
+ connection.closeSend(event.streamId);
184
+ break;
185
+ }
186
+ }
187
+ };
188
+ const portToWorker = options.portToWorker;
189
+ if (!portToWorker) {
190
+ // Start a local instance.
191
+ state.instance = {
192
+ status: "not-ready",
193
+ whenReady: wasmModule
194
+ .then((wasmModule) => {
195
+ return instance.startLocalInstance({
196
+ forbidTcp: options.forbidTcp || false,
197
+ forbidWs: options.forbidWs || false,
198
+ forbidNonLocalWs: options.forbidNonLocalWs || false,
199
+ forbidWss: options.forbidWss || false,
200
+ forbidWebRtc: options.forbidWebRtc || false,
201
+ maxLogLevel: options.maxLogLevel || 3,
202
+ cpuRateLimit,
203
+ envVars: [],
204
+ performanceNow: platformBindings.performanceNow,
205
+ getRandomValues: platformBindings.getRandomValues,
206
+ }, wasmModule.wasm, eventCallback);
207
+ })
208
+ .then((instance) => {
209
+ // The Wasm instance might have been crashed before this callback is called.
210
+ if (state.instance.status === "destroyed")
211
+ return;
212
+ state.instance = {
213
+ status: "ready",
214
+ instance,
215
+ };
216
+ })
217
+ };
218
+ }
219
+ else {
220
+ // Connect to the remote instance.
221
+ state.instance = {
222
+ status: "not-ready",
223
+ whenReady: remote.connectToInstanceServer({
224
+ wasmModule: wasmModule.then((b) => b.wasm),
225
+ forbidTcp: options.forbidTcp || false,
226
+ forbidWs: options.forbidWs || false,
227
+ forbidNonLocalWs: options.forbidNonLocalWs || false,
228
+ forbidWss: options.forbidWss || false,
229
+ forbidWebRtc: options.forbidWebRtc || false,
230
+ maxLogLevel: options.maxLogLevel || 3,
231
+ cpuRateLimit,
232
+ portToServer: portToWorker,
233
+ eventCallback
234
+ }).then((instance) => {
235
+ // The Wasm instance might have been crashed before this callback is called.
236
+ if (state.instance.status === "destroyed")
237
+ return;
238
+ state.instance = {
239
+ status: "ready",
240
+ instance,
241
+ };
242
+ })
243
+ };
244
+ }
245
+ return {
246
+ addChain: (options) => __awaiter(this, void 0, void 0, function* () {
247
+ if (state.instance.status === "not-ready")
248
+ yield state.instance.whenReady;
249
+ if (state.instance.status === "destroyed")
250
+ throw state.instance.error;
251
+ if (state.instance.status === "not-created" || state.instance.status === "not-ready")
252
+ throw new Error(); // Internal error, not supposed to ever happen.
253
+ // Passing a JSON object for the chain spec is an easy mistake, so we provide a more
254
+ // readable error.
255
+ if (!(typeof options.chainSpec === 'string'))
256
+ throw new Error("Chain specification must be a string");
257
+ let potentialRelayChainsIds = [];
258
+ if (!!options.potentialRelayChains) {
259
+ for (const chain of options.potentialRelayChains) {
260
+ // The content of `options.potentialRelayChains` are supposed to be chains earlier
261
+ // returned by `addChain`.
262
+ const id = state.chainIds.get(chain);
263
+ if (id === undefined) // It is possible for `id` to be missing if it has earlier been removed.
264
+ continue;
265
+ potentialRelayChainsIds.push(id);
266
+ }
267
+ }
268
+ const promise = new Promise((resolve) => state.addChainResults.push(resolve));
269
+ state.instance.instance.addChain(options.chainSpec, typeof options.databaseContent === 'string' ? options.databaseContent : "", potentialRelayChainsIds, !!options.disableJsonRpc);
270
+ const outcome = yield promise;
271
+ if (!outcome.success)
272
+ throw new public_types_js_1.AddChainError(outcome.error);
273
+ const chainId = outcome.chainId;
274
+ state.chains.set(chainId, {
275
+ jsonRpcResponsesPromises: new Array()
276
+ });
277
+ const newChain = {
278
+ sendJsonRpc: (request) => {
279
+ if (state.instance.status === "destroyed")
280
+ throw state.instance.error;
281
+ if (state.instance.status !== "ready")
282
+ throw new Error(); // Internal error. Never supposed to happen.
283
+ if (!state.chains.has(chainId))
284
+ throw new public_types_js_1.AlreadyDestroyedError();
285
+ if (options.disableJsonRpc)
286
+ throw new public_types_js_1.JsonRpcDisabledError();
287
+ if (request.length >= 64 * 1024 * 1024) {
288
+ throw new public_types_js_1.MalformedJsonRpcError();
289
+ }
290
+ ;
291
+ const retVal = state.instance.instance.request(request, chainId);
292
+ switch (retVal) {
293
+ case 0: break;
294
+ case 1: throw new public_types_js_1.MalformedJsonRpcError();
295
+ case 2: throw new public_types_js_1.QueueFullError();
296
+ default: throw new Error("Internal error: unknown json_rpc_send error code: " + retVal);
297
+ }
298
+ },
299
+ nextJsonRpcResponse: () => __awaiter(this, void 0, void 0, function* () {
300
+ if (!state.chains.has(chainId))
301
+ throw new public_types_js_1.AlreadyDestroyedError();
302
+ if (options.disableJsonRpc)
303
+ return Promise.reject(new public_types_js_1.JsonRpcDisabledError());
304
+ while (true) {
305
+ if (state.instance.status === "destroyed")
306
+ throw state.instance.error;
307
+ if (state.instance.status !== "ready")
308
+ throw new Error(); // Internal error. Never supposed to happen.
309
+ // Try to pop a message from the queue.
310
+ const message = state.instance.instance.peekJsonRpcResponse(chainId);
311
+ if (message)
312
+ return message;
313
+ // If no message is available, wait for one to be.
314
+ yield new Promise((resolve) => {
315
+ state.chains.get(chainId).jsonRpcResponsesPromises.push(resolve);
316
+ });
317
+ }
318
+ }),
319
+ remove: () => {
320
+ if (state.instance.status === "destroyed")
321
+ throw state.instance.error;
322
+ if (state.instance.status !== "ready")
323
+ throw new Error(); // Internal error. Never supposed to happen.
324
+ if (!state.chains.has(chainId))
325
+ throw new public_types_js_1.AlreadyDestroyedError();
326
+ console.assert(state.chainIds.has(newChain));
327
+ state.chainIds.delete(newChain);
328
+ for (const callback of state.chains.get(chainId).jsonRpcResponsesPromises) {
329
+ callback();
330
+ }
331
+ state.chains.delete(chainId);
332
+ state.instance.instance.removeChain(chainId);
333
+ },
334
+ };
335
+ state.chainIds.set(newChain, chainId);
336
+ return newChain;
337
+ }),
338
+ terminate: () => __awaiter(this, void 0, void 0, function* () {
339
+ if (state.instance.status === "not-ready")
340
+ yield state.instance.whenReady;
341
+ if (state.instance.status === "destroyed")
342
+ throw state.instance.error;
343
+ if (state.instance.status !== "ready")
344
+ throw new Error(); // Internal error. Never supposed to happen.
345
+ state.instance.instance.startShutdown();
346
+ state.instance = { status: "destroyed", error: new public_types_js_1.AlreadyDestroyedError() };
347
+ state.connections.forEach((connec) => connec.reset());
348
+ state.connections.clear();
349
+ for (const addChainResult of state.addChainResults) {
350
+ addChainResult({ success: false, error: "Smoldot has crashed" });
351
+ }
352
+ state.addChainResults = [];
353
+ for (const chain of Array.from(state.chains.values())) {
354
+ for (const callback of chain.jsonRpcResponsesPromises) {
355
+ callback();
356
+ }
357
+ chain.jsonRpcResponsesPromises = [];
358
+ }
359
+ state.chains.clear();
360
+ state.currentTaskName = null;
361
+ })
362
+ };
363
+ }
364
+ exports.start = start;
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Configuration for {@link startLocalInstance}.
3
+ */
4
+ export interface Config {
5
+ forbidTcp: boolean;
6
+ forbidWs: boolean;
7
+ forbidNonLocalWs: boolean;
8
+ forbidWss: boolean;
9
+ forbidWebRtc: boolean;
10
+ /**
11
+ * Maximum level of the logs that are generated.
12
+ */
13
+ maxLogLevel: number;
14
+ /**
15
+ * Number between 0.0 and 1.0 indicating how much of the CPU time the instance is allowed to
16
+ * consume.
17
+ */
18
+ cpuRateLimit: number;
19
+ /**
20
+ * Environment variables that the instance can pull.
21
+ */
22
+ envVars: string[];
23
+ /**
24
+ * Returns the number of milliseconds since an arbitrary epoch.
25
+ */
26
+ performanceNow: () => number;
27
+ /**
28
+ * Fills the given buffer with randomly-generated bytes.
29
+ */
30
+ getRandomValues: (buffer: Uint8Array) => void;
31
+ }
32
+ export type Event = {
33
+ ty: "add-chain-result";
34
+ success: true;
35
+ chainId: number;
36
+ } | {
37
+ ty: "add-chain-result";
38
+ success: false;
39
+ error: string;
40
+ } | {
41
+ ty: "log";
42
+ level: number;
43
+ target: string;
44
+ message: string;
45
+ } | {
46
+ ty: "json-rpc-responses-non-empty";
47
+ chainId: number;
48
+ } | {
49
+ ty: "current-task";
50
+ taskName: string | null;
51
+ } | {
52
+ ty: "wasm-panic";
53
+ message: string;
54
+ } | {
55
+ ty: "new-connection";
56
+ connectionId: number;
57
+ address: ParsedMultiaddr;
58
+ } | {
59
+ ty: "connection-reset";
60
+ connectionId: number;
61
+ } | {
62
+ ty: "connection-stream-open";
63
+ connectionId: number;
64
+ } | {
65
+ ty: "connection-stream-reset";
66
+ connectionId: number;
67
+ streamId: number;
68
+ } | {
69
+ ty: "stream-send";
70
+ connectionId: number;
71
+ streamId?: number;
72
+ data: Uint8Array;
73
+ } | {
74
+ ty: "stream-send-close";
75
+ connectionId: number;
76
+ streamId?: number;
77
+ };
78
+ export type ParsedMultiaddr = {
79
+ ty: "tcp";
80
+ hostname: string;
81
+ port: number;
82
+ } | {
83
+ ty: "websocket";
84
+ url: string;
85
+ } | {
86
+ ty: "webrtc";
87
+ targetPort: string;
88
+ ipVersion: string;
89
+ targetIp: string;
90
+ remoteCertMultibase: string;
91
+ };
92
+ export interface Instance {
93
+ request: (request: string, chainId: number) => number;
94
+ peekJsonRpcResponse: (chainId: number) => string | null;
95
+ addChain: (chainSpec: string, databaseContent: string, potentialRelayChains: number[], disableJsonRpc: boolean) => void;
96
+ removeChain: (chainId: number) => void;
97
+ /**
98
+ * Starts the instance shutdown process in the background. After this function returns, no
99
+ * more event is generated and all further function calls might throw or have no effect.
100
+ * Existing connections are *not* closed. It is the responsibility of the API user to close
101
+ * all connections.
102
+ */
103
+ startShutdown: () => void;
104
+ connectionOpened: (connectionId: number, info: {
105
+ type: 'single-stream';
106
+ handshake: 'multistream-select-noise-yamux';
107
+ initialWritableBytes: number;
108
+ writeClosable: boolean;
109
+ } | {
110
+ type: 'multi-stream';
111
+ handshake: 'webrtc';
112
+ localTlsCertificateMultihash: Uint8Array;
113
+ remoteTlsCertificateMultihash: Uint8Array;
114
+ }) => void;
115
+ connectionReset: (connectionId: number, message: string) => void;
116
+ streamWritableBytes: (connectionId: number, numExtra: number, streamId?: number) => void;
117
+ streamMessage: (connectionId: number, message: Uint8Array, streamId?: number) => void;
118
+ streamOpened: (connectionId: number, streamId: number, direction: 'inbound' | 'outbound', initialWritableBytes: number) => void;
119
+ streamReset: (connectionId: number, streamId: number) => void;
120
+ }
121
+ /**
122
+ * Starts a new instance using the given configuration.
123
+ *
124
+ * Even though this function doesn't do anything asynchronous, it needs to be asynchronous due to
125
+ * the fact that `WebAssembly.instantiate` is for some reason asynchronous.
126
+ *
127
+ * After this function returns, the execution of CPU-heavy tasks of smoldot will happen
128
+ * asynchronously in the background.
129
+ *
130
+ * This instance is low-level in the sense that invalid input can lead to crashes and that input
131
+ * isn't sanitized. In other words, you know what you're doing.
132
+ */
133
+ export declare function startLocalInstance(config: Config, wasmModule: WebAssembly.Module, eventCallback: (event: Event) => void): Promise<Instance>;
134
+ export declare function parseMultiaddr(address: string, forbidTcp: boolean, forbidWs: boolean, forbidNonLocalWs: boolean, forbidWss: boolean, forbidWebRtc: boolean): {
135
+ success: true;
136
+ address: ParsedMultiaddr;
137
+ } | {
138
+ success: false;
139
+ error: string;
140
+ };