slotstrike 1.0.0

Low-latency Solana slotstrike runtime for event-driven token execution
Documentation
const LAMPORTS_PER_SOL: u64 = 1_000_000_000;

#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub struct Lamports(u64);

impl Lamports {
    #[inline(always)]
    pub const fn new(value: u64) -> Self {
        Self(value)
    }

    #[inline(always)]
    pub const fn as_u64(self) -> u64 {
        self.0
    }

    #[inline(always)]
    pub fn as_sol_string(self) -> String {
        let whole = self.0 / LAMPORTS_PER_SOL;
        let fractional = self.0 % LAMPORTS_PER_SOL;

        if fractional == 0 {
            return whole.to_string();
        }

        let mut fractional_string = format!("{fractional:09}");
        while fractional_string.ends_with('0') {
            fractional_string.pop();
        }

        format!("{whole}.{fractional_string}")
    }
}

pub fn parse_positive_sol_str_to_lamports(sol: &str) -> Option<Lamports> {
    let lamports = parse_sol_str_to_lamports(sol.trim())?;
    if lamports == 0 {
        return None;
    }

    Some(Lamports::new(lamports))
}

fn parse_sol_str_to_lamports(sol: &str) -> Option<u64> {
    if sol.is_empty() || sol.starts_with('-') {
        return None;
    }

    let (whole_raw, fractional_raw) = match sol.split_once('.') {
        Some((whole, fractional)) if !fractional.contains('.') => (whole, fractional),
        Some(_) => return None,
        None => (sol, ""),
    };

    if whole_raw.is_empty() && fractional_raw.is_empty() {
        return None;
    }

    if !whole_raw.is_empty()
        && !whole_raw
            .chars()
            .all(|character| character.is_ascii_digit())
    {
        return None;
    }

    if !fractional_raw.is_empty()
        && !fractional_raw
            .chars()
            .all(|character| character.is_ascii_digit())
    {
        return None;
    }

    if fractional_raw.len() > 9 {
        return None;
    }

    let whole = if whole_raw.is_empty() {
        0_u64
    } else {
        parse_ascii_u64(whole_raw)?
    };

    let mut fractional = if fractional_raw.is_empty() {
        0_u64
    } else {
        parse_ascii_u64(fractional_raw)?
    };

    for _ in fractional_raw.len()..9 {
        fractional = fractional.checked_mul(10)?;
    }

    whole
        .checked_mul(LAMPORTS_PER_SOL)
        .and_then(|whole_lamports| whole_lamports.checked_add(fractional))
}

fn parse_ascii_u64(value: &str) -> Option<u64> {
    if value.is_empty() {
        return None;
    }

    let mut parsed = 0_u64;
    for byte in value.bytes() {
        if !byte.is_ascii_digit() {
            return None;
        }

        parsed = parsed
            .checked_mul(10)?
            .checked_add(u64::from(byte.saturating_sub(b'0')))?;
    }

    Some(parsed)
}

#[cfg(test)]
mod tests {
    use super::{Lamports, parse_positive_sol_str_to_lamports};

    #[test]
    fn parses_fixed_point_sol_amounts() {
        assert_eq!(
            parse_positive_sol_str_to_lamports("1").map(Lamports::as_u64),
            Some(1_000_000_000)
        );
        assert_eq!(
            parse_positive_sol_str_to_lamports("1.23").map(Lamports::as_u64),
            Some(1_230_000_000)
        );
        assert_eq!(
            parse_positive_sol_str_to_lamports(".5").map(Lamports::as_u64),
            Some(500_000_000)
        );
        assert_eq!(
            parse_positive_sol_str_to_lamports("0.000000001").map(Lamports::as_u64),
            Some(1)
        );
    }

    #[test]
    fn rejects_invalid_or_non_positive_values() {
        assert_eq!(parse_positive_sol_str_to_lamports("0"), None);
        assert_eq!(parse_positive_sol_str_to_lamports("0.000000000"), None);
        assert_eq!(parse_positive_sol_str_to_lamports("1.0000000001"), None);
        assert_eq!(parse_positive_sol_str_to_lamports("abc"), None);
        assert_eq!(parse_positive_sol_str_to_lamports("-1"), None);
    }

    #[test]
    fn formats_sol_strings_without_float_drift() {
        assert_eq!(Lamports::new(1_000_000_000).as_sol_string(), "1");
        assert_eq!(Lamports::new(1_230_000_000).as_sol_string(), "1.23");
        assert_eq!(Lamports::new(1).as_sol_string(), "0.000000001");
    }
}