Skip to content

Commit a859380

Browse files
committed
Feat/collateral
* add user collateral endpoint
1 parent 8c51e57 commit a859380

File tree

6 files changed

+66
-5
lines changed

6 files changed

+66
-5
lines changed

Cargo.lock

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ edition = "2021"
66
[dependencies]
77
actix-web = "4.4.0"
88
argh = "0.1.12"
9-
drift-sdk = { git = "https://github.com/drift-labs/drift-rs", rev = "8384f6" }
9+
drift-sdk = { git = "https://github.com/drift-labs/drift-rs", rev = "6749bcd" }
1010
env_logger = "0.10.1"
1111
futures-util = "0.3.29"
1212
log = "0.4.20"

README.md

+17
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ Self hosted API gateway to easily interact with Drift V2 Protocol
2121
- [`GET` SOL Balance](#get-sol-balance)
2222
- [`GET` Margin Info](#get-margin-info)
2323
- [`GET` Leverage](#get-leverage)
24+
- [`GET` Collateral](#get-collateral)
2425
- [`POST` Place Orders](#place-orders)
2526
- [`PATCH` Modify Orders](#modify-orders)
2627
- [`DELETE` Cancel Orders](#cancel-orders)
@@ -225,6 +226,22 @@ $ curl localhost:8080/v2/leverage
225226
}
226227
```
227228

229+
## Get Collateral
230+
Returns the account's maintenance collateral
231+
232+
```bash
233+
$ curl localhost:8080/v2/collateral
234+
```
235+
236+
**Response**
237+
238+
```json
239+
{
240+
"total":"1661.195815",
241+
"free":"1653.531255"
242+
}
243+
```
244+
228245
## Get Market Info
229246

230247
Returns market details (perps only)

src/controller.rs

+19-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ use drift_sdk::{
44
dlob_client::DLOBClient,
55
event_subscriber::{try_parse_log, CommitmentConfig},
66
math::liquidation::{
7-
calculate_liquidation_price_and_unrealized_pnl, calculate_margin_requirements,
7+
calculate_collateral, calculate_liquidation_price_and_unrealized_pnl,
8+
calculate_margin_requirements, MarginCategory,
89
},
910
types::{
1011
self, MarketId, MarketType, ModifyOrderParams, RpcSendTransactionConfig, SdkError,
@@ -21,13 +22,14 @@ use solana_transaction_status::{option_serializer::OptionSerializer, UiTransacti
2122
use std::{borrow::Cow, str::FromStr, sync::Arc};
2223
use thiserror::Error;
2324

25+
use crate::types::UserCollateralResponse;
2426
use crate::{
2527
types::{
2628
get_market_decimals, AllMarketsResponse, CancelAndPlaceRequest, CancelOrdersRequest,
2729
GetOrderbookRequest, GetOrdersRequest, GetOrdersResponse, GetPositionsRequest,
2830
GetPositionsResponse, Market, MarketInfoResponse, ModifyOrdersRequest, Order, OrderbookL2,
2931
PerpPosition, PerpPositionExtended, PlaceOrdersRequest, SolBalanceResponse, SpotPosition,
30-
TxEventsResponse, TxResponse, UserMarginResponse, UserLeverageResponse, PRICE_DECIMALS,
32+
TxEventsResponse, TxResponse, UserLeverageResponse, UserMarginResponse, PRICE_DECIMALS,
3133
},
3234
websocket::map_drift_event_for_account,
3335
Context, LOG_TARGET,
@@ -227,6 +229,21 @@ impl AppState {
227229
.map_err(|err| ControllerError::Sdk(err))
228230
}
229231

232+
pub async fn get_collateral(
233+
&self,
234+
ctx: Context,
235+
margin_category: Option<MarginCategory>,
236+
) -> GatewayResult<UserCollateralResponse> {
237+
let sub_account = self.resolve_sub_account(ctx.sub_account_id);
238+
calculate_collateral(
239+
&self.client,
240+
&self.client.get_user_account(&sub_account).await?,
241+
margin_category.unwrap_or(MarginCategory::Maintenance),
242+
)
243+
.map(Into::into)
244+
.map_err(|err| ControllerError::Sdk(err))
245+
}
246+
230247
pub async fn get_position_extended(
231248
&self,
232249
ctx: Context,

src/main.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,14 @@ async fn get_leverage(controller: web::Data<AppState>, ctx: web::Query<Context>)
197197
handle_result(controller.get_leverage(ctx.0).await)
198198
}
199199

200+
#[get("/collateral")]
201+
async fn get_collateral(
202+
controller: web::Data<AppState>,
203+
ctx: web::Query<Context>,
204+
) -> impl Responder {
205+
handle_result(controller.get_collateral(ctx.0, None).await)
206+
}
207+
200208
#[actix_web::main]
201209
async fn main() -> std::io::Result<()> {
202210
let config: GatewayConfig = argh::from_env();
@@ -283,7 +291,8 @@ async fn main() -> std::io::Result<()> {
283291
.service(get_tx_events)
284292
.service(get_market_info)
285293
.service(get_margin_info)
286-
.service(get_leverage),
294+
.service(get_leverage)
295+
.service(get_collateral),
287296
)
288297
})
289298
.keep_alive(Duration::from_secs(config.keep_alive_timeout as u64))

src/types.rs

+18
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
//! - gateway request/responses
33
//! - wrappers for presenting drift program types with less implementation detail
44
//!
5+
use drift_sdk::constants::QUOTE_PRECISION;
6+
use drift_sdk::math::liquidation::CollateralInfo;
57
use drift_sdk::{
68
constants::{ProgramData, BASE_PRECISION, PRICE_PRECISION},
79
dlob_client::{L2Level, L2Orderbook},
@@ -18,6 +20,7 @@ use crate::websocket::AccountEvent;
1820

1921
/// decimal places in price values
2022
pub const PRICE_DECIMALS: u32 = PRICE_PRECISION.ilog10();
23+
pub const QUOTE_DECIMALS: u32 = QUOTE_PRECISION.ilog10();
2124

2225
#[derive(Serialize, Deserialize, Debug)]
2326
#[serde(rename_all = "camelCase")]
@@ -629,6 +632,21 @@ impl From<u128> for UserLeverageResponse {
629632
}
630633
}
631634

635+
#[derive(Serialize, Debug)]
636+
pub struct UserCollateralResponse {
637+
pub total: Decimal,
638+
pub free: Decimal,
639+
}
640+
641+
impl From<CollateralInfo> for UserCollateralResponse {
642+
fn from(value: CollateralInfo) -> Self {
643+
Self {
644+
total: Decimal::from_i128_with_scale(value.total, QUOTE_DECIMALS).normalize(),
645+
free: Decimal::from_i128_with_scale(value.free, QUOTE_DECIMALS).normalize(),
646+
}
647+
}
648+
}
649+
632650
#[cfg(test)]
633651
mod tests {
634652
use drift_sdk::{

0 commit comments

Comments
 (0)