Skip to content

Commit

Permalink
Enforce timeout for DEX solver price estimators
Browse files Browse the repository at this point in the history
  • Loading branch information
fleupold committed Jan 3, 2024
1 parent 274881d commit bffb3cb
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 26 deletions.
2 changes: 1 addition & 1 deletion crates/driver/src/boundary/liquidity/zeroex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pub async fn collector(
http_timeout: config.http_timeout,
});
let api = Arc::new(DefaultZeroExApi::new(
http_client_factory,
http_client_factory.builder(),
config.base_url.clone(),
config.api_key.clone(),
blocks,
Expand Down
32 changes: 28 additions & 4 deletions crates/shared/src/price_estimation/factory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ use {
uniswap_v3::pool_fetching::PoolFetching as UniswapV3PoolFetching,
},
token_info::TokenInfoFetching,
trade_finding,
zeroex_api::DefaultZeroExApi,
},
anyhow::{anyhow, Context as _, Result},
Expand Down Expand Up @@ -443,7 +444,13 @@ impl PriceEstimatorCreating for ParaswapPriceEstimator {
fn init(factory: &PriceEstimatorFactory, name: &str, solver: Self::Params) -> Result<Self> {
Ok(ParaswapPriceEstimator::new(
Arc::new(DefaultParaswapApi {
client: factory.components.http_factory.create(),
client: factory.components.http_factory.configure(|builder| {
builder.timeout(
trade_finding::time_limit()
.to_std()
.expect("negative time limit"),
)
}),
base_url: factory.shared_args.paraswap_api_url.clone(),
partner: factory
.shared_args
Expand All @@ -467,8 +474,13 @@ impl PriceEstimatorCreating for ZeroExPriceEstimator {
type Params = H160;

fn init(factory: &PriceEstimatorFactory, name: &str, solver: Self::Params) -> Result<Self> {
let client_builder = factory.components.http_factory.builder().timeout(
trade_finding::time_limit()
.to_std()
.expect("negative time limit"),
);
let api = DefaultZeroExApi::new(
&factory.components.http_factory,
client_builder,
factory
.shared_args
.zeroex_url
Expand Down Expand Up @@ -498,7 +510,13 @@ impl PriceEstimatorCreating for OneInchPriceEstimator {
fn init(factory: &PriceEstimatorFactory, name: &str, solver: Self::Params) -> Result<Self> {
let api = OneInchClientImpl::new(
factory.shared_args.one_inch_url.clone(),
factory.components.http_factory.create(),
factory.components.http_factory.configure(|builder| {
builder.timeout(
trade_finding::time_limit()
.to_std()
.expect("negative time limit"),
)
}),
factory.network.chain_id,
factory.network.block_stream.clone(),
)
Expand All @@ -524,7 +542,13 @@ impl PriceEstimatorCreating for BalancerSor {
fn init(factory: &PriceEstimatorFactory, name: &str, solver: Self::Params) -> Result<Self> {
Ok(BalancerSor::new(
Arc::new(DefaultBalancerSorApi::new(
factory.components.http_factory.create(),
factory.components.http_factory.configure(|builder| {
builder.timeout(
trade_finding::time_limit()
.to_std()
.expect("negative time limit"),
)
}),
factory
.args
.balancer_sor_url
Expand Down
6 changes: 6 additions & 0 deletions crates/shared/src/trade_finding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ use {
thiserror::Error,
};

/// Returns the default time limit used for quoting with external co-located
/// solvers.
pub fn time_limit() -> chrono::Duration {
chrono::Duration::seconds(5)
}

/// Find a trade for a token pair.
///
/// This is similar to the `PriceEstimating` interface, but it expects calldata
Expand Down
8 changes: 1 addition & 7 deletions crates/shared/src/trade_finding/external.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ impl ExternalTradeFinder {
/// Queries the `/quote` endpoint of the configured driver and deserializes
/// the result into a Quote or Trade.
async fn shared_query(&self, query: &Query) -> Result<Trade, TradeError> {
let deadline = chrono::Utc::now() + Self::time_limit();
let deadline = chrono::Utc::now() + super::time_limit();
let order = dto::Order {
sell_token: query.sell_token,
buy_token: query.buy_token,
Expand Down Expand Up @@ -97,12 +97,6 @@ impl ExternalTradeFinder {
.await
.map_err(TradeError::from)
}

/// Returns the default time limit used for quoting with external co-located
/// solvers.
fn time_limit() -> chrono::Duration {
chrono::Duration::seconds(5)
}
}

impl From<dto::Quote> for Trade {
Expand Down
25 changes: 12 additions & 13 deletions crates/shared/src/zeroex_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
use {
crate::{
debug_bytes,
http_client::HttpClientFactory,
interaction::{EncodedInteraction, Interaction},
},
anyhow::{Context, Result},
Expand All @@ -19,6 +18,7 @@ use {
reqwest::{
header::{HeaderMap, HeaderValue},
Client,
ClientBuilder,
IntoUrl,
StatusCode,
Url,
Expand Down Expand Up @@ -375,26 +375,25 @@ impl DefaultZeroExApi {

/// Create a new 0x HTTP API client with the specified base URL.
pub fn new(
http_factory: &HttpClientFactory,
client_builder: ClientBuilder,
base_url: impl IntoUrl,
api_key: Option<String>,
block_stream: CurrentBlockStream,
) -> Result<Self> {
let client = match api_key {
Some(api_key) => {
let mut key = HeaderValue::from_str(&api_key)?;
key.set_sensitive(true);
let client_builder = if let Some(api_key) = api_key {
let mut key = HeaderValue::from_str(&api_key)?;
key.set_sensitive(true);

let mut headers = HeaderMap::new();
headers.insert("0x-api-key", key);
let mut headers = HeaderMap::new();
headers.insert("0x-api-key", key);

http_factory.configure(|builder| builder.default_headers(headers))
}
None => http_factory.create(),
client_builder.default_headers(headers)
} else {
client_builder
};

Ok(Self {
client,
client: client_builder.build().unwrap(),
base_url: base_url.into_url().context("zeroex api url")?,
block_stream,
})
Expand All @@ -408,7 +407,7 @@ impl DefaultZeroExApi {
pub fn test() -> Self {
let (_, block_stream) = watch::channel(BlockInfo::default());
Self::new(
&HttpClientFactory::default(),
Client::builder(),
std::env::var("ZEROEX_URL").unwrap_or_else(|_| Self::DEFAULT_URL.to_string()),
std::env::var("ZEROEX_API_KEY").ok(),
block_stream,
Expand Down
2 changes: 1 addition & 1 deletion crates/solver/src/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ pub async fn run(args: Arguments) {

let zeroex_api = Arc::new(
DefaultZeroExApi::new(
&http_factory,
http_factory.builder(),
args.shared
.zeroex_url
.as_deref()
Expand Down

0 comments on commit bffb3cb

Please sign in to comment.