From 83368c5f18760fcab990958ce069843c23eb6a78 Mon Sep 17 00:00:00 2001 From: Sunli Date: Wed, 24 Jun 2026 22:51:11 +0800 Subject: [PATCH] feat(config): add paper trading mode support across all SDK bindings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add LONGBRIDGE_PAPERTRADING env var and enable_papertrading() API to all language bindings (Rust, Python, Node.js, Java, C, C++). When enabled, the SDK declares the request targets the paper trading (simulation) environment; the server validates the token and returns an error if it belongs to a real-money account. Default is false — no restriction imposed by the server. - Rust: new field, env read, builder/setter methods, HTTP header injection, unit tests - Python: from_apikey/from_oauth new param, type stub updated - Node.js: ExtraConfigParams new field, apply_extra handler - C: lb_config_enable_papertrading() function, longbridge.h auto-updated - Java: JNI impl, SdkNative native method, Config.enablePapertrading() - C++: enable_papertrading() method in Config class - All READMEs: Paper Trading section and env var table entry added --- README.md | 2 + c/README.md | 29 ++++++++++++ c/csrc/include/longbridge.h | 16 +++++++ c/src/config.rs | 17 +++++++ cpp/README.md | 29 ++++++++++++ cpp/include/config.hpp | 12 +++++ cpp/src/config.cpp | 7 +++ java/README.md | 31 ++++++++++++ .../src/main/java/com/longbridge/Config.java | 19 ++++++++ .../main/java/com/longbridge/SdkNative.java | 2 + java/src/config.rs | 12 +++++ nodejs/README.md | 35 ++++++++++++++ nodejs/src/config.rs | 14 ++++++ python/README.md | 33 +++++++++++++ python/pysrc/longbridge/openapi.pyi | 18 ++++++- python/src/config.rs | 10 ++++ rust/README.md | 34 ++++++++++++++ rust/src/config.rs | 47 +++++++++++++++++++ 18 files changed, 365 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 114d42e6c..f4b226a48 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,8 @@ https://longbridge.github.io/openapi - Debugging - Enable logs via `LONGBRIDGE_LOG_PATH`. - If quotes connect but look empty, keep `LONGBRIDGE_PRINT_QUOTE_PACKAGES=true` to confirm opened quote packages. +- Paper trading + - If your account is a paper trading (simulation) account and you want to place orders, set `LONGBRIDGE_PAPERTRADING=true`. When enabled, all API calls target the paper trading environment and the server validates the token — if the token belongs to a real-money account the server returns an error. When `false` (the default) the server imposes no restrictions. ## Minimal Verification diff --git a/c/README.md b/c/README.md index c1df4e0b2..3f0e74471 100644 --- a/c/README.md +++ b/c/README.md @@ -162,6 +162,35 @@ setx LONGBRIDGE_ACCESS_TOKEN "Access Token get from user center" | LONGBRIDGE_PUSH_CANDLESTICK_MODE | `realtime` or `confirmed` (Default: `realtime`) | | LONGBRIDGE_PRINT_QUOTE_PACKAGES | Print quote packages when connected, `true` or `false` (Default: `true`) | | LONGBRIDGE_LOG_PATH | Set the path of the log files (Default: `no logs`) | +| LONGBRIDGE_PAPERTRADING | Enable paper trading mode, `true` or `false` (Default: `false`). See [Paper Trading](#paper-trading). | + +## Paper Trading + +If your account is a **paper trading** (simulation) account and you want to +place orders, you must explicitly enable paper trading mode. When enabled, all +API calls target the paper trading environment and the server validates the +token — if the token belongs to a real-money account the server returns an +error. + +By default this option is **off**: the server imposes no restrictions and +accepts requests from both paper trading and real-money accounts. + +**Via environment variable** (applies automatically to all constructor methods): + +```bash +export LONGBRIDGE_PAPERTRADING=true # macOS / Linux +``` + +```powershell +$env:LONGBRIDGE_PAPERTRADING = "true" # Windows PowerShell +``` + +**Programmatically:** + +```c +lb_config_t* config = lb_config_from_apikey("app-key", "app-secret", "access-token"); +lb_config_enable_papertrading(config); +``` ## Quote API _(Get basic information of securities)_ diff --git a/c/csrc/include/longbridge.h b/c/csrc/include/longbridge.h index 1b2fdc031..faa3dc880 100644 --- a/c/csrc/include/longbridge.h +++ b/c/csrc/include/longbridge.h @@ -9028,6 +9028,22 @@ void lb_config_set_push_candlestick_mode(struct lb_config_t *config, */ void lb_config_disable_print_quote_packages(struct lb_config_t *config); +/** + * Enable paper trading mode. + * + * When enabled, all API calls target the paper trading (simulation) + * environment. The server validates the token: if it belongs to a real-money + * account the server returns an error. + * + * When disabled (the default) the server imposes no restrictions — both + * paper trading and real-money accounts are accepted. + * + * Paper trading users should call this function as a safety guard. + * + * @param config Config object + */ +void lb_config_enable_papertrading(struct lb_config_t *config); + /** * Set the log file path * diff --git a/c/src/config.rs b/c/src/config.rs index 18ecc7b7f..0b7f20c2c 100644 --- a/c/src/config.rs +++ b/c/src/config.rs @@ -171,6 +171,23 @@ pub unsafe extern "C" fn lb_config_disable_print_quote_packages(config: *mut CCo (*config).0.set_dont_print_quote_packages(); } +/// Enable paper trading mode. +/// +/// When enabled, all API calls target the paper trading (simulation) +/// environment. The server validates the token: if it belongs to a real-money +/// account the server returns an error. +/// +/// When disabled (the default) the server imposes no restrictions — both +/// paper trading and real-money accounts are accepted. +/// +/// Paper trading users should call this function as a safety guard. +/// +/// @param config Config object +#[unsafe(no_mangle)] +pub unsafe extern "C" fn lb_config_enable_papertrading(config: *mut CConfig) { + (*config).0.set_enable_papertrading(); +} + /// Set the log file path /// /// @param config Config object diff --git a/cpp/README.md b/cpp/README.md index c3a37d913..be58e35af 100644 --- a/cpp/README.md +++ b/cpp/README.md @@ -157,6 +157,35 @@ setx LONGBRIDGE_ACCESS_TOKEN "Access Token get from user center" | LONGBRIDGE_PUSH_CANDLESTICK_MODE | `realtime` or `confirmed` (Default: `realtime`) | | LONGBRIDGE_PRINT_QUOTE_PACKAGES | Print quote packages when connected, `true` or `false` (Default: `true`) | | LONGBRIDGE_LOG_PATH | Set the path of the log files (Default: `no logs`) | +| LONGBRIDGE_PAPERTRADING | Enable paper trading mode, `true` or `false` (Default: `false`). See [Paper Trading](#paper-trading). | + +## Paper Trading + +If your account is a **paper trading** (simulation) account and you want to +place orders, you must explicitly enable paper trading mode. When enabled, all +API calls target the paper trading environment and the server validates the +token — if the token belongs to a real-money account the server returns an +error. + +By default this option is **off**: the server imposes no restrictions and +accepts requests from both paper trading and real-money accounts. + +**Via environment variable** (applies automatically to all constructor methods): + +```bash +export LONGBRIDGE_PAPERTRADING=true # macOS / Linux +``` + +```powershell +$env:LONGBRIDGE_PAPERTRADING = "true" # Windows PowerShell +``` + +**Programmatically:** + +```c++ +Config config = Config::from_apikey("app-key", "app-secret", "access-token") + .enable_papertrading(); +``` ## Quote API _(Get basic information of securities)_ diff --git a/cpp/include/config.hpp b/cpp/include/config.hpp index 75bd26cab..928c5b80e 100644 --- a/cpp/include/config.hpp +++ b/cpp/include/config.hpp @@ -81,6 +81,18 @@ class Config /// Enable overnight quote Config& enable_overnight(); + /// Enable paper trading mode. + /// + /// When enabled, all API calls target the paper trading (simulation) + /// environment. The server validates the token: if it belongs to a + /// real-money account the server returns an error. + /// + /// By default this option is disabled and the server imposes no restrictions + /// — both paper trading and real-money accounts are accepted. + /// + /// Paper trading users should call this method as a safety guard. + Config& enable_papertrading(); + /// Set the push candlestick mode Config& set_push_candlestick_mode(PushCandlestickMode mode); diff --git a/cpp/src/config.cpp b/cpp/src/config.cpp index 5b6972c64..f2c40c9cd 100644 --- a/cpp/src/config.cpp +++ b/cpp/src/config.cpp @@ -98,6 +98,13 @@ Config::enable_overnight() return *this; } +Config& +Config::enable_papertrading() +{ + lb_config_enable_papertrading(config_); + return *this; +} + Config& Config::set_push_candlestick_mode(PushCandlestickMode mode) { diff --git a/java/README.md b/java/README.md index b803e34a3..9ab211e10 100644 --- a/java/README.md +++ b/java/README.md @@ -152,6 +152,37 @@ setx LONGBRIDGE_ACCESS_TOKEN "Access Token get from user center" | LONGBRIDGE_PUSH_CANDLESTICK_MODE | `realtime` or `confirmed` (Default: `realtime`) | | LONGBRIDGE_PRINT_QUOTE_PACKAGES | Print quote packages when connected, `true` or `false` (Default: `true`) | | LONGBRIDGE_LOG_PATH | Set the path of the log files (Default: `no logs`) | +| LONGBRIDGE_PAPERTRADING | Enable paper trading mode, `true` or `false` (Default: `false`). See [Paper Trading](#paper-trading). | + +## Paper Trading + +If your account is a **paper trading** (simulation) account and you want to +place orders, you must explicitly enable paper trading mode. When enabled, all +API calls target the paper trading environment and the server validates the +token — if the token belongs to a real-money account the server returns an +error. + +By default this option is **off**: the server imposes no restrictions and +accepts requests from both paper trading and real-money accounts. + +**Via environment variable** (applies automatically to all constructor methods): + +```bash +export LONGBRIDGE_PAPERTRADING=true # macOS / Linux +``` + +```powershell +$env:LONGBRIDGE_PAPERTRADING = "true" # Windows PowerShell +``` + +**Programmatically:** + +```java +import com.longbridge.*; + +Config config = Config.fromApikey("app-key", "app-secret", "access-token") + .enablePapertrading(); +``` ## Quote API _(Get basic information of securities)_ diff --git a/java/javasrc/src/main/java/com/longbridge/Config.java b/java/javasrc/src/main/java/com/longbridge/Config.java index 6b6044577..ca28e9b1b 100644 --- a/java/javasrc/src/main/java/com/longbridge/Config.java +++ b/java/javasrc/src/main/java/com/longbridge/Config.java @@ -187,6 +187,25 @@ public Config logPath(String path) { return this; } + /** + * Enable paper trading mode. + * + *

