1use serde::{Deserialize, Serialize};
5
6use crate::client::Client;
7use crate::error::Error;
8use crate::models::transaction::{ClientConfigureRejectTransaction, ClientConfigureTransaction};
9use crate::models::{
10 Account, AccountChanges, AccountChangesState, AccountId, AccountProperties, AccountSummary,
11 DecimalNumber, Instrument, InstrumentName, TransactionId,
12};
13
14impl Client {
15 pub async fn account(
20 &self,
21 account_id: impl Into<AccountId>,
22 ) -> Result<AccountResponse, Error> {
23 let account_id = account_id.into();
24 self.execute(self.get(&["accounts", account_id.as_str()]))
25 .await
26 }
27
28 pub fn account_changes(&self, account_id: impl Into<AccountId>) -> AccountChangesRequest {
38 AccountChangesRequest {
39 client: self.clone(),
40 account_id: account_id.into(),
41 since_transaction_id: None,
42 }
43 }
44 pub async fn list_accounts(&self) -> Result<ListAccountsResponse, Error> {
60 self.execute(self.get(&["accounts"])).await
61 }
62
63 pub async fn account_summary(
78 &self,
79 account_id: impl Into<AccountId>,
80 ) -> Result<AccountSummaryResponse, Error> {
81 let account_id = account_id.into();
82 self.execute(self.get(&["accounts", account_id.as_str(), "summary"]))
83 .await
84 }
85
86 pub fn account_instruments(
111 &self,
112 account_id: impl Into<AccountId>,
113 ) -> AccountInstrumentsRequest {
114 AccountInstrumentsRequest {
115 client: self.clone(),
116 account_id: account_id.into(),
117 instruments: None,
118 }
119 }
120
121 pub fn configure_account(&self, account_id: impl Into<AccountId>) -> ConfigureAccountRequest {
149 ConfigureAccountRequest {
150 client: self.clone(),
151 account_id: account_id.into(),
152 body: ConfigureAccountBody {
153 alias: None,
154 margin_rate: None,
155 },
156 }
157 }
158}
159
160#[derive(Debug, Clone, Serialize, Deserialize)]
162#[non_exhaustive]
163pub struct AccountResponse {
164 #[serde(rename = "account")]
166 pub account: Account,
167 #[serde(rename = "lastTransactionID", skip_serializing_if = "Option::is_none")]
169 pub last_transaction_id: Option<TransactionId>,
170}
171
172#[derive(Debug)]
174pub struct AccountChangesRequest {
175 client: Client,
176 account_id: AccountId,
177 since_transaction_id: Option<TransactionId>,
178}
179
180impl AccountChangesRequest {
181 pub fn since_transaction_id(mut self, id: impl Into<TransactionId>) -> Self {
183 self.since_transaction_id = Some(id.into());
184 self
185 }
186
187 pub async fn send(self) -> Result<AccountChangesResponse, Error> {
189 let mut request = self
190 .client
191 .get(&["accounts", self.account_id.as_str(), "changes"]);
192 if let Some(id) = &self.since_transaction_id {
193 request = request.query(&[("sinceTransactionID", id.as_str())]);
194 }
195 self.client.execute(request).await
196 }
197}
198
199#[derive(Debug, Clone, Serialize, Deserialize)]
201#[non_exhaustive]
202pub struct AccountChangesResponse {
203 #[serde(rename = "changes", skip_serializing_if = "Option::is_none")]
207 pub changes: Option<AccountChanges>,
208 #[serde(rename = "state", skip_serializing_if = "Option::is_none")]
210 pub state: Option<AccountChangesState>,
211 #[serde(rename = "lastTransactionID", skip_serializing_if = "Option::is_none")]
214 pub last_transaction_id: Option<TransactionId>,
215}
216
217#[derive(Debug, Clone, Serialize, Deserialize)]
219#[non_exhaustive]
220pub struct ListAccountsResponse {
221 #[serde(rename = "accounts", default, skip_serializing_if = "Vec::is_empty")]
224 pub accounts: Vec<AccountProperties>,
225}
226
227#[derive(Debug, Clone, Serialize, Deserialize)]
229#[non_exhaustive]
230pub struct AccountSummaryResponse {
231 #[serde(rename = "account")]
233 pub account: AccountSummary,
234 #[serde(rename = "lastTransactionID", skip_serializing_if = "Option::is_none")]
236 pub last_transaction_id: Option<TransactionId>,
237}
238
239#[derive(Debug)]
241pub struct AccountInstrumentsRequest {
242 client: Client,
243 account_id: AccountId,
244 instruments: Option<Vec<InstrumentName>>,
245}
246
247impl AccountInstrumentsRequest {
248 pub fn instruments<I>(mut self, instruments: I) -> Self
251 where
252 I: IntoIterator,
253 I::Item: Into<InstrumentName>,
254 {
255 self.instruments = Some(instruments.into_iter().map(Into::into).collect());
256 self
257 }
258
259 pub async fn send(self) -> Result<AccountInstrumentsResponse, Error> {
261 let mut request = self
262 .client
263 .get(&["accounts", self.account_id.as_str(), "instruments"]);
264 if let Some(instruments) = &self.instruments {
265 request = request.query(&[("instruments", join_names(instruments))]);
266 }
267 self.client.execute(request).await
268 }
269}
270
271#[derive(Debug, Clone, Serialize, Deserialize)]
273#[non_exhaustive]
274pub struct AccountInstrumentsResponse {
275 #[serde(rename = "instruments", default, skip_serializing_if = "Vec::is_empty")]
277 pub instruments: Vec<Instrument>,
278 #[serde(rename = "lastTransactionID", skip_serializing_if = "Option::is_none")]
280 pub last_transaction_id: Option<TransactionId>,
281}
282
283#[derive(Debug)]
285pub struct ConfigureAccountRequest {
286 client: Client,
287 account_id: AccountId,
288 body: ConfigureAccountBody,
289}
290
291#[derive(Debug, Serialize)]
292struct ConfigureAccountBody {
293 #[serde(rename = "alias", skip_serializing_if = "Option::is_none")]
294 alias: Option<String>,
295 #[serde(rename = "marginRate", skip_serializing_if = "Option::is_none")]
296 margin_rate: Option<DecimalNumber>,
297}
298
299impl ConfigureAccountRequest {
300 pub fn alias(mut self, alias: impl Into<String>) -> Self {
302 self.body.alias = Some(alias.into());
303 self
304 }
305
306 pub fn margin_rate(mut self, margin_rate: impl Into<DecimalNumber>) -> Self {
308 self.body.margin_rate = Some(margin_rate.into());
309 self
310 }
311
312 pub async fn send(self) -> Result<ConfigureAccountResponse, Error> {
314 let request = self
315 .client
316 .patch(&["accounts", self.account_id.as_str(), "configuration"])
317 .json(&self.body);
318 self.client.execute(request).await
319 }
320}
321
322#[derive(Debug, Clone, Serialize, Deserialize)]
324#[non_exhaustive]
325pub struct ConfigureAccountResponse {
326 #[serde(
328 rename = "clientConfigureTransaction",
329 skip_serializing_if = "Option::is_none"
330 )]
331 pub client_configure_transaction: Option<ClientConfigureTransaction>,
332 #[serde(rename = "lastTransactionID", skip_serializing_if = "Option::is_none")]
334 pub last_transaction_id: Option<TransactionId>,
335}
336
337#[derive(Debug, Clone, Serialize, Deserialize)]
341#[non_exhaustive]
342pub struct ConfigureAccountRejectBody {
343 #[serde(
345 rename = "clientConfigureRejectTransaction",
346 skip_serializing_if = "Option::is_none"
347 )]
348 pub client_configure_reject_transaction: Option<ClientConfigureRejectTransaction>,
349 #[serde(rename = "lastTransactionID", skip_serializing_if = "Option::is_none")]
351 pub last_transaction_id: Option<TransactionId>,
352}
353
354pub(crate) fn join_names(instruments: &[InstrumentName]) -> String {
356 instruments
357 .iter()
358 .map(InstrumentName::as_str)
359 .collect::<Vec<_>>()
360 .join(",")
361}