@xyo-network/xl1-rest-block-viewer 2.1.2 → 2.1.4

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 CHANGED
@@ -64,7 +64,9 @@ bun add @xyo-network/xl1-rest-block-viewer
64
64
  ## What's Inside
65
65
 
66
66
  - **`RestBlockViewer`** — full `BlockViewer` implementation: blocks by number/hash, walking reads, `currentBlock` head polling with `headUpdated` events, completed-step `blocksByStep`, payloads by hash, and the rate calculations.
67
- - **`paths.ts`** — the static layout contract (`headPath`, `blockNumberPath`, `blockHashPath`, `blocksStepPath`, `payloadPath`) shared with the publisher.
67
+ - **`RestChainStateViewer`** — focused `ChainStateViewer` implementation: just the head pointer, with optional `headUpdated` polling.
68
+ - **`RestIndexViewer`** — focused `IndexViewer` implementation: published step summaries (the chain index).
69
+ - **`paths.ts`** — the static layout contract (`headPath`, `blockNumberPath`, `blockHashPath`, `blocksStepPath`, `payloadPath`) shared with the publish runners.
68
70
 
69
71
  ## Building Locally
70
72
 
@@ -0,0 +1,51 @@
1
+ import type { Hash } from '@xylabs/sdk-js';
2
+ import type { ChainStateViewer, SignedHydratedBlockWithHashMeta, XL1BlockNumber } from '@xyo-network/xl1-protocol-lib';
3
+ import type { CreatableProviderParams } from '@xyo-network/xl1-protocol-sdk';
4
+ import { AbstractCreatableProvider } from '@xyo-network/xl1-protocol-sdk';
5
+ /** Parameters for RestChainStateViewer. */
6
+ export interface RestChainStateViewerParams extends CreatableProviderParams {
7
+ /** Base URL serving the mutable chain state (the head pointer, `chain/head.json`). */
8
+ chainStateBaseUrl: string;
9
+ /** Optional fetch override (custom agents, auth headers, tests). Defaults to the global fetch. */
10
+ fetchFn?: typeof globalThis.fetch;
11
+ headPollIntervalMs?: number;
12
+ }
13
+ /**
14
+ * A ChainStateViewer over the statically generated REST file layout (see `paths.ts`):
15
+ * anonymous HTTP reads of the one mutable file, the head pointer. When configured with
16
+ * `headPollIntervalMs`, polls the head and emits `headUpdated` as the chain advances.
17
+ */
18
+ export declare class RestChainStateViewer extends AbstractCreatableProvider<RestChainStateViewerParams, ChainStateViewer['eventData']> implements ChainStateViewer {
19
+ static readonly defaultMoniker: "ChainStateViewer";
20
+ static readonly dependencies: never[];
21
+ static readonly monikers: "ChainStateViewer"[];
22
+ moniker: "ChainStateViewer";
23
+ private _headPollHash?;
24
+ private _headPollInProgress;
25
+ private _headPollTimer;
26
+ get chainStateBaseUrl(): string;
27
+ protected get fetchFn(): typeof globalThis.fetch;
28
+ protected get headPollIntervalMs(): number | undefined;
29
+ static paramsHandler(params: Partial<RestChainStateViewerParams>): Promise<{
30
+ chainStateBaseUrl: string;
31
+ fetchFn: typeof fetch | undefined;
32
+ headPollIntervalMs: number | undefined;
33
+ context: import("@xyo-network/xl1-protocol-sdk").CreatableProviderContextType;
34
+ name?: import("@xylabs/sdk-js").CreatableName;
35
+ statusReporter?: import("@xylabs/sdk-js").CreatableStatusReporter<void> | undefined;
36
+ logger?: import("@xylabs/sdk-js").Logger;
37
+ meterProvider?: import("@opentelemetry/api").MeterProvider;
38
+ traceProvider?: import("@opentelemetry/api").TracerProvider;
39
+ }>;
40
+ currentBlock(): Promise<SignedHydratedBlockWithHashMeta>;
41
+ currentBlockHash(): Promise<Hash>;
42
+ currentBlockNumber(): Promise<XL1BlockNumber>;
43
+ /** The published head, or undefined when no head pointer has been published yet. */
44
+ tryCurrentBlock(): Promise<SignedHydratedBlockWithHashMeta | undefined>;
45
+ protected startHandler(): Promise<void>;
46
+ protected stopHandler(): Promise<void>;
47
+ private pollHead;
48
+ private startHeadPolling;
49
+ private stopHeadPolling;
50
+ }
51
+ //# sourceMappingURL=RestChainStateViewer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RestChainStateViewer.d.ts","sourceRoot":"","sources":["../../src/RestChainStateViewer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAA;AAE1C,OAAO,KAAK,EACV,gBAAgB,EAAE,+BAA+B,EAAE,cAAc,EAClE,MAAM,+BAA+B,CAAA;AAEtC,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAA;AAC5E,OAAO,EAAE,yBAAyB,EAAqB,MAAM,+BAA+B,CAAA;AAI5F,2CAA2C;AAC3C,MAAM,WAAW,0BAA2B,SAAQ,uBAAuB;IACzE,sFAAsF;IACtF,iBAAiB,EAAE,MAAM,CAAA;IACzB,kGAAkG;IAClG,OAAO,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAA;IACjC,kBAAkB,CAAC,EAAE,MAAM,CAAA;CAC5B;AAID;;;;GAIG;AACH,qBACa,oBAAqB,SAAQ,yBAAyB,CAAC,0BAA0B,EAAE,gBAAgB,CAAC,WAAW,CAAC,CAC3H,YAAW,gBAAgB;IAC3B,MAAM,CAAC,QAAQ,CAAC,cAAc,qBAA0B;IACxD,MAAM,CAAC,QAAQ,CAAC,YAAY,UAAK;IACjC,MAAM,CAAC,QAAQ,CAAC,QAAQ,uBAA4B;IACpD,OAAO,qBAAsC;IAE7C,OAAO,CAAC,aAAa,CAAC,CAAM;IAC5B,OAAO,CAAC,mBAAmB,CAAQ;IACnC,OAAO,CAAC,cAAc,CAA8C;IAEpE,IAAI,iBAAiB,IAAI,MAAM,CAE9B;IAED,SAAS,KAAK,OAAO,IAAI,OAAO,UAAU,CAAC,KAAK,CAE/C;IAED,SAAS,KAAK,kBAAkB,uBAE/B;WAEqB,aAAa,CAAC,MAAM,EAAE,OAAO,CAAC,0BAA0B,CAAC;;;;;;;;;;;IAazE,YAAY,IAAI,OAAO,CAAC,+BAA+B,CAAC;IAQxD,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;IAIjC,kBAAkB,IAAI,OAAO,CAAC,cAAc,CAAC;IAInD,oFAAoF;IAC9E,eAAe,IAAI,OAAO,CAAC,+BAA+B,GAAG,SAAS,CAAC;cAOpD,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;cAO7B,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;YAMvC,QAAQ;IAuBtB,OAAO,CAAC,gBAAgB;IAQxB,OAAO,CAAC,eAAe;CAMxB"}
@@ -0,0 +1,39 @@
1
+ import { LruCacheMap } from '@xyo-network/xl1-driver-memory';
2
+ import type { BlocksStepSummary, IndexViewer } from '@xyo-network/xl1-protocol-lib';
3
+ import type { CreatableProviderParams } from '@xyo-network/xl1-protocol-sdk';
4
+ import { AbstractCreatableProvider } from '@xyo-network/xl1-protocol-sdk';
5
+ /** Parameters for RestIndexViewer. */
6
+ export interface RestIndexViewerParams extends CreatableProviderParams {
7
+ /** Optional fetch override (custom agents, auth headers, tests). Defaults to the global fetch. */
8
+ fetchFn?: typeof globalThis.fetch;
9
+ /** Base URL of the finalized (immutable) static chain files (e.g. a public R2 bucket or CDN domain). */
10
+ finalizedBaseUrl: string;
11
+ }
12
+ /**
13
+ * An IndexViewer over the statically generated REST file layout (see `paths.ts`): anonymous
14
+ * HTTP reads of published step summary files. Only completed steps are published — the
15
+ * in-flight tail step has no file and reads as null. Files are immutable, so responses are
16
+ * cached aggressively (in-memory LRU here, CDN/edge in front).
17
+ */
18
+ export declare class RestIndexViewer extends AbstractCreatableProvider<RestIndexViewerParams> implements IndexViewer {
19
+ static readonly defaultMoniker: "IndexViewer";
20
+ static readonly dependencies: never[];
21
+ static readonly monikers: "IndexViewer"[];
22
+ moniker: "IndexViewer";
23
+ protected summaryCache: LruCacheMap<string, BlocksStepSummary, () => void>;
24
+ get finalizedBaseUrl(): string;
25
+ protected get fetchFn(): typeof globalThis.fetch;
26
+ static paramsHandler(params: Partial<RestIndexViewerParams>): Promise<{
27
+ fetchFn: typeof fetch | undefined;
28
+ finalizedBaseUrl: string;
29
+ context: import("@xyo-network/xl1-protocol-sdk").CreatableProviderContextType;
30
+ name?: import("@xylabs/sdk-js").CreatableName;
31
+ statusReporter?: import("@xylabs/sdk-js").CreatableStatusReporter<void> | undefined;
32
+ logger?: import("@xylabs/sdk-js").Logger;
33
+ meterProvider?: import("@opentelemetry/api").MeterProvider;
34
+ traceProvider?: import("@opentelemetry/api").TracerProvider;
35
+ }>;
36
+ /** The published summary for a completed step, or null when not (yet) published. */
37
+ blocksStepSummary(stepLevel: number, stepIndex: number): Promise<BlocksStepSummary | null>;
38
+ }
39
+ //# sourceMappingURL=RestIndexViewer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RestIndexViewer.d.ts","sourceRoot":"","sources":["../../src/RestIndexViewer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAA;AAC5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAA;AAInF,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAA;AAC5E,OAAO,EACL,yBAAyB,EAC1B,MAAM,+BAA+B,CAAA;AAItC,sCAAsC;AACtC,MAAM,WAAW,qBAAsB,SAAQ,uBAAuB;IACpE,kGAAkG;IAClG,OAAO,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAA;IACjC,wGAAwG;IACxG,gBAAgB,EAAE,MAAM,CAAA;CACzB;AAED;;;;;GAKG;AACH,qBACa,eAAgB,SAAQ,yBAAyB,CAAC,qBAAqB,CAAE,YAAW,WAAW;IAC1G,MAAM,CAAC,QAAQ,CAAC,cAAc,gBAAqB;IACnD,MAAM,CAAC,QAAQ,CAAC,YAAY,UAAK;IACjC,MAAM,CAAC,QAAQ,CAAC,QAAQ,kBAAuB;IAC/C,OAAO,gBAAiC;IAExC,SAAS,CAAC,YAAY,qDAAyD;IAE/E,IAAI,gBAAgB,IAAI,MAAM,CAE7B;IAED,SAAS,KAAK,OAAO,IAAI,OAAO,UAAU,CAAC,KAAK,CAE/C;WAEqB,aAAa,CAAC,MAAM,EAAE,OAAO,CAAC,qBAAqB,CAAC;;;;;;;;;;IAQ1E,oFAAoF;IAC9E,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;CAqBjG"}
@@ -1,3 +1,5 @@
1
1
  export * from './paths.ts';
