1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
//! # Coinbase Advanced Fee API
//!
//! `fee` gives access to the Fee API and the various endpoints associated with it.
//! Currently the only endpoint available is the Transaction Summary endpoint.
use crate::signer::Signer;
use crate::utils::{CBAdvError, Result};
use serde::{Deserialize, Serialize};
use serde_with::{serde_as, DisplayFromStr};
use std::fmt;
/// Pricing tier for user, determined by notional (USD) volume.
#[serde_as]
#[derive(Deserialize, Debug)]
pub struct FeeTier {
/// Current fee teir for the user.
pub pricing_tier: String,
/// Lower bound (inclusive) of pricing tier in notional volume.
#[serde_as(as = "DisplayFromStr")]
pub usd_from: u32,
/// Upper bound (exclusive) of pricing tier in notional volume.
#[serde_as(as = "DisplayFromStr")]
pub usd_to: u32,
/// Taker fee rate, applied if the order takes liquidity.
#[serde_as(as = "DisplayFromStr")]
pub taker_fee_rate: f64,
/// Maker fee rate, applied if the order creates liquidity.
#[serde_as(as = "DisplayFromStr")]
pub maker_fee_rate: f64,
}
/// Represents a decimal number with precision.
#[serde_as]
#[derive(Deserialize, Debug)]
pub struct MarginRate {
/// Value of the margin rate.
#[serde_as(as = "DisplayFromStr")]
pub value: f64,
}
// Represents a Tax.
#[serde_as]
#[derive(Deserialize, Debug)]
pub struct Tax {
/// Amount of tax.
#[serde_as(as = "DisplayFromStr")]
pub value: f64,
/// Type of tax. Possible values: [INCLUSIVE, EXCLUSIVE]
pub r#type: String,
}
/// Represents the transaction summary for fees received from the API.
#[derive(Deserialize, Debug)]
pub struct TransactionSummary {
/// Total volume across assets, denoted in USD.
pub total_volume: f64,
/// Total fees across assets, denoted in USD.
pub total_fees: f64,
/// Fee tier for the summary.
pub fee_tier: FeeTier,
/// Margin rate for the summary.
pub margin_rate: Option<MarginRate>,
/// Goods and Services Tax rate.
pub goods_and_services_tax: Option<Tax>,
/// Advanced Trade volume (non-inclusive of Pro) across assets, denoted in USD.
pub advanced_trade_only_volume: f64,
/// Advanced Trade fees (non-inclusive of Pro) across assets, denoted in USD.
pub advanced_trade_only_fees: f64,
/// Coinbase Pro volume across assets, denoted in USD.
pub coinbase_pro_volume: f64,
/// Coinbase Pro fees across assets, denoted in USD.
pub coinbase_pro_fees: f64,
}
/// Represents parameters that are optional for transaction summary API request.
#[derive(Serialize, Default, Debug)]
pub struct TransactionSummaryQuery {
/// Start date for the summary.
pub start_date: Option<String>,
/// End date for the summary.
pub end_date: Option<String>,
/// String of the users native currency, default is USD.
pub user_native_currency: Option<String>,
/// Type of products to return. Valid options: SPOT or FUTURE
pub product_type: Option<String>,
}
impl fmt::Display for TransactionSummaryQuery {
/// Converts the object into HTTP request parameters.
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut query: String = "".to_string();
query = match &self.start_date {
Some(v) => format!("{}&start_date={}", query, v),
_ => query,
};
query = match &self.end_date {
Some(v) => format!("{}&end_date={}", query, v),
_ => query,
};
query = match &self.user_native_currency {
Some(v) => format!("{}&user_native_currency={}", query, v),
_ => query,
};
query = match &self.product_type {
Some(v) => format!("{}&product_type={}", query, v),
_ => query,
};
match query.is_empty() {
true => write!(f, ""),
false => write!(f, "{}", query[1..].to_string()),
}
}
}
/// Provides access to the Fee API for the service.
pub struct FeeAPI {
/// Object used to sign requests made to the API.
signer: Signer,
}
impl FeeAPI {
/// Resource for the API.
const RESOURCE: &str = "/api/v3/brokerage/transaction_summary";
/// Creates a new instance of the Fee API. This grants access to product information.
///
/// # Arguments
///
/// * `signer` - A Signer that include the API Key & Secret along with a client to make
/// requests.
pub(crate) fn new(signer: Signer) -> Self {
Self { signer }
}
/// Obtains fee transaction summary from the API.
///
/// # Arguments
///
/// * `query` - Optional paramaters used to modify the resulting scope of the
/// summary.
///
/// # Endpoint / Reference
///
#[allow(rustdoc::bare_urls)]
/// https://api.coinbase.com/api/v3/brokerage/transaction_summary
///
/// <https://docs.cloud.coinbase.com/advanced-trade-api/reference/retailbrokerageapi_gettransactionsummary>
pub async fn get(&self, query: &TransactionSummaryQuery) -> Result<TransactionSummary> {
match self.signer.get(Self::RESOURCE, &query.to_string()).await {
Ok(value) => match value.json::<TransactionSummary>().await {
Ok(resp) => Ok(resp),
Err(_) => Err(CBAdvError::BadParse("fee summary object".to_string())),
},
Err(error) => Err(error),
}
}
}