use anyhow::Result;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::collections::BTreeMap;
use crate::client::BitgetClient;
use crate::consts;
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct TickerResp {
pub symbol: Option<String>,
pub last: Option<String>,
pub buy: Option<String>,
pub sell: Option<String>,
pub high: Option<String>,
pub low: Option<String>,
pub volume: Option<String>,
pub quote_volume: Option<String>,
pub timestamp: Option<String>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct CandleResp {
pub timestamp: Option<String>,
pub open: Option<String>,
pub high: Option<String>,
pub low: Option<String>,
pub close: Option<String>,
pub volume: Option<String>,
}
impl BitgetClient {
pub fn get_ticker(&self, symbol: &str) -> Result<String> {
let mut params = BTreeMap::new();
params.insert("symbol".to_string(), symbol.to_string());
tracing::debug!("查询现货行情(v1) - 交易对: {}", symbol);
self.request(consts::GET, "/api/spot/v1/market/ticker", ¶ms, false)
}
pub fn get_ticker_v2(&self, symbol: &str) -> Result<String> {
let mut params = BTreeMap::new();
params.insert("symbol".to_string(), symbol.to_string());
tracing::debug!("查询现货行情(v2) - 交易对: {}", symbol);
let resp = self.request(consts::GET, "/api/v2/spot/market/tickers", ¶ms, false)?;
let v: Value = serde_json::from_str(&resp)?;
if v["code"] == "00000" {
if let Some(arr) = v["data"].as_array() {
if let Some(ticker) = arr.get(0) {
return Ok(ticker.to_string());
}
}
Err(anyhow::anyhow!("未找到行情数据: {}", resp))
} else {
Err(anyhow::anyhow!("bitget v2 ticker 错误: {}", resp))
}
}
pub async fn get_ticker_v2_async(&self, symbol: &str) -> Result<String> {
let mut params = BTreeMap::new();
params.insert("symbol".to_string(), symbol.to_string());
tracing::debug!("查询现货行情(v2) - 交易对: {}", symbol);
let resp = self.request(consts::GET, "/api/v2/spot/market/tickers", ¶ms, false)?;
let v: Value = serde_json::from_str(&resp)?;
if v["code"] == "00000" {
if let Some(arr) = v["data"].as_array() {
if let Some(ticker) = arr.get(0) {
return Ok(ticker.to_string());
}
}
Err(anyhow::anyhow!("未找到行情数据: {}", resp))
} else {
Err(anyhow::anyhow!("bitget v2 ticker 错误: {}", resp))
}
}
pub fn get_candles(&self, symbol: &str, period: &str, limit: Option<u32>) -> Result<String> {
let mut params = BTreeMap::new();
params.insert("symbol".to_string(), symbol.to_string());
params.insert("period".to_string(), period.to_string());
if let Some(limit_val) = limit {
params.insert("limit".to_string(), limit_val.to_string());
}
tracing::debug!("查询K线数据 - 交易对: {}, 周期: {}", symbol, period);
self.request(consts::GET, "/api/v2/spot/market/candles", ¶ms, false)
}
pub async fn get_candles_async(
&self,
symbol: &str,
period: &str,
limit: Option<u32>,
) -> Result<String> {
let mut params = BTreeMap::new();
params.insert("symbol".to_string(), symbol.to_string());
params.insert("period".to_string(), period.to_string());
if let Some(limit_val) = limit {
params.insert("limit".to_string(), limit_val.to_string());
}
tracing::debug!("查询K线数据 - 交易对: {}, 周期: {}", symbol, period);
self.request(consts::GET, "/api/v2/spot/market/candles", ¶ms, false)
}
pub fn get_depth(&self, symbol: &str, limit: Option<u32>) -> Result<String> {
let mut params = BTreeMap::new();
params.insert("symbol".to_string(), symbol.to_string());
if let Some(limit_val) = limit {
params.insert("limit".to_string(), limit_val.to_string());
}
tracing::debug!("查询深度数据 - 交易对: {}", symbol);
self.request(consts::GET, "/api/v2/spot/market/orderbook", ¶ms, false)
}
pub async fn get_depth_async(&self, symbol: &str, limit: Option<u32>) -> Result<String> {
let mut params = BTreeMap::new();
params.insert("symbol".to_string(), symbol.to_string());
if let Some(limit_val) = limit {
params.insert("limit".to_string(), limit_val.to_string());
}
tracing::debug!("查询深度数据 - 交易对: {}", symbol);
self.request(consts::GET, "/api/v2/spot/market/orderbook", ¶ms, false)
}
}