wisespace-io / binance-rs

Rust Library for the Binance API

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Client construction API change

danieleades opened this issue · comments

this is a feature request

The API for constructing binance clients is a little clunky. There is a trait (Binance) which contains two construction methods for creating clients for different parts of the API. This trait is effectively used as a factory. I have a couple of concerns with the approach

  • since the methods on the trait have to be reimplemented for each different client, the total amount of code is not reduced compared to simply implementing the 'constructor' methods directly on the separate clients
  • the common 'constructor' methods optionally take different credentials, however some of the endpoints require credentials. The API allows you to create clients that can never work.
  • The client type you're after is resolved using type inference. This is perhaps a little opaque for less experienced Rust devs, and means that the API is not self-documenting.

I see two possible alternatives-

  1. Remove the 'factory' trait, implement the construction methods directly on the client objects, and require the appropriate credentials for that endpoint in the constructor
  2. use a builder struct with a type-guard that describes the credentials that are passed. Something like-
let factory = client::Builder::build()  // client::Builder<NoCredentials>
    .with_api_key("API_KEY")  // client::Builder<ApiKey>
    .with_secret_key("SECRET_KEY");  // client::Builder<ApiAndSecretKeys>

impl client::Builder<NoCredentials> {
    pub fn build() -> Self {
        ...
    }

    pub fn with_api_key(self, api_key: String) -> client::Builder<ApiKey> {
        ...
    }

    // client constructors for anything that doesn't need an API_KEY or SECRET_KEY
}

impl client::Builder<ApiKey> {
    pub fn with_secret_key(self, secret_key: String) -> client::Builder<ApiAndSecretKeys> {
        ...
    }

    // client constructors for anything that needs an API_KEY (only)
}

...

you get the idea