Skip to main content

BcsConfig

Struct BcsConfig 

Source
pub struct BcsConfig {
    pub refresh_token: String,
    pub request_timeout: Duration,
    pub is_write: bool,
    pub http_base_url: String,
    pub ws_base_url: String,
}
Expand description

Configuration of the HTTP and WebSocket clients.

The one secret in it is the refresh token, which you issue in the BCS web cabinet (section “API tokens” of the account). The broker issues two kinds of refresh tokens:

  • a read token: market data, portfolio, orders and trades history, no trading,
  • a write token: everything the read token does, plus placing, changing and cancelling orders.

A token belongs to one brokerage account and lives 90 days by the broker docs. The token is shown once, at issue. BcsConfig::is_write must say which kind you hold, because it picks the client_id of the token request (trade-api-write or trade-api-read).

The Debug output of this struct hides the refresh token (<redacted>), so a config can be logged.

§Examples

use brokapi_bcs_protocol::config::BcsConfig;

// A read-only configuration, then a trading one.
let read = BcsConfig::new("refresh-token-of-a-read-token".to_string());
assert!(!read.is_write);

let trade = BcsConfig::new("refresh-token-of-a-write-token".to_string()).with_write(true);
assert!(trade.is_write);
assert_eq!(trade.request_timeout.as_secs(), 30);

Fields§

§refresh_token: String

The long-lived refresh token from the BCS web cabinet.

The HTTP client exchanges it for short-lived access tokens. If the broker returns a new refresh token with an access token (rotation), the client keeps the new one in memory only. It does not write it back to this struct or to disk, so a restart starts again from the token you supply.

§request_timeout: Duration

Timeout of one REST request, from sending to the end of the body.

Default 30 seconds. It does not apply to WebSocket sessions. A request that times out ends with BcsApiError::HttpError and no status. For an order placement that is an unknown outcome: ask the broker for the order before you send it again.

§is_write: bool

true if BcsConfig::refresh_token is a write (trading) token, false for a read token.

It selects client_id = "trade-api-write" or "trade-api-read" in the token request, as the broker docs describe. What the broker does when the flag and the token kind disagree is not verified against the live API. A read token cannot place orders.

§http_base_url: String

Base URL of the REST API, without a trailing slash.

Default is the production host HTTP_BASE_URL. The path of each endpoint is appended to it.

§ws_base_url: String

Base URL of the WebSocket API, without a trailing slash.

Default is the production host WS_BASE_URL. The path of each channel is appended to it.

Implementations§

Source§

impl BcsConfig

Source

pub fn from_env() -> Result<Self, VarError>

Reads the configuration from the environment (and from a .env file, if there is one).

It reads two variables:

  • BCS_REFRESH_TOKEN: required, the refresh token.
  • BCS_IS_WRITE: optional. The exact text true means a write token. Any other value, or no variable, means a read token.

A .env file in the working directory is loaded first, without overriding variables that are already set. Parent directories are not searched (see BcsConfig::from_env_file for another path). The URLs and the timeout are the defaults (production host, 30 seconds). No network call is made.

§Errors

Returns std::env::VarError::NotPresent when BCS_REFRESH_TOKEN is not set, and std::env::VarError::NotUnicode when it is not valid Unicode. A wrong or expired token is not detected here. It shows up as BcsApiError::AuthError at the first request.

§Examples

The example does not need a token: it handles both outcomes, as a program would.

use brokapi_bcs_protocol::config::BcsConfig;

match BcsConfig::from_env() {
    Ok(cfg) => assert_eq!(cfg.request_timeout.as_secs(), 30),
    Err(std::env::VarError::NotPresent) => { /* BCS_REFRESH_TOKEN is not set */ }
    Err(other) => panic!("unexpected: {other}"),
}
Source

pub fn from_env_file(path: impl AsRef<Path>) -> Result<Self, VarError>

Like BcsConfig::from_env, but loads the .env file at path (a file that is not there is skipped, variables that are already set are kept).

§Errors

The same as BcsConfig::from_env.

§Examples
use brokapi_bcs_protocol::config::BcsConfig;

// No such file: only the environment is read.
let _ = BcsConfig::from_env_file("/no/such/.env");
Source

pub fn new(refresh_token: String) -> Self

Builds a read-only configuration for the production host from a refresh token.

Chain BcsConfig::with_write if the token is a write token.

§Examples
use brokapi_bcs_protocol::config::BcsConfig;

let cfg = BcsConfig::new("my-refresh-token".to_string());
assert_eq!(cfg.refresh_token, "my-refresh-token");
assert!(!cfg.is_write);
assert!(cfg.http_base_url.starts_with("https://"));
assert!(cfg.ws_base_url.starts_with("wss://"));
Source

pub fn for_mock( refresh_token: impl Into<String>, http_base_url: impl Into<String>, ) -> Self

Points both the REST and the WebSocket client at a local server, for tests and examples.

http_base_url is the base of the local server (for example http://127.0.0.1:34567). The WebSocket base is derived from it by swapping the scheme (http to ws, https to wss). The token is only a label for the imitation, it is never sent to the real broker. The result is a read configuration, add BcsConfig::with_write for the trading calls.

§Examples
use brokapi_bcs_protocol::config::BcsConfig;

let cfg = BcsConfig::for_mock("mock-refresh-token", "http://127.0.0.1:9000").with_write(true);
assert_eq!(cfg.http_base_url, "http://127.0.0.1:9000");
assert_eq!(cfg.ws_base_url, "ws://127.0.0.1:9000");
assert!(cfg.is_write);
Source

pub fn with_write(self, is_write: bool) -> Self

Sets whether the refresh token is a write (trading) token. Returns the changed config.

Pass true only when the token really is a write token. See BcsConfig::is_write.

§Examples
use brokapi_bcs_protocol::config::BcsConfig;

let cfg = BcsConfig::new("t".to_string()).with_write(true);
assert!(cfg.is_write);

Trait Implementations§

Source§

impl Clone for BcsConfig

Source§

fn clone(&self) -> BcsConfig

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for BcsConfig

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

§

impl<T> PolicyExt for T
where T: ?Sized,

§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] only if self and other return Action::Follow. Read more
§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] if either self or other returns Action::Follow. Read more
§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more