Overview
Each exchange in Parsecular has its own configuration struct with exchange-specific options. All configurations share a common base that provides networking and retry settings.
Base Configuration
All exchanges inherit from ExchangeConfig:
pub struct ExchangeConfig {
pub timeout : Duration , // Request timeout
pub rate_limit_per_second : u32 , // Max requests per second
pub max_retries : u32 , // Retry attempts
pub retry_delay : Duration , // Delay between retries
pub verbose : bool , // Enable logging
}
Defaults
Setting Default Value timeout30 seconds rate_limit_per_second10 max_retries3 retry_delay1 second verbosefalse
Builder Pattern
use pc_core :: ExchangeConfig ;
use std :: time :: Duration ;
let config = ExchangeConfig :: default ()
. with_timeout ( Duration :: from_secs ( 60 ))
. with_rate_limit ( 5 )
. with_retries ( 5 , Duration :: from_secs ( 2 ))
. with_verbose ( true );
Exchange-Specific Configurations
Polymarket
use pc_exchange_polymarket :: { PolymarketConfig , PolymarketSignatureType };
let config = PolymarketConfig :: new ()
. with_private_key ( "0x..." ) // Ethereum private key
. with_funder ( "0x..." ) // Funder wallet address
. with_signature_type ( PolymarketSignatureType :: Proxy ) // Wallet type
. with_api_credentials ( "key" , "secret" , "passphrase" ) // Pre-existing creds (optional)
. with_gamma_url ( "https://..." ) // Custom Gamma API URL
. with_clob_url ( "https://..." ) // Custom CLOB API URL
. with_verbose ( true );
Option Required Description private_keyFor trading Ethereum private key funderFor Proxy/GnosisSafe Funder wallet address (auto-derived if omitted) signature_typeNo Wallet type: Eoa (default), Proxy, or GnosisSafe api_keyNo Pre-existing CLOB API key (auto-derived if omitted) api_secretNo Pre-existing CLOB API secret api_passphraseNo Pre-existing CLOB API passphrase gamma_urlNo Gamma API endpoint clob_urlNo CLOB API endpoint chain_idNo Polygon chain ID (default: 137)
Limitless
use pc_exchange_limitless :: LimitlessConfig ;
let config = LimitlessConfig :: new ()
. with_private_key ( "0x..." )
. with_verbose ( true );
Option Required Description private_keyFor trading Ethereum private key
Kalshi
use pc_exchange_kalshi :: KalshiConfig ;
// Production
let config = KalshiConfig :: new ()
. with_api_key_id ( "key-id" )
. with_private_key_path ( "/path/to/key.pem" )
. with_verbose ( true );
// Demo environment
let demo = KalshiConfig :: demo ();
Option Required Description api_key_idFor trading API key identifier private_key_pathFor trading Path to RSA private key PEM private_key_pemAlternative PEM content directly api_urlNo Custom API endpoint demoNo Use demo environment
Opinion
use pc_exchange_opinion :: OpinionConfig ;
let config = OpinionConfig :: new ()
. with_api_key ( "api-key" )
. with_private_key ( "0x..." )
. with_multi_sig_addr ( "0x..." )
. with_verbose ( true );
Option Required Description api_keyYes API key private_keyFor trading Ethereum private key multi_sig_addrFor trading Multi-sig wallet address
Predict.fun
use pc_exchange_predictfun :: PredictFunConfig ;
// Production
let config = PredictFunConfig :: new ()
. with_api_key ( "api-key" )
. with_private_key ( "0x..." )
. with_verbose ( true );
// Testnet
let testnet = PredictFunConfig :: testnet ();
Option Required Description api_keyFor production API key private_keyFor trading Ethereum private key
API Server Configuration
When running the Parsec API server (pc-api), configure it using these environment variables:
Variable Default Description PARSEC_HOST0.0.0.0Server bind address PARSEC_PORT3000Server port PARSEC_API_KEY- Legacy API key (optional, DynamoDB is primary) LOCAL_MODEfalseBypass relay infrastructure for local development SERVER_REGIONus-east-2Server region identifier PARSEC_ENVdevEnvironment: prod, staging, or dev CREDENTIAL_SOURCEenvWhere to load credentials from METRICS_TOKEN- Token required to access /metrics endpoint
Quick Start
# Minimal local development setup
export LOCAL_MODE = true
export PARSEC_PORT = 3000
# Add exchange credentials
export POLYMARKET_PRIVATE_KEY = "0x..."
# Start the server
cargo run --bin pc-api
The server will be available at http://localhost:3000.
Endpoints
Endpoint Description GET /healthHealth check GET /metricsPrometheus metrics (requires METRICS_TOKEN) /api/v1/*API routes (requires API key)
Environment Variables
Required Variables by Exchange
Polymarket
Limitless
Kalshi
Opinion
Predict.fun
export POLYMARKET_PRIVATE_KEY = "0x..."
export POLYMARKET_FUNDER = "0x..."
# Wallet type: eoa (default), proxy (Magic/email), gnosis (MetaMask/browser)
export POLYMARKET_SIGNATURE_TYPE = "eoa"
# Optional: pre-existing API credentials (auto-derived if omitted)
export POLYMARKET_API_KEY = "..."
export POLYMARKET_API_SECRET = "..."
export POLYMARKET_API_PASSPHRASE = "..."
export LIMITLESS_PRIVATE_KEY = "0x..."
export KALSHI_API_KEY_ID = "your-key-id"
export KALSHI_PRIVATE_KEY_PATH = "/path/to/key.pem"
export OPINION_API_KEY = "your-api-key"
export OPINION_PRIVATE_KEY = "0x..."
export OPINION_MULTI_SIG_ADDR = "0x..."
export PREDICTFUN_API_KEY = "your-api-key"
export PREDICTFUN_PRIVATE_KEY = "0x..."
Loading from Environment
use std :: env;
// Manual loading
let mut config = PolymarketConfig :: new ()
. with_private_key ( env :: var ( "POLYMARKET_PRIVATE_KEY" ) ? );
if let Ok ( funder ) = env :: var ( "POLYMARKET_FUNDER" ) {
config = config . with_funder ( funder );
}
if let Ok ( sig_type ) = env :: var ( "POLYMARKET_SIGNATURE_TYPE" ) {
config = config . with_signature_type (
pc_exchange_polymarket :: PolymarketSignatureType :: from ( sig_type . as_str ())
);
}
// Or use validation helper
use pc_core :: { ExchangeId , validate_env_config};
match validate_env_config ( ExchangeId :: Polymarket ) {
Ok (()) => println! ( "Configuration valid" ),
Err ( e ) => println! ( "Missing env vars: {}" , e ),
}
Validation Helpers
Validate Environment
use pc_core :: { ExchangeId , validate_env_config};
// Check if all required env vars are set
let result = validate_env_config ( ExchangeId :: Polymarket );
Validate Private Key
use pc_core :: validate_private_key;
match validate_private_key ( "0x..." ) {
Ok (()) => println! ( "Valid key" ),
Err ( e ) => println! ( "Invalid: {}" , e ),
}
Key validation checks:
Not empty
64 hex characters (with optional 0x prefix)
Valid hexadecimal format
List Exchanges
use pc_core :: {list_exchanges, list_exchange_names, ExchangeId };
// Get all exchange IDs
let ids = list_exchanges ();
// [Polymarket, Opinion, Limitless, Kalshi, PredictFun]
// Get names as strings
let names = list_exchange_names ();
// ["polymarket", "opinion", "limitless", "kalshi", "predictfun"]
// Parse from string
let id : ExchangeId = "polymarket" . parse () . unwrap ();
// Get required env vars
let vars = id . required_env_vars ();
// ["POLYMARKET_PRIVATE_KEY", "POLYMARKET_FUNDER"]
Rate Limiting
Built-in rate limiting prevents API throttling:
use pc_core :: RateLimiter ;
// Create a limiter for 5 requests/second
let mut limiter = RateLimiter :: new ( 5 );
// Automatically waits if needed
limiter . wait () . await ;
make_request () . await ;
limiter . wait () . await ;
make_request () . await ;
Retry with Backoff
use pc_core :: retry_with_backoff;
use std :: time :: Duration ;
let result = retry_with_backoff (
3 , // max attempts
Duration :: from_secs ( 1 ), // initial delay
|| async {
exchange . fetch_markets ( None ) . await
},
) . await ? ;
Security Best Practices
Never commit private keys or API credentials to version control.
Use environment variables
Store credentials in environment variables, not in code.
For production, consider using AWS Secrets Manager, HashiCorp Vault, or similar.
Periodically rotate API keys and private keys.
Use separate keys for testing
Use different credentials for development and production.
Some exchanges allow read-only or trading-only keys.
Next Steps