MEV Bundle RPC Endpoint

Blocknative's MEV Bundle RPC Endpoint follows the standards of builders in the ecosystem to allow searchers to quickly start sending bundles to the Blocknative Builder.

How to interact directly with the Blocknative RPC endpoints

Searchers can interact with the RPC endpoints :
Mainnet: https://api.blocknative.com/v1/auction Goerli:https://api.blocknative.com/v1/auction?network=goerli
The API provides JSON-RPC methods for interfacing with Blocknative builders, which are documented below:

eth_sendBundle

To send your bundles to the Blocknative builders, you can use eth_sendBundle with the following payload format:
{
"jsonrpc": "2.0",
"id": 1,
"method": "eth_sendBundle",
"params": [
{
txs, // Array[String], A list of signed transactions to execute in an atomic bundle
blockNumber, // String, a hex encoded block number for which this bundle is valid on
minTimestamp, // (Optional) Number, the minimum timestamp for which this bundle is valid, in seconds since the unix epoch
maxTimestamp, // (Optional) Number, the maximum timestamp for which this bundle is valid, in seconds since the unix epoch
revertingTxHashes, // (Optional) Array[String], A list of tx hashes that are allowed to revert
uuid, // (Optional) String, a unique identifier of the bundle. This field can be used for bundle replacement and bundle cancellation
refundPercent, // (Optional) Number, the percentage (from 0 to 99) of the ETH reward of the last transaction, or the transaction specified by refundIndex, that should be refunded back to the ‘refundRecipient’
refundIndex, // (Optional) Number, the index of the transaction of which the ETH reward should be refunded. Default, last transaction in the bundle
refundRecipient, // (Optional) Address, the address that will receive the ETH refund. Default, sender of the first transaction in the bundle
}
]
}
In order to use eth_cancelBundle or bundle replacement the Uuid must be set when submitting the bundle
example request:
{
"jsonrpc": "2.0",
"id": 1,
"method": "eth_sendBundle",
"params": [
{
"txs": ["0x123abc...", "0x456def..."],
"blockNumber": "0xb63dcd",
"minTimestamp": 0,
"maxTimestamp": 1615920932
}
]
}
example response:
{
"jsonrpc": "2.0",
"id": "123",
"result": {
"bundleHash": "0x2228f5d8954ce31dc1601a8ba264dbd401bf1428388ce88238932815c5d6f23f"
}
}

Bundle Replacement

To replace a bundle, send the new bundle via eth_sendBundle with the same uuid as the bundle you want to replace. Your previous bundle will be canceled and replaced with the new bundle - this is faster than canceling and resubmitting.

eth_cancelBundle

To prevent a previously submitted bundle from being included on-chain eth_cancelBundle should be called with the UUID of the target bundle.
example request:
{
"jsonrpc": "2.0",
"id": 1,
"method": "eth_cancelBundle",
"params": [
{
uuid, // UUID of the previously submitted bundle
}
]
}
example response: The response is empty/null

eth_callBundle

