Skip to content

Commit

Permalink
feat: builder submission bidtraces endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
merklefruit committed Nov 14, 2023
1 parent 8c51b74 commit 319b660
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 6 deletions.
5 changes: 5 additions & 0 deletions crates/mevboost-relay-api/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,9 @@ lazy_static! {
///
/// [Visit the docs](https://flashbots.github.io/relay-specs/#/Data/getDeliveredPayloads) for more info.
pub static ref GET_DELIVERED_PAYLOADS: &'static str = "/relay/v1/data/bidtraces/proposer_payload_delivered";

/// Relay endpoint for getting the block submission bids delivered to the relay.
///
/// [Visit the docs](https://flashbots.github.io/relay-specs/#/Data/getReceivedBids) for more info.
pub static ref GET_BUILDER_BLOCKS_RECEIVED: &'static str = "/relay/v1/data/bidtraces/builder_blocks_received";
}
44 changes: 41 additions & 3 deletions crates/mevboost-relay-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,13 @@ impl<'a> Client<'a> {
.map_err(|e| anyhow::anyhow!("Failed to parse JSON response: {}", e))
}

/// Perform a relay query to get the
/// Perform a relay query to get the payloads delivered by the relay to the proposer.
/// Query options act as filters.
pub async fn get_payload_delivered_bidtraces(
&self,
relay_name: &str,
opts: types::PayloadDeliveredQueryOptions,
) -> anyhow::Result<Vec<types::DeliveredPayloadBidtrace>> {
) -> anyhow::Result<Vec<types::PayloadBidtrace>> {
let relay_url = self.get_relay_url(relay_name)?;
let endpoint = format!(
"{}{}{}",
Expand All @@ -102,7 +103,27 @@ impl<'a> Client<'a> {
);
let response = self.fetch(endpoint).await?;

serde_json::from_str::<Vec<types::DeliveredPayloadBidtrace>>(&response)
serde_json::from_str::<Vec<types::PayloadBidtrace>>(&response)
.map_err(|e| anyhow::anyhow!("Failed to parse JSON response: {}", e))
}

/// Perform a relay query to get the builder bid submissions.
/// Query options act as filters.
pub async fn get_builder_blocks_received(
&self,
relay_name: &str,
opts: types::BuilderBidsReceivedOptions,
) -> anyhow::Result<Vec<types::BuilderBlockBidtrace>> {
let relay_url = self.get_relay_url(relay_name)?;
let endpoint = format!(
"{}{}{}",
relay_url,
*constants::GET_BUILDER_BLOCKS_RECEIVED,
opts.to_string()
);
let response = self.fetch(endpoint).await?;

serde_json::from_str::<Vec<types::BuilderBlockBidtrace>>(&response)
.map_err(|e| anyhow::anyhow!("Failed to parse JSON response: {}", e))
}

Expand Down Expand Up @@ -282,4 +303,21 @@ mod tests {
assert!(!response.is_empty());
Ok(())
}

#[tokio::test]
async fn test_get_builder_blocks_received() -> anyhow::Result<()> {
let client = super::Client::default();
let opts = super::types::BuilderBidsReceivedOptions {
slot: Some(7761220),
..Default::default()
};

let response = client
.get_builder_blocks_received("ultrasound", opts)
.await?;

dbg!(&response);
assert!(!response.is_empty());
Ok(())
}
}
57 changes: 54 additions & 3 deletions crates/mevboost-relay-api/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ pub struct PayloadDeliveredQueryOptions {
pub slot: Option<u64>,
/// A starting slot for multiple results.
pub cursor: Option<u64>,
/// The number of results
/// The number of results.
pub limit: Option<u64>,
/// A block hash.
pub block_hash: Option<String>,
Expand All @@ -49,7 +49,7 @@ pub struct PayloadDeliveredQueryOptions {
pub proposer_pubkey: Option<String>,
/// A specific builder public key.
pub builder_pubkey: Option<String>,
/// Sort results in order of: `value` or `-value`
/// Sort results in order of: `value` or `-value`.
pub order_by: Option<String>,
}

Expand Down Expand Up @@ -90,7 +90,7 @@ impl ToString for PayloadDeliveredQueryOptions {
/// Entry for the validator payload delivered response.
#[derive(Deserialize, Debug)]
#[allow(missing_docs)]
pub struct DeliveredPayloadBidtrace {
pub struct PayloadBidtrace {
#[serde(deserialize_with = "deserialize_number_from_string")]
pub slot: u64,
pub parent_hash: String,
Expand All @@ -108,3 +108,54 @@ pub struct DeliveredPayloadBidtrace {
#[serde(deserialize_with = "deserialize_number_from_string")]
pub block_number: u64,
}

/// Filter arguments for the get builder blocks bidtraces relay query
#[derive(Debug, Default)]
pub struct BuilderBidsReceivedOptions {
/// A specific slot number.
pub slot: Option<u64>,
/// A block hash.
pub block_hash: Option<String>,
/// A specific block number.
pub block_number: Option<u64>,
/// A specific builder public key.
pub builder_pubkey: Option<String>,
/// The number of results.
pub limit: Option<u64>,
}

impl ToString for BuilderBidsReceivedOptions {
fn to_string(&self) -> String {
let mut query = String::new();
query.push('?');

if let Some(slot) = self.slot {
query.push_str(&format!("slot={}&", slot));
}
if let Some(block_hash) = &self.block_hash {
query.push_str(&format!("block_hash={}&", block_hash));
}
if let Some(block_number) = self.block_number {
query.push_str(&format!("block_number={}&", block_number));
}
if let Some(builder_pubkey) = &self.builder_pubkey {
query.push_str(&format!("builder_pubkey={}&", builder_pubkey));
}
if let Some(limit) = self.limit {
query.push_str(&format!("limit={}&", limit));
}

query
}
}

/// Entry for the builder block bidtrace response.
#[derive(Deserialize, Debug)]
#[allow(missing_docs)]
pub struct BuilderBlockBidtrace {
#[serde(flatten)]
pub payload: PayloadBidtrace,
#[serde(deserialize_with = "deserialize_datetime_utc_from_milliseconds")]
pub timestamp_ms: DateTime<Utc>,
pub optimistic_submission: Option<bool>,
}

0 comments on commit 319b660

Please sign in to comment.