//! All endpoints for HTTP requests.
pub(crate) use reqwest::Method as HttpVerb;
/// Fully describes the HTTP endpoint:
///
/// - path;
/// - HTTP method (verb);
/// - weight (how much API limits will be affected by the query);
/// - additional security to access the endpoint.
pub trait Endpoint {
/// The HTTP path for the given request.
fn as_endpoint(&self) -> String;
/// HTTP method (verb) used to access the endpoint. The most common are:
///
/// - GET
/// - POST
/// - PUT
/// - DELETE
fn http_verb(&self) -> HttpVerb;
/// The API weight regarding [IP limits](https://binance-docs.github.io/apidocs/spot/en/#ip-limits)
/// for the given request.
///
/// Endpoints share the 1200 per minute limit based on IP.
///
/// Responses contain the header `X-MBX-USED-WEIGHT-(intervalNum)(intervalLetter)`,
/// defining the weight used by the current IP.
fn ip_weight(&self) -> Option<u16>;
/// The API weight regarding [UID (account) limits](https://binance-docs.github.io/apidocs/spot/en/#order-rate-limits)
/// for the given request.
///
/// The order rate limit is counted against each account.
///
/// Successful order responses contain the header `X-MBX-ORDER-COUNT-(intervalNum)(intervalLetter)`,
/// defining the order limit used by the UID.
///
/// To monitor order count usage, refer to `GET api/v3/rateLimit/order`.
fn order_weight(&self) -> Option<u16>;
/// Determines access to the endpoint.
fn security_type(&self) -> SecurityType;
}
#[derive(Debug, Copy, Clone)]
/// Each endpoint has a security type that determines how you will interact with it.
///
/// - API-keys are passed into the Rest API via the `X-MBX-APIKEY` header.
/// - API-keys and secret-keys are case sensitive.
/// - API-keys can be configured to only access certain types of secure endpoints.
/// For example, one API-key could be used for [TRADE][Self::Trade] only,
/// while another API-key can access everything except for [TRADE][Self::Trade] routes.
/// - By default, API-keys can access all secure routes.
///
/// More on it: <https://binance-docs.github.io/apidocs/spot/en/#endpoint-security-type>
pub enum SecurityType {
/// Those endpoints include:
///
/// - general info about exchange;
/// - recent market data.
///
/// Endpoints can be accessed freely.
///
/// Usually accessed via the `GET` (idempotent and not able to change server state).
///
/// Those endpoints can be found at:
///
/// - [spot](https://binance-docs.github.io/apidocs/spot/en/#market-data-endpoints);
/// - [futures](https://binance-docs.github.io/apidocs/futures/en/#market-data-endpoints).
None,
/// Query of historical market data.
///
/// Can be accessed with the API-key.
///
/// Usually accessed via the `GET` (idempotent and not able to change server state).
MarketData,
/// Management of Websocket streams to receive any account updates.
///
/// Those endpoints can be found at:
///
/// - [spot and margin](https://binance-docs.github.io/apidocs/spot/en/#user-data-streams);
/// - [futures](https://binance-docs.github.io/apidocs/futures/en/#user-data-streams).
UserStream,
/// The endpoints changing the actual trading status of an account:
///
/// - placing a new order (usually `POST`);
/// - cancelling an active order (usually `DELETE`);
/// - requesting the order count usage (usually `GET`).
///
/// Can only be accessed with the API-key and signed with the secret key.
///
/// Those endpoints can be found at:
///
/// - [spot](https://binance-docs.github.io/apidocs/spot/en/#spot-account-trade);
/// - [futures](https://binance-docs.github.io/apidocs/futures/en/#account-trades-endpoints);
/// - [margin](https://binance-docs.github.io/apidocs/spot/en/#margin-account-trade).
Trade,
/// Query User data.
///
/// Can only be accessed with the API-key and signed with the secret key.
///
/// Usually accessed via the `GET` (idempotent and not able to change server state).
///
/// Those endpoints can be found at:
///
/// - [spot](https://binance-docs.github.io/apidocs/spot/en/#spot-account-trade);
/// - [futures](https://binance-docs.github.io/apidocs/futures/en/#account-trades-endpoints);
/// - [margin](https://binance-docs.github.io/apidocs/spot/en/#margin-account-trade).
UserData,
/// Account action associated with transferring of funds on Margin trading.
///
/// Can only be accessed with the API-key and signed with the secret key.
///
/// Those endpoints can be found at:
/// - [margin](https://binance-docs.github.io/apidocs/spot/en/#margin-account-trade).
Margin,
}
impl SecurityType {
/// Endpoint requires sending a valid API-Key.
pub fn is_key_required(self) -> bool {
match self {
Self::None => false,
Self::MarketData | Self::UserStream | Self::Trade | Self::UserData | Self::Margin => {
true
}
}
}
/// Endpoint requires sending a valid API-Key and signature.
///
/// - Signed endpoints require an additional parameter, `signature`,
/// to be sent in the query string or request body.
/// - Endpoints use HMAC SHA256 signatures. The HMAC SHA256 signature is a keyed HMAC SHA256 operation.
/// - Use your `secretKey` as the key and `totalParams` as the value for the HMAC operation.
/// - The signature is **not case sensitive**.
/// - `totalParams` is defined as the query string concatenated with the request body.
///
/// ### Timing security
///
/// - A signed endpoint also requires a parameter, `timestamp`,
/// to be sent which should be the millisecond timestamp of when
/// the request was created and sent.
/// - An additional parameter, `recvWindow`, may be sent to specify the number of milliseconds
/// after timestamp the request is valid for. If `recvWindow` is not sent, it defaults to 5000.
///
/// The logic is as follows:
///
/// ```no-compile
/// if timestamp < (server_time + 1000) &&
/// (server_time - timestamp) <= recv_window {
/// // process request
/// }
/// else {
/// // reject request
/// }
/// ```
///
/// **Serious trading is about timing.** Networks can be unstable and unreliable,
/// which can lead to requests taking varying amounts of time to reach the servers.
/// With `recvWindow`, you can specify that the request must be processed within
/// a certain number of milliseconds or be rejected by the server.
/// It is recommended to use a small `recvWindow` of `5000` or less!
/// The max cannot go beyond `60,000`!
pub fn is_signature_required(self) -> bool {
match self {
Self::None => false,
Self::MarketData | Self::UserStream => false,
Self::Trade | Self::UserData | Self::Margin => true,
}
}
pub fn http_method_hint(self) -> Option<HttpVerb> {
match self {
// idempotent and not able to change server state
Self::None | Self::MarketData | Self::UserData => Some(HttpVerb::GET),
Self::UserStream | Self::Trade | Self::Margin => None,
}
}
}