mirror of
https://github.com/0xfnzero/solana-streamer.git
synced 2026-08-14 17:38:05 +00:00
Merge PR #65: refactor streaming core cleanup and dependency simplification
This commit is contained in:
@@ -2,9 +2,9 @@ use borsh::{BorshDeserialize, BorshSerialize};
|
||||
use crossbeam_queue::ArrayQueue;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use solana_sdk::{pubkey::Pubkey, signature::Signature};
|
||||
use std::{borrow::Cow, fmt, str::FromStr, sync::Arc};
|
||||
use std::{borrow::Cow, fmt, sync::Arc};
|
||||
|
||||
use crate::streaming::{common::SimdUtils, event_parser::DexEvent};
|
||||
use crate::streaming::event_parser::DexEvent;
|
||||
|
||||
// Object pool size configuration
|
||||
const EVENT_METADATA_POOL_SIZE: usize = 1000;
|
||||
@@ -165,122 +165,7 @@ pub const BLOCK_EVENT_TYPES: &[EventType] = &[EventType::BlockMeta];
|
||||
|
||||
impl fmt::Display for EventType {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
EventType::PumpSwapBuy => write!(f, "PumpSwapBuy"),
|
||||
EventType::PumpSwapSell => write!(f, "PumpSwapSell"),
|
||||
EventType::PumpSwapCreatePool => write!(f, "PumpSwapCreatePool"),
|
||||
EventType::PumpSwapDeposit => write!(f, "PumpSwapDeposit"),
|
||||
EventType::PumpSwapWithdraw => write!(f, "PumpSwapWithdraw"),
|
||||
EventType::PumpFunCreateToken => write!(f, "PumpFunCreateToken"),
|
||||
EventType::PumpFunCreateV2Token => write!(f, "PumpFunCreateV2Token"),
|
||||
EventType::PumpFunBuy => write!(f, "PumpFunBuy"),
|
||||
EventType::PumpFunSell => write!(f, "PumpFunSell"),
|
||||
EventType::PumpFunMigrate => write!(f, "PumpFunMigrate"),
|
||||
EventType::BonkBuyExactIn => write!(f, "BonkBuyExactIn"),
|
||||
EventType::BonkBuyExactOut => write!(f, "BonkBuyExactOut"),
|
||||
EventType::BonkSellExactIn => write!(f, "BonkSellExactIn"),
|
||||
EventType::BonkSellExactOut => write!(f, "BonkSellExactOut"),
|
||||
EventType::BonkInitialize => write!(f, "BonkInitialize"),
|
||||
EventType::BonkInitializeV2 => write!(f, "BonkInitializeV2"),
|
||||
EventType::BonkInitializeWithToken2022 => write!(f, "BonkInitializeWithToken2022"),
|
||||
EventType::BonkMigrateToAmm => write!(f, "BonkMigrateToAmm"),
|
||||
EventType::BonkMigrateToCpswap => write!(f, "BonkMigrateToCpswap"),
|
||||
EventType::RaydiumCpmmSwapBaseInput => write!(f, "RaydiumCpmmSwapBaseInput"),
|
||||
EventType::RaydiumCpmmSwapBaseOutput => write!(f, "RaydiumCpmmSwapBaseOutput"),
|
||||
EventType::RaydiumCpmmDeposit => write!(f, "RaydiumCpmmDeposit"),
|
||||
EventType::RaydiumCpmmInitialize => write!(f, "RaydiumCpmmInitialize"),
|
||||
EventType::RaydiumCpmmWithdraw => write!(f, "RaydiumCpmmWithdraw"),
|
||||
EventType::RaydiumClmmSwap => write!(f, "RaydiumClmmSwap"),
|
||||
EventType::RaydiumClmmSwapV2 => write!(f, "RaydiumClmmSwapV2"),
|
||||
EventType::RaydiumClmmClosePosition => write!(f, "RaydiumClmmClosePosition"),
|
||||
EventType::RaydiumClmmDecreaseLiquidityV2 => {
|
||||
write!(f, "RaydiumClmmDecreaseLiquidityV2")
|
||||
}
|
||||
EventType::RaydiumClmmCreatePool => write!(f, "RaydiumClmmCreatePool"),
|
||||
EventType::RaydiumClmmIncreaseLiquidityV2 => {
|
||||
write!(f, "RaydiumClmmIncreaseLiquidityV2")
|
||||
}
|
||||
EventType::RaydiumClmmOpenPositionWithToken22Nft => {
|
||||
write!(f, "RaydiumClmmOpenPositionWithToken22Nft")
|
||||
}
|
||||
EventType::RaydiumClmmOpenPositionV2 => write!(f, "RaydiumClmmOpenPositionV2"),
|
||||
EventType::RaydiumAmmV4SwapBaseIn => write!(f, "RaydiumAmmV4SwapBaseIn"),
|
||||
EventType::RaydiumAmmV4SwapBaseOut => write!(f, "RaydiumAmmV4SwapBaseOut"),
|
||||
EventType::RaydiumAmmV4Deposit => write!(f, "RaydiumAmmV4Deposit"),
|
||||
EventType::RaydiumAmmV4Initialize2 => write!(f, "RaydiumAmmV4Initialize2"),
|
||||
EventType::RaydiumAmmV4Withdraw => write!(f, "RaydiumAmmV4Withdraw"),
|
||||
EventType::RaydiumAmmV4WithdrawPnl => write!(f, "RaydiumAmmV4WithdrawPnl"),
|
||||
EventType::MeteoraDammV2Swap => write!(f, "MeteoraDammV2Swap"),
|
||||
EventType::MeteoraDammV2Swap2 => write!(f, "MeteoraDammV2Swap2"),
|
||||
EventType::MeteoraDammV2InitializePool => write!(f, "MeteoraDammV2InitializePool"),
|
||||
EventType::MeteoraDammV2InitializeCustomizablePool => write!(f, "MeteoraDammV2InitializeCustomizablePool"),
|
||||
EventType::MeteoraDammV2InitializePoolWithDynamicConfig => write!(f, "MeteoraDammV2InitializePoolWithDynamicConfig"),
|
||||
EventType::AccountRaydiumAmmV4AmmInfo => write!(f, "AccountRaydiumAmmV4AmmInfo"),
|
||||
EventType::AccountPumpSwapGlobalConfig => write!(f, "AccountPumpSwapGlobalConfig"),
|
||||
EventType::AccountPumpSwapPool => write!(f, "AccountPumpSwapPool"),
|
||||
EventType::AccountBonkPoolState => write!(f, "AccountBonkPoolState"),
|
||||
EventType::AccountBonkGlobalConfig => write!(f, "AccountBonkGlobalConfig"),
|
||||
EventType::AccountBonkPlatformConfig => write!(f, "AccountBonkPlatformConfig"),
|
||||
EventType::AccountBonkVestingRecord => write!(f, "AccountBonkVestingRecord"),
|
||||
EventType::AccountPumpFunBondingCurve => write!(f, "AccountPumpFunBondingCurve"),
|
||||
EventType::AccountPumpFunGlobal => write!(f, "AccountPumpFunGlobal"),
|
||||
EventType::AccountRaydiumClmmAmmConfig => write!(f, "AccountRaydiumClmmAmmConfig"),
|
||||
EventType::AccountRaydiumClmmPoolState => write!(f, "AccountRaydiumClmmPoolState"),
|
||||
EventType::AccountRaydiumClmmTickArrayState => {
|
||||
write!(f, "AccountRaydiumClmmTickArrayState")
|
||||
}
|
||||
EventType::AccountRaydiumCpmmAmmConfig => write!(f, "AccountRaydiumCpmmAmmConfig"),
|
||||
EventType::AccountRaydiumCpmmPoolState => write!(f, "AccountRaydiumCpmmPoolState"),
|
||||
EventType::TokenAccount => write!(f, "TokenAccount"),
|
||||
EventType::NonceAccount => write!(f, "NonceAccount"),
|
||||
EventType::BlockMeta => write!(f, "BlockMeta"),
|
||||
EventType::SetComputeUnitLimit => write!(f, "SetComputeUnitLimit"),
|
||||
EventType::SetComputeUnitPrice => write!(f, "SetComputeUnitPrice"),
|
||||
EventType::Unknown => write!(f, "Unknown"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse result
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ParseResult<T> {
|
||||
pub success: bool,
|
||||
pub data: Option<T>,
|
||||
pub error: Option<String>,
|
||||
}
|
||||
|
||||
impl<T> ParseResult<T> {
|
||||
pub fn success(data: T) -> Self {
|
||||
Self { success: true, data: Some(data), error: None }
|
||||
}
|
||||
|
||||
pub fn failure(error: String) -> Self {
|
||||
Self { success: false, data: None, error: Some(error) }
|
||||
}
|
||||
|
||||
pub fn is_success(&self) -> bool {
|
||||
self.success
|
||||
}
|
||||
|
||||
pub fn is_failure(&self) -> bool {
|
||||
!self.success
|
||||
}
|
||||
}
|
||||
|
||||
/// Protocol information
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct ProtocolInfo {
|
||||
pub name: String,
|
||||
pub program_ids: Vec<Pubkey>,
|
||||
}
|
||||
|
||||
impl ProtocolInfo {
|
||||
pub fn new(name: String, program_ids: Vec<Pubkey>) -> Self {
|
||||
Self { name, program_ids }
|
||||
}
|
||||
|
||||
pub fn supports_program(&self, program_id: &Pubkey) -> bool {
|
||||
self.program_ids.contains(program_id)
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -353,356 +238,240 @@ impl EventMetadata {
|
||||
pub fn set_swap_data(&mut self, swap_data: SwapData) {
|
||||
self.swap_data = Some(swap_data);
|
||||
}
|
||||
|
||||
/// Recycle EventMetadata to object pool
|
||||
pub fn recycle(self) {
|
||||
EVENT_METADATA_POOL.release(self);
|
||||
}
|
||||
}
|
||||
|
||||
static SOL_MINT: std::sync::LazyLock<Pubkey> =
|
||||
std::sync::LazyLock::new(|| Pubkey::from_str("So11111111111111111111111111111111111111111").unwrap());
|
||||
std::sync::LazyLock::new(spl_token::native_mint::id);
|
||||
static SYSTEM_PROGRAMS: std::sync::LazyLock<[Pubkey; 3]> = std::sync::LazyLock::new(|| [
|
||||
Pubkey::from_str("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA").unwrap(),
|
||||
Pubkey::from_str("TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb").unwrap(),
|
||||
Pubkey::from_str("11111111111111111111111111111111").unwrap(),
|
||||
spl_token::id(),
|
||||
spl_token_2022::id(),
|
||||
solana_sdk::pubkey!("11111111111111111111111111111111"),
|
||||
]);
|
||||
|
||||
/// Parse token transfer data from next instructions
|
||||
/// Trait abstracting over different inner-instruction types for swap data extraction
|
||||
pub trait InnerInstructionLike {
|
||||
fn program_id_index(&self) -> usize;
|
||||
fn accounts(&self) -> &[u8];
|
||||
fn data(&self) -> &[u8];
|
||||
}
|
||||
|
||||
/// Adapter for standard Solana compiled instructions
|
||||
impl InnerInstructionLike for solana_sdk::message::compiled_instruction::CompiledInstruction {
|
||||
fn program_id_index(&self) -> usize {
|
||||
self.program_id_index as usize
|
||||
}
|
||||
fn accounts(&self) -> &[u8] {
|
||||
&self.accounts
|
||||
}
|
||||
fn data(&self) -> &[u8] {
|
||||
&self.data
|
||||
}
|
||||
}
|
||||
|
||||
/// Adapter for gRPC inner instructions (yellowstone)
|
||||
impl InnerInstructionLike for yellowstone_grpc_proto::prelude::InnerInstruction {
|
||||
fn program_id_index(&self) -> usize {
|
||||
self.program_id_index as usize
|
||||
}
|
||||
fn accounts(&self) -> &[u8] {
|
||||
&self.accounts
|
||||
}
|
||||
fn data(&self) -> &[u8] {
|
||||
&self.data
|
||||
}
|
||||
}
|
||||
|
||||
/// Extract event context (mint/token account/vault info) from a DexEvent
|
||||
fn extract_swap_context(event: &DexEvent) -> (
|
||||
SwapData,
|
||||
Option<Pubkey>, Option<Pubkey>,
|
||||
Option<Pubkey>, Option<Pubkey>,
|
||||
Option<Pubkey>, Option<Pubkey>,
|
||||
) {
|
||||
let mut swap_data = SwapData::default();
|
||||
let mut from_mint: Option<Pubkey> = None;
|
||||
let mut to_mint: Option<Pubkey> = None;
|
||||
let mut user_from_token: Option<Pubkey> = None;
|
||||
let mut user_to_token: Option<Pubkey> = None;
|
||||
let mut from_vault: Option<Pubkey> = None;
|
||||
let mut to_vault: Option<Pubkey> = None;
|
||||
|
||||
match event {
|
||||
DexEvent::BonkTradeEvent(e) => {
|
||||
from_mint = Some(e.base_token_mint);
|
||||
to_mint = Some(e.quote_token_mint);
|
||||
user_from_token = Some(e.user_base_token);
|
||||
user_to_token = Some(e.user_quote_token);
|
||||
from_vault = Some(e.base_vault);
|
||||
to_vault = Some(e.quote_vault);
|
||||
}
|
||||
DexEvent::PumpFunTradeEvent(e) => {
|
||||
swap_data.from_mint = if e.is_buy { *SOL_MINT } else { e.mint };
|
||||
swap_data.to_mint = if e.is_buy { e.mint } else { *SOL_MINT };
|
||||
}
|
||||
DexEvent::PumpSwapBuyEvent(e) => {
|
||||
swap_data.from_mint = e.quote_mint;
|
||||
swap_data.to_mint = e.base_mint;
|
||||
}
|
||||
DexEvent::PumpSwapSellEvent(e) => {
|
||||
swap_data.from_mint = e.base_mint;
|
||||
swap_data.to_mint = e.quote_mint;
|
||||
}
|
||||
DexEvent::RaydiumCpmmSwapEvent(e) => {
|
||||
from_mint = Some(e.input_token_mint);
|
||||
to_mint = Some(e.output_token_mint);
|
||||
user_from_token = Some(e.input_token_account);
|
||||
user_to_token = Some(e.output_token_account);
|
||||
from_vault = Some(e.input_vault);
|
||||
to_vault = Some(e.output_vault);
|
||||
}
|
||||
DexEvent::RaydiumClmmSwapEvent(e) => {
|
||||
swap_data.description =
|
||||
Some("Unable to get from_mint and to_mint from RaydiumClmmSwapEvent".into());
|
||||
user_from_token = Some(e.input_token_account);
|
||||
user_to_token = Some(e.output_token_account);
|
||||
from_vault = Some(e.input_vault);
|
||||
to_vault = Some(e.output_vault);
|
||||
}
|
||||
DexEvent::RaydiumClmmSwapV2Event(e) => {
|
||||
from_mint = Some(e.input_vault_mint);
|
||||
to_mint = Some(e.output_vault_mint);
|
||||
user_from_token = Some(e.input_token_account);
|
||||
user_to_token = Some(e.output_token_account);
|
||||
from_vault = Some(e.input_vault);
|
||||
to_vault = Some(e.output_vault);
|
||||
}
|
||||
DexEvent::RaydiumAmmV4SwapEvent(e) => {
|
||||
swap_data.description =
|
||||
Some("Unable to get from_mint and to_mint from RaydiumAmmV4SwapEvent".into());
|
||||
user_from_token = Some(e.user_source_token_account);
|
||||
user_to_token = Some(e.user_destination_token_account);
|
||||
from_vault = Some(e.pool_pc_token_account);
|
||||
to_vault = Some(e.pool_coin_token_account);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
(swap_data, from_mint, to_mint, user_from_token, user_to_token, from_vault, to_vault)
|
||||
}
|
||||
|
||||
/// Generic swap data extraction that works with any instruction type implementing InnerInstructionLike
|
||||
fn extract_swap_data_from_instructions<I: InnerInstructionLike>(
|
||||
event: &DexEvent,
|
||||
instructions: impl Iterator<Item = I>,
|
||||
current_index: i8,
|
||||
accounts: &[Pubkey],
|
||||
) -> Option<SwapData> {
|
||||
let (mut swap_data, fm, tm, uft, utt, fv, tv) = extract_swap_context(event);
|
||||
|
||||
let user_to_token = utt.unwrap_or_default();
|
||||
let user_from_token = uft.unwrap_or_default();
|
||||
let to_vault = tv.unwrap_or_default();
|
||||
let from_vault = fv.unwrap_or_default();
|
||||
let to_mint = tm.unwrap_or_default();
|
||||
let from_mint = fm.unwrap_or_default();
|
||||
|
||||
for instruction in instructions.skip((current_index + 1) as usize) {
|
||||
let program_id = accounts[instruction.program_id_index()];
|
||||
if !SYSTEM_PROGRAMS.contains(&program_id) {
|
||||
break;
|
||||
}
|
||||
let data = instruction.data();
|
||||
let accs = instruction.accounts();
|
||||
|
||||
if data.len() < 8 {
|
||||
continue;
|
||||
}
|
||||
|
||||
let get_pubkey = |i: usize| accounts[accs[i] as usize];
|
||||
let (source, destination, amount) = match data[0] {
|
||||
12 if accs.len() >= 4 => {
|
||||
let amt = u64::from_le_bytes(data[1..9].try_into().unwrap());
|
||||
(get_pubkey(0), get_pubkey(2), amt)
|
||||
}
|
||||
3 if accs.len() >= 3 => {
|
||||
let amt = u64::from_le_bytes(data[1..9].try_into().unwrap());
|
||||
(get_pubkey(0), get_pubkey(1), amt)
|
||||
}
|
||||
2 if accs.len() >= 2 => {
|
||||
let amt = u64::from_le_bytes(data[4..12].try_into().unwrap());
|
||||
(get_pubkey(0), get_pubkey(1), amt)
|
||||
}
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
match (source, destination) {
|
||||
(s, d) if s == user_to_token && d == to_vault => {
|
||||
swap_data.from_mint = to_mint;
|
||||
swap_data.from_amount = amount;
|
||||
}
|
||||
(s, d) if s == from_vault && d == user_from_token => {
|
||||
swap_data.to_mint = from_mint;
|
||||
swap_data.to_amount = amount;
|
||||
}
|
||||
(s, d) if s == user_from_token && d == from_vault => {
|
||||
swap_data.from_mint = from_mint;
|
||||
swap_data.from_amount = amount;
|
||||
}
|
||||
(s, d) if s == to_vault && d == user_to_token => {
|
||||
swap_data.to_mint = to_mint;
|
||||
swap_data.to_amount = amount;
|
||||
}
|
||||
(s, d) if s == user_from_token && d == to_vault => {
|
||||
swap_data.from_mint = from_mint;
|
||||
swap_data.from_amount = amount;
|
||||
}
|
||||
(s, d) if s == from_vault && d == user_to_token => {
|
||||
swap_data.to_mint = to_mint;
|
||||
swap_data.to_amount = amount;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
if swap_data.from_mint != Pubkey::default() && swap_data.to_mint != Pubkey::default() {
|
||||
break;
|
||||
}
|
||||
if swap_data.from_amount != 0 && swap_data.to_amount != 0 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if swap_data.from_mint != Pubkey::default()
|
||||
|| swap_data.to_mint != Pubkey::default()
|
||||
|| swap_data.from_amount != 0
|
||||
|| swap_data.to_amount != 0
|
||||
{
|
||||
Some(swap_data)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse token transfer data from standard Solana inner instructions
|
||||
pub fn parse_swap_data_from_next_instructions(
|
||||
event: &DexEvent,
|
||||
inner_instruction: &solana_transaction_status::InnerInstructions,
|
||||
current_index: i8,
|
||||
accounts: &[Pubkey],
|
||||
) -> Option<SwapData> {
|
||||
let mut swap_data = SwapData {
|
||||
from_mint: Pubkey::default(),
|
||||
to_mint: Pubkey::default(),
|
||||
from_amount: 0,
|
||||
to_amount: 0,
|
||||
description: None,
|
||||
};
|
||||
|
||||
// 先根据 event 取出关键信息
|
||||
// let mut user: Option<Pubkey> = None;
|
||||
let mut from_mint: Option<Pubkey> = None;
|
||||
let mut to_mint: Option<Pubkey> = None;
|
||||
let mut user_from_token: Option<Pubkey> = None;
|
||||
let mut user_to_token: Option<Pubkey> = None;
|
||||
let mut from_vault: Option<Pubkey> = None;
|
||||
let mut to_vault: Option<Pubkey> = None;
|
||||
|
||||
match event {
|
||||
DexEvent::BonkTradeEvent(e) => {
|
||||
// user = Some(e.payer);
|
||||
from_mint = Some(e.base_token_mint);
|
||||
to_mint = Some(e.quote_token_mint);
|
||||
user_from_token = Some(e.user_base_token);
|
||||
user_to_token = Some(e.user_quote_token);
|
||||
from_vault = Some(e.base_vault);
|
||||
to_vault = Some(e.quote_vault);
|
||||
}
|
||||
DexEvent::PumpFunTradeEvent(e) => {
|
||||
swap_data.from_mint = if e.is_buy { *SOL_MINT } else { e.mint };
|
||||
swap_data.to_mint = if e.is_buy { e.mint } else { *SOL_MINT };
|
||||
}
|
||||
DexEvent::PumpSwapBuyEvent(e) => {
|
||||
swap_data.from_mint = e.quote_mint;
|
||||
swap_data.to_mint = e.base_mint;
|
||||
}
|
||||
DexEvent::PumpSwapSellEvent(e) => {
|
||||
swap_data.from_mint = e.base_mint;
|
||||
swap_data.to_mint = e.quote_mint;
|
||||
}
|
||||
DexEvent::RaydiumCpmmSwapEvent(e) => {
|
||||
// user = Some(e.payer);
|
||||
from_mint = Some(e.input_token_mint);
|
||||
to_mint = Some(e.output_token_mint);
|
||||
user_from_token = Some(e.input_token_account);
|
||||
user_to_token = Some(e.output_token_account);
|
||||
from_vault = Some(e.input_vault);
|
||||
to_vault = Some(e.output_vault);
|
||||
}
|
||||
DexEvent::RaydiumClmmSwapEvent(e) => {
|
||||
// user = Some(e.payer);
|
||||
swap_data.description =
|
||||
Some("Unable to get from_mint and to_mint from RaydiumClmmSwapEvent".into());
|
||||
user_from_token = Some(e.input_token_account);
|
||||
user_to_token = Some(e.output_token_account);
|
||||
from_vault = Some(e.input_vault);
|
||||
to_vault = Some(e.output_vault);
|
||||
}
|
||||
DexEvent::RaydiumClmmSwapV2Event(e) => {
|
||||
// user = Some(e.payer);
|
||||
from_mint = Some(e.input_vault_mint);
|
||||
to_mint = Some(e.output_vault_mint);
|
||||
user_from_token = Some(e.input_token_account);
|
||||
user_to_token = Some(e.output_token_account);
|
||||
from_vault = Some(e.input_vault);
|
||||
to_vault = Some(e.output_vault);
|
||||
}
|
||||
DexEvent::RaydiumAmmV4SwapEvent(e) => {
|
||||
// user = Some(e.user_source_owner);
|
||||
swap_data.description =
|
||||
Some("Unable to get from_mint and to_mint from RaydiumAmmV4SwapEvent".into());
|
||||
user_from_token = Some(e.user_source_token_account);
|
||||
user_to_token = Some(e.user_destination_token_account);
|
||||
from_vault = Some(e.pool_pc_token_account);
|
||||
to_vault = Some(e.pool_coin_token_account);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let user_to_token = user_to_token.unwrap_or_default();
|
||||
let user_from_token = user_from_token.unwrap_or_default();
|
||||
let to_vault = to_vault.unwrap_or_default();
|
||||
let from_vault = from_vault.unwrap_or_default();
|
||||
let to_mint = to_mint.unwrap_or_default();
|
||||
let from_mint = from_mint.unwrap_or_default();
|
||||
|
||||
// 单次循环完成提取和判断
|
||||
for instruction in inner_instruction.instructions.iter().skip((current_index + 1) as usize) {
|
||||
let compiled = &instruction.instruction;
|
||||
let program_id = accounts[compiled.program_id_index as usize];
|
||||
if !SYSTEM_PROGRAMS.contains(&program_id) {
|
||||
break;
|
||||
}
|
||||
let data = &compiled.data;
|
||||
|
||||
// 使用 SIMD 验证数据格式
|
||||
if !SimdUtils::validate_data_format(data, 8) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let get_pubkey = |i: usize| accounts[compiled.accounts[i] as usize];
|
||||
let (source, destination, amount) = match data[0] {
|
||||
12 if compiled.accounts.len() >= 4 => {
|
||||
let amt = u64::from_le_bytes(data[1..9].try_into().unwrap());
|
||||
(get_pubkey(0), get_pubkey(2), amt)
|
||||
}
|
||||
3 if compiled.accounts.len() >= 3 => {
|
||||
let amt = u64::from_le_bytes(data[1..9].try_into().unwrap());
|
||||
(get_pubkey(0), get_pubkey(1), amt)
|
||||
}
|
||||
2 if compiled.accounts.len() >= 2 => {
|
||||
let amt = u64::from_le_bytes(data[4..12].try_into().unwrap());
|
||||
(get_pubkey(0), get_pubkey(1), amt)
|
||||
}
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
match (source, destination) {
|
||||
(s, d) if s == user_to_token && d == to_vault => {
|
||||
swap_data.from_mint = to_mint;
|
||||
swap_data.from_amount = amount;
|
||||
}
|
||||
(s, d) if s == from_vault && d == user_from_token => {
|
||||
swap_data.to_mint = from_mint;
|
||||
swap_data.to_amount = amount;
|
||||
}
|
||||
(s, d) if s == user_from_token && d == from_vault => {
|
||||
swap_data.from_mint = from_mint;
|
||||
swap_data.from_amount = amount;
|
||||
}
|
||||
(s, d) if s == to_vault && d == user_to_token => {
|
||||
swap_data.to_mint = to_mint;
|
||||
swap_data.to_amount = amount;
|
||||
}
|
||||
(s, d) if s == user_from_token && d == to_vault => {
|
||||
swap_data.from_mint = from_mint;
|
||||
swap_data.from_amount = amount;
|
||||
}
|
||||
(s, d) if s == from_vault && d == user_to_token => {
|
||||
swap_data.to_mint = to_mint;
|
||||
swap_data.to_amount = amount;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
if swap_data.from_mint != Pubkey::default() && swap_data.to_mint != Pubkey::default() {
|
||||
break;
|
||||
}
|
||||
if swap_data.from_amount != 0 && swap_data.to_amount != 0 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if swap_data.from_mint != Pubkey::default()
|
||||
|| swap_data.to_mint != Pubkey::default()
|
||||
|| swap_data.from_amount != 0
|
||||
|| swap_data.to_amount != 0
|
||||
{
|
||||
Some(swap_data)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
extract_swap_data_from_instructions(
|
||||
event,
|
||||
inner_instruction.instructions.iter().map(|ix| ix.instruction.clone()),
|
||||
current_index,
|
||||
accounts,
|
||||
)
|
||||
}
|
||||
|
||||
/// Parse token transfer data from next instructions
|
||||
/// TODO: - wait refactor
|
||||
/// Parse token transfer data from gRPC inner instructions
|
||||
pub fn parse_swap_data_from_next_grpc_instructions(
|
||||
event: &DexEvent,
|
||||
inner_instruction: &yellowstone_grpc_proto::prelude::InnerInstructions,
|
||||
current_index: i8,
|
||||
accounts: &[Pubkey],
|
||||
) -> Option<SwapData> {
|
||||
let mut swap_data = SwapData {
|
||||
from_mint: Pubkey::default(),
|
||||
to_mint: Pubkey::default(),
|
||||
from_amount: 0,
|
||||
to_amount: 0,
|
||||
description: None,
|
||||
};
|
||||
|
||||
// 先根据 event 取出关键信息
|
||||
// let mut user: Option<Pubkey> = None;
|
||||
let mut from_mint: Option<Pubkey> = None;
|
||||
let mut to_mint: Option<Pubkey> = None;
|
||||
let mut user_from_token: Option<Pubkey> = None;
|
||||
let mut user_to_token: Option<Pubkey> = None;
|
||||
let mut from_vault: Option<Pubkey> = None;
|
||||
let mut to_vault: Option<Pubkey> = None;
|
||||
|
||||
match event {
|
||||
DexEvent::BonkTradeEvent(e) => {
|
||||
// user = Some(e.payer);
|
||||
from_mint = Some(e.base_token_mint);
|
||||
to_mint = Some(e.quote_token_mint);
|
||||
user_from_token = Some(e.user_base_token);
|
||||
user_to_token = Some(e.user_quote_token);
|
||||
from_vault = Some(e.base_vault);
|
||||
to_vault = Some(e.quote_vault);
|
||||
}
|
||||
DexEvent::PumpFunTradeEvent(e) => {
|
||||
swap_data.from_mint = if e.is_buy { *SOL_MINT } else { e.mint };
|
||||
swap_data.to_mint = if e.is_buy { e.mint } else { *SOL_MINT };
|
||||
}
|
||||
DexEvent::PumpSwapBuyEvent(e) => {
|
||||
swap_data.from_mint = e.quote_mint;
|
||||
swap_data.to_mint = e.base_mint;
|
||||
}
|
||||
DexEvent::PumpSwapSellEvent(e) => {
|
||||
swap_data.from_mint = e.base_mint;
|
||||
swap_data.to_mint = e.quote_mint;
|
||||
}
|
||||
DexEvent::RaydiumCpmmSwapEvent(e) => {
|
||||
// user = Some(e.payer);
|
||||
from_mint = Some(e.input_token_mint);
|
||||
to_mint = Some(e.output_token_mint);
|
||||
user_from_token = Some(e.input_token_account);
|
||||
user_to_token = Some(e.output_token_account);
|
||||
from_vault = Some(e.input_vault);
|
||||
to_vault = Some(e.output_vault);
|
||||
}
|
||||
DexEvent::RaydiumClmmSwapEvent(e) => {
|
||||
// user = Some(e.payer);
|
||||
swap_data.description =
|
||||
Some("Unable to get from_mint and to_mint from RaydiumClmmSwapEvent".into());
|
||||
user_from_token = Some(e.input_token_account);
|
||||
user_to_token = Some(e.output_token_account);
|
||||
from_vault = Some(e.input_vault);
|
||||
to_vault = Some(e.output_vault);
|
||||
}
|
||||
DexEvent::RaydiumClmmSwapV2Event(e) => {
|
||||
// user = Some(e.payer);
|
||||
from_mint = Some(e.input_vault_mint);
|
||||
to_mint = Some(e.output_vault_mint);
|
||||
user_from_token = Some(e.input_token_account);
|
||||
user_to_token = Some(e.output_token_account);
|
||||
from_vault = Some(e.input_vault);
|
||||
to_vault = Some(e.output_vault);
|
||||
}
|
||||
DexEvent::RaydiumAmmV4SwapEvent(e) => {
|
||||
// user = Some(e.user_source_owner);
|
||||
swap_data.description =
|
||||
Some("Unable to get from_mint and to_mint from RaydiumAmmV4SwapEvent".into());
|
||||
user_from_token = Some(e.user_source_token_account);
|
||||
user_to_token = Some(e.user_destination_token_account);
|
||||
from_vault = Some(e.pool_pc_token_account);
|
||||
to_vault = Some(e.pool_coin_token_account);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let user_to_token = user_to_token.unwrap_or_default();
|
||||
let user_from_token = user_from_token.unwrap_or_default();
|
||||
let to_vault = to_vault.unwrap_or_default();
|
||||
let from_vault = from_vault.unwrap_or_default();
|
||||
let to_mint = to_mint.unwrap_or_default();
|
||||
let from_mint = from_mint.unwrap_or_default();
|
||||
|
||||
// 单次循环完成提取和判断
|
||||
for instruction in inner_instruction.instructions.iter().skip((current_index + 1) as usize) {
|
||||
let compiled = &instruction;
|
||||
let program_id = accounts[compiled.program_id_index as usize];
|
||||
if !SYSTEM_PROGRAMS.contains(&program_id) {
|
||||
break;
|
||||
}
|
||||
let data = &compiled.data;
|
||||
|
||||
// 使用 SIMD 验证数据格式
|
||||
if !SimdUtils::validate_data_format(data, 8) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let get_pubkey = |i: usize| accounts[compiled.accounts[i] as usize];
|
||||
let (source, destination, amount) = match data[0] {
|
||||
12 if compiled.accounts.len() >= 4 => {
|
||||
let amt = u64::from_le_bytes(data[1..9].try_into().unwrap());
|
||||
(get_pubkey(0), get_pubkey(2), amt)
|
||||
}
|
||||
3 if compiled.accounts.len() >= 3 => {
|
||||
let amt = u64::from_le_bytes(data[1..9].try_into().unwrap());
|
||||
(get_pubkey(0), get_pubkey(1), amt)
|
||||
}
|
||||
2 if compiled.accounts.len() >= 2 => {
|
||||
let amt = u64::from_le_bytes(data[4..12].try_into().unwrap());
|
||||
(get_pubkey(0), get_pubkey(1), amt)
|
||||
}
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
match (source, destination) {
|
||||
(s, d) if s == user_to_token && d == to_vault => {
|
||||
swap_data.from_mint = to_mint;
|
||||
swap_data.from_amount = amount;
|
||||
}
|
||||
(s, d) if s == from_vault && d == user_from_token => {
|
||||
swap_data.to_mint = from_mint;
|
||||
swap_data.to_amount = amount;
|
||||
}
|
||||
(s, d) if s == user_from_token && d == from_vault => {
|
||||
swap_data.from_mint = from_mint;
|
||||
swap_data.from_amount = amount;
|
||||
}
|
||||
(s, d) if s == to_vault && d == user_to_token => {
|
||||
swap_data.to_mint = to_mint;
|
||||
swap_data.to_amount = amount;
|
||||
}
|
||||
(s, d) if s == user_from_token && d == to_vault => {
|
||||
swap_data.from_mint = from_mint;
|
||||
swap_data.from_amount = amount;
|
||||
}
|
||||
(s, d) if s == from_vault && d == user_to_token => {
|
||||
swap_data.to_mint = to_mint;
|
||||
swap_data.to_amount = amount;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
if swap_data.from_mint != Pubkey::default() && swap_data.to_mint != Pubkey::default() {
|
||||
break;
|
||||
}
|
||||
if swap_data.from_amount != 0 && swap_data.to_amount != 0 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if swap_data.from_mint != Pubkey::default()
|
||||
|| swap_data.to_mint != Pubkey::default()
|
||||
|| swap_data.from_amount != 0
|
||||
|| swap_data.to_amount != 0
|
||||
{
|
||||
Some(swap_data)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
extract_swap_data_from_instructions(
|
||||
event,
|
||||
inner_instruction.instructions.iter().cloned(),
|
||||
current_index,
|
||||
accounts,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -58,14 +58,14 @@ pub fn read_u8_le(data: &[u8], offset: usize) -> Option<u8> {
|
||||
}
|
||||
|
||||
pub fn read_option_bool(data: &[u8], offset: &mut usize) -> Option<Option<bool>> {
|
||||
let has_value = data.get(*offset)?.clone();
|
||||
let has_value = data.get(*offset).copied()?;
|
||||
*offset += 1;
|
||||
|
||||
if has_value == 0 {
|
||||
return Some(None);
|
||||
}
|
||||
|
||||
let value = data.get(*offset)?.clone();
|
||||
let value = data.get(*offset).copied()?;
|
||||
*offset += 1;
|
||||
|
||||
Some(Some(value != 0))
|
||||
|
||||
@@ -85,7 +85,7 @@ impl EventParser {
|
||||
let recent_blockhash = if message.recent_blockhash.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(bs58::encode(&message.recent_blockhash).into_string())
|
||||
Some(solana_sdk::bs58::encode(&message.recent_blockhash).into_string())
|
||||
};
|
||||
Self::parse_instruction_events_from_grpc_transaction(
|
||||
protocols,
|
||||
|
||||
@@ -49,16 +49,11 @@ impl GlobalState {
|
||||
return; // Another thread is cleaning up
|
||||
}
|
||||
|
||||
// Collect signatures to remove (random selection for simplicity)
|
||||
let mut signatures_to_remove: Vec<Signature> = self.signature_data.iter()
|
||||
// Collect only the batch we need to remove (avoid allocating full list)
|
||||
let signatures_to_remove: Vec<Signature> = self.signature_data.iter()
|
||||
.take(CLEANUP_BATCH_SIZE)
|
||||
.map(|entry| *entry.key())
|
||||
.collect();
|
||||
|
||||
if signatures_to_remove.len() <= MAX_SIGNATURES {
|
||||
return; // Race condition, already cleaned up
|
||||
}
|
||||
|
||||
signatures_to_remove.truncate(CLEANUP_BATCH_SIZE);
|
||||
|
||||
// Remove old signatures atomically
|
||||
for signature in signatures_to_remove {
|
||||
|
||||
@@ -90,122 +90,86 @@ pub enum DexEvent {
|
||||
SetComputeUnitPriceEvent(SetComputeUnitPriceEvent),
|
||||
}
|
||||
|
||||
impl DexEvent {
|
||||
pub fn metadata(&self) -> &EventMetadata {
|
||||
match self {
|
||||
DexEvent::BonkTradeEvent(e) => &e.metadata,
|
||||
DexEvent::BonkPoolCreateEvent(e) => &e.metadata,
|
||||
DexEvent::BonkMigrateToAmmEvent(e) => &e.metadata,
|
||||
DexEvent::BonkMigrateToCpswapEvent(e) => &e.metadata,
|
||||
DexEvent::BonkPoolStateAccountEvent(e) => &e.metadata,
|
||||
DexEvent::BonkGlobalConfigAccountEvent(e) => &e.metadata,
|
||||
DexEvent::BonkPlatformConfigAccountEvent(e) => &e.metadata,
|
||||
DexEvent::PumpFunCreateTokenEvent(e) => &e.metadata,
|
||||
DexEvent::PumpFunCreateV2TokenEvent(e) => &e.metadata,
|
||||
DexEvent::PumpFunTradeEvent(e) => &e.metadata,
|
||||
DexEvent::PumpFunMigrateEvent(e) => &e.metadata,
|
||||
DexEvent::PumpFunBondingCurveAccountEvent(e) => &e.metadata,
|
||||
DexEvent::PumpFunGlobalAccountEvent(e) => &e.metadata,
|
||||
DexEvent::PumpSwapBuyEvent(e) => &e.metadata,
|
||||
DexEvent::PumpSwapSellEvent(e) => &e.metadata,
|
||||
DexEvent::PumpSwapCreatePoolEvent(e) => &e.metadata,
|
||||
DexEvent::PumpSwapDepositEvent(e) => &e.metadata,
|
||||
DexEvent::PumpSwapWithdrawEvent(e) => &e.metadata,
|
||||
DexEvent::PumpSwapGlobalConfigAccountEvent(e) => &e.metadata,
|
||||
DexEvent::PumpSwapPoolAccountEvent(e) => &e.metadata,
|
||||
DexEvent::RaydiumAmmV4SwapEvent(e) => &e.metadata,
|
||||
DexEvent::RaydiumAmmV4DepositEvent(e) => &e.metadata,
|
||||
DexEvent::RaydiumAmmV4WithdrawEvent(e) => &e.metadata,
|
||||
DexEvent::RaydiumAmmV4WithdrawPnlEvent(e) => &e.metadata,
|
||||
DexEvent::RaydiumAmmV4Initialize2Event(e) => &e.metadata,
|
||||
DexEvent::RaydiumAmmV4AmmInfoAccountEvent(e) => &e.metadata,
|
||||
DexEvent::RaydiumClmmSwapEvent(e) => &e.metadata,
|
||||
DexEvent::RaydiumClmmSwapV2Event(e) => &e.metadata,
|
||||
DexEvent::RaydiumClmmClosePositionEvent(e) => &e.metadata,
|
||||
DexEvent::RaydiumClmmIncreaseLiquidityV2Event(e) => &e.metadata,
|
||||
DexEvent::RaydiumClmmDecreaseLiquidityV2Event(e) => &e.metadata,
|
||||
DexEvent::RaydiumClmmCreatePoolEvent(e) => &e.metadata,
|
||||
DexEvent::RaydiumClmmOpenPositionWithToken22NftEvent(e) => &e.metadata,
|
||||
DexEvent::RaydiumClmmOpenPositionV2Event(e) => &e.metadata,
|
||||
DexEvent::RaydiumClmmAmmConfigAccountEvent(e) => &e.metadata,
|
||||
DexEvent::RaydiumClmmPoolStateAccountEvent(e) => &e.metadata,
|
||||
DexEvent::RaydiumClmmTickArrayStateAccountEvent(e) => &e.metadata,
|
||||
DexEvent::RaydiumCpmmSwapEvent(e) => &e.metadata,
|
||||
DexEvent::RaydiumCpmmDepositEvent(e) => &e.metadata,
|
||||
DexEvent::RaydiumCpmmWithdrawEvent(e) => &e.metadata,
|
||||
DexEvent::RaydiumCpmmInitializeEvent(e) => &e.metadata,
|
||||
DexEvent::RaydiumCpmmAmmConfigAccountEvent(e) => &e.metadata,
|
||||
DexEvent::RaydiumCpmmPoolStateAccountEvent(e) => &e.metadata,
|
||||
DexEvent::MeteoraDammV2SwapEvent(e) => &e.metadata,
|
||||
DexEvent::MeteoraDammV2Swap2Event(e) => &e.metadata,
|
||||
DexEvent::MeteoraDammV2InitializePoolEvent(e) => &e.metadata,
|
||||
DexEvent::MeteoraDammV2InitializeCustomizablePoolEvent(e) => &e.metadata,
|
||||
DexEvent::MeteoraDammV2InitializePoolWithDynamicConfigEvent(e) => &e.metadata,
|
||||
DexEvent::TokenAccountEvent(e) => &e.metadata,
|
||||
DexEvent::NonceAccountEvent(e) => &e.metadata,
|
||||
DexEvent::TokenInfoEvent(e) => &e.metadata,
|
||||
DexEvent::BlockMetaEvent(e) => &e.metadata,
|
||||
DexEvent::SetComputeUnitLimitEvent(e) => &e.metadata,
|
||||
DexEvent::SetComputeUnitPriceEvent(e) => &e.metadata,
|
||||
}
|
||||
}
|
||||
/// Macro to generate metadata accessors for all DexEvent variants
|
||||
macro_rules! impl_dex_event_metadata {
|
||||
($($variant:ident),* $(,)?) => {
|
||||
impl DexEvent {
|
||||
pub fn metadata(&self) -> &EventMetadata {
|
||||
match self {
|
||||
$(DexEvent::$variant(e) => &e.metadata,)*
|
||||
}
|
||||
}
|
||||
|
||||
pub fn metadata_mut(&mut self) -> &mut EventMetadata {
|
||||
match self {
|
||||
DexEvent::BonkTradeEvent(e) => &mut e.metadata,
|
||||
DexEvent::BonkPoolCreateEvent(e) => &mut e.metadata,
|
||||
DexEvent::BonkMigrateToAmmEvent(e) => &mut e.metadata,
|
||||
DexEvent::BonkMigrateToCpswapEvent(e) => &mut e.metadata,
|
||||
DexEvent::BonkPoolStateAccountEvent(e) => &mut e.metadata,
|
||||
DexEvent::BonkGlobalConfigAccountEvent(e) => &mut e.metadata,
|
||||
DexEvent::BonkPlatformConfigAccountEvent(e) => &mut e.metadata,
|
||||
DexEvent::PumpFunCreateTokenEvent(e) => &mut e.metadata,
|
||||
DexEvent::PumpFunCreateV2TokenEvent(e) => &mut e.metadata,
|
||||
DexEvent::PumpFunTradeEvent(e) => &mut e.metadata,
|
||||
DexEvent::PumpFunMigrateEvent(e) => &mut e.metadata,
|
||||
DexEvent::PumpFunBondingCurveAccountEvent(e) => &mut e.metadata,
|
||||
DexEvent::PumpFunGlobalAccountEvent(e) => &mut e.metadata,
|
||||
DexEvent::PumpSwapBuyEvent(e) => &mut e.metadata,
|
||||
DexEvent::PumpSwapSellEvent(e) => &mut e.metadata,
|
||||
DexEvent::PumpSwapCreatePoolEvent(e) => &mut e.metadata,
|
||||
DexEvent::PumpSwapDepositEvent(e) => &mut e.metadata,
|
||||
DexEvent::PumpSwapWithdrawEvent(e) => &mut e.metadata,
|
||||
DexEvent::PumpSwapGlobalConfigAccountEvent(e) => &mut e.metadata,
|
||||
DexEvent::PumpSwapPoolAccountEvent(e) => &mut e.metadata,
|
||||
DexEvent::RaydiumAmmV4SwapEvent(e) => &mut e.metadata,
|
||||
DexEvent::RaydiumAmmV4DepositEvent(e) => &mut e.metadata,
|
||||
DexEvent::RaydiumAmmV4WithdrawEvent(e) => &mut e.metadata,
|
||||
DexEvent::RaydiumAmmV4WithdrawPnlEvent(e) => &mut e.metadata,
|
||||
DexEvent::RaydiumAmmV4Initialize2Event(e) => &mut e.metadata,
|
||||
DexEvent::RaydiumAmmV4AmmInfoAccountEvent(e) => &mut e.metadata,
|
||||
DexEvent::RaydiumClmmSwapEvent(e) => &mut e.metadata,
|
||||
DexEvent::RaydiumClmmSwapV2Event(e) => &mut e.metadata,
|
||||
DexEvent::RaydiumClmmClosePositionEvent(e) => &mut e.metadata,
|
||||
DexEvent::RaydiumClmmIncreaseLiquidityV2Event(e) => &mut e.metadata,
|
||||
DexEvent::RaydiumClmmDecreaseLiquidityV2Event(e) => &mut e.metadata,
|
||||
DexEvent::RaydiumClmmCreatePoolEvent(e) => &mut e.metadata,
|
||||
DexEvent::RaydiumClmmOpenPositionWithToken22NftEvent(e) => &mut e.metadata,
|
||||
DexEvent::RaydiumClmmOpenPositionV2Event(e) => &mut e.metadata,
|
||||
DexEvent::RaydiumClmmAmmConfigAccountEvent(e) => &mut e.metadata,
|
||||
DexEvent::RaydiumClmmPoolStateAccountEvent(e) => &mut e.metadata,
|
||||
DexEvent::RaydiumClmmTickArrayStateAccountEvent(e) => &mut e.metadata,
|
||||
DexEvent::RaydiumCpmmSwapEvent(e) => &mut e.metadata,
|
||||
DexEvent::RaydiumCpmmDepositEvent(e) => &mut e.metadata,
|
||||
DexEvent::RaydiumCpmmWithdrawEvent(e) => &mut e.metadata,
|
||||
DexEvent::RaydiumCpmmInitializeEvent(e) => &mut e.metadata,
|
||||
DexEvent::RaydiumCpmmAmmConfigAccountEvent(e) => &mut e.metadata,
|
||||
DexEvent::RaydiumCpmmPoolStateAccountEvent(e) => &mut e.metadata,
|
||||
DexEvent::MeteoraDammV2SwapEvent(e) => &mut e.metadata,
|
||||
DexEvent::MeteoraDammV2Swap2Event(e) => &mut e.metadata,
|
||||
DexEvent::MeteoraDammV2InitializePoolEvent(e) => &mut e.metadata,
|
||||
DexEvent::MeteoraDammV2InitializeCustomizablePoolEvent(e) => &mut e.metadata,
|
||||
DexEvent::MeteoraDammV2InitializePoolWithDynamicConfigEvent(e) => &mut e.metadata,
|
||||
DexEvent::TokenAccountEvent(e) => &mut e.metadata,
|
||||
DexEvent::NonceAccountEvent(e) => &mut e.metadata,
|
||||
DexEvent::TokenInfoEvent(e) => &mut e.metadata,
|
||||
DexEvent::BlockMetaEvent(e) => &mut e.metadata,
|
||||
DexEvent::SetComputeUnitLimitEvent(e) => &mut e.metadata,
|
||||
DexEvent::SetComputeUnitPriceEvent(e) => &mut e.metadata,
|
||||
pub fn metadata_mut(&mut self) -> &mut EventMetadata {
|
||||
match self {
|
||||
$(DexEvent::$variant(e) => &mut e.metadata,)*
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl_dex_event_metadata!(
|
||||
// Bonk events
|
||||
BonkTradeEvent,
|
||||
BonkPoolCreateEvent,
|
||||
BonkMigrateToAmmEvent,
|
||||
BonkMigrateToCpswapEvent,
|
||||
BonkPoolStateAccountEvent,
|
||||
BonkGlobalConfigAccountEvent,
|
||||
BonkPlatformConfigAccountEvent,
|
||||
// PumpFun events
|
||||
PumpFunCreateTokenEvent,
|
||||
PumpFunCreateV2TokenEvent,
|
||||
PumpFunTradeEvent,
|
||||
PumpFunMigrateEvent,
|
||||
PumpFunBondingCurveAccountEvent,
|
||||
PumpFunGlobalAccountEvent,
|
||||
// PumpSwap events
|
||||
PumpSwapBuyEvent,
|
||||
PumpSwapSellEvent,
|
||||
PumpSwapCreatePoolEvent,
|
||||
PumpSwapDepositEvent,
|
||||
PumpSwapWithdrawEvent,
|
||||
PumpSwapGlobalConfigAccountEvent,
|
||||
PumpSwapPoolAccountEvent,
|
||||
// Raydium AMM V4 events
|
||||
RaydiumAmmV4SwapEvent,
|
||||
RaydiumAmmV4DepositEvent,
|
||||
RaydiumAmmV4WithdrawEvent,
|
||||
RaydiumAmmV4WithdrawPnlEvent,
|
||||
RaydiumAmmV4Initialize2Event,
|
||||
RaydiumAmmV4AmmInfoAccountEvent,
|
||||
// Raydium CLMM events
|
||||
RaydiumClmmSwapEvent,
|
||||
RaydiumClmmSwapV2Event,
|
||||
RaydiumClmmClosePositionEvent,
|
||||
RaydiumClmmIncreaseLiquidityV2Event,
|
||||
RaydiumClmmDecreaseLiquidityV2Event,
|
||||
RaydiumClmmCreatePoolEvent,
|
||||
RaydiumClmmOpenPositionWithToken22NftEvent,
|
||||
RaydiumClmmOpenPositionV2Event,
|
||||
RaydiumClmmAmmConfigAccountEvent,
|
||||
RaydiumClmmPoolStateAccountEvent,
|
||||
RaydiumClmmTickArrayStateAccountEvent,
|
||||
// Raydium CPMM events
|
||||
RaydiumCpmmSwapEvent,
|
||||
RaydiumCpmmDepositEvent,
|
||||
RaydiumCpmmWithdrawEvent,
|
||||
RaydiumCpmmInitializeEvent,
|
||||
RaydiumCpmmAmmConfigAccountEvent,
|
||||
RaydiumCpmmPoolStateAccountEvent,
|
||||
// Meteora DAMM v2 events
|
||||
MeteoraDammV2SwapEvent,
|
||||
MeteoraDammV2Swap2Event,
|
||||
MeteoraDammV2InitializePoolEvent,
|
||||
MeteoraDammV2InitializeCustomizablePoolEvent,
|
||||
MeteoraDammV2InitializePoolWithDynamicConfigEvent,
|
||||
// Common events
|
||||
TokenAccountEvent,
|
||||
NonceAccountEvent,
|
||||
TokenInfoEvent,
|
||||
BlockMetaEvent,
|
||||
SetComputeUnitLimitEvent,
|
||||
SetComputeUnitPriceEvent,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user