@solarpunkltd/swarm-id 0.0.0-stage → 0.8.1

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.
Files changed (111) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +89 -2
  3. package/dist/bus/account-bus.d.ts +104 -0
  4. package/dist/bus/account-delta.d.ts +52 -0
  5. package/dist/bus/bus-context.d.ts +7 -0
  6. package/dist/bus/envelope.d.ts +9 -0
  7. package/dist/bus/messages.d.ts +241 -0
  8. package/dist/bus/presence.d.ts +62 -0
  9. package/dist/bus/signaling-transport.d.ts +79 -0
  10. package/dist/chunk/bmt.d.ts +16 -0
  11. package/dist/chunk/cac.d.ts +17 -0
  12. package/dist/chunk/constants.d.ts +10 -0
  13. package/dist/chunk/encrypted-cac.d.ts +47 -0
  14. package/dist/chunk/encryption.d.ts +85 -0
  15. package/dist/chunk/index.d.ts +5 -0
  16. package/dist/chunks/chat-binding-DO5aGhPl.js +23 -0
  17. package/dist/chunks/chat-binding-DO5aGhPl.js.map +1 -0
  18. package/dist/errors.d.ts +35 -0
  19. package/dist/index.d.ts +27 -0
  20. package/dist/internal.d.ts +49 -0
  21. package/dist/internal.esm.js +2 -0
  22. package/dist/internal.esm.js.map +1 -0
  23. package/dist/proxy/act/act.d.ts +58 -0
  24. package/dist/proxy/act/crypto.d.ts +46 -0
  25. package/dist/proxy/act/grantee-list.d.ts +81 -0
  26. package/dist/proxy/act/history.d.ts +182 -0
  27. package/dist/proxy/act/index.d.ts +114 -0
  28. package/dist/proxy/app-stamp-limits.d.ts +62 -0
  29. package/dist/proxy/chunk-upload-stream.d.ts +37 -0
  30. package/dist/proxy/chunking.d.ts +15 -0
  31. package/dist/proxy/collection.d.ts +38 -0
  32. package/dist/proxy/download-data.d.ts +27 -0
  33. package/dist/proxy/errors.d.ts +8 -0
  34. package/dist/proxy/feed-manifest.d.ts +60 -0
  35. package/dist/proxy/feeds/epochs/async-finder.d.ts +70 -0
  36. package/dist/proxy/feeds/epochs/epoch.d.ts +79 -0
  37. package/dist/proxy/feeds/epochs/finder.d.ts +60 -0
  38. package/dist/proxy/feeds/epochs/index.d.ts +30 -0
  39. package/dist/proxy/feeds/epochs/types.d.ts +110 -0
  40. package/dist/proxy/feeds/epochs/updater.d.ts +76 -0
  41. package/dist/proxy/feeds/epochs/utils.d.ts +21 -0
  42. package/dist/proxy/feeds/index.d.ts +4 -0
  43. package/dist/proxy/feeds/sequence/async-finder.d.ts +14 -0
  44. package/dist/proxy/feeds/sequence/finder.d.ts +11 -0
  45. package/dist/proxy/feeds/sequence/index.d.ts +22 -0
  46. package/dist/proxy/feeds/sequence/types.d.ts +82 -0
  47. package/dist/proxy/feeds/sequence/updater.d.ts +20 -0
  48. package/dist/proxy/index.d.ts +5 -0
  49. package/dist/proxy/manifest-builder.d.ts +164 -0
  50. package/dist/proxy/mantaray.d.ts +76 -0
  51. package/dist/proxy/soc-restamp-slots.d.ts +48 -0
  52. package/dist/proxy/stamp-chunk.d.ts +45 -0
  53. package/dist/proxy/stamp-worker-handler.d.ts +32 -0
  54. package/dist/proxy/stamp-worker-pool.d.ts +52 -0
  55. package/dist/proxy/stamp-worker.d.ts +1 -0
  56. package/dist/proxy/types.d.ts +38 -0
  57. package/dist/proxy/upload.d.ts +207 -0
  58. package/dist/schemas.d.ts +671 -0
  59. package/dist/stamp-worker.iife.js +1 -0
  60. package/dist/storage/debounced-uploader.d.ts +61 -0
  61. package/dist/storage/utilization-store.d.ts +113 -0
  62. package/dist/swarm-id-client.d.ts +1143 -0
  63. package/dist/swarm-id-proxy.d.ts +1079 -0
  64. package/dist/swarm-id.esm.js +2 -0
  65. package/dist/swarm-id.esm.js.map +1 -0
  66. package/dist/sync/batch-write-coordinator.d.ts +348 -0
  67. package/dist/sync/device-roster.d.ts +59 -0
  68. package/dist/sync/device-state.d.ts +199 -0
  69. package/dist/sync/fold-account-from-swarm.d.ts +53 -0
  70. package/dist/sync/index.d.ts +11 -0
  71. package/dist/sync/merge-snapshot.d.ts +57 -0
  72. package/dist/sync/partition-intent.d.ts +218 -0
  73. package/dist/sync/partition-lease.d.ts +531 -0
  74. package/dist/sync/partition-lock.d.ts +218 -0
  75. package/dist/sync/partition-state.d.ts +287 -0
  76. package/dist/sync/session-check.d.ts +29 -0
  77. package/dist/sync/store-interfaces.d.ts +48 -0
  78. package/dist/sync/sync-account.d.ts +45 -0
  79. package/dist/sync/timing-constants.d.ts +32 -0
  80. package/dist/sync/types.d.ts +18 -0
  81. package/dist/types.d.ts +3042 -0
  82. package/dist/utils/account-state-snapshot.d.ts +43 -0
  83. package/dist/utils/active-devices.d.ts +45 -0
  84. package/dist/utils/avatar.d.ts +30 -0
  85. package/dist/utils/batch-utilization.d.ts +840 -0
  86. package/dist/utils/batch-write-lock.d.ts +12 -0
  87. package/dist/utils/bee-error.d.ts +11 -0
  88. package/dist/utils/chat-binding.d.ts +113 -0
  89. package/dist/utils/coalesced-task.d.ts +28 -0
  90. package/dist/utils/collection.d.ts +6 -0
  91. package/dist/utils/connection-info.d.ts +11 -0
  92. package/dist/utils/constants.d.ts +28 -0
  93. package/dist/utils/device-id.d.ts +109 -0
  94. package/dist/utils/hex.d.ts +31 -0
  95. package/dist/utils/json-rpc.d.ts +34 -0
  96. package/dist/utils/key-derivation.d.ts +124 -0
  97. package/dist/utils/lock-soc.d.ts +35 -0
  98. package/dist/utils/postage-contract.d.ts +143 -0
  99. package/dist/utils/postage-stamp-association.d.ts +39 -0
  100. package/dist/utils/promise.d.ts +37 -0
  101. package/dist/utils/sealed-values.d.ts +23 -0
  102. package/dist/utils/seed-encryption.d.ts +17 -0
  103. package/dist/utils/site-allow-list.d.ts +54 -0
  104. package/dist/utils/stamp-lifespan.d.ts +37 -0
  105. package/dist/utils/storage-managers.d.ts +62 -0
  106. package/dist/utils/storage-probe.d.ts +40 -0
  107. package/dist/utils/tag.d.ts +11 -0
  108. package/dist/utils/ttl.d.ts +120 -0
  109. package/dist/utils/url.d.ts +55 -0
  110. package/dist/utils/versioned-storage.d.ts +183 -0
  111. package/package.json +91 -3
