@@ -4,29 +4,28 @@ use chrono::{DateTime, TimeDelta, Utc};
44use derive_more:: { Deref , DerefMut } ;
55use eyre:: { Report , Result } ;
66use v_utils:: trades:: { Asset , Kline , Pair , Timeframe } ;
7+ use eyre:: bail;
78use crate :: { binance, bybit} ;
89
910//TODO!!!!!!!!!!!!!: klines switch to defining the range via an Enum over either limit either start and end times
1011
1112pub trait Exchange {
1213 fn auth < S : Into < String > > ( & mut self , key : S , secret : S ) ;
1314
14- fn spot_klines ( & self , pair : Pair , tf : Timeframe , range : KlinesRequestRange ) -> impl std:: future:: Future < Output = Result < Klines > > + Send ;
15- fn spot_price ( & self , pair : Pair ) -> impl std:: future:: Future < Output = Result < f64 > > + Send ;
16- /// If no symbols are specified, returns all spot prices.
17- fn spot_prices ( & self , pairs : Option < Vec < Pair > > ) -> impl std:: future:: Future < Output = Result < Vec < ( Pair , f64 ) > > > + Send ;
18-
1915 //? should I have Self::Pair too? Like to catch the non-existent ones immediately? Although this would increase the error surface on new listings.
20- fn futures_klines ( & self , pair : Pair , tf : Timeframe , range : KlinesRequestRange ) -> impl std:: future:: Future < Output = Result < Klines > > + Send ;
21- fn futures_price ( & self , pair : Pair ) -> impl std:: future:: Future < Output = Result < f64 > > + Send ;
16+ fn klines ( & self , pair : Pair , tf : Timeframe , range : KlinesRequestRange , market : Market ) -> impl std:: future:: Future < Output = Result < Klines > > + Send ;
17+
18+ /// If no pairs are specified, returns for all;
19+ fn prices ( & self , pairs : Option < Vec < Pair > > , market : Market ) -> impl std:: future:: Future < Output = Result < Vec < ( Pair , f64 ) > > > + Send ;
20+ fn price ( & self , pair : Pair , market : Market ) -> impl std:: future:: Future < Output = Result < f64 > > + Send ;
2221
2322 // Defined in terms of actors
2423 //TODO!!!: fn spawn_klines_listener(&self, symbol: Pair, tf: Timeframe) -> mpsc::Receiver<Kline>;
2524
2625 /// balance of a specific asset
27- fn futures_asset_balance ( & self , asset : Asset ) -> impl std:: future:: Future < Output = Result < AssetBalance > > + Send ;
26+ fn asset_balance ( & self , asset : Asset , market : Market ) -> impl std:: future:: Future < Output = Result < AssetBalance > > + Send ;
2827 /// vec of balances of specific assets
29- fn futures_balances ( & self ) -> impl std:: future:: Future < Output = Result < Vec < AssetBalance > > > + Send ;
28+ fn balances ( & self , market : Market ) -> impl std:: future:: Future < Output = Result < Vec < AssetBalance > > > + Send ;
3029 //? potentially `total_balance`? Would return precompiled USDT-denominated balance of a (bybit::wallet/binance::account)
3130 // balances are defined for each margin type: [futures_balance, spot_balance, margin_balance], but note that on some exchanges, (like bybit), some of these may point to the same exact call
3231 // to negate confusion could add a `total_balance` endpoint
@@ -155,6 +154,14 @@ pub enum Market {
155154 Bybit ( bybit:: Market ) ,
156155 //TODO
157156}
157+ impl Market {
158+ pub fn client ( & self ) -> Box < impl Exchange > {
159+ match self {
160+ Market :: Binance ( m) => m. client ( ) ,
161+ Market :: Bybit ( m) => m. client ( ) ,
162+ }
163+ }
164+ }
158165impl Default for Market {
159166 fn default ( ) -> Self {
160167 Self :: Binance ( binance:: Market :: default ( ) )
@@ -178,12 +185,35 @@ impl std::str::FromStr for Market {
178185 if parts. len ( ) != 2 {
179186 return Err ( eyre:: eyre!( "Invalid market string: {}" , s) ) ;
180187 }
181- let market = parts[ 0 ] ;
182- let exchange = parts[ 1 ] ;
183- match market. to_lowercase ( ) . as_str ( ) {
184- "binance" => Ok ( Self :: Binance ( exchange. parse ( ) ?) ) ,
185- "bybit" => Ok ( Self :: Bybit ( exchange. parse ( ) ?) ) ,
186- _ => Err ( eyre:: eyre!( "Invalid market string: {}" , s) ) ,
188+ let exchange = parts[ 0 ] ;
189+ let sub_market = parts[ 1 ] ;
190+ match exchange. to_lowercase ( ) . as_str ( ) {
191+ "binance" => Ok ( Self :: Binance ( sub_market. parse ( ) ?) ) ,
192+ "bybit" => Ok ( Self :: Bybit ( {
193+ match sub_market. parse ( ) {
194+ Ok ( m) => m,
195+ Err ( e) => match sub_market. to_lowercase ( ) == "futures" {
196+ true => bybit:: Market :: Linear ,
197+ false => bail ! ( e) ,
198+ }
199+ }
200+ } ) ) ,
201+ _ => bail ! ( "Invalid market string: {}" , s) ,
187202 }
188203 }
189204}
205+ impl From < Market > for String {
206+ fn from ( value : Market ) -> Self {
207+ value. to_string ( )
208+ }
209+ }
210+ impl From < String > for Market {
211+ fn from ( value : String ) -> Self {
212+ value. parse ( ) . unwrap ( )
213+ }
214+ }
215+ impl From < & str > for Market {
216+ fn from ( value : & str ) -> Self {
217+ value. parse ( ) . unwrap ( )
218+ }
219+ }
0 commit comments