use solana_program_error::ProgramError;
pub use solana_sdk_ids::sysvar::instructions::ID as INSTRUCTIONS_SYSVAR_ID;
pub use spl_token_interface::ID as SPL_TOKEN_PROGRAM_ID;
mod begin;
mod finalize;
pub use begin::{BeginSettle, BeginSettleInput, Pull, SettledOrder, SettledOrders};
pub use finalize::{
finalize_push_amounts, FinalizeSettle, FinalizeSettleInput, Push, Pushes,
FINALIZE_FIXED_ACCOUNTS,
};
pub fn recover_counterpart(instruction_data: &[u8]) -> Result<(u16, &[u8]), ProgramError> {
match instruction_data {
[b1, b2, rest @ ..] => Ok((u16::from_le_bytes([*b1, *b2]), rest)),
_ => Err(ProgramError::InvalidInstructionData),
}
}
#[cfg(any(test, feature = "test-fixtures"))]
pub mod fixtures {
use proptest::prelude::*;
use solana_pubkey::Pubkey;
pub fn arb_pushes(
count: impl Into<prop::collection::SizeRange>,
) -> impl Strategy<Value = (Vec<Pubkey>, Vec<Pubkey>, Vec<u8>, Vec<u64>)> {
prop::collection::vec(
(
any::<[u8; 32]>().prop_map(Pubkey::new_from_array),
any::<[u8; 32]>().prop_map(Pubkey::new_from_array),
any::<u8>(),
any::<u64>(),
),
count,
)
.prop_map(|pushes| {
let source_buffers = pushes.iter().map(|&(source, ..)| source).collect();
let destinations = pushes.iter().map(|&(_, dest, ..)| dest).collect();
let bumps = pushes.iter().map(|&(.., bump, _)| bump).collect();
let amounts = pushes.iter().map(|&(.., amount)| amount).collect();
(source_buffers, destinations, bumps, amounts)
})
}
}
#[cfg(test)]
mod tests {
use super::*;
use hex_literal::hex;
macro_rules! ix_data {
($($chunk:expr),* $(,)?) => {
[$(&$chunk[..]),*].concat()
};
}
pub(crate) use ix_data;
#[test]
fn rejects_empty_payload() {
assert_eq!(
recover_counterpart(&[]),
Err(ProgramError::InvalidInstructionData),
);
}
#[test]
fn rejects_too_short_payload() {
assert_eq!(
recover_counterpart(&[42]),
Err(ProgramError::InvalidInstructionData),
);
}
#[test]
fn returns_trailing_bytes() {
assert_eq!(
recover_counterpart(
&[
&hex!("3713")[..], &[42][..], ]
.concat()
),
Ok((0x1337, [42].as_slice())),
);
}
}