Skip to content

Commit

Permalink
Add some integration tests
Browse files Browse the repository at this point in the history
Fix orderbook amount/price to use human readble numbers
Add responses to docs
  • Loading branch information
jordy25519 committed Dec 18, 2023
1 parent 04d76f3 commit 6c1a332
Show file tree
Hide file tree
Showing 5 changed files with 309 additions and 37 deletions.
13 changes: 7 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

108 changes: 107 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,16 +46,70 @@ Options:
Please refer to https://drift-labs.github.io/v2-teacher/ for further examples and reference documentation on various types, fields, and operations available on drift.

### Get Market Info
gets info on all available spot & perp markets
```bash
$ curl localhost:8080/v2/markets
```

**Response**
```json
{
"spot": [
{
"marketIndex": 0,
"symbol": "USDC",
"precision": 6
},
// ...
],
"perp": [
{
"marketIndex": 0,
"symbol": "SOL-PERP",
"precision": 6
},
]
// ...
}
```

### Get Orderbook
gets a full snapshot of the current orderbook
gets a full snapshot of the current orderbook for a given market
```bash
$ curl localhost:8080/v2/orderbook -X GET -H 'content-type: application/json' -d '{"marketIndex":0,"marketType":"perp"}'
```

**Response**
```json
{
"slot": 266118166,
"bids": [
{
"price": "53.616300",
"amount": "7.110000000"
},
{
"price": "47.014300",
"amount": "2.000000000"
},
{
"price": "20.879800",
"amount": "12.160000000"
}
],
"asks": [
{
"price": "80.000000",
"amount": "1.230000000"
},
{
"price": "120.015569",
"amount": "1.000000000"
}
]
}
```

to stream orderbooks via websocket public DLOB servers are available at:
- devnet: `wss://master.dlob.drift.trade/ws`
- mainnet: `wss://dlob.drift.trade/ws`
Expand All @@ -71,6 +125,40 @@ get orders by market
$ curl localhost:8080/v2/orders -X GET -H 'content-type: application/json' -d '{"marketIndex":1,"marketType":"spot"}'
```

**Response**
```json
{
"orders": [
{
"order_type": "limit",
"market_id": 1,
"market_type": "spot",
"amount": "-1.100000000",
"filled": "0.000000000",
"price": "80.500000",
"post_only": true,
"reduce_only": false,
"user_order_id": 101,
"order_id": 35,
"immediate_or_cancel": false
},
{
"order_type": "limit",
"market_id": 0,
"market_type": "perp",
"amount": "-1.230000000",
"filled": "0.000000000",
"price": "80.000000",
"post_only": true,
"reduce_only": false,
"user_order_id": 0,
"order_id": 37,
"immediate_or_cancel": false
}
]
}
```

### Get Positions
get all positions
```bash
Expand All @@ -81,6 +169,24 @@ get positions by market
$ curl localhost:8080/v2/positions -X GET -H 'content-type: application/json' -d '{"marketIndex":0,"marketType":"perp"}'
```

```json
{
"spot": [
{
"amount": "0.400429",
"type": "deposit",
"market_id": 0
},
{
"amount": "9.971961702",
"type": "deposit",
"market_id": 1
}
],
"perp": []
}
```

### Place Orders

- use sub-zero `amount` to indicate sell/offer order
Expand Down
10 changes: 5 additions & 5 deletions src/controller.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::sync::Arc;

use drift_sdk::{
dlob::{DLOBClient, L2Orderbook},
dlob::DLOBClient,
types::{Context, MarketType, ModifyOrderParams, SdkError, SdkResult},
DriftClient, Pubkey, TransactionBuilder, Wallet, WsAccountProvider,
};
Expand All @@ -12,7 +12,7 @@ use thiserror::Error;
use crate::types::{
AllMarketsResponse, CancelAndPlaceRequest, CancelOrdersRequest, GetOrderbookRequest,
GetOrdersRequest, GetOrdersResponse, GetPositionsRequest, GetPositionsResponse,
ModifyOrdersRequest, Order, PlaceOrdersRequest, SpotPosition, TxResponse,
ModifyOrdersRequest, Order, OrderbookL2, PlaceOrdersRequest, SpotPosition, TxResponse,
};

pub type GatewayResult<T> = Result<T, ControllerError>;
Expand Down Expand Up @@ -300,9 +300,9 @@ impl AppState {
.map_err(handle_tx_err)
}

pub async fn get_orderbook(&self, req: GetOrderbookRequest) -> GatewayResult<L2Orderbook> {
let book = self.dlob_client.get_l2(req.market.as_market_id()).await;
Ok(book?)
pub async fn get_orderbook(&self, req: GetOrderbookRequest) -> GatewayResult<OrderbookL2> {
let book = self.dlob_client.get_l2(req.market.as_market_id()).await?;
Ok(OrderbookL2::new(book, req.market, self.context()))
}
}

Expand Down
81 changes: 78 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,20 +193,95 @@ fn handle_deser_error<T>(err: serde_json::Error) -> Either<HttpResponse, Json<T>

#[cfg(test)]
mod tests {
use actix_web::{http::header::ContentType, test, App};
use actix_web::{http::Method, test, App};

use crate::types::Market;

use super::*;

const TEST_ENDPOINT: &str = "https://api.devnet.solana.com";

fn get_seed() -> String {
std::env::var("DRIFT_GATEWAY_KEY")
.expect("DRIFT_GATEWAY_KEY is set")
.to_string()
}

async fn setup_controller() -> AppState {
AppState::new(&get_seed(), TEST_ENDPOINT, true).await
}

#[actix_web::test]
async fn get_orders_works() {
let controller = AppState::new("test", "example.com", true).await;
let controller = setup_controller().await;
let app = test::init_service(
App::new()
.app_data(web::Data::new(controller))
.service(get_orders),
)
.await;
let req = test::TestRequest::default().to_request();
let req = test::TestRequest::default()
.method(Method::GET)
.uri("/orders")
.to_request();

let resp = test::call_service(&app, req).await;
assert!(resp.status().is_success());
}

#[actix_web::test]
async fn get_positions_works() {
let controller = setup_controller().await;
let app = test::init_service(
App::new()
.app_data(web::Data::new(controller))
.service(get_positions),
)
.await;
let req = test::TestRequest::default()
.method(Method::GET)
.uri("/positions")
.to_request();

let resp = test::call_service(&app, req).await;
assert!(resp.status().is_success());
}

#[actix_web::test]
async fn get_orderbook_works() {
let controller = setup_controller().await;
let app = test::init_service(
App::new()
.app_data(web::Data::new(controller))
.service(get_orderbook),
)
.await;
let req = test::TestRequest::default()
.method(Method::GET)
.uri("/orderbook")
.set_json(GetOrderbookRequest {
market: Market::perp(0), // sol-perp
})
.to_request();

let resp = test::call_service(&app, req).await;
assert!(resp.status().is_success());
}

#[actix_web::test]
async fn get_markets_works() {
let controller = setup_controller().await;
let app = test::init_service(
App::new()
.app_data(web::Data::new(controller))
.service(get_markets),
)
.await;
let req = test::TestRequest::default()
.method(Method::GET)
.uri("/markets")
.to_request();

let resp = test::call_service(&app, req).await;
assert!(resp.status().is_success());
}
Expand Down
Loading

0 comments on commit 6c1a332

Please sign in to comment.