roshi 0.0.1

A Rust client for the Kalshi API
Documentation
pub fn format_endpoint(template: &str, params: &[(&str, &str)]) -> String {
    let mut result = template.to_string();
    for (key, val) in params {
        result = result.replace(&format!("{{{}}}", key), val);
    }
    result
}

use std::time::{SystemTime, UNIX_EPOCH};

pub fn get_timestamp_in_milliseconds() -> Result<u128, std::time::SystemTimeError> {
    let current_system_time = SystemTime::now();
    let duration_since_epoch = current_system_time.duration_since(UNIX_EPOCH)?;
    let milliseconds_timestamp = duration_since_epoch.as_millis();
    Ok(milliseconds_timestamp)
}

use base64::{engine::general_purpose, Engine as _};
use rsa::{pkcs1::DecodeRsaPrivateKey, Pss, RsaPrivateKey};

pub fn sign_pss_text(private_key: &RsaPrivateKey, text: &str) -> Result<String, String> {
    use rand::rngs::OsRng;
    use sha2::Digest;
    use sha2::Sha256;

    let message = text.as_bytes();
    let mut rng = OsRng;
    let pss = Pss::new::<Sha256>();

    let mut hasher = Sha256::new();
    hasher.update(message);
    let message = hasher.finalize();

    match private_key.sign_with_rng(&mut rng, pss, &message) {
        Ok(signature) => Ok(general_purpose::STANDARD.encode(signature)),
        Err(e) => Err(format!("RSA sign PSS failed: {}", e)),
    }
}

fn load_private_key_from_pem(pem: &str) -> Result<RsaPrivateKey, String> {
    RsaPrivateKey::from_pkcs1_pem(pem)
        .map_err(|e| format!("Failed to parse RSA private key from PEM: {}", e))
}

pub fn load_private_key_from_file(file_path: &str) -> Result<RsaPrivateKey, String> {
    let pem = std::fs::read_to_string(file_path)
        .map_err(|e| format!("Failed to read private key file: {}", e))?;
    load_private_key_from_pem(&pem)
}

pub fn load_and_sign_with_private_key(file_path: &str, text: &str) -> Result<String, String> {
    let private_key = load_private_key_from_file(file_path)?;
    sign_pss_text(&private_key, text)
}