Skip to content

Commit

Permalink
Use NativePriceEstimating version of RacingEstimating in factory (#1883)
Browse files Browse the repository at this point in the history
Now that we have a RacingPriceEstimator that can deal with
`NativePriceEstimating`, we can change the factory to instead of being:

`Native(Sanitized(Competition(inner))`

to

`Competition(inner)`

Since currently all inner are still general purpose `PriceEstimating`
implementations, nothing much changes (each inner becomes a
`Native(Sanitized)`, but this allows for new types of estimators that
only implement the `NativePriceEstimating` trait.

It also makes it so that price estimates only require n (by default 2)
solutions in order to return a price (we used to wait for all estimators
before)
  • Loading branch information
fleupold authored Sep 21, 2023
1 parent 013dfc8 commit daa9f72
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 28 deletions.
7 changes: 7 additions & 0 deletions crates/autopilot/src/arguments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,13 @@ pub struct Arguments {
#[clap(long, env, default_value_t)]
pub native_price_estimators: PriceEstimators,

/// How many successful price estimates for each order will cause a native
/// price estimation to return its result early. It's possible to pass
/// values greater than the total number of enabled estimators but that
/// will not have any further effect.
#[clap(long, env, default_value = "2")]
pub native_price_estimation_results_required: NonZeroUsize,

/// The minimum amount of time in seconds an order has to be valid for.
#[clap(
long,
Expand Down
13 changes: 8 additions & 5 deletions crates/autopilot/src/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -399,11 +399,14 @@ pub async fn run(args: Arguments) {
))
.unwrap();
let native_price_estimator = price_estimator_factory
.native_price_estimator(&PriceEstimatorSource::for_args(
args.native_price_estimators.as_slice(),
&args.order_quoting.price_estimation_drivers,
&args.order_quoting.price_estimation_legacy_solvers,
))
.native_price_estimator(
&PriceEstimatorSource::for_args(
args.native_price_estimators.as_slice(),
&args.order_quoting.price_estimation_drivers,
&args.order_quoting.price_estimation_legacy_solvers,
),
args.native_price_estimation_results_required,
)
.unwrap();

let skip_event_sync_start = if args.skip_event_sync {
Expand Down
2 changes: 1 addition & 1 deletion crates/orderbook/src/arguments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ pub struct Arguments {
pub native_price_estimators: PriceEstimators,

/// How many successful price estimates for each order will cause a fast
/// price estimation to return its result early.
/// or native price estimation to return its result early.
/// The bigger the value the more the fast price estimation performs like
/// the optimal price estimation.
/// It's possible to pass values greater than the total number of enabled
Expand Down
13 changes: 8 additions & 5 deletions crates/orderbook/src/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -399,11 +399,14 @@ pub async fn run(args: Arguments) {
)
.unwrap();
let native_price_estimator = price_estimator_factory
.native_price_estimator(&PriceEstimatorSource::for_args(
args.native_price_estimators.as_slice(),
&args.order_quoting.price_estimation_drivers,
&args.order_quoting.price_estimation_legacy_solvers,
))
.native_price_estimator(
&PriceEstimatorSource::for_args(
args.native_price_estimators.as_slice(),
&args.order_quoting.price_estimation_drivers,
&args.order_quoting.price_estimation_legacy_solvers,
),
args.fast_price_estimation_results_required,
)
.unwrap();

let fee_subsidy = Arc::new(FeeSubsidyConfiguration {
Expand Down
39 changes: 26 additions & 13 deletions crates/shared/src/price_estimation/factory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ use {
http_solver::{DefaultHttpSolverApi, Objective, SolverConfig},
oneinch_api::OneInchClient,
paraswap_api::DefaultParaswapApi,
price_estimation::native::NativePriceEstimating,
rate_limiter::RateLimiter,
sources::{
balancer_v2::BalancerPoolFetching,
Expand Down Expand Up @@ -278,9 +279,9 @@ impl<'a> PriceEstimatorFactory<'a> {
.collect()
}

fn sanitized(&self, estimator: impl PriceEstimating) -> SanitizedPriceEstimator {
fn sanitized(&self, estimator: Arc<dyn PriceEstimating>) -> SanitizedPriceEstimator {
SanitizedPriceEstimator::new(
Box::new(estimator),
estimator,
self.network.native_token,
self.components.bad_token_detector.clone(),
)
Expand All @@ -292,7 +293,7 @@ impl<'a> PriceEstimatorFactory<'a> {
) -> Result<Arc<dyn PriceEstimating>> {
let estimators = self.get_estimators(sources, |entry| &entry.optimal)?;
let competition_estimator = CompetitionEstimator::new(estimators);
Ok(Arc::new(self.sanitized(competition_estimator)))
Ok(Arc::new(self.sanitized(Arc::new(competition_estimator))))
}

pub fn fast_price_estimator(
Expand All @@ -301,28 +302,40 @@ impl<'a> PriceEstimatorFactory<'a> {
fast_price_estimation_results_required: NonZeroUsize,
) -> Result<Arc<dyn PriceEstimating>> {
let estimators = self.get_estimators(sources, |entry| &entry.fast)?;
Ok(Arc::new(self.sanitized(RacingCompetitionEstimator::new(
estimators,
fast_price_estimation_results_required,
Ok(Arc::new(self.sanitized(Arc::new(
RacingCompetitionEstimator::new(estimators, fast_price_estimation_results_required),
))))
}

pub fn native_price_estimator(
&mut self,
sources: &[PriceEstimatorSource],
results_required: NonZeroUsize,
) -> Result<Arc<CachingNativePriceEstimator>> {
anyhow::ensure!(
self.args.native_price_cache_max_age_secs > self.args.native_price_prefetch_time_secs,
"price cache prefetch time needs to be less than price cache max age"
);
let estimators = self.get_estimators(sources, |entry| &entry.native)?;
let competition_estimator = CompetitionEstimator::new(estimators);
let native_token_price_estimation_amount = self.native_token_price_estimation_amount()?;
let estimators = self
.get_estimators(sources, |entry| &entry.native)?
.into_iter()
.map(
|(name, estimator)| -> (String, Arc<dyn NativePriceEstimating>) {
(
name,
Arc::new(NativePriceEstimator::new(
Arc::new(self.sanitized(estimator)),
self.network.native_token,
native_token_price_estimation_amount,
)),
)
},
)
.collect::<Vec<_>>();
let competition_estimator = RacingCompetitionEstimator::new(estimators, results_required);
let native_estimator = Arc::new(CachingNativePriceEstimator::new(
Box::new(NativePriceEstimator::new(
Arc::new(self.sanitized(competition_estimator)),
self.network.native_token,
self.native_token_price_estimation_amount()?,
)),
Box::new(competition_estimator),
self.args.native_price_cache_max_age_secs,
self.args.native_price_cache_refresh_secs,
Some(self.args.native_price_cache_max_update_size),
Expand Down
8 changes: 4 additions & 4 deletions crates/shared/src/price_estimation/sanitized.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@ use {
/// Verifies that buy and sell tokens are supported and handles
/// ETH as buy token appropriately.
pub struct SanitizedPriceEstimator {
inner: Box<dyn PriceEstimating>,
inner: Arc<dyn PriceEstimating>,
bad_token_detector: Arc<dyn BadTokenDetecting>,
native_token: H160,
}

impl SanitizedPriceEstimator {
pub fn new(
inner: Box<dyn PriceEstimating>,
inner: Arc<dyn PriceEstimating>,
native_token: H160,
bad_token_detector: Arc<dyn BadTokenDetecting>,
) -> Self {
Expand Down Expand Up @@ -344,7 +344,7 @@ mod tests {
..queries[3].0.clone()
};

let mut wrapped_estimator = Box::new(MockPriceEstimating::new());
let mut wrapped_estimator = MockPriceEstimating::new();
wrapped_estimator
.expect_estimate()
.times(1)
Expand Down Expand Up @@ -403,7 +403,7 @@ mod tests {
});

let sanitized_estimator = SanitizedPriceEstimator {
inner: wrapped_estimator,
inner: Arc::new(wrapped_estimator),
bad_token_detector: Arc::new(bad_token_detector),
native_token,
};
Expand Down

0 comments on commit daa9f72

Please sign in to comment.