-
Notifications
You must be signed in to change notification settings - Fork 257
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
zcash_client_backend: Add exchanges we know how to query for USD/ZEC
Currently only unauthenticated connections are supported (i.e. no API keys can be configured). However, AFAICT none of these exchanges provide non-IP-based rate limits for authenticated connections to public APIs, so authentication wouldn't help to make connections over Tor more reliable.
- Loading branch information
Showing
7 changed files
with
379 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
use async_trait::async_trait; | ||
use rust_decimal::Decimal; | ||
use serde::Deserialize; | ||
|
||
use super::{Exchange, ExchangeData}; | ||
use crate::tor::{Client, Error}; | ||
|
||
/// Querier for the Binance exchange. | ||
pub struct Binance { | ||
_private: (), | ||
} | ||
|
||
impl Binance { | ||
/// Prepares for unauthenticated connections to Binance. | ||
pub fn unauthenticated() -> Self { | ||
Self { _private: () } | ||
} | ||
} | ||
|
||
#[derive(Clone, Debug, Deserialize)] | ||
#[allow(dead_code)] | ||
#[allow(non_snake_case)] | ||
struct BinanceData { | ||
symbol: String, | ||
priceChange: Decimal, | ||
priceChangePercent: Decimal, | ||
weightedAvgPrice: Decimal, | ||
prevClosePrice: Decimal, | ||
lastPrice: Decimal, | ||
lastQty: Decimal, | ||
bidPrice: Decimal, | ||
bidQty: Decimal, | ||
askPrice: Decimal, | ||
askQty: Decimal, | ||
openPrice: Decimal, | ||
highPrice: Decimal, | ||
lowPrice: Decimal, | ||
volume: Decimal, | ||
quoteVolume: Decimal, | ||
openTime: u64, | ||
closeTime: u64, | ||
firstId: u32, | ||
lastId: u32, | ||
count: u32, | ||
} | ||
|
||
#[async_trait] | ||
impl Exchange for Binance { | ||
async fn query_zec_to_usd(&self, client: &Client) -> Result<ExchangeData, Error> { | ||
// API documentation: | ||
// https://binance-docs.github.io/apidocs/spot/en/#24hr-ticker-price-change-statistics | ||
let res = client | ||
.get_json::<BinanceData>( | ||
"https://api.binance.com/api/v3/ticker/24hr?symbol=ZECUSDT" | ||
.parse() | ||
.unwrap(), | ||
) | ||
.await?; | ||
let data = res.into_body(); | ||
Ok(ExchangeData { | ||
bid: data.bidPrice, | ||
ask: data.askPrice, | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
use async_trait::async_trait; | ||
use rust_decimal::Decimal; | ||
use serde::Deserialize; | ||
|
||
use super::{Exchange, ExchangeData}; | ||
use crate::tor::{Client, Error}; | ||
|
||
/// Querier for the Coinbase exchange. | ||
pub struct Coinbase { | ||
_private: (), | ||
} | ||
|
||
impl Coinbase { | ||
/// Prepares for unauthenticated connections to Coinbase. | ||
pub fn unauthenticated() -> Self { | ||
Self { _private: () } | ||
} | ||
} | ||
|
||
#[derive(Debug, Deserialize)] | ||
#[allow(dead_code)] | ||
struct CoinbaseData { | ||
ask: Decimal, | ||
bid: Decimal, | ||
volume: Decimal, | ||
trade_id: u32, | ||
price: Decimal, | ||
size: Decimal, | ||
time: String, | ||
rfq_volume: Option<Decimal>, | ||
conversions_volume: Option<Decimal>, | ||
} | ||
|
||
#[async_trait] | ||
impl Exchange for Coinbase { | ||
#[allow(dead_code)] | ||
async fn query_zec_to_usd(&self, client: &Client) -> Result<ExchangeData, Error> { | ||
// API documentation: | ||
// https://docs.cdp.coinbase.com/exchange/reference/exchangerestapi_getproductticker | ||
let res = client | ||
.get_json::<CoinbaseData>( | ||
"https://api.exchange.coinbase.com/products/ZEC-USD/ticker" | ||
.parse() | ||
.unwrap(), | ||
) | ||
.await?; | ||
let data = res.into_body(); | ||
Ok(ExchangeData { | ||
bid: data.bid, | ||
ask: data.ask, | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
use async_trait::async_trait; | ||
use hyper::StatusCode; | ||
use rust_decimal::Decimal; | ||
use serde::Deserialize; | ||
|
||
use super::{Exchange, ExchangeData}; | ||
use crate::tor::{Client, Error}; | ||
|
||
/// Querier for the Gate.io exchange. | ||
pub struct GateIo { | ||
_private: (), | ||
} | ||
|
||
impl GateIo { | ||
/// Prepares for unauthenticated connections to Gate.io. | ||
pub fn unauthenticated() -> Self { | ||
Self { _private: () } | ||
} | ||
} | ||
|
||
#[derive(Debug, Deserialize)] | ||
#[allow(dead_code)] | ||
struct GateIoData { | ||
currency_pair: String, | ||
last: Decimal, | ||
lowest_ask: Decimal, | ||
highest_bid: Decimal, | ||
change_percentage: Decimal, | ||
base_volume: Decimal, | ||
quote_volume: Decimal, | ||
high_24h: Decimal, | ||
low_24h: Decimal, | ||
} | ||
|
||
#[async_trait] | ||
impl Exchange for GateIo { | ||
async fn query_zec_to_usd(&self, client: &Client) -> Result<ExchangeData, Error> { | ||
// API documentation: | ||
// https://www.gate.io/docs/developers/apiv4/#retrieve-ticker-information | ||
let res = client | ||
.get_json::<Vec<GateIoData>>( | ||
"https://api.gateio.ws/api/v4/spot/tickers?currency_pair=ZEC_USDT" | ||
.parse() | ||
.unwrap(), | ||
) | ||
.await?; | ||
let data = res.into_body().into_iter().next().ok_or(Error::Http( | ||
super::super::HttpError::Unsuccessful(StatusCode::GONE), | ||
))?; | ||
|
||
Ok(ExchangeData { | ||
bid: data.highest_bid, | ||
ask: data.lowest_ask, | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
use async_trait::async_trait; | ||
use rust_decimal::Decimal; | ||
use serde::Deserialize; | ||
|
||
use super::{Exchange, ExchangeData}; | ||
use crate::tor::{Client, Error}; | ||
|
||
/// Querier for the Gemini exchange. | ||
pub struct Gemini { | ||
_private: (), | ||
} | ||
|
||
impl Gemini { | ||
/// Prepares for unauthenticated connections to Gemini. | ||
pub fn unauthenticated() -> Self { | ||
Self { _private: () } | ||
} | ||
} | ||
|
||
#[derive(Debug, Deserialize)] | ||
#[allow(dead_code)] | ||
struct GeminiData { | ||
symbol: String, | ||
open: Decimal, | ||
high: Decimal, | ||
low: Decimal, | ||
close: Decimal, | ||
changes: Vec<Decimal>, | ||
bid: Decimal, | ||
ask: Decimal, | ||
} | ||
|
||
#[async_trait] | ||
impl Exchange for Gemini { | ||
async fn query_zec_to_usd(&self, client: &Client) -> Result<ExchangeData, Error> { | ||
// API documentation: | ||
// https://docs.gemini.com/rest-api/#ticker-v2 | ||
let res = client | ||
.get_json::<GeminiData>("https://api.gemini.com/v2/ticker/zecusd".parse().unwrap()) | ||
.await?; | ||
let data = res.into_body(); | ||
Ok(ExchangeData { | ||
bid: data.bid, | ||
ask: data.ask, | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
use async_trait::async_trait; | ||
use rust_decimal::Decimal; | ||
use serde::Deserialize; | ||
|
||
use super::{Exchange, ExchangeData}; | ||
use crate::tor::{Client, Error}; | ||
|
||
/// Querier for the KuCoin exchange. | ||
pub struct KuCoin { | ||
_private: (), | ||
} | ||
|
||
impl KuCoin { | ||
/// Prepares for unauthenticated connections to KuCoin. | ||
pub fn unauthenticated() -> Self { | ||
Self { _private: () } | ||
} | ||
} | ||
|
||
#[derive(Debug, Deserialize)] | ||
#[allow(dead_code)] | ||
#[allow(non_snake_case)] | ||
struct KuCoinData { | ||
time: u64, | ||
symbol: String, | ||
buy: Decimal, | ||
sell: Decimal, | ||
changeRate: Decimal, | ||
changePrice: Decimal, | ||
high: Decimal, | ||
low: Decimal, | ||
vol: Decimal, | ||
volValue: Decimal, | ||
last: Decimal, | ||
averagePrice: Decimal, | ||
takerFeeRate: Decimal, | ||
makerFeeRate: Decimal, | ||
takerCoefficient: Decimal, | ||
makerCoefficient: Decimal, | ||
} | ||
|
||
#[derive(Debug, Deserialize)] | ||
#[allow(dead_code)] | ||
struct KuCoinResponse { | ||
code: String, | ||
data: KuCoinData, | ||
} | ||
|
||
#[async_trait] | ||
impl Exchange for KuCoin { | ||
async fn query_zec_to_usd(&self, client: &Client) -> Result<ExchangeData, Error> { | ||
// API documentation: | ||
// https://www.kucoin.com/docs/rest/spot-trading/market-data/get-24hr-stats | ||
let res = client | ||
.get_json::<KuCoinResponse>( | ||
"https://api.kucoin.com/api/v1/market/stats?symbol=ZEC-USDT" | ||
.parse() | ||
.unwrap(), | ||
) | ||
.await?; | ||
let data = res.into_body().data; | ||
Ok(ExchangeData { | ||
bid: data.buy, | ||
ask: data.sell, | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
use async_trait::async_trait; | ||
use rust_decimal::Decimal; | ||
use serde::Deserialize; | ||
|
||
use super::{Exchange, ExchangeData}; | ||
use crate::tor::{Client, Error}; | ||
|
||
/// Querier for the MEXC exchange. | ||
pub struct Mexc { | ||
_private: (), | ||
} | ||
|
||
impl Mexc { | ||
/// Prepares for unauthenticated connections to MEXC. | ||
pub fn unauthenticated() -> Self { | ||
Self { _private: () } | ||
} | ||
} | ||
|
||
#[derive(Debug, Deserialize)] | ||
#[allow(dead_code)] | ||
#[allow(non_snake_case)] | ||
struct MexcData { | ||
symbol: String, | ||
priceChange: Decimal, | ||
priceChangePercent: Decimal, | ||
prevClosePrice: Decimal, | ||
lastPrice: Decimal, | ||
bidPrice: Decimal, | ||
bidQty: Decimal, | ||
askPrice: Decimal, | ||
askQty: Decimal, | ||
openPrice: Decimal, | ||
highPrice: Decimal, | ||
lowPrice: Decimal, | ||
volume: Decimal, | ||
quoteVolume: Decimal, | ||
openTime: u64, | ||
closeTime: u64, | ||
} | ||
|
||
#[async_trait] | ||
impl Exchange for Mexc { | ||
async fn query_zec_to_usd(&self, client: &Client) -> Result<ExchangeData, Error> { | ||
// API documentation: | ||
// https://mexcdevelop.github.io/apidocs/spot_v3_en/#24hr-ticker-price-change-statistics | ||
let res = client | ||
.get_json::<MexcData>( | ||
"https://api.mexc.com/api/v3/ticker/24hr?symbol=ZECUSDT" | ||
.parse() | ||
.unwrap(), | ||
) | ||
.await?; | ||
let data = res.into_body(); | ||
Ok(ExchangeData { | ||
bid: data.bidPrice, | ||
ask: data.askPrice, | ||
}) | ||
} | ||
} |