@@ -292,10 +292,25 @@ impl BuilderHttpClient {
292
292
Ok ( ( ) )
293
293
}
294
294
295
- /// `POST /eth/v1/builder/blinded_blocks` with SSZ serialized request body
296
295
pub async fn post_builder_blinded_blocks_ssz < E : EthSpec > (
297
296
& self ,
298
297
blinded_block : & SignedBlindedBeaconBlock < E > ,
298
+ ) -> Result < Option < FullPayloadContents < E > > , Error > {
299
+ if blinded_block. fork_name_unchecked ( ) . fulu_enabled ( ) {
300
+ self . post_builder_blinded_blocks_v2_ssz ( blinded_block)
301
+ . await
302
+ . map ( |_| None )
303
+ } else {
304
+ self . post_builder_blinded_blocks_v1_ssz ( blinded_block)
305
+ . await
306
+ . map ( Some )
307
+ }
308
+ }
309
+
310
+ /// `POST /eth/v1/builder/blinded_blocks` with SSZ serialized request body
311
+ pub async fn post_builder_blinded_blocks_v1_ssz < E : EthSpec > (
312
+ & self ,
313
+ blinded_block : & SignedBlindedBeaconBlock < E > ,
299
314
) -> Result < FullPayloadContents < E > , Error > {
300
315
let mut path = self . server . full . clone ( ) ;
301
316
@@ -340,10 +355,73 @@ impl BuilderHttpClient {
340
355
. map_err ( Error :: InvalidSsz )
341
356
}
342
357
343
- /// `POST /eth/v1/builder/blinded_blocks`
358
+ /// `POST /eth/v2/builder/blinded_blocks` with SSZ serialized request body
359
+ pub async fn post_builder_blinded_blocks_v2_ssz < E : EthSpec > (
360
+ & self ,
361
+ blinded_block : & SignedBlindedBeaconBlock < E > ,
362
+ ) -> Result < ( ) , Error > {
363
+ let mut path = self . server . full . clone ( ) ;
364
+
365
+ let body = blinded_block. as_ssz_bytes ( ) ;
366
+
367
+ path. path_segments_mut ( )
368
+ . map_err ( |( ) | Error :: InvalidUrl ( self . server . clone ( ) ) ) ?
369
+ . push ( "eth" )
370
+ . push ( "v2" )
371
+ . push ( "builder" )
372
+ . push ( "blinded_blocks" ) ;
373
+
374
+ let mut headers = HeaderMap :: new ( ) ;
375
+ headers. insert (
376
+ CONSENSUS_VERSION_HEADER ,
377
+ HeaderValue :: from_str ( & blinded_block. fork_name_unchecked ( ) . to_string ( ) )
378
+ . map_err ( |e| Error :: InvalidHeaders ( format ! ( "{}" , e) ) ) ?,
379
+ ) ;
380
+ headers. insert (
381
+ CONTENT_TYPE_HEADER ,
382
+ HeaderValue :: from_str ( SSZ_CONTENT_TYPE_HEADER )
383
+ . map_err ( |e| Error :: InvalidHeaders ( format ! ( "{}" , e) ) ) ?,
384
+ ) ;
385
+ headers. insert (
386
+ ACCEPT ,
387
+ HeaderValue :: from_str ( PREFERENCE_ACCEPT_VALUE )
388
+ . map_err ( |e| Error :: InvalidHeaders ( format ! ( "{}" , e) ) ) ?,
389
+ ) ;
390
+
391
+ let result = self
392
+ . post_ssz_with_raw_response (
393
+ path,
394
+ body,
395
+ headers,
396
+ Some ( self . timeouts . post_blinded_blocks ) ,
397
+ )
398
+ . await ?;
399
+
400
+ if result. status ( ) == StatusCode :: ACCEPTED {
401
+ Ok ( ( ) )
402
+ } else {
403
+ // ACCEPTED is the only valid status code response
404
+ Err ( Error :: StatusCode ( result. status ( ) ) )
405
+ }
406
+ }
407
+
344
408
pub async fn post_builder_blinded_blocks < E : EthSpec > (
345
409
& self ,
346
410
blinded_block : & SignedBlindedBeaconBlock < E > ,
411
+ ) -> Result < Option < ForkVersionedResponse < FullPayloadContents < E > > > , Error > {
412
+ if blinded_block. fork_name_unchecked ( ) . fulu_enabled ( ) {
413
+ self . post_builder_blinded_blocks_v2 ( blinded_block)
414
+ . await
415
+ . map ( |_| None )
416
+ } else {
417
+ self . post_builder_blinded_blocks_v1 ( blinded_block) . await . map ( Some )
418
+ }
419
+ }
420
+
421
+ /// `POST /eth/v1/builder/blinded_blocks`
422
+ pub async fn post_builder_blinded_blocks_v1 < E : EthSpec > (
423
+ & self ,
424
+ blinded_block : & SignedBlindedBeaconBlock < E > ,
347
425
) -> Result < ForkVersionedResponse < FullPayloadContents < E > > , Error > {
348
426
let mut path = self . server . full . clone ( ) ;
349
427
@@ -383,6 +461,54 @@ impl BuilderHttpClient {
383
461
. await ?)
384
462
}
385
463
464
+ /// `POST /eth/v2/builder/blinded_blocks`
465
+ pub async fn post_builder_blinded_blocks_v2 < E : EthSpec > (
466
+ & self ,
467
+ blinded_block : & SignedBlindedBeaconBlock < E > ,
468
+ ) -> Result < ( ) , Error > {
469
+ let mut path = self . server . full . clone ( ) ;
470
+
471
+ path. path_segments_mut ( )
472
+ . map_err ( |( ) | Error :: InvalidUrl ( self . server . clone ( ) ) ) ?
473
+ . push ( "eth" )
474
+ . push ( "v2" )
475
+ . push ( "builder" )
476
+ . push ( "blinded_blocks" ) ;
477
+
478
+ let mut headers = HeaderMap :: new ( ) ;
479
+ headers. insert (
480
+ CONSENSUS_VERSION_HEADER ,
481
+ HeaderValue :: from_str ( & blinded_block. fork_name_unchecked ( ) . to_string ( ) )
482
+ . map_err ( |e| Error :: InvalidHeaders ( format ! ( "{}" , e) ) ) ?,
483
+ ) ;
484
+ headers. insert (
485
+ CONTENT_TYPE_HEADER ,
486
+ HeaderValue :: from_str ( JSON_CONTENT_TYPE_HEADER )
487
+ . map_err ( |e| Error :: InvalidHeaders ( format ! ( "{}" , e) ) ) ?,
488
+ ) ;
489
+ headers. insert (
490
+ ACCEPT ,
491
+ HeaderValue :: from_str ( JSON_ACCEPT_VALUE )
492
+ . map_err ( |e| Error :: InvalidHeaders ( format ! ( "{}" , e) ) ) ?,
493
+ ) ;
494
+
495
+ let result = self
496
+ . post_with_raw_response (
497
+ path,
498
+ & blinded_block,
499
+ headers,
500
+ Some ( self . timeouts . post_blinded_blocks ) ,
501
+ )
502
+ . await ?;
503
+
504
+ if result. status ( ) == StatusCode :: ACCEPTED {
505
+ Ok ( ( ) )
506
+ } else {
507
+ // ACCEPTED is the only valid status code response
508
+ Err ( Error :: StatusCode ( result. status ( ) ) )
509
+ }
510
+ }
511
+
386
512
/// `GET /eth/v1/builder/header`
387
513
pub async fn get_builder_header < E : EthSpec > (
388
514
& self ,
0 commit comments