sequence-algo-sdk 0.4.0

Sequence Markets Algo SDK — write HFT trading algos in Rust, compile to WASM, deploy to Sequence
Documentation
//! HFT-safe async logging — non-blocking, ~100ns per call.

// =============================================================================
// LOGGING - HFT-safe async logging
// =============================================================================

/// Log levels for algo logging.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(u8)]
pub enum LogLevel {
    Trace = 0,
    Debug = 1,
    Info = 2,
    Warn = 3,
    Error = 4,
}

// Host import - only for WASM builds
#[cfg(target_arch = "wasm32")]
extern "C" {
    fn host_log_impl(level: u8, ptr: *const u8, len: u32);
}

#[cfg(target_arch = "wasm32")]
#[inline(always)]
fn host_log(level: u8, ptr: *const u8, len: u32) {
    unsafe {
        host_log_impl(level, ptr, len);
    }
}

// Stub for native builds (no-op)
#[cfg(not(target_arch = "wasm32"))]
#[inline(always)]
fn host_log(_level: u8, _ptr: *const u8, _len: u32) {}

// Re-export formatted log functions at module level so log_info!/log_warn!/etc.
// macros can use the path $crate::log::info_fmt (not $crate::log::log::info_fmt).
pub use self::log::{debug_fmt, error_fmt, info_fmt, log_fmt, warn_fmt};

/// Algo logging - non-blocking, ~100ns per call.
/// Logs are batched and viewable via dashboard with 1-2s delay.
pub mod log {
    use super::LogLevel;
    use core::fmt::Write;

    /// Log buffer for formatting.
    struct LogBuf {
        buf: [u8; 255],
        pos: usize,
    }

    impl LogBuf {
        #[inline(always)]
        const fn new() -> Self {
            Self {
                buf: [0u8; 255],
                pos: 0,
            }
        }

        #[inline(always)]
        fn as_slice(&self) -> &[u8] {
            &self.buf[..self.pos]
        }
    }

    impl Write for LogBuf {
        fn write_str(&mut self, s: &str) -> core::fmt::Result {
            let bytes = s.as_bytes();
            let space = self.buf.len() - self.pos;
            let n = bytes.len().min(space);
            self.buf[self.pos..self.pos + n].copy_from_slice(&bytes[..n]);
            self.pos += n;
            Ok(())
        }
    }

    #[inline(always)]
    fn send(level: LogLevel, msg: &[u8]) {
        super::host_log(level as u8, msg.as_ptr(), msg.len() as u32);
    }

    /// Log a trace message.
    #[inline(always)]
    pub fn trace(msg: &str) {
        send(LogLevel::Trace, msg.as_bytes());
    }

    /// Log a debug message.
    #[inline(always)]
    pub fn debug(msg: &str) {
        send(LogLevel::Debug, msg.as_bytes());
    }

    /// Log an info message.
    #[inline(always)]
    pub fn info(msg: &str) {
        send(LogLevel::Info, msg.as_bytes());
    }

    /// Log a warning message.
    #[inline(always)]
    pub fn warn(msg: &str) {
        send(LogLevel::Warn, msg.as_bytes());
    }

    /// Log an error message.
    #[inline(always)]
    pub fn error(msg: &str) {
        send(LogLevel::Error, msg.as_bytes());
    }

    /// Log with formatting (slightly slower).
    #[inline]
    pub fn log_fmt(level: LogLevel, args: core::fmt::Arguments<'_>) {
        let mut buf = LogBuf::new();
        let _ = buf.write_fmt(args);
        send(level, buf.as_slice());
    }

    /// Formatted info log.
    #[inline]
    pub fn info_fmt(args: core::fmt::Arguments<'_>) {
        log_fmt(LogLevel::Info, args);
    }

    /// Formatted warn log.
    #[inline]
    pub fn warn_fmt(args: core::fmt::Arguments<'_>) {
        log_fmt(LogLevel::Warn, args);
    }

    /// Formatted error log.
    #[inline]
    pub fn error_fmt(args: core::fmt::Arguments<'_>) {
        log_fmt(LogLevel::Error, args);
    }

    /// Formatted debug log.
    #[inline]
    pub fn debug_fmt(args: core::fmt::Arguments<'_>) {
        log_fmt(LogLevel::Debug, args);
    }
}