apca/api/v2/
account_config.rs1use http::Method;
5use http_endpoint::Bytes;
6
7use serde::Deserialize;
8use serde::Serialize;
9use serde_json::to_vec as to_json;
10
11use crate::Str;
12
13
14#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
16#[non_exhaustive]
17pub enum TradeConfirmation {
18 #[serde(rename = "all")]
20 Email,
21 #[serde(rename = "none")]
23 None,
24}
25
26
27#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
30pub struct Configuration {
31 #[serde(rename = "trade_confirm_email")]
33 pub trade_confirmation: TradeConfirmation,
34 #[serde(rename = "suspend_trade")]
36 pub trading_suspended: bool,
37 #[serde(rename = "no_shorting")]
39 pub no_shorting: bool,
40 #[doc(hidden)]
42 #[serde(skip)]
43 pub _non_exhaustive: (),
44}
45
46
47Endpoint! {
48 pub Get(()),
51 Ok => Configuration, [
52 OK,
54 ],
55 Err => GetError, []
56
57 #[inline]
58 fn path(_input: &Self::Input) -> Str {
59 "/v2/account/configurations".into()
60 }
61}
62
63
64Endpoint! {
65 pub Change(Configuration),
68 Ok => Configuration, [
69 OK,
71 ],
72 Err => ChangeError, [
73 BAD_REQUEST => InvalidValues,
75 ]
76
77 #[inline]
78 fn method() -> Method {
79 Method::PATCH
80 }
81
82 #[inline]
83 fn path(_input: &Self::Input) -> Str {
84 "/v2/account/configurations".into()
85 }
86
87 fn body(input: &Self::Input) -> Result<Option<Bytes>, Self::ConversionError> {
88 let json = to_json(input)?;
89 let bytes = Bytes::from(json);
90 Ok(Some(bytes))
91 }
92}
93
94
95#[cfg(test)]
96mod tests {
97 use super::*;
98
99 use serde_json::from_str as from_json;
100
101 use test_log::test;
102
103 use crate::api_info::ApiInfo;
104 use crate::Client;
105
106
107 #[test]
108 fn parse_reference_configuration() {
109 let response = r#"{
110 "dtbp_check": "entry",
111 "no_shorting": false,
112 "suspend_trade": false,
113 "trade_confirm_email": "all"
114}"#;
115
116 let config = from_json::<Configuration>(response).unwrap();
117 assert_eq!(config.trade_confirmation, TradeConfirmation::Email);
118 assert!(!config.trading_suspended);
119 assert!(!config.no_shorting);
120 }
121
122 #[test(tokio::test)]
123 async fn retrieve_and_update_configuration() {
124 let api_info = ApiInfo::from_env().unwrap();
125 let client = Client::new(api_info);
126 let config = client.issue::<Get>(&()).await.unwrap();
127
128 let new_confirmation = match config.trade_confirmation {
131 TradeConfirmation::Email => TradeConfirmation::None,
132 TradeConfirmation::None => TradeConfirmation::Email,
133 };
134
135 let changed = Configuration {
136 trade_confirmation: new_confirmation,
137 ..config
138 };
139 let change_result = client.issue::<Change>(&changed).await;
140 let get_result = client.issue::<Get>(&()).await;
142 let reverted = client.issue::<Change>(&config).await.unwrap();
144
145 assert_eq!(change_result.unwrap(), changed);
146 assert_eq!(get_result.unwrap(), changed);
147 assert_eq!(reverted, config);
148 }
149}