Skip to main content

oanda_client/
account.rs

1//! OANDA account endpoint contracts.
2// Shared imports vary by capability; unused ones are deliberately allowed.
3#[allow(unused_imports)]
4use crate::Timestamp;
5#[allow(unused_imports)]
6use crate::ids::*;
7#[allow(unused_imports)]
8use crate::models::*;
9#[allow(unused_imports)]
10use crate::{Client, Result};
11#[allow(unused_imports)]
12use reqwest::Method;
13#[allow(unused_imports)]
14use rust_decimal::Decimal;
15#[allow(unused_imports)]
16use serde::{Deserialize, Serialize};
17
18/// Successful response for `list_accounts`.
19#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
20#[serde(rename_all = "camelCase")]
21pub struct ListAccountsResponse {
22    /// The list of Accounts the client is authorized to access and their associated properties.
23    #[serde(rename = "accounts", default, skip_serializing_if = "Option::is_none")]
24    pub accounts: Option<Vec<AccountProperties>>,
25}
26
27impl Client {
28    /// List accounts.
29    pub async fn list_accounts(
30        &self,
31    ) -> std::result::Result<
32        crate::ApiResponse<ListAccountsResponse>,
33        crate::OperationError<crate::GenericRejection>,
34    > {
35        let path = "/v3/accounts".to_owned();
36        self.execute(Method::GET, &path, None::<&()>, None::<&()>, None, None)
37            .await
38    }
39}
40
41/// Successful response for `account_details`.
42#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
43#[serde(rename_all = "camelCase")]
44pub struct AccountDetailsResponse {
45    /// The full details of the requested Account.
46    #[serde(rename = "account", default, skip_serializing_if = "Option::is_none")]
47    pub account: Option<Account>,
48    /// The ID of the most recent Transaction created for the Account.
49    #[serde(
50        rename = "lastTransactionID",
51        default,
52        skip_serializing_if = "Option::is_none"
53    )]
54    pub last_transaction_id: Option<TransactionID>,
55}
56
57impl Client {
58    /// Account details.
59    pub async fn account_details(
60        &self,
61        account_id: &AccountID,
62    ) -> std::result::Result<
63        crate::ApiResponse<AccountDetailsResponse>,
64        crate::OperationError<crate::GenericRejection>,
65    > {
66        let account_id_encoded = crate::client::segment(account_id.as_str());
67        let path = format!("/v3/accounts/{account_id_encoded}");
68        self.execute(Method::GET, &path, None::<&()>, None::<&()>, None, None)
69            .await
70    }
71}
72
73/// Successful response for `account_summary`.
74#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
75#[serde(rename_all = "camelCase")]
76pub struct AccountSummaryResponse {
77    /// The summary of the requested Account.
78    #[serde(rename = "account", default, skip_serializing_if = "Option::is_none")]
79    pub account: Option<AccountSummary>,
80    /// The ID of the most recent Transaction created for the Account.
81    #[serde(
82        rename = "lastTransactionID",
83        default,
84        skip_serializing_if = "Option::is_none"
85    )]
86    pub last_transaction_id: Option<TransactionID>,
87}
88
89impl Client {
90    /// Account summary.
91    pub async fn account_summary(
92        &self,
93        account_id: &AccountID,
94    ) -> std::result::Result<
95        crate::ApiResponse<AccountSummaryResponse>,
96        crate::OperationError<crate::GenericRejection>,
97    > {
98        let account_id_encoded = crate::client::segment(account_id.as_str());
99        let path = format!("/v3/accounts/{account_id_encoded}/summary");
100        self.execute(Method::GET, &path, None::<&()>, None::<&()>, None, None)
101            .await
102    }
103}
104
105/// Query parameters for `account_instruments`.
106#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
107#[serde(rename_all = "camelCase")]
108pub struct AccountInstrumentsQuery {
109    /// List of instruments to query specifically.
110    #[serde(
111        rename = "instruments",
112        default,
113        skip_serializing_if = "Option::is_none"
114    )]
115    pub instruments: Option<Vec<InstrumentName>>,
116}
117
118/// Successful response for `account_instruments`.
119#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
120#[serde(rename_all = "camelCase")]
121pub struct AccountInstrumentsResponse {
122    /// The requested list of instruments.
123    #[serde(
124        rename = "instruments",
125        default,
126        skip_serializing_if = "Option::is_none"
127    )]
128    pub instruments: Option<Vec<Instrument>>,
129    /// The ID of the most recent Transaction created for the Account.
130    #[serde(
131        rename = "lastTransactionID",
132        default,
133        skip_serializing_if = "Option::is_none"
134    )]
135    pub last_transaction_id: Option<TransactionID>,
136}
137
138impl Client {
139    /// Account instruments.
140    pub async fn account_instruments(
141        &self,
142        account_id: &AccountID,
143        query: Option<&AccountInstrumentsQuery>,
144    ) -> std::result::Result<
145        crate::ApiResponse<AccountInstrumentsResponse>,
146        crate::OperationError<crate::GenericRejection>,
147    > {
148        let account_id_encoded = crate::client::segment(account_id.as_str());
149        let path = format!("/v3/accounts/{account_id_encoded}/instruments");
150        self.execute(Method::GET, &path, query, None::<&()>, None, None)
151            .await
152    }
153}
154
155/// Request body for `configure_account`.
156#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
157#[serde(rename_all = "camelCase")]
158pub struct ConfigureAccountBody {
159    /// Client-defined alias (name) for the Account
160    #[serde(rename = "alias", default, skip_serializing_if = "Option::is_none")]
161    pub alias: Option<String>,
162    /// The string representation of a decimal number.
163    #[serde(
164        rename = "marginRate",
165        default,
166        skip_serializing_if = "Option::is_none"
167    )]
168    #[serde(deserialize_with = "crate::decimal_wire::optional_number_or_string")]
169    pub margin_rate: Option<Decimal>,
170}
171
172/// Successful response for `configure_account`.
173#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
174#[serde(rename_all = "camelCase")]
175pub struct ConfigureAccountResponse {
176    /// The transaction that configures the Account.
177    #[serde(
178        rename = "clientConfigureTransaction",
179        default,
180        skip_serializing_if = "Option::is_none"
181    )]
182    pub client_configure_transaction: Option<ClientConfigureTransaction>,
183    /// The ID of the last Transaction created for the Account.
184    #[serde(
185        rename = "lastTransactionID",
186        default,
187        skip_serializing_if = "Option::is_none"
188    )]
189    pub last_transaction_id: Option<TransactionID>,
190}
191
192/// Documented rejection fields for `configure_account`.
193#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
194#[serde(rename_all = "camelCase")]
195pub struct ConfigureAccountRejection {
196    /// The transaction that rejects the configuration of the Account.
197    #[serde(
198        rename = "clientConfigureRejectTransaction",
199        default,
200        skip_serializing_if = "Option::is_none"
201    )]
202    pub client_configure_reject_transaction: Option<ClientConfigureRejectTransaction>,
203    /// The ID of the last Transaction created for the Account.
204    #[serde(
205        rename = "lastTransactionID",
206        default,
207        skip_serializing_if = "Option::is_none"
208    )]
209    pub last_transaction_id: Option<TransactionID>,
210    /// The code of the error that has occurred. This field may not be returned for some errors.
211    #[serde(rename = "errorCode", default, skip_serializing_if = "Option::is_none")]
212    pub error_code: Option<String>,
213    /// The human-readable description of the error that has occurred.
214    #[serde(
215        rename = "errorMessage",
216        default,
217        skip_serializing_if = "Option::is_none"
218    )]
219    pub error_message: Option<String>,
220}
221
222impl Client {
223    /// Configure account.
224    pub async fn configure_account(
225        &self,
226        account_id: &AccountID,
227        body: &ConfigureAccountBody,
228    ) -> std::result::Result<
229        crate::ApiResponse<ConfigureAccountResponse>,
230        crate::OperationError<ConfigureAccountRejection>,
231    > {
232        let account_id_encoded = crate::client::segment(account_id.as_str());
233        let path = format!("/v3/accounts/{account_id_encoded}/configuration");
234        self.execute(
235            Method::PATCH,
236            &path,
237            None::<&()>,
238            Some(body),
239            Some(crate::client::MutationAdmission::Ordinary(account_id)),
240            None,
241        )
242        .await
243    }
244}
245
246/// Query parameters for `account_changes`.
247#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
248#[serde(rename_all = "camelCase")]
249pub struct AccountChangesQuery {
250    /// ID of the Transaction to get Account changes since.
251    #[serde(
252        rename = "sinceTransactionID",
253        default,
254        skip_serializing_if = "Option::is_none"
255    )]
256    pub since_transaction_id: Option<TransactionID>,
257}
258
259/// Successful response for `account_changes`.
260#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
261#[serde(rename_all = "camelCase")]
262pub struct AccountChangesResponse {
263    /// The changes to the Account’s Orders, Trades and Positions since the specified Transaction ID. Only
264    /// provided if the sinceTransactionID is supplied to the poll request.
265    #[serde(rename = "changes", default, skip_serializing_if = "Option::is_none")]
266    pub changes: Option<AccountChanges>,
267    /// The Account’s current price-dependent state.
268    #[serde(rename = "state", default, skip_serializing_if = "Option::is_none")]
269    pub state: Option<AccountChangesState>,
270    /// The ID of the last Transaction created for the Account. This Transaction ID should be used for future
271    /// poll requests, as the client has already observed all changes up to and including it.
272    #[serde(
273        rename = "lastTransactionID",
274        default,
275        skip_serializing_if = "Option::is_none"
276    )]
277    pub last_transaction_id: Option<TransactionID>,
278}
279
280impl Client {
281    /// Account changes.
282    pub async fn account_changes(
283        &self,
284        account_id: &AccountID,
285        query: Option<&AccountChangesQuery>,
286    ) -> std::result::Result<
287        crate::ApiResponse<AccountChangesResponse>,
288        crate::OperationError<crate::GenericRejection>,
289    > {
290        let account_id_encoded = crate::client::segment(account_id.as_str());
291        let path = format!("/v3/accounts/{account_id_encoded}/changes");
292        self.execute(Method::GET, &path, query, None::<&()>, None, None)
293            .await
294    }
295}