@qntx/nostr 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/README.md +16 -0
  2. package/dist/{builder-CyrGKRVP.mjs → builder-8VQ_Xr6X.mjs} +2 -2
  3. package/dist/{builder-CyrGKRVP.mjs.map → builder-8VQ_Xr6X.mjs.map} +1 -1
  4. package/dist/{builder-BWn55Paf.d.mts → builder-C9VuhbfY.d.mts} +2 -2
  5. package/dist/{client-BWsX9Cv1.mjs → client-BZMG37De.mjs} +21 -3
  6. package/dist/client-BZMG37De.mjs.map +1 -0
  7. package/dist/client.d.mts +1 -1
  8. package/dist/client.mjs +1 -1
  9. package/dist/core.d.mts +4 -4
  10. package/dist/core.mjs +4 -3
  11. package/dist/{gossip-BRQwIM_q.d.mts → gossip-ZnGOJ1fo.d.mts} +2 -2
  12. package/dist/gossip.d.mts +1 -1
  13. package/dist/{index-Ba7bJ7DD.d.mts → index-23sRP0wl.d.mts} +2 -2
  14. package/dist/{index-B425CAcQ.d.mts → index-CLGInxR5.d.mts} +17 -6
  15. package/dist/{index-Boe8FshM.d.mts → index-CvkvqB16.d.mts} +20 -2
  16. package/dist/{index-CUIvFQdE.d.mts → index-D-TK_KJG.d.mts} +14 -3
  17. package/dist/{index-BVyfUBuG.d.mts → index-D1bqFHKB.d.mts} +17 -10
  18. package/dist/{index-JdaS_uce.d.mts → index-Dj2TED7O.d.mts} +5 -5
  19. package/dist/index.d.mts +12 -12
  20. package/dist/index.mjs +7 -6
  21. package/dist/{key-Bbtys6o7.mjs → key-BZBap2p-.mjs} +3 -26
  22. package/dist/key-BZBap2p-.mjs.map +1 -0
  23. package/dist/{key-BlsYhN1V.d.mts → key-C6w9Fskk.d.mts} +2 -4
  24. package/dist/loaders.d.mts +1 -1
  25. package/dist/{nip17-DNEkz8rM.d.mts → nip17-jlcdeIQ8.d.mts} +2 -2
  26. package/dist/{nip65-DBfh2smt.d.mts → nip65-BlSAp_8P.d.mts} +2 -2
  27. package/dist/nips/blossom.d.mts +1 -1
  28. package/dist/nips/blossom.mjs +1 -1
  29. package/dist/nips/nip10.d.mts +1 -1
  30. package/dist/nips/nip10.mjs +1 -1
  31. package/dist/nips/nip17.d.mts +1 -1
  32. package/dist/nips/nip17.mjs +1 -1
  33. package/dist/nips/nip51.d.mts +1 -1
  34. package/dist/nips/nip51.mjs +1 -1
  35. package/dist/nips/nip57.mjs +1 -1
  36. package/dist/nips/nip57.mjs.map +1 -1
  37. package/dist/nips/nip59.mjs +2 -1
  38. package/dist/nips/nip59.mjs.map +1 -1
  39. package/dist/nips/nip65.d.mts +1 -1
  40. package/dist/nips/nip65.mjs +1 -1
  41. package/dist/nips/nip98.mjs +1 -1
  42. package/dist/nips/nip98.mjs.map +1 -1
  43. package/dist/{pool-tEr7c5bG.d.mts → pool-B7p_reAm.d.mts} +33 -2
  44. package/dist/{pool-XmAGaufS.mjs → pool-BGVx59yd.mjs} +104 -4
  45. package/dist/pool-BGVx59yd.mjs.map +1 -0
  46. package/dist/relay.d.mts +3 -3
  47. package/dist/relay.mjs +2 -2
  48. package/dist/{signer-CKR9EHce.mjs → signer-BGSpLC7e.mjs} +3 -2
  49. package/dist/signer-BGSpLC7e.mjs.map +1 -0
  50. package/dist/signer.d.mts +1 -1
  51. package/dist/signer.mjs +1 -1
  52. package/dist/storage-xXxLGCVb.mjs.map +1 -1
  53. package/dist/storage.d.mts +1 -1
  54. package/dist/testing.d.mts +10 -0
  55. package/dist/testing.mjs +9 -2
  56. package/dist/testing.mjs.map +1 -1
  57. package/dist/verifier-t5WoWbtY.mjs +38 -0
  58. package/dist/verifier-t5WoWbtY.mjs.map +1 -0
  59. package/dist/wasm.mjs +14 -21
  60. package/dist/wasm.mjs.map +1 -1
  61. package/package.json +65 -33
  62. package/dist/client-BWsX9Cv1.mjs.map +0 -1
  63. package/dist/key-Bbtys6o7.mjs.map +0 -1
  64. package/dist/pool-XmAGaufS.mjs.map +0 -1
  65. package/dist/signer-CKR9EHce.mjs.map +0 -1
@@ -1,9 +1,9 @@
1
1
  import { t as Event } from "./event-fU3Y01PR.mjs";
2
- import { n as ProfileMetadata } from "./builder-BWn55Paf.mjs";
3
- import { t as RelayListItem } from "./nip65-DBfh2smt.mjs";
4
- import { t as Gossip } from "./gossip-BRQwIM_q.mjs";
2
+ import { n as ProfileMetadata } from "./builder-C9VuhbfY.mjs";
3
+ import { t as RelayListItem } from "./nip65-BlSAp_8P.mjs";
4
+ import { t as Gossip } from "./gossip-ZnGOJ1fo.mjs";
5
5
  import { a as NostrError } from "./error-CR8Urc84.mjs";
6
- import { t as Pool } from "./pool-tEr7c5bG.mjs";
6
+ import { n as Pool } from "./pool-B7p_reAm.mjs";
7
7
  import { r as OutboxBound, t as EventStore } from "./types-2pCUprRU.mjs";
8
8
  import { t as ReactiveEventStore } from "./reactive-DFpqtIf_.mjs";
9
9
  import { i as EventPointer, t as AddressPointer } from "./nip19-BevCJZsp.mjs";
