This document outlines the key aspects of integrating with TitanRelay, a high-performance MEV-Boost relay. It supports standard APIs with a few enhancements for improved functionality and performance.
Get Validators
We've added a "preferences" field to validator submissions, enabling relay-level PEPC (Protocol Enforced Proposer Commitments). Currently, we support two preferences:
filtering: The relay supports both filtering and non-filtering proposers under a single URL. Filtering is now per-proposer instead of per-relay.
trusted_builders: When signing up for optimistic relaying, you'll receive a BuilderID (e.g., "Titan"). Proposers can specify to only accept blocks from certain builders.
structValidatorPreferences{/// A string indicating which filtering policy to use ("regional" or "global").filtering:String,/// An optional list of BuilderIDs. If this is set, the relay will only accept/// submissions from builders whose public keys are linked to the IDs in this list./// This allows for limiting submissions to a trusted set of builders.trusted_builders:Option<Vec<String>>,}structBuilderGetValidatorsResponse{slot:u64,validator_index:usize,entry:SignedValidatorRegistration,preferences:ValidatorPreferences,}
Optimistic Relaying
Optimistic V1
We support standard optimistic v1 relaying with up to 64 ETH collateral. See the Optimistic Relaying page for more details.
Optimistic V2
This endpoint is now deprecated
We support OptimisticV2 submissions. If enabled for v1, you can submit to our v2 endpoints. OptimisticV2 decouples the lightweight header from the heavier payload, allowing for faster processing. See the original proposal here.
To send a block submission with OptimisticV2, you will need to call these two new endpoints:
relay/v1/builder/headers: Contains the header and signed bid trace.
relay/v1/builder/blocks_optimistic_v2: The submission struct is identical to the block submitted with the current relay/v1/builder/blocks endpoint.
We recommend submitting v2 alongside normal block submissions for extra redundancy and because v2 is still in the testing phase. We often over-demote so it’s best if you use separate pubkeys to mitigate the impact of incorrect demotions.
Alongside changing the submission endpoints, you must also manually track your collateral to guarantee it covers the block value and ensure a valid full block is received within 2 seconds of a valid header submission to avoid demotion.
Optimistic V3
This endpoint is not currently implemented
Optimistic v3 submissions are enabled at relay/v3/builder/headers
Where SignedHeaderSubmission is the same as for V2. When submitting a header you need to ensure that the corresponding payload is available at [url]/get_payload_v3 . The relay may send a request for the payload via a ssz-encoded SignedGetPayloadV3 request:
The builder is expected to timely return the corresponding SignedBidSubmission , failure to do so may result in a missed slot and collateral slashing. Collateral requirements are the same as for V2 submissions.
To optimise bandwidth utilisation we support sending dehydrated payloads for V1 submissions. A builder may submit transactions and blobs only once per slot. Subsequent submissions within the same slot can reference those orders by their hash or proof, and the relay will rehydrate the payload using a local cache.
The transaction hashes are directly reusing the transaction field in the ExecutionPayload. To enable block deltas make sure to add a x-hydrate header to the submission.
Content-Encoding : optional, supported values: gzip, zstd . Default is no compression
Content-Type : optional, supported value: application/octet-stream for SSZ encoding. Default is json encoding
x-api-key : optional, if present and matching with an optimistic pubkey, signature verification will be skipped
x-hydrate: optional, if present enables block deltas submissions (NB: x-api-key required for this!)
x-sequence : optional, if present the relay will reject lower sequence numbers received for the same slot / pubkey
TCP Bid Submissions
As an alternative to HTTP submitBlock for latency-sensitive builders the relay exposes a persistent TCP endpoint. Contact us directly to get access to it.
Framing
Every message in both directions is wrapped in the same 12-byte frame header. The timestamp is recorded by the relay for latency tracking and does not affect processing.
Session lifecycle
A session consists of three phases: connection, registration, bid submissions. There is no teardown handshake; either side may close the connection at any time.
1. Registration Message
The first frame sent after connecting must be a registration message. It identifies the builder to the relay so that subsequent submissions do not need to carry credentials. The relay validates the (api_key, builder_pubkey)and if validation fails the connection is dropped immediately. On success the relay is ready to accept bid submissions.
The api_key is the same UUID used in the HTTP x-api-key header. The builder_pubkey is the BLS public key of the builder.
SSZ-encoded Payload
2. Bid Submissions
Bid submission payload begins with a 6-byte header that carries metadata, followed by the block submission body — identical in format to the HTTP SSZ-encoded submitBlock body.
The sequence_number is a client-managed per-slot counter. It is echoed back in the response so that the client can match responses to submissions when multiple bids are in-flight simultaneously. It must be unique within a slot; duplicate sequence numbers are rejected.
Payload:
Header — 6 bytes:
merge_type bit setting is not in use currently, and should be left empty.
Flags:
Bit
Name
Description
0
IS_DEHYDRATED
payload is a dehydrated block
1
WITH_ADJUSTMENTS
payload includes bid adjustments (not in use currently, should be left empty)
2
ZSTD_COMPRESSED
payload body is zstd-compressed
3. Responses
On success (status=0) error_msg is empty. On failure the relay populates error_msg with a human-readable UTF-8 description of the rejection reason, and request_id can be used to correlate the failure with relay-side logs.
Payload — SSZ-encoded BidSubmissionResponse:
Reconnection
The relay may close the connection at slot boundaries or on internal errors. Clients should detect disconnection and reconnect, sending a fresh registration message before resuming submissions. The sequence_number counter should be reset to zero at the start of each slot.
Websocket TopBid Stream
We provide a websocket stream at the endpoint builder/top_bid that sends real-time updates whenever a new top bid is received by the relay. Each time a new best bid is processed, a message containing the updated bid information will be pushed to connected clients. Authentication for this stream is done using an x-api-key header.
The structure of the TopBidUpdate message is as follows:
To access the TopBid stream, builders must meet three criteria:
Build ≥ 0.10% of all MevBoost blocks (weekly rolling basis)
struct GetPayloadV3 {
/// Hash of the block header from the `SignedHeaderSubmission`.
block_hash: B256,
/// Timestamp (in milliseconds) when the relay made this request.
request_ts_millis: u64,
/// Relay's public key
relay_pubkey: BlsPublicKey,
}
struct SignedGetPayloadV3 {
message: GetPayloadV3,
signature: BlsSignature,
}
[4B LE u32 payload_len]
[8B LE u64 timestamp_nanos]
[payload_len bytes payload]
[16B api_key — UUID, raw bytes]
[48B builder_pubkey — BLS public key, raw bytes]
[6B header]
[... SSZ-encoded block submission (same body as HTTP submitBlock)]
[4B BE u32 sequence_number] — per-slot counter; must be unique per slot
[1B merge_type] — 0=None 1=Mergeable 2=AppendOnly
[1B flags] — bitmask (see below)
[4B LE u32 sequence_number] — echoes the submission's sequence_number
[16B request_id] — UUID assigned by the relay
[1B status] — 0=Okay 1=InvalidRequest 2=InternalError
[4B LE u32 error_msg_offset] — SSZ variable-length offset (always 25)
[... error_msg] — UTF-8 string