1#[cfg(doctest)]
41#[doc = include_str!("../README.md")]
42struct ReadmeDoctests;
43
44#[macro_use]
45pub mod macros;
46
47pub mod auth;
48pub mod capacity;
49pub mod client;
50pub mod config;
51pub mod error;
52pub mod health;
53pub mod hold;
54pub mod hooks;
55pub mod polymarket;
56mod query;
57pub mod rate_limit;
58pub mod request;
59pub mod send;
60pub mod session_signer;
61pub mod signer_limit;
62
63#[cfg(feature = "keychain")]
64pub mod keychain;
65
66#[cfg(test)]
67mod macro_tests;
68
69const LOG_BODY_MAX_LEN: usize = 512;
71
72pub fn truncate_for_log(s: &str) -> std::borrow::Cow<'_, str> {
77 if s.len() <= LOG_BODY_MAX_LEN {
78 std::borrow::Cow::Borrowed(s)
79 } else {
80 let truncated = &s[..s.floor_char_boundary(LOG_BODY_MAX_LEN)];
81 std::borrow::Cow::Owned(format!("{}... [truncated]", truncated))
82 }
83}
84
85pub use reqwest;
92
93pub use auth::{current_timestamp, Base64Format, Signer};
94pub use capacity::CapacityBucket;
95pub use client::{
96 retry_after_header, HttpClient, HttpClientBuilder, DEFAULT_POOL_SIZE, DEFAULT_TIMEOUT_MS,
97};
98pub use config::ClientConfig;
99pub use error::{ApiError, ErrorResponse};
100pub use health::Pong;
101pub use hold::Hold;
102pub use hooks::{
103 AttemptInfo, Authenticator, Charge, Cost, Decision, DefaultRetryPolicy, DynAuthenticator,
104 DynRetryPolicy, DynThrottle, LayerCharge, LayerId, NoThrottle, Outcome, Refused, RequestMeta,
105 RequestParts, ResponseMeta, RetryPolicy, Throttle,
106};
107pub use query::csv;
108pub use rate_limit::{
109 BucketId, EffectiveQuota, Matching, QuotaRow, RateLimiter, RetryConfig, WindowQuotaTable,
110};
111pub use request::{QueryBuilder, Request, RequestError};
112pub use send::decode_json;
113pub use session_signer::{DepositWalletRole, SessionSignerScope};
114pub use signer_limit::{
115 BurstCapacityExceeded, RateLimitStatus, SignerLimiter, Tier, TradingBucket, TradingRequest,
116};
117
118#[cfg(feature = "keychain")]
119pub use keychain::KeychainError;
120
121const _: fn() = || {
125 fn is<T: polyoxide_venue::Classify>() {}
126 is::<ApiError>();
127 is::<BurstCapacityExceeded>();
128 is::<Refused>();
129 #[cfg(feature = "keychain")]
130 is::<KeychainError>();
131};
132
133#[cfg(test)]
134mod tests {
135 use super::*;
136
137 #[test]
138 fn test_truncate_for_log_short_string_unchanged() {
139 let short = "hello world";
140 let result = truncate_for_log(short);
141 assert_eq!(result.as_ref(), short);
142 }
143
144 #[test]
145 fn test_truncate_for_log_exact_limit_unchanged() {
146 let exact = "a".repeat(LOG_BODY_MAX_LEN);
147 let result = truncate_for_log(&exact);
148 assert_eq!(result.as_ref(), exact.as_str());
149 }
150
151 #[test]
152 fn test_truncate_for_log_over_limit_truncated() {
153 let long = "x".repeat(LOG_BODY_MAX_LEN + 100);
154 let result = truncate_for_log(&long);
155 assert!(result.ends_with("... [truncated]"));
156 assert!(result.len() < long.len());
157 }
158
159 #[test]
160 fn test_truncate_for_log_multibyte_char_boundary() {
161 let mut s = "a".repeat(LOG_BODY_MAX_LEN - 1);
163 s.push('\u{1F600}'); s.push_str("overflow");
165 let result = truncate_for_log(&s);
166 assert!(result.ends_with("... [truncated]"));
167 assert!(result.is_char_boundary(0));
169 }
170}