When enabled, all API calls target the paper trading (simulation) + * environment. The server validates the token: if it belongs to a real-money + * account the server returns an error. + * + *

By default this option is disabled and the server imposes no restrictions + * — requests from both paper trading and real-money accounts are accepted. + * + *

Paper trading users should call this method as a safety guard. + * + * @return this object + */ + public Config enablePapertrading() { + this.raw = SdkNative.configSetEnablePapertrading(this.raw); + return this; + } + /** * Gets a new {@code access_token}. * diff --git a/java/javasrc/src/main/java/com/longbridge/SdkNative.java b/java/javasrc/src/main/java/com/longbridge/SdkNative.java index 7beea04c5..bb228c353 100644 --- a/java/javasrc/src/main/java/com/longbridge/SdkNative.java +++ b/java/javasrc/src/main/java/com/longbridge/SdkNative.java @@ -52,6 +52,8 @@ public static native long newHttpClientFromApikey(String appKey, String appSecre public static native long configSetLogPath(long config, String logPath); + public static native long configSetEnablePapertrading(long config); + public static native void configRefreshAccessToken(long config, OffsetDateTime expiredAt, AsyncCallback callback); diff --git a/java/src/config.rs b/java/src/config.rs index bae1c9016..d3b35533c 100644 --- a/java/src/config.rs +++ b/java/src/config.rs @@ -166,6 +166,18 @@ pub unsafe extern "system" fn Java_com_longbridge_SdkNative_configSetLogPath( }) } +#[unsafe(no_mangle)] +pub unsafe extern "system" fn Java_com_longbridge_SdkNative_configSetEnablePapertrading( + mut env: JNIEnv, + _class: JClass, + config: jlong, +) -> jlong { + jni_result(&mut env, config, |_env| { + (*(config as *mut Config)).set_enable_papertrading(); + Ok(config) + }) +} + // ── Async operations // ────────────────────────────────────────────────────────── diff --git a/nodejs/README.md b/nodejs/README.md index b2eafde9f..198e59387 100644 --- a/nodejs/README.md +++ b/nodejs/README.md @@ -145,6 +145,7 @@ setx LONGBRIDGE_ACCESS_TOKEN "Access Token get from user center" | LONGBRIDGE_PUSH_CANDLESTICK_MODE | `realtime` or `confirmed` (Default: `realtime`) | | LONGBRIDGE_PRINT_QUOTE_PACKAGES | Print quote packages when connected, `true` or `false` (Default: `true`) | | LONGBRIDGE_LOG_PATH | Set the path of the log files (Default: `no logs`) | +| LONGBRIDGE_PAPERTRADING | Enable paper trading mode, `true` or `false` (Default: `false`). See [Paper Trading](#paper-trading). | Then create a config from the environment: @@ -230,6 +231,40 @@ async function main() { main(); ``` +## Paper Trading + +If your account is a **paper trading** (simulation) account and you want to +place orders, you must explicitly enable paper trading mode. When enabled, all +API calls target the paper trading environment and the server validates the +token — if the token belongs to a real-money account the server returns an +error. + +By default this option is **off**: the server imposes no restrictions and +accepts requests from both paper trading and real-money accounts. + +**Via environment variable** (applies automatically to all constructor methods): + +```bash +export LONGBRIDGE_PAPERTRADING=true # macOS / Linux +``` + +```powershell +$env:LONGBRIDGE_PAPERTRADING = "true" # Windows PowerShell +``` + +**Programmatically:** + +```javascript +const { Config } = require('longbridge'); + +const config = Config.fromApikey( + process.env.LONGBRIDGE_APP_KEY, + process.env.LONGBRIDGE_APP_SECRET, + process.env.LONGBRIDGE_ACCESS_TOKEN, + { enablePapertrading: true }, +); +``` + ## Troubleshooting - Windows `setx` requires a new terminal; use `set` for the current `cmd.exe` session. diff --git a/nodejs/src/config.rs b/nodejs/src/config.rs index 8d8fbb95b..ff732cad5 100644 --- a/nodejs/src/config.rs +++ b/nodejs/src/config.rs @@ -31,6 +31,17 @@ pub struct ExtraConfigParams { pub enable_print_quote_packages: Option, /// Set the path of the log files (Default: `no logs`) pub log_path: Option, + /// Enable paper trading mode (default: `false`). + /// + /// When `true`, all API calls target the paper trading (simulation) + /// environment. The server validates the token: if it belongs to a + /// real-money account the server returns an error. + /// + /// When `false` (the default) the server imposes no restrictions — both + /// paper trading and real-money accounts are accepted. + /// + /// Paper trading users should set this to `true` as a safety guard. + pub enable_papertrading: Option, } fn apply_extra( @@ -62,6 +73,9 @@ fn apply_extra( if let Some(log_path) = extra.log_path { config.set_log_path(log_path); } + if let Some(true) = extra.enable_papertrading { + config.set_enable_papertrading(); + } } config } diff --git a/python/README.md b/python/README.md index 7e525be67..df12f8e22 100644 --- a/python/README.md +++ b/python/README.md @@ -181,6 +181,7 @@ setx LONGBRIDGE_ACCESS_TOKEN "Access Token get from user center" | LONGBRIDGE_PUSH_CANDLESTICK_MODE | `realtime` or `confirmed` (Default: `realtime`) | | LONGBRIDGE_PRINT_QUOTE_PACKAGES | Print quote packages when connected, `true` or `false` (Default: `true`) | | LONGBRIDGE_LOG_PATH | Set the path of the log files (Default: `no logs`) | +| LONGBRIDGE_PAPERTRADING | Enable paper trading mode, `true` or `false` (Default: `false`). See [Paper Trading](#paper-trading). | Then create a config from the environment: @@ -292,6 +293,38 @@ asyncio.run(main()) See the `*_async.py` examples in `examples/python/` for full async flows. +## Paper Trading + +If your account is a **paper trading** (simulation) account and you want to +place orders, you must explicitly enable paper trading mode. When enabled, all +API calls target the paper trading environment and the server validates the +token — if the token belongs to a real-money account the server returns an +error. + +By default this option is **off**: the server imposes no restrictions and +accepts requests from both paper trading and real-money accounts. + +**Via environment variable** (applies automatically to all constructor methods): + +```bash +export LONGBRIDGE_PAPERTRADING=true # macOS / Linux +``` + +```powershell +$env:LONGBRIDGE_PAPERTRADING = "true" # Windows PowerShell +``` + +**Programmatically:** + +```python +from longbridge.openapi import Config + +config = Config.from_apikey( + "app-key", "app-secret", "access-token", + enable_papertrading=True, +) +``` + ## Troubleshooting - Windows `setx` requires a new terminal; use `set` for the current `cmd.exe` session. diff --git a/python/pysrc/longbridge/openapi.pyi b/python/pysrc/longbridge/openapi.pyi index b5a518f60..22953c72a 100644 --- a/python/pysrc/longbridge/openapi.pyi +++ b/python/pysrc/longbridge/openapi.pyi @@ -295,6 +295,7 @@ class Config: push_candlestick_mode: Type[PushCandlestickMode] = PushCandlestickMode.Realtime, enable_print_quote_packages: bool = True, log_path: Optional[str] = None, + enable_papertrading: bool = False, ) -> Config: """ Create a new ``Config`` using API Key authentication. @@ -303,7 +304,8 @@ class Config: (``LONGBRIDGE_HTTP_URL``, ``LONGBRIDGE_LANGUAGE``, ``LONGBRIDGE_QUOTE_WS_URL``, ``LONGBRIDGE_TRADE_WS_URL``, ``LONGBRIDGE_ENABLE_OVERNIGHT``, ``LONGBRIDGE_PUSH_CANDLESTICK_MODE``, - ``LONGBRIDGE_PRINT_QUOTE_PACKAGES``, ``LONGBRIDGE_LOG_PATH``). + ``LONGBRIDGE_PRINT_QUOTE_PACKAGES``, ``LONGBRIDGE_LOG_PATH``, + ``LONGBRIDGE_PAPERTRADING``). Any explicit parameter overrides the corresponding env variable. Args: @@ -323,6 +325,11 @@ class Config: enable_print_quote_packages: Print opened quote packages on connect (default: ``True``) log_path: Path for log files (default: no logs) + enable_papertrading: When ``True``, all API calls target the + paper trading (simulation) environment. The server validates + the token: if it belongs to a real-money account the server + returns an error. Default: ``False`` (no restriction imposed + by server). """ @classmethod @@ -365,6 +372,7 @@ class Config: push_candlestick_mode: Optional[Type[PushCandlestickMode]] = None, enable_print_quote_packages: Optional[bool] = None, log_path: Optional[str] = None, + enable_papertrading: Optional[bool] = None, ) -> Config: """ Create a new ``Config`` for OAuth 2.0 authentication. @@ -376,7 +384,8 @@ class Config: (``LONGBRIDGE_HTTP_URL``, ``LONGBRIDGE_LANGUAGE``, ``LONGBRIDGE_QUOTE_WS_URL``, ``LONGBRIDGE_TRADE_WS_URL``, ``LONGBRIDGE_ENABLE_OVERNIGHT``, ``LONGBRIDGE_PUSH_CANDLESTICK_MODE``, - ``LONGBRIDGE_PRINT_QUOTE_PACKAGES``, ``LONGBRIDGE_LOG_PATH``). + ``LONGBRIDGE_PRINT_QUOTE_PACKAGES``, ``LONGBRIDGE_LOG_PATH``, + ``LONGBRIDGE_PAPERTRADING``). Any explicit parameter overrides the corresponding env variable. Args: @@ -395,6 +404,11 @@ class Config: enable_print_quote_packages: Print opened quote packages on connect (optional) log_path: Path for log files (optional) + enable_papertrading: When ``True``, all API calls target the + paper trading (simulation) environment. The server validates + the token: if it belongs to a real-money account the server + returns an error. Default: ``None`` (no restriction imposed + by server). Returns: Config object diff --git a/python/src/config.rs b/python/src/config.rs index 9663b0647..cd5c4b35e 100644 --- a/python/src/config.rs +++ b/python/src/config.rs @@ -52,6 +52,7 @@ impl Config { push_candlestick_mode = PushCandlestickMode::Realtime, enable_print_quote_packages = true, log_path = None, + enable_papertrading = false, ))] #[allow(clippy::too_many_arguments)] fn from_apikey( @@ -66,6 +67,7 @@ impl Config { push_candlestick_mode: PushCandlestickMode, enable_print_quote_packages: bool, log_path: Option, + enable_papertrading: bool, ) -> Self { let mut config = longbridge::Config::from_apikey(app_key, app_secret, access_token); @@ -91,6 +93,9 @@ impl Config { if let Some(log_path) = log_path { config.set_log_path(log_path); } + if enable_papertrading { + config.set_enable_papertrading(); + } Self(config) } @@ -167,6 +172,7 @@ impl Config { push_candlestick_mode = None, enable_print_quote_packages = None, log_path = None, + enable_papertrading = None, ))] #[allow(clippy::too_many_arguments)] fn from_oauth( @@ -180,6 +186,7 @@ impl Config { push_candlestick_mode: Option, enable_print_quote_packages: Option, log_path: Option, + enable_papertrading: Option, ) -> Self { let mut config = longbridge::Config::from_oauth(oauth.0.clone()); @@ -207,6 +214,9 @@ impl Config { if let Some(log_path) = log_path { config.set_log_path(log_path); } + if let Some(true) = enable_papertrading { + config.set_enable_papertrading(); + } Self(config) } diff --git a/rust/README.md b/rust/README.md index 8a1fe6c1e..81b4aba94 100644 --- a/rust/README.md +++ b/rust/README.md @@ -175,6 +175,40 @@ setx LONGBRIDGE_ACCESS_TOKEN "Access Token get from user center" | LONGBRIDGE_PUSH_CANDLESTICK_MODE | `realtime` or `confirmed` (Default: `realtime`) | | LONGBRIDGE_PRINT_QUOTE_PACKAGES | Print quote packages when connected, `true` or `false` (Default: `true`) | | LONGBRIDGE_LOG_PATH | Set the path of the log files (Default: `no logs`) | +| LONGBRIDGE_PAPERTRADING | Enable paper trading mode, `true` or `false` (Default: `false`). See [Paper Trading](#paper-trading). | + +## Paper Trading + +If your account is a **paper trading** (simulation) account and you want to +place orders, you must explicitly enable paper trading mode. When enabled, all +API calls target the paper trading environment and the server validates the +token — if the token belongs to a real-money account the server returns an +error. + +By default this option is **off**: the server imposes no restrictions and +accepts requests from both paper trading and real-money accounts. + +**Via environment variable** (applies automatically to all constructor methods): + +```bash +export LONGBRIDGE_PAPERTRADING=true # macOS / Linux +``` + +```powershell +$env:LONGBRIDGE_PAPERTRADING = "true" # Windows PowerShell +``` + +**Programmatically:** + +```rust,no_run +use std::sync::Arc; +use longbridge::Config; + +let config = Arc::new( + Config::from_apikey("app-key", "app-secret", "access-token") + .enable_papertrading() +); +``` ## Quote API _(Get basic information of securities)_ diff --git a/rust/src/config.rs b/rust/src/config.rs index c2f0c49c5..22628e629 100644 --- a/rust/src/config.rs +++ b/rust/src/config.rs @@ -131,6 +131,7 @@ pub struct Config { pub(crate) log_path: Option, /// Extra headers injected into every HTTP and WebSocket upgrade request. pub(crate) custom_headers: HashMap, + pub(crate) enable_papertrading: bool, } /// Reads an env var by trying `LONGBRIDGE_` first, then falling back @@ -162,6 +163,7 @@ struct ConfigExtras { push_candlestick_mode: Option, enable_print_quote_packages: bool, log_path: Option, + enable_papertrading: bool, } impl ConfigExtras { @@ -176,6 +178,7 @@ impl ConfigExtras { }); let enable_print_quote_packages = env_var("PRINT_QUOTE_PACKAGES").as_deref().unwrap_or("true") == "true"; + let enable_papertrading = env_var("PAPERTRADING").as_deref() == Some("true"); Self { http_url: env_var("HTTP_URL"), quote_ws_url: env_var("QUOTE_WS_URL"), @@ -185,6 +188,7 @@ impl ConfigExtras { push_candlestick_mode, enable_print_quote_packages, log_path: env_var("LOG_PATH").map(PathBuf::from), + enable_papertrading, } } } @@ -223,6 +227,7 @@ impl Config { enable_print_quote_packages: extras.enable_print_quote_packages, log_path: extras.log_path, custom_headers: Default::default(), + enable_papertrading: extras.enable_papertrading, } } @@ -272,6 +277,7 @@ impl Config { enable_print_quote_packages: extras.enable_print_quote_packages, log_path: extras.log_path, custom_headers: Default::default(), + enable_papertrading: extras.enable_papertrading, } } @@ -327,6 +333,7 @@ impl Config { enable_print_quote_packages: extras.enable_print_quote_packages, log_path: extras.log_path, custom_headers: Default::default(), + enable_papertrading: extras.enable_papertrading, }) } @@ -402,6 +409,23 @@ impl Config { } } + /// Enable paper trading mode. + /// + /// When enabled, all API calls target the paper trading (simulation) + /// environment. The server validates the token: if it belongs to a + /// real-money account the server returns an error. + /// + /// By default this option is disabled (`false`): the server imposes no + /// restrictions and accepts requests from both paper trading and real-money + /// accounts. + /// + /// Paper trading users should enable this option as a safety guard to avoid + /// accidentally submitting orders against their real-money account. + pub fn enable_papertrading(mut self) -> Self { + self.enable_papertrading = true; + self + } + /// Create metadata for auth/reconnect request pub fn create_metadata(&self) -> HashMap { let mut metadata = HashMap::new(); @@ -431,6 +455,9 @@ impl Config { for (key, value) in &self.custom_headers { client = client.header(key.as_str(), value.as_str()); } + if self.enable_papertrading { + client = client.header("x-papertrading", "true"); + } client } @@ -597,6 +624,13 @@ impl Config { self.enable_print_quote_packages = false; } + /// Enable paper trading mode in place. + /// + /// See [`Config::enable_papertrading`] for full semantics. + pub fn set_enable_papertrading(&mut self) { + self.enable_papertrading = true; + } + /// Set the log path in place. pub fn set_log_path(&mut self, path: impl Into) { self.log_path = Some(path.into()); @@ -660,4 +694,17 @@ mod tests { assert_eq!(config.push_candlestick_mode, None); assert!(config.enable_print_quote_packages); } + + #[test] + fn test_enable_papertrading_builder() { + let config = Config::from_apikey("key", "secret", "token").enable_papertrading(); + assert!(config.enable_papertrading); + } + + #[test] + fn test_enable_papertrading_setter() { + let mut config = Config::from_apikey("key", "secret", "token"); + config.set_enable_papertrading(); + assert!(config.enable_papertrading); + } }