use solana_program::pubkey::Pubkey;
use super::types::{AmmCreatorFeeOn, VestingSchedule};
#[derive(Clone, Debug, Default)]
pub struct PoolState {
pub epoch: u64,
pub auth_bump: u8,
pub status: u8,
pub base_decimals: u8,
pub quote_decimals: u8,
pub migrate_type: u8,
pub supply: u64,
pub total_base_sell: u64,
pub virtual_base: u64,
pub virtual_quote: u64,
pub real_base: u64,
pub real_quote: u64,
pub total_quote_fund_raising: u64,
pub quote_protocol_fee: u64,
pub platform_fee: u64,
pub migrate_fee: u64,
pub vesting_schedule: VestingSchedule,
pub global_config: Pubkey,
pub platform_config: Pubkey,
pub base_mint: Pubkey,
pub quote_mint: Pubkey,
pub base_vault: Pubkey,
pub quote_vault: Pubkey,
pub creator: Pubkey,
pub token_program_flag: u8,
pub amm_creator_fee_on: AmmCreatorFeeOn,
}
impl PoolState {
pub const DISCRIMINATOR: [u8; 8] = [247, 237, 227, 245, 215, 195, 222, 70];
pub fn try_from_bytes(data: &[u8]) -> Result<Self, std::io::Error> {
if data.len() < 8 {
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
"Data too short",
));
}
let (discriminator, rest) = data.split_at(8);
if discriminator != Self::DISCRIMINATOR {
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
"Invalid discriminator",
));
}
Self::deserialize(rest)
}
fn deserialize(data: &[u8]) -> Result<Self, std::io::Error> {
let mut offset = 0;
let epoch = read_u64(data, &mut offset)?;
let auth_bump = read_u8(data, &mut offset)?;
let status = read_u8(data, &mut offset)?;
let base_decimals = read_u8(data, &mut offset)?;
let quote_decimals = read_u8(data, &mut offset)?;
let migrate_type = read_u8(data, &mut offset)?;
let supply = read_u64(data, &mut offset)?;
let total_base_sell = read_u64(data, &mut offset)?;
let virtual_base = read_u64(data, &mut offset)?;
let virtual_quote = read_u64(data, &mut offset)?;
let real_base = read_u64(data, &mut offset)?;
let real_quote = read_u64(data, &mut offset)?;
let total_quote_fund_raising = read_u64(data, &mut offset)?;
let quote_protocol_fee = read_u64(data, &mut offset)?;
let platform_fee = read_u64(data, &mut offset)?;
let migrate_fee = read_u64(data, &mut offset)?;
let total_locked_amount = read_u64(data, &mut offset)?;
let cliff_period = read_u64(data, &mut offset)?;
let unlock_period = read_u64(data, &mut offset)?;
let start_time = read_u64(data, &mut offset)?;
let allocated_share_amount = read_u64(data, &mut offset)?;
let vesting_schedule = VestingSchedule {
total_locked_amount,
cliff_period,
unlock_period,
start_time,
allocated_share_amount,
};
let global_config = read_pubkey(data, &mut offset)?;
let platform_config = read_pubkey(data, &mut offset)?;
let base_mint = read_pubkey(data, &mut offset)?;
let quote_mint = read_pubkey(data, &mut offset)?;
let base_vault = read_pubkey(data, &mut offset)?;
let quote_vault = read_pubkey(data, &mut offset)?;
let creator = read_pubkey(data, &mut offset)?;
let token_program_flag = read_u8(data, &mut offset)?;
let amm_creator_fee_on_byte = read_u8(data, &mut offset)?;
Ok(Self {
epoch,
auth_bump,
status,
base_decimals,
quote_decimals,
migrate_type,
supply,
total_base_sell,
virtual_base,
virtual_quote,
real_base,
real_quote,
total_quote_fund_raising,
quote_protocol_fee,
platform_fee,
migrate_fee,
vesting_schedule,
global_config,
platform_config,
base_mint,
quote_mint,
base_vault,
quote_vault,
creator,
token_program_flag,
amm_creator_fee_on: AmmCreatorFeeOn::from_u8(amm_creator_fee_on_byte),
})
}
pub fn is_funding(&self) -> bool {
self.status == 0
}
pub fn is_migrate(&self) -> bool {
self.status == 1
}
pub fn is_trading(&self) -> bool {
self.status == 2
}
pub fn is_base_token_2022(&self) -> bool {
self.token_program_flag & 0x01 != 0
}
pub fn is_quote_token_2022(&self) -> bool {
self.token_program_flag & 0x02 != 0
}
}
#[derive(Clone, Debug, Default)]
pub struct GlobalConfig {
pub epoch: u64,
pub quote_mint: Pubkey,
pub protocol_fee_owner: Pubkey,
pub migrate_fee_owner: Pubkey,
pub migrate_to_amm_wallet: Pubkey,
pub migrate_to_cpswap_wallet: Pubkey,
pub trade_fee_rate: u64,
pub migrate_fee: u64,
pub curve_type: u8,
pub index: u16,
}
impl GlobalConfig {
pub const DISCRIMINATOR: [u8; 8] = [149, 8, 156, 202, 160, 252, 176, 217];
pub fn try_from_bytes(data: &[u8]) -> Result<Self, std::io::Error> {
if data.len() < 8 {
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
"Data too short",
));
}
let (discriminator, rest) = data.split_at(8);
if discriminator != Self::DISCRIMINATOR {
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
"Invalid discriminator",
));
}
let mut offset = 0;
let epoch = read_u64(rest, &mut offset)?;
let quote_mint = read_pubkey(rest, &mut offset)?;
let protocol_fee_owner = read_pubkey(rest, &mut offset)?;
let migrate_fee_owner = read_pubkey(rest, &mut offset)?;
let migrate_to_amm_wallet = read_pubkey(rest, &mut offset)?;
let migrate_to_cpswap_wallet = read_pubkey(rest, &mut offset)?;
let trade_fee_rate = read_u64(rest, &mut offset)?;
let migrate_fee = read_u64(rest, &mut offset)?;
let curve_type = read_u8(rest, &mut offset)?;
let index = read_u16(rest, &mut offset)?;
Ok(Self {
epoch,
quote_mint,
protocol_fee_owner,
migrate_fee_owner,
migrate_to_amm_wallet,
migrate_to_cpswap_wallet,
trade_fee_rate,
migrate_fee,
curve_type,
index,
})
}
}
fn read_u8(data: &[u8], offset: &mut usize) -> Result<u8, std::io::Error> {
if *offset >= data.len() {
return Err(std::io::Error::new(
std::io::ErrorKind::UnexpectedEof,
"Unexpected end of data",
));
}
let value = data[*offset];
*offset += 1;
Ok(value)
}
fn read_u16(data: &[u8], offset: &mut usize) -> Result<u16, std::io::Error> {
if *offset + 2 > data.len() {
return Err(std::io::Error::new(
std::io::ErrorKind::UnexpectedEof,
"Unexpected end of data",
));
}
let value = u16::from_le_bytes([data[*offset], data[*offset + 1]]);
*offset += 2;
Ok(value)
}
fn read_u64(data: &[u8], offset: &mut usize) -> Result<u64, std::io::Error> {
if *offset + 8 > data.len() {
return Err(std::io::Error::new(
std::io::ErrorKind::UnexpectedEof,
"Unexpected end of data",
));
}
let bytes: [u8; 8] = data[*offset..*offset + 8].try_into().unwrap();
let value = u64::from_le_bytes(bytes);
*offset += 8;
Ok(value)
}
fn read_pubkey(data: &[u8], offset: &mut usize) -> Result<Pubkey, std::io::Error> {
if *offset + 32 > data.len() {
return Err(std::io::Error::new(
std::io::ErrorKind::UnexpectedEof,
"Unexpected end of data",
));
}
let bytes: [u8; 32] = data[*offset..*offset + 32].try_into().unwrap();
let pubkey = Pubkey::new_from_array(bytes);
*offset += 32;
Ok(pubkey)
}
#[derive(Clone, Debug)]
pub struct PlatformConfig {
pub epoch: u64,
pub platform_fee_wallet: Pubkey,
pub platform_nft_wallet: Pubkey,
pub platform_scale: u64,
pub creator_scale: u64,
pub burn_scale: u64,
pub fee_rate: u64,
pub name: [u8; 64],
}
impl Default for PlatformConfig {
fn default() -> Self {
Self {
epoch: 0,
platform_fee_wallet: Pubkey::default(),
platform_nft_wallet: Pubkey::default(),
platform_scale: 0,
creator_scale: 0,
burn_scale: 0,
fee_rate: 0,
name: [0; 64],
}
}
}
impl PlatformConfig {
pub const DISCRIMINATOR: [u8; 8] = [160, 78, 128, 0, 248, 83, 230, 160];
pub fn try_from_bytes(data: &[u8]) -> Result<Self, std::io::Error> {
if data.len() < 8 {
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
"Data too short",
));
}
let (discriminator, rest) = data.split_at(8);
if discriminator != Self::DISCRIMINATOR {
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
"Invalid discriminator",
));
}
let mut offset = 0;
let epoch = read_u64(rest, &mut offset)?;
let platform_fee_wallet = read_pubkey(rest, &mut offset)?;
let platform_nft_wallet = read_pubkey(rest, &mut offset)?;
let platform_scale = read_u64(rest, &mut offset)?;
let creator_scale = read_u64(rest, &mut offset)?;
let burn_scale = read_u64(rest, &mut offset)?;
let fee_rate = read_u64(rest, &mut offset)?;
if offset + 64 > rest.len() {
return Err(std::io::Error::new(
std::io::ErrorKind::UnexpectedEof,
"Unexpected end of data",
));
}
let name: [u8; 64] = rest[offset..offset + 64].try_into().unwrap();
Ok(Self {
epoch,
platform_fee_wallet,
platform_nft_wallet,
platform_scale,
creator_scale,
burn_scale,
fee_rate,
name,
})
}
}