@estiva-app/protocol 0.1.0
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/CHANGELOG.md +57 -0
- package/LICENSE +21 -0
- package/README.md +158 -0
- package/dist/bridge.d.ts +91 -0
- package/dist/bridge.d.ts.map +1 -0
- package/dist/bridge.js +138 -0
- package/dist/bridge.js.map +1 -0
- package/dist/events.d.ts +432 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +616 -0
- package/dist/events.js.map +1 -0
- package/dist/index.d.ts +57 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +63 -0
- package/dist/index.js.map +1 -0
- package/dist/live.d.ts +205 -0
- package/dist/live.d.ts.map +1 -0
- package/dist/live.js +398 -0
- package/dist/live.js.map +1 -0
- package/dist/nip19.d.ts +98 -0
- package/dist/nip19.d.ts.map +1 -0
- package/dist/nip19.js +320 -0
- package/dist/nip19.js.map +1 -0
- package/dist/nip98.d.ts +61 -0
- package/dist/nip98.d.ts.map +1 -0
- package/dist/nip98.js +134 -0
- package/dist/nip98.js.map +1 -0
- package/dist/sign.d.ts +67 -0
- package/dist/sign.d.ts.map +1 -0
- package/dist/sign.js +58 -0
- package/dist/sign.js.map +1 -0
- package/dist/subscriptions.d.ts +120 -0
- package/dist/subscriptions.d.ts.map +1 -0
- package/dist/subscriptions.js +68 -0
- package/dist/subscriptions.js.map +1 -0
- package/package.json +59 -0
- package/src/bridge.ts +198 -0
- package/src/events.ts +821 -0
- package/src/index.ts +159 -0
- package/src/live.ts +536 -0
- package/src/nip19.ts +354 -0
- package/src/nip98.ts +164 -0
- package/src/sign.ts +113 -0
- package/src/subscriptions.ts +200 -0
package/dist/live.js
ADDED
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One live relay socket, with NIP-42 AUTH and reconnect (PEE-5).
|
|
3
|
+
*
|
|
4
|
+
* A WebSocket that stays open, authenticates as the viewer, and keeps
|
|
5
|
+
* subscriptions alive across disconnects. Nothing is *interpreted* here: this
|
|
6
|
+
* delivers frames, and folding them into state is the consuming app's business.
|
|
7
|
+
*
|
|
8
|
+
* The socket belongs in the **client**, not in a backend: a request-scoped
|
|
9
|
+
* server runtime cannot hold one, and more importantly the viewer's own
|
|
10
|
+
* credential is the only thing that can see the viewer's channels. Buzz gates
|
|
11
|
+
* reads per channel (`is_member_cached`), so a service identity would need
|
|
12
|
+
* membership in every conversation — a product decision, not an implementation
|
|
13
|
+
* detail.
|
|
14
|
+
*
|
|
15
|
+
* **This was built inside Peek** (PEE-5, PEE-6) because Gate 2 had not happened
|
|
16
|
+
* when it was due, and it was Peek-only for two days. SHA-3 is the ticket that
|
|
17
|
+
* owed the move; `subscriptions.ts` beside this file is PEE-6's half.
|
|
18
|
+
*
|
|
19
|
+
* No nostr library. Raw `WebSocket` plus `buildUnsignedRelayAuthEvent` is
|
|
20
|
+
* enough, and the tag layout stays in one place.
|
|
21
|
+
*
|
|
22
|
+
* ## Three things the relay does that shape this file
|
|
23
|
+
*
|
|
24
|
+
* All three were read out of `crates/buzz-*` rather than assumed, because each
|
|
25
|
+
* one fails as a healthy-looking socket that delivers nothing.
|
|
26
|
+
*
|
|
27
|
+
* 1. **A second AUTH on an authenticated connection is refused.** `handle_auth`
|
|
28
|
+
* matches on `AuthState::{Pending, Authenticated, Failed}` and answers
|
|
29
|
+
* anything but `Pending` with `OK … false "auth-required: already
|
|
30
|
+
* authenticated"`. So re-authenticating in place is not possible, and
|
|
31
|
+
* {@link LiveRelay} never tries.
|
|
32
|
+
*
|
|
33
|
+
* 2. **A failed AUTH poisons the connection and leaves it open.** Only a *ban*
|
|
34
|
+
* closes the socket; a verification failure sets `AuthState::Failed` and
|
|
35
|
+
* returns. Every later REQ is answered `CLOSED … "auth-required:
|
|
36
|
+
* authenticate before subscribing"`, forever, on a socket whose readyState
|
|
37
|
+
* is OPEN. Treating an AUTH refusal as fatal-for-this-socket and reconnecting
|
|
38
|
+
* is the only way out.
|
|
39
|
+
*
|
|
40
|
+
* 3. **The `relay` tag is bound to the connection's host**, not the deployment
|
|
41
|
+
* URL — see `relayAuthUrl`.
|
|
42
|
+
*
|
|
43
|
+
* ## Token rotation needs nothing here, and that is worth stating
|
|
44
|
+
*
|
|
45
|
+
* PEE-5 asked for re-authentication when the app renews its access token,
|
|
46
|
+
* preferring it to a reconnect. Neither is needed, and the first is impossible
|
|
47
|
+
* (point 1 above).
|
|
48
|
+
*
|
|
49
|
+
* The relay authenticates a **pubkey**, by verifying a Schnorr signature. It
|
|
50
|
+
* never sees the Estiva ID access token and has no idea one exists. Renewal
|
|
51
|
+
* issues a new token for the *same* keypair, so nothing the relay checked has
|
|
52
|
+
* changed and the connection stays valid. The token is needed only to *sign* a
|
|
53
|
+
* fresh 22242, which happens on the next connect.
|
|
54
|
+
*
|
|
55
|
+
* What genuinely does not propagate is offboarding: a person whose Estiva ID
|
|
56
|
+
* access is revoked keeps an already-authenticated socket until it drops. That
|
|
57
|
+
* is the relay's session model — its own ban gate is the control for it — and
|
|
58
|
+
* re-authenticating on a timer would not have fixed it either, since a banned
|
|
59
|
+
* pubkey is caught at connect.
|
|
60
|
+
*
|
|
61
|
+
* ## Never logged, never persisted
|
|
62
|
+
*
|
|
63
|
+
* The AUTH event and the access token appear in no log line. Buzz refuses to
|
|
64
|
+
* store kind:22242 for this reason, and Convex surfaces function arguments in
|
|
65
|
+
* its dashboard logs — which is the entire reason Peek's credential lives in the
|
|
66
|
+
* browser. {@link LiveRelayOptions.log} receives states and reasons, never
|
|
67
|
+
* events or credentials, and this module must keep it that way.
|
|
68
|
+
*/
|
|
69
|
+
import { buildUnsignedRelayAuthEvent, } from './events.js';
|
|
70
|
+
/** How many consecutive AUTH refusals before giving up rather than looping. */
|
|
71
|
+
const MAX_AUTH_FAILURES = 3;
|
|
72
|
+
/** `https://` → `wss://`, `http://` → `ws://`; a `ws`-scheme URL is left alone. */
|
|
73
|
+
export function toWebSocketUrl(url) {
|
|
74
|
+
const trimmed = url.trim().replace(/\/+$/, '');
|
|
75
|
+
if (trimmed.startsWith('wss://') || trimmed.startsWith('ws://'))
|
|
76
|
+
return trimmed;
|
|
77
|
+
if (trimmed.startsWith('https://'))
|
|
78
|
+
return `wss://${trimmed.slice('https://'.length)}`;
|
|
79
|
+
if (trimmed.startsWith('http://'))
|
|
80
|
+
return `ws://${trimmed.slice('http://'.length)}`;
|
|
81
|
+
return `wss://${trimmed}`;
|
|
82
|
+
}
|
|
83
|
+
export function parseFrame(raw) {
|
|
84
|
+
if (typeof raw !== 'string')
|
|
85
|
+
return { type: 'OTHER' };
|
|
86
|
+
let parsed;
|
|
87
|
+
try {
|
|
88
|
+
parsed = JSON.parse(raw);
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
return { type: 'OTHER' };
|
|
92
|
+
}
|
|
93
|
+
if (!Array.isArray(parsed) || typeof parsed[0] !== 'string')
|
|
94
|
+
return { type: 'OTHER' };
|
|
95
|
+
switch (parsed[0]) {
|
|
96
|
+
case 'AUTH':
|
|
97
|
+
return typeof parsed[1] === 'string'
|
|
98
|
+
? { type: 'AUTH', challenge: parsed[1] }
|
|
99
|
+
: { type: 'OTHER' };
|
|
100
|
+
case 'OK':
|
|
101
|
+
return typeof parsed[1] === 'string' && typeof parsed[2] === 'boolean'
|
|
102
|
+
? {
|
|
103
|
+
type: 'OK',
|
|
104
|
+
eventId: parsed[1],
|
|
105
|
+
accepted: parsed[2],
|
|
106
|
+
message: typeof parsed[3] === 'string' ? parsed[3] : '',
|
|
107
|
+
}
|
|
108
|
+
: { type: 'OTHER' };
|
|
109
|
+
case 'EVENT':
|
|
110
|
+
return typeof parsed[1] === 'string' && parsed[2] && typeof parsed[2] === 'object'
|
|
111
|
+
? { type: 'EVENT', subId: parsed[1], event: parsed[2] }
|
|
112
|
+
: { type: 'OTHER' };
|
|
113
|
+
case 'EOSE':
|
|
114
|
+
return typeof parsed[1] === 'string' ? { type: 'EOSE', subId: parsed[1] } : { type: 'OTHER' };
|
|
115
|
+
case 'CLOSED':
|
|
116
|
+
return typeof parsed[1] === 'string'
|
|
117
|
+
? {
|
|
118
|
+
type: 'CLOSED',
|
|
119
|
+
subId: parsed[1],
|
|
120
|
+
message: typeof parsed[2] === 'string' ? parsed[2] : '',
|
|
121
|
+
}
|
|
122
|
+
: { type: 'OTHER' };
|
|
123
|
+
case 'NOTICE':
|
|
124
|
+
return typeof parsed[1] === 'string'
|
|
125
|
+
? { type: 'NOTICE', message: parsed[1] }
|
|
126
|
+
: { type: 'OTHER' };
|
|
127
|
+
default:
|
|
128
|
+
return { type: 'OTHER' };
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
export function createLiveRelay(options) {
|
|
132
|
+
const wsUrl = toWebSocketUrl(options.url);
|
|
133
|
+
const now = options.now ?? (() => Date.now());
|
|
134
|
+
const setTimer = options.setTimer ?? ((fn, ms) => setTimeout(fn, ms));
|
|
135
|
+
const clearTimer = options.clearTimer ?? ((h) => clearTimeout(h));
|
|
136
|
+
const makeSocket = options.socketFactory ?? ((url) => new WebSocket(url));
|
|
137
|
+
const backoff = options.backoff ?? { baseMs: 1_000, maxMs: 30_000, jitter: () => Math.random() };
|
|
138
|
+
const log = options.log ?? (() => { });
|
|
139
|
+
const subscriptions = new Map();
|
|
140
|
+
let socket = null;
|
|
141
|
+
let state = 'connecting';
|
|
142
|
+
let attempt = 0;
|
|
143
|
+
let authFailures = 0;
|
|
144
|
+
let stopped = false;
|
|
145
|
+
let reconnectTimer = null;
|
|
146
|
+
/** The id of the AUTH event in flight, so its `OK` is distinguishable. */
|
|
147
|
+
let pendingAuthEventId = null;
|
|
148
|
+
let nextSubId = 0;
|
|
149
|
+
function setState(next) {
|
|
150
|
+
if (state === next)
|
|
151
|
+
return;
|
|
152
|
+
state = next;
|
|
153
|
+
options.onState?.(next);
|
|
154
|
+
}
|
|
155
|
+
function send(frame) {
|
|
156
|
+
try {
|
|
157
|
+
socket?.send(JSON.stringify(frame));
|
|
158
|
+
}
|
|
159
|
+
catch (error) {
|
|
160
|
+
// A send on a socket the browser has already torn down. The close
|
|
161
|
+
// handler is what recovers; swallowing here keeps that the only path.
|
|
162
|
+
log('send failed', { reason: error.message });
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
function openSubscription(sub) {
|
|
166
|
+
send(['REQ', sub.id, ...sub.filters]);
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Tear the socket down and schedule another attempt.
|
|
170
|
+
*
|
|
171
|
+
* `fatal` is for authentication refusals, which reconnecting cannot fix past
|
|
172
|
+
* a point — see {@link MAX_AUTH_FAILURES}.
|
|
173
|
+
*/
|
|
174
|
+
function scheduleReconnect(reason) {
|
|
175
|
+
if (stopped)
|
|
176
|
+
return;
|
|
177
|
+
if (socket) {
|
|
178
|
+
// Drop the handlers before closing so our own `onclose` does not fire and
|
|
179
|
+
// schedule a second reconnect on top of this one.
|
|
180
|
+
socket.onopen = socket.onmessage = socket.onclose = socket.onerror = null;
|
|
181
|
+
try {
|
|
182
|
+
socket.close();
|
|
183
|
+
}
|
|
184
|
+
catch {
|
|
185
|
+
// Already closing. Nothing to recover.
|
|
186
|
+
}
|
|
187
|
+
socket = null;
|
|
188
|
+
}
|
|
189
|
+
pendingAuthEventId = null;
|
|
190
|
+
if (authFailures >= MAX_AUTH_FAILURES) {
|
|
191
|
+
setState('failed');
|
|
192
|
+
log('giving up after repeated auth refusals', { authFailures, reason });
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
setState('reconnecting');
|
|
196
|
+
const delay = Math.min(backoff.maxMs, backoff.baseMs * 2 ** attempt) * (0.5 + backoff.jitter() / 2);
|
|
197
|
+
attempt += 1;
|
|
198
|
+
log('reconnecting', { reason, delayMs: Math.round(delay), attempt });
|
|
199
|
+
reconnectTimer = setTimer(() => {
|
|
200
|
+
reconnectTimer = null;
|
|
201
|
+
connect();
|
|
202
|
+
}, delay);
|
|
203
|
+
}
|
|
204
|
+
async function answerChallenge(challenge) {
|
|
205
|
+
const credential = options.getCredential();
|
|
206
|
+
if (!credential) {
|
|
207
|
+
// Not signed in. Not an auth *failure* — there is nothing to sign with,
|
|
208
|
+
// and a session may yet appear, so this does not count toward the cap.
|
|
209
|
+
log('no credential; deferring auth');
|
|
210
|
+
scheduleReconnect('no credential');
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
setState('authenticating');
|
|
214
|
+
try {
|
|
215
|
+
const unsigned = buildUnsignedRelayAuthEvent({
|
|
216
|
+
// Left empty deliberately: `/sign` overwrites it with the token's
|
|
217
|
+
// subject, and `expectedPubkey` below is the check that it matched.
|
|
218
|
+
pubkey: '',
|
|
219
|
+
relayUrl: wsUrl,
|
|
220
|
+
challenge,
|
|
221
|
+
nowMs: now(),
|
|
222
|
+
});
|
|
223
|
+
// `expectedPubkey` is not a request — `/sign` signs as the token's
|
|
224
|
+
// subject whatever it is handed, so a mismatch returns HTTP 200 with a
|
|
225
|
+
// valid event authored by somebody else. Passing it is the only thing
|
|
226
|
+
// that catches that, and `bridge.ts` says not to drop it.
|
|
227
|
+
const signed = await options.sign(unsigned, credential.accessToken, credential.pubkey);
|
|
228
|
+
if (stopped || !socket)
|
|
229
|
+
return;
|
|
230
|
+
pendingAuthEventId = signed.id;
|
|
231
|
+
send(['AUTH', signed]);
|
|
232
|
+
}
|
|
233
|
+
catch (error) {
|
|
234
|
+
// Signing failed: an expired token, /sign refusing the kind, the network.
|
|
235
|
+
// Not counted as an auth refusal — the relay never saw anything, and the
|
|
236
|
+
// common cause (a token that just expired) fixes itself on reconnect.
|
|
237
|
+
log('could not sign the auth challenge', { reason: error.message });
|
|
238
|
+
scheduleReconnect('sign failed');
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
function onAuthResult(frame) {
|
|
242
|
+
pendingAuthEventId = null;
|
|
243
|
+
if (!frame.accepted) {
|
|
244
|
+
// The connection is now `AuthState::Failed` relay-side and will refuse
|
|
245
|
+
// every REQ while staying open. There is no recovery on this socket.
|
|
246
|
+
authFailures += 1;
|
|
247
|
+
log('relay refused the auth event', { reason: frame.message, authFailures });
|
|
248
|
+
scheduleReconnect('auth refused');
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
authFailures = 0;
|
|
252
|
+
attempt = 0;
|
|
253
|
+
setState('live');
|
|
254
|
+
log('authenticated', { subscriptions: subscriptions.size });
|
|
255
|
+
// Re-issue every live subscription. A reconnect that restores the socket
|
|
256
|
+
// and not the subscriptions is the silent half of this failure: the app
|
|
257
|
+
// looks connected and never hears anything again.
|
|
258
|
+
for (const sub of subscriptions.values())
|
|
259
|
+
openSubscription(sub);
|
|
260
|
+
}
|
|
261
|
+
function onFrame(raw) {
|
|
262
|
+
const frame = parseFrame(raw);
|
|
263
|
+
switch (frame.type) {
|
|
264
|
+
case 'AUTH':
|
|
265
|
+
void answerChallenge(frame.challenge);
|
|
266
|
+
return;
|
|
267
|
+
case 'OK':
|
|
268
|
+
if (pendingAuthEventId && frame.eventId === pendingAuthEventId)
|
|
269
|
+
onAuthResult(frame);
|
|
270
|
+
return;
|
|
271
|
+
case 'EVENT':
|
|
272
|
+
subscriptions.get(frame.subId)?.onEvent(frame.event);
|
|
273
|
+
return;
|
|
274
|
+
case 'EOSE':
|
|
275
|
+
subscriptions.get(frame.subId)?.onEose?.();
|
|
276
|
+
return;
|
|
277
|
+
case 'CLOSED': {
|
|
278
|
+
const sub = subscriptions.get(frame.subId);
|
|
279
|
+
log('subscription closed by the relay', { subId: frame.subId, reason: frame.message });
|
|
280
|
+
sub?.onClosed?.(frame.message);
|
|
281
|
+
// `auth-required` here means the connection is unauthenticated — the
|
|
282
|
+
// poisoned-but-open state. Reconnecting is the only fix, and dropping
|
|
283
|
+
// the subscription would hide it.
|
|
284
|
+
if (frame.message.startsWith('auth-required'))
|
|
285
|
+
scheduleReconnect('req refused');
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
case 'NOTICE':
|
|
289
|
+
log('relay notice', { message: frame.message });
|
|
290
|
+
return;
|
|
291
|
+
default:
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
function connect() {
|
|
296
|
+
if (stopped)
|
|
297
|
+
return;
|
|
298
|
+
setState(attempt === 0 ? 'connecting' : 'reconnecting');
|
|
299
|
+
let created;
|
|
300
|
+
try {
|
|
301
|
+
created = makeSocket(wsUrl);
|
|
302
|
+
}
|
|
303
|
+
catch (error) {
|
|
304
|
+
log('could not open a socket', { reason: error.message });
|
|
305
|
+
scheduleReconnect('open threw');
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
socket = created;
|
|
309
|
+
created.onopen = () => {
|
|
310
|
+
// Nothing to do but wait: Buzz sends `["AUTH", challenge]` immediately on
|
|
311
|
+
// connect, so authentication starts from the message handler.
|
|
312
|
+
log('socket open');
|
|
313
|
+
};
|
|
314
|
+
created.onmessage = (ev) => {
|
|
315
|
+
if (socket !== created)
|
|
316
|
+
return;
|
|
317
|
+
onFrame(ev.data);
|
|
318
|
+
};
|
|
319
|
+
created.onerror = () => {
|
|
320
|
+
// `onclose` always follows, and that is where recovery lives. Logging
|
|
321
|
+
// here only helps distinguish a refused connection from a clean drop.
|
|
322
|
+
log('socket error');
|
|
323
|
+
};
|
|
324
|
+
created.onclose = () => {
|
|
325
|
+
if (socket !== created)
|
|
326
|
+
return;
|
|
327
|
+
socket = null;
|
|
328
|
+
scheduleReconnect('socket closed');
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
connect();
|
|
332
|
+
return {
|
|
333
|
+
subscribe(filters, onEvent, subOptions) {
|
|
334
|
+
const id = `${options.subscriptionPrefix ?? 'sub'}-${nextSubId++}`;
|
|
335
|
+
const sub = {
|
|
336
|
+
id,
|
|
337
|
+
filters,
|
|
338
|
+
onEvent,
|
|
339
|
+
onEose: subOptions?.onEose,
|
|
340
|
+
onClosed: subOptions?.onClosed,
|
|
341
|
+
};
|
|
342
|
+
subscriptions.set(id, sub);
|
|
343
|
+
if (state === 'live')
|
|
344
|
+
openSubscription(sub);
|
|
345
|
+
return {
|
|
346
|
+
close() {
|
|
347
|
+
if (!subscriptions.delete(id))
|
|
348
|
+
return;
|
|
349
|
+
if (state === 'live')
|
|
350
|
+
send(['CLOSE', id]);
|
|
351
|
+
},
|
|
352
|
+
};
|
|
353
|
+
},
|
|
354
|
+
reconnect() {
|
|
355
|
+
if (stopped)
|
|
356
|
+
return;
|
|
357
|
+
if (reconnectTimer !== null) {
|
|
358
|
+
clearTimer(reconnectTimer);
|
|
359
|
+
reconnectTimer = null;
|
|
360
|
+
}
|
|
361
|
+
// Reset the backoff: this is not another failed attempt in a series, it
|
|
362
|
+
// is new information that the network changed.
|
|
363
|
+
attempt = 0;
|
|
364
|
+
if (socket) {
|
|
365
|
+
socket.onopen = socket.onmessage = socket.onclose = socket.onerror = null;
|
|
366
|
+
try {
|
|
367
|
+
socket.close();
|
|
368
|
+
}
|
|
369
|
+
catch {
|
|
370
|
+
// Already gone.
|
|
371
|
+
}
|
|
372
|
+
socket = null;
|
|
373
|
+
}
|
|
374
|
+
pendingAuthEventId = null;
|
|
375
|
+
connect();
|
|
376
|
+
},
|
|
377
|
+
state: () => state,
|
|
378
|
+
close() {
|
|
379
|
+
stopped = true;
|
|
380
|
+
if (reconnectTimer !== null) {
|
|
381
|
+
clearTimer(reconnectTimer);
|
|
382
|
+
reconnectTimer = null;
|
|
383
|
+
}
|
|
384
|
+
subscriptions.clear();
|
|
385
|
+
if (socket) {
|
|
386
|
+
socket.onopen = socket.onmessage = socket.onclose = socket.onerror = null;
|
|
387
|
+
try {
|
|
388
|
+
socket.close();
|
|
389
|
+
}
|
|
390
|
+
catch {
|
|
391
|
+
// Already gone.
|
|
392
|
+
}
|
|
393
|
+
socket = null;
|
|
394
|
+
}
|
|
395
|
+
},
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
//# sourceMappingURL=live.js.map
|
package/dist/live.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"live.js","sourceRoot":"","sources":["../src/live.ts"],"names":[],"mappings":"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"}
|
package/dist/nip19.d.ts
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/** Regroup bytes between bit widths, e.g. 8-bit bytes → 5-bit bech32 symbols. */
|
|
2
|
+
export declare function convertBits(data: ArrayLike<number>, from: number, to: number, pad: boolean): number[];
|
|
3
|
+
/**
|
|
4
|
+
* Exported for the bare NIP-19 types (`npub`, `note`) and for tests.
|
|
5
|
+
*
|
|
6
|
+
* The checksum layer is the part worth testing directly: a wrong constant still
|
|
7
|
+
* round-trips against itself, so only an external vector catches it.
|
|
8
|
+
*
|
|
9
|
+
* Strict about case, deliberately — BIP-173 forbids mixing. `decodeNaddr` is the
|
|
10
|
+
* forgiving entry point, because what reaches it was typed or pasted by a person.
|
|
11
|
+
*/
|
|
12
|
+
export declare function bech32Encode(hrp: string, data: number[]): string;
|
|
13
|
+
export declare function bech32Decode(encoded: string): {
|
|
14
|
+
hrp: string;
|
|
15
|
+
data: number[];
|
|
16
|
+
};
|
|
17
|
+
/** A decoded `naddr` — everything needed to fetch the event it points at. */
|
|
18
|
+
export interface AddressPointer {
|
|
19
|
+
/** The `d` tag of the addressable event. */
|
|
20
|
+
identifier: string;
|
|
21
|
+
pubkey: string;
|
|
22
|
+
kind: number;
|
|
23
|
+
/** Relay hints, in the order they appeared. May be empty. */
|
|
24
|
+
relays: string[];
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Encode an address as `naddr1…`.
|
|
28
|
+
*
|
|
29
|
+
* TLV order is identifier, relays, author, kind — see the header on why that is
|
|
30
|
+
* a choice rather than a rule.
|
|
31
|
+
*/
|
|
32
|
+
export declare function encodeNaddr(pointer: AddressPointer): string;
|
|
33
|
+
/**
|
|
34
|
+
* Decode `naddr1…`, with or without a `nostr:` prefix, in any case.
|
|
35
|
+
*
|
|
36
|
+
* Forgiving on purpose: what arrives here was pasted by a person, sometimes out
|
|
37
|
+
* of an email client that capitalised the first letter. `bech32Decode` is the
|
|
38
|
+
* strict primitive underneath — this lowercases first, so a mixed-case string
|
|
39
|
+
* that would be refused there is accepted here.
|
|
40
|
+
*/
|
|
41
|
+
export declare function decodeNaddr(encoded: string): AddressPointer;
|
|
42
|
+
/** `<kind>:<pubkey>:<d>` — the form used in `a` tags and relay filters. */
|
|
43
|
+
export declare function pointerToAddress(pointer: AddressPointer): string;
|
|
44
|
+
/**
|
|
45
|
+
* The inverse: `<kind>:<pubkey>:<d>` back to a pointer.
|
|
46
|
+
*
|
|
47
|
+
* An address carries no relay hints — `naddr` has a TLV for them and an `a` tag
|
|
48
|
+
* does not — so the relays come back empty. That is a real loss of information,
|
|
49
|
+
* not an oversight: it is why the two forms are not interchangeable and why the
|
|
50
|
+
* encoder is not simply run in reverse.
|
|
51
|
+
*
|
|
52
|
+
* The `d` identifier may itself contain colons, so only the first two are
|
|
53
|
+
* separators.
|
|
54
|
+
*/
|
|
55
|
+
export declare function addressToPointer(address: string): AddressPointer;
|
|
56
|
+
/** `<kind>:<pubkey>:<d>` → `naddr1…`. */
|
|
57
|
+
export declare function addrToNaddr(address: string, relays?: string[]): string;
|
|
58
|
+
/** `naddr1…` → `<kind>:<pubkey>:<d>`. */
|
|
59
|
+
export declare function naddrToAddr(encoded: string): string;
|
|
60
|
+
/**
|
|
61
|
+
* A pointer from *either* form a reference arrives in.
|
|
62
|
+
*
|
|
63
|
+
* A message composed in an app carries `nostr:naddr1…` in its body. The same
|
|
64
|
+
* message read back off the relay carries the same reference as an `a` tag,
|
|
65
|
+
* which is a plain `<kind>:<pubkey>:<d>` address — that is what the NIP says a
|
|
66
|
+
* tag holds.
|
|
67
|
+
*
|
|
68
|
+
* Both name one object. Accepting only the first is what made a reference stop
|
|
69
|
+
* rendering the moment its own message came back from the relay (FEE-2).
|
|
70
|
+
*/
|
|
71
|
+
export declare function referenceToPointer(input: string): AddressPointer;
|
|
72
|
+
/**
|
|
73
|
+
* Every `nostr:naddr1…` in a body of text (NIP-27).
|
|
74
|
+
*
|
|
75
|
+
* The character class is bech32's own alphabet, which excludes `1`, `b`, `i`
|
|
76
|
+
* and `o`, so a match ends cleanly at punctuation without a lookahead.
|
|
77
|
+
*/
|
|
78
|
+
export declare const NADDR_RE: RegExp;
|
|
79
|
+
export declare function findNaddrs(text: string): string[];
|
|
80
|
+
/**
|
|
81
|
+
* The same text with every `nostr:naddr1…` taken out (PEEK-18).
|
|
82
|
+
*
|
|
83
|
+
* A reference that resolves into a widget should not also sit in the prose as
|
|
84
|
+
* sixty characters of bech32: the widget *is* the reference, rendered. Ship
|
|
85
|
+
* appends one to every thread it starts about an issue, so leaving it in means
|
|
86
|
+
* most cross-app messages open with a wall of noise nobody reads.
|
|
87
|
+
*
|
|
88
|
+
* Whitespace is repaired rather than merely removed. A pointer is usually
|
|
89
|
+
* trailing or on a line of its own, and deleting it in place otherwise leaves a
|
|
90
|
+
* double space mid-sentence or a hole between paragraphs — both of which look
|
|
91
|
+
* like the message itself is broken. Runs of blanks collapse *within* a line
|
|
92
|
+
* only, so indentation and paragraph breaks survive.
|
|
93
|
+
*
|
|
94
|
+
* Display-only. The stored body keeps the pointer, which is what lets the
|
|
95
|
+
* reference still be found, resolved and followed.
|
|
96
|
+
*/
|
|
97
|
+
export declare function stripNaddrs(text: string): string;
|
|
98
|
+
//# sourceMappingURL=nip19.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nip19.d.ts","sourceRoot":"","sources":["../src/nip19.ts"],"names":[],"mappings":"AAkFA,iFAAiF;AACjF,wBAAgB,WAAW,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,MAAM,EAAE,CAqBrG;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAGhE;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,CAgB7E;AAED,6EAA6E;AAC7E,MAAM,WAAW,cAAc;IAC7B,4CAA4C;IAC5C,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,6DAA6D;IAC7D,MAAM,EAAE,MAAM,EAAE,CAAA;CACjB;AAWD;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,CA8B3D;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,CAyC3D;AAED,2EAA2E;AAC3E,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,CAEhE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,CAWhE;AAED,yCAAyC;AACzC,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,EAAO,GAAG,MAAM,CAG1E;AAED,yCAAyC;AACzC,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,CAKhE;AAED;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,QAAwD,CAAA;AAE7E,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAEjD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAoBhD"}
|