Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add get_account_fees() #173

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions src/any_exchange.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ use crate::{
};
use crate::{
model::{
websocket::Subscription, Balance, CancelAllOrdersRequest, CancelOrderRequest, Candle,
GetHistoricRatesRequest, GetHistoricTradesRequest, GetOrderHistoryRequest, GetOrderRequest,
GetPriceTickerRequest, OpenLimitOrderRequest, OpenMarketOrderRequest, Order,
OrderBookRequest, OrderBookResponse, OrderCanceled, Paginator, Ticker, Trade,
websocket::Subscription, AccountFees, Balance, CancelAllOrdersRequest, CancelOrderRequest,
Candle, GetHistoricRatesRequest, GetHistoricTradesRequest, GetOrderHistoryRequest,
GetOrderRequest, GetPriceTickerRequest, OpenLimitOrderRequest, OpenMarketOrderRequest,
Order, OrderBookRequest, OrderBookResponse, OrderCanceled, Paginator, Ticker, Trade,
TradeHistoryRequest,
},
shared::Result,
Expand Down Expand Up @@ -165,6 +165,13 @@ impl ExchangeAccount for AnyExchange {
Self::Coinbase(coinbase) => coinbase.get_account_balances(paginator).await,
}
}
async fn get_account_fees(&self) -> Result<AccountFees> {
match self {
Self::Nash(nash) => nash.get_account_fees().await,
Self::Binance(binance) => binance.get_account_fees().await,
Self::Coinbase(coinbase) => coinbase.get_account_fees().await,
}
}
async fn get_order(&self, req: &GetOrderRequest) -> Result<Order> {
match self {
Self::Nash(nash) => nash.get_order(req).await,
Expand Down
12 changes: 11 additions & 1 deletion src/binance/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
pub mod client;
pub mod model;
mod transport;
use rust_decimal::prelude::*;
use std::convert::TryFrom;

use crate::{
Expand All @@ -10,7 +11,7 @@ use crate::{
exchange::{Exchange, ExchangeMarketData},
exchange_info::{ExchangeInfo, ExchangeInfoRetrieval, MarketPair, MarketPairHandle},
model::{
AskBid, Balance, CancelAllOrdersRequest, CancelOrderRequest, Candle,
AccountFees, AskBid, Balance, CancelAllOrdersRequest, CancelOrderRequest, Candle,
GetHistoricRatesRequest, GetHistoricTradesRequest, GetOrderHistoryRequest, GetOrderRequest,
GetPriceTickerRequest, Interval, Liquidity, OpenLimitOrderRequest, OpenMarketOrderRequest,
Order, OrderBookRequest, OrderBookResponse, OrderCanceled, OrderStatus, OrderType,
Expand Down Expand Up @@ -279,6 +280,15 @@ impl ExchangeAccount for Binance {
.map(|v| v.balances.into_iter().map(Into::into).collect())
}

async fn get_account_fees(&self) -> Result<AccountFees> {
// Binance returns 10 for 0.1%
let coefficient = Decimal::from_i32(10000).unwrap();
self.client.get_account().await.map(|v| AccountFees {
maker: v.maker_commission / coefficient,
taker: v.taker_commission / coefficient,
})
}

async fn get_order(&self, req: &GetOrderRequest) -> Result<Order> {
let pair = req.market_pair.clone().ok_or_else(|| {
OpenLimitsError::MissingParameter("market_pair parameter is required.".to_string())
Expand Down
8 changes: 5 additions & 3 deletions src/binance/model/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
pub mod websocket;
use crate::shared::{string_to_decimal, string_to_opt_decimal};
use crate::shared::{f32_to_decimal, string_to_decimal, string_to_opt_decimal};
use serde::{Deserialize, Serialize};

use rust_decimal::prelude::Decimal;
Expand Down Expand Up @@ -30,8 +30,10 @@ pub struct ExchangeInformation {
#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct AccountInformation {
pub maker_commission: f32,
pub taker_commission: f32,
#[serde(with = "f32_to_decimal")]
pub maker_commission: Decimal,
#[serde(with = "f32_to_decimal")]
pub taker_commission: Decimal,
pub buyer_commission: f32,
pub seller_commission: f32,
pub can_trade: bool,
Expand Down
6 changes: 5 additions & 1 deletion src/coinbase/client/account.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use super::BaseClient;
use crate::{
coinbase::model::{
Account, CancelAllOrders, CancelOrder, Fill, GetFillsReq, GetOrderRequest, Order,
Account, CancelAllOrders, CancelOrder, Fees, Fill, GetFillsReq, GetOrderRequest, Order,
OrderRequest, OrderRequestMarketType, OrderRequestType, OrderSide, OrderTimeInForce,
Paginator,
},
Expand All @@ -16,6 +16,10 @@ impl BaseClient {
self.transport.signed_get("/accounts", paginator).await
}

pub async fn get_fees(&self) -> Result<Fees> {
self.transport.signed_get::<_, ()>("/fees", None).await
}

pub async fn get_orders(&self, params: Option<&GetOrderRequest>) -> Result<Vec<Order>> {
self.transport.signed_get::<_, _>("/orders", params).await
}
Expand Down
15 changes: 14 additions & 1 deletion src/coinbase/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::{
exchange_info::ExchangeInfo,
exchange_info::{ExchangeInfoRetrieval, MarketPair, MarketPairHandle},
model::{
AskBid, Balance, CancelAllOrdersRequest, CancelOrderRequest, Candle,
AccountFees, AskBid, Balance, CancelAllOrdersRequest, CancelOrderRequest, Candle,
GetHistoricRatesRequest, GetHistoricTradesRequest, GetOrderHistoryRequest, GetOrderRequest,
GetPriceTickerRequest, Interval, Liquidity, OpenLimitOrderRequest, OpenMarketOrderRequest,
Order, OrderBookRequest, OrderBookResponse, OrderCanceled, OrderStatus, OrderType,
Expand Down Expand Up @@ -160,6 +160,15 @@ impl From<model::Book<model::BookRecordL2>> for OrderBookResponse {
}
}

impl From<model::Fees> for AccountFees {
fn from(fees: model::Fees) -> Self {
Self {
maker: fees.maker_fee_rate,
taker: fees.taker_fee_rate,
}
}
}

impl From<model::BookRecordL2> for AskBid {
fn from(bids: model::BookRecordL2) -> Self {
Self {
Expand Down Expand Up @@ -293,6 +302,10 @@ impl ExchangeAccount for Coinbase {
.map(|v| v.into_iter().map(Into::into).collect())
}

async fn get_account_fees(&self) -> Result<AccountFees> {
self.client.get_fees().await.map(Into::into)
}

async fn get_order(&self, req: &GetOrderRequest) -> Result<Order> {
let id = req.id.clone();

Expand Down
10 changes: 10 additions & 0 deletions src/coinbase/model/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,16 @@ pub struct Account {
pub profile_id: String,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Fees {
#[serde(with = "string_to_decimal")]
pub maker_fee_rate: Decimal,
#[serde(with = "string_to_decimal")]
pub taker_fee_rate: Decimal,
#[serde(with = "string_to_decimal")]
pub usd_volume: Decimal,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Candle {
pub time: u64,
Expand Down
10 changes: 6 additions & 4 deletions src/exchange.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ use async_trait::async_trait;
use crate::exchange_info::ExchangeInfoRetrieval;
use crate::{
model::{
Balance, CancelAllOrdersRequest, CancelOrderRequest, Candle, GetHistoricRatesRequest,
GetHistoricTradesRequest, GetOrderHistoryRequest, GetOrderRequest, GetPriceTickerRequest,
OpenLimitOrderRequest, OpenMarketOrderRequest, Order, OrderBookRequest, OrderBookResponse,
OrderCanceled, Paginator, Ticker, Trade, TradeHistoryRequest,
AccountFees, Balance, CancelAllOrdersRequest, CancelOrderRequest, Candle,
GetHistoricRatesRequest, GetHistoricTradesRequest, GetOrderHistoryRequest, GetOrderRequest,
GetPriceTickerRequest, OpenLimitOrderRequest, OpenMarketOrderRequest, Order,
OrderBookRequest, OrderBookResponse, OrderCanceled, Paginator, Ticker, Trade,
TradeHistoryRequest,
},
shared::Result,
};
Expand Down Expand Up @@ -47,5 +48,6 @@ pub trait ExchangeAccount {
async fn get_order_history(&self, req: &GetOrderHistoryRequest) -> Result<Vec<Order>>;
async fn get_trade_history(&self, req: &TradeHistoryRequest) -> Result<Vec<Trade>>;
async fn get_account_balances(&self, paginator: Option<Paginator>) -> Result<Vec<Balance>>;
async fn get_account_fees(&self) -> Result<AccountFees>;
async fn get_order(&self, req: &GetOrderRequest) -> Result<Order>;
}
6 changes: 6 additions & 0 deletions src/model/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,12 @@ pub enum Liquidity {
Taker,
}

#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct AccountFees {
pub maker: Decimal,
pub taker: Decimal,
}

#[derive(Serialize, Deserialize, Default)]
pub struct TradeHistoryRequest {
pub market_pair: Option<String>,
Expand Down
10 changes: 9 additions & 1 deletion src/nash/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::{
model::websocket::OpenLimitsWebSocketMessage,
model::{
websocket::{Subscription, WebSocketResponse},
AskBid, Balance, CancelAllOrdersRequest, CancelOrderRequest, Candle,
AccountFees, AskBid, Balance, CancelAllOrdersRequest, CancelOrderRequest, Candle,
GetHistoricRatesRequest, GetHistoricTradesRequest, GetOrderHistoryRequest, GetOrderRequest,
GetPriceTickerRequest, Interval, Liquidity, OpenLimitOrderRequest, OpenMarketOrderRequest,
Order, OrderBookRequest, OrderBookResponse, OrderCanceled, OrderStatus, OrderType,
Expand Down Expand Up @@ -217,6 +217,14 @@ impl ExchangeAccount for Nash {
Ok(balances)
}

async fn get_account_fees(&self) -> Result<AccountFees> {
Err(OpenLimitsError::MissingImplementation(
MissingImplementationContent {
message: "'get_account_fees' for nash is not implemented".to_string(),
},
))
}

async fn get_all_open_orders(&self) -> Result<Vec<Order>> {
let req = nash_protocol::protocol::list_account_orders::ListAccountOrdersRequest {
market: Default::default(),
Expand Down
32 changes: 32 additions & 0 deletions src/shared.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,37 @@
pub type Result<T> = std::result::Result<T, crate::errors::OpenLimitsError>;

pub mod f32_to_decimal {
use std::fmt;

use rust_decimal::prelude::*;
use serde::{de, Deserialize, Deserializer, Serializer};

pub fn serialize<T, S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
where
T: fmt::Display,
S: Serializer,
{
serializer.collect_str(value)
}

pub fn deserialize<'de, D>(deserializer: D) -> Result<Decimal, D::Error>
where
D: Deserializer<'de>,
{
#[derive(Deserialize)]
#[serde(untagged)]
enum F32ToDecimal {
F32(f32),
}

let F32ToDecimal::F32(val) = F32ToDecimal::deserialize(deserializer)?;
Decimal::from_f32(val).ok_or(de::Error::custom(format!(
"Failed to convert {} to Decimal",
val
)))
}
}

pub mod string_to_decimal {
use std::fmt;

Expand Down
26 changes: 21 additions & 5 deletions tests/binance/account.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use dotenv::dotenv;
use std::env;

use openlimits::exchange::ExchangeMarketData;
use openlimits::model::GetPriceTickerRequest;
use openlimits::{
binance::Binance,
binance::BinanceCredentials,
Expand All @@ -12,8 +14,6 @@ use openlimits::{
},
};
use rust_decimal::prelude::Decimal;
use openlimits::exchange::ExchangeMarketData;
use openlimits::model::GetPriceTickerRequest;

#[tokio::test]
#[ignore]
Expand Down Expand Up @@ -179,8 +179,13 @@ async fn get_order_history() {
}

async fn get_price(exchange: &Binance, pair: &str) -> Decimal {
let get_price_ticker_request = GetPriceTickerRequest { market_pair: pair.to_string() };
let ticker = exchange.get_price_ticker(&get_price_ticker_request).await.expect("Couldn't get ticker.");
let get_price_ticker_request = GetPriceTickerRequest {
market_pair: pair.to_string(),
};
let ticker = exchange
.get_price_ticker(&get_price_ticker_request)
.await
.expect("Couldn't get ticker.");
ticker.price.expect("Couldn't get price.")
}

Expand Down Expand Up @@ -214,7 +219,18 @@ async fn get_account_balances() {
let resp = exchange
.get_account_balances(None)
.await
.expect("Couldn't get acount balances.");
.expect("Couldn't get account balances.");
println!("{:?}", resp);
}

#[tokio::test]
async fn get_account_fees() {
let exchange = init().await;

let resp = exchange
.get_account_fees()
.await
.expect("couldn't get account fees.");
println!("{:?}", resp);
}

Expand Down
11 changes: 11 additions & 0 deletions tests/coinbase/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,17 @@ async fn get_account_balances() {
println!("{:?}", resp);
}

#[tokio::test]
async fn get_account_fees() {
let exchange = init().await;

let resp = exchange
.get_account_fees()
.await
.expect("couldn't get account fees.");
println!("{:?}", resp);
}

#[tokio::test]
async fn get_trade_history() {
let exchange = init().await;
Expand Down
11 changes: 11 additions & 0 deletions tests/nash/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,17 @@ async fn get_account_balances() {
println!("{:?}", resp);
}

#[tokio::test]
async fn get_account_fees() {
let exchange = init().await;

let resp = exchange
.get_account_fees()
.await
.expect("couldn't get account fees.");
println!("{:?}", resp);
}

#[tokio::test]
async fn get_trade_history() {
let exchange = init().await;
Expand Down