Skip to main content

nash_protocol/protocol/list_markets/
response.rs

1use super::types::ListMarketsResponse;
2use crate::errors::{ProtocolError, Result};
3use crate::graphql::list_markets;
4use crate::types::{Asset, Market};
5
6use std::collections::HashMap;
7use std::convert::TryFrom;
8
9fn decimal_str_to_precision(decimal_str: &str) -> Result<u32> {
10    let parts: Vec<&str> = decimal_str.split(".").collect();
11    if parts.len() != 2 {
12        return Err(ProtocolError("Invalid format for decimal string"));
13    }
14    Ok(parts[1].len() as u32)
15}
16
17impl TryFrom<list_markets::ResponseData> for ListMarketsResponse {
18    type Error = ProtocolError;
19
20    fn try_from(response: list_markets::ResponseData) -> Result<Self> {
21        let mut markets = HashMap::new();
22        for market_data in response.list_markets {
23            let market_name = market_data.name;
24            // Skip all markets that are not primary
25            if market_data.primary == false {
26                continue;
27            }
28            let asset_a_str = market_data.a_asset.symbol;
29            let asset_b_str = market_data.b_asset.symbol;
30            let asset_a = Asset::from_str(&asset_a_str);
31            let asset_b = Asset::from_str(&asset_b_str);
32            // Only return markets for assets known to the client
33            // These unwraps are safe if
34            if let (Ok(asset_a), Ok(asset_b)) = (asset_a, asset_b) {
35                let precision_a =
36                    decimal_str_to_precision(&market_data.min_trade_increment).expect("Impossible given 'decimal_str_to_precision' unless ME returns garbage for a precision");
37                let precision_b =
38                    decimal_str_to_precision(&market_data.min_trade_increment_b).expect("Impossible given 'decimal_str_to_precision' unless ME returns garbage for b precision");
39                let prec_asset_a = asset_a.with_precision(precision_a);
40                let prec_asset_b = asset_b.with_precision(precision_b);
41                let min_trade_size_a = prec_asset_a.with_amount(&market_data.min_trade_size)?;
42                let min_trade_size_b = prec_asset_b.with_amount(&market_data.min_trade_size_b)?;
43                markets.insert(
44                    market_name,
45                    Market::new(
46                        prec_asset_a,
47                        prec_asset_b,
48                        min_trade_size_a,
49                        min_trade_size_b,
50                    ),
51                );
52            }
53        }
54        Ok(Self { markets })
55    }
56}