acta-maker-sdk 0.4.1

Rust SDK for Acta options market makers — WebSocket client, order signing, message types
Documentation
use super::*;

fn account(owner: Pubkey, data: Vec<u8>) -> Account {
    Account {
        lamports: 0,
        data,
        owner,
        executable: false,
        rent_epoch: 0,
    }
}

#[test]
fn position_layout_decodes_canonical_offsets() {
    let program_id = Pubkey::new_unique();
    let taker = Pubkey::new_unique();
    let maker = Pubkey::new_unique();
    let market = Pubkey::new_unique();
    let mut data = vec![0; POSITION_MIN_LEN];
    data[ACCOUNT_OFFSET_DISCRIMINATOR] = POSITION_DISCRIMINATOR;
    data[ACCOUNT_OFFSET_VERSION] = 1;
    data[POSITION_OFFSET_POSITION_TYPE] = 1;
    data[POSITION_OFFSET_STATUS] = PositionStatus::Open as u8;
    data[POSITION_OFFSET_TAKER_OWNER..POSITION_OFFSET_TAKER_OWNER + 32]
        .copy_from_slice(taker.as_ref());
    data[POSITION_OFFSET_MAKER_OWNER..POSITION_OFFSET_MAKER_OWNER + 32]
        .copy_from_slice(maker.as_ref());
    data[POSITION_OFFSET_MARKET..POSITION_OFFSET_MARKET + 32].copy_from_slice(market.as_ref());
    data[POSITION_OFFSET_STRIKE..POSITION_OFFSET_STRIKE + 8].copy_from_slice(&7u64.to_le_bytes());
    data[POSITION_OFFSET_QUANTITY..POSITION_OFFSET_QUANTITY + 8]
        .copy_from_slice(&9u64.to_le_bytes());
    data[POSITION_OFFSET_ORDER_ID..POSITION_OFFSET_ORDER_ID + 32].fill(11);

    let position = parse_position(&account(program_id, data), &program_id).unwrap();
    assert_eq!(position.position_type, PositionType::CashSecuredPut);
    assert_eq!(position.status, PositionStatus::Open);
    assert_eq!(position.taker_owner, taker);
    assert_eq!(position.maker_owner, maker);
    assert_eq!(position.market_pda, market);
    assert_eq!(position.strike, Strike::new(7));
    assert_eq!(position.quantity, Quantity::new(9));
    assert_eq!(position.order_id, OrderId::new([11; 32]));
}

#[test]
fn account_codecs_reject_truncated_or_unknown_data() {
    let program_id = Pubkey::new_unique();
    let mut truncated = vec![0; POSITION_MIN_LEN - 1];
    truncated[ACCOUNT_OFFSET_DISCRIMINATOR] = POSITION_DISCRIMINATOR;
    truncated[ACCOUNT_OFFSET_VERSION] = 1;
    assert!(matches!(
        parse_position(&account(program_id, truncated), &program_id),
        Err(ChainError::InvalidAccountData)
    ));
    let mut position = vec![0; POSITION_MIN_LEN];
    position[ACCOUNT_OFFSET_DISCRIMINATOR] = POSITION_DISCRIMINATOR;
    position[ACCOUNT_OFFSET_VERSION] = 1;
    position[POSITION_OFFSET_STATUS] = 99;
    assert!(matches!(
        parse_position(&account(program_id, position), &program_id),
        Err(ChainError::UnknownPositionStatus(99))
    ));
    let mut market = vec![0; MARKET_MIN_LEN - 1];
    market[ACCOUNT_OFFSET_DISCRIMINATOR] = MARKET_DISCRIMINATOR;
    market[ACCOUNT_OFFSET_VERSION] = 1;
    assert!(matches!(
        parse_market(&account(program_id, market), &program_id),
        Err(ChainError::InvalidAccountData)
    ));
}

#[test]
fn account_codecs_reject_wrong_owner_type_and_uninitialized_data() {
    let program_id = Pubkey::new_unique();
    let wrong_owner = Pubkey::new_unique();
    let mut data = vec![0; POSITION_MIN_LEN];
    data[ACCOUNT_OFFSET_DISCRIMINATOR] = POSITION_DISCRIMINATOR;
    data[ACCOUNT_OFFSET_VERSION] = 1;

    assert!(matches!(
        parse_position(&account(wrong_owner, data.clone()), &program_id),
        Err(ChainError::AccountOwnerMismatch { .. })
    ));

    data[ACCOUNT_OFFSET_DISCRIMINATOR] = MARKET_DISCRIMINATOR;
    assert!(matches!(
        parse_position(&account(program_id, data.clone()), &program_id),
        Err(ChainError::AccountDiscriminatorMismatch { .. })
    ));

    data[ACCOUNT_OFFSET_DISCRIMINATOR] = POSITION_DISCRIMINATOR;
    data[ACCOUNT_OFFSET_VERSION] = 0;
    assert!(matches!(
        parse_position(&account(program_id, data), &program_id),
        Err(ChainError::UninitializedAccount)
    ));
}

#[test]
fn market_layout_keeps_token_programs_distinct_from_oracles() {
    let program_id = Pubkey::new_unique();
    let underlying_program = Pubkey::new_unique();
    let quote_program = Pubkey::new_unique();
    let mut data = vec![0; MARKET_MIN_LEN];
    data[ACCOUNT_OFFSET_DISCRIMINATOR] = MARKET_DISCRIMINATOR;
    data[ACCOUNT_OFFSET_VERSION] = 1;
    data[MARKET_OFFSET_UNDERLYING_DECIMALS] = 9;
    data[MARKET_OFFSET_QUOTE_DECIMALS] = 6;
    data[MARKET_OFFSET_UNDERLYING_TOKEN_PROGRAM..MARKET_OFFSET_UNDERLYING_TOKEN_PROGRAM + 32]
        .copy_from_slice(underlying_program.as_ref());
    data[MARKET_OFFSET_QUOTE_TOKEN_PROGRAM..MARKET_OFFSET_QUOTE_TOKEN_PROGRAM + 32]
        .copy_from_slice(quote_program.as_ref());

    let market = parse_market(&account(program_id, data), &program_id).unwrap();
    assert_eq!(market.underlying_decimals, Decimals::new(9));
    assert_eq!(market.quote_decimals, Decimals::new(6));
    assert_eq!(market.underlying_token_program_id, underlying_program);
    assert_eq!(market.quote_token_program_id, quote_program);
}