2
2
  export * from './RestBlockViewer.ts';
3
+ export * from './RestChainStateViewer.ts';
4
+ export * from './RestIndexViewer.ts';
3
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAC1B,cAAc,sBAAsB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAC1B,cAAc,sBAAsB,CAAA;AACpC,cAAc,2BAA2B,CAAA;AACzC,cAAc,sBAAsB,CAAA"}
@@ -23,6 +23,7 @@ import { assertEx, exists } from "@xylabs/sdk-js";
23
23
  import { PayloadZodLoose, WithHashMetaZod } from "@xyo-network/sdk-js";
24
24
  import { LruCacheMap } from "@xyo-network/xl1-driver-memory";
25
25
  import {
26
+ asBlocksStepSummary,
26
27
  asSignedHydratedBlockWithHashMeta,
27
28
  asXL1BlockNumber,
28
29
  BlockViewerMoniker,
@@ -30,7 +31,6 @@ import {
30
31
  } from "@xyo-network/xl1-protocol-lib";
31
32
  import {
32
33
  AbstractCreatableProvider,
33
- asBlocksStepSummary,
34
34
  blocksMaxStep,
35
35
  calculateBlockRate,
36
36
  calculateStepSizeRate,
@@ -247,8 +247,173 @@ __publicField(RestBlockViewer, "monikers", [BlockViewerMoniker]);
247
247
  RestBlockViewer = __decorateClass([
248
248
  creatableProvider()
249
249
  ], RestBlockViewer);
250
+
251
+ // src/RestChainStateViewer.ts
252
+ import { assertEx as assertEx2 } from "@xylabs/sdk-js";
253
+ import { asSignedHydratedBlockWithHashMeta as asSignedHydratedBlockWithHashMeta2, ChainStateViewerMoniker } from "@xyo-network/xl1-protocol-lib";
254
+ import { AbstractCreatableProvider as AbstractCreatableProvider2, creatableProvider as creatableProvider2 } from "@xyo-network/xl1-protocol-sdk";
255
+ var MIN_HEAD_POLL_INTERVAL_MS2 = 5e3;
256
+ var RestChainStateViewer = class extends AbstractCreatableProvider2 {
257
+ moniker = RestChainStateViewer.defaultMoniker;
258
+ _headPollHash;
259
+ _headPollInProgress = false;
260
+ _headPollTimer = null;
261
+ get chainStateBaseUrl() {
262
+ return this.params.chainStateBaseUrl;
263
+ }
264
+ get fetchFn() {
265
+ return this.params.fetchFn ?? globalThis.fetch.bind(globalThis);
266
+ }
267
+ get headPollIntervalMs() {
268
+ return this.params.headPollIntervalMs;
269
+ }
270
+ static async paramsHandler(params) {
271
+ const headPollIntervalMs = params.headPollIntervalMs;
272
+ if (headPollIntervalMs !== void 0) {
273
+ assertEx2(headPollIntervalMs >= MIN_HEAD_POLL_INTERVAL_MS2, () => `headPollIntervalMs must be at least ${MIN_HEAD_POLL_INTERVAL_MS2}ms`);
274
+ }
275
+ return {
276
+ ...await super.paramsHandler(params),
277
+ chainStateBaseUrl: assertEx2(params.chainStateBaseUrl, () => "chainStateBaseUrl is required").replace(/\/+$/, ""),
278
+ fetchFn: params.fetchFn,
279
+ headPollIntervalMs
280
+ };
281
+ }
282
+ async currentBlock() {
283
+ return await this.spanAsync("currentBlock", async () => {
284
+ const response = await this.fetchFn(`${this.chainStateBaseUrl}/${headPath()}`);
285
+ assertEx2(response.ok, () => `Head not found [${response.status}]`);
286
+ return asSignedHydratedBlockWithHashMeta2(await response.json(), true);
287
+ }, this.context);
288
+ }
289
+ async currentBlockHash() {
290
+ return (await this.currentBlock())[0]._hash;
291
+ }
292
+ async currentBlockNumber() {
293
+ return (await this.currentBlock())[0].block;
294
+ }
295
+ /** The published head, or undefined when no head pointer has been published yet. */
296
+ async tryCurrentBlock() {
297
+ const response = await this.fetchFn(`${this.chainStateBaseUrl}/${headPath()}`);
298
+ if (response.status === 404) return void 0;
299
+ assertEx2(response.ok, () => `Head request failed [${response.status}]`);
300
+ return asSignedHydratedBlockWithHashMeta2(await response.json(), true);
301
+ }
302
+ async startHandler() {
303
+ await super.startHandler();
304
+ if (this.headPollIntervalMs === void 0) return;
305
+ await this.pollHead(false);
306
+ this.startHeadPolling();
307
+ }
308
+ async stopHandler() {
309
+ this.stopHeadPolling();
310
+ this._headPollHash = void 0;
311
+ await super.stopHandler();
312
+ }
313
+ async pollHead(emitOnChange) {
314
+ if (this._headPollInProgress) return;
315
+ this._headPollInProgress = true;
316
+ try {
317
+ const block = await this.currentBlock();
318
+ const hash = block[0]._hash;
319
+ if (this._headPollHash === void 0) {
320
+ this._headPollHash = hash;
321
+ return;
322
+ }
323
+ if (hash !== this._headPollHash) {
324
+ this._headPollHash = hash;
325
+ if (emitOnChange) {
326
+ await this.emit("headUpdated", { block });
327
+ }
328
+ }
329
+ } catch (ex) {
330
+ this.logger?.error("Error polling block head", ex);
331
+ } finally {
332
+ this._headPollInProgress = false;
333
+ }
334
+ }
335
+ startHeadPolling() {
336
+ if (this.headPollIntervalMs === void 0) return;
337
+ this.stopHeadPolling();
338
+ this._headPollTimer = setInterval(() => {
339
+ void this.pollHead(true);
340
+ }, this.headPollIntervalMs);
341
+ }
342
+ stopHeadPolling() {
343
+ if (this._headPollTimer) {
344
+ clearInterval(this._headPollTimer);
345
+ this._headPollTimer = null;
346
+ }
347
+ }
348
+ };
349
+ __publicField(RestChainStateViewer, "defaultMoniker", ChainStateViewerMoniker);
350
+ __publicField(RestChainStateViewer, "dependencies", []);
351
+ __publicField(RestChainStateViewer, "monikers", [ChainStateViewerMoniker]);
352
+ RestChainStateViewer = __decorateClass([
353
+ creatableProvider2()
354
+ ], RestChainStateViewer);
355
+
356
+ // src/RestIndexViewer.ts
357
+ import { assertEx as assertEx3 } from "@xylabs/sdk-js";
358
+ import { LruCacheMap as LruCacheMap2 } from "@xyo-network/xl1-driver-memory";
359
+ import {
360
+ asBlocksStepSummary as asBlocksStepSummary2,
361
+ IndexViewerMoniker,
362
+ stepSize as stepSize2
363
+ } from "@xyo-network/xl1-protocol-lib";
364
+ import {
365
+ AbstractCreatableProvider as AbstractCreatableProvider3,
366
+ blocksMaxStep as blocksMaxStep2,
367
+ creatableProvider as creatableProvider3
368
+ } from "@xyo-network/xl1-protocol-sdk";
369
+ var RestIndexViewer = class extends AbstractCreatableProvider3 {
370
+ moniker = RestIndexViewer.defaultMoniker;
371
+ summaryCache = new LruCacheMap2({ max: 8 });
372
+ get finalizedBaseUrl() {
373
+ return this.params.finalizedBaseUrl;
374
+ }
375
+ get fetchFn() {
376
+ return this.params.fetchFn ?? globalThis.fetch.bind(globalThis);
377
+ }
378
+ static async paramsHandler(params) {
379
+ return {
380
+ ...await super.paramsHandler(params),
381
+ fetchFn: params.fetchFn,
382
+ finalizedBaseUrl: assertEx3(params.finalizedBaseUrl, () => "finalizedBaseUrl is required").replace(/\/+$/, "")
383
+ };
384
+ }
385
+ /** The published summary for a completed step, or null when not (yet) published. */
386
+ async blocksStepSummary(stepLevel, stepIndex) {
387
+ return await this.spanAsync("blocksStepSummary", async () => {
388
+ assertEx3(Number.isInteger(stepIndex) && stepIndex >= 0, () => "stepIndex must be a non-negative integer");
389
+ stepSize2(stepLevel);
390
+ assertEx3(
391
+ stepLevel <= blocksMaxStep2,
392
+ () => `blocksStepSummary does not support step levels above ${blocksMaxStep2} (requested ${stepLevel})`
393
+ );
394
+ const cacheKey = `${stepLevel}|${stepIndex}`;
395
+ const cached = this.summaryCache.get(cacheKey);
396
+ if (cached) return cached;
397
+ const response = await this.fetchFn(`${this.finalizedBaseUrl}/${blocksStepPath(stepLevel, stepIndex)}`);
398
+ if (response.status === 404) return null;
399
+ assertEx3(response.ok, () => `Request failed [${response.status}] for step ${stepLevel}/${stepIndex}`);
400
+ const parsed = await response.json();
401
+ const summary = asBlocksStepSummary2(parsed, { required: true });
402
+ this.summaryCache.set(cacheKey, summary);
403
+ return summary;
404
+ }, this.context);
405
+ }
406
+ };
407
+ __publicField(RestIndexViewer, "defaultMoniker", IndexViewerMoniker);
408
+ __publicField(RestIndexViewer, "dependencies", []);
409
+ __publicField(RestIndexViewer, "monikers", [IndexViewerMoniker]);
410
+ RestIndexViewer = __decorateClass([
411
+ creatableProvider3()
412
+ ], RestIndexViewer);
250
413
  export {
251
414
  RestBlockViewer,
415
+ RestChainStateViewer,
416
+ RestIndexViewer,
252
417
  blockHashPath,
253
418
  blockNumberPath,
254
419
  blocksStepPath,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../src/paths.ts", "../../src/RestBlockViewer.ts"],
4
- "sourcesContent": ["import type { Hash } from '@xylabs/sdk-js'\n\n/**\n * Path contract for the static REST chain layout.\n *\n * These builders are the single source of truth for where files live, shared by the\n * publisher (which writes the static files) and `RestBlockViewer` (which reads them),\n * so the layout cannot drift between the two. Paths are relative \u2014 no leading slash \u2014\n * and joined to a base URL by the consumer.\n *\n * Every file except the head pointer is immutable once written:\n * - block and payload files never change after finalization\n * - step files are only written for completed steps\n * - the head pointer is rewritten as the chain advances and must not be cached long-term\n *\n * The finalized (immutable) files and the mutable chain state (the head pointer) may live\n * in separate buckets behind separate domains: the publisher writes only the finalized\n * files, the chain's finalizer writes the head pointer, and the viewer joins `headPath` to\n * its chain-state base URL and everything else to its finalized base URL.\n */\n\n/** The mutable head pointer: the current head SignedHydratedBlockWithHashMeta. */\nexport const headPath = (): string => 'chain/head.json'\n\n/** A block by number: SignedHydratedBlockWithHashMeta. */\nexport const blockNumberPath = (block: number): string => `block/number/${block}.json`\n\n/** A block by hash: the same content as its by-number twin. */\nexport const blockHashPath = (hash: Hash): string => `block/hash/${hash}.json`\n\n/**\n * A completed step's blocks: a BlocksStepSummary payload whose `blocks` array is ordered\n * oldest-first. Only complete steps are published; the in-flight tail step has no file.\n */\nexport const blocksStepPath = (stepLevel: number, stepIndex: number): string => `blocks/step/${stepLevel}/${stepIndex}.json`\n\n/** A payload by hash: WithHashMeta<Payload>. */\nexport const payloadPath = (hash: Hash): string => `payload/${hash}.json`\n", "import type { Hash } from '@xylabs/sdk-js'\nimport { assertEx, exists } from '@xylabs/sdk-js'\nimport type { Payload, WithHashMeta } from '@xyo-network/sdk-js'\nimport { PayloadZodLoose, WithHashMetaZod } from '@xyo-network/sdk-js'\nimport { LruCacheMap } from '@xyo-network/xl1-driver-memory'\nimport type {\n BlockRate, BlockViewer, ChainId,\n SignedHydratedBlockWithHashMeta, SingleTimeConfig, TimeDurations, XL1BlockNumber, XL1BlockRange,\n} from '@xyo-network/xl1-protocol-lib'\nimport {\n asSignedHydratedBlockWithHashMeta, asXL1BlockNumber, BlockViewerMoniker, stepSize,\n} from '@xyo-network/xl1-protocol-lib'\nimport type { CreatableProviderParams } from '@xyo-network/xl1-protocol-sdk'\nimport {\n AbstractCreatableProvider, asBlocksStepSummary, blocksMaxStep, calculateBlockRate, calculateStepSizeRate, calculateTimeRate, creatableProvider,\n} from '@xyo-network/xl1-protocol-sdk'\n\nimport {\n blockHashPath, blockNumberPath, blocksStepPath, headPath, payloadPath,\n} from './paths.ts'\n\n/** Parameters for RestBlockViewer. */\nexport interface RestBlockViewerParams extends CreatableProviderParams {\n /**\n * Base URL serving the mutable chain state (the head pointer, `chain/head.json`) when it\n * lives in a separate bucket/domain from the finalized files. Defaults to `finalizedBaseUrl`.\n */\n chainStateBaseUrl?: string\n /** Optional fetch override (custom agents, auth headers, tests). Defaults to the global fetch. */\n fetchFn?: typeof globalThis.fetch\n /** Base URL of the finalized (immutable) static chain files (e.g. a public R2 bucket or CDN domain). */\n finalizedBaseUrl: string\n headPollIntervalMs?: number\n}\n\nconst MIN_HEAD_POLL_INTERVAL_MS = 5000\n\nconst PayloadFileZod = WithHashMetaZod(PayloadZodLoose)\n\n/**\n * A BlockViewer over a statically generated REST file layout (see `paths.ts`).\n *\n * Reads are anonymous HTTP GETs against immutable files, so everything except the head\n * pointer is cached aggressively. The head pointer is read from `chainStateBaseUrl` when\n * the chain state and finalized files live in separate buckets/domains. `blocksByStep`\n * serves only completed steps \u2014 the in-flight tail step has no static file and returns [].\n */\n@creatableProvider()\nexport class RestBlockViewer extends AbstractCreatableProvider<RestBlockViewerParams, BlockViewer['eventData']> implements BlockViewer {\n static readonly defaultMoniker = BlockViewerMoniker\n static readonly dependencies = []\n static readonly monikers = [BlockViewerMoniker]\n moniker = RestBlockViewer.defaultMoniker\n\n protected blockByHashCache = new LruCacheMap<Hash, SignedHydratedBlockWithHashMeta>({ max: 2000 })\n protected blockByNumberCache = new LruCacheMap<XL1BlockNumber, SignedHydratedBlockWithHashMeta>({ max: 2000 })\n protected payloadCache = new LruCacheMap<Hash, WithHashMeta<Payload>>({ max: 10_000 })\n protected stepCache = new LruCacheMap<string, SignedHydratedBlockWithHashMeta[]>({ max: 4 })\n\n private _headPollHash?: Hash\n private _headPollInProgress = false\n private _headPollTimer: ReturnType<typeof setInterval> | null = null\n\n get chainStateBaseUrl(): string {\n return this.params.chainStateBaseUrl ?? this.params.finalizedBaseUrl\n }\n\n get finalizedBaseUrl(): string {\n return this.params.finalizedBaseUrl\n }\n\n protected get fetchFn(): typeof globalThis.fetch {\n return this.params.fetchFn ?? globalThis.fetch.bind(globalThis)\n }\n\n protected get headPollIntervalMs() {\n return this.params.headPollIntervalMs\n }\n\n static override async paramsHandler(params: Partial<RestBlockViewerParams>) {\n const headPollIntervalMs = params.headPollIntervalMs\n if (headPollIntervalMs !== undefined) {\n assertEx(headPollIntervalMs >= MIN_HEAD_POLL_INTERVAL_MS, () => `headPollIntervalMs must be at least ${MIN_HEAD_POLL_INTERVAL_MS}ms`)\n }\n return {\n ...await super.paramsHandler(params),\n chainStateBaseUrl: params.chainStateBaseUrl?.replace(/\\/+$/, ''),\n fetchFn: params.fetchFn,\n finalizedBaseUrl: assertEx(params.finalizedBaseUrl, () => 'finalizedBaseUrl is required').replace(/\\/+$/, ''),\n headPollIntervalMs,\n } satisfies RestBlockViewerParams\n }\n\n async blockByHash(hash: Hash): Promise<SignedHydratedBlockWithHashMeta | null> {\n return await this.spanAsync('blockByHash', async () => {\n const cached = this.blockByHashCache.get(hash)\n if (cached) return cached\n const parsed = await this.fetchJson(blockHashPath(hash))\n return parsed === undefined ? null : this.cacheBlock(parsed)\n }, { ...this.context, timeBudgetLimit: 100 })\n }\n\n async blockByNumber(blockNumber: XL1BlockNumber): Promise<SignedHydratedBlockWithHashMeta | null> {\n return await this.spanAsync('blockByNumber', async () => {\n const cached = this.blockByNumberCache.get(blockNumber)\n if (cached) return cached\n const parsed = await this.fetchJson(blockNumberPath(blockNumber))\n return parsed === undefined ? null : this.cacheBlock(parsed)\n }, { ...this.context, timeBudgetLimit: 100 })\n }\n\n async blocksByHash(hash: Hash, limit = 50): Promise<SignedHydratedBlockWithHashMeta[]> {\n return await this.spanAsync('blocksByHash', async () => {\n assertEx(limit > 0, () => 'limit must be greater than 0')\n assertEx(limit <= 100, () => 'limit must be less than 100')\n const blocks: SignedHydratedBlockWithHashMeta[] = []\n let current = await this.blockByHash(hash)\n while (current && blocks.length < limit) {\n blocks.push(current)\n const previousHash = current[0].previous\n if (previousHash === null) break\n current = await this.blockByHash(previousHash)\n }\n return blocks\n }, { ...this.context, timeBudgetLimit: 300 })\n }\n\n async blocksByNumber(blockNumber: XL1BlockNumber, limit = 50): Promise<SignedHydratedBlockWithHashMeta[]> {\n return await this.spanAsync('blocksByNumber', async () => {\n assertEx(limit > 0, () => 'limit must be greater than 0')\n assertEx(limit <= 100, () => 'limit must be less than 100')\n const blocks: SignedHydratedBlockWithHashMeta[] = []\n let current = await this.blockByNumber(blockNumber)\n while (current && blocks.length < limit) {\n blocks.push(current)\n if (current[0].block === 0) break\n current = await this.blockByNumber(asXL1BlockNumber(current[0].block - 1, true))\n }\n return blocks\n }, this.context)\n }\n\n async blocksByStep(stepLevel: number, stepIndex: number): Promise<SignedHydratedBlockWithHashMeta[]> {\n return await this.spanAsync('blocksByStep', async () => {\n assertEx(Number.isInteger(stepIndex) && stepIndex >= 0, () => 'stepIndex must be a non-negative integer')\n stepSize(stepLevel) // validates the level against StepSizes\n assertEx(\n stepLevel <= blocksMaxStep,\n () => `blocksByStep does not support step levels above ${blocksMaxStep} (requested ${stepLevel})`,\n )\n const cacheKey = `${stepLevel}|${stepIndex}`\n const cached = this.stepCache.get(cacheKey)\n if (cached) return cached\n const parsed = await this.fetchJson(blocksStepPath(stepLevel, stepIndex))\n // Only completed steps are published; the in-flight tail step has no file\n if (parsed === undefined) return []\n const summary = asBlocksStepSummary(parsed, { required: true })\n // Step files store blocks oldest-first; the viewer interface returns newest-first\n const blocks = summary.blocks.map(b => asSignedHydratedBlockWithHashMeta(b, true)).toReversed()\n this.stepCache.set(cacheKey, blocks)\n return blocks\n }, this.context)\n }\n\n chainId(): Promise<ChainId>\n chainId(blockNumber: XL1BlockNumber): Promise<ChainId>\n chainId(blockNumber: 'latest'): Promise<ChainId>\n async chainId(blockNumber: XL1BlockNumber | 'latest' = 'latest'): Promise<ChainId> {\n return await this.spanAsync('chainId', async () => {\n return blockNumber === 'latest'\n ? (await this.currentBlock())[0].chain\n : assertEx(await this.blockByNumber(blockNumber), () => `Block not found [${blockNumber}]`)[0].chain\n }, this.context)\n }\n\n async currentBlock(): Promise<SignedHydratedBlockWithHashMeta> {\n return await this.spanAsync('currentBlock', async () => {\n const parsed = assertEx(await this.fetchJson(headPath(), this.chainStateBaseUrl), () => 'Head not found')\n return this.cacheBlock(parsed)\n }, this.context)\n }\n\n async currentBlockHash(): Promise<Hash> {\n return (await this.currentBlock())[0]._hash\n }\n\n async currentBlockNumber(): Promise<XL1BlockNumber> {\n return (await this.currentBlock())[0].block\n }\n\n async payloadByHash(hash: Hash): Promise<WithHashMeta<Payload> | null> {\n const [payload] = await this.payloadsByHash([hash])\n return payload ?? null\n }\n\n async payloadsByHash(hashes: Hash[]): Promise<WithHashMeta<Payload>[]> {\n return await this.spanAsync('payloadsByHash', async () => {\n const results = await Promise.all(hashes.map(async (hash) => {\n const cached = this.payloadCache.get(hash)\n if (cached) return cached\n const parsed = await this.fetchJson(payloadPath(hash))\n if (parsed === undefined) return\n const payload = PayloadFileZod.parse(parsed)\n this.payloadCache.set(hash, payload)\n return payload\n }))\n return results.filter(exists)\n }, this.context)\n }\n\n async rate(range: XL1BlockRange, timeUnit?: keyof TimeDurations): Promise<BlockRate> {\n return await calculateBlockRate(this, range, timeUnit)\n }\n\n async stepSizeRate(start: XL1BlockNumber, stepIndex: number, count = 1, timeUnit?: keyof TimeDurations): Promise<BlockRate> {\n return await calculateStepSizeRate(this, start, stepIndex, count, timeUnit)\n }\n\n async timeDurationRate(\n timeConfig: SingleTimeConfig,\n startBlockNumber?: XL1BlockNumber,\n timeUnit?: keyof TimeDurations,\n toleranceMs?: number,\n maxAttempts?: number,\n ): Promise<BlockRate> {\n return await calculateTimeRate(this, timeConfig, startBlockNumber, timeUnit, toleranceMs, maxAttempts)\n }\n\n protected override async startHandler(): Promise<void> {\n await super.startHandler()\n if (this.headPollIntervalMs === undefined) return\n await this.pollHead(false)\n this.startHeadPolling()\n }\n\n protected override async stopHandler(): Promise<void> {\n this.stopHeadPolling()\n this._headPollHash = undefined\n await super.stopHandler()\n }\n\n /** Validates a parsed block file and populates both block caches. */\n private cacheBlock(parsed: unknown): SignedHydratedBlockWithHashMeta {\n const block = asSignedHydratedBlockWithHashMeta(parsed, true)\n this.blockByHashCache.set(block[0]._hash, block)\n this.blockByNumberCache.set(block[0].block, block)\n return block\n }\n\n private async fetchJson(path: string, baseUrl = this.finalizedBaseUrl): Promise<unknown> {\n const response = await this.fetchFn(`${baseUrl}/${path}`)\n if (response.status === 404) return undefined\n assertEx(response.ok, () => `Request failed [${response.status}] for ${path}`)\n return await response.json()\n }\n\n private async pollHead(emitOnChange: boolean): Promise<void> {\n if (this._headPollInProgress) return\n this._headPollInProgress = true\n try {\n const block = await this.currentBlock()\n const hash = block[0]._hash\n if (this._headPollHash === undefined) {\n this._headPollHash = hash\n return\n }\n if (hash !== this._headPollHash) {\n this._headPollHash = hash\n if (emitOnChange) {\n await this.emit('headUpdated', { block })\n }\n }\n } catch (ex) {\n this.logger?.error('Error polling block head', ex)\n } finally {\n this._headPollInProgress = false\n }\n }\n\n private startHeadPolling() {\n if (this.headPollIntervalMs === undefined) return\n this.stopHeadPolling()\n this._headPollTimer = setInterval(() => {\n void this.pollHead(true)\n }, this.headPollIntervalMs)\n }\n\n private stopHeadPolling() {\n if (this._headPollTimer) {\n clearInterval(this._headPollTimer)\n this._headPollTimer = null\n }\n }\n}\n"],
5
- "mappings": "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",
6
- "names": []
3
+ "sources": ["../../src/paths.ts", "../../src/RestBlockViewer.ts", "../../src/RestChainStateViewer.ts", "../../src/RestIndexViewer.ts"],
4
+ "sourcesContent": ["import type { Hash } from '@xylabs/sdk-js'\n\n/**\n * Path contract for the static REST chain layout.\n *\n * These builders are the single source of truth for where files live, shared by the\n * publisher (which writes the static files) and `RestBlockViewer` (which reads them),\n * so the layout cannot drift between the two. Paths are relative \u2014 no leading slash \u2014\n * and joined to a base URL by the consumer.\n *\n * Every file except the head pointer is immutable once written:\n * - block and payload files never change after finalization\n * - step files are only written for completed steps\n * - the head pointer is rewritten as the chain advances and must not be cached long-term\n *\n * The finalized (immutable) files and the mutable chain state (the head pointer) may live\n * in separate buckets behind separate domains: the publisher writes only the finalized\n * files, the chain's finalizer writes the head pointer, and the viewer joins `headPath` to\n * its chain-state base URL and everything else to its finalized base URL.\n */\n\n/** The mutable head pointer: the current head SignedHydratedBlockWithHashMeta. */\nexport const headPath = (): string => 'chain/head.json'\n\n/** A block by number: SignedHydratedBlockWithHashMeta. */\nexport const blockNumberPath = (block: number): string => `block/number/${block}.json`\n\n/** A block by hash: the same content as its by-number twin. */\nexport const blockHashPath = (hash: Hash): string => `block/hash/${hash}.json`\n\n/**\n * A completed step's blocks: a BlocksStepSummary payload whose `blocks` array is ordered\n * oldest-first. Only complete steps are published; the in-flight tail step has no file.\n */\nexport const blocksStepPath = (stepLevel: number, stepIndex: number): string => `blocks/step/${stepLevel}/${stepIndex}.json`\n\n/** A payload by hash: WithHashMeta<Payload>. */\nexport const payloadPath = (hash: Hash): string => `payload/${hash}.json`\n", "import type { Hash } from '@xylabs/sdk-js'\nimport { assertEx, exists } from '@xylabs/sdk-js'\nimport type { Payload, WithHashMeta } from '@xyo-network/sdk-js'\nimport { PayloadZodLoose, WithHashMetaZod } from '@xyo-network/sdk-js'\nimport { LruCacheMap } from '@xyo-network/xl1-driver-memory'\nimport type {\n BlockRate, BlockViewer, ChainId,\n SignedHydratedBlockWithHashMeta, SingleTimeConfig, TimeDurations, XL1BlockNumber, XL1BlockRange,\n} from '@xyo-network/xl1-protocol-lib'\nimport {\n asBlocksStepSummary, asSignedHydratedBlockWithHashMeta, asXL1BlockNumber, BlockViewerMoniker, stepSize,\n} from '@xyo-network/xl1-protocol-lib'\nimport type { CreatableProviderParams } from '@xyo-network/xl1-protocol-sdk'\nimport {\n AbstractCreatableProvider, blocksMaxStep, calculateBlockRate, calculateStepSizeRate, calculateTimeRate, creatableProvider,\n} from '@xyo-network/xl1-protocol-sdk'\n\nimport {\n blockHashPath, blockNumberPath, blocksStepPath, headPath, payloadPath,\n} from './paths.ts'\n\n/** Parameters for RestBlockViewer. */\nexport interface RestBlockViewerParams extends CreatableProviderParams {\n /**\n * Base URL serving the mutable chain state (the head pointer, `chain/head.json`) when it\n * lives in a separate bucket/domain from the finalized files. Defaults to `finalizedBaseUrl`.\n */\n chainStateBaseUrl?: string\n /** Optional fetch override (custom agents, auth headers, tests). Defaults to the global fetch. */\n fetchFn?: typeof globalThis.fetch\n /** Base URL of the finalized (immutable) static chain files (e.g. a public R2 bucket or CDN domain). */\n finalizedBaseUrl: string\n headPollIntervalMs?: number\n}\n\nconst MIN_HEAD_POLL_INTERVAL_MS = 5000\n\nconst PayloadFileZod = WithHashMetaZod(PayloadZodLoose)\n\n/**\n * A BlockViewer over a statically generated REST file layout (see `paths.ts`).\n *\n * Reads are anonymous HTTP GETs against immutable files, so everything except the head\n * pointer is cached aggressively. The head pointer is read from `chainStateBaseUrl` when\n * the chain state and finalized files live in separate buckets/domains. `blocksByStep`\n * serves only completed steps \u2014 the in-flight tail step has no static file and returns [].\n */\n@creatableProvider()\nexport class RestBlockViewer extends AbstractCreatableProvider<RestBlockViewerParams, BlockViewer['eventData']> implements BlockViewer {\n static readonly defaultMoniker = BlockViewerMoniker\n static readonly dependencies = []\n static readonly monikers = [BlockViewerMoniker]\n moniker = RestBlockViewer.defaultMoniker\n\n protected blockByHashCache = new LruCacheMap<Hash, SignedHydratedBlockWithHashMeta>({ max: 2000 })\n protected blockByNumberCache = new LruCacheMap<XL1BlockNumber, SignedHydratedBlockWithHashMeta>({ max: 2000 })\n protected payloadCache = new LruCacheMap<Hash, WithHashMeta<Payload>>({ max: 10_000 })\n protected stepCache = new LruCacheMap<string, SignedHydratedBlockWithHashMeta[]>({ max: 4 })\n\n private _headPollHash?: Hash\n private _headPollInProgress = false\n private _headPollTimer: ReturnType<typeof setInterval> | null = null\n\n get chainStateBaseUrl(): string {\n return this.params.chainStateBaseUrl ?? this.params.finalizedBaseUrl\n }\n\n get finalizedBaseUrl(): string {\n return this.params.finalizedBaseUrl\n }\n\n protected get fetchFn(): typeof globalThis.fetch {\n return this.params.fetchFn ?? globalThis.fetch.bind(globalThis)\n }\n\n protected get headPollIntervalMs() {\n return this.params.headPollIntervalMs\n }\n\n static override async paramsHandler(params: Partial<RestBlockViewerParams>) {\n const headPollIntervalMs = params.headPollIntervalMs\n if (headPollIntervalMs !== undefined) {\n assertEx(headPollIntervalMs >= MIN_HEAD_POLL_INTERVAL_MS, () => `headPollIntervalMs must be at least ${MIN_HEAD_POLL_INTERVAL_MS}ms`)\n }\n return {\n ...await super.paramsHandler(params),\n chainStateBaseUrl: params.chainStateBaseUrl?.replace(/\\/+$/, ''),\n fetchFn: params.fetchFn,\n finalizedBaseUrl: assertEx(params.finalizedBaseUrl, () => 'finalizedBaseUrl is required').replace(/\\/+$/, ''),\n headPollIntervalMs,\n } satisfies RestBlockViewerParams\n }\n\n async blockByHash(hash: Hash): Promise<SignedHydratedBlockWithHashMeta | null> {\n return await this.spanAsync('blockByHash', async () => {\n const cached = this.blockByHashCache.get(hash)\n if (cached) return cached\n const parsed = await this.fetchJson(blockHashPath(hash))\n return parsed === undefined ? null : this.cacheBlock(parsed)\n }, { ...this.context, timeBudgetLimit: 100 })\n }\n\n async blockByNumber(blockNumber: XL1BlockNumber): Promise<SignedHydratedBlockWithHashMeta | null> {\n return await this.spanAsync('blockByNumber', async () => {\n const cached = this.blockByNumberCache.get(blockNumber)\n if (cached) return cached\n const parsed = await this.fetchJson(blockNumberPath(blockNumber))\n return parsed === undefined ? null : this.cacheBlock(parsed)\n }, { ...this.context, timeBudgetLimit: 100 })\n }\n\n async blocksByHash(hash: Hash, limit = 50): Promise<SignedHydratedBlockWithHashMeta[]> {\n return await this.spanAsync('blocksByHash', async () => {\n assertEx(limit > 0, () => 'limit must be greater than 0')\n assertEx(limit <= 100, () => 'limit must be less than 100')\n const blocks: SignedHydratedBlockWithHashMeta[] = []\n let current = await this.blockByHash(hash)\n while (current && blocks.length < limit) {\n blocks.push(current)\n const previousHash = current[0].previous\n if (previousHash === null) break\n current = await this.blockByHash(previousHash)\n }\n return blocks\n }, { ...this.context, timeBudgetLimit: 300 })\n }\n\n async blocksByNumber(blockNumber: XL1BlockNumber, limit = 50): Promise<SignedHydratedBlockWithHashMeta[]> {\n return await this.spanAsync('blocksByNumber', async () => {\n assertEx(limit > 0, () => 'limit must be greater than 0')\n assertEx(limit <= 100, () => 'limit must be less than 100')\n const blocks: SignedHydratedBlockWithHashMeta[] = []\n let current = await this.blockByNumber(blockNumber)\n while (current && blocks.length < limit) {\n blocks.push(current)\n if (current[0].block === 0) break\n current = await this.blockByNumber(asXL1BlockNumber(current[0].block - 1, true))\n }\n return blocks\n }, this.context)\n }\n\n async blocksByStep(stepLevel: number, stepIndex: number): Promise<SignedHydratedBlockWithHashMeta[]> {\n return await this.spanAsync('blocksByStep', async () => {\n assertEx(Number.isInteger(stepIndex) && stepIndex >= 0, () => 'stepIndex must be a non-negative integer')\n stepSize(stepLevel) // validates the level against StepSizes\n assertEx(\n stepLevel <= blocksMaxStep,\n () => `blocksByStep does not support step levels above ${blocksMaxStep} (requested ${stepLevel})`,\n )\n const cacheKey = `${stepLevel}|${stepIndex}`\n const cached = this.stepCache.get(cacheKey)\n if (cached) return cached\n const parsed = await this.fetchJson(blocksStepPath(stepLevel, stepIndex))\n // Only completed steps are published; the in-flight tail step has no file\n if (parsed === undefined) return []\n const summary = asBlocksStepSummary(parsed, { required: true })\n // Step files store blocks oldest-first; the viewer interface returns newest-first\n const blocks = summary.blocks.map(b => asSignedHydratedBlockWithHashMeta(b, true)).toReversed()\n this.stepCache.set(cacheKey, blocks)\n return blocks\n }, this.context)\n }\n\n chainId(): Promise<ChainId>\n chainId(blockNumber: XL1BlockNumber): Promise<ChainId>\n chainId(blockNumber: 'latest'): Promise<ChainId>\n async chainId(blockNumber: XL1BlockNumber | 'latest' = 'latest'): Promise<ChainId> {\n return await this.spanAsync('chainId', async () => {\n return blockNumber === 'latest'\n ? (await this.currentBlock())[0].chain\n : assertEx(await this.blockByNumber(blockNumber), () => `Block not found [${blockNumber}]`)[0].chain\n }, this.context)\n }\n\n async currentBlock(): Promise<SignedHydratedBlockWithHashMeta> {\n return await this.spanAsync('currentBlock', async () => {\n const parsed = assertEx(await this.fetchJson(headPath(), this.chainStateBaseUrl), () => 'Head not found')\n return this.cacheBlock(parsed)\n }, this.context)\n }\n\n async currentBlockHash(): Promise<Hash> {\n return (await this.currentBlock())[0]._hash\n }\n\n async currentBlockNumber(): Promise<XL1BlockNumber> {\n return (await this.currentBlock())[0].block\n }\n\n async payloadByHash(hash: Hash): Promise<WithHashMeta<Payload> | null> {\n const [payload] = await this.payloadsByHash([hash])\n return payload ?? null\n }\n\n async payloadsByHash(hashes: Hash[]): Promise<WithHashMeta<Payload>[]> {\n return await this.spanAsync('payloadsByHash', async () => {\n const results = await Promise.all(hashes.map(async (hash) => {\n const cached = this.payloadCache.get(hash)\n if (cached) return cached\n const parsed = await this.fetchJson(payloadPath(hash))\n if (parsed === undefined) return\n const payload = PayloadFileZod.parse(parsed)\n this.payloadCache.set(hash, payload)\n return payload\n }))\n return results.filter(exists)\n }, this.context)\n }\n\n async rate(range: XL1BlockRange, timeUnit?: keyof TimeDurations): Promise<BlockRate> {\n return await calculateBlockRate(this, range, timeUnit)\n }\n\n async stepSizeRate(start: XL1BlockNumber, stepIndex: number, count = 1, timeUnit?: keyof TimeDurations): Promise<BlockRate> {\n return await calculateStepSizeRate(this, start, stepIndex, count, timeUnit)\n }\n\n async timeDurationRate(\n timeConfig: SingleTimeConfig,\n startBlockNumber?: XL1BlockNumber,\n timeUnit?: keyof TimeDurations,\n toleranceMs?: number,\n maxAttempts?: number,\n ): Promise<BlockRate> {\n return await calculateTimeRate(this, timeConfig, startBlockNumber, timeUnit, toleranceMs, maxAttempts)\n }\n\n protected override async startHandler(): Promise<void> {\n await super.startHandler()\n if (this.headPollIntervalMs === undefined) return\n await this.pollHead(false)\n this.startHeadPolling()\n }\n\n protected override async stopHandler(): Promise<void> {\n this.stopHeadPolling()\n this._headPollHash = undefined\n await super.stopHandler()\n }\n\n /** Validates a parsed block file and populates both block caches. */\n private cacheBlock(parsed: unknown): SignedHydratedBlockWithHashMeta {\n const block = asSignedHydratedBlockWithHashMeta(parsed, true)\n this.blockByHashCache.set(block[0]._hash, block)\n this.blockByNumberCache.set(block[0].block, block)\n return block\n }\n\n private async fetchJson(path: string, baseUrl = this.finalizedBaseUrl): Promise<unknown> {\n const response = await this.fetchFn(`${baseUrl}/${path}`)\n if (response.status === 404) return undefined\n assertEx(response.ok, () => `Request failed [${response.status}] for ${path}`)\n return await response.json()\n }\n\n private async pollHead(emitOnChange: boolean): Promise<void> {\n if (this._headPollInProgress) return\n this._headPollInProgress = true\n try {\n const block = await this.currentBlock()\n const hash = block[0]._hash\n if (this._headPollHash === undefined) {\n this._headPollHash = hash\n return\n }\n if (hash !== this._headPollHash) {\n this._headPollHash = hash\n if (emitOnChange) {\n await this.emit('headUpdated', { block })\n }\n }\n } catch (ex) {\n this.logger?.error('Error polling block head', ex)\n } finally {\n this._headPollInProgress = false\n }\n }\n\n private startHeadPolling() {\n if (this.headPollIntervalMs === undefined) return\n this.stopHeadPolling()\n this._headPollTimer = setInterval(() => {\n void this.pollHead(true)\n }, this.headPollIntervalMs)\n }\n\n private stopHeadPolling() {\n if (this._headPollTimer) {\n clearInterval(this._headPollTimer)\n this._headPollTimer = null\n }\n }\n}\n", "import type { Hash } from '@xylabs/sdk-js'\nimport { assertEx } from '@xylabs/sdk-js'\nimport type {\n ChainStateViewer, SignedHydratedBlockWithHashMeta, XL1BlockNumber,\n} from '@xyo-network/xl1-protocol-lib'\nimport { asSignedHydratedBlockWithHashMeta, ChainStateViewerMoniker } from '@xyo-network/xl1-protocol-lib'\nimport type { CreatableProviderParams } from '@xyo-network/xl1-protocol-sdk'\nimport { AbstractCreatableProvider, creatableProvider } from '@xyo-network/xl1-protocol-sdk'\n\nimport { headPath } from './paths.ts'\n\n/** Parameters for RestChainStateViewer. */\nexport interface RestChainStateViewerParams extends CreatableProviderParams {\n /** Base URL serving the mutable chain state (the head pointer, `chain/head.json`). */\n chainStateBaseUrl: string\n /** Optional fetch override (custom agents, auth headers, tests). Defaults to the global fetch. */\n fetchFn?: typeof globalThis.fetch\n headPollIntervalMs?: number\n}\n\nconst MIN_HEAD_POLL_INTERVAL_MS = 5000\n\n/**\n * A ChainStateViewer over the statically generated REST file layout (see `paths.ts`):\n * anonymous HTTP reads of the one mutable file, the head pointer. When configured with\n * `headPollIntervalMs`, polls the head and emits `headUpdated` as the chain advances.\n */\n@creatableProvider()\nexport class RestChainStateViewer extends AbstractCreatableProvider<RestChainStateViewerParams, ChainStateViewer['eventData']>\n implements ChainStateViewer {\n static readonly defaultMoniker = ChainStateViewerMoniker\n static readonly dependencies = []\n static readonly monikers = [ChainStateViewerMoniker]\n moniker = RestChainStateViewer.defaultMoniker\n\n private _headPollHash?: Hash\n private _headPollInProgress = false\n private _headPollTimer: ReturnType<typeof setInterval> | null = null\n\n get chainStateBaseUrl(): string {\n return this.params.chainStateBaseUrl\n }\n\n protected get fetchFn(): typeof globalThis.fetch {\n return this.params.fetchFn ?? globalThis.fetch.bind(globalThis)\n }\n\n protected get headPollIntervalMs() {\n return this.params.headPollIntervalMs\n }\n\n static override async paramsHandler(params: Partial<RestChainStateViewerParams>) {\n const headPollIntervalMs = params.headPollIntervalMs\n if (headPollIntervalMs !== undefined) {\n assertEx(headPollIntervalMs >= MIN_HEAD_POLL_INTERVAL_MS, () => `headPollIntervalMs must be at least ${MIN_HEAD_POLL_INTERVAL_MS}ms`)\n }\n return {\n ...await super.paramsHandler(params),\n chainStateBaseUrl: assertEx(params.chainStateBaseUrl, () => 'chainStateBaseUrl is required').replace(/\\/+$/, ''),\n fetchFn: params.fetchFn,\n headPollIntervalMs,\n } satisfies RestChainStateViewerParams\n }\n\n async currentBlock(): Promise<SignedHydratedBlockWithHashMeta> {\n return await this.spanAsync('currentBlock', async () => {\n const response = await this.fetchFn(`${this.chainStateBaseUrl}/${headPath()}`)\n assertEx(response.ok, () => `Head not found [${response.status}]`)\n return asSignedHydratedBlockWithHashMeta(await response.json(), true)\n }, this.context)\n }\n\n async currentBlockHash(): Promise<Hash> {\n return (await this.currentBlock())[0]._hash\n }\n\n async currentBlockNumber(): Promise<XL1BlockNumber> {\n return (await this.currentBlock())[0].block\n }\n\n /** The published head, or undefined when no head pointer has been published yet. */\n async tryCurrentBlock(): Promise<SignedHydratedBlockWithHashMeta | undefined> {\n const response = await this.fetchFn(`${this.chainStateBaseUrl}/${headPath()}`)\n if (response.status === 404) return undefined\n assertEx(response.ok, () => `Head request failed [${response.status}]`)\n return asSignedHydratedBlockWithHashMeta(await response.json(), true)\n }\n\n protected override async startHandler(): Promise<void> {\n await super.startHandler()\n if (this.headPollIntervalMs === undefined) return\n await this.pollHead(false)\n this.startHeadPolling()\n }\n\n protected override async stopHandler(): Promise<void> {\n this.stopHeadPolling()\n this._headPollHash = undefined\n await super.stopHandler()\n }\n\n private async pollHead(emitOnChange: boolean): Promise<void> {\n if (this._headPollInProgress) return\n this._headPollInProgress = true\n try {\n const block = await this.currentBlock()\n const hash = block[0]._hash\n if (this._headPollHash === undefined) {\n this._headPollHash = hash\n return\n }\n if (hash !== this._headPollHash) {\n this._headPollHash = hash\n if (emitOnChange) {\n await this.emit('headUpdated', { block })\n }\n }\n } catch (ex) {\n this.logger?.error('Error polling block head', ex)\n } finally {\n this._headPollInProgress = false\n }\n }\n\n private startHeadPolling() {\n if (this.headPollIntervalMs === undefined) return\n this.stopHeadPolling()\n this._headPollTimer = setInterval(() => {\n void this.pollHead(true)\n }, this.headPollIntervalMs)\n }\n\n private stopHeadPolling() {\n if (this._headPollTimer) {\n clearInterval(this._headPollTimer)\n this._headPollTimer = null\n }\n }\n}\n", "import { assertEx } from '@xylabs/sdk-js'\nimport { LruCacheMap } from '@xyo-network/xl1-driver-memory'\nimport type { BlocksStepSummary, IndexViewer } from '@xyo-network/xl1-protocol-lib'\nimport {\n asBlocksStepSummary, IndexViewerMoniker, stepSize,\n} from '@xyo-network/xl1-protocol-lib'\nimport type { CreatableProviderParams } from '@xyo-network/xl1-protocol-sdk'\nimport {\n AbstractCreatableProvider, blocksMaxStep, creatableProvider,\n} from '@xyo-network/xl1-protocol-sdk'\n\nimport { blocksStepPath } from './paths.ts'\n\n/** Parameters for RestIndexViewer. */\nexport interface RestIndexViewerParams extends CreatableProviderParams {\n /** Optional fetch override (custom agents, auth headers, tests). Defaults to the global fetch. */\n fetchFn?: typeof globalThis.fetch\n /** Base URL of the finalized (immutable) static chain files (e.g. a public R2 bucket or CDN domain). */\n finalizedBaseUrl: string\n}\n\n/**\n * An IndexViewer over the statically generated REST file layout (see `paths.ts`): anonymous\n * HTTP reads of published step summary files. Only completed steps are published \u2014 the\n * in-flight tail step has no file and reads as null. Files are immutable, so responses are\n * cached aggressively (in-memory LRU here, CDN/edge in front).\n */\n@creatableProvider()\nexport class RestIndexViewer extends AbstractCreatableProvider<RestIndexViewerParams> implements IndexViewer {\n static readonly defaultMoniker = IndexViewerMoniker\n static readonly dependencies = []\n static readonly monikers = [IndexViewerMoniker]\n moniker = RestIndexViewer.defaultMoniker\n\n protected summaryCache = new LruCacheMap<string, BlocksStepSummary>({ max: 8 })\n\n get finalizedBaseUrl(): string {\n return this.params.finalizedBaseUrl\n }\n\n protected get fetchFn(): typeof globalThis.fetch {\n return this.params.fetchFn ?? globalThis.fetch.bind(globalThis)\n }\n\n static override async paramsHandler(params: Partial<RestIndexViewerParams>) {\n return {\n ...await super.paramsHandler(params),\n fetchFn: params.fetchFn,\n finalizedBaseUrl: assertEx(params.finalizedBaseUrl, () => 'finalizedBaseUrl is required').replace(/\\/+$/, ''),\n } satisfies RestIndexViewerParams\n }\n\n /** The published summary for a completed step, or null when not (yet) published. */\n async blocksStepSummary(stepLevel: number, stepIndex: number): Promise<BlocksStepSummary | null> {\n return await this.spanAsync('blocksStepSummary', async () => {\n assertEx(Number.isInteger(stepIndex) && stepIndex >= 0, () => 'stepIndex must be a non-negative integer')\n stepSize(stepLevel) // validates the level against StepSizes\n assertEx(\n stepLevel <= blocksMaxStep,\n () => `blocksStepSummary does not support step levels above ${blocksMaxStep} (requested ${stepLevel})`,\n )\n const cacheKey = `${stepLevel}|${stepIndex}`\n const cached = this.summaryCache.get(cacheKey)\n if (cached) return cached\n const response = await this.fetchFn(`${this.finalizedBaseUrl}/${blocksStepPath(stepLevel, stepIndex)}`)\n // Only completed steps are published; the in-flight tail step has no file\n if (response.status === 404) return null\n assertEx(response.ok, () => `Request failed [${response.status}] for step ${stepLevel}/${stepIndex}`)\n const parsed: unknown = await response.json()\n const summary = asBlocksStepSummary(parsed as object, { required: true })\n this.summaryCache.set(cacheKey, summary)\n return summary\n }, this.context)\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["assertEx", "asSignedHydratedBlockWithHashMeta", "AbstractCreatableProvider", "creatableProvider", "MIN_HEAD_POLL_INTERVAL_MS", "AbstractCreatableProvider", "assertEx", "asSignedHydratedBlockWithHashMeta", "creatableProvider", "assertEx", "LruCacheMap", "asBlocksStepSummary", "stepSize", "AbstractCreatableProvider", "blocksMaxStep", "creatableProvider", "AbstractCreatableProvider", "LruCacheMap", "assertEx", "stepSize", "blocksMaxStep", "asBlocksStepSummary", "creatableProvider"]
7
7
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "http://json.schemastore.org/package.json",
3
3
  "name": "@xyo-network/xl1-rest-block-viewer",
4
- "version": "2.1.2",
4
+ "version": "2.1.4",
5
5
  "description": "XYO Layer One BlockViewer over a statically generated REST file layout",
6
6
  "homepage": "https://xylabs.com",
7
7
  "bugs": {
@@ -35,9 +35,9 @@
35
35
  "README.md"
36
36
  ],
37
37
  "dependencies": {
38
- "@xyo-network/xl1-protocol-lib": "~2.1.2",
39
- "@xyo-network/xl1-driver-memory": "~2.1.2",
40
- "@xyo-network/xl1-protocol-sdk": "~2.1.2"
38
+ "@xyo-network/xl1-driver-memory": "~2.1.4",
39
+ "@xyo-network/xl1-protocol-lib": "~2.1.4",
40
+ "@xyo-network/xl1-protocol-sdk": "~2.1.4"
41
41
  },
42
42
  "devDependencies": {
43
43
  "@bitauth/libauth": "~3.0.0",
@@ -47,18 +47,16 @@
47
47
  "@opentelemetry/sdk-trace-base": "^2.7.1",
48
48
  "@scure/base": "~2.2.0",
49
49
  "@scure/bip39": "~2.2.0",
50
- "@xylabs/geo": "^6.1.0",
51
- "@xylabs/sdk-js": "^6.1.0",
52
- "@xylabs/threads": "~6.1",
50
+ "@xylabs/geo": "^6.1.1",
51
+ "@xylabs/sdk-js": "^6.1.1",
52
+ "@xylabs/threads": "^6.1.1",
53
53
  "@xylabs/toolchain": "~8.1.20",
54
54
  "@xylabs/tsconfig": "~8.1.20",
55
- "@xyo-network/address": "^6.0.9",
56
- "@xyo-network/sdk-js": "^6.0.4",
57
- "@xyo-network/sdk-protocol-js": "~6.0.9",
55
+ "@xyo-network/address": "^6.1.0",
56
+ "@xyo-network/sdk-js": "^6.1.0",
57
+ "@xyo-network/sdk-protocol-js": "~6.1",
58
58
  "ajv": "^8.20.0",
59
59
  "async-mutex": "^0.5.0",
60
- "bn.js": "^5.2.3",
61
- "buffer": "^6.0.3",
62
60
  "cosmiconfig": "^9.0.2",
63
61
  "debug": "~4.4.3",
64
62
  "eslint": "^10.4.1",
@@ -86,11 +84,9 @@
86
84
  "@xylabs/threads": "^6.1",
87
85
  "@xyo-network/address": "^6.0",
88
86
  "@xyo-network/sdk-js": "^6.0",
89
- "@xyo-network/sdk-protocol-js": "~6.0",
87
+ "@xyo-network/sdk-protocol-js": "~6.1",
90
88
  "ajv": "^8.20",
91
89
  "async-mutex": "^0.5",
92
- "bn.js": "^5.2",
93
- "buffer": "^6.0",
94
90
  "cosmiconfig": "^9.0",
95
91
  "debug": "~4.4",
96
92
  "ethers": "^6.16",