@lodestar/api 1.45.0-dev.f535421f29 → 1.45.0-dev.fadf0fbb1f

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.
@@ -4,6 +4,8 @@ import {
4
4
  ForkPostDeneb,
5
5
  ForkPostGloas,
6
6
  ForkPreDeneb,
7
+ MIN_SEED_LOOKAHEAD,
8
+ SLOTS_PER_EPOCH,
7
9
  VALIDATOR_REGISTRY_LIMIT,
8
10
  isForkPostDeneb,
9
11
  isForkPostElectra,
@@ -246,6 +248,10 @@ export const SignedValidatorRegistrationV1ListType = ArrayOf(
246
248
  ssz.bellatrix.SignedValidatorRegistrationV1,
247
249
  VALIDATOR_REGISTRY_LIMIT
248
250
  );
251
+ export const SignedProposerPreferencesListType = ArrayOf(
252
+ ssz.gloas.SignedProposerPreferences,
253
+ (MIN_SEED_LOOKAHEAD + 1) * SLOTS_PER_EPOCH
254
+ );
249
255
 
250
256
  export type ValidatorIndices = ValueOf<typeof ValidatorIndicesType>;
251
257
  export type AttesterDuty = ValueOf<typeof AttesterDutyType>;
@@ -273,6 +279,13 @@ export type SyncCommitteeSelectionList = ValueOf<typeof SyncCommitteeSelectionLi
273
279
  export type LivenessResponseData = ValueOf<typeof LivenessResponseDataType>;
274
280
  export type LivenessResponseDataList = ValueOf<typeof LivenessResponseDataListType>;
275
281
  export type SignedValidatorRegistrationV1List = ValueOf<typeof SignedValidatorRegistrationV1ListType>;
282
+ export type SignedProposerPreferencesList = ValueOf<typeof SignedProposerPreferencesListType>;
283
+
284
+ // The beacon node does not return any data if there is no canonical block at the requested slot (missed slot).
285
+ // In this case, we receive a success response (204) which is not handled as an error. The generic response
286
+ // handler already checks the status code and will not attempt to parse the body, but it will return no value.
287
+ // It is important that this type indicates that there might be no value to ensure it is properly handled downstream.
288
+ export type MaybePayloadAttestationData = gloas.PayloadAttestationData | undefined;
276
289
 
277
290
  export type Endpoints = {
278
291
  /**
@@ -483,7 +496,7 @@ export type Endpoints = {
483
496
  slot: Slot;
484
497
  },
485
498
  {params: {slot: Slot}},
486
- gloas.PayloadAttestationData,
499
+ MaybePayloadAttestationData,
487
500
  VersionMeta
488
501
  >;
489
502
 
@@ -646,6 +659,20 @@ export type Endpoints = {
646
659
  EmptyResponseData,
647
660
  EmptyMeta
648
661
  >;
662
+
663
+ /**
664
+ * Submit signed proposer preferences
665
+ *
666
+ * Verifies given signed proposer preferences and publishes them on the `proposer_preferences`
667
+ * gossipsub topic. Supersedes `prepareBeaconProposer` and `registerValidator` from Gloas onwards.
668
+ */
669
+ submitProposerPreferences: Endpoint<
670
+ "POST",
671
+ {signedProposerPreferences: SignedProposerPreferencesList},
672
+ {body: unknown; headers: {[MetaHeader.Version]: string}},
673
+ EmptyResponseData,
674
+ EmptyMeta
675
+ >;
649
676
  };
650
677
 
651
678
  export function getDefinitions(config: ChainForkConfig): RouteDefinitions<Endpoints> {
@@ -982,7 +1009,7 @@ export function getDefinitions(config: ChainForkConfig): RouteDefinitions<Endpoi
982
1009
  },
983
1010
  },
984
1011
  resp: {
985
- data: ssz.gloas.PayloadAttestationData,
1012
+ data: WithVersion<MaybePayloadAttestationData, VersionMeta>(() => ssz.gloas.PayloadAttestationData),
986
1013
  meta: VersionCodec,
987
1014
  },
988
1015
  },
@@ -1210,6 +1237,33 @@ export function getDefinitions(config: ChainForkConfig): RouteDefinitions<Endpoi
1210
1237
  requestWireFormat: WireFormat.ssz,
1211
1238
  },
1212
1239
  },
1240
+ submitProposerPreferences: {
1241
+ url: "/eth/v1/validator/proposer_preferences",
1242
+ method: "POST",
1243
+ req: {
1244
+ writeReqJson: ({signedProposerPreferences}) => ({
1245
+ body: SignedProposerPreferencesListType.toJson(signedProposerPreferences),
1246
+ headers: {[MetaHeader.Version]: config.getForkName(signedProposerPreferences[0]?.message.proposalSlot ?? 0)},
1247
+ }),
1248
+ parseReqJson: ({body, headers}) => {
1249
+ toForkName(fromHeaders(headers, MetaHeader.Version));
1250
+ return {signedProposerPreferences: SignedProposerPreferencesListType.fromJson(body)};
1251
+ },
1252
+ writeReqSsz: ({signedProposerPreferences}) => ({
1253
+ body: SignedProposerPreferencesListType.serialize(signedProposerPreferences),
1254
+ headers: {[MetaHeader.Version]: config.getForkName(signedProposerPreferences[0]?.message.proposalSlot ?? 0)},
1255
+ }),
1256
+ parseReqSsz: ({body, headers}) => {
1257
+ toForkName(fromHeaders(headers, MetaHeader.Version));
1258
+ return {signedProposerPreferences: SignedProposerPreferencesListType.deserialize(body)};
1259
+ },
1260
+ schema: {
1261
+ body: Schema.ObjectArray,
1262
+ headers: {[MetaHeader.Version]: Schema.String},
1263
+ },
1264
+ },
1265
+ resp: EmptyResponseCodec,
1266
+ },
1213
1267
  };
1214
1268
  }
1215
1269
 
@@ -75,6 +75,9 @@ export function fromValidatorIdsStr(ids?: string[]): (string | number)[] | undef
75
75
  return ids?.map((id) => (typeof id === "string" && id.startsWith("0x") ? id : fromU64Str(id)));
76
76
  }
77
77
 
78
+ export const toBuilderIdsStr = toValidatorIdsStr;
79
+ export const fromBuilderIdsStr = fromValidatorIdsStr;
80
+
78
81
  const GRAFFITI_HEX_LENGTH = 66;
79
82
 
80
83
  export function toGraffitiHex(utf8?: string): string | undefined {
@@ -111,6 +111,11 @@ export function createFastifyHandler<E extends Endpoint>(
111
111
  resp.statusCode = response.status;
112
112
  }
113
113
 
114
+ // A 204 No Content response has no body
115
+ if (resp.statusCode === 204) {
116
+ return;
117
+ }
118
+
114
119
  switch (responseWireFormat) {
115
120
  case WireFormat.json: {
116
121
  const metaHeaders = definition.resp.meta.toHeadersObject(response?.meta);