Skip to main content

ig_client/
constants.rs

1/// Default number of days to look back when fetching historical data
2pub const DAYS_TO_BACK_LOOK: i64 = 10;
3/// Maximum number of consecutive errors before forcing a cooldown
4pub const MAX_CONSECUTIVE_ERRORS: u32 = 3;
5/// Cooldown time in seconds when hitting max errors (5 minutes)
6pub const ERROR_COOLDOWN_SECONDS: u64 = 300;
7/// Default sleep time in hours if not specified in environment (24 hours)
8pub const DEFAULT_SLEEP_TIME: u64 = 24;
9/// Default page size for API requests
10pub const DEFAULT_PAGE_SIZE: u32 = 50;
11/// Default maximum number of retries for transient HTTP failures when the
12/// `MAX_RETRY_COUNT` environment variable is unset.
13///
14/// This default is intentionally finite: unbounded retry was removed in
15/// PR #26 and must never be reintroduced. "No retry count configured" now
16/// means "use this finite default", never "retry forever".
17pub const DEFAULT_MAX_RETRIES: u32 = 3;
18/// Default base delay in seconds between retries when the `RETRY_DELAY_SECS`
19/// environment variable is unset. Used as the base for exponential backoff.
20pub const DEFAULT_RETRY_DELAY_SECS: u64 = 10;
21/// Maximum backoff delay in seconds. Exponential backoff (`base * 2^attempt`)
22/// saturates at this cap — the cap is the policy, so rounding down to it is
23/// intentional and documented.
24pub const MAX_RETRY_DELAY_SECS: u64 = 60;
25/// Compatibility retry cap for the deprecated "infinite" retry constructors
26/// ([`crate::model::retry::RetryConfig::infinite`] and
27/// [`crate::model::retry::RetryConfig::with_delay`]). Unbounded retry is banned
28/// (PR #26); these constructors now clamp to this large-but-finite value so
29/// existing callers keep compiling while never looping forever.
30pub const DEPRECATED_INFINITE_RETRY_CAP: u32 = 1000;
31/// Base delay in milliseconds used for proximity-based delays in the rate limiter
32/// This value is used to calculate wait times when approaching rate limits
33pub const BASE_DELAY_MS: u64 = 1000;
34/// Additional safety buffer in milliseconds added to wait times
35/// This provides extra margin to ensure rate limits are not exceeded
36pub const SAFETY_BUFFER_MS: u64 = 1000;
37/// User agent string used in HTTP requests to identify this client to the IG
38/// Markets API.
39///
40/// The version is derived from `CARGO_PKG_VERSION` at compile time so it can
41/// never drift from the crate version and mislead server-side diagnostics.
42pub const USER_AGENT: &str = concat!("ig-client/", env!("CARGO_PKG_VERSION"));
43/// Conservative per-app trading request budget, in requests per second,
44/// enforced by the rate limiter for order / position mutations
45/// (`positions/otc`, `workingorders/otc`).
46///
47/// IG applies account-level bans for trading rate violations and the published
48/// per-app trading limit is roughly one request per second, so this budget is
49/// fixed independently of the configured non-trading budget: a permissive
50/// `RateLimiterConfig` can never loosen it.
51pub const TRADING_RATE_LIMIT_PER_SECOND: u32 = 1;
52/// Conservative per-app historical-price request budget, in requests per second,
53/// enforced by the rate limiter for endpoints under `prices/`.
54///
55/// Historical price fetches also draw down a weekly data-point allowance (default
56/// 10,000 points), so the per-second rate is kept low to avoid exhausting the
57/// allowance in bursts. Like the trading budget, it is fixed independently of the
58/// configured non-trading budget.
59pub const HISTORICAL_RATE_LIMIT_PER_SECOND: u32 = 1;
60/// Burst capacity for the derived trading and historical rate-limit buckets.
61///
62/// Kept at one so the derived per-second budgets admit no burst beyond a single
63/// in-flight request, matching IG's strict trading / historical limits.
64pub const TRADING_HISTORICAL_BURST_SIZE: u32 = 1;
65/// Fallback replenishment budget (requests per period) used when
66/// [`crate::application::config::RateLimiterConfig::max_requests`] is configured
67/// as zero, which is structurally invalid.
68///
69/// One request per configured period is the safe floor and avoids a
70/// divide-by-zero when computing the per-cell replenishment interval.
71pub const FALLBACK_RATE_LIMIT_MAX_REQUESTS: u32 = 1;
72/// Fallback burst capacity used when
73/// [`crate::application::config::RateLimiterConfig::burst_size`] is configured as
74/// zero. Preserves the historical default of allowing a small burst.
75pub const DEFAULT_RATE_LIMIT_BURST_SIZE: u32 = 10;
76/// A constant representing the default sell level for orders.
77///
78/// This value is set to `0.0` by default and can be used to indicate an initial or
79/// baseline sell level for order-related computations or configurations.
80pub const DEFAULT_ORDER_SELL_LEVEL: f64 = 0.0;
81/// A constant representing the default buy level for orders.
82///
83/// This value is set as a `f64` and determines the default threshold for the buy level in an order system.
84/// Developers can use this constant to ensure uniformity and consistency when working with order buy levels
85/// across the application.
86pub const DEFAULT_ORDER_BUY_LEVEL: f64 = 10000.0;
87
88/// Sentinel value used for `account_id` when `IG_ACCOUNT_ID` is not configured.
89///
90/// This is not a real IG account id: it signals "no account was explicitly
91/// configured, use whatever account the session lands on". Auth flows must not
92/// attempt to switch to this value.
93pub const DEFAULT_ACCOUNT_ID: &str = "default_account_id";
94
95/// Credential-less placeholder used for `DATABASE_URL` when it is not configured.
96///
97/// Persistence is optional, so an unset `DATABASE_URL` is not fatal at config
98/// construction; this placeholder lets `Config::new` produce a value while
99/// deliberately carrying NO username or password. It is not a working
100/// connection string — any component that actually needs Postgres must fail
101/// when it tries to connect. Never hard-code real credentials here.
102pub const DEFAULT_DATABASE_URL: &str = "postgres://localhost/ig";
103
104/// Default size of the Postgres connection pool
105/// ([`crate::application::config::DatabaseConfig::max_connections`]).
106pub const DEFAULT_DATABASE_MAX_CONNECTIONS: u32 = 5;
107
108/// Default IG REST gateway: the **demo** environment.
109///
110/// Pointing the client at production requires an explicit opt-in (setting
111/// `IG_REST_BASE_URL` or supplying a
112/// [`crate::application::config::RestApiConfig`] directly).
113pub const DEFAULT_REST_BASE_URL: &str = "https://demo-api.ig.com/gateway/deal";
114
115/// Default REST request timeout in seconds
116/// ([`crate::application::config::RestApiConfig::timeout`]).
117pub const DEFAULT_REST_TIMEOUT_SECS: u64 = 30;
118
119/// Default Lightstreamer endpoint: the **demo** environment. Production
120/// requires an explicit opt-in via `IG_WS_URL` or a
121/// [`crate::application::config::WebSocketConfig`] supplied by the caller.
122pub const DEFAULT_WS_URL: &str = "wss://demo-apd.marketdatasystems.com";
123
124/// Default delay between Lightstreamer reconnection attempts, in seconds
125/// ([`crate::application::config::WebSocketConfig::reconnect_interval`]).
126pub const DEFAULT_WS_RECONNECT_INTERVAL_SECS: u64 = 5;
127
128/// Default request budget of the configured rate limiter
129/// ([`crate::application::config::RateLimiterConfig::max_requests`]).
130///
131/// Distinct from the per-endpoint-class limits above: this is the general
132/// non-trading budget applied when nothing else is configured. Not to be
133/// confused with [`FALLBACK_RATE_LIMIT_MAX_REQUESTS`], which is the floor
134/// applied when a caller configures a budget of zero.
135pub const DEFAULT_CONFIG_RATE_LIMIT_MAX_REQUESTS: u32 = 4;
136
137/// Default period of the configured rate limiter, in seconds
138/// ([`crate::application::config::RateLimiterConfig::period_seconds`]).
139pub const DEFAULT_CONFIG_RATE_LIMIT_PERIOD_SECONDS: u64 = 12;
140
141/// Default burst size of the configured rate limiter
142/// ([`crate::application::config::RateLimiterConfig::burst_size`]).
143///
144/// Not to be confused with [`DEFAULT_RATE_LIMIT_BURST_SIZE`], which is the
145/// fallback applied when a caller configures a burst size of zero.
146pub const DEFAULT_CONFIG_RATE_LIMIT_BURST_SIZE: u32 = 3;
147
148/// Default IG API version used for authentication when `IG_API_VERSION` is not
149/// set: v3 (OAuth).
150pub const DEFAULT_API_VERSION: u8 = 3;
151
152/// Lifetime of an IG API v2 (CST / X-SECURITY-TOKEN) session, in seconds
153/// (21600 = 6 hours).
154///
155/// This is the single source of truth for the v2 session lifetime: the session
156/// `expires_at` is derived from `created_at + V2_SESSION_LIFETIME_SECS`, staying
157/// consistent with how [`crate::model::auth::V2Response::is_expired`] computes
158/// expiry. It replaces the previously duplicated `now + 3600 * 6` / `21600`
159/// literals.
160pub const V2_SESSION_LIFETIME_SECS: u64 = 21600;
161
162/// Proactive-refresh safety margin for API v2 (CST / X-SECURITY-TOKEN) sessions,
163/// in seconds (5 minutes).
164///
165/// v2 sessions live for [`V2_SESSION_LIFETIME_SECS`] (~6 hours), so a 5-minute
166/// lead time before expiry is ample without churning tokens. The *same* margin
167/// is used both to decide a refresh is due and to actually perform it, so the
168/// proactive refresh window is consistent (see
169/// [`crate::application::auth::Auth::get_session`]).
170pub const PROACTIVE_REFRESH_MARGIN_V2_SECS: u64 = 300;
171
172/// Proactive-refresh safety margin for API v3 (OAuth) sessions, in seconds.
173///
174/// v3 access tokens are short-lived (~60 seconds), so the v2 margin (300s) would
175/// keep them permanently "about to expire" and trigger a login on every call. A
176/// small 10-second margin is sized relative to the ~60s token lifetime: it still
177/// refreshes ahead of expiry without spinning. The *same* margin is used both to
178/// decide a refresh is due and to perform it.
179pub const PROACTIVE_REFRESH_MARGIN_V3_SECS: u64 = 10;