UNPKG

@gear-js/react-hooks

Version:
1,029 lines (1,028 loc) 37.5 kB
class I extends Error { constructor(a) { super(a), this.name = "AddChainError"; } } class g extends Error { constructor() { super(), this.name = "AlreadyDestroyedError"; } } class E extends Error { constructor() { super(), this.name = "JsonRpcDisabledError"; } } class A extends Error { constructor(a) { super(a); } } class M extends Error { constructor() { super("JSON-RPC requests queue is full"); } } function y(r, a, d) { return R(r, a, d), new TextDecoder().decode(r.slice(a, a + d)); } function v(r, a) { return R(r, a, 1), r[a]; } function x(r, a) { return R(r, a, 2), r[a] << 8 | r[a + 1]; } function S(r, a) { return R(r, a, 4), (r[a] | r[a + 1] << 8 | r[a + 2] << 16) + r[a + 3] * 16777216; } function O(r, a, d) { R(r, a, 1), r[a] = d & 255; } function j(r, a, d) { R(r, a, 4), r[a + 3] = d >>> 24 & 255, r[a + 2] = d >>> 16 & 255, r[a + 1] = d >>> 8 & 255, r[a] = d & 255; } function R(r, a, d) { if (!Number.isInteger(a) || a < 0) throw new RangeError(); if (a + d > r.length) throw new RangeError(); } var k = function(r, a, d, o) { function h(n) { return n instanceof d ? n : new d(function(u) { u(n); }); } return new (d || (d = Promise))(function(n, u) { function t(c) { try { s(o.next(c)); } catch (i) { u(i); } } function e(c) { try { s(o.throw(c)); } catch (i) { u(i); } } function s(c) { c.done ? n(c.value) : h(c.value).then(t, e); } s((o = o.apply(r, a || [])).next()); }); }; function P(r, a, d) { return k(this, void 0, void 0, function* () { const o = { instance: null, currentTask: null, bufferIndices: new Array(), advanceExecutionPromise: null, onShutdownExecutorOrWasmPanic: () => { } }, h = { // Must exit with an error. A human-readable message can be found in the WebAssembly // memory in the given buffer. panic: (t, e) => { const s = o.instance; o.instance = null, t >>>= 0, e >>>= 0; const c = y(new Uint8Array(s.exports.memory.buffer), t, e); throw d({ ty: "wasm-panic", message: c, currentTask: o.currentTask }), o.onShutdownExecutorOrWasmPanic(), o.onShutdownExecutorOrWasmPanic = () => { }, new Error(); }, chain_initialized: (t, e, s) => { const c = o.instance, i = new Uint8Array(c.exports.memory.buffer); if (e >>>= 0, s >>>= 0, e === 0) d({ ty: "add-chain-result", chainId: t, success: !0 }); else { const l = y(i, e, s); d({ ty: "add-chain-result", chainId: t, success: !1, error: l }); } }, random_get: (t, e) => { const s = o.instance; t >>>= 0, e >>>= 0; const c = new Uint8Array(s.exports.memory.buffer).subarray(t, t + e); for (let i = 0; i < e; i += 65536) r.getRandomValues(c.subarray(i, i + 65536)); }, unix_timestamp_us: () => { const t = Math.floor(Date.now()); if (t < 0) throw new Error("UNIX timestamp inferior to 0"); return BigInt(t) * BigInt(1e3); }, monotonic_clock_us: () => { const t = r.performanceNow(), e = Math.floor(t); return BigInt(e) * BigInt(1e3) + BigInt(Math.floor((t - e) * 1e3)); }, buffer_size: (t) => o.bufferIndices[t].byteLength, buffer_copy: (t, e) => { const s = o.instance; e = e >>> 0; const c = o.bufferIndices[t]; new Uint8Array(s.exports.memory.buffer).set(c, e); }, advance_execution_ready: () => { o.advanceExecutionPromise && o.advanceExecutionPromise(), o.advanceExecutionPromise = null; }, // Used by the Rust side to notify that a JSON-RPC response or subscription notification // is available in the queue of JSON-RPC responses. json_rpc_responses_non_empty: (t) => { d({ ty: "json-rpc-responses-non-empty", chainId: t }); }, // Used by the Rust side to emit a log entry. // See also the `max_log_level` parameter in the configuration. log: (t, e, s, c, i) => { const l = o.instance; e >>>= 0, s >>>= 0, c >>>= 0, i >>>= 0; const f = new Uint8Array(l.exports.memory.buffer); let p = y(f, e, s), m = y(f, c, i); d({ ty: "log", level: t, message: m, target: p }); }, // Must call `timer_finished` after the given number of milliseconds has elapsed. start_timer: (t) => { const e = o.instance; t > 2147483647 && (t = 2147483647), t < 1 && typeof setImmediate == "function" ? setImmediate(() => { if (o.instance) try { e.exports.timer_finished(); } catch { } }) : setTimeout(() => { if (o.instance) try { e.exports.timer_finished(); } catch { } }, t); }, // Must indicate whether the given connection type is supported. connection_type_supported: (t) => { switch (t) { case 0: case 1: case 2: return r.forbidTcp ? 0 : 1; case 4: case 5: case 6: return r.forbidWs || r.forbidNonLocalWs ? 0 : 1; case 7: return r.forbidWs ? 0 : 1; case 14: return r.forbidWss ? 0 : 1; case 16: case 17: return r.forbidWebRtc ? 0 : 1; default: throw new Error("Invalid connection type passed to `connection_type_supported`"); } }, // Must create a new connection object. This implementation stores the created object in // `connections`. connection_new: (t, e, s) => { const c = o.instance, i = new Uint8Array(c.exports.memory.buffer); e >>>= 0, s >>>= 0; let l; switch (v(i, e)) { case 0: case 1: case 2: { const f = x(i, e + 1), p = y(i, e + 3, s - 3); l = { ty: "tcp", port: f, hostname: p }; break; } case 4: case 6: { const f = x(i, e + 1); l = { ty: "websocket", url: "ws://" + y(i, e + 3, s - 3) + ":" + f }; break; } case 5: { const f = x(i, e + 1); l = { ty: "websocket", url: "ws://[" + y(i, e + 3, s - 3) + "]:" + f }; break; } case 14: { const f = x(i, e + 1); l = { ty: "websocket", url: "wss://" + y(i, e + 3, s - 3) + ":" + f }; break; } case 16: { const f = x(i, e + 1), p = i.slice(e + 3, e + 35), m = y(i, e + 35, s - 35); l = { ty: "webrtc", ipVersion: "4", remoteTlsCertificateSha256: p, targetIp: m, targetPort: f }; break; } case 17: { const f = x(i, e + 1), p = i.slice(e + 3, e + 35), m = y(i, e + 35, s - 35); l = { ty: "webrtc", ipVersion: "6", remoteTlsCertificateSha256: p, targetIp: m, targetPort: f }; break; } default: throw new Error("Invalid encoded address passed to `connection_new`"); } d({ ty: "new-connection", connectionId: t, address: l }); }, // Must close and destroy the connection object. reset_connection: (t) => { d({ ty: "connection-reset", connectionId: t }); }, // Opens a new substream on a multi-stream connection. connection_stream_open: (t) => { d({ ty: "connection-stream-open", connectionId: t }); }, // Closes a substream on a multi-stream connection. connection_stream_reset: (t, e) => { d({ ty: "connection-stream-reset", connectionId: t, streamId: e }); }, // Must queue the data found in the WebAssembly memory at the given pointer. It is assumed // that this function is called only when the connection is in an open state. stream_send: (t, e, s, c) => { const i = o.instance, l = new Uint8Array(i.exports.memory.buffer); s >>>= 0, c >>>= 0; const f = new Array(); for (let p = 0; p < c; ++p) { const m = S(l, s + 8 * p), w = S(l, s + 8 * p + 4); f.push(l.slice(m, m + w)); } d({ ty: "stream-send", connectionId: t, streamId: e, data: f }); }, stream_send_close: (t, e) => { d({ ty: "stream-send-close", connectionId: t, streamId: e }); }, current_task_entered: (t, e) => { t >>>= 0, e >>>= 0; const s = y(new Uint8Array(o.instance.exports.memory.buffer), t, e); o.currentTask = s; }, current_task_exit: () => { o.currentTask = null; } }, n = yield WebAssembly.instantiate(a, { // The functions with the "smoldot" prefix are specific to smoldot. smoldot: h }); o.instance = n, o.instance.exports.init(r.maxLogLevel); const u = new Promise((t) => o.onShutdownExecutorOrWasmPanic = () => t("stop")); return k(this, void 0, void 0, function* () { const t = r.cpuRateLimit; let e = 0, s = r.performanceNow(); for (; ; ) { const c = new Promise((m) => o.advanceExecutionPromise = () => m("ready")); if (!o.instance) break; o.instance.exports.advance_execution(); const i = r.performanceNow(), l = i - s; s = i; const f = l * (1 / t - 1); if (e += f, e > 5) { e > 2147483646 && (e = 2147483646); const m = new Promise((w) => setTimeout(() => w("timeout"), e)); if ((yield Promise.race([m, u])) === "stop") break; } if ((yield Promise.race([c, u])) === "stop") break; const p = r.performanceNow(); e -= p - s, e < -1e4 && (e = -1e4), s = p; } o.instance && d({ ty: "executor-shutdown" }); }), { request: (t, e) => o.instance ? (o.bufferIndices[0] = new TextEncoder().encode(t), o.instance.exports.json_rpc_send(0, e) >>> 0) : 1, peekJsonRpcResponse: (t) => { if (!o.instance) return null; const e = o.instance.exports.json_rpc_responses_peek(t) >>> 0, s = new Uint8Array(o.instance.exports.memory.buffer), c = S(s, e) >>> 0, i = S(s, e + 4) >>> 0; if (i !== 0) { const l = y(s, c, i); return o.instance.exports.json_rpc_responses_pop(t), l; } else return null; }, addChain: (t, e, s, c, i, l) => { if (!o.instance) { d({ ty: "add-chain-id-allocated", chainId: 0 }), d({ ty: "add-chain-result", chainId: 0, success: !1, error: "Smoldot has crashed" }); return; } console.assert(c || i != 0, "invalid jsonRpcMaxPendingRequests value passed to local-instance::addChain"), o.bufferIndices[0] = new TextEncoder().encode(t), o.bufferIndices[1] = new TextEncoder().encode(e); const f = new Uint8Array(s.length * 4); for (let m = 0; m < s.length; ++m) j(f, m * 4, s[m]); o.bufferIndices[2] = f; const p = o.instance.exports.add_chain(0, 1, c ? 0 : i, l, 2); delete o.bufferIndices[0], delete o.bufferIndices[1], delete o.bufferIndices[2], d({ ty: "add-chain-id-allocated", chainId: p }); }, removeChain: (t) => { o.instance && o.instance.exports.remove_chain(t); }, shutdownExecutor: () => { if (!o.instance) return; const t = o.onShutdownExecutorOrWasmPanic; o.onShutdownExecutorOrWasmPanic = () => { }, t(); }, connectionMultiStreamSetHandshakeInfo: (t, e) => { if (!o.instance) return; const s = new Uint8Array(1 + e.localTlsCertificateSha256.length); O(s, 0, 0), s.set(e.localTlsCertificateSha256, 1), o.bufferIndices[0] = s, o.instance.exports.connection_multi_stream_set_handshake_info(t, 0), delete o.bufferIndices[0]; }, connectionReset: (t, e) => { o.instance && (o.bufferIndices[0] = new TextEncoder().encode(e), o.instance.exports.connection_reset(t, 0), delete o.bufferIndices[0]); }, streamWritableBytes: (t, e, s) => { o.instance && o.instance.exports.stream_writable_bytes(t, s || 0, e); }, streamMessage: (t, e, s) => { o.instance && (o.bufferIndices[0] = e, o.instance.exports.stream_message(t, s || 0, 0), delete o.bufferIndices[0]); }, streamOpened: (t, e, s) => { o.instance && o.instance.exports.connection_stream_opened(t, e, s === "outbound" ? 1 : 0); }, streamReset: (t, e, s) => { o.instance && (o.bufferIndices[0] = new TextEncoder().encode(s), o.instance.exports.stream_reset(t, e, 0), delete o.bufferIndices[0]); } }; }); } var W = function(r, a, d, o) { function h(n) { return n instanceof d ? n : new d(function(u) { u(n); }); } return new (d || (d = Promise))(function(n, u) { function t(c) { try { s(o.next(c)); } catch (i) { u(i); } } function e(c) { try { s(o.throw(c)); } catch (i) { u(i); } } function s(c) { c.done ? n(c.value) : h(c.value).then(t, e); } s((o = o.apply(r, a || [])).next()); }); }; function U(r) { return W(this, void 0, void 0, function* () { const { port1: a, port2: d } = new MessageChannel(), o = r.portToServer, h = { wasmModule: yield r.wasmModule, serverToClient: d, maxLogLevel: r.maxLogLevel, cpuRateLimit: r.cpuRateLimit, forbidWs: r.forbidWs, forbidWss: r.forbidWss, forbidNonLocalWs: r.forbidNonLocalWs, forbidTcp: r.forbidTcp, forbidWebRtc: r.forbidWebRtc }; o.postMessage(h, [d]); const n = { jsonRpcResponses: /* @__PURE__ */ new Map(), connections: /* @__PURE__ */ new Map() }; return a.onmessage = (u) => { const t = u.data; switch (t.ty) { case "wasm-panic": case "executor-shutdown": { a.close(), o.close(); break; } case "add-chain-result": { if (t.success) { n.jsonRpcResponses.set(t.chainId, new Array()); const e = { ty: "accept-more-json-rpc-answers", chainId: t.chainId }; for (let s = 0; s < 10; ++s) a.postMessage(e); } break; } case "new-connection": { n.connections.set(t.connectionId, /* @__PURE__ */ new Set()); break; } case "connection-reset": { if (!n.connections.has(t.connectionId)) return; n.connections.delete(t.connectionId); break; } case "connection-stream-open": { if (!n.connections.has(t.connectionId)) return; break; } case "connection-stream-reset": { if (!n.connections.has(t.connectionId) || !n.connections.get(t.connectionId).has(t.streamId)) return; break; } case "stream-send": { if (!n.connections.has(t.connectionId) || t.streamId && !n.connections.get(t.connectionId).has(t.streamId)) return; break; } case "stream-send-close": { if (!n.connections.has(t.connectionId) || t.streamId && !n.connections.get(t.connectionId).has(t.streamId)) return; break; } case "json-rpc-response": { const e = n.jsonRpcResponses.get(t.chainId); e && (e.push(t.response), r.eventCallback({ ty: "json-rpc-responses-non-empty", chainId: t.chainId })); return; } } r.eventCallback(t); }, { addChain(u, t, e, s, c, i) { return W(this, void 0, void 0, function* () { const l = { ty: "add-chain", chainSpec: u, databaseContent: t, potentialRelayChains: e, disableJsonRpc: s, jsonRpcMaxPendingRequests: c, jsonRpcMaxSubscriptions: i }; a.postMessage(l); }); }, removeChain(u) { n.jsonRpcResponses.delete(u); const t = { ty: "remove-chain", chainId: u }; a.postMessage(t); }, request(u, t) { const e = { ty: "request", chainId: t, request: u }; return a.postMessage(e), 0; }, peekJsonRpcResponse(u) { const t = n.jsonRpcResponses.get(u).shift(); if (!t) return null; const e = { ty: "accept-more-json-rpc-answers", chainId: u }; return a.postMessage(e), t; }, shutdownExecutor() { const u = { ty: "shutdown" }; a.postMessage(u); }, connectionReset(u, t) { n.connections.delete(u); const e = { ty: "connection-reset", connectionId: u, message: t }; a.postMessage(e); }, connectionMultiStreamSetHandshakeInfo(u, t) { const e = { ty: "connection-multistream-set-info", connectionId: u, info: t }; a.postMessage(e); }, streamMessage(u, t, e) { const s = { ty: "stream-message", connectionId: u, message: t, streamId: e }; a.postMessage(s); }, streamOpened(u, t, e) { n.connections.get(u).add(t); const s = { ty: "stream-opened", connectionId: u, streamId: t, direction: e }; a.postMessage(s); }, streamWritableBytes(u, t, e) { const s = { ty: "stream-writable-bytes", connectionId: u, numExtra: t, streamId: e }; a.postMessage(s); }, streamReset(u, t, e) { n.connections.get(u).delete(t); const s = { ty: "stream-reset", connectionId: u, streamId: t, message: e }; a.postMessage(s); } }; }); } var _ = function(r, a, d, o) { function h(n) { return n instanceof d ? n : new d(function(u) { u(n); }); } return new (d || (d = Promise))(function(n, u) { function t(c) { try { s(o.next(c)); } catch (i) { u(i); } } function e(c) { try { s(o.throw(c)); } catch (i) { u(i); } } function s(c) { c.done ? n(c.value) : h(c.value).then(t, e); } s((o = o.apply(r, a || [])).next()); }); }; function B(r, a, d) { const o = r.logCallback || ((e, s, c) => { e <= 1 ? console.error("[%s] %s", s, c) : e == 2 ? console.warn("[%s] %s", s, c) : e == 3 ? console.info("[%s] %s", s, c) : e == 4 ? console.debug("[%s] %s", s, c) : console.trace("[%s] %s", s, c); }); a instanceof Promise || (a = Promise.resolve(a)); let h = r.cpuRateLimit || 1; isNaN(h) && (h = 1), h > 1 && (h = 1), h < 0 && (h = 0); const n = { instance: { status: "not-created" }, chainIds: /* @__PURE__ */ new WeakMap(), connections: /* @__PURE__ */ new Map(), addChainIdAllocations: [], addChainResults: /* @__PURE__ */ new Map(), onExecutorShutdownOrWasmPanic: () => { }, chains: /* @__PURE__ */ new Map() }, u = (e) => { switch (e.ty) { case "wasm-panic": { console.error("Smoldot has panicked" + (e.currentTask ? " while executing task `" + e.currentTask + "`" : "") + `. This is a bug in smoldot. Please open an issue at https://github.com/smol-dot/smoldot/issues with the following message: ` + e.message), n.instance = { status: "destroyed", error: new A(e.message) }, n.connections.forEach((c) => c.reset()), n.connections.clear(); for (const c of n.addChainIdAllocations) c({ success: !1, error: "Smoldot has crashed" }); n.addChainIdAllocations = [], n.addChainResults.forEach((c) => { c({ success: !1, error: "Smoldot has crashed" }); }), n.addChainResults.clear(); for (const c of Array.from(n.chains.values())) { for (const i of c.jsonRpcResponsesPromises) i(); c.jsonRpcResponsesPromises = []; } n.chains.clear(); const s = n.onExecutorShutdownOrWasmPanic; n.onExecutorShutdownOrWasmPanic = () => { }, s(); break; } case "executor-shutdown": { const s = n.onExecutorShutdownOrWasmPanic; n.onExecutorShutdownOrWasmPanic = () => { }, s(); break; } case "log": { o(e.level, e.target, e.message); break; } case "add-chain-id-allocated": { const s = n.addChainIdAllocations.shift(); n.addChainResults.set(e.chainId, s); break; } case "add-chain-result": { n.addChainResults.get(e.chainId)(e), n.addChainResults.delete(e.chainId); break; } case "json-rpc-responses-non-empty": { const s = n.chains.get(e.chainId).jsonRpcResponsesPromises; for (; s.length !== 0; ) s.shift()(); break; } case "new-connection": { const s = e.connectionId; n.connections.set(s, d.connect({ address: e.address, onConnectionReset(c) { if (n.instance.status !== "ready") throw new Error(); n.connections.delete(s), n.instance.instance.connectionReset(s, c); }, onMessage(c, i) { if (n.instance.status !== "ready") throw new Error(); n.instance.instance.streamMessage(s, c, i); }, onStreamOpened(c, i) { if (n.instance.status !== "ready") throw new Error(); n.instance.instance.streamOpened(s, c, i); }, onMultistreamHandshakeInfo(c) { if (n.instance.status !== "ready") throw new Error(); n.instance.instance.connectionMultiStreamSetHandshakeInfo(s, c); }, onWritableBytes(c, i) { if (n.instance.status !== "ready") throw new Error(); n.instance.instance.streamWritableBytes(s, c, i); }, onStreamReset(c, i) { if (n.instance.status !== "ready") throw new Error(); n.instance.instance.streamReset(s, c, i); } })); break; } case "connection-reset": { n.connections.get(e.connectionId).reset(), n.connections.delete(e.connectionId); break; } case "connection-stream-open": { n.connections.get(e.connectionId).openOutSubstream(); break; } case "connection-stream-reset": { n.connections.get(e.connectionId).reset(e.streamId); break; } case "stream-send": { n.connections.get(e.connectionId).send(e.data, e.streamId); break; } case "stream-send-close": { n.connections.get(e.connectionId).closeSend(e.streamId); break; } } }, t = r.portToWorker; return t ? n.instance = { status: "not-ready", whenReady: U({ wasmModule: a.then((e) => e.wasm), forbidTcp: r.forbidTcp || !1, forbidWs: r.forbidWs || !1, forbidNonLocalWs: r.forbidNonLocalWs || !1, forbidWss: r.forbidWss || !1, forbidWebRtc: r.forbidWebRtc || !1, maxLogLevel: r.maxLogLevel || 3, cpuRateLimit: h, portToServer: t, eventCallback: u }).then((e) => { n.instance.status !== "destroyed" && (n.instance = { status: "ready", instance: e }); }) } : n.instance = { status: "not-ready", whenReady: a.then((e) => P({ forbidTcp: r.forbidTcp || !1, forbidWs: r.forbidWs || !1, forbidNonLocalWs: r.forbidNonLocalWs || !1, forbidWss: r.forbidWss || !1, forbidWebRtc: r.forbidWebRtc || !1, maxLogLevel: r.maxLogLevel || 3, cpuRateLimit: h, envVars: [], performanceNow: d.performanceNow, getRandomValues: d.getRandomValues }, e.wasm, u)).then((e) => { n.instance.status !== "destroyed" && (n.instance = { status: "ready", instance: e }); }) }, { addChain: (e) => _(this, void 0, void 0, function* () { if (n.instance.status === "not-ready" && (yield n.instance.whenReady), n.instance.status === "destroyed") throw n.instance.error; if (n.instance.status === "not-created" || n.instance.status === "not-ready") throw new Error(); if (typeof e.chainSpec != "string") throw new Error("Chain specification must be a string"); let s = []; if (e.potentialRelayChains) for (const w of e.potentialRelayChains) { const b = n.chainIds.get(w); b !== void 0 && s.push(b); } let c = e.jsonRpcMaxPendingRequests === void 0 ? 1 / 0 : e.jsonRpcMaxPendingRequests; if (c = Math.floor(c), c <= 0 || isNaN(c)) throw new I("Invalid value for `jsonRpcMaxPendingRequests`"); c > 4294967295 && (c = 4294967295); let i = e.jsonRpcMaxSubscriptions === void 0 ? 1 / 0 : e.jsonRpcMaxSubscriptions; if (i = Math.floor(i), i < 0 || isNaN(i)) throw new I("Invalid value for `jsonRpcMaxSubscriptions`"); if (i > 4294967295 && (i = 4294967295), e.databaseContent !== void 0 && typeof e.databaseContent != "string") throw new I("`databaseContent` is not a string"); const l = new Promise((w) => n.addChainIdAllocations.push(w)); n.instance.instance.addChain(e.chainSpec, e.databaseContent || "", s, !!e.disableJsonRpc, c, i); const f = yield l; if (!f.success) throw new I(f.error); const p = f.chainId; n.chains.set(p, { jsonRpcResponsesPromises: new Array() }); const m = { sendJsonRpc: (w) => { if (n.instance.status === "destroyed") throw n.instance.error; if (n.instance.status !== "ready") throw new Error(); if (!n.chains.has(p)) throw new g(); if (e.disableJsonRpc) throw new E(); const b = n.instance.instance.request(w, p); switch (b) { case 0: break; case 1: throw new M(); default: throw new Error("Internal error: unknown json_rpc_send error code: " + b); } }, jsonRpcResponses: { next: () => _(this, void 0, void 0, function* () { for (; ; ) { if (!n.chains.has(p)) return { done: !0, value: void 0 }; if (e.disableJsonRpc) throw new E(); if (n.instance.status === "destroyed") throw n.instance.error; if (n.instance.status !== "ready") throw new Error(); const w = n.instance.instance.peekJsonRpcResponse(p); if (w) return { done: !1, value: w }; yield new Promise((b) => { n.chains.get(p).jsonRpcResponsesPromises.push(b); }); } }), [Symbol.asyncIterator]() { return this; } }, nextJsonRpcResponse: () => _(this, void 0, void 0, function* () { const w = yield m.jsonRpcResponses.next(); if (w.done) throw new g(); return w.value; }), remove: () => { if (n.instance.status === "destroyed") throw n.instance.error; if (n.instance.status !== "ready") throw new Error(); if (!n.chains.has(p)) throw new g(); console.assert(n.chainIds.has(m)), n.chainIds.delete(m); for (const w of n.chains.get(p).jsonRpcResponsesPromises) w(); n.chains.delete(p), n.instance.instance.removeChain(p); } }; return n.chainIds.set(m, p), m; }), terminate: () => _(this, void 0, void 0, function* () { if (n.instance.status === "not-ready" && (yield n.instance.whenReady), n.instance.status === "destroyed") throw n.instance.error; if (n.instance.status !== "ready") throw new Error(); n.instance.instance.shutdownExecutor(), yield new Promise((e) => n.onExecutorShutdownOrWasmPanic = e), n.instance.status === "ready" && (n.instance = { status: "destroyed", error: new g() }), n.connections.forEach((e) => e.reset()), n.connections.clear(); for (const e of n.addChainIdAllocations) e({ success: !1, error: "Client.terminate() has been called" }); n.addChainIdAllocations = [], n.addChainResults.forEach((e) => { e({ success: !1, error: "Client.terminate() has been called" }); }), n.addChainResults.clear(); for (const e of Array.from(n.chains.values())) { for (const s of e.jsonRpcResponsesPromises) s(); e.jsonRpcResponsesPromises = []; } n.chains.clear(); }) }; } var C = function(r, a, d, o) { function h(n) { return n instanceof d ? n : new d(function(u) { u(n); }); } return new (d || (d = Promise))(function(n, u) { function t(c) { try { s(o.next(c)); } catch (i) { u(i); } } function e(c) { try { s(o.throw(c)); } catch (i) { u(i); } } function s(c) { c.done ? n(c.value) : h(c.value).then(t, e); } s((o = o.apply(r, a || [])).next()); }); }; function N(r) { if (r.forbidTcp = !0, typeof isSecureContext == "boolean" && isSecureContext && typeof location !== void 0) { const a = location.toString(); a.indexOf("localhost") !== -1 && a.indexOf("127.0.0.1") !== -1 && a.indexOf("::1") !== -1 && (r.forbidNonLocalWs = !0); } return B(r, r.bytecode, { performanceNow: () => performance.now(), getRandomValues: (a) => { const d = globalThis.crypto; if (!d) throw new Error("randomness not available"); if (a.buffer instanceof ArrayBuffer) d.getRandomValues(a); else { const o = new Uint8Array(a.length); d.getRandomValues(o), a.set(o); } }, connect: (a) => L(a) }); } function L(r) { if (r.address.ty === "websocket") { let a; try { a = new WebSocket(r.address.url); } catch (h) { a = h instanceof Error ? h.toString() : "Exception thrown by new WebSocket"; } const d = { quenedUnreportedBytes: 0, nextTimeout: 10 }, o = () => { if (!(a instanceof WebSocket) || a.readyState != 1) return; const h = a.bufferedAmount; let n = d.quenedUnreportedBytes - h; n < 0 && (n = 0), d.quenedUnreportedBytes -= n, d.quenedUnreportedBytes != 0 && (setTimeout(o, d.nextTimeout), d.nextTimeout *= 2, d.nextTimeout > 500 && (d.nextTimeout = 500)), n != 0 && r.onWritableBytes(n); }; return a instanceof WebSocket ? (a.binaryType = "arraybuffer", a.onopen = () => { r.onWritableBytes(1024 * 1024); }, a.onclose = (h) => { const n = "Error code " + h.code + (h.reason ? ": " + h.reason : ""); r.onConnectionReset(n); }, a.onmessage = (h) => { r.onMessage(new Uint8Array(h.data)); }) : setTimeout(() => { a && !(a instanceof WebSocket) && (r.onConnectionReset(a), a = null); }, 1), { reset: () => { a instanceof WebSocket && (a.onopen = null, a.onclose = null, a.onmessage = null, a.onerror = null, a.readyState == WebSocket.OPEN && a.close()), a = null; }, send: (h) => { d.quenedUnreportedBytes == 0 && (d.nextTimeout = 10, setTimeout(o, 10)); for (const n of h) d.quenedUnreportedBytes += n.length; a.send(new Blob(h)); }, closeSend: () => { throw new Error("Wrong connection type"); }, openOutSubstream: () => { throw new Error("Wrong connection type"); } }; } else if (r.address.ty === "webrtc") { const { targetPort: a, ipVersion: d, targetIp: o, remoteTlsCertificateSha256: h } = r.address, n = { pc: void 0, dataChannels: /* @__PURE__ */ new Map(), nextStreamId: 0, isFirstOutSubstream: !0 }, u = () => { if (!n.pc) { console.assert(n.dataChannels.size === 0, "substreams exist while pc is undef"), n.pc = null; return; } n.pc.onconnectionstatechange = null, n.pc.onnegotiationneeded = null, n.pc.ondatachannel = null; for (const e of Array.from(n.dataChannels.values())) e.channel.onopen = null, e.channel.onerror = null, e.channel.onclose = null, e.channel.onbufferedamountlow = null, e.channel.onmessage = null; n.dataChannels.clear(), n.pc.close(); }, t = (e, s) => { const c = n.nextStreamId; n.nextStreamId += 1, e.binaryType = "arraybuffer"; let i = { value: !1 }; e.onopen = () => { console.assert(!i.value, "substream opened twice"), i.value = !0, r.onStreamOpened(c, s), r.onWritableBytes(65536, c); }, e.onerror = e.onclose = (l) => { const f = l instanceof RTCErrorEvent ? l.error.toString() : "RTCDataChannel closed"; i.value ? (e.onopen = null, e.onerror = null, e.onclose = null, e.onbufferedamountlow = null, e.onmessage = null, n.dataChannels.delete(c), r.onStreamReset(c, f)) : (u(), r.onConnectionReset("data channel failed to open: " + f)); }, e.onbufferedamountlow = () => { const l = n.dataChannels.get(c), f = l.bufferedBytes; l.bufferedBytes = 0, r.onWritableBytes(f, c); }, e.onmessage = (l) => { r.onMessage(new Uint8Array(l.data), c); }, n.dataChannels.set(c, { channel: e, bufferedBytes: 0 }); }; return RTCPeerConnection.generateCertificate({ name: "ECDSA", namedCurve: "P-256", hash: "SHA-256" }).then((e) => C(this, void 0, void 0, function* () { if (n.pc === null) return; if ((o == "localhost" || o == "127.0.0.1" || o == "::1") && navigator.userAgent.indexOf("Firefox") !== -1) { u(), r.onConnectionReset("Firefox can't connect to a localhost WebRTC server"); return; } n.pc = new RTCPeerConnection({ certificates: [e] }); let s; if (e.getFingerprints) { for (const { algorithm: i, value: l } of e.getFingerprints()) if (i === "sha-256") { s = l; break; } } else { const l = (yield n.pc.createOffer()).sdp.match(/a(\s*)=(\s*)fingerprint:(\s*)(sha|SHA)-256(\s*)(([a-fA-F0-9]{2}(:)*){32})/); l && (s = l[6]); } if (s === void 0) { r.onConnectionReset("Failed to obtain the browser certificate fingerprint"); return; } let c = new Uint8Array(32); c.set(s.split(":").map((i) => parseInt(i, 16)), 0), n.pc.onconnectionstatechange = (i) => { (n.pc.connectionState == "closed" || n.pc.connectionState == "disconnected" || n.pc.connectionState == "failed") && (u(), r.onConnectionReset("WebRTC state transitioned to " + n.pc.connectionState)); }, n.pc.onnegotiationneeded = (i) => C(this, void 0, void 0, function* () { var l; let f = (yield n.pc.createOffer()).sdp; f.match(/^m=application(\s+)(\d+)(\s+)UDP\/DTLS\/SCTP(\s+)webrtc-datachannel$/m) === null && console.error("Local offer doesn't contain UDP data channel. WebRTC connections will likely fail. Please report this issue."); const p = (l = f.match(/^a=ice-pwd:(.+)$/m)) === null || l === void 0 ? void 0 : l.at(1); p === void 0 && console.error("Failed to set ufrag to pwd. WebRTC connections will likely fail. Please report this issue."); const m = "libp2p+webrtc+v1/" + p; f = f.replace(/^a=ice-ufrag.*$/m, "a=ice-ufrag:" + m), f = f.replace(/^a=ice-pwd.*$/m, "a=ice-pwd:" + m), yield n.pc.setLocalDescription({ type: "offer", sdp: f }); const w = Array.from(h).map((T) => ("0" + T.toString(16)).slice(-2).toUpperCase()).join(":"), b = ( // Version of the SDP protocol. Always 0. (RFC8866) `v=0 o=- 0 0 IN IP` + d + " " + o + ` s=- t=0 0 a=ice-lite m=application ` + String(a) + ` UDP/DTLS/SCTP webrtc-datachannel c=IN IP` + d + " " + o + ` a=mid:0 a=ice-options:ice2 a=ice-ufrag:` + m + ` a=ice-pwd:` + m + ` a=fingerprint:sha-256 ` + w + ` a=setup:passive a=sctp-port:5000 a=max-message-size:16384 a=candidate:1 1 UDP 1 ` + o + " " + String(a) + ` typ host ` ); yield n.pc.setRemoteDescription({ type: "answer", sdp: b }); }), n.pc.ondatachannel = ({ channel: i }) => { t(i, "inbound"); }, r.onMultistreamHandshakeInfo({ handshake: "webrtc", localTlsCertificateSha256: c }); })), { reset: (e) => { if (e === void 0) u(); else { const s = n.dataChannels.get(e); s.channel.onopen = null, s.channel.onerror = null, s.channel.onclose = null, s.channel.onbufferedamountlow = null, s.channel.onmessage = null, s.channel.close(), n.dataChannels.delete(e); } }, send: (e, s) => { const c = n.dataChannels.get(s); for (const i of e) c.bufferedBytes += i.length; c.channel.send(new Blob(e)); }, closeSend: () => { throw new Error("Wrong connection type"); }, openOutSubstream: () => { const e = n.isFirstOutSubstream ? { negotiated: !0, id: 0 } : {}; n.isFirstOutSubstream = !1, t(n.pc.createDataChannel("", e), "outbound"); } }; } else throw new Error(); } export { I as AddChainError, g as AlreadyDestroyedError, A as CrashError, E as JsonRpcDisabledError, M as QueueFullError, N as startWithBytecode };