@aztec/blob-client 0.0.1-commit.f504929 → 0.0.1-commit.f81dbcf

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.
@@ -14,10 +14,6 @@ export declare class HttpBlobClient implements BlobClientInterface {
14
14
  protected readonly fileStoreUploadClient: FileStoreBlobClient | undefined;
15
15
  private disabled;
16
16
  private healthcheckUploadIntervalId?;
17
- /** Cached beacon genesis time (seconds since Unix epoch). Fetched once at startup. */
18
- private beaconGenesisTime?;
19
- /** Cached beacon slot duration in seconds. Fetched once at startup. */
20
- private beaconSecondsPerSlot?;
21
17
  constructor(config?: BlobClientConfig, opts?: {
22
18
  logger?: Logger;
23
19
  archiveClient?: BlobArchiveClient;
@@ -58,7 +54,7 @@ export declare class HttpBlobClient implements BlobClientInterface {
58
54
  getBlobSidecar(blockHash: `0x${string}`, blobHashes: Buffer[], opts?: GetBlobSidecarOptions): Promise<Blob[]>;
59
55
  private tryFileStores;
60
56
  getBlobSidecarFrom(hostUrl: string, blockHashOrSlot: string | number, blobHashes?: Buffer[], l1ConsensusHostIndex?: number): Promise<Blob[]>;
61
- getBlobsFromHost(hostUrl: string, blockHashOrSlot: string | number, l1ConsensusHostIndex?: number, blobHashes?: Buffer[]): Promise<BlobJson[]>;
57
+ getBlobsFromHost(hostUrl: string, blockHashOrSlot: string | number, l1ConsensusHostIndex?: number): Promise<BlobJson[]>;
62
58
  private fetchBlobSidecars;
63
59
  private getLatestSlotNumber;
64
60
  private getSlotNumber;
@@ -68,18 +64,16 @@ export declare class HttpBlobClient implements BlobClientInterface {
68
64
  canUpload(): boolean;
69
65
  /**
70
66
  * Start the blob client.
71
- * Fetches and caches beacon genesis config for timestamp-based slot resolution,
72
- * then uploads the initial healthcheck file (awaited) and starts periodic uploads.
67
+ * Uploads the initial healthcheck file (awaited) and starts periodic uploads.
73
68
  */
74
69
  start(): Promise<void>;
75
70
  /**
76
71
  * Start periodic healthcheck upload to the file store to ensure it remains available even if accidentally deleted.
77
72
  */
78
73
  private startPeriodicHealthcheckUpload;
79
- private fetchBeaconConfig;
80
74
  /**
81
75
  * Stop the blob client, clearing any periodic tasks.
82
76
  */
83
77
  stop(): void;
84
78
  }
85
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaHR0cC5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NsaWVudC9odHRwLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxJQUFJLEVBQUUsS0FBSyxRQUFRLEVBQStCLE1BQU0saUJBQWlCLENBQUM7QUFFbkYsT0FBTyxFQUFFLEtBQUssTUFBTSxFQUFnQixNQUFNLHVCQUF1QixDQUFDO0FBT2xFLE9BQU8sS0FBSyxFQUFFLGlCQUFpQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDakUsT0FBTyxLQUFLLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSx1Q0FBdUMsQ0FBQztBQUVqRixPQUFPLEVBQUUsS0FBSyxnQkFBZ0IsRUFBOEIsTUFBTSxhQUFhLENBQUM7QUFDaEYsT0FBTyxLQUFLLEVBQUUsbUJBQW1CLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUVqRixxQkFBYSxjQUFlLFlBQVcsbUJBQW1CO0lBa0J0RCxPQUFPLENBQUMsUUFBUSxDQUFDLElBQUk7SUFqQnZCLFNBQVMsQ0FBQyxRQUFRLENBQUMsR0FBRyxFQUFFLE1BQU0sQ0FBQztJQUMvQixTQUFTLENBQUMsUUFBUSxDQUFDLE1BQU0sRUFBRSxnQkFBZ0IsQ0FBQztJQUM1QyxTQUFTLENBQUMsUUFBUSxDQUFDLGFBQWEsRUFBRSxpQkFBaUIsR0FBRyxTQUFTLENBQUM7SUFDaEUsU0FBUyxDQUFDLFFBQVEsQ0FBQyxLQUFLLEVBQUUsT0FBTyxLQUFLLENBQUM7SUFDdkMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxnQkFBZ0IsRUFBRSxtQkFBbUIsRUFBRSxDQUFDO0lBQzNELFNBQVMsQ0FBQyxRQUFRLENBQUMscUJBQXFCLEVBQUUsbUJBQW1CLEdBQUcsU0FBUyxDQUFDO0lBRTFFLE9BQU8sQ0FBQyxRQUFRLENBQVM7SUFDekIsT0FBTyxDQUFDLDJCQUEyQixDQUFDLENBQWlCO0lBRXJELHNGQUFzRjtJQUN0RixPQUFPLENBQUMsaUJBQWlCLENBQUMsQ0FBUztJQUNuQyx1RUFBdUU7SUFDdkUsT0FBTyxDQUFDLG9CQUFvQixDQUFDLENBQVM7SUFFdEMsWUFDRSxNQUFNLENBQUMsRUFBRSxnQkFBZ0IsRUFDUixJQUFJLEdBQUU7UUFDckIsTUFBTSxDQUFDLEVBQUUsTUFBTSxDQUFDO1FBQ2hCLGFBQWEsQ0FBQyxFQUFFLGlCQUFpQixDQUFDO1FBQ2xDLGdCQUFnQixDQUFDLEVBQUUsbUJBQW1CLEVBQUUsQ0FBQztRQUN6QyxxQkFBcUIsQ0FBQyxFQUFFLG1CQUFtQixDQUFDO1FBQzVDLHlFQUF5RTtRQUN6RSxjQUFjLENBQUMsRUFBRSxDQUFDLEtBQUssRUFBRSxJQUFJLEVBQUUsS0FBSyxJQUFJLENBQUM7S0FDckMsRUF3QlA7SUFFRDs7O09BR0c7SUFDSCxPQUFPLENBQUMsc0JBQXNCO0lBVTlCOzs7OztPQUtHO0lBQ0ksV0FBVyxDQUFDLEtBQUssRUFBRSxPQUFPLEdBQUcsSUFBSSxDQUd2QztJQUVZLFdBQVcsa0JBb0V2QjtJQUVZLG9CQUFvQixDQUFDLEtBQUssRUFBRSxJQUFJLEVBQUUsR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLENBbUJqRTtJQUVEOzs7Ozs7Ozs7Ozs7OztPQWNHO0lBQ1UsY0FBYyxDQUN6QixTQUFTLEVBQUUsS0FBSyxNQUFNLEVBQUUsRUFDeEIsVUFBVSxFQUFFLE1BQU0sRUFBRSxFQUNwQixJQUFJLENBQUMsRUFBRSxxQkFBcUIsR0FDM0IsT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDLENBa0pqQjtZQVFhLGFBQWE7SUFzQ2Qsa0JBQWtCLENBQzdCLE9BQU8sRUFBRSxNQUFNLEVBQ2YsZUFBZSxFQUFFLE1BQU0sR0FBRyxNQUFNLEVBQ2hDLFVBQVUsR0FBRSxNQUFNLEVBQU8sRUFDekIsb0JBQW9CLENBQUMsRUFBRSxNQUFNLEdBQzVCLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUdqQjtJQUVZLGdCQUFnQixDQUMzQixPQUFPLEVBQUUsTUFBTSxFQUNmLGVBQWUsRUFBRSxNQUFNLEdBQUcsTUFBTSxFQUNoQyxvQkFBb0IsQ0FBQyxFQUFFLE1BQU0sRUFDN0IsVUFBVSxDQUFDLEVBQUUsTUFBTSxFQUFFLEdBQ3BCLE9BQU8sQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQXNDckI7SUFFRCxPQUFPLENBQUMsaUJBQWlCO1lBcUJYLG1CQUFtQjtZQW1DbkIsYUFBYTtJQTZFM0Isc0NBQXNDO0lBQy9CLGdCQUFnQixJQUFJLGlCQUFpQixHQUFHLFNBQVMsQ0FFdkQ7SUFFRCxpRUFBaUU7SUFDMUQsU0FBUyxJQUFJLE9BQU8sQ0FFMUI7SUFFRDs7OztPQUlHO0lBQ1UsS0FBSyxJQUFJLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FXbEM7SUFFRDs7T0FFRztJQUNILE9BQU8sQ0FBQyw4QkFBOEI7WUFnQnhCLGlCQUFpQjtJQTBDL0I7O09BRUc7SUFDSSxJQUFJLElBQUksSUFBSSxDQUtsQjtDQUNGIn0=
79
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaHR0cC5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NsaWVudC9odHRwLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxJQUFJLEVBQUUsS0FBSyxRQUFRLEVBQStCLE1BQU0saUJBQWlCLENBQUM7QUFFbkYsT0FBTyxFQUFFLEtBQUssTUFBTSxFQUFnQixNQUFNLHVCQUF1QixDQUFDO0FBT2xFLE9BQU8sS0FBSyxFQUFFLGlCQUFpQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDakUsT0FBTyxLQUFLLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSx1Q0FBdUMsQ0FBQztBQUVqRixPQUFPLEVBQUUsS0FBSyxnQkFBZ0IsRUFBOEIsTUFBTSxhQUFhLENBQUM7QUFDaEYsT0FBTyxLQUFLLEVBQUUsbUJBQW1CLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUVqRixxQkFBYSxjQUFlLFlBQVcsbUJBQW1CO0lBYXRELE9BQU8sQ0FBQyxRQUFRLENBQUMsSUFBSTtJQVp2QixTQUFTLENBQUMsUUFBUSxDQUFDLEdBQUcsRUFBRSxNQUFNLENBQUM7SUFDL0IsU0FBUyxDQUFDLFFBQVEsQ0FBQyxNQUFNLEVBQUUsZ0JBQWdCLENBQUM7SUFDNUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxhQUFhLEVBQUUsaUJBQWlCLEdBQUcsU0FBUyxDQUFDO0lBQ2hFLFNBQVMsQ0FBQyxRQUFRLENBQUMsS0FBSyxFQUFFLE9BQU8sS0FBSyxDQUFDO0lBQ3ZDLFNBQVMsQ0FBQyxRQUFRLENBQUMsZ0JBQWdCLEVBQUUsbUJBQW1CLEVBQUUsQ0FBQztJQUMzRCxTQUFTLENBQUMsUUFBUSxDQUFDLHFCQUFxQixFQUFFLG1CQUFtQixHQUFHLFNBQVMsQ0FBQztJQUUxRSxPQUFPLENBQUMsUUFBUSxDQUFTO0lBQ3pCLE9BQU8sQ0FBQywyQkFBMkIsQ0FBQyxDQUFpQjtJQUVyRCxZQUNFLE1BQU0sQ0FBQyxFQUFFLGdCQUFnQixFQUNSLElBQUksR0FBRTtRQUNyQixNQUFNLENBQUMsRUFBRSxNQUFNLENBQUM7UUFDaEIsYUFBYSxDQUFDLEVBQUUsaUJBQWlCLENBQUM7UUFDbEMsZ0JBQWdCLENBQUMsRUFBRSxtQkFBbUIsRUFBRSxDQUFDO1FBQ3pDLHFCQUFxQixDQUFDLEVBQUUsbUJBQW1CLENBQUM7UUFDNUMseUVBQXlFO1FBQ3pFLGNBQWMsQ0FBQyxFQUFFLENBQUMsS0FBSyxFQUFFLElBQUksRUFBRSxLQUFLLElBQUksQ0FBQztLQUNyQyxFQXdCUDtJQUVEOzs7T0FHRztJQUNILE9BQU8sQ0FBQyxzQkFBc0I7SUFVOUI7Ozs7O09BS0c7SUFDSSxXQUFXLENBQUMsS0FBSyxFQUFFLE9BQU8sR0FBRyxJQUFJLENBR3ZDO0lBRVksV0FBVyxrQkFvRXZCO0lBRVksb0JBQW9CLENBQUMsS0FBSyxFQUFFLElBQUksRUFBRSxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FtQmpFO0lBRUQ7Ozs7Ozs7Ozs7Ozs7O09BY0c7SUFDVSxjQUFjLENBQ3pCLFNBQVMsRUFBRSxLQUFLLE1BQU0sRUFBRSxFQUN4QixVQUFVLEVBQUUsTUFBTSxFQUFFLEVBQ3BCLElBQUksQ0FBQyxFQUFFLHFCQUFxQixHQUMzQixPQUFPLENBQUMsSUFBSSxFQUFFLENBQUMsQ0E2SWpCO1lBUWEsYUFBYTtJQXNDZCxrQkFBa0IsQ0FDN0IsT0FBTyxFQUFFLE1BQU0sRUFDZixlQUFlLEVBQUUsTUFBTSxHQUFHLE1BQU0sRUFDaEMsVUFBVSxHQUFFLE1BQU0sRUFBTyxFQUN6QixvQkFBb0IsQ0FBQyxFQUFFLE1BQU0sR0FDNUIsT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDLENBR2pCO0lBRVksZ0JBQWdCLENBQzNCLE9BQU8sRUFBRSxNQUFNLEVBQ2YsZUFBZSxFQUFFLE1BQU0sR0FBRyxNQUFNLEVBQ2hDLG9CQUFvQixDQUFDLEVBQUUsTUFBTSxHQUM1QixPQUFPLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FzQ3JCO0lBRUQsT0FBTyxDQUFDLGlCQUFpQjtZQVlYLG1CQUFtQjtZQW1DbkIsYUFBYTtJQTZEM0Isc0NBQXNDO0lBQy9CLGdCQUFnQixJQUFJLGlCQUFpQixHQUFHLFNBQVMsQ0FFdkQ7SUFFRCxpRUFBaUU7SUFDMUQsU0FBUyxJQUFJLE9BQU8sQ0FFMUI7SUFFRDs7O09BR0c7SUFDVSxLQUFLLElBQUksT0FBTyxDQUFDLElBQUksQ0FBQyxDQVNsQztJQUVEOztPQUVHO0lBQ0gsT0FBTyxDQUFDLDhCQUE4QjtJQVd0Qzs7T0FFRztJQUNJLElBQUksSUFBSSxJQUFJLENBS2xCO0NBQ0YifQ==
@@ -1 +1 @@
1
- {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/client/http.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/client/http.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,KAAK,QAAQ,EAA+B,MAAM,iBAAiB,CAAC;AAEnF,OAAO,EAAE,KAAK,MAAM,EAAgB,MAAM,uBAAuB,CAAC;AAOlE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,uCAAuC,CAAC;AAEjF,OAAO,EAAE,KAAK,gBAAgB,EAA8B,MAAM,aAAa,CAAC;AAChF,OAAO,KAAK,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAEjF,qBAAa,cAAe,YAAW,mBAAmB;IAatD,OAAO,CAAC,QAAQ,CAAC,IAAI;IAZvB,SAAS,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAC/B,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;IAC5C,SAAS,CAAC,QAAQ,CAAC,aAAa,EAAE,iBAAiB,GAAG,SAAS,CAAC;IAChE,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,KAAK,CAAC;IACvC,SAAS,CAAC,QAAQ,CAAC,gBAAgB,EAAE,mBAAmB,EAAE,CAAC;IAC3D,SAAS,CAAC,QAAQ,CAAC,qBAAqB,EAAE,mBAAmB,GAAG,SAAS,CAAC;IAE1E,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,2BAA2B,CAAC,CAAiB;IAErD,YACE,MAAM,CAAC,EAAE,gBAAgB,EACR,IAAI,GAAE;QACrB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,aAAa,CAAC,EAAE,iBAAiB,CAAC;QAClC,gBAAgB,CAAC,EAAE,mBAAmB,EAAE,CAAC;QACzC,qBAAqB,CAAC,EAAE,mBAAmB,CAAC;QAC5C,yEAAyE;QACzE,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC;KACrC,EAwBP;IAED;;;OAGG;IACH,OAAO,CAAC,sBAAsB;IAU9B;;;;;OAKG;IACI,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAGvC;IAEY,WAAW,kBAoEvB;IAEY,oBAAoB,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAmBjE;IAED;;;;;;;;;;;;;;OAcG;IACU,cAAc,CACzB,SAAS,EAAE,KAAK,MAAM,EAAE,EACxB,UAAU,EAAE,MAAM,EAAE,EACpB,IAAI,CAAC,EAAE,qBAAqB,GAC3B,OAAO,CAAC,IAAI,EAAE,CAAC,CA6IjB;YAQa,aAAa;IAsCd,kBAAkB,CAC7B,OAAO,EAAE,MAAM,EACf,eAAe,EAAE,MAAM,GAAG,MAAM,EAChC,UAAU,GAAE,MAAM,EAAO,EACzB,oBAAoB,CAAC,EAAE,MAAM,GAC5B,OAAO,CAAC,IAAI,EAAE,CAAC,CAGjB;IAEY,gBAAgB,CAC3B,OAAO,EAAE,MAAM,EACf,eAAe,EAAE,MAAM,GAAG,MAAM,EAChC,oBAAoB,CAAC,EAAE,MAAM,GAC5B,OAAO,CAAC,QAAQ,EAAE,CAAC,CAsCrB;IAED,OAAO,CAAC,iBAAiB;YAYX,mBAAmB;YAmCnB,aAAa;IA6D3B,sCAAsC;IAC/B,gBAAgB,IAAI,iBAAiB,GAAG,SAAS,CAEvD;IAED,iEAAiE;IAC1D,SAAS,IAAI,OAAO,CAE1B;IAED;;;OAGG;IACU,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CASlC;IAED;;OAEG;IACH,OAAO,CAAC,8BAA8B;IAWtC;;OAEG;IACI,IAAI,IAAI,IAAI,CAKlB;CACF"}
@@ -17,8 +17,6 @@ export class HttpBlobClient {
17
17
  fileStoreUploadClient;
18
18
  disabled;
19
19
  healthcheckUploadIntervalId;
20
- /** Cached beacon genesis time (seconds since Unix epoch). Fetched once at startup. */ beaconGenesisTime;
21
- /** Cached beacon slot duration in seconds. Fetched once at startup. */ beaconSecondsPerSlot;
22
20
  constructor(config, opts = {}){
23
21
  this.opts = opts;
24
22
  this.disabled = false;
@@ -222,7 +220,7 @@ export class HttpBlobClient {
222
220
  ...ctx
223
221
  };
224
222
  this.log.trace(`Attempting to get slot number for block hash`, consensusCtx);
225
- const slotNumber = await this.getSlotNumber(blockHash, opts?.parentBeaconBlockRoot, opts?.l1BlockTimestamp);
223
+ const slotNumber = await this.getSlotNumber(blockHash);
226
224
  this.log.debug(`Got slot number ${slotNumber} from consensus host for querying blobs`, consensusCtx);
227
225
  if (slotNumber) {
228
226
  let l1ConsensusHostUrl;
@@ -237,7 +235,7 @@ export class HttpBlobClient {
237
235
  l1ConsensusHostUrl,
238
236
  ...ctx
239
237
  });
240
- const blobs = await this.getBlobsFromHost(l1ConsensusHostUrl, slotNumber, l1ConsensusHostIndex, getMissingBlobHashes());
238
+ const blobs = await this.getBlobsFromHost(l1ConsensusHostUrl, slotNumber, l1ConsensusHostIndex);
241
239
  const result = await fillResults(blobs);
242
240
  this.log.debug(`Got ${blobs.length} blobs from consensus host (total: ${result.length}/${blobHashes.length})`, {
243
241
  slotNumber,
@@ -336,14 +334,14 @@ export class HttpBlobClient {
336
334
  }
337
335
  }
338
336
  async getBlobSidecarFrom(hostUrl, blockHashOrSlot, blobHashes = [], l1ConsensusHostIndex) {
339
- const blobs = await this.getBlobsFromHost(hostUrl, blockHashOrSlot, l1ConsensusHostIndex, blobHashes);
337
+ const blobs = await this.getBlobsFromHost(hostUrl, blockHashOrSlot, l1ConsensusHostIndex);
340
338
  return (await processFetchedBlobs(blobs, blobHashes, this.log)).filter((b)=>b !== undefined);
341
339
  }
342
- async getBlobsFromHost(hostUrl, blockHashOrSlot, l1ConsensusHostIndex, blobHashes) {
340
+ async getBlobsFromHost(hostUrl, blockHashOrSlot, l1ConsensusHostIndex) {
343
341
  try {
344
- let res = await this.fetchBlobSidecars(hostUrl, blockHashOrSlot, l1ConsensusHostIndex, blobHashes);
342
+ let res = await this.fetchBlobSidecars(hostUrl, blockHashOrSlot, l1ConsensusHostIndex);
345
343
  if (res.ok) {
346
- return await parseBlobJsonsFromResponse(await res.json(), this.log);
344
+ return parseBlobJsonsFromResponse(await res.json(), this.log);
347
345
  }
348
346
  if (res.status === 404 && typeof blockHashOrSlot === 'number') {
349
347
  const latestSlot = await this.getLatestSlotNumber(hostUrl, l1ConsensusHostIndex);
@@ -356,9 +354,9 @@ export class HttpBlobClient {
356
354
  let currentSlot = blockHashOrSlot + 1;
357
355
  while(res.status === 404 && maxRetries > 0 && latestSlot !== undefined && currentSlot <= latestSlot){
358
356
  this.log.debug(`Trying slot ${currentSlot}`);
359
- res = await this.fetchBlobSidecars(hostUrl, currentSlot, l1ConsensusHostIndex, blobHashes);
357
+ res = await this.fetchBlobSidecars(hostUrl, currentSlot, l1ConsensusHostIndex);
360
358
  if (res.ok) {
361
- return await parseBlobJsonsFromResponse(await res.json(), this.log);
359
+ return parseBlobJsonsFromResponse(await res.json(), this.log);
362
360
  }
363
361
  currentSlot++;
364
362
  maxRetries--;
@@ -375,15 +373,8 @@ export class HttpBlobClient {
375
373
  return [];
376
374
  }
377
375
  }
378
- fetchBlobSidecars(hostUrl, blockHashOrSlot, l1ConsensusHostIndex, blobHashes) {
379
- let baseUrl = `${hostUrl}/eth/v1/beacon/blobs/${blockHashOrSlot}`;
380
- if (blobHashes && blobHashes.length > 0) {
381
- const params = new URLSearchParams();
382
- for (const hash of blobHashes){
383
- params.append('versioned_hashes', `0x${hash.toString('hex')}`);
384
- }
385
- baseUrl += `?${params.toString()}`;
386
- }
376
+ fetchBlobSidecars(hostUrl, blockHashOrSlot, l1ConsensusHostIndex) {
377
+ const baseUrl = `${hostUrl}/eth/v1/beacon/blob_sidecars/${blockHashOrSlot}`;
387
378
  const { url, ...options } = getBeaconNodeFetchOptions(baseUrl, this.config, l1ConsensusHostIndex);
388
379
  this.log.debug(`Fetching blob sidecar for ${blockHashOrSlot}`, {
389
380
  url,
@@ -429,45 +420,36 @@ export class HttpBlobClient {
429
420
  *
430
421
  * @param blockHash - The block hash
431
422
  * @returns The slot number
432
- */ async getSlotNumber(blockHash, parentBeaconBlockRoot, l1BlockTimestamp) {
423
+ */ async getSlotNumber(blockHash) {
433
424
  const { l1ConsensusHostUrls, l1RpcUrls } = this.config;
434
425
  if (!l1ConsensusHostUrls || l1ConsensusHostUrls.length === 0) {
435
426
  this.log.debug('No consensus host url configured');
436
427
  return undefined;
437
428
  }
438
- // Primary path: compute slot from timestamp if genesis config is cached (no network call needed)
439
- if (l1BlockTimestamp !== undefined && this.beaconGenesisTime !== undefined && this.beaconSecondsPerSlot !== undefined) {
440
- const slot = Number((l1BlockTimestamp - this.beaconGenesisTime) / BigInt(this.beaconSecondsPerSlot));
441
- this.log.debug(`Computed slot ${slot} from L1 block timestamp`, {
442
- l1BlockTimestamp
443
- });
444
- return slot;
429
+ if (!l1RpcUrls || l1RpcUrls.length === 0) {
430
+ this.log.debug('No execution host url configured');
431
+ return undefined;
445
432
  }
446
- if (!parentBeaconBlockRoot) {
447
- // parentBeaconBlockRoot not provided by caller — fetch it from the execution RPC
448
- if (!l1RpcUrls || l1RpcUrls.length === 0) {
449
- this.log.debug('No execution host url configured');
450
- return undefined;
451
- }
452
- const client = createPublicClient({
453
- transport: fallback(l1RpcUrls.map((url)=>http(url, {
454
- batch: false
455
- })))
433
+ // Ping execution node to get the parentBeaconBlockRoot for this block
434
+ let parentBeaconBlockRoot;
435
+ const client = createPublicClient({
436
+ transport: fallback(l1RpcUrls.map((url)=>http(url, {
437
+ batch: false
438
+ })))
439
+ });
440
+ try {
441
+ const res = await client.request({
442
+ method: 'eth_getBlockByHash',
443
+ params: [
444
+ blockHash,
445
+ /*tx flag*/ false
446
+ ]
456
447
  });
457
- try {
458
- const res = await client.request({
459
- method: 'eth_getBlockByHash',
460
- params: [
461
- blockHash,
462
- /*tx flag*/ false
463
- ]
464
- });
465
- if (res.parentBeaconBlockRoot) {
466
- parentBeaconBlockRoot = res.parentBeaconBlockRoot;
467
- }
468
- } catch (err) {
469
- this.log.error(`Error getting parent beacon block root`, err);
448
+ if (res.parentBeaconBlockRoot) {
449
+ parentBeaconBlockRoot = res.parentBeaconBlockRoot;
470
450
  }
451
+ } catch (err) {
452
+ this.log.error(`Error getting parent beacon block root`, err);
471
453
  }
472
454
  if (!parentBeaconBlockRoot) {
473
455
  this.log.error(`No parent beacon block root found for block ${blockHash}`);
@@ -499,10 +481,8 @@ export class HttpBlobClient {
499
481
  }
500
482
  /**
501
483
  * Start the blob client.
502
- * Fetches and caches beacon genesis config for timestamp-based slot resolution,
503
- * then uploads the initial healthcheck file (awaited) and starts periodic uploads.
484
+ * Uploads the initial healthcheck file (awaited) and starts periodic uploads.
504
485
  */ async start() {
505
- await this.fetchBeaconConfig();
506
486
  if (!this.fileStoreUploadClient) {
507
487
  return;
508
488
  }
@@ -521,40 +501,6 @@ export class HttpBlobClient {
521
501
  }, intervalMs);
522
502
  }
523
503
  /**
524
- * Fetches and caches beacon genesis time and slot duration from the first available consensus host.
525
- * These static values enable timestamp-based slot resolution, eliminating the per-fetch headers call.
526
- * Logs a warning and leaves fields undefined if all hosts fail, callers fall back gracefully.
527
- */ async fetchBeaconConfig() {
528
- const { l1ConsensusHostUrls } = this.config;
529
- if (!l1ConsensusHostUrls || l1ConsensusHostUrls.length === 0) {
530
- return;
531
- }
532
- for(let i = 0; i < l1ConsensusHostUrls.length; i++){
533
- try {
534
- const { url: genesisUrl, ...genesisOptions } = getBeaconNodeFetchOptions(`${l1ConsensusHostUrls[i]}/eth/v1/config/genesis`, this.config, i);
535
- const { url: specUrl, ...specOptions } = getBeaconNodeFetchOptions(`${l1ConsensusHostUrls[i]}/eth/v1/config/spec`, this.config, i);
536
- const [genesisRes, specRes] = await Promise.all([
537
- this.fetch(genesisUrl, genesisOptions),
538
- this.fetch(specUrl, specOptions)
539
- ]);
540
- if (genesisRes.ok && specRes.ok) {
541
- const genesis = await genesisRes.json();
542
- const spec = await specRes.json();
543
- this.beaconGenesisTime = BigInt(genesis.data.genesisTime);
544
- this.beaconSecondsPerSlot = parseInt(spec.data.secondsPerSlot);
545
- this.log.debug(`Fetched beacon genesis config`, {
546
- genesisTime: this.beaconGenesisTime,
547
- secondsPerSlot: this.beaconSecondsPerSlot
548
- });
549
- return;
550
- }
551
- } catch (err) {
552
- this.log.warn(`Failed to fetch beacon config from host ${l1ConsensusHostUrls[i]}`, err);
553
- }
554
- }
555
- this.log.warn('Could not fetch beacon genesis config from any consensus host — will use headers call fallback');
556
- }
557
- /**
558
504
  * Stop the blob client, clearing any periodic tasks.
559
505
  */ stop() {
560
506
  if (this.healthcheckUploadIntervalId) {
@@ -563,9 +509,10 @@ export class HttpBlobClient {
563
509
  }
564
510
  }
565
511
  }
566
- async function parseBlobJsonsFromResponse(response, logger) {
512
+ function parseBlobJsonsFromResponse(response, logger) {
567
513
  try {
568
- return await Promise.all(response.data.map(parseBlobJson));
514
+ const blobs = response.data.map(parseBlobJson);
515
+ return blobs;
569
516
  } catch (err) {
570
517
  logger.error(`Error parsing blob json from response`, err);
571
518
  return [];
@@ -575,9 +522,10 @@ async function parseBlobJsonsFromResponse(response, logger) {
575
522
  // https://ethereum.github.io/beacon-APIs/?urls.primaryName=dev#/Beacon/getBlobSidecars
576
523
  // Here we attempt to parse the response data to Buffer, and check the lengths (via Blob's constructor), to avoid
577
524
  // throwing an error down the line when calling Blob.fromJson().
578
- async function parseBlobJson(rawHex) {
579
- const blobBuffer = Buffer.from(rawHex.slice(2), 'hex');
580
- const blob = await Blob.fromBlobBuffer(blobBuffer);
525
+ function parseBlobJson(data) {
526
+ const blobBuffer = Buffer.from(data.blob.slice(2), 'hex');
527
+ const commitmentBuffer = Buffer.from(data.kzg_commitment.slice(2), 'hex');
528
+ const blob = new Blob(blobBuffer, commitmentBuffer);
581
529
  return blob.toJSON();
582
530
  }
583
531
  // Returns an array that maps each blob hash to the corresponding blob, or undefined if the blob is not found
@@ -10,17 +10,6 @@ export interface GetBlobSidecarOptions {
10
10
  * - Near tip: FileStore first with no retries (data should exist), L1 consensus second (freshest data), then FileStore with retries, then archive (eg. blobscan)
11
11
  */
12
12
  isHistoricalSync?: boolean;
13
- /**
14
- * The parent beacon block root for the L1 block containing the blobs.
15
- * If provided, skips the eth_getBlockByHash execution RPC call inside getSlotNumber.
16
- */
17
- parentBeaconBlockRoot?: string;
18
- /**
19
- * The timestamp of the L1 execution block containing the blobs.
20
- * When provided alongside a cached beacon genesis config (fetched at startup), allows computing
21
- * the beacon slot directly via timestamp math, skipping the beacon headers network call entirely.
22
- */
23
- l1BlockTimestamp?: bigint;
24
13
  }
25
14
  export interface BlobClientInterface {
26
15
  /** Sends the given blobs to the filestore, to be indexed by blob hash. */
@@ -36,4 +25,4 @@ export interface BlobClientInterface {
36
25
  /** Returns true if this client can upload blobs to filestore. */
37
26
  canUpload(): boolean;
38
27
  }
39
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW50ZXJmYWNlLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY2xpZW50L2ludGVyZmFjZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssRUFBRSxJQUFJLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUU1Qzs7R0FFRztBQUNILE1BQU0sV0FBVyxxQkFBcUI7SUFDcEM7Ozs7O09BS0c7SUFDSCxnQkFBZ0IsQ0FBQyxFQUFFLE9BQU8sQ0FBQztJQUMzQjs7O09BR0c7SUFDSCxxQkFBcUIsQ0FBQyxFQUFFLE1BQU0sQ0FBQztJQUMvQjs7OztPQUlHO0lBQ0gsZ0JBQWdCLENBQUMsRUFBRSxNQUFNLENBQUM7Q0FDM0I7QUFFRCxNQUFNLFdBQVcsbUJBQW1CO0lBQ2xDLDBFQUEwRTtJQUMxRSxvQkFBb0IsQ0FBQyxLQUFLLEVBQUUsSUFBSSxFQUFFLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ3RELHFFQUFxRTtJQUNyRSxjQUFjLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxVQUFVLENBQUMsRUFBRSxNQUFNLEVBQUUsRUFBRSxJQUFJLENBQUMsRUFBRSxxQkFBcUIsR0FBRyxPQUFPLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUN0Ryw2RUFBNkU7SUFDN0UsS0FBSyxDQUFDLElBQUksT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3hCLG9GQUFvRjtJQUNwRixXQUFXLElBQUksT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzdCLDBEQUEwRDtJQUMxRCxJQUFJLENBQUMsSUFBSSxJQUFJLENBQUM7SUFDZCxpRUFBaUU7SUFDakUsU0FBUyxJQUFJLE9BQU8sQ0FBQztDQUN0QiJ9
28
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW50ZXJmYWNlLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY2xpZW50L2ludGVyZmFjZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssRUFBRSxJQUFJLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUU1Qzs7R0FFRztBQUNILE1BQU0sV0FBVyxxQkFBcUI7SUFDcEM7Ozs7O09BS0c7SUFDSCxnQkFBZ0IsQ0FBQyxFQUFFLE9BQU8sQ0FBQztDQUM1QjtBQUVELE1BQU0sV0FBVyxtQkFBbUI7SUFDbEMsMEVBQTBFO0lBQzFFLG9CQUFvQixDQUFDLEtBQUssRUFBRSxJQUFJLEVBQUUsR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDdEQscUVBQXFFO0lBQ3JFLGNBQWMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLFVBQVUsQ0FBQyxFQUFFLE1BQU0sRUFBRSxFQUFFLElBQUksQ0FBQyxFQUFFLHFCQUFxQixHQUFHLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQ3RHLDZFQUE2RTtJQUM3RSxLQUFLLENBQUMsSUFBSSxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDeEIsb0ZBQW9GO0lBQ3BGLFdBQVcsSUFBSSxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDN0IsMERBQTBEO0lBQzFELElBQUksQ0FBQyxJQUFJLElBQUksQ0FBQztJQUNkLGlFQUFpRTtJQUNqRSxTQUFTLElBQUksT0FBTyxDQUFDO0NBQ3RCIn0=
@@ -1 +1 @@
1
- {"version":3,"file":"interface.d.ts","sourceRoot":"","sources":["../../src/client/interface.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAE5C;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;;OAGG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,mBAAmB;IAClC,0EAA0E;IAC1E,oBAAoB,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACtD,qEAAqE;IACrE,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,EAAE,IAAI,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IACtG,6EAA6E;IAC7E,KAAK,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACxB,oFAAoF;IACpF,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,0DAA0D;IAC1D,IAAI,CAAC,IAAI,IAAI,CAAC;IACd,iEAAiE;IACjE,SAAS,IAAI,OAAO,CAAC;CACtB"}
1
+ {"version":3,"file":"interface.d.ts","sourceRoot":"","sources":["../../src/client/interface.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAE5C;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,mBAAmB;IAClC,0EAA0E;IAC1E,oBAAoB,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACtD,qEAAqE;IACrE,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,EAAE,IAAI,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IACtG,6EAA6E;IAC7E,KAAK,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACxB,oFAAoF;IACpF,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,0DAA0D;IAC1D,IAAI,CAAC,IAAI,IAAI,CAAC;IACd,iEAAiE;IACjE,SAAS,IAAI,OAAO,CAAC;CACtB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/blob-client",
3
- "version": "0.0.1-commit.f504929",
3
+ "version": "0.0.1-commit.f81dbcf",
4
4
  "type": "module",
5
5
  "bin": "./dest/client/bin/index.js",
6
6
  "exports": {
@@ -56,12 +56,12 @@
56
56
  ]
57
57
  },
58
58
  "dependencies": {
59
- "@aztec/blob-lib": "0.0.1-commit.f504929",
60
- "@aztec/ethereum": "0.0.1-commit.f504929",
61
- "@aztec/foundation": "0.0.1-commit.f504929",
62
- "@aztec/kv-store": "0.0.1-commit.f504929",
63
- "@aztec/stdlib": "0.0.1-commit.f504929",
64
- "@aztec/telemetry-client": "0.0.1-commit.f504929",
59
+ "@aztec/blob-lib": "0.0.1-commit.f81dbcf",
60
+ "@aztec/ethereum": "0.0.1-commit.f81dbcf",
61
+ "@aztec/foundation": "0.0.1-commit.f81dbcf",
62
+ "@aztec/kv-store": "0.0.1-commit.f81dbcf",
63
+ "@aztec/stdlib": "0.0.1-commit.f81dbcf",
64
+ "@aztec/telemetry-client": "0.0.1-commit.f81dbcf",
65
65
  "express": "^4.21.2",
66
66
  "snappy": "^7.2.2",
67
67
  "source-map-support": "^0.5.21",
@@ -24,11 +24,6 @@ export class HttpBlobClient implements BlobClientInterface {
24
24
  private disabled = false;
25
25
  private healthcheckUploadIntervalId?: NodeJS.Timeout;
26
26
 
27
- /** Cached beacon genesis time (seconds since Unix epoch). Fetched once at startup. */
28
- private beaconGenesisTime?: bigint;
29
- /** Cached beacon slot duration in seconds. Fetched once at startup. */
30
- private beaconSecondsPerSlot?: number;
31
-
32
27
  constructor(
33
28
  config?: BlobClientConfig,
34
29
  private readonly opts: {
@@ -256,7 +251,7 @@ export class HttpBlobClient implements BlobClientInterface {
256
251
  // The beacon api can query by slot number, so we get that first
257
252
  const consensusCtx = { l1ConsensusHostUrls, ...ctx };
258
253
  this.log.trace(`Attempting to get slot number for block hash`, consensusCtx);
259
- const slotNumber = await this.getSlotNumber(blockHash, opts?.parentBeaconBlockRoot, opts?.l1BlockTimestamp);
254
+ const slotNumber = await this.getSlotNumber(blockHash);
260
255
  this.log.debug(`Got slot number ${slotNumber} from consensus host for querying blobs`, consensusCtx);
261
256
 
262
257
  if (slotNumber) {
@@ -273,12 +268,7 @@ export class HttpBlobClient implements BlobClientInterface {
273
268
  l1ConsensusHostUrl,
274
269
  ...ctx,
275
270
  });
276
- const blobs = await this.getBlobsFromHost(
277
- l1ConsensusHostUrl,
278
- slotNumber,
279
- l1ConsensusHostIndex,
280
- getMissingBlobHashes(),
281
- );
271
+ const blobs = await this.getBlobsFromHost(l1ConsensusHostUrl, slotNumber, l1ConsensusHostIndex);
282
272
  const result = await fillResults(blobs);
283
273
  this.log.debug(
284
274
  `Got ${blobs.length} blobs from consensus host (total: ${result.length}/${blobHashes.length})`,
@@ -397,7 +387,7 @@ export class HttpBlobClient implements BlobClientInterface {
397
387
  blobHashes: Buffer[] = [],
398
388
  l1ConsensusHostIndex?: number,
399
389
  ): Promise<Blob[]> {
400
- const blobs = await this.getBlobsFromHost(hostUrl, blockHashOrSlot, l1ConsensusHostIndex, blobHashes);
390
+ const blobs = await this.getBlobsFromHost(hostUrl, blockHashOrSlot, l1ConsensusHostIndex);
401
391
  return (await processFetchedBlobs(blobs, blobHashes, this.log)).filter((b): b is Blob => b !== undefined);
402
392
  }
403
393
 
@@ -405,12 +395,11 @@ export class HttpBlobClient implements BlobClientInterface {
405
395
  hostUrl: string,
406
396
  blockHashOrSlot: string | number,
407
397
  l1ConsensusHostIndex?: number,
408
- blobHashes?: Buffer[],
409
398
  ): Promise<BlobJson[]> {
410
399
  try {
411
- let res = await this.fetchBlobSidecars(hostUrl, blockHashOrSlot, l1ConsensusHostIndex, blobHashes);
400
+ let res = await this.fetchBlobSidecars(hostUrl, blockHashOrSlot, l1ConsensusHostIndex);
412
401
  if (res.ok) {
413
- return await parseBlobJsonsFromResponse(await res.json(), this.log);
402
+ return parseBlobJsonsFromResponse(await res.json(), this.log);
414
403
  }
415
404
 
416
405
  if (res.status === 404 && typeof blockHashOrSlot === 'number') {
@@ -425,9 +414,9 @@ export class HttpBlobClient implements BlobClientInterface {
425
414
  let currentSlot = blockHashOrSlot + 1;
426
415
  while (res.status === 404 && maxRetries > 0 && latestSlot !== undefined && currentSlot <= latestSlot) {
427
416
  this.log.debug(`Trying slot ${currentSlot}`);
428
- res = await this.fetchBlobSidecars(hostUrl, currentSlot, l1ConsensusHostIndex, blobHashes);
417
+ res = await this.fetchBlobSidecars(hostUrl, currentSlot, l1ConsensusHostIndex);
429
418
  if (res.ok) {
430
- return await parseBlobJsonsFromResponse(await res.json(), this.log);
419
+ return parseBlobJsonsFromResponse(await res.json(), this.log);
431
420
  }
432
421
  currentSlot++;
433
422
  maxRetries--;
@@ -450,17 +439,8 @@ export class HttpBlobClient implements BlobClientInterface {
450
439
  hostUrl: string,
451
440
  blockHashOrSlot: string | number,
452
441
  l1ConsensusHostIndex?: number,
453
- blobHashes?: Buffer[],
454
442
  ): Promise<Response> {
455
- let baseUrl = `${hostUrl}/eth/v1/beacon/blobs/${blockHashOrSlot}`;
456
-
457
- if (blobHashes && blobHashes.length > 0) {
458
- const params = new URLSearchParams();
459
- for (const hash of blobHashes) {
460
- params.append('versioned_hashes', `0x${hash.toString('hex')}`);
461
- }
462
- baseUrl += `?${params.toString()}`;
463
- }
443
+ const baseUrl = `${hostUrl}/eth/v1/beacon/blob_sidecars/${blockHashOrSlot}`;
464
444
 
465
445
  const { url, ...options } = getBeaconNodeFetchOptions(baseUrl, this.config, l1ConsensusHostIndex);
466
446
  this.log.debug(`Fetching blob sidecar for ${blockHashOrSlot}`, { url, ...options });
@@ -502,50 +482,34 @@ export class HttpBlobClient implements BlobClientInterface {
502
482
  * @param blockHash - The block hash
503
483
  * @returns The slot number
504
484
  */
505
- private async getSlotNumber(
506
- blockHash: `0x${string}`,
507
- parentBeaconBlockRoot?: string,
508
- l1BlockTimestamp?: bigint,
509
- ): Promise<number | undefined> {
485
+ private async getSlotNumber(blockHash: `0x${string}`): Promise<number | undefined> {
510
486
  const { l1ConsensusHostUrls, l1RpcUrls } = this.config;
511
487
  if (!l1ConsensusHostUrls || l1ConsensusHostUrls.length === 0) {
512
488
  this.log.debug('No consensus host url configured');
513
489
  return undefined;
514
490
  }
515
491
 
516
- // Primary path: compute slot from timestamp if genesis config is cached (no network call needed)
517
- if (
518
- l1BlockTimestamp !== undefined &&
519
- this.beaconGenesisTime !== undefined &&
520
- this.beaconSecondsPerSlot !== undefined
521
- ) {
522
- const slot = Number((l1BlockTimestamp - this.beaconGenesisTime) / BigInt(this.beaconSecondsPerSlot));
523
- this.log.debug(`Computed slot ${slot} from L1 block timestamp`, { l1BlockTimestamp });
524
- return slot;
492
+ if (!l1RpcUrls || l1RpcUrls.length === 0) {
493
+ this.log.debug('No execution host url configured');
494
+ return undefined;
525
495
  }
526
496
 
527
- if (!parentBeaconBlockRoot) {
528
- // parentBeaconBlockRoot not provided by caller — fetch it from the execution RPC
529
- if (!l1RpcUrls || l1RpcUrls.length === 0) {
530
- this.log.debug('No execution host url configured');
531
- return undefined;
532
- }
533
-
534
- const client = createPublicClient({
535
- transport: fallback(l1RpcUrls.map(url => http(url, { batch: false }))),
497
+ // Ping execution node to get the parentBeaconBlockRoot for this block
498
+ let parentBeaconBlockRoot: string | undefined;
499
+ const client = createPublicClient({
500
+ transport: fallback(l1RpcUrls.map(url => http(url, { batch: false }))),
501
+ });
502
+ try {
503
+ const res: RpcBlock = await client.request({
504
+ method: 'eth_getBlockByHash',
505
+ params: [blockHash, /*tx flag*/ false],
536
506
  });
537
- try {
538
- const res: RpcBlock = await client.request({
539
- method: 'eth_getBlockByHash',
540
- params: [blockHash, /*tx flag*/ false],
541
- });
542
507
 
543
- if (res.parentBeaconBlockRoot) {
544
- parentBeaconBlockRoot = res.parentBeaconBlockRoot;
545
- }
546
- } catch (err) {
547
- this.log.error(`Error getting parent beacon block root`, err);
508
+ if (res.parentBeaconBlockRoot) {
509
+ parentBeaconBlockRoot = res.parentBeaconBlockRoot;
548
510
  }
511
+ } catch (err) {
512
+ this.log.error(`Error getting parent beacon block root`, err);
549
513
  }
550
514
 
551
515
  if (!parentBeaconBlockRoot) {
@@ -591,12 +555,9 @@ export class HttpBlobClient implements BlobClientInterface {
591
555
 
592
556
  /**
593
557
  * Start the blob client.
594
- * Fetches and caches beacon genesis config for timestamp-based slot resolution,
595
- * then uploads the initial healthcheck file (awaited) and starts periodic uploads.
558
+ * Uploads the initial healthcheck file (awaited) and starts periodic uploads.
596
559
  */
597
560
  public async start(): Promise<void> {
598
- await this.fetchBeaconConfig();
599
-
600
561
  if (!this.fileStoreUploadClient) {
601
562
  return;
602
563
  }
@@ -621,53 +582,6 @@ export class HttpBlobClient implements BlobClientInterface {
621
582
  }, intervalMs);
622
583
  }
623
584
 
624
- /**
625
- * Fetches and caches beacon genesis time and slot duration from the first available consensus host.
626
- * These static values enable timestamp-based slot resolution, eliminating the per-fetch headers call.
627
- * Logs a warning and leaves fields undefined if all hosts fail, callers fall back gracefully.
628
- */
629
- private async fetchBeaconConfig(): Promise<void> {
630
- const { l1ConsensusHostUrls } = this.config;
631
- if (!l1ConsensusHostUrls || l1ConsensusHostUrls.length === 0) {
632
- return;
633
- }
634
-
635
- for (let i = 0; i < l1ConsensusHostUrls.length; i++) {
636
- try {
637
- const { url: genesisUrl, ...genesisOptions } = getBeaconNodeFetchOptions(
638
- `${l1ConsensusHostUrls[i]}/eth/v1/config/genesis`,
639
- this.config,
640
- i,
641
- );
642
- const { url: specUrl, ...specOptions } = getBeaconNodeFetchOptions(
643
- `${l1ConsensusHostUrls[i]}/eth/v1/config/spec`,
644
- this.config,
645
- i,
646
- );
647
-
648
- const [genesisRes, specRes] = await Promise.all([
649
- this.fetch(genesisUrl, genesisOptions),
650
- this.fetch(specUrl, specOptions),
651
- ]);
652
-
653
- if (genesisRes.ok && specRes.ok) {
654
- const genesis = await genesisRes.json();
655
- const spec = await specRes.json();
656
- this.beaconGenesisTime = BigInt(genesis.data.genesisTime);
657
- this.beaconSecondsPerSlot = parseInt(spec.data.secondsPerSlot);
658
- this.log.debug(`Fetched beacon genesis config`, {
659
- genesisTime: this.beaconGenesisTime,
660
- secondsPerSlot: this.beaconSecondsPerSlot,
661
- });
662
- return;
663
- }
664
- } catch (err) {
665
- this.log.warn(`Failed to fetch beacon config from host ${l1ConsensusHostUrls[i]}`, err);
666
- }
667
- }
668
- this.log.warn('Could not fetch beacon genesis config from any consensus host — will use headers call fallback');
669
- }
670
-
671
585
  /**
672
586
  * Stop the blob client, clearing any periodic tasks.
673
587
  */
@@ -679,9 +593,10 @@ export class HttpBlobClient implements BlobClientInterface {
679
593
  }
680
594
  }
681
595
 
682
- async function parseBlobJsonsFromResponse(response: any, logger: Logger): Promise<BlobJson[]> {
596
+ function parseBlobJsonsFromResponse(response: any, logger: Logger): BlobJson[] {
683
597
  try {
684
- return await Promise.all((response.data as string[]).map(parseBlobJson));
598
+ const blobs = response.data.map(parseBlobJson);
599
+ return blobs;
685
600
  } catch (err) {
686
601
  logger.error(`Error parsing blob json from response`, err);
687
602
  return [];
@@ -692,9 +607,10 @@ async function parseBlobJsonsFromResponse(response: any, logger: Logger): Promis
692
607
  // https://ethereum.github.io/beacon-APIs/?urls.primaryName=dev#/Beacon/getBlobSidecars
693
608
  // Here we attempt to parse the response data to Buffer, and check the lengths (via Blob's constructor), to avoid
694
609
  // throwing an error down the line when calling Blob.fromJson().
695
- async function parseBlobJson(rawHex: string): Promise<BlobJson> {
696
- const blobBuffer = Buffer.from(rawHex.slice(2), 'hex');
697
- const blob = await Blob.fromBlobBuffer(blobBuffer);
610
+ function parseBlobJson(data: any): BlobJson {
611
+ const blobBuffer = Buffer.from(data.blob.slice(2), 'hex');
612
+ const commitmentBuffer = Buffer.from(data.kzg_commitment.slice(2), 'hex');
613
+ const blob = new Blob(blobBuffer, commitmentBuffer);
698
614
  return blob.toJSON();
699
615
  }
700
616
 
@@ -11,17 +11,6 @@ export interface GetBlobSidecarOptions {
11
11
  * - Near tip: FileStore first with no retries (data should exist), L1 consensus second (freshest data), then FileStore with retries, then archive (eg. blobscan)
12
12
  */
13
13
  isHistoricalSync?: boolean;
14
- /**
15
- * The parent beacon block root for the L1 block containing the blobs.
16
- * If provided, skips the eth_getBlockByHash execution RPC call inside getSlotNumber.
17
- */
18
- parentBeaconBlockRoot?: string;
19
- /**
20
- * The timestamp of the L1 execution block containing the blobs.
21
- * When provided alongside a cached beacon genesis config (fetched at startup), allows computing
22
- * the beacon slot directly via timestamp math, skipping the beacon headers network call entirely.
23
- */
24
- l1BlockTimestamp?: bigint;
25
14
  }
26
15
 
27
16
  export interface BlobClientInterface {