@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,164 @@
1
+ import { MantarayNode } from "@ethersphere/core-sdk";
2
+ /**
3
+ * Result of building a /bzz/-compatible manifest.
4
+ *
5
+ * This is a FLAT manifest with no child nodes - just the root manifest.
6
+ * Bee's /bzz/ endpoint can directly resolve paths from this structure.
7
+ *
8
+ * IMPORTANT: The `data` field contains RAW manifest bytes (without span prefix).
9
+ * When uploaded via `uploadData()`, span will be added and the resulting address
10
+ * will match the pre-computed `address` field.
11
+ */
12
+ export interface BzzCompatibleManifestResult {
13
+ /** The manifest chunk to upload. Raw bytes, no span. */
14
+ manifestChunk: {
15
+ data: Uint8Array;
16
+ address: string;
17
+ };
18
+ }
19
+ /**
20
+ * Build a /bzz/-compatible flat manifest with VALUE forks.
21
+ *
22
+ * Creates a flat manifest with two VALUE forks at root level:
23
+ * - "/" → VALUE fork with website-index-document metadata pointing to NULL
24
+ * - "index.bin" → VALUE fork pointing directly to content reference
25
+ *
26
+ * This is built manually because bee-js MantarayNode always creates EDGE forks
27
+ * with child nodes, which causes Bee to fail to resolve the content.
28
+ *
29
+ * When Bee accesses /bzz/manifest/:
30
+ * 1. Finds "/" fork, reads website-index-document metadata
31
+ * 2. Looks up "index.bin" fork at root level
32
+ * 3. "index.bin" is VALUE type → serves content directly
33
+ *
34
+ * Binary format (Mantaray v0.2):
35
+ * - obfuscationKey (32 bytes): All zeros for no obfuscation
36
+ * - versionHash (31 bytes): MANTARAY_VERSION_HASH
37
+ * - refBytesCount (1 byte): 32
38
+ * - entry (32 bytes): All zeros (root has no entry)
39
+ * - indexBitmap (32 bytes): Bits set for '/' (47) and 'i' (105)
40
+ * - fork1 (64+ bytes): "/" fork with metadata
41
+ * - fork2 (64+ bytes): "index.bin" fork with metadata
42
+ *
43
+ * @param contentReference - Reference to the actual content (32 bytes / 64 hex chars)
44
+ * @returns Single manifest chunk to upload
45
+ */
46
+ export declare function buildBzzCompatibleManifest(contentReference: string | Uint8Array): Promise<BzzCompatibleManifestResult>;
47
+ /**
48
+ * Result of building a /bzz/-compatible MantarayNode manifest.
49
+ */
50
+ export interface BzzManifestNodeResult {
51
+ /** The MantarayNode to be uploaded with saveMantarayTreeRecursively */
52
+ manifestNode: MantarayNode;
53
+ }
54
+ /**
55
+ * Build a /bzz/-compatible manifest as a MantarayNode.
56
+ *
57
+ * This function creates a MantarayNode with the proper structure for /bzz/ access:
58
+ * - "/" fork with website-index-document metadata pointing to "index.bin"
59
+ * - "index.bin" fork pointing to the actual content reference
60
+ *
61
+ * IMPORTANT: After calling this function, use saveMantarayTreeRecursively() to
62
+ * upload the manifest. This ensures all child nodes are uploaded bottom-up and
63
+ * their addresses are correctly set from Bee's responses.
64
+ *
65
+ * Usage:
66
+ * ```typescript
67
+ * const { manifestNode } = buildBzzManifestNode(contentReference)
68
+ * const result = await saveMantarayTreeRecursively(manifestNode, async (data, isRoot) => {
69
+ * const uploadResult = await uploadData(bee, stamper, data, uploadOptions)
70
+ * return { reference: uploadResult.reference }
71
+ * })
72
+ * // result.rootReference is the /bzz/ compatible manifest address
73
+ * ```
74
+ *
75
+ * @param contentReference - Reference to the actual content (32 bytes / 64 hex chars)
76
+ * @returns MantarayNode ready for upload with saveMantarayTreeRecursively
77
+ */
78
+ export declare function buildBzzManifestNode(contentReference: string | Uint8Array): BzzManifestNodeResult;
79
+ /**
80
+ * @deprecated Use buildBzzManifestNode() with saveMantarayTreeRecursively() instead.
81
+ * This function manually builds binary format but doesn't upload child nodes,
82
+ * which causes Bee to fail to resolve content via /bzz/.
83
+ */
84
+ /**
85
+ * @deprecated Use buildBzzCompatibleManifest() for /bzz/ compatibility.
86
+ * This function creates a manifest that won't work with Bee's /bzz/ endpoint
87
+ * because it embeds the content reference directly in the manifest instead
88
+ * of using the proper two-level structure (root → child → content).
89
+ *
90
+ * Build a minimal mantaray manifest for /bzz/ feed compatibility.
91
+ *
92
+ * This creates a manifest with a single "/" fork pointing to a content reference.
93
+ * The manifest is built manually (not using bee-js MantarayNode.marshal()) because
94
+ * bee-js doesn't embed the targetAddress correctly for value-type nodes.
95
+ *
96
+ * Binary format (Mantaray v0.2):
97
+ * - obfuscationKey (32 bytes): All zeros for no obfuscation
98
+ * - versionHash (31 bytes): MANTARAY_VERSION_HASH
99
+ * - refBytesCount (1 byte): 32 (size of entry reference)
100
+ * - entry (32 bytes): All zeros (root has no entry)
101
+ * - indexBitmap (32 bytes): Bitmap with bit 47 set (for '/')
102
+ * - fork (64+ bytes): flags + prefixLen + prefix(30) + reference(32) + metadata
103
+ *
104
+ * @param contentReference - Reference to the actual content (32 bytes / 64 hex chars)
105
+ * @returns Marshaled manifest bytes
106
+ */
107
+ export declare function buildMinimalManifest(contentReference: string | Uint8Array): Uint8Array;
108
+ /**
109
+ * Extract content reference from a minimal mantaray manifest.
110
+ *
111
+ * This is the reverse of buildMinimalManifest() - it parses the manifest
112
+ * binary format and extracts the "/" fork's targetAddress.
113
+ *
114
+ * Binary format (Mantaray v0.2):
115
+ * - Offset 0-31: obfuscationKey
116
+ * - Offset 32-62: versionHash (31 bytes)
117
+ * - Offset 63: refBytesCount
118
+ * - Offset 64-95: entry (refBytesCount bytes, assuming 32)
119
+ * - Offset 96-127: indexBitmap
120
+ * - Offset 128+: forks (flags + prefixLen + prefix + reference + metadata)
121
+ *
122
+ * For a minimal manifest with just "/" fork:
123
+ * - Fork flags at offset 128
124
+ * - Prefix length at offset 129
125
+ * - Prefix (30 bytes) at offset 130
126
+ * - Reference (32 bytes) at offset 160
127
+ *
128
+ * @param manifestData - Raw manifest bytes (from feed payload)
129
+ * @returns Content reference as 64 hex characters
130
+ */
131
+ export declare function extractReferenceFromManifest(manifestData: Uint8Array): string;
132
+ /**
133
+ * Extract entry (targetAddress) from a leaf manifest node.
134
+ *
135
+ * In Mantaray v0.2, leaf nodes store their targetAddress in the entry field
136
+ * (bytes 64-95), not in a fork. This is used for the second level of parsing
137
+ * when using buildBzzCompatibleManifest().
138
+ *
139
+ * Binary format (Mantaray v0.2):
140
+ * - Offset 0-31: obfuscationKey
141
+ * - Offset 32-62: versionHash (31 bytes)
142
+ * - Offset 63: refBytesCount
143
+ * - Offset 64-95: entry (32 bytes) ← targetAddress for leaf nodes
144
+ * - Offset 96-127: indexBitmap
145
+ * - Offset 128+: forks
146
+ *
147
+ * @param manifestData - Raw manifest bytes (child chunk data from two-level structure)
148
+ * @returns Content reference as 64 hex characters
149
+ */
150
+ export declare function extractEntryFromManifest(manifestData: Uint8Array): string;
151
+ /**
152
+ * Extract content reference from a flat /bzz/-compatible manifest.
153
+ *
154
+ * In the flat structure, the manifest has:
155
+ * - "/" fork with NULL_ADDRESS and website-index-document metadata
156
+ * - "index.bin" fork with VALUE type pointing to content reference
157
+ *
158
+ * This function looks for the "index.bin" fork ('i' = ASCII 105) and
159
+ * extracts its reference.
160
+ *
161
+ * @param manifestData - Raw manifest bytes (flat manifest)
162
+ * @returns Content reference as 64 hex characters
163
+ */
164
+ export declare function extractContentFromFlatManifest(manifestData: Uint8Array): string;
@@ -0,0 +1,76 @@
1
+ import { MantarayNode } from "@ethersphere/core-sdk";
2
+ import type { Bee, BeeRequestOptions } from "@ethersphere/bee-js";
3
+ /**
4
+ * Upload callback type for saveMantarayTreeRecursively
5
+ */
6
+ export type UploadCallback = (data: Uint8Array, isRoot: boolean) => Promise<{
7
+ reference: string;
8
+ tagUid?: number;
9
+ }>;
10
+ /**
11
+ * Save a Mantaray tree by uploading bottom-up
12
+ *
13
+ * This mirrors MantarayNode.saveRecursively() but allows custom upload logic
14
+ * and uses Bee's returned references to avoid address mismatches.
15
+ *
16
+ * This is the variant that is safe to use from outside the proxy: the callback
17
+ * receives a marshaled node payload and hands back the reference it was stored
18
+ * under, so any uploader that wraps a payload in a chunk of its own fits.
19
+ * `SwarmIdClient.uploadData` is the one to reach for — `uploadChunk` fits the
20
+ * contract too, but a node payload over its 4 KB chunk limit (a wide directory)
21
+ * fails there, which is why the demo's feed upload uses `uploadData`.
22
+ */
23
+ export declare function saveMantarayTreeRecursively(node: MantarayNode, uploadFn: UploadCallback): Promise<{
24
+ rootReference: string;
25
+ tagUid?: number;
26
+ }>;
27
+ /**
28
+ * Options for saveMantarayTree
29
+ */
30
+ export interface SaveMantarayOptions {
31
+ /** Encrypt manifest chunks (64-byte references with address + key) */
32
+ encrypt?: boolean;
33
+ }
34
+ /**
35
+ * Upload callback for saveMantarayTree
36
+ *
37
+ * @param chunkData - A finished content-addressed chunk, span header included;
38
+ * it must be stored exactly as given, not wrapped in another chunk
39
+ * @param isRoot - Whether this is the root node
40
+ * @returns Upload result with optional tag UID
41
+ */
42
+ export type MantarayUploadCallback = (chunkData: Uint8Array, isRoot: boolean) => Promise<{
43
+ tagUid?: number;
44
+ }>;
45
+ /**
46
+ * Save a Mantaray tree by uploading bottom-up with unified encryption support
47
+ *
48
+ * Proxy-internal, and deliberately not part of the package's public API.
49
+ *
50
+ * Creates CAC or encrypted CAC internally based on encrypt option.
51
+ * Returns 64-byte reference (address + key) when encrypted, 32-byte otherwise.
52
+ *
53
+ * `uploadFn` receives a finished content-addressed chunk built here, span
54
+ * header included, and each node's address is computed locally from those same
55
+ * bytes. The callback must therefore store them as-is: an uploader that treats
56
+ * its argument as a payload and wraps it in a new chunk stores every node under
57
+ * a different address than the tree records, which fails silently and leaves the
58
+ * returned root reference pointing at nothing. `SwarmIdClient.uploadChunk` wraps
59
+ * its input that way and cannot be used here; no public client method accepts a
60
+ * finished chunk. Outside the proxy, use `saveMantarayTreeRecursively` instead.
61
+ *
62
+ * @param node - Root Mantaray node to save
63
+ * @param uploadFn - Callback that uploads each finished chunk verbatim
64
+ * @param options - Optional settings (encrypt: boolean)
65
+ * @returns Root reference and optional tag UID
66
+ */
67
+ export declare function saveMantarayTree(node: MantarayNode, uploadFn: MantarayUploadCallback, options?: SaveMantarayOptions): Promise<{
68
+ rootReference: string;
69
+ tagUid?: number;
70
+ }>;
71
+ /**
72
+ * Load a Mantaray tree using only the chunk API.
73
+ *
74
+ * This avoids /bytes and supports encrypted references.
75
+ */
76
+ export declare function loadMantarayTreeWithChunkAPI(bee: Bee, rootReference: string, requestOptions?: BeeRequestOptions): Promise<MantarayNode>;
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Which slot each single-owner chunk an app had stamped went to. A chat sends
3
+ * every message as a new version of one inbox chunk, whose address never
4
+ * changes, and a mutable batch replaces a chunk stamped at the same slot with
5
+ * a newer timestamp. So stamping that address again reuses its slot instead
6
+ * of filling the bucket. The record is per app origin and per stamp, in the
7
+ * frame's own storage, and belongs to one lane of the stamp: when this device
8
+ * holds another lane the record starts empty, and a new slot is taken.
9
+ */
10
+ import { z } from "zod";
11
+ /** Single-owner chunk addresses remembered per app and stamp. Past it a new address takes a new slot each time */
12
+ export declare const SOC_RESTAMP_SLOT_LIMIT = 256;
13
+ /** One lane of the stamp: this device's partition and the account's partition count */
14
+ export interface StampLane {
15
+ partition: number;
16
+ partitionCount: number;
17
+ }
18
+ declare const SocRestampSlotsSchema: z.ZodObject<{
19
+ partition: z.ZodNumber;
20
+ partitionCount: z.ZodNumber;
21
+ slots: z.ZodRecord<z.ZodString, z.ZodObject<{
22
+ slot: z.ZodNumber;
23
+ timestampMs: z.ZodNumber;
24
+ }, z.core.$strip>>;
25
+ }, z.core.$strip>;
26
+ /** The slots one app's single-owner chunks hold in one lane of one stamp */
27
+ export type SocRestampSlots = z.infer<typeof SocRestampSlotsSchema>;
28
+ export declare function emptySocRestampSlots(lane: StampLane): SocRestampSlots;
29
+ /**
30
+ * The stored record for `lane`, or an empty one when there is none, it
31
+ * belongs to another lane, or it is malformed. Only the frame writes it, so a
32
+ * malformed one is a bug of ours and starts over, which only costs new slots.
33
+ */
34
+ export declare function parseSocRestampSlots(raw: string | null, lane: StampLane): SocRestampSlots;
35
+ /**
36
+ * The record once `addressHex` holds `slot` with a stamp at `timestampMs`.
37
+ * Unchanged when the record is full and the address is new.
38
+ */
39
+ export declare function recordSocSlot(record: SocRestampSlots, addressHex: string, slot: number, timestampMs: number): SocRestampSlots;
40
+ /**
41
+ * The timestamp for a stamp again at a slot whose last stamp had
42
+ * `previousMs`. Bee keeps the chunk with the newer stamp, so when the clock
43
+ * went back it is one millisecond past the last rather than now.
44
+ */
45
+ export declare function restampTimestamp(previousMs: number, now: number): number;
46
+ /** The slot in a stamp's 8-byte index, which is the bucket then the slot, big-endian */
47
+ export declare function slotOfStampIndex(index: Uint8Array): number;
48
+ export {};
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Stamp and return: the frame stamps a chunk with the account's own stamp
3
+ * and hands the stamp back, so the app sends the chunk through the Swarm
4
+ * access it chose. The app sends the whole chunk and the frame computes its
5
+ * address, so a stamp is only ever issued for bytes the frame has seen, and a
6
+ * single-owner chunk is only ever one the frame signed in the same request.
7
+ */
8
+ import { EthAddress } from "@ethersphere/bee-js";
9
+ import type { EnvelopeWithBatchId, Signature } from "@ethersphere/bee-js";
10
+ import type { StampChunkRequest } from "../types";
11
+ /** What the frame stamps: the address it computed, and a SOC's owner and signature */
12
+ export interface ChunkToStamp {
13
+ address: Uint8Array;
14
+ owner?: EthAddress;
15
+ signature?: Signature;
16
+ }
17
+ /** The account keys the internal owners are derived from */
18
+ export interface InternalOwnerKeys {
19
+ /** The account's own address */
20
+ accountAddress: string;
21
+ derivationKey: string;
22
+ /** The resolved stamp's signer, which an imported stamp may not derive */
23
+ postageSignerKey?: string;
24
+ }
25
+ /**
26
+ * Every owner address the account's own chunks may carry, lowercase hex. A
27
+ * single-owner chunk owned by one of these is refused, so an app can never be
28
+ * handed a stamp for the account's lock, partition state, device state or
29
+ * roster chunks (owned by the backup signer), nor sign as any other key the
30
+ * frame holds for the account.
31
+ */
32
+ export declare function accountInternalOwners(keys: InternalOwnerKeys): Set<string>;
33
+ /**
34
+ * Compute the address of the chunk to stamp, and sign it when it is a
35
+ * single-owner chunk.
36
+ *
37
+ * @throws SwarmIdError `invalid-request` for a chunk of the wrong length, or a
38
+ * single-owner chunk whose owner is one of `internalOwners`
39
+ */
40
+ export declare function prepareChunkToStamp(chunk: StampChunkRequest, context: {
41
+ appSecret: string;
42
+ internalOwners: ReadonlySet<string>;
43
+ }): ChunkToStamp;
44
+ /** A stamp in the form Bee's `swarm-postage-stamp` upload header takes */
45
+ export declare function marshalStamp(envelope: EnvelopeWithBatchId): string;
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Message types for main thread ↔ worker communication.
3
+ */
4
+ export interface StampWorkerInitMessage {
5
+ type: "init";
6
+ signerKeyHex: string;
7
+ }
8
+ export interface StampWorkerSignMessage {
9
+ type: "sign";
10
+ id: number;
11
+ message: Uint8Array;
12
+ }
13
+ export interface StampWorkerReadyResponse {
14
+ type: "ready";
15
+ issuerHex: string;
16
+ }
17
+ export interface StampWorkerSignedResponse {
18
+ type: "signed";
19
+ id: number;
20
+ signatureHex: string;
21
+ }
22
+ export type StampWorkerMessage = StampWorkerInitMessage | StampWorkerSignMessage;
23
+ export type StampWorkerResponse = StampWorkerReadyResponse | StampWorkerSignedResponse;
24
+ /**
25
+ * Handle an incoming message from the main thread.
26
+ *
27
+ * Replicates core-sdk's `PrivateKey.sign()`:
28
+ * 1. digest = concat(ETH_PREFIX, keccak256(message))
29
+ * 2. [r, s, v] = Elliptic.signMessage(digest, privateKey)
30
+ * 3. signature = concat(r[32], s[32], v[1])
31
+ */
32
+ export declare function handleMessage(msg: StampWorkerMessage): StampWorkerResponse;
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Web Worker pool for parallel stamp signing.
3
+ *
4
+ * Architecture:
5
+ * - Main thread: slot assignment (fast, stateful, sequential)
6
+ * - Workers: ECDSA signing (slow, stateless, parallel)
7
+ *
8
+ * The pool only signs. The slot comes from the stamper it was created for — a
9
+ * `SlotAssigner`'s `assignSlot()`, or a plain core-sdk `Stamper`'s `buckets` —
10
+ * so a pooled stamp lands where `stamper.stamp()` would have put it.
11
+ */
12
+ import type { Stamper, EnvelopeWithBatchId } from "@ethersphere/bee-js";
13
+ import type { SlotAssigner } from "../utils/batch-utilization";
14
+ export declare class StampWorkerPool {
15
+ private workers;
16
+ private nextWorker;
17
+ private nextId;
18
+ private issuer;
19
+ private batchId;
20
+ private assignSlot;
21
+ readonly size: number;
22
+ /** The stamper this pool signs for: a pool must not outlive it. */
23
+ readonly stamper: Stamper | SlotAssigner;
24
+ private constructor();
25
+ /**
26
+ * Create a worker pool from an existing stamper.
27
+ *
28
+ * @param signerKeyHex - Signer private key as hex (proxy already has this)
29
+ * @param stamper - Stamper the pool signs for; it stays the slot owner
30
+ * @param workerCount - Number of workers (defaults to 4)
31
+ */
32
+ static create(signerKeyHex: string, stamper: Stamper | SlotAssigner, workerCount?: number): Promise<StampWorkerPool>;
33
+ /**
34
+ * Stamp a chunk address using parallel worker signing.
35
+ *
36
+ * Slot assignment happens on the main thread, before the first await, so
37
+ * concurrent calls cannot interleave inside it. ECDSA signing is dispatched
38
+ * to a worker (slow, parallel).
39
+ *
40
+ * Takes the same `timestampMs` as core-sdk's `Stamper.stamp`, and produces
41
+ * the same envelope for the same inputs — `stamp-worker-pool.test.ts` holds
42
+ * the two to that, field by field.
43
+ */
44
+ stampChunkData(address: Uint8Array, timestampMs?: number): Promise<EnvelopeWithBatchId>;
45
+ private dispatchSign;
46
+ /**
47
+ * Terminate all workers and release resources. Signs still in flight are
48
+ * rejected: a terminated worker never answers, and an upload awaiting one
49
+ * would hang.
50
+ */
51
+ terminate(): void;
52
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,38 @@
1
+ import type { Bee, Stamper } from "@ethersphere/bee-js";
2
+ import type { StampWorkerPool } from "./stamp-worker-pool";
3
+ /**
4
+ * Upload context shared across handlers
5
+ */
6
+ export interface UploadContext {
7
+ bee: Bee;
8
+ stamper: Stamper;
9
+ workerPool?: StampWorkerPool;
10
+ }
11
+ /**
12
+ * Upload progress information
13
+ */
14
+ export interface UploadProgress {
15
+ total: number;
16
+ processed: number;
17
+ }
18
+ /**
19
+ * Chunk reference (32-byte address)
20
+ */
21
+ export interface ChunkReference {
22
+ address: Uint8Array;
23
+ span?: bigint;
24
+ }
25
+ /**
26
+ * Encrypted chunk reference (64-byte reference: address + encryption key)
27
+ */
28
+ export interface EncryptedChunkReference {
29
+ address: Uint8Array;
30
+ key: Uint8Array;
31
+ }
32
+ /**
33
+ * Options for WebSocket-based chunk upload
34
+ */
35
+ export interface WebSocketUploadOptions {
36
+ /** WebSocket concurrency (in-flight chunks). Defaults to 32. */
37
+ concurrency?: number;
38
+ }
@@ -0,0 +1,207 @@
1
+ import { Reference, PrivateKey, Identifier } from "@ethersphere/bee-js";
2
+ import type { Bee, BeeRequestOptions, Stamper, UploadOptions, EnvelopeWithBatchId } from "@ethersphere/bee-js";
3
+ import { type ContentAddressedChunk, type EncryptedChunk } from "../chunk";
4
+ import type { ChunkReference, UploadProgress } from "./types";
5
+ import type { StampWorkerPool } from "./stamp-worker-pool";
6
+ /**
7
+ * Thrown when a SOC upload gets a non-OK HTTP response. Carries the numeric
8
+ * `status` so callers can distinguish a definitive stamp rejection (400) from a
9
+ * transient / not-yet-synced condition (404 "batch not found", 422 "not usable
10
+ * yet") without regex-matching the message — see `verifyBatchStampable`.
11
+ */
12
+ export declare class SocUploadError extends Error {
13
+ readonly status: number;
14
+ /** What the node or gateway answered, for the bridge's `beeMessage` (#761) */
15
+ readonly body: string;
16
+ constructor(status: number, statusText: string, body: string);
17
+ }
18
+ /**
19
+ * Upload target: stamper-based (user has postage batch) or subsidised gateway
20
+ */
21
+ export type UploadTarget = {
22
+ mode: "stamper";
23
+ bee: Bee;
24
+ stamper: Stamper;
25
+ workerPool?: StampWorkerPool;
26
+ } | {
27
+ mode: "subsidised";
28
+ gatewayUrl: string;
29
+ };
30
+ /**
31
+ * Type guard for stamper target
32
+ */
33
+ export declare function isStamperTarget(target: UploadTarget): target is UploadTarget & {
34
+ mode: "stamper";
35
+ };
36
+ /**
37
+ * Type guard for subsidised target
38
+ */
39
+ export declare function isSubsidisedTarget(target: UploadTarget): target is UploadTarget & {
40
+ mode: "subsidised";
41
+ };
42
+ /**
43
+ * Unified options for data upload
44
+ */
45
+ export interface UploadDataOptions {
46
+ /**
47
+ * Encryption key: undefined = plain, Uint8Array = use this key, true =
48
+ * auto-generate. An explicit key only applies to single-chunk data
49
+ * (≤ 4096 bytes); larger data throws — pass true instead.
50
+ */
51
+ encryptionKey?: Uint8Array | true;
52
+ /** Pin the uploaded data (stamper mode only; a subsidised gateway never sees it, #752) */
53
+ pin?: boolean;
54
+ /** Use deferred upload mode */
55
+ deferred?: boolean;
56
+ /** Tag for tracking upload progress */
57
+ tag?: number;
58
+ /** WebSocket upload options (stamper mode only) */
59
+ webSocket?: {
60
+ concurrency?: number;
61
+ };
62
+ /** HTTP concurrency for parallel uploads */
63
+ httpConcurrency?: number;
64
+ /** Progress callback */
65
+ onProgress?: (progress: UploadProgress) => void;
66
+ /** Bee request options (stamper mode only) */
67
+ requestOptions?: BeeRequestOptions;
68
+ }
69
+ /**
70
+ * Result of uploading data
71
+ */
72
+ export interface UploadDataResult {
73
+ /** Reference to the uploaded data (32-byte hex for plain, 64-byte for encrypted) */
74
+ reference: string;
75
+ /** Tag UID if one was created */
76
+ tagUid?: number;
77
+ /** Addresses of all uploaded chunks (encrypted mode only) */
78
+ chunkAddresses?: Uint8Array[];
79
+ }
80
+ /**
81
+ * Options for SOC upload
82
+ */
83
+ export interface UploadSOCOptions {
84
+ /** Encryption key: undefined = plain SOC, Uint8Array = use this key, true = auto-generate */
85
+ encryptionKey?: Uint8Array | true;
86
+ /** Pin the uploaded SOC (stamper mode only; a subsidised gateway never sees it, #752) */
87
+ pin?: boolean;
88
+ /** Use deferred upload mode */
89
+ deferred?: boolean;
90
+ /** Tag for tracking */
91
+ tag?: number;
92
+ /** Bee request options (stamper mode only) */
93
+ requestOptions?: BeeRequestOptions;
94
+ }
95
+ /**
96
+ * Result of uploading a SOC
97
+ */
98
+ export interface UploadSOCResult {
99
+ /** SOC address (32 bytes) */
100
+ socAddress: Uint8Array;
101
+ /** Encryption key (only for encrypted SOCs) */
102
+ encryptionKey?: Uint8Array;
103
+ /** Tag UID if one was created */
104
+ tagUid?: number;
105
+ }
106
+ /**
107
+ * Options for single chunk upload
108
+ */
109
+ export interface UploadChunkOptions {
110
+ /** Pin the uploaded chunk (stamper mode only; a subsidised gateway never sees it, #752) */
111
+ pin?: boolean;
112
+ /** Use deferred upload mode */
113
+ deferred?: boolean;
114
+ /** Tag for tracking */
115
+ tag?: number;
116
+ /** Bee request options (stamper mode only) */
117
+ requestOptions?: BeeRequestOptions;
118
+ }
119
+ /**
120
+ * Result of uploading a chunk
121
+ */
122
+ export interface UploadChunkResult {
123
+ /** Chunk reference (address) */
124
+ reference: string;
125
+ }
126
+ /**
127
+ * Async stamp function - abstraction over sync Stamper and parallel StampWorkerPool.
128
+ */
129
+ type StampChunkFn = (address: Uint8Array) => Promise<EnvelopeWithBatchId>;
130
+ /**
131
+ * Create a StampChunkFn from a Stamper and optional worker pool.
132
+ */
133
+ declare function makeStampFn(stamper: Stamper, workerPool?: StampWorkerPool): StampChunkFn;
134
+ interface EncryptedChunkRef {
135
+ address: Uint8Array;
136
+ key: Uint8Array;
137
+ span: bigint;
138
+ }
139
+ /**
140
+ * Encrypt all payloads into EncryptedChunks and collect their references.
141
+ *
142
+ * An explicit key is only valid for a single payload: every chunk of a
143
+ * multi-chunk upload carries its own key, so honouring one shared key is
144
+ * impossible and substituting random keys would silently break the caller's
145
+ * expectation of a key-addressed reference.
146
+ */
147
+ declare function encryptChunkPayloads(payloads: Uint8Array[], encryptionKey?: Uint8Array): {
148
+ chunks: EncryptedChunk[];
149
+ refs: EncryptedChunkRef[];
150
+ };
151
+ /**
152
+ * Upload a single stamped chunk via HTTP (stamper mode).
153
+ */
154
+ declare function uploadStampedChunkViaHttp(bee: Bee, stamp: StampChunkFn, chunkData: Uint8Array, address: Uint8Array, options: UploadOptions, requestOptions?: BeeRequestOptions): Promise<void>;
155
+ /**
156
+ * Upload a chunk via subsidised gateway (no stamp required).
157
+ */
158
+ declare function uploadChunkViaSubsidisedGatewayInternal(gatewayUrl: string, chunkData: Uint8Array, options?: {
159
+ deferred?: boolean;
160
+ }): Promise<{
161
+ reference: string;
162
+ }>;
163
+ /**
164
+ * Build merkle tree from plain chunk references.
165
+ * Returns 32-byte root reference.
166
+ */
167
+ declare function buildPlainMerkleTree(chunkRefs: ChunkReference[], uploadIntermediate: (chunk: ContentAddressedChunk) => Promise<void>): Promise<Reference>;
168
+ /**
169
+ * Build merkle tree from encrypted chunk references.
170
+ * Returns 64-byte root reference (address + encryption key).
171
+ */
172
+ declare function buildEncryptedMerkleTree(refs: EncryptedChunkRef[], uploadIntermediate: (chunkData: Uint8Array) => Promise<void>): Promise<Reference>;
173
+ /**
174
+ * Upload data to Swarm.
175
+ *
176
+ * This is the unified entry point for all data uploads:
177
+ * - Plain or encrypted (via encryptionKey option)
178
+ * - Stamper-based or subsidised gateway (via target)
179
+ * - HTTP or WebSocket transport (via webSocket option)
180
+ *
181
+ * @param target - Upload target (stamper or subsidised gateway)
182
+ * @param data - Data to upload
183
+ * @param options - Upload options
184
+ * @returns Upload result with reference
185
+ */
186
+ export declare function uploadData(target: UploadTarget, data: Uint8Array, options?: UploadDataOptions): Promise<UploadDataResult>;
187
+ /**
188
+ * Upload a Single Owner Chunk (SOC).
189
+ *
190
+ * @param target - Upload target (stamper or subsidised gateway)
191
+ * @param signer - Private key for signing the SOC
192
+ * @param identifier - SOC identifier
193
+ * @param data - Chunk payload (1-4096 bytes)
194
+ * @param options - Upload options
195
+ * @returns SOC address and optional encryption key
196
+ */
197
+ export declare function uploadSOC(target: UploadTarget, signer: PrivateKey, identifier: Identifier, data: Uint8Array, options?: UploadSOCOptions): Promise<UploadSOCResult>;
198
+ /**
199
+ * Upload a single pre-built chunk.
200
+ *
201
+ * @param target - Upload target (stamper or subsidised gateway)
202
+ * @param chunkData - Full chunk data (span + payload)
203
+ * @param options - Upload options
204
+ * @returns Chunk reference
205
+ */
206
+ export declare function uploadChunk(target: UploadTarget, chunkData: Uint8Array, options?: UploadChunkOptions): Promise<UploadChunkResult>;
207
+ export { uploadChunkViaSubsidisedGatewayInternal, uploadStampedChunkViaHttp, makeStampFn, buildPlainMerkleTree, buildEncryptedMerkleTree, encryptChunkPayloads, type EncryptedChunkRef, type StampChunkFn, };