Skip to main content

Overview

EngineApiService exposes the Engine API (engine_*) used by consensus clients to communicate with execution clients. These methods are typically available only on authenticated engine endpoints, not public RPC URLs.

Quick Start

import { Effect, Layer } from 'effect'
import { EngineApiService, EngineApi, HttpTransport } from 'voltaire-effect'

// Compose layers first
const EngineLayer = EngineApi.pipe(
  Layer.provide(HttpTransport('http://localhost:8551'))
)

const program = Effect.gen(function* () {
  const engine = yield* EngineApiService
  const caps = yield* engine.exchangeCapabilities([
    'engine_newPayloadV3',
    'engine_forkchoiceUpdatedV3',
    'engine_getPayloadV3'
  ])
  return caps
}).pipe(Effect.provide(EngineLayer))

Forkchoice and Payloads

const forkchoice = {
  headBlockHash: '0x...',
  safeBlockHash: '0x...',
  finalizedBlockHash: '0x...'
}

const payloadAttrs = {
  timestamp: '0x654321',
  prevRandao: '0x...',
  suggestedFeeRecipient: '0x...'
}

const update = yield* engine.forkchoiceUpdatedV3(forkchoice, payloadAttrs)
const payload = yield* engine.getPayloadV3('0xpayloadId')

New Payload Submission

const payload = { /* execution payload object */ }

const result = yield* engine.newPayloadV3(
  payload,
  ['0xversionedHash1', '0xversionedHash2'],
  '0xparentBeaconBlockRoot'
)

Payload Bodies and Blobs

const bodiesByHash = yield* engine.getPayloadBodiesByHashV1(['0xblockHash1'])
const bodiesByRange = yield* engine.getPayloadBodiesByRangeV1(0x1000, 0x10)
const blobs = yield* engine.getBlobsV1(['0xblobHash'])

Error Handling

All methods raise TransportError when the engine endpoint rejects the request or the network fails.
import { TransportError } from 'voltaire-effect'

program.pipe(
  Effect.catchTag('TransportError', (e) =>
    Effect.log(`Engine API failed: ${e.message}`)
  )
)

Service Interface

type EngineApiShape = {
  readonly exchangeCapabilities: (caps: readonly string[]) => Effect.Effect<readonly string[], TransportError>
  readonly exchangeTransitionConfigurationV1: (config: unknown) => Effect.Effect<unknown, TransportError>
  readonly forkchoiceUpdatedV1: (forkchoiceState: unknown, payloadAttributes?: unknown) => Effect.Effect<unknown, TransportError>
  readonly forkchoiceUpdatedV2: (forkchoiceState: unknown, payloadAttributes?: unknown) => Effect.Effect<unknown, TransportError>
  readonly forkchoiceUpdatedV3: (forkchoiceState: unknown, payloadAttributes?: unknown) => Effect.Effect<unknown, TransportError>
  readonly getPayloadV1: (payloadId: `0x${string}`) => Effect.Effect<unknown, TransportError>
  readonly getPayloadV2: (payloadId: `0x${string}`) => Effect.Effect<unknown, TransportError>
  readonly getPayloadV3: (payloadId: `0x${string}`) => Effect.Effect<unknown, TransportError>
  readonly getPayloadV4: (payloadId: `0x${string}`) => Effect.Effect<unknown, TransportError>
  readonly newPayloadV1: (payload: unknown) => Effect.Effect<unknown, TransportError>
  readonly newPayloadV2: (payload: unknown) => Effect.Effect<unknown, TransportError>
  readonly newPayloadV3: (
    payload: unknown,
    expectedBlobVersionedHashes?: readonly `0x${string}`[],
    parentBeaconBlockRoot?: `0x${string}`
  ) => Effect.Effect<unknown, TransportError>
  readonly newPayloadV4: (payload: unknown, ...extra: readonly unknown[]) => Effect.Effect<unknown, TransportError>
  readonly getPayloadBodiesByHashV1: (blockHashes: readonly `0x${string}`[]) => Effect.Effect<unknown, TransportError>
  readonly getPayloadBodiesByRangeV1: (start: `0x${string}` | number | bigint, count: `0x${string}` | number | bigint) => Effect.Effect<unknown, TransportError>
  readonly getBlobsV1: (versionedHashes: readonly `0x${string}`[]) => Effect.Effect<unknown, TransportError>
}

Dependencies

EngineApi --- requires --> TransportService

See Also