@@ -0,0 +1,241 @@
1
+ /**
2
+ * Account-bus message schemas.
3
+ *
4
+ * Wire format is JSON-serializable (plain objects, hex strings) so the same
5
+ * messages can later travel transports that leave the browser (WebRTC,
6
+ * SWIP-60). Receivers parse with `BusMessageSchema`, which revives typed
7
+ * values (BatchId, PrivateKey, bigint) exactly like the device-state feed
8
+ * payloads do — see `docs/Account-Bus.md`.
9
+ */
10
+ import { z } from "zod";
11
+ /**
12
+ * A full account-state snapshot from another live context. Merged with the
13
+ * same LWW primitives as a device-state feed payload, minus the session
14
+ * material above.
15
+ */
16
+ export declare const AccountDeltaMessageSchema: z.ZodObject<{
17
+ type: z.ZodLiteral<"account-delta">;
18
+ snapshot: z.ZodObject<{
19
+ version: z.ZodLiteral<1>;
20
+ timestamp: z.ZodNumber;
21
+ accountId: z.ZodString;
22
+ metadata: z.ZodObject<{
23
+ accountName: z.ZodString;
24
+ defaultPostageStampBatchID: z.ZodOptional<z.ZodString>;
25
+ publicKey: z.ZodString;
26
+ settings: z.ZodOptional<z.ZodObject<{
27
+ appSessionDuration: z.ZodOptional<z.ZodNumber>;
28
+ }, z.core.$strip>>;
29
+ accountNameAt: z.ZodOptional<z.ZodNumber>;
30
+ defaultStampAt: z.ZodOptional<z.ZodNumber>;
31
+ settingsAt: z.ZodOptional<z.ZodNumber>;
32
+ createdAt: z.ZodNumber;
33
+ lastModified: z.ZodNumber;
34
+ devices: z.ZodDefault<z.ZodArray<z.ZodObject<{
35
+ deviceId: z.ZodString;
36
+ createdAt: z.ZodNumber;
37
+ lastSignedInAt: z.ZodNumber;
38
+ name: z.ZodOptional<z.ZodString>;
39
+ nameUpdatedAt: z.ZodOptional<z.ZodNumber>;
40
+ removedAt: z.ZodOptional<z.ZodNumber>;
41
+ }, z.core.$strip>>>;
42
+ partitionCount: z.ZodDefault<z.ZodNumber>;
43
+ }, z.core.$strip>;
44
+ postageStamps: z.ZodArray<z.ZodObject<{
45
+ batchID: z.ZodPipe<z.ZodString, z.ZodTransform<import("@ethersphere/core-sdk").BatchId, string>>;
46
+ signerKey: z.ZodPipe<z.ZodString, z.ZodTransform<import("@ethersphere/core-sdk").PrivateKey, string>>;
47
+ name: z.ZodOptional<z.ZodString>;
48
+ nameUpdatedAt: z.ZodOptional<z.ZodNumber>;
49
+ utilization: z.ZodNumber;
50
+ usable: z.ZodBoolean;
51
+ depth: z.ZodNumber;
52
+ amount: z.ZodPipe<z.ZodString, z.ZodTransform<bigint, string>>;
53
+ bucketDepth: z.ZodNumber;
54
+ blockNumber: z.ZodNumber;
55
+ immutableFlag: z.ZodBoolean;
56
+ exists: z.ZodBoolean;
57
+ batchTTL: z.ZodOptional<z.ZodNumber>;
58
+ createdAt: z.ZodNumber;
59
+ updatedAt: z.ZodOptional<z.ZodNumber>;
60
+ deletedAt: z.ZodOptional<z.ZodNumber>;
61
+ }, z.core.$strip>>;
62
+ connectedApps: z.ZodArray<z.ZodObject<{
63
+ appName: z.ZodString;
64
+ appDescription: z.ZodOptional<z.ZodString>;
65
+ appIcon: z.ZodOptional<z.ZodString>;
66
+ appUrl: z.ZodString;
67
+ lastConnectedAt: z.ZodNumber;
68
+ postageStampBatchID: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<import("@ethersphere/core-sdk").BatchId, string>>>;
69
+ postageStampBatchIDAt: z.ZodOptional<z.ZodNumber>;
70
+ revokedAt: z.ZodOptional<z.ZodNumber>;
71
+ disconnectedAt: z.ZodOptional<z.ZodNumber>;
72
+ }, z.core.$strip>>;
73
+ }, z.core.$strip>;
74
+ }, z.core.$strip>;
75
+ /**
76
+ * A context waiting for a batch-write partition (all slots held by live
77
+ * peers) asks live holders to yield. An idle holder releases via the normal
78
+ * Swarm lease protocol and answers with `lease-released`; holders mid-write
79
+ * ignore it. Repeats are harmless (yield-if-idle is a guarded no-op).
80
+ *
81
+ * `batchId` scopes the ask, because the lock it is a fast path for is scoped
82
+ * that way: lanes are per (batch, partition) since #589, so a holder on batch X
83
+ * and a waiter on batch Y contend for nothing. Answering across batches would
84
+ * drop a lease for a waiter it cannot help — the bus must not be broader than
85
+ * the lock it front-runs, any more than it may be narrower.
86
+ *
87
+ * `requestId` is 8 hex chars, fresh per poll round, and exists so exactly one
88
+ * holder answers: each derives the same permutation of the partitions from it
89
+ * and yields at its own rank (`swarm-id-proxy.ts`, `yieldRankDelayMs`). It is
90
+ * format-checked: the rank is `parseInt(requestId, 16)`, so an unconstrained
91
+ * string reintroduces the very bug this fixes (`NaN` or a negative collapses
92
+ * every holder onto the same rank), silently and with nothing to diagnose.
93
+ */
94
+ export declare const LeaseRequestMessageSchema: z.ZodObject<{
95
+ type: z.ZodLiteral<"lease-request">;
96
+ accountId: z.ZodString;
97
+ batchId: z.ZodString;
98
+ fromDeviceId: z.ZodString;
99
+ requestId: z.ZodString;
100
+ }, z.core.$strip>;
101
+ /**
102
+ * The holder that drew the lowest rank for `requestId` is answering it. Sent
103
+ * BEFORE the release starts, because the release itself is two stamped Swarm
104
+ * writes — an order of magnitude longer than the rank step — so a signal sent
105
+ * after it would reach the other holders only once they had all begun yielding
106
+ * too, which is #576 again. Holders further down the order stand down on this;
107
+ * the waiter ignores it (no slot is free yet).
108
+ */
109
+ export declare const LeaseClaimMessageSchema: z.ZodObject<{
110
+ type: z.ZodLiteral<"lease-claim">;
111
+ accountId: z.ZodString;
112
+ batchId: z.ZodString;
113
+ fromDeviceId: z.ZodString;
114
+ requestId: z.ZodString;
115
+ }, z.core.$strip>;
116
+ /**
117
+ * A holder released its partition (on request or teardown) — waiting peers
118
+ * wake their slot poll immediately instead of sleeping out the interval. The
119
+ * lock SOCs on Swarm remain the authority; this is purely a wake-up.
120
+ *
121
+ * `requestId` echoes the `lease-request` this answers, so holders further down
122
+ * the rank order can stand down. Absent on a teardown release, which answers
123
+ * no request.
124
+ */
125
+ export declare const LeaseReleasedMessageSchema: z.ZodObject<{
126
+ type: z.ZodLiteral<"lease-released">;
127
+ accountId: z.ZodString;
128
+ batchId: z.ZodString;
129
+ partition: z.ZodNumber;
130
+ fromDeviceId: z.ZodString;
131
+ requestId: z.ZodOptional<z.ZodString>;
132
+ }, z.core.$strip>;
133
+ /**
134
+ * "This device is live." Published on joining the room and every
135
+ * `PRESENCE_INTERVAL_MS` (`presence.ts`); a receiver stamps its own clock, so
136
+ * there is no timestamp to skew and a replay (#604) only refreshes a device it
137
+ * has already heard. A peer on an older bundle drops it at the schema — a new
138
+ * kind, not an envelope change, so nothing to deploy in step.
139
+ */
140
+ export declare const PresenceMessageSchema: z.ZodObject<{
141
+ type: z.ZodLiteral<"presence">;
142
+ accountId: z.ZodString;
143
+ fromDeviceId: z.ZodString;
144
+ }, z.core.$strip>;
145
+ export declare const BusMessageSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
146
+ type: z.ZodLiteral<"utilization-updated">;
147
+ batchId: z.ZodString;
148
+ partition: z.ZodNumber;
149
+ partitionCount: z.ZodNumber;
150
+ buckets: z.ZodArray<z.ZodObject<{
151
+ index: z.ZodNumber;
152
+ value: z.ZodNumber;
153
+ }, z.core.$strip>>;
154
+ }, z.core.$strip>, z.ZodObject<{
155
+ type: z.ZodLiteral<"account-delta">;
156
+ snapshot: z.ZodObject<{
157
+ version: z.ZodLiteral<1>;
158
+ timestamp: z.ZodNumber;
159
+ accountId: z.ZodString;
160
+ metadata: z.ZodObject<{
161
+ accountName: z.ZodString;
162
+ defaultPostageStampBatchID: z.ZodOptional<z.ZodString>;
163
+ publicKey: z.ZodString;
164
+ settings: z.ZodOptional<z.ZodObject<{
165
+ appSessionDuration: z.ZodOptional<z.ZodNumber>;
166
+ }, z.core.$strip>>;
167
+ accountNameAt: z.ZodOptional<z.ZodNumber>;
168
+ defaultStampAt: z.ZodOptional<z.ZodNumber>;
169
+ settingsAt: z.ZodOptional<z.ZodNumber>;
170
+ createdAt: z.ZodNumber;
171
+ lastModified: z.ZodNumber;
172
+ devices: z.ZodDefault<z.ZodArray<z.ZodObject<{
173
+ deviceId: z.ZodString;
174
+ createdAt: z.ZodNumber;
175
+ lastSignedInAt: z.ZodNumber;
176
+ name: z.ZodOptional<z.ZodString>;
177
+ nameUpdatedAt: z.ZodOptional<z.ZodNumber>;
178
+ removedAt: z.ZodOptional<z.ZodNumber>;
179
+ }, z.core.$strip>>>;
180
+ partitionCount: z.ZodDefault<z.ZodNumber>;
181
+ }, z.core.$strip>;
182
+ postageStamps: z.ZodArray<z.ZodObject<{
183
+ batchID: z.ZodPipe<z.ZodString, z.ZodTransform<import("@ethersphere/core-sdk").BatchId, string>>;
184
+ signerKey: z.ZodPipe<z.ZodString, z.ZodTransform<import("@ethersphere/core-sdk").PrivateKey, string>>;
185
+ name: z.ZodOptional<z.ZodString>;
186
+ nameUpdatedAt: z.ZodOptional<z.ZodNumber>;
187
+ utilization: z.ZodNumber;
188
+ usable: z.ZodBoolean;
189
+ depth: z.ZodNumber;
190
+ amount: z.ZodPipe<z.ZodString, z.ZodTransform<bigint, string>>;
191
+ bucketDepth: z.ZodNumber;
192
+ blockNumber: z.ZodNumber;
193
+ immutableFlag: z.ZodBoolean;
194
+ exists: z.ZodBoolean;
195
+ batchTTL: z.ZodOptional<z.ZodNumber>;
196
+ createdAt: z.ZodNumber;
197
+ updatedAt: z.ZodOptional<z.ZodNumber>;
198
+ deletedAt: z.ZodOptional<z.ZodNumber>;
199
+ }, z.core.$strip>>;
200
+ connectedApps: z.ZodArray<z.ZodObject<{
201
+ appName: z.ZodString;
202
+ appDescription: z.ZodOptional<z.ZodString>;
203
+ appIcon: z.ZodOptional<z.ZodString>;
204
+ appUrl: z.ZodString;
205
+ lastConnectedAt: z.ZodNumber;
206
+ postageStampBatchID: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<import("@ethersphere/core-sdk").BatchId, string>>>;
207
+ postageStampBatchIDAt: z.ZodOptional<z.ZodNumber>;
208
+ revokedAt: z.ZodOptional<z.ZodNumber>;
209
+ disconnectedAt: z.ZodOptional<z.ZodNumber>;
210
+ }, z.core.$strip>>;
211
+ }, z.core.$strip>;
212
+ }, z.core.$strip>, z.ZodObject<{
213
+ type: z.ZodLiteral<"lease-request">;
214
+ accountId: z.ZodString;
215
+ batchId: z.ZodString;
216
+ fromDeviceId: z.ZodString;
217
+ requestId: z.ZodString;
218
+ }, z.core.$strip>, z.ZodObject<{
219
+ type: z.ZodLiteral<"lease-claim">;
220
+ accountId: z.ZodString;
221
+ batchId: z.ZodString;
222
+ fromDeviceId: z.ZodString;
223
+ requestId: z.ZodString;
224
+ }, z.core.$strip>, z.ZodObject<{
225
+ type: z.ZodLiteral<"lease-released">;
226
+ accountId: z.ZodString;
227
+ batchId: z.ZodString;
228
+ partition: z.ZodNumber;
229
+ fromDeviceId: z.ZodString;
230
+ requestId: z.ZodOptional<z.ZodString>;
231
+ }, z.core.$strip>, z.ZodObject<{
232
+ type: z.ZodLiteral<"presence">;
233
+ accountId: z.ZodString;
234
+ fromDeviceId: z.ZodString;
235
+ }, z.core.$strip>], "type">;
236
+ export type AccountDeltaMessage = z.infer<typeof AccountDeltaMessageSchema>;
237
+ /** The wire form of a delta: hex strings, not revived `BatchId`/`PrivateKey`. */
238
+ export type AccountDeltaInput = z.input<typeof AccountDeltaMessageSchema>;
239
+ export type BusMessage = z.infer<typeof BusMessageSchema>;
240
+ /** What publishers hand to the bus: the JSON-serializable wire form. */
241
+ export type BusMessageInput = z.input<typeof BusMessageSchema>;
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Who is live on the account bus, as seen from one context.
3
+ *
4
+ * Every context in the room publishes a `presence` on join and every
5
+ * `PRESENCE_INTERVAL_MS`; a receiver notes the time it heard each device. A
6
+ * device unheard for `PRESENCE_MAX_AGE_MS` is no longer live. That is the whole
7
+ * mechanism: the bus already knows who is in the room, this only ties room
8
+ * membership to a `deviceId`.
9
+ *
10
+ * A clean departure does not wait for the window. The signaling server sends
11
+ * `peer-left` when a socket closes — including one its own reaper terminated,
12
+ * so a crash and a dropped network count too — and `forgetPeer` drops the
13
+ * device that socket carried (#572). Ageing is the backstop for what that
14
+ * cannot see: a peer the server has not yet reaped, and a device heard only
15
+ * over the local transport. A leave message of our own is not an option — a
16
+ * publish encrypts before it sends, and a page being torn down never gets
17
+ * back to the send.
18
+ *
19
+ * In memory only, and deliberately never persisted or published as state. A
20
+ * `lastSeenAt` that rode the account snapshot would make every publish a byte
21
+ * change to fold and re-persist, and the unpartitioned proxy answers every
22
+ * storage event with a bus delta and a stamped feed write — a loop that never
23
+ * settles, even on one device. Durable truth (`lastSignedInAt`) keeps meaning
24
+ * "signed in"; liveness lives here and is rebuilt from scratch on every load.
25
+ */
26
+ export declare const PRESENCE_INTERVAL_MS = 20000;
27
+ /**
28
+ * Three missed beats — of the THROTTLED interval, not ours. A window of three
29
+ * of our own beats sits exactly at a hidden tab's clamped cadence, so a
30
+ * backgrounded-but-live device would flap in and out of its peers' live sets:
31
+ * a blinking badge, and a coordinator repeatedly re-including the same peer in
32
+ * an idle-yield round. Being slow to drop a device that really left costs only
33
+ * an absent intent read, which is why the window errs long. Still well past
34
+ * `LEASE_TTL_MS` and far inside `KNOWN_DEVICE_MAX_AGE_MS`.
35
+ */
36
+ export declare const PRESENCE_MAX_AGE_MS: number;
37
+ export declare class PresenceTracker {
38
+ private seen;
39
+ /**
40
+ * Note a beat. `peerId` is the transport's own name for whoever sent it —
41
+ * present on the signaling transport, absent on the local one, which has no
42
+ * peers. It is what lets a departure be attributed to a device (#572).
43
+ */
44
+ observe(deviceId: string, nowMs: number, peerId?: string): void;
45
+ /**
46
+ * A socket left the room, so whatever it carried is gone with it.
47
+ *
48
+ * Only when it was the device's LAST socket: two tabs of one dApp share a
49
+ * partition, and therefore a `deviceId`, while holding a socket each — one
50
+ * of them closing is not the device leaving. A device heard only over the
51
+ * local transport has no socket to lose and is left to age out.
52
+ *
53
+ * Every entry is checked rather than stopping at the first match. Nothing
54
+ * here enforces that one socket only ever beats under one `deviceId`, and a
55
+ * device left holding a dead socket id could only age out — the three-minute
56
+ * wait this exists to remove. The loop is over a handful of entries.
57
+ */
58
+ forgetPeer(peerId: string): void;
59
+ /** Devices heard within `PRESENCE_MAX_AGE_MS` of `nowMs`. */
60
+ liveDeviceIds(nowMs: number): string[];
61
+ clear(): void;
62
+ }
@@ -0,0 +1,79 @@
1
+ import type { BusTransport } from "./account-bus";
2
+ import type { BusMessageInput } from "./messages";
3
+ export interface SignalingTransportOptions {
4
+ /** Signaling server URL, e.g. `wss://bus.example.com/bus`. */
5
+ url: string;
6
+ /** Account-derived room topic (`deriveBusContext`). */
7
+ topic: string;
8
+ /** Account-derived AES-GCM envelope key (`deriveBusContext`). */
9
+ encryptionKey: CryptoKey;
10
+ /**
11
+ * Factory for the WebRTC upgrade; omit to stay relay-only (e.g. in
12
+ * environments without RTCPeerConnection). No STUN/TURN is configured by
13
+ * default: same-device loopback and LAN peers connect via host candidates,
14
+ * everything else falls back to the relay.
15
+ */
16
+ createPeerConnection?: () => RTCPeerConnection;
17
+ }
18
+ export declare class SignalingTransport implements BusTransport {
19
+ readonly local = false;
20
+ private options;
21
+ private socket;
22
+ private peers;
23
+ private handlers;
24
+ private peerLeftHandlers;
25
+ private closed;
26
+ private reconnectDelayMs;
27
+ private reconnectTimer;
28
+ /** In-flight `deliver` calls, awaited by `close()` so a teardown
29
+ * announcement published in the closing tick still reaches the wire. */
30
+ private pendingDeliveries;
31
+ constructor(options: SignalingTransportOptions);
32
+ /** Live peers currently visible in the room (test/debug aid). */
33
+ get peerCount(): number;
34
+ publish(message: BusMessageInput): void;
35
+ subscribe(handler: (raw: unknown, from?: string) => void): () => void;
36
+ onPeerLeft(handler: (peerId: string) => void): () => void;
37
+ /**
38
+ * Stops reconnecting at once, but lets in-flight publishes reach the wire
39
+ * first: `deliver` awaits envelope encryption, and callers announce a
40
+ * teardown (`lease-released`) and close the bus in the same tick, so tearing
41
+ * the socket down synchronously would drop exactly the message a waiting
42
+ * peer is owed. Each pending delivery is a single encrypt plus synchronous
43
+ * sends, so this settles promptly — it is not a flush of a send queue.
44
+ */
45
+ close(): void;
46
+ private shutdown;
47
+ private connect;
48
+ private scheduleReconnect;
49
+ private deliver;
50
+ private sendToServer;
51
+ private handleServerMessage;
52
+ private receiveEnvelope;
53
+ private initiatePeerConnection;
54
+ private handleSignal;
55
+ /**
56
+ * Install a freshly created connection on a peer, closing whatever was there.
57
+ * A duplicate or renegotiated offer used to overwrite the field and leak the
58
+ * previous `RTCPeerConnection`, which keeps its ICE agent and sockets alive.
59
+ * The candidate queue resets with it: the new connection has no remote
60
+ * description, and candidates gathered for the old one are meaningless.
61
+ */
62
+ private adoptConnection;
63
+ /**
64
+ * Replay the candidates that arrived before the remote description. One bad
65
+ * candidate must not strand the rest, so each is applied on its own.
66
+ *
67
+ * Takes the connection whose description just landed, and does nothing if the
68
+ * peer has moved on to another: signals are handled concurrently, so a second
69
+ * offer can be adopted while this one is still awaiting
70
+ * `setRemoteDescription`, and marking the flag then would describe a
71
+ * connection that has no remote description — re-opening the drop window this
72
+ * queue exists to close, for candidates that arrive before the new
73
+ * negotiation finishes.
74
+ */
75
+ private flushPendingCandidates;
76
+ private adoptDataChannel;
77
+ private forwardIceCandidates;
78
+ private sendSignal;
79
+ }
@@ -0,0 +1,16 @@
1
+ import { Reference } from "@ethersphere/bee-js";
2
+ /**
3
+ * Calculate a Binary Merkle Tree hash for a chunk
4
+ *
5
+ * The BMT chunk address is the hash of the 8 byte span and the root
6
+ * hash of a binary Merkle tree (BMT) built on the 32-byte segments
7
+ * of the underlying data.
8
+ *
9
+ * If the chunk content is less than 4k, the hash is calculated as
10
+ * if the chunk was padded with all zeros up to 4096 bytes.
11
+ *
12
+ * @param chunkContent Chunk data including span and payload as well
13
+ *
14
+ * @returns the keccak256 hash in a byte array
15
+ */
16
+ export declare function calculateChunkAddress(chunkContent: Uint8Array): Reference;
@@ -0,0 +1,17 @@
1
+ import { Bytes, Reference, Span } from "@ethersphere/bee-js";
2
+ /**
3
+ * Content addressed chunk interface
4
+ */
5
+ export interface ContentAddressedChunk {
6
+ readonly data: Uint8Array;
7
+ readonly span: Span;
8
+ readonly payload: Bytes;
9
+ readonly address: Reference;
10
+ }
11
+ /**
12
+ * Creates a content addressed chunk from payload data
13
+ *
14
+ * @param payloadBytes the data to be stored in the chunk (1-4096 bytes)
15
+ * @param spanOverride optional span value to use instead of payload length
16
+ */
17
+ export declare function makeContentAddressedChunk(payloadBytes: Uint8Array | string, spanOverride?: Span | bigint): ContentAddressedChunk;
@@ -0,0 +1,10 @@
1
+ export declare const MIN_PAYLOAD_SIZE = 0;
2
+ export declare const MAX_PAYLOAD_SIZE = 4096;
3
+ export declare const SPAN_SIZE = 8;
4
+ export declare const UNENCRYPTED_REF_SIZE = 32;
5
+ export declare const ENCRYPTED_REF_SIZE = 64;
6
+ export declare const IDENTIFIER_SIZE = 32;
7
+ export declare const SIGNATURE_SIZE = 65;
8
+ export declare const SOC_HEADER_SIZE: number;
9
+ export declare const DEFAULT_DOWNLOAD_CONCURRENCY = 64;
10
+ export declare const DEFAULT_UPLOAD_CONCURRENCY = 8;
@@ -0,0 +1,47 @@
1
+ import { Bytes, Reference, Span } from "@ethersphere/bee-js";
2
+ import { type Key } from "./encryption";
3
+ /**
4
+ * Encrypted chunk interface
5
+ *
6
+ * The reference includes both the chunk address and the encryption key (64 bytes total)
7
+ */
8
+ export interface EncryptedChunk {
9
+ readonly data: Uint8Array;
10
+ readonly encryptionKey: Key;
11
+ readonly span: Span;
12
+ readonly payload: Bytes;
13
+ readonly address: Reference;
14
+ readonly reference: Reference;
15
+ }
16
+ /**
17
+ * Creates an encrypted content addressed chunk
18
+ *
19
+ * Process:
20
+ * 1. Create chunk with span + payload
21
+ * 2. Encrypt the chunk data
22
+ * 3. Calculate BMT hash on encrypted data
23
+ * 4. Return reference = address + encryption key (64 bytes)
24
+ *
25
+ * @param payloadBytes the data to be stored in the chunk
26
+ * @param encryptionKey optional encryption key (if not provided, a random key will be generated)
27
+ */
28
+ export declare function makeEncryptedContentAddressedChunk(payloadBytes: Uint8Array | string, encryptionKey?: Key): EncryptedChunk;
29
+ /**
30
+ * Decrypts an encrypted chunk given the encryption key
31
+ *
32
+ * @param encryptedChunkData The encrypted chunk data (span + payload)
33
+ * @param encryptionKey The 32-byte encryption key
34
+ */
35
+ export declare function decryptEncryptedChunk(encryptedChunkData: Uint8Array, encryptionKey: Key): Uint8Array;
36
+ /**
37
+ * Extracts encryption key from a 64-byte encrypted reference
38
+ *
39
+ * @param reference 64-byte reference (address + key)
40
+ */
41
+ export declare function extractEncryptionKey(reference: Reference): Key;
42
+ /**
43
+ * Extracts the chunk address from a 64-byte encrypted reference
44
+ *
45
+ * @param reference 64-byte reference (address + key)
46
+ */
47
+ export declare function extractChunkAddress(reference: Reference): Reference;
@@ -0,0 +1,85 @@
1
+ export declare const KEY_LENGTH = 32;
2
+ export declare const REFERENCE_SIZE = 64;
3
+ export type Key = Uint8Array;
4
+ export interface Encrypter {
5
+ key(): Key;
6
+ encrypt(data: Uint8Array): Uint8Array;
7
+ }
8
+ export interface Decrypter {
9
+ key(): Key;
10
+ decrypt(data: Uint8Array): Uint8Array;
11
+ }
12
+ export interface EncryptionInterface extends Encrypter, Decrypter {
13
+ reset(): void;
14
+ }
15
+ /**
16
+ * Core encryption class implementing CTR-mode encryption with Keccak256
17
+ * This matches the Go implementation in bee/pkg/encryption/encryption.go
18
+ */
19
+ export declare class Encryption implements EncryptionInterface {
20
+ private readonly encryptionKey;
21
+ private readonly keyLen;
22
+ private readonly padding;
23
+ private index;
24
+ private readonly initCtr;
25
+ constructor(key: Key, padding: number, initCtr: number);
26
+ key(): Key;
27
+ /**
28
+ * Encrypts data with optional padding
29
+ */
30
+ encrypt(data: Uint8Array): Uint8Array;
31
+ /**
32
+ * Decrypts data (caller must know original length if padding was used)
33
+ */
34
+ decrypt(data: Uint8Array): Uint8Array;
35
+ /**
36
+ * Resets the counter - only safe to call after encryption/decryption is completed
37
+ */
38
+ reset(): void;
39
+ /**
40
+ * Transforms data by splitting into key-length segments and encrypting sequentially
41
+ */
42
+ private transform;
43
+ /**
44
+ * Segment-wise transformation using XOR with Keccak256-derived keys
45
+ * Matches the Go implementation's Transcrypt function
46
+ */
47
+ private transcrypt;
48
+ }
49
+ /**
50
+ * Generates a cryptographically secure random key
51
+ */
52
+ export declare function generateRandomKey(length?: number): Key;
53
+ /**
54
+ * Creates encryption interface for chunk span (first 8 bytes)
55
+ */
56
+ export declare function newSpanEncryption(key: Key): EncryptionInterface;
57
+ /**
58
+ * Creates encryption interface for chunk data
59
+ */
60
+ export declare function newDataEncryption(key: Key): EncryptionInterface;
61
+ export interface ChunkEncrypter {
62
+ encryptChunk(chunkData: Uint8Array, key?: Key): {
63
+ key: Key;
64
+ encryptedSpan: Uint8Array;
65
+ encryptedData: Uint8Array;
66
+ };
67
+ }
68
+ /**
69
+ * Default chunk encrypter implementation
70
+ */
71
+ export declare class DefaultChunkEncrypter implements ChunkEncrypter {
72
+ encryptChunk(chunkData: Uint8Array, key?: Key): {
73
+ key: Key;
74
+ encryptedSpan: Uint8Array;
75
+ encryptedData: Uint8Array;
76
+ };
77
+ }
78
+ /**
79
+ * Creates a new chunk encrypter
80
+ */
81
+ export declare function newChunkEncrypter(): ChunkEncrypter;
82
+ /**
83
+ * Decrypts encrypted chunk data using the provided encryption key
84
+ */
85
+ export declare function decryptChunkData(key: Key, encryptedChunkData: Uint8Array): Uint8Array;
@@ -0,0 +1,5 @@
1
+ export { MIN_PAYLOAD_SIZE, MAX_PAYLOAD_SIZE, SPAN_SIZE, UNENCRYPTED_REF_SIZE, ENCRYPTED_REF_SIZE, IDENTIFIER_SIZE, SIGNATURE_SIZE, SOC_HEADER_SIZE, DEFAULT_DOWNLOAD_CONCURRENCY, DEFAULT_UPLOAD_CONCURRENCY, } from "./constants";
2
+ export { type Key, type ChunkEncrypter, type Encrypter, type Decrypter, type EncryptionInterface, KEY_LENGTH, REFERENCE_SIZE, newChunkEncrypter, decryptChunkData, generateRandomKey, newSpanEncryption, newDataEncryption, Encryption, DefaultChunkEncrypter, } from "./encryption";
3
+ export { calculateChunkAddress } from "./bmt";
4
+ export { type ContentAddressedChunk, makeContentAddressedChunk } from "./cac";
5
+ export { type EncryptedChunk, makeEncryptedContentAddressedChunk, decryptEncryptedChunk, extractEncryptionKey, extractChunkAddress, } from "./encrypted-cac";