scematica-core 1.11.0

Core types, traits, and shared utilities for Scematica — config, RPC, wallet, metrics, token helpers.
Documentation
use solana_sdk::pubkey::Pubkey;
use spl_associated_token_account::{get_associated_token_address, get_associated_token_address_with_program_id};
use crate::types::known_tokens;

/// Token-2022 program ID (used by SCEMA and other modern tokens)
pub const TOKEN_2022_PROGRAM_ID: Pubkey =
    solana_sdk::pubkey!("TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb");

/// Legacy SPL Token program ID
pub const TOKEN_PROGRAM_ID: Pubkey =
    solana_sdk::pubkey!("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA");

/// Derive the associated token account address for a wallet + mint (legacy SPL Token program)
pub fn get_ata(wallet: &Pubkey, mint: &Pubkey) -> Pubkey {
    get_associated_token_address(wallet, mint)
}

/// Derive the ATA for a Token-2022 mint (different program ID → different address)
pub fn get_ata_2022(wallet: &Pubkey, mint: &Pubkey) -> Pubkey {
    get_associated_token_address_with_program_id(wallet, mint, &TOKEN_2022_PROGRAM_ID)
}

/// Derive the correct ATA for SCEMA (Token-2022)
pub fn get_scema_ata(wallet: &Pubkey) -> Pubkey {
    get_ata_2022(wallet, &known_tokens::SCEMATICA_MINT)
}

/// Resolve a token symbol to its mint pubkey
pub fn resolve_mint(symbol: &str) -> Option<Pubkey> {
    match symbol.to_uppercase().as_str() {
        "WSOL" | "SOL" => Some(known_tokens::WSOL_MINT),
        "USDC" => Some(known_tokens::USDC_MINT),
        "USDT" => Some(known_tokens::USDT_MINT),
        "RAY" => Some(known_tokens::RAY_MINT),
        "BONK" => Some(known_tokens::BONK_MINT),
        "SCEMA" | "SCEMATICA" => Some(known_tokens::SCEMATICA_MINT),
        _ => None,
    }
}

/// Resolve a token symbol to its decimals
pub fn resolve_decimals(symbol: &str) -> Option<u8> {
    match symbol.to_uppercase().as_str() {
        "WSOL" | "SOL" => Some(9),
        "USDC" => Some(6),
        "USDT" => Some(6),
        "RAY" => Some(6),
        "BONK" => Some(5),
        "SCEMA" | "SCEMATICA" => Some(known_tokens::SCEMATICA_DECIMALS),
        _ => None,
    }
}

/// Resolve a raw mint pubkey string to a human-readable symbol.
/// Returns the symbol if the mint is a known token, otherwise returns a
/// truncated version of the mint address (first 8 chars).
pub fn mint_to_symbol(mint: &str) -> String {
    match mint {
        m if m == known_tokens::WSOL_MINT.to_string() => "WSOL".into(),
        m if m == known_tokens::USDC_MINT.to_string() => "USDC".into(),
        m if m == known_tokens::USDT_MINT.to_string() => "USDT".into(),
        m if m == known_tokens::RAY_MINT.to_string() => "RAY".into(),
        m if m == known_tokens::BONK_MINT.to_string() => "BONK".into(),
        m if m == known_tokens::SCEMATICA_MINT.to_string() => known_tokens::SCEMATICA_SYMBOL.into(),
        m => m[..8.min(m.len())].into(),
    }
}

/// Convert UI amount (e.g. 1.5 SOL) to raw lamports/tokens
pub fn ui_to_raw(ui_amount: f64, decimals: u8) -> u64 {
    (ui_amount * 10f64.powi(decimals as i32)) as u64
}

/// Convert raw amount to UI amount
pub fn raw_to_ui(raw: u64, decimals: u8) -> f64 {
    raw as f64 / 10f64.powi(decimals as i32)
}

/// Apply slippage to get minimum output amount
pub fn apply_slippage(amount: u64, slippage_pct: f64) -> u64 {
    let factor = 1.0 - (slippage_pct / 100.0);
    (amount as f64 * factor) as u64
}