Skip to main content

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

SettingDefault 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);
OptionRequiredDescription
private_keyFor tradingEthereum private key
funderFor Proxy/GnosisSafeFunder wallet address (auto-derived if omitted)
signature_typeNoWallet type: Eoa (default), Proxy, or GnosisSafe
api_keyNoPre-existing CLOB API key (auto-derived if omitted)
api_secretNoPre-existing CLOB API secret
api_passphraseNoPre-existing CLOB API passphrase
gamma_urlNoGamma API endpoint
clob_urlNoCLOB API endpoint
chain_idNoPolygon chain ID (default: 137)

Limitless

use pc_exchange_limitless::LimitlessConfig;

let config = LimitlessConfig::new()
    .with_private_key("0x...")
    .with_verbose(true);
OptionRequiredDescription
private_keyFor tradingEthereum 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();
OptionRequiredDescription
api_key_idFor tradingAPI key identifier
private_key_pathFor tradingPath to RSA private key PEM
private_key_pemAlternativePEM content directly
api_urlNoCustom API endpoint
demoNoUse 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);
OptionRequiredDescription
api_keyYesAPI key
private_keyFor tradingEthereum private key
multi_sig_addrFor tradingMulti-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();
OptionRequiredDescription
api_keyFor productionAPI key
private_keyFor tradingEthereum private key

API Server Configuration

When running the Parsec API server (pc-api), configure it using these environment variables:
VariableDefaultDescription
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

EndpointDescription
GET /healthHealth check
GET /metricsPrometheus metrics (requires METRICS_TOKEN)
/api/v1/*API routes (requires API key)

Environment Variables

Required Variables by Exchange

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="..."

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.
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 different credentials for development and production.
Some exchanges allow read-only or trading-only keys.

Next Steps