@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,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Examples of using NDKRelayFeedList (NIP-51 kind 10012)
|
|
3
|
+
*
|
|
4
|
+
* This kind represents user's favorite browsable relays and relay sets.
|
|
5
|
+
* It can contain both individual relay URLs and references to relay sets (kind:30002).
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { NDK } from "../../ndk/index.js";
|
|
9
|
+
import { NDKPrivateKeySigner } from "../../signers/private-key/index.js";
|
|
10
|
+
import { NDKRelayFeedList } from "./relay-feed-list.js";
|
|
11
|
+
|
|
12
|
+
async function createRelayFeedList() {
|
|
13
|
+
// Initialize NDK with a signer
|
|
14
|
+
const ndk = new NDK();
|
|
15
|
+
const signer = NDKPrivateKeySigner.generate();
|
|
16
|
+
ndk.signer = signer;
|
|
17
|
+
|
|
18
|
+
// Create a new relay feed list
|
|
19
|
+
const relayFeedList = new NDKRelayFeedList(ndk);
|
|
20
|
+
relayFeedList.title = "My Favorite Relays";
|
|
21
|
+
relayFeedList.description = "Relays I browse regularly";
|
|
22
|
+
|
|
23
|
+
// Add individual relay URLs
|
|
24
|
+
await relayFeedList.addRelay("wss://relay.damus.io");
|
|
25
|
+
await relayFeedList.addRelay("wss://nos.lol");
|
|
26
|
+
await relayFeedList.addRelay("wss://relay.nostr.band");
|
|
27
|
+
|
|
28
|
+
// Add relay set references (kind:30002)
|
|
29
|
+
await relayFeedList.addRelaySet("30002:pubkey123:my-outbox-relays");
|
|
30
|
+
await relayFeedList.addRelaySet("30002:pubkey456:trusted-relays");
|
|
31
|
+
|
|
32
|
+
// Publish the list
|
|
33
|
+
await relayFeedList.publish();
|
|
34
|
+
|
|
35
|
+
return relayFeedList;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async function readRelayFeedList() {
|
|
39
|
+
const ndk = new NDK();
|
|
40
|
+
const signer = NDKPrivateKeySigner.generate();
|
|
41
|
+
ndk.signer = signer;
|
|
42
|
+
|
|
43
|
+
// Fetch the user's relay feed list
|
|
44
|
+
const user = await signer.user();
|
|
45
|
+
const lists = await ndk.fetchEvents({
|
|
46
|
+
kinds: [10012],
|
|
47
|
+
authors: [user.pubkey],
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
for (const event of lists) {
|
|
51
|
+
const relayFeedList = NDKRelayFeedList.from(event);
|
|
52
|
+
|
|
53
|
+
console.log("Title:", relayFeedList.title);
|
|
54
|
+
console.log("Description:", relayFeedList.description);
|
|
55
|
+
|
|
56
|
+
// Get all relay URLs
|
|
57
|
+
console.log("Relay URLs:", relayFeedList.relayUrls);
|
|
58
|
+
|
|
59
|
+
// Get all relay set references
|
|
60
|
+
console.log("Relay Sets:", relayFeedList.relaySets);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async function modifyRelayFeedList() {
|
|
65
|
+
const ndk = new NDK();
|
|
66
|
+
const signer = NDKPrivateKeySigner.generate();
|
|
67
|
+
ndk.signer = signer;
|
|
68
|
+
|
|
69
|
+
const relayFeedList = new NDKRelayFeedList(ndk);
|
|
70
|
+
|
|
71
|
+
// Add some relays
|
|
72
|
+
await relayFeedList.addRelay("wss://relay.damus.io");
|
|
73
|
+
await relayFeedList.addRelay("wss://nos.lol");
|
|
74
|
+
|
|
75
|
+
// Remove a relay (don't publish yet)
|
|
76
|
+
await relayFeedList.removeRelay("wss://nos.lol", false);
|
|
77
|
+
|
|
78
|
+
// Add it back at the top of the list
|
|
79
|
+
await relayFeedList.addRelay("wss://nos.lol", undefined, false, "top");
|
|
80
|
+
|
|
81
|
+
// Publish all changes at once
|
|
82
|
+
await relayFeedList.publish();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Export examples for documentation purposes
|
|
86
|
+
export { createRelayFeedList, modifyRelayFeedList, readRelayFeedList };
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { describe, expect, test } from "vitest";
|
|
2
|
+
import { NDK } from "../../ndk";
|
|
3
|
+
import { NDKPrivateKeySigner } from "../../signers/private-key";
|
|
4
|
+
import { NDKKind } from "./index.js";
|
|
5
|
+
import { NDKRelayFeedList } from "./relay-feed-list.js";
|
|
6
|
+
|
|
7
|
+
const ndk = new NDK();
|
|
8
|
+
|
|
9
|
+
describe("NDKRelayFeedList", () => {
|
|
10
|
+
test("creates a new relay feed list", () => {
|
|
11
|
+
const list = new NDKRelayFeedList(ndk);
|
|
12
|
+
expect(list.kind).toBe(NDKKind.RelayFeedList);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
test("has correct title", () => {
|
|
16
|
+
const list = new NDKRelayFeedList(ndk);
|
|
17
|
+
expect(list.title).toBe("Relay Feeds");
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
test("adds relay URLs", async () => {
|
|
21
|
+
ndk.signer = NDKPrivateKeySigner.generate();
|
|
22
|
+
|
|
23
|
+
const list = new NDKRelayFeedList(ndk);
|
|
24
|
+
await list.addRelay("wss://relay.damus.io");
|
|
25
|
+
await list.addRelay("wss://nos.lol");
|
|
26
|
+
|
|
27
|
+
expect(list.relayUrls).toEqual(["wss://relay.damus.io", "wss://nos.lol"]);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test("adds relay sets", async () => {
|
|
31
|
+
const signer = NDKPrivateKeySigner.generate();
|
|
32
|
+
ndk.signer = signer;
|
|
33
|
+
|
|
34
|
+
const list = new NDKRelayFeedList(ndk);
|
|
35
|
+
const relaySetNaddr = "30002:pubkey123:my-relay-set";
|
|
36
|
+
await list.addRelaySet(relaySetNaddr);
|
|
37
|
+
|
|
38
|
+
expect(list.relaySets).toEqual([relaySetNaddr]);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test("removes relay URLs", async () => {
|
|
42
|
+
const signer = NDKPrivateKeySigner.generate();
|
|
43
|
+
ndk.signer = signer;
|
|
44
|
+
|
|
45
|
+
const list = new NDKRelayFeedList(ndk);
|
|
46
|
+
await list.addRelay("wss://relay.damus.io");
|
|
47
|
+
await list.addRelay("wss://nos.lol");
|
|
48
|
+
await list.removeRelay("wss://relay.damus.io", false);
|
|
49
|
+
|
|
50
|
+
expect(list.relayUrls).toEqual(["wss://nos.lol"]);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test("removes relay sets", async () => {
|
|
54
|
+
const signer = NDKPrivateKeySigner.generate();
|
|
55
|
+
ndk.signer = signer;
|
|
56
|
+
|
|
57
|
+
const list = new NDKRelayFeedList(ndk);
|
|
58
|
+
const relaySet1 = "30002:pubkey123:set1";
|
|
59
|
+
const relaySet2 = "30002:pubkey123:set2";
|
|
60
|
+
await list.addRelaySet(relaySet1);
|
|
61
|
+
await list.addRelaySet(relaySet2);
|
|
62
|
+
await list.removeRelaySet(relaySet1, false);
|
|
63
|
+
|
|
64
|
+
expect(list.relaySets).toEqual([relaySet2]);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
// Note: Encrypted tags are supported via the base NDKList class but are not tested here
|
|
68
|
+
// due to a known issue with the encryptedTagsLength cache in the base class.
|
|
69
|
+
// The encryption functionality works but the cache invalidation needs to be fixed upstream.
|
|
70
|
+
|
|
71
|
+
test("creates from existing NDKEvent", () => {
|
|
72
|
+
const list = new NDKRelayFeedList(ndk);
|
|
73
|
+
list.tags = [
|
|
74
|
+
["relay", "wss://relay.damus.io"],
|
|
75
|
+
["a", "30002:pubkey:relay-set"],
|
|
76
|
+
];
|
|
77
|
+
|
|
78
|
+
const wrapped = NDKRelayFeedList.from(list);
|
|
79
|
+
expect(wrapped).toBeInstanceOf(NDKRelayFeedList);
|
|
80
|
+
expect(wrapped.relayUrls).toEqual(["wss://relay.damus.io"]);
|
|
81
|
+
expect(wrapped.relaySets).toEqual(["30002:pubkey:relay-set"]);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test("supports mixed relay and relay set items", async () => {
|
|
85
|
+
const signer = NDKPrivateKeySigner.generate();
|
|
86
|
+
ndk.signer = signer;
|
|
87
|
+
|
|
88
|
+
const list = new NDKRelayFeedList(ndk);
|
|
89
|
+
await list.addRelay("wss://relay.damus.io");
|
|
90
|
+
await list.addRelaySet("30002:pubkey:outbox-relays");
|
|
91
|
+
await list.addRelay("wss://nos.lol");
|
|
92
|
+
await list.addRelaySet("30002:pubkey:inbox-relays");
|
|
93
|
+
|
|
94
|
+
expect(list.relayUrls).toEqual(["wss://relay.damus.io", "wss://nos.lol"]);
|
|
95
|
+
expect(list.relaySets).toEqual(["30002:pubkey:outbox-relays", "30002:pubkey:inbox-relays"]);
|
|
96
|
+
});
|
|
97
|
+
});
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import type { NDK } from "../../ndk/index.js";
|
|
2
|
+
import type { NostrEvent } from "../index.js";
|
|
3
|
+
import { NDKEvent } from "../index.js";
|
|
4
|
+
import { NDKKind } from "./index.js";
|
|
5
|
+
import { NDKList } from "./lists/index.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Represents a NIP-51 kind 10012 Relay Feed List.
|
|
9
|
+
*
|
|
10
|
+
* This list contains user's favorite browsable relays and relay sets.
|
|
11
|
+
* Items can be:
|
|
12
|
+
* - `relay` tags pointing to relay URLs
|
|
13
|
+
* - `a` tags pointing to kind:30002 relay sets
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* const relayFeedList = new NDKRelayFeedList(ndk);
|
|
17
|
+
* relayFeedList.addRelay("wss://relay.damus.io");
|
|
18
|
+
* relayFeedList.addRelaySet("30002:pubkey:dtagvalue");
|
|
19
|
+
* await relayFeedList.publish();
|
|
20
|
+
*
|
|
21
|
+
* @group Kind Wrapper
|
|
22
|
+
*/
|
|
23
|
+
export class NDKRelayFeedList extends NDKList {
|
|
24
|
+
static kind = NDKKind.RelayFeedList;
|
|
25
|
+
static kinds = [NDKKind.RelayFeedList];
|
|
26
|
+
|
|
27
|
+
constructor(ndk?: NDK, rawEvent?: NostrEvent | NDKEvent) {
|
|
28
|
+
super(ndk, rawEvent);
|
|
29
|
+
if (!rawEvent?.kind) {
|
|
30
|
+
this.kind = NDKKind.RelayFeedList;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
static from(ndkEvent: NDKEvent): NDKRelayFeedList {
|
|
35
|
+
return new NDKRelayFeedList(ndkEvent.ndk, ndkEvent);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Gets all relay URLs from the list.
|
|
40
|
+
*/
|
|
41
|
+
get relayUrls(): string[] {
|
|
42
|
+
return this.getMatchingTags("relay").map(tag => tag[1]);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Gets all relay set references (kind:30002 naddr) from the list.
|
|
47
|
+
* Returns them in the format "kind:pubkey:dtag".
|
|
48
|
+
*/
|
|
49
|
+
get relaySets(): string[] {
|
|
50
|
+
return this.getMatchingTags("a").map(tag => tag[1]);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Adds a relay URL to the list.
|
|
55
|
+
* @param relayUrl - WebSocket URL of the relay
|
|
56
|
+
* @param mark - Optional mark to add to the relay tag
|
|
57
|
+
* @param encrypted - Whether to encrypt the item
|
|
58
|
+
* @param position - Where to add the item in the list
|
|
59
|
+
*/
|
|
60
|
+
async addRelay(
|
|
61
|
+
relayUrl: string,
|
|
62
|
+
mark?: string,
|
|
63
|
+
encrypted = false,
|
|
64
|
+
position: "top" | "bottom" = "bottom"
|
|
65
|
+
): Promise<void> {
|
|
66
|
+
const tag: string[] = ["relay", relayUrl];
|
|
67
|
+
if (mark) tag.push(mark);
|
|
68
|
+
await this.addItem(tag, undefined, encrypted, position);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Adds a relay set reference to the list.
|
|
73
|
+
* @param relaySetNaddr - NIP-33 address in format "kind:pubkey:dtag" (kind should be 30002)
|
|
74
|
+
* @param mark - Optional mark to add to the relay set tag
|
|
75
|
+
* @param encrypted - Whether to encrypt the item
|
|
76
|
+
* @param position - Where to add the item in the list
|
|
77
|
+
*/
|
|
78
|
+
async addRelaySet(
|
|
79
|
+
relaySetNaddr: string,
|
|
80
|
+
mark?: string,
|
|
81
|
+
encrypted = false,
|
|
82
|
+
position: "top" | "bottom" = "bottom"
|
|
83
|
+
): Promise<void> {
|
|
84
|
+
const tag: string[] = ["a", relaySetNaddr];
|
|
85
|
+
if (mark) tag.push(mark);
|
|
86
|
+
await this.addItem(tag, undefined, encrypted, position);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Removes a relay URL from the list.
|
|
91
|
+
* @param relayUrl - The relay URL to remove
|
|
92
|
+
* @param publish - Whether to publish the change
|
|
93
|
+
*/
|
|
94
|
+
async removeRelay(relayUrl: string, publish = true): Promise<void> {
|
|
95
|
+
await this.removeItemByValue(relayUrl, publish);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Removes a relay set from the list.
|
|
100
|
+
* @param relaySetNaddr - The relay set naddr to remove
|
|
101
|
+
* @param publish - Whether to publish the change
|
|
102
|
+
*/
|
|
103
|
+
async removeRelaySet(relaySetNaddr: string, publish = true): Promise<void> {
|
|
104
|
+
await this.removeItemByValue(relaySetNaddr, publish);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export default NDKRelayFeedList;
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import type { NDK } from "../../ndk/index.js";
|
|
2
|
+
import { NDKRelaySet } from "../../relay/sets/index.js";
|
|
3
|
+
import { normalizeRelayUrl, tryNormalizeRelayUrl } from "../../utils/normalize-url.js";
|
|
4
|
+
import type { NostrEvent } from "../index.js";
|
|
5
|
+
import { NDKEvent } from "../index.js";
|
|
6
|
+
import { NDKKind } from "./index.js";
|
|
7
|
+
|
|
8
|
+
const READ_MARKER = "read";
|
|
9
|
+
const WRITE_MARKER = "write";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Represents a relay list for a user, ideally coming from a NIP-65 kind:10002 or alternatively from a kind:3 event's content.
|
|
13
|
+
* @group Kind Wrapper
|
|
14
|
+
*/
|
|
15
|
+
export class NDKRelayList extends NDKEvent {
|
|
16
|
+
static kind = NDKKind.RelayList;
|
|
17
|
+
static kinds = [NDKKind.RelayList];
|
|
18
|
+
|
|
19
|
+
constructor(ndk?: NDK, rawEvent?: NostrEvent) {
|
|
20
|
+
super(ndk, rawEvent);
|
|
21
|
+
this.kind ??= NDKKind.RelayList;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
static from(ndkEvent: NDKEvent): NDKRelayList {
|
|
25
|
+
return new NDKRelayList(ndkEvent.ndk, ndkEvent.rawEvent());
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
get readRelayUrls(): WebSocket["url"][] {
|
|
29
|
+
return this.tags
|
|
30
|
+
.filter((tag) => tag[0] === "r" || tag[0] === "relay")
|
|
31
|
+
.filter((tag) => !tag[2] || (tag[2] && tag[2] === READ_MARKER))
|
|
32
|
+
.map((tag) => tryNormalizeRelayUrl(tag[1]))
|
|
33
|
+
.filter((url) => !!url) as WebSocket["url"][];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
set readRelayUrls(relays: WebSocket["url"][]) {
|
|
37
|
+
for (const relay of relays) {
|
|
38
|
+
this.tags.push(["r", relay, READ_MARKER]);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
get writeRelayUrls(): WebSocket["url"][] {
|
|
43
|
+
return this.tags
|
|
44
|
+
.filter((tag) => tag[0] === "r" || tag[0] === "relay")
|
|
45
|
+
.filter((tag) => !tag[2] || (tag[2] && tag[2] === WRITE_MARKER))
|
|
46
|
+
.map((tag) => tryNormalizeRelayUrl(tag[1]))
|
|
47
|
+
.filter((url) => !!url) as WebSocket["url"][];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
set writeRelayUrls(relays: WebSocket["url"][]) {
|
|
51
|
+
for (const relay of relays) {
|
|
52
|
+
this.tags.push(["r", relay, WRITE_MARKER]);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
get bothRelayUrls(): WebSocket["url"][] {
|
|
57
|
+
return this.tags
|
|
58
|
+
.filter((tag) => tag[0] === "r" || tag[0] === "relay")
|
|
59
|
+
.filter((tag) => !tag[2])
|
|
60
|
+
.map((tag) => tag[1]);
|
|
61
|
+
}
|
|
62
|
+
set bothRelayUrls(relays: WebSocket["url"][]) {
|
|
63
|
+
for (const relay of relays) {
|
|
64
|
+
this.tags.push(["r", relay]);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
get relays(): WebSocket["url"][] {
|
|
69
|
+
return this.tags.filter((tag) => tag[0] === "r" || tag[0] === "relay").map((tag) => tag[1]);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Provides a relaySet for the relays in this list.
|
|
74
|
+
*/
|
|
75
|
+
get relaySet(): NDKRelaySet {
|
|
76
|
+
if (!this.ndk) throw new Error("NDKRelayList has no NDK instance");
|
|
77
|
+
|
|
78
|
+
return new NDKRelaySet(
|
|
79
|
+
new Set(this.relays.map((u) => this.ndk?.pool.getRelay(u)).filter((r) => !!r)),
|
|
80
|
+
this.ndk,
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export function relayListFromKind3(ndk: NDK, contactList: NDKEvent): NDKRelayList | undefined {
|
|
86
|
+
try {
|
|
87
|
+
const content = JSON.parse(contactList.content);
|
|
88
|
+
const relayList = new NDKRelayList(ndk);
|
|
89
|
+
const readRelays = new Set<string>();
|
|
90
|
+
const writeRelays = new Set<string>();
|
|
91
|
+
|
|
92
|
+
for (let [key, config] of Object.entries(content)) {
|
|
93
|
+
try {
|
|
94
|
+
key = normalizeRelayUrl(key);
|
|
95
|
+
} catch {
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (!config) {
|
|
100
|
+
readRelays.add(key);
|
|
101
|
+
writeRelays.add(key);
|
|
102
|
+
} else {
|
|
103
|
+
const relayConfig: { read?: boolean; write?: boolean } = config;
|
|
104
|
+
if (relayConfig.write) writeRelays.add(key);
|
|
105
|
+
if (relayConfig.read) readRelays.add(key);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
relayList.readRelayUrls = Array.from(readRelays);
|
|
110
|
+
relayList.writeRelayUrls = Array.from(writeRelays);
|
|
111
|
+
|
|
112
|
+
return relayList;
|
|
113
|
+
} catch {
|
|
114
|
+
/* */
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return undefined;
|
|
118
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { NDK } from "../../ndk/index.js";
|
|
2
|
+
import type { NDKFilter, NDKSubscriptionOptions } from "../../subscription/index.js";
|
|
3
|
+
import type { NDKTag, NostrEvent } from "../index.js";
|
|
4
|
+
import { NDKEvent } from "../index.js";
|
|
5
|
+
import { NDKKind } from "./index.js";
|
|
6
|
+
|
|
7
|
+
type classWithConvertFunction<T> = {
|
|
8
|
+
from: (event: NDKEvent) => T;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Handles NIP-18 reposts.
|
|
13
|
+
* @group Kind Wrapper
|
|
14
|
+
*/
|
|
15
|
+
export class NDKRepost<T> extends NDKEvent {
|
|
16
|
+
private _repostedEvents: T[] | undefined;
|
|
17
|
+
static kind = NDKKind.Repost;
|
|
18
|
+
static kinds = [NDKKind.Repost, NDKKind.GenericRepost];
|
|
19
|
+
|
|
20
|
+
static from(event: NDKEvent) {
|
|
21
|
+
return new NDKRepost(event.ndk, event.rawEvent());
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Returns all reposted events by the current event.
|
|
26
|
+
*
|
|
27
|
+
* @param klass Optional class to convert the events to.
|
|
28
|
+
* @returns
|
|
29
|
+
*/
|
|
30
|
+
async repostedEvents(klass?: classWithConvertFunction<T>, opts?: NDKSubscriptionOptions): Promise<T[]> {
|
|
31
|
+
const items: T[] = [];
|
|
32
|
+
|
|
33
|
+
if (!this.ndk) throw new Error("NDK instance not set");
|
|
34
|
+
|
|
35
|
+
if (this._repostedEvents !== undefined) return this._repostedEvents;
|
|
36
|
+
|
|
37
|
+
for (const eventId of this.repostedEventIds()) {
|
|
38
|
+
const filter = filterForId(eventId);
|
|
39
|
+
const event = await this.ndk.fetchEvent(filter, opts);
|
|
40
|
+
|
|
41
|
+
if (event) {
|
|
42
|
+
items.push(klass ? klass.from(event) : (event as T));
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return items;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Returns the reposted event IDs.
|
|
51
|
+
*/
|
|
52
|
+
repostedEventIds(): string[] {
|
|
53
|
+
return this.tags.filter((t: NDKTag) => t[0] === "e" || t[0] === "a").map((t: NDKTag) => t[1]);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function filterForId(id: string): NDKFilter {
|
|
58
|
+
if (id.match(/:/)) {
|
|
59
|
+
const [kind, pubkey, identifier] = id.split(":");
|
|
60
|
+
return {
|
|
61
|
+
kinds: [Number.parseInt(kind)],
|
|
62
|
+
authors: [pubkey],
|
|
63
|
+
"#d": [identifier],
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
return { ids: [id] };
|
|
67
|
+
}
|