use crate::{
accounts::{BondingCurve, Global},
deserialize_checked, ID,
};
#[allow(clippy::large_enum_variant)]
#[derive(Debug)]
#[cfg_attr(feature = "tracing", derive(strum_macros::Display))]
pub enum PumpProgramState {
BondingCurve(BondingCurve),
Global(Global),
}
impl PumpProgramState {
pub fn try_unpack(data_bytes: &[u8]) -> yellowstone_vixen_core::ParseResult<Self> {
let acc_discriminator: [u8; 8] = data_bytes[0..8].try_into()?;
let acc = match acc_discriminator {
[23, 183, 248, 55, 96, 216, 172, 96] => Ok(PumpProgramState::BondingCurve(
deserialize_checked(data_bytes, &acc_discriminator)?,
)),
[167, 232, 232, 177, 200, 108, 114, 127] => Ok(PumpProgramState::Global(
deserialize_checked(data_bytes, &acc_discriminator)?,
)),
_ => Err(yellowstone_vixen_core::ParseError::from(
"Invalid Account discriminator".to_owned(),
)),
};
#[cfg(feature = "tracing")]
match &acc {
Ok(acc) => {
tracing::info!(
name: "correctly_parsed_account",
name = "account_update",
program = ID.to_string(),
account = acc.to_string()
);
},
Err(e) => {
tracing::info!(
name: "incorrectly_parsed_account",
name = "account_update",
program = ID.to_string(),
account = "error",
discriminator = ?acc_discriminator,
error = ?e
);
},
}
acc
}
}
#[derive(Debug, Copy, Clone)]
pub struct AccountParser;
impl yellowstone_vixen_core::Parser for AccountParser {
type Input = yellowstone_vixen_core::AccountUpdate;
type Output = PumpProgramState;
fn id(&self) -> std::borrow::Cow<'static, str> { "pump::AccountParser".into() }
fn prefilter(&self) -> yellowstone_vixen_core::Prefilter {
yellowstone_vixen_core::Prefilter::builder()
.account_owners([ID])
.build()
.unwrap()
}
async fn parse(
&self,
acct: &yellowstone_vixen_core::AccountUpdate,
) -> yellowstone_vixen_core::ParseResult<Self::Output> {
let inner = acct
.account
.as_ref()
.ok_or(solana_program_error::ProgramError::InvalidArgument)?;
let res = PumpProgramState::try_unpack(&inner.data);
#[cfg(feature = "tracing")]
if let Err(e) = &res {
let acc_discriminator: [u8; 8] = inner.data[0..8].try_into()?;
tracing::info!(
name: "incorrectly_parsed_account",
name = "account_update",
program = ID.to_string(),
account = "deserialization_error",
discriminator = ?acc_discriminator,
error = ?e
);
}
res
}
}
impl yellowstone_vixen_core::ProgramParser for AccountParser {
#[inline]
fn program_id(&self) -> yellowstone_vixen_core::Pubkey { ID.to_bytes().into() }
}
mod proto_parser {
use yellowstone_vixen_core::proto::ParseProto;
use super::{AccountParser, BondingCurve, PumpProgramState};
use crate::{proto_def, proto_helpers::proto_types_parsers::IntoProto};
impl IntoProto<proto_def::BondingCurve> for BondingCurve {
fn into_proto(self) -> proto_def::BondingCurve {
proto_def::BondingCurve {
virtual_token_reserves: self.virtual_token_reserves,
virtual_sol_reserves: self.virtual_sol_reserves,
real_token_reserves: self.real_token_reserves,
real_sol_reserves: self.real_sol_reserves,
token_total_supply: self.token_total_supply,
complete: self.complete,
creator: self.creator.to_string(),
}
}
}
use super::Global;
impl IntoProto<proto_def::Global> for Global {
fn into_proto(self) -> proto_def::Global {
proto_def::Global {
initialized: self.initialized,
authority: self.authority.to_string(),
fee_recipient: self.fee_recipient.to_string(),
initial_virtual_token_reserves: self.initial_virtual_token_reserves,
initial_virtual_sol_reserves: self.initial_virtual_sol_reserves,
initial_real_token_reserves: self.initial_real_token_reserves,
token_total_supply: self.token_total_supply,
fee_basis_points: self.fee_basis_points,
withdraw_authority: self.withdraw_authority.to_string(),
enable_migrate: self.enable_migrate,
pool_migration_fee: self.pool_migration_fee,
creator_fee_basis_points: self.creator_fee_basis_points,
fee_recipients: self
.fee_recipients
.into_iter()
.map(|x| x.to_string())
.collect(),
set_creator_authority: self.set_creator_authority.to_string(),
}
}
}
impl IntoProto<proto_def::ProgramState> for PumpProgramState {
fn into_proto(self) -> proto_def::ProgramState {
let state_oneof = match self {
PumpProgramState::BondingCurve(data) => {
proto_def::program_state::StateOneof::BondingCurve(data.into_proto())
},
PumpProgramState::Global(data) => {
proto_def::program_state::StateOneof::Global(data.into_proto())
},
};
proto_def::ProgramState {
state_oneof: Some(state_oneof),
}
}
}
impl ParseProto for AccountParser {
type Message = proto_def::ProgramState;
fn output_into_message(value: Self::Output) -> Self::Message { value.into_proto() }
}
}