-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
dev(better_theoros): supports N datafeeds + returns N calldata
!
- Loading branch information
Showing
5 changed files
with
168 additions
and
134 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,66 +1,89 @@ | ||
use std::str::FromStr; | ||
|
||
use alloy::hex; | ||
use axum::extract::{Query, State}; | ||
use axum::Json; | ||
use axum::{ | ||
extract::{Query, State}, | ||
Json, | ||
}; | ||
use serde::{Deserialize, Serialize}; | ||
use utoipa::{IntoParams, ToResponse, ToSchema}; | ||
|
||
use crate::configs::evm_config::EvmChainName; | ||
use crate::errors::GetCalldataError; | ||
use crate::extractors::PathExtractor; | ||
use crate::types::calldata::{AsCalldata, Calldata}; | ||
use crate::AppState; | ||
use crate::{ | ||
configs::evm_config::EvmChainName, | ||
errors::GetCalldataError, | ||
types::calldata::{AsCalldata, Calldata}, | ||
AppState, | ||
}; | ||
|
||
#[derive(Default, Deserialize, IntoParams, ToSchema)] | ||
pub struct GetCalldataQuery {} | ||
#[derive(Deserialize, IntoParams, ToSchema)] | ||
pub struct GetCalldataQuery { | ||
pub chain: String, | ||
#[serde(deserialize_with = "deserialize_feed_ids")] | ||
pub feed_ids: Vec<String>, | ||
} | ||
|
||
#[derive(Debug, Serialize, Deserialize, ToResponse, ToSchema)] | ||
pub struct GetCalldataResponse { | ||
pub calldata: Calldata, | ||
pub feed_id: String, | ||
pub encoded_calldata: String, | ||
} | ||
|
||
#[utoipa::path( | ||
get, | ||
path = "/v1/calldata/{chain_name}/{feed_id}", | ||
path = "/v1/calldata", | ||
params( | ||
GetCalldataQuery | ||
), | ||
responses( | ||
( | ||
status = 200, | ||
description = "Constructs the calldata used to update the feed id specified", | ||
description = "Constructs the calldata used to update the specified feed IDs", | ||
body = [GetCalldataResponse] | ||
), | ||
( | ||
status = 404, | ||
description = "Unknown Feed Id", | ||
body = [GetCalldataError] | ||
description = "Unknown Feed ID", | ||
body = GetCalldataError | ||
) | ||
), | ||
params( | ||
GetCalldataQuery | ||
), | ||
)] | ||
pub async fn get_calldata( | ||
State(state): State<AppState>, | ||
PathExtractor(path_args): PathExtractor<(String, String)>, | ||
Query(_params): Query<GetCalldataQuery>, | ||
) -> Result<Json<GetCalldataResponse>, GetCalldataError> { | ||
Query(params): Query<GetCalldataQuery>, | ||
) -> Result<Json<Vec<GetCalldataResponse>>, GetCalldataError> { | ||
let started_at = std::time::Instant::now(); | ||
let (raw_chain_name, feed_id) = path_args; | ||
let chain_name = EvmChainName::from_str(&raw_chain_name) | ||
.map_err(|_| GetCalldataError::ChainNotSupported(raw_chain_name.clone()))?; | ||
|
||
let chain_name = | ||
EvmChainName::from_str(¶ms.chain).map_err(|_| GetCalldataError::ChainNotSupported(params.chain.clone()))?; | ||
|
||
let stored_feed_ids = state.storage.feed_ids(); | ||
if !stored_feed_ids.contains(&feed_id).await { | ||
return Err(GetCalldataError::FeedNotFound(feed_id)); | ||
}; | ||
|
||
let calldata = Calldata::build_from(&state, chain_name, feed_id) | ||
.await | ||
.map_err(|e| GetCalldataError::CalldataError(e.to_string()))?; | ||
// Check if all requested feed IDs are supported. | ||
if let Some(missing_id) = stored_feed_ids.contains_vec(¶ms.feed_ids).await { | ||
return Err(GetCalldataError::FeedNotFound(missing_id)); | ||
} | ||
|
||
// Build calldata for each feed ID. | ||
let mut responses = Vec::with_capacity(params.feed_ids.len()); | ||
for feed_id in ¶ms.feed_ids { | ||
let calldata = Calldata::build_from(&state, chain_name, feed_id.clone()) | ||
.await | ||
.map_err(|e| GetCalldataError::CalldataError(e.to_string()))?; | ||
|
||
let response = | ||
GetCalldataResponse { feed_id: feed_id.clone(), encoded_calldata: hex::encode(calldata.as_bytes()) }; | ||
responses.push(response); | ||
} | ||
|
||
let response = | ||
GetCalldataResponse { calldata: calldata.clone(), encoded_calldata: hex::encode(calldata.as_bytes()) }; | ||
tracing::info!("🌐 get_calldata - {:?}", started_at.elapsed()); | ||
Ok(Json(response)) | ||
Ok(Json(responses)) | ||
} | ||
|
||
/// Deserialize a list of feed ids "A, B, C" into a Vec<String> = [A, B, C]. | ||
fn deserialize_feed_ids<'de, D>(deserializer: D) -> Result<Vec<String>, D::Error> | ||
where | ||
D: serde::Deserializer<'de>, | ||
{ | ||
let s: String = String::deserialize(deserializer)?; | ||
Ok(s.split(',').map(|s| s.trim().to_string()).collect()) | ||
} |
Oops, something went wrong.