@solarpunkltd/swarm-chat-js 7.2.0 → 8.0.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/README.md +119 -24
- package/dist/chat.d.ts +10 -3
- package/dist/events.d.ts +9 -5
- package/dist/follower.d.ts +17 -5
- package/dist/index.cjs +1 -1
- package/dist/index.js +149 -110
- package/dist/message/binding.d.ts +48 -0
- package/dist/message/canonicalSignature.d.ts +6 -0
- package/dist/message/entry.d.ts +25 -6
- package/dist/message/index.d.ts +2 -0
- package/dist/message/message.d.ts +60 -14
- package/dist/message/ownFeed.d.ts +9 -0
- package/dist/message-Bmwh3SCs.cjs +3 -0
- package/dist/message-Dbh8qrpg.js +455 -0
- package/dist/message.cjs +1 -1
- package/dist/message.js +2 -308
- package/dist/notes.d.ts +8 -1
- package/dist/pacer.d.ts +31 -0
- package/dist/sender.d.ts +11 -4
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Bee as
|
|
1
|
+
import { A as e, B as t, C as n, D as r, E as i, F as a, H as o, I as s, L as c, M as l, N as ee, O as u, P as d, R as f, S as p, T as m, V as te, _ as ne, a as re, b as ie, c as h, d as g, f as _, g as v, h as y, i as ae, j as oe, k as b, l as x, m as S, n as C, o as w, p as T, r as E, s as D, t as O, u as k, v as A, w as se, x as ce, y as j, z as M } from "./message-Dbh8qrpg.js";
|
|
2
|
+
import { Bee as N, BeeResponseError as P, Identifier as F, PrivateKey as I, Topic as L } from "@ethersphere/bee-js";
|
|
3
3
|
//#region src/events.ts
|
|
4
|
-
var
|
|
4
|
+
var R = {
|
|
5
5
|
LOADING_INIT: "loadingInit",
|
|
6
6
|
LOADING_PREVIOUS_MESSAGES: "loadingPreviousMessages",
|
|
7
7
|
MESSAGE_RECEIVED: "messageReceived",
|
|
@@ -13,13 +13,13 @@ var I = {
|
|
|
13
13
|
MESSAGE_SKIPPED: "messageSkipped",
|
|
14
14
|
ERROR: "error"
|
|
15
15
|
};
|
|
16
|
-
function
|
|
17
|
-
return
|
|
16
|
+
function z(e) {
|
|
17
|
+
return V(e, -1, e.ts);
|
|
18
18
|
}
|
|
19
|
-
function
|
|
20
|
-
return
|
|
19
|
+
function B(e) {
|
|
20
|
+
return V(e.msg, e.seq, e.at);
|
|
21
21
|
}
|
|
22
|
-
function
|
|
22
|
+
function V(e, t, n) {
|
|
23
23
|
return {
|
|
24
24
|
id: e.id,
|
|
25
25
|
type: e.type,
|
|
@@ -28,13 +28,11 @@ function z(e, t, n) {
|
|
|
28
28
|
address: e.addr,
|
|
29
29
|
timestamp: n,
|
|
30
30
|
...e.target ? { targetMessageId: e.target } : {},
|
|
31
|
-
chatTopic: e.topic,
|
|
32
|
-
signature: e.sig,
|
|
33
31
|
index: t,
|
|
34
|
-
|
|
32
|
+
signedMessage: e
|
|
35
33
|
};
|
|
36
34
|
}
|
|
37
|
-
var
|
|
35
|
+
var H = class {
|
|
38
36
|
constructor() {
|
|
39
37
|
this.listeners = /* @__PURE__ */ new Map(), this.on = (e, t) => {
|
|
40
38
|
this.listeners.set(e, [...this.listeners.get(e) ?? [], t]);
|
|
@@ -51,67 +49,92 @@ var B = class {
|
|
|
51
49
|
console.error(`a listener for ${e} threw`, t);
|
|
52
50
|
}
|
|
53
51
|
}
|
|
54
|
-
},
|
|
52
|
+
}, U = 2e4, W = class {
|
|
53
|
+
constructor(e, t) {
|
|
54
|
+
this.spacingMs = e, this.now = t, this.missedAt = /* @__PURE__ */ new Map();
|
|
55
|
+
}
|
|
56
|
+
readableAt(e, t = this.now()) {
|
|
57
|
+
let n = this.missedAt.get(e);
|
|
58
|
+
return n === void 0 || this.expired(n, t) ? -Infinity : n + this.spacingMs;
|
|
59
|
+
}
|
|
60
|
+
mayRead(e, t = this.now()) {
|
|
61
|
+
return t >= this.readableAt(e, t);
|
|
62
|
+
}
|
|
63
|
+
missed(e, t = this.now()) {
|
|
64
|
+
for (let [e, n] of this.missedAt) this.expired(n, t) && this.missedAt.delete(e);
|
|
65
|
+
this.missedAt.set(e, t);
|
|
66
|
+
}
|
|
67
|
+
found(e) {
|
|
68
|
+
this.missedAt.delete(e);
|
|
69
|
+
}
|
|
70
|
+
clear() {
|
|
71
|
+
this.missedAt.clear();
|
|
72
|
+
}
|
|
73
|
+
expired(e, t) {
|
|
74
|
+
return e > t || t - e >= this.spacingMs;
|
|
75
|
+
}
|
|
76
|
+
}, G = class extends Error {
|
|
55
77
|
constructor(e) {
|
|
56
78
|
super("the feed head lookup did not answer in time", e), this.name = "HeadLookupTimeoutError";
|
|
57
79
|
}
|
|
58
|
-
},
|
|
80
|
+
}, K = class extends Error {
|
|
59
81
|
constructor(e, t) {
|
|
60
82
|
super(`feed slot ${e} was served but could not be read`, t), this.index = e, this.name = "UnreadableSlotError";
|
|
61
83
|
}
|
|
62
84
|
};
|
|
63
|
-
function
|
|
64
|
-
return e instanceof
|
|
85
|
+
function q(e) {
|
|
86
|
+
return e instanceof P && (e.status === 404 || e.status === 500);
|
|
65
87
|
}
|
|
66
|
-
async function
|
|
88
|
+
async function J(e, t) {
|
|
67
89
|
try {
|
|
68
90
|
return await t();
|
|
69
91
|
} catch (t) {
|
|
70
|
-
if (
|
|
71
|
-
throw t instanceof
|
|
92
|
+
if (q(t)) return null;
|
|
93
|
+
throw t instanceof P ? t : new K(e, { cause: t });
|
|
72
94
|
}
|
|
73
95
|
}
|
|
74
|
-
function
|
|
75
|
-
let
|
|
96
|
+
function le(e, t, n, r, i = C) {
|
|
97
|
+
let a = L.fromString(n), o = (n) => e.feed.makeReader(a, t, Y(n));
|
|
76
98
|
return {
|
|
77
|
-
readNote: (
|
|
78
|
-
readSlot: (e) =>
|
|
99
|
+
readNote: (a) => J(a, async () => (await e.soc.makeReader(t, Y(r.slotReadMs)).download(D(n, i, a))).payload.toUint8Array()),
|
|
100
|
+
readSlot: (e) => J(e, async () => (await o(r.slotReadMs).downloadPayload({ index: e })).payload.toUint8Array()),
|
|
79
101
|
async readHead() {
|
|
80
|
-
let n =
|
|
102
|
+
let n = Y(r.feedReadMs);
|
|
81
103
|
try {
|
|
82
|
-
let { payload: r, feedIndex: i } = await e.feed.makeReader(
|
|
104
|
+
let { payload: r, feedIndex: i } = await e.feed.makeReader(a, t, n).downloadPayload();
|
|
83
105
|
return {
|
|
84
106
|
index: Number(i.toBigInt()),
|
|
85
107
|
payload: r.toUint8Array()
|
|
86
108
|
};
|
|
87
109
|
} catch (e) {
|
|
88
|
-
if (
|
|
89
|
-
throw n.signal?.aborted ? new
|
|
110
|
+
if (q(e)) return null;
|
|
111
|
+
throw n.signal?.aborted ? new G({ cause: e }) : e;
|
|
90
112
|
}
|
|
91
113
|
},
|
|
92
114
|
async readFile(t) {
|
|
93
|
-
return (await e.data.download(t, void 0,
|
|
115
|
+
return (await e.data.download(t, void 0, Y(r.feedReadMs))).toUint8Array();
|
|
94
116
|
}
|
|
95
117
|
};
|
|
96
118
|
}
|
|
97
|
-
function
|
|
119
|
+
function Y(e) {
|
|
98
120
|
return { signal: AbortSignal.timeout(e) };
|
|
99
121
|
}
|
|
100
|
-
var
|
|
101
|
-
function
|
|
102
|
-
let a = new
|
|
122
|
+
var ue = "0123456789abcdef".repeat(4);
|
|
123
|
+
function de(e, t, n, r, i) {
|
|
124
|
+
let a = new I(n), o = F.fromString(r);
|
|
103
125
|
return async (n) => {
|
|
104
|
-
await e.messaging.gsocSend(t, a, o, n, { deferred: !1 },
|
|
126
|
+
await e.messaging.gsocSend(t, a, o, n, { deferred: !1 }, Y(i.writeMs));
|
|
105
127
|
};
|
|
106
128
|
}
|
|
107
129
|
//#endregion
|
|
108
130
|
//#region src/follower.ts
|
|
109
|
-
var
|
|
131
|
+
var X = {
|
|
110
132
|
LIVE: "live",
|
|
111
133
|
RECONNECTING: "reconnecting",
|
|
112
134
|
STALLED: "stalled"
|
|
113
|
-
},
|
|
135
|
+
}, fe = {
|
|
114
136
|
pollIntervalMs: 1e3,
|
|
137
|
+
missingReadSpacingMs: U,
|
|
115
138
|
maxSlotsPerPoll: 16,
|
|
116
139
|
unservedPollsBeforeProbe: 3,
|
|
117
140
|
unreadablePollsBeforeFailure: 3,
|
|
@@ -129,16 +152,16 @@ var J = {
|
|
|
129
152
|
stallAfterMs: 8e3,
|
|
130
153
|
random: Math.random,
|
|
131
154
|
now: Date.now
|
|
132
|
-
},
|
|
155
|
+
}, Z = class extends Error {
|
|
133
156
|
constructor(e) {
|
|
134
157
|
super(`the gateway keeps answering feed slot ${e} with something that is not a chunk`), this.index = e, this.name = "UnreadableGatewayError";
|
|
135
158
|
}
|
|
136
|
-
},
|
|
159
|
+
}, pe = class {
|
|
137
160
|
constructor(e, t, n, r = {}, i = null) {
|
|
138
161
|
this.source = e, this.topic = t, this.events = n, this.notes = i, this.next = 0, this.ceiling = null, this.nextNoteSlot = 0, this.lastNoteFoundAt = 0, this.unservedPolls = 0, this.nextProbeAt = 0, this.unreadablePolls = 0, this.gatewayFailures = 0, this.missed = /* @__PURE__ */ new Map(), this.timer = null, this.generation = 0, this.running = !1, this.status = null, this.settings = {
|
|
139
|
-
...
|
|
162
|
+
...fe,
|
|
140
163
|
...r
|
|
141
|
-
};
|
|
164
|
+
}, this.pacer = new W(this.settings.missingReadSpacingMs, this.settings.now);
|
|
142
165
|
}
|
|
143
166
|
get nextIndex() {
|
|
144
167
|
return this.next;
|
|
@@ -150,7 +173,7 @@ var J = {
|
|
|
150
173
|
return this.ceiling !== null;
|
|
151
174
|
}
|
|
152
175
|
start(e, t = null) {
|
|
153
|
-
this.stop(), this.next = e, this.ceiling = t?.newest ?? null, this.nextNoteSlot = t?.nextNoteSlot ?? (this.notes ? this.notes.lastReadableSlot() + 1 : 0), this.lastNoteFoundAt = this.settings.now(), this.resetRefusals(), this.unreadablePolls = 0, this.gatewayFailures = 0, this.missed.clear(), this.status = null, this.running = !0, this.schedule(0);
|
|
176
|
+
this.stop(), this.next = e, this.ceiling = t?.newest ?? null, this.nextNoteSlot = t?.nextNoteSlot ?? (this.notes ? this.notes.lastReadableSlot() + 1 : 0), this.lastNoteFoundAt = this.settings.now(), this.resetRefusals(), this.unreadablePolls = 0, this.gatewayFailures = 0, this.missed.clear(), this.pacer.clear(), this.status = null, this.running = !0, this.schedule(0);
|
|
154
177
|
}
|
|
155
178
|
stop() {
|
|
156
179
|
this.running = !1, this.generation++, this.timer &&= (clearTimeout(this.timer), null);
|
|
@@ -177,7 +200,11 @@ var J = {
|
|
|
177
200
|
}
|
|
178
201
|
}
|
|
179
202
|
untilNextRead() {
|
|
180
|
-
|
|
203
|
+
let e = this.settings.now(), t = (t) => {
|
|
204
|
+
let n = this.pacer.readableAt(t);
|
|
205
|
+
return n > e ? n : e + this.settings.pollIntervalMs;
|
|
206
|
+
}, n = [...this.missed.keys()].map(t);
|
|
207
|
+
return this.notes !== null && n.push(this.notes.readableAt(this.nextNoteSlot)), this.ceiling === null && n.push(t(this.next)), Math.max(0, Math.min(...n) - e);
|
|
181
208
|
}
|
|
182
209
|
async readDueNotes(e, t) {
|
|
183
210
|
let n = this.settings.now(), r = e.lastReadableSlot(n);
|
|
@@ -192,19 +219,24 @@ var J = {
|
|
|
192
219
|
}
|
|
193
220
|
}
|
|
194
221
|
async read(e) {
|
|
222
|
+
let t;
|
|
195
223
|
try {
|
|
196
|
-
|
|
224
|
+
t = await this.source.readSlot(e);
|
|
197
225
|
} catch (e) {
|
|
198
|
-
if (e instanceof
|
|
226
|
+
if (e instanceof K) return "unreadable";
|
|
199
227
|
throw e;
|
|
200
228
|
}
|
|
229
|
+
return t === null ? this.pacer.missed(e) : this.pacer.found(e), t;
|
|
230
|
+
}
|
|
231
|
+
async readUnnamed(e) {
|
|
232
|
+
return this.pacer.mayRead(e) ? this.read(e) : "held";
|
|
201
233
|
}
|
|
202
234
|
async walk(e) {
|
|
203
235
|
for (let t = 0; t < this.settings.maxSlotsPerPoll; t++) {
|
|
204
236
|
let n = this.next;
|
|
205
237
|
if (this.ceiling !== null && n > this.ceiling) return t;
|
|
206
|
-
let r = await this.read(n);
|
|
207
|
-
if (e !== this.generation) return t;
|
|
238
|
+
let r = this.ceiling === null ? await this.readUnnamed(n) : await this.read(n);
|
|
239
|
+
if (e !== this.generation || r === "held") return t;
|
|
208
240
|
if (this.ceiling !== null && (r === null || r === "unreadable")) {
|
|
209
241
|
this.remember(n), this.next = n + 1;
|
|
210
242
|
continue;
|
|
@@ -215,7 +247,7 @@ var J = {
|
|
|
215
247
|
this.unreadablePolls = 0;
|
|
216
248
|
continue;
|
|
217
249
|
}
|
|
218
|
-
if (this.unreadablePolls >= this.settings.unreadablePollsBeforeFailure) throw new
|
|
250
|
+
if (this.unreadablePolls >= this.settings.unreadablePollsBeforeFailure) throw new Z(n);
|
|
219
251
|
}
|
|
220
252
|
return t;
|
|
221
253
|
}
|
|
@@ -225,8 +257,8 @@ var J = {
|
|
|
225
257
|
}
|
|
226
258
|
shouldProbe() {
|
|
227
259
|
if (this.unservedPolls !== this.nextProbeAt) return !1;
|
|
228
|
-
let { probeIntervalCapMs: e, pollIntervalMs: t } = this.settings,
|
|
229
|
-
return this.nextProbeAt += Math.min(this.nextProbeAt,
|
|
260
|
+
let { probeIntervalCapMs: e, pollIntervalMs: t, missingReadSpacingMs: n } = this.settings, r = Math.max(1, Math.ceil(e / Math.max(t, n)));
|
|
261
|
+
return this.nextProbeAt += Math.min(this.nextProbeAt, r), !0;
|
|
230
262
|
}
|
|
231
263
|
resetRefusals() {
|
|
232
264
|
this.unservedPolls = 0, this.nextProbeAt = this.settings.unservedPollsBeforeProbe;
|
|
@@ -234,17 +266,17 @@ var J = {
|
|
|
234
266
|
async probePast(e, t) {
|
|
235
267
|
let n = /* @__PURE__ */ new Set([e]);
|
|
236
268
|
for (let r of this.settings.probeDistances) {
|
|
237
|
-
let i = e + r, a = await this.
|
|
269
|
+
let i = e + r, a = await this.readUnnamed(i);
|
|
238
270
|
if (t !== this.generation) return !1;
|
|
239
|
-
if (a === null || a === "unreadable") {
|
|
271
|
+
if (a === null || a === "unreadable" || a === "held") {
|
|
240
272
|
n.add(i);
|
|
241
273
|
continue;
|
|
242
274
|
}
|
|
243
275
|
this.resetRefusals(), this.remember(e);
|
|
244
276
|
for (let r = e + 1; r < i; r++) {
|
|
245
|
-
let e = n.has(r) ? null : await this.
|
|
277
|
+
let e = n.has(r) ? null : await this.readUnnamed(r);
|
|
246
278
|
if (t !== this.generation) return !1;
|
|
247
|
-
e === null || e === "unreadable" ? this.remember(r) : this.accept(r, e);
|
|
279
|
+
e === null || e === "unreadable" || e === "held" ? this.remember(r) : this.accept(r, e);
|
|
248
280
|
}
|
|
249
281
|
return this.next = i + 1, this.accept(i, a), !0;
|
|
250
282
|
}
|
|
@@ -262,7 +294,7 @@ var J = {
|
|
|
262
294
|
async readMissed(e) {
|
|
263
295
|
let t = this.settings.now();
|
|
264
296
|
for (let [e, n] of this.missed) t - n >= this.settings.missedExpiryMs && (this.missed.delete(e), this.events.skipped(e, "unreachable", "not served within the time a stepped-past slot is kept"));
|
|
265
|
-
let n = [...this.missed.keys()].slice(0, this.settings.missedReadsPerPoll);
|
|
297
|
+
let n = [...this.missed.keys()].filter((e) => this.pacer.mayRead(e, t)).slice(0, this.settings.missedReadsPerPoll);
|
|
266
298
|
for (let t of n) {
|
|
267
299
|
let n = await this.read(t);
|
|
268
300
|
if (e !== this.generation) return;
|
|
@@ -271,16 +303,16 @@ var J = {
|
|
|
271
303
|
}
|
|
272
304
|
}
|
|
273
305
|
accept(e, t) {
|
|
274
|
-
let n =
|
|
306
|
+
let n = A(t, e, this.topic);
|
|
275
307
|
n.ok ? (this.notes?.clock.observe(n.value.at, this.settings.now()), this.events.entry(n.value)) : this.events.skipped(e, n.reason, n.detail);
|
|
276
308
|
}
|
|
277
309
|
gatewayFailed(e) {
|
|
278
|
-
this.gatewayFailures++, this.setStatus(
|
|
310
|
+
this.gatewayFailures++, this.setStatus(X.RECONNECTING), this.events.error(e);
|
|
279
311
|
}
|
|
280
312
|
gatewayAnswered() {
|
|
281
313
|
this.gatewayFailures = 0;
|
|
282
314
|
let e = this.settings.now(), t = [...this.missed.values()].some((t) => e - t >= this.settings.stallAfterMs);
|
|
283
|
-
this.setStatus(t ?
|
|
315
|
+
this.setStatus(t ? X.STALLED : X.LIVE);
|
|
284
316
|
}
|
|
285
317
|
backoffMs() {
|
|
286
318
|
let { pollIntervalMs: e, backoffCapMs: t, random: n } = this.settings, r = Math.min(t, e * 2 ** this.gatewayFailures);
|
|
@@ -289,7 +321,7 @@ var J = {
|
|
|
289
321
|
setStatus(e) {
|
|
290
322
|
e !== this.status && (this.status = e, this.events.status(e));
|
|
291
323
|
}
|
|
292
|
-
},
|
|
324
|
+
}, me = 16, he = class {
|
|
293
325
|
constructor(e, t, n, r = null) {
|
|
294
326
|
this.source = e, this.topic = t, this.events = n, this.notes = r, this.older = null, this.loading = null;
|
|
295
327
|
}
|
|
@@ -334,7 +366,7 @@ var J = {
|
|
|
334
366
|
try {
|
|
335
367
|
return await this.source.readHead();
|
|
336
368
|
} catch (e) {
|
|
337
|
-
if (e instanceof
|
|
369
|
+
if (e instanceof G) return this.events.error(e), null;
|
|
338
370
|
throw e;
|
|
339
371
|
}
|
|
340
372
|
}
|
|
@@ -349,30 +381,30 @@ var J = {
|
|
|
349
381
|
async loadOlderOnce() {
|
|
350
382
|
let e = this.older;
|
|
351
383
|
if (e === null) return [];
|
|
352
|
-
let t = await this.source.readFile(e.ref), n =
|
|
384
|
+
let t = await this.source.readFile(e.ref), n = j(t, this.topic, e);
|
|
353
385
|
if (!n.ok) throw this.older = null, Error(`history file ${e.ref} refused (${n.reason}): ${n.detail}`);
|
|
354
386
|
return this.report(n.value.skipped), this.older = n.value.prev, n.value.rows;
|
|
355
387
|
}
|
|
356
388
|
async newestLink(e, t) {
|
|
357
389
|
let n = t === void 0 ? e : e - 1;
|
|
358
390
|
if (t !== void 0) {
|
|
359
|
-
let n =
|
|
391
|
+
let n = A(t, e, this.topic);
|
|
360
392
|
if (n.ok) return n.value.history;
|
|
361
393
|
}
|
|
362
|
-
for (let t = n; t >= Math.max(0, e -
|
|
394
|
+
for (let t = n; t >= Math.max(0, e - me); t--) {
|
|
363
395
|
let e = await this.source.readSlot(t).catch((e) => {
|
|
364
|
-
if (e instanceof
|
|
396
|
+
if (e instanceof K) return null;
|
|
365
397
|
throw e;
|
|
366
398
|
});
|
|
367
399
|
if (e === null) continue;
|
|
368
|
-
let n =
|
|
400
|
+
let n = A(e, t, this.topic);
|
|
369
401
|
if (n.ok) return n.value.history;
|
|
370
402
|
}
|
|
371
403
|
return null;
|
|
372
404
|
}
|
|
373
405
|
async readFile(e) {
|
|
374
406
|
try {
|
|
375
|
-
let t =
|
|
407
|
+
let t = j(await this.source.readFile(e.ref), this.topic, e);
|
|
376
408
|
return t.ok ? (this.report(t.value.skipped), this.older = t.value.prev, t.value.rows) : (this.events.error(/* @__PURE__ */ Error(`history file ${e.ref} refused (${t.reason}): ${t.detail}`)), "refused");
|
|
377
409
|
} catch (t) {
|
|
378
410
|
return this.events.error(t), this.older = e, null;
|
|
@@ -381,17 +413,18 @@ var J = {
|
|
|
381
413
|
report(e) {
|
|
382
414
|
e > 0 && this.events.skipped(e);
|
|
383
415
|
}
|
|
384
|
-
},
|
|
385
|
-
slotMs:
|
|
386
|
-
heartbeatMs:
|
|
416
|
+
}, ge = {
|
|
417
|
+
slotMs: C,
|
|
418
|
+
heartbeatMs: O,
|
|
387
419
|
marginMs: 1e3,
|
|
388
420
|
scanBatch: 4,
|
|
389
|
-
clockLimitMs: 3e5
|
|
421
|
+
clockLimitMs: 3e5,
|
|
422
|
+
missingReadSpacingMs: U
|
|
390
423
|
};
|
|
391
|
-
function
|
|
424
|
+
function _e(e) {
|
|
392
425
|
return typeof e.readNote == "function";
|
|
393
426
|
}
|
|
394
|
-
var
|
|
427
|
+
var ve = class {
|
|
395
428
|
constructor(e) {
|
|
396
429
|
this.limitMs = e, this.aheadAtMost = Infinity, this.trusted = !0;
|
|
397
430
|
}
|
|
@@ -408,21 +441,21 @@ var ue = class {
|
|
|
408
441
|
let e = Number.isFinite(this.aheadAtMost), t = this.trusted || !e ? Math.min(0, this.aheadAtMost) : this.aheadAtMost;
|
|
409
442
|
return Math.max(-this.limitMs, Math.min(this.limitMs, t));
|
|
410
443
|
}
|
|
411
|
-
},
|
|
444
|
+
}, ye = class {
|
|
412
445
|
constructor(e, t, n) {
|
|
413
446
|
this.source = e, this.now = n, this.counts = {
|
|
414
447
|
found: 0,
|
|
415
448
|
empty: 0
|
|
416
449
|
}, this.settings = {
|
|
417
|
-
...
|
|
450
|
+
...ge,
|
|
418
451
|
...t
|
|
419
|
-
}, this.clock = new
|
|
452
|
+
}, this.clock = new ve(this.settings.clockLimitMs), this.pacer = new W(this.settings.missingReadSpacingMs, n);
|
|
420
453
|
}
|
|
421
454
|
lastReadableSlot(e = this.now()) {
|
|
422
|
-
return
|
|
455
|
+
return k(e - this.settings.marginMs - this.clock.ms, this.settings.slotMs) - 1;
|
|
423
456
|
}
|
|
424
457
|
readableAt(e) {
|
|
425
|
-
return
|
|
458
|
+
return x(e, this.settings.slotMs) + this.settings.marginMs + this.clock.ms;
|
|
426
459
|
}
|
|
427
460
|
get lookBackSlots() {
|
|
428
461
|
return Math.ceil(this.settings.heartbeatMs / this.settings.slotMs) + 2;
|
|
@@ -431,14 +464,15 @@ var ue = class {
|
|
|
431
464
|
return this.settings.heartbeatMs + 2 * this.settings.slotMs + this.settings.marginMs;
|
|
432
465
|
}
|
|
433
466
|
async read(e) {
|
|
467
|
+
if (!this.pacer.mayRead(e)) return null;
|
|
434
468
|
let t;
|
|
435
469
|
try {
|
|
436
|
-
t = await this.source.readNote(e);
|
|
470
|
+
t = await this.source.readNote(e), t === null && this.pacer.missed(e);
|
|
437
471
|
} catch (e) {
|
|
438
|
-
if (!(e instanceof
|
|
472
|
+
if (!(e instanceof K)) throw e;
|
|
439
473
|
t = null;
|
|
440
474
|
}
|
|
441
|
-
let n = t === null ? null :
|
|
475
|
+
let n = t === null ? null : g(t);
|
|
442
476
|
return n === null ? (this.counts.empty++, null) : (this.counts.found++, this.clock.observe(n.writtenAt, this.now()), n);
|
|
443
477
|
}
|
|
444
478
|
async scan(e, t) {
|
|
@@ -458,17 +492,18 @@ var ue = class {
|
|
|
458
492
|
maxResends: 5,
|
|
459
493
|
reactionWindowMs: 1e3,
|
|
460
494
|
isLive: () => !0
|
|
461
|
-
},
|
|
495
|
+
}, be = class {
|
|
462
496
|
constructor(e, t, n, r, i = Q) {
|
|
463
|
-
this.key = e, this.
|
|
497
|
+
this.key = e, this.profile = t, this.write = n, this.events = r, this.settings = i, this.outgoing = /* @__PURE__ */ new Map(), this.reactions = /* @__PURE__ */ new Map(), this.stopped = !1;
|
|
464
498
|
}
|
|
465
499
|
get address() {
|
|
466
500
|
return this.key.publicKey().address().toHex();
|
|
467
501
|
}
|
|
468
502
|
send(e) {
|
|
469
|
-
let { message: t, bytes: n } =
|
|
503
|
+
let { message: t, bytes: n } = l(this.key, {
|
|
470
504
|
...e,
|
|
471
|
-
|
|
505
|
+
...this.profile,
|
|
506
|
+
own: !1
|
|
472
507
|
}), r = {
|
|
473
508
|
message: t,
|
|
474
509
|
bytes: n,
|
|
@@ -545,22 +580,26 @@ var ue = class {
|
|
|
545
580
|
clearTimer(e) {
|
|
546
581
|
e.timer &&= (clearTimeout(e.timer), null);
|
|
547
582
|
}
|
|
548
|
-
},
|
|
583
|
+
}, xe = [
|
|
549
584
|
1e3,
|
|
550
585
|
2e3,
|
|
551
586
|
4e3,
|
|
552
587
|
8e3
|
|
553
|
-
],
|
|
588
|
+
], Se = 3;
|
|
554
589
|
function $(e) {
|
|
555
590
|
return (e.startsWith("0x") ? e.slice(2) : e).toLowerCase();
|
|
556
591
|
}
|
|
557
|
-
var
|
|
592
|
+
var Ce = class {
|
|
558
593
|
constructor(e, t = {}) {
|
|
559
|
-
this.emitter = new
|
|
594
|
+
this.emitter = new H(), this.seen = /* @__PURE__ */ new Set(), this.status = null, this.generation = 0, this.running = !1, this.starting = null, this.openTimer = null, this.wakeOpen = null;
|
|
560
595
|
let { user: n, infra: r } = e;
|
|
561
|
-
this.key = new
|
|
596
|
+
this.key = new I($(n.privateKey)), this.topic = r.chatTopic, this.profile = {
|
|
597
|
+
name: n.nickname,
|
|
598
|
+
via: r.via,
|
|
599
|
+
...n.binding ? { idb: n.binding } : {}
|
|
600
|
+
}, this.openRetryMs = t.openRetryMs ?? xe, this.senderSettings = {
|
|
562
601
|
...Q,
|
|
563
|
-
isLive: () => this.status ===
|
|
602
|
+
isLive: () => this.status === X.LIVE,
|
|
564
603
|
...t.sender
|
|
565
604
|
};
|
|
566
605
|
let i = {
|
|
@@ -572,28 +611,28 @@ var me = class {
|
|
|
572
611
|
...r.noteHeartbeatMs === void 0 ? {} : { heartbeatMs: r.noteHeartbeatMs },
|
|
573
612
|
...t.notes
|
|
574
613
|
};
|
|
575
|
-
this.source = t.source ??
|
|
614
|
+
this.source = t.source ?? le(new N(r.beeUrl), $(r.chatAddress), r.chatTopic, i, a.slotMs), this.write = t.write ?? de(new N(r.writeUrl ?? r.beeUrl), r.stamp ? $(r.stamp) : ue, $(r.gsocResourceId), r.gsocTopic, i);
|
|
576
615
|
let o = t.follower?.now ?? (() => Date.now()), s = {
|
|
577
616
|
pollIntervalMs: r.pollingInterval ?? 1e3,
|
|
578
617
|
...t.follower,
|
|
579
618
|
now: o
|
|
580
619
|
}, c = this.source;
|
|
581
|
-
this.notes =
|
|
620
|
+
this.notes = _e(c) ? new ye(c, a, o) : null, this.follower = new pe(this.source, this.topic, {
|
|
582
621
|
entry: (e) => this.show(e),
|
|
583
|
-
skipped: (e, t, n) => this.emitter.emit(
|
|
622
|
+
skipped: (e, t, n) => this.emitter.emit(R.MESSAGE_SKIPPED, {
|
|
584
623
|
index: e,
|
|
585
624
|
reason: t,
|
|
586
625
|
detail: n
|
|
587
626
|
}),
|
|
588
627
|
status: (e) => this.setStatus(e),
|
|
589
|
-
error: (e) => this.emitter.emit(
|
|
590
|
-
}, s, this.notes), this.history = new
|
|
591
|
-
skipped: (e) => this.emitter.emit(
|
|
628
|
+
error: (e) => this.emitter.emit(R.ERROR, e)
|
|
629
|
+
}, s, this.notes), this.history = new he(this.source, this.topic, {
|
|
630
|
+
skipped: (e) => this.emitter.emit(R.MESSAGE_SKIPPED, {
|
|
592
631
|
index: -1,
|
|
593
632
|
reason: "history-row",
|
|
594
633
|
detail: `${e} rows of a history file`
|
|
595
634
|
}),
|
|
596
|
-
error: (e) => this.emitter.emit(
|
|
635
|
+
error: (e) => this.emitter.emit(R.ERROR, e)
|
|
597
636
|
}, this.notes), this.sender = this.makeSender();
|
|
598
637
|
}
|
|
599
638
|
getEmitter() {
|
|
@@ -621,7 +660,7 @@ var me = class {
|
|
|
621
660
|
if (!n) throw Error("a reaction names the message it reacts to");
|
|
622
661
|
return this.sender.react(this.topic, n, e), null;
|
|
623
662
|
}
|
|
624
|
-
return
|
|
663
|
+
return z(this.sender.send({
|
|
625
664
|
topic: this.topic,
|
|
626
665
|
type: t,
|
|
627
666
|
target: n ?? "",
|
|
@@ -632,12 +671,12 @@ var me = class {
|
|
|
632
671
|
return this.sender.retry(typeof e == "string" ? e : e.id);
|
|
633
672
|
}
|
|
634
673
|
async fetchPreviousMessages() {
|
|
635
|
-
this.emitter.emit(
|
|
674
|
+
this.emitter.emit(R.LOADING_PREVIOUS_MESSAGES, !0);
|
|
636
675
|
try {
|
|
637
676
|
let e = this.generation, t = await this.history.loadOlder();
|
|
638
677
|
return e === this.generation ? this.showRows(t) : [];
|
|
639
678
|
} finally {
|
|
640
|
-
this.emitter.emit(
|
|
679
|
+
this.emitter.emit(R.LOADING_PREVIOUS_MESSAGES, !1);
|
|
641
680
|
}
|
|
642
681
|
}
|
|
643
682
|
hasPreviousMessages() {
|
|
@@ -647,16 +686,16 @@ var me = class {
|
|
|
647
686
|
return [...e].sort((e, t) => e.index >= 0 && t.index >= 0 ? e.index - t.index : e.index >= 0 || t.index >= 0 ? e.index >= 0 ? -1 : 1 : e.timestamp - t.timestamp);
|
|
648
687
|
}
|
|
649
688
|
async open(e) {
|
|
650
|
-
this.emitter.emit(
|
|
689
|
+
this.emitter.emit(R.LOADING_INIT, !0);
|
|
651
690
|
let t = 0;
|
|
652
691
|
for (; e === this.generation;) try {
|
|
653
692
|
let t = await this.history.open();
|
|
654
693
|
if (e !== this.generation) return;
|
|
655
|
-
this.showRows(t.rows), this.follower.start(t.startAt, t.notes), this.emitter.emit(
|
|
694
|
+
this.showRows(t.rows), this.follower.start(t.startAt, t.notes), this.emitter.emit(R.LOADING_INIT, !1);
|
|
656
695
|
return;
|
|
657
696
|
} catch (n) {
|
|
658
697
|
if (e !== this.generation) return;
|
|
659
|
-
t++, this.emitter.emit(
|
|
698
|
+
t++, this.emitter.emit(R.ERROR, n), this.setStatus(X.RECONNECTING), t === Se && this.emitter.emit(R.CRITICAL_ERROR, n), await this.waitToOpen(this.openRetryMs[Math.min(t, this.openRetryMs.length) - 1] ?? 8e3);
|
|
660
699
|
}
|
|
661
700
|
}
|
|
662
701
|
waitToOpen(e) {
|
|
@@ -669,31 +708,31 @@ var me = class {
|
|
|
669
708
|
});
|
|
670
709
|
}
|
|
671
710
|
makeSender() {
|
|
672
|
-
return new
|
|
673
|
-
pending: (e) => this.emitter.emit(
|
|
674
|
-
written: (e) => this.emitter.emit(
|
|
711
|
+
return new be(this.key, this.profile, this.write, {
|
|
712
|
+
pending: (e) => this.emitter.emit(R.MESSAGE_REQUEST_INITIATED, z(e)),
|
|
713
|
+
written: (e) => this.emitter.emit(R.MESSAGE_REQUEST_UPLOADED, z(e)),
|
|
675
714
|
failed: (e, t) => {
|
|
676
|
-
this.emitter.emit(
|
|
715
|
+
this.emitter.emit(R.ERROR, t), this.emitter.emit(R.MESSAGE_REQUEST_ERROR, z(e));
|
|
677
716
|
},
|
|
678
717
|
confirmed: () => {}
|
|
679
718
|
}, this.senderSettings);
|
|
680
719
|
}
|
|
681
720
|
show(e) {
|
|
682
|
-
this.seen.has(e.seq) || (this.seen.add(e.seq), this.sender.confirm(e.msg), this.emitter.emit(
|
|
721
|
+
this.seen.has(e.seq) || (this.seen.add(e.seq), this.sender.confirm(e.msg), this.emitter.emit(R.MESSAGE_RECEIVED, B(e)));
|
|
683
722
|
}
|
|
684
723
|
showRows(e) {
|
|
685
724
|
let t = [];
|
|
686
725
|
for (let n of e) {
|
|
687
726
|
if (this.seen.has(n.seq)) continue;
|
|
688
727
|
this.seen.add(n.seq), this.sender.confirm(n.msg);
|
|
689
|
-
let e =
|
|
690
|
-
t.push(e), this.emitter.emit(
|
|
728
|
+
let e = B(n);
|
|
729
|
+
t.push(e), this.emitter.emit(R.MESSAGE_RECEIVED, e);
|
|
691
730
|
}
|
|
692
731
|
return t;
|
|
693
732
|
}
|
|
694
733
|
setStatus(e) {
|
|
695
|
-
e !== this.status && (this.status = e, this.emitter.emit(
|
|
734
|
+
e !== this.status && (this.status = e, this.emitter.emit(R.STATUS, e));
|
|
696
735
|
}
|
|
697
736
|
};
|
|
698
737
|
//#endregion
|
|
699
|
-
export {
|
|
738
|
+
export { M as CHAT_BINDING_TITLE, H as ChatEmitter, p as ChatMessageError, O as DEFAULT_NOTE_HEARTBEAT_MS, C as DEFAULT_NOTE_SLOT_MS, R as EVENTS, X as FeedStatus, G as HeadLookupTimeoutError, t as MAX_BINDING_CHARACTERS, T as MAX_ENTRY_BYTES, n as MAX_MESSAGE_BYTES, se as MAX_NAME_CHARACTERS, E as MAX_NOTE_BYTES, m as MAX_TEXT_CHARACTERS, i as MAX_TOPIC_CHARACTERS, r as MESSAGE_VERSION, u as MessageType, b as MessageVia, ae as NOTE_VERSION, ie as OWN_FEED_TOPIC_PREFIX, Ce as SwarmChat, Z as UnreadableGatewayError, K as UnreadableSlotError, te as chatBindingSchema, e as chatMessageSchema, o as checkChatBinding, oe as countCharacters, l as createChatMessage, ee as encodeChatMessage, re as encodeSlotNote, S as feedEntrySchema, d as hasValidSignature, y as historyFileSchema, v as historyLinkSchema, ne as historyRowSchema, a as newMessageId, w as noteAddress, D as noteIdentifier, h as noteIdentifierText, x as noteSlotEnd, k as noteSlotOf, ce as ownFeedTopic, s as parseChatMessage, A as parseFeedEntry, j as parseHistoryFile, g as parseSlotNote, c as signedBytes, _ as slotNoteSchema, f as verifyChatMessage };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* The Swarm ID chat binding: the account's statement, signed with its own key, that a chat address on one site is its
|
|
4
|
+
* own. The Swarm ID fork (solarpunk-id, `lib/src/utils/chat-binding.ts`) makes it, and this module reads it exactly as
|
|
5
|
+
* the fork's `verifyChatBinding` does, without importing the fork: the same four lines, the same clean site origin,
|
|
6
|
+
* the same EIP-191 personal_sign recovery with v 27 or 28 and a low s.
|
|
7
|
+
*/
|
|
8
|
+
/** The first line, which also versions the binding format. */
|
|
9
|
+
export declare const CHAT_BINDING_TITLE = "Swarm ID chat binding v1";
|
|
10
|
+
/** The fork's own bound on a binding's text. */
|
|
11
|
+
export declare const MAX_BINDING_CHARACTERS = 512;
|
|
12
|
+
/**
|
|
13
|
+
* A binding as a message carries it. `sig` is spelled as the fork writes it, `0x` and 130 lowercase hex characters
|
|
14
|
+
* of r, s and v, so one binding has one spelling inside the signed bytes.
|
|
15
|
+
*/
|
|
16
|
+
export declare const chatBindingSchema: z.ZodObject<{
|
|
17
|
+
msg: z.ZodString;
|
|
18
|
+
sig: z.ZodString;
|
|
19
|
+
}, z.core.$strict>;
|
|
20
|
+
export type ChatBinding = z.infer<typeof chatBindingSchema>;
|
|
21
|
+
/** Who a verified binding says the sender is. */
|
|
22
|
+
export interface ChatIdentity {
|
|
23
|
+
/** The Swarm ID account that signed the binding, `0x` and 40 lowercase hex characters. */
|
|
24
|
+
account: string;
|
|
25
|
+
/** The site the binding was signed for, a bare origin. */
|
|
26
|
+
site: string;
|
|
27
|
+
/** When the account says it signed, ISO 8601 UTC. */
|
|
28
|
+
date: string;
|
|
29
|
+
}
|
|
30
|
+
export interface BindingOptions {
|
|
31
|
+
/** The origin the reader runs on. When given, a binding for any other site is refused. */
|
|
32
|
+
origin?: string;
|
|
33
|
+
/** Accept a binding for `http://localhost`, `http://127.0.0.1` or `http://[::1]`, as only a development build signs. */
|
|
34
|
+
allowLocalHttp?: boolean;
|
|
35
|
+
}
|
|
36
|
+
export type BindingCheck = {
|
|
37
|
+
ok: true;
|
|
38
|
+
identity: ChatIdentity;
|
|
39
|
+
} | {
|
|
40
|
+
ok: false;
|
|
41
|
+
detail: string;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Reads a binding for the chat address `addr` (40 lowercase hex characters, no `0x`). Refuses every text but the four
|
|
45
|
+
* lines the fork writes, a binding for another chat address, one for another site than `origin` when that is given,
|
|
46
|
+
* and a signature nothing recovers an account from. Never throws.
|
|
47
|
+
*/
|
|
48
|
+
export declare function checkChatBinding(binding: ChatBinding, addr: string, options?: BindingOptions): BindingCheck;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether r and s, 64 hex characters each, are in range with s in the lower half of the curve order. Every ECDSA
|
|
3
|
+
* signature has a second valid spelling with s replaced by n - s and v flipped, which recovers the same signer, so
|
|
4
|
+
* refusing the high s one leaves one valid signature per signed text. bee-js and the Swarm ID fork both sign low s.
|
|
5
|
+
*/
|
|
6
|
+
export declare function isCanonicalSignature(rHex: string, sHex: string): boolean;
|