Integration Guide

Step 1: Check Builder Capabilities

Before submitting, query the builder's current limits:

import requests
from eth_account import Account

EUREKA_RPC = "https://rpc.eurekabuilder.xyz"

def get_capabilities(private_key: str):
    body = {
        "jsonrpc": "2.0",
        "method": "bex_capabilities",
        "params": [],
        "id": 1,
    }

    message = json.dumps(body)
    account = Account.from_key(private_key)
    signature = account.sign_message(encode_defunct(text=message))
    header_value = f"{account.address}:{signature.signature.hex()}"

    response = requests.post(
        EUREKA_RPC,
        json=body,
        headers={"X-Flashbots-Signature": header_value},
    )
    return response.json()

This returns maxCalldataBytes, maxComputeGas, and maxExecuteGas. Stay within these limits or your request will be rejected.

Step 2: Design Your Compute + Execute Pair

Think in two steps:

  1. What do I need to read? — This is your compute spec. It's a staticcall against live mid-block state. Any view function works.

  2. What do I need to execute? — This is your execute spec. The builder signs and submits this transaction using the compute result as input.

Example: Read a user's token balance, then transfer exactly that amount.

Step 3: Validate with bex_simulate

Before submitting for real, use bex_simulate to catch validation issues:

If accepted: true, you're good to submit. If accepted: false, fix the issues before proceeding.

Step 4: Submit

The response includes a deterministic bundleHash — same inputs always produce the same hash. Use it to track inclusion via eureka_getBundleStats.

Step 5: Updating Before the Block

To update your BEX request before the target block is built, use replacementUuid:

Resubmit the same UUID with updated fields to replace the previous request. Requires X-Flashbots-Signature.

To cancel without replacing:

Calldata Encoding Reference

The final on-chain calldata is assembled as:

All arguments must be ABI-encoded. prefixArgs and the compute return data are concatenated raw — there is no additional ABI wrapping between them.

Example with two fixed args and one dynamic arg from compute:

Tips

  • Use bex_simulate whenever you change your compute/execute spec — the bundleHash it returns will match what bex_sendBundle returns, so you can pre-compute it.

  • Requests expire after 60 seconds even if the target block hasn't been reached. Resubmit if your strategy is long-running.

  • The compute step is a staticcall — it cannot write state or emit events. Pure read operations only.

  • The execute transaction is signed by the builder's coinbase key, not yours. Your contract must be designed to accept calls from that address.

Last updated