Skip to main content

API Interface

Echo supports the same API interface as the Flashbots RPC, with additional features which are defined below.

The Echo API is available in both HTTP and Websocket flavors:

  • The HTTP API entrypoint is https://v1.echo-rpc.io/.
  • The Websocket API entrypoint is wss://v1.echo-rpc.io/ws.

Authentication


Echo uses the same authentication mechanism as Fiber. To use the API, you must specify a valid API key in the x-api-key header of your request. You can obtain a free API key by reaching out to us at admin@chainbound.io or by joining our Discord and opening a ticket.

You can test the authentication from your terminal as follows:

# HTTP
curl https://v1.echo-rpc.io -X POST -H "x-api-key: <YOUR_API_KEY>" -H "Content-Type: application/json" -d '{"id":1,"jsonrpc":"2.0","method":"echo_status","params":[]}'
# Websocket
wscat -c wss://v1.echo-rpc.io/ws -H "x-api-key: <YOUR_API_KEY>" -x '{"id":1,"jsonrpc":"2.0","method":"echo_status","params":[]}

Flashbots Authentication


Additionally to an API key, you may also specify a Flashbots signature token in the x-flashbots-signature header of your HTTP requests. Echo will automatically forward the signature to the builders that support it, so that you can focus on your strategies and not worry about the details of each builder's API. For more details on the Flashbots signature, please refer to the Flashbots documentation.

info

If you are using Echo via Websocket, you have to specify this field in the message body instead. This is done by encapsulating your existing request (the entire JSON-RPC object) in a new JSON object, with the x-flashbots-signature field as a sibling of the payload field. Here is an example:

{
"x-flashbots-signature": "0x...:0x...",
"payload": {
"id": 1,
"jsonrpc": "2.0",
"method": "eth_sendBundle",
"params": [
{
"txs": ["0x..."],
"blockNumber": "0x1234"
}
]
}
}

Available Methods


eth_sendBundle


Users can send bundles via the eth_sendBundle method with this interface:

{
"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 (in seconds) for which this bundle is valid
maxTimestamp, // (Optional) Number, the maximum timestamp (in seconds) for which this bundle is valid
revertingTxHashes, // (Optional) Array[String], A list of tx hashes that are allowed to revert
replacementUuid, // (Optional) String, UUIDv4 that can be used to cancel/replace this bundle
refundPercent, // (Optional) Number, the percentage (from 0 to 100) 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
mevBuilders, // (Optional) Array[String], A list of mev builders to send this bundle to.
// If not specified, the bundle will be sent to all available builders
usePublicMempool, // (Optional) Boolean, If true, the bundle will also be propagated to the public mempool
// through Fiber's internal network. Defaults to false.
// WARNING: Using this flag will void the privacy guarantees of the bundle, making it
// frontrunnable by MEV searchers.
awaitBuilderResponses, // (Optional) Boolean, If true, the HTTP request will hang until all builders have
// responded, and the result will contain a `builderResponses` field. Defaults to false.
awaitReceipt, // (Optional) Boolean, If true, the HTTP request will hang until the bundle is either
// included in a block, or the specified timeout is reached. Defaults to false.
awaitReceiptTimeoutMs, // (Optional) Number, The timeout (in milliseconds) for the awaitReceipt flag.
// Defaults to 30000 (30 seconds) if not specified and awaitReceipt is true.
retryUntil, // (Optional) String, a hex encoded block number until which the bundle should be retried
// with the same parameters if it is not included in the target block.
}
]
}
danger

The usePublicMempool flag will void the privacy guarantees of the bundle, making it frontrunnable by anyone else, including other MEV searchers. Use it only to send bundles that are not vulnerable to frontrunning.

info

The awaitBuilderResponses flag can be very useful during testing & debugging, as it allows you to see the response from each builder. If for some reason some builders are returning an error, you can easily identify them and fix the issue. It's recommended to set this flag to false in production, as it will slow down the API response time significantly.

Successful response

Here is the successful response format that you can expect from the API:

{
"jsonrpc": "2.0",
"id": "123",
"result": {
bundleHash, // String, a unique 256-bit bundle identifier, based its payload.
receiptNotification, // (Optional) object containing the on-chain receipt of the bundle.
// This field will only be present if you specified the `awaitReceipt` flag
// in the request.
builderResponses, // (Optional) object containing the various builder responses as a key-value map,
// with the key being the builder name, and the value being the response from that builder.
// This field will only be present if you specified the `awaitBuilderResponses` flag
// in the request.
}
}

Bundle Receipt Notification

If you set the awaitReceipt flag to true in the request params, the response will also include the receiptNotification field, which will be one of the following:

