Files
lodestar/packages/light-client/src/transport/rest.ts
Nazar Hussain 0c6f50771f chore: use latest TS module resolution (#8419)
**Motivation**

Use latest `module` and `moduleResolution` for TS.

**Description**

- To use [subpath
imports](https://nodejs.org/api/packages.html#subpath-imports) in the PR
#8320 we need to update the module solution strategy for TS.
- That requires to change the `module` for the TS as well. 
- Earlier tried to stay with `node18` or `node20`, but the `ts-node`
does not work with that.
- Maintaining different tsconfig for ts-node is more of hassle on wrong
run.
- So decided to stick with `nodenext` strategy for `moduleResolution` 

**Steps to test or reproduce**

Run all tests

---------

Co-authored-by: Cayman <caymannava@gmail.com>
2025-09-18 11:36:48 -04:00

90 lines
3.3 KiB
TypeScript

import {type ApiClient, routes} from "@lodestar/api";
import {type ForkName} from "@lodestar/params";
import {
LightClientBootstrap,
LightClientFinalityUpdate,
LightClientOptimisticUpdate,
LightClientUpdate,
type SyncPeriod,
} from "@lodestar/types";
import mitt, {Emitter as MittEmitter} from "mitt";
import {type LightClientTransport} from "./interface.js";
export type LightClientRestEvents = {
[routes.events.EventType.lightClientFinalityUpdate]: (update: LightClientFinalityUpdate) => void;
[routes.events.EventType.lightClientOptimisticUpdate]: (update: LightClientOptimisticUpdate) => void;
};
export type LightClientRestEmitter = MittEmitter<LightClientRestEvents>;
export class LightClientRestTransport implements LightClientTransport {
private controller = new AbortController();
private readonly eventEmitter: LightClientRestEmitter = mitt();
private subscribedEventstream = false;
constructor(private readonly api: ApiClient) {}
async getUpdates(
startPeriod: SyncPeriod,
count: number
): Promise<
{
version: ForkName;
data: LightClientUpdate;
}[]
> {
const res = await this.api.lightclient.getLightClientUpdatesByRange({startPeriod, count});
const updates = res.value();
const {versions} = res.meta();
return updates.map((data, i) => ({data, version: versions[i]}));
}
async getOptimisticUpdate(): Promise<{version: ForkName; data: LightClientOptimisticUpdate}> {
const res = await this.api.lightclient.getLightClientOptimisticUpdate();
return {version: res.meta().version, data: res.value()};
}
async getFinalityUpdate(): Promise<{version: ForkName; data: LightClientFinalityUpdate}> {
const res = await this.api.lightclient.getLightClientFinalityUpdate();
return {version: res.meta().version, data: res.value()};
}
async getBootstrap(blockRoot: string): Promise<{version: ForkName; data: LightClientBootstrap}> {
const res = await this.api.lightclient.getLightClientBootstrap({blockRoot});
return {version: res.meta().version, data: res.value()};
}
onOptimisticUpdate(handler: (optimisticUpdate: LightClientOptimisticUpdate) => void): void {
this.subscribeEventstream();
this.eventEmitter.on(routes.events.EventType.lightClientOptimisticUpdate, handler);
}
onFinalityUpdate(handler: (finalityUpdate: LightClientFinalityUpdate) => void): void {
this.subscribeEventstream();
this.eventEmitter.on(routes.events.EventType.lightClientFinalityUpdate, handler);
}
private subscribeEventstream(): void {
if (this.subscribedEventstream) {
return;
}
void this.api.events.eventstream({
topics: [routes.events.EventType.lightClientOptimisticUpdate, routes.events.EventType.lightClientFinalityUpdate],
signal: this.controller.signal,
onEvent: (event) => {
switch (event.type) {
case routes.events.EventType.lightClientOptimisticUpdate:
this.eventEmitter.emit(routes.events.EventType.lightClientOptimisticUpdate, event.message.data);
break;
case routes.events.EventType.lightClientFinalityUpdate:
this.eventEmitter.emit(routes.events.EventType.lightClientFinalityUpdate, event.message.data);
break;
}
},
});
this.subscribedEventstream = true;
}
}