@@ -8,11 +8,14 @@ use crate::{
88 simulation:: {
99 errors:: { SimulationError , TransitionError } ,
1010 indicatively_priced:: IndicativelyPriced ,
11+ swap:: {
12+ self , LimitsParams , MarginalPriceParams , QuoteParams , SwapQuoter , TransitionParams ,
13+ } ,
1114 } ,
1215 Bytes ,
1316} ;
1417
15- #[ derive( Default ) ]
18+ #[ derive( Default , Debug , Clone ) ]
1619pub struct Balances {
1720 pub component_balances : HashMap < String , HashMap < Bytes , Bytes > > ,
1821 pub account_balances : HashMap < Bytes , HashMap < Bytes , Bytes > > ,
@@ -347,7 +350,7 @@ pub trait ProtocolSim: fmt::Debug + Send + Sync + 'static {
347350 delta : ProtocolStateDelta ,
348351 tokens : & HashMap < Bytes , Token > ,
349352 balances : & Balances ,
350- ) -> Result < ( ) , TransitionError < String > > ;
353+ ) -> Result < ( ) , TransitionError > ;
351354
352355 /// Calculates the swap volume required to achieve the provided goal when trading against this
353356 /// pool.
@@ -403,6 +406,149 @@ impl Clone for Box<dyn ProtocolSim> {
403406 }
404407}
405408
409+ impl < T > ProtocolSim for T
410+ where
411+ T : SwapQuoter + Clone + Send + Sync + Eq + ' static ,
412+ {
413+ fn fee ( & self ) -> f64 {
414+ self . quotable_pairs ( )
415+ . iter ( )
416+ . map ( |( t0, t1) | {
417+ let amount = BigUint :: from ( 10u32 ) . pow ( t0. decimals ) ;
418+ if let Ok ( params) = QuoteParams :: fixed_in ( & t0. address , & t1. address , amount) {
419+ self . fee ( params)
420+ . map ( |f| f. fee ( ) )
421+ . unwrap_or ( f64:: MAX )
422+ } else {
423+ f64:: MAX
424+ }
425+ } )
426+ . reduce ( f64:: min)
427+ . unwrap_or ( f64:: MAX )
428+ }
429+
430+ fn spot_price ( & self , base : & Token , quote : & Token ) -> Result < f64 , SimulationError > {
431+ self . marginal_price ( MarginalPriceParams :: new ( & base. address , & quote. address ) )
432+ . map ( |r| r. price ( ) )
433+ }
434+
435+ fn get_amount_out (
436+ & self ,
437+ amount_in : BigUint ,
438+ token_in : & Token ,
439+ token_out : & Token ,
440+ ) -> Result < GetAmountOutResult , SimulationError > {
441+ #[ allow( deprecated) ]
442+ self . quote (
443+ QuoteParams :: fixed_in ( & token_in. address , & token_out. address , amount_in) ?
444+ . with_new_state ( ) ,
445+ )
446+ . map ( |r| {
447+ GetAmountOutResult :: new (
448+ r. amount_out ( ) . clone ( ) ,
449+ r. gas ( ) . clone ( ) ,
450+ r. new_state ( )
451+ . expect ( "quote includes new state" )
452+ . to_protocol_sim ( ) ,
453+ )
454+ } )
455+ }
456+
457+ fn get_limits (
458+ & self ,
459+ sell_token : Bytes ,
460+ buy_token : Bytes ,
461+ ) -> Result < ( BigUint , BigUint ) , SimulationError > {
462+ self . swap_limits ( LimitsParams :: new ( & sell_token, & buy_token) )
463+ . map ( |r| ( r. range_in ( ) . upper ( ) . clone ( ) , r. range_out ( ) . upper ( ) . clone ( ) ) )
464+ }
465+
466+ fn delta_transition (
467+ & mut self ,
468+ delta : ProtocolStateDelta ,
469+ tokens : & HashMap < Bytes , Token > ,
470+ balances : & Balances ,
471+ ) -> Result < ( ) , TransitionError > {
472+ self . delta_transition ( TransitionParams :: new ( delta, tokens, balances) )
473+ . map ( |_| ( ) )
474+ }
475+
476+ fn query_pool_swap ( & self , params : & QueryPoolSwapParams ) -> Result < PoolSwap , SimulationError > {
477+ let constraint = match params. swap_constraint . clone ( ) {
478+ SwapConstraint :: TradeLimitPrice { limit, tolerance, min_amount_in, max_amount_in } => {
479+ swap:: SwapConstraint :: TradeLimitPrice {
480+ limit,
481+ tolerance,
482+ min_amount_in,
483+ max_amount_in,
484+ }
485+ }
486+ SwapConstraint :: PoolTargetPrice { target, tolerance, min_amount_in, max_amount_in } => {
487+ swap:: SwapConstraint :: PoolTargetPrice {
488+ target,
489+ tolerance,
490+ min_amount_in,
491+ max_amount_in,
492+ }
493+ }
494+ } ;
495+ #[ allow( deprecated) ]
496+ self . query_swap ( swap:: QuerySwapParams :: new (
497+ & params. token_in . address ,
498+ & params. token_out . address ,
499+ constraint,
500+ ) )
501+ . map ( |r| {
502+ PoolSwap :: new (
503+ r. amount_in ( ) . clone ( ) ,
504+ r. amount_out ( ) . clone ( ) ,
505+ r. new_state ( ) . unwrap ( ) . to_protocol_sim ( ) ,
506+ r. price_points ( ) . as_ref ( ) . map ( |points| {
507+ points
508+ . iter ( )
509+ . map ( |p| {
510+ PricePoint :: new (
511+ p. amount_in ( ) . clone ( ) ,
512+ p. amount_out ( ) . clone ( ) ,
513+ p. price ( ) ,
514+ )
515+ } )
516+ . collect ( )
517+ } ) ,
518+ )
519+ } )
520+ }
521+
522+ fn clone_box ( & self ) -> Box < dyn ProtocolSim > {
523+ #[ allow( deprecated) ]
524+ self . to_protocol_sim ( )
525+ }
526+
527+ fn as_any ( & self ) -> & dyn Any {
528+ self
529+ }
530+
531+ fn as_any_mut ( & mut self ) -> & mut dyn Any {
532+ self
533+ }
534+
535+ fn eq ( & self , other : & dyn ProtocolSim ) -> bool {
536+ if let Some ( other) = other. as_any ( ) . downcast_ref :: < T > ( ) {
537+ self == other
538+ } else {
539+ false
540+ }
541+ }
542+
543+ fn typetag_name ( & self ) -> & ' static str {
544+ self . typetag_name ( )
545+ }
546+
547+ fn typetag_deserialize ( & self ) {
548+ self . typetag_deserialize ( )
549+ }
550+ }
551+
406552#[ cfg( test) ]
407553mod tests {
408554
@@ -466,7 +612,7 @@ mod tests {
466612 _delta : ProtocolStateDelta ,
467613 _tokens : & HashMap < Bytes , Token > ,
468614 _balances : & Balances ,
469- ) -> Result < ( ) , TransitionError < String > > {
615+ ) -> Result < ( ) , TransitionError > {
470616 todo ! ( )
471617 }
472618 }
0 commit comments