switchboard_utils/exchanges/
bitfinex.rs1use crate::*;
2
3use serde::Deserialize;
4
5#[derive(Debug, Clone, Deserialize)]
6pub struct BitfinexTickerInfo {
7 pub bid: Decimal,
8 pub bid_size: Decimal,
9 pub ask: Decimal,
10 pub ask_size: Decimal,
11 pub daily_change: Decimal,
12 pub daily_change_relative: Decimal,
13 pub last_price: Decimal,
14 pub volume: Decimal,
15 pub high: Decimal,
16 pub low: Decimal,
17}
18
19pub struct BitfinexApi {}
20
21impl BitfinexApi {
22 fn get_ticker_url(ticker: &str, url: Option<&str>) -> String {
24 format!(
25 "{}/v2/ticker/{}",
26 url.unwrap_or("https://api-pub.bitfinex.com"),
27 ticker
28 )
29 }
30
31 pub async fn fetch_ticker(
32 ticker: &str,
33 url: Option<&str>,
34 ) -> Result<BitfinexTickerInfo, SbError> {
35 let ticker_url = BitfinexApi::get_ticker_url(ticker, url);
36
37 let response: Vec<f64> = reqwest::get(&ticker_url)
38 .await
39 .map_err(handle_reqwest_err)?
40 .json()
41 .await
42 .map_err(handle_reqwest_err)?;
43
44 if response.len() < 10 {
45 return Err(SbError::Message("Bitfinex response too short"));
46 }
47
48 Ok(BitfinexTickerInfo {
49 bid: Decimal::from_f64(response[0]).unwrap(),
50 bid_size: Decimal::from_f64(response[1]).unwrap(),
51 ask: Decimal::from_f64(response[2]).unwrap(),
52 ask_size: Decimal::from_f64(response[3]).unwrap(),
53 daily_change: Decimal::from_f64(response[4]).unwrap(),
54 daily_change_relative: Decimal::from_f64(response[5]).unwrap(),
55 last_price: Decimal::from_f64(response[6]).unwrap(),
56 volume: Decimal::from_f64(response[7]).unwrap(),
57 high: Decimal::from_f64(response[8]).unwrap(),
58 low: Decimal::from_f64(response[9]).unwrap(),
59 })
60 }
61}
62
63#[cfg(test)]
64mod tests {
65 use super::*;
66
67 const MOCK_BITFINEX_RESPONSE: &str =
68 r#"[27686,18.95873976,27687,13.79181632,310,0.01132503,27683,800.37680489,27846,27211]"#;
69
70 #[tokio::test]
71 async fn test_bitfinex_api() {
72 let mut server = mockito::Server::new();
74 let server_url = server.url();
75
76 let mock = server
78 .mock("GET", "/v2/ticker/tBTCUSD")
79 .with_status(201)
80 .with_header("content-type", "application/json")
81 .with_body(MOCK_BITFINEX_RESPONSE)
82 .create();
83
84 let ticker = BitfinexApi::fetch_ticker("tBTCUSD", Some(server_url.as_str()))
85 .await
86 .unwrap();
87
88 mock.assert();
90
91 assert_eq!(ticker.bid, Decimal::from_str("27686").unwrap());
92 }
93}