feat: bridge streamer to sol-parser-sdk

This commit is contained in:
0xfnzero
2026-05-15 05:09:29 +08:00
parent e29a2e4f5a
commit ab84249f4a
85 changed files with 6350 additions and 1362 deletions
+133
View File
@@ -0,0 +1,133 @@
//! Account parser bridge: keep SDK account parsing details out of streamer core paths.
use crate::streaming::event_parser::common::filter::{passes_event_type_filter, EventTypeFilter};
use crate::streaming::event_parser::common::EventType;
use crate::streaming::event_parser::{DexEvent, Protocol};
use crate::streaming::grpc::AccountPretty;
use sol_parser_sdk::grpc::types::{
EventType as SdkGrpcEventType, EventTypeFilter as SdkGrpcEventTypeFilter,
};
use super::convert_parser_event;
use super::filter::event_matches_protocol;
pub(crate) enum AccountParseResult {
Event(DexEvent),
Filtered,
Unsupported,
}
// SDK account event omits the streamer wrapper fields and this byte; recover them from raw data.
const PUMPFUN_GLOBAL_CASHBACK_OFFSET: usize = 8 + 764;
pub(crate) fn parse_account_event(
account: &AccountPretty,
protocols: &[Protocol],
event_type_filter: Option<&EventTypeFilter>,
) -> Option<DexEvent> {
match parse_account_event_for_streamer(account, protocols, event_type_filter) {
AccountParseResult::Event(event) => Some(event),
AccountParseResult::Filtered | AccountParseResult::Unsupported => None,
}
}
pub(crate) fn parse_account_event_for_streamer(
account: &AccountPretty,
protocols: &[Protocol],
event_type_filter: Option<&EventTypeFilter>,
) -> AccountParseResult {
let sdk_account = sol_parser_sdk::accounts::AccountData {
pubkey: account.pubkey,
executable: account.executable,
lamports: account.lamports,
owner: account.owner,
rent_epoch: account.rent_epoch,
data: account.data.clone(),
};
let sdk_metadata = sol_parser_sdk::core::events::EventMetadata {
signature: account.signature,
slot: account.slot,
tx_index: 0,
block_time_us: 0,
grpc_recv_us: account.recv_us,
recent_blockhash: None,
};
let sdk_parse_filter = build_sdk_account_event_filter(event_type_filter);
let sdk_event = sol_parser_sdk::accounts::parse_account_unified(
&sdk_account,
sdk_metadata,
Some(&sdk_parse_filter),
);
let Some(sdk_event) = sdk_event else {
return AccountParseResult::Unsupported;
};
let Some(mut event) = convert_parser_event(sdk_event, None, account.recv_us) else {
return AccountParseResult::Unsupported;
};
if !event_matches_protocol(protocols, &event)
|| !passes_event_type_filter(event_type_filter, &event)
{
return AccountParseResult::Filtered;
}
normalize_account_event(&mut event, account);
AccountParseResult::Event(event)
}
fn build_sdk_account_event_filter(filter: Option<&EventTypeFilter>) -> SdkGrpcEventTypeFilter {
let Some(f) = filter else {
return SdkGrpcEventTypeFilter::exclude_types(Vec::new());
};
if f.include.is_empty() {
let mut raw = Vec::new();
for et in &f.exclude {
raw.extend(streamer_account_event_to_sdk_types(et));
}
dedup_sdk_grpc_event_types(&mut raw);
return SdkGrpcEventTypeFilter::exclude_types(raw);
}
let mut raw = Vec::new();
for et in &f.include {
raw.extend(streamer_account_event_to_sdk_types(et));
}
dedup_sdk_grpc_event_types(&mut raw);
SdkGrpcEventTypeFilter::include_only(raw)
}
fn streamer_account_event_to_sdk_types(t: &EventType) -> Vec<SdkGrpcEventType> {
match t {
EventType::TokenAccount | EventType::TokenInfo => vec![SdkGrpcEventType::TokenAccount],
EventType::NonceAccount => vec![SdkGrpcEventType::NonceAccount],
EventType::AccountPumpFunGlobal => vec![SdkGrpcEventType::AccountPumpFunGlobal],
EventType::AccountPumpSwapGlobalConfig => {
vec![SdkGrpcEventType::AccountPumpSwapGlobalConfig]
}
EventType::AccountPumpSwapPool => vec![SdkGrpcEventType::AccountPumpSwapPool],
_ => Vec::new(),
}
}
fn dedup_sdk_grpc_event_types(v: &mut Vec<SdkGrpcEventType>) {
let mut i = 0;
while i < v.len() {
if v[..i].contains(&v[i]) {
v.remove(i);
} else {
i += 1;
}
}
}
fn normalize_account_event(event: &mut DexEvent, account: &AccountPretty) {
if let DexEvent::PumpFunGlobalAccountEvent(e) = event {
e.executable = account.executable;
e.lamports = account.lamports;
e.owner = account.owner;
e.rent_epoch = account.rent_epoch;
if let Some(flag) = account.data.get(PUMPFUN_GLOBAL_CASHBACK_OFFSET) {
e.global.is_cashback_enabled = *flag != 0;
}
}
}
+54
View File
@@ -0,0 +1,54 @@
//! Block time and `recv_us` alignment with streamer [`EventMetadata`].
use crate::streaming::event_parser::common::types::{EventType, ProtocolType};
use crate::streaming::event_parser::common::EventMetadata;
use crate::streaming::event_parser::DexEvent;
use prost_types::Timestamp;
use solana_sdk::pubkey::Pubkey;
/// Build a prost `Timestamp` from streamer `EventMetadata`.
pub(crate) fn block_timestamp_from_stream_meta(meta: &EventMetadata) -> Timestamp {
let sec = meta.block_time;
let rem_ms = meta.block_time_ms.saturating_sub(sec.saturating_mul(1000));
let nanos = rem_ms.saturating_mul(1_000_000).min(999_999_999) as i32;
Timestamp { seconds: sec, nanos }
}
/// Preserve outer parser instruction indexes and optional blockhash when the SDK metadata has no
/// equivalent context.
pub(crate) fn fuse_streamer_ix_ctx(mut ev: DexEvent, sm: &EventMetadata) -> DexEvent {
let m = ev.metadata_mut();
m.outer_index = sm.outer_index;
m.inner_index = sm.inner_index;
if sm.recent_blockhash.is_some() {
m.recent_blockhash = sm.recent_blockhash.clone();
}
ev
}
pub(crate) fn adapt_pm(
pm: sol_parser_sdk::core::events::EventMetadata,
bt: Option<&Timestamp>,
recv_wall_us: i64,
proto: ProtocolType,
et: EventType,
program_id: Pubkey,
) -> EventMetadata {
let block_time_sec = bt.map(|t| t.seconds).unwrap_or_else(|| pm.block_time_us / 1_000_000);
let block_time_ms = bt
.map(|t| t.seconds * 1000 + t.nanos as i64 / 1_000_000)
.unwrap_or(pm.block_time_us / 1000);
EventMetadata::new(
pm.signature,
pm.slot,
block_time_sec,
block_time_ms,
proto,
et,
program_id,
0,
None,
recv_wall_us,
Some(pm.tx_index),
pm.recent_blockhash.clone(),
)
}
@@ -0,0 +1,220 @@
//! Bonk plus Token / Nonce / PumpSwap account event mapping.
use crate::streaming::event_parser::common::EventMetadata;
use crate::streaming::event_parser::core::account_event_parser::{
NonceAccountEvent, TokenAccountEvent, TokenInfoEvent,
};
use crate::streaming::event_parser::protocols::bonk::events::{
BonkMigrateToAmmEvent, BonkPoolCreateEvent, BonkTradeEvent,
};
use crate::streaming::event_parser::protocols::bonk::types::{
CurveParams, MintParams, PoolStatus, TradeDirection as BonkTradeDirection, VestingParams,
};
use crate::streaming::event_parser::protocols::pumpswap::events::{
PumpSwapGlobalConfigAccountEvent, PumpSwapPoolAccountEvent,
};
use crate::streaming::event_parser::protocols::pumpswap::types::{GlobalConfig, Pool};
use sol_parser_sdk::core::events::{
BonkTradeEvent as PbBonkTrade, TradeDirection as PbBonkTradeDirection,
};
use solana_sdk::pubkey::Pubkey;
#[inline]
pub(crate) fn pb_bonk_trade_direction(d: PbBonkTradeDirection) -> BonkTradeDirection {
match d {
PbBonkTradeDirection::Buy => BonkTradeDirection::Buy,
PbBonkTradeDirection::Sell => BonkTradeDirection::Sell,
}
}
/// Align SDK Bonk trades with the four native Bonk trade instruction variants.
#[inline]
pub(crate) fn sdk_bonk_trade_event_type(
b: &PbBonkTrade,
) -> crate::streaming::event_parser::common::types::EventType {
use crate::streaming::event_parser::common::types::EventType;
match (&b.trade_direction, b.exact_in) {
(&PbBonkTradeDirection::Buy, true) => EventType::BonkBuyExactIn,
(&PbBonkTradeDirection::Buy, false) => EventType::BonkBuyExactOut,
(&PbBonkTradeDirection::Sell, true) => EventType::BonkSellExactIn,
(&PbBonkTradeDirection::Sell, false) => EventType::BonkSellExactOut,
}
}
/// SDK Bonk trade events do not expose reserves or fee rates; keep those fields at streamer
/// defaults.
pub(crate) fn bonk_trade_from_parser(
b: sol_parser_sdk::core::events::BonkTradeEvent,
meta: EventMetadata,
) -> BonkTradeEvent {
BonkTradeEvent {
metadata: meta,
pool_state: b.pool_state,
total_base_sell: 0,
virtual_base: 0,
virtual_quote: 0,
real_base_before: 0,
real_quote_before: 0,
real_base_after: 0,
real_quote_after: 0,
amount_in: b.amount_in,
amount_out: b.amount_out,
protocol_fee: 0,
platform_fee: 0,
creator_fee: 0,
share_fee: 0,
trade_direction: pb_bonk_trade_direction(b.trade_direction),
pool_status: PoolStatus::Trade,
exact_in: b.exact_in,
payer: b.user,
..Default::default()
}
}
pub(crate) fn bonk_pool_create_from_parser(
p: sol_parser_sdk::core::events::BonkPoolCreateEvent,
meta: EventMetadata,
) -> BonkPoolCreateEvent {
BonkPoolCreateEvent {
metadata: meta,
pool_state: p.pool_state,
creator: p.creator,
config: Pubkey::default(),
base_mint_param: MintParams {
decimals: p.base_mint_param.decimals,
name: p.base_mint_param.name.clone(),
symbol: p.base_mint_param.symbol.clone(),
uri: p.base_mint_param.uri.clone(),
},
curve_param: CurveParams::default(),
vesting_param: VestingParams::default(),
amm_fee_on: None,
..Default::default()
}
}
pub(crate) fn bonk_migrate_to_amm_from_parser(
m: sol_parser_sdk::core::events::BonkMigrateAmmEvent,
meta: EventMetadata,
) -> BonkMigrateToAmmEvent {
BonkMigrateToAmmEvent {
metadata: meta,
payer: m.user,
pool_state: m.old_pool,
amm_pool: m.new_pool,
..Default::default()
}
}
pub(crate) fn token_account_from_parser(
e: sol_parser_sdk::core::events::TokenAccountEvent,
meta: EventMetadata,
) -> TokenAccountEvent {
TokenAccountEvent {
metadata: meta,
pubkey: e.pubkey,
executable: e.executable,
lamports: e.lamports,
owner: e.owner,
rent_epoch: e.rent_epoch,
amount: e.amount,
token_owner: e.token_owner,
}
}
pub(crate) fn token_info_from_parser(
e: sol_parser_sdk::core::events::TokenInfoEvent,
meta: EventMetadata,
) -> TokenInfoEvent {
TokenInfoEvent {
metadata: meta,
pubkey: e.pubkey,
executable: e.executable,
lamports: e.lamports,
owner: e.owner,
rent_epoch: e.rent_epoch,
supply: e.supply,
decimals: e.decimals,
}
}
pub(crate) fn nonce_account_from_parser(
e: sol_parser_sdk::core::events::NonceAccountEvent,
meta: EventMetadata,
) -> NonceAccountEvent {
NonceAccountEvent {
metadata: meta,
pubkey: e.pubkey,
executable: e.executable,
lamports: e.lamports,
owner: e.owner,
rent_epoch: e.rent_epoch,
nonce: e.nonce,
authority: e.authority,
}
}
pub(crate) fn pumpswap_global_config_from_pb(
g: sol_parser_sdk::core::events::PumpSwapGlobalConfig,
) -> GlobalConfig {
GlobalConfig {
admin: g.admin,
lp_fee_basis_points: g.lp_fee_basis_points,
protocol_fee_basis_points: g.protocol_fee_basis_points,
disable_flags: g.disable_flags,
protocol_fee_recipients: g.protocol_fee_recipients,
coin_creator_fee_basis_points: g.coin_creator_fee_basis_points,
admin_set_coin_creator_authority: g.admin_set_coin_creator_authority,
whitelist_pda: g.whitelist_pda,
reserved_fee_recipient: g.reserved_fee_recipient,
mayhem_mode_enabled: g.mayhem_mode_enabled,
reserved_fee_recipients: g.reserved_fee_recipients,
}
}
pub(crate) fn pumpswap_pool_from_pb(p: sol_parser_sdk::core::events::PumpSwapPool) -> Pool {
Pool {
pool_bump: p.pool_bump,
index: p.index,
creator: p.creator,
base_mint: p.base_mint,
quote_mint: p.quote_mint,
lp_mint: p.lp_mint,
pool_base_token_account: p.pool_base_token_account,
pool_quote_token_account: p.pool_quote_token_account,
lp_supply: p.lp_supply,
coin_creator: p.coin_creator,
is_mayhem_mode: p.is_mayhem_mode,
is_cashback_coin: p.is_cashback_coin,
reserved: [0u8; 7],
}
}
pub(crate) fn pumpswap_global_config_account_from_parser(
e: sol_parser_sdk::core::events::PumpSwapGlobalConfigAccountEvent,
meta: EventMetadata,
) -> PumpSwapGlobalConfigAccountEvent {
PumpSwapGlobalConfigAccountEvent {
metadata: meta,
pubkey: e.pubkey,
executable: e.executable,
lamports: e.lamports,
owner: e.owner,
rent_epoch: e.rent_epoch,
global_config: pumpswap_global_config_from_pb(e.global_config),
}
}
pub(crate) fn pumpswap_pool_account_from_parser(
e: sol_parser_sdk::core::events::PumpSwapPoolAccountEvent,
meta: EventMetadata,
) -> PumpSwapPoolAccountEvent {
PumpSwapPoolAccountEvent {
metadata: meta,
pubkey: e.pubkey,
executable: e.executable,
lamports: e.lamports,
owner: e.owner,
rent_epoch: e.rent_epoch,
pool: pumpswap_pool_from_pb(e.pool),
}
}
+917
View File
@@ -0,0 +1,917 @@
//! Main dispatch from [`sol_parser_sdk::DexEvent`] to streamer [`DexEvent`].
use crate::streaming::event_parser::common::filter::passes_event_type_filter;
use crate::streaming::event_parser::common::types::{EventType, ProtocolType};
use crate::streaming::event_parser::common::EventMetadata;
use crate::streaming::event_parser::protocols::block::block_meta_event::BlockMetaEvent;
use crate::streaming::event_parser::protocols::sol_parser_forward::events::ParserSdkErrorEvent;
use crate::streaming::event_parser::{DexEvent, Protocol};
use prost_types::Timestamp;
use sol_parser_sdk::DexEvent as PbDexEvent;
use solana_sdk::pubkey::Pubkey;
use super::adapt::adapt_pm;
use super::bonk_accounts::*;
use super::filter::event_matches_protocol;
use super::forward_pb::*;
use super::program_ids::*;
use super::pump_pumpswap::*;
use super::raydium_and_damm::*;
pub(crate) fn convert_parser_event(
ev: PbDexEvent,
bt: Option<&Timestamp>,
recv_wall_us: i64,
) -> Option<DexEvent> {
match ev {
PbDexEvent::PumpFunTrade(t) => Some(pumpfun_trade_from_parser(t, bt, recv_wall_us)),
PbDexEvent::PumpFunBuy(t) => Some(pumpfun_trade_from_parser_with_event_type(
t,
bt,
recv_wall_us,
EventType::PumpFunBuy,
)),
PbDexEvent::PumpFunSell(t) => Some(pumpfun_trade_from_parser_with_event_type(
t,
bt,
recv_wall_us,
EventType::PumpFunSell,
)),
PbDexEvent::PumpFunBuyExactSolIn(t) => Some(pumpfun_trade_from_parser_with_event_type(
t,
bt,
recv_wall_us,
EventType::PumpFunBuyExactSolIn,
)),
PbDexEvent::PumpFunCreate(c) => {
let meta = adapt_pm(
c.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::PumpFun,
EventType::PumpFunCreateToken,
pump_program(),
);
Some(DexEvent::PumpFunCreateTokenEvent(pumpfun_create_token_from_parser(c, meta)))
}
PbDexEvent::PumpFunCreateV2(c) => {
let meta = adapt_pm(
c.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::PumpFun,
EventType::PumpFunCreateV2Token,
pump_program(),
);
Some(DexEvent::PumpFunCreateV2TokenEvent(pumpfun_create_v2_from_parser(c, meta)))
}
PbDexEvent::PumpFunMigrate(m) => {
let meta = adapt_pm(
m.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::PumpFun,
EventType::PumpFunMigrate,
pump_program(),
);
Some(DexEvent::PumpFunMigrateEvent(pumpfun_migrate_from_parser(m, meta)))
}
PbDexEvent::PumpFeesCreateFeeSharingConfig(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::PumpFun,
EventType::PumpFeesCreateFeeSharingConfig,
pump_fees_program(),
);
Some(DexEvent::PumpFeesCreateFeeSharingConfigEvent(
pump_fees_create_sharing_config_from_parser(e, meta),
))
}
PbDexEvent::PumpFeesInitializeFeeConfig(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::PumpFun,
EventType::PumpFeesInitializeFeeConfig,
pump_fees_program(),
);
Some(DexEvent::PumpFeesInitializeFeeConfigEvent(
pump_fees_initialize_fee_config_from_parser(e, meta),
))
}
PbDexEvent::PumpFeesResetFeeSharingConfig(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::PumpFun,
EventType::PumpFeesResetFeeSharingConfig,
pump_fees_program(),
);
Some(DexEvent::PumpFeesResetFeeSharingConfigEvent(
pump_fees_reset_sharing_config_from_parser(e, meta),
))
}
PbDexEvent::PumpFeesRevokeFeeSharingAuthority(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::PumpFun,
EventType::PumpFeesRevokeFeeSharingAuthority,
pump_fees_program(),
);
Some(DexEvent::PumpFeesRevokeFeeSharingAuthorityEvent(
pump_fees_revoke_authority_from_parser(e, meta),
))
}
PbDexEvent::PumpFeesTransferFeeSharingAuthority(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::PumpFun,
EventType::PumpFeesTransferFeeSharingAuthority,
pump_fees_program(),
);
Some(DexEvent::PumpFeesTransferFeeSharingAuthorityEvent(
pump_fees_transfer_authority_from_parser(e, meta),
))
}
PbDexEvent::PumpFeesUpdateAdmin(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::PumpFun,
EventType::PumpFeesUpdateAdmin,
pump_fees_program(),
);
Some(DexEvent::PumpFeesUpdateAdminEvent(pump_fees_update_admin_from_parser(e, meta)))
}
PbDexEvent::PumpFeesUpdateFeeConfig(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::PumpFun,
EventType::PumpFeesUpdateFeeConfig,
pump_fees_program(),
);
Some(DexEvent::PumpFeesUpdateFeeConfigEvent(pump_fees_update_fee_config_from_parser(
e, meta,
)))
}
PbDexEvent::PumpFeesUpdateFeeShares(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::PumpFun,
EventType::PumpFeesUpdateFeeShares,
pump_fees_program(),
);
Some(DexEvent::PumpFeesUpdateFeeSharesEvent(pump_fees_update_fee_shares_from_parser(
e, meta,
)))
}
PbDexEvent::PumpFeesUpsertFeeTiers(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::PumpFun,
EventType::PumpFeesUpsertFeeTiers,
pump_fees_program(),
);
Some(DexEvent::PumpFeesUpsertFeeTiersEvent(pump_fees_upsert_fee_tiers_from_parser(
e, meta,
)))
}
PbDexEvent::PumpFunMigrateBondingCurveCreator(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::PumpFun,
EventType::PumpFunMigrateBondingCurveCreator,
pump_program(),
);
Some(DexEvent::PumpFunMigrateBondingCurveCreatorEvent(
pumpfun_migrate_bonding_creator_from_parser(e, meta),
))
}
PbDexEvent::PumpFunGlobalAccount(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::PumpFun,
EventType::AccountPumpFunGlobal,
pump_program(),
);
Some(DexEvent::PumpFunGlobalAccountEvent(pumpfun_global_account_from_parser(e, meta)))
}
PbDexEvent::PumpSwapTrade(t) => pumpswap_trade_from_parser(t, bt, recv_wall_us),
PbDexEvent::PumpSwapBuy(b) => {
let meta = adapt_pm(
b.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::PumpSwap,
EventType::PumpSwapBuy,
pumpswap_program(),
);
Some(DexEvent::PumpSwapBuyEvent(pumpswap_buy_full_from_parser(b, meta)))
}
PbDexEvent::PumpSwapSell(s) => {
let meta = adapt_pm(
s.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::PumpSwap,
EventType::PumpSwapSell,
pumpswap_program(),
);
Some(DexEvent::PumpSwapSellEvent(pumpswap_sell_full_from_parser(s, meta)))
}
PbDexEvent::PumpSwapCreatePool(c) => {
let meta = adapt_pm(
c.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::PumpSwap,
EventType::PumpSwapCreatePool,
pumpswap_program(),
);
Some(DexEvent::PumpSwapCreatePoolEvent(pumpswap_create_pool_from_parser(c, meta)))
}
PbDexEvent::PumpSwapLiquidityAdded(a) => {
let meta = adapt_pm(
a.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::PumpSwap,
EventType::PumpSwapDeposit,
pumpswap_program(),
);
Some(DexEvent::PumpSwapDepositEvent(pumpswap_liquidity_added_to_deposit(a, meta)))
}
PbDexEvent::PumpSwapLiquidityRemoved(r) => {
let meta = adapt_pm(
r.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::PumpSwap,
EventType::PumpSwapWithdraw,
pumpswap_program(),
);
Some(DexEvent::PumpSwapWithdrawEvent(pumpswap_liquidity_removed_to_withdraw(r, meta)))
}
PbDexEvent::BonkTrade(b) => {
let et = sdk_bonk_trade_event_type(&b);
let meta = adapt_pm(
b.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::Bonk,
et,
bonk_program(),
);
Some(DexEvent::BonkTradeEvent(bonk_trade_from_parser(b, meta)))
}
PbDexEvent::BonkPoolCreate(p) => {
let meta = adapt_pm(
p.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::Bonk,
EventType::BonkInitialize,
bonk_program(),
);
Some(DexEvent::BonkPoolCreateEvent(bonk_pool_create_from_parser(p, meta)))
}
PbDexEvent::BonkMigrateAmm(m) => {
let meta = adapt_pm(
m.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::Bonk,
EventType::BonkMigrateToAmm,
bonk_program(),
);
Some(DexEvent::BonkMigrateToAmmEvent(bonk_migrate_to_amm_from_parser(m, meta)))
}
PbDexEvent::RaydiumCpmmSwap(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::RaydiumCpmm,
EventType::RaydiumCpmmSwapBaseInput,
raydium_cpmm_program(),
);
Some(DexEvent::RaydiumCpmmSwapEvent(raydium_cpmm_swap_from_parser(e, meta)))
}
PbDexEvent::RaydiumCpmmDeposit(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::RaydiumCpmm,
EventType::RaydiumCpmmDeposit,
raydium_cpmm_program(),
);
Some(DexEvent::RaydiumCpmmDepositEvent(raydium_cpmm_deposit_from_parser(e, meta)))
}
PbDexEvent::RaydiumCpmmWithdraw(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::RaydiumCpmm,
EventType::RaydiumCpmmWithdraw,
raydium_cpmm_program(),
);
Some(DexEvent::RaydiumCpmmWithdrawEvent(raydium_cpmm_withdraw_from_parser(e, meta)))
}
PbDexEvent::RaydiumCpmmInitialize(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::RaydiumCpmm,
EventType::RaydiumCpmmInitialize,
raydium_cpmm_program(),
);
Some(DexEvent::RaydiumCpmmInitializeEvent(raydium_cpmm_initialize_from_parser(e, meta)))
}
PbDexEvent::RaydiumClmmSwap(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::RaydiumClmm,
EventType::RaydiumClmmSwap,
raydium_clmm_program(),
);
Some(DexEvent::RaydiumClmmSwapEvent(raydium_clmm_swap_from_parser(e, meta)))
}
PbDexEvent::RaydiumClmmCreatePool(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::RaydiumClmm,
EventType::RaydiumClmmCreatePool,
raydium_clmm_program(),
);
Some(DexEvent::RaydiumClmmCreatePoolEvent(raydium_clmm_create_pool_from_parser(
e, meta,
)))
}
PbDexEvent::RaydiumClmmOpenPosition(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::RaydiumClmm,
EventType::RaydiumClmmOpenPositionV2,
raydium_clmm_program(),
);
Some(DexEvent::RaydiumClmmOpenPositionV2Event(
raydium_clmm_open_position_v2_from_parser(e, meta),
))
}
PbDexEvent::RaydiumClmmOpenPositionWithTokenExtNft(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::RaydiumClmm,
EventType::RaydiumClmmOpenPositionWithToken22Nft,
raydium_clmm_program(),
);
Some(DexEvent::RaydiumClmmOpenPositionWithToken22NftEvent(
raydium_clmm_open_position_token22_from_parser(e, meta),
))
}
PbDexEvent::RaydiumClmmClosePosition(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::RaydiumClmm,
EventType::RaydiumClmmClosePosition,
raydium_clmm_program(),
);
Some(DexEvent::RaydiumClmmClosePositionEvent(raydium_clmm_close_position_from_parser(
e, meta,
)))
}
PbDexEvent::RaydiumClmmIncreaseLiquidity(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::RaydiumClmm,
EventType::RaydiumClmmIncreaseLiquidityV2,
raydium_clmm_program(),
);
Some(DexEvent::RaydiumClmmIncreaseLiquidityV2Event(
raydium_clmm_increase_liquidity_v2_from_parser(e, meta),
))
}
PbDexEvent::RaydiumClmmDecreaseLiquidity(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::RaydiumClmm,
EventType::RaydiumClmmDecreaseLiquidityV2,
raydium_clmm_program(),
);
Some(DexEvent::RaydiumClmmDecreaseLiquidityV2Event(
raydium_clmm_decrease_liquidity_v2_from_parser(e, meta),
))
}
PbDexEvent::RaydiumClmmCollectFee(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::RaydiumClmm,
EventType::RaydiumClmmCollectFee,
raydium_clmm_program(),
);
Some(DexEvent::RaydiumClmmCollectFeeEvent(raydium_clmm_collect_fee_from_parser(
e, meta,
)))
}
PbDexEvent::RaydiumAmmV4Swap(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::RaydiumAmmV4,
EventType::RaydiumAmmV4SwapBaseIn,
raydium_amm_v4_program(),
);
Some(DexEvent::RaydiumAmmV4SwapEvent(raydium_amm_v4_swap_from_parser(e, meta)))
}
PbDexEvent::RaydiumAmmV4Deposit(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::RaydiumAmmV4,
EventType::RaydiumAmmV4Deposit,
raydium_amm_v4_program(),
);
Some(DexEvent::RaydiumAmmV4DepositEvent(raydium_amm_v4_deposit_from_parser(e, meta)))
}
PbDexEvent::RaydiumAmmV4Withdraw(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::RaydiumAmmV4,
EventType::RaydiumAmmV4Withdraw,
raydium_amm_v4_program(),
);
Some(DexEvent::RaydiumAmmV4WithdrawEvent(raydium_amm_v4_withdraw_from_parser(e, meta)))
}
PbDexEvent::RaydiumAmmV4WithdrawPnl(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::RaydiumAmmV4,
EventType::RaydiumAmmV4WithdrawPnl,
raydium_amm_v4_program(),
);
Some(DexEvent::RaydiumAmmV4WithdrawPnlEvent(raydium_amm_v4_withdraw_pnl_from_parser(
e, meta,
)))
}
PbDexEvent::RaydiumAmmV4Initialize2(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::RaydiumAmmV4,
EventType::RaydiumAmmV4Initialize2,
raydium_amm_v4_program(),
);
Some(DexEvent::RaydiumAmmV4Initialize2Event(raydium_amm_v4_initialize2_from_parser(
e, meta,
)))
}
PbDexEvent::MeteoraDammV2Swap(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::MeteoraDammV2,
EventType::MeteoraDammV2Swap,
meteora_damm_program(),
);
Some(DexEvent::MeteoraDammV2SwapEvent(meteora_damm_v2_swap_from_parser(e, meta)))
}
PbDexEvent::MeteoraDammV2AddLiquidity(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::MeteoraDammV2,
EventType::MeteoraDammV2AddLiquidity,
meteora_damm_program(),
);
Some(DexEvent::MeteoraDammV2AddLiquidityEvent(meteora_damm_v2_add_liquidity_from_pb(
e, meta,
)))
}
PbDexEvent::MeteoraDammV2RemoveLiquidity(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::MeteoraDammV2,
EventType::MeteoraDammV2RemoveLiquidity,
meteora_damm_program(),
);
Some(DexEvent::MeteoraDammV2RemoveLiquidityEvent(
meteora_damm_v2_remove_liquidity_from_pb(e, meta),
))
}
PbDexEvent::MeteoraDammV2CreatePosition(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::MeteoraDammV2,
EventType::MeteoraDammV2CreatePosition,
meteora_damm_program(),
);
Some(DexEvent::MeteoraDammV2CreatePositionEvent(
meteora_damm_v2_create_position_from_pb(e, meta),
))
}
PbDexEvent::MeteoraDammV2ClosePosition(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::MeteoraDammV2,
EventType::MeteoraDammV2ClosePosition,
meteora_damm_program(),
);
Some(DexEvent::MeteoraDammV2ClosePositionEvent(meteora_damm_v2_close_position_from_pb(
e, meta,
)))
}
PbDexEvent::TokenAccount(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::Common,
EventType::TokenAccount,
Pubkey::default(),
);
Some(DexEvent::TokenAccountEvent(token_account_from_parser(e, meta)))
}
PbDexEvent::TokenInfo(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::Common,
EventType::TokenInfo,
Pubkey::default(),
);
Some(DexEvent::TokenInfoEvent(token_info_from_parser(e, meta)))
}
PbDexEvent::NonceAccount(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::Common,
EventType::NonceAccount,
Pubkey::default(),
);
Some(DexEvent::NonceAccountEvent(nonce_account_from_parser(e, meta)))
}
PbDexEvent::PumpSwapGlobalConfigAccount(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::PumpSwap,
EventType::AccountPumpSwapGlobalConfig,
pumpswap_program(),
);
Some(DexEvent::PumpSwapGlobalConfigAccountEvent(
pumpswap_global_config_account_from_parser(e, meta),
))
}
PbDexEvent::PumpSwapPoolAccount(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::PumpSwap,
EventType::AccountPumpSwapPool,
pumpswap_program(),
);
Some(DexEvent::PumpSwapPoolAccountEvent(pumpswap_pool_account_from_parser(e, meta)))
}
PbDexEvent::BlockMeta(m) => {
let meta = adapt_pm(
m.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::Common,
EventType::BlockMeta,
Pubkey::default(),
);
Some(DexEvent::BlockMetaEvent(BlockMetaEvent {
metadata: meta,
slot: m.metadata.slot,
block_hash: m.metadata.recent_blockhash.clone().unwrap_or_default(),
}))
}
PbDexEvent::Error(msg) => Some(DexEvent::ParserSdkErrorEvent(ParserSdkErrorEvent {
metadata: EventMetadata {
recv_us: recv_wall_us,
protocol: ProtocolType::Common,
event_type: EventType::ParserSdkError,
..Default::default()
},
message: msg,
})),
PbDexEvent::OrcaWhirlpoolSwap(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::OrcaWhirlpool,
EventType::OrcaWhirlpoolSwap,
orca_whirlpool_program(),
);
Some(DexEvent::OrcaWhirlpoolSwapEvent(orca_swap_from_pb(e, meta)))
}
PbDexEvent::OrcaWhirlpoolLiquidityIncreased(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::OrcaWhirlpool,
EventType::OrcaWhirlpoolLiquidityIncreased,
orca_whirlpool_program(),
);
Some(DexEvent::OrcaWhirlpoolLiquidityIncreasedEvent(orca_liquidity_increased_from_pb(
e, meta,
)))
}
PbDexEvent::OrcaWhirlpoolLiquidityDecreased(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::OrcaWhirlpool,
EventType::OrcaWhirlpoolLiquidityDecreased,
orca_whirlpool_program(),
);
Some(DexEvent::OrcaWhirlpoolLiquidityDecreasedEvent(orca_liquidity_decreased_from_pb(
e, meta,
)))
}
PbDexEvent::OrcaWhirlpoolPoolInitialized(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::OrcaWhirlpool,
EventType::OrcaWhirlpoolPoolInitialized,
orca_whirlpool_program(),
);
Some(DexEvent::OrcaWhirlpoolPoolInitializedEvent(orca_pool_initialized_from_pb(
e, meta,
)))
}
PbDexEvent::MeteoraPoolsSwap(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::MeteoraPools,
EventType::MeteoraPoolsSwap,
meteora_pools_program(),
);
Some(DexEvent::MeteoraPoolsSwapEvent(meteora_pools_swap_from_pb(e, meta)))
}
PbDexEvent::MeteoraPoolsAddLiquidity(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::MeteoraPools,
EventType::MeteoraPoolsAddLiquidity,
meteora_pools_program(),
);
Some(DexEvent::MeteoraPoolsAddLiquidityEvent(meteora_pools_add_liquidity_from_pb(
e, meta,
)))
}
PbDexEvent::MeteoraPoolsRemoveLiquidity(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::MeteoraPools,
EventType::MeteoraPoolsRemoveLiquidity,
meteora_pools_program(),
);
Some(DexEvent::MeteoraPoolsRemoveLiquidityEvent(
meteora_pools_remove_liquidity_from_pb(e, meta),
))
}
PbDexEvent::MeteoraPoolsBootstrapLiquidity(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::MeteoraPools,
EventType::MeteoraPoolsBootstrapLiquidity,
meteora_pools_program(),
);
Some(DexEvent::MeteoraPoolsBootstrapLiquidityEvent(meteora_pools_bootstrap_from_pb(
e, meta,
)))
}
PbDexEvent::MeteoraPoolsPoolCreated(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::MeteoraPools,
EventType::MeteoraPoolsPoolCreated,
meteora_pools_program(),
);
Some(DexEvent::MeteoraPoolsPoolCreatedEvent(meteora_pools_pool_created_from_pb(
e, meta,
)))
}
PbDexEvent::MeteoraPoolsSetPoolFees(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::MeteoraPools,
EventType::MeteoraPoolsSetPoolFees,
meteora_pools_program(),
);
Some(DexEvent::MeteoraPoolsSetPoolFeesEvent(meteora_pools_set_fees_from_pb(e, meta)))
}
PbDexEvent::MeteoraDlmmSwap(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::MeteoraDlmm,
EventType::MeteoraDlmmSwap,
meteora_dlmm_program(),
);
Some(DexEvent::MeteoraDlmmSwapEvent(meteora_dlmm_swap_from_pb(e, meta)))
}
PbDexEvent::MeteoraDlmmAddLiquidity(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::MeteoraDlmm,
EventType::MeteoraDlmmAddLiquidity,
meteora_dlmm_program(),
);
Some(DexEvent::MeteoraDlmmAddLiquidityEvent(meteora_dlmm_add_liquidity_from_pb(
e, meta,
)))
}
PbDexEvent::MeteoraDlmmRemoveLiquidity(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::MeteoraDlmm,
EventType::MeteoraDlmmRemoveLiquidity,
meteora_dlmm_program(),
);
Some(DexEvent::MeteoraDlmmRemoveLiquidityEvent(meteora_dlmm_remove_liquidity_from_pb(
e, meta,
)))
}
PbDexEvent::MeteoraDlmmInitializePool(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::MeteoraDlmm,
EventType::MeteoraDlmmInitializePool,
meteora_dlmm_program(),
);
Some(DexEvent::MeteoraDlmmInitializePoolEvent(meteora_dlmm_init_pool_from_pb(e, meta)))
}
PbDexEvent::MeteoraDlmmInitializeBinArray(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::MeteoraDlmm,
EventType::MeteoraDlmmInitializeBinArray,
meteora_dlmm_program(),
);
Some(DexEvent::MeteoraDlmmInitializeBinArrayEvent(meteora_dlmm_init_bin_array_from_pb(
e, meta,
)))
}
PbDexEvent::MeteoraDlmmCreatePosition(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::MeteoraDlmm,
EventType::MeteoraDlmmCreatePosition,
meteora_dlmm_program(),
);
Some(DexEvent::MeteoraDlmmCreatePositionEvent(meteora_dlmm_create_position_from_pb(
e, meta,
)))
}
PbDexEvent::MeteoraDlmmClosePosition(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::MeteoraDlmm,
EventType::MeteoraDlmmClosePosition,
meteora_dlmm_program(),
);
Some(DexEvent::MeteoraDlmmClosePositionEvent(meteora_dlmm_close_position_from_pb(
e, meta,
)))
}
PbDexEvent::MeteoraDlmmClaimFee(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::MeteoraDlmm,
EventType::MeteoraDlmmClaimFee,
meteora_dlmm_program(),
);
Some(DexEvent::MeteoraDlmmClaimFeeEvent(meteora_dlmm_claim_fee_from_pb(e, meta)))
}
}
}
pub(crate) fn adapt_parser_events_list(
pb: Vec<PbDexEvent>,
bt: Option<&Timestamp>,
recv_wall_us: i64,
protocols: &[Protocol],
event_type_filter: Option<&crate::streaming::event_parser::common::filter::EventTypeFilter>,
) -> Vec<DexEvent> {
pb.into_iter()
.filter_map(|e| adapt_parser_event(e, bt, recv_wall_us, protocols, event_type_filter))
.collect()
}
pub(crate) fn adapt_parser_event(
pb: PbDexEvent,
bt: Option<&Timestamp>,
recv_wall_us: i64,
protocols: &[Protocol],
event_type_filter: Option<&crate::streaming::event_parser::common::filter::EventTypeFilter>,
) -> Option<DexEvent> {
let ev = convert_parser_event(pb, bt, recv_wall_us)?;
if !event_matches_protocol(protocols, &ev) {
return None;
}
if !passes_event_type_filter(event_type_filter, &ev) {
return None;
}
Some(ev)
}
+116
View File
@@ -0,0 +1,116 @@
//! Matching between subscribed [`Protocol`] values and streamer [`DexEvent`] variants.
use crate::streaming::event_parser::{DexEvent, Protocol};
pub(crate) fn event_matches_protocol(protocols: &[Protocol], ev: &DexEvent) -> bool {
if is_protocol_independent_event(ev) {
return true;
}
if protocols.is_empty() {
return true;
}
protocols.iter().any(|p| protocol_matches_event(p, ev))
}
#[inline]
fn is_protocol_independent_event(ev: &DexEvent) -> bool {
matches!(
ev,
DexEvent::TokenAccountEvent(_)
| DexEvent::TokenInfoEvent(_)
| DexEvent::NonceAccountEvent(_)
| DexEvent::BlockMetaEvent(_)
| DexEvent::SetComputeUnitLimitEvent(_)
| DexEvent::SetComputeUnitPriceEvent(_)
| DexEvent::ParserSdkErrorEvent(_)
)
}
fn protocol_matches_event(p: &Protocol, ev: &DexEvent) -> bool {
match (p, ev) {
(Protocol::PumpFun, DexEvent::PumpFunCreateTokenEvent(_))
| (Protocol::PumpFun, DexEvent::PumpFunCreateV2TokenEvent(_))
| (Protocol::PumpFun, DexEvent::PumpFunTradeEvent(_))
| (Protocol::PumpFun, DexEvent::PumpFunMigrateEvent(_))
| (Protocol::PumpFun, DexEvent::PumpFeesCreateFeeSharingConfigEvent(_))
| (Protocol::PumpFun, DexEvent::PumpFeesInitializeFeeConfigEvent(_))
| (Protocol::PumpFun, DexEvent::PumpFeesResetFeeSharingConfigEvent(_))
| (Protocol::PumpFun, DexEvent::PumpFeesRevokeFeeSharingAuthorityEvent(_))
| (Protocol::PumpFun, DexEvent::PumpFeesTransferFeeSharingAuthorityEvent(_))
| (Protocol::PumpFun, DexEvent::PumpFeesUpdateAdminEvent(_))
| (Protocol::PumpFun, DexEvent::PumpFeesUpdateFeeConfigEvent(_))
| (Protocol::PumpFun, DexEvent::PumpFeesUpdateFeeSharesEvent(_))
| (Protocol::PumpFun, DexEvent::PumpFeesUpsertFeeTiersEvent(_))
| (Protocol::PumpFun, DexEvent::PumpFunMigrateBondingCurveCreatorEvent(_))
| (Protocol::PumpFun, DexEvent::PumpFunBondingCurveAccountEvent(_))
| (Protocol::PumpFun, DexEvent::PumpFunGlobalAccountEvent(_)) => true,
(Protocol::PumpSwap, DexEvent::PumpSwapBuyEvent(_))
| (Protocol::PumpSwap, DexEvent::PumpSwapSellEvent(_))
| (Protocol::PumpSwap, DexEvent::PumpSwapCreatePoolEvent(_))
| (Protocol::PumpSwap, DexEvent::PumpSwapDepositEvent(_))
| (Protocol::PumpSwap, DexEvent::PumpSwapWithdrawEvent(_))
| (Protocol::PumpSwap, DexEvent::PumpSwapGlobalConfigAccountEvent(_))
| (Protocol::PumpSwap, DexEvent::PumpSwapPoolAccountEvent(_)) => true,
(Protocol::Bonk, DexEvent::BonkTradeEvent(_))
| (Protocol::Bonk, DexEvent::BonkPoolCreateEvent(_))
| (Protocol::Bonk, DexEvent::BonkMigrateToAmmEvent(_))
| (Protocol::Bonk, DexEvent::BonkMigrateToCpswapEvent(_))
| (Protocol::Bonk, DexEvent::BonkPoolStateAccountEvent(_))
| (Protocol::Bonk, DexEvent::BonkGlobalConfigAccountEvent(_))
| (Protocol::Bonk, DexEvent::BonkPlatformConfigAccountEvent(_)) => true,
(Protocol::RaydiumCpmm, DexEvent::RaydiumCpmmSwapEvent(_))
| (Protocol::RaydiumCpmm, DexEvent::RaydiumCpmmDepositEvent(_))
| (Protocol::RaydiumCpmm, DexEvent::RaydiumCpmmWithdrawEvent(_))
| (Protocol::RaydiumCpmm, DexEvent::RaydiumCpmmInitializeEvent(_))
| (Protocol::RaydiumCpmm, DexEvent::RaydiumCpmmAmmConfigAccountEvent(_))
| (Protocol::RaydiumCpmm, DexEvent::RaydiumCpmmPoolStateAccountEvent(_)) => true,
(Protocol::RaydiumClmm, DexEvent::RaydiumClmmSwapEvent(_))
| (Protocol::RaydiumClmm, DexEvent::RaydiumClmmSwapV2Event(_))
| (Protocol::RaydiumClmm, DexEvent::RaydiumClmmClosePositionEvent(_))
| (Protocol::RaydiumClmm, DexEvent::RaydiumClmmIncreaseLiquidityV2Event(_))
| (Protocol::RaydiumClmm, DexEvent::RaydiumClmmDecreaseLiquidityV2Event(_))
| (Protocol::RaydiumClmm, DexEvent::RaydiumClmmCollectFeeEvent(_))
| (Protocol::RaydiumClmm, DexEvent::RaydiumClmmCreatePoolEvent(_))
| (Protocol::RaydiumClmm, DexEvent::RaydiumClmmOpenPositionWithToken22NftEvent(_))
| (Protocol::RaydiumClmm, DexEvent::RaydiumClmmOpenPositionV2Event(_))
| (Protocol::RaydiumClmm, DexEvent::RaydiumClmmAmmConfigAccountEvent(_))
| (Protocol::RaydiumClmm, DexEvent::RaydiumClmmPoolStateAccountEvent(_))
| (Protocol::RaydiumClmm, DexEvent::RaydiumClmmTickArrayStateAccountEvent(_)) => true,
(Protocol::RaydiumAmmV4, DexEvent::RaydiumAmmV4SwapEvent(_))
| (Protocol::RaydiumAmmV4, DexEvent::RaydiumAmmV4DepositEvent(_))
| (Protocol::RaydiumAmmV4, DexEvent::RaydiumAmmV4WithdrawEvent(_))
| (Protocol::RaydiumAmmV4, DexEvent::RaydiumAmmV4WithdrawPnlEvent(_))
| (Protocol::RaydiumAmmV4, DexEvent::RaydiumAmmV4Initialize2Event(_))
| (Protocol::RaydiumAmmV4, DexEvent::RaydiumAmmV4AmmInfoAccountEvent(_)) => true,
(Protocol::MeteoraDammV2, DexEvent::MeteoraDammV2SwapEvent(_))
| (Protocol::MeteoraDammV2, DexEvent::MeteoraDammV2Swap2Event(_))
| (Protocol::MeteoraDammV2, DexEvent::MeteoraDammV2InitializePoolEvent(_))
| (Protocol::MeteoraDammV2, DexEvent::MeteoraDammV2InitializeCustomizablePoolEvent(_))
| (
Protocol::MeteoraDammV2,
DexEvent::MeteoraDammV2InitializePoolWithDynamicConfigEvent(_),
)
| (Protocol::MeteoraDammV2, DexEvent::MeteoraDammV2AddLiquidityEvent(_))
| (Protocol::MeteoraDammV2, DexEvent::MeteoraDammV2RemoveLiquidityEvent(_))
| (Protocol::MeteoraDammV2, DexEvent::MeteoraDammV2CreatePositionEvent(_))
| (Protocol::MeteoraDammV2, DexEvent::MeteoraDammV2ClosePositionEvent(_)) => true,
(Protocol::OrcaWhirlpool, DexEvent::OrcaWhirlpoolSwapEvent(_))
| (Protocol::OrcaWhirlpool, DexEvent::OrcaWhirlpoolLiquidityIncreasedEvent(_))
| (Protocol::OrcaWhirlpool, DexEvent::OrcaWhirlpoolLiquidityDecreasedEvent(_))
| (Protocol::OrcaWhirlpool, DexEvent::OrcaWhirlpoolPoolInitializedEvent(_)) => true,
(Protocol::MeteoraPools, DexEvent::MeteoraPoolsSwapEvent(_))
| (Protocol::MeteoraPools, DexEvent::MeteoraPoolsAddLiquidityEvent(_))
| (Protocol::MeteoraPools, DexEvent::MeteoraPoolsRemoveLiquidityEvent(_))
| (Protocol::MeteoraPools, DexEvent::MeteoraPoolsBootstrapLiquidityEvent(_))
| (Protocol::MeteoraPools, DexEvent::MeteoraPoolsPoolCreatedEvent(_))
| (Protocol::MeteoraPools, DexEvent::MeteoraPoolsSetPoolFeesEvent(_)) => true,
(Protocol::MeteoraDlmm, DexEvent::MeteoraDlmmSwapEvent(_))
| (Protocol::MeteoraDlmm, DexEvent::MeteoraDlmmAddLiquidityEvent(_))
| (Protocol::MeteoraDlmm, DexEvent::MeteoraDlmmRemoveLiquidityEvent(_))
| (Protocol::MeteoraDlmm, DexEvent::MeteoraDlmmInitializePoolEvent(_))
| (Protocol::MeteoraDlmm, DexEvent::MeteoraDlmmInitializeBinArrayEvent(_))
| (Protocol::MeteoraDlmm, DexEvent::MeteoraDlmmCreatePositionEvent(_))
| (Protocol::MeteoraDlmm, DexEvent::MeteoraDlmmClosePositionEvent(_))
| (Protocol::MeteoraDlmm, DexEvent::MeteoraDlmmClaimFeeEvent(_)) => true,
_ => false,
}
}
@@ -0,0 +1,278 @@
//! Orca Whirlpool and Meteora Pools / DLMM events with SDK-shaped payloads.
use crate::streaming::event_parser::common::EventMetadata;
use crate::streaming::event_parser::protocols::sol_parser_forward::events::{
MeteoraDlmmAddLiquidityEvent, MeteoraDlmmClaimFeeEvent, MeteoraDlmmClosePositionEvent,
MeteoraDlmmCreatePositionEvent, MeteoraDlmmInitializeBinArrayEvent,
MeteoraDlmmInitializePoolEvent, MeteoraDlmmRemoveLiquidityEvent, MeteoraDlmmSwapEvent,
MeteoraPoolsAddLiquidityEvent, MeteoraPoolsBootstrapLiquidityEvent,
MeteoraPoolsPoolCreatedEvent, MeteoraPoolsRemoveLiquidityEvent, MeteoraPoolsSetPoolFeesEvent,
MeteoraPoolsSwapEvent, OrcaWhirlpoolLiquidityDecreasedEvent,
OrcaWhirlpoolLiquidityIncreasedEvent, OrcaWhirlpoolPoolInitializedEvent,
OrcaWhirlpoolSwapEvent,
};
pub(crate) fn orca_swap_from_pb(
e: sol_parser_sdk::core::events::OrcaWhirlpoolSwapEvent,
meta: EventMetadata,
) -> OrcaWhirlpoolSwapEvent {
OrcaWhirlpoolSwapEvent {
metadata: meta,
whirlpool: e.whirlpool,
input_amount: e.input_amount,
output_amount: e.output_amount,
a_to_b: e.a_to_b,
pre_sqrt_price: e.pre_sqrt_price,
post_sqrt_price: e.post_sqrt_price,
input_transfer_fee: e.input_transfer_fee,
output_transfer_fee: e.output_transfer_fee,
lp_fee: e.lp_fee,
protocol_fee: e.protocol_fee,
}
}
pub(crate) fn orca_liquidity_increased_from_pb(
e: sol_parser_sdk::core::events::OrcaWhirlpoolLiquidityIncreasedEvent,
meta: EventMetadata,
) -> OrcaWhirlpoolLiquidityIncreasedEvent {
OrcaWhirlpoolLiquidityIncreasedEvent {
metadata: meta,
whirlpool: e.whirlpool,
liquidity: e.liquidity,
token_a_amount: e.token_a_amount,
token_b_amount: e.token_b_amount,
position: e.position,
tick_lower_index: e.tick_lower_index,
tick_upper_index: e.tick_upper_index,
token_a_transfer_fee: e.token_a_transfer_fee,
token_b_transfer_fee: e.token_b_transfer_fee,
}
}
pub(crate) fn orca_liquidity_decreased_from_pb(
e: sol_parser_sdk::core::events::OrcaWhirlpoolLiquidityDecreasedEvent,
meta: EventMetadata,
) -> OrcaWhirlpoolLiquidityDecreasedEvent {
OrcaWhirlpoolLiquidityDecreasedEvent {
metadata: meta,
whirlpool: e.whirlpool,
liquidity: e.liquidity,
token_a_amount: e.token_a_amount,
token_b_amount: e.token_b_amount,
position: e.position,
tick_lower_index: e.tick_lower_index,
tick_upper_index: e.tick_upper_index,
token_a_transfer_fee: e.token_a_transfer_fee,
token_b_transfer_fee: e.token_b_transfer_fee,
}
}
pub(crate) fn orca_pool_initialized_from_pb(
e: sol_parser_sdk::core::events::OrcaWhirlpoolPoolInitializedEvent,
meta: EventMetadata,
) -> OrcaWhirlpoolPoolInitializedEvent {
OrcaWhirlpoolPoolInitializedEvent {
metadata: meta,
whirlpool: e.whirlpool,
whirlpools_config: e.whirlpools_config,
token_mint_a: e.token_mint_a,
token_mint_b: e.token_mint_b,
tick_spacing: e.tick_spacing,
token_program_a: e.token_program_a,
token_program_b: e.token_program_b,
decimals_a: e.decimals_a,
decimals_b: e.decimals_b,
initial_sqrt_price: e.initial_sqrt_price,
}
}
pub(crate) fn meteora_pools_swap_from_pb(
e: sol_parser_sdk::core::events::MeteoraPoolsSwapEvent,
meta: EventMetadata,
) -> MeteoraPoolsSwapEvent {
MeteoraPoolsSwapEvent {
metadata: meta,
in_amount: e.in_amount,
out_amount: e.out_amount,
trade_fee: e.trade_fee,
admin_fee: e.admin_fee,
host_fee: e.host_fee,
}
}
pub(crate) fn meteora_pools_add_liquidity_from_pb(
e: sol_parser_sdk::core::events::MeteoraPoolsAddLiquidityEvent,
meta: EventMetadata,
) -> MeteoraPoolsAddLiquidityEvent {
MeteoraPoolsAddLiquidityEvent {
metadata: meta,
lp_mint_amount: e.lp_mint_amount,
token_a_amount: e.token_a_amount,
token_b_amount: e.token_b_amount,
}
}
pub(crate) fn meteora_pools_remove_liquidity_from_pb(
e: sol_parser_sdk::core::events::MeteoraPoolsRemoveLiquidityEvent,
meta: EventMetadata,
) -> MeteoraPoolsRemoveLiquidityEvent {
MeteoraPoolsRemoveLiquidityEvent {
metadata: meta,
lp_unmint_amount: e.lp_unmint_amount,
token_a_out_amount: e.token_a_out_amount,
token_b_out_amount: e.token_b_out_amount,
}
}
pub(crate) fn meteora_pools_bootstrap_from_pb(
e: sol_parser_sdk::core::events::MeteoraPoolsBootstrapLiquidityEvent,
meta: EventMetadata,
) -> MeteoraPoolsBootstrapLiquidityEvent {
MeteoraPoolsBootstrapLiquidityEvent {
metadata: meta,
lp_mint_amount: e.lp_mint_amount,
token_a_amount: e.token_a_amount,
token_b_amount: e.token_b_amount,
pool: e.pool,
}
}
pub(crate) fn meteora_pools_pool_created_from_pb(
e: sol_parser_sdk::core::events::MeteoraPoolsPoolCreatedEvent,
meta: EventMetadata,
) -> MeteoraPoolsPoolCreatedEvent {
MeteoraPoolsPoolCreatedEvent {
metadata: meta,
lp_mint: e.lp_mint,
token_a_mint: e.token_a_mint,
token_b_mint: e.token_b_mint,
pool_type: e.pool_type,
pool: e.pool,
}
}
pub(crate) fn meteora_pools_set_fees_from_pb(
e: sol_parser_sdk::core::events::MeteoraPoolsSetPoolFeesEvent,
meta: EventMetadata,
) -> MeteoraPoolsSetPoolFeesEvent {
MeteoraPoolsSetPoolFeesEvent {
metadata: meta,
trade_fee_numerator: e.trade_fee_numerator,
trade_fee_denominator: e.trade_fee_denominator,
owner_trade_fee_numerator: e.owner_trade_fee_numerator,
owner_trade_fee_denominator: e.owner_trade_fee_denominator,
pool: e.pool,
}
}
pub(crate) fn meteora_dlmm_swap_from_pb(
e: sol_parser_sdk::core::events::MeteoraDlmmSwapEvent,
meta: EventMetadata,
) -> MeteoraDlmmSwapEvent {
MeteoraDlmmSwapEvent {
metadata: meta,
pool: e.pool,
from: e.from,
start_bin_id: e.start_bin_id,
end_bin_id: e.end_bin_id,
amount_in: e.amount_in,
amount_out: e.amount_out,
swap_for_y: e.swap_for_y,
fee: e.fee,
protocol_fee: e.protocol_fee,
fee_bps: e.fee_bps,
host_fee: e.host_fee,
}
}
pub(crate) fn meteora_dlmm_add_liquidity_from_pb(
e: sol_parser_sdk::core::events::MeteoraDlmmAddLiquidityEvent,
meta: EventMetadata,
) -> MeteoraDlmmAddLiquidityEvent {
MeteoraDlmmAddLiquidityEvent {
metadata: meta,
pool: e.pool,
from: e.from,
position: e.position,
amounts: e.amounts,
active_bin_id: e.active_bin_id,
}
}
pub(crate) fn meteora_dlmm_remove_liquidity_from_pb(
e: sol_parser_sdk::core::events::MeteoraDlmmRemoveLiquidityEvent,
meta: EventMetadata,
) -> MeteoraDlmmRemoveLiquidityEvent {
MeteoraDlmmRemoveLiquidityEvent {
metadata: meta,
pool: e.pool,
from: e.from,
position: e.position,
amounts: e.amounts,
active_bin_id: e.active_bin_id,
}
}
pub(crate) fn meteora_dlmm_init_pool_from_pb(
e: sol_parser_sdk::core::events::MeteoraDlmmInitializePoolEvent,
meta: EventMetadata,
) -> MeteoraDlmmInitializePoolEvent {
MeteoraDlmmInitializePoolEvent {
metadata: meta,
pool: e.pool,
creator: e.creator,
active_bin_id: e.active_bin_id,
bin_step: e.bin_step,
}
}
pub(crate) fn meteora_dlmm_init_bin_array_from_pb(
e: sol_parser_sdk::core::events::MeteoraDlmmInitializeBinArrayEvent,
meta: EventMetadata,
) -> MeteoraDlmmInitializeBinArrayEvent {
MeteoraDlmmInitializeBinArrayEvent {
metadata: meta,
pool: e.pool,
bin_array: e.bin_array,
index: e.index,
}
}
pub(crate) fn meteora_dlmm_create_position_from_pb(
e: sol_parser_sdk::core::events::MeteoraDlmmCreatePositionEvent,
meta: EventMetadata,
) -> MeteoraDlmmCreatePositionEvent {
MeteoraDlmmCreatePositionEvent {
metadata: meta,
pool: e.pool,
position: e.position,
owner: e.owner,
lower_bin_id: e.lower_bin_id,
width: e.width,
}
}
pub(crate) fn meteora_dlmm_close_position_from_pb(
e: sol_parser_sdk::core::events::MeteoraDlmmClosePositionEvent,
meta: EventMetadata,
) -> MeteoraDlmmClosePositionEvent {
MeteoraDlmmClosePositionEvent {
metadata: meta,
pool: e.pool,
position: e.position,
owner: e.owner,
}
}
pub(crate) fn meteora_dlmm_claim_fee_from_pb(
e: sol_parser_sdk::core::events::MeteoraDlmmClaimFeeEvent,
meta: EventMetadata,
) -> MeteoraDlmmClaimFeeEvent {
MeteoraDlmmClaimFeeEvent {
metadata: meta,
pool: e.pool,
position: e.position,
owner: e.owner,
fee_x: e.fee_x,
fee_y: e.fee_y,
}
}
+299
View File
@@ -0,0 +1,299 @@
//! `sol-parser-sdk` to streamer [`DexEvent`](crate::streaming::event_parser::DexEvent) mapping.
//!
//! The bridge is split by responsibility so the conversion layer stays reviewable.
//!
//! | Module | Responsibility |
//! |------|------|
//! | [`adapt`] | block_time / recv_us alignment with [`EventMetadata`] |
//! | [`program_ids`] | protocol program pubkeys |
//! | [`filter`] | subscribed [`Protocol`](crate::streaming::event_parser::Protocol) checks |
//! | [`pump_pumpswap`] | PumpFun and PumpSwap field mapping |
//! | [`bonk_accounts`] | Bonk plus Token / Nonce / PumpSwap account events |
//! | [`raydium_and_damm`] | Raydium lines and Meteora DAMM v2 |
//! | [`forward_pb`] | Orca / Meteora Pools / Meteora DLMM SDK-shaped events |
//! | [`convert`] | `PbDexEvent` dispatch and batch adaptation |
//! | [`accounts`] | SDK account parser compatibility |
mod accounts;
mod adapt;
mod bonk_accounts;
mod convert;
mod filter;
mod forward_pb;
mod program_ids;
mod pump_pumpswap;
mod raydium_and_damm;
pub(crate) use accounts::{
parse_account_event as parse_sdk_account_event, parse_account_event_for_streamer,
AccountParseResult,
};
pub(crate) use adapt::{block_timestamp_from_stream_meta, fuse_streamer_ix_ctx};
pub(crate) use convert::{adapt_parser_event, adapt_parser_events_list, convert_parser_event};
#[cfg(test)]
mod tests {
use super::filter::event_matches_protocol;
use super::{adapt_parser_event, convert_parser_event};
use crate::streaming::event_parser::common::filter::EventTypeFilter;
use crate::streaming::event_parser::common::types::{EventType, ProtocolType};
use crate::streaming::event_parser::core::account_event_parser::TokenInfoEvent;
use crate::streaming::event_parser::{DexEvent, Protocol};
use sol_parser_sdk::core::events::{
BonkTradeEvent as PbBonkTrade, EventMetadata, MeteoraDlmmSwapEvent as PbDlmmSwap,
OrcaWhirlpoolSwapEvent as PbOrcaSwap, PumpFunTradeEvent as PbPumpTrade,
TokenInfoEvent as PbTokenInfo, TradeDirection as PbBonkDir,
};
use sol_parser_sdk::DexEvent as PbDexEvent;
use solana_sdk::{pubkey::Pubkey, signature::Signature};
#[test]
fn converts_pumpfun_trade_preserving_amounts() {
let mut t = PbPumpTrade::default();
t.metadata = EventMetadata {
signature: Signature::default(),
slot: 42,
tx_index: 7,
block_time_us: 1_000_000,
grpc_recv_us: 88,
recent_blockhash: None,
};
t.mint = Pubkey::new_unique();
t.user = Pubkey::new_unique();
t.sol_amount = 100;
t.token_amount = 200;
t.is_buy = true;
let ev = convert_parser_event(PbDexEvent::PumpFunTrade(t), None, 999).expect("convert");
match ev {
DexEvent::PumpFunTradeEvent(st) => {
assert_eq!(st.metadata.slot, 42);
assert_eq!(st.metadata.recv_us, 999);
assert_eq!(st.sol_amount, 100);
assert_eq!(st.token_amount, 200);
assert!(st.is_buy);
}
_ => panic!("expected PumpFunTradeEvent"),
}
}
#[test]
fn converts_pumpfun_buy_exact_sol_in_preserving_event_type() {
let mut t = PbPumpTrade::default();
t.metadata = EventMetadata::default();
t.is_buy = true;
let ev =
convert_parser_event(PbDexEvent::PumpFunBuyExactSolIn(t), None, 999).expect("convert");
match ev {
DexEvent::PumpFunTradeEvent(st) => {
assert_eq!(st.metadata.event_type, EventType::PumpFunBuyExactSolIn);
assert!(st.is_buy);
}
_ => panic!("expected PumpFunTradeEvent"),
}
}
#[test]
fn protocol_filter_keeps_pumpfun_only_when_requested() {
let mut t = PbPumpTrade::default();
t.metadata = EventMetadata::default();
let dex = convert_parser_event(PbDexEvent::PumpFunTrade(t), None, 0).expect("convert");
assert!(event_matches_protocol(&[Protocol::PumpFun], &dex));
assert!(!event_matches_protocol(&[Protocol::PumpSwap], &dex));
}
#[test]
fn converts_parser_sdk_error_preserves_message() {
let ev = convert_parser_event(PbDexEvent::Error("decode failed".into()), None, 404)
.expect("convert");
match ev {
DexEvent::ParserSdkErrorEvent(e) => {
assert_eq!(e.message, "decode failed");
assert_eq!(e.metadata.recv_us, 404);
assert_eq!(e.metadata.protocol, ProtocolType::Common);
assert_eq!(e.metadata.event_type, EventType::ParserSdkError);
}
_ => panic!("expected ParserSdkErrorEvent"),
}
}
#[test]
fn converts_token_info_preserving_event_type() {
let ev = convert_parser_event(PbDexEvent::TokenInfo(PbTokenInfo::default()), None, 404)
.expect("convert");
match ev {
DexEvent::TokenInfoEvent(e) => {
assert_eq!(e.metadata.event_type, EventType::TokenInfo);
assert_eq!(e.metadata.protocol, ProtocolType::Common);
}
_ => panic!("expected TokenInfoEvent"),
}
}
#[test]
fn protocol_filter_allows_protocol_independent_events() {
let mut token_info = TokenInfoEvent::default();
token_info.metadata.event_type = EventType::TokenInfo;
token_info.metadata.protocol = ProtocolType::Common;
let dex = DexEvent::TokenInfoEvent(token_info);
assert!(event_matches_protocol(&[Protocol::PumpFun], &dex));
assert!(event_matches_protocol(&[Protocol::RaydiumCpmm], &dex));
}
#[test]
fn adapt_token_info_passes_protocol_and_token_account_filter() {
let filter = EventTypeFilter::include_only([EventType::TokenAccount]);
let ev = adapt_parser_event(
PbDexEvent::TokenInfo(PbTokenInfo::default()),
None,
404,
&[Protocol::PumpFun],
Some(&filter),
)
.expect("token info should pass common protocol and token-account filter");
assert!(matches!(ev, DexEvent::TokenInfoEvent(_)));
assert_eq!(ev.metadata().event_type, EventType::TokenInfo);
}
#[test]
fn converts_orca_whirlpool_swap_preserving_amounts() {
let whirlpool = Pubkey::new_unique();
let pb = PbOrcaSwap {
metadata: EventMetadata {
signature: Signature::default(),
slot: 9,
tx_index: 0,
block_time_us: 0,
grpc_recv_us: 0,
recent_blockhash: None,
},
whirlpool,
input_amount: 10,
output_amount: 20,
a_to_b: false,
pre_sqrt_price: 100,
post_sqrt_price: 200,
input_transfer_fee: 1,
output_transfer_fee: 2,
lp_fee: 3,
protocol_fee: 4,
};
let ev =
convert_parser_event(PbDexEvent::OrcaWhirlpoolSwap(pb), None, 111).expect("convert");
match ev {
DexEvent::OrcaWhirlpoolSwapEvent(e) => {
assert_eq!(e.whirlpool, whirlpool);
assert_eq!(e.input_amount, 10);
assert_eq!(e.output_amount, 20);
assert!(!e.a_to_b);
assert_eq!(e.pre_sqrt_price, 100);
assert_eq!(e.post_sqrt_price, 200);
assert_eq!(e.lp_fee, 3);
assert_eq!(e.protocol_fee, 4);
assert_eq!(e.metadata.slot, 9);
assert_eq!(e.metadata.recv_us, 111);
}
_ => panic!("expected OrcaWhirlpoolSwapEvent"),
}
}
#[test]
fn converts_meteora_dlmm_swap_preserving_amounts() {
let pool = Pubkey::new_unique();
let from = Pubkey::new_unique();
let pb = PbDlmmSwap {
metadata: EventMetadata::default(),
pool,
from,
start_bin_id: -5,
end_bin_id: 12,
amount_in: 300,
amount_out: 299,
swap_for_y: true,
fee: 1,
protocol_fee: 2,
fee_bps: 25,
host_fee: 0,
};
let ev = convert_parser_event(PbDexEvent::MeteoraDlmmSwap(pb), None, 0).expect("convert");
match ev {
DexEvent::MeteoraDlmmSwapEvent(e) => {
assert_eq!(e.pool, pool);
assert_eq!(e.from, from);
assert_eq!(e.start_bin_id, -5);
assert_eq!(e.end_bin_id, 12);
assert_eq!(e.amount_in, 300);
assert_eq!(e.amount_out, 299);
assert!(e.swap_for_y);
assert_eq!(e.fee_bps, 25);
}
_ => panic!("expected MeteoraDlmmSwapEvent"),
}
}
#[test]
fn protocol_filter_keeps_orca_only_when_requested() {
let pb = PbOrcaSwap {
metadata: EventMetadata::default(),
whirlpool: Pubkey::new_unique(),
input_amount: 0,
output_amount: 0,
a_to_b: true,
pre_sqrt_price: 0,
post_sqrt_price: 0,
input_transfer_fee: 0,
output_transfer_fee: 0,
lp_fee: 0,
protocol_fee: 0,
};
let dex =
convert_parser_event(PbDexEvent::OrcaWhirlpoolSwap(pb), None, 0).expect("convert");
assert!(event_matches_protocol(&[Protocol::OrcaWhirlpool], &dex));
assert!(!event_matches_protocol(&[Protocol::PumpFun], &dex));
}
#[test]
fn converts_bonk_trade_maps_event_type_buy_exact_in() {
let b = PbBonkTrade {
metadata: EventMetadata::default(),
pool_state: Pubkey::default(),
user: Pubkey::default(),
amount_in: 0,
amount_out: 0,
is_buy: true,
trade_direction: PbBonkDir::Buy,
exact_in: true,
};
let dex = convert_parser_event(PbDexEvent::BonkTrade(b), None, 0).expect("convert");
match dex {
DexEvent::BonkTradeEvent(e) => {
assert_eq!(e.metadata.event_type, EventType::BonkBuyExactIn)
}
_ => panic!("expected BonkTradeEvent"),
}
}
#[test]
fn converts_bonk_trade_maps_event_type_sell_exact_out() {
let b = PbBonkTrade {
metadata: EventMetadata::default(),
pool_state: Pubkey::default(),
user: Pubkey::default(),
amount_in: 0,
amount_out: 0,
is_buy: false,
trade_direction: PbBonkDir::Sell,
exact_in: false,
};
let dex = convert_parser_event(PbDexEvent::BonkTrade(b), None, 0).expect("convert");
match dex {
DexEvent::BonkTradeEvent(e) => {
assert_eq!(e.metadata.event_type, EventType::BonkSellExactOut)
}
_ => panic!("expected BonkTradeEvent"),
}
}
}
@@ -0,0 +1,41 @@
//! Protocol program ids used by bridged events.
use crate::streaming::event_parser::protocols::sol_parser_forward;
use solana_sdk::pubkey::Pubkey;
pub(crate) fn pumpswap_program() -> Pubkey {
crate::streaming::event_parser::protocols::pumpswap::parser::PUMPSWAP_PROGRAM_ID
}
pub(crate) fn pump_program() -> Pubkey {
crate::streaming::event_parser::protocols::pumpfun::parser::PUMPFUN_PROGRAM_ID
}
pub(crate) fn pump_fees_program() -> Pubkey {
sol_parser_sdk::instr::program_ids::PUMP_FEES_PROGRAM_ID
}
pub(crate) fn bonk_program() -> Pubkey {
crate::streaming::event_parser::protocols::bonk::parser::BONK_PROGRAM_ID
}
pub(crate) fn raydium_cpmm_program() -> Pubkey {
crate::streaming::event_parser::protocols::raydium_cpmm::parser::RAYDIUM_CPMM_PROGRAM_ID
}
pub(crate) fn raydium_clmm_program() -> Pubkey {
crate::streaming::event_parser::protocols::raydium_clmm::parser::RAYDIUM_CLMM_PROGRAM_ID
}
pub(crate) fn raydium_amm_v4_program() -> Pubkey {
crate::streaming::event_parser::protocols::raydium_amm_v4::parser::RAYDIUM_AMM_V4_PROGRAM_ID
}
pub(crate) fn meteora_damm_program() -> Pubkey {
crate::streaming::event_parser::protocols::meteora_damm_v2::parser::METEORA_DAMM_V2_PROGRAM_ID
}
pub(crate) fn orca_whirlpool_program() -> Pubkey {
sol_parser_forward::ORCA_WHIRLPOOL_PROGRAM_ID
}
pub(crate) fn meteora_pools_program() -> Pubkey {
sol_parser_forward::METEORA_POOLS_PROGRAM_ID
}
pub(crate) fn meteora_dlmm_program() -> Pubkey {
sol_parser_forward::METEORA_DLMM_PROGRAM_ID
}
@@ -0,0 +1,650 @@
//! PumpFun / PumpSwap field mapping and aggregate trade conversion.
use crate::streaming::event_parser::common::types::{EventType, ProtocolType};
use crate::streaming::event_parser::common::EventMetadata;
use crate::streaming::event_parser::protocols::pumpfun::events::{
PumpFeesConfigStatus, PumpFeesCreateFeeSharingConfigEvent, PumpFeesFeeTier, PumpFeesFees,
PumpFeesInitializeFeeConfigEvent, PumpFeesResetFeeSharingConfigEvent,
PumpFeesRevokeFeeSharingAuthorityEvent, PumpFeesShareholder,
PumpFeesTransferFeeSharingAuthorityEvent, PumpFeesUpdateAdminEvent,
PumpFeesUpdateFeeConfigEvent, PumpFeesUpdateFeeSharesEvent, PumpFeesUpsertFeeTiersEvent,
PumpFunCreateTokenEvent, PumpFunCreateV2TokenEvent, PumpFunGlobalAccountEvent,
PumpFunMigrateBondingCurveCreatorEvent, PumpFunMigrateEvent, PumpFunTradeEvent,
};
use crate::streaming::event_parser::protocols::pumpfun::types::Global;
use crate::streaming::event_parser::protocols::pumpswap::events::{
PumpSwapBuyEvent, PumpSwapCreatePoolEvent, PumpSwapDepositEvent, PumpSwapSellEvent,
PumpSwapWithdrawEvent,
};
use crate::streaming::event_parser::DexEvent;
use prost_types::Timestamp;
use solana_sdk::pubkey::Pubkey;
use super::adapt::adapt_pm;
use super::program_ids::{pump_program, pumpswap_program};
pub(crate) fn pumpfun_create_token_from_parser(
c: sol_parser_sdk::core::events::PumpFunCreateTokenEvent,
meta: EventMetadata,
) -> PumpFunCreateTokenEvent {
PumpFunCreateTokenEvent {
metadata: meta,
name: c.name,
symbol: c.symbol,
uri: c.uri,
mint: c.mint,
bonding_curve: c.bonding_curve,
user: c.user,
creator: c.creator,
timestamp: c.timestamp,
virtual_token_reserves: c.virtual_token_reserves,
virtual_sol_reserves: c.virtual_sol_reserves,
real_token_reserves: c.real_token_reserves,
token_total_supply: c.token_total_supply,
token_program: c.token_program,
is_mayhem_mode: c.is_mayhem_mode,
is_cashback_enabled: c.is_cashback_enabled,
..Default::default()
}
}
pub(crate) fn pumpfun_create_v2_from_parser(
c: sol_parser_sdk::core::events::PumpFunCreateV2TokenEvent,
meta: EventMetadata,
) -> PumpFunCreateV2TokenEvent {
PumpFunCreateV2TokenEvent {
metadata: meta,
name: c.name,
symbol: c.symbol,
uri: c.uri,
mint: c.mint,
bonding_curve: c.bonding_curve,
user: c.user,
creator: c.creator,
timestamp: c.timestamp,
virtual_token_reserves: c.virtual_token_reserves,
virtual_sol_reserves: c.virtual_sol_reserves,
real_token_reserves: c.real_token_reserves,
token_total_supply: c.token_total_supply,
token_program: c.token_program,
is_mayhem_mode: c.is_mayhem_mode,
is_cashback_enabled: c.is_cashback_enabled,
mint_authority: c.mint_authority,
associated_bonding_curve: c.associated_bonding_curve,
global: c.global,
system_program: c.system_program,
associated_token_program: c.associated_token_program,
mayhem_program_id: c.mayhem_program_id,
global_params: c.global_params,
sol_vault: c.sol_vault,
mayhem_state: c.mayhem_state,
mayhem_token_vault: c.mayhem_token_vault,
event_authority: c.event_authority,
program: c.program,
}
}
pub(crate) fn pumpfun_migrate_from_parser(
m: sol_parser_sdk::core::events::PumpFunMigrateEvent,
meta: EventMetadata,
) -> PumpFunMigrateEvent {
PumpFunMigrateEvent {
metadata: meta,
user: m.user,
mint: m.mint,
mint_amount: m.mint_amount,
sol_amount: m.sol_amount,
pool_migration_fee: m.pool_migration_fee,
bonding_curve: m.bonding_curve,
timestamp: m.timestamp,
pool: m.pool,
..Default::default()
}
}
fn pump_fees_status_from_parser(
s: sol_parser_sdk::core::events::PumpFeesConfigStatus,
) -> PumpFeesConfigStatus {
match s {
sol_parser_sdk::core::events::PumpFeesConfigStatus::Paused => PumpFeesConfigStatus::Paused,
sol_parser_sdk::core::events::PumpFeesConfigStatus::Active => PumpFeesConfigStatus::Active,
}
}
fn pump_fees_shareholder_from_parser(
s: sol_parser_sdk::core::events::PumpFeesShareholder,
) -> PumpFeesShareholder {
PumpFeesShareholder { address: s.address, share_bps: s.share_bps }
}
fn pump_fees_fees_from_parser(f: sol_parser_sdk::core::events::PumpFeesFees) -> PumpFeesFees {
PumpFeesFees {
lp_fee_bps: f.lp_fee_bps,
protocol_fee_bps: f.protocol_fee_bps,
creator_fee_bps: f.creator_fee_bps,
}
}
fn pump_fees_tier_from_parser(t: sol_parser_sdk::core::events::PumpFeesFeeTier) -> PumpFeesFeeTier {
PumpFeesFeeTier {
market_cap_lamports_threshold: t.market_cap_lamports_threshold,
fees: pump_fees_fees_from_parser(t.fees),
}
}
pub(crate) fn pump_fees_create_sharing_config_from_parser(
e: sol_parser_sdk::core::events::PumpFeesCreateFeeSharingConfigEvent,
meta: EventMetadata,
) -> PumpFeesCreateFeeSharingConfigEvent {
PumpFeesCreateFeeSharingConfigEvent {
metadata: meta,
timestamp: e.timestamp,
mint: e.mint,
bonding_curve: e.bonding_curve,
pool: e.pool,
sharing_config: e.sharing_config,
admin: e.admin,
initial_shareholders: e
.initial_shareholders
.into_iter()
.map(pump_fees_shareholder_from_parser)
.collect(),
status: pump_fees_status_from_parser(e.status),
}
}
pub(crate) fn pump_fees_initialize_fee_config_from_parser(
e: sol_parser_sdk::core::events::PumpFeesInitializeFeeConfigEvent,
meta: EventMetadata,
) -> PumpFeesInitializeFeeConfigEvent {
PumpFeesInitializeFeeConfigEvent {
metadata: meta,
timestamp: e.timestamp,
admin: e.admin,
fee_config: e.fee_config,
}
}
pub(crate) fn pump_fees_reset_sharing_config_from_parser(
e: sol_parser_sdk::core::events::PumpFeesResetFeeSharingConfigEvent,
meta: EventMetadata,
) -> PumpFeesResetFeeSharingConfigEvent {
PumpFeesResetFeeSharingConfigEvent {
metadata: meta,
timestamp: e.timestamp,
mint: e.mint,
sharing_config: e.sharing_config,
old_admin: e.old_admin,
old_shareholders: e
.old_shareholders
.into_iter()
.map(pump_fees_shareholder_from_parser)
.collect(),
new_admin: e.new_admin,
new_shareholders: e
.new_shareholders
.into_iter()
.map(pump_fees_shareholder_from_parser)
.collect(),
}
}
pub(crate) fn pump_fees_revoke_authority_from_parser(
e: sol_parser_sdk::core::events::PumpFeesRevokeFeeSharingAuthorityEvent,
meta: EventMetadata,
) -> PumpFeesRevokeFeeSharingAuthorityEvent {
PumpFeesRevokeFeeSharingAuthorityEvent {
metadata: meta,
timestamp: e.timestamp,
mint: e.mint,
sharing_config: e.sharing_config,
admin: e.admin,
}
}
pub(crate) fn pump_fees_transfer_authority_from_parser(
e: sol_parser_sdk::core::events::PumpFeesTransferFeeSharingAuthorityEvent,
meta: EventMetadata,
) -> PumpFeesTransferFeeSharingAuthorityEvent {
PumpFeesTransferFeeSharingAuthorityEvent {
metadata: meta,
timestamp: e.timestamp,
mint: e.mint,
sharing_config: e.sharing_config,
old_admin: e.old_admin,
new_admin: e.new_admin,
}
}
pub(crate) fn pump_fees_update_admin_from_parser(
e: sol_parser_sdk::core::events::PumpFeesUpdateAdminEvent,
meta: EventMetadata,
) -> PumpFeesUpdateAdminEvent {
PumpFeesUpdateAdminEvent {
metadata: meta,
timestamp: e.timestamp,
old_admin: e.old_admin,
new_admin: e.new_admin,
}
}
pub(crate) fn pump_fees_update_fee_config_from_parser(
e: sol_parser_sdk::core::events::PumpFeesUpdateFeeConfigEvent,
meta: EventMetadata,
) -> PumpFeesUpdateFeeConfigEvent {
PumpFeesUpdateFeeConfigEvent {
metadata: meta,
timestamp: e.timestamp,
admin: e.admin,
fee_config: e.fee_config,
fee_tiers: e.fee_tiers.into_iter().map(pump_fees_tier_from_parser).collect(),
flat_fees: pump_fees_fees_from_parser(e.flat_fees),
}
}
pub(crate) fn pump_fees_update_fee_shares_from_parser(
e: sol_parser_sdk::core::events::PumpFeesUpdateFeeSharesEvent,
meta: EventMetadata,
) -> PumpFeesUpdateFeeSharesEvent {
PumpFeesUpdateFeeSharesEvent {
metadata: meta,
timestamp: e.timestamp,
mint: e.mint,
sharing_config: e.sharing_config,
admin: e.admin,
bonding_curve: e.bonding_curve,
pump_creator_vault: e.pump_creator_vault,
new_shareholders: e
.new_shareholders
.into_iter()
.map(pump_fees_shareholder_from_parser)
.collect(),
}
}
pub(crate) fn pump_fees_upsert_fee_tiers_from_parser(
e: sol_parser_sdk::core::events::PumpFeesUpsertFeeTiersEvent,
meta: EventMetadata,
) -> PumpFeesUpsertFeeTiersEvent {
PumpFeesUpsertFeeTiersEvent {
metadata: meta,
timestamp: e.timestamp,
admin: e.admin,
fee_config: e.fee_config,
fee_tiers: e.fee_tiers.into_iter().map(pump_fees_tier_from_parser).collect(),
offset: e.offset,
}
}
pub(crate) fn pumpfun_migrate_bonding_creator_from_parser(
e: sol_parser_sdk::core::events::PumpFunMigrateBondingCurveCreatorEvent,
meta: EventMetadata,
) -> PumpFunMigrateBondingCurveCreatorEvent {
PumpFunMigrateBondingCurveCreatorEvent {
metadata: meta,
timestamp: e.timestamp,
mint: e.mint,
bonding_curve: e.bonding_curve,
sharing_config: e.sharing_config,
old_creator: e.old_creator,
new_creator: e.new_creator,
}
}
pub(crate) fn pumpfun_global_account_from_parser(
e: sol_parser_sdk::core::events::PumpFunGlobalAccountEvent,
meta: EventMetadata,
) -> PumpFunGlobalAccountEvent {
let mut fee_recipients = [Pubkey::default(); 7];
for (dst, src) in fee_recipients.iter_mut().zip(e.global.fee_recipients.iter()) {
*dst = *src;
}
PumpFunGlobalAccountEvent {
metadata: meta,
pubkey: e.pubkey,
executable: false,
lamports: 0,
owner: pump_program(),
rent_epoch: 0,
global: Global {
initialized: e.global.initialized,
authority: e.global.authority,
fee_recipient: e.global.fee_recipient,
initial_virtual_token_reserves: e.global.initial_virtual_token_reserves,
initial_virtual_sol_reserves: e.global.initial_virtual_sol_reserves,
initial_real_token_reserves: e.global.initial_real_token_reserves,
token_total_supply: e.global.token_total_supply,
fee_basis_points: e.global.fee_basis_points,
withdraw_authority: e.global.withdraw_authority,
enable_migrate: e.global.enable_migrate,
pool_migration_fee: e.global.pool_migration_fee,
creator_fee_basis_points: e.global.creator_fee_basis_points,
fee_recipients,
set_creator_authority: e.global.set_creator_authority,
admin_set_creator_authority: e.global.admin_set_creator_authority,
create_v2_enabled: e.global.create_v2_enabled,
whitelist_pda: e.global.whitelist_pda,
reserved_fee_recipient: e.global.reserved_fee_recipient,
mayhem_mode_enabled: e.global.mayhem_mode_enabled,
reserved_fee_recipients: e.global.reserved_fee_recipients,
is_cashback_enabled: false,
},
}
}
pub(crate) fn pumpswap_buy_full_from_parser(
b: sol_parser_sdk::core::events::PumpSwapBuyEvent,
meta: EventMetadata,
) -> PumpSwapBuyEvent {
PumpSwapBuyEvent {
metadata: meta,
timestamp: b.timestamp,
base_amount_out: b.base_amount_out,
max_quote_amount_in: b.max_quote_amount_in,
user_base_token_reserves: b.user_base_token_reserves,
user_quote_token_reserves: b.user_quote_token_reserves,
pool_base_token_reserves: b.pool_base_token_reserves,
pool_quote_token_reserves: b.pool_quote_token_reserves,
quote_amount_in: b.quote_amount_in,
lp_fee_basis_points: b.lp_fee_basis_points,
lp_fee: b.lp_fee,
protocol_fee_basis_points: b.protocol_fee_basis_points,
protocol_fee: b.protocol_fee,
quote_amount_in_with_lp_fee: b.quote_amount_in_with_lp_fee,
user_quote_amount_in: b.user_quote_amount_in,
pool: b.pool,
user: b.user,
user_base_token_account: b.user_base_token_account,
user_quote_token_account: b.user_quote_token_account,
protocol_fee_recipient: b.protocol_fee_recipient,
protocol_fee_recipient_token_account: b.protocol_fee_recipient_token_account,
coin_creator: b.coin_creator,
coin_creator_fee_basis_points: b.coin_creator_fee_basis_points,
coin_creator_fee: b.coin_creator_fee,
track_volume: b.track_volume,
total_unclaimed_tokens: b.total_unclaimed_tokens,
total_claimed_tokens: b.total_claimed_tokens,
current_sol_volume: b.current_sol_volume,
last_update_timestamp: b.last_update_timestamp,
min_base_amount_out: b.min_base_amount_out,
ix_name: b.ix_name,
cashback_fee_basis_points: b.cashback_fee_basis_points,
cashback: b.cashback,
is_pump_pool: b.is_pump_pool,
base_mint: b.base_mint,
quote_mint: b.quote_mint,
pool_base_token_account: b.pool_base_token_account,
pool_quote_token_account: b.pool_quote_token_account,
coin_creator_vault_ata: b.coin_creator_vault_ata,
coin_creator_vault_authority: b.coin_creator_vault_authority,
base_token_program: b.base_token_program,
quote_token_program: b.quote_token_program,
}
}
pub(crate) fn pumpswap_sell_full_from_parser(
s: sol_parser_sdk::core::events::PumpSwapSellEvent,
meta: EventMetadata,
) -> PumpSwapSellEvent {
PumpSwapSellEvent {
metadata: meta,
timestamp: s.timestamp,
base_amount_in: s.base_amount_in,
min_quote_amount_out: s.min_quote_amount_out,
user_base_token_reserves: s.user_base_token_reserves,
user_quote_token_reserves: s.user_quote_token_reserves,
pool_base_token_reserves: s.pool_base_token_reserves,
pool_quote_token_reserves: s.pool_quote_token_reserves,
quote_amount_out: s.quote_amount_out,
lp_fee_basis_points: s.lp_fee_basis_points,
lp_fee: s.lp_fee,
protocol_fee_basis_points: s.protocol_fee_basis_points,
protocol_fee: s.protocol_fee,
quote_amount_out_without_lp_fee: s.quote_amount_out_without_lp_fee,
user_quote_amount_out: s.user_quote_amount_out,
pool: s.pool,
user: s.user,
user_base_token_account: s.user_base_token_account,
user_quote_token_account: s.user_quote_token_account,
protocol_fee_recipient: s.protocol_fee_recipient,
protocol_fee_recipient_token_account: s.protocol_fee_recipient_token_account,
coin_creator: s.coin_creator,
coin_creator_fee_basis_points: s.coin_creator_fee_basis_points,
coin_creator_fee: s.coin_creator_fee,
cashback_fee_basis_points: s.cashback_fee_basis_points,
cashback: s.cashback,
is_pump_pool: s.is_pump_pool,
base_mint: s.base_mint,
quote_mint: s.quote_mint,
pool_base_token_account: s.pool_base_token_account,
pool_quote_token_account: s.pool_quote_token_account,
coin_creator_vault_ata: s.coin_creator_vault_ata,
coin_creator_vault_authority: s.coin_creator_vault_authority,
base_token_program: s.base_token_program,
quote_token_program: s.quote_token_program,
}
}
pub(crate) fn pumpswap_create_pool_from_parser(
c: sol_parser_sdk::core::events::PumpSwapCreatePoolEvent,
meta: EventMetadata,
) -> PumpSwapCreatePoolEvent {
PumpSwapCreatePoolEvent {
metadata: meta,
timestamp: c.timestamp,
index: c.index,
creator: c.creator,
base_mint: c.base_mint,
quote_mint: c.quote_mint,
base_mint_decimals: c.base_mint_decimals,
quote_mint_decimals: c.quote_mint_decimals,
base_amount_in: c.base_amount_in,
quote_amount_in: c.quote_amount_in,
pool_base_amount: c.pool_base_amount,
pool_quote_amount: c.pool_quote_amount,
minimum_liquidity: c.minimum_liquidity,
initial_liquidity: c.initial_liquidity,
lp_token_amount_out: c.lp_token_amount_out,
pool_bump: c.pool_bump,
pool: c.pool,
lp_mint: c.lp_mint,
user_base_token_account: c.user_base_token_account,
user_quote_token_account: c.user_quote_token_account,
coin_creator: c.coin_creator,
..Default::default()
}
}
pub(crate) fn pumpswap_liquidity_added_to_deposit(
a: sol_parser_sdk::core::events::PumpSwapLiquidityAdded,
meta: EventMetadata,
) -> PumpSwapDepositEvent {
PumpSwapDepositEvent {
metadata: meta,
timestamp: a.timestamp,
lp_token_amount_out: a.lp_token_amount_out,
max_base_amount_in: a.max_base_amount_in,
max_quote_amount_in: a.max_quote_amount_in,
user_base_token_reserves: a.user_base_token_reserves,
user_quote_token_reserves: a.user_quote_token_reserves,
pool_base_token_reserves: a.pool_base_token_reserves,
pool_quote_token_reserves: a.pool_quote_token_reserves,
base_amount_in: a.base_amount_in,
quote_amount_in: a.quote_amount_in,
lp_mint_supply: a.lp_mint_supply,
pool: a.pool,
user: a.user,
user_base_token_account: a.user_base_token_account,
user_quote_token_account: a.user_quote_token_account,
user_pool_token_account: a.user_pool_token_account,
..Default::default()
}
}
pub(crate) fn pumpswap_liquidity_removed_to_withdraw(
r: sol_parser_sdk::core::events::PumpSwapLiquidityRemoved,
meta: EventMetadata,
) -> PumpSwapWithdrawEvent {
PumpSwapWithdrawEvent {
metadata: meta,
timestamp: r.timestamp,
lp_token_amount_in: r.lp_token_amount_in,
min_base_amount_out: r.min_base_amount_out,
min_quote_amount_out: r.min_quote_amount_out,
user_base_token_reserves: r.user_base_token_reserves,
user_quote_token_reserves: r.user_quote_token_reserves,
pool_base_token_reserves: r.pool_base_token_reserves,
pool_quote_token_reserves: r.pool_quote_token_reserves,
base_amount_out: r.base_amount_out,
quote_amount_out: r.quote_amount_out,
lp_mint_supply: r.lp_mint_supply,
pool: r.pool,
user: r.user,
user_base_token_account: r.user_base_token_account,
user_quote_token_account: r.user_quote_token_account,
user_pool_token_account: r.user_pool_token_account,
..Default::default()
}
}
pub(crate) fn pumpfun_trade_from_parser(
t: sol_parser_sdk::core::events::PumpFunTradeEvent,
bt: Option<&Timestamp>,
recv_wall_us: i64,
) -> DexEvent {
let event_type = if t.is_buy { EventType::PumpFunBuy } else { EventType::PumpFunSell };
pumpfun_trade_from_parser_with_event_type(t, bt, recv_wall_us, event_type)
}
pub(crate) fn pumpfun_trade_from_parser_with_event_type(
t: sol_parser_sdk::core::events::PumpFunTradeEvent,
bt: Option<&Timestamp>,
recv_wall_us: i64,
event_type: EventType,
) -> DexEvent {
let pm = t.metadata.clone();
let meta = adapt_pm(pm, bt, recv_wall_us, ProtocolType::PumpFun, event_type, pump_program());
let st = PumpFunTradeEvent {
metadata: meta,
mint: t.mint,
sol_amount: t.sol_amount,
token_amount: t.token_amount,
is_buy: t.is_buy,
user: t.user,
timestamp: t.timestamp,
virtual_sol_reserves: t.virtual_sol_reserves,
virtual_token_reserves: t.virtual_token_reserves,
real_sol_reserves: t.real_sol_reserves,
real_token_reserves: t.real_token_reserves,
fee_recipient: t.fee_recipient,
fee_basis_points: t.fee_basis_points,
fee: t.fee,
creator: t.creator,
creator_fee_basis_points: t.creator_fee_basis_points,
creator_fee: t.creator_fee,
track_volume: t.track_volume,
total_unclaimed_tokens: t.total_unclaimed_tokens,
total_claimed_tokens: t.total_claimed_tokens,
current_sol_volume: t.current_sol_volume,
last_update_timestamp: t.last_update_timestamp,
bonding_curve: t.bonding_curve,
associated_bonding_curve: t.associated_bonding_curve,
token_program: t.token_program,
creator_vault: t.creator_vault,
account: t.account,
ix_name: t.ix_name,
mayhem_mode: t.mayhem_mode,
cashback_fee_basis_points: t.cashback_fee_basis_points,
cashback: t.cashback,
is_cashback_coin: t.is_cashback_coin,
..Default::default()
};
DexEvent::PumpFunTradeEvent(st)
}
pub(crate) fn pumpswap_trade_from_parser(
t: sol_parser_sdk::core::events::PumpSwapTradeEvent,
bt: Option<&Timestamp>,
recv_wall_us: i64,
) -> Option<DexEvent> {
let pm = t.metadata.clone();
let meta = adapt_pm(
pm,
bt,
recv_wall_us,
ProtocolType::PumpSwap,
if t.is_buy { EventType::PumpSwapBuy } else { EventType::PumpSwapSell },
pumpswap_program(),
);
if t.is_buy {
Some(DexEvent::PumpSwapBuyEvent(PumpSwapBuyEvent {
metadata: meta,
timestamp: t.timestamp,
base_amount_out: t.token_amount,
max_quote_amount_in: t.sol_amount,
user_base_token_reserves: t.virtual_token_reserves,
user_quote_token_reserves: t.virtual_sol_reserves,
pool_base_token_reserves: t.real_token_reserves,
pool_quote_token_reserves: t.real_sol_reserves,
quote_amount_in: t.sol_amount,
lp_fee_basis_points: t.fee_basis_points,
lp_fee: t.fee,
protocol_fee_basis_points: 0,
protocol_fee: 0,
quote_amount_in_with_lp_fee: t.sol_amount,
user_quote_amount_in: t.sol_amount,
pool: Pubkey::default(),
user: t.user,
user_base_token_account: Pubkey::default(),
user_quote_token_account: Pubkey::default(),
protocol_fee_recipient: t.fee_recipient,
protocol_fee_recipient_token_account: Pubkey::default(),
coin_creator: t.creator,
coin_creator_fee_basis_points: t.creator_fee_basis_points,
coin_creator_fee: t.creator_fee,
track_volume: t.track_volume,
total_unclaimed_tokens: t.total_unclaimed_tokens,
total_claimed_tokens: t.total_claimed_tokens,
current_sol_volume: t.current_sol_volume,
last_update_timestamp: t.last_update_timestamp,
min_base_amount_out: 0,
ix_name: t.ix_name.clone(),
cashback_fee_basis_points: 0,
cashback: 0,
is_pump_pool: false,
base_mint: t.mint,
..Default::default()
}))
} else {
Some(DexEvent::PumpSwapSellEvent(PumpSwapSellEvent {
metadata: meta,
timestamp: t.timestamp,
base_amount_in: t.token_amount,
min_quote_amount_out: t.sol_amount,
user_base_token_reserves: t.virtual_token_reserves,
user_quote_token_reserves: t.virtual_sol_reserves,
pool_base_token_reserves: t.real_token_reserves,
pool_quote_token_reserves: t.real_sol_reserves,
quote_amount_out: t.sol_amount,
lp_fee_basis_points: t.fee_basis_points,
lp_fee: t.fee,
protocol_fee_basis_points: 0,
protocol_fee: 0,
quote_amount_out_without_lp_fee: t.sol_amount,
user_quote_amount_out: t.sol_amount,
pool: Pubkey::default(),
user: t.user,
user_base_token_account: Pubkey::default(),
user_quote_token_account: Pubkey::default(),
protocol_fee_recipient: t.fee_recipient,
protocol_fee_recipient_token_account: Pubkey::default(),
coin_creator: t.creator,
coin_creator_fee_basis_points: t.creator_fee_basis_points,
coin_creator_fee: t.creator_fee,
cashback_fee_basis_points: 0,
cashback: 0,
is_pump_pool: false,
base_mint: t.mint,
..Default::default()
}))
}
}
@@ -0,0 +1,496 @@
//! Raydium CPMM / CLMM / AMM V4 and Meteora DAMM v2 mapping.
use crate::streaming::event_parser::common::EventMetadata;
use crate::streaming::event_parser::protocols::meteora_damm_v2::events::{
MeteoraDammV2AddLiquidityEvent, MeteoraDammV2ClosePositionEvent,
MeteoraDammV2CreatePositionEvent, MeteoraDammV2RemoveLiquidityEvent, MeteoraDammV2SwapEvent,
};
use crate::streaming::event_parser::protocols::raydium_amm_v4::events::{
RaydiumAmmV4DepositEvent, RaydiumAmmV4Initialize2Event, RaydiumAmmV4SwapEvent,
RaydiumAmmV4WithdrawEvent, RaydiumAmmV4WithdrawPnlEvent,
};
use crate::streaming::event_parser::protocols::raydium_clmm::events::{
RaydiumClmmClosePositionEvent, RaydiumClmmCollectFeeEvent, RaydiumClmmCreatePoolEvent,
RaydiumClmmDecreaseLiquidityV2Event, RaydiumClmmIncreaseLiquidityV2Event,
RaydiumClmmOpenPositionV2Event, RaydiumClmmOpenPositionWithToken22NftEvent,
RaydiumClmmSwapEvent,
};
use crate::streaming::event_parser::protocols::raydium_cpmm::events::{
RaydiumCpmmDepositEvent, RaydiumCpmmInitializeEvent, RaydiumCpmmSwapEvent,
RaydiumCpmmWithdrawEvent,
};
use solana_sdk::pubkey::Pubkey;
pub(crate) fn meteora_damm_v2_swap_from_parser(
e: sol_parser_sdk::core::events::MeteoraDammV2SwapEvent,
meta: EventMetadata,
) -> MeteoraDammV2SwapEvent {
MeteoraDammV2SwapEvent {
metadata: meta,
pool: e.pool,
trade_direction: e.trade_direction,
collect_fee_mode: 0,
has_referral: e.has_referral,
amount_0: e.amount_in,
amount_1: 0,
swap_mode: 0,
included_fee_input_amount: e.actual_amount_in,
excluded_fee_input_amount: e.amount_in,
amount_left: 0,
output_amount: e.output_amount,
next_sqrt_price: e.next_sqrt_price,
trading_fee: e.lp_fee,
protocol_fee: e.protocol_fee,
partner_fee: e.partner_fee,
referral_fee: e.referral_fee,
included_transfer_fee_amount_in: 0,
included_transfer_fee_amount_out: 0,
excluded_transfer_fee_amount_out: 0,
current_timestamp: e.current_timestamp,
reserve_a_amount: 0,
reserve_b_amount: 0,
pool_authority: Pubkey::default(),
input_token_account: Pubkey::default(),
output_token_account: Pubkey::default(),
token_a_vault: e.token_a_vault,
token_b_vault: e.token_b_vault,
token_a_mint: e.token_a_mint,
token_b_mint: e.token_b_mint,
payer: Pubkey::default(),
token_a_program: e.token_a_program,
token_b_program: e.token_b_program,
referral_token_account: None,
event_authority: Pubkey::default(),
program: Pubkey::default(),
}
}
pub(crate) fn raydium_cpmm_swap_from_parser(
e: sol_parser_sdk::core::events::RaydiumCpmmSwapEvent,
meta: EventMetadata,
) -> RaydiumCpmmSwapEvent {
RaydiumCpmmSwapEvent {
metadata: meta,
amount_in: e.input_amount,
minimum_amount_out: 0,
max_amount_in: e.input_amount,
amount_out: e.output_amount,
payer: Pubkey::default(),
authority: Pubkey::default(),
amm_config: Pubkey::default(),
pool_state: e.pool_id,
input_token_account: Pubkey::default(),
output_token_account: Pubkey::default(),
input_vault: Pubkey::default(),
output_vault: Pubkey::default(),
input_token_program: Pubkey::default(),
output_token_program: Pubkey::default(),
input_token_mint: Pubkey::default(),
output_token_mint: Pubkey::default(),
observation_state: Pubkey::default(),
}
}
pub(crate) fn raydium_cpmm_deposit_from_parser(
e: sol_parser_sdk::core::events::RaydiumCpmmDepositEvent,
meta: EventMetadata,
) -> RaydiumCpmmDepositEvent {
RaydiumCpmmDepositEvent {
metadata: meta,
lp_token_amount: e.lp_token_amount,
maximum_token0_amount: e.token0_amount,
maximum_token1_amount: e.token1_amount,
owner: e.user,
authority: Pubkey::default(),
pool_state: e.pool,
owner_lp_token: Pubkey::default(),
token_0_account: Pubkey::default(),
token_1_account: Pubkey::default(),
token_0_vault: Pubkey::default(),
token_1_vault: Pubkey::default(),
token_program: Pubkey::default(),
token_program2022: Pubkey::default(),
vault_0_mint: Pubkey::default(),
vault_1_mint: Pubkey::default(),
lp_mint: Pubkey::default(),
}
}
pub(crate) fn raydium_cpmm_withdraw_from_parser(
e: sol_parser_sdk::core::events::RaydiumCpmmWithdrawEvent,
meta: EventMetadata,
) -> RaydiumCpmmWithdrawEvent {
RaydiumCpmmWithdrawEvent {
metadata: meta,
lp_token_amount: e.lp_token_amount,
minimum_token0_amount: e.token0_amount,
minimum_token1_amount: e.token1_amount,
owner: e.user,
authority: Pubkey::default(),
pool_state: e.pool,
owner_lp_token: Pubkey::default(),
token_0_account: Pubkey::default(),
token_1_account: Pubkey::default(),
token_0_vault: Pubkey::default(),
token_1_vault: Pubkey::default(),
token_program: Pubkey::default(),
token_program2022: Pubkey::default(),
vault_0_mint: Pubkey::default(),
vault_1_mint: Pubkey::default(),
lp_mint: Pubkey::default(),
memo_program: Pubkey::default(),
}
}
pub(crate) fn raydium_cpmm_initialize_from_parser(
e: sol_parser_sdk::core::events::RaydiumCpmmInitializeEvent,
meta: EventMetadata,
) -> RaydiumCpmmInitializeEvent {
RaydiumCpmmInitializeEvent {
metadata: meta,
init_amount0: e.init_amount0,
init_amount1: e.init_amount1,
open_time: 0,
creator: e.creator,
pool_state: e.pool,
..Default::default()
}
}
pub(crate) fn raydium_amm_v4_swap_from_parser(
e: sol_parser_sdk::core::events::RaydiumAmmV4SwapEvent,
meta: EventMetadata,
) -> RaydiumAmmV4SwapEvent {
RaydiumAmmV4SwapEvent {
metadata: meta,
amount_in: e.amount_in,
minimum_amount_out: e.minimum_amount_out,
max_amount_in: e.max_amount_in,
amount_out: e.amount_out,
token_program: e.token_program,
amm: e.amm,
amm_authority: e.amm_authority,
amm_open_orders: e.amm_open_orders,
amm_target_orders: e.amm_target_orders,
pool_coin_token_account: e.pool_coin_token_account,
pool_pc_token_account: e.pool_pc_token_account,
serum_program: e.serum_program,
serum_market: e.serum_market,
serum_bids: e.serum_bids,
serum_asks: e.serum_asks,
serum_event_queue: e.serum_event_queue,
serum_coin_vault_account: e.serum_coin_vault_account,
serum_pc_vault_account: e.serum_pc_vault_account,
serum_vault_signer: e.serum_vault_signer,
user_source_token_account: e.user_source_token_account,
user_destination_token_account: e.user_destination_token_account,
user_source_owner: e.user_source_owner,
}
}
pub(crate) fn raydium_amm_v4_deposit_from_parser(
e: sol_parser_sdk::core::events::RaydiumAmmV4DepositEvent,
meta: EventMetadata,
) -> RaydiumAmmV4DepositEvent {
RaydiumAmmV4DepositEvent {
metadata: meta,
max_coin_amount: e.max_coin_amount,
max_pc_amount: e.max_pc_amount,
base_side: e.base_side,
token_program: e.token_program,
amm: e.amm,
amm_authority: e.amm_authority,
amm_open_orders: e.amm_open_orders,
amm_target_orders: e.amm_target_orders,
lp_mint_address: e.lp_mint_address,
pool_coin_token_account: e.pool_coin_token_account,
pool_pc_token_account: e.pool_pc_token_account,
serum_market: e.serum_market,
user_coin_token_account: e.user_coin_token_account,
user_pc_token_account: e.user_pc_token_account,
user_lp_token_account: e.user_lp_token_account,
user_owner: e.user_owner,
serum_event_queue: e.serum_event_queue,
}
}
pub(crate) fn raydium_amm_v4_withdraw_from_parser(
e: sol_parser_sdk::core::events::RaydiumAmmV4WithdrawEvent,
meta: EventMetadata,
) -> RaydiumAmmV4WithdrawEvent {
RaydiumAmmV4WithdrawEvent {
metadata: meta,
amount: e.amount,
token_program: e.token_program,
amm: e.amm,
amm_authority: e.amm_authority,
amm_open_orders: e.amm_open_orders,
amm_target_orders: e.amm_target_orders,
lp_mint_address: e.lp_mint_address,
pool_coin_token_account: e.pool_coin_token_account,
pool_pc_token_account: e.pool_pc_token_account,
pool_withdraw_queue: e.pool_withdraw_queue,
pool_temp_lp_token_account: e.pool_temp_lp_token_account,
serum_program: e.serum_program,
serum_market: e.serum_market,
serum_coin_vault_account: e.serum_coin_vault_account,
serum_pc_vault_account: e.serum_pc_vault_account,
serum_vault_signer: e.serum_vault_signer,
user_lp_token_account: e.user_lp_token_account,
user_coin_token_account: e.user_coin_token_account,
user_pc_token_account: e.user_pc_token_account,
user_owner: e.user_owner,
serum_event_queue: e.serum_event_queue,
serum_bids: e.serum_bids,
serum_asks: e.serum_asks,
}
}
pub(crate) fn raydium_amm_v4_withdraw_pnl_from_parser(
e: sol_parser_sdk::core::events::RaydiumAmmV4WithdrawPnlEvent,
meta: EventMetadata,
) -> RaydiumAmmV4WithdrawPnlEvent {
RaydiumAmmV4WithdrawPnlEvent {
metadata: meta,
token_program: e.token_program,
amm: e.amm,
amm_config: e.amm_config,
amm_authority: e.amm_authority,
amm_open_orders: e.amm_open_orders,
pool_coin_token_account: e.pool_coin_token_account,
pool_pc_token_account: e.pool_pc_token_account,
coin_pnl_token_account: e.coin_pnl_token_account,
pc_pnl_token_account: e.pc_pnl_token_account,
pnl_owner_account: e.pnl_owner,
amm_target_orders: e.amm_target_orders,
serum_program: e.serum_program,
serum_market: e.serum_market,
serum_event_queue: e.serum_event_queue,
serum_coin_vault_account: e.serum_coin_vault_account,
serum_pc_vault_account: e.serum_pc_vault_account,
serum_vault_signer: e.serum_vault_signer,
}
}
pub(crate) fn raydium_amm_v4_initialize2_from_parser(
e: sol_parser_sdk::core::events::RaydiumAmmV4Initialize2Event,
meta: EventMetadata,
) -> RaydiumAmmV4Initialize2Event {
RaydiumAmmV4Initialize2Event {
metadata: meta,
nonce: e.nonce,
open_time: e.open_time,
init_pc_amount: e.init_pc_amount,
init_coin_amount: e.init_coin_amount,
token_program: e.token_program,
spl_associated_token_account: e.spl_associated_token_account,
system_program: e.system_program,
rent: e.rent,
amm: e.amm,
amm_authority: e.amm_authority,
amm_open_orders: e.amm_open_orders,
lp_mint: e.lp_mint,
coin_mint: e.coin_mint,
pc_mint: e.pc_mint,
pool_coin_token_account: e.pool_coin_token_account,
pool_pc_token_account: e.pool_pc_token_account,
pool_withdraw_queue: e.pool_withdraw_queue,
amm_target_orders: e.amm_target_orders,
pool_temp_lp: e.pool_temp_lp,
serum_program: e.serum_program,
serum_market: e.serum_market,
user_wallet: e.user_wallet,
user_token_coin: e.user_token_coin,
user_token_pc: e.user_token_pc,
user_lp_token_account: e.user_lp_token_account,
}
}
pub(crate) fn raydium_clmm_swap_from_parser(
e: sol_parser_sdk::core::events::RaydiumClmmSwapEvent,
meta: EventMetadata,
) -> RaydiumClmmSwapEvent {
let (amount, other_amount_threshold, input_token_account, output_token_account) =
if e.zero_for_one {
(e.amount_0, e.amount_1, e.token_account_0, e.token_account_1)
} else {
(e.amount_1, e.amount_0, e.token_account_1, e.token_account_0)
};
RaydiumClmmSwapEvent {
metadata: meta,
amount,
other_amount_threshold,
sqrt_price_limit_x64: e.sqrt_price_x64,
is_base_input: e.zero_for_one,
payer: e.sender,
pool_state: e.pool_state,
input_token_account,
output_token_account,
..Default::default()
}
}
pub(crate) fn raydium_clmm_create_pool_from_parser(
e: sol_parser_sdk::core::events::RaydiumClmmCreatePoolEvent,
meta: EventMetadata,
) -> RaydiumClmmCreatePoolEvent {
RaydiumClmmCreatePoolEvent {
metadata: meta,
sqrt_price_x64: e.sqrt_price_x64,
open_time: e.open_time,
pool_creator: e.creator,
pool_state: e.pool,
token_mint0: e.token_0_mint,
token_mint1: e.token_1_mint,
..Default::default()
}
}
pub(crate) fn raydium_clmm_open_position_v2_from_parser(
e: sol_parser_sdk::core::events::RaydiumClmmOpenPositionEvent,
meta: EventMetadata,
) -> RaydiumClmmOpenPositionV2Event {
RaydiumClmmOpenPositionV2Event {
metadata: meta,
tick_lower_index: e.tick_lower_index,
tick_upper_index: e.tick_upper_index,
liquidity: e.liquidity,
payer: e.user,
position_nft_owner: e.user,
position_nft_mint: e.position_nft_mint,
pool_state: e.pool,
..Default::default()
}
}
pub(crate) fn raydium_clmm_open_position_token22_from_parser(
e: sol_parser_sdk::core::events::RaydiumClmmOpenPositionWithTokenExtNftEvent,
meta: EventMetadata,
) -> RaydiumClmmOpenPositionWithToken22NftEvent {
RaydiumClmmOpenPositionWithToken22NftEvent {
metadata: meta,
tick_lower_index: e.tick_lower_index,
tick_upper_index: e.tick_upper_index,
liquidity: e.liquidity,
payer: e.user,
position_nft_owner: e.user,
position_nft_mint: e.position_nft_mint,
pool_state: e.pool,
..Default::default()
}
}
pub(crate) fn raydium_clmm_close_position_from_parser(
e: sol_parser_sdk::core::events::RaydiumClmmClosePositionEvent,
meta: EventMetadata,
) -> RaydiumClmmClosePositionEvent {
RaydiumClmmClosePositionEvent {
metadata: meta,
nft_owner: e.user,
position_nft_mint: e.position_nft_mint,
..Default::default()
}
}
pub(crate) fn raydium_clmm_increase_liquidity_v2_from_parser(
e: sol_parser_sdk::core::events::RaydiumClmmIncreaseLiquidityEvent,
meta: EventMetadata,
) -> RaydiumClmmIncreaseLiquidityV2Event {
RaydiumClmmIncreaseLiquidityV2Event {
metadata: meta,
liquidity: e.liquidity,
amount0_max: e.amount0_max,
amount1_max: e.amount1_max,
nft_owner: e.user,
pool_state: e.pool,
..Default::default()
}
}
pub(crate) fn raydium_clmm_decrease_liquidity_v2_from_parser(
e: sol_parser_sdk::core::events::RaydiumClmmDecreaseLiquidityEvent,
meta: EventMetadata,
) -> RaydiumClmmDecreaseLiquidityV2Event {
RaydiumClmmDecreaseLiquidityV2Event {
metadata: meta,
liquidity: e.liquidity,
amount0_min: e.amount0_min,
amount1_min: e.amount1_min,
nft_owner: e.user,
pool_state: e.pool,
..Default::default()
}
}
pub(crate) fn raydium_clmm_collect_fee_from_parser(
e: sol_parser_sdk::core::events::RaydiumClmmCollectFeeEvent,
meta: EventMetadata,
) -> RaydiumClmmCollectFeeEvent {
RaydiumClmmCollectFeeEvent {
metadata: meta,
pool_state: e.pool_state,
position_nft_mint: e.position_nft_mint,
amount_0: e.amount_0,
amount_1: e.amount_1,
}
}
pub(crate) fn meteora_damm_v2_add_liquidity_from_pb(
e: sol_parser_sdk::core::events::MeteoraDammV2AddLiquidityEvent,
meta: EventMetadata,
) -> MeteoraDammV2AddLiquidityEvent {
MeteoraDammV2AddLiquidityEvent {
metadata: meta,
pool: e.pool,
position: e.position,
owner: e.owner,
token_a_amount: e.token_a_amount,
token_b_amount: e.token_b_amount,
liquidity_delta: e.liquidity_delta,
token_a_amount_threshold: e.token_a_amount_threshold,
token_b_amount_threshold: e.token_b_amount_threshold,
total_amount_a: e.total_amount_a,
total_amount_b: e.total_amount_b,
}
}
pub(crate) fn meteora_damm_v2_remove_liquidity_from_pb(
e: sol_parser_sdk::core::events::MeteoraDammV2RemoveLiquidityEvent,
meta: EventMetadata,
) -> MeteoraDammV2RemoveLiquidityEvent {
MeteoraDammV2RemoveLiquidityEvent {
metadata: meta,
pool: e.pool,
position: e.position,
owner: e.owner,
token_a_amount: e.token_a_amount,
token_b_amount: e.token_b_amount,
liquidity_delta: e.liquidity_delta,
token_a_amount_threshold: e.token_a_amount_threshold,
token_b_amount_threshold: e.token_b_amount_threshold,
}
}
pub(crate) fn meteora_damm_v2_create_position_from_pb(
e: sol_parser_sdk::core::events::MeteoraDammV2CreatePositionEvent,
meta: EventMetadata,
) -> MeteoraDammV2CreatePositionEvent {
MeteoraDammV2CreatePositionEvent {
metadata: meta,
pool: e.pool,
owner: e.owner,
position: e.position,
position_nft_mint: e.position_nft_mint,
}
}
pub(crate) fn meteora_damm_v2_close_position_from_pb(
e: sol_parser_sdk::core::events::MeteoraDammV2ClosePositionEvent,
meta: EventMetadata,
) -> MeteoraDammV2ClosePositionEvent {
MeteoraDammV2ClosePositionEvent {
metadata: meta,
pool: e.pool,
owner: e.owner,
position: e.position,
position_nft_mint: e.position_nft_mint,
}
}