@@ -79,13 +79,23 @@ fn extract_token_pairs_from_auction(
7979/// Converts a data transfer object into its domain object representation.
8080/// If liquidity_client is provided and auction has empty liquidity, fetches
8181/// independently.
82+ /// Returns the auction and optionally the fetched liquidity response.
8283pub async fn into_domain (
8384 auction : Auction ,
8485 liquidity_client : Option < & LiquidityClient > ,
8586 base_tokens : Option < & [ eth:: H160 ] > ,
8687 protocols : Option < & [ String ] > ,
87- ) -> Result < auction:: Auction , Error > {
88- Ok ( auction:: Auction {
88+ save_directory : Option < & std:: path:: Path > ,
89+ ) -> Result <
90+ (
91+ auction:: Auction ,
92+ Option < crate :: infra:: liquidity_client:: LiquidityResponse > ,
93+ ) ,
94+ Error ,
95+ > {
96+ let mut fetched_liquidity_response = None ;
97+
98+ let auction_domain = auction:: Auction {
8999 id : match auction. id {
90100 Some ( id) => auction:: Id :: Solve ( id) ,
91101 None => auction:: Id :: Quote ,
@@ -188,12 +198,29 @@ pub async fn into_domain(
188198 "Successfully fetched liquidity from API"
189199 ) ;
190200
201+ // Save liquidity to JSON if save_directory is provided
202+ if let Some ( save_dir) = save_directory {
203+ let liquidity_json = serde_json:: to_value ( & response) . ok ( ) ;
204+ let save_dir = save_dir. to_path_buf ( ) ;
205+ let auction_id = auction. id ;
206+ tokio:: spawn ( async move {
207+ if let Some ( liquidity) = liquidity_json {
208+ save_liquidity_json ( liquidity, auction_id, & save_dir) . await ;
209+ }
210+ } ) ;
211+ }
212+
191213 // Process the fetched liquidity
192- response
214+ let domain_liquidity = response
193215 . liquidity
194216 . iter ( )
195217 . map ( |liquidity| convert_dto_liquidity_to_domain ( liquidity) )
196- . try_collect ( ) ?
218+ . try_collect ( ) ?;
219+
220+ // Store the response for enhanced solutions
221+ fetched_liquidity_response = Some ( response) ;
222+
223+ domain_liquidity
197224 }
198225 Err ( e) => {
199226 tracing:: warn!(
@@ -215,7 +242,9 @@ pub async fn into_domain(
215242 } ,
216243 gas_price : auction:: GasPrice ( eth:: Ether ( auction. effective_gas_price ) ) ,
217244 deadline : auction:: Deadline ( auction. deadline ) ,
218- } )
245+ } ;
246+
247+ Ok ( ( auction_domain, fetched_liquidity_response) )
219248}
220249
221250/// Helper function to convert DTO liquidity to domain liquidity
@@ -238,6 +267,73 @@ fn convert_dto_liquidity_to_domain(liquidity: &Liquidity) -> Result<liquidity::L
238267 }
239268}
240269
270+ /// Saves fetched liquidity data to a JSON file in the configured directory.
271+ /// This function runs in a background task and logs errors without failing the
272+ /// request.
273+ async fn save_liquidity_json (
274+ liquidity : serde_json:: Value ,
275+ auction_id : Option < i64 > ,
276+ save_dir : & std:: path:: Path ,
277+ ) {
278+ use tokio:: fs;
279+
280+ // Determine filename based on auction ID
281+ let base_filename = match auction_id {
282+ Some ( id) => id. to_string ( ) ,
283+ None => {
284+ // Use timestamp for quote auctions
285+ let timestamp = chrono:: Utc :: now ( ) . format ( "%Y%m%d_%H%M%S_%3f" ) ;
286+ format ! ( "quote_{}" , timestamp)
287+ }
288+ } ;
289+
290+ let liquidity_file_path = save_dir. join ( format ! ( "{}_liquidity.json" , base_filename) ) ;
291+
292+ // Create directory if it doesn't exist
293+ if let Err ( err) = fs:: create_dir_all ( save_dir) . await {
294+ tracing:: warn!(
295+ ?err,
296+ directory = ?save_dir,
297+ "Failed to create liquidity save directory"
298+ ) ;
299+ return ;
300+ }
301+
302+ // Serialize liquidity to pretty JSON
303+ let liquidity_json = match serde_json:: to_string_pretty ( & liquidity) {
304+ Ok ( content) => content,
305+ Err ( err) => {
306+ tracing:: warn!( ?err, "Failed to serialize liquidity to JSON" ) ;
307+ return ;
308+ }
309+ } ;
310+
311+ let liquidity_count = liquidity
312+ . get ( "liquidity" )
313+ . and_then ( |l| l. as_array ( ) )
314+ . map ( |a| a. len ( ) )
315+ . unwrap_or ( 0 ) ;
316+
317+ // Write liquidity file
318+ match fs:: write ( & liquidity_file_path, liquidity_json) . await {
319+ Ok ( _) => {
320+ tracing:: info!(
321+ liquidity_file = ?liquidity_file_path,
322+ auction_id = ?auction_id,
323+ liquidity_count,
324+ "💾 Saved fetched liquidity to JSON file"
325+ ) ;
326+ }
327+ Err ( err) => {
328+ tracing:: warn!(
329+ ?err,
330+ file_path = ?liquidity_file_path,
331+ "Failed to write liquidity JSON file"
332+ ) ;
333+ }
334+ }
335+ }
336+
241337mod erc4626 {
242338 use super :: * ;
243339 pub fn to_domain ( edge : & Erc4626Edge ) -> Result < liquidity:: Liquidity , Error > {
@@ -301,6 +397,7 @@ mod weighted_product_pool {
301397 scale : conv:: decimal_to_rational ( & token. scaling_factor )
302398 . and_then ( liquidity:: ScalingFactor :: new)
303399 . ok_or ( "invalid token scaling factor" ) ?,
400+ rate : conv:: decimal_to_rational ( & token. rate ) . ok_or ( "invalid token rate" ) ?,
304401 } )
305402 } )
306403 . collect :: < Result < Vec < _ > , Error > > ( ) ?;
@@ -340,6 +437,7 @@ mod stable_pool {
340437 scale : conv:: decimal_to_rational ( & token. scaling_factor )
341438 . and_then ( liquidity:: ScalingFactor :: new)
342439 . ok_or ( "invalid token scaling factor" ) ?,
440+ rate : conv:: decimal_to_rational ( & token. rate ) . ok_or ( "invalid token rate" ) ?,
343441 } )
344442 } )
345443 . collect :: < Result < Vec < _ > , Error > > ( ) ?;
@@ -439,6 +537,7 @@ mod gyro_e_pool {
439537 scale : conv:: decimal_to_rational ( & token. scaling_factor )
440538 . and_then ( liquidity:: ScalingFactor :: new)
441539 . ok_or ( "invalid token scaling factor" ) ?,
540+ rate : conv:: decimal_to_rational ( & token. rate ) . ok_or ( "invalid token rate" ) ?,
442541 } )
443542 } )
444543 . collect :: < Result < Vec < _ > , Error > > ( ) ?;
@@ -502,6 +601,7 @@ mod gyro_2clp_pool {
502601 scale : conv:: decimal_to_rational ( & token. scaling_factor )
503602 . and_then ( liquidity:: ScalingFactor :: new)
504603 . ok_or ( "invalid token scaling factor" ) ?,
604+ rate : conv:: decimal_to_rational ( & token. rate ) . ok_or ( "invalid token rate" ) ?,
505605 } )
506606 } )
507607 . collect :: < Result < Vec < _ > , Error > > ( ) ?;
@@ -547,6 +647,7 @@ mod gyro_3clp_pool {
547647 . ok_or ( "invalid scaling factor" ) ?,
548648 )
549649 . ok_or ( "invalid scaling factor" ) ?,
650+ rate : conv:: decimal_to_rational ( & token. rate ) . ok_or ( "invalid token rate" ) ?,
550651 } )
551652 } )
552653 . collect :: < Result < Vec < _ > , Error > > ( ) ?;
@@ -585,6 +686,7 @@ mod reclamm_pool {
585686 scale : conv:: decimal_to_rational ( & token. scaling_factor )
586687 . and_then ( liquidity:: ScalingFactor :: new)
587688 . ok_or ( "invalid token scaling factor" ) ?,
689+ rate : conv:: decimal_to_rational ( & token. rate ) . ok_or ( "invalid token rate" ) ?,
588690 } )
589691 } )
590692 . collect :: < Result < Vec < _ > , Error > > ( ) ?;
@@ -644,6 +746,7 @@ mod stable_surge_pool {
644746 scale : conv:: decimal_to_rational ( & token. scaling_factor )
645747 . and_then ( liquidity:: ScalingFactor :: new)
646748 . ok_or ( "invalid token scaling factor" ) ?,
749+ rate : conv:: decimal_to_rational ( & token. rate ) . ok_or ( "invalid token rate" ) ?,
647750 } )
648751 } )
649752 . collect :: < Result < Vec < _ > , Error > > ( ) ?;
@@ -685,6 +788,7 @@ mod quant_amm_pool {
685788 scale : conv:: decimal_to_rational ( & token. scaling_factor )
686789 . and_then ( liquidity:: ScalingFactor :: new)
687790 . ok_or ( "invalid token scaling factor" ) ?,
791+ rate : conv:: decimal_to_rational ( & token. rate ) . ok_or ( "invalid token rate" ) ?,
688792 } )
689793 } )
690794 . collect :: < Result < Vec < _ > , Error > > ( ) ?;
@@ -725,3 +829,60 @@ mod quant_amm_pool {
725829 } )
726830 }
727831}
832+
833+ /// Creates an enhanced solutions JSON with full liquidity details embedded
834+ pub fn create_enhanced_solutions (
835+ solutions : & solvers_dto:: solution:: Solutions ,
836+ liquidity_response : & crate :: infra:: liquidity_client:: LiquidityResponse ,
837+ ) -> serde_json:: Value {
838+ // Convert to JSON value
839+ let mut solutions_json = serde_json:: to_value ( solutions) . unwrap ( ) ;
840+
841+ // Build a map of liquidity ID -> full liquidity details
842+ let mut liquidity_map: std:: collections:: HashMap < String , & solvers_dto:: auction:: Liquidity > =
843+ std:: collections:: HashMap :: new ( ) ;
844+
845+ for liq in & liquidity_response. liquidity {
846+ let id = extract_liquidity_id ( liq) ;
847+ liquidity_map. insert ( id, liq) ;
848+ }
849+
850+ // Enhance each solution's interactions
851+ if let Some ( solutions_array) = solutions_json[ "solutions" ] . as_array_mut ( ) {
852+ for solution in solutions_array {
853+ if let Some ( interactions) = solution[ "interactions" ] . as_array_mut ( ) {
854+ for interaction in interactions {
855+ if interaction[ "kind" ] == "liquidity" {
856+ if let Some ( id) = interaction[ "id" ] . as_str ( ) {
857+ if let Some ( liquidity_details) = liquidity_map. get ( id) {
858+ // Embed full liquidity details
859+ interaction[ "liquidityDetails" ] =
860+ serde_json:: to_value ( liquidity_details) . unwrap ( ) ;
861+ }
862+ }
863+ }
864+ }
865+ }
866+ }
867+ }
868+
869+ solutions_json
870+ }
871+
872+ fn extract_liquidity_id ( liq : & solvers_dto:: auction:: Liquidity ) -> String {
873+ // Extract ID from each liquidity variant
874+ match liq {
875+ solvers_dto:: auction:: Liquidity :: ConstantProduct ( p) => p. id . clone ( ) ,
876+ solvers_dto:: auction:: Liquidity :: WeightedProduct ( p) => p. id . clone ( ) ,
877+ solvers_dto:: auction:: Liquidity :: Stable ( p) => p. id . clone ( ) ,
878+ solvers_dto:: auction:: Liquidity :: ConcentratedLiquidity ( p) => p. id . clone ( ) ,
879+ solvers_dto:: auction:: Liquidity :: GyroE ( p) => p. id . clone ( ) ,
880+ solvers_dto:: auction:: Liquidity :: Gyro2CLP ( p) => p. id . clone ( ) ,
881+ solvers_dto:: auction:: Liquidity :: Gyro3CLP ( p) => p. id . clone ( ) ,
882+ solvers_dto:: auction:: Liquidity :: LimitOrder ( p) => p. id . clone ( ) ,
883+ solvers_dto:: auction:: Liquidity :: Erc4626 ( p) => p. id . clone ( ) ,
884+ solvers_dto:: auction:: Liquidity :: ReClamm ( p) => p. id . clone ( ) ,
885+ solvers_dto:: auction:: Liquidity :: QuantAmm ( p) => p. id . clone ( ) ,
886+ solvers_dto:: auction:: Liquidity :: StableSurge ( p) => p. id . clone ( ) ,
887+ }
888+ }
0 commit comments