To simulate a bundle against a specific block number, including simulating a bundle at the top of the next block, you can use eth_callBundle with the following payload format:
{
"jsonrpc": "2.0",
"id": 1,
"method": "eth_callBundle",
"params": [
{
txs, // Array[String], A list of signed transactions to execute in an atomic bundle
blockNumber, // String, a hex encoded block number for which this bundle is valid on
stateBlockNumber, // String, either a hex encoded number or a block tag for which state to base this simulation on. Can use "latest"
timestamp, // (Optional) Number, the timestamp to use for this bundle simulation, in seconds since the unix epoch
}
]
}
example request:
{
"jsonrpc": "2.0",
"id": 1,
"method": "eth_callBundle",
"params": [
{
"txs": ["0x123abc...", "0x456def..."],
"blockNumber": "0xb63dcd",
"stateBlockNumber": "latest",
"timestamp": 1615920932
}
]
}
example response:
{
"jsonrpc": "2.0",
"id": "123",
"result": {
"bundleGasPrice": "476190476193",
"bundleHash": "0x73b1e258c7a42fd0230b2fd05529c5d4b6fcb66c227783f8bece8aeacdd1db2e",
"coinbaseDiff": "20000000000126000",
"ethSentToCoinbase": "20000000000000000",
"gasFees": "126000",
"results": [
{
"coinbaseDiff": "10000000000063000",
"ethSentToCoinbase": "10000000000000000",
"fromAddress": "0x02A727155aeF8609c9f7F2179b2a1f560B39F5A0",
"gasFees": "63000",
"gasPrice": "476190476193",
"gasUsed": 21000,
"toAddress": "0x73625f59CAdc5009Cb458B751b3E7b6b48C06f2C",
"txHash": "0x669b4704a7d993a946cdd6e2f95233f308ce0c4649d2e04944e8299efcaa098a",
"value": "0x"
},
{
"coinbaseDiff": "10000000000063000",
"ethSentToCoinbase": "10000000000000000",
"fromAddress": "0x02A727155aeF8609c9f7F2179b2a1f560B39F5A0",
"gasFees": "63000",
"gasPrice": "476190476193",
"gasUsed": 21000,
"toAddress": "0x73625f59CAdc5009Cb458B751b3E7b6b48C06f2C",
"txHash": "0xa839ee83465657cac01adc1d50d96c1b586ed498120a84a64749c0034b4f19fa",
"value": "0x"
}
],
"stateBlockNumber": 5221585,
"totalGasUsed": 42000
}
}

Authentication

Payload signature

To authenticate your request, Blocknative endpoints require you to sign the payload and include the signed payload in the X-Flashbots-Signature or X-Auction-Signature header of your request:
Using X-Flashbots-Signature
curl -X POST -H "Content-Type: application/json" -H "X-Flashbots-Signature: 0x1234:0xabcd" --data '{"jsonrpc":"2.0","method":"eth_sendBundle","params":[{see above}],"id":1}' <https://api.blocknative.com/v1/auction>
Using X-Auction-Signature
curl -X POST -H "Content-Type: application/json" -H "X-Auction-Signature: 0x1234:0xabcd" --data '{"jsonrpc":"2.0","method":"eth_sendBundle","params":[{see above}],"id":1}' <https://api.blocknative.com/v1/auction>
Note: both X-Auction-Signature and x-auction-signature will work, this is case insensitive.
Any valid Ethereum key can be used to sign the payload. The Ethereum address associated with this key will be used by Blocknative to keep track of your requests over time and provide user statistics. You can change the key you use at any time.
The signature is calculated by taking the EIP-191 hash of the json body encoded as UTF-8 bytes.
Here's an example using ethers.js:
ether.js
web3.py
Go
import { Wallet, utils } from "ethers";
const privateKey = "0x1234";
const wallet = new Wallet(privateKey);
const body =
'{"jsonrpc":"2.0","method":"eth_sendBundle","params":[{see above}],"id":1}';
const signature = wallet.address + ":" + wallet.signMessage(utils.id(body));
from web3 import Web3
from eth_account import Account, messages
body = '{"jsonrpc":"2.0","method":"eth_sendBundle","params":[{see above}],"id":1}'
message = messages.encode_defunct(text=Web3.keccak(text=body).hex())
signature = Account.from_key(private_key).address + ':' + Account.sign_message(message, private_key).signature.hex()
body := `{"jsonrpc":"2.0","method":"eth_sendBundle","params":[{see above}],"id":1}`
hashedBody := crypto.Keccak256Hash([]byte(body)).Hex()
sig, err := crypto.Sign(accounts.TextHash([]byte(hashedBody)), privKey)
signature := crypto.PubkeyToAddress(privKey.PublicKey).Hex() + ":" + hexutil.Encode(sig)

Questions?

If you have questions about the Bundle RPC endpoint, join our Discord.