UNPKG

@lodestar/api

Version:

A Typescript REST client for the Ethereum Consensus API

234 lines (223 loc) 6.61 kB
import {ContainerType, Type, ValueOf} from "@chainsafe/ssz"; import {ChainForkConfig} from "@lodestar/config"; import {isForkPostFulu} from "@lodestar/params"; import {ArrayOf, BeaconState, DataColumnSidecars, StringType, ssz, sszTypesFor} from "@lodestar/types"; import { EmptyArgs, EmptyMeta, EmptyMetaCodec, EmptyRequest, EmptyRequestCodec, WithVersion, } from "../../utils/codecs.js"; import { ExecutionOptimisticFinalizedAndVersionCodec, ExecutionOptimisticFinalizedAndVersionMeta, } from "../../utils/metadata.js"; import {Schema} from "../../utils/schema.js"; import {Endpoint, RouteDefinitions} from "../../utils/types.js"; import {WireFormat} from "../../utils/wireFormat.js"; import {BlockArgs} from "./beacon/block.js"; import {StateArgs} from "./beacon/state.js"; const stringType = new StringType(); const ProtoNodeType = new ContainerType( { executionPayloadBlockHash: stringType, executionPayloadNumber: ssz.UintNum64, executionStatus: stringType, slot: ssz.Slot, blockRoot: stringType, parentRoot: stringType, stateRoot: stringType, targetRoot: stringType, timeliness: ssz.Boolean, justifiedEpoch: ssz.Epoch, justifiedRoot: stringType, finalizedEpoch: ssz.Epoch, finalizedRoot: stringType, unrealizedJustifiedEpoch: ssz.Epoch, unrealizedJustifiedRoot: stringType, unrealizedFinalizedEpoch: ssz.Epoch, unrealizedFinalizedRoot: stringType, parent: stringType, weight: ssz.Uint32, bestChild: stringType, bestDescendant: stringType, }, {jsonCase: "eth2"} ); const DebugChainHeadType = new ContainerType( { slot: ssz.Slot, root: stringType, executionOptimistic: ssz.Boolean, }, {jsonCase: "eth2"} ); const ForkChoiceNodeType = new ContainerType( { slot: ssz.Slot, blockRoot: stringType, parentRoot: stringType, justifiedEpoch: ssz.Epoch, finalizedEpoch: ssz.Epoch, weight: ssz.UintNum64, validity: new StringType<"valid" | "invalid" | "optimistic">(), executionBlockHash: stringType, }, {jsonCase: "eth2"} ); const ForkChoiceResponseType = new ContainerType( { justifiedCheckpoint: ssz.phase0.Checkpoint, finalizedCheckpoint: ssz.phase0.Checkpoint, forkChoiceNodes: ArrayOf(ForkChoiceNodeType), }, {jsonCase: "eth2"} ); const ProtoNodeListType = ArrayOf(ProtoNodeType); const DebugChainHeadListType = ArrayOf(DebugChainHeadType); type ProtoNodeList = ValueOf<typeof ProtoNodeListType>; type DebugChainHeadList = ValueOf<typeof DebugChainHeadListType>; type ForkChoiceResponse = ValueOf<typeof ForkChoiceResponseType>; export type Endpoints = { /** * Retrieves all possible chain heads (leaves of fork choice tree). */ getDebugChainHeadsV2: Endpoint< // ⏎ "GET", EmptyArgs, EmptyRequest, DebugChainHeadList, EmptyMeta >; /** * Retrieves all current fork choice context */ getDebugForkChoice: Endpoint< // ⏎ "GET", EmptyArgs, EmptyRequest, ForkChoiceResponse, EmptyMeta >; /** * Dump all ProtoArray's nodes to debug */ getProtoArrayNodes: Endpoint< // ⏎ "GET", EmptyArgs, EmptyRequest, ProtoNodeList, EmptyMeta >; /** * Get full BeaconState object * Returns full BeaconState object for given stateId. * Depending on `Accept` header it can be returned either as json or as bytes serialized by SSZ */ getStateV2: Endpoint< "GET", StateArgs, {params: {state_id: string}}, BeaconState, ExecutionOptimisticFinalizedAndVersionMeta >; /** * Get data column sidecars * Retrieves data column sidecars for a given block id. */ getDebugDataColumnSidecars: Endpoint< "GET", BlockArgs & { /** * Array of indices for data column sidecars to request for in the specified block. * This endpoint will only return columns that the node is actually custodying. * If not specified, returns all data column sidecars that this node is custodying in the block. */ indices?: number[]; }, {params: {block_id: string}; query: {indices?: number[]}}, DataColumnSidecars, ExecutionOptimisticFinalizedAndVersionMeta >; }; export function getDefinitions(_config: ChainForkConfig): RouteDefinitions<Endpoints> { return { getDebugChainHeadsV2: { url: "/eth/v2/debug/beacon/heads", method: "GET", req: EmptyRequestCodec, resp: { data: DebugChainHeadListType, meta: EmptyMetaCodec, onlySupport: WireFormat.json, }, }, getDebugForkChoice: { url: "/eth/v1/debug/fork_choice", method: "GET", req: EmptyRequestCodec, resp: { data: ForkChoiceResponseType, meta: EmptyMetaCodec, onlySupport: WireFormat.json, transform: { toResponse: (data) => ({ ...(data as ForkChoiceResponse), }), fromResponse: (resp) => ({ data: resp as ForkChoiceResponse, }), }, }, }, getProtoArrayNodes: { url: "/eth/v0/debug/forkchoice", method: "GET", req: EmptyRequestCodec, resp: { data: ProtoNodeListType, meta: EmptyMetaCodec, onlySupport: WireFormat.json, }, }, getStateV2: { url: "/eth/v2/debug/beacon/states/{state_id}", method: "GET", req: { writeReq: ({stateId}) => ({params: {state_id: stateId.toString()}}), parseReq: ({params}) => ({stateId: params.state_id}), schema: { params: {state_id: Schema.StringRequired}, }, }, resp: { data: WithVersion((fork) => ssz[fork].BeaconState as Type<BeaconState>), meta: ExecutionOptimisticFinalizedAndVersionCodec, }, init: { // Default timeout is not sufficient to download state as JSON timeoutMs: 5 * 60 * 1000, }, }, getDebugDataColumnSidecars: { url: "/eth/v1/debug/beacon/data_column_sidecars/{block_id}", method: "GET", req: { writeReq: ({blockId, indices}) => ({params: {block_id: blockId.toString()}, query: {indices}}), parseReq: ({params, query}) => ({blockId: params.block_id, indices: query.indices}), schema: {params: {block_id: Schema.StringRequired}, query: {indices: Schema.UintArray}}, }, resp: { data: WithVersion((fork) => isForkPostFulu(fork) ? sszTypesFor(fork).DataColumnSidecars : ssz.fulu.DataColumnSidecars ), meta: ExecutionOptimisticFinalizedAndVersionCodec, }, }, }; }