@@ -204,4 +204,4 @@ type CreateLoadersOptions = {
204
204
  declare function createLoaders(opts: CreateLoadersOptions): Loaders;
205
205
  //#endregion
206
206
  export { ReplaceableLoader as _, OutboxFeed as a, groupAuthorsByOutboxRelay as c, bareNostrUser as d, ListLoaders as f, ReplaceableLoadResult as g, LoadStyle as h, OutboxError as i, NostrUser as l, MutedEntity as m, Loaders as n, OutboxFeedOptions as o, ListResult as p, createLoaders as r, createOutboxFeed as s, CreateLoadersOptions as t, ProfileLoader as u, EventLoader as v, EventRef as y };
207
- //# sourceMappingURL=index-JdaS_uce.d.mts.map
207
+ //# sourceMappingURL=index-Dj2TED7O.d.mts.map
package/dist/index.d.mts CHANGED
@@ -1,24 +1,24 @@
1
1
  import { C as parseEventAddress, S as isTag, T as tagValue, _ as Tag, b as formatEventAddress, d as signedMatchesUnsigned, f as sortEvents, g as EventAddress, h as validateSignedEvent, i as getEventHash, m as validateEvent, n as EventTemplate, o as isReplaceableWinner, p as sortedEvents, r as UnsignedEvent, s as itemCompare, t as Event, u as serializeEvent, v as TagInput, w as tagName, x as getDTag, y as eventAddress } from "./event-fU3Y01PR.mjs";
2
- import { a as getPublicKey, c as verifyEvent, i as finalizeEvent, n as PublicKey, o as publicKeyFromHex, r as SecretKey, s as signEvent, t as Keys } from "./key-BlsYhN1V.mjs";
3
- import { n as ProfileMetadata, t as EventBuilder } from "./builder-BWn55Paf.mjs";
2
+ import { a as getPublicKey, i as finalizeEvent, n as PublicKey, o as publicKeyFromHex, r as SecretKey, s as signEvent, t as Keys } from "./key-C6w9Fskk.mjs";
3
+ import { n as ProfileMetadata, t as EventBuilder } from "./builder-C9VuhbfY.mjs";
4
4
  import { a as getFilterLimit, c as mergeFilters, i as filterFingerprint, n as canonicalizeFilter, o as matchFilter, r as canonicalizeFilters, s as matchFilters, t as Filter } from "./filter-C0IMByE3.mjs";
5
- import { a as readRelays, c as writeRelays, i as parseRelayList, n as RelayMarker, o as relayListEventBuilder, r as markerOf, s as relayListToTags, t as RelayListItem } from "./nip65-DBfh2smt.mjs";
6
- import { i as RoutedFilter, r as PubkeyRoutes, t as Gossip } from "./gossip-BRQwIM_q.mjs";
5
+ import { a as readRelays, c as writeRelays, i as parseRelayList, n as RelayMarker, o as relayListEventBuilder, r as markerOf, s as relayListToTags, t as RelayListItem } from "./nip65-BlSAp_8P.mjs";
6
+ import { i as RoutedFilter, r as PubkeyRoutes, t as Gossip } from "./gossip-ZnGOJ1fo.mjs";
7
7
  import { a as assertSubscriptionId, c as encodeRelayMessage, d as parseRelayMessage, i as SubscriptionId, l as mergeCountHll, n as CountResult, o as createSubscriptionId, r as RelayMessage, s as encodeClientMessage, t as ClientMessage, u as parseClientMessage } from "./message-iGPIqnn0.mjs";
8
8
  import { a as NostrError, i as MessageError, n as EventValidationError, o as UrlError, r as HexError, s as WasmVerifyPoisonedError, t as CryptoError } from "./error-CR8Urc84.mjs";
9
- import { a as PoolSubscribeOptions, c as RelayOptions, d as SubscribeOptions, i as PoolPublishResult, l as RelayStatus, n as PoolCountResult, o as PublishResult, r as PoolOptions, s as Relay, t as Pool, u as RelayStatusName } from "./pool-tEr7c5bG.mjs";
9
+ import { a as PoolPublishResult, c as Relay, d as RelayStatusName, f as SubscribeOptions, i as PoolOptions, l as RelayOptions, n as Pool, o as PoolSubscribeOptions, r as PoolCountResult, s as PublishResult, t as InvalidEventPolicy, u as RelayStatus } from "./pool-B7p_reAm.mjs";
10
10
  import { i as useWebSocketImplementation } from "./websocket-CmeqvAkp.mjs";
11
11
  import { i as PutResult, n as NegentropyItem, r as OutboxBound, t as EventStore } from "./types-2pCUprRU.mjs";
12
12
  import { n as ReactiveEventStoreOptions, r as Watch, t as ReactiveEventStore } from "./reactive-DFpqtIf_.mjs";
13
13
  import { _ as neventEncode, a as NAddr, b as npubEncode, c as NPub, d as Note, f as ProfilePointer, g as naddrEncode, i as EventPointer, l as NSec, m as decodeNostrURI, n as Bech32MaxSize, o as NEvent, p as decode, r as DecodedResult, s as NProfile, t as AddressPointer, u as Nip19Error, v as noteEncode, x as nsecEncode, y as nprofileEncode } from "./nip19-BevCJZsp.mjs";
14
- import { _ as ReplaceableLoader, a as OutboxFeed, c as groupAuthorsByOutboxRelay, d as bareNostrUser, g as ReplaceableLoadResult, h as LoadStyle, i as OutboxError, l as NostrUser, m as MutedEntity, n as Loaders, o as OutboxFeedOptions, p as ListResult, r as createLoaders, s as createOutboxFeed } from "./index-JdaS_uce.mjs";
14
+ import { _ as ReplaceableLoader, a as OutboxFeed, c as groupAuthorsByOutboxRelay, d as bareNostrUser, g as ReplaceableLoadResult, h as LoadStyle, i as OutboxError, l as NostrUser, m as MutedEntity, n as Loaders, o as OutboxFeedOptions, p as ListResult, r as createLoaders, s as createOutboxFeed } from "./index-Dj2TED7O.mjs";
15
15
  import { t as NostrSigner } from "./types-CRQEk0Oi.mjs";
16
16
  import { t as StorageError } from "./error-BW7re1UN.mjs";
17
- import { f as SubscribePrivateMessagesOptions, g as SyncSummary, h as SyncOptions, i as ClientOptions, l as ReceivedPrivateMessage, m as SyncDirectionName, n as ClientBuilder, o as FetchPrivateMessagesOptions, p as SyncDirection, r as ClientError, s as PrivateMessageSendResult, t as Client, u as SendPrivateMessageOptions } from "./index-B425CAcQ.mjs";
18
- import { _ as EVENT_ID_BYTES, a as classifyKind, b as SIGNATURE_BYTES, c as isRegularKind, f as bytesToHex, g as normalizeURL, h as isHex64, i as KnownKind, l as isReplaceableKind, m as isHex32, n as KindClassification, o as isAddressableKind, p as hexToBytes, r as KindName, s as isEphemeralKind, t as Kind, v as PUBLIC_KEY_BYTES, x as SUBSCRIPTION_ID_MAX_CHARS, y as SECRET_KEY_BYTES } from "./index-Boe8FshM.mjs";
19
- import { a as Nip07Signer, c as isNip07Available, i as Nip46Transport, l as KeysSigner, n as Nip46SignerOptions, o as WindowNostr, r as Nip46SubscribeOptions, s as getWindowNostr, t as Nip46Signer, u as NoSignerError } from "./index-Ba7bJ7DD.mjs";
17
+ import { f as SubscribePrivateMessagesOptions, g as SyncSummary, h as SyncOptions, i as ClientOptions, l as ReceivedPrivateMessage, m as SyncDirectionName, n as ClientBuilder, o as FetchPrivateMessagesOptions, p as SyncDirection, r as ClientError, s as PrivateMessageSendResult, t as Client, u as SendPrivateMessageOptions } from "./index-CLGInxR5.mjs";
18
+ import { C as SIGNATURE_BYTES, S as SECRET_KEY_BYTES, _ as isHex32, a as KindClassification, b as EVENT_ID_BYTES, c as classifyKind, d as isRegularKind, f as isReplaceableKind, g as hexToBytes, h as bytesToHex, i as Kind, l as isAddressableKind, n as createEventVerifier, o as KindName, r as verifyEvent, s as KnownKind, t as SerializedEventVerifier, u as isEphemeralKind, v as isHex64, w as SUBSCRIPTION_ID_MAX_CHARS, x as PUBLIC_KEY_BYTES, y as normalizeURL } from "./index-CvkvqB16.mjs";
19
+ import { a as Nip07Signer, c as isNip07Available, i as Nip46Transport, l as KeysSigner, n as Nip46SignerOptions, o as WindowNostr, r as Nip46SubscribeOptions, s as getWindowNostr, t as Nip46Signer, u as NoSignerError } from "./index-23sRP0wl.mjs";
20
20
  import { ReplyTagsOptions, ThreadReferences, buildReplyTags, parseThreadTags, replyTo } from "./nips/nip10.mjs";
21
21
  import { isAuthRequired, makeAuthEvent } from "./nips/nip42.mjs";
22
- import { a as isInsecureRelayUrl, c as RelayError, l as RelayPublishError, o as RelayClosedError, s as RelayConnectionError, u as RelayTimeoutError } from "./index-CUIvFQdE.mjs";
23
- import { a as IndexedDbEventStoreOptions, i as IndexedDbEventStore, n as SqlValue, o as MemoryEventStore, r as SqliteEventStore, t as SqlDriver } from "./index-BVyfUBuG.mjs";
24
- export { type AddressPointer, Bech32MaxSize, Client, ClientBuilder, ClientError, type ClientMessage, type ClientOptions, type CountResult, CryptoError, type DecodedResult, EVENT_ID_BYTES, type Event, type EventAddress, EventBuilder, type EventPointer, type EventStore, type EventTemplate, EventValidationError, type FetchPrivateMessagesOptions, type Filter, Gossip, HexError, IndexedDbEventStore, type IndexedDbEventStoreOptions, Keys, KeysSigner, Kind, type KindClassification, type KindName, type KnownKind, type ListResult, type LoadStyle, type Loaders, MemoryEventStore, MessageError, type MutedEntity, type NAddr, type NEvent, type NProfile, type NPub, type NSec, type NegentropyItem, Nip07Signer, Nip19Error, Nip46Signer, type Nip46SignerOptions, type Nip46SubscribeOptions, type Nip46Transport, NoSignerError, NostrError, type NostrSigner, type NostrUser, type Note, type OutboxBound, OutboxError, OutboxFeed, type OutboxFeedOptions, PUBLIC_KEY_BYTES, Pool, type PoolCountResult, type PoolOptions, type PoolPublishResult, type PoolSubscribeOptions, type PrivateMessageSendResult, type ProfileMetadata, type ProfilePointer, type PubkeyRoutes, type PublicKey, type PublishResult, type PutResult, ReactiveEventStore, type ReactiveEventStoreOptions, type ReceivedPrivateMessage, Relay, RelayClosedError, RelayConnectionError, RelayError, type RelayListItem, type RelayMarker, type RelayMessage, type RelayOptions, RelayPublishError, RelayStatus, type RelayStatusName, RelayTimeoutError, type ReplaceableLoadResult, type ReplaceableLoader, type ReplyTagsOptions, type RoutedFilter, SECRET_KEY_BYTES, SIGNATURE_BYTES, SUBSCRIPTION_ID_MAX_CHARS, SecretKey, type SendPrivateMessageOptions, type SqlDriver, type SqlValue, SqliteEventStore, StorageError, type SubscribeOptions, type SubscribePrivateMessagesOptions, type SubscriptionId, SyncDirection, type SyncDirectionName, type SyncOptions, type SyncSummary, Tag, type TagInput, type ThreadReferences, type UnsignedEvent, UrlError, WasmVerifyPoisonedError, type Watch, type WindowNostr, assertSubscriptionId, bareNostrUser, buildReplyTags, bytesToHex, canonicalizeFilter, canonicalizeFilters, classifyKind, createLoaders, createOutboxFeed, createSubscriptionId, decodeNostrURI, encodeClientMessage, encodeRelayMessage, eventAddress, filterFingerprint, finalizeEvent, formatEventAddress, getDTag, getEventHash, getFilterLimit, getPublicKey, getWindowNostr, groupAuthorsByOutboxRelay, hexToBytes, isAddressableKind, isAuthRequired, isEphemeralKind, isHex32, isHex64, isInsecureRelayUrl, isNip07Available, isRegularKind, isReplaceableKind, isReplaceableWinner, isTag, itemCompare, makeAuthEvent, markerOf, matchFilter, matchFilters, mergeCountHll, mergeFilters, naddrEncode, neventEncode, decode as nip19Decode, normalizeURL, noteEncode, nprofileEncode, npubEncode, nsecEncode, parseClientMessage, parseEventAddress, parseRelayList, parseRelayMessage, parseThreadTags, publicKeyFromHex, readRelays, relayListEventBuilder, relayListToTags, replyTo, serializeEvent, signEvent, signedMatchesUnsigned, sortEvents, sortedEvents, tagName, tagValue, useWebSocketImplementation, validateEvent, validateSignedEvent, verifyEvent, writeRelays };
22
+ import { a as isInsecureRelayUrl, c as RelayError, d as RelayTimeoutError, l as RelayPublishError, o as RelayClosedError, s as RelayConnectionError, u as RelaySuspendedError } from "./index-D-TK_KJG.mjs";
23
+ import { a as IndexedDbEventStoreOptions, i as IndexedDbEventStore, n as SqlValue, o as MemoryEventStore, r as SqliteEventStore, t as SqlDriver } from "./index-D1bqFHKB.mjs";
24
+ export { type AddressPointer, Bech32MaxSize, Client, ClientBuilder, ClientError, type ClientMessage, type ClientOptions, type CountResult, CryptoError, type DecodedResult, EVENT_ID_BYTES, type Event, type EventAddress, EventBuilder, type EventPointer, type EventStore, type EventTemplate, EventValidationError, type FetchPrivateMessagesOptions, type Filter, Gossip, HexError, IndexedDbEventStore, type IndexedDbEventStoreOptions, type InvalidEventPolicy, Keys, KeysSigner, Kind, type KindClassification, type KindName, type KnownKind, type ListResult, type LoadStyle, type Loaders, MemoryEventStore, MessageError, type MutedEntity, type NAddr, type NEvent, type NProfile, type NPub, type NSec, type NegentropyItem, Nip07Signer, Nip19Error, Nip46Signer, type Nip46SignerOptions, type Nip46SubscribeOptions, type Nip46Transport, NoSignerError, NostrError, type NostrSigner, type NostrUser, type Note, type OutboxBound, OutboxError, OutboxFeed, type OutboxFeedOptions, PUBLIC_KEY_BYTES, Pool, type PoolCountResult, type PoolOptions, type PoolPublishResult, type PoolSubscribeOptions, type PrivateMessageSendResult, type ProfileMetadata, type ProfilePointer, type PubkeyRoutes, type PublicKey, type PublishResult, type PutResult, ReactiveEventStore, type ReactiveEventStoreOptions, type ReceivedPrivateMessage, Relay, RelayClosedError, RelayConnectionError, RelayError, type RelayListItem, type RelayMarker, type RelayMessage, type RelayOptions, RelayPublishError, RelayStatus, type RelayStatusName, RelaySuspendedError, RelayTimeoutError, type ReplaceableLoadResult, type ReplaceableLoader, type ReplyTagsOptions, type RoutedFilter, SECRET_KEY_BYTES, SIGNATURE_BYTES, SUBSCRIPTION_ID_MAX_CHARS, SecretKey, type SendPrivateMessageOptions, type SerializedEventVerifier, type SqlDriver, type SqlValue, SqliteEventStore, StorageError, type SubscribeOptions, type SubscribePrivateMessagesOptions, type SubscriptionId, SyncDirection, type SyncDirectionName, type SyncOptions, type SyncSummary, Tag, type TagInput, type ThreadReferences, type UnsignedEvent, UrlError, WasmVerifyPoisonedError, type Watch, type WindowNostr, assertSubscriptionId, bareNostrUser, buildReplyTags, bytesToHex, canonicalizeFilter, canonicalizeFilters, classifyKind, createEventVerifier, createLoaders, createOutboxFeed, createSubscriptionId, decodeNostrURI, encodeClientMessage, encodeRelayMessage, eventAddress, filterFingerprint, finalizeEvent, formatEventAddress, getDTag, getEventHash, getFilterLimit, getPublicKey, getWindowNostr, groupAuthorsByOutboxRelay, hexToBytes, isAddressableKind, isAuthRequired, isEphemeralKind, isHex32, isHex64, isInsecureRelayUrl, isNip07Available, isRegularKind, isReplaceableKind, isReplaceableWinner, isTag, itemCompare, makeAuthEvent, markerOf, matchFilter, matchFilters, mergeCountHll, mergeFilters, naddrEncode, neventEncode, decode as nip19Decode, normalizeURL, noteEncode, nprofileEncode, npubEncode, nsecEncode, parseClientMessage, parseEventAddress, parseRelayList, parseRelayMessage, parseThreadTags, publicKeyFromHex, readRelays, relayListEventBuilder, relayListToTags, replyTo, serializeEvent, signEvent, signedMatchesUnsigned, sortEvents, sortedEvents, tagName, tagValue, useWebSocketImplementation, validateEvent, validateSignedEvent, verifyEvent, writeRelays };
package/dist/index.mjs CHANGED
@@ -1,24 +1,25 @@
1
1
  import { C as SUBSCRIPTION_ID_MAX_CHARS, S as SIGNATURE_BYTES, _ as UrlError, a as hexToBytes, b as PUBLIC_KEY_BYTES, f as CryptoError, g as NostrError, h as MessageError, i as bytesToHex, l as normalizeURL, m as HexError, o as isHex32, p as EventValidationError, s as isHex64, v as WasmVerifyPoisonedError, x as SECRET_KEY_BYTES, y as EVENT_ID_BYTES } from "./util-LfQirgDk.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
3
  import { S as tagValue, _ as formatEventAddress, a as isReplaceableWinner, b as parseEventAddress, 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 getDTag, x as tagName, y as isTag } from "./event-D8Nfoh4K.mjs";
4
- import { a as publicKeyFromHex, i as getPublicKey, n as SecretKey, o as signEvent, r as finalizeEvent, s as verifyEvent, t as Keys } from "./key-Bbtys6o7.mjs";
5
- import { t as EventBuilder } from "./builder-CyrGKRVP.mjs";
4
+ import { a as publicKeyFromHex, i as getPublicKey, n as SecretKey, o as signEvent, r as finalizeEvent, t as Keys } from "./key-BZBap2p-.mjs";
5
+ import { n as verifyEvent, t as createEventVerifier } from "./verifier-t5WoWbtY.mjs";
6
+ import { t as EventBuilder } from "./builder-8VQ_Xr6X.mjs";
6
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";
7
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-DcY6Fi9o.mjs";
8
9
  import { t as NoSignerError } from "./error-B__OMBRY.mjs";
9
- import { a as KeysSigner, i as isNip07Available, n as Nip07Signer, r as getWindowNostr, t as Nip46Signer } from "./signer-CKR9EHce.mjs";
10
+ import { a as KeysSigner, i as isNip07Available, n as Nip07Signer, r as getWindowNostr, t as Nip46Signer } from "./signer-BGSpLC7e.mjs";
10
11
  import { Bech32MaxSize, Nip19Error, decode, decodeNostrURI, naddrEncode, neventEncode, noteEncode, nprofileEncode, npubEncode, nsecEncode } from "./nips/nip19.mjs";
11
12
  import { buildReplyTags, parseThreadTags, replyTo } from "./nips/nip10.mjs";
12
13
  import { isAuthRequired, makeAuthEvent } from "./nips/nip42.mjs";
13
14
  import { markerOf, parseRelayList, readRelays, relayListEventBuilder, relayListToTags, writeRelays } from "./nips/nip65.mjs";
14
- import { a as RelayStatus, c as isInsecureRelayUrl, d as RelayClosedError, f as RelayConnectionError, h as RelayTimeoutError, i as Relay, m as RelayPublishError, p as RelayError, t as Pool, u as useWebSocketImplementation } from "./pool-XmAGaufS.mjs";
15
+ import { a as RelayStatus, c as isInsecureRelayUrl, d as RelayClosedError, f as RelayConnectionError, g as RelayTimeoutError, h as RelaySuspendedError, i as Relay, m as RelayPublishError, p as RelayError, t as Pool, u as useWebSocketImplementation } from "./pool-BGVx59yd.mjs";
15
16
  import "./relay.mjs";
16
17
  import { t as Gossip } from "./gossip-oloDMWEj.mjs";
17
18
  import { a as groupAuthorsByOutboxRelay, i as createOutboxFeed, n as OutboxError, o as bareNostrUser, r as OutboxFeed, t as createLoaders } from "./loaders-o6YXB_Ri.mjs";
18
19
  import { t as StorageError } from "./error-DrEIM7FO.mjs";
19
20
  import { t as MemoryEventStore } from "./memory-C2EVx0_O.mjs";
20
21
  import { t as ReactiveEventStore } from "./reactive-DDlThDSZ.mjs";
21
- import { i as ClientBuilder, n as ClientError, r as SyncDirection, t as Client } from "./client-BWsX9Cv1.mjs";
22
+ import { i as ClientBuilder, n as ClientError, r as SyncDirection, t as Client } from "./client-BZMG37De.mjs";
22
23
  import { n as IndexedDbEventStore, t as SqliteEventStore } from "./storage-xXxLGCVb.mjs";
23
24
  import "./store.mjs";
24
- export { Bech32MaxSize, Client, ClientBuilder, ClientError, CryptoError, EVENT_ID_BYTES, EventBuilder, EventValidationError, Gossip, HexError, IndexedDbEventStore, Keys, KeysSigner, Kind, MemoryEventStore, MessageError, Nip07Signer, Nip19Error, Nip46Signer, NoSignerError, NostrError, OutboxError, OutboxFeed, PUBLIC_KEY_BYTES, Pool, ReactiveEventStore, Relay, RelayClosedError, RelayConnectionError, RelayError, RelayPublishError, RelayStatus, RelayTimeoutError, SECRET_KEY_BYTES, SIGNATURE_BYTES, SUBSCRIPTION_ID_MAX_CHARS, SecretKey, SqliteEventStore, StorageError, SyncDirection, Tag, UrlError, WasmVerifyPoisonedError, assertSubscriptionId, bareNostrUser, buildReplyTags, bytesToHex, canonicalizeFilter, canonicalizeFilters, classifyKind, createLoaders, createOutboxFeed, createSubscriptionId, decodeNostrURI, encodeClientMessage, encodeRelayMessage, eventAddress, filterFingerprint, finalizeEvent, formatEventAddress, getDTag, getEventHash, getFilterLimit, getPublicKey, getWindowNostr, groupAuthorsByOutboxRelay, hexToBytes, isAddressableKind, isAuthRequired, isEphemeralKind, isHex32, isHex64, isInsecureRelayUrl, isNip07Available, isRegularKind, isReplaceableKind, isReplaceableWinner, isTag, itemCompare, makeAuthEvent, markerOf, matchFilter, matchFilters, mergeCountHll, mergeFilters, naddrEncode, neventEncode, decode as nip19Decode, normalizeURL, noteEncode, nprofileEncode, npubEncode, nsecEncode, parseClientMessage, parseEventAddress, parseRelayList, parseRelayMessage, parseThreadTags, publicKeyFromHex, readRelays, relayListEventBuilder, relayListToTags, replyTo, serializeEvent, signEvent, signedMatchesUnsigned, sortEvents, sortedEvents, tagName, tagValue, useWebSocketImplementation, validateEvent, validateSignedEvent, verifyEvent, writeRelays };
25
+ export { Bech32MaxSize, Client, ClientBuilder, ClientError, CryptoError, EVENT_ID_BYTES, EventBuilder, EventValidationError, Gossip, HexError, IndexedDbEventStore, Keys, KeysSigner, Kind, MemoryEventStore, MessageError, Nip07Signer, Nip19Error, 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, WasmVerifyPoisonedError, assertSubscriptionId, bareNostrUser, buildReplyTags, bytesToHex, canonicalizeFilter, canonicalizeFilters, classifyKind, createEventVerifier, createLoaders, createOutboxFeed, createSubscriptionId, decodeNostrURI, encodeClientMessage, encodeRelayMessage, eventAddress, filterFingerprint, finalizeEvent, formatEventAddress, getDTag, getEventHash, getFilterLimit, getPublicKey, getWindowNostr, groupAuthorsByOutboxRelay, hexToBytes, isAddressableKind, isAuthRequired, isEphemeralKind, isHex32, isHex64, isInsecureRelayUrl, isNip07Available, isRegularKind, isReplaceableKind, isReplaceableWinner, isTag, itemCompare, makeAuthEvent, markerOf, matchFilter, matchFilters, mergeCountHll, mergeFilters, naddrEncode, neventEncode, decode as nip19Decode, normalizeURL, noteEncode, nprofileEncode, npubEncode, nsecEncode, parseClientMessage, parseEventAddress, parseRelayList, parseRelayMessage, parseThreadTags, publicKeyFromHex, readRelays, relayListEventBuilder, relayListToTags, replyTo, serializeEvent, signEvent, signedMatchesUnsigned, sortEvents, sortedEvents, tagName, tagValue, useWebSocketImplementation, validateEvent, validateSignedEvent, verifyEvent, writeRelays };
@@ -1,5 +1,5 @@
1
1
  import { a as hexToBytes, f as CryptoError, i as bytesToHex, n as assertHex32, r as assertSecretKeyBytes } from "./util-LfQirgDk.mjs";
2
- import { c as markVerified, i as isMarkedVerified, m as validateSignedEvent, n as getEventHash, p as validateEvent, r as isMarkedFailed, s as markUnverified } from "./event-D8Nfoh4K.mjs";
2
+ import { c as markVerified, n as getEventHash, p as validateEvent } from "./event-D8Nfoh4K.mjs";
3
3
  import { schnorr } from "@noble/curves/secp256k1.js";
4
4
  //#region src/core/key.ts
5
5
  /** 32-byte secret key held as bytes; prefer zeroize when done. */
@@ -109,30 +109,7 @@ function signEvent(unsigned, secretKey) {
109
109
  markVerified(event);
110
110
  return event;
111
111
  }
112
- /** Verify event id and BIP-340 signature. Uses WeakSet cache (does not mutate the event). */
113
- function verifyEvent(event) {
114
- if (isMarkedVerified(event)) return true;
115
- if (isMarkedFailed(event)) return false;
116
- if (!validateSignedEvent(event)) {
117
- markUnverified(event);
118
- return false;
119
- }
120
- try {
121
- const hash = getEventHash(event);
122
- if (hash !== event.id) {
123
- markUnverified(event);
124
- return false;
125
- }
126
- const ok = schnorr.verify(hexToBytes(event.sig), hexToBytes(hash), hexToBytes(event.pubkey));
127
- if (ok) markVerified(event);
128
- else markUnverified(event);
129
- return ok;
130
- } catch {
131
- markUnverified(event);
132
- return false;
133
- }
134
- }
135
112
  //#endregion
136
- export { publicKeyFromHex as a, getPublicKey as i, SecretKey as n, signEvent as o, finalizeEvent as r, verifyEvent as s, Keys as t };
113
+ export { publicKeyFromHex as a, getPublicKey as i, SecretKey as n, signEvent as o, finalizeEvent as r, Keys as t };
137
114
 
138
- //# sourceMappingURL=key-Bbtys6o7.mjs.map
115
+ //# sourceMappingURL=key-BZBap2p-.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"key-BZBap2p-.mjs","names":[],"sources":["../src/core/key.ts"],"sourcesContent":["import { schnorr } from \"@noble/curves/secp256k1.js\";\n\nimport { CryptoError } 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/** 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/** Derive the public key for a secret key given as SecretKey, bytes, or hex. */\nexport function getPublicKey(secretKey: SecretKey | Uint8Array | string): PublicKey {\n const bytes =\n secretKey instanceof SecretKey\n ? secretKey.bytes\n : typeof secretKey === \"string\"\n ? hexToBytes(assertHex32(secretKey, \"secret key\"))\n : (assertSecretKeyBytes(secretKey), secretKey);\n return bytesToHex(schnorr.getPublicKey(bytes));\n}\n\n/** Keypair convenience wrapper. */\nexport class Keys {\n readonly secretKey: SecretKey;\n readonly publicKey: PublicKey;\n\n private constructor(secretKey: SecretKey) {\n this.secretKey = secretKey;\n this.publicKey = getPublicKey(secretKey);\n }\n\n static generate(): Keys {\n return new Keys(SecretKey.generate());\n }\n\n static fromSecretKey(secretKey: SecretKey | Uint8Array | string): Keys {\n const sk =\n secretKey instanceof SecretKey\n ? secretKey\n : typeof secretKey === \"string\"\n ? SecretKey.fromHex(secretKey)\n : SecretKey.fromBytes(secretKey);\n return new Keys(sk);\n }\n}\n\nfunction resolveSecretKeyBytes(secretKey: SecretKey | Uint8Array | string): Uint8Array {\n if (secretKey instanceof SecretKey) {\n return secretKey.bytes;\n }\n if (typeof secretKey === \"string\") {\n return hexToBytes(assertHex32(secretKey, \"secret key\"));\n }\n assertSecretKeyBytes(secretKey);\n return secretKey;\n}\n\nfunction resolveSigningKey(secretKey: SecretKey | Uint8Array | string | Keys): {\n bytes: Uint8Array;\n publicKey?: PublicKey;\n} {\n if (secretKey instanceof Keys) {\n return { bytes: secretKey.secretKey.bytes, publicKey: secretKey.publicKey };\n }\n return { bytes: resolveSecretKeyBytes(secretKey) };\n}\n\n/** Fill pubkey/id/sig on a template and return a signed event. */\nexport function finalizeEvent(\n template: EventTemplate,\n secretKey: SecretKey | Uint8Array | string | Keys,\n): Event {\n const { bytes: sk, publicKey } = resolveSigningKey(secretKey);\n const pubkey = publicKey ?? bytesToHex(schnorr.getPublicKey(sk));\n const unsigned: UnsignedEvent = {\n kind: template.kind,\n tags: template.tags,\n content: template.content,\n created_at: template.created_at,\n pubkey,\n };\n return signEvent(unsigned, sk);\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(\n unsigned: UnsignedEvent,\n secretKey: SecretKey | Uint8Array | string | Keys,\n): Event {\n const { bytes: sk, publicKey } = resolveSigningKey(secretKey);\n if (!validateEvent(unsigned)) {\n throw new CryptoError(\"cannot sign invalid unsigned event\");\n }\n\n const expected = publicKey ?? bytesToHex(schnorr.getPublicKey(sk));\n if (unsigned.pubkey !== expected) {\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: expected,\n };\n\n const id = getEventHash(normalized);\n const sig = bytesToHex(schnorr.sign(hexToBytes(id), sk));\n const event: Event = { ...normalized, id, sig };\n markVerified(event);\n return event;\n}\n"],"mappings":"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"}
@@ -33,8 +33,6 @@ declare function finalizeEvent(template: EventTemplate, secretKey: SecretKey | U
33
33
  * secret key.
34
34
  */
35
35
  declare function signEvent(unsigned: UnsignedEvent, secretKey: SecretKey | Uint8Array | string | Keys): Event;
36
- /** Verify event id and BIP-340 signature. Uses WeakSet cache (does not mutate the event). */
37
- declare function verifyEvent(event: Event): boolean;
38
36
  //#endregion
39
- export { getPublicKey as a, verifyEvent as c, finalizeEvent as i, PublicKey as n, publicKeyFromHex as o, SecretKey as r, signEvent as s, Keys as t };
40
- //# sourceMappingURL=key-BlsYhN1V.d.mts.map
37
+ export { getPublicKey as a, finalizeEvent as i, PublicKey as n, publicKeyFromHex as o, SecretKey as r, signEvent as s, Keys as t };
38
+ //# sourceMappingURL=key-C6w9Fskk.d.mts.map
@@ -1,3 +1,3 @@
1
1
  import { r as OutboxBound } from "./types-2pCUprRU.mjs";
2
- import { _ as ReplaceableLoader, a as OutboxFeed, c as groupAuthorsByOutboxRelay, d as bareNostrUser, f as ListLoaders, g as ReplaceableLoadResult, h as LoadStyle, i as OutboxError, l as NostrUser, m as MutedEntity, n as Loaders, o as OutboxFeedOptions, p as ListResult, r as createLoaders, s as createOutboxFeed, t as CreateLoadersOptions, u as ProfileLoader, v as EventLoader, y as EventRef } from "./index-JdaS_uce.mjs";
2
+ import { _ as ReplaceableLoader, a as OutboxFeed, c as groupAuthorsByOutboxRelay, d as bareNostrUser, f as ListLoaders, g as ReplaceableLoadResult, h as LoadStyle, i as OutboxError, l as NostrUser, m as MutedEntity, n as Loaders, o as OutboxFeedOptions, p as ListResult, r as createLoaders, s as createOutboxFeed, t as CreateLoadersOptions, u as ProfileLoader, v as EventLoader, y as EventRef } from "./index-Dj2TED7O.mjs";
3
3
  export { CreateLoadersOptions, type EventLoader, type EventRef, type ListLoaders, type ListResult, type LoadStyle, Loaders, type MutedEntity, type NostrUser, type OutboxBound, OutboxError, OutboxFeed, type OutboxFeedOptions, type ProfileLoader, type ReplaceableLoadResult, type ReplaceableLoader, bareNostrUser, createLoaders, createOutboxFeed, groupAuthorsByOutboxRelay };
@@ -1,5 +1,5 @@
1
1
  import { _ as Tag, t as Event } from "./event-fU3Y01PR.mjs";
2
- import { t as EventBuilder } from "./builder-BWn55Paf.mjs";
2
+ import { t as EventBuilder } from "./builder-C9VuhbfY.mjs";
3
3
  import { a as NostrError } from "./error-CR8Urc84.mjs";
4
4
  import { a as Rumor, l as WrapOptions, r as Nip59Crypto } from "./nip59-zQgdLcEr.mjs";
5
5
  //#region src/nips/nip17.d.ts
@@ -36,4 +36,4 @@ declare function wrapDirectMessage(crypto: Nip59Crypto, recipients: ReadonlyArra
36
36
  declare function requireDmRelays(pubkey: string, relays: ReadonlyArray<string>): string[];
37
37
  //#endregion
38
38
  export { buildChatMessageRumor as a, normalizeRecipients as c, wrapDirectMessage as d, ReplyTo as i, parseDmRelayList as l, Nip17Error as n, dmRelayListEventBuilder as o, Recipient as r, dmRelayListToTags as s, ChatMessageOptions as t, requireDmRelays as u };
39
- //# sourceMappingURL=nip17-DNEkz8rM.d.mts.map
39
+ //# sourceMappingURL=nip17-jlcdeIQ8.d.mts.map
@@ -1,5 +1,5 @@
1
1
  import { _ as Tag, t as Event } from "./event-fU3Y01PR.mjs";
2
- import { t as EventBuilder } from "./builder-BWn55Paf.mjs";
2
+ import { t as EventBuilder } from "./builder-C9VuhbfY.mjs";
3
3
  //#region src/nips/nip65.d.ts
4
4
  /** NIP-65 `r` tag marker: read-only, write-only, or unmarked (both). */
5
5
  type RelayMarker = "read" | "write" | "readwrite";
@@ -23,4 +23,4 @@ declare function readRelays(items: RelayListItem[]): string[];
23
23
  declare function writeRelays(items: RelayListItem[]): string[];
24
24
  //#endregion
25
25
  export { readRelays as a, writeRelays as c, parseRelayList as i, RelayMarker as n, relayListEventBuilder as o, markerOf as r, relayListToTags as s, RelayListItem as t };
26
- //# sourceMappingURL=nip65-DBfh2smt.d.mts.map
26
+ //# sourceMappingURL=nip65-BlSAp_8P.d.mts.map
@@ -1,5 +1,5 @@
1
1
  import { n as EventTemplate, t as Event } from "../event-fU3Y01PR.mjs";
2
- import { t as EventBuilder } from "../builder-BWn55Paf.mjs";
2
+ import { t as EventBuilder } from "../builder-C9VuhbfY.mjs";
3
3
  import { a as NostrError } from "../error-CR8Urc84.mjs";
4
4
  import { t as ManualFetch } from "../http-C4HwIu4B.mjs";
5
5
  //#region src/nips/blossom.d.ts
@@ -1,6 +1,6 @@
1
1
  import { c as isRecord, d as utf8Encoder, g as NostrError, i as bytesToHex, n as assertHex32, p as EventValidationError } from "../util-LfQirgDk.mjs";
2
2
  import { t as Kind } from "../kind-Cxwhhkx8.mjs";
3
- import { t as EventBuilder } from "../builder-CyrGKRVP.mjs";
3
+ import { t as EventBuilder } from "../builder-8VQ_Xr6X.mjs";
4
4
  import { n as requireGlobalFetch, r as sendManual, t as fetchManual } from "../http-CuazNRIP.mjs";
5
5
  import { sha256 } from "@noble/hashes/sha2.js";
6
6
  import { base64urlnopad } from "@scure/base";
@@ -1,5 +1,5 @@
1
1
  import { _ as Tag, t as Event } from "../event-fU3Y01PR.mjs";
2
- import { t as EventBuilder } from "../builder-BWn55Paf.mjs";
2
+ import { t as EventBuilder } from "../builder-C9VuhbfY.mjs";
3
3
  import { f as ProfilePointer, i as EventPointer, t as AddressPointer } from "../nip19-BevCJZsp.mjs";
4
4
  //#region src/nips/nip10.d.ts
5
5
  /** Parsed NIP-10 thread references from an event's `e`/`q`/`p` tags. */
@@ -1,7 +1,7 @@
1
1
  import { o as isHex32, p as EventValidationError } from "../util-LfQirgDk.mjs";
2
2
  import { t as Kind } from "../kind-Cxwhhkx8.mjs";
3
3
  import { _ as formatEventAddress, b as parseEventAddress, h as Tag } from "../event-D8Nfoh4K.mjs";
4
- import { t as EventBuilder } from "../builder-CyrGKRVP.mjs";
4
+ import { t as EventBuilder } from "../builder-8VQ_Xr6X.mjs";
5
5
  //#region src/nips/nip10.ts
6
6
  /**
7
7
  * NIP-10: Text Notes and Threads
@@ -1,2 +1,2 @@
1
- import { a as buildChatMessageRumor, c as normalizeRecipients, d as wrapDirectMessage, i as ReplyTo, l as parseDmRelayList, n as Nip17Error, o as dmRelayListEventBuilder, r as Recipient, s as dmRelayListToTags, t as ChatMessageOptions, u as requireDmRelays } from "../nip17-DNEkz8rM.mjs";
1
+ import { a as buildChatMessageRumor, c as normalizeRecipients, d as wrapDirectMessage, i as ReplyTo, l as parseDmRelayList, n as Nip17Error, o as dmRelayListEventBuilder, r as Recipient, s as dmRelayListToTags, t as ChatMessageOptions, u as requireDmRelays } from "../nip17-jlcdeIQ8.mjs";
2
2
  export { ChatMessageOptions, Nip17Error, Recipient, ReplyTo, buildChatMessageRumor, dmRelayListEventBuilder, dmRelayListToTags, normalizeRecipients, parseDmRelayList, requireDmRelays, wrapDirectMessage };
@@ -1,7 +1,7 @@
1
1
  import { g as NostrError, l as normalizeURL, n as assertHex32, p as EventValidationError } from "../util-LfQirgDk.mjs";
2
2
  import { t as Kind } from "../kind-Cxwhhkx8.mjs";
3
3
  import { h as Tag } from "../event-D8Nfoh4K.mjs";
4
- import { t as EventBuilder } from "../builder-CyrGKRVP.mjs";
4
+ import { t as EventBuilder } from "../builder-8VQ_Xr6X.mjs";
5
5
  import { createGiftWrap, createRumor, createSeal } from "./nip59.mjs";
6
6
  //#region src/nips/nip17.ts
7
7
  var Nip17Error = class extends NostrError {
@@ -1,5 +1,5 @@
1
1
  import { t as Event } from "../event-fU3Y01PR.mjs";
2
- import { t as EventBuilder } from "../builder-BWn55Paf.mjs";
2
+ import { t as EventBuilder } from "../builder-C9VuhbfY.mjs";
3
3
  //#region src/nips/nip51.d.ts
4
4
  /**
5
5
  * Structural crypto used by NIP-51 private tags. Satisfied by NostrSigner when
@@ -1,7 +1,7 @@
1
1
  import { l as normalizeURL, n as assertHex32, o as isHex32, p as EventValidationError } from "../util-LfQirgDk.mjs";
2
2
  import { t as Kind } from "../kind-Cxwhhkx8.mjs";
3
3
  import { h as Tag, v as getDTag, y as isTag } from "../event-D8Nfoh4K.mjs";
4
- import { t as EventBuilder } from "../builder-CyrGKRVP.mjs";
4
+ import { t as EventBuilder } from "../builder-8VQ_Xr6X.mjs";
5
5
  //#region src/nips/nip51.ts
6
6
  /**
7
7
  * NIP-51: Lists Public tags plus NIP-44 private `.content` (author encrypts to self). Crypto is
@@ -1,7 +1,7 @@
1
1
  import { a as hexToBytes, d as utf8Encoder, p as EventValidationError } from "../util-LfQirgDk.mjs";
2
2
  import { r as isAddressableKind, t as Kind } from "../kind-Cxwhhkx8.mjs";
3
3
  import { b as parseEventAddress, g as eventAddress, h as Tag, m as validateSignedEvent, v as getDTag } from "../event-D8Nfoh4K.mjs";
4
- import { s as verifyEvent } from "../key-Bbtys6o7.mjs";
4
+ import { n as verifyEvent } from "../verifier-t5WoWbtY.mjs";
5
5
  import { sha256 } from "@noble/hashes/sha2.js";
6
6
  import { bech32 } from "@scure/base";
7
7
  import { equalBytes } from "@noble/ciphers/utils.js";
@@ -1 +1 @@
1
- {"version":3,"file":"nip57.mjs","names":[],"sources":["../../src/nips/nip57.ts"],"sourcesContent":["/**\n * NIP-57 Lightning Zaps — zap request template (kind 9734) and receipt validation (kind 9735). Does\n * not fetch LNURL. Receipt checks never throw.\n *\n * @see https://github.com/nostr-protocol/nips/blob/master/57.md\n */\nimport { equalBytes } from \"@noble/ciphers/utils.js\";\nimport { sha256 } from \"@noble/hashes/sha2.js\";\nimport { bech32 } from \"@scure/base\";\n\nimport { EventValidationError } from \"../core/error.ts\";\nimport { validateSignedEvent } from \"../core/event.ts\";\nimport type { Event, EventTemplate } from \"../core/event.ts\";\nimport { verifyEvent } from \"../core/key.ts\";\nimport { isAddressableKind, Kind } from \"../core/kind.ts\";\nimport { eventAddress, getDTag, parseEventAddress, Tag } from \"../core/tag.ts\";\nimport { hexToBytes, utf8Encoder } from \"../core/util.ts\";\n\nexport type ProfileZapRequest = {\n pubkey: string;\n /** Amount in millisats. */\n amount: number;\n relays: ReadonlyArray<string>;\n comment?: string;\n lnurl?: string;\n};\n\nexport type EventZapRequest = {\n event: Event;\n /** Amount in millisats. */\n amount: number;\n relays: ReadonlyArray<string>;\n comment?: string;\n lnurl?: string;\n};\n\nexport function makeZapRequest(params: ProfileZapRequest | EventZapRequest): EventTemplate {\n if (params.relays.length === 0) {\n throw new EventValidationError(\"relays tag requires one or more URLs\");\n }\n\n const recipient = \"event\" in params ? params.event.pubkey : params.pubkey;\n const tags: Tag[] = [\n Tag.p(recipient),\n [\"amount\", params.amount.toString()],\n [\"relays\", ...params.relays],\n ];\n\n if (\"event\" in params) {\n const { event } = params;\n tags.push(Tag.e(event.id));\n if (isAddressableKind(event.kind)) {\n const d = getDTag(event.tags);\n if (d === undefined) {\n throw new EventValidationError(\"d tag not found\");\n }\n const addr = eventAddress(event);\n if (addr !== undefined) {\n tags.push([\"a\", addr]);\n }\n }\n tags.push([\"k\", event.kind.toString()]);\n }\n\n if (params.lnurl !== undefined && params.lnurl !== \"\") {\n tags.push([\"lnurl\", params.lnurl]);\n }\n\n return {\n kind: Kind.ZapRequest,\n created_at: Math.floor(Date.now() / 1000),\n content: params.comment ?? \"\",\n tags,\n };\n}\n\nexport type ZapReceiptContext = {\n nostrPubkey: string;\n lnurl?: string;\n};\n\nexport type ZapReceiptValidation = {\n valid: boolean;\n reason?: string;\n request?: Event;\n amountMsats?: number;\n};\n\nexport type Bolt11Fields = {\n amountMsats?: number;\n descriptionHash?: Uint8Array;\n paymentHash?: Uint8Array;\n};\n\nfunction firstTagValue(tags: ReadonlyArray<Tag>, name: string): string | undefined {\n for (const tag of tags) {\n if (tag[0] === name && tag[1] !== undefined) {\n return tag[1];\n }\n }\n return undefined;\n}\n\nfunction fail(reason: string): ZapReceiptValidation {\n return { valid: false, reason };\n}\n\nconst MSATS_PER_BTC = 100_000_000_000;\nconst MSATS_PER_MILLI = 100_000_000;\nconst MSATS_PER_MICRO = 100_000;\nconst MSATS_PER_NANO = 100;\n\n/** Amount is digits after `ln` + currency letters, optional m/u/n/p. Non-integer pico is omitted. */\nfunction amountMsatsFromHrp(hrp: string): number | undefined {\n if (!hrp.startsWith(\"ln\")) {\n return undefined;\n }\n let i = 2;\n while (i < hrp.length) {\n const c = hrp.codePointAt(i);\n if (c === undefined || c < 97 || c > 122) {\n break;\n }\n i++;\n }\n if (i === hrp.length) {\n return undefined;\n }\n const rest = hrp.slice(i);\n const m = /^([0-9]+)([munp])?$/.exec(rest);\n if (!m) {\n return undefined;\n }\n const n = Number(m[1]);\n if (!Number.isSafeInteger(n)) {\n return undefined;\n }\n const mul = m.at(2);\n if (mul === undefined) {\n return n * MSATS_PER_BTC;\n }\n if (mul === \"m\") {\n return n * MSATS_PER_MILLI;\n }\n if (mul === \"u\") {\n return n * MSATS_PER_MICRO;\n }\n if (mul === \"n\") {\n return n * MSATS_PER_NANO;\n }\n // p: 0.1 msat; drop amounts that are not whole millisats\n if (n % 10 !== 0) {\n return undefined;\n }\n return n / 10;\n}\n\nfunction parseMsatsTag(value: string): number | undefined {\n if (!/^[0-9]+$/.test(value)) {\n return undefined;\n }\n const n = Number(value);\n return Number.isSafeInteger(n) ? n : undefined;\n}\n\nfunction countTags(tags: ReadonlyArray<Tag>, name: string): number {\n let n = 0;\n for (const tag of tags) {\n if (tag[0] === name) {\n n++;\n }\n }\n return n;\n}\n\nfunction hasHexTagValue(tags: ReadonlyArray<Tag>, name: string, value: string): boolean {\n const needle = value.toLowerCase();\n for (const tag of tags) {\n if (tag[0] === name && tag[1] !== undefined && tag[1].toLowerCase() === needle) {\n return true;\n }\n }\n return false;\n}\n\nfunction hasAddressTag(tags: ReadonlyArray<Tag>, value: string): boolean {\n const want = parseEventAddress(value);\n if (!want) {\n return false;\n }\n for (const tag of tags) {\n if (tag[0] !== \"a\" || tag[1] === undefined) {\n continue;\n }\n const got = parseEventAddress(tag[1]);\n if (\n got &&\n got.kind === want.kind &&\n got.pubkey === want.pubkey &&\n got.identifier === want.identifier\n ) {\n return true;\n }\n }\n return false;\n}\n\nconst BOLT11_TIMESTAMP_WORDS = 7;\nconst BOLT11_SIGNATURE_WORDS = 104;\nconst BOLT11_HASH_WORDS = 52;\nconst HASH_BYTES = 32;\n\n/** Decode a BOLT11 invoice. Never throws. Requires a 32-byte payment hash (type 1). */\nexport function parseBolt11(pr: string): Bolt11Fields | undefined {\n try {\n // Invoices exceed bech32's default 90-char limit.\n const { prefix, words } = bech32.decode(pr.toLowerCase(), false);\n if (!prefix.startsWith(\"ln\")) {\n return undefined;\n }\n // timestamp (7) + tagged fields + secp256k1 signature (104)\n if (words.length < BOLT11_TIMESTAMP_WORDS + BOLT11_SIGNATURE_WORDS) {\n return undefined;\n }\n const fields: Bolt11Fields = {};\n const amountMsats = amountMsatsFromHrp(prefix);\n if (amountMsats !== undefined) {\n fields.amountMsats = amountMsats;\n }\n const tlvEnd = words.length - BOLT11_SIGNATURE_WORDS;\n let i = BOLT11_TIMESTAMP_WORDS;\n while (i + 3 <= tlvEnd) {\n const type = words[i];\n const lenHigh = words[i + 1];\n const lenLow = words[i + 2];\n if (type === undefined || lenHigh === undefined || lenLow === undefined) {\n break;\n }\n const dataLen = lenHigh * 32 + lenLow;\n i += 3;\n if (i + dataLen > tlvEnd) {\n break;\n }\n const data = words.slice(i, i + dataLen);\n i += dataLen;\n if ((type !== 1 && type !== 23) || dataLen !== BOLT11_HASH_WORDS) {\n continue;\n }\n const bytes = bech32.fromWordsUnsafe(data);\n if (!bytes || bytes.length !== HASH_BYTES) {\n continue;\n }\n if (type === 1) {\n fields.paymentHash ??= bytes;\n } else {\n fields.descriptionHash ??= bytes;\n }\n }\n if (!fields.paymentHash) {\n return undefined;\n }\n return fields;\n } catch {\n return undefined;\n }\n}\n\n/** Parse the `description` tag of a kind 9735 receipt as a signed kind 9734. Never throws. */\nexport function parseZapRequestFromReceipt(receipt: Event): Event | undefined {\n try {\n const raw = firstTagValue(receipt.tags, \"description\");\n if (raw === undefined) {\n return undefined;\n }\n const parsed: unknown = JSON.parse(raw);\n if (!validateSignedEvent(parsed) || parsed.kind !== Kind.ZapRequest) {\n return undefined;\n }\n if (!verifyEvent(parsed)) {\n return undefined;\n }\n return parsed;\n } catch {\n return undefined;\n }\n}\n\n/** Validate a kind 9735 zap receipt. Never throws. */\nexport function validateZapReceipt(receipt: Event, ctx: ZapReceiptContext): ZapReceiptValidation {\n try {\n if (receipt.kind !== Kind.Zap || !verifyEvent(receipt)) {\n return fail(\"invalid receipt\");\n }\n if (receipt.pubkey.toLowerCase() !== ctx.nostrPubkey.toLowerCase()) {\n return fail(\"pubkey mismatch\");\n }\n\n const descriptionRaw = firstTagValue(receipt.tags, \"description\");\n const request = parseZapRequestFromReceipt(receipt);\n if (descriptionRaw === undefined || !request) {\n return fail(\"invalid zap request\");\n }\n if (countTags(request.tags, \"p\") !== 1) {\n return fail(\"invalid p count\");\n }\n if (countTags(request.tags, \"e\") > 1) {\n return fail(\"too many e tags\");\n }\n const relaysValue = firstTagValue(request.tags, \"relays\");\n if (relaysValue === undefined || relaysValue === \"\") {\n return fail(\"missing relays\");\n }\n\n for (const tag of request.tags) {\n if (tag[0] !== \"a\") {\n continue;\n }\n if (tag[1] === undefined) {\n return fail(\"invalid a\");\n }\n const parsed = parseEventAddress(tag[1]);\n if (!parsed || !isAddressableKind(parsed.kind)) {\n return fail(\"invalid a\");\n }\n }\n\n // Request P is the LNURL provider (receipt pubkey), not the zap sender.\n const requestPCount = countTags(request.tags, \"P\");\n if (requestPCount > 1) {\n return fail(\"too many P tags\");\n }\n if (requestPCount === 1) {\n const requestP = firstTagValue(request.tags, \"P\");\n if (requestP === undefined || requestP.toLowerCase() !== receipt.pubkey.toLowerCase()) {\n return fail(\"request P mismatch\");\n }\n }\n\n const bolt11Tag = firstTagValue(receipt.tags, \"bolt11\");\n if (bolt11Tag === undefined) {\n return fail(\"missing bolt11\");\n }\n const bolt11 = parseBolt11(bolt11Tag);\n if (!bolt11 || !bolt11.descriptionHash) {\n return fail(\"invalid bolt11\");\n }\n\n const requestAmount = firstTagValue(request.tags, \"amount\");\n if (requestAmount !== undefined) {\n const msats = parseMsatsTag(requestAmount);\n if (msats === undefined || bolt11.amountMsats !== msats) {\n return fail(\"amount mismatch\");\n }\n }\n\n // Hash the tag payload, not JSON.stringify(parsed) (key order may differ).\n const digest = sha256(utf8Encoder.encode(descriptionRaw));\n if (!equalBytes(digest, bolt11.descriptionHash)) {\n return fail(\"description hash mismatch\");\n }\n\n const requestLnurl = firstTagValue(request.tags, \"lnurl\");\n if (\n requestLnurl !== undefined &&\n ctx.lnurl !== undefined &&\n requestLnurl.toLowerCase() !== ctx.lnurl.toLowerCase()\n ) {\n return fail(\"lnurl mismatch\");\n }\n\n const preimageHex = firstTagValue(receipt.tags, \"preimage\");\n if (preimageHex !== undefined && bolt11.paymentHash) {\n let preimage: Uint8Array;\n try {\n preimage = hexToBytes(preimageHex);\n } catch {\n return fail(\"preimage mismatch\");\n }\n if (!equalBytes(sha256(preimage), bolt11.paymentHash)) {\n return fail(\"preimage mismatch\");\n }\n }\n\n const recipient = firstTagValue(request.tags, \"p\");\n if (recipient === undefined || !hasHexTagValue(receipt.tags, \"p\", recipient)) {\n return fail(\"missing p\");\n }\n const requestE = firstTagValue(request.tags, \"e\");\n if (requestE !== undefined && !hasHexTagValue(receipt.tags, \"e\", requestE)) {\n return fail(\"missing e\");\n }\n for (const tag of request.tags) {\n if (tag[0] !== \"a\" || tag[1] === undefined) {\n continue;\n }\n if (!hasAddressTag(receipt.tags, tag[1])) {\n return fail(\"missing a\");\n }\n }\n\n // Receipt P is the zap sender (request pubkey). Do not copy request tag P.\n for (const tag of receipt.tags) {\n if (tag[0] !== \"P\") {\n continue;\n }\n if (tag[1] === undefined || tag[1].toLowerCase() !== request.pubkey.toLowerCase()) {\n return fail(\"receipt P mismatch\");\n }\n }\n\n const amountMsats =\n bolt11.amountMsats ??\n (requestAmount === undefined ? undefined : parseMsatsTag(requestAmount));\n return amountMsats === undefined\n ? { valid: true, request }\n : { valid: true, request, amountMsats };\n } catch {\n return fail(\"invalid receipt\");\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"nip57.mjs","names":[],"sources":["../../src/nips/nip57.ts"],"sourcesContent":["/**\n * NIP-57 Lightning Zaps — zap request template (kind 9734) and receipt validation (kind 9735). Does\n * not fetch LNURL. Receipt checks never throw.\n *\n * @see https://github.com/nostr-protocol/nips/blob/master/57.md\n */\nimport { equalBytes } from \"@noble/ciphers/utils.js\";\nimport { sha256 } from \"@noble/hashes/sha2.js\";\nimport { bech32 } from \"@scure/base\";\n\nimport { EventValidationError } from \"../core/error.ts\";\nimport { validateSignedEvent } from \"../core/event.ts\";\nimport type { Event, EventTemplate } from \"../core/event.ts\";\nimport { isAddressableKind, Kind } from \"../core/kind.ts\";\nimport { eventAddress, getDTag, parseEventAddress, Tag } from \"../core/tag.ts\";\nimport { hexToBytes, utf8Encoder } from \"../core/util.ts\";\nimport { verifyEvent } from \"../core/verifier.ts\";\n\nexport type ProfileZapRequest = {\n pubkey: string;\n /** Amount in millisats. */\n amount: number;\n relays: ReadonlyArray<string>;\n comment?: string;\n lnurl?: string;\n};\n\nexport type EventZapRequest = {\n event: Event;\n /** Amount in millisats. */\n amount: number;\n relays: ReadonlyArray<string>;\n comment?: string;\n lnurl?: string;\n};\n\nexport function makeZapRequest(params: ProfileZapRequest | EventZapRequest): EventTemplate {\n if (params.relays.length === 0) {\n throw new EventValidationError(\"relays tag requires one or more URLs\");\n }\n\n const recipient = \"event\" in params ? params.event.pubkey : params.pubkey;\n const tags: Tag[] = [\n Tag.p(recipient),\n [\"amount\", params.amount.toString()],\n [\"relays\", ...params.relays],\n ];\n\n if (\"event\" in params) {\n const { event } = params;\n tags.push(Tag.e(event.id));\n if (isAddressableKind(event.kind)) {\n const d = getDTag(event.tags);\n if (d === undefined) {\n throw new EventValidationError(\"d tag not found\");\n }\n const addr = eventAddress(event);\n if (addr !== undefined) {\n tags.push([\"a\", addr]);\n }\n }\n tags.push([\"k\", event.kind.toString()]);\n }\n\n if (params.lnurl !== undefined && params.lnurl !== \"\") {\n tags.push([\"lnurl\", params.lnurl]);\n }\n\n return {\n kind: Kind.ZapRequest,\n created_at: Math.floor(Date.now() / 1000),\n content: params.comment ?? \"\",\n tags,\n };\n}\n\nexport type ZapReceiptContext = {\n nostrPubkey: string;\n lnurl?: string;\n};\n\nexport type ZapReceiptValidation = {\n valid: boolean;\n reason?: string;\n request?: Event;\n amountMsats?: number;\n};\n\nexport type Bolt11Fields = {\n amountMsats?: number;\n descriptionHash?: Uint8Array;\n paymentHash?: Uint8Array;\n};\n\nfunction firstTagValue(tags: ReadonlyArray<Tag>, name: string): string | undefined {\n for (const tag of tags) {\n if (tag[0] === name && tag[1] !== undefined) {\n return tag[1];\n }\n }\n return undefined;\n}\n\nfunction fail(reason: string): ZapReceiptValidation {\n return { valid: false, reason };\n}\n\nconst MSATS_PER_BTC = 100_000_000_000;\nconst MSATS_PER_MILLI = 100_000_000;\nconst MSATS_PER_MICRO = 100_000;\nconst MSATS_PER_NANO = 100;\n\n/** Amount is digits after `ln` + currency letters, optional m/u/n/p. Non-integer pico is omitted. */\nfunction amountMsatsFromHrp(hrp: string): number | undefined {\n if (!hrp.startsWith(\"ln\")) {\n return undefined;\n }\n let i = 2;\n while (i < hrp.length) {\n const c = hrp.codePointAt(i);\n if (c === undefined || c < 97 || c > 122) {\n break;\n }\n i++;\n }\n if (i === hrp.length) {\n return undefined;\n }\n const rest = hrp.slice(i);\n const m = /^([0-9]+)([munp])?$/.exec(rest);\n if (!m) {\n return undefined;\n }\n const n = Number(m[1]);\n if (!Number.isSafeInteger(n)) {\n return undefined;\n }\n const mul = m.at(2);\n if (mul === undefined) {\n return n * MSATS_PER_BTC;\n }\n if (mul === \"m\") {\n return n * MSATS_PER_MILLI;\n }\n if (mul === \"u\") {\n return n * MSATS_PER_MICRO;\n }\n if (mul === \"n\") {\n return n * MSATS_PER_NANO;\n }\n // p: 0.1 msat; drop amounts that are not whole millisats\n if (n % 10 !== 0) {\n return undefined;\n }\n return n / 10;\n}\n\nfunction parseMsatsTag(value: string): number | undefined {\n if (!/^[0-9]+$/.test(value)) {\n return undefined;\n }\n const n = Number(value);\n return Number.isSafeInteger(n) ? n : undefined;\n}\n\nfunction countTags(tags: ReadonlyArray<Tag>, name: string): number {\n let n = 0;\n for (const tag of tags) {\n if (tag[0] === name) {\n n++;\n }\n }\n return n;\n}\n\nfunction hasHexTagValue(tags: ReadonlyArray<Tag>, name: string, value: string): boolean {\n const needle = value.toLowerCase();\n for (const tag of tags) {\n if (tag[0] === name && tag[1] !== undefined && tag[1].toLowerCase() === needle) {\n return true;\n }\n }\n return false;\n}\n\nfunction hasAddressTag(tags: ReadonlyArray<Tag>, value: string): boolean {\n const want = parseEventAddress(value);\n if (!want) {\n return false;\n }\n for (const tag of tags) {\n if (tag[0] !== \"a\" || tag[1] === undefined) {\n continue;\n }\n const got = parseEventAddress(tag[1]);\n if (\n got &&\n got.kind === want.kind &&\n got.pubkey === want.pubkey &&\n got.identifier === want.identifier\n ) {\n return true;\n }\n }\n return false;\n}\n\nconst BOLT11_TIMESTAMP_WORDS = 7;\nconst BOLT11_SIGNATURE_WORDS = 104;\nconst BOLT11_HASH_WORDS = 52;\nconst HASH_BYTES = 32;\n\n/** Decode a BOLT11 invoice. Never throws. Requires a 32-byte payment hash (type 1). */\nexport function parseBolt11(pr: string): Bolt11Fields | undefined {\n try {\n // Invoices exceed bech32's default 90-char limit.\n const { prefix, words } = bech32.decode(pr.toLowerCase(), false);\n if (!prefix.startsWith(\"ln\")) {\n return undefined;\n }\n // timestamp (7) + tagged fields + secp256k1 signature (104)\n if (words.length < BOLT11_TIMESTAMP_WORDS + BOLT11_SIGNATURE_WORDS) {\n return undefined;\n }\n const fields: Bolt11Fields = {};\n const amountMsats = amountMsatsFromHrp(prefix);\n if (amountMsats !== undefined) {\n fields.amountMsats = amountMsats;\n }\n const tlvEnd = words.length - BOLT11_SIGNATURE_WORDS;\n let i = BOLT11_TIMESTAMP_WORDS;\n while (i + 3 <= tlvEnd) {\n const type = words[i];\n const lenHigh = words[i + 1];\n const lenLow = words[i + 2];\n if (type === undefined || lenHigh === undefined || lenLow === undefined) {\n break;\n }\n const dataLen = lenHigh * 32 + lenLow;\n i += 3;\n if (i + dataLen > tlvEnd) {\n break;\n }\n const data = words.slice(i, i + dataLen);\n i += dataLen;\n if ((type !== 1 && type !== 23) || dataLen !== BOLT11_HASH_WORDS) {\n continue;\n }\n const bytes = bech32.fromWordsUnsafe(data);\n if (!bytes || bytes.length !== HASH_BYTES) {\n continue;\n }\n if (type === 1) {\n fields.paymentHash ??= bytes;\n } else {\n fields.descriptionHash ??= bytes;\n }\n }\n if (!fields.paymentHash) {\n return undefined;\n }\n return fields;\n } catch {\n return undefined;\n }\n}\n\n/** Parse the `description` tag of a kind 9735 receipt as a signed kind 9734. Never throws. */\nexport function parseZapRequestFromReceipt(receipt: Event): Event | undefined {\n try {\n const raw = firstTagValue(receipt.tags, \"description\");\n if (raw === undefined) {\n return undefined;\n }\n const parsed: unknown = JSON.parse(raw);\n if (!validateSignedEvent(parsed) || parsed.kind !== Kind.ZapRequest) {\n return undefined;\n }\n if (!verifyEvent(parsed)) {\n return undefined;\n }\n return parsed;\n } catch {\n return undefined;\n }\n}\n\n/** Validate a kind 9735 zap receipt. Never throws. */\nexport function validateZapReceipt(receipt: Event, ctx: ZapReceiptContext): ZapReceiptValidation {\n try {\n if (receipt.kind !== Kind.Zap || !verifyEvent(receipt)) {\n return fail(\"invalid receipt\");\n }\n if (receipt.pubkey.toLowerCase() !== ctx.nostrPubkey.toLowerCase()) {\n return fail(\"pubkey mismatch\");\n }\n\n const descriptionRaw = firstTagValue(receipt.tags, \"description\");\n const request = parseZapRequestFromReceipt(receipt);\n if (descriptionRaw === undefined || !request) {\n return fail(\"invalid zap request\");\n }\n if (countTags(request.tags, \"p\") !== 1) {\n return fail(\"invalid p count\");\n }\n if (countTags(request.tags, \"e\") > 1) {\n return fail(\"too many e tags\");\n }\n const relaysValue = firstTagValue(request.tags, \"relays\");\n if (relaysValue === undefined || relaysValue === \"\") {\n return fail(\"missing relays\");\n }\n\n for (const tag of request.tags) {\n if (tag[0] !== \"a\") {\n continue;\n }\n if (tag[1] === undefined) {\n return fail(\"invalid a\");\n }\n const parsed = parseEventAddress(tag[1]);\n if (!parsed || !isAddressableKind(parsed.kind)) {\n return fail(\"invalid a\");\n }\n }\n\n // Request P is the LNURL provider (receipt pubkey), not the zap sender.\n const requestPCount = countTags(request.tags, \"P\");\n if (requestPCount > 1) {\n return fail(\"too many P tags\");\n }\n if (requestPCount === 1) {\n const requestP = firstTagValue(request.tags, \"P\");\n if (requestP === undefined || requestP.toLowerCase() !== receipt.pubkey.toLowerCase()) {\n return fail(\"request P mismatch\");\n }\n }\n\n const bolt11Tag = firstTagValue(receipt.tags, \"bolt11\");\n if (bolt11Tag === undefined) {\n return fail(\"missing bolt11\");\n }\n const bolt11 = parseBolt11(bolt11Tag);\n if (!bolt11 || !bolt11.descriptionHash) {\n return fail(\"invalid bolt11\");\n }\n\n const requestAmount = firstTagValue(request.tags, \"amount\");\n if (requestAmount !== undefined) {\n const msats = parseMsatsTag(requestAmount);\n if (msats === undefined || bolt11.amountMsats !== msats) {\n return fail(\"amount mismatch\");\n }\n }\n\n // Hash the tag payload, not JSON.stringify(parsed) (key order may differ).\n const digest = sha256(utf8Encoder.encode(descriptionRaw));\n if (!equalBytes(digest, bolt11.descriptionHash)) {\n return fail(\"description hash mismatch\");\n }\n\n const requestLnurl = firstTagValue(request.tags, \"lnurl\");\n if (\n requestLnurl !== undefined &&\n ctx.lnurl !== undefined &&\n requestLnurl.toLowerCase() !== ctx.lnurl.toLowerCase()\n ) {\n return fail(\"lnurl mismatch\");\n }\n\n const preimageHex = firstTagValue(receipt.tags, \"preimage\");\n if (preimageHex !== undefined && bolt11.paymentHash) {\n let preimage: Uint8Array;\n try {\n preimage = hexToBytes(preimageHex);\n } catch {\n return fail(\"preimage mismatch\");\n }\n if (!equalBytes(sha256(preimage), bolt11.paymentHash)) {\n return fail(\"preimage mismatch\");\n }\n }\n\n const recipient = firstTagValue(request.tags, \"p\");\n if (recipient === undefined || !hasHexTagValue(receipt.tags, \"p\", recipient)) {\n return fail(\"missing p\");\n }\n const requestE = firstTagValue(request.tags, \"e\");\n if (requestE !== undefined && !hasHexTagValue(receipt.tags, \"e\", requestE)) {\n return fail(\"missing e\");\n }\n for (const tag of request.tags) {\n if (tag[0] !== \"a\" || tag[1] === undefined) {\n continue;\n }\n if (!hasAddressTag(receipt.tags, tag[1])) {\n return fail(\"missing a\");\n }\n }\n\n // Receipt P is the zap sender (request pubkey). Do not copy request tag P.\n for (const tag of receipt.tags) {\n if (tag[0] !== \"P\") {\n continue;\n }\n if (tag[1] === undefined || tag[1].toLowerCase() !== request.pubkey.toLowerCase()) {\n return fail(\"receipt P mismatch\");\n }\n }\n\n const amountMsats =\n bolt11.amountMsats ??\n (requestAmount === undefined ? undefined : parseMsatsTag(requestAmount));\n return amountMsats === undefined\n ? { valid: true, request }\n : { valid: true, request, amountMsats };\n } catch {\n return fail(\"invalid receipt\");\n }\n}\n"],"mappings":"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"}
@@ -1,7 +1,8 @@
1
1
  import { c as isRecord, g as NostrError, n as assertHex32 } from "../util-LfQirgDk.mjs";
2
2
  import { t as Kind } from "../kind-Cxwhhkx8.mjs";
3
3
  import { h as Tag, m as validateSignedEvent, n as getEventHash, p as validateEvent } from "../event-D8Nfoh4K.mjs";
4
- import { r as finalizeEvent, s as verifyEvent, t as Keys } from "../key-Bbtys6o7.mjs";
4
+ import { r as finalizeEvent, t as Keys } from "../key-BZBap2p-.mjs";
5
+ import { n as verifyEvent } from "../verifier-t5WoWbtY.mjs";
5
6
  import { encryptToPubkey } from "./nip44.mjs";
6
7
  import { randomBytes } from "@noble/hashes/utils.js";
7
8
  //#region src/nips/nip59.ts
@@ -1 +1 @@
1
- {"version":3,"file":"nip59.mjs","names":["TagBuilder"],"sources":["../../src/nips/nip59.ts"],"sourcesContent":["/**\n * NIP-59: Gift Wrap. Rumor → NIP-44 seal (kind 13) → gift wrap (kind 1059). Does not import signer,\n * relay, or client. Crypto is a structural type.\n *\n * @see https://github.com/nostr-protocol/nips/blob/master/59.md\n */\nimport { randomBytes } from \"@noble/hashes/utils.js\";\n\nimport { NostrError } from \"../core/error.ts\";\nimport type { Event, UnsignedEvent } from \"../core/event.ts\";\nimport { getEventHash, validateEvent, validateSignedEvent } from \"../core/event.ts\";\nimport { Keys, finalizeEvent, verifyEvent } from \"../core/key.ts\";\nimport { Kind } from \"../core/kind.ts\";\nimport type { Tag } from \"../core/tag.ts\";\nimport { Tag as TagBuilder } from \"../core/tag.ts\";\nimport { assertHex32, isRecord } from \"../core/util.ts\";\nimport { encryptToPubkey } from \"./nip44.ts\";\n\n/** Unsigned event with a computed id. Never has `sig`. */\nexport type Rumor = UnsignedEvent & {\n readonly id: string;\n};\n\n/**\n * Structural crypto used by NIP-59. Satisfied by NostrSigner when nip44Encrypt/nip44Decrypt are\n * present. This module must not import src/signer/.\n */\nexport type Nip59Crypto = {\n getPublicKey: () => Promise<string>;\n signEvent: (unsigned: UnsignedEvent) => Promise<Event>;\n nip44Encrypt: (peer: string, plaintext: string) => Promise<string>;\n nip44Decrypt: (peer: string, payload: string) => Promise<string>;\n};\n\nexport type Nip44Decryptor = {\n nip44Decrypt: (peer: string, payload: string) => Promise<string>;\n};\n\nexport type GiftWrapTimestamps = {\n readonly seal: number;\n readonly wrap: number;\n};\n\n/** `\"wrap\"` randomizes only the gift wrap; `\"seal+wrap\"` (default) randomizes both. */\nexport type TimestampRandomize = \"wrap\" | \"seal+wrap\";\n\nexport type WrapOptions = {\n /** Unix seconds used as the randomization window end. Default: floor(Date.now()/1000). */\n readonly now?: number | undefined;\n /** Uniform integer in [0, maxExclusive). Default: CSPRNG via @noble/hashes randomBytes. */\n readonly randomInt?: ((maxExclusive: number) => number) | undefined;\n /** When set, used as-is. Overrides now/randomInt for this call. */\n readonly timestamps?: GiftWrapTimestamps | undefined;\n readonly relayHint?: string | undefined;\n /** Appended after the required wrap `p` tag. Never applied to the seal. */\n readonly extraTags?: ReadonlyArray<Tag> | undefined;\n /**\n * Default `\"seal+wrap\"` (NIP-59). `\"wrap\"` = only wrap timestamp is randomized; seal uses\n * rumor.created_at.\n */\n readonly randomize?: TimestampRandomize | undefined;\n};\n\nexport type SealOptions = Pick<WrapOptions, \"now\" | \"randomInt\" | \"timestamps\" | \"randomize\">;\n\nexport class Nip59Error extends NostrError {\n override name = \"Nip59Error\";\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n }\n}\n\nexport const TWO_DAYS_SECS: number = 2 * 24 * 60 * 60;\n\nexport function isGiftWrapKind(kind: number): boolean {\n return kind === Kind.GiftWrap || kind === Kind.GiftWrapEphemeral;\n}\n\ntype Nip59CryptoInput = {\n getPublicKey: () => Promise<string>;\n signEvent: (unsigned: UnsignedEvent) => Promise<Event>;\n nip44Encrypt?: (peer: string, plaintext: string) => Promise<string>;\n nip44Decrypt?: (peer: string, payload: string) => Promise<string>;\n};\n\n/** Narrow a signer-shaped object to {@link Nip59Crypto}, or throw. */\nexport function requireNip59Crypto(crypto: Nip59CryptoInput): Nip59Crypto {\n const encrypt = crypto.nip44Encrypt;\n const decrypt = crypto.nip44Decrypt;\n if (!encrypt || !decrypt) {\n throw new Nip59Error(\"NIP-44 is required\");\n }\n return {\n getPublicKey: async () => crypto.getPublicKey(),\n signEvent: async (unsigned) => crypto.signEvent(unsigned),\n nip44Encrypt: async (peer, plaintext) => encrypt.call(crypto, peer, plaintext),\n nip44Decrypt: async (peer, payload) => decrypt.call(crypto, peer, payload),\n };\n}\n\nexport function requireNip44Decryptor(crypto: {\n nip44Decrypt?: (peer: string, payload: string) => Promise<string>;\n}): Nip44Decryptor {\n const decrypt = crypto.nip44Decrypt;\n if (!decrypt) {\n throw new Nip59Error(\"NIP-44 is required\");\n }\n return {\n nip44Decrypt: async (peer, payload) => decrypt.call(crypto, peer, payload),\n };\n}\n\nexport function rumorToJson(rumor: Rumor): string {\n return JSON.stringify({\n id: rumor.id,\n pubkey: rumor.pubkey,\n created_at: rumor.created_at,\n kind: rumor.kind,\n tags: rumor.tags,\n content: rumor.content,\n });\n}\n\nexport function eventToJson(event: Event): string {\n return JSON.stringify({\n id: event.id,\n pubkey: event.pubkey,\n created_at: event.created_at,\n kind: event.kind,\n tags: event.tags,\n content: event.content,\n sig: event.sig,\n });\n}\n\nfunction defaultRandomInt(maxExclusive: number): number {\n if (!Number.isSafeInteger(maxExclusive) || maxExclusive <= 0) {\n throw new Nip59Error(\"randomInt bound must be a positive integer\");\n }\n const bytes = randomBytes(4);\n const n = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength).getUint32(0);\n return n % maxExclusive;\n}\n\nexport function randomPastTimestamp(opts?: {\n now?: number | undefined;\n randomInt?: ((maxExclusive: number) => number) | undefined;\n}): number {\n const now = opts?.now ?? Math.floor(Date.now() / 1000);\n const offset = (opts?.randomInt ?? defaultRandomInt)(TWO_DAYS_SECS);\n return now - offset;\n}\n\nexport function createRumor(\n pubkey: string,\n template: {\n kind: number;\n content?: string | undefined;\n tags?: ReadonlyArray<Tag> | undefined;\n created_at?: number | undefined;\n },\n): Rumor {\n const unsigned: UnsignedEvent = {\n kind: template.kind,\n content: template.content ?? \"\",\n tags: template.tags ? [...template.tags] : [],\n created_at: template.created_at ?? Math.floor(Date.now() / 1000),\n pubkey: assertHex32(pubkey, \"public key\"),\n };\n return { ...unsigned, id: getEventHash(unsigned) };\n}\n\nexport async function createSeal(\n crypto: Nip59Crypto,\n recipient: string,\n rumor: Rumor,\n opts?: SealOptions,\n): Promise<Event> {\n const sealer = requireNip59Crypto(crypto);\n const recipientPk = assertHex32(recipient, \"public key\");\n let content: string;\n try {\n content = await sealer.nip44Encrypt(recipientPk, rumorToJson(rumor));\n } catch (error) {\n throw new Nip59Error(\"failed to encrypt\", { cause: error });\n }\n const created_at =\n opts?.timestamps?.seal ??\n (opts?.randomize === \"wrap\" ? rumor.created_at : randomPastTimestamp(opts));\n const pubkey = await sealer.getPublicKey();\n return sealer.signEvent({\n kind: Kind.Seal,\n content,\n created_at,\n tags: [],\n pubkey,\n });\n}\n\nexport function createGiftWrap(seal: Event, recipient: string, opts?: WrapOptions): Event {\n const recipientPk = assertHex32(recipient, \"public key\");\n const ephemeral = Keys.generate();\n const content = encryptToPubkey(eventToJson(seal), ephemeral.secretKey.bytes, recipientPk);\n const created_at = opts?.timestamps?.wrap ?? randomPastTimestamp(opts);\n const tags: Tag[] = [TagBuilder.p(recipientPk, opts?.relayHint), ...(opts?.extraTags ?? [])];\n return finalizeEvent(\n {\n kind: Kind.GiftWrap,\n content,\n created_at,\n tags,\n },\n ephemeral.secretKey,\n );\n}\n\nexport async function wrap(\n crypto: Nip59Crypto,\n recipient: string,\n rumor: Rumor,\n opts?: WrapOptions,\n): Promise<Event> {\n const seal = await createSeal(crypto, recipient, rumor, opts);\n return createGiftWrap(seal, recipient, opts);\n}\n\nfunction parseJson(text: string): unknown {\n try {\n return JSON.parse(text);\n } catch (error) {\n throw new Nip59Error(\"invalid JSON\", { cause: error });\n }\n}\n\nfunction parseRumor(value: unknown): Rumor {\n if (!isRecord(value)) {\n throw new Nip59Error(\"invalid rumor\");\n }\n if (Object.hasOwn(value, \"sig\")) {\n throw new Nip59Error(\"rumor must be unsigned\");\n }\n const givenId = value[\"id\"];\n if (!validateEvent(value)) {\n throw new Nip59Error(\"invalid rumor\");\n }\n const unsigned: UnsignedEvent = {\n kind: value.kind,\n tags: value.tags,\n content: value.content,\n created_at: value.created_at,\n pubkey: value.pubkey.toLowerCase(),\n };\n const expected = getEventHash(unsigned);\n if (typeof givenId === \"string\" && givenId.toLowerCase() !== expected) {\n throw new Nip59Error(\"invalid rumor\");\n }\n return { ...unsigned, id: expected };\n}\n\nasync function decryptLayer(\n crypto: Nip44Decryptor,\n peer: string,\n payload: string,\n): Promise<string> {\n try {\n return await crypto.nip44Decrypt(peer, payload);\n } catch (error) {\n throw new Nip59Error(\"failed to decrypt\", { cause: error });\n }\n}\n\nexport async function unwrap(crypto: Nip44Decryptor, giftWrap: Event): Promise<Rumor> {\n const decryptor = requireNip44Decryptor(crypto);\n if (!validateSignedEvent(giftWrap) || !isGiftWrapKind(giftWrap.kind)) {\n throw new Nip59Error(\"expected gift wrap\");\n }\n if (!verifyEvent(giftWrap)) {\n throw new Nip59Error(\"gift wrap signature\");\n }\n\n const sealJson = await decryptLayer(decryptor, giftWrap.pubkey, giftWrap.content);\n const sealRaw = parseJson(sealJson);\n if (!validateSignedEvent(sealRaw)) {\n throw new Nip59Error(\"expected seal\");\n }\n if (sealRaw.kind !== Kind.Seal) {\n throw new Nip59Error(\"expected seal\");\n }\n // NIP-17: seals may carry an [\"expiration\", <unix ts>] tag for disappearing messages.\n for (const tag of sealRaw.tags) {\n if (tag[0] !== \"expiration\" || typeof tag[1] !== \"string\" || !/^\\d+$/.test(tag[1])) {\n throw new Nip59Error(\"seal tags must be empty\");\n }\n }\n if (!verifyEvent(sealRaw)) {\n throw new Nip59Error(\"seal signature\");\n }\n\n const rumorJson = await decryptLayer(decryptor, sealRaw.pubkey, sealRaw.content);\n const rumor = parseRumor(parseJson(rumorJson));\n if (sealRaw.pubkey.toLowerCase() !== rumor.pubkey.toLowerCase()) {\n throw new Nip59Error(\"seal pubkey does not match rumor pubkey\");\n }\n return rumor;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"nip59.mjs","names":["TagBuilder"],"sources":["../../src/nips/nip59.ts"],"sourcesContent":["/**\n * NIP-59: Gift Wrap. Rumor → NIP-44 seal (kind 13) → gift wrap (kind 1059). Does not import signer,\n * relay, or client. Crypto is a structural type.\n *\n * @see https://github.com/nostr-protocol/nips/blob/master/59.md\n */\nimport { randomBytes } from \"@noble/hashes/utils.js\";\n\nimport { NostrError } from \"../core/error.ts\";\nimport type { Event, UnsignedEvent } from \"../core/event.ts\";\nimport { getEventHash, validateEvent, validateSignedEvent } from \"../core/event.ts\";\nimport { Keys, finalizeEvent } from \"../core/key.ts\";\nimport { Kind } from \"../core/kind.ts\";\nimport type { Tag } from \"../core/tag.ts\";\nimport { Tag as TagBuilder } from \"../core/tag.ts\";\nimport { assertHex32, isRecord } from \"../core/util.ts\";\nimport { verifyEvent } from \"../core/verifier.ts\";\nimport { encryptToPubkey } from \"./nip44.ts\";\n\n/** Unsigned event with a computed id. Never has `sig`. */\nexport type Rumor = UnsignedEvent & {\n readonly id: string;\n};\n\n/**\n * Structural crypto used by NIP-59. Satisfied by NostrSigner when nip44Encrypt/nip44Decrypt are\n * present. This module must not import src/signer/.\n */\nexport type Nip59Crypto = {\n getPublicKey: () => Promise<string>;\n signEvent: (unsigned: UnsignedEvent) => Promise<Event>;\n nip44Encrypt: (peer: string, plaintext: string) => Promise<string>;\n nip44Decrypt: (peer: string, payload: string) => Promise<string>;\n};\n\nexport type Nip44Decryptor = {\n nip44Decrypt: (peer: string, payload: string) => Promise<string>;\n};\n\nexport type GiftWrapTimestamps = {\n readonly seal: number;\n readonly wrap: number;\n};\n\n/** `\"wrap\"` randomizes only the gift wrap; `\"seal+wrap\"` (default) randomizes both. */\nexport type TimestampRandomize = \"wrap\" | \"seal+wrap\";\n\nexport type WrapOptions = {\n /** Unix seconds used as the randomization window end. Default: floor(Date.now()/1000). */\n readonly now?: number | undefined;\n /** Uniform integer in [0, maxExclusive). Default: CSPRNG via @noble/hashes randomBytes. */\n readonly randomInt?: ((maxExclusive: number) => number) | undefined;\n /** When set, used as-is. Overrides now/randomInt for this call. */\n readonly timestamps?: GiftWrapTimestamps | undefined;\n readonly relayHint?: string | undefined;\n /** Appended after the required wrap `p` tag. Never applied to the seal. */\n readonly extraTags?: ReadonlyArray<Tag> | undefined;\n /**\n * Default `\"seal+wrap\"` (NIP-59). `\"wrap\"` = only wrap timestamp is randomized; seal uses\n * rumor.created_at.\n */\n readonly randomize?: TimestampRandomize | undefined;\n};\n\nexport type SealOptions = Pick<WrapOptions, \"now\" | \"randomInt\" | \"timestamps\" | \"randomize\">;\n\nexport class Nip59Error extends NostrError {\n override name = \"Nip59Error\";\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n }\n}\n\nexport const TWO_DAYS_SECS: number = 2 * 24 * 60 * 60;\n\nexport function isGiftWrapKind(kind: number): boolean {\n return kind === Kind.GiftWrap || kind === Kind.GiftWrapEphemeral;\n}\n\ntype Nip59CryptoInput = {\n getPublicKey: () => Promise<string>;\n signEvent: (unsigned: UnsignedEvent) => Promise<Event>;\n nip44Encrypt?: (peer: string, plaintext: string) => Promise<string>;\n nip44Decrypt?: (peer: string, payload: string) => Promise<string>;\n};\n\n/** Narrow a signer-shaped object to {@link Nip59Crypto}, or throw. */\nexport function requireNip59Crypto(crypto: Nip59CryptoInput): Nip59Crypto {\n const encrypt = crypto.nip44Encrypt;\n const decrypt = crypto.nip44Decrypt;\n if (!encrypt || !decrypt) {\n throw new Nip59Error(\"NIP-44 is required\");\n }\n return {\n getPublicKey: async () => crypto.getPublicKey(),\n signEvent: async (unsigned) => crypto.signEvent(unsigned),\n nip44Encrypt: async (peer, plaintext) => encrypt.call(crypto, peer, plaintext),\n nip44Decrypt: async (peer, payload) => decrypt.call(crypto, peer, payload),\n };\n}\n\nexport function requireNip44Decryptor(crypto: {\n nip44Decrypt?: (peer: string, payload: string) => Promise<string>;\n}): Nip44Decryptor {\n const decrypt = crypto.nip44Decrypt;\n if (!decrypt) {\n throw new Nip59Error(\"NIP-44 is required\");\n }\n return {\n nip44Decrypt: async (peer, payload) => decrypt.call(crypto, peer, payload),\n };\n}\n\nexport function rumorToJson(rumor: Rumor): string {\n return JSON.stringify({\n id: rumor.id,\n pubkey: rumor.pubkey,\n created_at: rumor.created_at,\n kind: rumor.kind,\n tags: rumor.tags,\n content: rumor.content,\n });\n}\n\nexport function eventToJson(event: Event): string {\n return JSON.stringify({\n id: event.id,\n pubkey: event.pubkey,\n created_at: event.created_at,\n kind: event.kind,\n tags: event.tags,\n content: event.content,\n sig: event.sig,\n });\n}\n\nfunction defaultRandomInt(maxExclusive: number): number {\n if (!Number.isSafeInteger(maxExclusive) || maxExclusive <= 0) {\n throw new Nip59Error(\"randomInt bound must be a positive integer\");\n }\n const bytes = randomBytes(4);\n const n = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength).getUint32(0);\n return n % maxExclusive;\n}\n\nexport function randomPastTimestamp(opts?: {\n now?: number | undefined;\n randomInt?: ((maxExclusive: number) => number) | undefined;\n}): number {\n const now = opts?.now ?? Math.floor(Date.now() / 1000);\n const offset = (opts?.randomInt ?? defaultRandomInt)(TWO_DAYS_SECS);\n return now - offset;\n}\n\nexport function createRumor(\n pubkey: string,\n template: {\n kind: number;\n content?: string | undefined;\n tags?: ReadonlyArray<Tag> | undefined;\n created_at?: number | undefined;\n },\n): Rumor {\n const unsigned: UnsignedEvent = {\n kind: template.kind,\n content: template.content ?? \"\",\n tags: template.tags ? [...template.tags] : [],\n created_at: template.created_at ?? Math.floor(Date.now() / 1000),\n pubkey: assertHex32(pubkey, \"public key\"),\n };\n return { ...unsigned, id: getEventHash(unsigned) };\n}\n\nexport async function createSeal(\n crypto: Nip59Crypto,\n recipient: string,\n rumor: Rumor,\n opts?: SealOptions,\n): Promise<Event> {\n const sealer = requireNip59Crypto(crypto);\n const recipientPk = assertHex32(recipient, \"public key\");\n let content: string;\n try {\n content = await sealer.nip44Encrypt(recipientPk, rumorToJson(rumor));\n } catch (error) {\n throw new Nip59Error(\"failed to encrypt\", { cause: error });\n }\n const created_at =\n opts?.timestamps?.seal ??\n (opts?.randomize === \"wrap\" ? rumor.created_at : randomPastTimestamp(opts));\n const pubkey = await sealer.getPublicKey();\n return sealer.signEvent({\n kind: Kind.Seal,\n content,\n created_at,\n tags: [],\n pubkey,\n });\n}\n\nexport function createGiftWrap(seal: Event, recipient: string, opts?: WrapOptions): Event {\n const recipientPk = assertHex32(recipient, \"public key\");\n const ephemeral = Keys.generate();\n const content = encryptToPubkey(eventToJson(seal), ephemeral.secretKey.bytes, recipientPk);\n const created_at = opts?.timestamps?.wrap ?? randomPastTimestamp(opts);\n const tags: Tag[] = [TagBuilder.p(recipientPk, opts?.relayHint), ...(opts?.extraTags ?? [])];\n return finalizeEvent(\n {\n kind: Kind.GiftWrap,\n content,\n created_at,\n tags,\n },\n ephemeral.secretKey,\n );\n}\n\nexport async function wrap(\n crypto: Nip59Crypto,\n recipient: string,\n rumor: Rumor,\n opts?: WrapOptions,\n): Promise<Event> {\n const seal = await createSeal(crypto, recipient, rumor, opts);\n return createGiftWrap(seal, recipient, opts);\n}\n\nfunction parseJson(text: string): unknown {\n try {\n return JSON.parse(text);\n } catch (error) {\n throw new Nip59Error(\"invalid JSON\", { cause: error });\n }\n}\n\nfunction parseRumor(value: unknown): Rumor {\n if (!isRecord(value)) {\n throw new Nip59Error(\"invalid rumor\");\n }\n if (Object.hasOwn(value, \"sig\")) {\n throw new Nip59Error(\"rumor must be unsigned\");\n }\n const givenId = value[\"id\"];\n if (!validateEvent(value)) {\n throw new Nip59Error(\"invalid rumor\");\n }\n const unsigned: UnsignedEvent = {\n kind: value.kind,\n tags: value.tags,\n content: value.content,\n created_at: value.created_at,\n pubkey: value.pubkey.toLowerCase(),\n };\n const expected = getEventHash(unsigned);\n if (typeof givenId === \"string\" && givenId.toLowerCase() !== expected) {\n throw new Nip59Error(\"invalid rumor\");\n }\n return { ...unsigned, id: expected };\n}\n\nasync function decryptLayer(\n crypto: Nip44Decryptor,\n peer: string,\n payload: string,\n): Promise<string> {\n try {\n return await crypto.nip44Decrypt(peer, payload);\n } catch (error) {\n throw new Nip59Error(\"failed to decrypt\", { cause: error });\n }\n}\n\nexport async function unwrap(crypto: Nip44Decryptor, giftWrap: Event): Promise<Rumor> {\n const decryptor = requireNip44Decryptor(crypto);\n if (!validateSignedEvent(giftWrap) || !isGiftWrapKind(giftWrap.kind)) {\n throw new Nip59Error(\"expected gift wrap\");\n }\n if (!verifyEvent(giftWrap)) {\n throw new Nip59Error(\"gift wrap signature\");\n }\n\n const sealJson = await decryptLayer(decryptor, giftWrap.pubkey, giftWrap.content);\n const sealRaw = parseJson(sealJson);\n if (!validateSignedEvent(sealRaw)) {\n throw new Nip59Error(\"expected seal\");\n }\n if (sealRaw.kind !== Kind.Seal) {\n throw new Nip59Error(\"expected seal\");\n }\n // NIP-17: seals may carry an [\"expiration\", <unix ts>] tag for disappearing messages.\n for (const tag of sealRaw.tags) {\n if (tag[0] !== \"expiration\" || typeof tag[1] !== \"string\" || !/^\\d+$/.test(tag[1])) {\n throw new Nip59Error(\"seal tags must be empty\");\n }\n }\n if (!verifyEvent(sealRaw)) {\n throw new Nip59Error(\"seal signature\");\n }\n\n const rumorJson = await decryptLayer(decryptor, sealRaw.pubkey, sealRaw.content);\n const rumor = parseRumor(parseJson(rumorJson));\n if (sealRaw.pubkey.toLowerCase() !== rumor.pubkey.toLowerCase()) {\n throw new Nip59Error(\"seal pubkey does not match rumor pubkey\");\n }\n return rumor;\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import { a as readRelays, c as writeRelays, i as parseRelayList, n as RelayMarker, o as relayListEventBuilder, r as markerOf, s as relayListToTags, t as RelayListItem } from "../nip65-DBfh2smt.mjs";
1
+ import { a as readRelays, c as writeRelays, i as parseRelayList, n as RelayMarker, o as relayListEventBuilder, r as markerOf, s as relayListToTags, t as RelayListItem } from "../nip65-BlSAp_8P.mjs";
2
2
  export { RelayListItem, RelayMarker, markerOf, parseRelayList, readRelays, relayListEventBuilder, relayListToTags, writeRelays };
@@ -1,6 +1,6 @@
1
1
  import { l as normalizeURL, p as EventValidationError } from "../util-LfQirgDk.mjs";
2
2
  import { t as Kind } from "../kind-Cxwhhkx8.mjs";
3
- import { t as EventBuilder } from "../builder-CyrGKRVP.mjs";
3
+ import { t as EventBuilder } from "../builder-8VQ_Xr6X.mjs";
4
4
  //#region src/nips/nip65.ts
5
5
  /** The NIP-65 marker an item's read/write flags map to. */
6
6
  function markerOf(item) {
@@ -1,7 +1,7 @@
1
1
  import { d as utf8Encoder, g as NostrError, i as bytesToHex, u as utf8Decoder } from "../util-LfQirgDk.mjs";
2
2
  import { t as Kind } from "../kind-Cxwhhkx8.mjs";
3
3
  import { m as validateSignedEvent } from "../event-D8Nfoh4K.mjs";
4
- import { s as verifyEvent } from "../key-Bbtys6o7.mjs";
4
+ import { n as verifyEvent } from "../verifier-t5WoWbtY.mjs";
5
5
  import { sha256 } from "@noble/hashes/sha2.js";
6
6
  import { base64 } from "@scure/base";
7
7
  //#region src/nips/nip98.ts
@@ -1 +1 @@
1
- {"version":3,"file":"nip98.mjs","names":[],"sources":["../../src/nips/nip98.ts"],"sourcesContent":["/**\n * NIP-98: HTTP Auth (kind 27235). Token is standard base64 of the signed event JSON, not base64url.\n *\n * @see https://github.com/nostr-protocol/nips/blob/master/98.md\n */\nimport { sha256 } from \"@noble/hashes/sha2.js\";\nimport { base64 } from \"@scure/base\";\n\nimport { NostrError } from \"../core/error.ts\";\nimport type { Event, EventTemplate } from \"../core/event.ts\";\nimport { validateSignedEvent } from \"../core/event.ts\";\nimport { verifyEvent } from \"../core/key.ts\";\nimport { Kind } from \"../core/kind.ts\";\nimport type { Tag } from \"../core/tag.ts\";\nimport { bytesToHex, utf8Decoder, utf8Encoder } from \"../core/util.ts\";\n\nconst AUTHORIZATION_SCHEME = \"Nostr \";\nconst DEFAULT_MAX_SKEW_SEC = 60;\n\nexport class Nip98Error extends NostrError {\n override name = \"Nip98Error\";\n}\n\n/** SHA-256 of the request body: raw bytes for string/Uint8Array, else JSON.stringify. */\nfunction hashPayload(payload: unknown): string {\n const bytes =\n typeof payload === \"string\"\n ? utf8Encoder.encode(payload)\n : payload instanceof Uint8Array\n ? payload\n : utf8Encoder.encode(JSON.stringify(payload));\n return bytesToHex(sha256(bytes));\n}\n\n/** RFC 4648 standard base64; accept missing `=` (NIP-98 spec example is unpadded). */\nfunction decodeStandardBase64(encoded: string): Uint8Array {\n const rem = encoded.length % 4;\n const padded = rem === 0 ? encoded : encoded + \"=\".repeat(4 - rem);\n return base64.decode(padded);\n}\n\nfunction stripAuthorizationScheme(token: string): string {\n const prefix = /^nostr\\s+/i.exec(token);\n return prefix ? token.slice(prefix[0].length) : token;\n}\n\n/**\n * Sign a kind 27235 auth event and encode it as a NIP-98 token. Uses standard base64\n * (`@scure/base`), not base64url.\n */\nexport async function getToken(\n url: string,\n method: string,\n sign: (template: EventTemplate) => Promise<Event> | Event,\n opts?: {\n includeAuthorizationScheme?: boolean;\n content?: string;\n payload?: unknown;\n now?: number;\n },\n): Promise<string> {\n const tags: Tag[] = [\n [\"u\", url],\n [\"method\", method],\n ];\n if (opts?.payload !== undefined) {\n tags.push([\"payload\", hashPayload(opts.payload)]);\n }\n\n const signed = await sign({\n kind: Kind.HttpAuth,\n created_at: opts?.now ?? Math.floor(Date.now() / 1000),\n tags,\n content: opts?.content ?? \"\",\n });\n\n const encoded = base64.encode(utf8Encoder.encode(JSON.stringify(signed)));\n return opts?.includeAuthorizationScheme === true ? AUTHORIZATION_SCHEME + encoded : encoded;\n}\n\n/** Decode a NIP-98 token (with or without the `Nostr ` scheme) into an event. */\nexport function unpackEventFromToken(token: string): Event {\n if (token === \"\") {\n throw new Nip98Error(\"missing token\");\n }\n\n const encoded = stripAuthorizationScheme(token);\n\n let json: string;\n try {\n json = utf8Decoder.decode(decodeStandardBase64(encoded));\n } catch (error) {\n throw new Nip98Error(\"invalid token encoding\", { cause: error });\n }\n if (!json.startsWith(\"{\")) {\n throw new Nip98Error(\"invalid token\");\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(json);\n } catch (error) {\n throw new Nip98Error(\"invalid token JSON\", { cause: error });\n }\n if (!validateSignedEvent(parsed)) {\n throw new Nip98Error(\"token is not a signed event\");\n }\n return parsed;\n}\n\n/**\n * True when `event` is a valid NIP-98 auth event for `url` + `method`. Verifies signature, kind\n * 27235, timestamp window, `u`, `method`, and optional `payload` tag.\n */\nexport function validateAuthEvent(\n event: Event,\n url: string,\n method: string,\n opts?: { payload?: unknown; maxSkewSec?: number },\n): boolean {\n if (!verifyEvent(event)) {\n return false;\n }\n if (event.kind !== Kind.HttpAuth) {\n return false;\n }\n\n const maxSkewSec = opts?.maxSkewSec ?? DEFAULT_MAX_SKEW_SEC;\n const now = Math.floor(Date.now() / 1000);\n if (Math.abs(now - event.created_at) > maxSkewSec) {\n return false;\n }\n\n const u = event.tags.find((t) => t[0] === \"u\")?.[1];\n if (u !== url) {\n return false;\n }\n\n const m = event.tags.find((t) => t[0] === \"method\")?.[1];\n if (m === undefined || m.toLowerCase() !== method.toLowerCase()) {\n return false;\n }\n\n if (opts?.payload !== undefined) {\n const payloadTag = event.tags.find((t) => t[0] === \"payload\")?.[1];\n if (payloadTag !== hashPayload(opts.payload)) {\n return false;\n }\n }\n\n return true;\n}\n"],"mappings":";;;;;;;;;;;;AAgBA,MAAM,uBAAuB;AAC7B,MAAM,uBAAuB;AAE7B,IAAa,aAAb,cAAgC,WAAW;CACzC,OAAgB;AAClB;;AAGA,SAAS,YAAY,SAA0B;CAC7C,MAAM,QACJ,OAAO,YAAY,WACf,YAAY,OAAO,OAAO,IAC1B,mBAAmB,aACjB,UACA,YAAY,OAAO,KAAK,UAAU,OAAO,CAAC;CAClD,OAAO,WAAW,OAAO,KAAK,CAAC;AACjC;;AAGA,SAAS,qBAAqB,SAA6B;CACzD,MAAM,MAAM,QAAQ,SAAS;CAC7B,MAAM,SAAS,QAAQ,IAAI,UAAU,UAAU,IAAI,OAAO,IAAI,GAAG;CACjE,OAAO,OAAO,OAAO,MAAM;AAC7B;AAEA,SAAS,yBAAyB,OAAuB;CACvD,MAAM,SAAS,aAAa,KAAK,KAAK;CACtC,OAAO,SAAS,MAAM,MAAM,OAAO,EAAE,CAAC,MAAM,IAAI;AAClD;;;;;AAMA,eAAsB,SACpB,KACA,QACA,MACA,MAMiB;CACjB,MAAM,OAAc,CAClB,CAAC,KAAK,GAAG,GACT,CAAC,UAAU,MAAM,CACnB;CACA,IAAI,MAAM,YAAY,KAAA,GACpB,KAAK,KAAK,CAAC,WAAW,YAAY,KAAK,OAAO,CAAC,CAAC;CAGlD,MAAM,SAAS,MAAM,KAAK;EACxB,MAAM,KAAK;EACX,YAAY,MAAM,OAAO,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;EACrD;EACA,SAAS,MAAM,WAAW;CAC5B,CAAC;CAED,MAAM,UAAU,OAAO,OAAO,YAAY,OAAO,KAAK,UAAU,MAAM,CAAC,CAAC;CACxE,OAAO,MAAM,+BAA+B,OAAO,uBAAuB,UAAU;AACtF;;AAGA,SAAgB,qBAAqB,OAAsB;CACzD,IAAI,UAAU,IACZ,MAAM,IAAI,WAAW,eAAe;CAGtC,MAAM,UAAU,yBAAyB,KAAK;CAE9C,IAAI;CACJ,IAAI;EACF,OAAO,YAAY,OAAO,qBAAqB,OAAO,CAAC;CACzD,SAAS,OAAO;EACd,MAAM,IAAI,WAAW,0BAA0B,EAAE,OAAO,MAAM,CAAC;CACjE;CACA,IAAI,CAAC,KAAK,WAAW,GAAG,GACtB,MAAM,IAAI,WAAW,eAAe;CAGtC,IAAI;CACJ,IAAI;EACF,SAAS,KAAK,MAAM,IAAI;CAC1B,SAAS,OAAO;EACd,MAAM,IAAI,WAAW,sBAAsB,EAAE,OAAO,MAAM,CAAC;CAC7D;CACA,IAAI,CAAC,oBAAoB,MAAM,GAC7B,MAAM,IAAI,WAAW,6BAA6B;CAEpD,OAAO;AACT;;;;;AAMA,SAAgB,kBACd,OACA,KACA,QACA,MACS;CACT,IAAI,CAAC,YAAY,KAAK,GACpB,OAAO;CAET,IAAI,MAAM,SAAS,KAAK,UACtB,OAAO;CAGT,MAAM,aAAa,MAAM,cAAc;CACvC,MAAM,MAAM,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;CACxC,IAAI,KAAK,IAAI,MAAM,MAAM,UAAU,IAAI,YACrC,OAAO;CAIT,IADU,MAAM,KAAK,MAAM,MAAM,EAAE,OAAO,GAAG,CAAC,GAAG,OACvC,KACR,OAAO;CAGT,MAAM,IAAI,MAAM,KAAK,MAAM,MAAM,EAAE,OAAO,QAAQ,CAAC,GAAG;CACtD,IAAI,MAAM,KAAA,KAAa,EAAE,YAAY,MAAM,OAAO,YAAY,GAC5D,OAAO;CAGT,IAAI,MAAM,YAAY,KAAA,GACD;MAAA,MAAM,KAAK,MAAM,MAAM,EAAE,OAAO,SAAS,CAAC,GAAG,OAC7C,YAAY,KAAK,OAAO,GACzC,OAAO;CAAA;CAIX,OAAO;AACT"}
1
+ {"version":3,"file":"nip98.mjs","names":[],"sources":["../../src/nips/nip98.ts"],"sourcesContent":["/**\n * NIP-98: HTTP Auth (kind 27235). Token is standard base64 of the signed event JSON, not base64url.\n *\n * @see https://github.com/nostr-protocol/nips/blob/master/98.md\n */\nimport { sha256 } from \"@noble/hashes/sha2.js\";\nimport { base64 } from \"@scure/base\";\n\nimport { NostrError } from \"../core/error.ts\";\nimport type { Event, EventTemplate } from \"../core/event.ts\";\nimport { validateSignedEvent } from \"../core/event.ts\";\nimport { Kind } from \"../core/kind.ts\";\nimport type { Tag } from \"../core/tag.ts\";\nimport { bytesToHex, utf8Decoder, utf8Encoder } from \"../core/util.ts\";\nimport { verifyEvent } from \"../core/verifier.ts\";\n\nconst AUTHORIZATION_SCHEME = \"Nostr \";\nconst DEFAULT_MAX_SKEW_SEC = 60;\n\nexport class Nip98Error extends NostrError {\n override name = \"Nip98Error\";\n}\n\n/** SHA-256 of the request body: raw bytes for string/Uint8Array, else JSON.stringify. */\nfunction hashPayload(payload: unknown): string {\n const bytes =\n typeof payload === \"string\"\n ? utf8Encoder.encode(payload)\n : payload instanceof Uint8Array\n ? payload\n : utf8Encoder.encode(JSON.stringify(payload));\n return bytesToHex(sha256(bytes));\n}\n\n/** RFC 4648 standard base64; accept missing `=` (NIP-98 spec example is unpadded). */\nfunction decodeStandardBase64(encoded: string): Uint8Array {\n const rem = encoded.length % 4;\n const padded = rem === 0 ? encoded : encoded + \"=\".repeat(4 - rem);\n return base64.decode(padded);\n}\n\nfunction stripAuthorizationScheme(token: string): string {\n const prefix = /^nostr\\s+/i.exec(token);\n return prefix ? token.slice(prefix[0].length) : token;\n}\n\n/**\n * Sign a kind 27235 auth event and encode it as a NIP-98 token. Uses standard base64\n * (`@scure/base`), not base64url.\n */\nexport async function getToken(\n url: string,\n method: string,\n sign: (template: EventTemplate) => Promise<Event> | Event,\n opts?: {\n includeAuthorizationScheme?: boolean;\n content?: string;\n payload?: unknown;\n now?: number;\n },\n): Promise<string> {\n const tags: Tag[] = [\n [\"u\", url],\n [\"method\", method],\n ];\n if (opts?.payload !== undefined) {\n tags.push([\"payload\", hashPayload(opts.payload)]);\n }\n\n const signed = await sign({\n kind: Kind.HttpAuth,\n created_at: opts?.now ?? Math.floor(Date.now() / 1000),\n tags,\n content: opts?.content ?? \"\",\n });\n\n const encoded = base64.encode(utf8Encoder.encode(JSON.stringify(signed)));\n return opts?.includeAuthorizationScheme === true ? AUTHORIZATION_SCHEME + encoded : encoded;\n}\n\n/** Decode a NIP-98 token (with or without the `Nostr ` scheme) into an event. */\nexport function unpackEventFromToken(token: string): Event {\n if (token === \"\") {\n throw new Nip98Error(\"missing token\");\n }\n\n const encoded = stripAuthorizationScheme(token);\n\n let json: string;\n try {\n json = utf8Decoder.decode(decodeStandardBase64(encoded));\n } catch (error) {\n throw new Nip98Error(\"invalid token encoding\", { cause: error });\n }\n if (!json.startsWith(\"{\")) {\n throw new Nip98Error(\"invalid token\");\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(json);\n } catch (error) {\n throw new Nip98Error(\"invalid token JSON\", { cause: error });\n }\n if (!validateSignedEvent(parsed)) {\n throw new Nip98Error(\"token is not a signed event\");\n }\n return parsed;\n}\n\n/**\n * True when `event` is a valid NIP-98 auth event for `url` + `method`. Verifies signature, kind\n * 27235, timestamp window, `u`, `method`, and optional `payload` tag.\n */\nexport function validateAuthEvent(\n event: Event,\n url: string,\n method: string,\n opts?: { payload?: unknown; maxSkewSec?: number },\n): boolean {\n if (!verifyEvent(event)) {\n return false;\n }\n if (event.kind !== Kind.HttpAuth) {\n return false;\n }\n\n const maxSkewSec = opts?.maxSkewSec ?? DEFAULT_MAX_SKEW_SEC;\n const now = Math.floor(Date.now() / 1000);\n if (Math.abs(now - event.created_at) > maxSkewSec) {\n return false;\n }\n\n const u = event.tags.find((t) => t[0] === \"u\")?.[1];\n if (u !== url) {\n return false;\n }\n\n const m = event.tags.find((t) => t[0] === \"method\")?.[1];\n if (m === undefined || m.toLowerCase() !== method.toLowerCase()) {\n return false;\n }\n\n if (opts?.payload !== undefined) {\n const payloadTag = event.tags.find((t) => t[0] === \"payload\")?.[1];\n if (payloadTag !== hashPayload(opts.payload)) {\n return false;\n }\n }\n\n return true;\n}\n"],"mappings":";;;;;;;;;;;;AAgBA,MAAM,uBAAuB;AAC7B,MAAM,uBAAuB;AAE7B,IAAa,aAAb,cAAgC,WAAW;CACzC,OAAgB;AAClB;;AAGA,SAAS,YAAY,SAA0B;CAC7C,MAAM,QACJ,OAAO,YAAY,WACf,YAAY,OAAO,OAAO,IAC1B,mBAAmB,aACjB,UACA,YAAY,OAAO,KAAK,UAAU,OAAO,CAAC;CAClD,OAAO,WAAW,OAAO,KAAK,CAAC;AACjC;;AAGA,SAAS,qBAAqB,SAA6B;CACzD,MAAM,MAAM,QAAQ,SAAS;CAC7B,MAAM,SAAS,QAAQ,IAAI,UAAU,UAAU,IAAI,OAAO,IAAI,GAAG;CACjE,OAAO,OAAO,OAAO,MAAM;AAC7B;AAEA,SAAS,yBAAyB,OAAuB;CACvD,MAAM,SAAS,aAAa,KAAK,KAAK;CACtC,OAAO,SAAS,MAAM,MAAM,OAAO,EAAE,CAAC,MAAM,IAAI;AAClD;;;;;AAMA,eAAsB,SACpB,KACA,QACA,MACA,MAMiB;CACjB,MAAM,OAAc,CAClB,CAAC,KAAK,GAAG,GACT,CAAC,UAAU,MAAM,CACnB;CACA,IAAI,MAAM,YAAY,KAAA,GACpB,KAAK,KAAK,CAAC,WAAW,YAAY,KAAK,OAAO,CAAC,CAAC;CAGlD,MAAM,SAAS,MAAM,KAAK;EACxB,MAAM,KAAK;EACX,YAAY,MAAM,OAAO,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;EACrD;EACA,SAAS,MAAM,WAAW;CAC5B,CAAC;CAED,MAAM,UAAU,OAAO,OAAO,YAAY,OAAO,KAAK,UAAU,MAAM,CAAC,CAAC;CACxE,OAAO,MAAM,+BAA+B,OAAO,uBAAuB,UAAU;AACtF;;AAGA,SAAgB,qBAAqB,OAAsB;CACzD,IAAI,UAAU,IACZ,MAAM,IAAI,WAAW,eAAe;CAGtC,MAAM,UAAU,yBAAyB,KAAK;CAE9C,IAAI;CACJ,IAAI;EACF,OAAO,YAAY,OAAO,qBAAqB,OAAO,CAAC;CACzD,SAAS,OAAO;EACd,MAAM,IAAI,WAAW,0BAA0B,EAAE,OAAO,MAAM,CAAC;CACjE;CACA,IAAI,CAAC,KAAK,WAAW,GAAG,GACtB,MAAM,IAAI,WAAW,eAAe;CAGtC,IAAI;CACJ,IAAI;EACF,SAAS,KAAK,MAAM,IAAI;CAC1B,SAAS,OAAO;EACd,MAAM,IAAI,WAAW,sBAAsB,EAAE,OAAO,MAAM,CAAC;CAC7D;CACA,IAAI,CAAC,oBAAoB,MAAM,GAC7B,MAAM,IAAI,WAAW,6BAA6B;CAEpD,OAAO;AACT;;;;;AAMA,SAAgB,kBACd,OACA,KACA,QACA,MACS;CACT,IAAI,CAAC,YAAY,KAAK,GACpB,OAAO;CAET,IAAI,MAAM,SAAS,KAAK,UACtB,OAAO;CAGT,MAAM,aAAa,MAAM,cAAc;CACvC,MAAM,MAAM,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;CACxC,IAAI,KAAK,IAAI,MAAM,MAAM,UAAU,IAAI,YACrC,OAAO;CAIT,IADU,MAAM,KAAK,MAAM,MAAM,EAAE,OAAO,GAAG,CAAC,GAAG,OACvC,KACR,OAAO;CAGT,MAAM,IAAI,MAAM,KAAK,MAAM,MAAM,EAAE,OAAO,QAAQ,CAAC,GAAG;CACtD,IAAI,MAAM,KAAA,KAAa,EAAE,YAAY,MAAM,OAAO,YAAY,GAC5D,OAAO;CAGT,IAAI,MAAM,YAAY,KAAA,GACD;MAAA,MAAM,KAAK,MAAM,MAAM,EAAE,OAAO,SAAS,CAAC,GAAG,OAC7C,YAAY,KAAK,OAAO,GACzC,OAAO;CAAA;CAIX,OAAO;AACT"}