use crate::core::types::{AccountType, Symbol};
pub struct CoinbaseUrls;
impl CoinbaseUrls {
pub fn base_url() -> &'static str {
"https://api.coinbase.com/api/v3/brokerage"
}
pub fn v2_url() -> &'static str {
"https://api.coinbase.com/v2"
}
pub fn market_url() -> &'static str {
"https://api.coinbase.com/api/v3/brokerage/market"
}
pub fn ws_public_url() -> &'static str {
"wss://advanced-trade-ws.coinbase.com"
}
pub fn ws_user_url() -> &'static str {
"wss://advanced-trade-ws-user.coinbase.com"
}
pub fn ws_url(authenticated: bool) -> &'static str {
if authenticated {
Self::ws_user_url()
} else {
Self::ws_public_url()
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum CoinbaseEndpoint {
ServerTime, Products, ProductDetails, BestBidAsk, ProductBook, Candles, MarketTrades,
Accounts, AccountDetails, TransactionSummary,
CreateOrder, CancelOrders, EditOrder, OrderDetails, ListOrders, ListFills, FillHistory, PreviewOrder,
V2AccountDeposits, V2AccountTransactions, V2CreateAddress, V2SendTransaction, }
impl CoinbaseEndpoint {
pub fn path(&self) -> &'static str {
match self {
Self::ServerTime => "/time",
Self::Products => "/products",
Self::ProductDetails => "/products", Self::BestBidAsk => "/best_bid_ask",
Self::ProductBook => "/product_book",
Self::Candles => "/products", Self::MarketTrades => "/products",
Self::Accounts => "/accounts",
Self::AccountDetails => "/accounts", Self::TransactionSummary => "/transaction_summary",
Self::CreateOrder => "/orders",
Self::CancelOrders => "/orders/batch_cancel",
Self::EditOrder => "/orders/edit",
Self::OrderDetails => "/orders/historical", Self::ListOrders => "/orders/historical/batch",
Self::ListFills => "/orders/historical/fills",
Self::FillHistory => "/orders/historical/fills",
Self::PreviewOrder => "/orders/preview",
Self::V2AccountDeposits => "/accounts/{account_id}/deposits",
Self::V2AccountTransactions => "/accounts/{account_id}/transactions",
Self::V2CreateAddress => "/accounts/{account_id}/addresses",
Self::V2SendTransaction => "/accounts/{account_id}/transactions",
}
}
pub fn method(&self) -> &'static str {
match self {
Self::CreateOrder
| Self::CancelOrders
| Self::EditOrder
| Self::PreviewOrder
| Self::V2CreateAddress
| Self::V2SendTransaction => "POST",
_ => "GET",
}
}
pub fn is_private(&self) -> bool {
match self {
Self::ServerTime => false,
_ => true,
}
}
pub fn is_v2(&self) -> bool {
matches!(
self,
Self::V2AccountDeposits
| Self::V2AccountTransactions
| Self::V2CreateAddress
| Self::V2SendTransaction
)
}
pub fn has_public_alternative(&self) -> bool {
matches!(
self,
Self::Products | Self::ProductDetails | Self::ProductBook | Self::Candles | Self::MarketTrades
)
}
pub fn market_path(&self) -> Option<&'static str> {
match self {
Self::Products => Some("/products"),
Self::ProductDetails => Some("/products"), Self::ProductBook => Some("/product_book"),
Self::Candles => Some("/products"), Self::MarketTrades => Some("/products"), _ => None,
}
}
}
pub fn format_symbol(symbol: &Symbol, account_type: AccountType) -> String {
match account_type {
AccountType::Spot => {
format!("{}-{}", symbol.base.to_uppercase(), symbol.quote.to_uppercase())
}
AccountType::FuturesCross | AccountType::FuturesIsolated => {
format!("{}-PERP", symbol.base.to_uppercase())
}
_ => {
format!("{}-{}", symbol.base.to_uppercase(), symbol.quote.to_uppercase())
}
}
}
pub fn parse_symbol(product_id: &str) -> (String, String) {
let parts: Vec<&str> = product_id.split('-').collect();
if parts.len() == 2 {
(parts[0].to_string(), parts[1].to_string())
} else {
("".to_string(), "".to_string())
}
}
pub fn is_perpetual(product_id: &str) -> bool {
product_id.ends_with("-PERP")
}
pub fn map_kline_interval(interval: &str) -> &'static str {
match interval {
"1m" => "ONE_MINUTE",
"5m" => "FIVE_MINUTE",
"15m" => "FIFTEEN_MINUTE",
"30m" => "THIRTY_MINUTE",
"1h" => "ONE_HOUR",
"2h" => "TWO_HOUR",
"6h" => "SIX_HOUR",
"1d" => "ONE_DAY",
_ => "ONE_HOUR", }
}
pub fn granularity_to_seconds(granularity: &str) -> u64 {
match granularity {
"ONE_MINUTE" => 60,
"FIVE_MINUTE" => 300,
"FIFTEEN_MINUTE" => 900,
"THIRTY_MINUTE" => 1800,
"ONE_HOUR" => 3600,
"TWO_HOUR" => 7200,
"SIX_HOUR" => 21600,
"ONE_DAY" => 86400,
_ => 3600,
}
}