finance_query/adapters/polygon/crypto/
trades.rs1use serde::{Deserialize, Serialize};
4
5use crate::adapters::common::encode_path_segment;
6use crate::error::{FinanceError, Result};
7
8use super::super::build_client;
9use super::super::models::*;
10
11#[derive(Debug, Clone, Serialize, Deserialize)]
13#[non_exhaustive]
14pub struct CryptoLastTrade {
15 pub price: Option<f64>,
17 pub size: Option<f64>,
19 pub exchange: Option<i32>,
21 pub conditions: Option<Vec<i32>>,
23 pub timestamp: Option<i64>,
25}
26
27#[derive(Debug, Clone, Serialize, Deserialize)]
29#[non_exhaustive]
30pub struct CryptoLastTradeResponse {
31 pub last: Option<CryptoLastTrade>,
33 pub request_id: Option<String>,
35 pub status: Option<String>,
37 pub symbol: Option<String>,
39}
40
41pub async fn crypto_last_trade(from: &str, to: &str) -> Result<CryptoLastTradeResponse> {
49 let client = build_client()?;
50 let path = format!(
51 "/v1/last/crypto/{}/{}",
52 encode_path_segment(from),
53 encode_path_segment(to)
54 );
55 let json = client.get_raw(&path, &[]).await?;
56 serde_json::from_value(json).map_err(|e| FinanceError::ResponseStructureError {
57 field: "crypto_last_trade".to_string(),
58 context: format!("Failed to parse crypto last trade response: {e}"),
59 })
60}
61
62pub async fn crypto_trades(
67 ticker: &str,
68 params: &[(&str, &str)],
69) -> Result<PaginatedResponse<Trade>> {
70 let client = build_client()?;
71 let path = format!("/v3/trades/{}", encode_path_segment(ticker));
72 client.get(&path, params).await
73}
74
75#[cfg(test)]
76mod tests {
77 use super::*;
78
79 #[tokio::test]
80 async fn test_crypto_last_trade_mock() {
81 let mut server = mockito::Server::new_async().await;
82 let _mock = server
83 .mock("GET", "/v1/last/crypto/BTC/USD")
84 .match_query(mockito::Matcher::AllOf(vec![mockito::Matcher::UrlEncoded(
85 "apiKey".into(),
86 "test-key".into(),
87 )]))
88 .with_status(200)
89 .with_header("content-type", "application/json")
90 .with_body(
91 serde_json::json!({
92 "request_id": "abc123",
93 "status": "OK",
94 "symbol": "X:BTCUSD",
95 "last": {
96 "price": 43100.50,
97 "size": 0.5,
98 "exchange": 2,
99 "conditions": [1],
100 "timestamp": 1705363200000_i64
101 }
102 })
103 .to_string(),
104 )
105 .create_async()
106 .await;
107
108 let client = super::super::super::build_test_client(&server.url()).unwrap();
109 let json = client
110 .get_raw("/v1/last/crypto/BTC/USD", &[])
111 .await
112 .unwrap();
113
114 let resp: CryptoLastTradeResponse = serde_json::from_value(json).unwrap();
115 assert_eq!(resp.status.as_deref(), Some("OK"));
116 assert_eq!(resp.symbol.as_deref(), Some("X:BTCUSD"));
117 let last = resp.last.unwrap();
118 assert!((last.price.unwrap() - 43100.50).abs() < 0.01);
119 assert!((last.size.unwrap() - 0.5).abs() < 0.01);
120 }
121}