{
// ...,
"receiptNotification": {
status: "included" | "timedOut", // "included" if the bundle was included in a block, "timedOut" if the
// "awaitReceiptTimeoutMs" (default: 30s) was reached without inclusion.
data: {
blockNumber, // Number, the block number in which the bundle was included. Only present if status == "included"
elapsedMs // Number, the time (in milliseconds) since the bundle was submitted. Always present.
}
}
}

eth_cancelBundle


Echo allows users to cancel pending bundles by submitting a cancellation request via the eth_cancelBundle method:

{
"jsonrpc": "2.0",
"id": 1,
"method": "eth_cancelBundle",
"params": [
{
replacementUuid, // UUIDv4 to uniquely identify submission
mevBuilders // (Optional) Array[String], A list of mev builders to send the cancel request to.
// If not specified, the cancelBundle request will be sent only to the builders
// that were originally specified when the bundle was submitted with `eth_sendBundle`
}
]
}
note

The replacementUuid field must have been set when the bundle was originally submitted with eth_sendBundle.

danger

You cannot specify a replacementUuid together with the usePublicMempool flag, as transactions sent to the public mempool can always be included by anyone.

Successful response

{
"jsonrpc": "2.0",
"id": "123",
"result": true // Boolean, true if the cancellation request was successfully sent to block builders
}

eth_sendPrivateRawTransaction


Echo allows users to send private transactions via the eth_sendPrivateRawTransaction method:

{
"jsonrpc": "2.0",
"id": 1,
"method": "eth_sendPrivateRawTransaction",
"params": [
{
tx, // String, the signed private transaction to execute
mevBuilders, // (Optional) Array[String], A list of mev builders to send this transaction to.
// If not specified, the transaction will be sent to all available builders that
// support receiving private transactions.
// If "mevBuilders":["none"] and "usePublicMempool":true transactions will ONLY be
// sent via mempool thorugh Fiber's internal network.
awaitReceipt, // (Optional) Boolean, If true, the HTTP request will hang until the transaction is either
// included in a block, or the specified timeout is reached. Defaults to false.
awaitReceiptTimeoutMs, // (Optional) Number, The timeout (in milliseconds) for the awaitReceipt flag.
// Defaults to 30000 (30 seconds) if not specified and awaitReceipt is true.
usePublicMempool, // (Optional) Boolean, If true, the transaction will be propagated to the public mempool
// through Fiber's internal network. Defaults to false.
// WARNING: Using this flag will void the privacy guarantees of the transactions, making it
// frontrunnable by MEV searchers.
sendAsBundle, // (Optional) Boolean, If true, the transaction will be sent as a bundle to the builders.
// This option can significantly speed up on-chain inclusion. Defaults to false.
retryUntil, // (Optional) String, a hex encoded block number until which the transaction should be retried
// with the same parameters if it is not included in the target block. Only valid if
// `sendAsBundle` is set to true. Default to current block number + 25.
}
]
}
info

You can also omit the params object in the request and just include the signed transaction as a hex string like so:

{
"jsonrpc": "2.0",
"id": 1,
"method": "eth_sendPrivateRawTransaction",
"params": [
"0x..." // String, the signed private transaction to execute
]
}

In this case, the transaction will be forwarded to all available builders that support receiving private transactions.

Successful response

Here is the successful response format that you can expect from the API:

{
"jsonrpc": "2.0",
"id": "123",
"result": {
txHash, // String, the transaction hash of the private transaction.
receiptNotification, // (Optional) object containing the on-chain receipt of the transaction.
// This field will only be present if you specified the `awaitReceipt` flag
// in the request. See below for more details.
bundleHash, // (Optional) String, a unique bundle identifier, based on the payload.
// This field will only be present if you specified the `sendAsBundle` flag
// as true in the request. It can be used for analytics purposes.
replacementUuid, // (Optional) String, UUIDv4 that can be used to cancel/replace this transaction.
// This field will only be present if you specified the `sendAsBundle` flag
// as true in the request.
}
}

Transaction Receipt Notification

If you set the awaitReceipt flag to true in the request params, the response will also include the receiptNotification field, which will be one of the following:

{
// ...,
"receiptNotification": {
status: "included" | "timedOut", // "included" if the transaction was included in a block, "timedOut" if the
// "awaitReceiptTimeoutMs" (default: 60s) was reached without inclusion.
data: {
blockNumber, // Number, the block number in which the transaction was included. Only present if status == "included"
elapsedMs // Number, the time (in milliseconds) since the bundle was submitted. Always present.
}
}
}

echo_status


This endpoint can be used to fetch information about the status of the Echo API. This is mainly useful for testing your API key and connectivity.

{
"jsonrpc": "2.0",
"id": 1,
"method": "echo_status",
"params": [
{} // Empty object
]
}

Successful response

{
"jsonrpc": "2.0",
"id": "1",
"result": "online"
}