@qntx/nostr 0.6.0 → 0.8.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/{abort-Ba8tDrOI.mjs → abort-DBq2STPj.mjs} +13 -6
- package/dist/abort-DBq2STPj.mjs.map +1 -0
- package/dist/{builder-sSflu6nB.d.mts → builder-CTwkB2zM.d.mts} +14 -15
- package/dist/{builder-9tjI6WQ3.mjs → builder-aNU2gGFP.mjs} +11 -17
- package/dist/builder-aNU2gGFP.mjs.map +1 -0
- package/dist/{client-CadO5fAX.mjs → client-Cj2lUaVh.mjs} +141 -353
- package/dist/client-Cj2lUaVh.mjs.map +1 -0
- package/dist/client.d.mts +2 -2
- package/dist/client.mjs +2 -2
- package/dist/collections-DtwMc1NU.mjs +33 -0
- package/dist/collections-DtwMc1NU.mjs.map +1 -0
- package/dist/core.d.mts +9 -8
- package/dist/core.mjs +7 -7
- package/dist/emitter-DkCY6NkU.mjs +32 -0
- package/dist/emitter-DkCY6NkU.mjs.map +1 -0
- package/dist/{error-BW7re1UN.d.mts → error-BD_0QFKT.d.mts} +2 -2
- package/dist/{error-DrEIM7FO.mjs → error-BILMe3Gr.mjs} +2 -2
- package/dist/{error-DrEIM7FO.mjs.map → error-BILMe3Gr.mjs.map} +1 -1
- package/dist/{error-CR8Urc84.d.mts → error-BquXDmIN.d.mts} +4 -4
- package/dist/{error-B__OMBRY.mjs → error-DlhGW4mJ.mjs} +2 -2
- package/dist/{error-B__OMBRY.mjs.map → error-DlhGW4mJ.mjs.map} +1 -1
- package/dist/{event-D8Nfoh4K.mjs → event-CHf47dPM.mjs} +16 -10
- package/dist/event-CHf47dPM.mjs.map +1 -0
- package/dist/{event-fU3Y01PR.d.mts → event-DJeb_DIL.d.mts} +4 -2
- package/dist/{filter-C0IMByE3.d.mts → filter-jI_9htF7.d.mts} +2 -2
- package/dist/{gossip-oloDMWEj.mjs → gossip-DFxIBlsr.mjs} +23 -33
- package/dist/gossip-DFxIBlsr.mjs.map +1 -0
- package/dist/{gossip-DpIvkBuj.d.mts → gossip-OOeeFzG5.d.mts} +37 -28
- package/dist/gossip.d.mts +1 -1
- package/dist/gossip.mjs +1 -1
- package/dist/{index-D1bqFHKB.d.mts → index-BxCBX-8R.d.mts} +18 -18
- package/dist/{index-lvXeER5t.d.mts → index-CPVEyzNX.d.mts} +32 -50
- package/dist/{index-MxC28S4P.d.mts → index-C_w2WfVz.d.mts} +27 -29
- package/dist/{index-CNl2q67H.d.mts → index-Cl_1XdYP.d.mts} +111 -180
- package/dist/{index-CvkvqB16.d.mts → index-DU9tRFTZ.d.mts} +7 -20
- package/dist/{index-q4MDce_r.d.mts → index-DyKwQnbt.d.mts} +6 -8
- package/dist/index.d.mts +23 -21
- package/dist/index.mjs +21 -19
- package/dist/{instance-DQE8BoWt.mjs → instance-C62w3cEt.mjs} +26 -27
- package/dist/instance-C62w3cEt.mjs.map +1 -0
- package/dist/{instance-CIca-ynn.d.mts → instance-DjsL8h84.d.mts} +5 -5
- package/dist/{key-Cv4_pN3x.d.mts → key-D_5OgGT7.d.mts} +11 -7
- package/dist/{key-Bps-LqX7.mjs → key-DnVpchl6.mjs} +13 -9
- package/dist/key-DnVpchl6.mjs.map +1 -0
- package/dist/{loaders-o6YXB_Ri.mjs → loaders-BmPkQfzI.mjs} +73 -82
- package/dist/loaders-BmPkQfzI.mjs.map +1 -0
- package/dist/loaders.d.mts +3 -3
- package/dist/loaders.mjs +2 -2
- package/dist/{memory-C2EVx0_O.mjs → memory-CdJ07kub.mjs} +2 -2
- package/dist/memory-CdJ07kub.mjs.map +1 -0
- package/dist/{memory-index-Do1mz0WF.mjs → memory-index-Cbc83vOZ.mjs} +30 -247
- package/dist/memory-index-Cbc83vOZ.mjs.map +1 -0
- package/dist/message-oNr7t0SJ.mjs +194 -0
- package/dist/message-oNr7t0SJ.mjs.map +1 -0
- package/dist/{message-iGPIqnn0.d.mts → message-tclYCVNc.d.mts} +6 -6
- package/dist/{nip17-CKIufV98.d.mts → nip17-B5WgW4C4.d.mts} +6 -7
- package/dist/{nip19-BevCJZsp.d.mts → nip19-DpPN17bY.d.mts} +25 -31
- package/dist/{nip46-DDV4dC56.d.mts → nip46-BHaxC9TZ.d.mts} +19 -21
- package/dist/nip51-CR0Q8eym.d.mts +87 -0
- package/dist/{nip59-zQgdLcEr.d.mts → nip59-C-RWFQIv.d.mts} +11 -5
- package/dist/nip65-D1fbmhOg.d.mts +23 -0
- package/dist/{nip77-DH4RhS5r.d.mts → nip77-DzUwUxHq.d.mts} +8 -9
- package/dist/nips/blossom.d.mts +17 -13
- package/dist/nips/blossom.mjs +30 -9
- package/dist/nips/blossom.mjs.map +1 -1
- package/dist/nips/nip04.mjs +17 -7
- package/dist/nips/nip04.mjs.map +1 -1
- package/dist/nips/nip05.d.mts +9 -10
- package/dist/nips/nip05.mjs +1 -4
- package/dist/nips/nip05.mjs.map +1 -1
- package/dist/nips/nip10.d.mts +8 -8
- package/dist/nips/nip10.mjs +34 -32
- package/dist/nips/nip10.mjs.map +1 -1
- package/dist/nips/nip11.d.mts +28 -28
- package/dist/nips/nip11.mjs +4 -4
- package/dist/nips/nip11.mjs.map +1 -1
- package/dist/nips/nip13.d.mts +7 -7
- package/dist/nips/nip13.mjs +32 -10
- package/dist/nips/nip13.mjs.map +1 -1
- package/dist/nips/nip17.d.mts +1 -1
- package/dist/nips/nip17.mjs +16 -34
- package/dist/nips/nip17.mjs.map +1 -1
- package/dist/nips/nip19.d.mts +2 -2
- package/dist/nips/nip19.mjs +16 -28
- package/dist/nips/nip19.mjs.map +1 -1
- package/dist/nips/nip21.d.mts +9 -4
- package/dist/nips/nip21.mjs +15 -5
- package/dist/nips/nip21.mjs.map +1 -1
- package/dist/nips/nip27.d.mts +22 -22
- package/dist/nips/nip27.mjs +2 -2
- package/dist/nips/nip27.mjs.map +1 -1
- package/dist/nips/nip42.d.mts +1 -1
- package/dist/nips/nip42.mjs +2 -1
- package/dist/nips/nip42.mjs.map +1 -1
- package/dist/nips/nip44.mjs +2 -2
- package/dist/nips/nip44.mjs.map +1 -1
- package/dist/nips/nip46.d.mts +2 -2
- package/dist/nips/nip46.mjs +15 -19
- package/dist/nips/nip46.mjs.map +1 -1
- package/dist/nips/nip49.d.mts +9 -9
- package/dist/nips/nip49.mjs +4 -4
- package/dist/nips/nip49.mjs.map +1 -1
- package/dist/nips/nip51.d.mts +2 -86
- package/dist/nips/nip51.mjs +7 -23
- package/dist/nips/nip51.mjs.map +1 -1
- package/dist/nips/nip57.d.mts +25 -23
- package/dist/nips/nip57.mjs +12 -17
- package/dist/nips/nip57.mjs.map +1 -1
- package/dist/nips/nip59.d.mts +1 -1
- package/dist/nips/nip59.mjs +27 -19
- package/dist/nips/nip59.mjs.map +1 -1
- package/dist/nips/nip65.d.mts +2 -2
- package/dist/nips/nip65.mjs +14 -37
- package/dist/nips/nip65.mjs.map +1 -1
- package/dist/nips/nip77.d.mts +1 -1
- package/dist/nips/nip77.mjs +33 -32
- package/dist/nips/nip77.mjs.map +1 -1
- package/dist/nips/nip98.d.mts +5 -5
- package/dist/nips/nip98.mjs +8 -8
- package/dist/nips/nip98.mjs.map +1 -1
- package/dist/{pool-DBIYMtwy.d.mts → pool-CqQvUnsq.d.mts} +132 -108
- package/dist/pool-vlw74C4t.mjs +606 -0
- package/dist/pool-vlw74C4t.mjs.map +1 -0
- package/dist/put-w13ci3sC.mjs +187 -0
- package/dist/put-w13ci3sC.mjs.map +1 -0
- package/dist/{reactive-BfhPp9a3.mjs → reactive-Tz0otDIP.mjs} +125 -88
- package/dist/reactive-Tz0otDIP.mjs.map +1 -0
- package/dist/{reactive-7aqeip4A.d.mts → reactive-gGqUrzW8.d.mts} +20 -26
- package/dist/relay-quCs7MHD.mjs +1811 -0
- package/dist/relay-quCs7MHD.mjs.map +1 -0
- package/dist/relay.d.mts +4 -4
- package/dist/relay.mjs +3 -2
- package/dist/serial-Bzpw-xz3.mjs +21 -0
- package/dist/serial-Bzpw-xz3.mjs.map +1 -0
- package/dist/{signer-CYQutDzD.mjs → signer-poTGe6Er.mjs} +12 -14
- package/dist/signer-poTGe6Er.mjs.map +1 -0
- package/dist/signer.d.mts +2 -2
- package/dist/signer.mjs +2 -2
- package/dist/{storage-Dky3wuoH.mjs → storage-B5IXTVuS.mjs} +28 -51
- package/dist/storage-B5IXTVuS.mjs.map +1 -0
- package/dist/storage.d.mts +3 -3
- package/dist/storage.mjs +4 -4
- package/dist/store.d.mts +2 -2
- package/dist/store.mjs +1 -1
- package/dist/testing.d.mts +19 -19
- package/dist/testing.mjs +9 -9
- package/dist/testing.mjs.map +1 -1
- package/dist/{types-2pCUprRU.d.mts → types-BacwnDtU.d.mts} +10 -10
- package/dist/{types-CRQEk0Oi.d.mts → types-DNmiscfd.d.mts} +2 -2
- package/dist/{util-LfQirgDk.mjs → util-DMF9AIO0.mjs} +33 -7
- package/dist/util-DMF9AIO0.mjs.map +1 -0
- package/dist/{verifier-t5WoWbtY.mjs → verifier-B51Wkt5H.mjs} +3 -3
- package/dist/verifier-B51Wkt5H.mjs.map +1 -0
- package/dist/verifier-CgTFpgsC.d.mts +22 -0
- package/dist/wasm.browser.d.mts +3 -3
- package/dist/wasm.browser.mjs +3 -3
- package/dist/wasm.d.mts +3 -3
- package/dist/wasm.mjs +3 -3
- package/dist/wasm.mjs.map +1 -1
- package/package.json +5 -9
- package/dist/abort-Ba8tDrOI.mjs.map +0 -1
- package/dist/builder-9tjI6WQ3.mjs.map +0 -1
- package/dist/client-CadO5fAX.mjs.map +0 -1
- package/dist/event-D8Nfoh4K.mjs.map +0 -1
- package/dist/gossip-oloDMWEj.mjs.map +0 -1
- package/dist/instance-DQE8BoWt.mjs.map +0 -1
- package/dist/key-Bps-LqX7.mjs.map +0 -1
- package/dist/loaders-o6YXB_Ri.mjs.map +0 -1
- package/dist/memory-C2EVx0_O.mjs.map +0 -1
- package/dist/memory-index-Do1mz0WF.mjs.map +0 -1
- package/dist/message-DcY6Fi9o.mjs +0 -193
- package/dist/message-DcY6Fi9o.mjs.map +0 -1
- package/dist/nip65-CjgmdpPB.d.mts +0 -26
- package/dist/nips/nip96.d.mts +0 -40
- package/dist/nips/nip96.mjs +0 -118
- package/dist/nips/nip96.mjs.map +0 -1
- package/dist/pool-As20OGxB.mjs +0 -2166
- package/dist/pool-As20OGxB.mjs.map +0 -1
- package/dist/reactive-BfhPp9a3.mjs.map +0 -1
- package/dist/signer-CYQutDzD.mjs.map +0 -1
- package/dist/storage-Dky3wuoH.mjs.map +0 -1
- package/dist/util-LfQirgDk.mjs.map +0 -1
- package/dist/verifier-t5WoWbtY.mjs.map +0 -1
package/dist/index.mjs
CHANGED
|
@@ -1,25 +1,27 @@
|
|
|
1
|
-
import { C as SUBSCRIPTION_ID_MAX_CHARS,
|
|
1
|
+
import { C as EVENT_ID_BYTES, D as SUBSCRIPTION_ID_MAX_CHARS, E as SIGNATURE_BYTES, T as SECRET_KEY_BYTES, _ as MessageError, a as hexToBytes, b as WasmPoisonedError, g as HexError, h as EventValidationError, i as bytesToHex, m as CryptoError, o as isHex32, s as isHex64, u as normalizeURL, v as NostrError, w as PUBLIC_KEY_BYTES, y as UrlError } from "./util-DMF9AIO0.mjs";
|
|
2
2
|
import { a as isRegularKind, i as isEphemeralKind, n as classifyKind, o as isReplaceableKind, r as isAddressableKind, t as Kind } from "./kind-Cxwhhkx8.mjs";
|
|
3
|
-
import {
|
|
4
|
-
import { a as publicKeyFromHex, i as getPublicKey, n as SecretKey, o as signEvent, r as finalizeEvent, t as Keys } from "./key-
|
|
5
|
-
import { n as verifyEvent, t as createEventVerifier } from "./verifier-
|
|
6
|
-
import { t as EventBuilder } from "./builder-
|
|
3
|
+
import { C as tagValue, S as tagName, a as isReplaceableWinner, b as isTag, d as sortEvents, f as sortedEvents, g as eventAddress, h as Tag, l as serializeEvent, m as validateSignedEvent, n as getEventHash, o as itemCompare, p as validateEvent, u as signedMatchesUnsigned, v as formatEventAddress, x as parseEventAddress, y as getDTag } from "./event-CHf47dPM.mjs";
|
|
4
|
+
import { a as publicKeyFromHex, i as getPublicKey, n as SecretKey, o as signEvent, r as finalizeEvent, s as toSecretKey, t as Keys } from "./key-DnVpchl6.mjs";
|
|
5
|
+
import { n as verifyEvent, t as createEventVerifier } from "./verifier-B51Wkt5H.mjs";
|
|
6
|
+
import { t as EventBuilder } from "./builder-aNU2gGFP.mjs";
|
|
7
7
|
import { a as matchFilter, i as getFilterLimit, n as canonicalizeFilters, o as matchFilters, r as filterFingerprint, s as mergeFilters, t as canonicalizeFilter } from "./filter-BQl3GlHt.mjs";
|
|
8
|
-
import { a as mergeCountHll, i as encodeRelayMessage, n as createSubscriptionId, o as parseClientMessage, r as encodeClientMessage, s as parseRelayMessage, t as assertSubscriptionId } from "./message-
|
|
9
|
-
import { t as NoSignerError } from "./error-
|
|
10
|
-
import { a as KeysSigner, i as isNip07Available, n as Nip07Signer, r as getWindowNostr, t as Nip46Signer } from "./signer-
|
|
11
|
-
import { Bech32MaxSize, Nip19Error, decode,
|
|
8
|
+
import { a as mergeCountHll, i as encodeRelayMessage, n as createSubscriptionId, o as parseClientMessage, r as encodeClientMessage, s as parseRelayMessage, t as assertSubscriptionId } from "./message-oNr7t0SJ.mjs";
|
|
9
|
+
import { t as NoSignerError } from "./error-DlhGW4mJ.mjs";
|
|
10
|
+
import { a as KeysSigner, i as isNip07Available, n as Nip07Signer, r as getWindowNostr, t as Nip46Signer } from "./signer-poTGe6Er.mjs";
|
|
11
|
+
import { Bech32MaxSize, Nip19Error, decode, naddrEncode, neventEncode, noteEncode, nprofileEncode, npubEncode, nsecEncode } from "./nips/nip19.mjs";
|
|
12
|
+
import { Nip21Error, isNostrURI, parseNostrURI } from "./nips/nip21.mjs";
|
|
12
13
|
import { buildReplyTags, parseThreadTags, replyTo } from "./nips/nip10.mjs";
|
|
13
14
|
import { isAuthRequired, makeAuthEvent } from "./nips/nip42.mjs";
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
15
|
+
import { parseRelayList, readRelays, relayListEventBuilder, relayListToTags, writeRelays } from "./nips/nip65.mjs";
|
|
16
|
+
import { c as RelayConnectionError, d as RelaySuspendedError, f as RelayTimeoutError, l as RelayError, n as Relay, o as useWebSocketImplementation, r as RelayStatus, s as RelayClosedError, u as RelayPublishError } from "./relay-quCs7MHD.mjs";
|
|
17
|
+
import { i as isInsecureRelayUrl, t as Pool } from "./pool-vlw74C4t.mjs";
|
|
16
18
|
import "./relay.mjs";
|
|
17
|
-
import { t as Gossip } from "./gossip-
|
|
18
|
-
import { a as
|
|
19
|
-
import { t as StorageError } from "./error-
|
|
20
|
-
import { t as MemoryEventStore } from "./memory-
|
|
21
|
-
import { t as ReactiveEventStore } from "./reactive-
|
|
22
|
-
import {
|
|
23
|
-
import { n as IndexedDbEventStore, t as SqliteEventStore } from "./storage-
|
|
19
|
+
import { t as Gossip } from "./gossip-DFxIBlsr.mjs";
|
|
20
|
+
import { a as bareNostrUser, i as groupAuthorsByOutboxRelay, n as OutboxError, r as OutboxFeed, t as createLoaders } from "./loaders-BmPkQfzI.mjs";
|
|
21
|
+
import { t as StorageError } from "./error-BILMe3Gr.mjs";
|
|
22
|
+
import { t as MemoryEventStore } from "./memory-CdJ07kub.mjs";
|
|
23
|
+
import { t as ReactiveEventStore } from "./reactive-Tz0otDIP.mjs";
|
|
24
|
+
import { n as ClientError, r as SyncDirection, t as Client } from "./client-Cj2lUaVh.mjs";
|
|
25
|
+
import { n as IndexedDbEventStore, t as SqliteEventStore } from "./storage-B5IXTVuS.mjs";
|
|
24
26
|
import "./store.mjs";
|
|
25
|
-
export { Bech32MaxSize, Client,
|
|
27
|
+
export { Bech32MaxSize, Client, ClientError, CryptoError, EVENT_ID_BYTES, EventBuilder, EventValidationError, Gossip, HexError, IndexedDbEventStore, Keys, KeysSigner, Kind, MemoryEventStore, MessageError, Nip07Signer, Nip19Error, Nip21Error, Nip46Signer, NoSignerError, NostrError, OutboxError, OutboxFeed, PUBLIC_KEY_BYTES, Pool, ReactiveEventStore, Relay, RelayClosedError, RelayConnectionError, RelayError, RelayPublishError, RelayStatus, RelaySuspendedError, RelayTimeoutError, SECRET_KEY_BYTES, SIGNATURE_BYTES, SUBSCRIPTION_ID_MAX_CHARS, SecretKey, SqliteEventStore, StorageError, SyncDirection, Tag, UrlError, WasmPoisonedError, assertSubscriptionId, bareNostrUser, buildReplyTags, bytesToHex, canonicalizeFilter, canonicalizeFilters, classifyKind, createEventVerifier, createLoaders, createSubscriptionId, encodeClientMessage, encodeRelayMessage, eventAddress, filterFingerprint, finalizeEvent, formatEventAddress, getDTag, getEventHash, getFilterLimit, getPublicKey, getWindowNostr, groupAuthorsByOutboxRelay, hexToBytes, isAddressableKind, isAuthRequired, isEphemeralKind, isHex32, isHex64, isInsecureRelayUrl, isNip07Available, isNostrURI, isRegularKind, isReplaceableKind, isReplaceableWinner, isTag, itemCompare, makeAuthEvent, matchFilter, matchFilters, mergeCountHll, mergeFilters, naddrEncode, neventEncode, decode as nip19Decode, normalizeURL, noteEncode, nprofileEncode, npubEncode, nsecEncode, parseClientMessage, parseEventAddress, parseNostrURI, parseRelayList, parseRelayMessage, parseThreadTags, publicKeyFromHex, readRelays, relayListEventBuilder, relayListToTags, replyTo, serializeEvent, signEvent, signedMatchesUnsigned, sortEvents, sortedEvents, tagName, tagValue, toSecretKey, useWebSocketImplementation, validateEvent, validateSignedEvent, verifyEvent, writeRelays };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as createEventVerifier } from "./verifier-
|
|
1
|
+
import { b as WasmPoisonedError, m as CryptoError } from "./util-DMF9AIO0.mjs";
|
|
2
|
+
import { t as createEventVerifier } from "./verifier-B51Wkt5H.mjs";
|
|
3
3
|
//#region src/wasm/abi.ts
|
|
4
4
|
/** Imports 0.2.122 may request. Instantiation fails if anything else appears. */
|
|
5
5
|
const ALLOWED_WASM_IMPORTS = [{
|
|
@@ -121,21 +121,32 @@ async function instantiateCryptoWasm(bytes) {
|
|
|
121
121
|
//#endregion
|
|
122
122
|
//#region src/wasm/adapter.ts
|
|
123
123
|
/**
|
|
124
|
+
* Run `fn` unless the instance is already poisoned; a `WebAssembly.RuntimeError` aborts the
|
|
125
|
+
* instance, so it is converted to {@link WasmPoisonedError} and rethrown on every later call.
|
|
126
|
+
*/
|
|
127
|
+
function runPoisoned(poison, fn) {
|
|
128
|
+
if (poison.error !== void 0) throw poison.error;
|
|
129
|
+
try {
|
|
130
|
+
return fn();
|
|
131
|
+
} catch (error) {
|
|
132
|
+
if (error instanceof WebAssembly.RuntimeError) {
|
|
133
|
+
poison.error = new WasmPoisonedError("wasm instance aborted", { cause: error });
|
|
134
|
+
throw poison.error;
|
|
135
|
+
}
|
|
136
|
+
throw error;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
124
140
|
* Build the WASM event verifier on {@link createEventVerifier}. A `WebAssembly.RuntimeError` from
|
|
125
141
|
* the module means the instance aborted — it poisons every later call with the same
|
|
126
|
-
* `
|
|
127
|
-
* failed).
|
|
142
|
+
* `WasmPoisonedError`; any other backend error verifies `false` (the event is marked failed).
|
|
128
143
|
*/
|
|
129
144
|
function createWasmEventVerifier(verifySerialized, poison) {
|
|
130
145
|
const backend = (serializedUtf8, id, pubkey, sig) => {
|
|
131
|
-
if (poison.error !== void 0) throw poison.error;
|
|
132
146
|
try {
|
|
133
|
-
return verifySerialized(serializedUtf8, id, pubkey, sig);
|
|
147
|
+
return runPoisoned(poison, () => verifySerialized(serializedUtf8, id, pubkey, sig));
|
|
134
148
|
} catch (error) {
|
|
135
|
-
if (error instanceof
|
|
136
|
-
poison.error = new WasmVerifyPoisonedError("wasm verify aborted the instance", { cause: error });
|
|
137
|
-
throw poison.error;
|
|
138
|
-
}
|
|
149
|
+
if (error instanceof WasmPoisonedError) throw error;
|
|
139
150
|
return false;
|
|
140
151
|
}
|
|
141
152
|
};
|
|
@@ -154,26 +165,14 @@ async function fetchWasmUrl(url) {
|
|
|
154
165
|
function requireByteLength(bytes, expected, label) {
|
|
155
166
|
if (bytes.length !== expected) throw new CryptoError(`invalid ${label} length: expected ${expected}, got ${bytes.length}`);
|
|
156
167
|
}
|
|
157
|
-
function wrapPoison(poison, fn) {
|
|
158
|
-
if (poison.error) throw poison.error;
|
|
159
|
-
try {
|
|
160
|
-
return fn();
|
|
161
|
-
} catch (error) {
|
|
162
|
-
if (error instanceof WebAssembly.RuntimeError) {
|
|
163
|
-
poison.error = new WasmVerifyPoisonedError("wasm verify aborted the instance", { cause: error });
|
|
164
|
-
throw poison.error;
|
|
165
|
-
}
|
|
166
|
-
throw error;
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
168
|
function bindExports(exports) {
|
|
170
169
|
const poison = {};
|
|
171
170
|
const rawSerialized = (serializedUtf8, id, pubkey, sig) => wasmVerifySerialized(exports, serializedUtf8, id, pubkey, sig);
|
|
172
171
|
return {
|
|
173
|
-
verify: (id, pubkey, sig) =>
|
|
174
|
-
verifySerialized: (serializedUtf8, id, pubkey, sig) =>
|
|
172
|
+
verify: (id, pubkey, sig) => runPoisoned(poison, () => wasmVerify(exports, id, pubkey, sig)),
|
|
173
|
+
verifySerialized: (serializedUtf8, id, pubkey, sig) => runPoisoned(poison, () => rawSerialized(serializedUtf8, id, pubkey, sig)),
|
|
175
174
|
verifyEvent: createWasmEventVerifier(rawSerialized, poison),
|
|
176
|
-
sign: (id, seckey, aux) =>
|
|
175
|
+
sign: (id, seckey, aux) => runPoisoned(poison, () => {
|
|
177
176
|
requireByteLength(id, 32, "id");
|
|
178
177
|
requireByteLength(seckey, 32, "secret key");
|
|
179
178
|
requireByteLength(aux, 32, "aux");
|
|
@@ -181,7 +180,7 @@ function bindExports(exports) {
|
|
|
181
180
|
if (sig.length !== 64) throw new CryptoError("wasm sign failed");
|
|
182
181
|
return sig;
|
|
183
182
|
}),
|
|
184
|
-
publicKey: (seckey) =>
|
|
183
|
+
publicKey: (seckey) => runPoisoned(poison, () => {
|
|
185
184
|
requireByteLength(seckey, 32, "secret key");
|
|
186
185
|
const pk = wasmPublicKey(exports, seckey);
|
|
187
186
|
if (pk.length !== 32) throw new CryptoError("wasm publicKey failed");
|
|
@@ -218,4 +217,4 @@ function createNostrWasmLoader(wasmBytes) {
|
|
|
218
217
|
//#endregion
|
|
219
218
|
export { fetchWasmUrl as n, isWasmBytes as r, createNostrWasmLoader as t };
|
|
220
219
|
|
|
221
|
-
//# sourceMappingURL=instance-
|
|
220
|
+
//# sourceMappingURL=instance-C62w3cEt.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instance-C62w3cEt.mjs","names":[],"sources":["../src/wasm/abi.ts","../src/wasm/adapter.ts","../src/wasm/instance.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 { WasmPoisonedError } from \"../core/error.ts\";\nimport { createEventVerifier } from \"../core/verifier.ts\";\nimport type { EventVerifier, SerializedEventVerifier } from \"../core/verifier.ts\";\n\nexport { WasmPoisonedError } from \"../core/error.ts\";\n\n/**\n * Run `fn` unless the instance is already poisoned; a `WebAssembly.RuntimeError` aborts the\n * instance, so it is converted to {@link WasmPoisonedError} and rethrown on every later call.\n */\nexport function runPoisoned<T>(poison: { error?: Error }, fn: () => T): T {\n if (poison.error !== undefined) {\n throw poison.error;\n }\n try {\n return fn();\n } catch (error) {\n if (error instanceof WebAssembly.RuntimeError) {\n poison.error = new WasmPoisonedError(\"wasm instance aborted\", {\n cause: error,\n });\n throw poison.error;\n }\n throw error;\n }\n}\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 * `WasmPoisonedError`; any other backend error verifies `false` (the event is marked failed).\n */\nexport function createWasmEventVerifier(\n verifySerialized: SerializedEventVerifier,\n poison: { error?: Error },\n): EventVerifier {\n const backend: SerializedEventVerifier = (serializedUtf8, id, pubkey, sig) => {\n try {\n return runPoisoned(poison, () => verifySerialized(serializedUtf8, id, pubkey, sig));\n } catch (error) {\n if (error instanceof WasmPoisonedError) {\n throw error;\n }\n return false;\n }\n };\n return createEventVerifier(backend);\n}\n","import { CryptoError } from \"../core/error.ts\";\nimport type { SigningBackend } from \"../core/key.ts\";\nimport type { EventVerifier } from \"../core/verifier.ts\";\nimport {\n instantiateCryptoWasm,\n wasmPublicKey,\n wasmSign,\n wasmVerify,\n wasmVerifySerialized,\n} from \"./abi.ts\";\nimport type { CryptoWasmExports } from \"./abi.ts\";\nimport { createWasmEventVerifier, runPoisoned } from \"./adapter.ts\";\n\nexport type LoadNostrWasmOptions = {\n /** Bytes, or a URL whose bytes will be read by the platform loader. */\n module?: ArrayBuffer | ArrayBufferView | URL | undefined;\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: EventVerifier;\n};\n\nexport function isWasmBytes(value: unknown): value is ArrayBuffer | ArrayBufferView {\n return value instanceof ArrayBuffer || ArrayBuffer.isView(value);\n}\n\nexport async function fetchWasmUrl(url: URL): Promise<Uint8Array> {\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\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 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) => runPoisoned(poison, () => wasmVerify(exports, id, pubkey, sig)),\n verifySerialized: (serializedUtf8, id, pubkey, sig) =>\n runPoisoned(poison, () => rawSerialized(serializedUtf8, id, pubkey, sig)),\n verifyEvent: createWasmEventVerifier(rawSerialized, poison),\n sign: (id, seckey, aux) =>\n runPoisoned(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 runPoisoned(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\n/** Builds a loader that interns a single instance per module slot. */\nexport function createNostrWasmLoader(\n wasmBytes: (opts?: LoadNostrWasmOptions) => Promise<ArrayBuffer | ArrayBufferView>,\n): {\n loadNostrWasm: (opts?: LoadNostrWasmOptions) => Promise<NostrWasm>;\n resetNostrWasm: () => void;\n} {\n let interned: Promise<NostrWasm> | undefined;\n\n async function instantiate(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. */\n async function loadNostrWasm(opts?: LoadNostrWasmOptions): Promise<NostrWasm> {\n if (interned) {\n return interned;\n }\n const pending = instantiate(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 function resetNostrWasm(): void {\n interned = undefined;\n }\n\n return { loadNostrWasm, resetNostrWasm };\n}\n"],"mappings":"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"}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { a as SigningBackend } from "./key-D_5OgGT7.mjs";
|
|
2
|
+
import { t as EventVerifier } from "./verifier-CgTFpgsC.mjs";
|
|
3
3
|
//#region src/wasm/instance.d.ts
|
|
4
4
|
type LoadNostrWasmOptions = {
|
|
5
5
|
/** Bytes, or a URL whose bytes will be read by the platform loader. */
|
|
6
|
-
module?: ArrayBuffer | ArrayBufferView | URL;
|
|
6
|
+
module?: ArrayBuffer | ArrayBufferView | URL | undefined;
|
|
7
7
|
};
|
|
8
8
|
type NostrWasm = SigningBackend & {
|
|
9
9
|
verify: (id: Uint8Array, pubkey: Uint8Array, sig: Uint8Array) => boolean;
|
|
10
10
|
verifySerialized: (serializedUtf8: Uint8Array, id: Uint8Array, pubkey: Uint8Array, sig: Uint8Array) => boolean;
|
|
11
|
-
verifyEvent:
|
|
11
|
+
verifyEvent: EventVerifier;
|
|
12
12
|
};
|
|
13
13
|
//#endregion
|
|
14
14
|
export { NostrWasm as n, LoadNostrWasmOptions as t };
|
|
15
|
-
//# sourceMappingURL=instance-
|
|
15
|
+
//# sourceMappingURL=instance-DjsL8h84.d.mts.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as EventTemplate, r as UnsignedEvent, t as Event } from "./event-
|
|
1
|
+
import { n as EventTemplate, r as UnsignedEvent, t as Event } from "./event-DJeb_DIL.mjs";
|
|
2
2
|
//#region src/core/key.d.ts
|
|
3
3
|
/** 32-byte secret key held as bytes; prefer zeroize when done. */
|
|
4
4
|
declare class SecretKey {
|
|
@@ -12,6 +12,10 @@ declare class SecretKey {
|
|
|
12
12
|
/** Best-effort wipe of the internal buffer. */
|
|
13
13
|
zeroize(): void;
|
|
14
14
|
}
|
|
15
|
+
/** Anything a secret key can be given as: instance, raw bytes, or hex. */
|
|
16
|
+
type SecretKeyInput = SecretKey | Uint8Array | string;
|
|
17
|
+
/** Coerce a {@link SecretKeyInput} to {@link SecretKey}. */
|
|
18
|
+
declare function toSecretKey(input: SecretKeyInput): SecretKey;
|
|
15
19
|
/** Lowercase hex-encoded secp256k1 public key (x-only, 64 chars). */
|
|
16
20
|
type PublicKey = string;
|
|
17
21
|
/** Validate and normalize a hex public key; throws {@link HexError} on bad input. */
|
|
@@ -26,7 +30,7 @@ type SigningBackend = {
|
|
|
26
30
|
sign: (id: Uint8Array, secretKey: Uint8Array, auxRand: Uint8Array) => Uint8Array;
|
|
27
31
|
};
|
|
28
32
|
/** Derive the public key for a secret key given as SecretKey, bytes, or hex. */
|
|
29
|
-
declare function getPublicKey(secretKey:
|
|
33
|
+
declare function getPublicKey(secretKey: SecretKeyInput): PublicKey;
|
|
30
34
|
/** Keypair convenience wrapper. */
|
|
31
35
|
declare class Keys {
|
|
32
36
|
readonly secretKey: SecretKey;
|
|
@@ -39,15 +43,15 @@ declare class Keys {
|
|
|
39
43
|
readonly backend: SigningBackend;
|
|
40
44
|
private constructor();
|
|
41
45
|
static generate(backend?: SigningBackend): Keys;
|
|
42
|
-
static fromSecretKey(secretKey:
|
|
46
|
+
static fromSecretKey(secretKey: SecretKeyInput, backend?: SigningBackend): Keys;
|
|
43
47
|
}
|
|
44
48
|
/** Fill pubkey/id/sig on a template and return a signed event. */
|
|
45
|
-
declare function finalizeEvent(template: EventTemplate, secretKey:
|
|
49
|
+
declare function finalizeEvent(template: EventTemplate, secretKey: SecretKeyInput | Keys): Event;
|
|
46
50
|
/**
|
|
47
51
|
* Sign an already-assembled unsigned event. Rejects when `unsigned.pubkey` does not match the
|
|
48
52
|
* secret key.
|
|
49
53
|
*/
|
|
50
|
-
declare function signEvent(unsigned: UnsignedEvent, secretKey:
|
|
54
|
+
declare function signEvent(unsigned: UnsignedEvent, secretKey: SecretKeyInput | Keys): Event;
|
|
51
55
|
//#endregion
|
|
52
|
-
export {
|
|
53
|
-
//# sourceMappingURL=key-
|
|
56
|
+
export { SigningBackend as a, publicKeyFromHex as c, SecretKeyInput as i, signEvent as l, PublicKey as n, finalizeEvent as o, SecretKey as r, getPublicKey as s, Keys as t, toSecretKey as u };
|
|
57
|
+
//# sourceMappingURL=key-D_5OgGT7.d.mts.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as hexToBytes$1,
|
|
2
|
-
import { c as markVerified, n as getEventHash, p as validateEvent } from "./event-
|
|
1
|
+
import { a as hexToBytes$1, h as EventValidationError, i as bytesToHex$1, m as CryptoError, n as assertHex32, r as assertSecretKeyBytes } from "./util-DMF9AIO0.mjs";
|
|
2
|
+
import { c as markVerified, n as getEventHash, p as validateEvent } from "./event-CHf47dPM.mjs";
|
|
3
3
|
import { randomBytes } from "@noble/hashes/utils.js";
|
|
4
4
|
import { schnorr } from "@noble/curves/secp256k1.js";
|
|
5
5
|
//#region src/core/key.ts
|
|
@@ -34,6 +34,12 @@ var SecretKey = class SecretKey {
|
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
36
|
};
|
|
37
|
+
/** Coerce a {@link SecretKeyInput} to {@link SecretKey}. */
|
|
38
|
+
function toSecretKey(input) {
|
|
39
|
+
if (input instanceof SecretKey) return input;
|
|
40
|
+
if (typeof input === "string") return SecretKey.fromHex(input);
|
|
41
|
+
return SecretKey.fromBytes(input);
|
|
42
|
+
}
|
|
37
43
|
/** Validate and normalize a hex public key; throws {@link HexError} on bad input. */
|
|
38
44
|
function publicKeyFromHex(hex) {
|
|
39
45
|
return assertHex32(hex, "public key");
|
|
@@ -44,8 +50,7 @@ const nobleSigning = {
|
|
|
44
50
|
};
|
|
45
51
|
/** Derive the public key for a secret key given as SecretKey, bytes, or hex. */
|
|
46
52
|
function getPublicKey(secretKey) {
|
|
47
|
-
|
|
48
|
-
return bytesToHex$1(schnorr.getPublicKey(bytes));
|
|
53
|
+
return bytesToHex$1(schnorr.getPublicKey(toSecretKey(secretKey).bytes));
|
|
49
54
|
}
|
|
50
55
|
/** Keypair convenience wrapper. */
|
|
51
56
|
var Keys = class Keys {
|
|
@@ -68,8 +73,7 @@ var Keys = class Keys {
|
|
|
68
73
|
return new Keys(SecretKey.generate(), backend);
|
|
69
74
|
}
|
|
70
75
|
static fromSecretKey(secretKey, backend = nobleSigning) {
|
|
71
|
-
|
|
72
|
-
return new Keys(sk, backend);
|
|
76
|
+
return new Keys(toSecretKey(secretKey), backend);
|
|
73
77
|
}
|
|
74
78
|
};
|
|
75
79
|
function resolveKeys(secretKey) {
|
|
@@ -92,7 +96,7 @@ function finalizeEvent(template, secretKey) {
|
|
|
92
96
|
*/
|
|
93
97
|
function signEvent(unsigned, secretKey) {
|
|
94
98
|
const keys = resolveKeys(secretKey);
|
|
95
|
-
if (!validateEvent(unsigned)) throw new
|
|
99
|
+
if (!validateEvent(unsigned)) throw new EventValidationError("cannot sign invalid unsigned event");
|
|
96
100
|
if (unsigned.pubkey !== keys.publicKey) throw new CryptoError("unsigned event pubkey does not match secret key");
|
|
97
101
|
const normalized = {
|
|
98
102
|
kind: unsigned.kind,
|
|
@@ -113,6 +117,6 @@ function signEvent(unsigned, secretKey) {
|
|
|
113
117
|
return event;
|
|
114
118
|
}
|
|
115
119
|
//#endregion
|
|
116
|
-
export { publicKeyFromHex as a, getPublicKey as i, SecretKey as n, signEvent as o, finalizeEvent as r, Keys as t };
|
|
120
|
+
export { publicKeyFromHex as a, getPublicKey as i, SecretKey as n, signEvent as o, finalizeEvent as r, toSecretKey as s, Keys as t };
|
|
117
121
|
|
|
118
|
-
//# sourceMappingURL=key-
|
|
122
|
+
//# sourceMappingURL=key-DnVpchl6.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"key-DnVpchl6.mjs","names":["hexToBytes","bytesToHex"],"sources":["../src/core/key.ts"],"sourcesContent":["import { schnorr } from \"@noble/curves/secp256k1.js\";\nimport { randomBytes } from \"@noble/hashes/utils.js\";\n\nimport { CryptoError, EventValidationError } from \"./error.ts\";\nimport { getEventHash, markVerified, validateEvent } from \"./event.ts\";\nimport type { Event, EventTemplate, UnsignedEvent } from \"./event.ts\";\nimport { assertHex32, assertSecretKeyBytes, bytesToHex, hexToBytes } from \"./util.ts\";\n\n/** 32-byte secret key held as bytes; prefer zeroize when done. */\nexport class SecretKey {\n #bytes: Uint8Array | undefined;\n\n private constructor(bytes: Uint8Array) {\n assertSecretKeyBytes(bytes);\n this.#bytes = new Uint8Array(bytes);\n }\n\n static generate(): SecretKey {\n return new SecretKey(schnorr.utils.randomSecretKey());\n }\n\n static fromBytes(bytes: Uint8Array): SecretKey {\n return new SecretKey(bytes);\n }\n\n static fromHex(hex: string): SecretKey {\n return new SecretKey(hexToBytes(assertHex32(hex, \"secret key\")));\n }\n\n get bytes(): Uint8Array {\n if (!this.#bytes) {\n throw new CryptoError(\"secret key has been zeroized\");\n }\n return new Uint8Array(this.#bytes);\n }\n\n toHex(): string {\n return bytesToHex(this.bytes);\n }\n\n /** Best-effort wipe of the internal buffer. */\n zeroize(): void {\n if (this.#bytes) {\n this.#bytes.fill(0);\n this.#bytes = undefined;\n }\n }\n}\n\n/** Anything a secret key can be given as: instance, raw bytes, or hex. */\nexport type SecretKeyInput = SecretKey | Uint8Array | string;\n\n/** Coerce a {@link SecretKeyInput} to {@link SecretKey}. */\nexport function toSecretKey(input: SecretKeyInput): SecretKey {\n if (input instanceof SecretKey) {\n return input;\n }\n if (typeof input === \"string\") {\n return SecretKey.fromHex(input);\n }\n return SecretKey.fromBytes(input);\n}\n\n/** Lowercase hex-encoded secp256k1 public key (x-only, 64 chars). */\nexport type PublicKey = string;\n\n/** Validate and normalize a hex public key; throws {@link HexError} on bad input. */\nexport function publicKeyFromHex(hex: string): PublicKey {\n return assertHex32(hex, \"public key\");\n}\n\n/**\n * BIP-340 signing backend. `publicKey` returns the 32-byte x-only public key of a 32-byte secret\n * key; `sign` returns the 64-byte BIP-340 signature of a 32-byte `id` using 32 bytes of auxiliary\n * randomness. Both throw on invalid input (for example an out-of-range secret key).\n */\nexport type SigningBackend = {\n publicKey: (secretKey: Uint8Array) => Uint8Array;\n sign: (id: Uint8Array, secretKey: Uint8Array, auxRand: Uint8Array) => Uint8Array;\n};\n\nconst nobleSigning: SigningBackend = {\n publicKey: (secretKey) => schnorr.getPublicKey(secretKey),\n sign: (id, secretKey, auxRand) => schnorr.sign(id, secretKey, auxRand),\n};\n\n/** Derive the public key for a secret key given as SecretKey, bytes, or hex. */\nexport function getPublicKey(secretKey: SecretKeyInput): PublicKey {\n return bytesToHex(schnorr.getPublicKey(toSecretKey(secretKey).bytes));\n}\n\n/** Keypair convenience wrapper. */\nexport class Keys {\n readonly secretKey: SecretKey;\n readonly publicKey: PublicKey;\n /**\n * BIP-340 backend that derived {@link publicKey} and signs in {@link finalizeEvent}/\n * {@link signEvent}. Defaults to noble; pass a loaded `NostrWasm` module or a native backend to\n * delegate signing.\n */\n readonly backend: SigningBackend;\n\n private constructor(secretKey: SecretKey, backend: SigningBackend) {\n this.secretKey = secretKey;\n this.backend = backend;\n const pubkey = backend.publicKey(secretKey.bytes);\n if (pubkey.length !== 32) {\n throw new CryptoError(\"signing backend returned an invalid public key\");\n }\n this.publicKey = bytesToHex(pubkey);\n }\n\n static generate(backend: SigningBackend = nobleSigning): Keys {\n return new Keys(SecretKey.generate(), backend);\n }\n\n static fromSecretKey(secretKey: SecretKeyInput, backend: SigningBackend = nobleSigning): Keys {\n return new Keys(toSecretKey(secretKey), backend);\n }\n}\n\nfunction resolveKeys(secretKey: SecretKeyInput | Keys): Keys {\n return secretKey instanceof Keys ? secretKey : Keys.fromSecretKey(secretKey);\n}\n\n/** Fill pubkey/id/sig on a template and return a signed event. */\nexport function finalizeEvent(template: EventTemplate, secretKey: SecretKeyInput | Keys): Event {\n const keys = resolveKeys(secretKey);\n const unsigned: UnsignedEvent = {\n kind: template.kind,\n tags: template.tags,\n content: template.content,\n created_at: template.created_at,\n pubkey: keys.publicKey,\n };\n return signEvent(unsigned, keys);\n}\n\n/**\n * Sign an already-assembled unsigned event. Rejects when `unsigned.pubkey` does not match the\n * secret key.\n */\nexport function signEvent(unsigned: UnsignedEvent, secretKey: SecretKeyInput | Keys): Event {\n const keys = resolveKeys(secretKey);\n if (!validateEvent(unsigned)) {\n throw new EventValidationError(\"cannot sign invalid unsigned event\");\n }\n\n if (unsigned.pubkey !== keys.publicKey) {\n throw new CryptoError(\"unsigned event pubkey does not match secret key\");\n }\n\n const normalized: UnsignedEvent = {\n kind: unsigned.kind,\n tags: unsigned.tags,\n content: unsigned.content,\n created_at: unsigned.created_at,\n pubkey: keys.publicKey,\n };\n\n const id = getEventHash(normalized);\n const sig = keys.backend.sign(hexToBytes(id), keys.secretKey.bytes, randomBytes(32));\n if (sig.length !== 64) {\n throw new CryptoError(\"signing backend returned an invalid signature\");\n }\n const event: Event = { ...normalized, id, sig: bytesToHex(sig) };\n markVerified(event);\n return event;\n}\n"],"mappings":"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"}
|
|
@@ -1,12 +1,16 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { c as isRecord, d as nowSeconds, l as normalizeRelayUrls, o as isHex32, v as NostrError } from "./util-DMF9AIO0.mjs";
|
|
2
2
|
import { r as isAddressableKind, t as Kind } from "./kind-Cxwhhkx8.mjs";
|
|
3
|
-
import {
|
|
3
|
+
import { f as sortedEvents, v as formatEventAddress } from "./event-CHf47dPM.mjs";
|
|
4
4
|
import { t as invokeSafely } from "./report-CHld4uWj.mjs";
|
|
5
5
|
import { Nip19Error, decode, npubEncode } from "./nips/nip19.mjs";
|
|
6
6
|
import { parseRelayList } from "./nips/nip65.mjs";
|
|
7
|
-
import
|
|
7
|
+
import "./relay-quCs7MHD.mjs";
|
|
8
|
+
import { i as throwIfAborted } from "./abort-DBq2STPj.mjs";
|
|
9
|
+
import { i as trimOldest, r as touchKey } from "./collections-DtwMc1NU.mjs";
|
|
8
10
|
import { parseDmRelayList } from "./nips/nip17.mjs";
|
|
9
|
-
import {
|
|
11
|
+
import { parseMuteList } from "./nips/nip51.mjs";
|
|
12
|
+
import { n as toStorageError } from "./error-BILMe3Gr.mjs";
|
|
13
|
+
import { r as outboxBoundKey } from "./put-w13ci3sC.mjs";
|
|
10
14
|
//#region src/loaders/context.ts
|
|
11
15
|
/** Internal dependency bag for loaders — never a module-level singleton. */
|
|
12
16
|
var LoaderContext = class {
|
|
@@ -37,7 +41,7 @@ var LoaderContext = class {
|
|
|
37
41
|
setRelays(urls) {
|
|
38
42
|
this.#relays = [...urls];
|
|
39
43
|
}
|
|
40
|
-
isFresh(fetchedAt, now =
|
|
44
|
+
isFresh(fetchedAt, now = nowSeconds()) {
|
|
41
45
|
return now - fetchedAt < this.staleAfterSec;
|
|
42
46
|
}
|
|
43
47
|
};
|
|
@@ -164,31 +168,16 @@ function createListLoaders(replaceable) {
|
|
|
164
168
|
},
|
|
165
169
|
async muteList(pubkey, opts) {
|
|
166
170
|
const { event, fresh } = await muteLoader(pubkey, opts);
|
|
171
|
+
let items = [];
|
|
172
|
+
if (event) try {
|
|
173
|
+
items = parseMuteList(event);
|
|
174
|
+
} catch {
|
|
175
|
+
items = [];
|
|
176
|
+
}
|
|
167
177
|
return {
|
|
168
178
|
event,
|
|
169
179
|
fresh,
|
|
170
|
-
items
|
|
171
|
-
if (tag[1] === void 0 || tag[1] === "") return;
|
|
172
|
-
switch (tag[0]) {
|
|
173
|
-
case "p": return isHex32(tag[1].toLowerCase()) ? {
|
|
174
|
-
label: "pubkey",
|
|
175
|
-
value: tag[1].toLowerCase()
|
|
176
|
-
} : void 0;
|
|
177
|
-
case "e": return isHex32(tag[1].toLowerCase()) ? {
|
|
178
|
-
label: "thread",
|
|
179
|
-
value: tag[1].toLowerCase()
|
|
180
|
-
} : void 0;
|
|
181
|
-
case "t": return {
|
|
182
|
-
label: "hashtag",
|
|
183
|
-
value: tag[1]
|
|
184
|
-
};
|
|
185
|
-
case "word": return {
|
|
186
|
-
label: "word",
|
|
187
|
-
value: tag[1]
|
|
188
|
-
};
|
|
189
|
-
default: return;
|
|
190
|
-
}
|
|
191
|
-
})
|
|
180
|
+
items
|
|
192
181
|
};
|
|
193
182
|
},
|
|
194
183
|
async relayList(pubkey, opts) {
|
|
@@ -199,16 +188,6 @@ function createListLoaders(replaceable) {
|
|
|
199
188
|
} catch {
|
|
200
189
|
items = [];
|
|
201
190
|
}
|
|
202
|
-
items = items.map((i) => {
|
|
203
|
-
try {
|
|
204
|
-
return {
|
|
205
|
-
...i,
|
|
206
|
-
url: normalizeURL(i.url)
|
|
207
|
-
};
|
|
208
|
-
} catch {
|
|
209
|
-
return i;
|
|
210
|
-
}
|
|
211
|
-
});
|
|
212
191
|
return {
|
|
213
192
|
event,
|
|
214
193
|
fresh,
|
|
@@ -255,11 +234,27 @@ function bareNostrUser(pubkey) {
|
|
|
255
234
|
function nonEmpty(value) {
|
|
256
235
|
return typeof value === "string" && value !== "" ? value : void 0;
|
|
257
236
|
}
|
|
237
|
+
const PROFILE_METADATA_KEYS = [
|
|
238
|
+
"name",
|
|
239
|
+
"display_name",
|
|
240
|
+
"about",
|
|
241
|
+
"picture",
|
|
242
|
+
"banner",
|
|
243
|
+
"website",
|
|
244
|
+
"nip05",
|
|
245
|
+
"lud06",
|
|
246
|
+
"lud16"
|
|
247
|
+
];
|
|
258
248
|
function parseMetadata(content) {
|
|
259
249
|
try {
|
|
260
250
|
const obj = JSON.parse(content);
|
|
261
|
-
if (
|
|
262
|
-
|
|
251
|
+
if (!isRecord(obj)) return {};
|
|
252
|
+
const out = {};
|
|
253
|
+
for (const key of PROFILE_METADATA_KEYS) {
|
|
254
|
+
const value = obj[key];
|
|
255
|
+
if (typeof value === "string") out[key] = value;
|
|
256
|
+
}
|
|
257
|
+
return out;
|
|
263
258
|
} catch {
|
|
264
259
|
return {};
|
|
265
260
|
}
|
|
@@ -390,16 +385,11 @@ const MAX_FETCHED_AT = 1e4;
|
|
|
390
385
|
function createReplaceableLoader(ctx, kind) {
|
|
391
386
|
const fetchedAt = /* @__PURE__ */ new Map();
|
|
392
387
|
const markFetched = (addr, hit, now) => {
|
|
393
|
-
fetchedAt
|
|
394
|
-
fetchedAt.set(addr, {
|
|
388
|
+
touchKey(fetchedAt, addr, {
|
|
395
389
|
at: now,
|
|
396
390
|
hit
|
|
397
391
|
});
|
|
398
|
-
|
|
399
|
-
const oldest = fetchedAt.keys().next().value;
|
|
400
|
-
if (oldest === void 0) break;
|
|
401
|
-
fetchedAt.delete(oldest);
|
|
402
|
-
}
|
|
392
|
+
trimOldest(fetchedAt, MAX_FETCHED_AT);
|
|
403
393
|
};
|
|
404
394
|
const loader = new DataLoader(async (keys) => {
|
|
405
395
|
const authors = [...new Set(keys.map((k) => k.pubkey))];
|
|
@@ -414,7 +404,7 @@ function createReplaceableLoader(ctx, kind) {
|
|
|
414
404
|
onevent: (event, relayUrl) => ctx.ingest(event, relayUrl)
|
|
415
405
|
});
|
|
416
406
|
}
|
|
417
|
-
const now =
|
|
407
|
+
const now = nowSeconds();
|
|
418
408
|
return keys.map((k) => {
|
|
419
409
|
const addr = formatEventAddress(kind, k.pubkey, "");
|
|
420
410
|
const event = ctx.index.getByAddress(addr);
|
|
@@ -458,18 +448,8 @@ function createReplaceableLoader(ctx, kind) {
|
|
|
458
448
|
var OutboxError = class extends NostrError {
|
|
459
449
|
name = "OutboxError";
|
|
460
450
|
};
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
}
|
|
464
|
-
/** Same skip/dedup as Gossip.setRoutes so prefer can match Client.relays. */
|
|
465
|
-
function canonicalRelayUrls(urls) {
|
|
466
|
-
const out = [];
|
|
467
|
-
for (const raw of urls) try {
|
|
468
|
-
const url = normalizeURL(raw);
|
|
469
|
-
if (!out.includes(url)) out.push(url);
|
|
470
|
-
} catch {}
|
|
471
|
-
return out;
|
|
472
|
-
}
|
|
451
|
+
/** Trailing-flush delay for live bound persistence: one write per dirty bound per window. */
|
|
452
|
+
const BOUND_FLUSH_MS = 1e3;
|
|
473
453
|
/**
|
|
474
454
|
* Group authors by outbox relay (discovery fallback). `prefer` reorders existing candidates only;
|
|
475
455
|
* it never appends a URL that is not already in the author's outbox or discovery list. Returns
|
|
@@ -477,8 +457,8 @@ function canonicalRelayUrls(urls) {
|
|
|
477
457
|
*/
|
|
478
458
|
function groupAuthorsByOutboxRelay(authors, gossip, discoveryRelays, maxRelaysPerAuthor = 3, prefer = []) {
|
|
479
459
|
const leftover = new Set((gossip.route({ authors: authors.map((a) => a.toLowerCase()) }).remainder?.authors ?? []).map((a) => a.toLowerCase()));
|
|
480
|
-
const preferSet = new Set(
|
|
481
|
-
const discovery =
|
|
460
|
+
const preferSet = new Set(normalizeRelayUrls(prefer));
|
|
461
|
+
const discovery = normalizeRelayUrls(discoveryRelays);
|
|
482
462
|
const map = /* @__PURE__ */ new Map();
|
|
483
463
|
for (const author of authors) {
|
|
484
464
|
const pk = author.toLowerCase();
|
|
@@ -513,6 +493,9 @@ var OutboxFeed = class {
|
|
|
513
493
|
#applySync;
|
|
514
494
|
#hydrate;
|
|
515
495
|
#bounds = /* @__PURE__ */ new Map();
|
|
496
|
+
/** Bound keys dirtied by live events since the last flush. */
|
|
497
|
+
#dirtyBounds = /* @__PURE__ */ new Set();
|
|
498
|
+
#boundTimer;
|
|
516
499
|
#authors;
|
|
517
500
|
#liveCloser;
|
|
518
501
|
#closed = false;
|
|
@@ -542,7 +525,7 @@ var OutboxFeed = class {
|
|
|
542
525
|
this.#authors = [...new Set(authors.map((a) => a.toLowerCase()))];
|
|
543
526
|
}
|
|
544
527
|
getBound(pubkey, kind) {
|
|
545
|
-
return this.#bounds.get(
|
|
528
|
+
return this.#bounds.get(outboxBoundKey(pubkey, kind));
|
|
546
529
|
}
|
|
547
530
|
/** Load NIP-65 relay lists for authors that have no outbox routes yet. */
|
|
548
531
|
async hydrate() {
|
|
@@ -585,7 +568,7 @@ var OutboxFeed = class {
|
|
|
585
568
|
const dirty = /* @__PURE__ */ new Set();
|
|
586
569
|
for (const event of applied) {
|
|
587
570
|
this.#updateBounds(event);
|
|
588
|
-
dirty.add(
|
|
571
|
+
dirty.add(outboxBoundKey(event.pubkey, event.kind));
|
|
589
572
|
invokeSafely(() => this.#onEvent?.(event));
|
|
590
573
|
}
|
|
591
574
|
await this.#persistBounds(dirty);
|
|
@@ -601,7 +584,7 @@ var OutboxFeed = class {
|
|
|
601
584
|
const byRelay = groupAuthorsByOutboxRelay(this.#authors, this.#gossip, this.#discovery, this.#maxRelays, this.#pool.connectedUrls());
|
|
602
585
|
const seen = /* @__PURE__ */ new Set();
|
|
603
586
|
const closers = [];
|
|
604
|
-
const since = opts?.since ??
|
|
587
|
+
const since = opts?.since ?? nowSeconds() - 60;
|
|
605
588
|
for (const [url, authors] of byRelay) {
|
|
606
589
|
const filter = {
|
|
607
590
|
authors,
|
|
@@ -641,13 +624,18 @@ var OutboxFeed = class {
|
|
|
641
624
|
this.#closed = true;
|
|
642
625
|
this.#liveCloser?.close("feed closed");
|
|
643
626
|
this.#liveCloser = void 0;
|
|
627
|
+
if (this.#boundTimer !== void 0) {
|
|
628
|
+
clearTimeout(this.#boundTimer);
|
|
629
|
+
this.#boundTimer = void 0;
|
|
630
|
+
}
|
|
631
|
+
this.#flushBounds();
|
|
644
632
|
}
|
|
645
633
|
#assertOpen() {
|
|
646
634
|
if (this.#closed) throw new OutboxError("OutboxFeed is closed");
|
|
647
635
|
}
|
|
648
636
|
async #hydrateBoundsFromStore() {
|
|
649
637
|
await Promise.all(this.#authors.flatMap((pk) => this.#kinds.map(async (kind) => {
|
|
650
|
-
const key =
|
|
638
|
+
const key = outboxBoundKey(pk, kind);
|
|
651
639
|
if (this.#bounds.has(key)) return;
|
|
652
640
|
const bound = await this.#storage.getOutboxBound(pk, kind);
|
|
653
641
|
if (!bound) return;
|
|
@@ -676,7 +664,7 @@ var OutboxFeed = class {
|
|
|
676
664
|
let newest;
|
|
677
665
|
let complete = true;
|
|
678
666
|
for (const kind of this.#kinds) {
|
|
679
|
-
const b = this.#bounds.get(
|
|
667
|
+
const b = this.#bounds.get(outboxBoundKey(pk, kind));
|
|
680
668
|
if (!b) {
|
|
681
669
|
complete = false;
|
|
682
670
|
break;
|
|
@@ -708,18 +696,25 @@ var OutboxFeed = class {
|
|
|
708
696
|
}
|
|
709
697
|
#noteEvent(event, relayUrl) {
|
|
710
698
|
this.#updateBounds(event);
|
|
711
|
-
const
|
|
712
|
-
if (
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
})();
|
|
699
|
+
const key = outboxBoundKey(event.pubkey, event.kind);
|
|
700
|
+
if (this.#bounds.has(key)) {
|
|
701
|
+
this.#dirtyBounds.add(key);
|
|
702
|
+
this.#boundTimer ??= setTimeout(() => {
|
|
703
|
+
this.#boundTimer = void 0;
|
|
704
|
+
this.#flushBounds();
|
|
705
|
+
}, BOUND_FLUSH_MS);
|
|
706
|
+
}
|
|
720
707
|
invokeSafely(() => this.#observe?.(event, relayUrl));
|
|
721
708
|
invokeSafely(() => this.#onEvent?.(event));
|
|
722
709
|
}
|
|
710
|
+
/** Persist all bounds dirtied since the last flush. Best-effort: errors are swallowed. */
|
|
711
|
+
async #flushBounds() {
|
|
712
|
+
const keys = [...this.#dirtyBounds];
|
|
713
|
+
this.#dirtyBounds.clear();
|
|
714
|
+
try {
|
|
715
|
+
await this.#persistBounds(keys);
|
|
716
|
+
} catch {}
|
|
717
|
+
}
|
|
723
718
|
async #persistBounds(keys) {
|
|
724
719
|
const writes = [];
|
|
725
720
|
for (const key of keys) {
|
|
@@ -739,7 +734,7 @@ var OutboxFeed = class {
|
|
|
739
734
|
}
|
|
740
735
|
}
|
|
741
736
|
#updateBounds(event) {
|
|
742
|
-
const key =
|
|
737
|
+
const key = outboxBoundKey(event.pubkey, event.kind);
|
|
743
738
|
const prev = this.#bounds.get(key);
|
|
744
739
|
if (!prev) {
|
|
745
740
|
this.#bounds.set(key, {
|
|
@@ -752,10 +747,6 @@ var OutboxFeed = class {
|
|
|
752
747
|
if (event.created_at > prev.newest) prev.newest = event.created_at;
|
|
753
748
|
}
|
|
754
749
|
};
|
|
755
|
-
/** Factory matching other loaders helpers. */
|
|
756
|
-
function createOutboxFeed(opts) {
|
|
757
|
-
return new OutboxFeed(opts);
|
|
758
|
-
}
|
|
759
750
|
//#endregion
|
|
760
751
|
//#region src/loaders/index.ts
|
|
761
752
|
/** Build an instance-scoped loader suite (no module globals). */
|
|
@@ -786,6 +777,6 @@ function createLoaders(opts) {
|
|
|
786
777
|
};
|
|
787
778
|
}
|
|
788
779
|
//#endregion
|
|
789
|
-
export {
|
|
780
|
+
export { bareNostrUser as a, groupAuthorsByOutboxRelay as i, OutboxError as n, OutboxFeed as r, createLoaders as t };
|
|
790
781
|
|
|
791
|
-
//# sourceMappingURL=loaders-
|
|
782
|
+
//# sourceMappingURL=loaders-BmPkQfzI.mjs.map
|