nordnet_api/resources/markets.rs
1//! Resource methods for the `markets` API group.
2//!
3//! # Operations
4//!
5//! | Method | Op | Path |
6//! |--------|-----|------|
7//! | GET | `list_markets` | `/markets` |
8//! | GET | `get_market` | `/markets/{market_id}` |
9//!
10//!
11//! ## Multi-ID lookups for `get_market`
12//!
13//! The Nordnet API path parameter for `get_market` accepts a comma-separated
14//! list of market IDs. This method covers the single-ID case via the
15//! [`MarketId`] newtype, mirroring the [`Client::get_country`] pattern. A
16//! future helper may be added for multi-ID lookups when needed.
17//!
18//!
19//! ## 204 No Content
20//!
21//! `GET /markets/{market_id}` may return HTTP 204 (No Content) when no
22//! matching market is found. The base [`Client::get`] method attempts to
23//! parse the empty response body as JSON, which fails. `get_market` detects
24//! this specific case (a [`Error::Decode`] with an empty body) and maps it
25//! to an empty `Vec`, mirroring [`Client::get_country`].
26
27use crate::client::Client;
28use crate::error::Error;
29use nordnet_model::ids::MarketId;
30use nordnet_model::models::markets::Market;
31
32impl Client {
33 /// `GET /markets` — Returns information about all tradable markets.
34 ///
35 /// # Errors
36 ///
37 /// Returns [`Error::Unauthorized`] (401), [`Error::TooManyRequests`]
38 /// (429), or [`Error::ServiceUnavailable`] (503) as documented.
39 #[doc(alias = "GET /markets")]
40 pub async fn list_markets(&self) -> Result<Vec<Market>, Error> {
41 self.get("/markets").await
42 }
43
44 /// `GET /markets/{market_id}` — Returns information about the market
45 /// identified by `id`.
46 ///
47 /// Returns an empty `Vec` when the API responds with 204 No Content (no
48 /// matching markets).
49 ///
50 /// # Errors
51 ///
52 /// Returns [`Error::BadRequest`] (400), [`Error::Unauthorized`] (401),
53 /// [`Error::TooManyRequests`] (429), or [`Error::ServiceUnavailable`]
54 /// (503) as documented.
55 #[doc(alias = "GET /markets/{market_id}")]
56 pub async fn get_market(&self, id: MarketId) -> Result<Vec<Market>, Error> {
57 let path = format!("/markets/{id}");
58 match self.get::<Vec<Market>>(&path).await {
59 Ok(markets) => Ok(markets),
60 // HTTP 204 No Content: the base client sees an empty body and
61 // produces a Decode error. Map it to an empty Vec instead.
62 Err(Error::Decode { ref body, .. }) if body.trim().is_empty() => Ok(vec![]),
63 Err(e) => Err(e),
64 }
65 }
66}