usdc-plus-exchange 0.1.4

USDC <-> USDC+ exchange library for the Reflect protocol.
Documentation
use crate::ReflectErrorCodes;
use anchor_lang::prelude::*;

const PUBKEY_SIZE: usize = 32;
const COPTION_TAG_SIZE: usize = 4; // COption<T> in Solana wire format = 4-byte tag + T bytes (when Some) (matches solana_program::program_option::COption packing).
const COPTION_PUBKEY_SIZE: usize = COPTION_TAG_SIZE + PUBKEY_SIZE; // 36

const SUPPLY_OFFSET: usize = COPTION_PUBKEY_SIZE;
const SUPPLY_SIZE: usize = 8;
const SUPPLY_END: usize = SUPPLY_OFFSET + SUPPLY_SIZE;

/// Reads only the u64 supply from a raw Mint account (no Anchor discriminator).
/// Layout:
///   0..36  : COption<Pubkey> mint_authority  (4-byte tag + 32-byte key)
///   36..44 : u64 supply (LE)   <-- Desirable field
///   44     : u8 decimals
///   45     : bool is_initialized
///   46..82 : COption<Pubkey> freeze_authority
///   ...    : (Token-2022 TLV extensions may follow)
pub fn get_mint_supply(data: &[u8]) -> Result<u64> {
    if data.len() < SUPPLY_END {
        return Err(ReflectErrorCodes::InsufficientData.into());
    }

    if data.len() < SUPPLY_END {
        return Err(ReflectErrorCodes::InsufficientData.into());
    }

    // Little-endian u64 at offset 36.
    let mut buf = [0u8; SUPPLY_SIZE];
    buf.copy_from_slice(&data[SUPPLY_OFFSET..SUPPLY_END]);
    Ok(u64::from_le_bytes(buf))
}

// cargo test --lib spl_mint -- --nocapture

#[test]
fn test_log_mint_supply() {
    use std::fs;
    use std::path::PathBuf;

    // Keep these in sync with your other tests.
    const LOCAL_USDC_PLUS_MINT: &str = "usdc_plus_mint.bin";

    fn get_test_assets_dir() -> PathBuf {
        let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
        path.push("./test_assets/local/");
        path
    }

    let assets_dir = get_test_assets_dir();
    let mint_data = fs::read(assets_dir.join(LOCAL_USDC_PLUS_MINT))
        .expect(&format!("Missing: {}", LOCAL_USDC_PLUS_MINT));

    // ---- via your reader ----
    let supply_via_fn = get_mint_supply(&mint_data)
        .expect("get_mint_supply failed");

    // ---- manual decode for cross-check (SPL Mint layout) ----
    // COption<Pubkey> mint_authority: 4-byte tag + 32-byte key = 36 bytes
    // supply: u64 LE at [36..44]
    // decimals: u8 at [44]
    // is_initialized: u8 (bool) at [45]
    // freeze_authority COption tag at [46..50] (4 bytes), then 32 bytes if Some
    assert!(mint_data.len() >= 46, "Mint buffer too short: {} bytes", mint_data.len());

    let mut supply_bytes = [0u8; 8];
    supply_bytes.copy_from_slice(&mint_data[36..44]);
    let supply_manual = u64::from_le_bytes(supply_bytes);

    let decimals = mint_data[44];
    let is_initialized = mint_data[45] != 0;

    // Optional: print COption tags for extra sanity.
    let mut mint_auth_tag_bytes = [0u8; 4];
    mint_auth_tag_bytes.copy_from_slice(&mint_data[0..4]);
    let mint_auth_tag = u32::from_le_bytes(mint_auth_tag_bytes); // 0=None, 1=Some

    let mut freeze_auth_tag_bytes = [0u8; 4];
    freeze_auth_tag_bytes.copy_from_slice(&mint_data[46..50]);
    let freeze_auth_tag = u32::from_le_bytes(freeze_auth_tag_bytes); // 0=None, 1=Some

    println!("\n=== Mint Sanity ===");
    println!("supply (get_mint_supply): {}", supply_via_fn);
    println!("supply (manual decode)  : {}", supply_manual);
    println!("decimals                : {}", decimals);
    println!("is_initialized          : {}", is_initialized);
    println!("mint_authority tag      : {} (0=None, 1=Some)", mint_auth_tag);
    println!("freeze_authority tag    : {} (0=None, 1=Some)", freeze_auth_tag);
    println!("mint_data len           : {}", mint_data.len());

    // Cross-check consistency (don’t assert exact value; just that both methods agree).
    assert_eq!(supply_via_fn, supply_manual, "Mismatch between get_mint_supply and manual decode");
}