@bzzsocial/ndk 0.0.0-stage → 3.0.3-bzz.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +104 -2
- package/dist/index.d.mts +7392 -0
- package/dist/index.d.ts +7392 -0
- package/dist/index.js +15372 -0
- package/dist/index.mjs +15195 -0
- package/dist/test/index.d.mts +4584 -0
- package/dist/test/index.d.ts +4584 -0
- package/dist/test/index.js +13744 -0
- package/dist/test/index.mjs +13712 -0
- package/dist/workers/sig-verification.d.mts +2 -0
- package/dist/workers/sig-verification.d.ts +2 -0
- package/dist/workers/sig-verification.js +38 -0
- package/dist/workers/sig-verification.mjs +36 -0
- package/package.json +72 -4
- package/src/ai-guardrails/event/publishing.test.ts +176 -0
- package/src/ai-guardrails/event/signing.test.ts +124 -0
- package/src/ai-guardrails/event/signing.ts +225 -0
- package/src/ai-guardrails/index.ts +364 -0
- package/src/ai-guardrails/ndk/fetch-events.test.ts +257 -0
- package/src/ai-guardrails/ndk/fetch-events.ts +166 -0
- package/src/ai-guardrails/ndk.test.ts +64 -0
- package/src/ai-guardrails/ndk.ts +34 -0
- package/src/ai-guardrails/subscription/deprecated-handlers.test.ts +105 -0
- package/src/ai-guardrails/subscription/deprecated-handlers.ts +75 -0
- package/src/ai-guardrails/types.ts +69 -0
- package/src/app-settings/index.ts +71 -0
- package/src/cache/filter.test.ts +139 -0
- package/src/cache/filter.ts +78 -0
- package/src/cache/index.ts +474 -0
- package/src/count/index.test.ts +247 -0
- package/src/count/index.ts +213 -0
- package/src/dvm/schedule.ts +132 -0
- package/src/events/content-tagger.test.ts +284 -0
- package/src/events/content-tagger.ts +249 -0
- package/src/events/dedup.ts +14 -0
- package/src/events/encode.test.ts +35 -0
- package/src/events/encryption.test.ts +484 -0
- package/src/events/encryption.ts +106 -0
- package/src/events/fetch-tagged-event.ts +44 -0
- package/src/events/gift-wrapping.test.ts +139 -0
- package/src/events/gift-wrapping.ts +155 -0
- package/src/events/index.test.ts +863 -0
- package/src/events/index.ts +1130 -0
- package/src/events/kind.ts +20 -0
- package/src/events/kinds/article.ts +152 -0
- package/src/events/kinds/blossom-list.ts +91 -0
- package/src/events/kinds/cashu/fedimint.ts +95 -0
- package/src/events/kinds/cashu/mint-recommendation.ts +95 -0
- package/src/events/kinds/cashu/mint.ts +93 -0
- package/src/events/kinds/cashu/token.ts +155 -0
- package/src/events/kinds/cashu/tx.test.ts +44 -0
- package/src/events/kinds/cashu/tx.ts +190 -0
- package/src/events/kinds/classified.ts +182 -0
- package/src/events/kinds/collaborative.test.ts +453 -0
- package/src/events/kinds/collaborative.ts +346 -0
- package/src/events/kinds/drafts.ts +152 -0
- package/src/events/kinds/dvm/NDKTranscriptionDVM.ts +69 -0
- package/src/events/kinds/dvm/feedback.ts +51 -0
- package/src/events/kinds/dvm/index.ts +6 -0
- package/src/events/kinds/dvm/request.ts +131 -0
- package/src/events/kinds/dvm/result.ts +93 -0
- package/src/events/kinds/follow-pack.test.ts +169 -0
- package/src/events/kinds/follow-pack.ts +123 -0
- package/src/events/kinds/highlight.ts +116 -0
- package/src/events/kinds/image.ts +51 -0
- package/src/events/kinds/index.ts +224 -0
- package/src/events/kinds/interest-list.test.ts +171 -0
- package/src/events/kinds/interest-list.ts +82 -0
- package/src/events/kinds/lists/index.test.ts +51 -0
- package/src/events/kinds/lists/index.ts +415 -0
- package/src/events/kinds/nip89/app-handler.test.ts +106 -0
- package/src/events/kinds/nip89/app-handler.ts +83 -0
- package/src/events/kinds/nutzap/index.test.ts +192 -0
- package/src/events/kinds/nutzap/index.ts +384 -0
- package/src/events/kinds/nutzap/mint-list.ts +76 -0
- package/src/events/kinds/nutzap/proof.ts +18 -0
- package/src/events/kinds/nutzap/validation.test.ts +340 -0
- package/src/events/kinds/nutzap/validation.ts +79 -0
- package/src/events/kinds/p2p-order.test.ts +359 -0
- package/src/events/kinds/p2p-order.ts +469 -0
- package/src/events/kinds/project-template.ts +132 -0
- package/src/events/kinds/project.ts +114 -0
- package/src/events/kinds/relay-feed-list.example.ts +86 -0
- package/src/events/kinds/relay-feed-list.test.ts +97 -0
- package/src/events/kinds/relay-feed-list.ts +108 -0
- package/src/events/kinds/relay-list.ts +118 -0
- package/src/events/kinds/repost.ts +67 -0
- package/src/events/kinds/simple-group/index.ts +234 -0
- package/src/events/kinds/simple-group/member-list.ts +43 -0
- package/src/events/kinds/simple-group/metadata.ts +64 -0
- package/src/events/kinds/story.test.ts +141 -0
- package/src/events/kinds/story.ts +458 -0
- package/src/events/kinds/subscriptions/amount.ts +61 -0
- package/src/events/kinds/subscriptions/receipt.ts +148 -0
- package/src/events/kinds/subscriptions/subscription-start.ts +149 -0
- package/src/events/kinds/subscriptions/tier.test.ts +76 -0
- package/src/events/kinds/subscriptions/tier.ts +121 -0
- package/src/events/kinds/task.ts +42 -0
- package/src/events/kinds/thread.ts +45 -0
- package/src/events/kinds/video.ts +140 -0
- package/src/events/kinds/voice-message.ts +257 -0
- package/src/events/kinds/wiki.ts +88 -0
- package/src/events/kinds/zap.ts +115 -0
- package/src/events/nip10.test.ts +108 -0
- package/src/events/nip10.ts +75 -0
- package/src/events/nip19.test.ts +49 -0
- package/src/events/nip19.ts +36 -0
- package/src/events/nip73.ts +13 -0
- package/src/events/repost.test.ts +40 -0
- package/src/events/repost.ts +44 -0
- package/src/events/serializer.test.ts +174 -0
- package/src/events/serializer.ts +120 -0
- package/src/events/signature.ts +97 -0
- package/src/events/signed-event-types.test.ts +149 -0
- package/src/events/validation.ts +113 -0
- package/src/events/wrap.test.ts +164 -0
- package/src/events/wrap.ts +128 -0
- package/src/index.ts +103 -0
- package/src/light-bolt11-decoder.d.ts +4 -0
- package/src/ndk/active-user.test.ts +89 -0
- package/src/ndk/active-user.ts +41 -0
- package/src/ndk/entity.ts +31 -0
- package/src/ndk/fetch-event-from-tag.ts +156 -0
- package/src/ndk/fetchEvent-guardrails.test.ts +208 -0
- package/src/ndk/fetchEvent-invalid-filter.test.ts +80 -0
- package/src/ndk/fetchUser.test.ts +149 -0
- package/src/ndk/guardrailOff.test.ts +75 -0
- package/src/ndk/index.ts +1249 -0
- package/src/ndk/nip19.test.ts +122 -0
- package/src/ndk/queue/index.ts +89 -0
- package/src/nip19/index.ts +5 -0
- package/src/nip49/index.test.ts +100 -0
- package/src/nip49/index.ts +5 -0
- package/src/outbox/index.ts +128 -0
- package/src/outbox/read/with-authors.ts +24 -0
- package/src/outbox/relay-ranking.ts +27 -0
- package/src/outbox/tracker.test.ts +68 -0
- package/src/outbox/tracker.ts +185 -0
- package/src/outbox/write.ts +37 -0
- package/src/relay/auth-on-demand.test.ts +197 -0
- package/src/relay/auth-policies.test.ts +19 -0
- package/src/relay/auth-policies.ts +109 -0
- package/src/relay/auth-retry.test.ts +241 -0
- package/src/relay/connections.test.ts +231 -0
- package/src/relay/connectivity.test.ts +370 -0
- package/src/relay/connectivity.ts +1106 -0
- package/src/relay/index.test.ts +167 -0
- package/src/relay/index.ts +446 -0
- package/src/relay/keepalive-bun.test.ts +86 -0
- package/src/relay/keepalive.test.ts +196 -0
- package/src/relay/keepalive.ts +118 -0
- package/src/relay/nip11.test.ts +196 -0
- package/src/relay/nip11.ts +85 -0
- package/src/relay/nip42.test.ts +269 -0
- package/src/relay/pool/index.test.ts +183 -0
- package/src/relay/pool/index.ts +537 -0
- package/src/relay/pool/system-disconnection.test.ts +280 -0
- package/src/relay/publisher.ts +114 -0
- package/src/relay/reconnection-backoff.test.ts +92 -0
- package/src/relay/reconnection-integration.bun.test.ts +112 -0
- package/src/relay/score.ts +2 -0
- package/src/relay/sets/calculate.test.ts +220 -0
- package/src/relay/sets/calculate.ts +203 -0
- package/src/relay/sets/index.ts +416 -0
- package/src/relay/sets/publish.test.ts +231 -0
- package/src/relay/sets/utils.ts +29 -0
- package/src/relay/signature-verification-stats.ts +150 -0
- package/src/relay/signature-verification.test.ts +192 -0
- package/src/relay/simple-verification.test.ts +13 -0
- package/src/relay/sub-manager.ts +81 -0
- package/src/relay/subscription.test.ts +166 -0
- package/src/relay/subscription.ts +542 -0
- package/src/relay/validation-ratio.test.ts +37 -0
- package/src/signers/deserialization.ts +39 -0
- package/src/signers/index.ts +97 -0
- package/src/signers/nip07/index.test.ts +32 -0
- package/src/signers/nip07/index.ts +302 -0
- package/src/signers/nip46/backend/connect.ts +41 -0
- package/src/signers/nip46/backend/get-public-key.ts +12 -0
- package/src/signers/nip46/backend/index.test.ts +340 -0
- package/src/signers/nip46/backend/index.ts +232 -0
- package/src/signers/nip46/backend/nip04-decrypt.ts +39 -0
- package/src/signers/nip46/backend/nip04-encrypt.ts +39 -0
- package/src/signers/nip46/backend/nip44-decrypt.ts +39 -0
- package/src/signers/nip46/backend/nip44-encrypt.ts +39 -0
- package/src/signers/nip46/backend/ping.ts +25 -0
- package/src/signers/nip46/backend/sign-event.ts +48 -0
- package/src/signers/nip46/backend/switch-relays.ts +28 -0
- package/src/signers/nip46/index.test.ts +560 -0
- package/src/signers/nip46/index.ts +640 -0
- package/src/signers/nip46/nostrconnect.ts +50 -0
- package/src/signers/nip46/restore.test.ts +44 -0
- package/src/signers/nip46/rpc.ts +221 -0
- package/src/signers/private-key/index.test.ts +151 -0
- package/src/signers/private-key/index.ts +241 -0
- package/src/signers/registry.ts +14 -0
- package/src/signers/serialization.test.ts +212 -0
- package/src/signers/types.ts +7 -0
- package/src/subscription/eose.test.ts +92 -0
- package/src/subscription/event-dedup.test.ts +445 -0
- package/src/subscription/exclusive-relay.test.ts +444 -0
- package/src/subscription/future-timestamp-grace.test.ts +276 -0
- package/src/subscription/grouping.test.ts +71 -0
- package/src/subscription/grouping.ts +76 -0
- package/src/subscription/index.test.ts +113 -0
- package/src/subscription/index.ts +1136 -0
- package/src/subscription/manager.test.ts +64 -0
- package/src/subscription/manager.ts +121 -0
- package/src/subscription/outbox-late-arrival.test.ts +172 -0
- package/src/subscription/utils/format-filters.ts +57 -0
- package/src/subscription/utils.test.ts +91 -0
- package/src/subscription/utils.ts +276 -0
- package/src/subscription/verify-before-emit.test.ts +108 -0
- package/src/subscription.test.ts +175 -0
- package/src/test-relay-autoconnect.ts +133 -0
- package/src/thread/index.test.ts +267 -0
- package/src/thread/index.ts +242 -0
- package/src/types.ts +45 -0
- package/src/user/follows.test.ts +58 -0
- package/src/user/follows.ts +45 -0
- package/src/user/index.test.ts +365 -0
- package/src/user/index.ts +465 -0
- package/src/user/nip05.test.ts +39 -0
- package/src/user/nip05.ts +107 -0
- package/src/user/pin.ts +45 -0
- package/src/user/profile.ts +112 -0
- package/src/utils/filter-validation.test.ts +925 -0
- package/src/utils/filter-validation.ts +436 -0
- package/src/utils/filter.ts +41 -0
- package/src/utils/get-users-relay-list.ts +171 -0
- package/src/utils/imeta.test.ts +100 -0
- package/src/utils/imeta.ts +74 -0
- package/src/utils/index.ts +5 -0
- package/src/utils/normalize-url.ts +352 -0
- package/src/utils/timeout.ts +15 -0
- package/src/utils/validation.ts +86 -0
- package/src/workers/sig-verification.ts +54 -0
- package/src/zap/invoice.ts +111 -0
- package/src/zapper/index.test.ts +151 -0
- package/src/zapper/index.ts +701 -0
- package/src/zapper/ln.ts +84 -0
- package/src/zapper/nip57.test.ts +329 -0
- package/src/zapper/nip57.ts +85 -0
- package/src/zapper/nip61.ts +57 -0
|
@@ -0,0 +1,4584 @@
|
|
|
1
|
+
import { EventEmitter } from 'tseep';
|
|
2
|
+
import debug$1 from 'debug';
|
|
3
|
+
import { LRUCache } from 'typescript-lru-cache';
|
|
4
|
+
import { nip19 } from 'nostr-tools';
|
|
5
|
+
import { EventEmitter as EventEmitter$1 } from 'node:events';
|
|
6
|
+
|
|
7
|
+
declare enum NDKKind {
|
|
8
|
+
Metadata = 0,
|
|
9
|
+
Text = 1,
|
|
10
|
+
RecommendRelay = 2,
|
|
11
|
+
Contacts = 3,
|
|
12
|
+
EncryptedDirectMessage = 4,
|
|
13
|
+
EventDeletion = 5,
|
|
14
|
+
Repost = 6,
|
|
15
|
+
Reaction = 7,
|
|
16
|
+
BadgeAward = 8,
|
|
17
|
+
GroupChat = 9,
|
|
18
|
+
Thread = 11,
|
|
19
|
+
GroupReply = 12,
|
|
20
|
+
GiftWrapSeal = 13,
|
|
21
|
+
PrivateDirectMessage = 14,
|
|
22
|
+
Image = 20,
|
|
23
|
+
Video = 21,
|
|
24
|
+
ShortVideo = 22,
|
|
25
|
+
Story = 23,
|
|
26
|
+
Vanish = 62,
|
|
27
|
+
CashuWalletBackup = 375,
|
|
28
|
+
GiftWrap = 1059,
|
|
29
|
+
GenericRepost = 16,
|
|
30
|
+
ChannelCreation = 40,
|
|
31
|
+
ChannelMetadata = 41,
|
|
32
|
+
ChannelMessage = 42,
|
|
33
|
+
ChannelHideMessage = 43,
|
|
34
|
+
ChannelMuteUser = 44,
|
|
35
|
+
WikiMergeRequest = 818,
|
|
36
|
+
GenericReply = 1111,
|
|
37
|
+
Media = 1063,
|
|
38
|
+
VoiceMessage = 1222,
|
|
39
|
+
VoiceReply = 1244,
|
|
40
|
+
DraftCheckpoint = 1234,
|
|
41
|
+
Task = 1934,
|
|
42
|
+
Report = 1984,
|
|
43
|
+
Label = 1985,
|
|
44
|
+
DVMReqTextExtraction = 5000,
|
|
45
|
+
DVMReqTextSummarization = 5001,
|
|
46
|
+
DVMReqTextTranslation = 5002,
|
|
47
|
+
DVMReqTextGeneration = 5050,
|
|
48
|
+
DVMReqImageGeneration = 5100,
|
|
49
|
+
DVMReqTextToSpeech = 5250,
|
|
50
|
+
DVMReqDiscoveryNostrContent = 5300,
|
|
51
|
+
DVMReqDiscoveryNostrPeople = 5301,
|
|
52
|
+
DVMReqTimestamping = 5900,
|
|
53
|
+
DVMEventSchedule = 5905,
|
|
54
|
+
DVMJobFeedback = 7000,
|
|
55
|
+
Subscribe = 7001,
|
|
56
|
+
Unsubscribe = 7002,
|
|
57
|
+
SubscriptionReceipt = 7003,
|
|
58
|
+
CashuReserve = 7373,
|
|
59
|
+
CashuQuote = 7374,
|
|
60
|
+
CashuToken = 7375,
|
|
61
|
+
CashuWalletTx = 7376,
|
|
62
|
+
GroupAdminAddUser = 9000,
|
|
63
|
+
GroupAdminRemoveUser = 9001,
|
|
64
|
+
GroupAdminEditMetadata = 9002,
|
|
65
|
+
GroupAdminEditStatus = 9006,
|
|
66
|
+
GroupAdminCreateGroup = 9007,
|
|
67
|
+
GroupAdminRequestJoin = 9021,
|
|
68
|
+
MuteList = 10000,
|
|
69
|
+
PinList = 10001,
|
|
70
|
+
RelayList = 10002,
|
|
71
|
+
BookmarkList = 10003,
|
|
72
|
+
CommunityList = 10004,
|
|
73
|
+
PublicChatList = 10005,
|
|
74
|
+
BlockRelayList = 10006,
|
|
75
|
+
SearchRelayList = 10007,
|
|
76
|
+
SimpleGroupList = 10009,
|
|
77
|
+
RelayFeedList = 10012,
|
|
78
|
+
InterestList = 10015,
|
|
79
|
+
CashuMintList = 10019,
|
|
80
|
+
EmojiList = 10030,
|
|
81
|
+
DirectMessageReceiveRelayList = 10050,
|
|
82
|
+
BlossomList = 10063,
|
|
83
|
+
NostrWaletConnectInfo = 13194,
|
|
84
|
+
TierList = 17000,
|
|
85
|
+
CashuWallet = 17375,
|
|
86
|
+
FollowSet = 30000,
|
|
87
|
+
CategorizedPeopleList = 30000,// Deprecated but left for backwards compatibility
|
|
88
|
+
CategorizedBookmarkList = 30001,// Deprecated but left for backwards compatibility
|
|
89
|
+
RelaySet = 30002,
|
|
90
|
+
CategorizedRelayList = 30002,// Deprecated but left for backwards compatibility
|
|
91
|
+
BookmarkSet = 30003,
|
|
92
|
+
/**
|
|
93
|
+
* @deprecated Use ArticleCurationSet instead
|
|
94
|
+
*/
|
|
95
|
+
CurationSet = 30004,// Deprecated but left for backwards compatibility
|
|
96
|
+
ArticleCurationSet = 30004,
|
|
97
|
+
VideoCurationSet = 30005,
|
|
98
|
+
ImageCurationSet = 30006,
|
|
99
|
+
InterestSet = 30015,
|
|
100
|
+
InterestsList = 30015,// Deprecated but left for backwards compatibility
|
|
101
|
+
ProjectTemplate = 30717,
|
|
102
|
+
EmojiSet = 30030,
|
|
103
|
+
ModularArticle = 30040,
|
|
104
|
+
ModularArticleItem = 30041,
|
|
105
|
+
Wiki = 30818,
|
|
106
|
+
Draft = 31234,
|
|
107
|
+
Project = 31933,
|
|
108
|
+
SubscriptionTier = 37001,
|
|
109
|
+
EcashMintRecommendation = 38000,
|
|
110
|
+
CashuMintAnnouncement = 38172,
|
|
111
|
+
FedimintMintAnnouncement = 38173,
|
|
112
|
+
P2POrder = 38383,
|
|
113
|
+
CollaborativeEvent = 39382,
|
|
114
|
+
HighlightSet = 39802,
|
|
115
|
+
CategorizedHighlightList = 39802,// Deprecated but left for backwards compatibility
|
|
116
|
+
Nutzap = 9321,
|
|
117
|
+
ZapRequest = 9734,
|
|
118
|
+
Zap = 9735,
|
|
119
|
+
Highlight = 9802,
|
|
120
|
+
ClientAuth = 22242,
|
|
121
|
+
NostrWalletConnectReq = 23194,
|
|
122
|
+
NostrWalletConnectRes = 23195,
|
|
123
|
+
NostrConnect = 24133,
|
|
124
|
+
BlossomUpload = 24242,
|
|
125
|
+
HttpAuth = 27235,
|
|
126
|
+
ProfileBadge = 30008,
|
|
127
|
+
BadgeDefinition = 30009,
|
|
128
|
+
MarketStall = 30017,
|
|
129
|
+
MarketProduct = 30018,
|
|
130
|
+
Article = 30023,
|
|
131
|
+
AppSpecificData = 30078,
|
|
132
|
+
Classified = 30402,
|
|
133
|
+
HorizontalVideo = 34235,
|
|
134
|
+
VerticalVideo = 34236,
|
|
135
|
+
GroupMetadata = 39000,// NIP-29
|
|
136
|
+
GroupAdmins = 39001,// NIP-29
|
|
137
|
+
GroupMembers = 39002,// NIP-29
|
|
138
|
+
FollowPack = 39089,
|
|
139
|
+
MediaFollowPack = 39092,
|
|
140
|
+
AppRecommendation = 31989,
|
|
141
|
+
AppHandler = 31990
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Represents an HLL (HyperLogLog) data structure for cardinality estimation.
|
|
146
|
+
* Contains 256 uint8 registers as specified in NIP-45.
|
|
147
|
+
*/
|
|
148
|
+
declare class NDKCountHll {
|
|
149
|
+
/**
|
|
150
|
+
* The 256 uint8 registers used for HLL estimation
|
|
151
|
+
*/
|
|
152
|
+
readonly registers: Uint8Array;
|
|
153
|
+
constructor(registers?: Uint8Array);
|
|
154
|
+
/**
|
|
155
|
+
* Creates an NDKCountHll from a hex-encoded string (512 characters).
|
|
156
|
+
* Each register is a uint8 value encoded as 2 hex characters.
|
|
157
|
+
*
|
|
158
|
+
* @param hex - The hex string (512 characters = 256 bytes)
|
|
159
|
+
* @returns A new NDKCountHll instance
|
|
160
|
+
* @throws Error if the hex string is invalid
|
|
161
|
+
*/
|
|
162
|
+
static fromHex(hex: string): NDKCountHll;
|
|
163
|
+
/**
|
|
164
|
+
* Converts the HLL registers to a hex-encoded string.
|
|
165
|
+
*
|
|
166
|
+
* @returns The hex string representation (512 characters)
|
|
167
|
+
*/
|
|
168
|
+
toHex(): string;
|
|
169
|
+
/**
|
|
170
|
+
* Merges this HLL with another HLL by taking the maximum value for each register.
|
|
171
|
+
* This is the standard HLL merge operation that allows combining counts
|
|
172
|
+
* from multiple relays without double-counting.
|
|
173
|
+
*
|
|
174
|
+
* @param other - The other HLL to merge with
|
|
175
|
+
* @returns A new NDKCountHll with the merged registers
|
|
176
|
+
*/
|
|
177
|
+
merge(other: NDKCountHll): NDKCountHll;
|
|
178
|
+
/**
|
|
179
|
+
* Merges multiple HLLs by taking the maximum value for each register.
|
|
180
|
+
*
|
|
181
|
+
* @param hlls - Array of HLLs to merge
|
|
182
|
+
* @returns A new NDKCountHll with the merged registers
|
|
183
|
+
*/
|
|
184
|
+
static merge(hlls: NDKCountHll[]): NDKCountHll;
|
|
185
|
+
/**
|
|
186
|
+
* Estimates the cardinality (unique count) using the HyperLogLog algorithm.
|
|
187
|
+
*
|
|
188
|
+
* Uses the standard HLL formula with bias correction for small and large cardinalities.
|
|
189
|
+
*
|
|
190
|
+
* @returns The estimated unique count
|
|
191
|
+
*/
|
|
192
|
+
estimate(): number;
|
|
193
|
+
/**
|
|
194
|
+
* Checks if this HLL is empty (all registers are zero).
|
|
195
|
+
*
|
|
196
|
+
* @returns True if all registers are zero
|
|
197
|
+
*/
|
|
198
|
+
isEmpty(): boolean;
|
|
199
|
+
/**
|
|
200
|
+
* Creates a copy of this HLL.
|
|
201
|
+
*
|
|
202
|
+
* @returns A new NDKCountHll with the same register values
|
|
203
|
+
*/
|
|
204
|
+
clone(): NDKCountHll;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Result of a COUNT request, including optional HLL data.
|
|
208
|
+
*/
|
|
209
|
+
interface NDKCountResult {
|
|
210
|
+
/**
|
|
211
|
+
* The count value returned by the relay.
|
|
212
|
+
* This is the exact count if HLL is not available,
|
|
213
|
+
* or an approximate count if HLL is used.
|
|
214
|
+
*/
|
|
215
|
+
count: number;
|
|
216
|
+
/**
|
|
217
|
+
* The HLL data if returned by the relay.
|
|
218
|
+
* Can be used to merge counts from multiple relays.
|
|
219
|
+
*/
|
|
220
|
+
hll?: NDKCountHll;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Aggregated result from multiple relays for a COUNT request.
|
|
224
|
+
*/
|
|
225
|
+
interface NDKAggregatedCountResult {
|
|
226
|
+
/**
|
|
227
|
+
* The best estimate of the count.
|
|
228
|
+
* If HLL data is available from multiple relays, this is computed from the merged HLL.
|
|
229
|
+
* Otherwise, it's the maximum count from all relays.
|
|
230
|
+
*/
|
|
231
|
+
count: number;
|
|
232
|
+
/**
|
|
233
|
+
* The merged HLL from all relays that returned HLL data.
|
|
234
|
+
* Can be used for further aggregation or analysis.
|
|
235
|
+
*/
|
|
236
|
+
mergedHll?: NDKCountHll;
|
|
237
|
+
/**
|
|
238
|
+
* Individual results from each relay.
|
|
239
|
+
*/
|
|
240
|
+
relayResults: Map<string, NDKCountResult>;
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Options for count requests.
|
|
244
|
+
*/
|
|
245
|
+
interface NDKCountOptions {
|
|
246
|
+
/**
|
|
247
|
+
* Custom ID for the count request.
|
|
248
|
+
*/
|
|
249
|
+
id?: string;
|
|
250
|
+
/**
|
|
251
|
+
* Timeout in milliseconds for the count request.
|
|
252
|
+
* @default 5000
|
|
253
|
+
*/
|
|
254
|
+
timeout?: number;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* NDKUserProfile represents a user's kind 0 profile metadata
|
|
259
|
+
*/
|
|
260
|
+
interface NDKUserProfile {
|
|
261
|
+
[key: string]: string | number | undefined;
|
|
262
|
+
created_at?: number;
|
|
263
|
+
name?: string;
|
|
264
|
+
displayName?: string;
|
|
265
|
+
/**
|
|
266
|
+
* @deprecated Use picture instead
|
|
267
|
+
*/
|
|
268
|
+
image?: string;
|
|
269
|
+
picture?: string;
|
|
270
|
+
banner?: string;
|
|
271
|
+
bio?: string;
|
|
272
|
+
nip05?: string;
|
|
273
|
+
lud06?: string;
|
|
274
|
+
lud16?: string;
|
|
275
|
+
about?: string;
|
|
276
|
+
website?: string;
|
|
277
|
+
profileEvent?: string;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
type Hexpubkey = string;
|
|
281
|
+
type Npub = string;
|
|
282
|
+
type ProfilePointer = {
|
|
283
|
+
pubkey: string;
|
|
284
|
+
relays?: string[];
|
|
285
|
+
nip46?: string[];
|
|
286
|
+
};
|
|
287
|
+
interface NDKUserParams {
|
|
288
|
+
npub?: Npub;
|
|
289
|
+
hexpubkey?: Hexpubkey;
|
|
290
|
+
pubkey?: Hexpubkey;
|
|
291
|
+
nip05?: string;
|
|
292
|
+
relayUrls?: string[];
|
|
293
|
+
nip46Urls?: string[];
|
|
294
|
+
nprofile?: string;
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Represents a pubkey.
|
|
298
|
+
*/
|
|
299
|
+
declare class NDKUser {
|
|
300
|
+
ndk: NDK | undefined;
|
|
301
|
+
profile?: NDKUserProfile;
|
|
302
|
+
profileEvent?: NDKEvent;
|
|
303
|
+
private _npub?;
|
|
304
|
+
private _pubkey?;
|
|
305
|
+
relayUrls: string[];
|
|
306
|
+
readonly nip46Urls: string[];
|
|
307
|
+
constructor(opts: NDKUserParams);
|
|
308
|
+
get npub(): string;
|
|
309
|
+
get nprofile(): string;
|
|
310
|
+
set npub(npub: Npub);
|
|
311
|
+
/**
|
|
312
|
+
* Get the user's pubkey
|
|
313
|
+
* @returns {string} The user's pubkey
|
|
314
|
+
*/
|
|
315
|
+
get pubkey(): string;
|
|
316
|
+
/**
|
|
317
|
+
* Set the user's pubkey
|
|
318
|
+
* @param pubkey {string} The user's pubkey
|
|
319
|
+
*/
|
|
320
|
+
set pubkey(pubkey: string);
|
|
321
|
+
/**
|
|
322
|
+
* Equivalent to NDKEvent.filters().
|
|
323
|
+
* @returns {NDKFilter}
|
|
324
|
+
*/
|
|
325
|
+
filter(): NDKFilter;
|
|
326
|
+
/**
|
|
327
|
+
* Gets NIP-57 and NIP-61 information that this user has signaled
|
|
328
|
+
*
|
|
329
|
+
* @param getAll {boolean} Whether to get all zap info or just the first one
|
|
330
|
+
*/
|
|
331
|
+
getZapInfo(timeoutMs?: number): Promise<Map<NDKZapMethod, NDKZapMethodInfo>>;
|
|
332
|
+
/**
|
|
333
|
+
* Instantiate an NDKUser from a NIP-05 string
|
|
334
|
+
* @param nip05Id {string} The user's NIP-05
|
|
335
|
+
* @param ndk {NDK} An NDK instance
|
|
336
|
+
* @param skipCache {boolean} Whether to skip the cache or not
|
|
337
|
+
* @returns {NDKUser | undefined} An NDKUser if one is found for the given NIP-05, undefined otherwise.
|
|
338
|
+
*/
|
|
339
|
+
static fromNip05(nip05Id: string, ndk: NDK, skipCache?: boolean): Promise<NDKUser | undefined>;
|
|
340
|
+
/**
|
|
341
|
+
* Fetch a user's profile
|
|
342
|
+
* @param opts {NDKSubscriptionOptions} A set of NDKSubscriptionOptions
|
|
343
|
+
* @param storeProfileEvent {boolean} Whether to store the profile event or not
|
|
344
|
+
* @returns User Profile
|
|
345
|
+
*/
|
|
346
|
+
fetchProfile(opts?: NDKSubscriptionOptions, storeProfileEvent?: boolean): Promise<NDKUserProfile | null>;
|
|
347
|
+
/**
|
|
348
|
+
* Returns a set of users that this user follows.
|
|
349
|
+
*
|
|
350
|
+
* @deprecated Use followSet instead
|
|
351
|
+
*/
|
|
352
|
+
follows: (opts?: NDKSubscriptionOptions | undefined, outbox?: boolean | undefined, kind?: number | undefined) => Promise<Set<NDKUser>>;
|
|
353
|
+
/**
|
|
354
|
+
* Returns a set of pubkeys that this user follows.
|
|
355
|
+
*
|
|
356
|
+
* @param opts - NDKSubscriptionOptions
|
|
357
|
+
* @param outbox - boolean
|
|
358
|
+
* @param kind - number
|
|
359
|
+
*/
|
|
360
|
+
followSet(opts?: NDKSubscriptionOptions, outbox?: boolean, kind?: number): Promise<Set<Hexpubkey>>;
|
|
361
|
+
/** @deprecated Use referenceTags instead. */
|
|
362
|
+
/**
|
|
363
|
+
* Get the tag that can be used to reference this user in an event
|
|
364
|
+
* @returns {NDKTag} an NDKTag
|
|
365
|
+
*/
|
|
366
|
+
tagReference(): NDKTag;
|
|
367
|
+
/**
|
|
368
|
+
* Get the tags that can be used to reference this user in an event
|
|
369
|
+
* @returns {NDKTag[]} an array of NDKTag
|
|
370
|
+
*/
|
|
371
|
+
referenceTags(marker?: string): NDKTag[];
|
|
372
|
+
/**
|
|
373
|
+
* Publishes the current profile.
|
|
374
|
+
*/
|
|
375
|
+
publish(): Promise<void>;
|
|
376
|
+
/**
|
|
377
|
+
* Add one or more follows to this user's contact list
|
|
378
|
+
*
|
|
379
|
+
* @param newFollow {NDKUser | Hexpubkey | Array} The user(s) to follow
|
|
380
|
+
* @param currentFollowList {Set<NDKUser | Hexpubkey>} The current follow list
|
|
381
|
+
* @param kind {NDKKind} The kind to use for this contact list (defaults to `3`)
|
|
382
|
+
* @returns {Promise<boolean>} True if any follows were added, false if all already exist
|
|
383
|
+
*/
|
|
384
|
+
follow(newFollow: NDKUser | Hexpubkey | (NDKUser | Hexpubkey)[], currentFollowList?: Set<NDKUser | Hexpubkey>, kind?: NDKKind): Promise<boolean>;
|
|
385
|
+
/**
|
|
386
|
+
* Remove one or more follows from this user's contact list
|
|
387
|
+
*
|
|
388
|
+
* @param user {NDKUser | Hexpubkey | Array} The user(s) to unfollow
|
|
389
|
+
* @param currentFollowList {Set<NDKUser | Hexpubkey>} The current follow list
|
|
390
|
+
* @param kind {NDKKind} The kind to use for this contact list (defaults to `3`)
|
|
391
|
+
* @returns The relays where the follow list was published or false if none were found
|
|
392
|
+
*/
|
|
393
|
+
unfollow(user: NDKUser | Hexpubkey | (NDKUser | Hexpubkey)[], currentFollowList?: Set<NDKUser | Hexpubkey>, kind?: NDKKind): Promise<Set<NDKRelay> | boolean>;
|
|
394
|
+
/**
|
|
395
|
+
* Validate a user's NIP-05 identifier (usually fetched from their kind:0 profile data)
|
|
396
|
+
*
|
|
397
|
+
* @param nip05Id The NIP-05 string to validate
|
|
398
|
+
* @returns {Promise<boolean | null>} True if the NIP-05 is found and matches this user's pubkey,
|
|
399
|
+
* False if the NIP-05 is found but doesn't match this user's pubkey,
|
|
400
|
+
* null if the NIP-05 isn't found on the domain or we're unable to verify (because of network issues, etc.)
|
|
401
|
+
*/
|
|
402
|
+
validateNip05(nip05Id: string): Promise<boolean | null>;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
interface NDKSigner {
|
|
406
|
+
/**
|
|
407
|
+
* Synchronously get the public key of the signer.
|
|
408
|
+
* @throws {Error} "Not ready" when the signer is not ready to provide a pubkey synchronously (e.g., NIP-07 or NIP-46 signers)
|
|
409
|
+
* @returns The public key in hex format
|
|
410
|
+
*/
|
|
411
|
+
get pubkey(): string;
|
|
412
|
+
/**
|
|
413
|
+
* Blocks until the signer is ready and returns the associated NDKUser.
|
|
414
|
+
* @returns A promise that resolves to the NDKUser instance.
|
|
415
|
+
*/
|
|
416
|
+
blockUntilReady(): Promise<NDKUser>;
|
|
417
|
+
/**
|
|
418
|
+
* Getter for the user property.
|
|
419
|
+
* @returns A promise that resolves to the NDKUser instance.
|
|
420
|
+
*/
|
|
421
|
+
user(): Promise<NDKUser>;
|
|
422
|
+
get userSync(): NDKUser;
|
|
423
|
+
/**
|
|
424
|
+
* Signs the given Nostr event.
|
|
425
|
+
* @param event - The Nostr event to be signed.
|
|
426
|
+
* @returns A promise that resolves to the signature of the signed event.
|
|
427
|
+
*/
|
|
428
|
+
sign(event: NostrEvent): Promise<string>;
|
|
429
|
+
/**
|
|
430
|
+
* Getter for the preferred relays.
|
|
431
|
+
* @returns A promise containing a simple map of preferred relays and their read/write policies.
|
|
432
|
+
*/
|
|
433
|
+
relays?(ndk?: NDK): Promise<NDKRelay[]>;
|
|
434
|
+
/**
|
|
435
|
+
* Determine the types of encryption (by nip) that this signer can perform.
|
|
436
|
+
* Implementing classes SHOULD return a value even for legacy (only nip04) third party signers.
|
|
437
|
+
* @nip Optionally returns an array with single supported nip or empty, to check for truthy or falsy.
|
|
438
|
+
* @return A promised list of any (or none) of these strings ['nip04', 'nip44']
|
|
439
|
+
*/
|
|
440
|
+
encryptionEnabled?(scheme?: NDKEncryptionScheme): Promise<NDKEncryptionScheme[]>;
|
|
441
|
+
/**
|
|
442
|
+
* Encrypts the given Nostr event for the given recipient.
|
|
443
|
+
* Implementing classes SHOULD equate legacy (only nip04) to nip == `nip04` || undefined
|
|
444
|
+
* @param recipient - The recipient (pubkey or conversationKey) of the encrypted value.
|
|
445
|
+
* @param value - The value to be encrypted.
|
|
446
|
+
* @param nip - which NIP is being implemented ('nip04', 'nip44')
|
|
447
|
+
*/
|
|
448
|
+
encrypt(recipient: NDKUser, value: string, scheme?: NDKEncryptionScheme): Promise<string>;
|
|
449
|
+
/**
|
|
450
|
+
* Decrypts the given value.
|
|
451
|
+
* Implementing classes SHOULD equate legacy (only nip04) to nip == `nip04` || undefined
|
|
452
|
+
* @param sender - The sender (pubkey or conversationKey) of the encrypted value
|
|
453
|
+
* @param value - The value to be decrypted
|
|
454
|
+
* @param scheme - which NIP is being implemented ('nip04', 'nip44', 'nip49')
|
|
455
|
+
*/
|
|
456
|
+
decrypt(sender: NDKUser, value: string, scheme?: NDKEncryptionScheme): Promise<string>;
|
|
457
|
+
/**
|
|
458
|
+
* Serializes the signer's essential data into a storable format.
|
|
459
|
+
* @returns A JSON string containing the type and payload.
|
|
460
|
+
*/
|
|
461
|
+
toPayload(): string;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
type NDKPoolStats = {
|
|
465
|
+
total: number;
|
|
466
|
+
connected: number;
|
|
467
|
+
disconnected: number;
|
|
468
|
+
connecting: number;
|
|
469
|
+
};
|
|
470
|
+
/**
|
|
471
|
+
* Handles connections to all relays. A single pool should be used per NDK instance.
|
|
472
|
+
*
|
|
473
|
+
* @emit connecting - Emitted when a relay in the pool is connecting.
|
|
474
|
+
* @emit connect - Emitted when all relays in the pool are connected, or when the specified timeout has elapsed, and some relays are connected.
|
|
475
|
+
* @emit notice - Emitted when a relay in the pool sends a notice.
|
|
476
|
+
* @emit flapping - Emitted when a relay in the pool is flapping.
|
|
477
|
+
* @emit relay:connect - Emitted when a relay in the pool connects.
|
|
478
|
+
* @emit relay:ready - Emitted when a relay in the pool is ready to serve requests.
|
|
479
|
+
* @emit relay:disconnect - Emitted when a relay in the pool disconnects.
|
|
480
|
+
*/
|
|
481
|
+
declare class NDKPool extends EventEmitter<{
|
|
482
|
+
notice: (relay: NDKRelay, notice: string) => void;
|
|
483
|
+
flapping: (relay: NDKRelay) => void;
|
|
484
|
+
connect: () => void;
|
|
485
|
+
"relay:connecting": (relay: NDKRelay) => void;
|
|
486
|
+
/**
|
|
487
|
+
* Emitted when a relay in the pool connects.
|
|
488
|
+
* @param relay - The relay that connected.
|
|
489
|
+
*/
|
|
490
|
+
"relay:connect": (relay: NDKRelay) => void;
|
|
491
|
+
"relay:ready": (relay: NDKRelay) => void;
|
|
492
|
+
"relay:disconnect": (relay: NDKRelay) => void;
|
|
493
|
+
"relay:auth": (relay: NDKRelay, challenge: string) => void;
|
|
494
|
+
"relay:authed": (relay: NDKRelay) => void;
|
|
495
|
+
}> {
|
|
496
|
+
private _relays;
|
|
497
|
+
private status;
|
|
498
|
+
autoConnectRelays: Set<string>;
|
|
499
|
+
private debug;
|
|
500
|
+
private temporaryRelayTimers;
|
|
501
|
+
private flappingRelays;
|
|
502
|
+
private backoffTimes;
|
|
503
|
+
private ndk;
|
|
504
|
+
private disconnectionTimes;
|
|
505
|
+
private systemEventDetector?;
|
|
506
|
+
/**
|
|
507
|
+
* @param relayUrls - The URLs of the relays to connect to.
|
|
508
|
+
* @param ndk - The NDK instance.
|
|
509
|
+
* @param opts - Options for the pool.
|
|
510
|
+
*/
|
|
511
|
+
constructor(relayUrls: WebSocket["url"][], ndk: NDK, { debug, name, }?: {
|
|
512
|
+
debug?: debug$1.Debugger;
|
|
513
|
+
name?: string;
|
|
514
|
+
});
|
|
515
|
+
get relays(): Map<string, NDKRelay>;
|
|
516
|
+
set relayUrls(urls: WebSocket["url"][]);
|
|
517
|
+
private _name;
|
|
518
|
+
get name(): string;
|
|
519
|
+
set name(name: string);
|
|
520
|
+
/**
|
|
521
|
+
* Adds a relay to the pool, and sets a timer to remove it if it is not used within the specified time.
|
|
522
|
+
* @param relay - The relay to add to the pool.
|
|
523
|
+
* @param removeIfUnusedAfter - The time in milliseconds to wait before removing the relay from the pool after it is no longer used.
|
|
524
|
+
*/
|
|
525
|
+
useTemporaryRelay(relay: NDKRelay, removeIfUnusedAfter?: number, filters?: NDKFilter[] | string): void;
|
|
526
|
+
/**
|
|
527
|
+
* Adds a relay to the pool.
|
|
528
|
+
*
|
|
529
|
+
* @param relay - The relay to add to the pool.
|
|
530
|
+
* @param connect - Whether or not to connect to the relay.
|
|
531
|
+
*/
|
|
532
|
+
addRelay(relay: NDKRelay, connect?: boolean): void;
|
|
533
|
+
/**
|
|
534
|
+
* Removes a relay from the pool.
|
|
535
|
+
* @param relayUrl - The URL of the relay to remove.
|
|
536
|
+
* @returns {boolean} True if the relay was removed, false if it was not found.
|
|
537
|
+
*/
|
|
538
|
+
removeRelay(relayUrl: string): boolean;
|
|
539
|
+
/**
|
|
540
|
+
* Checks whether a relay is already connected in the pool.
|
|
541
|
+
*/
|
|
542
|
+
isRelayConnected(url: WebSocket["url"]): boolean;
|
|
543
|
+
/**
|
|
544
|
+
* Fetches a relay from the pool, or creates a new one if it does not exist.
|
|
545
|
+
*
|
|
546
|
+
* New relays will be attempted to be connected.
|
|
547
|
+
*/
|
|
548
|
+
getRelay(url: WebSocket["url"], connect?: boolean, temporary?: boolean, filters?: NDKFilter[]): NDKRelay;
|
|
549
|
+
private handleRelayConnect;
|
|
550
|
+
private handleRelayReady;
|
|
551
|
+
/**
|
|
552
|
+
* Attempts to establish a connection to each relay in the pool.
|
|
553
|
+
*
|
|
554
|
+
* @async
|
|
555
|
+
* @param {number} [timeoutMs] - Optional timeout in milliseconds for each connection attempt.
|
|
556
|
+
* @returns {Promise<void>} A promise that resolves when all connection attempts have completed.
|
|
557
|
+
* @throws {Error} If any of the connection attempts result in an error or timeout.
|
|
558
|
+
*/
|
|
559
|
+
connect(timeoutMs?: number): Promise<void>;
|
|
560
|
+
private checkOnFlappingRelays;
|
|
561
|
+
/**
|
|
562
|
+
* Records when a relay disconnects to detect system-wide events
|
|
563
|
+
*/
|
|
564
|
+
private recordDisconnection;
|
|
565
|
+
/**
|
|
566
|
+
* Checks if multiple relays disconnected simultaneously, indicating a system event
|
|
567
|
+
*/
|
|
568
|
+
private checkForSystemWideDisconnection;
|
|
569
|
+
/**
|
|
570
|
+
* Handles system-wide reconnection (e.g., after sleep/wake or network change)
|
|
571
|
+
*/
|
|
572
|
+
private handleSystemWideReconnection;
|
|
573
|
+
private handleFlapping;
|
|
574
|
+
size(): number;
|
|
575
|
+
/**
|
|
576
|
+
* Returns the status of each relay in the pool.
|
|
577
|
+
* @returns {NDKPoolStats} An object containing the number of relays in each status.
|
|
578
|
+
*/
|
|
579
|
+
stats(): NDKPoolStats;
|
|
580
|
+
connectedRelays(): NDKRelay[];
|
|
581
|
+
permanentAndConnectedRelays(): NDKRelay[];
|
|
582
|
+
/**
|
|
583
|
+
* Get a list of all relay urls in the pool.
|
|
584
|
+
*/
|
|
585
|
+
urls(): string[];
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
/**
|
|
589
|
+
* Why a policy is being asked to authenticate.
|
|
590
|
+
*
|
|
591
|
+
* - `challenge`: the relay sent an AUTH challenge and nothing is waiting on it. Many relays send
|
|
592
|
+
* one on every connection as an offer; declining it is quiet and leaves the connection as is.
|
|
593
|
+
* - `auth-required`: the relay refused a publish or a REQ with `auth-required:` — answering is
|
|
594
|
+
* the only way that publish or REQ gets through.
|
|
595
|
+
* - `manual`: the application called `relay.authenticate()`.
|
|
596
|
+
*/
|
|
597
|
+
type NDKAuthReason = "challenge" | "auth-required" | "manual";
|
|
598
|
+
/**
|
|
599
|
+
* NDKAuthPolicies are functions that are called when a relay requests authentication
|
|
600
|
+
* so that you can define a behavior for your application.
|
|
601
|
+
*
|
|
602
|
+
* @param relay The relay that requested authentication.
|
|
603
|
+
* @param challenge The challenge that the relay sent.
|
|
604
|
+
* @param reason Why authentication is being asked for. See NDKAuthReason.
|
|
605
|
+
*/
|
|
606
|
+
type NDKAuthPolicy = (relay: NDKRelay, challenge: string, reason?: NDKAuthReason) => Promise<boolean | undefined | NDKEvent>;
|
|
607
|
+
|
|
608
|
+
type NDKFilterFingerprint = string;
|
|
609
|
+
|
|
610
|
+
type NDKSubscriptionId = string;
|
|
611
|
+
/**
|
|
612
|
+
* This class monitors active subscriptions.
|
|
613
|
+
*/
|
|
614
|
+
declare class NDKSubscriptionManager {
|
|
615
|
+
subscriptions: Map<NDKSubscriptionId, NDKSubscription>;
|
|
616
|
+
seenEvents: LRUCache<string, NDKRelay[]>;
|
|
617
|
+
constructor();
|
|
618
|
+
add(sub: NDKSubscription): void;
|
|
619
|
+
seenEvent(eventId: NDKEventId, relay: NDKRelay): void;
|
|
620
|
+
/**
|
|
621
|
+
* Whenever an event comes in, this function is called.
|
|
622
|
+
* This function matches the received event against all the
|
|
623
|
+
* known (i.e. active) NDKSubscriptions, and if it matches,
|
|
624
|
+
* it sends the event to the subscription.
|
|
625
|
+
*
|
|
626
|
+
* This is the single place in the codebase that matches
|
|
627
|
+
* incoming events with parties interested in the event.
|
|
628
|
+
*
|
|
629
|
+
* This is also what allows for reactivity in NDK apps, such that
|
|
630
|
+
* whenever an active subscription receives an event that some
|
|
631
|
+
* other active subscription would want to receive, both receive it.
|
|
632
|
+
*
|
|
633
|
+
* TODO This also allows for subscriptions that overlap in meaning
|
|
634
|
+
* to be collapsed into one.
|
|
635
|
+
*
|
|
636
|
+
* I.e. if a subscription with filter: kinds: [1], authors: [alice]
|
|
637
|
+
* is created and EOSEs, and then a subsequent subscription with
|
|
638
|
+
* kinds: [1], authors: [alice] is created, once the second subscription
|
|
639
|
+
* EOSEs we can safely close it, increment its refCount and close it,
|
|
640
|
+
* and when the first subscription receives a new event from Alice this
|
|
641
|
+
* code will make the second subscription receive the event even though
|
|
642
|
+
* it has no active subscription on a relay.
|
|
643
|
+
* @param event Raw event received from a relay
|
|
644
|
+
* @param relay Relay that sent the event
|
|
645
|
+
* @param optimisticPublish Whether the event is coming from an optimistic publish
|
|
646
|
+
*/
|
|
647
|
+
dispatchEvent(event: NostrEvent, relay?: NDKRelay, optimisticPublish?: boolean): void;
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
type Item = {
|
|
651
|
+
subscription: NDKSubscription;
|
|
652
|
+
filters: NDKFilter[];
|
|
653
|
+
};
|
|
654
|
+
declare enum NDKRelaySubscriptionStatus {
|
|
655
|
+
INITIAL = 0,
|
|
656
|
+
/**
|
|
657
|
+
* The subscription is pending execution.
|
|
658
|
+
*/
|
|
659
|
+
PENDING = 1,
|
|
660
|
+
/**
|
|
661
|
+
* The subscription is waiting for the relay to be ready.
|
|
662
|
+
*/
|
|
663
|
+
WAITING = 2,
|
|
664
|
+
/**
|
|
665
|
+
* The subscription is currently running.
|
|
666
|
+
*/
|
|
667
|
+
RUNNING = 3,
|
|
668
|
+
CLOSED = 4
|
|
669
|
+
}
|
|
670
|
+
/**
|
|
671
|
+
* Groups together a number of NDKSubscriptions (as created by the user),
|
|
672
|
+
* filters (as computed internally), executed, or to be executed, within
|
|
673
|
+
* a single specific relay.
|
|
674
|
+
*/
|
|
675
|
+
declare class NDKRelaySubscription {
|
|
676
|
+
fingerprint: NDKFilterFingerprint;
|
|
677
|
+
items: Map<NDKSubscriptionInternalId, Item>;
|
|
678
|
+
topSubManager: NDKSubscriptionManager;
|
|
679
|
+
debug: debug.Debugger;
|
|
680
|
+
/**
|
|
681
|
+
* Tracks the status of this REQ.
|
|
682
|
+
*/
|
|
683
|
+
status: NDKRelaySubscriptionStatus;
|
|
684
|
+
onClose?: (sub: NDKRelaySubscription) => void;
|
|
685
|
+
private relay;
|
|
686
|
+
/**
|
|
687
|
+
* Whether this subscription has reached EOSE.
|
|
688
|
+
*/
|
|
689
|
+
private eosed;
|
|
690
|
+
/** Whether this REQ already re-sent after a CLOSED "auth-required:". */
|
|
691
|
+
private authRetried;
|
|
692
|
+
/**
|
|
693
|
+
* Timeout at which this subscription will
|
|
694
|
+
* start executing.
|
|
695
|
+
*/
|
|
696
|
+
private executionTimer?;
|
|
697
|
+
/**
|
|
698
|
+
* Track the time at which this subscription will fire.
|
|
699
|
+
*/
|
|
700
|
+
private fireTime?;
|
|
701
|
+
/**
|
|
702
|
+
* The delay type that the current fireTime was calculated with.
|
|
703
|
+
*/
|
|
704
|
+
private delayType?;
|
|
705
|
+
/**
|
|
706
|
+
* The filters that have been executed.
|
|
707
|
+
*/
|
|
708
|
+
executeFilters?: NDKFilter[];
|
|
709
|
+
readonly id: string;
|
|
710
|
+
/**
|
|
711
|
+
*
|
|
712
|
+
* @param fingerprint The fingerprint of this subscription.
|
|
713
|
+
*/
|
|
714
|
+
constructor(relay: NDKRelay, fingerprint: NDKFilterFingerprint | null, topSubManager: NDKSubscriptionManager);
|
|
715
|
+
private _subId?;
|
|
716
|
+
get subId(): string;
|
|
717
|
+
private subIdParts;
|
|
718
|
+
private addSubIdPart;
|
|
719
|
+
addItem(subscription: NDKSubscription, filters: NDKFilter[]): void;
|
|
720
|
+
/**
|
|
721
|
+
* A subscription has been closed, remove it from the list of items.
|
|
722
|
+
* @param subscription
|
|
723
|
+
*/
|
|
724
|
+
removeItem(subscription: NDKSubscription): void;
|
|
725
|
+
private close;
|
|
726
|
+
cleanup(): void;
|
|
727
|
+
private evaluateExecutionPlan;
|
|
728
|
+
private schedule;
|
|
729
|
+
private executeOnRelayReady;
|
|
730
|
+
private finalizeSubId;
|
|
731
|
+
private reExecuteAfterAuth;
|
|
732
|
+
private execute;
|
|
733
|
+
/**
|
|
734
|
+
* Sends this REQ again on a new connection, if anyone still wants it.
|
|
735
|
+
*/
|
|
736
|
+
resubscribe(): void;
|
|
737
|
+
onstart(): void;
|
|
738
|
+
onevent(event: NostrEvent): void;
|
|
739
|
+
oneose(subId: string): void;
|
|
740
|
+
onclose(_reason?: string): void;
|
|
741
|
+
/**
|
|
742
|
+
* The relay ended this REQ (NIP-01 CLOSED). "auth-required:" is answered once
|
|
743
|
+
* when this connection can authenticate; anything else is final for this relay.
|
|
744
|
+
*/
|
|
745
|
+
onclosed(reason?: string): void;
|
|
746
|
+
private closedByRelay;
|
|
747
|
+
/**
|
|
748
|
+
* Grabs the filters from all the subscriptions
|
|
749
|
+
* and merges them into a single filter.
|
|
750
|
+
*/
|
|
751
|
+
private compileFilters;
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
declare class NDKRelayConnectivity {
|
|
755
|
+
private ndkRelay;
|
|
756
|
+
private ws?;
|
|
757
|
+
private _status;
|
|
758
|
+
private timeoutMs?;
|
|
759
|
+
private connectedAt?;
|
|
760
|
+
private _connectionStats;
|
|
761
|
+
private debug;
|
|
762
|
+
netDebug?: NDKNetDebug;
|
|
763
|
+
private connectTimeout;
|
|
764
|
+
private reconnectTimeout;
|
|
765
|
+
private ndk?;
|
|
766
|
+
openSubs: Map<string, NDKRelaySubscription>;
|
|
767
|
+
private openCountRequests;
|
|
768
|
+
private openEventPublishes;
|
|
769
|
+
private pendingAuthPublishes;
|
|
770
|
+
/** Publishes the relay refused with auth-required, held until this connection authenticates.
|
|
771
|
+
* Only these are re-sent after AUTH, or rejected when it fails — not every publish in flight. */
|
|
772
|
+
private authBlocked;
|
|
773
|
+
/** Called when a publish starts waiting on AUTH, so its caller can extend its own timeout. */
|
|
774
|
+
private authWaitHooks;
|
|
775
|
+
/** Something asked to authenticate before the relay sent a challenge, and why. */
|
|
776
|
+
private authWanted?;
|
|
777
|
+
private serial;
|
|
778
|
+
baseEoseTimeout: number;
|
|
779
|
+
/** The latest NIP-42 challenge on the current connection. */
|
|
780
|
+
authChallenge?: string;
|
|
781
|
+
private authInFlight?;
|
|
782
|
+
/** How long to wait for the relay's OK on an AUTH event, and for a signer to sign it. */
|
|
783
|
+
authTimeoutMs: number;
|
|
784
|
+
/** Silence after which the keepalive pings the relay. */
|
|
785
|
+
keepaliveIdleMs: number;
|
|
786
|
+
private pings;
|
|
787
|
+
private pingInFlight?;
|
|
788
|
+
/** Subscriptions running when the last connection dropped; re-sent on the next one. */
|
|
789
|
+
private retiredSubs;
|
|
790
|
+
private keepalive?;
|
|
791
|
+
private wsStateMonitor?;
|
|
792
|
+
private sleepDetector?;
|
|
793
|
+
private lastSleepCheck;
|
|
794
|
+
private lastMessageSent;
|
|
795
|
+
private wasIdle;
|
|
796
|
+
constructor(ndkRelay: NDKRelay, ndk?: NDK);
|
|
797
|
+
/**
|
|
798
|
+
* Sets up keepalive, WebSocket state monitoring, and sleep detection
|
|
799
|
+
*/
|
|
800
|
+
private setupMonitoring;
|
|
801
|
+
/**
|
|
802
|
+
* Handles detection of a stale connection by cleaning up and triggering reconnection.
|
|
803
|
+
*/
|
|
804
|
+
private handleStaleConnection;
|
|
805
|
+
/**
|
|
806
|
+
* Handles possible system wake event
|
|
807
|
+
*/
|
|
808
|
+
private handlePossibleWake;
|
|
809
|
+
/**
|
|
810
|
+
* Resets the reconnection state for system-wide events
|
|
811
|
+
* Used by NDKPool when detecting system sleep/wake
|
|
812
|
+
*/
|
|
813
|
+
resetReconnectionState(): void;
|
|
814
|
+
/**
|
|
815
|
+
* Connects to the NDK relay and handles the connection lifecycle.
|
|
816
|
+
*
|
|
817
|
+
* This method attempts to establish a WebSocket connection to the NDK relay specified in the `ndkRelay` object.
|
|
818
|
+
* If the connection is successful, it updates the connection statistics, sets the connection status to `CONNECTED`,
|
|
819
|
+
* and emits `connect` and `ready` events on the `ndkRelay` object.
|
|
820
|
+
*
|
|
821
|
+
* If the connection attempt fails, it handles the error by either initiating a reconnection attempt or emitting a
|
|
822
|
+
* `delayed-connect` event on the `ndkRelay` object, depending on the `reconnect` parameter.
|
|
823
|
+
*
|
|
824
|
+
* @param timeoutMs - The timeout in milliseconds for the connection attempt. If not provided, the default timeout from the `ndkRelay` object is used.
|
|
825
|
+
* @param reconnect - Indicates whether a reconnection should be attempted if the connection fails. Defaults to `true`.
|
|
826
|
+
* @returns A Promise that resolves when the connection is established, or rejects if the connection fails.
|
|
827
|
+
*/
|
|
828
|
+
connect(timeoutMs?: number, reconnect?: boolean): Promise<void>;
|
|
829
|
+
/**
|
|
830
|
+
* Disconnects the WebSocket connection to the NDK relay.
|
|
831
|
+
* This method sets the connection status to `NDKRelayStatus.DISCONNECTING`,
|
|
832
|
+
* attempts to close the WebSocket connection, and sets the status to
|
|
833
|
+
* `NDKRelayStatus.DISCONNECTED` if the disconnect operation fails.
|
|
834
|
+
*/
|
|
835
|
+
disconnect(): void;
|
|
836
|
+
/**
|
|
837
|
+
* Handles the error that occurred when attempting to connect to the NDK relay.
|
|
838
|
+
* If `reconnect` is `true`, this method will initiate a reconnection attempt.
|
|
839
|
+
* Otherwise, it will emit a `delayed-connect` event on the `ndkRelay` object,
|
|
840
|
+
* indicating that a reconnection should be attempted after a delay.
|
|
841
|
+
*
|
|
842
|
+
* @param reconnect - Indicates whether a reconnection should be attempted.
|
|
843
|
+
*/
|
|
844
|
+
onConnectionError(reconnect: boolean): void;
|
|
845
|
+
/**
|
|
846
|
+
* Handles the connection event when the WebSocket connection is established.
|
|
847
|
+
* This method is called when the WebSocket connection is successfully opened.
|
|
848
|
+
* It clears any existing connection and reconnection timeouts, updates the connection statistics,
|
|
849
|
+
* sets the connection status to `CONNECTED`, and emits `connect` and `ready` events on the `ndkRelay` object.
|
|
850
|
+
*/
|
|
851
|
+
private onConnect;
|
|
852
|
+
/**
|
|
853
|
+
* Handles the disconnection event when the WebSocket connection is closed.
|
|
854
|
+
* This method is called when the WebSocket connection is successfully closed.
|
|
855
|
+
* It updates the connection statistics, sets the connection status to `DISCONNECTED`,
|
|
856
|
+
* initiates a reconnection attempt if we didn't disconnect ourselves,
|
|
857
|
+
* and emits a `disconnect` event on the `ndkRelay` object.
|
|
858
|
+
*/
|
|
859
|
+
private onDisconnect;
|
|
860
|
+
/**
|
|
861
|
+
* Handles incoming messages from the NDK relay WebSocket connection.
|
|
862
|
+
* This method is called whenever a message is received from the relay.
|
|
863
|
+
* It parses the message data and dispatches the appropriate handling logic based on the message type.
|
|
864
|
+
*
|
|
865
|
+
* @param event - The MessageEvent containing the received message data.
|
|
866
|
+
*/
|
|
867
|
+
private onMessage;
|
|
868
|
+
/**
|
|
869
|
+
* Handles an authentication request from the NDK relay.
|
|
870
|
+
*
|
|
871
|
+
* If an authentication policy is configured, it will be used to authenticate the connection.
|
|
872
|
+
* Otherwise, the `auth` event will be emitted to allow the application to handle the authentication.
|
|
873
|
+
*
|
|
874
|
+
* @param challenge - The authentication challenge provided by the NDK relay.
|
|
875
|
+
*/
|
|
876
|
+
private onAuthRequested;
|
|
877
|
+
private get authPolicy();
|
|
878
|
+
/**
|
|
879
|
+
* Answers the relay's current NIP-42 challenge with the auth policy.
|
|
880
|
+
*
|
|
881
|
+
* Resolves true once the relay accepts the AUTH event (or the connection is
|
|
882
|
+
* already authenticated), false when there is no challenge or policy, the policy
|
|
883
|
+
* declines, or the relay rejects it. Concurrent calls share one attempt.
|
|
884
|
+
*/
|
|
885
|
+
authenticate(reason?: NDKAuthReason): Promise<boolean>;
|
|
886
|
+
private runAuth;
|
|
887
|
+
private signAuthEvent;
|
|
888
|
+
private withAuthTimeout;
|
|
889
|
+
/**
|
|
890
|
+
* Handles errors that occur on the WebSocket connection to the relay.
|
|
891
|
+
* @param error - The error or event that occurred.
|
|
892
|
+
*/
|
|
893
|
+
private onError;
|
|
894
|
+
/**
|
|
895
|
+
* Gets the current status of the NDK relay connection.
|
|
896
|
+
* @returns {NDKRelayStatus} The current status of the NDK relay connection.
|
|
897
|
+
*/
|
|
898
|
+
get status(): NDKRelayStatus;
|
|
899
|
+
/**
|
|
900
|
+
* Checks if the NDK relay connection is currently available.
|
|
901
|
+
* @returns {boolean} `true` if the relay connection is in the `CONNECTED` status, `false` otherwise.
|
|
902
|
+
*/
|
|
903
|
+
isAvailable(): boolean;
|
|
904
|
+
/**
|
|
905
|
+
* Checks if the NDK relay connection is flapping, which means the connection is rapidly
|
|
906
|
+
* disconnecting and reconnecting. This is determined by analyzing the durations of the
|
|
907
|
+
* last three connection attempts. If the standard deviation of the durations is less
|
|
908
|
+
* than 1000 milliseconds, the connection is considered to be flapping.
|
|
909
|
+
*
|
|
910
|
+
* @returns {boolean} `true` if the connection is flapping, `false` otherwise.
|
|
911
|
+
*/
|
|
912
|
+
private isFlapping;
|
|
913
|
+
/**
|
|
914
|
+
* Handles a notice received from the NDK relay.
|
|
915
|
+
* If the notice indicates the relay is complaining (e.g. "too many" or "maximum"),
|
|
916
|
+
* the method disconnects from the relay and attempts to reconnect after a 2-second delay.
|
|
917
|
+
* A debug message is logged with the relay URL and the notice text.
|
|
918
|
+
* The "notice" event is emitted on the ndkRelay instance with the notice text.
|
|
919
|
+
*
|
|
920
|
+
* @param notice - The notice text received from the NDK relay.
|
|
921
|
+
*/
|
|
922
|
+
private onNotice;
|
|
923
|
+
/**
|
|
924
|
+
* Attempts to reconnect to the NDK relay after a connection is lost.
|
|
925
|
+
* This function is called recursively to handle multiple reconnection attempts.
|
|
926
|
+
* It checks if the relay is flapping and emits a "flapping" event if so.
|
|
927
|
+
* It then calculates a delay before the next reconnection attempt based on the number of previous attempts.
|
|
928
|
+
* The function sets a timeout to execute the next reconnection attempt after the calculated delay.
|
|
929
|
+
* If the maximum number of reconnection attempts is reached, a debug message is logged.
|
|
930
|
+
*
|
|
931
|
+
* @param attempt - The current attempt number (default is 0).
|
|
932
|
+
*/
|
|
933
|
+
private handleReconnection;
|
|
934
|
+
/**
|
|
935
|
+
* Sends a message to the NDK relay if the connection is in the CONNECTED state and the WebSocket is open.
|
|
936
|
+
* If the connection is not in the CONNECTED state or the WebSocket is not open, logs a debug message and throws an error.
|
|
937
|
+
*
|
|
938
|
+
* @param message - The message to send to the NDK relay.
|
|
939
|
+
* @throws {Error} If attempting to send on a closed relay connection.
|
|
940
|
+
*/
|
|
941
|
+
send(message: string): Promise<void>;
|
|
942
|
+
/**
|
|
943
|
+
* Authenticates the NDK event by sending it to the NDK relay and returning a promise that resolves with the result.
|
|
944
|
+
*
|
|
945
|
+
* @param event - The NDK event to authenticate.
|
|
946
|
+
* @returns A promise that resolves with the authentication result.
|
|
947
|
+
*/
|
|
948
|
+
private auth;
|
|
949
|
+
/**
|
|
950
|
+
* Clears all pending publish promises by rejecting them with the provided error.
|
|
951
|
+
* This is called on disconnection to prevent memory leaks and ensure promises
|
|
952
|
+
* don't hang indefinitely.
|
|
953
|
+
* @param error The error to reject the promises with
|
|
954
|
+
*/
|
|
955
|
+
private clearPendingPublishes;
|
|
956
|
+
/**
|
|
957
|
+
* Retries all pending publishes that failed due to auth-required.
|
|
958
|
+
* Called after successful authentication.
|
|
959
|
+
*/
|
|
960
|
+
private retryPendingAuthPublishes;
|
|
961
|
+
/**
|
|
962
|
+
* Rejects all pending publishes that failed due to auth-required.
|
|
963
|
+
* Called when authentication fails.
|
|
964
|
+
*/
|
|
965
|
+
private rejectPendingAuthPublishes;
|
|
966
|
+
private forgetPublish;
|
|
967
|
+
/**
|
|
968
|
+
* Publishes an NDK event to the relay and returns a promise that resolves with the result.
|
|
969
|
+
*
|
|
970
|
+
* @param event - The NDK event to publish.
|
|
971
|
+
* @returns A promise that resolves with the result of the event publication.
|
|
972
|
+
* @throws {Error} If attempting to publish on a closed relay connection.
|
|
973
|
+
*/
|
|
974
|
+
publish(event: NostrEvent, onAuthWait?: () => void): Promise<string>;
|
|
975
|
+
/**
|
|
976
|
+
* Counts the number of events that match the provided filters.
|
|
977
|
+
*
|
|
978
|
+
* @param filters - The filters to apply to the count request.
|
|
979
|
+
* @param params - An optional object containing a custom id for the count request.
|
|
980
|
+
* @returns A promise that resolves with the count result including optional HLL data.
|
|
981
|
+
* @throws {Error} If attempting to send the count request on a closed relay connection.
|
|
982
|
+
*/
|
|
983
|
+
count(filters: NDKFilter[], params: {
|
|
984
|
+
id?: string | null;
|
|
985
|
+
}): Promise<NDKCountResult>;
|
|
986
|
+
close(subId: string, reason?: string): void;
|
|
987
|
+
/**
|
|
988
|
+
* Subscribes to the NDK relay with the provided filters and parameters.
|
|
989
|
+
*
|
|
990
|
+
* @param filters - The filters to apply to the subscription.
|
|
991
|
+
* @param params - The subscription parameters, including an optional custom id.
|
|
992
|
+
* @returns A new NDKRelaySubscription instance.
|
|
993
|
+
*/
|
|
994
|
+
/**
|
|
995
|
+
* Asks the relay something it must answer (a REQ for nothing) and resolves true
|
|
996
|
+
* when it answers that REQ — EVENT, EOSE or CLOSED — or false after `timeoutMs`.
|
|
997
|
+
* Other traffic on the socket doesn't count. Concurrent calls share one probe.
|
|
998
|
+
*/
|
|
999
|
+
ping(timeoutMs?: number): Promise<boolean>;
|
|
1000
|
+
/**
|
|
1001
|
+
* Replaces the current socket with a new one, also while the old one is still
|
|
1002
|
+
* closing. Running subscriptions are re-sent on the new connection.
|
|
1003
|
+
*/
|
|
1004
|
+
reconnect(timeoutMs?: number): Promise<void>;
|
|
1005
|
+
/** Closes the socket without letting its later events reach this connection. */
|
|
1006
|
+
private dropSocket;
|
|
1007
|
+
/** The REQs on this connection end with it; running ones are re-sent on the next one. */
|
|
1008
|
+
private retireConnection;
|
|
1009
|
+
req(relaySub: NDKRelaySubscription): void;
|
|
1010
|
+
/**
|
|
1011
|
+
* Utility functions to update the connection stats.
|
|
1012
|
+
*/
|
|
1013
|
+
private updateConnectionStats;
|
|
1014
|
+
/** Returns the connection stats. */
|
|
1015
|
+
get connectionStats(): NDKRelayConnectionStats;
|
|
1016
|
+
/** Returns the relay URL */
|
|
1017
|
+
get url(): WebSocket["url"];
|
|
1018
|
+
get connected(): boolean;
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
/**
|
|
1022
|
+
* NIP-11: Relay Information Document
|
|
1023
|
+
* https://github.com/nostr-protocol/nips/blob/master/11.md
|
|
1024
|
+
*/
|
|
1025
|
+
interface NDKRelayInformation {
|
|
1026
|
+
name?: string;
|
|
1027
|
+
description?: string;
|
|
1028
|
+
banner?: string;
|
|
1029
|
+
icon?: string;
|
|
1030
|
+
pubkey?: string;
|
|
1031
|
+
contact?: string;
|
|
1032
|
+
supported_nips?: number[];
|
|
1033
|
+
software?: string;
|
|
1034
|
+
version?: string;
|
|
1035
|
+
privacy_policy?: string;
|
|
1036
|
+
terms_of_service?: string;
|
|
1037
|
+
limitation?: {
|
|
1038
|
+
max_message_length?: number;
|
|
1039
|
+
max_subscriptions?: number;
|
|
1040
|
+
max_subid_length?: number;
|
|
1041
|
+
max_limit?: number;
|
|
1042
|
+
max_event_tags?: number;
|
|
1043
|
+
max_content_length?: number;
|
|
1044
|
+
min_pow_difficulty?: number;
|
|
1045
|
+
auth_required?: boolean;
|
|
1046
|
+
payment_required?: boolean;
|
|
1047
|
+
restricted_writes?: boolean;
|
|
1048
|
+
created_at_lower_limit?: number;
|
|
1049
|
+
created_at_upper_limit?: number;
|
|
1050
|
+
default_limit?: number;
|
|
1051
|
+
};
|
|
1052
|
+
retention?: Array<{
|
|
1053
|
+
kinds?: Array<number | [number, number]>;
|
|
1054
|
+
time?: number | null;
|
|
1055
|
+
count?: number;
|
|
1056
|
+
}>;
|
|
1057
|
+
relay_countries?: string[];
|
|
1058
|
+
language_tags?: string[];
|
|
1059
|
+
tags?: string[];
|
|
1060
|
+
posting_policy?: string;
|
|
1061
|
+
payments_url?: string;
|
|
1062
|
+
fees?: {
|
|
1063
|
+
admission?: Array<{
|
|
1064
|
+
amount: number;
|
|
1065
|
+
unit: string;
|
|
1066
|
+
}>;
|
|
1067
|
+
subscription?: Array<{
|
|
1068
|
+
amount: number;
|
|
1069
|
+
unit: string;
|
|
1070
|
+
period: number;
|
|
1071
|
+
}>;
|
|
1072
|
+
publication?: Array<{
|
|
1073
|
+
kinds?: number[];
|
|
1074
|
+
amount: number;
|
|
1075
|
+
unit: string;
|
|
1076
|
+
}>;
|
|
1077
|
+
};
|
|
1078
|
+
[key: string]: unknown;
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
type NDKRelayScore = number;
|
|
1082
|
+
|
|
1083
|
+
/**
|
|
1084
|
+
* The subscription manager of an NDKRelay is in charge of orchestrating the subscriptions
|
|
1085
|
+
* that are created and closed in a given relay.
|
|
1086
|
+
*
|
|
1087
|
+
* The manager is responsible for:
|
|
1088
|
+
* * restarting subscriptions when they are unexpectedly closed
|
|
1089
|
+
* * scheduling subscriptions that are received before the relay is connected
|
|
1090
|
+
* * grouping similar subscriptions to be compiled into individual REQs
|
|
1091
|
+
*/
|
|
1092
|
+
declare class NDKRelaySubscriptionManager {
|
|
1093
|
+
private relay;
|
|
1094
|
+
subscriptions: Map<NDKFilterFingerprint, NDKRelaySubscription[]>;
|
|
1095
|
+
private generalSubManager;
|
|
1096
|
+
/**
|
|
1097
|
+
* @param relay - The relay instance.
|
|
1098
|
+
* @param generalSubManager - The subscription manager instance.
|
|
1099
|
+
*/
|
|
1100
|
+
constructor(relay: NDKRelay, generalSubManager: NDKSubscriptionManager);
|
|
1101
|
+
/**
|
|
1102
|
+
* Adds a subscription to the manager.
|
|
1103
|
+
*/
|
|
1104
|
+
addSubscription(sub: NDKSubscription, filters: NDKFilter[]): void;
|
|
1105
|
+
createSubscription(_sub: NDKSubscription, _filters: NDKFilter[], fingerprint?: NDKFilterFingerprint): NDKRelaySubscription;
|
|
1106
|
+
private onRelaySubscriptionClose;
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1109
|
+
/**
|
|
1110
|
+
* Protocol handler function type for handling custom relay messages.
|
|
1111
|
+
* @param relay The relay that received the message
|
|
1112
|
+
* @param message The parsed message array from the relay
|
|
1113
|
+
*/
|
|
1114
|
+
type NDKProtocolHandler = (relay: NDKRelay, message: unknown[]) => void;
|
|
1115
|
+
declare enum NDKRelayStatus {
|
|
1116
|
+
DISCONNECTING = 0,// 0
|
|
1117
|
+
DISCONNECTED = 1,// 1
|
|
1118
|
+
RECONNECTING = 2,// 2
|
|
1119
|
+
FLAPPING = 3,// 3
|
|
1120
|
+
CONNECTING = 4,// 4
|
|
1121
|
+
CONNECTED = 5,// 5
|
|
1122
|
+
AUTH_REQUESTED = 6,// 6
|
|
1123
|
+
AUTHENTICATING = 7,// 7
|
|
1124
|
+
AUTHENTICATED = 8
|
|
1125
|
+
}
|
|
1126
|
+
interface NDKRelayConnectionStats {
|
|
1127
|
+
/**
|
|
1128
|
+
* The number of times a connection has been attempted.
|
|
1129
|
+
*/
|
|
1130
|
+
attempts: number;
|
|
1131
|
+
/**
|
|
1132
|
+
* The number of times a connection has been successfully established.
|
|
1133
|
+
*/
|
|
1134
|
+
success: number;
|
|
1135
|
+
/**
|
|
1136
|
+
* The durations of the last 100 connections in milliseconds.
|
|
1137
|
+
*/
|
|
1138
|
+
durations: number[];
|
|
1139
|
+
/**
|
|
1140
|
+
* The time the current connection was established in milliseconds.
|
|
1141
|
+
*/
|
|
1142
|
+
connectedAt?: number;
|
|
1143
|
+
/**
|
|
1144
|
+
* Timestamp of the next reconnection attempt.
|
|
1145
|
+
*/
|
|
1146
|
+
nextReconnectAt?: number;
|
|
1147
|
+
/**
|
|
1148
|
+
* Signature validation ratio for this relay.
|
|
1149
|
+
* @see NDKRelayOptions.validationRatio
|
|
1150
|
+
*/
|
|
1151
|
+
validationRatio?: number;
|
|
1152
|
+
}
|
|
1153
|
+
/**
|
|
1154
|
+
* The NDKRelay class represents a connection to a relay.
|
|
1155
|
+
*
|
|
1156
|
+
* @emits NDKRelay#connect
|
|
1157
|
+
* @emits NDKRelay#ready
|
|
1158
|
+
* @emits NDKRelay#disconnect
|
|
1159
|
+
* @emits NDKRelay#notice
|
|
1160
|
+
* @emits NDKRelay#event
|
|
1161
|
+
* @emits NDKRelay#published when an event is published to the relay
|
|
1162
|
+
* @emits NDKRelay#publish:failed when an event fails to publish to the relay
|
|
1163
|
+
* @emits NDKRelay#eose when the relay has reached the end of stored events
|
|
1164
|
+
* @emits NDKRelay#auth when the relay requires authentication
|
|
1165
|
+
* @emits NDKRelay#authed when the relay has authenticated
|
|
1166
|
+
* @emits NDKRelay#delayed-connect when the relay will wait before reconnecting
|
|
1167
|
+
*/
|
|
1168
|
+
declare class NDKRelay extends EventEmitter<{
|
|
1169
|
+
connect: () => void;
|
|
1170
|
+
ready: () => void;
|
|
1171
|
+
/**
|
|
1172
|
+
* Emitted when the relay has reached the end of stored events.
|
|
1173
|
+
*/
|
|
1174
|
+
disconnect: () => void;
|
|
1175
|
+
flapping: (stats: NDKRelayConnectionStats) => void;
|
|
1176
|
+
notice: (notice: string) => void;
|
|
1177
|
+
auth: (challenge: string) => void;
|
|
1178
|
+
authed: () => void;
|
|
1179
|
+
"auth:failed": (error: Error) => void;
|
|
1180
|
+
published: (event: NDKEvent) => void;
|
|
1181
|
+
"publish:failed": (event: NDKEvent, error: Error) => void;
|
|
1182
|
+
"delayed-connect": (delayInMs: number) => void;
|
|
1183
|
+
}> {
|
|
1184
|
+
readonly url: WebSocket["url"];
|
|
1185
|
+
readonly scores: Map<NDKUser, NDKRelayScore>;
|
|
1186
|
+
connectivity: NDKRelayConnectivity;
|
|
1187
|
+
subs: NDKRelaySubscriptionManager;
|
|
1188
|
+
private publisher;
|
|
1189
|
+
authPolicy?: NDKAuthPolicy;
|
|
1190
|
+
/**
|
|
1191
|
+
* Protocol handlers for custom relay message types (e.g., NEG-OPEN, NEG-MSG).
|
|
1192
|
+
* Allows external packages to handle non-standard relay messages.
|
|
1193
|
+
*/
|
|
1194
|
+
private protocolHandlers;
|
|
1195
|
+
/**
|
|
1196
|
+
* Cached relay information from NIP-11.
|
|
1197
|
+
*/
|
|
1198
|
+
private _relayInfo?;
|
|
1199
|
+
/**
|
|
1200
|
+
* The lowest validation ratio this relay can reach.
|
|
1201
|
+
*/
|
|
1202
|
+
lowestValidationRatio?: number;
|
|
1203
|
+
/**
|
|
1204
|
+
* Current validation ratio this relay is targeting.
|
|
1205
|
+
*/
|
|
1206
|
+
targetValidationRatio?: number;
|
|
1207
|
+
validationRatioFn?: (relay: NDKRelay, validatedCount: number, nonValidatedCount: number) => number;
|
|
1208
|
+
/**
|
|
1209
|
+
* This tracks events that have been seen by this relay
|
|
1210
|
+
* with a valid signature.
|
|
1211
|
+
*/
|
|
1212
|
+
validatedEventCount: number;
|
|
1213
|
+
/**
|
|
1214
|
+
* This tracks events that have been seen by this relay
|
|
1215
|
+
* but have not been validated.
|
|
1216
|
+
*/
|
|
1217
|
+
nonValidatedEventCount: number;
|
|
1218
|
+
/**
|
|
1219
|
+
* Whether this relay is trusted.
|
|
1220
|
+
*
|
|
1221
|
+
* Trusted relay's events do not get their signature verified.
|
|
1222
|
+
*/
|
|
1223
|
+
trusted: boolean;
|
|
1224
|
+
complaining: boolean;
|
|
1225
|
+
readonly debug: debug$1.Debugger;
|
|
1226
|
+
static defaultValidationRatioUpdateFn: (relay: NDKRelay, validatedCount: number, _nonValidatedCount: number) => number;
|
|
1227
|
+
constructor(url: WebSocket["url"], authPolicy: NDKAuthPolicy | undefined, ndk: NDK);
|
|
1228
|
+
private updateValidationRatio;
|
|
1229
|
+
get status(): NDKRelayStatus;
|
|
1230
|
+
get connectionStats(): NDKRelayConnectionStats;
|
|
1231
|
+
/**
|
|
1232
|
+
* The NIP-42 challenge the relay sent on the current connection, if any.
|
|
1233
|
+
*/
|
|
1234
|
+
get authChallenge(): string | undefined;
|
|
1235
|
+
/**
|
|
1236
|
+
* Answers the relay's NIP-42 challenge with this relay's auth policy (or the
|
|
1237
|
+
* NDK default). Resolves true once the relay accepts, false otherwise.
|
|
1238
|
+
*
|
|
1239
|
+
* With no challenge on the connection yet, the one that comes is answered as soon as it
|
|
1240
|
+
* arrives (the policy sees `reason` rather than an unprompted `challenge`).
|
|
1241
|
+
*/
|
|
1242
|
+
authenticate(reason?: NDKAuthReason): Promise<boolean>;
|
|
1243
|
+
/**
|
|
1244
|
+
* Resolves true if the relay answers a probe REQ within `timeoutMs` (default 3s).
|
|
1245
|
+
* Use it to tell a silent-but-alive socket from a dead one.
|
|
1246
|
+
*/
|
|
1247
|
+
ping(timeoutMs?: number): Promise<boolean>;
|
|
1248
|
+
/**
|
|
1249
|
+
* Replaces this relay's socket with a new one (also while it is closing) and
|
|
1250
|
+
* resolves once the new one is ready. Running subscriptions are re-sent.
|
|
1251
|
+
*/
|
|
1252
|
+
reconnect(timeoutMs?: number): Promise<void>;
|
|
1253
|
+
/**
|
|
1254
|
+
* Connects to the relay.
|
|
1255
|
+
*/
|
|
1256
|
+
connect(timeoutMs?: number, reconnect?: boolean): Promise<void>;
|
|
1257
|
+
/**
|
|
1258
|
+
* Disconnects from the relay.
|
|
1259
|
+
*/
|
|
1260
|
+
disconnect(): void;
|
|
1261
|
+
/**
|
|
1262
|
+
* Queues or executes the subscription of a specific set of filters
|
|
1263
|
+
* within this relay.
|
|
1264
|
+
*
|
|
1265
|
+
* @param subscription NDKSubscription this filters belong to.
|
|
1266
|
+
* @param filters Filters to execute
|
|
1267
|
+
*/
|
|
1268
|
+
subscribe(subscription: NDKSubscription, filters: NDKFilter[]): void;
|
|
1269
|
+
/**
|
|
1270
|
+
* Publishes an event to the relay with an optional timeout.
|
|
1271
|
+
*
|
|
1272
|
+
* If the relay is not connected, the event will be published when the relay connects,
|
|
1273
|
+
* unless the timeout is reached before the relay connects.
|
|
1274
|
+
*
|
|
1275
|
+
* @param event The event to publish
|
|
1276
|
+
* @param timeoutMs The timeout for the publish operation in milliseconds
|
|
1277
|
+
* @returns A promise that resolves when the event has been published or rejects if the operation times out
|
|
1278
|
+
*/
|
|
1279
|
+
publish(event: NDKEvent, timeoutMs?: number): Promise<boolean>;
|
|
1280
|
+
referenceTags(): NDKTag[];
|
|
1281
|
+
addValidatedEvent(): void;
|
|
1282
|
+
addNonValidatedEvent(): void;
|
|
1283
|
+
/**
|
|
1284
|
+
* The current validation ratio this relay has achieved.
|
|
1285
|
+
*/
|
|
1286
|
+
get validationRatio(): number;
|
|
1287
|
+
shouldValidateEvent(): boolean;
|
|
1288
|
+
get connected(): boolean;
|
|
1289
|
+
req: (relaySub: NDKRelaySubscription) => void;
|
|
1290
|
+
close: (subId: string) => void;
|
|
1291
|
+
/**
|
|
1292
|
+
* Registers a protocol handler for a specific message type.
|
|
1293
|
+
* This allows external packages to handle custom relay messages (e.g., NIP-77 NEG-* messages).
|
|
1294
|
+
*
|
|
1295
|
+
* @param messageType The message type to handle (e.g., "NEG-OPEN", "NEG-MSG")
|
|
1296
|
+
* @param handler The function to call when a message of this type is received
|
|
1297
|
+
*
|
|
1298
|
+
* @example
|
|
1299
|
+
* ```typescript
|
|
1300
|
+
* relay.registerProtocolHandler('NEG-MSG', (relay, message) => {
|
|
1301
|
+
* console.log('Received NEG-MSG:', message);
|
|
1302
|
+
* });
|
|
1303
|
+
* ```
|
|
1304
|
+
*/
|
|
1305
|
+
registerProtocolHandler(messageType: string, handler: NDKProtocolHandler): void;
|
|
1306
|
+
/**
|
|
1307
|
+
* Unregisters a protocol handler for a specific message type.
|
|
1308
|
+
*
|
|
1309
|
+
* @param messageType The message type to stop handling
|
|
1310
|
+
*/
|
|
1311
|
+
unregisterProtocolHandler(messageType: string): void;
|
|
1312
|
+
/**
|
|
1313
|
+
* Checks if a protocol handler is registered for a message type.
|
|
1314
|
+
* This is used internally by the connectivity layer to route messages.
|
|
1315
|
+
*
|
|
1316
|
+
* @internal
|
|
1317
|
+
* @param messageType The message type to check
|
|
1318
|
+
* @returns The handler function if registered, undefined otherwise
|
|
1319
|
+
*/
|
|
1320
|
+
getProtocolHandler(messageType: string): NDKProtocolHandler | undefined;
|
|
1321
|
+
/**
|
|
1322
|
+
* Fetches relay information (NIP-11) from the relay.
|
|
1323
|
+
* Results are cached in persistent storage when cache adapter is available (24-hour TTL).
|
|
1324
|
+
* Falls back to in-memory cache. Pass force=true to bypass all caches.
|
|
1325
|
+
*
|
|
1326
|
+
* @param force Force a fresh fetch, bypassing all caches
|
|
1327
|
+
* @returns The relay information document
|
|
1328
|
+
* @throws Error if the fetch fails
|
|
1329
|
+
*
|
|
1330
|
+
* @example
|
|
1331
|
+
* ```typescript
|
|
1332
|
+
* const info = await relay.fetchInfo();
|
|
1333
|
+
* console.log(`Relay: ${info.name}`);
|
|
1334
|
+
* console.log(`Supported NIPs: ${info.supported_nips?.join(', ')}`);
|
|
1335
|
+
* ```
|
|
1336
|
+
*/
|
|
1337
|
+
fetchInfo(force?: boolean): Promise<NDKRelayInformation>;
|
|
1338
|
+
/**
|
|
1339
|
+
* Returns cached relay information if available, undefined otherwise.
|
|
1340
|
+
* Use fetchInfo() to retrieve fresh information.
|
|
1341
|
+
*/
|
|
1342
|
+
get info(): NDKRelayInformation | undefined;
|
|
1343
|
+
}
|
|
1344
|
+
|
|
1345
|
+
type NDKSubscriptionInternalId = string;
|
|
1346
|
+
|
|
1347
|
+
type NDKSubscriptionDelayedType = "at-least" | "at-most";
|
|
1348
|
+
type NDKFilter<K extends number = NDKKind> = {
|
|
1349
|
+
ids?: string[];
|
|
1350
|
+
kinds?: K[];
|
|
1351
|
+
authors?: string[];
|
|
1352
|
+
since?: number;
|
|
1353
|
+
until?: number;
|
|
1354
|
+
limit?: number;
|
|
1355
|
+
search?: string;
|
|
1356
|
+
[key: `#${string}`]: string[] | undefined;
|
|
1357
|
+
};
|
|
1358
|
+
declare enum NDKSubscriptionCacheUsage {
|
|
1359
|
+
ONLY_CACHE = "ONLY_CACHE",
|
|
1360
|
+
CACHE_FIRST = "CACHE_FIRST",
|
|
1361
|
+
PARALLEL = "PARALLEL",
|
|
1362
|
+
ONLY_RELAY = "ONLY_RELAY"
|
|
1363
|
+
}
|
|
1364
|
+
interface NDKSubscriptionOptions {
|
|
1365
|
+
/**
|
|
1366
|
+
* Whether to close the subscription when all relays have reached the end of the event stream.
|
|
1367
|
+
* @default false
|
|
1368
|
+
*/
|
|
1369
|
+
closeOnEose?: boolean;
|
|
1370
|
+
cacheUsage?: NDKSubscriptionCacheUsage;
|
|
1371
|
+
/**
|
|
1372
|
+
* Whether to skip caching events coming from this subscription
|
|
1373
|
+
**/
|
|
1374
|
+
dontSaveToCache?: boolean;
|
|
1375
|
+
/**
|
|
1376
|
+
* Groupable subscriptions are created with a slight time
|
|
1377
|
+
* delayed to allow similar filters to be grouped together.
|
|
1378
|
+
*/
|
|
1379
|
+
groupable?: boolean;
|
|
1380
|
+
/**
|
|
1381
|
+
* The delay to use when grouping subscriptions, specified in milliseconds.
|
|
1382
|
+
* @default 100
|
|
1383
|
+
* @example
|
|
1384
|
+
* const sub1 = ndk.subscribe({ kinds: [1], authors: ["alice"] }, { groupableDelay: 100 });
|
|
1385
|
+
* const sub2 = ndk.subscribe({ kinds: [0], authors: ["alice"] }, { groupableDelay: 1000 });
|
|
1386
|
+
* // sub1 and sub2 will be grouped together and executed 100ms after sub1 was created
|
|
1387
|
+
*/
|
|
1388
|
+
groupableDelay?: number;
|
|
1389
|
+
/**
|
|
1390
|
+
* Specifies how this delay should be interpreted.
|
|
1391
|
+
* "at-least" means "wait at least this long before sending the subscription"
|
|
1392
|
+
* "at-most" means "wait at most this long before sending the subscription"
|
|
1393
|
+
* @default "at-most"
|
|
1394
|
+
* @example
|
|
1395
|
+
* const sub1 = ndk.subscribe({ kinds: [1], authors: ["alice"] }, { groupableDelay: 100, groupableDelayType: "at-least" }); // 3 args
|
|
1396
|
+
* const sub2 = ndk.subscribe({ kinds: [0], authors: ["alice"] }, { groupableDelay: 1000, groupableDelayType: "at-most" }); // 3 args
|
|
1397
|
+
* // sub1 and sub2 will be grouped together and executed 1000ms after sub1 was created
|
|
1398
|
+
*/
|
|
1399
|
+
groupableDelayType?: NDKSubscriptionDelayedType;
|
|
1400
|
+
/**
|
|
1401
|
+
* The subscription ID to use for the subscription.
|
|
1402
|
+
*/
|
|
1403
|
+
subId?: string;
|
|
1404
|
+
/**
|
|
1405
|
+
* Pool to use
|
|
1406
|
+
*/
|
|
1407
|
+
pool?: NDKPool;
|
|
1408
|
+
/**
|
|
1409
|
+
* Skip signature verification
|
|
1410
|
+
* @default false
|
|
1411
|
+
*/
|
|
1412
|
+
skipVerification?: boolean;
|
|
1413
|
+
/**
|
|
1414
|
+
* Skip event validation. Event validation, checks whether received
|
|
1415
|
+
* kinds conform to what the expected schema of that kind should look like.rtwle
|
|
1416
|
+
* @default false
|
|
1417
|
+
*/
|
|
1418
|
+
skipValidation?: boolean;
|
|
1419
|
+
/**
|
|
1420
|
+
* Skip emitting on events before they are received from a relay. (skip optimistic publish)
|
|
1421
|
+
* @default false
|
|
1422
|
+
*/
|
|
1423
|
+
skipOptimisticPublishEvent?: boolean;
|
|
1424
|
+
/**
|
|
1425
|
+
* Remove filter constraints when querying the cache.
|
|
1426
|
+
*
|
|
1427
|
+
* This allows setting more aggressive filters that will be removed when hitting the cache.
|
|
1428
|
+
*
|
|
1429
|
+
* Useful uses of this include removing `since` or `until` constraints or `limit` filters.
|
|
1430
|
+
*
|
|
1431
|
+
* @example
|
|
1432
|
+
* ndk.subscribe({ kinds: [1], since: 1710000000, limit: 10 }, { cacheUnconstrainFilter: ['since', 'limit'] }); // 3 args
|
|
1433
|
+
*
|
|
1434
|
+
* This will hit relays with the since and limit constraints, while loading from the cache without them.
|
|
1435
|
+
*/
|
|
1436
|
+
cacheUnconstrainFilter?: (keyof NDKFilter)[];
|
|
1437
|
+
/**
|
|
1438
|
+
* Whether to wrap events in kind-specific classes when possible.
|
|
1439
|
+
* @default false
|
|
1440
|
+
*/
|
|
1441
|
+
wrap?: boolean;
|
|
1442
|
+
/**
|
|
1443
|
+
* Explicit relay set to use for this subscription instead of calculating it.
|
|
1444
|
+
* If `relayUrls` is also provided in the options, this `relaySet` takes precedence.
|
|
1445
|
+
* @since 2.13.0 Moved from `ndk.subscribe` parameter to options.
|
|
1446
|
+
*/
|
|
1447
|
+
relaySet?: NDKRelaySet;
|
|
1448
|
+
/**
|
|
1449
|
+
* Explicit relay URLs to use for this subscription instead of calculating the relay set.
|
|
1450
|
+
* An `NDKRelaySet` will be created internally from these URLs.
|
|
1451
|
+
* If `relaySet` is also provided in the options, the explicit `relaySet` takes precedence over these URLs.
|
|
1452
|
+
* @since 2.13.0
|
|
1453
|
+
*/
|
|
1454
|
+
relayUrls?: string[];
|
|
1455
|
+
/**
|
|
1456
|
+
* When set, the cache will be queried first, and, when hitting relays,
|
|
1457
|
+
* a `since` filter will be added to the subscription that is one second
|
|
1458
|
+
* after the last event received from the cache.
|
|
1459
|
+
*
|
|
1460
|
+
* This option implies cacheUsage: CACHE_FIRST.
|
|
1461
|
+
*/
|
|
1462
|
+
addSinceFromCache?: boolean;
|
|
1463
|
+
/**
|
|
1464
|
+
* Include muted events in subscription results.
|
|
1465
|
+
* When false (default), events that match ndk.muteFilter are filtered out.
|
|
1466
|
+
* When true, muted events are included.
|
|
1467
|
+
* @default false
|
|
1468
|
+
*/
|
|
1469
|
+
includeMuted?: boolean;
|
|
1470
|
+
/**
|
|
1471
|
+
* Number of relays to query for each author in the subscription.
|
|
1472
|
+
* This controls the outbox model relay selection when the filter has authors.
|
|
1473
|
+
* Higher values improve redundancy but increase bandwidth usage.
|
|
1474
|
+
* @default 2
|
|
1475
|
+
* @example
|
|
1476
|
+
* // Query 3 relays for each author
|
|
1477
|
+
* ndk.subscribe(
|
|
1478
|
+
* { kinds: [1], authors: ["alice", "bob"] },
|
|
1479
|
+
* { relayGoalPerAuthor: 3 }
|
|
1480
|
+
* );
|
|
1481
|
+
* @example
|
|
1482
|
+
* // Use all available relays for each author
|
|
1483
|
+
* ndk.subscribe(
|
|
1484
|
+
* { kinds: [1], authors: ["alice", "bob"] },
|
|
1485
|
+
* { relayGoalPerAuthor: Infinity }
|
|
1486
|
+
* );
|
|
1487
|
+
*/
|
|
1488
|
+
relayGoalPerAuthor?: number;
|
|
1489
|
+
/**
|
|
1490
|
+
* Called for each event received by the subscription.
|
|
1491
|
+
* This eliminates the race condition of subscribing and then attaching event handlers.
|
|
1492
|
+
* @param event The received NDKEvent.
|
|
1493
|
+
* @param relay The relay the event was received from (undefined if from cache).
|
|
1494
|
+
* @param subscription The subscription that received the event.
|
|
1495
|
+
* @param fromCache Whether the event came from cache.
|
|
1496
|
+
* @param optimisticPublish Whether this is an optimistic publish event.
|
|
1497
|
+
*/
|
|
1498
|
+
onEvent?: (event: NDKEvent, relay?: NDKRelay, subscription?: NDKSubscription, fromCache?: boolean, optimisticPublish?: boolean) => void;
|
|
1499
|
+
/**
|
|
1500
|
+
* Called with a batch of events from cache.
|
|
1501
|
+
* When this is provided, cached events are processed in batch instead of individually.
|
|
1502
|
+
* @param events Array of cached events to process in batch.
|
|
1503
|
+
*/
|
|
1504
|
+
onEvents?: (events: NDKEvent[]) => void;
|
|
1505
|
+
/**
|
|
1506
|
+
* Called when the subscription receives an EOSE (End of Stored Events) marker
|
|
1507
|
+
* from all connected relays.
|
|
1508
|
+
* @param subscription The subscription that reached EOSE.
|
|
1509
|
+
*/
|
|
1510
|
+
onEose?: (subscription: NDKSubscription) => void;
|
|
1511
|
+
/**
|
|
1512
|
+
* Called when a duplicate event is received by the subscription.
|
|
1513
|
+
* @param event The duplicate event received by the subscription.
|
|
1514
|
+
* @param relay The relay that received the event (undefined if from cache).
|
|
1515
|
+
* @param timeSinceFirstSeen The time elapsed since the first time the event was seen.
|
|
1516
|
+
* @param subscription The subscription that received the event.
|
|
1517
|
+
* @param fromCache Whether the event came from cache.
|
|
1518
|
+
* @param optimisticPublish Whether this is an optimistic publish event.
|
|
1519
|
+
*/
|
|
1520
|
+
onEventDup?: (event: NDKEvent | NostrEvent, relay: NDKRelay | undefined, timeSinceFirstSeen: number, subscription: NDKSubscription, fromCache: boolean, optimisticPublish: boolean) => void;
|
|
1521
|
+
/**
|
|
1522
|
+
* Called when the subscription is closed.
|
|
1523
|
+
* @param subscription The subscription that was closed.
|
|
1524
|
+
*/
|
|
1525
|
+
onClose?: (subscription: NDKSubscription) => void;
|
|
1526
|
+
/**
|
|
1527
|
+
* When true, only accept events from the relays specified in relaySet/relayUrls.
|
|
1528
|
+
* When false (default), events matching the filter from any relay will be delivered
|
|
1529
|
+
* to this subscription (cross-subscription matching behavior).
|
|
1530
|
+
*
|
|
1531
|
+
* This is useful when you need strict relay provenance, such as:
|
|
1532
|
+
* - Fetching events exclusively from a specific relay
|
|
1533
|
+
* - Implementing relay-based isolation or routing
|
|
1534
|
+
* - Testing relay-specific behavior
|
|
1535
|
+
*
|
|
1536
|
+
* @default false
|
|
1537
|
+
* @example
|
|
1538
|
+
* // Only receive events from relay-a.com, ignore matches from other relays
|
|
1539
|
+
* ndk.subscribe(
|
|
1540
|
+
* { kinds: [1] },
|
|
1541
|
+
* { relayUrls: ["wss://relay-a.com"], exclusiveRelay: true }
|
|
1542
|
+
* );
|
|
1543
|
+
*/
|
|
1544
|
+
exclusiveRelay?: boolean;
|
|
1545
|
+
}
|
|
1546
|
+
/**
|
|
1547
|
+
* Represents a subscription to an NDK event stream.
|
|
1548
|
+
*
|
|
1549
|
+
* @emits event
|
|
1550
|
+
* Emitted when an event is received by the subscription.
|
|
1551
|
+
* * ({NDKEvent} event - The event received by the subscription,
|
|
1552
|
+
* * {NDKRelay} relay - The relay that received the event,
|
|
1553
|
+
* * {NDKSubscription} subscription - The subscription that received the event.)
|
|
1554
|
+
*
|
|
1555
|
+
* @emits event:dup
|
|
1556
|
+
* Emitted when a duplicate event is received by the subscription.
|
|
1557
|
+
* * {NDKEvent} event - The duplicate event received by the subscription.
|
|
1558
|
+
* * {NDKRelay} relay - The relay that received the event.
|
|
1559
|
+
* * {number} timeSinceFirstSeen - The time elapsed since the first time the event was seen.
|
|
1560
|
+
* * {NDKSubscription} subscription - The subscription that received the event.
|
|
1561
|
+
*
|
|
1562
|
+
* @emits cacheEose - Emitted when the cache adapter has reached the end of the events it had.
|
|
1563
|
+
*
|
|
1564
|
+
* @emits eose - Emitted when all relays have reached the end of the event stream.
|
|
1565
|
+
* * {NDKSubscription} subscription - The subscription that received EOSE.
|
|
1566
|
+
*
|
|
1567
|
+
* @emits close - Emitted when the subscription is closed.
|
|
1568
|
+
* * {NDKSubscription} subscription - The subscription that was closed.
|
|
1569
|
+
*
|
|
1570
|
+
* @example
|
|
1571
|
+
* const sub = ndk.subscribe(
|
|
1572
|
+
* { kinds: [1] }, // Get all kind:1s
|
|
1573
|
+
* {
|
|
1574
|
+
* onEvent: (event) => console.log(event.content), // Show the content
|
|
1575
|
+
* onEose: () => console.log("All relays have reached the end of the event stream"),
|
|
1576
|
+
* onClose: () => console.log("Subscription closed")
|
|
1577
|
+
* }
|
|
1578
|
+
* );
|
|
1579
|
+
* setTimeout(() => sub.stop(), 10000); // Stop the subscription after 10 seconds
|
|
1580
|
+
*
|
|
1581
|
+
* @description
|
|
1582
|
+
* Subscriptions are created using {@link NDK.subscribe}.
|
|
1583
|
+
*
|
|
1584
|
+
* # Event validation
|
|
1585
|
+
* By defaults, subscriptions will validate events to comply with the minimal requirement
|
|
1586
|
+
* of each known NIP.
|
|
1587
|
+
* This can be disabled by setting the `skipValidation` option to `true`.
|
|
1588
|
+
*
|
|
1589
|
+
* @example
|
|
1590
|
+
* const sub = ndk.subscribe(
|
|
1591
|
+
* { kinds: [1] },
|
|
1592
|
+
* {
|
|
1593
|
+
* skipValidation: false,
|
|
1594
|
+
* onEvent: (event) => console.log(event.content) // Only valid events will be received
|
|
1595
|
+
* }
|
|
1596
|
+
* );
|
|
1597
|
+
*/
|
|
1598
|
+
declare class NDKSubscription extends EventEmitter<{
|
|
1599
|
+
cacheEose: () => void;
|
|
1600
|
+
eose: (sub: NDKSubscription) => void;
|
|
1601
|
+
/** One relay finished sending what it has (EOSE, or a final CLOSED); again after a re-send. */
|
|
1602
|
+
"relay:eose": (relay: NDKRelay, sub: NDKSubscription) => void;
|
|
1603
|
+
close: (sub: NDKSubscription) => void;
|
|
1604
|
+
/**
|
|
1605
|
+
* Emitted when a duplicate event is received by the subscription.
|
|
1606
|
+
* @param event - The duplicate event received by the subscription.
|
|
1607
|
+
* @param relay - The relay that received the event.
|
|
1608
|
+
* @param timeSinceFirstSeen - The time elapsed since the first time the event was seen.
|
|
1609
|
+
* @param sub - The subscription that received the event.
|
|
1610
|
+
*/
|
|
1611
|
+
"event:dup": (event: NDKEvent | NostrEvent, relay: NDKRelay | undefined, timeSinceFirstSeen: number, sub: NDKSubscription, fromCache: boolean, optimisticPublish: boolean) => void;
|
|
1612
|
+
/**
|
|
1613
|
+
* Emitted when an event is received by the subscription.
|
|
1614
|
+
* @param event - The event received by the subscription.
|
|
1615
|
+
* @param relay - The relay that received the event.
|
|
1616
|
+
* @param sub - The subscription that received the event.
|
|
1617
|
+
* @param fromCache - Whether the event was received from the cache.
|
|
1618
|
+
* @param optimisticPublish - Whether the event was received from an optimistic publish.
|
|
1619
|
+
*/
|
|
1620
|
+
event: (event: NDKSignedEvent, relay: NDKRelay | undefined, sub: NDKSubscription, fromCache: boolean, optimisticPublish: boolean) => void;
|
|
1621
|
+
/**
|
|
1622
|
+
* Emitted when a relay unilaterally closes the subscription.
|
|
1623
|
+
* @param relay
|
|
1624
|
+
* @param reason
|
|
1625
|
+
* @returns
|
|
1626
|
+
*/
|
|
1627
|
+
closed: (relay: NDKRelay, reason: string) => void;
|
|
1628
|
+
}> {
|
|
1629
|
+
readonly subId?: string;
|
|
1630
|
+
readonly filters: NDKFilter[];
|
|
1631
|
+
readonly opts: NDKSubscriptionOptions;
|
|
1632
|
+
readonly pool: NDKPool;
|
|
1633
|
+
readonly skipVerification: boolean;
|
|
1634
|
+
readonly skipValidation: boolean;
|
|
1635
|
+
readonly exclusiveRelay: boolean;
|
|
1636
|
+
/**
|
|
1637
|
+
* Tracks the filters as they are executed on each relay
|
|
1638
|
+
*/
|
|
1639
|
+
relayFilters?: Map<WebSocket["url"], NDKFilter[]>;
|
|
1640
|
+
relaySet?: NDKRelaySet;
|
|
1641
|
+
ndk: NDK;
|
|
1642
|
+
debug: debug.Debugger;
|
|
1643
|
+
/**
|
|
1644
|
+
* Events that have been seen by the subscription, with the time they were first seen.
|
|
1645
|
+
*/
|
|
1646
|
+
eventFirstSeen: Map<string, number>;
|
|
1647
|
+
/**
|
|
1648
|
+
* Relays that have sent an EOSE.
|
|
1649
|
+
*/
|
|
1650
|
+
eosesSeen: Set<NDKRelay>;
|
|
1651
|
+
/**
|
|
1652
|
+
* The time the last event was received by the subscription.
|
|
1653
|
+
* This is used to calculate when EOSE should be emitted.
|
|
1654
|
+
*/
|
|
1655
|
+
private lastEventReceivedAt;
|
|
1656
|
+
/**
|
|
1657
|
+
* The most recent event timestamp from cache results.
|
|
1658
|
+
* This is used for addSinceFromCache functionality.
|
|
1659
|
+
*/
|
|
1660
|
+
private mostRecentCacheEventTimestamp?;
|
|
1661
|
+
internalId: NDKSubscriptionInternalId;
|
|
1662
|
+
/**
|
|
1663
|
+
* Whether the subscription should close when all relays have reached the end of the event stream.
|
|
1664
|
+
*/
|
|
1665
|
+
closeOnEose: boolean;
|
|
1666
|
+
/**
|
|
1667
|
+
* Pool monitor callback
|
|
1668
|
+
*/
|
|
1669
|
+
private poolMonitor;
|
|
1670
|
+
skipOptimisticPublishEvent: boolean;
|
|
1671
|
+
/**
|
|
1672
|
+
* Filters to remove when querying the cache.
|
|
1673
|
+
*/
|
|
1674
|
+
cacheUnconstrainFilter?: Array<keyof NDKFilter>;
|
|
1675
|
+
constructor(ndk: NDK, filters: NDKFilter | NDKFilter[], opts?: NDKSubscriptionOptions, subId?: string);
|
|
1676
|
+
/**
|
|
1677
|
+
* Returns the relays that have not yet sent an EOSE.
|
|
1678
|
+
*/
|
|
1679
|
+
relaysMissingEose(): WebSocket["url"][];
|
|
1680
|
+
/**
|
|
1681
|
+
* Provides access to the first filter of the subscription for
|
|
1682
|
+
* backwards compatibility.
|
|
1683
|
+
*/
|
|
1684
|
+
get filter(): NDKFilter;
|
|
1685
|
+
get groupableDelay(): number | undefined;
|
|
1686
|
+
get groupableDelayType(): NDKSubscriptionDelayedType;
|
|
1687
|
+
isGroupable(): boolean;
|
|
1688
|
+
private shouldQueryCache;
|
|
1689
|
+
private shouldQueryRelays;
|
|
1690
|
+
private shouldWaitForCache;
|
|
1691
|
+
/**
|
|
1692
|
+
* Start the subscription. This is the main method that should be called
|
|
1693
|
+
* after creating a subscription.
|
|
1694
|
+
*
|
|
1695
|
+
* @param emitCachedEvents - Whether to emit events coming from a synchronous cache
|
|
1696
|
+
*
|
|
1697
|
+
* When using a synchronous cache, the events will be returned immediately
|
|
1698
|
+
* by this function. If you will use those returned events, you should
|
|
1699
|
+
* set emitCachedEvents to false to prevent seeing them as duplicate events.
|
|
1700
|
+
*/
|
|
1701
|
+
start(emitCachedEvents?: boolean): NDKEvent[] | null;
|
|
1702
|
+
/**
|
|
1703
|
+
* We want to monitor for new relays that are coming online, in case
|
|
1704
|
+
* they should be part of this subscription.
|
|
1705
|
+
*/
|
|
1706
|
+
private startPoolMonitor;
|
|
1707
|
+
onStopped?: () => void;
|
|
1708
|
+
stop(): void;
|
|
1709
|
+
/**
|
|
1710
|
+
* @returns Whether the subscription has an authors filter.
|
|
1711
|
+
*/
|
|
1712
|
+
hasAuthorsFilter(): boolean;
|
|
1713
|
+
private startWithCache;
|
|
1714
|
+
/**
|
|
1715
|
+
* Find available relays that should be part of this subscription and execute in them.
|
|
1716
|
+
*
|
|
1717
|
+
* Note that this is executed in addition to using the pool monitor, so even if the relay set
|
|
1718
|
+
* that is computed (i.e. we don't have any relays available), when relays come online, we will
|
|
1719
|
+
* check if we need to execute in them.
|
|
1720
|
+
*/
|
|
1721
|
+
private startWithRelays;
|
|
1722
|
+
/**
|
|
1723
|
+
* Refresh relay connections when outbox data becomes available.
|
|
1724
|
+
* This recalculates which relays should receive this subscription and
|
|
1725
|
+
* connects to any newly discovered relays.
|
|
1726
|
+
*/
|
|
1727
|
+
refreshRelayConnections(): void;
|
|
1728
|
+
/**
|
|
1729
|
+
* Called when an event is received from a relay or the cache
|
|
1730
|
+
* @param event
|
|
1731
|
+
* @param relay
|
|
1732
|
+
* @param fromCache Whether the event was received from the cache
|
|
1733
|
+
* @param optimisticPublish Whether this event is coming from an optimistic publish
|
|
1734
|
+
*/
|
|
1735
|
+
eventReceived(event: NDKEvent | NostrEvent, relay: NDKRelay | undefined, fromCache?: boolean, optimisticPublish?: boolean): void;
|
|
1736
|
+
/** Caches (relay events), applies the mute filter and emits an accepted event. */
|
|
1737
|
+
private deliverEvent;
|
|
1738
|
+
/**
|
|
1739
|
+
* Optionally wraps, sync or async, and emits the event (if one comes back from the wrapper)
|
|
1740
|
+
*/
|
|
1741
|
+
private emitEvent;
|
|
1742
|
+
closedReceived(relay: NDKRelay, reason: string): void;
|
|
1743
|
+
private eoseTimeout;
|
|
1744
|
+
private eosed;
|
|
1745
|
+
/** Relay events held until their signature is verified (verifyBeforeEmit). */
|
|
1746
|
+
private pendingVerifications;
|
|
1747
|
+
private holdUntilVerified;
|
|
1748
|
+
eoseReceived(relay: NDKRelay, afterPendingVerifications?: boolean): void;
|
|
1749
|
+
}
|
|
1750
|
+
|
|
1751
|
+
declare class NDKPublishError extends Error {
|
|
1752
|
+
errors: Map<NDKRelay, Error>;
|
|
1753
|
+
publishedToRelays: Set<NDKRelay>;
|
|
1754
|
+
/**
|
|
1755
|
+
* Intended relay set where the publishing was intended to happen.
|
|
1756
|
+
*/
|
|
1757
|
+
intendedRelaySet?: NDKRelaySet;
|
|
1758
|
+
constructor(message: string, errors: Map<NDKRelay, Error>, publishedToRelays: Set<NDKRelay>, intendedRelaySet?: NDKRelaySet);
|
|
1759
|
+
get relayErrors(): string;
|
|
1760
|
+
}
|
|
1761
|
+
/**
|
|
1762
|
+
* A relay set is a group of relays. This grouping can be short-living, for a single
|
|
1763
|
+
* REQ or can be long-lasting, for example for the explicit relay list the user
|
|
1764
|
+
* has specified.
|
|
1765
|
+
*
|
|
1766
|
+
* Requests to relays should be sent through this interface.
|
|
1767
|
+
*/
|
|
1768
|
+
declare class NDKRelaySet {
|
|
1769
|
+
readonly relays: Set<NDKRelay>;
|
|
1770
|
+
private debug;
|
|
1771
|
+
private ndk;
|
|
1772
|
+
private pool;
|
|
1773
|
+
constructor(relays: Set<NDKRelay>, ndk: NDK, pool?: NDKPool);
|
|
1774
|
+
/**
|
|
1775
|
+
* Adds a relay to this set.
|
|
1776
|
+
*/
|
|
1777
|
+
addRelay(relay: NDKRelay): void;
|
|
1778
|
+
get relayUrls(): WebSocket["url"][];
|
|
1779
|
+
/**
|
|
1780
|
+
* Creates a relay set from a list of relay URLs.
|
|
1781
|
+
*
|
|
1782
|
+
* If no connection to the relay is found in the pool it will temporarily
|
|
1783
|
+
* connect to it.
|
|
1784
|
+
*
|
|
1785
|
+
* @param relayUrls - list of relay URLs to include in this set
|
|
1786
|
+
* @param ndk
|
|
1787
|
+
* @param connect - whether to connect to the relay immediately if it was already in the pool but not connected
|
|
1788
|
+
* @returns NDKRelaySet
|
|
1789
|
+
*/
|
|
1790
|
+
static fromRelayUrls(relayUrls: readonly string[], ndk: NDK, connect?: boolean, pool?: NDKPool): NDKRelaySet;
|
|
1791
|
+
/**
|
|
1792
|
+
* Publish an event to all relays in this relay set.
|
|
1793
|
+
*
|
|
1794
|
+
* This method implements a robust mechanism for publishing events to multiple relays with
|
|
1795
|
+
* built-in handling for race conditions, timeouts, and partial failures. The implementation
|
|
1796
|
+
* uses a dual-tracking mechanism to ensure accurate reporting of which relays successfully
|
|
1797
|
+
* received an event.
|
|
1798
|
+
*
|
|
1799
|
+
* Key aspects of this implementation:
|
|
1800
|
+
*
|
|
1801
|
+
* 1. DUAL-TRACKING MECHANISM:
|
|
1802
|
+
* - Promise-based tracking: Records successes/failures from the promises returned by relay.publish()
|
|
1803
|
+
* - Event-based tracking: Listens for 'relay:published' events that indicate successful publishing
|
|
1804
|
+
* This approach ensures we don't miss successful publishes even if there are subsequent errors in
|
|
1805
|
+
* the promise chain.
|
|
1806
|
+
*
|
|
1807
|
+
* 2. RACE CONDITION HANDLING:
|
|
1808
|
+
* - If a relay emits a success event but later fails in the promise chain, we still count it as a success
|
|
1809
|
+
* - If a relay times out after successfully publishing, we still count it as a success
|
|
1810
|
+
* - All relay operations happen in parallel, with proper tracking regardless of completion order
|
|
1811
|
+
*
|
|
1812
|
+
* 3. TIMEOUT MANAGEMENT:
|
|
1813
|
+
* - Individual timeouts for each relay operation
|
|
1814
|
+
* - Proper cleanup of timeouts to prevent memory leaks
|
|
1815
|
+
* - Clear timeout error reporting
|
|
1816
|
+
*
|
|
1817
|
+
* 4. ERROR HANDLING:
|
|
1818
|
+
* - Detailed tracking of specific errors for each failed relay
|
|
1819
|
+
* - Special handling for ephemeral events (which don't expect acknowledgement)
|
|
1820
|
+
* - RequiredRelayCount parameter to control the minimum success threshold
|
|
1821
|
+
*
|
|
1822
|
+
* @param event Event to publish
|
|
1823
|
+
* @param timeoutMs Timeout in milliseconds for each relay publish operation
|
|
1824
|
+
* @param requiredRelayCount The minimum number of relays we expect the event to be published to
|
|
1825
|
+
* @returns A set of relays the event was published to
|
|
1826
|
+
* @throws {NDKPublishError} If the event could not be published to at least `requiredRelayCount` relays
|
|
1827
|
+
* @example
|
|
1828
|
+
* ```typescript
|
|
1829
|
+
* const relaySet = new NDKRelaySet(new Set([relay1, relay2]), ndk);
|
|
1830
|
+
* const publishedToRelays = await relaySet.publish(event);
|
|
1831
|
+
* // publishedToRelays can contain relay1, relay2, both, or none
|
|
1832
|
+
* // depending on which relays the event was successfully published to
|
|
1833
|
+
* if (publishedToRelays.size > 0) {
|
|
1834
|
+
* console.log("Event published to at least one relay");
|
|
1835
|
+
* }
|
|
1836
|
+
* ```
|
|
1837
|
+
*/
|
|
1838
|
+
publish(event: NDKEvent, timeoutMs?: number, requiredRelayCount?: number): Promise<Set<NDKRelay>>;
|
|
1839
|
+
get size(): number;
|
|
1840
|
+
/**
|
|
1841
|
+
* Counts events matching the given filters across all relays in this set.
|
|
1842
|
+
*
|
|
1843
|
+
* This method implements NIP-45 COUNT with HyperLogLog (HLL) support for
|
|
1844
|
+
* accurate cardinality estimation across multiple relays.
|
|
1845
|
+
*
|
|
1846
|
+
* When relays return HLL data, the counts are merged using the HLL algorithm
|
|
1847
|
+
* to avoid double-counting events that appear on multiple relays.
|
|
1848
|
+
*
|
|
1849
|
+
* @param filters - The filters to count events for
|
|
1850
|
+
* @param opts - Optional count options (timeout, custom id)
|
|
1851
|
+
* @returns An aggregated count result with the best estimate and per-relay results
|
|
1852
|
+
*
|
|
1853
|
+
* @example
|
|
1854
|
+
* ```typescript
|
|
1855
|
+
* const relaySet = new NDKRelaySet(new Set([relay1, relay2]), ndk);
|
|
1856
|
+
* const result = await relaySet.count([{ kinds: [1], authors: [pubkey] }]);
|
|
1857
|
+
* console.log(`Estimated unique count: ${result.count}`);
|
|
1858
|
+
* console.log(`Relay 1 reported: ${result.relayResults.get(relay1.url)?.count}`);
|
|
1859
|
+
* ```
|
|
1860
|
+
*/
|
|
1861
|
+
count(filters: NDKFilter | NDKFilter[], opts?: NDKCountOptions): Promise<NDKAggregatedCountResult>;
|
|
1862
|
+
}
|
|
1863
|
+
|
|
1864
|
+
/**
|
|
1865
|
+
* Options on how to handle when a relay hint doesn't respond
|
|
1866
|
+
* with the requested event.
|
|
1867
|
+
*
|
|
1868
|
+
* When a tag includes a relay hint, and the relay hint doesn't come back
|
|
1869
|
+
* with the event, the fallback options are used to try to fetch the event
|
|
1870
|
+
* from somewhere else.
|
|
1871
|
+
*/
|
|
1872
|
+
type NDKFetchFallbackOptions = {
|
|
1873
|
+
/**
|
|
1874
|
+
* Relay set to use as a fallback when the hint relay doesn't respond.
|
|
1875
|
+
* If not provided, the normal NDK calculation is used (whether explicit relays or outbox calculation)
|
|
1876
|
+
* Default is `undefined`.
|
|
1877
|
+
*/
|
|
1878
|
+
relaySet?: NDKRelaySet;
|
|
1879
|
+
/**
|
|
1880
|
+
* Type of fallback to use when the hint relay doesn't respond.
|
|
1881
|
+
* - "timeout" will wait for a timeout before falling back
|
|
1882
|
+
* - "eose" will wait for the EOSE before falling back
|
|
1883
|
+
* - "none" will not fall back
|
|
1884
|
+
* Default is "timeout".
|
|
1885
|
+
*/
|
|
1886
|
+
type: "timeout" | "eose" | "none";
|
|
1887
|
+
/**
|
|
1888
|
+
* Timeout in milliseconds for the fallback relay.
|
|
1889
|
+
* Default is 1500ms.
|
|
1890
|
+
*/
|
|
1891
|
+
timeout?: number;
|
|
1892
|
+
};
|
|
1893
|
+
|
|
1894
|
+
interface AIGuardrailConfig {
|
|
1895
|
+
skip?: Set<string>;
|
|
1896
|
+
}
|
|
1897
|
+
type AIGuardrailsMode = boolean | AIGuardrailConfig;
|
|
1898
|
+
|
|
1899
|
+
/**
|
|
1900
|
+
* AI Guardrails - Runtime validation to catch common mistakes made by LLMs and developers.
|
|
1901
|
+
*
|
|
1902
|
+
* This module provides a flexible system for warning about or preventing common anti-patterns
|
|
1903
|
+
* when using NDK. It's designed to be:
|
|
1904
|
+
* - Off by default (zero performance impact in production)
|
|
1905
|
+
* - Granularly configurable (can disable specific checks)
|
|
1906
|
+
* - Educational (provides actionable error messages)
|
|
1907
|
+
*
|
|
1908
|
+
* Architecture:
|
|
1909
|
+
* - Inline checks for synchronous validation (must block operations)
|
|
1910
|
+
* - Hook methods for observational warnings (async, non-blocking)
|
|
1911
|
+
* - All guardrail logic organized by domain (ndk, event, relay, etc.)
|
|
1912
|
+
* - Core code stays clean - just calls typed hook methods
|
|
1913
|
+
*
|
|
1914
|
+
* @example Enable all guardrails
|
|
1915
|
+
* ```typescript
|
|
1916
|
+
* const ndk = new NDK({ aiGuardrails: true });
|
|
1917
|
+
* ```
|
|
1918
|
+
*
|
|
1919
|
+
* @example Enable with exceptions
|
|
1920
|
+
* ```typescript
|
|
1921
|
+
* const ndk = new NDK({
|
|
1922
|
+
* aiGuardrails: { skip: new Set(['filter-large-limit']) }
|
|
1923
|
+
* });
|
|
1924
|
+
* ```
|
|
1925
|
+
*
|
|
1926
|
+
* @example Programmatic control
|
|
1927
|
+
* ```typescript
|
|
1928
|
+
* ndk.aiGuardrails.skip('filter-large-limit');
|
|
1929
|
+
* ndk.aiGuardrails.enable('filter-bech32-in-array');
|
|
1930
|
+
* ```
|
|
1931
|
+
*
|
|
1932
|
+
* @example Temporarily disable for one call
|
|
1933
|
+
* ```typescript
|
|
1934
|
+
* // Disable all guardrails for one call
|
|
1935
|
+
* ndk.guardrailOff().fetchEvents({ kinds: [1] });
|
|
1936
|
+
*
|
|
1937
|
+
* // Disable specific guardrail for one call
|
|
1938
|
+
* ndk.guardrailOff('fetch-events-usage').fetchEvents({ kinds: [1] });
|
|
1939
|
+
*
|
|
1940
|
+
* // Disable multiple guardrails for one call
|
|
1941
|
+
* ndk.guardrailOff(['fetch-events-usage', 'filter-large-limit'])
|
|
1942
|
+
* .fetchEvents({ kinds: [1], limit: 5000 });
|
|
1943
|
+
*
|
|
1944
|
+
* // Next call has guardrails re-enabled automatically
|
|
1945
|
+
* ndk.fetchEvents({ kinds: [1] }); // Guardrails active again
|
|
1946
|
+
* ```
|
|
1947
|
+
*
|
|
1948
|
+
* @example Hook usage in core code
|
|
1949
|
+
* ```typescript
|
|
1950
|
+
* // Clean, type-safe hook calls
|
|
1951
|
+
* this.aiGuardrails.ndkInstantiated(this);
|
|
1952
|
+
* this.aiGuardrails.eventReceived(event, relay);
|
|
1953
|
+
* ```
|
|
1954
|
+
*/
|
|
1955
|
+
|
|
1956
|
+
/**
|
|
1957
|
+
* Central guardrails manager.
|
|
1958
|
+
* Provides both inline validation methods and hook methods for observational checks.
|
|
1959
|
+
*/
|
|
1960
|
+
declare class AIGuardrails {
|
|
1961
|
+
private enabled;
|
|
1962
|
+
private skipSet;
|
|
1963
|
+
private extensions;
|
|
1964
|
+
private _nextCallDisabled;
|
|
1965
|
+
private _replyEvents;
|
|
1966
|
+
private _fetchEventsCount;
|
|
1967
|
+
private _subscribeCount;
|
|
1968
|
+
constructor(mode?: AIGuardrailsMode);
|
|
1969
|
+
/**
|
|
1970
|
+
* Register an extension namespace with custom guardrail hooks.
|
|
1971
|
+
* This allows external packages to add their own guardrails.
|
|
1972
|
+
*
|
|
1973
|
+
* @example
|
|
1974
|
+
* ```typescript
|
|
1975
|
+
* // In NDKSvelte package:
|
|
1976
|
+
* ndk.aiGuardrails.register('ndkSvelte', {
|
|
1977
|
+
* constructing: (params) => {
|
|
1978
|
+
* if (!params.session) {
|
|
1979
|
+
* warn('ndksvelte-no-session', 'NDKSvelte instantiated without session parameter...');
|
|
1980
|
+
* }
|
|
1981
|
+
* }
|
|
1982
|
+
* });
|
|
1983
|
+
*
|
|
1984
|
+
* // In NDKSvelte constructor:
|
|
1985
|
+
* this.ndk.aiGuardrails?.ndkSvelte?.constructing(params);
|
|
1986
|
+
* ```
|
|
1987
|
+
*/
|
|
1988
|
+
register(namespace: string, hooks: any): void;
|
|
1989
|
+
/**
|
|
1990
|
+
* Set the guardrails mode.
|
|
1991
|
+
*/
|
|
1992
|
+
setMode(mode: AIGuardrailsMode): void;
|
|
1993
|
+
/**
|
|
1994
|
+
* Check if guardrails are enabled at all.
|
|
1995
|
+
*/
|
|
1996
|
+
isEnabled(): boolean;
|
|
1997
|
+
/**
|
|
1998
|
+
* Check if a specific guardrail check should run.
|
|
1999
|
+
*/
|
|
2000
|
+
shouldCheck(id: string): boolean;
|
|
2001
|
+
/**
|
|
2002
|
+
* Disable a specific guardrail check.
|
|
2003
|
+
*/
|
|
2004
|
+
skip(id: string): void;
|
|
2005
|
+
/**
|
|
2006
|
+
* Re-enable a specific guardrail check.
|
|
2007
|
+
*/
|
|
2008
|
+
enable(id: string): void;
|
|
2009
|
+
/**
|
|
2010
|
+
* Get all currently skipped guardrails.
|
|
2011
|
+
*/
|
|
2012
|
+
getSkipped(): string[];
|
|
2013
|
+
/**
|
|
2014
|
+
* Capture the current _nextCallDisabled set and clear it atomically.
|
|
2015
|
+
* This is used by hook methods to handle one-time guardrail disabling.
|
|
2016
|
+
*/
|
|
2017
|
+
captureAndClearNextCallDisabled(): Set<string> | "all" | null;
|
|
2018
|
+
/**
|
|
2019
|
+
* Increment fetchEvents call counter for ratio tracking.
|
|
2020
|
+
*/
|
|
2021
|
+
incrementFetchEventsCount(): void;
|
|
2022
|
+
/**
|
|
2023
|
+
* Increment subscribe call counter for ratio tracking.
|
|
2024
|
+
*/
|
|
2025
|
+
incrementSubscribeCount(): void;
|
|
2026
|
+
/**
|
|
2027
|
+
* Check if fetchEvents usage ratio exceeds the threshold.
|
|
2028
|
+
* Returns true if more than 50% of calls are fetchEvents AND total calls > 6.
|
|
2029
|
+
*/
|
|
2030
|
+
shouldWarnAboutFetchEventsRatio(): boolean;
|
|
2031
|
+
/**
|
|
2032
|
+
* Throw an error if the check should run.
|
|
2033
|
+
* Also logs to console.error in case the throw gets swallowed.
|
|
2034
|
+
* @param canDisable - If false, this is a fatal error that cannot be disabled (default: true)
|
|
2035
|
+
*/
|
|
2036
|
+
error(id: string, message: string, hint?: string, canDisable?: boolean): never | undefined;
|
|
2037
|
+
/**
|
|
2038
|
+
* Throw a warning if the check should run.
|
|
2039
|
+
* Also logs to console.error in case the throw gets swallowed.
|
|
2040
|
+
* Warnings can always be disabled.
|
|
2041
|
+
*/
|
|
2042
|
+
warn(id: string, message: string, hint?: string): never | undefined;
|
|
2043
|
+
/**
|
|
2044
|
+
* Format a guardrail message with helpful metadata.
|
|
2045
|
+
*/
|
|
2046
|
+
private formatMessage;
|
|
2047
|
+
/**
|
|
2048
|
+
* Called when NDK instance is created.
|
|
2049
|
+
* Checks for cache presence and other initialization concerns.
|
|
2050
|
+
*/
|
|
2051
|
+
ndkInstantiated(ndk: NDK): void;
|
|
2052
|
+
/**
|
|
2053
|
+
* NDK-related guardrails
|
|
2054
|
+
*/
|
|
2055
|
+
ndk: {
|
|
2056
|
+
/**
|
|
2057
|
+
* Called when fetchEvents is about to be called
|
|
2058
|
+
*/
|
|
2059
|
+
fetchingEvents: (filters: any, opts?: any) => void;
|
|
2060
|
+
};
|
|
2061
|
+
/**
|
|
2062
|
+
* Event-related guardrails
|
|
2063
|
+
*/
|
|
2064
|
+
event: {
|
|
2065
|
+
/**
|
|
2066
|
+
* Called when an event is about to be signed
|
|
2067
|
+
*/
|
|
2068
|
+
signing: (event: NDKEvent) => void;
|
|
2069
|
+
/**
|
|
2070
|
+
* Called before an event is published
|
|
2071
|
+
*/
|
|
2072
|
+
publishing: (event: NDKEvent) => void;
|
|
2073
|
+
/**
|
|
2074
|
+
* Called when an event is received from a relay
|
|
2075
|
+
*/
|
|
2076
|
+
received: (_event: NDKEvent, _relay: NDKRelay) => void;
|
|
2077
|
+
/**
|
|
2078
|
+
* Called when a reply event is being created via .reply()
|
|
2079
|
+
* This allows guardrails to track legitimate reply events
|
|
2080
|
+
*/
|
|
2081
|
+
creatingReply: (event: NDKEvent) => void;
|
|
2082
|
+
};
|
|
2083
|
+
/**
|
|
2084
|
+
* Subscription-related guardrails
|
|
2085
|
+
*/
|
|
2086
|
+
subscription: {
|
|
2087
|
+
/**
|
|
2088
|
+
* Called when a subscription is created
|
|
2089
|
+
*/
|
|
2090
|
+
created: (_filters: any[], _opts?: any) => void;
|
|
2091
|
+
};
|
|
2092
|
+
/**
|
|
2093
|
+
* Relay-related guardrails
|
|
2094
|
+
*/
|
|
2095
|
+
relay: {
|
|
2096
|
+
/**
|
|
2097
|
+
* Called when a relay connection is established
|
|
2098
|
+
*/
|
|
2099
|
+
connected: (_relay: NDKRelay) => void;
|
|
2100
|
+
};
|
|
2101
|
+
}
|
|
2102
|
+
|
|
2103
|
+
type NDKPaymentConfirmationLN = {
|
|
2104
|
+
preimage: string;
|
|
2105
|
+
};
|
|
2106
|
+
type LNPaymentRequest = string;
|
|
2107
|
+
type LnPaymentInfo = {
|
|
2108
|
+
pr: LNPaymentRequest;
|
|
2109
|
+
};
|
|
2110
|
+
type NDKLUD18ServicePayerData = Partial<{
|
|
2111
|
+
name: {
|
|
2112
|
+
mandatory: boolean;
|
|
2113
|
+
};
|
|
2114
|
+
pubkey: {
|
|
2115
|
+
mandatory: boolean;
|
|
2116
|
+
};
|
|
2117
|
+
identifier: {
|
|
2118
|
+
mandatory: boolean;
|
|
2119
|
+
};
|
|
2120
|
+
email: {
|
|
2121
|
+
mandatory: boolean;
|
|
2122
|
+
};
|
|
2123
|
+
auth: {
|
|
2124
|
+
mandatory: boolean;
|
|
2125
|
+
k1: string;
|
|
2126
|
+
};
|
|
2127
|
+
}> & Record<string, unknown>;
|
|
2128
|
+
type NDKLnUrlData = {
|
|
2129
|
+
tag: string;
|
|
2130
|
+
callback: string;
|
|
2131
|
+
minSendable: number;
|
|
2132
|
+
maxSendable: number;
|
|
2133
|
+
metadata: string;
|
|
2134
|
+
payerData?: NDKLUD18ServicePayerData;
|
|
2135
|
+
commentAllowed?: number;
|
|
2136
|
+
/**
|
|
2137
|
+
* Pubkey of the zapper that should publish zap receipts for this user
|
|
2138
|
+
*/
|
|
2139
|
+
nostrPubkey?: Hexpubkey;
|
|
2140
|
+
allowsNostr?: boolean;
|
|
2141
|
+
};
|
|
2142
|
+
|
|
2143
|
+
type NDKCacheEntry<T> = T & {
|
|
2144
|
+
cachedAt?: number;
|
|
2145
|
+
};
|
|
2146
|
+
/**
|
|
2147
|
+
* Cache module definition for packages to extend the cache with their own data structures.
|
|
2148
|
+
* Packages define their schemas, indexes, and migrations.
|
|
2149
|
+
*/
|
|
2150
|
+
interface CacheModuleDefinition {
|
|
2151
|
+
/**
|
|
2152
|
+
* Unique namespace for this module (e.g., "messages", "wallet", "sync")
|
|
2153
|
+
*/
|
|
2154
|
+
namespace: string;
|
|
2155
|
+
/**
|
|
2156
|
+
* Current version of this module's schema
|
|
2157
|
+
*/
|
|
2158
|
+
version: number;
|
|
2159
|
+
/**
|
|
2160
|
+
* Collection definitions for this module
|
|
2161
|
+
*/
|
|
2162
|
+
collections: {
|
|
2163
|
+
[name: string]: {
|
|
2164
|
+
/**
|
|
2165
|
+
* Primary key field name
|
|
2166
|
+
*/
|
|
2167
|
+
primaryKey: string;
|
|
2168
|
+
/**
|
|
2169
|
+
* Fields to create indexes on for efficient querying
|
|
2170
|
+
*/
|
|
2171
|
+
indexes?: string[];
|
|
2172
|
+
/**
|
|
2173
|
+
* Optional schema definition (for validation or TypeScript generation)
|
|
2174
|
+
*/
|
|
2175
|
+
schema?: Record<string, any>;
|
|
2176
|
+
/**
|
|
2177
|
+
* Compound indexes for multi-field queries
|
|
2178
|
+
*/
|
|
2179
|
+
compoundIndexes?: Array<string[]>;
|
|
2180
|
+
};
|
|
2181
|
+
};
|
|
2182
|
+
/**
|
|
2183
|
+
* Migration functions keyed by version number
|
|
2184
|
+
* Version 1 is the initial setup, 2+ are upgrades
|
|
2185
|
+
*/
|
|
2186
|
+
migrations: {
|
|
2187
|
+
[version: number]: (adapter: CacheModuleMigrationContext) => Promise<void>;
|
|
2188
|
+
};
|
|
2189
|
+
}
|
|
2190
|
+
/**
|
|
2191
|
+
* Migration context passed to module migration functions
|
|
2192
|
+
*/
|
|
2193
|
+
interface CacheModuleMigrationContext {
|
|
2194
|
+
/**
|
|
2195
|
+
* Get a collection by name within the module's namespace
|
|
2196
|
+
*/
|
|
2197
|
+
getCollection(name: string): Promise<CacheModuleCollection<any>>;
|
|
2198
|
+
/**
|
|
2199
|
+
* Create a new collection
|
|
2200
|
+
*/
|
|
2201
|
+
createCollection(name: string, definition: CacheModuleDefinition["collections"][string]): Promise<void>;
|
|
2202
|
+
/**
|
|
2203
|
+
* Delete a collection
|
|
2204
|
+
*/
|
|
2205
|
+
deleteCollection(name: string): Promise<void>;
|
|
2206
|
+
/**
|
|
2207
|
+
* Add an index to a collection
|
|
2208
|
+
*/
|
|
2209
|
+
addIndex(collection: string, field: string | string[]): Promise<void>;
|
|
2210
|
+
/**
|
|
2211
|
+
* Current version being migrated from
|
|
2212
|
+
*/
|
|
2213
|
+
fromVersion: number;
|
|
2214
|
+
/**
|
|
2215
|
+
* Target version being migrated to
|
|
2216
|
+
*/
|
|
2217
|
+
toVersion: number;
|
|
2218
|
+
}
|
|
2219
|
+
/**
|
|
2220
|
+
* Collection interface for module data access
|
|
2221
|
+
*/
|
|
2222
|
+
interface CacheModuleCollection<T> {
|
|
2223
|
+
/**
|
|
2224
|
+
* Get an item by its primary key
|
|
2225
|
+
*/
|
|
2226
|
+
get(id: string): Promise<T | null>;
|
|
2227
|
+
/**
|
|
2228
|
+
* Get multiple items by their primary keys
|
|
2229
|
+
*/
|
|
2230
|
+
getMany(ids: string[]): Promise<T[]>;
|
|
2231
|
+
/**
|
|
2232
|
+
* Save an item (upsert)
|
|
2233
|
+
*/
|
|
2234
|
+
save(item: T): Promise<void>;
|
|
2235
|
+
/**
|
|
2236
|
+
* Save multiple items (bulk upsert)
|
|
2237
|
+
*/
|
|
2238
|
+
saveMany(items: T[]): Promise<void>;
|
|
2239
|
+
/**
|
|
2240
|
+
* Delete an item by its primary key
|
|
2241
|
+
*/
|
|
2242
|
+
delete(id: string): Promise<void>;
|
|
2243
|
+
/**
|
|
2244
|
+
* Delete multiple items by their primary keys
|
|
2245
|
+
*/
|
|
2246
|
+
deleteMany(ids: string[]): Promise<void>;
|
|
2247
|
+
/**
|
|
2248
|
+
* Query items by a single field
|
|
2249
|
+
*/
|
|
2250
|
+
findBy(field: string, value: any): Promise<T[]>;
|
|
2251
|
+
/**
|
|
2252
|
+
* Query items with multiple conditions
|
|
2253
|
+
*/
|
|
2254
|
+
where(conditions: Record<string, any>): Promise<T[]>;
|
|
2255
|
+
/**
|
|
2256
|
+
* Get all items in the collection
|
|
2257
|
+
*/
|
|
2258
|
+
all(): Promise<T[]>;
|
|
2259
|
+
/**
|
|
2260
|
+
* Count items matching conditions
|
|
2261
|
+
*/
|
|
2262
|
+
count(conditions?: Record<string, any>): Promise<number>;
|
|
2263
|
+
/**
|
|
2264
|
+
* Clear all items from the collection
|
|
2265
|
+
*/
|
|
2266
|
+
clear(): Promise<void>;
|
|
2267
|
+
}
|
|
2268
|
+
interface NDKCacheAdapter {
|
|
2269
|
+
/**
|
|
2270
|
+
* Whether this cache adapter is expected to be fast.
|
|
2271
|
+
* If this is true, the cache will be queried before the relays.
|
|
2272
|
+
* When this is false, the cache will be queried in addition to the relays.
|
|
2273
|
+
*/
|
|
2274
|
+
locking: boolean;
|
|
2275
|
+
/**
|
|
2276
|
+
* Weather the cache is ready.
|
|
2277
|
+
*/
|
|
2278
|
+
ready?: boolean;
|
|
2279
|
+
initializeAsync?(ndk: NDK): Promise<void>;
|
|
2280
|
+
initialize?(ndk: NDK): void;
|
|
2281
|
+
/**
|
|
2282
|
+
* Either synchronously or asynchronously queries the cache.
|
|
2283
|
+
*
|
|
2284
|
+
* Cache adapters that return values synchronously should return an array of events.
|
|
2285
|
+
* Asynchronous cache adapters should call the subscription.eventReceived method for each event.
|
|
2286
|
+
*/
|
|
2287
|
+
query(subscription: NDKSubscription): NDKEvent[] | Promise<NDKEvent[]>;
|
|
2288
|
+
setEvent(event: NDKEvent, filters: NDKFilter[], relay?: NDKRelay): Promise<void>;
|
|
2289
|
+
/**
|
|
2290
|
+
* Called when we receive a duplicate event from a relay.
|
|
2291
|
+
* This associates the relay with an existing cached event without re-processing the event data.
|
|
2292
|
+
* @param event - The duplicate event received.
|
|
2293
|
+
* @param relay - The relay that sent the duplicate event.
|
|
2294
|
+
*/
|
|
2295
|
+
setEventDup?(event: NDKEvent, relay: NDKRelay): Promise<void> | void;
|
|
2296
|
+
/**
|
|
2297
|
+
* Called when an event is deleted by the client.
|
|
2298
|
+
* Cache adapters should remove the event from their cache.
|
|
2299
|
+
* @param eventIds - The ids of the events that were deleted.
|
|
2300
|
+
*/
|
|
2301
|
+
deleteEventIds?(eventIds: NDKEventId[]): Promise<void>;
|
|
2302
|
+
/**
|
|
2303
|
+
* Fetches a profile from the cache synchronously.
|
|
2304
|
+
* @param pubkey - The pubkey of the profile to fetch.
|
|
2305
|
+
* @returns The profile, or null if it is not in the cache.
|
|
2306
|
+
*/
|
|
2307
|
+
fetchProfileSync?(pubkey: Hexpubkey): NDKCacheEntry<NDKUserProfile> | null;
|
|
2308
|
+
/**
|
|
2309
|
+
* Retrieve all profiles from the cache synchronously.
|
|
2310
|
+
* @returns A map of pubkeys to profiles.
|
|
2311
|
+
*/
|
|
2312
|
+
getAllProfilesSync?(): Map<Hexpubkey, NDKCacheEntry<NDKUserProfile>>;
|
|
2313
|
+
/**
|
|
2314
|
+
* Special purpose
|
|
2315
|
+
*/
|
|
2316
|
+
fetchProfile?(pubkey: Hexpubkey): Promise<NDKCacheEntry<NDKUserProfile> | null>;
|
|
2317
|
+
saveProfile?(pubkey: Hexpubkey, profile: NDKUserProfile): void | Promise<void>;
|
|
2318
|
+
/**
|
|
2319
|
+
* Fetches profiles that match the given filter.
|
|
2320
|
+
* @param filter - Either a filter function or a filter descriptor object
|
|
2321
|
+
* @returns NDKUserProfiles that match the filter.
|
|
2322
|
+
* @example
|
|
2323
|
+
* // Using a filter function
|
|
2324
|
+
* const searchFunc = (pubkey, profile) => profile.name.toLowerCase().includes("alice");
|
|
2325
|
+
* const allAliceProfiles = await cache.getProfiles(searchFunc);
|
|
2326
|
+
*
|
|
2327
|
+
* @example
|
|
2328
|
+
* // Using a filter descriptor (supported by some cache adapters like cache-sqlite-wasm)
|
|
2329
|
+
* const aliceProfiles = await cache.getProfiles({ field: 'name', contains: 'alice' });
|
|
2330
|
+
* // Or search multiple fields
|
|
2331
|
+
* const aliceProfiles = await cache.getProfiles({ fields: ['name', 'displayName'], contains: 'alice' });
|
|
2332
|
+
*/
|
|
2333
|
+
getProfiles?: (filter: ((pubkey: Hexpubkey, profile: NDKUserProfile) => boolean) | {
|
|
2334
|
+
field?: string;
|
|
2335
|
+
fields?: string[];
|
|
2336
|
+
contains: string;
|
|
2337
|
+
}) => Promise<Map<Hexpubkey, NDKUserProfile> | undefined>;
|
|
2338
|
+
loadNip05?(nip05: string, maxAgeForMissing?: number): Promise<ProfilePointer | null | "missing">;
|
|
2339
|
+
saveNip05?(nip05: string, profile: ProfilePointer | null): void;
|
|
2340
|
+
/**
|
|
2341
|
+
* Fetches a user's LNURL data from the cache.
|
|
2342
|
+
* @param pubkey The pubkey of the user to fetch the LNURL data for.
|
|
2343
|
+
* @param maxAgeInSecs The maximum age of the data in seconds.
|
|
2344
|
+
* @param maxAgeForMissing The maximum age of the data in seconds if it is missing before it returns that it should be refetched.
|
|
2345
|
+
* @returns The LNURL data, null if it is not in the cache and under the maxAgeForMissing, or "missing" if it should be refetched.
|
|
2346
|
+
*/
|
|
2347
|
+
loadUsersLNURLDoc?(pubkey: Hexpubkey, maxAgeInSecs?: number, maxAgeForMissing?: number): Promise<NDKLnUrlData | null | "missing">;
|
|
2348
|
+
saveUsersLNURLDoc?(pubkey: Hexpubkey, doc: NDKLnUrlData | null): void;
|
|
2349
|
+
/**
|
|
2350
|
+
* Updates information about the relay.
|
|
2351
|
+
*/
|
|
2352
|
+
updateRelayStatus?(relayUrl: WebSocket["url"], info: NDKCacheRelayInfo): void | Promise<void>;
|
|
2353
|
+
/**
|
|
2354
|
+
* Fetches information about the relay.
|
|
2355
|
+
*/
|
|
2356
|
+
getRelayStatus?(relayUrl: WebSocket["url"]): NDKCacheRelayInfo | undefined | Promise<NDKCacheRelayInfo | undefined>;
|
|
2357
|
+
/**
|
|
2358
|
+
* Tracks a publishing event.
|
|
2359
|
+
* @param event
|
|
2360
|
+
* @param relayUrls List of relays that the event will be published to.
|
|
2361
|
+
*/
|
|
2362
|
+
addUnpublishedEvent?(event: NDKEvent, relayUrls: WebSocket["url"][]): void | Promise<void>;
|
|
2363
|
+
/**
|
|
2364
|
+
* Fetches all unpublished events.
|
|
2365
|
+
*/
|
|
2366
|
+
getUnpublishedEvents?(): Promise<{
|
|
2367
|
+
event: NDKEvent;
|
|
2368
|
+
relays?: WebSocket["url"][];
|
|
2369
|
+
lastTryAt?: number;
|
|
2370
|
+
}[]>;
|
|
2371
|
+
/**
|
|
2372
|
+
* Removes an unpublished event.
|
|
2373
|
+
*/
|
|
2374
|
+
discardUnpublishedEvent?(eventId: NDKEventId): void | Promise<void>;
|
|
2375
|
+
/**
|
|
2376
|
+
* Called when the cache is ready.
|
|
2377
|
+
*/
|
|
2378
|
+
onReady?(callback: () => void): void;
|
|
2379
|
+
/**
|
|
2380
|
+
* Get a decrypted event from the cache by its wrapper ID.
|
|
2381
|
+
* @param wrapperId - The ID of the gift-wrapped event (kind 1059).
|
|
2382
|
+
* @returns The decrypted rumor event, or null if it doesn't exist.
|
|
2383
|
+
*/
|
|
2384
|
+
getDecryptedEvent?(wrapperId: NDKEventId): NDKEvent | null | Promise<NDKEvent | null>;
|
|
2385
|
+
/**
|
|
2386
|
+
* Store a decrypted event in the cache.
|
|
2387
|
+
* @param wrapperId - The ID of the gift-wrapped event (kind 1059) to use as the cache key.
|
|
2388
|
+
* @param decryptedEvent - The decrypted rumor event to store.
|
|
2389
|
+
*/
|
|
2390
|
+
addDecryptedEvent?(wrapperId: NDKEventId, decryptedEvent: NDKEvent): void | Promise<void>;
|
|
2391
|
+
/**
|
|
2392
|
+
* Cleans up the cache. This is called when the user logs out.
|
|
2393
|
+
*/
|
|
2394
|
+
clear?(): Promise<void>;
|
|
2395
|
+
/**
|
|
2396
|
+
* Gets all nutzap states from the cache.
|
|
2397
|
+
* @returns A map of event IDs to nutzap states.
|
|
2398
|
+
*/
|
|
2399
|
+
getAllNutzapStates?(): Promise<Map<NDKEventId, NDKNutzapState>>;
|
|
2400
|
+
/**
|
|
2401
|
+
* Sets the state of a nutzap in the cache.
|
|
2402
|
+
* @param id The ID of the nutzap event.
|
|
2403
|
+
* @param stateChange The partial state change to apply.
|
|
2404
|
+
*/
|
|
2405
|
+
setNutzapState?(id: NDKEventId, stateChange: Partial<NDKNutzapState>): Promise<void>;
|
|
2406
|
+
/**
|
|
2407
|
+
* Generic key-value cache storage for packages.
|
|
2408
|
+
* Packages should namespace their keys (e.g., "wallet:mint:info:https://mint.url").
|
|
2409
|
+
* @param namespace The namespace for the data (e.g., "wallet", "sync")
|
|
2410
|
+
* @param key The key within the namespace
|
|
2411
|
+
* @param maxAgeInSecs Maximum age of cached data in seconds (optional)
|
|
2412
|
+
* @returns The cached data, or undefined if not cached or expired
|
|
2413
|
+
*/
|
|
2414
|
+
getCacheData?<T>(namespace: string, key: string, maxAgeInSecs?: number): Promise<T | undefined>;
|
|
2415
|
+
/**
|
|
2416
|
+
* Generic key-value cache storage for packages.
|
|
2417
|
+
* @param namespace The namespace for the data (e.g., "wallet", "sync")
|
|
2418
|
+
* @param key The key within the namespace
|
|
2419
|
+
* @param data The data to cache
|
|
2420
|
+
*/
|
|
2421
|
+
setCacheData?<T>(namespace: string, key: string, data: T): Promise<void>;
|
|
2422
|
+
/**
|
|
2423
|
+
* Cache module support - Register a module with its schema and migrations
|
|
2424
|
+
* @param module Module definition with schema, indexes, and migrations
|
|
2425
|
+
* @returns Promise that resolves when the module is registered and migrations are complete
|
|
2426
|
+
*/
|
|
2427
|
+
registerModule?(module: CacheModuleDefinition): Promise<void>;
|
|
2428
|
+
/**
|
|
2429
|
+
* Cache module support - Get a collection from a registered module
|
|
2430
|
+
* @param namespace Module namespace
|
|
2431
|
+
* @param collection Collection name within the module
|
|
2432
|
+
* @returns Collection interface for data operations
|
|
2433
|
+
*/
|
|
2434
|
+
getModuleCollection?<T>(namespace: string, collection: string): Promise<CacheModuleCollection<T>>;
|
|
2435
|
+
}
|
|
2436
|
+
/**
|
|
2437
|
+
* Relay metadata and statistics stored in cache.
|
|
2438
|
+
*
|
|
2439
|
+
* This type supports both core connection tracking and extensible package-specific metadata.
|
|
2440
|
+
* Packages can store custom data using the metadata field with namespacing.
|
|
2441
|
+
*
|
|
2442
|
+
* @example
|
|
2443
|
+
* ```typescript
|
|
2444
|
+
* // Core connection tracking
|
|
2445
|
+
* await cache.updateRelayStatus(url, {
|
|
2446
|
+
* lastConnectedAt: Date.now(),
|
|
2447
|
+
* consecutiveFailures: 0
|
|
2448
|
+
* });
|
|
2449
|
+
*
|
|
2450
|
+
* // Package-specific metadata (sync package)
|
|
2451
|
+
* await cache.updateRelayStatus(url, {
|
|
2452
|
+
* metadata: {
|
|
2453
|
+
* sync: {
|
|
2454
|
+
* supportsNegentropy: false,
|
|
2455
|
+
* lastChecked: Date.now()
|
|
2456
|
+
* }
|
|
2457
|
+
* }
|
|
2458
|
+
* });
|
|
2459
|
+
*
|
|
2460
|
+
* // Package-specific metadata (auth/rate limiting)
|
|
2461
|
+
* await cache.updateRelayStatus(url, {
|
|
2462
|
+
* metadata: {
|
|
2463
|
+
* auth: {
|
|
2464
|
+
* token: 'AUTH_TOKEN_HERE',
|
|
2465
|
+
* expiresAt: Date.now() + 3600000
|
|
2466
|
+
* },
|
|
2467
|
+
* rateLimit: {
|
|
2468
|
+
* requestCount: 42,
|
|
2469
|
+
* windowStart: Date.now(),
|
|
2470
|
+
* maxPerWindow: 100
|
|
2471
|
+
* }
|
|
2472
|
+
* }
|
|
2473
|
+
* });
|
|
2474
|
+
*
|
|
2475
|
+
* // NIP-11 caching
|
|
2476
|
+
* await cache.updateRelayStatus(url, {
|
|
2477
|
+
* nip11: {
|
|
2478
|
+
* data: relayInfo,
|
|
2479
|
+
* fetchedAt: Date.now()
|
|
2480
|
+
* }
|
|
2481
|
+
* });
|
|
2482
|
+
* ```
|
|
2483
|
+
*/
|
|
2484
|
+
type NDKCacheRelayInfo = {
|
|
2485
|
+
/**
|
|
2486
|
+
* Timestamp of last successful connection
|
|
2487
|
+
*/
|
|
2488
|
+
lastConnectedAt?: number;
|
|
2489
|
+
/**
|
|
2490
|
+
* Don't attempt connection before this timestamp
|
|
2491
|
+
*/
|
|
2492
|
+
dontConnectBefore?: number;
|
|
2493
|
+
/**
|
|
2494
|
+
* Number of consecutive connection failures
|
|
2495
|
+
*/
|
|
2496
|
+
consecutiveFailures?: number;
|
|
2497
|
+
/**
|
|
2498
|
+
* Timestamp of last connection failure
|
|
2499
|
+
*/
|
|
2500
|
+
lastFailureAt?: number;
|
|
2501
|
+
/**
|
|
2502
|
+
* Cached NIP-11 relay information document
|
|
2503
|
+
*/
|
|
2504
|
+
nip11?: {
|
|
2505
|
+
data: NDKRelayInformation;
|
|
2506
|
+
fetchedAt: number;
|
|
2507
|
+
};
|
|
2508
|
+
/**
|
|
2509
|
+
* Package-specific metadata (namespaced).
|
|
2510
|
+
*
|
|
2511
|
+
* Packages should use their package name as the namespace key.
|
|
2512
|
+
*
|
|
2513
|
+
* @example
|
|
2514
|
+
* ```typescript
|
|
2515
|
+
* metadata: {
|
|
2516
|
+
* sync: { supportsNegentropy: false, lastChecked: 1234567890 },
|
|
2517
|
+
* auth: { token: 'abc123', expiresAt: 1234567890 },
|
|
2518
|
+
* rateLimit: { requestCount: 42, windowStart: 1234567890, maxPerWindow: 100 }
|
|
2519
|
+
* }
|
|
2520
|
+
* ```
|
|
2521
|
+
*/
|
|
2522
|
+
metadata?: Record<string, Record<string, unknown>>;
|
|
2523
|
+
};
|
|
2524
|
+
|
|
2525
|
+
type OutboxItemType = "user" | "kind";
|
|
2526
|
+
/**
|
|
2527
|
+
* Tracks outbox scoring of an item. An item can be any of:
|
|
2528
|
+
*
|
|
2529
|
+
* - A user
|
|
2530
|
+
* - A tag
|
|
2531
|
+
*/
|
|
2532
|
+
declare class OutboxItem {
|
|
2533
|
+
/**
|
|
2534
|
+
* Type of item
|
|
2535
|
+
*/
|
|
2536
|
+
type: OutboxItemType;
|
|
2537
|
+
/**
|
|
2538
|
+
* The relay URLs that are of interest to this item
|
|
2539
|
+
*/
|
|
2540
|
+
relayUrlScores: Map<WebSocket["url"], number>;
|
|
2541
|
+
readRelays: Set<WebSocket["url"]>;
|
|
2542
|
+
writeRelays: Set<WebSocket["url"]>;
|
|
2543
|
+
constructor(type: OutboxItemType);
|
|
2544
|
+
}
|
|
2545
|
+
/**
|
|
2546
|
+
* The responsibility of this class is to track relay:outbox-item associations
|
|
2547
|
+
* so that we can intelligently choose which relays to query for which items.
|
|
2548
|
+
*
|
|
2549
|
+
* A single instance of this class should be shared across all subscriptions within
|
|
2550
|
+
* an NDK instance.
|
|
2551
|
+
*
|
|
2552
|
+
* TODO: The state of this tracker needs to be added to cache adapters so that we
|
|
2553
|
+
* can rehydrate-it when a cache is present.
|
|
2554
|
+
*/
|
|
2555
|
+
declare class OutboxTracker extends EventEmitter {
|
|
2556
|
+
data: LRUCache<Hexpubkey, OutboxItem>;
|
|
2557
|
+
private ndk;
|
|
2558
|
+
private debug;
|
|
2559
|
+
constructor(ndk: NDK);
|
|
2560
|
+
/**
|
|
2561
|
+
* Adds a list of users to the tracker.
|
|
2562
|
+
* @param items
|
|
2563
|
+
* @param skipCache
|
|
2564
|
+
*/
|
|
2565
|
+
trackUsers(items: NDKUser[] | Hexpubkey[], skipCache?: boolean): Promise<void[]>;
|
|
2566
|
+
/**
|
|
2567
|
+
*
|
|
2568
|
+
* @param key
|
|
2569
|
+
* @param score
|
|
2570
|
+
*/
|
|
2571
|
+
track(item: NDKUser | Hexpubkey, type?: OutboxItemType, _skipCache?: boolean): OutboxItem;
|
|
2572
|
+
}
|
|
2573
|
+
|
|
2574
|
+
type Proof$1 = {
|
|
2575
|
+
/**
|
|
2576
|
+
* Keyset id, used to link proofs to a mint an its MintKeys.
|
|
2577
|
+
*/
|
|
2578
|
+
id: string;
|
|
2579
|
+
/**
|
|
2580
|
+
* Amount denominated in Satoshis. Has to match the amount of the mints signing key.
|
|
2581
|
+
*/
|
|
2582
|
+
amount: number;
|
|
2583
|
+
/**
|
|
2584
|
+
* The initial secret that was (randomly) chosen for the creation of this proof.
|
|
2585
|
+
*/
|
|
2586
|
+
secret: string;
|
|
2587
|
+
/**
|
|
2588
|
+
* The unblinded signature for this secret, signed by the mints private key.
|
|
2589
|
+
*/
|
|
2590
|
+
C: string;
|
|
2591
|
+
};
|
|
2592
|
+
|
|
2593
|
+
declare enum NutzapValidationCode {
|
|
2594
|
+
NO_PROOFS = "NO_PROOFS",
|
|
2595
|
+
INVALID_PROOF_COUNT = "INVALID_PROOF_COUNT",
|
|
2596
|
+
MULTIPLE_RECIPIENTS = "MULTIPLE_RECIPIENTS",
|
|
2597
|
+
NO_RECIPIENT = "NO_RECIPIENT",
|
|
2598
|
+
MULTIPLE_MINTS = "MULTIPLE_MINTS",
|
|
2599
|
+
NO_MINT = "NO_MINT",
|
|
2600
|
+
MULTIPLE_EVENT_TAGS = "MULTIPLE_EVENT_TAGS",
|
|
2601
|
+
MALFORMED_PROOF_SECRET = "MALFORMED_PROOF_SECRET",
|
|
2602
|
+
MISSING_EVENT_TAG_IN_PROOF = "MISSING_EVENT_TAG_IN_PROOF",
|
|
2603
|
+
MISMATCHED_EVENT_TAG_IN_PROOF = "MISMATCHED_EVENT_TAG_IN_PROOF",
|
|
2604
|
+
MISSING_SENDER_TAG_IN_PROOF = "MISSING_SENDER_TAG_IN_PROOF",
|
|
2605
|
+
MISMATCHED_SENDER_TAG_IN_PROOF = "MISMATCHED_SENDER_TAG_IN_PROOF",
|
|
2606
|
+
NO_EVENT_TAG_IN_EVENT = "NO_EVENT_TAG_IN_EVENT"
|
|
2607
|
+
}
|
|
2608
|
+
declare enum NutzapValidationSeverity {
|
|
2609
|
+
ERROR = "ERROR",
|
|
2610
|
+
WARNING = "WARNING"
|
|
2611
|
+
}
|
|
2612
|
+
type NutzapValidationIssue = {
|
|
2613
|
+
code: NutzapValidationCode;
|
|
2614
|
+
severity: NutzapValidationSeverity;
|
|
2615
|
+
message: string;
|
|
2616
|
+
proofIndex?: number;
|
|
2617
|
+
};
|
|
2618
|
+
type NutzapValidationResult = {
|
|
2619
|
+
valid: boolean;
|
|
2620
|
+
issues: NutzapValidationIssue[];
|
|
2621
|
+
};
|
|
2622
|
+
|
|
2623
|
+
/**
|
|
2624
|
+
* Represents a NIP-61 nutzap
|
|
2625
|
+
*/
|
|
2626
|
+
declare class NDKNutzap extends NDKEvent {
|
|
2627
|
+
private debug;
|
|
2628
|
+
private _proofs;
|
|
2629
|
+
static kind: NDKKind;
|
|
2630
|
+
static kinds: NDKKind[];
|
|
2631
|
+
constructor(ndk?: NDK, event?: NostrEvent | NDKEvent);
|
|
2632
|
+
static from(event: NDKEvent): NDKNutzap | undefined;
|
|
2633
|
+
set comment(comment: string | undefined);
|
|
2634
|
+
get comment(): string;
|
|
2635
|
+
set proofs(proofs: Proof$1[]);
|
|
2636
|
+
get proofs(): Proof$1[];
|
|
2637
|
+
get rawP2pk(): string | undefined;
|
|
2638
|
+
/**
|
|
2639
|
+
* Gets the p2pk pubkey that is embedded in the first proof.
|
|
2640
|
+
*
|
|
2641
|
+
* Note that this returns a nostr pubkey, not a cashu pubkey (no "02" prefix)
|
|
2642
|
+
*/
|
|
2643
|
+
get p2pk(): string | undefined;
|
|
2644
|
+
/**
|
|
2645
|
+
* Get the mint where this nutzap proofs exist
|
|
2646
|
+
*/
|
|
2647
|
+
get mint(): string;
|
|
2648
|
+
set mint(value: string);
|
|
2649
|
+
get unit(): string;
|
|
2650
|
+
set unit(value: string | undefined);
|
|
2651
|
+
get amount(): number;
|
|
2652
|
+
sender: NDKUser;
|
|
2653
|
+
/**
|
|
2654
|
+
* Set the target of the nutzap
|
|
2655
|
+
* @param target The target of the nutzap (a user or an event)
|
|
2656
|
+
*/
|
|
2657
|
+
set target(target: NDKEvent | NDKUser);
|
|
2658
|
+
set recipientPubkey(pubkey: Hexpubkey);
|
|
2659
|
+
get recipientPubkey(): Hexpubkey;
|
|
2660
|
+
get recipient(): NDKUser;
|
|
2661
|
+
toNostrEvent(): Promise<NostrEvent>;
|
|
2662
|
+
/**
|
|
2663
|
+
* Validates that the nutzap conforms to NIP-61
|
|
2664
|
+
* @deprecated Use validateNIP61() instead for detailed validation results
|
|
2665
|
+
*/
|
|
2666
|
+
get isValid(): boolean;
|
|
2667
|
+
/**
|
|
2668
|
+
* Performs comprehensive validation of the nutzap according to NIP-61.
|
|
2669
|
+
* Returns detailed validation results including errors and warnings.
|
|
2670
|
+
*
|
|
2671
|
+
* Errors make the nutzap invalid, warnings are recommendations for best practices.
|
|
2672
|
+
*/
|
|
2673
|
+
validateNIP61(): NutzapValidationResult;
|
|
2674
|
+
}
|
|
2675
|
+
|
|
2676
|
+
/**
|
|
2677
|
+
* Provides information that should be used to send a NIP-61 nutzap.
|
|
2678
|
+
* mints: URLs of the mints that can be used.
|
|
2679
|
+
* relays: URLs of the relays where nutzap must be published
|
|
2680
|
+
* p2pk: Optional pubkey to use for P2PK lock
|
|
2681
|
+
*/
|
|
2682
|
+
type CashuPaymentInfo = {
|
|
2683
|
+
/**
|
|
2684
|
+
* Mints that must be used for the payment
|
|
2685
|
+
*/
|
|
2686
|
+
mints?: string[];
|
|
2687
|
+
/**
|
|
2688
|
+
* Relays where nutzap must be published
|
|
2689
|
+
*/
|
|
2690
|
+
relays?: string[];
|
|
2691
|
+
/**
|
|
2692
|
+
* Optional pubkey to use for P2PK lock
|
|
2693
|
+
*/
|
|
2694
|
+
p2pk?: string;
|
|
2695
|
+
/**
|
|
2696
|
+
* Tags to include in the proof secrets (e.g., [["e", "event-id"], ["P", "sender-pubkey"]])
|
|
2697
|
+
* These tags will be added to the P2PK lock structure for replay protection and sender verification.
|
|
2698
|
+
*/
|
|
2699
|
+
proofTags?: [string, string][];
|
|
2700
|
+
/**
|
|
2701
|
+
* Intramint fallback allowed:
|
|
2702
|
+
*
|
|
2703
|
+
* When set to true, if cross-mint payments fail, we will
|
|
2704
|
+
* fallback to sending an intra-mint payment.
|
|
2705
|
+
*/
|
|
2706
|
+
allowIntramintFallback?: boolean;
|
|
2707
|
+
};
|
|
2708
|
+
/**
|
|
2709
|
+
* This is what a wallet implementing Cashu payments should provide back
|
|
2710
|
+
* when a payment has been requested.
|
|
2711
|
+
*/
|
|
2712
|
+
type NDKPaymentConfirmationCashu = {
|
|
2713
|
+
/**
|
|
2714
|
+
* Proof of the payment
|
|
2715
|
+
*/
|
|
2716
|
+
proofs: Proof$1[];
|
|
2717
|
+
/**
|
|
2718
|
+
* Mint
|
|
2719
|
+
*/
|
|
2720
|
+
mint: string;
|
|
2721
|
+
};
|
|
2722
|
+
|
|
2723
|
+
type NDKZapDetails<T> = T & {
|
|
2724
|
+
/**
|
|
2725
|
+
* Target of the zap
|
|
2726
|
+
*/
|
|
2727
|
+
target: NDKEvent | NDKUser;
|
|
2728
|
+
/**
|
|
2729
|
+
* Comment for the zap
|
|
2730
|
+
*/
|
|
2731
|
+
comment?: string;
|
|
2732
|
+
/**
|
|
2733
|
+
* Tags to add to the zap
|
|
2734
|
+
*/
|
|
2735
|
+
tags?: NDKTag[];
|
|
2736
|
+
/**
|
|
2737
|
+
* Pubkey of the user to zap to
|
|
2738
|
+
*/
|
|
2739
|
+
recipientPubkey: string;
|
|
2740
|
+
/**
|
|
2741
|
+
* Amount of the payment
|
|
2742
|
+
*/
|
|
2743
|
+
amount: number;
|
|
2744
|
+
/**
|
|
2745
|
+
* Unit of the payment (e.g. msat)
|
|
2746
|
+
*/
|
|
2747
|
+
unit: string;
|
|
2748
|
+
/**
|
|
2749
|
+
* Description of the payment for the sender's record
|
|
2750
|
+
*/
|
|
2751
|
+
paymentDescription?: string;
|
|
2752
|
+
/**
|
|
2753
|
+
* If this payment is for a nip57 zap, this will contain the zap request.
|
|
2754
|
+
*/
|
|
2755
|
+
nip57ZapRequest?: NDKEvent;
|
|
2756
|
+
/**
|
|
2757
|
+
* When set to true, when a pubkey is not zappable, we will
|
|
2758
|
+
* automatically fallback to using NIP-61.
|
|
2759
|
+
*
|
|
2760
|
+
* Every pubkey must be able to receive money.
|
|
2761
|
+
*
|
|
2762
|
+
* @default false
|
|
2763
|
+
*/
|
|
2764
|
+
nutzapAsFallback?: boolean;
|
|
2765
|
+
};
|
|
2766
|
+
type NDKPaymentConfirmation = NDKPaymentConfirmationLN | NDKNutzap;
|
|
2767
|
+
type NDKZapSplit = {
|
|
2768
|
+
pubkey: string;
|
|
2769
|
+
amount: number;
|
|
2770
|
+
};
|
|
2771
|
+
type NDKZapMethod = "nip57" | "nip61";
|
|
2772
|
+
type NDKLnLudData = {
|
|
2773
|
+
lud06?: string;
|
|
2774
|
+
lud16?: string;
|
|
2775
|
+
};
|
|
2776
|
+
type NDKZapMethodInfo = NDKLnLudData | CashuPaymentInfo;
|
|
2777
|
+
type LnPayCb = (payment: NDKZapDetails<LnPaymentInfo>) => Promise<NDKPaymentConfirmationLN | undefined>;
|
|
2778
|
+
type CashuPayCb = (payment: NDKZapDetails<CashuPaymentInfo>, onLnInvoice?: (pr: string) => void) => Promise<NDKPaymentConfirmationCashu | undefined>;
|
|
2779
|
+
|
|
2780
|
+
type QueueItem<T> = {
|
|
2781
|
+
/**
|
|
2782
|
+
* Deterministic id of the item
|
|
2783
|
+
*/
|
|
2784
|
+
id: string;
|
|
2785
|
+
/**
|
|
2786
|
+
* A function to process the item
|
|
2787
|
+
* @returns
|
|
2788
|
+
*/
|
|
2789
|
+
func: () => Promise<T>;
|
|
2790
|
+
};
|
|
2791
|
+
declare class Queue<T> {
|
|
2792
|
+
private queue;
|
|
2793
|
+
private maxConcurrency;
|
|
2794
|
+
private processing;
|
|
2795
|
+
private promises;
|
|
2796
|
+
constructor(_name: string, maxConcurrency: number);
|
|
2797
|
+
add(item: QueueItem<T>): Promise<T>;
|
|
2798
|
+
private process;
|
|
2799
|
+
clear(): void;
|
|
2800
|
+
clearProcessing(): void;
|
|
2801
|
+
clearAll(): void;
|
|
2802
|
+
length(): number;
|
|
2803
|
+
}
|
|
2804
|
+
|
|
2805
|
+
type NDKValidationRatioFn = (relay: NDKRelay, validatedCount: number, nonValidatedCount: number) => number;
|
|
2806
|
+
type NDKNetDebug = (msg: string, relay: NDKRelay, direction?: "send" | "recv") => void;
|
|
2807
|
+
/**
|
|
2808
|
+
* An interface compatible with ndk-wallet that allows setting multiple handlers and callbacks.
|
|
2809
|
+
*/
|
|
2810
|
+
interface NDKWalletInterface {
|
|
2811
|
+
lnPay?: LnPayCb;
|
|
2812
|
+
cashuPay?: CashuPayCb;
|
|
2813
|
+
onPaymentComplete?: (results: Map<NDKZapSplit, NDKPaymentConfirmation | Error | undefined>) => void;
|
|
2814
|
+
}
|
|
2815
|
+
interface NDKConstructorParams {
|
|
2816
|
+
/**
|
|
2817
|
+
* Relays we should explicitly connect to
|
|
2818
|
+
*/
|
|
2819
|
+
explicitRelayUrls?: string[];
|
|
2820
|
+
/**
|
|
2821
|
+
* When this is set, we always write only to this relays.
|
|
2822
|
+
*/
|
|
2823
|
+
devWriteRelayUrls?: string[];
|
|
2824
|
+
/**
|
|
2825
|
+
* Outbox relay URLs.
|
|
2826
|
+
*/
|
|
2827
|
+
outboxRelayUrls?: string[];
|
|
2828
|
+
/**
|
|
2829
|
+
* Enable outbox model (defaults to true)
|
|
2830
|
+
*/
|
|
2831
|
+
enableOutboxModel?: boolean;
|
|
2832
|
+
/**
|
|
2833
|
+
* Auto-connect to main user's relays. The "main" user is determined
|
|
2834
|
+
* by the presence of a signer. Upon connection to the explicit relays,
|
|
2835
|
+
* the user's relays will be fetched and connected to if this is set to true.
|
|
2836
|
+
* @default true
|
|
2837
|
+
*/
|
|
2838
|
+
autoConnectUserRelays?: boolean;
|
|
2839
|
+
/**
|
|
2840
|
+
* Signer to use for signing events by default
|
|
2841
|
+
*/
|
|
2842
|
+
signer?: NDKSigner;
|
|
2843
|
+
/**
|
|
2844
|
+
* Cache adapter to use for caching events
|
|
2845
|
+
*/
|
|
2846
|
+
cacheAdapter?: NDKCacheAdapter;
|
|
2847
|
+
/**
|
|
2848
|
+
* Debug instance to use
|
|
2849
|
+
*/
|
|
2850
|
+
debug?: debug$1.Debugger;
|
|
2851
|
+
/**
|
|
2852
|
+
* Provide a caller function to receive all networking traffic from relays
|
|
2853
|
+
*/
|
|
2854
|
+
netDebug?: NDKNetDebug;
|
|
2855
|
+
/**
|
|
2856
|
+
* Custom filter function to determine if an event should be muted.
|
|
2857
|
+
* @param event - The event to check
|
|
2858
|
+
* @returns true if the event should be muted
|
|
2859
|
+
*/
|
|
2860
|
+
muteFilter?: (event: NDKEvent) => boolean;
|
|
2861
|
+
/**
|
|
2862
|
+
* Custom filter function to determine if a relay connection should be allowed.
|
|
2863
|
+
* @param relayUrl - The relay URL to check
|
|
2864
|
+
* @returns true if the connection should be allowed, false to block it
|
|
2865
|
+
*/
|
|
2866
|
+
relayConnectionFilter?: (relayUrl: string) => boolean;
|
|
2867
|
+
/**
|
|
2868
|
+
* Client name to add to events' tag
|
|
2869
|
+
*/
|
|
2870
|
+
clientName?: string;
|
|
2871
|
+
/**
|
|
2872
|
+
* Client nip89 to add to events' tag
|
|
2873
|
+
*/
|
|
2874
|
+
clientNip89?: string;
|
|
2875
|
+
/**
|
|
2876
|
+
* Default relay-auth policy
|
|
2877
|
+
*/
|
|
2878
|
+
relayAuthDefaultPolicy?: NDKAuthPolicy;
|
|
2879
|
+
/**
|
|
2880
|
+
* Set a Web Worker for signature verification.
|
|
2881
|
+
*
|
|
2882
|
+
* @default undefined
|
|
2883
|
+
*
|
|
2884
|
+
* When provided, signature verification will be processed in a web worker.
|
|
2885
|
+
* You should listen for the `event:invalid-sig` event to handle invalid signatures.
|
|
2886
|
+
*
|
|
2887
|
+
* @example
|
|
2888
|
+
* ```typescript
|
|
2889
|
+
* const worker = new Worker("path/to/signature-verification.js");
|
|
2890
|
+
* ndk.signatureVerificationWorker = worker;
|
|
2891
|
+
* ndk.on("event:invalid-sig", (event) => {
|
|
2892
|
+
* console.error("Invalid signature", event);
|
|
2893
|
+
* });
|
|
2894
|
+
* ```
|
|
2895
|
+
*/
|
|
2896
|
+
signatureVerificationWorker?: Worker | undefined;
|
|
2897
|
+
/**
|
|
2898
|
+
* The signature verification validation ratio for new relays.
|
|
2899
|
+
*/
|
|
2900
|
+
initialValidationRatio?: number;
|
|
2901
|
+
/**
|
|
2902
|
+
* The lowest validation ratio any single relay can have.
|
|
2903
|
+
* Relays will have a sample of events verified based on this ratio.
|
|
2904
|
+
* When using this, you MUST listen for event:invalid-sig events
|
|
2905
|
+
* to handle invalid signatures and disconnect from evil relays.
|
|
2906
|
+
*
|
|
2907
|
+
* @default 0.1
|
|
2908
|
+
*/
|
|
2909
|
+
lowestValidationRatio?: number;
|
|
2910
|
+
/**
|
|
2911
|
+
* A function that is invoked to calculate the validation ratio for a relay.
|
|
2912
|
+
*/
|
|
2913
|
+
validationRatioFn?: NDKValidationRatioFn;
|
|
2914
|
+
/**
|
|
2915
|
+
* A custom function to verify event signatures.
|
|
2916
|
+
* When provided, this function will be used instead of the default verification logic.
|
|
2917
|
+
* This is particularly useful for platforms like React Native where Web Workers are not available.
|
|
2918
|
+
*
|
|
2919
|
+
* @example
|
|
2920
|
+
* ```typescript
|
|
2921
|
+
* import { verifySignatureAsync } from "@nostr-dev-kit/mobile";
|
|
2922
|
+
*
|
|
2923
|
+
* const ndk = new NDK({
|
|
2924
|
+
* signatureVerificationFunction: verifySignatureAsync
|
|
2925
|
+
* });
|
|
2926
|
+
* ```
|
|
2927
|
+
*/
|
|
2928
|
+
signatureVerificationFunction?: (event: NDKEvent) => Promise<boolean>;
|
|
2929
|
+
/**
|
|
2930
|
+
* With async signature verification (a worker or `signatureVerificationFunction`),
|
|
2931
|
+
* hold each relay event until its signature is verified: it is cached and emitted
|
|
2932
|
+
* only once verified, a forged one never is, and EOSE waits for the events before it.
|
|
2933
|
+
* Off by default, where events are emitted first and checked afterwards.
|
|
2934
|
+
*/
|
|
2935
|
+
verifyBeforeEmit?: boolean;
|
|
2936
|
+
/**
|
|
2937
|
+
* Filter validation mode for subscriptions.
|
|
2938
|
+
*
|
|
2939
|
+
* @default "validate" - Throws an error when filters contain undefined values
|
|
2940
|
+
* "fix" - Automatically removes undefined values from filters
|
|
2941
|
+
* "ignore" - Skip validation entirely (legacy behavior)
|
|
2942
|
+
*/
|
|
2943
|
+
filterValidationMode?: "validate" | "fix" | "ignore";
|
|
2944
|
+
/**
|
|
2945
|
+
* ⚠️ STRONGLY RECOMMENDED: Enable AI Guardrails during development
|
|
2946
|
+
*
|
|
2947
|
+
* AI Guardrails catch 90% of common mistakes before they cause silent failures:
|
|
2948
|
+
* - Using bech32 (npub/note1) in filter arrays instead of hex
|
|
2949
|
+
* - Missing required fields on events (kind, content, etc.)
|
|
2950
|
+
* - Invalid tag formats and duplicate tags
|
|
2951
|
+
* - Performance anti-patterns (fetchEvents abuse, no cache adapter)
|
|
2952
|
+
* - Wrong data types (milliseconds vs seconds for created_at)
|
|
2953
|
+
*
|
|
2954
|
+
* When enabled, you'll get clear, actionable error messages instead of silent failures.
|
|
2955
|
+
*
|
|
2956
|
+
* @default false - Guardrails are disabled (zero performance impact)
|
|
2957
|
+
*
|
|
2958
|
+
* @example RECOMMENDED: Enable during development
|
|
2959
|
+
* ```typescript
|
|
2960
|
+
* const ndk = new NDK({
|
|
2961
|
+
* explicitRelayUrls: ['wss://relay.primal.net'],
|
|
2962
|
+
* aiGuardrails: true // ⚠️ Enable this!
|
|
2963
|
+
* });
|
|
2964
|
+
* ```
|
|
2965
|
+
*
|
|
2966
|
+
* @example Disable in production
|
|
2967
|
+
* ```typescript
|
|
2968
|
+
* const ndk = new NDK({
|
|
2969
|
+
* aiGuardrails: process.env.NODE_ENV !== 'production'
|
|
2970
|
+
* });
|
|
2971
|
+
* ```
|
|
2972
|
+
*
|
|
2973
|
+
* @example Enable with specific checks disabled
|
|
2974
|
+
* ```typescript
|
|
2975
|
+
* const ndk = new NDK({
|
|
2976
|
+
* aiGuardrails: { skip: new Set(['filter-large-limit']) }
|
|
2977
|
+
* });
|
|
2978
|
+
* ```
|
|
2979
|
+
*
|
|
2980
|
+
* @example Programmatic control
|
|
2981
|
+
* ```typescript
|
|
2982
|
+
* ndk.aiGuardrails.skip('fetch-events-usage');
|
|
2983
|
+
* ndk.aiGuardrails.enable('filter-bech32-in-array');
|
|
2984
|
+
* ```
|
|
2985
|
+
*
|
|
2986
|
+
* @see https://github.com/nostr-dev-kit/ndk/tree/master/ndk/src/ai-guardrails
|
|
2987
|
+
*/
|
|
2988
|
+
aiGuardrails?: boolean | {
|
|
2989
|
+
skip?: Set<string>;
|
|
2990
|
+
};
|
|
2991
|
+
/**
|
|
2992
|
+
* Optional grace period (in seconds) for future timestamps.
|
|
2993
|
+
*
|
|
2994
|
+
* When set, subscriptions will automatically discard events where
|
|
2995
|
+
* `created_at` is more than this many seconds ahead of the current time.
|
|
2996
|
+
* This helps protect against malicious relays sending events with
|
|
2997
|
+
* manipulated timestamps.
|
|
2998
|
+
*
|
|
2999
|
+
* Set to `undefined` (default) to disable this check and accept all events
|
|
3000
|
+
* regardless of timestamp.
|
|
3001
|
+
*
|
|
3002
|
+
* @default undefined
|
|
3003
|
+
*
|
|
3004
|
+
* @example Reject events more than 5 minutes in the future
|
|
3005
|
+
* ```typescript
|
|
3006
|
+
* const ndk = new NDK({
|
|
3007
|
+
* explicitRelayUrls: ['wss://relay.primal.net'],
|
|
3008
|
+
* futureTimestampGrace: 300 // 5 minutes
|
|
3009
|
+
* });
|
|
3010
|
+
* ```
|
|
3011
|
+
*/
|
|
3012
|
+
futureTimestampGrace?: number;
|
|
3013
|
+
}
|
|
3014
|
+
interface GetUserParams extends NDKUserParams {
|
|
3015
|
+
npub?: string;
|
|
3016
|
+
pubkey?: string;
|
|
3017
|
+
/**
|
|
3018
|
+
* @deprecated Use `pubkey` instead
|
|
3019
|
+
*/
|
|
3020
|
+
hexpubkey?: string;
|
|
3021
|
+
}
|
|
3022
|
+
/**
|
|
3023
|
+
* Defines handlers that can be passed to `ndk.subscribe` via the `autoStart` parameter
|
|
3024
|
+
* to react to subscription lifecycle events.
|
|
3025
|
+
*/
|
|
3026
|
+
interface NDKSubscriptionEventHandlers {
|
|
3027
|
+
/**
|
|
3028
|
+
* Called for each individual event received from relays *after* the initial cache load (if `onEvents` is provided),
|
|
3029
|
+
* or for *all* events (including cached ones) if `onEvents` is not provided.
|
|
3030
|
+
* @param event The received NDKEvent.
|
|
3031
|
+
* @param relay The relay the event was received from (undefined if from cache).
|
|
3032
|
+
*/
|
|
3033
|
+
onEvent?: (event: NDKEvent, relay?: NDKRelay) => void;
|
|
3034
|
+
/**
|
|
3035
|
+
* Called *once* with an array of all events found synchronously in the cache when the subscription starts.
|
|
3036
|
+
* If this handler is provided, `onEvent` will *not* be called for this initial batch of cached events.
|
|
3037
|
+
* This is useful for bulk processing or batching UI updates based on the initial cached state.
|
|
3038
|
+
* @param events An array of NDKEvents loaded synchronously from the cache.
|
|
3039
|
+
*/
|
|
3040
|
+
onEvents?: (events: NDKEvent[]) => void;
|
|
3041
|
+
/**
|
|
3042
|
+
* Called when the subscription receives an EOSE (End of Stored Events) marker
|
|
3043
|
+
* from all connected relays involved in this subscription request.
|
|
3044
|
+
* @param sub The NDKSubscription instance that reached EOSE.
|
|
3045
|
+
*/
|
|
3046
|
+
onEose?: (sub: NDKSubscription) => void;
|
|
3047
|
+
/**
|
|
3048
|
+
* Called when the subscription is closed.
|
|
3049
|
+
* @param sub The NDKSubscription instance that was closed.
|
|
3050
|
+
*/
|
|
3051
|
+
onClose?: (sub: NDKSubscription) => void;
|
|
3052
|
+
}
|
|
3053
|
+
/**
|
|
3054
|
+
* The NDK class is the main entry point to the library.
|
|
3055
|
+
*
|
|
3056
|
+
* @emits signer:ready when a signer is ready
|
|
3057
|
+
* @emits activeUser:change when the active user changes
|
|
3058
|
+
* @emits invalid-signature when an event with an invalid signature is received
|
|
3059
|
+
*/
|
|
3060
|
+
declare class NDK extends EventEmitter<{
|
|
3061
|
+
"signer:ready": (signer: NDKSigner) => void;
|
|
3062
|
+
"signer:required": () => void;
|
|
3063
|
+
/**
|
|
3064
|
+
* Emitted when the active user changes.
|
|
3065
|
+
* This can happen when a signer is set or when activeUser is set directly.
|
|
3066
|
+
*/
|
|
3067
|
+
"activeUser:change": (user: NDKUser | undefined) => void;
|
|
3068
|
+
/**
|
|
3069
|
+
* Emitted when an event with an invalid signature is received.
|
|
3070
|
+
* Includes the relay that provided the invalid signature.
|
|
3071
|
+
*/
|
|
3072
|
+
"event:invalid-sig": (event: NDKEvent, relay?: NDKRelay) => void;
|
|
3073
|
+
/**
|
|
3074
|
+
* Emitted when an event fails to publish.
|
|
3075
|
+
* @param event The event that failed to publish
|
|
3076
|
+
* @param error The error that caused the event to fail to publish
|
|
3077
|
+
* @param relays The relays that the event was attempted to be published to
|
|
3078
|
+
*/
|
|
3079
|
+
"event:publish-failed": (event: NDKEvent, error: NDKPublishError, relays: WebSocket["url"][]) => void;
|
|
3080
|
+
}> {
|
|
3081
|
+
private _explicitRelayUrls?;
|
|
3082
|
+
pool: NDKPool;
|
|
3083
|
+
outboxPool?: NDKPool;
|
|
3084
|
+
private _signer?;
|
|
3085
|
+
private _activeUser?;
|
|
3086
|
+
cacheAdapter?: NDKCacheAdapter;
|
|
3087
|
+
debug: debug$1.Debugger;
|
|
3088
|
+
devWriteRelaySet?: NDKRelaySet;
|
|
3089
|
+
outboxTracker?: OutboxTracker;
|
|
3090
|
+
muteFilter?: (event: NDKEvent) => boolean;
|
|
3091
|
+
relayConnectionFilter?: (relayUrl: string) => boolean;
|
|
3092
|
+
clientName?: string;
|
|
3093
|
+
clientNip89?: string;
|
|
3094
|
+
queuesZapConfig: Queue<NDKLnUrlData | undefined>;
|
|
3095
|
+
queuesNip05: Queue<ProfilePointer | null>;
|
|
3096
|
+
asyncSigVerification: boolean;
|
|
3097
|
+
/** See {@link NDKConstructorParams.verifyBeforeEmit}. */
|
|
3098
|
+
verifyBeforeEmit: boolean;
|
|
3099
|
+
initialValidationRatio: number;
|
|
3100
|
+
lowestValidationRatio: number;
|
|
3101
|
+
validationRatioFn?: NDKValidationRatioFn;
|
|
3102
|
+
filterValidationMode: "validate" | "fix" | "ignore";
|
|
3103
|
+
subManager: NDKSubscriptionManager;
|
|
3104
|
+
aiGuardrails: AIGuardrails;
|
|
3105
|
+
futureTimestampGrace?: number;
|
|
3106
|
+
/**
|
|
3107
|
+
* Private storage for the signature verification function
|
|
3108
|
+
*/
|
|
3109
|
+
private _signatureVerificationFunction?;
|
|
3110
|
+
/**
|
|
3111
|
+
* Private storage for the signature verification worker
|
|
3112
|
+
*/
|
|
3113
|
+
private _signatureVerificationWorker?;
|
|
3114
|
+
/**
|
|
3115
|
+
* Rolling total of time spent (in ms) performing signature verifications.
|
|
3116
|
+
* Users can read this to monitor or display aggregate verification cost.
|
|
3117
|
+
*/
|
|
3118
|
+
signatureVerificationTimeMs: number;
|
|
3119
|
+
publishingFailureHandled: boolean;
|
|
3120
|
+
pools: NDKPool[];
|
|
3121
|
+
/**
|
|
3122
|
+
* Default relay-auth policy that will be used when a relay requests authentication,
|
|
3123
|
+
* if no other policy is specified for that relay.
|
|
3124
|
+
*
|
|
3125
|
+
* @example Disconnect from relays that request authentication:
|
|
3126
|
+
* ```typescript
|
|
3127
|
+
* ndk.relayAuthDefaultPolicy = NDKAuthPolicies.disconnect(ndk.pool);
|
|
3128
|
+
* ```
|
|
3129
|
+
*
|
|
3130
|
+
* @example Sign in to relays that request authentication:
|
|
3131
|
+
* ```typescript
|
|
3132
|
+
* ndk.relayAuthDefaultPolicy = NDKAuthPolicies.signIn({ndk})
|
|
3133
|
+
* ```
|
|
3134
|
+
*
|
|
3135
|
+
* @example Sign in to relays that request authentication, asking the user for confirmation:
|
|
3136
|
+
* ```typescript
|
|
3137
|
+
* ndk.relayAuthDefaultPolicy = (relay: NDKRelay) => {
|
|
3138
|
+
* const signIn = NDKAuthPolicies.signIn({ndk});
|
|
3139
|
+
* if (confirm(`Relay ${relay.url} is requesting authentication, do you want to sign in?`)) {
|
|
3140
|
+
* signIn(relay);
|
|
3141
|
+
* }
|
|
3142
|
+
* }
|
|
3143
|
+
* ```
|
|
3144
|
+
*/
|
|
3145
|
+
relayAuthDefaultPolicy?: NDKAuthPolicy;
|
|
3146
|
+
/**
|
|
3147
|
+
* Fetch function to use for HTTP requests.
|
|
3148
|
+
*
|
|
3149
|
+
* @example
|
|
3150
|
+
* ```typescript
|
|
3151
|
+
* import fetch from "node-fetch";
|
|
3152
|
+
*
|
|
3153
|
+
* ndk.httpFetch = fetch;
|
|
3154
|
+
* ```
|
|
3155
|
+
*/
|
|
3156
|
+
httpFetch: typeof fetch | undefined;
|
|
3157
|
+
/**
|
|
3158
|
+
* Provide a caller function to receive all networking traffic from relays
|
|
3159
|
+
*/
|
|
3160
|
+
readonly netDebug?: NDKNetDebug;
|
|
3161
|
+
autoConnectUserRelays: boolean;
|
|
3162
|
+
private _wallet?;
|
|
3163
|
+
walletConfig?: NDKWalletInterface;
|
|
3164
|
+
constructor(opts?: NDKConstructorParams);
|
|
3165
|
+
set explicitRelayUrls(urls: WebSocket["url"][]);
|
|
3166
|
+
get explicitRelayUrls(): WebSocket["url"][];
|
|
3167
|
+
/**
|
|
3168
|
+
* Set a Web Worker for signature verification.
|
|
3169
|
+
*
|
|
3170
|
+
* This method initializes the worker and sets the asyncSigVerification flag.
|
|
3171
|
+
* The actual verification is handled by the verifySignatureAsync function in signature.ts,
|
|
3172
|
+
* which will use the worker if available.
|
|
3173
|
+
*/
|
|
3174
|
+
set signatureVerificationWorker(worker: Worker | undefined);
|
|
3175
|
+
/**
|
|
3176
|
+
* Set a custom signature verification function.
|
|
3177
|
+
*
|
|
3178
|
+
* This method is particularly useful for platforms that don't support Web Workers,
|
|
3179
|
+
* such as React Native.
|
|
3180
|
+
*
|
|
3181
|
+
* When a function is provided, it will be used for signature verification
|
|
3182
|
+
* instead of the default worker-based verification. This enables signature
|
|
3183
|
+
* verification on platforms where Web Workers are not available.
|
|
3184
|
+
*
|
|
3185
|
+
* @example
|
|
3186
|
+
* ```typescript
|
|
3187
|
+
* import { verifySignatureAsync } from "@nostr-dev-kit/mobile";
|
|
3188
|
+
*
|
|
3189
|
+
* ndk.signatureVerificationFunction = verifySignatureAsync;
|
|
3190
|
+
* ```
|
|
3191
|
+
*/
|
|
3192
|
+
set signatureVerificationFunction(fn: ((event: NDKEvent) => Promise<boolean>) | undefined);
|
|
3193
|
+
/**
|
|
3194
|
+
* Get the custom signature verification function
|
|
3195
|
+
*/
|
|
3196
|
+
get signatureVerificationFunction(): ((event: NDKEvent) => Promise<boolean>) | undefined;
|
|
3197
|
+
/**
|
|
3198
|
+
* Adds an explicit relay to the pool.
|
|
3199
|
+
* @param url
|
|
3200
|
+
* @param relayAuthPolicy Authentication policy to use if different from the default
|
|
3201
|
+
* @param connect Whether to connect to the relay automatically
|
|
3202
|
+
* @returns
|
|
3203
|
+
*/
|
|
3204
|
+
addExplicitRelay(urlOrRelay: string | NDKRelay, relayAuthPolicy?: NDKAuthPolicy, connect?: boolean): NDKRelay;
|
|
3205
|
+
toJSON(): string;
|
|
3206
|
+
get activeUser(): NDKUser | undefined;
|
|
3207
|
+
/**
|
|
3208
|
+
* Sets the active user for this NDK instance, typically this will be
|
|
3209
|
+
* called when assigning a signer to the NDK instance.
|
|
3210
|
+
*
|
|
3211
|
+
* This function will automatically connect to the user's relays if
|
|
3212
|
+
* `autoConnectUserRelays` is set to true.
|
|
3213
|
+
*/
|
|
3214
|
+
set activeUser(user: NDKUser | undefined);
|
|
3215
|
+
get signer(): NDKSigner | undefined;
|
|
3216
|
+
set signer(newSigner: NDKSigner | undefined);
|
|
3217
|
+
/**
|
|
3218
|
+
* Connect to relays with optional timeout.
|
|
3219
|
+
* If the timeout is reached, the connection will be continued to be established in the background.
|
|
3220
|
+
*/
|
|
3221
|
+
connect(timeoutMs?: number): Promise<void>;
|
|
3222
|
+
/**
|
|
3223
|
+
* Centralized method to report an invalid signature, identifying the relay that provided it.
|
|
3224
|
+
* A single invalid signature means the relay is considered malicious.
|
|
3225
|
+
* All invalid signature detections (synchronous or asynchronous) should delegate to this method.
|
|
3226
|
+
*
|
|
3227
|
+
* @param event The event with an invalid signature
|
|
3228
|
+
* @param relay The relay that provided the invalid signature
|
|
3229
|
+
*/
|
|
3230
|
+
reportInvalidSignature(event: NDKEvent, relay?: NDKRelay): void;
|
|
3231
|
+
/**
|
|
3232
|
+
* Default function to calculate validation ratio based on historical validation results.
|
|
3233
|
+
* The more events validated successfully, the lower the ratio goes (down to the minimum).
|
|
3234
|
+
*/
|
|
3235
|
+
private defaultValidationRatioFn;
|
|
3236
|
+
/**
|
|
3237
|
+
* Get a NDKUser object
|
|
3238
|
+
*
|
|
3239
|
+
* @deprecated Use `fetchUser` instead - this method will be removed in the next major version
|
|
3240
|
+
* @param opts - User parameters object or a string (npub, nprofile, or hex pubkey)
|
|
3241
|
+
* @returns NDKUser instance
|
|
3242
|
+
*
|
|
3243
|
+
* @example
|
|
3244
|
+
* ```typescript
|
|
3245
|
+
* // Using parameters object
|
|
3246
|
+
* const user1 = ndk.getUser({ pubkey: "hex..." });
|
|
3247
|
+
*
|
|
3248
|
+
* // Using npub string
|
|
3249
|
+
* const user2 = ndk.getUser("npub1...");
|
|
3250
|
+
*
|
|
3251
|
+
* // Using nprofile string (includes relay hints)
|
|
3252
|
+
* const user3 = ndk.getUser("nprofile1...");
|
|
3253
|
+
*
|
|
3254
|
+
* // Using hex pubkey directly
|
|
3255
|
+
* const user4 = ndk.getUser("deadbeef...");
|
|
3256
|
+
* ```
|
|
3257
|
+
*/
|
|
3258
|
+
getUser(opts: GetUserParams | string): NDKUser;
|
|
3259
|
+
/**
|
|
3260
|
+
* Get a NDKUser from a NIP05
|
|
3261
|
+
* @deprecated Use `fetchUser` instead - this method will be removed in the next major version
|
|
3262
|
+
* @param nip05 NIP-05 ID
|
|
3263
|
+
* @param skipCache Skip cache
|
|
3264
|
+
* @returns
|
|
3265
|
+
*/
|
|
3266
|
+
getUserFromNip05(nip05: string, skipCache?: boolean): Promise<NDKUser | undefined>;
|
|
3267
|
+
/**
|
|
3268
|
+
* Fetch a NDKUser from a string identifier
|
|
3269
|
+
*
|
|
3270
|
+
* Supports multiple input formats:
|
|
3271
|
+
* - NIP-05 identifiers (e.g., "pablo@test.com" or "test.com")
|
|
3272
|
+
* - npub (NIP-19 encoded public key)
|
|
3273
|
+
* - nprofile (NIP-19 encoded profile with optional relay hints)
|
|
3274
|
+
* - Hex public key
|
|
3275
|
+
*
|
|
3276
|
+
* @param input - String identifier for the user (NIP-05, npub, nprofile, or hex pubkey)
|
|
3277
|
+
* @param skipCache - Skip cache when resolving NIP-05 (only applies to NIP-05 lookups)
|
|
3278
|
+
* @returns Promise resolving to NDKUser or undefined if not found
|
|
3279
|
+
*
|
|
3280
|
+
* @example
|
|
3281
|
+
* ```typescript
|
|
3282
|
+
* // Using NIP-05
|
|
3283
|
+
* const user1 = await ndk.fetchUser("pablo@test.com");
|
|
3284
|
+
* const user2 = await ndk.fetchUser("test.com"); // defaults to _@test.com
|
|
3285
|
+
*
|
|
3286
|
+
* // Using npub
|
|
3287
|
+
* const user3 = await ndk.fetchUser("npub1...");
|
|
3288
|
+
*
|
|
3289
|
+
* // Using nprofile (includes relay hints)
|
|
3290
|
+
* const user4 = await ndk.fetchUser("nprofile1...");
|
|
3291
|
+
*
|
|
3292
|
+
* // Using hex pubkey
|
|
3293
|
+
* const user5 = await ndk.fetchUser("deadbeef...");
|
|
3294
|
+
* ```
|
|
3295
|
+
*/
|
|
3296
|
+
fetchUser(input: string, skipCache?: boolean): Promise<NDKUser | undefined>;
|
|
3297
|
+
/**
|
|
3298
|
+
* Creates and starts a new subscription.
|
|
3299
|
+
*
|
|
3300
|
+
* Subscriptions automatically start unless `autoStart` is set to `false`.
|
|
3301
|
+
* You can control automatic closing on EOSE via `opts.closeOnEose`.
|
|
3302
|
+
*
|
|
3303
|
+
* @param filters - A single NDKFilter object or an array of filters.
|
|
3304
|
+
* @param opts - Optional NDKSubscriptionOptions to customize behavior (e.g., caching, grouping).
|
|
3305
|
+
* @param handlers - Optional handlers for subscription events. Passing handlers is the preferred method of using ndk.subscribe.
|
|
3306
|
+
* - `onEvent`: Called for each event received.
|
|
3307
|
+
* - `onEvents`: Called once with an array of events when the subscription starts (from the cache).
|
|
3308
|
+
* - `onEose`: Called when the subscription receives EOSE.
|
|
3309
|
+
* For backwards compatibility, this third parameter also accepts a relaySet, the relaySet should be passed via `opts.relaySet`.
|
|
3310
|
+
*
|
|
3311
|
+
* @param _autoStart - For backwards compatibility, this can be a boolean indicating whether to start the subscription immediately.
|
|
3312
|
+
* This parameter is deprecated and will be removed in a future version.
|
|
3313
|
+
* - `false`: Creates the subscription but does not start it (call `subscription.start()` manually).
|
|
3314
|
+
* @returns The created NDKSubscription instance.
|
|
3315
|
+
*
|
|
3316
|
+
* @example Basic subscription
|
|
3317
|
+
* ```typescript
|
|
3318
|
+
* const sub = ndk.subscribe(
|
|
3319
|
+
* { kinds: [1], authors: [pubkey] },
|
|
3320
|
+
* {
|
|
3321
|
+
* onEvent: (event) => console.log("Kind 1 event:", event.content)
|
|
3322
|
+
* }
|
|
3323
|
+
* );
|
|
3324
|
+
* ```
|
|
3325
|
+
*
|
|
3326
|
+
* @example Subscription with options and direct handlers
|
|
3327
|
+
* ```typescript
|
|
3328
|
+
* const sub = ndk.subscribe(
|
|
3329
|
+
* { kinds: [0], authors: [pubkey] },
|
|
3330
|
+
* {
|
|
3331
|
+
* closeOnEose: true,
|
|
3332
|
+
* cacheUsage: NDKSubscriptionCacheUsage.PARALLEL,
|
|
3333
|
+
* onEvents: (events) => console.log(`Got ${events.length} profile events from cache:`, events[0].content),
|
|
3334
|
+
* onEvent: (event) => console.log("Got profile update from relay:", event.content),
|
|
3335
|
+
* onEose: () => console.log("Profile subscription finished.")
|
|
3336
|
+
* }
|
|
3337
|
+
* );
|
|
3338
|
+
* ```
|
|
3339
|
+
*
|
|
3340
|
+
* @since 2.13.0 `relaySet` parameter removed; pass `relaySet` or `relayUrls` via `opts`.
|
|
3341
|
+
*/
|
|
3342
|
+
subscribe(filters: NDKFilter | NDKFilter[], opts?: NDKSubscriptionOptions, autoStartOrRelaySet?: NDKRelaySet | boolean | NDKSubscriptionEventHandlers, _autoStart?: boolean): NDKSubscription;
|
|
3343
|
+
/**
|
|
3344
|
+
* Attempts to fetch an event from a tag, following relay hints and
|
|
3345
|
+
* other best practices.
|
|
3346
|
+
* @param tag Tag to fetch the event from
|
|
3347
|
+
* @param originalEvent Event where the tag came from
|
|
3348
|
+
* @param subOpts Subscription options to use when fetching the event
|
|
3349
|
+
* @param fallback Fallback options to use when the hint relay doesn't respond
|
|
3350
|
+
* @returns
|
|
3351
|
+
*/
|
|
3352
|
+
fetchEventFromTag: (tag: NDKTag, originalEvent: NDKEvent, subOpts?: NDKSubscriptionOptions | undefined, fallback?: NDKFetchFallbackOptions | undefined) => Promise<NDKEvent | null>;
|
|
3353
|
+
/**
|
|
3354
|
+
* Fetch an event from the cache synchronously.
|
|
3355
|
+
* @param idOrFilter event id in bech32 format or filter
|
|
3356
|
+
* @returns events from the cache or null if the cache is empty
|
|
3357
|
+
*/
|
|
3358
|
+
fetchEventSync(idOrFilter: string | NDKFilter[]): NDKEvent[] | null;
|
|
3359
|
+
/**
|
|
3360
|
+
* Fetch a single event.
|
|
3361
|
+
*
|
|
3362
|
+
* @param idOrFilter event id in bech32 format or filter
|
|
3363
|
+
* @param opts subscription options
|
|
3364
|
+
* @param relaySetOrRelay explicit relay set to use
|
|
3365
|
+
*/
|
|
3366
|
+
fetchEvent(idOrFilter: string | NDKFilter | NDKFilter[], opts?: NDKSubscriptionOptions, relaySetOrRelay?: NDKRelaySet | NDKRelay): Promise<NDKEvent | null>;
|
|
3367
|
+
/**
|
|
3368
|
+
* Fetch events
|
|
3369
|
+
*/
|
|
3370
|
+
fetchEvents(filters: NDKFilter | NDKFilter[], opts?: NDKSubscriptionOptions, relaySet?: NDKRelaySet): Promise<Set<NDKEvent>>;
|
|
3371
|
+
/**
|
|
3372
|
+
* Count events matching the given filters using NIP-45.
|
|
3373
|
+
*
|
|
3374
|
+
* This method queries multiple relays and aggregates their COUNT responses.
|
|
3375
|
+
* When relays return HyperLogLog (HLL) data, it uses the HLL algorithm to
|
|
3376
|
+
* provide accurate cardinality estimation without double-counting events
|
|
3377
|
+
* that appear on multiple relays.
|
|
3378
|
+
*
|
|
3379
|
+
* @param filters - The filters to count events for
|
|
3380
|
+
* @param opts - Optional count options (timeout, custom id)
|
|
3381
|
+
* @param relaySet - Optional relay set to use for the count request
|
|
3382
|
+
* @returns An aggregated count result with the best estimate and per-relay results
|
|
3383
|
+
*
|
|
3384
|
+
* @example Basic count
|
|
3385
|
+
* ```typescript
|
|
3386
|
+
* const result = await ndk.count([{ kinds: [1], authors: [pubkey] }]);
|
|
3387
|
+
* console.log(`Found approximately ${result.count} events`);
|
|
3388
|
+
* ```
|
|
3389
|
+
*
|
|
3390
|
+
* @example Count with specific relays
|
|
3391
|
+
* ```typescript
|
|
3392
|
+
* const relaySet = NDKRelaySet.fromRelayUrls(['wss://relay1.com', 'wss://relay2.com'], ndk);
|
|
3393
|
+
* const result = await ndk.count([{ kinds: [7], "#e": [eventId] }], {}, relaySet);
|
|
3394
|
+
* console.log(`Approximately ${result.count} reactions`);
|
|
3395
|
+
* ```
|
|
3396
|
+
*
|
|
3397
|
+
* @example Using HLL data for further analysis
|
|
3398
|
+
* ```typescript
|
|
3399
|
+
* const result = await ndk.count([{ kinds: [3] }]);
|
|
3400
|
+
* if (result.mergedHll) {
|
|
3401
|
+
* console.log('HLL data available for further merging');
|
|
3402
|
+
* }
|
|
3403
|
+
* ```
|
|
3404
|
+
*/
|
|
3405
|
+
count(filters: NDKFilter | NDKFilter[], opts?: NDKCountOptions, relaySet?: NDKRelaySet): Promise<NDKAggregatedCountResult>;
|
|
3406
|
+
/**
|
|
3407
|
+
* Ensures that a signer is available to sign an event.
|
|
3408
|
+
*/
|
|
3409
|
+
assertSigner(): void;
|
|
3410
|
+
getEntity: (entity: string) => NDKUser | nip19.DecodedNevent | nip19.DecodedNaddr | nip19.DecodedNsec | nip19.DecodedNote | null;
|
|
3411
|
+
/**
|
|
3412
|
+
* Temporarily disable AI guardrails for the next method call.
|
|
3413
|
+
*
|
|
3414
|
+
* @param ids - Optional guardrail IDs to disable. If omitted, all guardrails are disabled for the next call.
|
|
3415
|
+
* Can be a single string or an array of strings.
|
|
3416
|
+
* @returns This NDK instance for method chaining
|
|
3417
|
+
*
|
|
3418
|
+
* @example Disable all guardrails for one call
|
|
3419
|
+
* ```typescript
|
|
3420
|
+
* ndk.guardrailOff().fetchEvents({ kinds: [1] });
|
|
3421
|
+
* ```
|
|
3422
|
+
*
|
|
3423
|
+
* @example Disable specific guardrail
|
|
3424
|
+
* ```typescript
|
|
3425
|
+
* ndk.guardrailOff('fetch-events-usage').fetchEvents({ kinds: [1] });
|
|
3426
|
+
* ```
|
|
3427
|
+
*
|
|
3428
|
+
* @example Disable multiple guardrails
|
|
3429
|
+
* ```typescript
|
|
3430
|
+
* ndk.guardrailOff(['fetch-events-usage', 'filter-large-limit']).fetchEvents({ kinds: [1], limit: 5000 });
|
|
3431
|
+
* ```
|
|
3432
|
+
*/
|
|
3433
|
+
guardrailOff(ids?: string | string[]): this;
|
|
3434
|
+
set wallet(wallet: NDKWalletInterface | undefined);
|
|
3435
|
+
get wallet(): NDKWalletInterface | undefined;
|
|
3436
|
+
}
|
|
3437
|
+
|
|
3438
|
+
type ContentTag = {
|
|
3439
|
+
tags: NDKTag[];
|
|
3440
|
+
content: string;
|
|
3441
|
+
};
|
|
3442
|
+
|
|
3443
|
+
/**
|
|
3444
|
+
* NIP-73 entity types
|
|
3445
|
+
*/
|
|
3446
|
+
type NIP73EntityType = "url" | "hashtag" | "geohash" | "isbn" | "podcast:guid" | "podcast:item:guid" | "podcast:publisher:guid" | "isan" | "doi";
|
|
3447
|
+
|
|
3448
|
+
type NDKEventSerialized = string;
|
|
3449
|
+
|
|
3450
|
+
type NDKEventId = string;
|
|
3451
|
+
type NDKTag = string[];
|
|
3452
|
+
type ContentTaggingOptions = {
|
|
3453
|
+
skipContentTagging?: boolean;
|
|
3454
|
+
pTagOnQTags?: boolean;
|
|
3455
|
+
pTagOnATags?: boolean;
|
|
3456
|
+
pTags?: boolean;
|
|
3457
|
+
copyPTagsFromTarget?: boolean;
|
|
3458
|
+
filters?: {
|
|
3459
|
+
includeTypes?: Array<"npub" | "nprofile" | "note" | "nevent" | "naddr" | "hashtag">;
|
|
3460
|
+
excludeTypes?: Array<"npub" | "nprofile" | "note" | "nevent" | "naddr" | "hashtag">;
|
|
3461
|
+
};
|
|
3462
|
+
};
|
|
3463
|
+
type NostrEvent = {
|
|
3464
|
+
created_at: number;
|
|
3465
|
+
content: string;
|
|
3466
|
+
tags: NDKTag[];
|
|
3467
|
+
kind?: NDKKind | number;
|
|
3468
|
+
pubkey: string;
|
|
3469
|
+
id?: string;
|
|
3470
|
+
sig?: string;
|
|
3471
|
+
};
|
|
3472
|
+
/**
|
|
3473
|
+
* A finalized event
|
|
3474
|
+
*/
|
|
3475
|
+
type NDKRawEvent = {
|
|
3476
|
+
created_at: number;
|
|
3477
|
+
content: string;
|
|
3478
|
+
tags: NDKTag[];
|
|
3479
|
+
kind: NDKKind | number;
|
|
3480
|
+
pubkey: string;
|
|
3481
|
+
id: string;
|
|
3482
|
+
sig: string;
|
|
3483
|
+
};
|
|
3484
|
+
/**
|
|
3485
|
+
* NDKEvent is the basic building block of NDK; most things
|
|
3486
|
+
* you do with NDK will revolve around writing or consuming NDKEvents.
|
|
3487
|
+
*/
|
|
3488
|
+
declare class NDKEvent extends EventEmitter {
|
|
3489
|
+
ndk?: NDK;
|
|
3490
|
+
created_at?: number;
|
|
3491
|
+
content: string;
|
|
3492
|
+
tags: NDKTag[];
|
|
3493
|
+
kind: NDKKind | number;
|
|
3494
|
+
id: string;
|
|
3495
|
+
sig?: string;
|
|
3496
|
+
pubkey: string;
|
|
3497
|
+
signatureVerified?: boolean;
|
|
3498
|
+
private _author;
|
|
3499
|
+
/**
|
|
3500
|
+
* The relay that this event was first received from.
|
|
3501
|
+
*/
|
|
3502
|
+
relay: NDKRelay | undefined;
|
|
3503
|
+
/**
|
|
3504
|
+
* The relays that this event was received from and/or successfully published to.
|
|
3505
|
+
*/
|
|
3506
|
+
get onRelays(): NDKRelay[];
|
|
3507
|
+
/**
|
|
3508
|
+
* The status of the publish operation.
|
|
3509
|
+
*/
|
|
3510
|
+
publishStatus?: "pending" | "success" | "error";
|
|
3511
|
+
publishError?: Error;
|
|
3512
|
+
constructor(ndk?: NDK, event?: Partial<NDKRawEvent> | NDKEvent);
|
|
3513
|
+
/**
|
|
3514
|
+
* Deserialize an NDKEvent from a serialized payload.
|
|
3515
|
+
* @param ndk
|
|
3516
|
+
* @param event
|
|
3517
|
+
* @returns
|
|
3518
|
+
*/
|
|
3519
|
+
static deserialize(ndk: NDK | undefined, event: NDKEventSerialized): NDKEvent;
|
|
3520
|
+
/**
|
|
3521
|
+
* Returns the event as is.
|
|
3522
|
+
*/
|
|
3523
|
+
rawEvent(): NDKRawEvent;
|
|
3524
|
+
set author(user: NDKUser);
|
|
3525
|
+
/**
|
|
3526
|
+
* Returns an NDKUser for the author of the event.
|
|
3527
|
+
*/
|
|
3528
|
+
get author(): NDKUser;
|
|
3529
|
+
/**
|
|
3530
|
+
* NIP-73 tagging of external entities
|
|
3531
|
+
* @param entity to be tagged
|
|
3532
|
+
* @param type of the entity
|
|
3533
|
+
* @param markerUrl to be used as the marker URL
|
|
3534
|
+
*
|
|
3535
|
+
* @example
|
|
3536
|
+
* ```typescript
|
|
3537
|
+
* event.tagExternal("https://example.com/article/123#nostr", "url");
|
|
3538
|
+
* event.tags => [["i", "https://example.com/123"], ["k", "https://example.com"]]
|
|
3539
|
+
* ```
|
|
3540
|
+
*
|
|
3541
|
+
* @example tag a podcast:item:guid
|
|
3542
|
+
* ```typescript
|
|
3543
|
+
* event.tagExternal("e32b4890-b9ea-4aef-a0bf-54b787833dc5", "podcast:item:guid");
|
|
3544
|
+
* event.tags => [["i", "podcast:item:guid:e32b4890-b9ea-4aef-a0bf-54b787833dc5"], ["k", "podcast:item:guid"]]
|
|
3545
|
+
* ```
|
|
3546
|
+
*
|
|
3547
|
+
* @see https://github.com/nostr-protocol/nips/blob/master/73.md
|
|
3548
|
+
*/
|
|
3549
|
+
tagExternal(entity: string, type: NIP73EntityType, markerUrl?: string): void;
|
|
3550
|
+
/**
|
|
3551
|
+
* Tag a user with an optional marker.
|
|
3552
|
+
* @param target What is to be tagged. Can be an NDKUser, NDKEvent, or an NDKTag.
|
|
3553
|
+
* @param marker The marker to use in the tag.
|
|
3554
|
+
* @param skipAuthorTag Whether to explicitly skip adding the author tag of the event.
|
|
3555
|
+
* @param forceTag Force a specific tag to be used instead of the default "e" or "a" tag.
|
|
3556
|
+
* @param opts Optional content tagging options to control p tag behavior.
|
|
3557
|
+
* @example
|
|
3558
|
+
* ```typescript
|
|
3559
|
+
* reply.tag(opEvent, "reply");
|
|
3560
|
+
* // reply.tags => [["e", <id>, <relay>, "reply"]]
|
|
3561
|
+
* ```
|
|
3562
|
+
*/
|
|
3563
|
+
tag(target: NDKTag | NDKUser | NDKEvent, marker?: string, skipAuthorTag?: boolean, forceTag?: string, opts?: ContentTaggingOptions): void;
|
|
3564
|
+
/**
|
|
3565
|
+
* Return a NostrEvent object, trying to fill in missing fields
|
|
3566
|
+
* when possible, adding tags when necessary.
|
|
3567
|
+
* @param pubkey {string} The pubkey of the user who the event belongs to.
|
|
3568
|
+
* @param opts {ContentTaggingOptions} Options for content tagging.
|
|
3569
|
+
* @returns {Promise<NostrEvent>} A promise that resolves to a NostrEvent.
|
|
3570
|
+
*/
|
|
3571
|
+
toNostrEvent(pubkey?: string, opts?: ContentTaggingOptions): Promise<NostrEvent>;
|
|
3572
|
+
serialize: (includeSig?: boolean | undefined, includeId?: boolean | undefined) => string;
|
|
3573
|
+
getEventHash: () => string;
|
|
3574
|
+
validate: () => boolean;
|
|
3575
|
+
verifySignature: (persist: boolean) => boolean | undefined;
|
|
3576
|
+
/**
|
|
3577
|
+
* Is this event replaceable (whether parameterized or not)?
|
|
3578
|
+
*
|
|
3579
|
+
* This will return true for kind 0, 3, 10k-20k and 30k-40k
|
|
3580
|
+
*/
|
|
3581
|
+
isReplaceable: () => boolean;
|
|
3582
|
+
isEphemeral: () => boolean;
|
|
3583
|
+
isDvm: () => boolean | 0;
|
|
3584
|
+
/**
|
|
3585
|
+
* Is this event parameterized replaceable?
|
|
3586
|
+
*
|
|
3587
|
+
* This will return true for kind 30k-40k
|
|
3588
|
+
*/
|
|
3589
|
+
isParamReplaceable: () => boolean;
|
|
3590
|
+
/**
|
|
3591
|
+
* Encodes a bech32 id.
|
|
3592
|
+
*
|
|
3593
|
+
* @param relays {string[]} The relays to encode in the id
|
|
3594
|
+
* @returns {string} - Encoded naddr, note or nevent.
|
|
3595
|
+
*/
|
|
3596
|
+
encode: (maxRelayCount?: number | undefined) => string;
|
|
3597
|
+
encrypt: (recipient?: NDKUser | undefined, signer?: NDKSigner | undefined, scheme?: NDKEncryptionScheme | undefined) => Promise<void>;
|
|
3598
|
+
decrypt: (sender?: NDKUser | undefined, signer?: NDKSigner | undefined, scheme?: NDKEncryptionScheme | undefined) => Promise<void>;
|
|
3599
|
+
/**
|
|
3600
|
+
* Get all tags with the given name
|
|
3601
|
+
* @param tagName {string} The name of the tag to search for
|
|
3602
|
+
* @returns {NDKTag[]} An array of the matching tags
|
|
3603
|
+
*/
|
|
3604
|
+
getMatchingTags(tagName: string, marker?: string): NDKTag[];
|
|
3605
|
+
/**
|
|
3606
|
+
* Check if the event has a tag with the given name
|
|
3607
|
+
* @param tagName
|
|
3608
|
+
* @param marker
|
|
3609
|
+
* @returns
|
|
3610
|
+
*/
|
|
3611
|
+
hasTag(tagName: string, marker?: string): boolean;
|
|
3612
|
+
/**
|
|
3613
|
+
* Get the first tag with the given name
|
|
3614
|
+
* @param tagName Tag name to search for
|
|
3615
|
+
* @returns The value of the first tag with the given name, or undefined if no such tag exists
|
|
3616
|
+
*/
|
|
3617
|
+
tagValue(tagName: string, marker?: string): string | undefined;
|
|
3618
|
+
/**
|
|
3619
|
+
* Gets the NIP-31 "alt" tag of the event.
|
|
3620
|
+
*/
|
|
3621
|
+
get alt(): string | undefined;
|
|
3622
|
+
/**
|
|
3623
|
+
* Sets the NIP-31 "alt" tag of the event. Use this to set an alt tag so
|
|
3624
|
+
* clients that don't handle a particular event kind can display something
|
|
3625
|
+
* useful for users.
|
|
3626
|
+
*/
|
|
3627
|
+
set alt(alt: string | undefined);
|
|
3628
|
+
/**
|
|
3629
|
+
* Gets the NIP-33 "d" tag of the event.
|
|
3630
|
+
*/
|
|
3631
|
+
get dTag(): string | undefined;
|
|
3632
|
+
/**
|
|
3633
|
+
* Sets the NIP-33 "d" tag of the event.
|
|
3634
|
+
*/
|
|
3635
|
+
set dTag(value: string | undefined);
|
|
3636
|
+
/**
|
|
3637
|
+
* Remove all tags with the given name (e.g. "d", "a", "p")
|
|
3638
|
+
* @param tagName Tag name(s) to search for and remove
|
|
3639
|
+
* @param marker Optional marker to check for too
|
|
3640
|
+
*
|
|
3641
|
+
* @example
|
|
3642
|
+
* Remove a tags with a "defer" marker
|
|
3643
|
+
* ```typescript
|
|
3644
|
+
* event.tags = [
|
|
3645
|
+
* ["a", "....", "defer"],
|
|
3646
|
+
* ["a", "....", "no-defer"],
|
|
3647
|
+
* ]
|
|
3648
|
+
*
|
|
3649
|
+
* event.removeTag("a", "defer");
|
|
3650
|
+
*
|
|
3651
|
+
* // event.tags => [["a", "....", "no-defer"]]
|
|
3652
|
+
*
|
|
3653
|
+
* @returns {void}
|
|
3654
|
+
*/
|
|
3655
|
+
removeTag(tagName: string | string[], marker?: string): void;
|
|
3656
|
+
/**
|
|
3657
|
+
* Replace a tag with a new value. If not found, it will be added.
|
|
3658
|
+
* @param tag The tag to replace.
|
|
3659
|
+
* @param value The new value for the tag.
|
|
3660
|
+
*/
|
|
3661
|
+
replaceTag(tag: NDKTag): void;
|
|
3662
|
+
/**
|
|
3663
|
+
* Sign the event if a signer is present.
|
|
3664
|
+
*
|
|
3665
|
+
* It will generate tags.
|
|
3666
|
+
* Repleacable events will have their created_at field set to the current time.
|
|
3667
|
+
* @param signer {NDKSigner} The NDKSigner to use to sign the event
|
|
3668
|
+
* @param opts {ContentTaggingOptions} Options for content tagging.
|
|
3669
|
+
* @returns {Promise<string>} A Promise that resolves to the signature of the signed event.
|
|
3670
|
+
*/
|
|
3671
|
+
sign(signer?: NDKSigner, opts?: ContentTaggingOptions): Promise<string>;
|
|
3672
|
+
/**
|
|
3673
|
+
*
|
|
3674
|
+
* @param relaySet
|
|
3675
|
+
* @param timeoutMs
|
|
3676
|
+
* @param requiredRelayCount
|
|
3677
|
+
* @returns
|
|
3678
|
+
*/
|
|
3679
|
+
publishReplaceable(relaySet?: NDKRelaySet, timeoutMs?: number, requiredRelayCount?: number): Promise<Set<NDKRelay>>;
|
|
3680
|
+
/**
|
|
3681
|
+
* Attempt to sign and then publish an NDKEvent to a given relaySet.
|
|
3682
|
+
* If no relaySet is provided, the relaySet will be calculated by NDK.
|
|
3683
|
+
* @param relaySet {NDKRelaySet} The relaySet to publish the even to.
|
|
3684
|
+
* @param timeoutM {number} The timeout for the publish operation in milliseconds.
|
|
3685
|
+
* @param requiredRelayCount The number of relays that must receive the event for the publish to be considered successful.
|
|
3686
|
+
* @param opts {ContentTaggingOptions} Options for content tagging.
|
|
3687
|
+
* @returns A promise that resolves to the relays the event was published to.
|
|
3688
|
+
*/
|
|
3689
|
+
publish(relaySet?: NDKRelaySet, timeoutMs?: number, requiredRelayCount?: number, opts?: ContentTaggingOptions): Promise<Set<NDKRelay>>;
|
|
3690
|
+
/**
|
|
3691
|
+
* Generates tags for users, notes, and other events tagged in content.
|
|
3692
|
+
* Will also generate random "d" tag for parameterized replaceable events where needed.
|
|
3693
|
+
* @param opts {ContentTaggingOptions} Options for content tagging.
|
|
3694
|
+
* @returns {ContentTag} The tags and content of the event.
|
|
3695
|
+
*/
|
|
3696
|
+
generateTags(opts?: ContentTaggingOptions): Promise<ContentTag>;
|
|
3697
|
+
get shouldAddClientTag(): boolean;
|
|
3698
|
+
get shouldStripClientTag(): boolean;
|
|
3699
|
+
muted(): string | null;
|
|
3700
|
+
/**
|
|
3701
|
+
* Returns the "d" tag of a parameterized replaceable event or throws an error if the event isn't
|
|
3702
|
+
* a parameterized replaceable event.
|
|
3703
|
+
* @returns {string} the "d" tag of the event.
|
|
3704
|
+
*
|
|
3705
|
+
* @deprecated Use `dTag` instead.
|
|
3706
|
+
*/
|
|
3707
|
+
replaceableDTag(): string;
|
|
3708
|
+
/**
|
|
3709
|
+
* Provides a deduplication key for the event.
|
|
3710
|
+
*
|
|
3711
|
+
* For kinds 0, 3, 10k-20k this will be the event <kind>:<pubkey>
|
|
3712
|
+
* For kinds 30k-40k this will be the event <kind>:<pubkey>:<d-tag>
|
|
3713
|
+
* For all other kinds this will be the event id
|
|
3714
|
+
*/
|
|
3715
|
+
deduplicationKey(): string;
|
|
3716
|
+
/**
|
|
3717
|
+
* Returns the id of the event or, if it's a parameterized event, the generated id of the event using "d" tag, pubkey, and kind.
|
|
3718
|
+
* @returns {string} The id
|
|
3719
|
+
*/
|
|
3720
|
+
tagId(): string;
|
|
3721
|
+
/**
|
|
3722
|
+
* Returns a stable reference value for a replaceable event.
|
|
3723
|
+
*
|
|
3724
|
+
* Param replaceable events are returned in the expected format of `<kind>:<pubkey>:<d-tag>`.
|
|
3725
|
+
* Kind-replaceable events are returned in the format of `<kind>:<pubkey>:`.
|
|
3726
|
+
*
|
|
3727
|
+
* @returns {string} A stable reference value for replaceable events
|
|
3728
|
+
*/
|
|
3729
|
+
tagAddress(): string;
|
|
3730
|
+
/**
|
|
3731
|
+
* Determines the type of tag that can be used to reference this event from another event.
|
|
3732
|
+
* @returns {string} The tag type
|
|
3733
|
+
* @example
|
|
3734
|
+
* event = new NDKEvent(ndk, { kind: 30000, pubkey: 'pubkey', tags: [ ["d", "d-code"] ] });
|
|
3735
|
+
* event.tagType(); // "a"
|
|
3736
|
+
*/
|
|
3737
|
+
tagType(): "e" | "a";
|
|
3738
|
+
/**
|
|
3739
|
+
* Get the tag that can be used to reference this event from another event.
|
|
3740
|
+
*
|
|
3741
|
+
* Consider using referenceTags() instead (unless you have a good reason to use this)
|
|
3742
|
+
*
|
|
3743
|
+
* @example
|
|
3744
|
+
* event = new NDKEvent(ndk, { kind: 30000, pubkey: 'pubkey', tags: [ ["d", "d-code"] ] });
|
|
3745
|
+
* event.tagReference(); // ["a", "30000:pubkey:d-code"]
|
|
3746
|
+
*
|
|
3747
|
+
* event = new NDKEvent(ndk, { kind: 1, pubkey: 'pubkey', id: "eventid" });
|
|
3748
|
+
* event.tagReference(); // ["e", "eventid"]
|
|
3749
|
+
* @returns {NDKTag} The NDKTag object referencing this event
|
|
3750
|
+
*/
|
|
3751
|
+
tagReference(marker?: string): NDKTag;
|
|
3752
|
+
/**
|
|
3753
|
+
* Get the tags that can be used to reference this event from another event
|
|
3754
|
+
* @param marker The marker to use in the tag
|
|
3755
|
+
* @param skipAuthorTag Whether to explicitly skip adding the author tag of the event
|
|
3756
|
+
* @param forceTag Force a specific tag to be used instead of the default "e" or "a" tag
|
|
3757
|
+
* @example
|
|
3758
|
+
* event = new NDKEvent(ndk, { kind: 30000, pubkey: 'pubkey', tags: [ ["d", "d-code"] ] });
|
|
3759
|
+
* event.referenceTags(); // [["a", "30000:pubkey:d-code"], ["e", "parent-id"]]
|
|
3760
|
+
*
|
|
3761
|
+
* event = new NDKEvent(ndk, { kind: 1, pubkey: 'pubkey', id: "eventid" });
|
|
3762
|
+
* event.referenceTags(); // [["e", "parent-id"]]
|
|
3763
|
+
* @returns {NDKTag} The NDKTag object referencing this event
|
|
3764
|
+
*/
|
|
3765
|
+
referenceTags(marker?: string, skipAuthorTag?: boolean, forceTag?: string, opts?: ContentTaggingOptions): NDKTag[];
|
|
3766
|
+
/**
|
|
3767
|
+
* Provides the filter that will return matching events for this event.
|
|
3768
|
+
*
|
|
3769
|
+
* @example
|
|
3770
|
+
* event = new NDKEvent(ndk, { kind: 30000, pubkey: 'pubkey', tags: [ ["d", "d-code"] ] });
|
|
3771
|
+
* event.filter(); // { "#a": ["30000:pubkey:d-code"] }
|
|
3772
|
+
* @example
|
|
3773
|
+
* event = new NDKEvent(ndk, { kind: 1, pubkey: 'pubkey', id: "eventid" });
|
|
3774
|
+
* event.filter(); // { "#e": ["eventid"] }
|
|
3775
|
+
*
|
|
3776
|
+
* @returns The filter that will return matching events for this event
|
|
3777
|
+
*/
|
|
3778
|
+
filter(): NDKFilter;
|
|
3779
|
+
nip22Filter(): NDKFilter;
|
|
3780
|
+
/**
|
|
3781
|
+
* Generates a deletion event of the current event
|
|
3782
|
+
*
|
|
3783
|
+
* @param reason The reason for the deletion
|
|
3784
|
+
* @param publish Whether to publish the deletion event automatically
|
|
3785
|
+
* @returns The deletion event
|
|
3786
|
+
*/
|
|
3787
|
+
delete(reason?: string, publish?: boolean): Promise<NDKEvent>;
|
|
3788
|
+
/**
|
|
3789
|
+
* Establishes whether this is a NIP-70-protectede event.
|
|
3790
|
+
* @@satisfies NIP-70
|
|
3791
|
+
*/
|
|
3792
|
+
set isProtected(val: boolean);
|
|
3793
|
+
/**
|
|
3794
|
+
* Whether this is a NIP-70-protected event.
|
|
3795
|
+
* @@satisfies NIP-70
|
|
3796
|
+
*/
|
|
3797
|
+
get isProtected(): boolean;
|
|
3798
|
+
/**
|
|
3799
|
+
* Fetch an event tagged with the given tag following relay hints if provided.
|
|
3800
|
+
* @param tag The tag to search for
|
|
3801
|
+
* @param marker The marker to use in the tag (e.g. "root")
|
|
3802
|
+
* @returns The fetched event or null if no event was found, undefined if no matching tag was found in the event
|
|
3803
|
+
* * @example
|
|
3804
|
+
* const replyEvent = await ndk.fetchEvent("nevent1qqs8x8vnycyha73grv380gmvlury4wtmx0nr9a5ds2dngqwgu87wn6gpzemhxue69uhhyetvv9ujuurjd9kkzmpwdejhgq3ql2vyh47mk2p0qlsku7hg0vn29faehy9hy34ygaclpn66ukqp3afqz4cwjd")
|
|
3805
|
+
* const originalEvent = await replyEvent.fetchTaggedEvent("e", "reply");
|
|
3806
|
+
* console.log(replyEvent.encode() + " is a reply to event " + originalEvent?.encode());
|
|
3807
|
+
*/
|
|
3808
|
+
fetchTaggedEvent: (tag: string, marker?: string | undefined) => Promise<NDKEvent | null | undefined>;
|
|
3809
|
+
/**
|
|
3810
|
+
* Fetch the root event of the current event.
|
|
3811
|
+
* @returns The fetched root event or null if no event was found
|
|
3812
|
+
* @example
|
|
3813
|
+
* const replyEvent = await ndk.fetchEvent("nevent1qqs8x8vnycyha73grv380gmvlury4wtmx0nr9a5ds2dngqwgu87wn6gpzemhxue69uhhyetvv9ujuurjd9kkzmpwdejhgq3ql2vyh47mk2p0qlsku7hg0vn29faehy9hy34ygaclpn66ukqp3afqz4cwjd")
|
|
3814
|
+
* const rootEvent = await replyEvent.fetchRootEvent();
|
|
3815
|
+
* console.log(replyEvent.encode() + " is a reply in the thread " + rootEvent?.encode());
|
|
3816
|
+
*/
|
|
3817
|
+
fetchRootEvent: (subOpts?: NDKSubscriptionOptions | undefined) => Promise<NDKEvent | null | undefined>;
|
|
3818
|
+
/**
|
|
3819
|
+
* Fetch the event the current event is replying to.
|
|
3820
|
+
* @returns The fetched reply event or null if no event was found
|
|
3821
|
+
*/
|
|
3822
|
+
fetchReplyEvent: (subOpts?: NDKSubscriptionOptions | undefined) => Promise<NDKEvent | null | undefined>;
|
|
3823
|
+
/**
|
|
3824
|
+
* NIP-18 reposting event.
|
|
3825
|
+
*
|
|
3826
|
+
* @param publish Whether to publish the reposted event automatically @default true
|
|
3827
|
+
* @param signer The signer to use for signing the reposted event
|
|
3828
|
+
* @returns The reposted event
|
|
3829
|
+
*
|
|
3830
|
+
* @function
|
|
3831
|
+
*/
|
|
3832
|
+
repost: (publish?: boolean | undefined, signer?: NDKSigner | undefined) => Promise<NDKEvent>;
|
|
3833
|
+
/**
|
|
3834
|
+
* React to an existing event
|
|
3835
|
+
*
|
|
3836
|
+
* @param content The content of the reaction
|
|
3837
|
+
*/
|
|
3838
|
+
react(content: string, publish?: boolean): Promise<NDKEvent>;
|
|
3839
|
+
/**
|
|
3840
|
+
* Checks whether the event is valid per underlying NIPs.
|
|
3841
|
+
*
|
|
3842
|
+
* This method is meant to be overridden by subclasses that implement specific NIPs
|
|
3843
|
+
* to allow the enforcement of NIP-specific validation rules.
|
|
3844
|
+
*
|
|
3845
|
+
* Otherwise, it will only check for basic event properties.
|
|
3846
|
+
*
|
|
3847
|
+
*/
|
|
3848
|
+
get isValid(): boolean;
|
|
3849
|
+
get inspect(): string;
|
|
3850
|
+
/**
|
|
3851
|
+
* Dump the event to console for debugging purposes.
|
|
3852
|
+
* Prints a JSON stringified version of rawEvent() with indentation
|
|
3853
|
+
* and also lists all relay URLs for onRelays.
|
|
3854
|
+
*/
|
|
3855
|
+
dump(): void;
|
|
3856
|
+
/**
|
|
3857
|
+
* Creates a reply event for the current event.
|
|
3858
|
+
*
|
|
3859
|
+
* This function will use NIP-22 when appropriate (i.e. replies to non-kind:1 events).
|
|
3860
|
+
* This function does not have side-effects; it will just return an event with the appropriate tags
|
|
3861
|
+
* to generate the reply event; the caller is responsible for publishing the event.
|
|
3862
|
+
*
|
|
3863
|
+
* @param forceNip22 - Optional flag to force NIP-22 style replies (kind 1111) regardless of the original event's kind
|
|
3864
|
+
* @param opts - Optional content tagging options
|
|
3865
|
+
*/
|
|
3866
|
+
reply(forceNip22?: boolean, opts?: ContentTaggingOptions): NDKEvent;
|
|
3867
|
+
}
|
|
3868
|
+
/**
|
|
3869
|
+
* Discriminated union types for signed and unsigned events
|
|
3870
|
+
*/
|
|
3871
|
+
/**
|
|
3872
|
+
* An NDKEvent that has been signed and has all required fields for relay transmission
|
|
3873
|
+
*/
|
|
3874
|
+
type NDKSignedEvent = NDKEvent & {
|
|
3875
|
+
readonly signed: true;
|
|
3876
|
+
id: string;
|
|
3877
|
+
sig: string;
|
|
3878
|
+
created_at: number;
|
|
3879
|
+
};
|
|
3880
|
+
|
|
3881
|
+
type NDKEncryptionScheme = "nip04" | "nip44";
|
|
3882
|
+
|
|
3883
|
+
declare enum NdkNutzapStatus {
|
|
3884
|
+
INITIAL = "initial",
|
|
3885
|
+
PROCESSING = "processing",
|
|
3886
|
+
REDEEMED = "redeemed",
|
|
3887
|
+
SPENT = "spent",
|
|
3888
|
+
MISSING_PRIVKEY = "missing_privkey",
|
|
3889
|
+
TEMPORARY_ERROR = "temporary_error",
|
|
3890
|
+
PERMANENT_ERROR = "permanent_error",
|
|
3891
|
+
INVALID_NUTZAP = "invalid_nutzap"
|
|
3892
|
+
}
|
|
3893
|
+
interface NDKNutzapState {
|
|
3894
|
+
nutzap?: NDKNutzap;
|
|
3895
|
+
status: NdkNutzapStatus;
|
|
3896
|
+
redeemedById?: NDKEventId;
|
|
3897
|
+
errorMessage?: string;
|
|
3898
|
+
redeemedAmount?: number;
|
|
3899
|
+
}
|
|
3900
|
+
|
|
3901
|
+
/**
|
|
3902
|
+
* A signer that uses an in-memory private key (nsec).
|
|
3903
|
+
*
|
|
3904
|
+
* @example
|
|
3905
|
+
* ```ts
|
|
3906
|
+
* const signer = NDKPrivateKeySigner.generate();
|
|
3907
|
+
* console.log('your nsec is', signer.nsec);
|
|
3908
|
+
* console.log('your pubkey is', signer.pubkey);
|
|
3909
|
+
* console.log('your npub is', signer.npub);
|
|
3910
|
+
* ```
|
|
3911
|
+
*
|
|
3912
|
+
* @example
|
|
3913
|
+
* ```ts
|
|
3914
|
+
* const signer = new NDKPrivateKeySigner(nsec);
|
|
3915
|
+
* ```
|
|
3916
|
+
*/
|
|
3917
|
+
declare class NDKPrivateKeySigner implements NDKSigner {
|
|
3918
|
+
private _user;
|
|
3919
|
+
private _privateKey;
|
|
3920
|
+
private _pubkey?;
|
|
3921
|
+
/**
|
|
3922
|
+
* Create a new signer from a private key.
|
|
3923
|
+
* @param privateKey - The private key to use in hex form or nsec.
|
|
3924
|
+
* @param ndk - The NDK instance to use.
|
|
3925
|
+
*
|
|
3926
|
+
* @ai-guardrail
|
|
3927
|
+
* If you have an nsec (bech32-encoded private key starting with "nsec1"), you can pass it directly
|
|
3928
|
+
* to this constructor without decoding it first. The constructor handles both hex and nsec formats automatically.
|
|
3929
|
+
* DO NOT use nip19.decode() to convert nsec to hex before passing it here - just pass the nsec string directly.
|
|
3930
|
+
*/
|
|
3931
|
+
constructor(privateKeyOrNsec: Uint8Array | string, ndk?: NDK);
|
|
3932
|
+
/**
|
|
3933
|
+
* Get the private key in hex form.
|
|
3934
|
+
*/
|
|
3935
|
+
get privateKey(): string;
|
|
3936
|
+
/**
|
|
3937
|
+
* Get the public key in hex form.
|
|
3938
|
+
*/
|
|
3939
|
+
get pubkey(): string;
|
|
3940
|
+
/**
|
|
3941
|
+
* Get the private key in nsec form.
|
|
3942
|
+
*/
|
|
3943
|
+
get nsec(): string;
|
|
3944
|
+
/**
|
|
3945
|
+
* Get the public key in npub form.
|
|
3946
|
+
*/
|
|
3947
|
+
get npub(): string;
|
|
3948
|
+
/**
|
|
3949
|
+
* Encrypt the private key with a password to ncryptsec format.
|
|
3950
|
+
* @param password - The password to encrypt the private key.
|
|
3951
|
+
* @param logn - The log2 of the scrypt N parameter (default: 16).
|
|
3952
|
+
* @param ksb - The key security byte (0x00, 0x01, or 0x02, default: 0x02).
|
|
3953
|
+
* @returns The encrypted private key in ncryptsec format.
|
|
3954
|
+
*
|
|
3955
|
+
* @example
|
|
3956
|
+
* ```ts
|
|
3957
|
+
* const signer = new NDKPrivateKeySigner(nsec);
|
|
3958
|
+
* const ncryptsec = signer.encryptToNcryptsec("my-password");
|
|
3959
|
+
* console.log('encrypted key:', ncryptsec);
|
|
3960
|
+
* ```
|
|
3961
|
+
*/
|
|
3962
|
+
encryptToNcryptsec(password: string, logn?: number, ksb?: 0x00 | 0x01 | 0x02): string;
|
|
3963
|
+
/**
|
|
3964
|
+
* Generate a new private key.
|
|
3965
|
+
*/
|
|
3966
|
+
static generate(): NDKPrivateKeySigner;
|
|
3967
|
+
/**
|
|
3968
|
+
* Create a signer from an encrypted private key (ncryptsec) using a password.
|
|
3969
|
+
* @param ncryptsec - The encrypted private key in ncryptsec format.
|
|
3970
|
+
* @param password - The password to decrypt the private key.
|
|
3971
|
+
* @param ndk - Optional NDK instance.
|
|
3972
|
+
* @returns A new NDKPrivateKeySigner instance.
|
|
3973
|
+
*
|
|
3974
|
+
* @example
|
|
3975
|
+
* ```ts
|
|
3976
|
+
* const signer = NDKPrivateKeySigner.fromNcryptsec(
|
|
3977
|
+
* "ncryptsec1qgg9947rlpvqu76pj5ecreduf9jxhselq2nae2kghhvd5g7dgjtcxfqtd67p9m0w57lspw8gsq6yphnm8623nsl8xn9j4jdzz84zm3frztj3z7s35vpzmqf6ksu8r89qk5z2zxfmu5gv8th8wclt0h4p",
|
|
3978
|
+
* "my-password"
|
|
3979
|
+
* );
|
|
3980
|
+
* console.log('your pubkey is', signer.pubkey);
|
|
3981
|
+
* ```
|
|
3982
|
+
*/
|
|
3983
|
+
static fromNcryptsec(ncryptsec: string, password: string, ndk?: NDK): NDKPrivateKeySigner;
|
|
3984
|
+
/**
|
|
3985
|
+
* Noop in NDKPrivateKeySigner.
|
|
3986
|
+
*/
|
|
3987
|
+
blockUntilReady(): Promise<NDKUser>;
|
|
3988
|
+
/**
|
|
3989
|
+
* Get the user.
|
|
3990
|
+
*/
|
|
3991
|
+
user(): Promise<NDKUser>;
|
|
3992
|
+
/**
|
|
3993
|
+
* Get the user.
|
|
3994
|
+
*/
|
|
3995
|
+
get userSync(): NDKUser;
|
|
3996
|
+
sign(event: NostrEvent): Promise<string>;
|
|
3997
|
+
encryptionEnabled(scheme?: NDKEncryptionScheme): Promise<NDKEncryptionScheme[]>;
|
|
3998
|
+
encrypt(recipient: NDKUser, value: string, scheme?: NDKEncryptionScheme): Promise<string>;
|
|
3999
|
+
decrypt(sender: NDKUser, value: string, scheme?: NDKEncryptionScheme): Promise<string>;
|
|
4000
|
+
/**
|
|
4001
|
+
* Serializes the signer's private key into a storable format.
|
|
4002
|
+
* @returns A JSON string containing the type and the hex private key.
|
|
4003
|
+
*/
|
|
4004
|
+
toPayload(): string;
|
|
4005
|
+
/**
|
|
4006
|
+
* Deserializes the signer from a payload string.
|
|
4007
|
+
* @param payloadString The JSON string obtained from toPayload().
|
|
4008
|
+
* @param ndk Optional NDK instance.
|
|
4009
|
+
* @returns An instance of NDKPrivateKeySigner.
|
|
4010
|
+
*/
|
|
4011
|
+
static fromPayload(payloadString: string, ndk?: NDK): Promise<NDKPrivateKeySigner>;
|
|
4012
|
+
}
|
|
4013
|
+
|
|
4014
|
+
type Nip07RelayMap = {
|
|
4015
|
+
[key: string]: {
|
|
4016
|
+
read: boolean;
|
|
4017
|
+
write: boolean;
|
|
4018
|
+
};
|
|
4019
|
+
};
|
|
4020
|
+
type Nip44 = {
|
|
4021
|
+
encrypt: (recipient: Hexpubkey, value: string) => Promise<string>;
|
|
4022
|
+
decrypt: (sender: Hexpubkey, value: string) => Promise<string>;
|
|
4023
|
+
};
|
|
4024
|
+
declare global {
|
|
4025
|
+
interface Window {
|
|
4026
|
+
nostr?: {
|
|
4027
|
+
getPublicKey(): Promise<string>;
|
|
4028
|
+
signEvent(event: NostrEvent): Promise<{
|
|
4029
|
+
sig: string;
|
|
4030
|
+
}>;
|
|
4031
|
+
getRelays?: () => Promise<Nip07RelayMap>;
|
|
4032
|
+
nip04?: {
|
|
4033
|
+
encrypt(recipientHexPubKey: string, value: string): Promise<string>;
|
|
4034
|
+
decrypt(senderHexPubKey: string, value: string): Promise<string>;
|
|
4035
|
+
};
|
|
4036
|
+
nip44?: Nip44;
|
|
4037
|
+
};
|
|
4038
|
+
}
|
|
4039
|
+
}
|
|
4040
|
+
|
|
4041
|
+
type Names = "alice" | "bob" | "carol" | "dave" | "eve";
|
|
4042
|
+
/**
|
|
4043
|
+
* Generates deterministic test users for consistent, reproducible testing.
|
|
4044
|
+
*
|
|
4045
|
+
* Provides predefined users (alice, bob, carol, dave, eve) with static keypairs,
|
|
4046
|
+
* ensuring your tests produce the same results every time. Perfect for testing
|
|
4047
|
+
* multi-user interactions in your Nostr application.
|
|
4048
|
+
*
|
|
4049
|
+
* @example
|
|
4050
|
+
* ```typescript
|
|
4051
|
+
* // Get a deterministic test user
|
|
4052
|
+
* const alice = await UserGenerator.getUser('alice', ndk);
|
|
4053
|
+
* const bob = await UserGenerator.getUser('bob', ndk);
|
|
4054
|
+
*
|
|
4055
|
+
* // Use in your app tests
|
|
4056
|
+
* const dm = await myApp.sendMessage(alice, bob, 'Hello!');
|
|
4057
|
+
* ```
|
|
4058
|
+
*/
|
|
4059
|
+
declare class UserGenerator {
|
|
4060
|
+
static privateKeys: Record<string, string>;
|
|
4061
|
+
/**
|
|
4062
|
+
* Get a deterministic test user by name.
|
|
4063
|
+
*
|
|
4064
|
+
* Returns a test user with a predefined keypair, ensuring consistent behavior
|
|
4065
|
+
* across test runs. Use this when testing features that involve specific users.
|
|
4066
|
+
*
|
|
4067
|
+
* @param name The name of the user (alice, bob, carol, dave, eve)
|
|
4068
|
+
* @param ndk Optional NDK instance to attach to the user
|
|
4069
|
+
* @returns The NDK user with a deterministic keypair
|
|
4070
|
+
*
|
|
4071
|
+
* @example
|
|
4072
|
+
* ```typescript
|
|
4073
|
+
* const alice = await UserGenerator.getUser('alice', ndk);
|
|
4074
|
+
* expect(alice.pubkey).toBe('e9e4276490374a0daf7759fd5f475deff6ffb9b0fc5fa98c902b5f4b2fe3bba1');
|
|
4075
|
+
* ```
|
|
4076
|
+
*/
|
|
4077
|
+
static getUser(name: Names, ndk?: NDK): Promise<NDKUser>;
|
|
4078
|
+
/**
|
|
4079
|
+
* Get the private key for a specific test user
|
|
4080
|
+
* @param name The name of the user (alice, bob, carol, dave, eve)
|
|
4081
|
+
* @returns The private key hex string
|
|
4082
|
+
*/
|
|
4083
|
+
static getPrivateKey(name: Names): string;
|
|
4084
|
+
/**
|
|
4085
|
+
* Get a user with a random private key
|
|
4086
|
+
* @param ndk The NDK instance to use for the user
|
|
4087
|
+
* @returns The NDK user
|
|
4088
|
+
*/
|
|
4089
|
+
static getRandomUser(ndk?: NDK): Promise<NDKUser>;
|
|
4090
|
+
}
|
|
4091
|
+
/**
|
|
4092
|
+
* Generates signers for test users to sign events in your application tests.
|
|
4093
|
+
*
|
|
4094
|
+
* Provides signers for predefined test users, allowing you to test event signing,
|
|
4095
|
+
* publishing, and authentication flows in your Nostr application.
|
|
4096
|
+
*
|
|
4097
|
+
* @example
|
|
4098
|
+
* ```typescript
|
|
4099
|
+
* // Get a signer for a test user
|
|
4100
|
+
* const aliceSigner = SignerGenerator.getSigner('alice');
|
|
4101
|
+
* ndk.signer = aliceSigner;
|
|
4102
|
+
*
|
|
4103
|
+
* // Now alice can sign events in your app
|
|
4104
|
+
* await myApp.publishNote('Hello, Nostr!');
|
|
4105
|
+
* ```
|
|
4106
|
+
*/
|
|
4107
|
+
declare class SignerGenerator {
|
|
4108
|
+
/**
|
|
4109
|
+
* Get a signer for a specific test user
|
|
4110
|
+
* @param name The name of the user (alice, bob, carol, dave, eve)
|
|
4111
|
+
* @returns The NDK signer
|
|
4112
|
+
*/
|
|
4113
|
+
static getSigner(name: Names): NDKPrivateKeySigner;
|
|
4114
|
+
static sign(event: NDKEvent, user: Names): Promise<NDKEvent>;
|
|
4115
|
+
/**
|
|
4116
|
+
* Generate a random signer
|
|
4117
|
+
* @returns The NDK signer
|
|
4118
|
+
*/
|
|
4119
|
+
static getRandomSigner(): NDKPrivateKeySigner;
|
|
4120
|
+
}
|
|
4121
|
+
/**
|
|
4122
|
+
* High-level event factory for creating test events with proper relationships and tagging.
|
|
4123
|
+
*
|
|
4124
|
+
* Provides convenient methods for creating common event patterns like notes, DMs,
|
|
4125
|
+
* replies, and conversation threads. Automatically handles proper NIP-10 tagging
|
|
4126
|
+
* and event relationships for testing your app's event handling logic.
|
|
4127
|
+
*
|
|
4128
|
+
* @example
|
|
4129
|
+
* ```typescript
|
|
4130
|
+
* const factory = new TestEventFactory(ndk);
|
|
4131
|
+
* const alice = await UserGenerator.getUser('alice', ndk);
|
|
4132
|
+
* const bob = await UserGenerator.getUser('bob', ndk);
|
|
4133
|
+
*
|
|
4134
|
+
* // Create a note
|
|
4135
|
+
* const note = await factory.createSignedTextNote('Hello!', alice);
|
|
4136
|
+
*
|
|
4137
|
+
* // Create a reply
|
|
4138
|
+
* const reply = await factory.createReply(note, 'Hi back!', bob);
|
|
4139
|
+
*
|
|
4140
|
+
* // Create a DM
|
|
4141
|
+
* const dm = await factory.createDirectMessage('Secret message', alice, bob);
|
|
4142
|
+
*
|
|
4143
|
+
* // Create a conversation thread
|
|
4144
|
+
* const thread = await factory.createEventChain('Original post', alice, [
|
|
4145
|
+
* { author: bob, content: 'First reply' },
|
|
4146
|
+
* { author: alice, content: 'Response' }
|
|
4147
|
+
* ]);
|
|
4148
|
+
* ```
|
|
4149
|
+
*/
|
|
4150
|
+
declare class TestEventFactory {
|
|
4151
|
+
private ndk;
|
|
4152
|
+
constructor(ndk: NDK);
|
|
4153
|
+
/**
|
|
4154
|
+
* Create a signed text note from a specific user
|
|
4155
|
+
* @param content The content of the note
|
|
4156
|
+
* @param user The user that authored the note, or name of predefined test user
|
|
4157
|
+
* @param kind The kind of the event (defaults to 1)
|
|
4158
|
+
* @returns The signed event
|
|
4159
|
+
*/
|
|
4160
|
+
createSignedTextNote(content: string, user: NDKUser | Names | undefined, kind?: number): Promise<any>;
|
|
4161
|
+
/**
|
|
4162
|
+
* Create a direct message from one user to another
|
|
4163
|
+
* @param content The content of the message
|
|
4164
|
+
* @param fromUser The sender (author)
|
|
4165
|
+
* @param toUser The recipient
|
|
4166
|
+
* @returns The created event (not necessarily signed)
|
|
4167
|
+
*/
|
|
4168
|
+
createDirectMessage(content: string, fromUser: NDKUser | Names, toUser: NDKUser | Names): Promise<any>;
|
|
4169
|
+
/**
|
|
4170
|
+
* Create a reply to an event
|
|
4171
|
+
* @param originalEvent The event being replied to
|
|
4172
|
+
* @param content The content of the reply
|
|
4173
|
+
* @param fromUser The author of the reply
|
|
4174
|
+
* @param kind The kind of the reply (defaults to same as original for kind 1, or 1111 for other kinds)
|
|
4175
|
+
* @returns The created reply event (not necessarily signed)
|
|
4176
|
+
*/
|
|
4177
|
+
createReply(originalEvent: any, content: string, fromUser: NDKUser | Names, kind?: number): Promise<any>;
|
|
4178
|
+
/**
|
|
4179
|
+
* Creates a chain of events (e.g., a thread)
|
|
4180
|
+
* @param initialContent Content of the first message
|
|
4181
|
+
* @param replies Array of {content, author} objects for each reply
|
|
4182
|
+
* @returns Array of events in the chain
|
|
4183
|
+
*/
|
|
4184
|
+
createEventChain(initialContent: string, initialAuthor: NDKUser | Names, replies: Array<{
|
|
4185
|
+
content: string;
|
|
4186
|
+
author: NDKUser | Names;
|
|
4187
|
+
}>): Promise<any[]>;
|
|
4188
|
+
}
|
|
4189
|
+
/**
|
|
4190
|
+
* Complete test environment with NDK, users, and event factory pre-configured.
|
|
4191
|
+
*
|
|
4192
|
+
* Provides a ready-to-use test environment that combines NDK instance, event factory,
|
|
4193
|
+
* and convenient access to test users and signers. Reduces boilerplate in your tests.
|
|
4194
|
+
*
|
|
4195
|
+
* @example
|
|
4196
|
+
* ```typescript
|
|
4197
|
+
* const fixture = new TestFixture();
|
|
4198
|
+
*
|
|
4199
|
+
* // Access NDK instance
|
|
4200
|
+
* fixture.ndk.connect();
|
|
4201
|
+
*
|
|
4202
|
+
* // Get test users
|
|
4203
|
+
* const alice = await fixture.getUser('alice');
|
|
4204
|
+
*
|
|
4205
|
+
* // Setup signer
|
|
4206
|
+
* fixture.setupSigner('alice');
|
|
4207
|
+
*
|
|
4208
|
+
* // Use event factory
|
|
4209
|
+
* const note = await fixture.eventFactory.createSignedTextNote('Test', alice);
|
|
4210
|
+
*
|
|
4211
|
+
* // Test your app with this environment
|
|
4212
|
+
* ```
|
|
4213
|
+
*/
|
|
4214
|
+
declare class TestFixture {
|
|
4215
|
+
ndk: NDK;
|
|
4216
|
+
eventFactory: TestEventFactory;
|
|
4217
|
+
constructor();
|
|
4218
|
+
/**
|
|
4219
|
+
* Get a predefined test user
|
|
4220
|
+
* @param name The name of the user (alice, bob, carol, dave, eve)
|
|
4221
|
+
* @returns The NDK user
|
|
4222
|
+
*/
|
|
4223
|
+
getUser(name: Names): Promise<NDKUser>;
|
|
4224
|
+
/**
|
|
4225
|
+
* Get a signer for a predefined test user
|
|
4226
|
+
* @param name The name of the user
|
|
4227
|
+
* @returns The NDK signer
|
|
4228
|
+
*/
|
|
4229
|
+
getSigner(name: Names): NDKPrivateKeySigner;
|
|
4230
|
+
/**
|
|
4231
|
+
* Set up the NDK instance with a specific signer
|
|
4232
|
+
* @param name The name of the predefined user to use as signer
|
|
4233
|
+
*/
|
|
4234
|
+
setupSigner(name: Names): void;
|
|
4235
|
+
}
|
|
4236
|
+
|
|
4237
|
+
/**
|
|
4238
|
+
* Controls time in tests for testing time-dependent application logic.
|
|
4239
|
+
*
|
|
4240
|
+
* Provides utilities to advance fake timers, control async operations, and test
|
|
4241
|
+
* features like retries, delays, and scheduled tasks in your Nostr application.
|
|
4242
|
+
* Works with Vitest's fake timer system.
|
|
4243
|
+
*
|
|
4244
|
+
* @example
|
|
4245
|
+
* ```typescript
|
|
4246
|
+
* import { vi } from 'vitest';
|
|
4247
|
+
* import { TimeController } from '@nostr-dev-kit/ndk/test';
|
|
4248
|
+
*
|
|
4249
|
+
* beforeEach(() => {
|
|
4250
|
+
* vi.useFakeTimers();
|
|
4251
|
+
* TimeController.setViObject(vi);
|
|
4252
|
+
* });
|
|
4253
|
+
*
|
|
4254
|
+
* it('should retry after delay', async () => {
|
|
4255
|
+
* const promise = myApp.retryPublish(event); // retries after 5 seconds
|
|
4256
|
+
*
|
|
4257
|
+
* // Advance time by 5 seconds
|
|
4258
|
+
* await TimeController.tickAsync(5000);
|
|
4259
|
+
*
|
|
4260
|
+
* await expect(promise).resolves.toBeTruthy();
|
|
4261
|
+
* });
|
|
4262
|
+
*
|
|
4263
|
+
* afterEach(() => {
|
|
4264
|
+
* TimeController.reset();
|
|
4265
|
+
* vi.useRealTimers();
|
|
4266
|
+
* });
|
|
4267
|
+
* ```
|
|
4268
|
+
*/
|
|
4269
|
+
declare class TimeController {
|
|
4270
|
+
private static viObject;
|
|
4271
|
+
/**
|
|
4272
|
+
* Set the Vitest object to use for time control
|
|
4273
|
+
*/
|
|
4274
|
+
static setViObject(vi: any): void;
|
|
4275
|
+
/**
|
|
4276
|
+
* Advance timers by a specified number of milliseconds
|
|
4277
|
+
*/
|
|
4278
|
+
static advanceTime(ms: number): void;
|
|
4279
|
+
/**
|
|
4280
|
+
* Advance timers asynchronously by a specified number of milliseconds
|
|
4281
|
+
*/
|
|
4282
|
+
static tickAsync(ms?: number): Promise<void>;
|
|
4283
|
+
/**
|
|
4284
|
+
* Clear all timers
|
|
4285
|
+
*/
|
|
4286
|
+
static reset(): void;
|
|
4287
|
+
/**
|
|
4288
|
+
* Wait for the next tick of the event loop
|
|
4289
|
+
*/
|
|
4290
|
+
static waitForNextTick(): Promise<void>;
|
|
4291
|
+
}
|
|
4292
|
+
/**
|
|
4293
|
+
* Helper function to create a TimeController with automatic setup/teardown.
|
|
4294
|
+
*
|
|
4295
|
+
* Convenience wrapper that automatically sets up fake timers before your test
|
|
4296
|
+
* and restores real timers after, reducing boilerplate in your test files.
|
|
4297
|
+
*
|
|
4298
|
+
* @param viObject The Vitest `vi` object
|
|
4299
|
+
* @returns A TimeController instance configured for your test
|
|
4300
|
+
*
|
|
4301
|
+
* @example
|
|
4302
|
+
* ```typescript
|
|
4303
|
+
* import { vi } from 'vitest';
|
|
4304
|
+
* import { withTimeControl } from '@nostr-dev-kit/ndk/test';
|
|
4305
|
+
*
|
|
4306
|
+
* const timeController = withTimeControl(vi);
|
|
4307
|
+
*
|
|
4308
|
+
* it('should handle delays', async () => {
|
|
4309
|
+
* const promise = myApp.delayedOperation();
|
|
4310
|
+
* await timeController.tickAsync(1000);
|
|
4311
|
+
* await expect(promise).resolves.toBeTruthy();
|
|
4312
|
+
* });
|
|
4313
|
+
* ```
|
|
4314
|
+
*/
|
|
4315
|
+
declare function withTimeControl(viObject: any): (fn: (timeController: typeof TimeController) => Promise<void>) => (() => Promise<void>);
|
|
4316
|
+
|
|
4317
|
+
/** biome-ignore-all lint/complexity/noStaticOnlyClass: <test purposes> */
|
|
4318
|
+
/** biome-ignore-all lint/suspicious/noExplicitAny: <test purposes> */
|
|
4319
|
+
|
|
4320
|
+
/**
|
|
4321
|
+
* Low-level event generator for creating test events in your Nostr application tests.
|
|
4322
|
+
*
|
|
4323
|
+
* Provides simple methods to create various types of Nostr events with automatic signing.
|
|
4324
|
+
* Must call `setNDK()` once before using any event creation methods.
|
|
4325
|
+
*
|
|
4326
|
+
* @example
|
|
4327
|
+
* ```typescript
|
|
4328
|
+
* import { EventGenerator, UserGenerator } from '@nostr-dev-kit/ndk/test';
|
|
4329
|
+
*
|
|
4330
|
+
* // Initialize once in your test setup
|
|
4331
|
+
* EventGenerator.setNDK(ndk);
|
|
4332
|
+
*
|
|
4333
|
+
* // Create events
|
|
4334
|
+
* const alice = await UserGenerator.getUser('alice', ndk);
|
|
4335
|
+
* const note = await EventGenerator.createSignedTextNote('Hello!', alice.pubkey);
|
|
4336
|
+
* const dm = await EventGenerator.createEncryptedDirectMessage('Secret', alice.pubkey, bob.pubkey);
|
|
4337
|
+
*
|
|
4338
|
+
* // Use these events to test your app's event handling
|
|
4339
|
+
* ```
|
|
4340
|
+
*/
|
|
4341
|
+
declare class EventGenerator {
|
|
4342
|
+
private static ndk;
|
|
4343
|
+
static setNDK(ndk: NDK): void;
|
|
4344
|
+
static createEvent(kind?: number, content?: string, pubkey?: string): NDKEvent;
|
|
4345
|
+
static createSignedTextNote(content: string, pubkey?: string): Promise<NDKEvent>;
|
|
4346
|
+
static createEncryptedDirectMessage(content: string, from: string, to: string): Promise<NDKEvent>;
|
|
4347
|
+
static createRepost(originalEvent: NDKEvent, pubkey?: string): Promise<NDKEvent>;
|
|
4348
|
+
static createParameterizedReplaceable(kind: number, content: string, pubkey?: string, dTag?: string): Promise<NDKEvent>;
|
|
4349
|
+
private static requireNDK;
|
|
4350
|
+
private static resolvePubkey;
|
|
4351
|
+
}
|
|
4352
|
+
|
|
4353
|
+
type Proof = {
|
|
4354
|
+
id: string;
|
|
4355
|
+
amount: number;
|
|
4356
|
+
secret: string;
|
|
4357
|
+
C: string;
|
|
4358
|
+
};
|
|
4359
|
+
/**
|
|
4360
|
+
* Creates a mock Cashu nutzap for testing zap/payment features in your application.
|
|
4361
|
+
*
|
|
4362
|
+
* Generates a complete NIP-61 nutzap event with Cashu tokens, perfect for testing
|
|
4363
|
+
* payment flows, zap handling, and wallet integration in your Nostr app without
|
|
4364
|
+
* requiring real mints or tokens.
|
|
4365
|
+
*
|
|
4366
|
+
* @param mint The mint URL
|
|
4367
|
+
* @param amount The amount in satoshis
|
|
4368
|
+
* @param ndk The NDK instance
|
|
4369
|
+
* @param opts Configuration options
|
|
4370
|
+
* @param opts.senderPk The private key signer of the sender (defaults to random)
|
|
4371
|
+
* @param opts.recipientPubkey The nostr pubkey of the recipient
|
|
4372
|
+
* @param opts.content Optional comment/message with the nutzap
|
|
4373
|
+
* @param opts.eventId Optional event ID being zapped (for replay protection)
|
|
4374
|
+
* @returns A signed nutzap event ready for testing
|
|
4375
|
+
*
|
|
4376
|
+
* @example
|
|
4377
|
+
* ```typescript
|
|
4378
|
+
* import { mockNutzap, UserGenerator } from '@nostr-dev-kit/ndk/test';
|
|
4379
|
+
*
|
|
4380
|
+
* const alice = await UserGenerator.getUser('alice', ndk);
|
|
4381
|
+
* const bob = await UserGenerator.getUser('bob', ndk);
|
|
4382
|
+
*
|
|
4383
|
+
* // Create a nutzap from alice to bob
|
|
4384
|
+
* const nutzap = await mockNutzap(
|
|
4385
|
+
* 'https://mint.example.com',
|
|
4386
|
+
* 1000, // 1000 sats
|
|
4387
|
+
* ndk,
|
|
4388
|
+
* {
|
|
4389
|
+
* recipientPubkey: bob.pubkey,
|
|
4390
|
+
* content: 'Great post!',
|
|
4391
|
+
* eventId: originalEvent.id
|
|
4392
|
+
* }
|
|
4393
|
+
* );
|
|
4394
|
+
*
|
|
4395
|
+
* // Test your app's nutzap handling
|
|
4396
|
+
* await myApp.handleNutzap(nutzap);
|
|
4397
|
+
* ```
|
|
4398
|
+
*/
|
|
4399
|
+
declare function mockNutzap(mint: string, amount: number, ndk: any, { senderPk, recipientPubkey, content, eventId, }?: {
|
|
4400
|
+
senderPk?: any;
|
|
4401
|
+
recipientPubkey?: string;
|
|
4402
|
+
content?: string;
|
|
4403
|
+
eventId?: string;
|
|
4404
|
+
}): Promise<NDKNutzap>;
|
|
4405
|
+
/**
|
|
4406
|
+
* Creates a mock Cashu proof for testing token handling in your application.
|
|
4407
|
+
*
|
|
4408
|
+
* Generates individual Cashu proofs with optional P2PK locking, useful for testing
|
|
4409
|
+
* token validation, redemption, and wallet operations without real Cashu tokens.
|
|
4410
|
+
*
|
|
4411
|
+
* @param C The commitment point (usually mint URL for testing)
|
|
4412
|
+
* @param amount The amount in satoshis
|
|
4413
|
+
* @param p2pk Optional pubkey for P2PK locking the proof
|
|
4414
|
+
* @param proofTags Optional tags for proof secret (e.g., [["e", "event-id"], ["P", "sender-pubkey"]])
|
|
4415
|
+
* @returns A mock Cashu proof object
|
|
4416
|
+
*
|
|
4417
|
+
* @example
|
|
4418
|
+
* ```typescript
|
|
4419
|
+
* import { mockProof } from '@nostr-dev-kit/ndk/test';
|
|
4420
|
+
*
|
|
4421
|
+
* // Create a simple proof
|
|
4422
|
+
* const proof = mockProof('https://mint.example.com', 100);
|
|
4423
|
+
*
|
|
4424
|
+
* // Create a P2PK-locked proof
|
|
4425
|
+
* const lockedProof = mockProof(
|
|
4426
|
+
* 'https://mint.example.com',
|
|
4427
|
+
* 500,
|
|
4428
|
+
* bobPubkey, // locked to bob
|
|
4429
|
+
* [['P', alicePubkey]] // from alice
|
|
4430
|
+
* );
|
|
4431
|
+
*
|
|
4432
|
+
* // Test your app's proof validation
|
|
4433
|
+
* const isValid = await myApp.validateProof(lockedProof);
|
|
4434
|
+
* ```
|
|
4435
|
+
*/
|
|
4436
|
+
declare function mockProof(C: string, amount: number, p2pk?: string, proofTags?: [string, string][]): Proof;
|
|
4437
|
+
|
|
4438
|
+
interface RelayMockOptions {
|
|
4439
|
+
simulateDisconnect?: boolean;
|
|
4440
|
+
disconnectAfter?: number;
|
|
4441
|
+
connectionDelay?: number;
|
|
4442
|
+
autoConnect?: boolean;
|
|
4443
|
+
failNextPublish?: boolean;
|
|
4444
|
+
}
|
|
4445
|
+
/**
|
|
4446
|
+
* Mock Nostr relay for testing your application without real relay connections.
|
|
4447
|
+
*
|
|
4448
|
+
* Simulates a full Nostr relay with configurable behavior including connection delays,
|
|
4449
|
+
* disconnections, and publish failures. Perfect for testing your app's relay interaction
|
|
4450
|
+
* logic without network dependencies.
|
|
4451
|
+
*
|
|
4452
|
+
* @example
|
|
4453
|
+
* ```typescript
|
|
4454
|
+
* import { RelayMock } from '@nostr-dev-kit/ndk/test';
|
|
4455
|
+
*
|
|
4456
|
+
* // Create a mock relay
|
|
4457
|
+
* const relay = new RelayMock('wss://relay.example.com', {
|
|
4458
|
+
* connectionDelay: 100, // Simulate 100ms connection delay
|
|
4459
|
+
* simulateDisconnect: true, // Randomly disconnect
|
|
4460
|
+
* disconnectAfter: 5000 // Disconnect after 5 seconds
|
|
4461
|
+
* });
|
|
4462
|
+
*
|
|
4463
|
+
* // Use it in your NDK instance
|
|
4464
|
+
* ndk.pool.relays.set(relay.url, relay);
|
|
4465
|
+
*
|
|
4466
|
+
* // Simulate events from relay
|
|
4467
|
+
* const event = await EventGenerator.createSignedTextNote('Hello!', alice.pubkey);
|
|
4468
|
+
* relay.simulateEvent(event);
|
|
4469
|
+
* relay.simulateEOSE();
|
|
4470
|
+
*
|
|
4471
|
+
* // Test publish failures
|
|
4472
|
+
* relay.failNextPublish = true;
|
|
4473
|
+
* await myApp.publishNote('This will fail');
|
|
4474
|
+
* ```
|
|
4475
|
+
*/
|
|
4476
|
+
declare class RelayMock extends EventEmitter$1 {
|
|
4477
|
+
url: string;
|
|
4478
|
+
private _status;
|
|
4479
|
+
messageLog: Array<{
|
|
4480
|
+
direction: "in" | "out";
|
|
4481
|
+
message: string;
|
|
4482
|
+
}>;
|
|
4483
|
+
private activeSubscriptions;
|
|
4484
|
+
validatedEvents: number;
|
|
4485
|
+
nonValidatedEvents: number;
|
|
4486
|
+
options: Required<RelayMockOptions>;
|
|
4487
|
+
constructor(url?: string, options?: RelayMockOptions);
|
|
4488
|
+
connect(): Promise<void>;
|
|
4489
|
+
disconnect(): Promise<void>;
|
|
4490
|
+
get status(): NDKRelayStatus;
|
|
4491
|
+
send(message: string): void;
|
|
4492
|
+
publish(event: NDKEvent): Promise<boolean>;
|
|
4493
|
+
subscribe(subscription: NDKSubscription, filters: NDKFilter[]): void;
|
|
4494
|
+
shouldValidateEvent(): boolean;
|
|
4495
|
+
/**
|
|
4496
|
+
* Track the number of validated events (used in tests)
|
|
4497
|
+
*/
|
|
4498
|
+
addValidatedEvent(): void;
|
|
4499
|
+
/**
|
|
4500
|
+
* Track the number of non-validated events (used in tests)
|
|
4501
|
+
*/
|
|
4502
|
+
addNonValidatedEvent(): void;
|
|
4503
|
+
/**
|
|
4504
|
+
* Simulate receiving a raw message
|
|
4505
|
+
*/
|
|
4506
|
+
simulateReceiveMessage(message: string): void;
|
|
4507
|
+
/**
|
|
4508
|
+
* Simulate receiving an event
|
|
4509
|
+
*/
|
|
4510
|
+
simulateEvent(event: NDKEvent, subId?: string): Promise<void>;
|
|
4511
|
+
/**
|
|
4512
|
+
* Simulate end of stored events
|
|
4513
|
+
*/
|
|
4514
|
+
simulateEOSE(subId: string): void;
|
|
4515
|
+
/**
|
|
4516
|
+
* Simulate a NOTICE message from the relay
|
|
4517
|
+
*/
|
|
4518
|
+
simulateNotice(message: string): void;
|
|
4519
|
+
reset(): void;
|
|
4520
|
+
}
|
|
4521
|
+
|
|
4522
|
+
/**
|
|
4523
|
+
* Mock relay pool for testing applications with multiple Nostr relays.
|
|
4524
|
+
*
|
|
4525
|
+
* Manages multiple mock relays and provides convenient methods to simulate
|
|
4526
|
+
* events across all or specific relays. Perfect for testing your app's
|
|
4527
|
+
* multi-relay behavior, redundancy, and relay selection logic.
|
|
4528
|
+
*
|
|
4529
|
+
* @example
|
|
4530
|
+
* ```typescript
|
|
4531
|
+
* import { RelayPoolMock, EventGenerator, UserGenerator } from '@nostr-dev-kit/ndk/test';
|
|
4532
|
+
*
|
|
4533
|
+
* const pool = new RelayPoolMock();
|
|
4534
|
+
* const ndk = new NDK({ explicitRelayUrls: [] });
|
|
4535
|
+
* ndk.pool = pool;
|
|
4536
|
+
*
|
|
4537
|
+
* // Add mock relays
|
|
4538
|
+
* pool.addMockRelay('wss://relay1.example.com');
|
|
4539
|
+
* pool.addMockRelay('wss://relay2.example.com', {
|
|
4540
|
+
* connectionDelay: 200
|
|
4541
|
+
* });
|
|
4542
|
+
*
|
|
4543
|
+
* // Simulate event on all relays
|
|
4544
|
+
* const alice = await UserGenerator.getUser('alice', ndk);
|
|
4545
|
+
* const event = await EventGenerator.createSignedTextNote('Hello!', alice.pubkey);
|
|
4546
|
+
* pool.simulateEventOnAll(event);
|
|
4547
|
+
*
|
|
4548
|
+
* // Simulate event on specific relays
|
|
4549
|
+
* pool.simulateEventOn(['wss://relay1.example.com'], event);
|
|
4550
|
+
*
|
|
4551
|
+
* // Send EOSE to all relays
|
|
4552
|
+
* pool.simulateEOSEOnAll(subscriptionId);
|
|
4553
|
+
*
|
|
4554
|
+
* // Cleanup
|
|
4555
|
+
* pool.disconnectAll();
|
|
4556
|
+
* pool.resetAll();
|
|
4557
|
+
* ```
|
|
4558
|
+
*/
|
|
4559
|
+
declare class RelayPoolMock {
|
|
4560
|
+
mockRelays: Map<string, RelayMock>;
|
|
4561
|
+
relays: Set<RelayMock>;
|
|
4562
|
+
private eventListeners;
|
|
4563
|
+
private onceListeners;
|
|
4564
|
+
addMockRelay(url: string, options?: {}): RelayMock;
|
|
4565
|
+
getMockRelay(url: string): RelayMock | undefined;
|
|
4566
|
+
addRelay(relay: RelayMock): void;
|
|
4567
|
+
removeRelay(relay: RelayMock): void;
|
|
4568
|
+
simulateEventOnAll(event: NDKEvent): void;
|
|
4569
|
+
simulateEventOn(relayUrls: string[], event: NDKEvent): void;
|
|
4570
|
+
simulateEOSEOnAll(subscriptionId: string): void;
|
|
4571
|
+
disconnectAll(): void;
|
|
4572
|
+
resetAll(): void;
|
|
4573
|
+
permanentAndConnectedRelays(): RelayMock[];
|
|
4574
|
+
connectedRelays(): RelayMock[];
|
|
4575
|
+
getRelay(url: string, connect?: boolean, createIfNotExists?: boolean, _filters?: NDKFilter[]): RelayMock;
|
|
4576
|
+
on(eventName: string, callback: Function): void;
|
|
4577
|
+
once(eventName: string, callback: Function): void;
|
|
4578
|
+
off(eventName: string, callback: Function): void;
|
|
4579
|
+
emit(eventName: string, ...args: any[]): void;
|
|
4580
|
+
useTemporaryRelay(_relay: RelayMock, _filters?: NDKFilter[], _subscription?: any): void;
|
|
4581
|
+
blacklistRelayUrls: Set<string>;
|
|
4582
|
+
}
|
|
4583
|
+
|
|
4584
|
+
export { EventGenerator, type Proof, RelayMock, RelayPoolMock, SignerGenerator, TestEventFactory, TestFixture, TimeController, UserGenerator, mockNutzap, mockProof, withTimeControl };
|