Integration Guide

Step 1: Design Your Bundle

Your bundle must contain three logical parts:

  1. The borrow([(tokenAaddress, tokenAAmount),(tokenBaddress, tokenBAmount)...]) call to the Eureka Router.

  2. Your strategy transactions — liquidations, arbitrage, or any logic that uses the borrowed tokens.

  3. Don't forget to add approve(routerAddress, loanAmount) for the next step not to revert.

  4. A repay() call to the Eureka Router — must come after your strategy and before the bundle ends.

Step 2: Construct and Submit the Bundle

Encode your strategy transactions and submit via eth_sendBundle:

import requests
from eth_account import Account

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

def send_loan_bundle(signed_txs: list[str], block_number: int, private_key: str):
    """
    signed_txs should contain, in order:
      1. borrow() call
      2. your strategy transactions
      3. approve() calls for repayment
      4. repay() call
    """
    body = {
        "jsonrpc": "2.0",
        "method": "eth_sendBundle",
        "params": [{
            "txs": signed_txs,
            "blockNumber": hex(block_number),
        }],
        "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()

send_loan_bundle(
    signed_txs=[
        "0x<signed borrow() call>",
        "0x<signed strategy txs>",
        "0x<signed approve txs>",
        "0x<signed repay() call>",
    ],
    block_number=20_400_000,
    private_key=private_key,
)

The builder automatically injects the allow() transaction before your borrow() call — you do not need to include it.

Step 3: Verify Inclusion

Use eureka_getBundleStats with the returned bundleHash to check whether the bundle was included:

If the bundle was rejected due to a failed repayment check, the error field will contain a PluginRejection message.

Common Rejection Reasons

Reason
Cause
Fix

missing repay transaction

No repay() call found in the bundle

Add a repay() call after your strategy

Any TX reverts

On reverting TX the bundle is dropped

Ensure all TXs can succeed

Using consumed nonce

Ethers/Viem only "know" your last nonce

Increment the TX nonces in your script

Borrow amount unavailable

Your borrow TX will fail

Make sure your amount is below or equals the loan funds

Tips

  • Borrow only what you need. If you ask for an amount exceeding the contract's funds, your bundle will revert.

  • If your strategy uses multiple tokens, pass all of them in a single borrow() call as an array of (token, amount) pairs. Only one borrow call per bundle is supported.

Examples

Last updated