@@ -22,11 +22,34 @@ export type EventId = Brand<string, "EventId">;
22
22
export type PublicKey = Brand < string , "PublicKey" > ;
23
23
export type Timestamp = Brand < number , "EventTimeStamp" > ;
24
24
25
- export type Tag = EventTag | PubKeyTag ;
26
- export type EventTag = [ "e" , EventId , RecmRelayUrl ] ;
27
- export type PubKeyTag = [ "p" , PublicKey , RecmRelayUrl ] ;
25
+ // ----------------------
26
+ // Tags
27
+ // ----------------------
28
+
29
+ export type Tag < T extends TagName = TagName > = [ T , ...string [ ] ] ;
30
+
31
+ export type TagName = Brand < string , "TagName" > ;
32
+ export type IndexedEventTag = [ IndexedEventTagName , ...string [ ] ] ;
33
+
34
+ export type EventTag = [ "e" , EventId , RecmRelayUrl ?] ;
35
+ export type PubKeyTag = [ "p" , PublicKey , RecmRelayUrl ?] ;
36
+ export type ParameterizedReplaceableEventTag = [
37
+ "a" ,
38
+ `${EventKind } :${PublicKey } :${TagValue < "d" > } `,
39
+ RecmRelayUrl ?,
40
+ ] ;
41
+ export type NonParameterizedReplaceableEventTag = [
42
+ "a" ,
43
+ `${EventKind } :${PublicKey } `,
44
+ RecmRelayUrl ?,
45
+ ] ;
46
+
47
+ // TODO: Use template literal
48
+ export type IndexedEventTagName = Brand < string , "IndexedEventTagName" > ;
49
+ // TODO: Use template literal
50
+ export type TagValue < T extends string = string > = Brand < string , `${T } TagValue`> ;
28
51
29
- export type RecmRelayUrl = RelayUrl | "" ;
52
+ export type RecmRelayUrl = RelayUrl ;
30
53
31
54
export type PrivateKey = Brand < string , "PrivateKey" > ;
32
55
export type Signature = Brand < string , "EventSignature" > ;
@@ -62,6 +85,7 @@ export type CloseMessage = ["CLOSE", SubscriptionId];
62
85
63
86
export type RelayToClientMessage =
64
87
| EventMessage
88
+ | OkMessage
65
89
| EoseMessage
66
90
| NoticeMessage ;
67
91
@@ -70,22 +94,46 @@ export type EventMessage<K extends EventKind = EventKind> = [
70
94
SubscriptionId ,
71
95
NostrEvent < K > ,
72
96
] ;
97
+ export type OkMessage < B extends boolean = boolean > = [
98
+ "OK" ,
99
+ EventId ,
100
+ B ,
101
+ OkMessageBody < B > ,
102
+ ] ;
73
103
export type EoseMessage = [ "EOSE" , SubscriptionId ] ;
74
- export type NoticeMessage = [ "NOTICE" , NoticeBody ] ;
104
+ export type NoticeMessage = [ "NOTICE" , string ] ;
75
105
76
106
export type SubscriptionId = Brand < string , "SubscriptionId" > ;
77
- export type NoticeBody = string ;
78
-
79
- export interface SubscriptionFilter < K extends EventKind = EventKind > {
80
- ids ?: EventId [ ] ;
81
- authors ?: PublicKey [ ] ;
82
- kinds ?: K [ ] ;
83
- "#e" ?: EventId [ ] ;
84
- "#p" ?: PublicKey [ ] ;
85
- since ?: Timestamp ;
86
- until ?: Timestamp ;
87
- limit ?: number ;
88
- }
107
+ export type OkMessageBody < B extends boolean > = B extends true
108
+ ? "" | OkMessageBodyString
109
+ : OkMessageBodyString ;
110
+ export type OkMessageBodyString = `${OkMessageBodyPrefix } : ${string } `;
111
+ export type OkMessageBodyPrefix =
112
+ | "duplicate"
113
+ | "pow"
114
+ | "blocked"
115
+ | "rate-limited"
116
+ | "invalid"
117
+ | "error" ;
118
+
119
+ export type SubscriptionFilter <
120
+ K extends EventKind = EventKind ,
121
+ T extends IndexedEventTagName = IndexedEventTagName ,
122
+ > =
123
+ & {
124
+ ids ?: EventId [ ] ;
125
+ authors ?: PublicKey [ ] ;
126
+ kinds ?: K [ ] ;
127
+ }
128
+ // TODO: Restrict to 1 tag per filter
129
+ & {
130
+ [ key in `#${T } `] ?: TagValue < T > [ ] ;
131
+ }
132
+ & {
133
+ since ?: Timestamp ;
134
+ until ?: Timestamp ;
135
+ limit ?: number ;
136
+ } ;
89
137
90
138
// ----------------------
91
139
// Basic event kinds
@@ -94,7 +142,24 @@ export interface SubscriptionFilter<K extends EventKind = EventKind> {
94
142
export enum EventKind {
95
143
Metadata = 0 ,
96
144
TextNote = 1 ,
97
- RecommendRelay = 2 ,
145
+ }
146
+
147
+ // deno-lint-ignore no-namespace
148
+ export namespace EventKind {
149
+ export function isRegularEventKind ( kind : EventKind | number ) : boolean {
150
+ return 1000 <= kind && kind < 10000 ;
151
+ }
152
+ export function isReplaceableEventKind ( kind : EventKind | number ) : boolean {
153
+ return ( 10000 <= kind && kind < 20000 ) || kind === 0 || kind === 3 ;
154
+ }
155
+ export function isEphemeralEventKind ( kind : EventKind | number ) : boolean {
156
+ return 20000 <= kind && kind < 30000 ;
157
+ }
158
+ export function isParameterizedReplaceableEventKind (
159
+ kind : EventKind | number ,
160
+ ) : boolean {
161
+ return 30000 <= kind && kind < 40000 ;
162
+ }
98
163
}
99
164
100
165
export type EventContent = [
0 commit comments