@qntx/nostr 0.5.0 → 0.6.0
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.
- package/dist/{client-BtIAtxrL.mjs → client-CadO5fAX.mjs} +2 -2
- package/dist/{client-BtIAtxrL.mjs.map → client-CadO5fAX.mjs.map} +1 -1
- package/dist/client.d.mts +1 -1
- package/dist/client.mjs +1 -1
- package/dist/{index-QxvrpMfF.d.mts → index-CNl2q67H.d.mts} +3 -3
- package/dist/{index-Dmc8FJgO.d.mts → index-lvXeER5t.d.mts} +2 -2
- package/dist/index.d.mts +3 -3
- package/dist/index.mjs +2 -2
- package/dist/instance-CIca-ynn.d.mts +15 -0
- package/dist/instance-DQE8BoWt.mjs +221 -0
- package/dist/instance-DQE8BoWt.mjs.map +1 -0
- package/dist/loaders.d.mts +1 -1
- package/dist/nostr_crypto_wasm_bg.wasm +0 -0
- package/dist/{reactive-DFpqtIf_.d.mts → reactive-7aqeip4A.d.mts} +3 -1
- package/dist/{reactive-DDlThDSZ.mjs → reactive-BfhPp9a3.mjs} +38 -4
- package/dist/reactive-BfhPp9a3.mjs.map +1 -0
- package/dist/store.d.mts +1 -1
- package/dist/store.mjs +1 -1
- package/dist/wasm.browser.d.mts +8 -0
- package/dist/wasm.browser.mjs +19 -0
- package/dist/wasm.browser.mjs.map +1 -0
- package/dist/wasm.d.mts +1 -11
- package/dist/wasm.mjs +6 -207
- package/dist/wasm.mjs.map +1 -1
- package/package.json +10 -3
- package/dist/reactive-DDlThDSZ.mjs.map +0 -1
package/dist/wasm.mjs
CHANGED
|
@@ -1,227 +1,26 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as
|
|
3
|
-
//#region src/wasm/abi.ts
|
|
4
|
-
/** Imports 0.2.122 may request. Instantiation fails if anything else appears. */
|
|
5
|
-
const ALLOWED_WASM_IMPORTS = [{
|
|
6
|
-
module: "wbg",
|
|
7
|
-
name: "__wbindgen_throw"
|
|
8
|
-
}, {
|
|
9
|
-
module: "./nostr_crypto_wasm_bg.js",
|
|
10
|
-
name: "__wbindgen_throw"
|
|
11
|
-
}];
|
|
12
|
-
const utf8 = new TextDecoder();
|
|
13
|
-
function decodeUtf8(memory, ptr, len) {
|
|
14
|
-
return utf8.decode(new Uint8Array(memory.buffer, ptr, len));
|
|
15
|
-
}
|
|
16
|
-
function makeWbgImports(holder) {
|
|
17
|
-
const throwRuntime = (ptr, len) => {
|
|
18
|
-
const mem = holder.exports?.memory;
|
|
19
|
-
const msg = mem ? decodeUtf8(mem, ptr, len) : "wasm panic";
|
|
20
|
-
throw new WebAssembly.RuntimeError(msg);
|
|
21
|
-
};
|
|
22
|
-
const wbg = { __wbindgen_throw: throwRuntime };
|
|
23
|
-
return {
|
|
24
|
-
wbg,
|
|
25
|
-
"./nostr_crypto_wasm_bg.js": wbg
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
/** Fail if the module imports anything outside {@link ALLOWED_WASM_IMPORTS}. */
|
|
29
|
-
function assertAllowedWasmImports(mod) {
|
|
30
|
-
const allowed = new Set(ALLOWED_WASM_IMPORTS.map((item) => `${item.module}\0${item.name}`));
|
|
31
|
-
for (const imp of WebAssembly.Module.imports(mod)) {
|
|
32
|
-
if (imp.kind !== "function") throw new TypeError(`unexpected wasm import kind ${imp.kind}: ${imp.module}.${imp.name}`);
|
|
33
|
-
if (!allowed.has(`${imp.module}\0${imp.name}`)) throw new TypeError(`unexpected wasm import ${imp.module}.${imp.name}`);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
function requireMemory(value) {
|
|
37
|
-
if (!(value instanceof WebAssembly.Memory)) throw new TypeError("wasm missing memory export");
|
|
38
|
-
return value;
|
|
39
|
-
}
|
|
40
|
-
function requireFn(value, name) {
|
|
41
|
-
if (typeof value !== "function") throw new TypeError(`wasm missing ${name} export`);
|
|
42
|
-
return value;
|
|
43
|
-
}
|
|
44
|
-
function asExports(raw) {
|
|
45
|
-
const exports = {
|
|
46
|
-
memory: requireMemory(raw["memory"]),
|
|
47
|
-
verify: requireFn(raw["verify"], "verify"),
|
|
48
|
-
verify_serialized: requireFn(raw["verify_serialized"], "verify_serialized"),
|
|
49
|
-
sign: requireFn(raw["sign"], "sign"),
|
|
50
|
-
public_key: requireFn(raw["public_key"], "public_key"),
|
|
51
|
-
__wbindgen_export: requireFn(raw["__wbindgen_export"], "__wbindgen_export"),
|
|
52
|
-
__wbindgen_export2: requireFn(raw["__wbindgen_export2"], "__wbindgen_export2"),
|
|
53
|
-
__wbindgen_add_to_stack_pointer: requireFn(raw["__wbindgen_add_to_stack_pointer"], "__wbindgen_add_to_stack_pointer")
|
|
54
|
-
};
|
|
55
|
-
const start = raw["__wbindgen_start"];
|
|
56
|
-
if (typeof start === "function") exports.__wbindgen_start = requireFn(start, "__wbindgen_start");
|
|
57
|
-
return exports;
|
|
58
|
-
}
|
|
59
|
-
function passBytes(exports, bytes) {
|
|
60
|
-
const len = bytes.length;
|
|
61
|
-
const ptr = exports.__wbindgen_export(len, 1) >>> 0;
|
|
62
|
-
new Uint8Array(exports.memory.buffer, ptr, len).set(bytes);
|
|
63
|
-
return {
|
|
64
|
-
ptr,
|
|
65
|
-
len
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
function wasmVerify(exports, id, pubkey, sig) {
|
|
69
|
-
const idP = passBytes(exports, id);
|
|
70
|
-
const pkP = passBytes(exports, pubkey);
|
|
71
|
-
const sigP = passBytes(exports, sig);
|
|
72
|
-
return exports.verify(idP.ptr, idP.len, pkP.ptr, pkP.len, sigP.ptr, sigP.len) !== 0;
|
|
73
|
-
}
|
|
74
|
-
function wasmVerifySerialized(exports, serialized, id, pubkey, sig) {
|
|
75
|
-
const serP = passBytes(exports, serialized);
|
|
76
|
-
const idP = passBytes(exports, id);
|
|
77
|
-
const pkP = passBytes(exports, pubkey);
|
|
78
|
-
const sigP = passBytes(exports, sig);
|
|
79
|
-
return exports.verify_serialized(serP.ptr, serP.len, idP.ptr, idP.len, pkP.ptr, pkP.len, sigP.ptr, sigP.len) !== 0;
|
|
80
|
-
}
|
|
81
|
-
function takeBytes(exports, ptr, len) {
|
|
82
|
-
const out = new Uint8Array(len);
|
|
83
|
-
if (len > 0) {
|
|
84
|
-
out.set(new Uint8Array(exports.memory.buffer, ptr, len));
|
|
85
|
-
exports.__wbindgen_export2(ptr, len, 1);
|
|
86
|
-
}
|
|
87
|
-
return out;
|
|
88
|
-
}
|
|
89
|
-
function callReturningBytes(exports, invoke) {
|
|
90
|
-
const retptr = exports.__wbindgen_add_to_stack_pointer(-16);
|
|
91
|
-
try {
|
|
92
|
-
invoke(retptr);
|
|
93
|
-
const view = new DataView(exports.memory.buffer);
|
|
94
|
-
return takeBytes(exports, view.getUint32(retptr, true), view.getUint32(retptr + 4, true));
|
|
95
|
-
} finally {
|
|
96
|
-
exports.__wbindgen_add_to_stack_pointer(16);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
function wasmSign(exports, id, seckey, aux) {
|
|
100
|
-
const idP = passBytes(exports, id);
|
|
101
|
-
const skP = passBytes(exports, seckey);
|
|
102
|
-
const auxP = passBytes(exports, aux);
|
|
103
|
-
return callReturningBytes(exports, (retptr) => {
|
|
104
|
-
exports.sign(retptr, idP.ptr, idP.len, skP.ptr, skP.len, auxP.ptr, auxP.len);
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
function wasmPublicKey(exports, seckey) {
|
|
108
|
-
const skP = passBytes(exports, seckey);
|
|
109
|
-
return callReturningBytes(exports, (retptr) => {
|
|
110
|
-
exports.public_key(retptr, skP.ptr, skP.len);
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
async function instantiateCryptoWasm(bytes) {
|
|
114
|
-
const holder = {};
|
|
115
|
-
const { module, instance } = await WebAssembly.instantiate(bytes, makeWbgImports(holder));
|
|
116
|
-
assertAllowedWasmImports(module);
|
|
117
|
-
holder.exports = asExports(instance.exports);
|
|
118
|
-
holder.exports.__wbindgen_start?.();
|
|
119
|
-
return holder.exports;
|
|
120
|
-
}
|
|
121
|
-
//#endregion
|
|
122
|
-
//#region src/wasm/adapter.ts
|
|
123
|
-
/**
|
|
124
|
-
* Build the WASM event verifier on {@link createEventVerifier}. A `WebAssembly.RuntimeError` from
|
|
125
|
-
* the module means the instance aborted — it poisons every later call with the same
|
|
126
|
-
* `WasmVerifyPoisonedError`; any other backend error verifies `false` (the event is marked
|
|
127
|
-
* failed).
|
|
128
|
-
*/
|
|
129
|
-
function createWasmEventVerifier(verifySerialized, poison) {
|
|
130
|
-
const backend = (serializedUtf8, id, pubkey, sig) => {
|
|
131
|
-
if (poison.error !== void 0) throw poison.error;
|
|
132
|
-
try {
|
|
133
|
-
return verifySerialized(serializedUtf8, id, pubkey, sig);
|
|
134
|
-
} catch (error) {
|
|
135
|
-
if (error instanceof WebAssembly.RuntimeError) {
|
|
136
|
-
poison.error = new WasmVerifyPoisonedError("wasm verify aborted the instance", { cause: error });
|
|
137
|
-
throw poison.error;
|
|
138
|
-
}
|
|
139
|
-
return false;
|
|
140
|
-
}
|
|
141
|
-
};
|
|
142
|
-
return createEventVerifier(backend);
|
|
143
|
-
}
|
|
144
|
-
//#endregion
|
|
1
|
+
import { v as WasmVerifyPoisonedError } from "./util-LfQirgDk.mjs";
|
|
2
|
+
import { n as fetchWasmUrl, r as isWasmBytes, t as createNostrWasmLoader } from "./instance-DQE8BoWt.mjs";
|
|
145
3
|
//#region src/wasm/load.ts
|
|
146
|
-
let interned;
|
|
147
|
-
function isNode() {
|
|
148
|
-
if (!("process" in globalThis)) return false;
|
|
149
|
-
const proc = globalThis.process;
|
|
150
|
-
return typeof proc === "object" && proc !== null && "versions" in proc && typeof proc.versions === "object" && proc.versions !== null && "node" in proc.versions && typeof proc.versions.node === "string";
|
|
151
|
-
}
|
|
152
|
-
function isWasmBytes(value) {
|
|
153
|
-
return value instanceof ArrayBuffer || ArrayBuffer.isView(value);
|
|
154
|
-
}
|
|
155
4
|
async function defaultWasmHref() {
|
|
156
5
|
return (await import("./nostr_crypto_wasm_bg-Czrdty7Q.mjs")).default;
|
|
157
6
|
}
|
|
158
7
|
async function readWasmUrl(url) {
|
|
159
|
-
if (
|
|
8
|
+
if (url.protocol === "file:") {
|
|
160
9
|
const { readFile } = await import("node:fs/promises");
|
|
161
10
|
const { fileURLToPath } = await import("node:url");
|
|
162
11
|
return new Uint8Array(await readFile(fileURLToPath(url)));
|
|
163
12
|
}
|
|
164
|
-
|
|
165
|
-
if (!res.ok) throw new CryptoError(`failed to fetch wasm: ${res.status} ${url.href}`);
|
|
166
|
-
return new Uint8Array(await res.arrayBuffer());
|
|
13
|
+
return fetchWasmUrl(url);
|
|
167
14
|
}
|
|
168
15
|
async function wasmBytes(opts) {
|
|
169
16
|
const source = opts?.module;
|
|
170
17
|
if (source !== void 0 && isWasmBytes(source)) return source;
|
|
171
18
|
return readWasmUrl(source instanceof URL ? source : new URL(await defaultWasmHref(), import.meta.url));
|
|
172
19
|
}
|
|
173
|
-
|
|
174
|
-
if (bytes.length !== expected) throw new CryptoError(`invalid ${label} length: expected ${expected}, got ${bytes.length}`);
|
|
175
|
-
}
|
|
176
|
-
function wrapPoison(poison, fn) {
|
|
177
|
-
if (poison.error) throw poison.error;
|
|
178
|
-
try {
|
|
179
|
-
return fn();
|
|
180
|
-
} catch (error) {
|
|
181
|
-
if (error instanceof WebAssembly.RuntimeError) {
|
|
182
|
-
poison.error = new WasmVerifyPoisonedError("wasm verify aborted the instance", { cause: error });
|
|
183
|
-
throw poison.error;
|
|
184
|
-
}
|
|
185
|
-
throw error;
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
function bindExports(exports) {
|
|
189
|
-
const poison = {};
|
|
190
|
-
const rawSerialized = (serializedUtf8, id, pubkey, sig) => wasmVerifySerialized(exports, serializedUtf8, id, pubkey, sig);
|
|
191
|
-
return {
|
|
192
|
-
verify: (id, pubkey, sig) => wrapPoison(poison, () => wasmVerify(exports, id, pubkey, sig)),
|
|
193
|
-
verifySerialized: (serializedUtf8, id, pubkey, sig) => wrapPoison(poison, () => rawSerialized(serializedUtf8, id, pubkey, sig)),
|
|
194
|
-
verifyEvent: createWasmEventVerifier(rawSerialized, poison),
|
|
195
|
-
sign: (id, seckey, aux) => wrapPoison(poison, () => {
|
|
196
|
-
requireByteLength(id, 32, "id");
|
|
197
|
-
requireByteLength(seckey, 32, "secret key");
|
|
198
|
-
requireByteLength(aux, 32, "aux");
|
|
199
|
-
const sig = wasmSign(exports, id, seckey, aux);
|
|
200
|
-
if (sig.length !== 64) throw new CryptoError("wasm sign failed");
|
|
201
|
-
return sig;
|
|
202
|
-
}),
|
|
203
|
-
publicKey: (seckey) => wrapPoison(poison, () => {
|
|
204
|
-
requireByteLength(seckey, 32, "secret key");
|
|
205
|
-
const pk = wasmPublicKey(exports, seckey);
|
|
206
|
-
if (pk.length !== 32) throw new CryptoError("wasm publicKey failed");
|
|
207
|
-
return pk;
|
|
208
|
-
})
|
|
209
|
-
};
|
|
210
|
-
}
|
|
211
|
-
async function instantiateNostrWasm(opts) {
|
|
212
|
-
return bindExports(await instantiateCryptoWasm(await wasmBytes(opts)));
|
|
213
|
-
}
|
|
20
|
+
const loader = createNostrWasmLoader(wasmBytes);
|
|
214
21
|
/** Instantiate once. Repeats reuse the same module. Failure throws; no noble fallback. */
|
|
215
22
|
async function loadNostrWasm(opts) {
|
|
216
|
-
|
|
217
|
-
const pending = instantiateNostrWasm(opts);
|
|
218
|
-
interned = pending;
|
|
219
|
-
try {
|
|
220
|
-
return await pending;
|
|
221
|
-
} catch (error) {
|
|
222
|
-
if (interned === pending) interned = void 0;
|
|
223
|
-
throw error;
|
|
224
|
-
}
|
|
23
|
+
return loader.loadNostrWasm(opts);
|
|
225
24
|
}
|
|
226
25
|
//#endregion
|
|
227
26
|
export { WasmVerifyPoisonedError, loadNostrWasm };
|
package/dist/wasm.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wasm.mjs","names":[],"sources":["../src/wasm/abi.ts","../src/wasm/adapter.ts","../src/wasm/load.ts"],"sourcesContent":["/** Wasm-bindgen 0.2.122 bundler-produced exports used by interned TS glue. */\nexport type CryptoWasmExports = {\n memory: WebAssembly.Memory;\n verify: (\n idPtr: number,\n idLen: number,\n pkPtr: number,\n pkLen: number,\n sigPtr: number,\n sigLen: number,\n ) => number;\n verify_serialized: (\n serPtr: number,\n serLen: number,\n idPtr: number,\n idLen: number,\n pkPtr: number,\n pkLen: number,\n sigPtr: number,\n sigLen: number,\n ) => number;\n sign: (\n retptr: number,\n idPtr: number,\n idLen: number,\n skPtr: number,\n skLen: number,\n auxPtr: number,\n auxLen: number,\n ) => void;\n public_key: (retptr: number, skPtr: number, skLen: number) => void;\n /** 0.2.122 name for `__wbindgen_malloc(size, align)`. */\n __wbindgen_export: (size: number, align: number) => number;\n /** 0.2.122 name for `__wbindgen_free(ptr, size, align)` after malloc claimed `__wbindgen_export`. */\n __wbindgen_export2: (ptr: number, size: number, align: number) => void;\n __wbindgen_add_to_stack_pointer: (delta: number) => number;\n __wbindgen_start?: () => void;\n};\n\n/** Imports 0.2.122 may request. Instantiation fails if anything else appears. */\nexport const ALLOWED_WASM_IMPORTS: ReadonlyArray<{ module: string; name: string }> = [\n { module: \"wbg\", name: \"__wbindgen_throw\" },\n { module: \"./nostr_crypto_wasm_bg.js\", name: \"__wbindgen_throw\" },\n];\n\nconst utf8 = new TextDecoder();\n\nfunction decodeUtf8(memory: WebAssembly.Memory, ptr: number, len: number): string {\n return utf8.decode(new Uint8Array(memory.buffer, ptr, len));\n}\n\nfunction makeWbgImports(holder: { exports?: CryptoWasmExports }): WebAssembly.Imports {\n const throwRuntime = (ptr: number, len: number): never => {\n const mem = holder.exports?.memory;\n const msg = mem ? decodeUtf8(mem, ptr, len) : \"wasm panic\";\n throw new WebAssembly.RuntimeError(msg);\n };\n const wbg = {\n __wbindgen_throw: throwRuntime,\n };\n return {\n wbg,\n \"./nostr_crypto_wasm_bg.js\": wbg,\n };\n}\n\n/** Fail if the module imports anything outside {@link ALLOWED_WASM_IMPORTS}. */\nexport function assertAllowedWasmImports(mod: WebAssembly.Module): void {\n const allowed = new Set(ALLOWED_WASM_IMPORTS.map((item) => `${item.module}\\0${item.name}`));\n for (const imp of WebAssembly.Module.imports(mod)) {\n if (imp.kind !== \"function\") {\n throw new TypeError(`unexpected wasm import kind ${imp.kind}: ${imp.module}.${imp.name}`);\n }\n if (!allowed.has(`${imp.module}\\0${imp.name}`)) {\n throw new TypeError(`unexpected wasm import ${imp.module}.${imp.name}`);\n }\n }\n}\n\nfunction requireMemory(value: WebAssembly.ExportValue | undefined): WebAssembly.Memory {\n if (!(value instanceof WebAssembly.Memory)) {\n throw new TypeError(\"wasm missing memory export\");\n }\n return value;\n}\n\n// oxlint-disable-next-line no-unnecessary-type-parameters -- T binds the declared ABI signature at each call site\nfunction requireFn<T extends (...args: number[]) => unknown>(\n value: WebAssembly.ExportValue | undefined,\n name: string,\n): T {\n if (typeof value !== \"function\") {\n throw new TypeError(`wasm missing ${name} export`);\n }\n // oxlint-disable-next-line no-unsafe-type-assertion -- wasm exports are opaque; each name is bound to the signature the ABI contract requires\n return value as T;\n}\n\nfunction asExports(raw: WebAssembly.Exports): CryptoWasmExports {\n const exports: CryptoWasmExports = {\n memory: requireMemory(raw[\"memory\"]),\n verify: requireFn(raw[\"verify\"], \"verify\"),\n verify_serialized: requireFn(raw[\"verify_serialized\"], \"verify_serialized\"),\n sign: requireFn(raw[\"sign\"], \"sign\"),\n public_key: requireFn(raw[\"public_key\"], \"public_key\"),\n __wbindgen_export: requireFn(raw[\"__wbindgen_export\"], \"__wbindgen_export\"),\n __wbindgen_export2: requireFn(raw[\"__wbindgen_export2\"], \"__wbindgen_export2\"),\n __wbindgen_add_to_stack_pointer: requireFn(\n raw[\"__wbindgen_add_to_stack_pointer\"],\n \"__wbindgen_add_to_stack_pointer\",\n ),\n };\n const start = raw[\"__wbindgen_start\"];\n if (typeof start === \"function\") {\n exports.__wbindgen_start = requireFn<() => void>(start, \"__wbindgen_start\");\n }\n return exports;\n}\n\nfunction passBytes(exports: CryptoWasmExports, bytes: Uint8Array): { ptr: number; len: number } {\n const len = bytes.length;\n const ptr = exports.__wbindgen_export(len, 1) >>> 0;\n new Uint8Array(exports.memory.buffer, ptr, len).set(bytes);\n return { ptr, len };\n}\n\nexport function wasmVerify(\n exports: CryptoWasmExports,\n id: Uint8Array,\n pubkey: Uint8Array,\n sig: Uint8Array,\n): boolean {\n const idP = passBytes(exports, id);\n const pkP = passBytes(exports, pubkey);\n const sigP = passBytes(exports, sig);\n return exports.verify(idP.ptr, idP.len, pkP.ptr, pkP.len, sigP.ptr, sigP.len) !== 0;\n}\n\nexport function wasmVerifySerialized(\n exports: CryptoWasmExports,\n serialized: Uint8Array,\n id: Uint8Array,\n pubkey: Uint8Array,\n sig: Uint8Array,\n): boolean {\n const serP = passBytes(exports, serialized);\n const idP = passBytes(exports, id);\n const pkP = passBytes(exports, pubkey);\n const sigP = passBytes(exports, sig);\n return (\n exports.verify_serialized(\n serP.ptr,\n serP.len,\n idP.ptr,\n idP.len,\n pkP.ptr,\n pkP.len,\n sigP.ptr,\n sigP.len,\n ) !== 0\n );\n}\n\nfunction takeBytes(exports: CryptoWasmExports, ptr: number, len: number): Uint8Array {\n const out = new Uint8Array(len);\n if (len > 0) {\n out.set(new Uint8Array(exports.memory.buffer, ptr, len));\n exports.__wbindgen_export2(ptr, len, 1);\n }\n return out;\n}\n\nfunction callReturningBytes(\n exports: CryptoWasmExports,\n invoke: (retptr: number) => void,\n): Uint8Array {\n const retptr = exports.__wbindgen_add_to_stack_pointer(-16);\n try {\n invoke(retptr);\n const view = new DataView(exports.memory.buffer);\n const ptr = view.getUint32(retptr, true);\n const len = view.getUint32(retptr + 4, true);\n return takeBytes(exports, ptr, len);\n } finally {\n exports.__wbindgen_add_to_stack_pointer(16);\n }\n}\n\nexport function wasmSign(\n exports: CryptoWasmExports,\n id: Uint8Array,\n seckey: Uint8Array,\n aux: Uint8Array,\n): Uint8Array {\n const idP = passBytes(exports, id);\n const skP = passBytes(exports, seckey);\n const auxP = passBytes(exports, aux);\n return callReturningBytes(exports, (retptr) => {\n exports.sign(retptr, idP.ptr, idP.len, skP.ptr, skP.len, auxP.ptr, auxP.len);\n });\n}\n\nexport function wasmPublicKey(exports: CryptoWasmExports, seckey: Uint8Array): Uint8Array {\n const skP = passBytes(exports, seckey);\n return callReturningBytes(exports, (retptr) => {\n exports.public_key(retptr, skP.ptr, skP.len);\n });\n}\n\nexport async function instantiateCryptoWasm(\n bytes: ArrayBuffer | ArrayBufferView,\n): Promise<CryptoWasmExports> {\n const holder: { exports?: CryptoWasmExports } = {};\n const { module, instance } = await WebAssembly.instantiate(bytes, makeWbgImports(holder));\n assertAllowedWasmImports(module);\n holder.exports = asExports(instance.exports);\n holder.exports.__wbindgen_start?.();\n return holder.exports;\n}\n","import { WasmVerifyPoisonedError } from \"../core/error.ts\";\nimport type { Event } from \"../core/event.ts\";\nimport { createEventVerifier } from \"../core/verifier.ts\";\nimport type { SerializedEventVerifier } from \"../core/verifier.ts\";\n\nexport { WasmVerifyPoisonedError } from \"../core/error.ts\";\n\n/**\n * Build the WASM event verifier on {@link createEventVerifier}. A `WebAssembly.RuntimeError` from\n * the module means the instance aborted — it poisons every later call with the same\n * `WasmVerifyPoisonedError`; any other backend error verifies `false` (the event is marked\n * failed).\n */\nexport function createWasmEventVerifier(\n verifySerialized: SerializedEventVerifier,\n poison: { error?: Error },\n): (event: Event) => boolean {\n const backend: SerializedEventVerifier = (serializedUtf8, id, pubkey, sig) => {\n if (poison.error !== undefined) {\n throw poison.error;\n }\n try {\n return verifySerialized(serializedUtf8, id, pubkey, sig);\n } catch (error) {\n if (error instanceof WebAssembly.RuntimeError) {\n poison.error = new WasmVerifyPoisonedError(\"wasm verify aborted the instance\", {\n cause: error,\n });\n throw poison.error;\n }\n return false;\n }\n };\n return createEventVerifier(backend);\n}\n","import { CryptoError } from \"../core/error.ts\";\nimport type { Event } from \"../core/event.ts\";\nimport type { SigningBackend } from \"../core/key.ts\";\nimport {\n instantiateCryptoWasm,\n wasmPublicKey,\n wasmSign,\n wasmVerify,\n wasmVerifySerialized,\n} from \"./abi.ts\";\nimport type { CryptoWasmExports } from \"./abi.ts\";\nimport { createWasmEventVerifier, WasmVerifyPoisonedError } from \"./adapter.ts\";\n\nexport { WasmVerifyPoisonedError } from \"./adapter.ts\";\nexport type LoadNostrWasmOptions = {\n /** Bytes, or a URL whose bytes will be read (Node fs for file:; fetch otherwise). */\n module?: ArrayBuffer | ArrayBufferView | URL;\n};\n\nexport type NostrWasm = SigningBackend & {\n verify: (id: Uint8Array, pubkey: Uint8Array, sig: Uint8Array) => boolean;\n verifySerialized: (\n serializedUtf8: Uint8Array,\n id: Uint8Array,\n pubkey: Uint8Array,\n sig: Uint8Array,\n ) => boolean;\n verifyEvent: (event: Event) => boolean;\n};\n\nlet interned: Promise<NostrWasm> | undefined;\n\nfunction isNode(): boolean {\n if (!(\"process\" in globalThis)) {\n return false;\n }\n const proc: unknown = globalThis.process;\n return (\n typeof proc === \"object\" &&\n proc !== null &&\n \"versions\" in proc &&\n typeof proc.versions === \"object\" &&\n proc.versions !== null &&\n \"node\" in proc.versions &&\n typeof proc.versions.node === \"string\"\n );\n}\n\nfunction isWasmBytes(value: unknown): value is ArrayBuffer | ArrayBufferView {\n return value instanceof ArrayBuffer || ArrayBuffer.isView(value);\n}\n\nasync function defaultWasmHref(): Promise<string> {\n const mod = await import(\"./nostr_crypto_wasm_bg.wasm?url\");\n return mod.default;\n}\n\nasync function readWasmUrl(url: URL): Promise<Uint8Array> {\n if (isNode() && url.protocol === \"file:\") {\n const { readFile } = await import(\"node:fs/promises\");\n const { fileURLToPath } = await import(\"node:url\");\n return new Uint8Array(await readFile(fileURLToPath(url)));\n }\n const res = await fetch(url);\n if (!res.ok) {\n throw new CryptoError(`failed to fetch wasm: ${res.status} ${url.href}`);\n }\n return new Uint8Array(await res.arrayBuffer());\n}\n\nasync function wasmBytes(opts?: LoadNostrWasmOptions): Promise<ArrayBuffer | ArrayBufferView> {\n const source = opts?.module;\n if (source !== undefined && isWasmBytes(source)) {\n return source;\n }\n const href = source instanceof URL ? source : new URL(await defaultWasmHref(), import.meta.url);\n return readWasmUrl(href);\n}\n\nfunction requireByteLength(bytes: Uint8Array, expected: number, label: string): void {\n if (bytes.length !== expected) {\n throw new CryptoError(`invalid ${label} length: expected ${expected}, got ${bytes.length}`);\n }\n}\n\nfunction wrapPoison<T>(poison: { error?: Error }, fn: () => T): T {\n if (poison.error) {\n throw poison.error;\n }\n try {\n return fn();\n } catch (error) {\n if (error instanceof WebAssembly.RuntimeError) {\n poison.error = new WasmVerifyPoisonedError(\"wasm verify aborted the instance\", {\n cause: error,\n });\n throw poison.error;\n }\n throw error;\n }\n}\n\nfunction bindExports(exports: CryptoWasmExports): NostrWasm {\n const poison: { error?: Error } = {};\n const rawSerialized = (\n serializedUtf8: Uint8Array,\n id: Uint8Array,\n pubkey: Uint8Array,\n sig: Uint8Array,\n ): boolean => wasmVerifySerialized(exports, serializedUtf8, id, pubkey, sig);\n return {\n verify: (id, pubkey, sig) => wrapPoison(poison, () => wasmVerify(exports, id, pubkey, sig)),\n verifySerialized: (serializedUtf8, id, pubkey, sig) =>\n wrapPoison(poison, () => rawSerialized(serializedUtf8, id, pubkey, sig)),\n verifyEvent: createWasmEventVerifier(rawSerialized, poison),\n sign: (id, seckey, aux) =>\n wrapPoison(poison, () => {\n requireByteLength(id, 32, \"id\");\n requireByteLength(seckey, 32, \"secret key\");\n requireByteLength(aux, 32, \"aux\");\n const sig = wasmSign(exports, id, seckey, aux);\n if (sig.length !== 64) {\n throw new CryptoError(\"wasm sign failed\");\n }\n return sig;\n }),\n publicKey: (seckey) =>\n wrapPoison(poison, () => {\n requireByteLength(seckey, 32, \"secret key\");\n const pk = wasmPublicKey(exports, seckey);\n if (pk.length !== 32) {\n throw new CryptoError(\"wasm publicKey failed\");\n }\n return pk;\n }),\n };\n}\n\nasync function instantiateNostrWasm(opts?: LoadNostrWasmOptions): Promise<NostrWasm> {\n const bytes = await wasmBytes(opts);\n const exports = await instantiateCryptoWasm(bytes);\n return bindExports(exports);\n}\n\n/** Instantiate once. Repeats reuse the same module. Failure throws; no noble fallback. */\nexport async function loadNostrWasm(opts?: LoadNostrWasmOptions): Promise<NostrWasm> {\n if (interned) {\n return interned;\n }\n const pending = instantiateNostrWasm(opts);\n interned = pending;\n try {\n return await pending;\n } catch (error) {\n if (interned === pending) {\n interned = undefined;\n }\n throw error;\n }\n}\n\n/** Clears intern so tests can re-instantiate. Not exported from the wasm subpath. */\nexport function resetNostrWasmForTests(): void {\n interned = undefined;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"wasm.mjs","names":[],"sources":["../src/wasm/load.ts"],"sourcesContent":["import { createNostrWasmLoader, fetchWasmUrl, isWasmBytes } from \"./instance.ts\";\nimport type { LoadNostrWasmOptions, NostrWasm } from \"./instance.ts\";\n\nexport { WasmVerifyPoisonedError } from \"./adapter.ts\";\nexport type { LoadNostrWasmOptions, NostrWasm } from \"./instance.ts\";\n\nasync function defaultWasmHref(): Promise<string> {\n const mod = await import(\"./nostr_crypto_wasm_bg.wasm?url\");\n return mod.default;\n}\n\nasync function readWasmUrl(url: URL): Promise<Uint8Array> {\n if (url.protocol === \"file:\") {\n const { readFile } = await import(\"node:fs/promises\");\n const { fileURLToPath } = await import(\"node:url\");\n return new Uint8Array(await readFile(fileURLToPath(url)));\n }\n return fetchWasmUrl(url);\n}\n\nasync function wasmBytes(opts?: LoadNostrWasmOptions): Promise<ArrayBuffer | ArrayBufferView> {\n const source = opts?.module;\n if (source !== undefined && isWasmBytes(source)) {\n return source;\n }\n const href = source instanceof URL ? source : new URL(await defaultWasmHref(), import.meta.url);\n return readWasmUrl(href);\n}\n\nconst loader = createNostrWasmLoader(wasmBytes);\n\n/** Instantiate once. Repeats reuse the same module. Failure throws; no noble fallback. */\nexport async function loadNostrWasm(opts?: LoadNostrWasmOptions): Promise<NostrWasm> {\n return loader.loadNostrWasm(opts);\n}\n\n/** Clears intern so tests can re-instantiate. Not exported from the wasm subpath. */\nexport function resetNostrWasmForTests(): void {\n loader.resetNostrWasm();\n}\n"],"mappings":";;;AAMA,eAAe,kBAAmC;CAEhD,QAAO,MADW,OAAO,uCAAA,CACd;AACb;AAEA,eAAe,YAAY,KAA+B;CACxD,IAAI,IAAI,aAAa,SAAS;EAC5B,MAAM,EAAE,aAAa,MAAM,OAAO;EAClC,MAAM,EAAE,kBAAkB,MAAM,OAAO;EACvC,OAAO,IAAI,WAAW,MAAM,SAAS,cAAc,GAAG,CAAC,CAAC;CAC1D;CACA,OAAO,aAAa,GAAG;AACzB;AAEA,eAAe,UAAU,MAAqE;CAC5F,MAAM,SAAS,MAAM;CACrB,IAAI,WAAW,KAAA,KAAa,YAAY,MAAM,GAC5C,OAAO;CAGT,OAAO,YADM,kBAAkB,MAAM,SAAS,IAAI,IAAI,MAAM,gBAAgB,GAAG,YAAY,GAAG,CACvE;AACzB;AAEA,MAAM,SAAS,sBAAsB,SAAS;;AAG9C,eAAsB,cAAc,MAAiD;CACnF,OAAO,OAAO,cAAc,IAAI;AAClC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qntx/nostr",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Nostr protocol implementation and SDK in TypeScript",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"decentralized",
|
|
@@ -184,9 +184,15 @@
|
|
|
184
184
|
"import": "./dist/testing.mjs",
|
|
185
185
|
"default": "./dist/testing.mjs"
|
|
186
186
|
},
|
|
187
|
+
"./wasm.browser": {
|
|
188
|
+
"types": "./dist/wasm.browser.d.mts",
|
|
189
|
+
"import": "./dist/wasm.browser.mjs",
|
|
190
|
+
"default": "./dist/wasm.browser.mjs"
|
|
191
|
+
},
|
|
187
192
|
"./package.json": "./package.json",
|
|
188
193
|
"./wasm": {
|
|
189
194
|
"types": "./dist/wasm.d.mts",
|
|
195
|
+
"browser": "./dist/wasm.browser.mjs",
|
|
190
196
|
"import": "./dist/wasm.mjs",
|
|
191
197
|
"default": "./dist/wasm.mjs"
|
|
192
198
|
}
|
|
@@ -199,7 +205,7 @@
|
|
|
199
205
|
"build:wasm": "bash scripts/build-wasm.sh && WASM_PACK=1 vp pack && ls dist/*.wasm >/dev/null && publint && attw --pack . --profile esm-only",
|
|
200
206
|
"dev": "vp pack --watch",
|
|
201
207
|
"test": "vp test",
|
|
202
|
-
"test:wasm": "WASM_TEST=1 vp test wasm-tests/verify.ts wasm-tests/node-load.ts wasm-tests/sign.ts",
|
|
208
|
+
"test:wasm": "WASM_TEST=1 vp test wasm-tests/verify.ts wasm-tests/node-load.ts wasm-tests/sign.ts wasm-tests/browser-entry.ts",
|
|
203
209
|
"bench:wasm": "WASM_TEST=1 vp test wasm-tests/bench.ts",
|
|
204
210
|
"bench:store": "STORE_BENCH=1 vp test bench/reactive-store.bench.ts",
|
|
205
211
|
"bench:store:sqlite": "STORE_BENCH=1 vp test bench/sqlite-store.bench.ts",
|
|
@@ -225,6 +231,7 @@
|
|
|
225
231
|
"@qntx/tsconfig": "^1.0.1",
|
|
226
232
|
"@types/node": "^26.6.3",
|
|
227
233
|
"@types/ws": "8.18.1",
|
|
234
|
+
"binaryen": "^132.0.0",
|
|
228
235
|
"buffer": "6.0.3",
|
|
229
236
|
"bumpp": "^12.3.0",
|
|
230
237
|
"publint": "^0.3.24",
|
|
@@ -232,7 +239,7 @@
|
|
|
232
239
|
"vite": "npm:@voidzero-dev/vite-plus-core@0.3.3",
|
|
233
240
|
"vite-plus": "0.3.3",
|
|
234
241
|
"whatwg-url": "7.1.0",
|
|
235
|
-
"ws": "8.
|
|
242
|
+
"ws": "8.22.0"
|
|
236
243
|
},
|
|
237
244
|
"peerDependencies": {
|
|
238
245
|
"ws": "^8.18.0"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"reactive-DDlThDSZ.mjs","names":[],"sources":["../src/store/reactive.ts"],"sourcesContent":["import { itemCompare } from \"../core/event.ts\";\nimport type { Event } from \"../core/event.ts\";\nimport type { Filter } from \"../core/filter.ts\";\nimport { filterFingerprint, matchFilters } from \"../core/filter.ts\";\nimport { invokeSafely } from \"../core/report.ts\";\nimport { formatEventAddress, eventAddress } from \"../core/tag.ts\";\nimport { normalizeURL } from \"../core/util.ts\";\nimport { MemoryIndex } from \"../storage/memory-index.ts\";\nimport type { PutResult } from \"../storage/types.ts\";\n\n/** A reactive snapshot source compatible with `useSyncExternalStore`. */\nexport type Watch<T> = {\n subscribe: (onChange: () => void) => () => void;\n getSnapshot: () => T;\n};\n\n/** Capacity options for {@link ReactiveEventStore}. */\nexport type ReactiveEventStoreOptions = {\n /** Max stored events before LRU eviction. Default 50_000. */\n maxEvents?: number;\n /** Max ids tracked by `seenOn`. Default 20_000. */\n maxSeenOnEntries?: number;\n /** FIFO cap on tombstoned deletion ids. Default 100_000. */\n maxTombstones?: number;\n};\n\nconst SEEN_ON_PER_ID = 16;\n\n/** Category of a {@link Watch} subscription. */\ntype WatchKind = \"event\" | \"replaceable\" | \"query\";\n\n/** Structural handle the store needs for invalidation; implemented by WatchImpl. */\ntype WatchHandle = {\n readonly kind: WatchKind;\n readonly key: string;\n readonly filters: ReadonlyArray<Filter> | undefined;\n readonly subscribed: boolean;\n readonly pinnedIds: ReadonlyArray<string>;\n _markDirty: () => void;\n _notify: () => void;\n};\n\nclass WatchImpl<T> implements Watch<T>, WatchHandle {\n readonly store: ReactiveEventStore;\n readonly kind: WatchKind;\n readonly key: string;\n readonly filters: ReadonlyArray<Filter> | undefined;\n readonly compute: () => T;\n readonly equal: (a: T, b: T) => boolean;\n readonly snapshotIds: (snapshot: T) => ReadonlyArray<string>;\n readonly #subscribers = new Set<() => void>();\n #snapshot: T;\n #version = -1;\n #dirty = false;\n #pendingRemove = false;\n\n constructor(\n store: ReactiveEventStore,\n kind: WatchKind,\n key: string,\n compute: () => T,\n equal: (a: T, b: T) => boolean,\n snapshotIds: (snapshot: T) => ReadonlyArray<string>,\n filters?: ReadonlyArray<Filter>,\n ) {\n this.store = store;\n this.kind = kind;\n this.key = key;\n this.filters = filters;\n this.compute = compute;\n this.equal = equal;\n this.snapshotIds = snapshotIds;\n this.#snapshot = compute();\n this.#version = store._version;\n }\n\n get subscribed(): boolean {\n return this.#subscribers.size > 0;\n }\n\n get pinnedIds(): ReadonlyArray<string> {\n return this.snapshotIds(this.#snapshot);\n }\n\n subscribe(onChange: () => void): () => void {\n const wasUnsubscribed = this.#subscribers.size === 0;\n this.#subscribers.add(onChange);\n this.#pendingRemove = false;\n // Writes that landed while unregistered must not be lost.\n if (wasUnsubscribed && this.#version !== this.store._version) {\n this.#dirty = true;\n }\n this.store._register(this);\n return () => {\n this.#subscribers.delete(onChange);\n if (this.#subscribers.size > 0 || this.#pendingRemove) {\n return;\n }\n this.#pendingRemove = true;\n queueMicrotask(() => {\n if (this.#pendingRemove) {\n this.store._unregister(this);\n }\n });\n };\n }\n\n getSnapshot(): T {\n if (this.subscribed ? this.#dirty : this.#version !== this.store._version) {\n const next = this.compute();\n if (!this.equal(next, this.#snapshot)) {\n this.#snapshot = next;\n }\n this.#version = this.store._version;\n this.#dirty = false;\n }\n return this.#snapshot;\n }\n\n _markDirty(): void {\n this.#dirty = true;\n }\n\n _notify(): void {\n // Do not sync #version here: subscribers will call getSnapshot, which\n // recomputes against the bumped store version and keeps the reference\n // when the result is element-wise identical. A throwing subscriber is\n // reported and never aborts the remaining notifications.\n for (const onChange of this.#subscribers) {\n invokeSafely(onChange);\n }\n }\n}\n\nconst EVENT_IDS = (e: Event | undefined): ReadonlyArray<string> => (e ? [e.id] : []);\nconst LIST_IDS = (events: ReadonlyArray<Event>): ReadonlyArray<string> => events.map((e) => e.id);\n\nfunction sameRef(a: Event | undefined, b: Event | undefined): boolean {\n return a === b;\n}\n\nfunction sameList(a: ReadonlyArray<Event>, b: ReadonlyArray<Event>): boolean {\n if (a.length !== b.length) {\n return false;\n }\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) {\n return false;\n }\n }\n return true;\n}\n\n/**\n * Synchronous reactive in-memory event store backed by {@link MemoryIndex}. The single read source\n * for Nostr events on the UI side: `Watch` snapshots keep referential stability for\n * `useSyncExternalStore` and are invalidated on matching writes, deletions and tombstones. Writes\n * batch notifications into one microtask flush.\n */\nexport class ReactiveEventStore {\n readonly #index: MemoryIndex;\n readonly #maxEvents: number;\n readonly #maxSeenOnEntries: number;\n\n _version = 0;\n\n // id -> recency-ordered access order (delete+add moves to the newest end)\n readonly #recency = new Set<string>();\n // id -> relay urls (≤ SEEN_ON_PER_ID); Map insertion order for eviction\n readonly #seenOn = new Map<string, string[]>();\n\n readonly #idWatches = new Map<string, Set<WatchHandle>>();\n readonly #addressWatches = new Map<string, Set<WatchHandle>>();\n readonly #queryCache = new Map<string, WatchImpl<ReadonlyArray<Event>>>();\n readonly #queryRegistry = new Set<WatchHandle>();\n\n readonly #dirty = new Set<WatchHandle>();\n #flushScheduled = false;\n readonly #insertListeners = new Set<(event: Event) => void>();\n\n constructor(opts?: ReactiveEventStoreOptions) {\n this.#maxEvents = opts?.maxEvents ?? 50_000;\n this.#maxSeenOnEntries = opts?.maxSeenOnEntries ?? 20_000;\n this.#index = new MemoryIndex({\n maxTombstones: opts?.maxTombstones ?? 100_000,\n // Keep evicted replaceable winners rejectable while their body is gone.\n maxWatermarks: this.#maxEvents,\n onInsert: (event) => this.#onInsert(event),\n onRemove: (event) => this.#onRemove(event),\n });\n }\n\n add(event: Event, relayUrl?: string): PutResult {\n const result = this.#index.put(event);\n // Stored events are canonical; seenOn keys are their lowercase ids.\n const { id } = event;\n if (\n relayUrl !== undefined &&\n result !== \"ephemeral\" &&\n result !== \"rejected\" &&\n result !== \"invalid\"\n ) {\n this.#recordSeen(id, relayUrl);\n }\n // The just-inserted event must survive its own eviction pass even when\n // every older entry is pinned by a subscribed watch snapshot.\n this.#evictIfNeeded(id);\n return result;\n }\n\n addMany(events: ReadonlyArray<Event>, relayUrl?: string): PutResult[] {\n const results: PutResult[] = [];\n for (const event of events) {\n results.push(this.add(event, relayUrl));\n }\n return results;\n }\n\n /** Record a relay sighting for an id already in the index. No notification. */\n markSeen(id: string, relayUrl: string): boolean {\n const key = id.toLowerCase();\n if (this.#index.get(key) === undefined) {\n return false;\n }\n this.#recordSeen(key, relayUrl);\n return true;\n }\n\n /** Bulk load (initial hydration): no seenOn, one batched notification. */\n hydrate(events: ReadonlyArray<Event>): void {\n // Insert oldest-first so recency ends with the newest entries hottest.\n const sorted = [...events].sort(itemCompare);\n for (const event of sorted) {\n this.#index.put(event);\n }\n this.#evictIfNeeded();\n }\n\n remove(ids: ReadonlyArray<string>): number {\n return this.#index.remove(ids);\n }\n\n clear(): void {\n this.#index.clear();\n this.#seenOn.clear();\n this.#recency.clear();\n this._version += 1;\n this.#invalidateAll();\n }\n\n get(id: string): Event | undefined {\n const event = this.#index.get(id);\n if (event) {\n this.#touch(event.id);\n }\n return event;\n }\n\n getReplaceable(kind: number, pubkey: string, d?: string): Event | undefined {\n return this.getByAddress(formatEventAddress(kind, pubkey, d ?? \"\"));\n }\n\n getByAddress(address: string): Event | undefined {\n const event = this.#index.getByAddress(address);\n if (event) {\n this.#touch(event.id);\n }\n return event;\n }\n\n query(filters: ReadonlyArray<Filter>): ReadonlyArray<Event> {\n const events = this.#index.query(filters);\n // Results come back newest-first; touch oldest→newest so the newest\n // entries end up hottest in the recency order.\n for (const event of [...events].reverse()) {\n this.#touch(event.id);\n }\n return events;\n }\n\n isDeleted(idOrAddress: string): boolean {\n return this.#index.isDeleted(idOrAddress);\n }\n\n seenOn(id: string): ReadonlyArray<string> {\n return this.#seenOn.get(id.toLowerCase()) ?? [];\n }\n\n get size(): number {\n return this.#index.size;\n }\n\n watchEvent(id: string): Watch<Event | undefined> {\n const key = id.toLowerCase();\n return new WatchImpl(this, \"event\", key, () => this.get(key), sameRef, EVENT_IDS);\n }\n\n watchReplaceable(kind: number, pubkey: string, d?: string): Watch<Event | undefined> {\n const address = formatEventAddress(kind, pubkey, d ?? \"\");\n return new WatchImpl(\n this,\n \"replaceable\",\n address,\n () => this.getByAddress(address),\n sameRef,\n EVENT_IDS,\n );\n }\n\n watchQuery(filters: ReadonlyArray<Filter>): Watch<ReadonlyArray<Event>> {\n const key = filterFingerprint(filters);\n let watch = this.#queryCache.get(key);\n if (!watch) {\n const list = [...filters];\n watch = new WatchImpl(this, \"query\", key, () => this.query(list), sameList, LIST_IDS, list);\n this.#queryCache.set(key, watch);\n }\n return watch;\n }\n\n /** Synchronous listener for every physical index insert (after update). */\n onInsert(listener: (event: Event) => void): () => void {\n this.#insertListeners.add(listener);\n return () => {\n this.#insertListeners.delete(listener);\n };\n }\n\n _register(watch: WatchHandle): void {\n switch (watch.kind) {\n case \"event\":\n addWatch(this.#idWatches, watch.key, watch);\n return;\n case \"replaceable\":\n addWatch(this.#addressWatches, watch.key, watch);\n return;\n case \"query\":\n this.#queryRegistry.add(watch);\n }\n }\n\n _unregister(watch: WatchHandle): void {\n if (watch.subscribed) {\n return;\n }\n switch (watch.kind) {\n case \"event\":\n removeWatch(this.#idWatches, watch.key, watch);\n return;\n case \"replaceable\":\n removeWatch(this.#addressWatches, watch.key, watch);\n return;\n case \"query\":\n this.#queryRegistry.delete(watch);\n if (this.#queryCache.get(watch.key) === watch) {\n this.#queryCache.delete(watch.key);\n }\n }\n }\n\n #touch(id: string): void {\n if (this.#recency.delete(id)) {\n this.#recency.add(id);\n } else {\n this.#recency.add(id);\n }\n }\n\n #recordSeen(id: string, relayUrl: string): void {\n const url = normalizeURL(relayUrl);\n let urls = this.#seenOn.get(id);\n if (!urls) {\n urls = [];\n this.#seenOn.set(id, urls);\n }\n if (!urls.includes(url) && urls.length < SEEN_ON_PER_ID) {\n urls.push(url);\n }\n while (this.#seenOn.size > this.#maxSeenOnEntries) {\n const oldest = this.#seenOn.keys().next().value;\n if (oldest === undefined) {\n break;\n }\n this.#seenOn.delete(oldest);\n }\n }\n\n #onInsert(event: Event): void {\n this._version += 1;\n this.#touch(event.id);\n this.#invalidateByEvent(event);\n for (const listener of this.#insertListeners) {\n invokeSafely(() => listener(event));\n }\n }\n\n #onRemove(event: Event): void {\n this._version += 1;\n this.#recency.delete(event.id);\n this.#invalidateByEvent(event);\n }\n\n #invalidateByEvent(event: Event): void {\n const byId = this.#idWatches.get(event.id);\n if (byId) {\n for (const watch of byId) {\n this.#markDirty(watch);\n }\n }\n const address = eventAddress(event);\n if (address !== undefined) {\n const byAddress = this.#addressWatches.get(address);\n if (byAddress) {\n for (const watch of byAddress) {\n this.#markDirty(watch);\n }\n }\n }\n for (const watch of this.#queryRegistry) {\n if (watch.filters !== undefined && matchFilters(watch.filters, event)) {\n this.#markDirty(watch);\n }\n }\n }\n\n #invalidateAll(): void {\n for (const watches of this.#idWatches.values()) {\n for (const watch of watches) {\n this.#markDirty(watch);\n }\n }\n for (const watches of this.#addressWatches.values()) {\n for (const watch of watches) {\n this.#markDirty(watch);\n }\n }\n for (const watch of this.#queryRegistry) {\n this.#markDirty(watch);\n }\n this.#scheduleFlush();\n }\n\n #markDirty(watch: WatchHandle): void {\n watch._markDirty();\n this.#dirty.add(watch);\n this.#scheduleFlush();\n }\n\n #scheduleFlush(): void {\n if (this.#flushScheduled) {\n return;\n }\n this.#flushScheduled = true;\n queueMicrotask(() => {\n // Keep the flag set while flushing: writes re-entered from a\n // subscriber land in #dirty and are notified in the same pass.\n while (this.#dirty.size > 0) {\n const batch = [...this.#dirty];\n this.#dirty.clear();\n for (const watch of batch) {\n watch._notify();\n }\n }\n this.#flushScheduled = false;\n });\n }\n\n #pinnedIds(): Set<string> {\n const pinned = new Set<string>();\n const collect = (watch: WatchHandle): void => {\n for (const id of watch.pinnedIds) {\n pinned.add(id);\n }\n };\n for (const watches of this.#idWatches.values()) {\n for (const watch of watches) {\n collect(watch);\n }\n }\n for (const watches of this.#addressWatches.values()) {\n for (const watch of watches) {\n collect(watch);\n }\n }\n for (const watch of this.#queryRegistry) {\n collect(watch);\n }\n return pinned;\n }\n\n #evictIfNeeded(protectedId?: string): void {\n if (this.#index.size <= this.#maxEvents) {\n return;\n }\n const pinned = this.#pinnedIds();\n const evicting: string[] = [];\n for (const id of this.#recency) {\n if (this.#index.size - evicting.length <= this.#maxEvents) {\n break;\n }\n if (pinned.has(id) || id === protectedId) {\n continue;\n }\n const event = this.#index.get(id);\n if (event === undefined) {\n continue;\n }\n // Replaceable/addressable winners evict like any other event; the index\n // records a watermark so stale versions stay rejected afterwards.\n evicting.push(id);\n }\n this.#index.evict(evicting);\n for (const id of evicting) {\n this.#recency.delete(id);\n }\n }\n}\n\nfunction addWatch(map: Map<string, Set<WatchHandle>>, key: string, watch: WatchHandle): void {\n let set = map.get(key);\n if (!set) {\n set = new Set();\n map.set(key, set);\n }\n set.add(watch);\n}\n\nfunction removeWatch(map: Map<string, Set<WatchHandle>>, key: string, watch: WatchHandle): void {\n const set = map.get(key);\n if (!set) {\n return;\n }\n set.delete(watch);\n if (set.size === 0) {\n map.delete(key);\n }\n}\n"],"mappings":";;;;;;AA0BA,MAAM,iBAAiB;AAgBvB,IAAM,YAAN,MAAoD;CAClD;CACA;CACA;CACA;CACA;CACA;CACA;CACA,+BAAwB,IAAI,IAAgB;CAC5C;CACA,WAAW;CACX,SAAS;CACT,iBAAiB;CAEjB,YACE,OACA,MACA,KACA,SACA,OACA,aACA,SACA;EACA,KAAK,QAAQ;EACb,KAAK,OAAO;EACZ,KAAK,MAAM;EACX,KAAK,UAAU;EACf,KAAK,UAAU;EACf,KAAK,QAAQ;EACb,KAAK,cAAc;EACnB,KAAK,YAAY,QAAQ;EACzB,KAAK,WAAW,MAAM;CACxB;CAEA,IAAI,aAAsB;EACxB,OAAO,KAAK,aAAa,OAAO;CAClC;CAEA,IAAI,YAAmC;EACrC,OAAO,KAAK,YAAY,KAAK,SAAS;CACxC;CAEA,UAAU,UAAkC;EAC1C,MAAM,kBAAkB,KAAK,aAAa,SAAS;EACnD,KAAK,aAAa,IAAI,QAAQ;EAC9B,KAAK,iBAAiB;EAEtB,IAAI,mBAAmB,KAAK,aAAa,KAAK,MAAM,UAClD,KAAK,SAAS;EAEhB,KAAK,MAAM,UAAU,IAAI;EACzB,aAAa;GACX,KAAK,aAAa,OAAO,QAAQ;GACjC,IAAI,KAAK,aAAa,OAAO,KAAK,KAAK,gBACrC;GAEF,KAAK,iBAAiB;GACtB,qBAAqB;IACnB,IAAI,KAAK,gBACP,KAAK,MAAM,YAAY,IAAI;GAE/B,CAAC;EACH;CACF;CAEA,cAAiB;EACf,IAAI,KAAK,aAAa,KAAK,SAAS,KAAK,aAAa,KAAK,MAAM,UAAU;GACzE,MAAM,OAAO,KAAK,QAAQ;GAC1B,IAAI,CAAC,KAAK,MAAM,MAAM,KAAK,SAAS,GAClC,KAAK,YAAY;GAEnB,KAAK,WAAW,KAAK,MAAM;GAC3B,KAAK,SAAS;EAChB;EACA,OAAO,KAAK;CACd;CAEA,aAAmB;EACjB,KAAK,SAAS;CAChB;CAEA,UAAgB;EAKd,KAAK,MAAM,YAAY,KAAK,cAC1B,aAAa,QAAQ;CAEzB;AACF;AAEA,MAAM,aAAa,MAAiD,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC;AAClF,MAAM,YAAY,WAAwD,OAAO,KAAK,MAAM,EAAE,EAAE;AAEhG,SAAS,QAAQ,GAAsB,GAA+B;CACpE,OAAO,MAAM;AACf;AAEA,SAAS,SAAS,GAAyB,GAAkC;CAC3E,IAAI,EAAE,WAAW,EAAE,QACjB,OAAO;CAET,KAAK,IAAI,IAAI,GAAG,IAAI,EAAE,QAAQ,KAC5B,IAAI,EAAE,OAAO,EAAE,IACb,OAAO;CAGX,OAAO;AACT;;;;;;;AAQA,IAAa,qBAAb,MAAgC;CAC9B;CACA;CACA;CAEA,WAAW;CAGX,2BAAoB,IAAI,IAAY;CAEpC,0BAAmB,IAAI,IAAsB;CAE7C,6BAAsB,IAAI,IAA8B;CACxD,kCAA2B,IAAI,IAA8B;CAC7D,8BAAuB,IAAI,IAA6C;CACxE,iCAA0B,IAAI,IAAiB;CAE/C,yBAAkB,IAAI,IAAiB;CACvC,kBAAkB;CAClB,mCAA4B,IAAI,IAA4B;CAE5D,YAAY,MAAkC;EAC5C,KAAK,aAAa,MAAM,aAAa;EACrC,KAAK,oBAAoB,MAAM,oBAAoB;EACnD,KAAK,SAAS,IAAI,YAAY;GAC5B,eAAe,MAAM,iBAAiB;GAEtC,eAAe,KAAK;GACpB,WAAW,UAAU,KAAK,UAAU,KAAK;GACzC,WAAW,UAAU,KAAK,UAAU,KAAK;EAC3C,CAAC;CACH;CAEA,IAAI,OAAc,UAA8B;EAC9C,MAAM,SAAS,KAAK,OAAO,IAAI,KAAK;EAEpC,MAAM,EAAE,OAAO;EACf,IACE,aAAa,KAAA,KACb,WAAW,eACX,WAAW,cACX,WAAW,WAEX,KAAK,YAAY,IAAI,QAAQ;EAI/B,KAAK,eAAe,EAAE;EACtB,OAAO;CACT;CAEA,QAAQ,QAA8B,UAAgC;EACpE,MAAM,UAAuB,CAAC;EAC9B,KAAK,MAAM,SAAS,QAClB,QAAQ,KAAK,KAAK,IAAI,OAAO,QAAQ,CAAC;EAExC,OAAO;CACT;;CAGA,SAAS,IAAY,UAA2B;EAC9C,MAAM,MAAM,GAAG,YAAY;EAC3B,IAAI,KAAK,OAAO,IAAI,GAAG,MAAM,KAAA,GAC3B,OAAO;EAET,KAAK,YAAY,KAAK,QAAQ;EAC9B,OAAO;CACT;;CAGA,QAAQ,QAAoC;EAE1C,MAAM,SAAS,CAAC,GAAG,MAAM,CAAC,CAAC,KAAK,WAAW;EAC3C,KAAK,MAAM,SAAS,QAClB,KAAK,OAAO,IAAI,KAAK;EAEvB,KAAK,eAAe;CACtB;CAEA,OAAO,KAAoC;EACzC,OAAO,KAAK,OAAO,OAAO,GAAG;CAC/B;CAEA,QAAc;EACZ,KAAK,OAAO,MAAM;EAClB,KAAK,QAAQ,MAAM;EACnB,KAAK,SAAS,MAAM;EACpB,KAAK,YAAY;EACjB,KAAK,eAAe;CACtB;CAEA,IAAI,IAA+B;EACjC,MAAM,QAAQ,KAAK,OAAO,IAAI,EAAE;EAChC,IAAI,OACF,KAAK,OAAO,MAAM,EAAE;EAEtB,OAAO;CACT;CAEA,eAAe,MAAc,QAAgB,GAA+B;EAC1E,OAAO,KAAK,aAAa,mBAAmB,MAAM,QAAQ,KAAK,EAAE,CAAC;CACpE;CAEA,aAAa,SAAoC;EAC/C,MAAM,QAAQ,KAAK,OAAO,aAAa,OAAO;EAC9C,IAAI,OACF,KAAK,OAAO,MAAM,EAAE;EAEtB,OAAO;CACT;CAEA,MAAM,SAAsD;EAC1D,MAAM,SAAS,KAAK,OAAO,MAAM,OAAO;EAGxC,KAAK,MAAM,SAAS,CAAC,GAAG,MAAM,CAAC,CAAC,QAAQ,GACtC,KAAK,OAAO,MAAM,EAAE;EAEtB,OAAO;CACT;CAEA,UAAU,aAA8B;EACtC,OAAO,KAAK,OAAO,UAAU,WAAW;CAC1C;CAEA,OAAO,IAAmC;EACxC,OAAO,KAAK,QAAQ,IAAI,GAAG,YAAY,CAAC,KAAK,CAAC;CAChD;CAEA,IAAI,OAAe;EACjB,OAAO,KAAK,OAAO;CACrB;CAEA,WAAW,IAAsC;EAC/C,MAAM,MAAM,GAAG,YAAY;EAC3B,OAAO,IAAI,UAAU,MAAM,SAAS,WAAW,KAAK,IAAI,GAAG,GAAG,SAAS,SAAS;CAClF;CAEA,iBAAiB,MAAc,QAAgB,GAAsC;EACnF,MAAM,UAAU,mBAAmB,MAAM,QAAQ,KAAK,EAAE;EACxD,OAAO,IAAI,UACT,MACA,eACA,eACM,KAAK,aAAa,OAAO,GAC/B,SACA,SACF;CACF;CAEA,WAAW,SAA6D;EACtE,MAAM,MAAM,kBAAkB,OAAO;EACrC,IAAI,QAAQ,KAAK,YAAY,IAAI,GAAG;EACpC,IAAI,CAAC,OAAO;GACV,MAAM,OAAO,CAAC,GAAG,OAAO;GACxB,QAAQ,IAAI,UAAU,MAAM,SAAS,WAAW,KAAK,MAAM,IAAI,GAAG,UAAU,UAAU,IAAI;GAC1F,KAAK,YAAY,IAAI,KAAK,KAAK;EACjC;EACA,OAAO;CACT;;CAGA,SAAS,UAA8C;EACrD,KAAK,iBAAiB,IAAI,QAAQ;EAClC,aAAa;GACX,KAAK,iBAAiB,OAAO,QAAQ;EACvC;CACF;CAEA,UAAU,OAA0B;EAClC,QAAQ,MAAM,MAAd;GACE,KAAK;IACH,SAAS,KAAK,YAAY,MAAM,KAAK,KAAK;IAC1C;GACF,KAAK;IACH,SAAS,KAAK,iBAAiB,MAAM,KAAK,KAAK;IAC/C;GACF,KAAK,SACH,KAAK,eAAe,IAAI,KAAK;EACjC;CACF;CAEA,YAAY,OAA0B;EACpC,IAAI,MAAM,YACR;EAEF,QAAQ,MAAM,MAAd;GACE,KAAK;IACH,YAAY,KAAK,YAAY,MAAM,KAAK,KAAK;IAC7C;GACF,KAAK;IACH,YAAY,KAAK,iBAAiB,MAAM,KAAK,KAAK;IAClD;GACF,KAAK;IACH,KAAK,eAAe,OAAO,KAAK;IAChC,IAAI,KAAK,YAAY,IAAI,MAAM,GAAG,MAAM,OACtC,KAAK,YAAY,OAAO,MAAM,GAAG;EAEvC;CACF;CAEA,OAAO,IAAkB;EACvB,IAAI,KAAK,SAAS,OAAO,EAAE,GACzB,KAAK,SAAS,IAAI,EAAE;OAEpB,KAAK,SAAS,IAAI,EAAE;CAExB;CAEA,YAAY,IAAY,UAAwB;EAC9C,MAAM,MAAM,aAAa,QAAQ;EACjC,IAAI,OAAO,KAAK,QAAQ,IAAI,EAAE;EAC9B,IAAI,CAAC,MAAM;GACT,OAAO,CAAC;GACR,KAAK,QAAQ,IAAI,IAAI,IAAI;EAC3B;EACA,IAAI,CAAC,KAAK,SAAS,GAAG,KAAK,KAAK,SAAS,gBACvC,KAAK,KAAK,GAAG;EAEf,OAAO,KAAK,QAAQ,OAAO,KAAK,mBAAmB;GACjD,MAAM,SAAS,KAAK,QAAQ,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC;GAC1C,IAAI,WAAW,KAAA,GACb;GAEF,KAAK,QAAQ,OAAO,MAAM;EAC5B;CACF;CAEA,UAAU,OAAoB;EAC5B,KAAK,YAAY;EACjB,KAAK,OAAO,MAAM,EAAE;EACpB,KAAK,mBAAmB,KAAK;EAC7B,KAAK,MAAM,YAAY,KAAK,kBAC1B,mBAAmB,SAAS,KAAK,CAAC;CAEtC;CAEA,UAAU,OAAoB;EAC5B,KAAK,YAAY;EACjB,KAAK,SAAS,OAAO,MAAM,EAAE;EAC7B,KAAK,mBAAmB,KAAK;CAC/B;CAEA,mBAAmB,OAAoB;EACrC,MAAM,OAAO,KAAK,WAAW,IAAI,MAAM,EAAE;EACzC,IAAI,MACF,KAAK,MAAM,SAAS,MAClB,KAAK,WAAW,KAAK;EAGzB,MAAM,UAAU,aAAa,KAAK;EAClC,IAAI,YAAY,KAAA,GAAW;GACzB,MAAM,YAAY,KAAK,gBAAgB,IAAI,OAAO;GAClD,IAAI,WACF,KAAK,MAAM,SAAS,WAClB,KAAK,WAAW,KAAK;EAG3B;EACA,KAAK,MAAM,SAAS,KAAK,gBACvB,IAAI,MAAM,YAAY,KAAA,KAAa,aAAa,MAAM,SAAS,KAAK,GAClE,KAAK,WAAW,KAAK;CAG3B;CAEA,iBAAuB;EACrB,KAAK,MAAM,WAAW,KAAK,WAAW,OAAO,GAC3C,KAAK,MAAM,SAAS,SAClB,KAAK,WAAW,KAAK;EAGzB,KAAK,MAAM,WAAW,KAAK,gBAAgB,OAAO,GAChD,KAAK,MAAM,SAAS,SAClB,KAAK,WAAW,KAAK;EAGzB,KAAK,MAAM,SAAS,KAAK,gBACvB,KAAK,WAAW,KAAK;EAEvB,KAAK,eAAe;CACtB;CAEA,WAAW,OAA0B;EACnC,MAAM,WAAW;EACjB,KAAK,OAAO,IAAI,KAAK;EACrB,KAAK,eAAe;CACtB;CAEA,iBAAuB;EACrB,IAAI,KAAK,iBACP;EAEF,KAAK,kBAAkB;EACvB,qBAAqB;GAGnB,OAAO,KAAK,OAAO,OAAO,GAAG;IAC3B,MAAM,QAAQ,CAAC,GAAG,KAAK,MAAM;IAC7B,KAAK,OAAO,MAAM;IAClB,KAAK,MAAM,SAAS,OAClB,MAAM,QAAQ;GAElB;GACA,KAAK,kBAAkB;EACzB,CAAC;CACH;CAEA,aAA0B;EACxB,MAAM,yBAAS,IAAI,IAAY;EAC/B,MAAM,WAAW,UAA6B;GAC5C,KAAK,MAAM,MAAM,MAAM,WACrB,OAAO,IAAI,EAAE;EAEjB;EACA,KAAK,MAAM,WAAW,KAAK,WAAW,OAAO,GAC3C,KAAK,MAAM,SAAS,SAClB,QAAQ,KAAK;EAGjB,KAAK,MAAM,WAAW,KAAK,gBAAgB,OAAO,GAChD,KAAK,MAAM,SAAS,SAClB,QAAQ,KAAK;EAGjB,KAAK,MAAM,SAAS,KAAK,gBACvB,QAAQ,KAAK;EAEf,OAAO;CACT;CAEA,eAAe,aAA4B;EACzC,IAAI,KAAK,OAAO,QAAQ,KAAK,YAC3B;EAEF,MAAM,SAAS,KAAK,WAAW;EAC/B,MAAM,WAAqB,CAAC;EAC5B,KAAK,MAAM,MAAM,KAAK,UAAU;GAC9B,IAAI,KAAK,OAAO,OAAO,SAAS,UAAU,KAAK,YAC7C;GAEF,IAAI,OAAO,IAAI,EAAE,KAAK,OAAO,aAC3B;GAGF,IADc,KAAK,OAAO,IAAI,EACtB,MAAM,KAAA,GACZ;GAIF,SAAS,KAAK,EAAE;EAClB;EACA,KAAK,OAAO,MAAM,QAAQ;EAC1B,KAAK,MAAM,MAAM,UACf,KAAK,SAAS,OAAO,EAAE;CAE3B;AACF;AAEA,SAAS,SAAS,KAAoC,KAAa,OAA0B;CAC3F,IAAI,MAAM,IAAI,IAAI,GAAG;CACrB,IAAI,CAAC,KAAK;EACR,sBAAM,IAAI,IAAI;EACd,IAAI,IAAI,KAAK,GAAG;CAClB;CACA,IAAI,IAAI,KAAK;AACf;AAEA,SAAS,YAAY,KAAoC,KAAa,OAA0B;CAC9F,MAAM,MAAM,IAAI,IAAI,GAAG;CACvB,IAAI,CAAC,KACH;CAEF,IAAI,OAAO,KAAK;CAChB,IAAI,IAAI,SAAS,GACf,IAAI,OAAO,GAAG;AAElB"}
|