@openclaw/nostr 2026.7.1-beta.2 → 2026.7.1-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api.js +5 -16
- package/dist/{channel-CV0aX1uq.js → channel-B2Y66pl3.js} +11 -4
- package/dist/channel-plugin-api.js +1 -1
- package/dist/doctor-contract-api.js +3 -22
- package/dist/setup-api.js +1 -1
- package/dist/setup-plugin-api.js +1 -1
- package/dist/{setup-surface-BqBa2C0K.js → setup-surface-CKamwGa3.js} +1 -1
- package/node_modules/nostr-tools/README.md +37 -15
- package/node_modules/nostr-tools/lib/cjs/abstract-pool.js +134 -6
- package/node_modules/nostr-tools/lib/cjs/abstract-pool.js.map +4 -4
- package/node_modules/nostr-tools/lib/cjs/abstract-relay.js +35 -6
- package/node_modules/nostr-tools/lib/cjs/abstract-relay.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/filter.js.map +1 -1
- package/node_modules/nostr-tools/lib/cjs/index.js +401 -72
- package/node_modules/nostr-tools/lib/cjs/index.js.map +4 -4
- package/node_modules/nostr-tools/lib/cjs/kinds.js +196 -4
- package/node_modules/nostr-tools/lib/cjs/kinds.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip10.js +5 -4
- package/node_modules/nostr-tools/lib/cjs/nip10.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip17.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip18.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip19.js +2 -0
- package/node_modules/nostr-tools/lib/cjs/nip19.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip21.js +2 -0
- package/node_modules/nostr-tools/lib/cjs/nip21.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip22.js +11 -5
- package/node_modules/nostr-tools/lib/cjs/nip22.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip25.js.map +1 -1
- package/node_modules/nostr-tools/lib/cjs/nip27.js +2 -0
- package/node_modules/nostr-tools/lib/cjs/nip27.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip28.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip29.js +2 -0
- package/node_modules/nostr-tools/lib/cjs/nip29.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip42.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip45.js +183 -0
- package/node_modules/nostr-tools/lib/cjs/nip45.js.map +7 -0
- package/node_modules/nostr-tools/lib/cjs/nip46.js +149 -9
- package/node_modules/nostr-tools/lib/cjs/nip46.js.map +4 -4
- package/node_modules/nostr-tools/lib/cjs/nip47.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip49.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip57.js.map +1 -1
- package/node_modules/nostr-tools/lib/cjs/nip58.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip59.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip75.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip94.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip98.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nip99.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/nipb0.js +1064 -0
- package/node_modules/nostr-tools/lib/cjs/nipb0.js.map +7 -0
- package/node_modules/nostr-tools/lib/cjs/pool.js +134 -6
- package/node_modules/nostr-tools/lib/cjs/pool.js.map +4 -4
- package/node_modules/nostr-tools/lib/cjs/references.js +2 -0
- package/node_modules/nostr-tools/lib/cjs/references.js.map +2 -2
- package/node_modules/nostr-tools/lib/cjs/relay.js +35 -6
- package/node_modules/nostr-tools/lib/cjs/relay.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/abstract-pool.js +134 -6
- package/node_modules/nostr-tools/lib/esm/abstract-pool.js.map +4 -4
- package/node_modules/nostr-tools/lib/esm/abstract-relay.js +35 -6
- package/node_modules/nostr-tools/lib/esm/abstract-relay.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/filter.js.map +1 -1
- package/node_modules/nostr-tools/lib/esm/index.js +377 -48
- package/node_modules/nostr-tools/lib/esm/index.js.map +4 -4
- package/node_modules/nostr-tools/lib/esm/kinds.js +196 -4
- package/node_modules/nostr-tools/lib/esm/kinds.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip10.js +5 -4
- package/node_modules/nostr-tools/lib/esm/nip10.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip17.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip18.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip19.js +2 -0
- package/node_modules/nostr-tools/lib/esm/nip19.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip21.js +2 -0
- package/node_modules/nostr-tools/lib/esm/nip21.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip22.js +11 -5
- package/node_modules/nostr-tools/lib/esm/nip22.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip25.js.map +1 -1
- package/node_modules/nostr-tools/lib/esm/nip27.js +2 -0
- package/node_modules/nostr-tools/lib/esm/nip27.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip28.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip29.js +2 -0
- package/node_modules/nostr-tools/lib/esm/nip29.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip42.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip45.js +162 -0
- package/node_modules/nostr-tools/lib/esm/nip45.js.map +7 -0
- package/node_modules/nostr-tools/lib/esm/nip46.js +149 -9
- package/node_modules/nostr-tools/lib/esm/nip46.js.map +4 -4
- package/node_modules/nostr-tools/lib/esm/nip47.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip49.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip57.js.map +1 -1
- package/node_modules/nostr-tools/lib/esm/nip58.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip59.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip75.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip94.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip98.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nip99.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/nipb0.js +1049 -0
- package/node_modules/nostr-tools/lib/esm/nipb0.js.map +7 -0
- package/node_modules/nostr-tools/lib/esm/pool.js +134 -6
- package/node_modules/nostr-tools/lib/esm/pool.js.map +4 -4
- package/node_modules/nostr-tools/lib/esm/references.js +2 -0
- package/node_modules/nostr-tools/lib/esm/references.js.map +2 -2
- package/node_modules/nostr-tools/lib/esm/relay.js +35 -6
- package/node_modules/nostr-tools/lib/esm/relay.js.map +2 -2
- package/node_modules/nostr-tools/lib/nostr.bundle.js +350 -23
- package/node_modules/nostr-tools/lib/nostr.bundle.js.map +4 -4
- package/node_modules/nostr-tools/lib/types/abstract-pool.d.ts +9 -0
- package/node_modules/nostr-tools/lib/types/abstract-relay.d.ts +10 -1
- package/node_modules/nostr-tools/lib/types/kinds.d.ts +200 -8
- package/node_modules/nostr-tools/lib/types/nip45.d.ts +13 -0
- package/node_modules/nostr-tools/lib/types/nip45.test.d.ts +1 -0
- package/node_modules/nostr-tools/lib/types/nip46.d.ts +12 -5
- package/node_modules/nostr-tools/lib/types/nipb0.d.ts +129 -0
- package/node_modules/nostr-tools/package.json +13 -1
- package/npm-shrinkwrap.json +7 -7
- package/package.json +5 -5
|
@@ -0,0 +1,1049 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __export = (target, all) => {
|
|
3
|
+
for (var name in all)
|
|
4
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
// nipb0.ts
|
|
8
|
+
import { sha256 } from "@noble/hashes/sha2.js";
|
|
9
|
+
import { bytesToHex } from "@noble/hashes/utils.js";
|
|
10
|
+
|
|
11
|
+
// core.ts
|
|
12
|
+
var verifiedSymbol = Symbol("verified");
|
|
13
|
+
var isRecord = (obj) => obj instanceof Object;
|
|
14
|
+
function validateEvent(event) {
|
|
15
|
+
if (!isRecord(event))
|
|
16
|
+
return false;
|
|
17
|
+
if (typeof event.kind !== "number")
|
|
18
|
+
return false;
|
|
19
|
+
if (typeof event.content !== "string")
|
|
20
|
+
return false;
|
|
21
|
+
if (typeof event.created_at !== "number")
|
|
22
|
+
return false;
|
|
23
|
+
if (typeof event.pubkey !== "string")
|
|
24
|
+
return false;
|
|
25
|
+
if (!event.pubkey.match(/^[a-f0-9]{64}$/))
|
|
26
|
+
return false;
|
|
27
|
+
if (!Array.isArray(event.tags))
|
|
28
|
+
return false;
|
|
29
|
+
for (let i = 0; i < event.tags.length; i++) {
|
|
30
|
+
let tag = event.tags[i];
|
|
31
|
+
if (!Array.isArray(tag))
|
|
32
|
+
return false;
|
|
33
|
+
for (let j = 0; j < tag.length; j++) {
|
|
34
|
+
if (typeof tag[j] !== "string")
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// kinds.ts
|
|
42
|
+
var kinds_exports = {};
|
|
43
|
+
__export(kinds_exports, {
|
|
44
|
+
AIEmbeddings: () => AIEmbeddings,
|
|
45
|
+
AppCurationSet: () => AppCurationSet,
|
|
46
|
+
Application: () => Application,
|
|
47
|
+
AuthoredPodcasts: () => AuthoredPodcasts,
|
|
48
|
+
BadgeAward: () => BadgeAward,
|
|
49
|
+
BadgeDefinition: () => BadgeDefinition,
|
|
50
|
+
Bid: () => Bid,
|
|
51
|
+
BidConfirmation: () => BidConfirmation,
|
|
52
|
+
BlobsAuth: () => BlobsAuth,
|
|
53
|
+
BlockedRelaysList: () => BlockedRelaysList,
|
|
54
|
+
BlossomServerList: () => BlossomServerList,
|
|
55
|
+
BookmarkList: () => BookmarkList,
|
|
56
|
+
Bookmarksets: () => Bookmarksets,
|
|
57
|
+
Calendar: () => Calendar,
|
|
58
|
+
CalendarEventRSVP: () => CalendarEventRSVP,
|
|
59
|
+
CashuMintAnnouncement: () => CashuMintAnnouncement,
|
|
60
|
+
CashuWalletEvent: () => CashuWalletEvent,
|
|
61
|
+
CashuWalletHistory: () => CashuWalletHistory,
|
|
62
|
+
CashuWalletTokens: () => CashuWalletTokens,
|
|
63
|
+
ChannelCreation: () => ChannelCreation,
|
|
64
|
+
ChannelHideMessage: () => ChannelHideMessage,
|
|
65
|
+
ChannelMessage: () => ChannelMessage,
|
|
66
|
+
ChannelMetadata: () => ChannelMetadata,
|
|
67
|
+
ChannelMuteUser: () => ChannelMuteUser,
|
|
68
|
+
ChatMessage: () => ChatMessage,
|
|
69
|
+
Chess: () => Chess,
|
|
70
|
+
ClassifiedListing: () => ClassifiedListing,
|
|
71
|
+
ClientAuth: () => ClientAuth,
|
|
72
|
+
CodeSnippet: () => CodeSnippet,
|
|
73
|
+
CoinjoinPool: () => CoinjoinPool,
|
|
74
|
+
Comment: () => Comment,
|
|
75
|
+
CommunitiesList: () => CommunitiesList,
|
|
76
|
+
CommunityDefinition: () => CommunityDefinition,
|
|
77
|
+
CommunityPostApproval: () => CommunityPostApproval,
|
|
78
|
+
ConferenceEvent: () => ConferenceEvent,
|
|
79
|
+
Contacts: () => Contacts,
|
|
80
|
+
CreateOrUpdateProduct: () => CreateOrUpdateProduct,
|
|
81
|
+
CreateOrUpdateStall: () => CreateOrUpdateStall,
|
|
82
|
+
CuratedVideoSets: () => CuratedVideoSets,
|
|
83
|
+
Curationsets: () => Curationsets,
|
|
84
|
+
Date: () => Date2,
|
|
85
|
+
DecoupledEncryptionKeyDistribution: () => DecoupledEncryptionKeyDistribution,
|
|
86
|
+
DecoupledKeyAnnouncement: () => DecoupledKeyAnnouncement,
|
|
87
|
+
DecoupledKeyClientAnnouncement: () => DecoupledKeyClientAnnouncement,
|
|
88
|
+
DirectMessageRelaysList: () => DirectMessageRelaysList,
|
|
89
|
+
DraftClassifiedListing: () => DraftClassifiedListing,
|
|
90
|
+
DraftEvent: () => DraftEvent,
|
|
91
|
+
DraftLong: () => DraftLong,
|
|
92
|
+
Emojisets: () => Emojisets,
|
|
93
|
+
EncryptedDirectMessage: () => EncryptedDirectMessage,
|
|
94
|
+
EventDeletion: () => EventDeletion,
|
|
95
|
+
FavoritePodcasts: () => FavoritePodcasts,
|
|
96
|
+
FavoriteRelays: () => FavoriteRelays,
|
|
97
|
+
FedimintAnnouncement: () => FedimintAnnouncement,
|
|
98
|
+
Feed: () => Feed,
|
|
99
|
+
FileMessage: () => FileMessage,
|
|
100
|
+
FileMetadata: () => FileMetadata,
|
|
101
|
+
FileServerPreference: () => FileServerPreference,
|
|
102
|
+
Followsets: () => Followsets,
|
|
103
|
+
ForumThread: () => ForumThread,
|
|
104
|
+
GenericRepost: () => GenericRepost,
|
|
105
|
+
Genericlists: () => Genericlists,
|
|
106
|
+
GeocacheListing: () => GeocacheListing,
|
|
107
|
+
GeocacheLog: () => GeocacheLog,
|
|
108
|
+
GeocacheLogEntry: () => GeocacheLogEntry,
|
|
109
|
+
GeocacheProofOfFind: () => GeocacheProofOfFind,
|
|
110
|
+
GiftWrap: () => GiftWrap,
|
|
111
|
+
GitPullRequest: () => GitPullRequest,
|
|
112
|
+
GitPullRequestUpdate: () => GitPullRequestUpdate,
|
|
113
|
+
GoodWikiAuthorList: () => GoodWikiAuthorList,
|
|
114
|
+
GoodWikiRelayList: () => GoodWikiRelayList,
|
|
115
|
+
GroupMetadata: () => GroupMetadata,
|
|
116
|
+
HTTPAuth: () => HTTPAuth,
|
|
117
|
+
Handlerinformation: () => Handlerinformation,
|
|
118
|
+
Handlerrecommendation: () => Handlerrecommendation,
|
|
119
|
+
Highlights: () => Highlights,
|
|
120
|
+
InteractiveRoom: () => InteractiveRoom,
|
|
121
|
+
InterestsList: () => InterestsList,
|
|
122
|
+
Interestsets: () => Interestsets,
|
|
123
|
+
Issue: () => Issue,
|
|
124
|
+
JobFeedback: () => JobFeedback,
|
|
125
|
+
JobRequest: () => JobRequest,
|
|
126
|
+
JobResult: () => JobResult,
|
|
127
|
+
Label: () => Label,
|
|
128
|
+
LegacyNsiteFile: () => LegacyNsiteFile,
|
|
129
|
+
LightningPubRPC: () => LightningPubRPC,
|
|
130
|
+
LinkSet: () => LinkSet,
|
|
131
|
+
LiveChatMessage: () => LiveChatMessage,
|
|
132
|
+
LiveEvent: () => LiveEvent,
|
|
133
|
+
LongFormArticle: () => LongFormArticle,
|
|
134
|
+
MarketplaceUI: () => MarketplaceUI,
|
|
135
|
+
MediaFollows: () => MediaFollows,
|
|
136
|
+
MediaStarterPacks: () => MediaStarterPacks,
|
|
137
|
+
MergeRequests: () => MergeRequests,
|
|
138
|
+
Metadata: () => Metadata,
|
|
139
|
+
ModularArticleContent: () => ModularArticleContent,
|
|
140
|
+
ModularArticleHeader: () => ModularArticleHeader,
|
|
141
|
+
MuteSets: () => MuteSets,
|
|
142
|
+
Mutelist: () => Mutelist,
|
|
143
|
+
NWCWalletInfo: () => NWCWalletInfo,
|
|
144
|
+
NWCWalletRequest: () => NWCWalletRequest,
|
|
145
|
+
NWCWalletResponse: () => NWCWalletResponse,
|
|
146
|
+
NormalVideo: () => NormalVideo,
|
|
147
|
+
NostrConnect: () => NostrConnect,
|
|
148
|
+
NsiteNamed: () => NsiteNamed,
|
|
149
|
+
NsiteRoot: () => NsiteRoot,
|
|
150
|
+
NutZap: () => NutZap,
|
|
151
|
+
NutZapInfo: () => NutZapInfo,
|
|
152
|
+
OpenTimestamps: () => OpenTimestamps,
|
|
153
|
+
Patch: () => Patch,
|
|
154
|
+
PeerToPeerOrderEvents: () => PeerToPeerOrderEvents,
|
|
155
|
+
Photo: () => Photo,
|
|
156
|
+
Pinlist: () => Pinlist,
|
|
157
|
+
PodcastEpisode: () => PodcastEpisode,
|
|
158
|
+
PodcastMetadata: () => PodcastMetadata,
|
|
159
|
+
Poll: () => Poll,
|
|
160
|
+
PollResponse: () => PollResponse,
|
|
161
|
+
PrivateDirectMessage: () => PrivateDirectMessage,
|
|
162
|
+
PrivateEventRelayList: () => PrivateEventRelayList,
|
|
163
|
+
ProblemTracker: () => ProblemTracker,
|
|
164
|
+
ProductSoldAsAuction: () => ProductSoldAsAuction,
|
|
165
|
+
ProfileBadges: () => ProfileBadges,
|
|
166
|
+
ProxyAnnouncement: () => ProxyAnnouncement,
|
|
167
|
+
PublicChatsList: () => PublicChatsList,
|
|
168
|
+
PublicMessage: () => PublicMessage,
|
|
169
|
+
Reaction: () => Reaction,
|
|
170
|
+
ReactionToWebsite: () => ReactionToWebsite,
|
|
171
|
+
RecommendRelay: () => RecommendRelay,
|
|
172
|
+
Redirects: () => Redirects,
|
|
173
|
+
RelayDiscovery: () => RelayDiscovery,
|
|
174
|
+
RelayList: () => RelayList,
|
|
175
|
+
RelayMonitorAnnouncement: () => RelayMonitorAnnouncement,
|
|
176
|
+
RelayReview: () => RelayReview,
|
|
177
|
+
RelayReviews: () => RelayReviews,
|
|
178
|
+
Relaysets: () => Relaysets,
|
|
179
|
+
ReleaseArtifactSets: () => ReleaseArtifactSets,
|
|
180
|
+
Reply: () => Reply,
|
|
181
|
+
Report: () => Report,
|
|
182
|
+
Reporting: () => Reporting,
|
|
183
|
+
RepositoryAnnouncement: () => RepositoryAnnouncement,
|
|
184
|
+
RepositoryState: () => RepositoryState,
|
|
185
|
+
Repost: () => Repost,
|
|
186
|
+
ReservedCashuWalletTokens: () => ReservedCashuWalletTokens,
|
|
187
|
+
RoomPresence: () => RoomPresence,
|
|
188
|
+
Scroll: () => Scroll,
|
|
189
|
+
Seal: () => Seal,
|
|
190
|
+
SearchRelaysList: () => SearchRelaysList,
|
|
191
|
+
ShortTextNote: () => ShortTextNote,
|
|
192
|
+
ShortVideo: () => ShortVideo,
|
|
193
|
+
SimpleGroupAdmins: () => SimpleGroupAdmins,
|
|
194
|
+
SimpleGroupCreateGroup: () => SimpleGroupCreateGroup,
|
|
195
|
+
SimpleGroupCreateInvite: () => SimpleGroupCreateInvite,
|
|
196
|
+
SimpleGroupDeleteEvent: () => SimpleGroupDeleteEvent,
|
|
197
|
+
SimpleGroupDeleteGroup: () => SimpleGroupDeleteGroup,
|
|
198
|
+
SimpleGroupEditMetadata: () => SimpleGroupEditMetadata,
|
|
199
|
+
SimpleGroupJoinRequest: () => SimpleGroupJoinRequest,
|
|
200
|
+
SimpleGroupLeaveRequest: () => SimpleGroupLeaveRequest,
|
|
201
|
+
SimpleGroupList: () => SimpleGroupList,
|
|
202
|
+
SimpleGroupLiveKitParticipants: () => SimpleGroupLiveKitParticipants,
|
|
203
|
+
SimpleGroupMembers: () => SimpleGroupMembers,
|
|
204
|
+
SimpleGroupPutUser: () => SimpleGroupPutUser,
|
|
205
|
+
SimpleGroupRemoveUser: () => SimpleGroupRemoveUser,
|
|
206
|
+
SimpleGroupReply: () => SimpleGroupReply,
|
|
207
|
+
SimpleGroupRoles: () => SimpleGroupRoles,
|
|
208
|
+
SimpleGroupThreadedReply: () => SimpleGroupThreadedReply,
|
|
209
|
+
SlideSet: () => SlideSet,
|
|
210
|
+
SoftwareApplication: () => SoftwareApplication,
|
|
211
|
+
StarterPacks: () => StarterPacks,
|
|
212
|
+
StatusApplied: () => StatusApplied,
|
|
213
|
+
StatusClosed: () => StatusClosed,
|
|
214
|
+
StatusDraft: () => StatusDraft,
|
|
215
|
+
StatusOpen: () => StatusOpen,
|
|
216
|
+
TidalLogin: () => TidalLogin,
|
|
217
|
+
Time: () => Time,
|
|
218
|
+
Torrent: () => Torrent,
|
|
219
|
+
TorrentComment: () => TorrentComment,
|
|
220
|
+
TransportMethodAnnouncement: () => TransportMethodAnnouncement,
|
|
221
|
+
UserEmojiList: () => UserEmojiList,
|
|
222
|
+
UserGraspList: () => UserGraspList,
|
|
223
|
+
UserStatuses: () => UserStatuses,
|
|
224
|
+
VideoViewEvent: () => VideoViewEvent,
|
|
225
|
+
Voice: () => Voice,
|
|
226
|
+
VoiceComment: () => VoiceComment,
|
|
227
|
+
WebBookmarks: () => WebBookmarks,
|
|
228
|
+
WikiArticle: () => WikiArticle,
|
|
229
|
+
Zap: () => Zap,
|
|
230
|
+
ZapGoal: () => ZapGoal,
|
|
231
|
+
ZapRequest: () => ZapRequest,
|
|
232
|
+
classifyKind: () => classifyKind,
|
|
233
|
+
isAddressableKind: () => isAddressableKind,
|
|
234
|
+
isEphemeralKind: () => isEphemeralKind,
|
|
235
|
+
isKind: () => isKind,
|
|
236
|
+
isRegularKind: () => isRegularKind,
|
|
237
|
+
isReplaceableKind: () => isReplaceableKind
|
|
238
|
+
});
|
|
239
|
+
function isRegularKind(kind) {
|
|
240
|
+
return kind < 1e4 && kind !== 0 && kind !== 3;
|
|
241
|
+
}
|
|
242
|
+
function isReplaceableKind(kind) {
|
|
243
|
+
return kind === 0 || kind === 3 || 1e4 <= kind && kind < 2e4;
|
|
244
|
+
}
|
|
245
|
+
function isEphemeralKind(kind) {
|
|
246
|
+
return 2e4 <= kind && kind < 3e4;
|
|
247
|
+
}
|
|
248
|
+
function isAddressableKind(kind) {
|
|
249
|
+
return 3e4 <= kind && kind < 4e4;
|
|
250
|
+
}
|
|
251
|
+
function classifyKind(kind) {
|
|
252
|
+
if (isRegularKind(kind))
|
|
253
|
+
return "regular";
|
|
254
|
+
if (isReplaceableKind(kind))
|
|
255
|
+
return "replaceable";
|
|
256
|
+
if (isEphemeralKind(kind))
|
|
257
|
+
return "ephemeral";
|
|
258
|
+
if (isAddressableKind(kind))
|
|
259
|
+
return "parameterized";
|
|
260
|
+
return "unknown";
|
|
261
|
+
}
|
|
262
|
+
function isKind(event, kind) {
|
|
263
|
+
const kindAsArray = kind instanceof Array ? kind : [kind];
|
|
264
|
+
return validateEvent(event) && kindAsArray.includes(event.kind) || false;
|
|
265
|
+
}
|
|
266
|
+
var Metadata = 0;
|
|
267
|
+
var ShortTextNote = 1;
|
|
268
|
+
var RecommendRelay = 2;
|
|
269
|
+
var Contacts = 3;
|
|
270
|
+
var EncryptedDirectMessage = 4;
|
|
271
|
+
var EventDeletion = 5;
|
|
272
|
+
var Repost = 6;
|
|
273
|
+
var Reaction = 7;
|
|
274
|
+
var BadgeAward = 8;
|
|
275
|
+
var ChatMessage = 9;
|
|
276
|
+
var SimpleGroupThreadedReply = 10;
|
|
277
|
+
var ForumThread = 11;
|
|
278
|
+
var SimpleGroupReply = 12;
|
|
279
|
+
var Seal = 13;
|
|
280
|
+
var PrivateDirectMessage = 14;
|
|
281
|
+
var FileMessage = 15;
|
|
282
|
+
var GenericRepost = 16;
|
|
283
|
+
var ReactionToWebsite = 17;
|
|
284
|
+
var Photo = 20;
|
|
285
|
+
var NormalVideo = 21;
|
|
286
|
+
var ShortVideo = 22;
|
|
287
|
+
var PublicMessage = 24;
|
|
288
|
+
var ChannelCreation = 40;
|
|
289
|
+
var ChannelMetadata = 41;
|
|
290
|
+
var ChannelMessage = 42;
|
|
291
|
+
var ChannelHideMessage = 43;
|
|
292
|
+
var ChannelMuteUser = 44;
|
|
293
|
+
var PodcastEpisode = 54;
|
|
294
|
+
var Chess = 64;
|
|
295
|
+
var MergeRequests = 818;
|
|
296
|
+
var PollResponse = 1018;
|
|
297
|
+
var Bid = 1021;
|
|
298
|
+
var BidConfirmation = 1022;
|
|
299
|
+
var OpenTimestamps = 1040;
|
|
300
|
+
var GiftWrap = 1059;
|
|
301
|
+
var FileMetadata = 1063;
|
|
302
|
+
var Poll = 1068;
|
|
303
|
+
var Comment = 1111;
|
|
304
|
+
var Voice = 1222;
|
|
305
|
+
var Scroll = 1227;
|
|
306
|
+
var VoiceComment = 1244;
|
|
307
|
+
var LiveChatMessage = 1311;
|
|
308
|
+
var CodeSnippet = 1337;
|
|
309
|
+
var Patch = 1617;
|
|
310
|
+
var GitPullRequest = 1618;
|
|
311
|
+
var GitPullRequestUpdate = 1619;
|
|
312
|
+
var Issue = 1621;
|
|
313
|
+
var Reply = 1622;
|
|
314
|
+
var StatusOpen = 1630;
|
|
315
|
+
var StatusApplied = 1631;
|
|
316
|
+
var StatusClosed = 1632;
|
|
317
|
+
var StatusDraft = 1633;
|
|
318
|
+
var ProblemTracker = 1971;
|
|
319
|
+
var Report = 1984;
|
|
320
|
+
var Reporting = 1984;
|
|
321
|
+
var Label = 1985;
|
|
322
|
+
var RelayReviews = 1986;
|
|
323
|
+
var AIEmbeddings = 1987;
|
|
324
|
+
var Torrent = 2003;
|
|
325
|
+
var TorrentComment = 2004;
|
|
326
|
+
var CoinjoinPool = 2022;
|
|
327
|
+
var DecoupledKeyClientAnnouncement = 4454;
|
|
328
|
+
var DecoupledEncryptionKeyDistribution = 4455;
|
|
329
|
+
var CommunityPostApproval = 4550;
|
|
330
|
+
var JobRequest = 5999;
|
|
331
|
+
var JobResult = 6999;
|
|
332
|
+
var JobFeedback = 7e3;
|
|
333
|
+
var ReservedCashuWalletTokens = 7374;
|
|
334
|
+
var CashuWalletTokens = 7375;
|
|
335
|
+
var CashuWalletHistory = 7376;
|
|
336
|
+
var GeocacheLog = 7516;
|
|
337
|
+
var GeocacheProofOfFind = 7517;
|
|
338
|
+
var SimpleGroupPutUser = 9e3;
|
|
339
|
+
var SimpleGroupRemoveUser = 9001;
|
|
340
|
+
var SimpleGroupEditMetadata = 9002;
|
|
341
|
+
var SimpleGroupDeleteEvent = 9005;
|
|
342
|
+
var SimpleGroupCreateGroup = 9007;
|
|
343
|
+
var SimpleGroupDeleteGroup = 9008;
|
|
344
|
+
var SimpleGroupCreateInvite = 9009;
|
|
345
|
+
var SimpleGroupJoinRequest = 9021;
|
|
346
|
+
var SimpleGroupLeaveRequest = 9022;
|
|
347
|
+
var ZapGoal = 9041;
|
|
348
|
+
var NutZap = 9321;
|
|
349
|
+
var TidalLogin = 9467;
|
|
350
|
+
var ZapRequest = 9734;
|
|
351
|
+
var Zap = 9735;
|
|
352
|
+
var Highlights = 9802;
|
|
353
|
+
var Mutelist = 1e4;
|
|
354
|
+
var Pinlist = 10001;
|
|
355
|
+
var RelayList = 10002;
|
|
356
|
+
var BookmarkList = 10003;
|
|
357
|
+
var CommunitiesList = 10004;
|
|
358
|
+
var PublicChatsList = 10005;
|
|
359
|
+
var BlockedRelaysList = 10006;
|
|
360
|
+
var SearchRelaysList = 10007;
|
|
361
|
+
var SimpleGroupList = 10009;
|
|
362
|
+
var FavoriteRelays = 10012;
|
|
363
|
+
var PrivateEventRelayList = 10013;
|
|
364
|
+
var InterestsList = 10015;
|
|
365
|
+
var NutZapInfo = 10019;
|
|
366
|
+
var MediaFollows = 10020;
|
|
367
|
+
var UserEmojiList = 10030;
|
|
368
|
+
var DecoupledKeyAnnouncement = 10044;
|
|
369
|
+
var DirectMessageRelaysList = 10050;
|
|
370
|
+
var FavoritePodcasts = 10054;
|
|
371
|
+
var BlossomServerList = 10063;
|
|
372
|
+
var FileServerPreference = 10096;
|
|
373
|
+
var GoodWikiAuthorList = 10101;
|
|
374
|
+
var GoodWikiRelayList = 10102;
|
|
375
|
+
var PodcastMetadata = 10154;
|
|
376
|
+
var AuthoredPodcasts = 10164;
|
|
377
|
+
var RelayMonitorAnnouncement = 10166;
|
|
378
|
+
var RoomPresence = 10312;
|
|
379
|
+
var UserGraspList = 10317;
|
|
380
|
+
var ProxyAnnouncement = 10377;
|
|
381
|
+
var TransportMethodAnnouncement = 11111;
|
|
382
|
+
var NWCWalletInfo = 13194;
|
|
383
|
+
var NsiteRoot = 15128;
|
|
384
|
+
var CashuWalletEvent = 17375;
|
|
385
|
+
var LightningPubRPC = 21e3;
|
|
386
|
+
var ClientAuth = 22242;
|
|
387
|
+
var NWCWalletRequest = 23194;
|
|
388
|
+
var NWCWalletResponse = 23195;
|
|
389
|
+
var NostrConnect = 24133;
|
|
390
|
+
var BlobsAuth = 24242;
|
|
391
|
+
var HTTPAuth = 27235;
|
|
392
|
+
var Followsets = 3e4;
|
|
393
|
+
var Genericlists = 30001;
|
|
394
|
+
var Relaysets = 30002;
|
|
395
|
+
var Bookmarksets = 30003;
|
|
396
|
+
var Curationsets = 30004;
|
|
397
|
+
var CuratedVideoSets = 30005;
|
|
398
|
+
var MuteSets = 30007;
|
|
399
|
+
var ProfileBadges = 30008;
|
|
400
|
+
var BadgeDefinition = 30009;
|
|
401
|
+
var Interestsets = 30015;
|
|
402
|
+
var CreateOrUpdateStall = 30017;
|
|
403
|
+
var CreateOrUpdateProduct = 30018;
|
|
404
|
+
var MarketplaceUI = 30019;
|
|
405
|
+
var ProductSoldAsAuction = 30020;
|
|
406
|
+
var LongFormArticle = 30023;
|
|
407
|
+
var DraftLong = 30024;
|
|
408
|
+
var Emojisets = 30030;
|
|
409
|
+
var ModularArticleHeader = 30040;
|
|
410
|
+
var ModularArticleContent = 30041;
|
|
411
|
+
var ReleaseArtifactSets = 30063;
|
|
412
|
+
var Application = 30078;
|
|
413
|
+
var RelayDiscovery = 30166;
|
|
414
|
+
var AppCurationSet = 30267;
|
|
415
|
+
var LiveEvent = 30311;
|
|
416
|
+
var InteractiveRoom = 30312;
|
|
417
|
+
var ConferenceEvent = 30313;
|
|
418
|
+
var UserStatuses = 30315;
|
|
419
|
+
var SlideSet = 30388;
|
|
420
|
+
var ClassifiedListing = 30402;
|
|
421
|
+
var DraftClassifiedListing = 30403;
|
|
422
|
+
var RepositoryAnnouncement = 30617;
|
|
423
|
+
var RepositoryState = 30618;
|
|
424
|
+
var WikiArticle = 30818;
|
|
425
|
+
var Redirects = 30819;
|
|
426
|
+
var DraftEvent = 31234;
|
|
427
|
+
var LinkSet = 31388;
|
|
428
|
+
var Feed = 31890;
|
|
429
|
+
var Date2 = 31922;
|
|
430
|
+
var Time = 31923;
|
|
431
|
+
var Calendar = 31924;
|
|
432
|
+
var CalendarEventRSVP = 31925;
|
|
433
|
+
var RelayReview = 31987;
|
|
434
|
+
var Handlerrecommendation = 31989;
|
|
435
|
+
var Handlerinformation = 31990;
|
|
436
|
+
var SoftwareApplication = 32267;
|
|
437
|
+
var LegacyNsiteFile = 34128;
|
|
438
|
+
var VideoViewEvent = 34237;
|
|
439
|
+
var CommunityDefinition = 34550;
|
|
440
|
+
var NsiteNamed = 35128;
|
|
441
|
+
var GeocacheListing = 37515;
|
|
442
|
+
var GeocacheLogEntry = 37516;
|
|
443
|
+
var CashuMintAnnouncement = 38172;
|
|
444
|
+
var FedimintAnnouncement = 38173;
|
|
445
|
+
var PeerToPeerOrderEvents = 38383;
|
|
446
|
+
var GroupMetadata = 39e3;
|
|
447
|
+
var SimpleGroupAdmins = 39001;
|
|
448
|
+
var SimpleGroupMembers = 39002;
|
|
449
|
+
var SimpleGroupRoles = 39003;
|
|
450
|
+
var SimpleGroupLiveKitParticipants = 39004;
|
|
451
|
+
var StarterPacks = 39089;
|
|
452
|
+
var MediaStarterPacks = 39092;
|
|
453
|
+
var WebBookmarks = 39701;
|
|
454
|
+
|
|
455
|
+
// nipb0.ts
|
|
456
|
+
function isSha256(str) {
|
|
457
|
+
return /^[0-9a-f]{64}$/i.test(str);
|
|
458
|
+
}
|
|
459
|
+
function getBlobSize(blob) {
|
|
460
|
+
if (typeof File !== "undefined" && blob instanceof File || blob instanceof Blob) {
|
|
461
|
+
return blob.size;
|
|
462
|
+
}
|
|
463
|
+
return blob.length;
|
|
464
|
+
}
|
|
465
|
+
function getBlobType(blob) {
|
|
466
|
+
if (typeof File !== "undefined" && blob instanceof File || blob instanceof Blob) {
|
|
467
|
+
return blob.type || void 0;
|
|
468
|
+
}
|
|
469
|
+
return void 0;
|
|
470
|
+
}
|
|
471
|
+
async function computeBlobSha256(blob) {
|
|
472
|
+
let buffer;
|
|
473
|
+
if (typeof File !== "undefined" && blob instanceof File || blob instanceof Blob) {
|
|
474
|
+
buffer = await blob.arrayBuffer();
|
|
475
|
+
} else {
|
|
476
|
+
buffer = blob;
|
|
477
|
+
}
|
|
478
|
+
const hash = sha256.create().update(new Uint8Array(buffer)).digest();
|
|
479
|
+
return bytesToHex(hash);
|
|
480
|
+
}
|
|
481
|
+
function encodeAuthorizationHeader(event) {
|
|
482
|
+
const json = JSON.stringify(event);
|
|
483
|
+
const bytes = new TextEncoder().encode(json);
|
|
484
|
+
let binary = "";
|
|
485
|
+
for (const byte of bytes)
|
|
486
|
+
binary += String.fromCharCode(byte);
|
|
487
|
+
return "Nostr " + btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
|
|
488
|
+
}
|
|
489
|
+
function now() {
|
|
490
|
+
return Math.floor(Date.now() / 1e3);
|
|
491
|
+
}
|
|
492
|
+
function oneHour() {
|
|
493
|
+
return now() + 3600;
|
|
494
|
+
}
|
|
495
|
+
function getAuthTagValues(auth, tagName) {
|
|
496
|
+
return auth.tags.filter((tag) => tag[0] === tagName).map((tag) => tag[1]);
|
|
497
|
+
}
|
|
498
|
+
function getAuthExpiration(auth) {
|
|
499
|
+
const expiration = auth.tags.find((tag) => tag[0] === "expiration")?.[1];
|
|
500
|
+
if (!expiration)
|
|
501
|
+
return void 0;
|
|
502
|
+
const timestamp = Number(expiration);
|
|
503
|
+
if (!Number.isFinite(timestamp))
|
|
504
|
+
return void 0;
|
|
505
|
+
return timestamp;
|
|
506
|
+
}
|
|
507
|
+
function isAuthExpired(auth, timestamp = now()) {
|
|
508
|
+
const expiration = getAuthExpiration(auth);
|
|
509
|
+
return expiration !== void 0 && expiration <= timestamp;
|
|
510
|
+
}
|
|
511
|
+
function normalizeServerTag(server) {
|
|
512
|
+
if (server instanceof URL)
|
|
513
|
+
return server.hostname.toLowerCase();
|
|
514
|
+
if (URL.canParse(server))
|
|
515
|
+
return new URL(server).hostname.toLowerCase();
|
|
516
|
+
return server.toLowerCase();
|
|
517
|
+
}
|
|
518
|
+
function areServersEqual(a, b) {
|
|
519
|
+
return normalizeServerTag(a) === normalizeServerTag(b);
|
|
520
|
+
}
|
|
521
|
+
function normalizeServers(servers) {
|
|
522
|
+
const values = Array.isArray(servers) ? servers : [servers];
|
|
523
|
+
return [...new Set(values.map(normalizeServerTag))];
|
|
524
|
+
}
|
|
525
|
+
async function createAuthEvent(signer, type, options) {
|
|
526
|
+
const draft = {
|
|
527
|
+
created_at: now(),
|
|
528
|
+
kind: kinds_exports.BlobsAuth,
|
|
529
|
+
content: options?.message ?? "",
|
|
530
|
+
tags: [
|
|
531
|
+
["t", type],
|
|
532
|
+
["expiration", String(options?.expiration ?? oneHour())]
|
|
533
|
+
]
|
|
534
|
+
};
|
|
535
|
+
if (options?.blobs) {
|
|
536
|
+
const blobList = Array.isArray(options.blobs) ? options.blobs : [options.blobs];
|
|
537
|
+
const seen = /* @__PURE__ */ new Set();
|
|
538
|
+
for (const blob of blobList) {
|
|
539
|
+
const hash = typeof blob === "string" ? blob : await computeBlobSha256(blob);
|
|
540
|
+
if (!seen.has(hash)) {
|
|
541
|
+
draft.tags.push(["x", hash]);
|
|
542
|
+
seen.add(hash);
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
if (options?.servers) {
|
|
547
|
+
for (const server of normalizeServers(options.servers)) {
|
|
548
|
+
draft.tags.push(["server", server]);
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
return signer(draft);
|
|
552
|
+
}
|
|
553
|
+
async function createUploadAuth(signer, blobs, options) {
|
|
554
|
+
return createAuthEvent(signer, options?.type ?? "upload", { message: "Upload Blob", ...options, blobs });
|
|
555
|
+
}
|
|
556
|
+
async function createDownloadAuth(signer, hash, options) {
|
|
557
|
+
return createAuthEvent(signer, "get", { message: "Download Blob", ...options, blobs: [hash] });
|
|
558
|
+
}
|
|
559
|
+
async function createMirrorAuth(signer, hash, options) {
|
|
560
|
+
return createAuthEvent(signer, "upload", { message: "Mirror Blob", ...options, blobs: [hash] });
|
|
561
|
+
}
|
|
562
|
+
async function createListAuth(signer, options) {
|
|
563
|
+
return createAuthEvent(signer, "list", { message: "List Blobs", ...options });
|
|
564
|
+
}
|
|
565
|
+
async function createDeleteAuth(signer, hash, options) {
|
|
566
|
+
return createAuthEvent(signer, "delete", { message: "Delete Blob", ...options, blobs: [hash] });
|
|
567
|
+
}
|
|
568
|
+
function parseBlossomURI(uri) {
|
|
569
|
+
if (!uri.startsWith("blossom:"))
|
|
570
|
+
throw new Error("Invalid blossom URI: missing blossom: scheme");
|
|
571
|
+
const body = uri.slice("blossom:".length);
|
|
572
|
+
const queryIndex = body.indexOf("?");
|
|
573
|
+
const path = queryIndex === -1 ? body : body.slice(0, queryIndex);
|
|
574
|
+
const query = queryIndex === -1 ? "" : body.slice(queryIndex + 1);
|
|
575
|
+
const dotIndex = path.indexOf(".");
|
|
576
|
+
if (dotIndex === -1)
|
|
577
|
+
throw new Error("Invalid blossom URI: missing file extension");
|
|
578
|
+
const sha2562 = path.slice(0, dotIndex);
|
|
579
|
+
const ext = path.slice(dotIndex + 1);
|
|
580
|
+
if (!isSha256(sha2562))
|
|
581
|
+
throw new Error("Invalid blossom URI: invalid sha256 hash");
|
|
582
|
+
if (!ext)
|
|
583
|
+
throw new Error("Invalid blossom URI: empty file extension");
|
|
584
|
+
const params = new URLSearchParams(query);
|
|
585
|
+
const servers = params.getAll("xs");
|
|
586
|
+
const authors = params.getAll("as");
|
|
587
|
+
const szValue = params.get("sz");
|
|
588
|
+
let size;
|
|
589
|
+
if (szValue !== null) {
|
|
590
|
+
size = Number(szValue);
|
|
591
|
+
if (!Number.isFinite(size) || size <= 0 || Math.floor(size) !== size) {
|
|
592
|
+
throw new Error("Invalid blossom URI: sz must be a positive integer");
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
return { sha256: sha2562, ext, servers, authors, size };
|
|
596
|
+
}
|
|
597
|
+
function buildBlossomURI(options) {
|
|
598
|
+
const params = new URLSearchParams();
|
|
599
|
+
for (const server of options.servers)
|
|
600
|
+
params.append("xs", server);
|
|
601
|
+
for (const author of options.authors)
|
|
602
|
+
params.append("as", author);
|
|
603
|
+
if (options.size !== void 0)
|
|
604
|
+
params.append("sz", String(options.size));
|
|
605
|
+
const query = params.toString();
|
|
606
|
+
return `blossom:${options.sha256}.${options.ext}${query ? "?" + query : ""}`;
|
|
607
|
+
}
|
|
608
|
+
function blossomURIToURL(uri) {
|
|
609
|
+
const str = typeof uri === "string" ? uri : buildBlossomURI(uri);
|
|
610
|
+
return new URL(str);
|
|
611
|
+
}
|
|
612
|
+
function blossomURIFromURL(url) {
|
|
613
|
+
if (url.protocol !== "blossom:")
|
|
614
|
+
throw new Error("Invalid blossom URL: expected blossom: protocol");
|
|
615
|
+
const path = url.pathname;
|
|
616
|
+
const dotIndex = path.indexOf(".");
|
|
617
|
+
if (dotIndex === -1)
|
|
618
|
+
throw new Error("Invalid blossom URL: missing file extension");
|
|
619
|
+
const sha2562 = path.slice(0, dotIndex);
|
|
620
|
+
const ext = path.slice(dotIndex + 1);
|
|
621
|
+
if (!isSha256(sha2562))
|
|
622
|
+
throw new Error("Invalid blossom URL: invalid sha256 hash");
|
|
623
|
+
if (!ext)
|
|
624
|
+
throw new Error("Invalid blossom URL: empty file extension");
|
|
625
|
+
const servers = url.searchParams.getAll("xs");
|
|
626
|
+
const authors = url.searchParams.getAll("as");
|
|
627
|
+
const szValue = url.searchParams.get("sz");
|
|
628
|
+
let size;
|
|
629
|
+
if (szValue !== null) {
|
|
630
|
+
size = Number(szValue);
|
|
631
|
+
if (!Number.isFinite(size) || size <= 0 || Math.floor(size) !== size) {
|
|
632
|
+
throw new Error("Invalid blossom URL: sz must be a positive integer");
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
return { sha256: sha2562, ext, servers, authors, size };
|
|
636
|
+
}
|
|
637
|
+
var commonMimeExtensions = {
|
|
638
|
+
"application/json": ".json",
|
|
639
|
+
"application/pdf": ".pdf",
|
|
640
|
+
"application/vnd.android.package-archive": ".apk",
|
|
641
|
+
"application/vnd.sqlite3": ".sqlite3",
|
|
642
|
+
"application/xml": ".xml",
|
|
643
|
+
"audio/aac": ".aac",
|
|
644
|
+
"audio/flac": ".flac",
|
|
645
|
+
"audio/midi": ".midi",
|
|
646
|
+
"audio/mp3": ".mp3",
|
|
647
|
+
"audio/mpeg": ".mp3",
|
|
648
|
+
"audio/mp4": ".m4a",
|
|
649
|
+
"audio/ogg": ".ogg",
|
|
650
|
+
"audio/wav": ".wav",
|
|
651
|
+
"audio/webm": ".weba",
|
|
652
|
+
"audio/x-aiff": ".aiff",
|
|
653
|
+
"audio/x-m4a": ".m4a",
|
|
654
|
+
"image/avif": ".avif",
|
|
655
|
+
"image/gif": ".gif",
|
|
656
|
+
"image/jpeg": ".jpg",
|
|
657
|
+
"image/png": ".png",
|
|
658
|
+
"image/svg+xml": ".svg",
|
|
659
|
+
"image/webp": ".webp",
|
|
660
|
+
"text/css": ".css",
|
|
661
|
+
"text/csv": ".csv",
|
|
662
|
+
"text/html": ".html",
|
|
663
|
+
"text/javascript": ".js",
|
|
664
|
+
"text/markdown": ".md",
|
|
665
|
+
"text/plain": ".txt",
|
|
666
|
+
"text/xml": ".xml",
|
|
667
|
+
"video/mp2t": ".ts",
|
|
668
|
+
"video/mp4": ".mp4",
|
|
669
|
+
"video/ogg": ".ogv",
|
|
670
|
+
"video/quicktime": ".mov",
|
|
671
|
+
"video/webm": ".webm",
|
|
672
|
+
"video/x-matroska": ".mkv"
|
|
673
|
+
};
|
|
674
|
+
var commonExtensionMimes = {
|
|
675
|
+
".aac": "audio/aac",
|
|
676
|
+
".aiff": "audio/x-aiff",
|
|
677
|
+
".apk": "application/vnd.android.package-archive",
|
|
678
|
+
".avif": "image/avif",
|
|
679
|
+
".css": "text/css; charset=utf-8",
|
|
680
|
+
".csv": "text/csv; charset=utf-8",
|
|
681
|
+
".flac": "audio/flac",
|
|
682
|
+
".gif": "image/gif",
|
|
683
|
+
".html": "text/html; charset=utf-8",
|
|
684
|
+
".jpeg": "image/jpeg",
|
|
685
|
+
".jpg": "image/jpeg",
|
|
686
|
+
".js": "text/javascript; charset=utf-8",
|
|
687
|
+
".json": "application/json",
|
|
688
|
+
".m4a": "audio/mp4",
|
|
689
|
+
".md": "text/markdown; charset=utf-8",
|
|
690
|
+
".midi": "audio/midi",
|
|
691
|
+
".mkv": "video/x-matroska",
|
|
692
|
+
".mov": "video/quicktime",
|
|
693
|
+
".mp3": "audio/mpeg",
|
|
694
|
+
".mp4": "video/mp4",
|
|
695
|
+
".oga": "audio/ogg",
|
|
696
|
+
".ogg": "audio/ogg",
|
|
697
|
+
".ogv": "video/ogg",
|
|
698
|
+
".pdf": "application/pdf",
|
|
699
|
+
".png": "image/png",
|
|
700
|
+
".sqlite3": "application/vnd.sqlite3",
|
|
701
|
+
".svg": "image/svg+xml",
|
|
702
|
+
".ts": "video/mp2t",
|
|
703
|
+
".txt": "text/plain; charset=utf-8",
|
|
704
|
+
".wav": "audio/wav",
|
|
705
|
+
".weba": "audio/webm",
|
|
706
|
+
".webm": "video/webm",
|
|
707
|
+
".webp": "image/webp",
|
|
708
|
+
".xml": "application/xml"
|
|
709
|
+
};
|
|
710
|
+
function normalizeMIMEType(mimetype) {
|
|
711
|
+
const idx = mimetype.indexOf(";");
|
|
712
|
+
return idx >= 0 ? mimetype.slice(0, idx).trim().toLowerCase() : mimetype.trim().toLowerCase();
|
|
713
|
+
}
|
|
714
|
+
function getExtension(mimetype) {
|
|
715
|
+
const normalized = normalizeMIMEType(mimetype);
|
|
716
|
+
if (!normalized)
|
|
717
|
+
return "";
|
|
718
|
+
return commonMimeExtensions[normalized] ?? "";
|
|
719
|
+
}
|
|
720
|
+
function getMIMEType(ext) {
|
|
721
|
+
if (!ext)
|
|
722
|
+
return "";
|
|
723
|
+
ext = ext.trim().toLowerCase();
|
|
724
|
+
if (ext[0] !== ".")
|
|
725
|
+
ext = "." + ext;
|
|
726
|
+
return commonExtensionMimes[ext] ?? "";
|
|
727
|
+
}
|
|
728
|
+
function getServersFromServerListEvent(event) {
|
|
729
|
+
const servers = [];
|
|
730
|
+
for (const tag of event.tags) {
|
|
731
|
+
if (tag[0] === "server" && tag[1]) {
|
|
732
|
+
try {
|
|
733
|
+
const url = new URL(tag[1]);
|
|
734
|
+
url.pathname = "/";
|
|
735
|
+
servers.push(url);
|
|
736
|
+
} catch {
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
return servers;
|
|
741
|
+
}
|
|
742
|
+
function getHashFromURL(url) {
|
|
743
|
+
try {
|
|
744
|
+
if (typeof url === "string")
|
|
745
|
+
url = new URL(url);
|
|
746
|
+
const hashes = Array.from(url.pathname.matchAll(/[0-9a-f]{64}/gi));
|
|
747
|
+
return hashes.length > 0 ? hashes[hashes.length - 1][0] : null;
|
|
748
|
+
} catch (_err) {
|
|
749
|
+
return null;
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
async function uploadBlob(server, blob, opts) {
|
|
753
|
+
const url = new URL("/upload", server).toString();
|
|
754
|
+
const sha2562 = await computeBlobSha256(blob);
|
|
755
|
+
const headers = { "X-SHA-256": sha2562 };
|
|
756
|
+
if (opts?.auth) {
|
|
757
|
+
const authEvent = typeof opts.auth === "boolean" ? await opts.onAuth?.(server, sha2562) : opts.auth;
|
|
758
|
+
if (authEvent)
|
|
759
|
+
headers["Authorization"] = encodeAuthorizationHeader(authEvent);
|
|
760
|
+
}
|
|
761
|
+
const res = await fetch(url, {
|
|
762
|
+
method: "PUT",
|
|
763
|
+
body: blob,
|
|
764
|
+
headers,
|
|
765
|
+
signal: opts?.signal
|
|
766
|
+
});
|
|
767
|
+
if (res.status >= 300) {
|
|
768
|
+
const reason = res.headers.get("X-Reason") || res.statusText;
|
|
769
|
+
throw new Error(`upload returned error (${res.status}): ${reason}`);
|
|
770
|
+
}
|
|
771
|
+
return res.json();
|
|
772
|
+
}
|
|
773
|
+
async function downloadBlob(server, hash, opts) {
|
|
774
|
+
const url = new URL("/" + hash, server).toString();
|
|
775
|
+
const headers = {};
|
|
776
|
+
if (opts?.auth) {
|
|
777
|
+
const authEvent = typeof opts.auth === "boolean" ? await opts.onAuth?.(server, hash) : opts.auth;
|
|
778
|
+
if (authEvent)
|
|
779
|
+
headers["Authorization"] = encodeAuthorizationHeader(authEvent);
|
|
780
|
+
}
|
|
781
|
+
const res = await fetch(url, { headers, signal: opts?.signal });
|
|
782
|
+
if (res.status >= 300) {
|
|
783
|
+
const reason = res.headers.get("X-Reason") || res.statusText;
|
|
784
|
+
throw new Error(`${hash} download error (${res.status}): ${reason}`);
|
|
785
|
+
}
|
|
786
|
+
return res;
|
|
787
|
+
}
|
|
788
|
+
async function listBlobs(server, pubkey, opts) {
|
|
789
|
+
const url = new URL("/list/" + pubkey, server);
|
|
790
|
+
if (opts?.cursor)
|
|
791
|
+
url.searchParams.append("cursor", opts.cursor);
|
|
792
|
+
if (opts?.limit)
|
|
793
|
+
url.searchParams.append("limit", String(opts.limit));
|
|
794
|
+
if (opts?.since)
|
|
795
|
+
url.searchParams.append("since", String(opts.since));
|
|
796
|
+
if (opts?.until)
|
|
797
|
+
url.searchParams.append("until", String(opts.until));
|
|
798
|
+
const headers = {};
|
|
799
|
+
if (opts?.auth) {
|
|
800
|
+
const authEvent = typeof opts.auth === "boolean" ? await opts.onAuth?.(server) : opts.auth;
|
|
801
|
+
if (authEvent)
|
|
802
|
+
headers["Authorization"] = encodeAuthorizationHeader(authEvent);
|
|
803
|
+
}
|
|
804
|
+
const res = await fetch(url.toString(), { headers, signal: opts?.signal });
|
|
805
|
+
if (res.status >= 300) {
|
|
806
|
+
const reason = res.headers.get("X-Reason") || res.statusText;
|
|
807
|
+
throw new Error(`list error (${res.status}): ${reason}`);
|
|
808
|
+
}
|
|
809
|
+
return res.json();
|
|
810
|
+
}
|
|
811
|
+
async function* iterateBlobs(server, pubkey, opts) {
|
|
812
|
+
let cursor = opts?.cursor;
|
|
813
|
+
while (true) {
|
|
814
|
+
const page = await listBlobs(server, pubkey, { ...opts, cursor });
|
|
815
|
+
if (page.length === 0)
|
|
816
|
+
return;
|
|
817
|
+
yield page;
|
|
818
|
+
if (opts?.limit && page.length < opts.limit)
|
|
819
|
+
return;
|
|
820
|
+
cursor = page[page.length - 1]?.sha256;
|
|
821
|
+
if (!cursor)
|
|
822
|
+
return;
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
async function deleteBlob(server, hash, opts) {
|
|
826
|
+
const url = new URL("/" + hash, server).toString();
|
|
827
|
+
const headers = {};
|
|
828
|
+
if (opts?.auth) {
|
|
829
|
+
const authEvent = typeof opts.auth === "boolean" ? await opts.onAuth?.(server, hash) : opts.auth;
|
|
830
|
+
if (authEvent)
|
|
831
|
+
headers["Authorization"] = encodeAuthorizationHeader(authEvent);
|
|
832
|
+
}
|
|
833
|
+
const res = await fetch(url, { method: "DELETE", headers, signal: opts?.signal });
|
|
834
|
+
if (res.status >= 300) {
|
|
835
|
+
const reason = res.headers.get("X-Reason") || res.statusText;
|
|
836
|
+
throw new Error(`delete error (${res.status}): ${reason}`);
|
|
837
|
+
}
|
|
838
|
+
return res.ok;
|
|
839
|
+
}
|
|
840
|
+
async function hasBlob(server, hash, opts) {
|
|
841
|
+
const url = new URL("/" + hash, server);
|
|
842
|
+
try {
|
|
843
|
+
const res = await fetch(url.toString(), { method: "HEAD", signal: opts?.signal });
|
|
844
|
+
return res.status !== 404;
|
|
845
|
+
} catch {
|
|
846
|
+
return false;
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
async function mirrorBlob(server, blob, opts) {
|
|
850
|
+
const url = new URL("/mirror", server).toString();
|
|
851
|
+
const headers = {
|
|
852
|
+
"Content-Type": "application/json",
|
|
853
|
+
"X-SHA-256": blob.sha256
|
|
854
|
+
};
|
|
855
|
+
if (opts?.auth) {
|
|
856
|
+
const authEvent = typeof opts.auth === "boolean" ? await opts.onAuth?.(server, blob.sha256) : opts.auth;
|
|
857
|
+
if (authEvent)
|
|
858
|
+
headers["Authorization"] = encodeAuthorizationHeader(authEvent);
|
|
859
|
+
}
|
|
860
|
+
const res = await fetch(url, {
|
|
861
|
+
method: "PUT",
|
|
862
|
+
body: JSON.stringify({ url: blob.url }),
|
|
863
|
+
headers,
|
|
864
|
+
signal: opts?.signal
|
|
865
|
+
});
|
|
866
|
+
if (res.status >= 300) {
|
|
867
|
+
const reason = res.headers.get("X-Reason") || res.statusText;
|
|
868
|
+
throw new Error(`mirror error (${res.status}): ${reason}`);
|
|
869
|
+
}
|
|
870
|
+
return res.json();
|
|
871
|
+
}
|
|
872
|
+
async function reportBlobs(servers, report, opts) {
|
|
873
|
+
if (report.kind !== 1984 || !report.tags.some((tag) => tag[0] === "x" && !!tag[1])) {
|
|
874
|
+
throw new Error("Invalid blob report event: must be kind 1984 with x tag");
|
|
875
|
+
}
|
|
876
|
+
const results = /* @__PURE__ */ new Map();
|
|
877
|
+
const body = JSON.stringify(report);
|
|
878
|
+
for (const server of servers) {
|
|
879
|
+
try {
|
|
880
|
+
const res = await fetch(new URL("/report", server).toString(), {
|
|
881
|
+
method: "PUT",
|
|
882
|
+
headers: { "Content-Type": "application/json" },
|
|
883
|
+
body,
|
|
884
|
+
signal: opts?.signal
|
|
885
|
+
});
|
|
886
|
+
if (res.status >= 300) {
|
|
887
|
+
const reason = res.headers.get("X-Reason") || res.statusText;
|
|
888
|
+
throw new Error(`report error (${res.status}): ${reason}`);
|
|
889
|
+
}
|
|
890
|
+
results.set(server, true);
|
|
891
|
+
} catch (error) {
|
|
892
|
+
if (opts?.onError && error instanceof Error)
|
|
893
|
+
opts.onError(server, error);
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
return results;
|
|
897
|
+
}
|
|
898
|
+
var BlossomClient = class {
|
|
899
|
+
constructor(mediaserver, signer) {
|
|
900
|
+
this.signer = signer;
|
|
901
|
+
if (!mediaserver.startsWith("http")) {
|
|
902
|
+
mediaserver = "https://" + mediaserver;
|
|
903
|
+
}
|
|
904
|
+
this.mediaserver = mediaserver.replace(/\/$/, "") + "/";
|
|
905
|
+
}
|
|
906
|
+
mediaserver;
|
|
907
|
+
getMediaServer() {
|
|
908
|
+
return this.mediaserver;
|
|
909
|
+
}
|
|
910
|
+
async authorizationHeader(modify) {
|
|
911
|
+
const event = {
|
|
912
|
+
created_at: now(),
|
|
913
|
+
kind: kinds_exports.BlobsAuth,
|
|
914
|
+
content: "blossom stuff",
|
|
915
|
+
tags: [["expiration", String(now() + 60)]]
|
|
916
|
+
};
|
|
917
|
+
modify?.(event);
|
|
918
|
+
try {
|
|
919
|
+
const signedEvent = await this.signer.signEvent(event);
|
|
920
|
+
const json = JSON.stringify(signedEvent);
|
|
921
|
+
return "Nostr " + btoa(json);
|
|
922
|
+
} catch {
|
|
923
|
+
return "";
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
async httpCall(method, url, contentType, addAuthorization, body) {
|
|
927
|
+
const headers = {};
|
|
928
|
+
if (contentType)
|
|
929
|
+
headers["Content-Type"] = contentType;
|
|
930
|
+
if (addAuthorization) {
|
|
931
|
+
const auth = await addAuthorization();
|
|
932
|
+
if (auth)
|
|
933
|
+
headers["Authorization"] = auth;
|
|
934
|
+
}
|
|
935
|
+
const res = await fetch(this.mediaserver + url, { method, headers, body });
|
|
936
|
+
if (res.status >= 300) {
|
|
937
|
+
const reason = res.headers.get("X-Reason") || res.statusText;
|
|
938
|
+
throw new Error(`${url} returned error (${res.status}): ${reason}`);
|
|
939
|
+
}
|
|
940
|
+
if (res.headers.get("content-type")?.includes("application/json")) {
|
|
941
|
+
return res.json();
|
|
942
|
+
}
|
|
943
|
+
return res;
|
|
944
|
+
}
|
|
945
|
+
async uploadBlob(file, contentType) {
|
|
946
|
+
const hash = bytesToHex(sha256(new Uint8Array(await file.arrayBuffer())));
|
|
947
|
+
const actualContentType = contentType || getBlobType(file) || "application/octet-stream";
|
|
948
|
+
return this.httpCall(
|
|
949
|
+
"PUT",
|
|
950
|
+
"upload",
|
|
951
|
+
actualContentType,
|
|
952
|
+
() => this.authorizationHeader((evt) => {
|
|
953
|
+
evt.tags.push(["t", "upload"], ["x", hash]);
|
|
954
|
+
}),
|
|
955
|
+
file
|
|
956
|
+
);
|
|
957
|
+
}
|
|
958
|
+
async download(hash) {
|
|
959
|
+
const authHeader = await this.authorizationHeader((evt) => {
|
|
960
|
+
evt.tags.push(["t", "get"], ["x", hash]);
|
|
961
|
+
});
|
|
962
|
+
const res = await fetch(this.mediaserver + hash, {
|
|
963
|
+
method: "GET",
|
|
964
|
+
headers: { Authorization: authHeader }
|
|
965
|
+
});
|
|
966
|
+
if (res.status >= 300) {
|
|
967
|
+
throw new Error(`${hash} not present on ${this.mediaserver}: ${res.status}`);
|
|
968
|
+
}
|
|
969
|
+
return res.arrayBuffer();
|
|
970
|
+
}
|
|
971
|
+
async downloadAsBlob(hash) {
|
|
972
|
+
return new Blob([await this.download(hash)]);
|
|
973
|
+
}
|
|
974
|
+
async list() {
|
|
975
|
+
const pubkey = await this.signer.getPublicKey();
|
|
976
|
+
return this.httpCall(
|
|
977
|
+
"GET",
|
|
978
|
+
`list/${pubkey}`,
|
|
979
|
+
void 0,
|
|
980
|
+
() => this.authorizationHeader((evt) => {
|
|
981
|
+
evt.tags.push(["t", "list"]);
|
|
982
|
+
})
|
|
983
|
+
);
|
|
984
|
+
}
|
|
985
|
+
async delete(hash) {
|
|
986
|
+
await this.httpCall(
|
|
987
|
+
"DELETE",
|
|
988
|
+
hash,
|
|
989
|
+
void 0,
|
|
990
|
+
() => this.authorizationHeader((evt) => {
|
|
991
|
+
evt.tags.push(["t", "delete"], ["x", hash]);
|
|
992
|
+
})
|
|
993
|
+
);
|
|
994
|
+
}
|
|
995
|
+
async check(hash) {
|
|
996
|
+
if (!isSha256(hash))
|
|
997
|
+
throw new Error(`${hash} is not valid 32-byte hex`);
|
|
998
|
+
await this.httpCall("HEAD", hash);
|
|
999
|
+
}
|
|
1000
|
+
async mirror(remoteBlobURL) {
|
|
1001
|
+
const hash = remoteBlobURL.split("/").pop()?.split(".")[0] || "";
|
|
1002
|
+
return this.httpCall(
|
|
1003
|
+
"PUT",
|
|
1004
|
+
"mirror",
|
|
1005
|
+
"application/json",
|
|
1006
|
+
() => this.authorizationHeader((evt) => {
|
|
1007
|
+
evt.tags.push(["t", "upload"], ["x", hash]);
|
|
1008
|
+
}),
|
|
1009
|
+
JSON.stringify({ url: remoteBlobURL })
|
|
1010
|
+
);
|
|
1011
|
+
}
|
|
1012
|
+
};
|
|
1013
|
+
export {
|
|
1014
|
+
BlossomClient,
|
|
1015
|
+
areServersEqual,
|
|
1016
|
+
blossomURIFromURL,
|
|
1017
|
+
blossomURIToURL,
|
|
1018
|
+
buildBlossomURI,
|
|
1019
|
+
computeBlobSha256,
|
|
1020
|
+
createAuthEvent,
|
|
1021
|
+
createDeleteAuth,
|
|
1022
|
+
createDownloadAuth,
|
|
1023
|
+
createListAuth,
|
|
1024
|
+
createMirrorAuth,
|
|
1025
|
+
createUploadAuth,
|
|
1026
|
+
deleteBlob,
|
|
1027
|
+
downloadBlob,
|
|
1028
|
+
encodeAuthorizationHeader,
|
|
1029
|
+
getAuthExpiration,
|
|
1030
|
+
getAuthTagValues,
|
|
1031
|
+
getBlobSize,
|
|
1032
|
+
getBlobType,
|
|
1033
|
+
getExtension,
|
|
1034
|
+
getHashFromURL,
|
|
1035
|
+
getMIMEType,
|
|
1036
|
+
getServersFromServerListEvent,
|
|
1037
|
+
hasBlob,
|
|
1038
|
+
isAuthExpired,
|
|
1039
|
+
isSha256,
|
|
1040
|
+
iterateBlobs,
|
|
1041
|
+
listBlobs,
|
|
1042
|
+
mirrorBlob,
|
|
1043
|
+
normalizeServerTag,
|
|
1044
|
+
now,
|
|
1045
|
+
oneHour,
|
|
1046
|
+
parseBlossomURI,
|
|
1047
|
+
reportBlobs,
|
|
1048
|
+
uploadBlob
|
|
1049
|
+
};
|