Skip to main content

kraken_api_client/spot/rest/private/
mod.rs

1//! Private REST API endpoints (authentication required).
2//!
3//! These endpoints require API credentials to be configured on the client.
4
5mod types;
6
7pub use types::*;
8
9use crate::error::KrakenError;
10use crate::spot::rest::SpotRestClient;
11use crate::spot::rest::endpoints::private;
12
13impl SpotRestClient {
14    /// Get account balance.
15    ///
16    /// Returns the balances of all assets in the account.
17    ///
18    /// # Example
19    ///
20    /// ```rust,no_run
21    /// use kraken_api_client::spot::rest::SpotRestClient;
22    /// use kraken_api_client::auth::StaticCredentials;
23    /// use std::sync::Arc;
24    ///
25    /// #[tokio::main]
26    /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
27    ///     let credentials = Arc::new(StaticCredentials::new("key", "secret"));
28    ///     let client = SpotRestClient::builder().credentials(credentials).build();
29    ///
30    ///     let balances = client.get_account_balance().await?;
31    ///     for (asset, balance) in balances {
32    ///         println!("{}: {}", asset, balance);
33    ///     }
34    ///     Ok(())
35    /// }
36    /// ```
37    pub async fn get_account_balance(
38        &self,
39    ) -> Result<std::collections::HashMap<String, rust_decimal::Decimal>, KrakenError> {
40        #[derive(serde::Serialize)]
41        struct Empty {}
42        self.private_post(private::BALANCE, &Empty {}).await
43    }
44
45    /// Get extended balance with hold amounts.
46    pub async fn get_extended_balance(&self) -> Result<ExtendedBalances, KrakenError> {
47        #[derive(serde::Serialize)]
48        struct Empty {}
49        self.private_post(private::BALANCE_EX, &Empty {}).await
50    }
51
52    /// Get trade balance.
53    ///
54    /// Returns margin account details including equity, margin, and P&L.
55    pub async fn get_trade_balance(
56        &self,
57        request: Option<&TradeBalanceRequest>,
58    ) -> Result<TradeBalance, KrakenError> {
59        match request {
60            Some(req) => self.private_post(private::TRADE_BALANCE, req).await,
61            None => {
62                #[derive(serde::Serialize)]
63                struct Empty {}
64                self.private_post(private::TRADE_BALANCE, &Empty {}).await
65            }
66        }
67    }
68
69    /// Get open orders.
70    pub async fn get_open_orders(
71        &self,
72        request: Option<&OpenOrdersRequest>,
73    ) -> Result<OpenOrders, KrakenError> {
74        match request {
75            Some(req) => self.private_post(private::OPEN_ORDERS, req).await,
76            None => {
77                #[derive(serde::Serialize)]
78                struct Empty {}
79                self.private_post(private::OPEN_ORDERS, &Empty {}).await
80            }
81        }
82    }
83
84    /// Get closed orders.
85    pub async fn get_closed_orders(
86        &self,
87        request: Option<&ClosedOrdersRequest>,
88    ) -> Result<ClosedOrders, KrakenError> {
89        match request {
90            Some(req) => self.private_post(private::CLOSED_ORDERS, req).await,
91            None => {
92                #[derive(serde::Serialize)]
93                struct Empty {}
94                self.private_post(private::CLOSED_ORDERS, &Empty {}).await
95            }
96        }
97    }
98
99    /// Query specific orders by ID.
100    pub async fn query_orders(
101        &self,
102        request: &QueryOrdersRequest,
103    ) -> Result<std::collections::HashMap<String, Order>, KrakenError> {
104        self.private_post(private::QUERY_ORDERS, request).await
105    }
106
107    /// Get trades history.
108    pub async fn get_trades_history(
109        &self,
110        request: Option<&TradesHistoryRequest>,
111    ) -> Result<TradesHistory, KrakenError> {
112        match request {
113            Some(req) => self.private_post(private::TRADES_HISTORY, req).await,
114            None => {
115                #[derive(serde::Serialize)]
116                struct Empty {}
117                self.private_post(private::TRADES_HISTORY, &Empty {}).await
118            }
119        }
120    }
121
122    /// Get open positions.
123    pub async fn get_open_positions(
124        &self,
125        request: Option<&OpenPositionsRequest>,
126    ) -> Result<std::collections::HashMap<String, Position>, KrakenError> {
127        match request {
128            Some(req) => self.private_post(private::OPEN_POSITIONS, req).await,
129            None => {
130                #[derive(serde::Serialize)]
131                struct Empty {}
132                self.private_post(private::OPEN_POSITIONS, &Empty {}).await
133            }
134        }
135    }
136
137    /// Get ledger entries.
138    pub async fn get_ledgers(
139        &self,
140        request: Option<&LedgersRequest>,
141    ) -> Result<LedgersInfo, KrakenError> {
142        match request {
143            Some(req) => self.private_post(private::LEDGERS, req).await,
144            None => {
145                #[derive(serde::Serialize)]
146                struct Empty {}
147                self.private_post(private::LEDGERS, &Empty {}).await
148            }
149        }
150    }
151
152    /// Get trade volume and fee info.
153    pub async fn get_trade_volume(
154        &self,
155        request: Option<&TradeVolumeRequest>,
156    ) -> Result<TradeVolume, KrakenError> {
157        match request {
158            Some(req) => self.private_post(private::TRADE_VOLUME, req).await,
159            None => {
160                #[derive(serde::Serialize)]
161                struct Empty {}
162                self.private_post(private::TRADE_VOLUME, &Empty {}).await
163            }
164        }
165    }
166
167    // ========== Funding Endpoints ==========
168
169    /// Get available deposit methods for an asset.
170    pub async fn get_deposit_methods(
171        &self,
172        request: &DepositMethodsRequest,
173    ) -> Result<Vec<DepositMethod>, KrakenError> {
174        self.private_post(private::DEPOSIT_METHODS, request).await
175    }
176
177    /// Get deposit addresses for an asset and method.
178    pub async fn get_deposit_addresses(
179        &self,
180        request: &DepositAddressesRequest,
181    ) -> Result<Vec<DepositAddress>, KrakenError> {
182        self.private_post(private::DEPOSIT_ADDRESSES, request).await
183    }
184
185    /// Get deposit status.
186    pub async fn get_deposit_status(
187        &self,
188        request: Option<&DepositStatusRequest>,
189    ) -> Result<DepositWithdrawStatusResponse, KrakenError> {
190        match request {
191            Some(req) => self.private_post(private::DEPOSIT_STATUS, req).await,
192            None => {
193                #[derive(serde::Serialize)]
194                struct Empty {}
195                self.private_post(private::DEPOSIT_STATUS, &Empty {}).await
196            }
197        }
198    }
199
200    /// Get available withdrawal methods.
201    pub async fn get_withdraw_methods(
202        &self,
203        request: Option<&WithdrawMethodsRequest>,
204    ) -> Result<Vec<WithdrawMethod>, KrakenError> {
205        match request {
206            Some(req) => self.private_post(private::WITHDRAW_METHODS, req).await,
207            None => {
208                #[derive(serde::Serialize)]
209                struct Empty {}
210                self.private_post(private::WITHDRAW_METHODS, &Empty {})
211                    .await
212            }
213        }
214    }
215
216    /// Get withdrawal addresses.
217    pub async fn get_withdraw_addresses(
218        &self,
219        request: Option<&WithdrawAddressesRequest>,
220    ) -> Result<Vec<WithdrawalAddress>, KrakenError> {
221        match request {
222            Some(req) => self.private_post(private::WITHDRAW_ADDRESSES, req).await,
223            None => {
224                #[derive(serde::Serialize)]
225                struct Empty {}
226                self.private_post(private::WITHDRAW_ADDRESSES, &Empty {})
227                    .await
228            }
229        }
230    }
231
232    /// Get withdrawal info (limits and fees).
233    pub async fn get_withdraw_info(
234        &self,
235        request: &WithdrawInfoRequest,
236    ) -> Result<WithdrawInfo, KrakenError> {
237        self.private_post(private::WITHDRAW_INFO, request).await
238    }
239
240    /// Withdraw funds.
241    pub async fn withdraw_funds(
242        &self,
243        request: &WithdrawRequest,
244    ) -> Result<ConfirmationRefId, KrakenError> {
245        self.private_post(private::WITHDRAW, request).await
246    }
247
248    /// Get withdrawal status.
249    pub async fn get_withdraw_status(
250        &self,
251        request: Option<&WithdrawStatusRequest>,
252    ) -> Result<DepositWithdrawStatusResponse, KrakenError> {
253        match request {
254            Some(req) => self.private_post(private::WITHDRAW_STATUS, req).await,
255            None => {
256                #[derive(serde::Serialize)]
257                struct Empty {}
258                self.private_post(private::WITHDRAW_STATUS, &Empty {}).await
259            }
260        }
261    }
262
263    /// Cancel a withdrawal.
264    pub async fn withdraw_cancel(
265        &self,
266        request: &WithdrawCancelRequest,
267    ) -> Result<bool, KrakenError> {
268        self.private_post(private::WITHDRAW_CANCEL, request).await
269    }
270
271    /// Transfer funds between wallets (e.g., Spot to Futures).
272    pub async fn wallet_transfer(
273        &self,
274        request: &WalletTransferRequest,
275    ) -> Result<ConfirmationRefId, KrakenError> {
276        self.private_post(private::WALLET_TRANSFER, request).await
277    }
278
279    // ========== Earn Endpoints ==========
280
281    /// Allocate funds to an earn strategy.
282    pub async fn earn_allocate(&self, request: &EarnAllocateRequest) -> Result<bool, KrakenError> {
283        self.private_post(private::EARN_ALLOCATE, request).await
284    }
285
286    /// Deallocate funds from an earn strategy.
287    pub async fn earn_deallocate(
288        &self,
289        request: &EarnAllocateRequest,
290    ) -> Result<bool, KrakenError> {
291        self.private_post(private::EARN_DEALLOCATE, request).await
292    }
293
294    /// Get earn allocation status.
295    pub async fn get_earn_allocation_status(
296        &self,
297        request: &EarnAllocationStatusRequest,
298    ) -> Result<AllocationStatus, KrakenError> {
299        self.private_post(private::EARN_ALLOCATE_STATUS, request)
300            .await
301    }
302
303    /// Get earn deallocation status.
304    pub async fn get_earn_deallocation_status(
305        &self,
306        request: &EarnAllocationStatusRequest,
307    ) -> Result<AllocationStatus, KrakenError> {
308        self.private_post(private::EARN_DEALLOCATE_STATUS, request)
309            .await
310    }
311
312    /// List earn strategies.
313    pub async fn list_earn_strategies(
314        &self,
315        request: Option<&EarnStrategiesRequest>,
316    ) -> Result<EarnStrategies, KrakenError> {
317        match request {
318            Some(req) => self.private_post(private::EARN_STRATEGIES, req).await,
319            None => {
320                #[derive(serde::Serialize)]
321                struct Empty {}
322                self.private_post(private::EARN_STRATEGIES, &Empty {}).await
323            }
324        }
325    }
326
327    /// List earn allocations.
328    pub async fn list_earn_allocations(
329        &self,
330        request: Option<&EarnAllocationsRequest>,
331    ) -> Result<EarnAllocations, KrakenError> {
332        match request {
333            Some(req) => self.private_post(private::EARN_ALLOCATIONS, req).await,
334            None => {
335                #[derive(serde::Serialize)]
336                struct Empty {}
337                self.private_post(private::EARN_ALLOCATIONS, &Empty {})
338                    .await
339            }
340        }
341    }
342
343    /// Add a new order.
344    ///
345    /// # Example
346    ///
347    /// ```rust,no_run
348    /// use kraken_api_client::spot::rest::{SpotRestClient, private::AddOrderRequest};
349    /// use kraken_api_client::{BuySell, OrderType};
350    /// use kraken_api_client::auth::StaticCredentials;
351    /// use rust_decimal::Decimal;
352    /// use std::str::FromStr;
353    /// use std::sync::Arc;
354    ///
355    /// #[tokio::main]
356    /// async fn main() -> Result<(), Box<dyn std::error::Error>> {
357    ///     let credentials = Arc::new(StaticCredentials::new("key", "secret"));
358    ///     let client = SpotRestClient::builder().credentials(credentials).build();
359    ///
360    ///     let request = AddOrderRequest::new(
361    ///         "XBTUSD",
362    ///         BuySell::Buy,
363    ///         OrderType::Limit,
364    ///         Decimal::from_str("0.001")?,
365    ///     )
366    ///     .price(Decimal::from_str("50000")?)
367    ///     .validate(true); // Validate only, don't actually place
368    ///
369    ///     let result = client.add_order(&request).await?;
370    ///     println!("Order result: {:?}", result);
371    ///     Ok(())
372    /// }
373    /// ```
374    pub async fn add_order(
375        &self,
376        request: &AddOrderRequest,
377    ) -> Result<AddOrderResponse, KrakenError> {
378        self.private_post(private::ADD_ORDER, request).await
379    }
380
381    /// Cancel an order.
382    pub async fn cancel_order(
383        &self,
384        request: &CancelOrderRequest,
385    ) -> Result<CancelOrderResponse, KrakenError> {
386        self.private_post(private::CANCEL_ORDER, request).await
387    }
388
389    /// Cancel all open orders.
390    pub async fn cancel_all_orders(&self) -> Result<CancelOrderResponse, KrakenError> {
391        #[derive(serde::Serialize)]
392        struct Empty {}
393        self.private_post(private::CANCEL_ALL, &Empty {}).await
394    }
395
396    /// Get a WebSocket authentication token.
397    ///
398    /// The token is valid for 15 minutes and is used to authenticate
399    /// WebSocket connections to private channels.
400    pub async fn get_websocket_token(&self) -> Result<WebSocketToken, KrakenError> {
401        #[derive(serde::Serialize)]
402        struct Empty {}
403        self.private_post(private::GET_WEBSOCKETS_TOKEN, &Empty {})
404            .await
405    }
406}