@snaha/swarm-id 0.0.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.
- package/README.md +431 -0
- package/dist/chunk/bmt.d.ts +17 -0
- package/dist/chunk/bmt.d.ts.map +1 -0
- package/dist/chunk/cac.d.ts +18 -0
- package/dist/chunk/cac.d.ts.map +1 -0
- package/dist/chunk/constants.d.ts +10 -0
- package/dist/chunk/constants.d.ts.map +1 -0
- package/dist/chunk/encrypted-cac.d.ts +48 -0
- package/dist/chunk/encrypted-cac.d.ts.map +1 -0
- package/dist/chunk/encryption.d.ts +86 -0
- package/dist/chunk/encryption.d.ts.map +1 -0
- package/dist/chunk/index.d.ts +6 -0
- package/dist/chunk/index.d.ts.map +1 -0
- package/dist/index.d.ts +46 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/proxy/act/act.d.ts +78 -0
- package/dist/proxy/act/act.d.ts.map +1 -0
- package/dist/proxy/act/crypto.d.ts +44 -0
- package/dist/proxy/act/crypto.d.ts.map +1 -0
- package/dist/proxy/act/grantee-list.d.ts +82 -0
- package/dist/proxy/act/grantee-list.d.ts.map +1 -0
- package/dist/proxy/act/history.d.ts +183 -0
- package/dist/proxy/act/history.d.ts.map +1 -0
- package/dist/proxy/act/index.d.ts +104 -0
- package/dist/proxy/act/index.d.ts.map +1 -0
- package/dist/proxy/chunking-encrypted.d.ts +14 -0
- package/dist/proxy/chunking-encrypted.d.ts.map +1 -0
- package/dist/proxy/chunking.d.ts +15 -0
- package/dist/proxy/chunking.d.ts.map +1 -0
- package/dist/proxy/download-data.d.ts +16 -0
- package/dist/proxy/download-data.d.ts.map +1 -0
- package/dist/proxy/feed-manifest.d.ts +62 -0
- package/dist/proxy/feed-manifest.d.ts.map +1 -0
- package/dist/proxy/feeds/epochs/async-finder.d.ts +77 -0
- package/dist/proxy/feeds/epochs/async-finder.d.ts.map +1 -0
- package/dist/proxy/feeds/epochs/epoch.d.ts +88 -0
- package/dist/proxy/feeds/epochs/epoch.d.ts.map +1 -0
- package/dist/proxy/feeds/epochs/finder.d.ts +67 -0
- package/dist/proxy/feeds/epochs/finder.d.ts.map +1 -0
- package/dist/proxy/feeds/epochs/index.d.ts +35 -0
- package/dist/proxy/feeds/epochs/index.d.ts.map +1 -0
- package/dist/proxy/feeds/epochs/test-utils.d.ts +93 -0
- package/dist/proxy/feeds/epochs/test-utils.d.ts.map +1 -0
- package/dist/proxy/feeds/epochs/types.d.ts +109 -0
- package/dist/proxy/feeds/epochs/types.d.ts.map +1 -0
- package/dist/proxy/feeds/epochs/updater.d.ts +68 -0
- package/dist/proxy/feeds/epochs/updater.d.ts.map +1 -0
- package/dist/proxy/feeds/epochs/utils.d.ts +22 -0
- package/dist/proxy/feeds/epochs/utils.d.ts.map +1 -0
- package/dist/proxy/feeds/index.d.ts +5 -0
- package/dist/proxy/feeds/index.d.ts.map +1 -0
- package/dist/proxy/feeds/sequence/async-finder.d.ts +14 -0
- package/dist/proxy/feeds/sequence/async-finder.d.ts.map +1 -0
- package/dist/proxy/feeds/sequence/finder.d.ts +17 -0
- package/dist/proxy/feeds/sequence/finder.d.ts.map +1 -0
- package/dist/proxy/feeds/sequence/index.d.ts +23 -0
- package/dist/proxy/feeds/sequence/index.d.ts.map +1 -0
- package/dist/proxy/feeds/sequence/types.d.ts +80 -0
- package/dist/proxy/feeds/sequence/types.d.ts.map +1 -0
- package/dist/proxy/feeds/sequence/updater.d.ts +26 -0
- package/dist/proxy/feeds/sequence/updater.d.ts.map +1 -0
- package/dist/proxy/index.d.ts +6 -0
- package/dist/proxy/index.d.ts.map +1 -0
- package/dist/proxy/manifest-builder.d.ts +183 -0
- package/dist/proxy/manifest-builder.d.ts.map +1 -0
- package/dist/proxy/mantaray-encrypted.d.ts +27 -0
- package/dist/proxy/mantaray-encrypted.d.ts.map +1 -0
- package/dist/proxy/mantaray.d.ts +26 -0
- package/dist/proxy/mantaray.d.ts.map +1 -0
- package/dist/proxy/types.d.ts +29 -0
- package/dist/proxy/types.d.ts.map +1 -0
- package/dist/proxy/upload-data.d.ts +17 -0
- package/dist/proxy/upload-data.d.ts.map +1 -0
- package/dist/proxy/upload-encrypted-data.d.ts +103 -0
- package/dist/proxy/upload-encrypted-data.d.ts.map +1 -0
- package/dist/schemas.d.ts +240 -0
- package/dist/schemas.d.ts.map +1 -0
- package/dist/storage/debounced-uploader.d.ts +62 -0
- package/dist/storage/debounced-uploader.d.ts.map +1 -0
- package/dist/storage/utilization-store.d.ts +108 -0
- package/dist/storage/utilization-store.d.ts.map +1 -0
- package/dist/swarm-id-auth.d.ts +74 -0
- package/dist/swarm-id-auth.d.ts.map +1 -0
- package/dist/swarm-id-auth.js +2 -0
- package/dist/swarm-id-auth.js.map +1 -0
- package/dist/swarm-id-client.d.ts +878 -0
- package/dist/swarm-id-client.d.ts.map +1 -0
- package/dist/swarm-id-client.js +2 -0
- package/dist/swarm-id-client.js.map +1 -0
- package/dist/swarm-id-proxy.d.ts +236 -0
- package/dist/swarm-id-proxy.d.ts.map +1 -0
- package/dist/swarm-id-proxy.js +2 -0
- package/dist/swarm-id-proxy.js.map +1 -0
- package/dist/swarm-id.esm.js +2 -0
- package/dist/swarm-id.esm.js.map +1 -0
- package/dist/swarm-id.umd.js +2 -0
- package/dist/swarm-id.umd.js.map +1 -0
- package/dist/sync/index.d.ts +9 -0
- package/dist/sync/index.d.ts.map +1 -0
- package/dist/sync/key-derivation.d.ts +25 -0
- package/dist/sync/key-derivation.d.ts.map +1 -0
- package/dist/sync/restore-account.d.ts +28 -0
- package/dist/sync/restore-account.d.ts.map +1 -0
- package/dist/sync/serialization.d.ts +16 -0
- package/dist/sync/serialization.d.ts.map +1 -0
- package/dist/sync/store-interfaces.d.ts +53 -0
- package/dist/sync/store-interfaces.d.ts.map +1 -0
- package/dist/sync/sync-account.d.ts +44 -0
- package/dist/sync/sync-account.d.ts.map +1 -0
- package/dist/sync/types.d.ts +13 -0
- package/dist/sync/types.d.ts.map +1 -0
- package/dist/test-fixtures.d.ts +17 -0
- package/dist/test-fixtures.d.ts.map +1 -0
- package/dist/types-BD_VkNn0.js +2 -0
- package/dist/types-BD_VkNn0.js.map +1 -0
- package/dist/types-lJCaT-50.js +2 -0
- package/dist/types-lJCaT-50.js.map +1 -0
- package/dist/types.d.ts +2157 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/utils/account-payload.d.ts +94 -0
- package/dist/utils/account-payload.d.ts.map +1 -0
- package/dist/utils/account-state-snapshot.d.ts +38 -0
- package/dist/utils/account-state-snapshot.d.ts.map +1 -0
- package/dist/utils/backup-encryption.d.ts +127 -0
- package/dist/utils/backup-encryption.d.ts.map +1 -0
- package/dist/utils/batch-utilization.d.ts +432 -0
- package/dist/utils/batch-utilization.d.ts.map +1 -0
- package/dist/utils/constants.d.ts +11 -0
- package/dist/utils/constants.d.ts.map +1 -0
- package/dist/utils/hex.d.ts +17 -0
- package/dist/utils/hex.d.ts.map +1 -0
- package/dist/utils/key-derivation.d.ts +92 -0
- package/dist/utils/key-derivation.d.ts.map +1 -0
- package/dist/utils/storage-managers.d.ts +65 -0
- package/dist/utils/storage-managers.d.ts.map +1 -0
- package/dist/utils/swarm-id-export.d.ts +24 -0
- package/dist/utils/swarm-id-export.d.ts.map +1 -0
- package/dist/utils/ttl.d.ts +49 -0
- package/dist/utils/ttl.d.ts.map +1 -0
- package/dist/utils/url.d.ts +41 -0
- package/dist/utils/url.d.ts.map +1 -0
- package/dist/utils/versioned-storage.d.ts +131 -0
- package/dist/utils/versioned-storage.d.ts.map +1 -0
- package/package.json +78 -0
- package/src/chunk/bmt.test.ts +217 -0
- package/src/chunk/bmt.ts +57 -0
- package/src/chunk/cac.test.ts +214 -0
- package/src/chunk/cac.ts +65 -0
- package/src/chunk/constants.ts +18 -0
- package/src/chunk/encrypted-cac.test.ts +385 -0
- package/src/chunk/encrypted-cac.ts +131 -0
- package/src/chunk/encryption.test.ts +352 -0
- package/src/chunk/encryption.ts +300 -0
- package/src/chunk/index.ts +47 -0
- package/src/index.ts +430 -0
- package/src/proxy/act/act.test.ts +278 -0
- package/src/proxy/act/act.ts +158 -0
- package/src/proxy/act/bee-compat.test.ts +948 -0
- package/src/proxy/act/crypto.test.ts +436 -0
- package/src/proxy/act/crypto.ts +376 -0
- package/src/proxy/act/grantee-list.test.ts +393 -0
- package/src/proxy/act/grantee-list.ts +239 -0
- package/src/proxy/act/history.test.ts +360 -0
- package/src/proxy/act/history.ts +413 -0
- package/src/proxy/act/index.test.ts +748 -0
- package/src/proxy/act/index.ts +853 -0
- package/src/proxy/chunking-encrypted.ts +95 -0
- package/src/proxy/chunking.ts +65 -0
- package/src/proxy/download-data.ts +448 -0
- package/src/proxy/feed-manifest.ts +174 -0
- package/src/proxy/feeds/epochs/async-finder.ts +372 -0
- package/src/proxy/feeds/epochs/epoch.test.ts +249 -0
- package/src/proxy/feeds/epochs/epoch.ts +181 -0
- package/src/proxy/feeds/epochs/finder.ts +282 -0
- package/src/proxy/feeds/epochs/index.ts +73 -0
- package/src/proxy/feeds/epochs/integration.test.ts +1336 -0
- package/src/proxy/feeds/epochs/test-utils.ts +274 -0
- package/src/proxy/feeds/epochs/types.ts +128 -0
- package/src/proxy/feeds/epochs/updater.ts +192 -0
- package/src/proxy/feeds/epochs/utils.ts +62 -0
- package/src/proxy/feeds/index.ts +5 -0
- package/src/proxy/feeds/sequence/async-finder.ts +31 -0
- package/src/proxy/feeds/sequence/finder.ts +73 -0
- package/src/proxy/feeds/sequence/index.ts +54 -0
- package/src/proxy/feeds/sequence/integration.test.ts +966 -0
- package/src/proxy/feeds/sequence/types.ts +103 -0
- package/src/proxy/feeds/sequence/updater.ts +71 -0
- package/src/proxy/index.ts +5 -0
- package/src/proxy/manifest-builder.test.ts +427 -0
- package/src/proxy/manifest-builder.ts +679 -0
- package/src/proxy/mantaray-encrypted.ts +78 -0
- package/src/proxy/mantaray.ts +104 -0
- package/src/proxy/types.ts +32 -0
- package/src/proxy/upload-data.ts +189 -0
- package/src/proxy/upload-encrypted-data.ts +658 -0
- package/src/schemas.ts +299 -0
- package/src/storage/debounced-uploader.ts +192 -0
- package/src/storage/utilization-store.ts +397 -0
- package/src/swarm-id-client.test.ts +99 -0
- package/src/swarm-id-client.ts +3095 -0
- package/src/swarm-id-proxy.ts +3891 -0
- package/src/sync/index.ts +28 -0
- package/src/sync/restore-account.ts +90 -0
- package/src/sync/serialization.ts +39 -0
- package/src/sync/store-interfaces.ts +62 -0
- package/src/sync/sync-account.test.ts +302 -0
- package/src/sync/sync-account.ts +396 -0
- package/src/sync/types.ts +11 -0
- package/src/test-fixtures.ts +109 -0
- package/src/types.ts +1651 -0
- package/src/utils/account-state-snapshot.test.ts +595 -0
- package/src/utils/account-state-snapshot.ts +94 -0
- package/src/utils/backup-encryption.test.ts +442 -0
- package/src/utils/backup-encryption.ts +352 -0
- package/src/utils/batch-utilization.ts +1309 -0
- package/src/utils/constants.ts +20 -0
- package/src/utils/hex.ts +27 -0
- package/src/utils/key-derivation.ts +197 -0
- package/src/utils/storage-managers.ts +365 -0
- package/src/utils/ttl.ts +129 -0
- package/src/utils/url.test.ts +136 -0
- package/src/utils/url.ts +71 -0
- package/src/utils/versioned-storage.ts +323 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { Bee, Stamper, UploadOptions, BeeRequestOptions } from "@ethersphere/bee-js";
|
|
2
|
+
/**
|
|
3
|
+
* Options for creating a feed manifest
|
|
4
|
+
*/
|
|
5
|
+
export interface CreateFeedManifestOptions {
|
|
6
|
+
/**
|
|
7
|
+
* Whether to encrypt the manifest.
|
|
8
|
+
* Default: true (encrypted)
|
|
9
|
+
*/
|
|
10
|
+
encrypt?: boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Feed type: "Sequence" for sequential feeds, "Epoch" for epoch feeds.
|
|
13
|
+
* Default: "Sequence"
|
|
14
|
+
*/
|
|
15
|
+
feedType?: "Sequence" | "Epoch";
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Result of creating a feed manifest
|
|
19
|
+
*/
|
|
20
|
+
export interface CreateFeedManifestResult {
|
|
21
|
+
/**
|
|
22
|
+
* Reference to the feed manifest.
|
|
23
|
+
* - Encrypted: 128 hex chars (64 bytes = address + encryption key)
|
|
24
|
+
* - Unencrypted: 64 hex chars (32 bytes = address)
|
|
25
|
+
*/
|
|
26
|
+
reference: string;
|
|
27
|
+
/**
|
|
28
|
+
* Tag UID if a tag was created during upload
|
|
29
|
+
*/
|
|
30
|
+
tagUid?: number;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Create a feed manifest directly using chunk upload
|
|
34
|
+
*
|
|
35
|
+
* Instead of using bee.createFeedManifest() which calls the /feeds endpoint,
|
|
36
|
+
* this function builds the manifest locally as a MantarayNode and uploads it
|
|
37
|
+
* via the encrypted chunk endpoint (or plain chunk endpoint if encrypt=false).
|
|
38
|
+
*
|
|
39
|
+
* Feed manifests have a single "/" path with metadata:
|
|
40
|
+
* - swarm-feed-owner: Owner's ethereum address (40 hex chars, no 0x)
|
|
41
|
+
* - swarm-feed-topic: Topic hash (64 hex chars)
|
|
42
|
+
* - swarm-feed-type: "Sequence" for sequential feeds
|
|
43
|
+
*
|
|
44
|
+
* IMPORTANT: This function implements client-side "saveRecursively" logic:
|
|
45
|
+
* 1. Upload the "/" child node first and get its address
|
|
46
|
+
* 2. Set the child's selfAddress to the uploaded address
|
|
47
|
+
* 3. Then upload the root node (which references the child's address)
|
|
48
|
+
*
|
|
49
|
+
* Without this, Bee's /bzz/ endpoint returns 404 because the "/" child chunk
|
|
50
|
+
* doesn't exist (only its calculated hash was stored in the root manifest).
|
|
51
|
+
*
|
|
52
|
+
* @param bee - Bee client instance
|
|
53
|
+
* @param stamper - Stamper for client-side signing
|
|
54
|
+
* @param topic - Topic hex string (64 chars)
|
|
55
|
+
* @param owner - Owner hex string (40 chars, no 0x prefix)
|
|
56
|
+
* @param options - Options for creating the manifest (encrypt, etc.)
|
|
57
|
+
* @param uploadOptions - Upload options (tag, deferred, etc.)
|
|
58
|
+
* @param requestOptions - Bee request options
|
|
59
|
+
* @returns Reference to the feed manifest
|
|
60
|
+
*/
|
|
61
|
+
export declare function createFeedManifestDirect(bee: Bee, stamper: Stamper, topic: string, owner: string, options?: CreateFeedManifestOptions, uploadOptions?: UploadOptions, requestOptions?: BeeRequestOptions): Promise<CreateFeedManifestResult>;
|
|
62
|
+
//# sourceMappingURL=feed-manifest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feed-manifest.d.ts","sourceRoot":"","sources":["../../src/proxy/feed-manifest.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,GAAG,EACH,OAAO,EACP,aAAa,EACb,iBAAiB,EAClB,MAAM,qBAAqB,CAAA;AAS5B;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB;;;OAGG;IACH,QAAQ,CAAC,EAAE,UAAU,GAAG,OAAO,CAAA;CAChC;AAED;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC;;;;OAIG;IACH,SAAS,EAAE,MAAM,CAAA;IACjB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAsB,wBAAwB,CAC5C,GAAG,EAAE,GAAG,EACR,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,yBAAyB,EACnC,aAAa,CAAC,EAAE,aAAa,EAC7B,cAAc,CAAC,EAAE,iBAAiB,GACjC,OAAO,CAAC,wBAAwB,CAAC,CAyFnC"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Async Epoch Feed Finder (Concurrent)
|
|
3
|
+
*
|
|
4
|
+
* Concurrent implementation for finding feed updates at specific timestamps
|
|
5
|
+
* using epoch-based indexing with parallel chunk fetching.
|
|
6
|
+
*/
|
|
7
|
+
import type { Bee } from "@ethersphere/bee-js";
|
|
8
|
+
import { EthAddress, Topic } from "@ethersphere/bee-js";
|
|
9
|
+
import type { EpochFinder, EpochLookupResult } from "./types";
|
|
10
|
+
/**
|
|
11
|
+
* Async concurrent finder for epoch-based feeds
|
|
12
|
+
*
|
|
13
|
+
* Launches parallel chunk fetches along the epoch tree path
|
|
14
|
+
* to find the feed update valid at a specific timestamp.
|
|
15
|
+
*
|
|
16
|
+
* Implements the EpochFinder interface.
|
|
17
|
+
*/
|
|
18
|
+
export declare class AsyncEpochFinder implements EpochFinder {
|
|
19
|
+
private readonly bee;
|
|
20
|
+
private readonly topic;
|
|
21
|
+
private readonly owner;
|
|
22
|
+
private readonly encryptionKey?;
|
|
23
|
+
constructor(bee: Bee, topic: Topic, owner: EthAddress, encryptionKey?: Uint8Array | undefined);
|
|
24
|
+
/**
|
|
25
|
+
* Find the feed update valid at time `at`
|
|
26
|
+
* @param at - Target unix timestamp (seconds)
|
|
27
|
+
* @param after - Hint of latest known update timestamp (0 if unknown)
|
|
28
|
+
* @returns 32-byte Swarm reference, or undefined if no update found
|
|
29
|
+
*/
|
|
30
|
+
findAt(at: bigint, after?: bigint): Promise<Uint8Array | undefined>;
|
|
31
|
+
/**
|
|
32
|
+
* Recursively find update at epoch, with parallel fetching
|
|
33
|
+
*
|
|
34
|
+
* @param at - Target timestamp
|
|
35
|
+
* @param epoch - Current epoch to check
|
|
36
|
+
* @param currentBest - Best result found so far
|
|
37
|
+
* @returns Reference if found, undefined otherwise
|
|
38
|
+
*/
|
|
39
|
+
private findAtEpoch;
|
|
40
|
+
/**
|
|
41
|
+
* Fetch chunk for a specific epoch
|
|
42
|
+
*
|
|
43
|
+
* @param at - Target timestamp for validation
|
|
44
|
+
* @param epoch - Epoch to fetch
|
|
45
|
+
* @returns Chunk payload
|
|
46
|
+
* @throws Error if chunk not found
|
|
47
|
+
*/
|
|
48
|
+
private getEpochChunk;
|
|
49
|
+
/**
|
|
50
|
+
* Find the feed update valid at time `at` with full metadata
|
|
51
|
+
* Used by updater to calculate next epoch when no hints provided
|
|
52
|
+
*
|
|
53
|
+
* @param at - Target unix timestamp (seconds)
|
|
54
|
+
* @returns EpochLookupResult with reference, epoch, and timestamp, or undefined if no update found
|
|
55
|
+
*/
|
|
56
|
+
findAtWithMetadata(at: bigint): Promise<EpochLookupResult | undefined>;
|
|
57
|
+
/**
|
|
58
|
+
* Recursively find update at epoch with full metadata tracking
|
|
59
|
+
*
|
|
60
|
+
* @param at - Target timestamp
|
|
61
|
+
* @param epoch - Current epoch to check
|
|
62
|
+
* @param currentBest - Best result found so far
|
|
63
|
+
* @returns EpochLookupResult if found, undefined otherwise
|
|
64
|
+
*/
|
|
65
|
+
private findAtEpochWithMetadata;
|
|
66
|
+
/**
|
|
67
|
+
* Fetch chunk for a specific epoch and return full metadata
|
|
68
|
+
*
|
|
69
|
+
* @param at - Target timestamp for validation
|
|
70
|
+
* @param epoch - Epoch to fetch
|
|
71
|
+
* @returns Object with reference and timestamp, or undefined if timestamp > at
|
|
72
|
+
* @throws Error if chunk not found
|
|
73
|
+
*/
|
|
74
|
+
private getEpochChunkWithMetadata;
|
|
75
|
+
private findPreviousLeaf;
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=async-finder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"async-finder.d.ts","sourceRoot":"","sources":["../../../../src/proxy/feeds/epochs/async-finder.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,GAAG,EAAqB,MAAM,qBAAqB,CAAA;AACjE,OAAO,EAAE,UAAU,EAAa,KAAK,EAAE,MAAM,qBAAqB,CAAA;AAElE,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAM7D;;;;;;;GAOG;AACH,qBAAa,gBAAiB,YAAW,WAAW;IAEhD,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC;gBAHd,GAAG,EAAE,GAAG,EACR,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,UAAU,EACjB,aAAa,CAAC,EAAE,UAAU,YAAA;IAG7C;;;;;OAKG;IACG,MAAM,CACV,EAAE,EAAE,MAAM,EACV,KAAK,GAAE,MAAW,GACjB,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAwClC;;;;;;;OAOG;YACW,WAAW;IAgDzB;;;;;;;OAOG;YACW,aAAa;IAQ3B;;;;;;OAMG;IACG,kBAAkB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,GAAG,SAAS,CAAC;IAwB5E;;;;;;;OAOG;YACW,uBAAuB;IA+DrC;;;;;;;OAOG;YACW,yBAAyB;IAmGvC,OAAO,CAAC,gBAAgB;CAQzB"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Epoch-based Feed Indexing
|
|
3
|
+
*
|
|
4
|
+
* Implements time-based indexing using a binary tree structure where each epoch
|
|
5
|
+
* represents a time range with start time and level (0-32).
|
|
6
|
+
*
|
|
7
|
+
* Based on the Swarm Book of Feeds and Bee's epochs implementation.
|
|
8
|
+
*/
|
|
9
|
+
/** Maximum epoch level (2^32 seconds ≈ 136 years) */
|
|
10
|
+
export declare const MAX_LEVEL = 32;
|
|
11
|
+
/**
|
|
12
|
+
* Epoch interface - represents a time slot in the epoch tree
|
|
13
|
+
*/
|
|
14
|
+
export interface Epoch {
|
|
15
|
+
start: bigint;
|
|
16
|
+
level: number;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* EpochIndex class - implements epoch-based feed indexing
|
|
20
|
+
*
|
|
21
|
+
* Each epoch represents a time range:
|
|
22
|
+
* - start: beginning timestamp of the epoch
|
|
23
|
+
* - level: determines the epoch's time span (2^level seconds)
|
|
24
|
+
*
|
|
25
|
+
* Epochs form a binary tree structure for efficient sparse updates.
|
|
26
|
+
*/
|
|
27
|
+
export declare class EpochIndex implements Epoch {
|
|
28
|
+
readonly start: bigint;
|
|
29
|
+
readonly level: number;
|
|
30
|
+
constructor(start: bigint, level: number);
|
|
31
|
+
/**
|
|
32
|
+
* Marshal epoch to binary format for hashing
|
|
33
|
+
* Returns Keccak256 hash of start (8 bytes big-endian) + level (1 byte)
|
|
34
|
+
*/
|
|
35
|
+
marshalBinary(): Promise<Uint8Array>;
|
|
36
|
+
/**
|
|
37
|
+
* Calculate the next epoch for a new update
|
|
38
|
+
* @param last - Timestamp of last update
|
|
39
|
+
* @param at - Timestamp of new update
|
|
40
|
+
*/
|
|
41
|
+
next(last: bigint, at: bigint): EpochIndex;
|
|
42
|
+
/**
|
|
43
|
+
* Calculate epoch length in seconds (2^level)
|
|
44
|
+
*/
|
|
45
|
+
length(): bigint;
|
|
46
|
+
/**
|
|
47
|
+
* Get parent epoch
|
|
48
|
+
* UNSAFE: Do not call on top-level epoch (level 32)
|
|
49
|
+
*/
|
|
50
|
+
parent(): EpochIndex;
|
|
51
|
+
/**
|
|
52
|
+
* Get left sibling epoch
|
|
53
|
+
* UNSAFE: Do not call on left sibling (when start is aligned to 2*length)
|
|
54
|
+
*/
|
|
55
|
+
left(): EpochIndex;
|
|
56
|
+
/**
|
|
57
|
+
* Get child epoch containing timestamp `at`
|
|
58
|
+
* UNSAFE: Do not call with `at` outside this epoch's range
|
|
59
|
+
*/
|
|
60
|
+
childAt(at: bigint): EpochIndex;
|
|
61
|
+
/**
|
|
62
|
+
* Check if this epoch is a left child of its parent
|
|
63
|
+
*/
|
|
64
|
+
isLeft(): boolean;
|
|
65
|
+
/**
|
|
66
|
+
* String representation: "start/level"
|
|
67
|
+
*/
|
|
68
|
+
toString(): string;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Calculate Lowest Common Ancestor epoch for two timestamps
|
|
72
|
+
*
|
|
73
|
+
* The LCA is the smallest epoch that contains both `at` and `after`.
|
|
74
|
+
* This is used to find the optimal starting point for feed lookups.
|
|
75
|
+
*
|
|
76
|
+
* @param at - Target timestamp
|
|
77
|
+
* @param after - Reference timestamp (0 if no previous update)
|
|
78
|
+
* @returns LCA epoch
|
|
79
|
+
*/
|
|
80
|
+
export declare function lca(at: bigint, after: bigint): EpochIndex;
|
|
81
|
+
/**
|
|
82
|
+
* Helper function to get next epoch for update, handling null previous epoch
|
|
83
|
+
* @param prevEpoch - Previous epoch (null if first update)
|
|
84
|
+
* @param last - Timestamp of last update
|
|
85
|
+
* @param at - Timestamp of new update
|
|
86
|
+
*/
|
|
87
|
+
export declare function next(prevEpoch: EpochIndex | undefined, last: bigint, at: bigint): EpochIndex;
|
|
88
|
+
//# sourceMappingURL=epoch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"epoch.d.ts","sourceRoot":"","sources":["../../../../src/proxy/feeds/epochs/epoch.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,qDAAqD;AACrD,eAAO,MAAM,SAAS,KAAK,CAAA;AAE3B;;GAEG;AACH,MAAM,WAAW,KAAK;IACpB,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;CACd;AAED;;;;;;;;GAQG;AACH,qBAAa,UAAW,YAAW,KAAK;aAEpB,KAAK,EAAE,MAAM;aACb,KAAK,EAAE,MAAM;gBADb,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM;IAS/B;;;OAGG;IACG,aAAa,IAAI,OAAO,CAAC,UAAU,CAAC;IAa1C;;;;OAIG;IACH,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,UAAU;IAO1C;;OAEG;IACH,MAAM,IAAI,MAAM;IAIhB;;;OAGG;IACH,MAAM,IAAI,UAAU;IAMpB;;;OAGG;IACH,IAAI,IAAI,UAAU;IAIlB;;;OAGG;IACH,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,UAAU;IAa/B;;OAEG;IACH,MAAM,IAAI,OAAO;IAIjB;;OAEG;IACH,QAAQ,IAAI,MAAM;CAGnB;AAED;;;;;;;;;GASG;AACH,wBAAgB,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,UAAU,CAwBzD;AAED;;;;;GAKG;AACH,wBAAgB,IAAI,CAClB,SAAS,EAAE,UAAU,GAAG,SAAS,EACjC,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,GACT,UAAU,CAKZ"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Synchronous Epoch Feed Finder
|
|
3
|
+
*
|
|
4
|
+
* Recursive implementation for finding feed updates at specific timestamps
|
|
5
|
+
* using epoch-based indexing.
|
|
6
|
+
*/
|
|
7
|
+
import type { Bee } from "@ethersphere/bee-js";
|
|
8
|
+
import { EthAddress, Topic } from "@ethersphere/bee-js";
|
|
9
|
+
import type { EpochFinder } from "./types";
|
|
10
|
+
/**
|
|
11
|
+
* Synchronous recursive finder for epoch-based feeds
|
|
12
|
+
*
|
|
13
|
+
* Traverses the epoch tree recursively to find the feed update
|
|
14
|
+
* valid at a specific timestamp.
|
|
15
|
+
*
|
|
16
|
+
* Implements the EpochFinder interface.
|
|
17
|
+
*/
|
|
18
|
+
export declare class SyncEpochFinder implements EpochFinder {
|
|
19
|
+
private readonly bee;
|
|
20
|
+
private readonly topic;
|
|
21
|
+
private readonly owner;
|
|
22
|
+
constructor(bee: Bee, topic: Topic, owner: EthAddress);
|
|
23
|
+
/**
|
|
24
|
+
* Find the feed update valid at time `at`
|
|
25
|
+
* @param at - Target unix timestamp (seconds)
|
|
26
|
+
* @param after - Hint of latest known update timestamp (0 if unknown)
|
|
27
|
+
* @returns 32-byte Swarm reference, or undefined if no update found
|
|
28
|
+
*/
|
|
29
|
+
findAt(at: bigint, after?: bigint): Promise<Uint8Array | undefined>;
|
|
30
|
+
/**
|
|
31
|
+
* Find the lowest common ancestor epoch with an existing chunk
|
|
32
|
+
*
|
|
33
|
+
* Traverses UP the epoch tree from the LCA until finding a chunk,
|
|
34
|
+
* or reaching the top level.
|
|
35
|
+
*
|
|
36
|
+
* @param at - Target timestamp
|
|
37
|
+
* @param after - Reference timestamp
|
|
38
|
+
* @returns Epoch and chunk found at that epoch (if any)
|
|
39
|
+
*/
|
|
40
|
+
private common;
|
|
41
|
+
/**
|
|
42
|
+
* Recursive descent to find exact update at timestamp
|
|
43
|
+
*
|
|
44
|
+
* Traverses DOWN the epoch tree, handling left/right branches
|
|
45
|
+
* to find the most recent update not later than `at`.
|
|
46
|
+
*
|
|
47
|
+
* @param at - Target timestamp
|
|
48
|
+
* @param epoch - Current epoch being examined
|
|
49
|
+
* @param currentChunk - Best chunk found so far
|
|
50
|
+
* @returns Final chunk reference, or undefined
|
|
51
|
+
*/
|
|
52
|
+
private atEpoch;
|
|
53
|
+
/**
|
|
54
|
+
* Fetch chunk for a specific epoch
|
|
55
|
+
*
|
|
56
|
+
* Calculates the chunk address from topic, epoch, and owner,
|
|
57
|
+
* then downloads it from the Bee node.
|
|
58
|
+
*
|
|
59
|
+
* @param at - Target timestamp for validation
|
|
60
|
+
* @param epoch - Epoch to fetch
|
|
61
|
+
* @returns Chunk reference (32 or 64 bytes), or undefined if timestamp invalid
|
|
62
|
+
* @throws Error if chunk not found or network error
|
|
63
|
+
*/
|
|
64
|
+
private getEpochChunk;
|
|
65
|
+
private findPreviousLeaf;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=finder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"finder.d.ts","sourceRoot":"","sources":["../../../../src/proxy/feeds/epochs/finder.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,GAAG,EAAqB,MAAM,qBAAqB,CAAA;AACjE,OAAO,EAAE,UAAU,EAAa,KAAK,EAAE,MAAM,qBAAqB,CAAA;AAElE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAK1C;;;;;;;GAOG;AACH,qBAAa,eAAgB,YAAW,WAAW;IAE/C,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAFL,GAAG,EAAE,GAAG,EACR,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,UAAU;IAGpC;;;;;OAKG;IACG,MAAM,CACV,EAAE,EAAE,MAAM,EACV,KAAK,GAAE,MAAW,GACjB,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IA0ClC;;;;;;;;;OASG;YACW,MAAM;IA+BpB;;;;;;;;;;OAUG;YACW,OAAO;IA+CrB;;;;;;;;;;OAUG;YACW,aAAa;IAiF3B,OAAO,CAAC,gBAAgB;CAQzB"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Epoch-Based Feeds
|
|
3
|
+
*
|
|
4
|
+
* Time-based feed indexing using a binary tree structure for efficient
|
|
5
|
+
* sparse updates across long time periods.
|
|
6
|
+
*/
|
|
7
|
+
export { EpochIndex, lca, next, MAX_LEVEL, type Epoch } from "./epoch";
|
|
8
|
+
export type { EpochFinder, EpochUpdater, EpochFeedOptions, EpochFeedWriterOptions, EpochLookupResult, } from "./types";
|
|
9
|
+
export { SyncEpochFinder } from "./finder";
|
|
10
|
+
export { AsyncEpochFinder } from "./async-finder";
|
|
11
|
+
export { BasicEpochUpdater } from "./updater";
|
|
12
|
+
import type { EpochFinder, EpochUpdater, EpochFeedOptions, EpochFeedWriterOptions } from "./types";
|
|
13
|
+
/**
|
|
14
|
+
* Create a synchronous epoch feed finder (non-concurrent)
|
|
15
|
+
*
|
|
16
|
+
* @returns EpochFinder implementation
|
|
17
|
+
*/
|
|
18
|
+
export declare function createSyncEpochFinder(options: EpochFeedOptions): EpochFinder;
|
|
19
|
+
/**
|
|
20
|
+
* Create an async epoch feed finder (concurrent)
|
|
21
|
+
*
|
|
22
|
+
* @returns EpochFinder implementation
|
|
23
|
+
*/
|
|
24
|
+
export declare function createAsyncEpochFinder(options: EpochFeedOptions): EpochFinder;
|
|
25
|
+
/**
|
|
26
|
+
* Create an epoch feed updater
|
|
27
|
+
*
|
|
28
|
+
* @returns EpochUpdater implementation
|
|
29
|
+
*/
|
|
30
|
+
export declare function createEpochUpdater(options: EpochFeedWriterOptions): EpochUpdater;
|
|
31
|
+
/**
|
|
32
|
+
* @deprecated Use createSyncEpochFinder instead
|
|
33
|
+
*/
|
|
34
|
+
export declare const createEpochFinder: typeof createSyncEpochFinder;
|
|
35
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/proxy/feeds/epochs/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,KAAK,EAAE,MAAM,SAAS,CAAA;AAGtE,YAAY,EACV,WAAW,EACX,YAAY,EACZ,gBAAgB,EAChB,sBAAsB,EACtB,iBAAiB,GAClB,MAAM,SAAS,CAAA;AAGhB,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAM7C,OAAO,KAAK,EACV,WAAW,EACX,YAAY,EACZ,gBAAgB,EAChB,sBAAsB,EACvB,MAAM,SAAS,CAAA;AAEhB;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,gBAAgB,GAAG,WAAW,CAE5E;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,gBAAgB,GAAG,WAAW,CAO7E;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,sBAAsB,GAC9B,YAAY,CAEd;AAED;;GAEG;AACH,eAAO,MAAM,iBAAiB,8BAAwB,CAAA"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test utilities for epoch feeds
|
|
3
|
+
*
|
|
4
|
+
* Provides mock storage and helpers for testing epoch feed operations
|
|
5
|
+
*/
|
|
6
|
+
import { PrivateKey, Topic, EthAddress } from "@ethersphere/bee-js";
|
|
7
|
+
/**
|
|
8
|
+
* In-memory chunk storage for testing
|
|
9
|
+
*/
|
|
10
|
+
export declare class MockChunkStore {
|
|
11
|
+
private chunks;
|
|
12
|
+
put(address: string, data: Uint8Array): Promise<void>;
|
|
13
|
+
get(address: string): Promise<Uint8Array>;
|
|
14
|
+
has(address: string): boolean;
|
|
15
|
+
clear(): void;
|
|
16
|
+
size(): number;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Mock Bee instance for testing
|
|
20
|
+
*/
|
|
21
|
+
export declare class MockBee {
|
|
22
|
+
readonly url = "http://localhost:1633";
|
|
23
|
+
private store;
|
|
24
|
+
private tagCounter;
|
|
25
|
+
constructor(store?: MockChunkStore);
|
|
26
|
+
createTag(): Promise<{
|
|
27
|
+
uid: number;
|
|
28
|
+
split: number;
|
|
29
|
+
seen: number;
|
|
30
|
+
stored: number;
|
|
31
|
+
sent: number;
|
|
32
|
+
synced: number;
|
|
33
|
+
address: string;
|
|
34
|
+
startedAt: string;
|
|
35
|
+
}>;
|
|
36
|
+
downloadChunk(reference: string): Promise<Uint8Array>;
|
|
37
|
+
uploadChunk(data: Uint8Array, _postageBatchId: string): Promise<{
|
|
38
|
+
reference: string;
|
|
39
|
+
}>;
|
|
40
|
+
getStore(): MockChunkStore;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Create test signer with a deterministic private key
|
|
44
|
+
*/
|
|
45
|
+
export declare function createTestSigner(): PrivateKey;
|
|
46
|
+
/**
|
|
47
|
+
* Create test topic
|
|
48
|
+
*/
|
|
49
|
+
export declare function createTestTopic(name?: string): Topic;
|
|
50
|
+
/**
|
|
51
|
+
* Create test owner address
|
|
52
|
+
*/
|
|
53
|
+
export declare function createTestOwner(): EthAddress;
|
|
54
|
+
/**
|
|
55
|
+
* Create test reference (32 bytes)
|
|
56
|
+
*/
|
|
57
|
+
export declare function createTestReference(value: number | bigint): Uint8Array;
|
|
58
|
+
/**
|
|
59
|
+
* Create test payload with timestamp
|
|
60
|
+
*/
|
|
61
|
+
export declare function createTestPayload(at: bigint): Uint8Array;
|
|
62
|
+
/**
|
|
63
|
+
* Create a mock Stamper for testing
|
|
64
|
+
*
|
|
65
|
+
* Returns an object with a stamp() method that produces a valid-looking
|
|
66
|
+
* EnvelopeWithBatchId without performing real cryptographic operations.
|
|
67
|
+
*/
|
|
68
|
+
export declare function createMockStamper(): {
|
|
69
|
+
stamp(_chunk: any): {
|
|
70
|
+
batchId: {
|
|
71
|
+
toUint8Array: () => Uint8Array<ArrayBuffer>;
|
|
72
|
+
};
|
|
73
|
+
index: Uint8Array<ArrayBuffer>;
|
|
74
|
+
timestamp: Uint8Array<ArrayBuffer>;
|
|
75
|
+
signature: Uint8Array<ArrayBuffer>;
|
|
76
|
+
issuer: Uint8Array<ArrayBuffer>;
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* Mock fetch for SOC and chunk uploads
|
|
81
|
+
*
|
|
82
|
+
* Intercepts fetch calls to /soc/ and /chunks endpoints, storing data
|
|
83
|
+
* in the provided MockChunkStore.
|
|
84
|
+
*
|
|
85
|
+
* @param store - Mock chunk store for persisting uploaded data
|
|
86
|
+
* @param owner - Owner address for computing SOC addresses on /chunks uploads
|
|
87
|
+
*/
|
|
88
|
+
export declare function mockFetch(store?: MockChunkStore, owner?: EthAddress): void;
|
|
89
|
+
/**
|
|
90
|
+
* Restore original fetch
|
|
91
|
+
*/
|
|
92
|
+
export declare function restoreFetch(): void;
|
|
93
|
+
//# sourceMappingURL=test-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-utils.d.ts","sourceRoot":"","sources":["../../../../src/proxy/feeds/epochs/test-utils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAEnE;;GAEG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAgC;IAExC,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAIrD,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAQ/C,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAI7B,KAAK,IAAI,IAAI;IAIb,IAAI,IAAI,MAAM;CAGf;AAED;;GAEG;AACH,qBAAa,OAAO;IAClB,SAAgB,GAAG,2BAA0B;IAC7C,OAAO,CAAC,KAAK,CAAgB;IAC7B,OAAO,CAAC,UAAU,CAAI;gBAEV,KAAK,CAAC,EAAE,cAAc;IAI5B,SAAS,IAAI,OAAO,CAAC;QACzB,GAAG,EAAE,MAAM,CAAA;QACX,KAAK,EAAE,MAAM,CAAA;QACb,IAAI,EAAE,MAAM,CAAA;QACZ,MAAM,EAAE,MAAM,CAAA;QACd,IAAI,EAAE,MAAM,CAAA;QACZ,MAAM,EAAE,MAAM,CAAA;QACd,OAAO,EAAE,MAAM,CAAA;QACf,SAAS,EAAE,MAAM,CAAA;KAClB,CAAC;IAcI,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAIrD,WAAW,CACf,IAAI,EAAE,UAAU,EAChB,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAOjC,QAAQ,IAAI,cAAc;CAG3B;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,UAAU,CAK7C;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,GAAE,MAAoB,GAAG,KAAK,CAIjE;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,UAAU,CAE5C;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,UAAU,CAKtE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,UAAU,CAKxD;AASD;;;;;GAKG;AACH,wBAAgB,iBAAiB;kBAEf,GAAG;;;;;;;;;EAYpB;AAED;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,KAAK,CAAC,EAAE,cAAc,EAAE,KAAK,CAAC,EAAE,UAAU,GAAG,IAAI,CAuF1E;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,IAAI,CAGnC"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types for Epoch-Based Feeds
|
|
3
|
+
*/
|
|
4
|
+
import type { Bee, EthAddress, Topic, PrivateKey, Stamper } from "@ethersphere/bee-js";
|
|
5
|
+
import type { EpochIndex } from "./epoch";
|
|
6
|
+
/**
|
|
7
|
+
* Options for creating an epoch feed reader
|
|
8
|
+
*/
|
|
9
|
+
export interface EpochFeedOptions {
|
|
10
|
+
/** Bee instance for chunk operations */
|
|
11
|
+
bee: Bee;
|
|
12
|
+
/** Feed topic (32 bytes) */
|
|
13
|
+
topic: Topic;
|
|
14
|
+
/** Feed owner address */
|
|
15
|
+
owner: EthAddress;
|
|
16
|
+
/** Optional encryption key for encrypted feed updates */
|
|
17
|
+
encryptionKey?: Uint8Array;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Options for creating an epoch feed writer
|
|
21
|
+
*/
|
|
22
|
+
export interface EpochFeedWriterOptions extends EpochFeedOptions {
|
|
23
|
+
/** Private key for signing chunks */
|
|
24
|
+
signer: PrivateKey;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Result from an epoch feed lookup
|
|
28
|
+
*/
|
|
29
|
+
export interface EpochLookupResult {
|
|
30
|
+
/** Swarm reference (32 bytes) */
|
|
31
|
+
reference: Uint8Array;
|
|
32
|
+
/** Epoch where the update was found */
|
|
33
|
+
epoch: EpochIndex;
|
|
34
|
+
/** Timestamp of the update */
|
|
35
|
+
timestamp: bigint;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Hints for calculating the next epoch in a stateless manner.
|
|
39
|
+
* Callers should store these after each update and pass them to subsequent updates.
|
|
40
|
+
*/
|
|
41
|
+
export interface EpochUpdateHints {
|
|
42
|
+
/** Previous epoch (for calculating next) */
|
|
43
|
+
lastEpoch?: {
|
|
44
|
+
start: bigint;
|
|
45
|
+
level: number;
|
|
46
|
+
};
|
|
47
|
+
/** Timestamp of last update */
|
|
48
|
+
lastTimestamp?: bigint;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Result from an epoch feed update, including epoch info for subsequent updates.
|
|
52
|
+
*/
|
|
53
|
+
export interface EpochUpdateResult {
|
|
54
|
+
/** SOC address of the uploaded chunk */
|
|
55
|
+
socAddress: Uint8Array;
|
|
56
|
+
/** Epoch used for this update (for caller to store as hint) */
|
|
57
|
+
epoch: {
|
|
58
|
+
start: bigint;
|
|
59
|
+
level: number;
|
|
60
|
+
};
|
|
61
|
+
/** Timestamp used (for caller to store as hint) */
|
|
62
|
+
timestamp: bigint;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Interface for epoch feed finders (readers)
|
|
66
|
+
*
|
|
67
|
+
* Implementations: SyncEpochFinder, AsyncEpochFinder
|
|
68
|
+
*/
|
|
69
|
+
export interface EpochFinder {
|
|
70
|
+
/**
|
|
71
|
+
* Find the feed update valid at time `at`
|
|
72
|
+
*
|
|
73
|
+
* @param at - Target unix timestamp (seconds)
|
|
74
|
+
* @param after - Hint of latest known update timestamp (0 if unknown)
|
|
75
|
+
* @returns 32 or 64-byte Swarm reference, or undefined if no update found
|
|
76
|
+
*/
|
|
77
|
+
findAt(at: bigint, after?: bigint): Promise<Uint8Array | undefined>;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Interface for epoch feed updaters (writers)
|
|
81
|
+
*
|
|
82
|
+
* Implementation: BasicEpochUpdater
|
|
83
|
+
*
|
|
84
|
+
* Implements Bee-compatible stateless epoch calculation.
|
|
85
|
+
* Each update uses hints from the previous update to calculate the next epoch,
|
|
86
|
+
* creating a proper epoch tree that Bee's finder can traverse.
|
|
87
|
+
*/
|
|
88
|
+
export interface EpochUpdater {
|
|
89
|
+
/**
|
|
90
|
+
* Update feed with a reference at given timestamp
|
|
91
|
+
*
|
|
92
|
+
* Calculates the appropriate epoch based on hints:
|
|
93
|
+
* - First update (no hints): uses root epoch (level 32, start 0)
|
|
94
|
+
* - Subsequent updates: calculates next epoch using LCA-based algorithm
|
|
95
|
+
*
|
|
96
|
+
* @param at - Unix timestamp for this update (seconds)
|
|
97
|
+
* @param reference - 32 or 64-byte Swarm reference to store
|
|
98
|
+
* @param stamper - Stamper object for stamping
|
|
99
|
+
* @param encryptionKey - Optional encryption key for the update
|
|
100
|
+
* @param hints - Optional hints from previous update for calculating epoch
|
|
101
|
+
* @returns Update result with SOC address and epoch info for next update
|
|
102
|
+
*/
|
|
103
|
+
update(at: bigint, reference: Uint8Array, stamper: Stamper, encryptionKey?: Uint8Array, hints?: EpochUpdateHints): Promise<EpochUpdateResult>;
|
|
104
|
+
/**
|
|
105
|
+
* Get the owner address (derived from signer)
|
|
106
|
+
*/
|
|
107
|
+
getOwner(): EthAddress;
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/proxy/feeds/epochs/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACV,GAAG,EACH,UAAU,EACV,KAAK,EACL,UAAU,EACV,OAAO,EACR,MAAM,qBAAqB,CAAA;AAC5B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAEzC;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,wCAAwC;IACxC,GAAG,EAAE,GAAG,CAAA;IAER,4BAA4B;IAC5B,KAAK,EAAE,KAAK,CAAA;IAEZ,yBAAyB;IACzB,KAAK,EAAE,UAAU,CAAA;IAEjB,yDAAyD;IACzD,aAAa,CAAC,EAAE,UAAU,CAAA;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,sBAAuB,SAAQ,gBAAgB;IAC9D,qCAAqC;IACrC,MAAM,EAAE,UAAU,CAAA;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,iCAAiC;IACjC,SAAS,EAAE,UAAU,CAAA;IAErB,uCAAuC;IACvC,KAAK,EAAE,UAAU,CAAA;IAEjB,8BAA8B;IAC9B,SAAS,EAAE,MAAM,CAAA;CAClB;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,4CAA4C;IAC5C,SAAS,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;IAC5C,+BAA+B;IAC/B,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,wCAAwC;IACxC,UAAU,EAAE,UAAU,CAAA;IACtB,+DAA+D;IAC/D,KAAK,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;IACvC,mDAAmD;IACnD,SAAS,EAAE,MAAM,CAAA;CAClB;AAED;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAAA;CACpE;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,YAAY;IAC3B;;;;;;;;;;;;;OAaG;IACH,MAAM,CACJ,EAAE,EAAE,MAAM,EACV,SAAS,EAAE,UAAU,EACrB,OAAO,EAAE,OAAO,EAChB,aAAa,CAAC,EAAE,UAAU,EAC1B,KAAK,CAAC,EAAE,gBAAgB,GACvB,OAAO,CAAC,iBAAiB,CAAC,CAAA;IAE7B;;OAEG;IACH,QAAQ,IAAI,UAAU,CAAA;CACvB"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Basic Epoch Feed Updater
|
|
3
|
+
*
|
|
4
|
+
* Handles writing updates to epoch-based feeds by calculating the next
|
|
5
|
+
* epoch and uploading chunks.
|
|
6
|
+
*/
|
|
7
|
+
import type { Bee, Stamper } from "@ethersphere/bee-js";
|
|
8
|
+
import { EthAddress, Topic, PrivateKey } from "@ethersphere/bee-js";
|
|
9
|
+
import type { EpochUpdater, EpochUpdateHints, EpochUpdateResult } from "./types";
|
|
10
|
+
/**
|
|
11
|
+
* Basic updater for epoch-based feeds
|
|
12
|
+
*
|
|
13
|
+
* Implements Bee-compatible stateless epoch calculation.
|
|
14
|
+
* Each update uses hints from the previous update to calculate the next epoch,
|
|
15
|
+
* creating a proper epoch tree that Bee's finder can traverse.
|
|
16
|
+
*
|
|
17
|
+
* - First update (no hints): uses root epoch (level 32, start 0)
|
|
18
|
+
* - Subsequent updates: calculates next epoch using the standard algorithm:
|
|
19
|
+
* - If new timestamp within previous epoch's range: dive to child
|
|
20
|
+
* - Else: jump to LCA(newTimestamp, prevTimestamp) and dive to child
|
|
21
|
+
*
|
|
22
|
+
* Implements the EpochUpdater interface.
|
|
23
|
+
*/
|
|
24
|
+
export declare class BasicEpochUpdater implements EpochUpdater {
|
|
25
|
+
private readonly bee;
|
|
26
|
+
private readonly topic;
|
|
27
|
+
private readonly signer;
|
|
28
|
+
constructor(bee: Bee, topic: Topic, signer: PrivateKey);
|
|
29
|
+
/**
|
|
30
|
+
* Update feed with a reference at given timestamp
|
|
31
|
+
*
|
|
32
|
+
* @param at - Unix timestamp for this update (seconds)
|
|
33
|
+
* @param reference - 32 or 64-byte Swarm reference to store
|
|
34
|
+
* @param stamper - Stamper object for stamping
|
|
35
|
+
* @param encryptionKey - Optional encryption key for the update
|
|
36
|
+
* @param hints - Optional hints from previous update for calculating epoch
|
|
37
|
+
* @returns Update result with SOC address and epoch info for next update
|
|
38
|
+
*/
|
|
39
|
+
update(at: bigint, reference: Uint8Array, stamper: Stamper, encryptionKey?: Uint8Array, hints?: EpochUpdateHints): Promise<EpochUpdateResult>;
|
|
40
|
+
/**
|
|
41
|
+
* Calculate the epoch for this update based on hints or auto-lookup
|
|
42
|
+
*
|
|
43
|
+
* When hints are provided, uses them for fast epoch calculation.
|
|
44
|
+
* When no hints are provided, looks up the current feed state to calculate
|
|
45
|
+
* the next epoch, preventing overwrites of previous updates.
|
|
46
|
+
*
|
|
47
|
+
* @param at - Timestamp for this update
|
|
48
|
+
* @param hints - Optional hints from previous update
|
|
49
|
+
* @param encryptionKey - Optional encryption key for looking up encrypted feeds
|
|
50
|
+
* @returns Epoch to use for this update
|
|
51
|
+
*/
|
|
52
|
+
private calculateEpoch;
|
|
53
|
+
/**
|
|
54
|
+
* Get the owner address (derived from signer)
|
|
55
|
+
*/
|
|
56
|
+
getOwner(): EthAddress;
|
|
57
|
+
/**
|
|
58
|
+
* Upload a chunk for a specific epoch
|
|
59
|
+
*
|
|
60
|
+
* @param epoch - Epoch to upload to
|
|
61
|
+
* @param at - Timestamp of this update
|
|
62
|
+
* @param reference - 32 or 64-byte reference to store
|
|
63
|
+
* @param stamper - Stamper object for stamping
|
|
64
|
+
* @returns SOC chunk address for utilization tracking
|
|
65
|
+
*/
|
|
66
|
+
private uploadEpochChunk;
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=updater.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"updater.d.ts","sourceRoot":"","sources":["../../../../src/proxy/feeds/epochs/updater.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AACvD,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAc,MAAM,qBAAqB,CAAA;AAM/E,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAGhF;;;;;;;;;;;;;GAaG;AACH,qBAAa,iBAAkB,YAAW,YAAY;IAElD,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAFN,GAAG,EAAE,GAAG,EACR,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,UAAU;IAGrC;;;;;;;;;OASG;IACG,MAAM,CACV,EAAE,EAAE,MAAM,EACV,SAAS,EAAE,UAAU,EACrB,OAAO,EAAE,OAAO,EAChB,aAAa,CAAC,EAAE,UAAU,EAC1B,KAAK,CAAC,EAAE,gBAAgB,GACvB,OAAO,CAAC,iBAAiB,CAAC;IA2B7B;;;;;;;;;;;OAWG;YACW,cAAc;IAmC5B;;OAEG;IACH,QAAQ,IAAI,UAAU;IAItB;;;;;;;;OAQG;YACW,gBAAgB;CA8C/B"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared utilities for epoch feed finders
|
|
3
|
+
*/
|
|
4
|
+
import { EpochIndex } from "./epoch";
|
|
5
|
+
/**
|
|
6
|
+
* Type for the chunk fetcher callback used by findPreviousLeaf.
|
|
7
|
+
* This allows both sync and async finders to share the same logic.
|
|
8
|
+
*/
|
|
9
|
+
export type EpochChunkFetcher = (at: bigint, epoch: EpochIndex) => Promise<Uint8Array | undefined>;
|
|
10
|
+
/**
|
|
11
|
+
* Find a previous leaf chunk by scanning backwards from the target timestamp.
|
|
12
|
+
*
|
|
13
|
+
* This is a recovery fallback for poisoned-ancestor histories where the tree
|
|
14
|
+
* traversal fails but valid leaf nodes exist.
|
|
15
|
+
*
|
|
16
|
+
* @param at - Target unix timestamp (seconds)
|
|
17
|
+
* @param after - Hint of latest known update timestamp (0 if unknown)
|
|
18
|
+
* @param getEpochChunk - Callback function to fetch epoch chunks
|
|
19
|
+
* @returns 32-byte Swarm reference, or undefined if no update found
|
|
20
|
+
*/
|
|
21
|
+
export declare function findPreviousLeaf(at: bigint, after: bigint, getEpochChunk: EpochChunkFetcher): Promise<Uint8Array | undefined>;
|
|
22
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../src/proxy/feeds/epochs/utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAIpC;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GAAG,CAC9B,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,UAAU,KACd,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAAA;AAEpC;;;;;;;;;;GAUG;AACH,wBAAsB,gBAAgB,CACpC,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,EACb,aAAa,EAAE,iBAAiB,GAC/B,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CA6BjC"}
|