mirror of
https://github.com/0xfnzero/solana-streamer.git
synced 2026-08-17 02:48:05 +00:00
refactor: replace static CONFIGS with dynamic event dispatcher
This commit is contained in:
@@ -1,8 +1,7 @@
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
|
||||
use crate::streaming::event_parser::{
|
||||
common::{utils::*, EventMetadata, EventType, ProtocolType},
|
||||
core::GenericEventParseConfig,
|
||||
common::{utils::*, EventMetadata, EventType},
|
||||
protocols::bonk::{
|
||||
bonk_pool_create_event_log_decode, bonk_trade_event_log_decode, discriminators, AmmFeeOn,
|
||||
BonkMigrateToAmmEvent, BonkMigrateToCpswapEvent, BonkPoolCreateEvent, BonkTradeEvent,
|
||||
@@ -16,104 +15,95 @@ use crate::streaming::event_parser::{
|
||||
pub const BONK_PROGRAM_ID: Pubkey =
|
||||
solana_sdk::pubkey!("LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj");
|
||||
|
||||
// Configure all event types
|
||||
pub const CONFIGS: &[GenericEventParseConfig] = &[
|
||||
GenericEventParseConfig {
|
||||
program_id: BONK_PROGRAM_ID,
|
||||
protocol_type: ProtocolType::Bonk,
|
||||
inner_instruction_discriminator: discriminators::TRADE_EVENT,
|
||||
instruction_discriminator: discriminators::BUY_EXACT_IN,
|
||||
event_type: EventType::BonkBuyExactIn,
|
||||
inner_instruction_parser: Some(parse_trade_inner_instruction),
|
||||
instruction_parser: Some(parse_buy_exact_in_instruction),
|
||||
requires_inner_instruction: false,
|
||||
},
|
||||
GenericEventParseConfig {
|
||||
program_id: BONK_PROGRAM_ID,
|
||||
protocol_type: ProtocolType::Bonk,
|
||||
inner_instruction_discriminator: discriminators::TRADE_EVENT,
|
||||
instruction_discriminator: discriminators::BUY_EXACT_OUT,
|
||||
event_type: EventType::BonkBuyExactOut,
|
||||
inner_instruction_parser: Some(parse_trade_inner_instruction),
|
||||
instruction_parser: Some(parse_buy_exact_out_instruction),
|
||||
requires_inner_instruction: false,
|
||||
},
|
||||
GenericEventParseConfig {
|
||||
program_id: BONK_PROGRAM_ID,
|
||||
protocol_type: ProtocolType::Bonk,
|
||||
inner_instruction_discriminator: discriminators::TRADE_EVENT,
|
||||
instruction_discriminator: discriminators::SELL_EXACT_IN,
|
||||
event_type: EventType::BonkSellExactIn,
|
||||
inner_instruction_parser: Some(parse_trade_inner_instruction),
|
||||
instruction_parser: Some(parse_sell_exact_in_instruction),
|
||||
requires_inner_instruction: false,
|
||||
},
|
||||
GenericEventParseConfig {
|
||||
program_id: BONK_PROGRAM_ID,
|
||||
protocol_type: ProtocolType::Bonk,
|
||||
inner_instruction_discriminator: discriminators::TRADE_EVENT,
|
||||
instruction_discriminator: discriminators::SELL_EXACT_OUT,
|
||||
event_type: EventType::BonkSellExactOut,
|
||||
inner_instruction_parser: Some(parse_trade_inner_instruction),
|
||||
instruction_parser: Some(parse_sell_exact_out_instruction),
|
||||
requires_inner_instruction: false,
|
||||
},
|
||||
GenericEventParseConfig {
|
||||
program_id: BONK_PROGRAM_ID,
|
||||
protocol_type: ProtocolType::Bonk,
|
||||
inner_instruction_discriminator: discriminators::POOL_CREATE_EVENT,
|
||||
instruction_discriminator: discriminators::INITIALIZE,
|
||||
event_type: EventType::BonkInitialize,
|
||||
inner_instruction_parser: Some(parse_pool_create_inner_instruction),
|
||||
instruction_parser: Some(parse_initialize_instruction),
|
||||
requires_inner_instruction: false,
|
||||
},
|
||||
GenericEventParseConfig {
|
||||
program_id: BONK_PROGRAM_ID,
|
||||
protocol_type: ProtocolType::Bonk,
|
||||
inner_instruction_discriminator: discriminators::POOL_CREATE_EVENT,
|
||||
instruction_discriminator: discriminators::INITIALIZE_V2,
|
||||
event_type: EventType::BonkInitializeV2,
|
||||
inner_instruction_parser: Some(parse_pool_create_inner_instruction),
|
||||
instruction_parser: Some(parse_initialize_v2_instruction),
|
||||
requires_inner_instruction: false,
|
||||
},
|
||||
GenericEventParseConfig {
|
||||
program_id: BONK_PROGRAM_ID,
|
||||
protocol_type: ProtocolType::Bonk,
|
||||
inner_instruction_discriminator: discriminators::POOL_CREATE_EVENT,
|
||||
instruction_discriminator: discriminators::INITIALIZE_WITH_TOKEN_2022,
|
||||
event_type: EventType::BonkInitializeWithToken2022,
|
||||
inner_instruction_parser: Some(parse_pool_create_inner_instruction),
|
||||
instruction_parser: Some(parse_initialize_with_token_2022_instruction),
|
||||
requires_inner_instruction: false,
|
||||
},
|
||||
GenericEventParseConfig {
|
||||
program_id: BONK_PROGRAM_ID,
|
||||
protocol_type: ProtocolType::Bonk,
|
||||
inner_instruction_discriminator: &[],
|
||||
instruction_discriminator: discriminators::MIGRATE_TO_AMM,
|
||||
event_type: EventType::BonkMigrateToAmm,
|
||||
inner_instruction_parser: None,
|
||||
instruction_parser: Some(parse_migrate_to_amm_instruction),
|
||||
requires_inner_instruction: false,
|
||||
},
|
||||
GenericEventParseConfig {
|
||||
program_id: BONK_PROGRAM_ID,
|
||||
protocol_type: ProtocolType::Bonk,
|
||||
inner_instruction_discriminator: &[],
|
||||
instruction_discriminator: discriminators::MIGRATE_TO_CP_SWAP,
|
||||
event_type: EventType::BonkMigrateToCpswap,
|
||||
inner_instruction_parser: None,
|
||||
instruction_parser: Some(parse_migrate_to_cpswap_instruction),
|
||||
requires_inner_instruction: false,
|
||||
},
|
||||
];
|
||||
/// 解析 Bonk instruction data
|
||||
///
|
||||
/// 根据判别器路由到具体的 instruction 解析函数
|
||||
pub fn parse_bonk_instruction_data(
|
||||
discriminator: &[u8],
|
||||
data: &[u8],
|
||||
accounts: &[Pubkey],
|
||||
metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
match discriminator {
|
||||
discriminators::BUY_EXACT_IN => {
|
||||
parse_buy_exact_in_instruction(data, accounts, metadata)
|
||||
}
|
||||
discriminators::BUY_EXACT_OUT => {
|
||||
parse_buy_exact_out_instruction(data, accounts, metadata)
|
||||
}
|
||||
discriminators::SELL_EXACT_IN => {
|
||||
parse_sell_exact_in_instruction(data, accounts, metadata)
|
||||
}
|
||||
discriminators::SELL_EXACT_OUT => {
|
||||
parse_sell_exact_out_instruction(data, accounts, metadata)
|
||||
}
|
||||
discriminators::INITIALIZE => {
|
||||
parse_initialize_instruction(data, accounts, metadata)
|
||||
}
|
||||
discriminators::INITIALIZE_V2 => {
|
||||
parse_initialize_v2_instruction(data, accounts, metadata)
|
||||
}
|
||||
discriminators::INITIALIZE_WITH_TOKEN_2022 => {
|
||||
parse_initialize_with_token_2022_instruction(data, accounts, metadata)
|
||||
}
|
||||
discriminators::MIGRATE_TO_AMM => {
|
||||
parse_migrate_to_amm_instruction(data, accounts, metadata)
|
||||
}
|
||||
discriminators::MIGRATE_TO_CP_SWAP => {
|
||||
parse_migrate_to_cpswap_instruction(data, accounts, metadata)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// 解析 Bonk inner instruction data
|
||||
///
|
||||
/// 根据判别器路由到具体的 inner instruction 解析函数
|
||||
pub fn parse_bonk_inner_instruction_data(
|
||||
discriminator: &[u8],
|
||||
data: &[u8],
|
||||
metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
match discriminator {
|
||||
discriminators::TRADE_EVENT => {
|
||||
parse_trade_inner_instruction(data, metadata)
|
||||
}
|
||||
discriminators::POOL_CREATE_EVENT => {
|
||||
parse_pool_create_inner_instruction(data, metadata)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// 解析 Bonk 账户数据
|
||||
///
|
||||
/// 根据判别器路由到具体的账户解析函数
|
||||
pub fn parse_bonk_account_data(
|
||||
discriminator: &[u8],
|
||||
account: &crate::streaming::grpc::AccountPretty,
|
||||
metadata: crate::streaming::event_parser::common::EventMetadata,
|
||||
) -> Option<crate::streaming::event_parser::DexEvent> {
|
||||
match discriminator {
|
||||
discriminators::POOL_STATE_ACCOUNT => {
|
||||
crate::streaming::event_parser::protocols::bonk::types::pool_state_parser(account, metadata)
|
||||
}
|
||||
discriminators::GLOBAL_CONFIG_ACCOUNT => {
|
||||
crate::streaming::event_parser::protocols::bonk::types::global_config_parser(account, metadata)
|
||||
}
|
||||
discriminators::PLATFORM_CONFIG_ACCOUNT => {
|
||||
crate::streaming::event_parser::protocols::bonk::types::platform_config_parser(account, metadata)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse pool creation event
|
||||
fn parse_pool_create_inner_instruction(
|
||||
data: &[u8],
|
||||
metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
// Note: event_type will be set by the instruction parser, not here
|
||||
// Because different initialize instructions have different event types
|
||||
if let Some(event) = bonk_pool_create_event_log_decode(data) {
|
||||
Some(DexEvent::BonkPoolCreateEvent(BonkPoolCreateEvent { metadata, ..event }))
|
||||
} else {
|
||||
@@ -146,8 +136,10 @@ fn parse_trade_inner_instruction(data: &[u8], metadata: EventMetadata) -> Option
|
||||
fn parse_buy_exact_in_instruction(
|
||||
data: &[u8],
|
||||
accounts: &[Pubkey],
|
||||
metadata: EventMetadata,
|
||||
mut metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
metadata.event_type = EventType::BonkBuyExactIn;
|
||||
|
||||
if data.len() < 16 || accounts.len() < 18 {
|
||||
return None;
|
||||
}
|
||||
@@ -184,8 +176,10 @@ fn parse_buy_exact_in_instruction(
|
||||
fn parse_buy_exact_out_instruction(
|
||||
data: &[u8],
|
||||
accounts: &[Pubkey],
|
||||
metadata: EventMetadata,
|
||||
mut metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
metadata.event_type = EventType::BonkBuyExactOut;
|
||||
|
||||
if data.len() < 16 || accounts.len() < 18 {
|
||||
return None;
|
||||
}
|
||||
@@ -222,8 +216,10 @@ fn parse_buy_exact_out_instruction(
|
||||
fn parse_sell_exact_in_instruction(
|
||||
data: &[u8],
|
||||
accounts: &[Pubkey],
|
||||
metadata: EventMetadata,
|
||||
mut metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
metadata.event_type = EventType::BonkSellExactIn;
|
||||
|
||||
if data.len() < 16 || accounts.len() < 18 {
|
||||
return None;
|
||||
}
|
||||
@@ -260,8 +256,10 @@ fn parse_sell_exact_in_instruction(
|
||||
fn parse_sell_exact_out_instruction(
|
||||
data: &[u8],
|
||||
accounts: &[Pubkey],
|
||||
metadata: EventMetadata,
|
||||
mut metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
metadata.event_type = EventType::BonkSellExactOut;
|
||||
|
||||
if data.len() < 16 || accounts.len() < 18 {
|
||||
return None;
|
||||
}
|
||||
@@ -299,8 +297,10 @@ fn parse_sell_exact_out_instruction(
|
||||
fn parse_initialize_instruction(
|
||||
data: &[u8],
|
||||
accounts: &[Pubkey],
|
||||
metadata: EventMetadata,
|
||||
mut metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
metadata.event_type = EventType::BonkInitialize;
|
||||
|
||||
if data.len() < 24 {
|
||||
return None;
|
||||
}
|
||||
@@ -332,8 +332,10 @@ fn parse_initialize_instruction(
|
||||
fn parse_initialize_v2_instruction(
|
||||
data: &[u8],
|
||||
accounts: &[Pubkey],
|
||||
metadata: EventMetadata,
|
||||
mut metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
metadata.event_type = EventType::BonkInitializeV2;
|
||||
|
||||
if data.len() < 24 {
|
||||
return None;
|
||||
}
|
||||
@@ -371,8 +373,10 @@ fn parse_initialize_v2_instruction(
|
||||
fn parse_initialize_with_token_2022_instruction(
|
||||
data: &[u8],
|
||||
accounts: &[Pubkey],
|
||||
metadata: EventMetadata,
|
||||
mut metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
metadata.event_type = EventType::BonkInitializeWithToken2022;
|
||||
|
||||
if data.len() < 24 {
|
||||
return None;
|
||||
}
|
||||
@@ -515,8 +519,10 @@ fn parse_vesting_params(data: &[u8], offset: &mut usize) -> Option<VestingParams
|
||||
fn parse_migrate_to_amm_instruction(
|
||||
data: &[u8],
|
||||
accounts: &[Pubkey],
|
||||
metadata: EventMetadata,
|
||||
mut metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
metadata.event_type = EventType::BonkMigrateToAmm;
|
||||
|
||||
if data.len() < 16 {
|
||||
return None;
|
||||
}
|
||||
@@ -570,8 +576,10 @@ fn parse_migrate_to_amm_instruction(
|
||||
fn parse_migrate_to_cpswap_instruction(
|
||||
_data: &[u8],
|
||||
accounts: &[Pubkey],
|
||||
metadata: EventMetadata,
|
||||
mut metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
metadata.event_type = EventType::BonkMigrateToCpswap;
|
||||
|
||||
Some(DexEvent::BonkMigrateToCpswapEvent(BonkMigrateToCpswapEvent {
|
||||
metadata,
|
||||
payer: accounts[0],
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use crate::streaming::event_parser::{
|
||||
common::{EventMetadata, EventType, ProtocolType},
|
||||
core::GenericEventParseConfig,
|
||||
common::{EventMetadata, EventType},
|
||||
protocols::pumpfun::{
|
||||
discriminators, pumpfun_create_token_event_log_decode, pumpfun_migrate_event_log_decode,
|
||||
pumpfun_trade_event_log_decode, PumpFunCreateTokenEvent, PumpFunMigrateEvent,
|
||||
@@ -14,53 +13,78 @@ use solana_sdk::pubkey::Pubkey;
|
||||
pub const PUMPFUN_PROGRAM_ID: Pubkey =
|
||||
solana_sdk::pubkey!("6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P");
|
||||
|
||||
// 配置所有事件类型
|
||||
pub const CONFIGS: &[GenericEventParseConfig] = &[
|
||||
GenericEventParseConfig {
|
||||
program_id: PUMPFUN_PROGRAM_ID,
|
||||
protocol_type: ProtocolType::PumpFun,
|
||||
inner_instruction_discriminator: discriminators::CREATE_TOKEN_EVENT,
|
||||
instruction_discriminator: discriminators::CREATE_TOKEN_IX,
|
||||
event_type: EventType::PumpFunCreateToken,
|
||||
inner_instruction_parser: Some(parse_create_token_inner_instruction),
|
||||
instruction_parser: Some(parse_create_token_instruction),
|
||||
requires_inner_instruction: false,
|
||||
},
|
||||
GenericEventParseConfig {
|
||||
program_id: PUMPFUN_PROGRAM_ID,
|
||||
protocol_type: ProtocolType::PumpFun,
|
||||
inner_instruction_discriminator: discriminators::TRADE_EVENT,
|
||||
instruction_discriminator: discriminators::BUY_IX,
|
||||
event_type: EventType::PumpFunBuy,
|
||||
inner_instruction_parser: Some(parse_trade_inner_instruction),
|
||||
instruction_parser: Some(parse_buy_instruction),
|
||||
requires_inner_instruction: false,
|
||||
},
|
||||
GenericEventParseConfig {
|
||||
program_id: PUMPFUN_PROGRAM_ID,
|
||||
protocol_type: ProtocolType::PumpFun,
|
||||
inner_instruction_discriminator: discriminators::TRADE_EVENT,
|
||||
instruction_discriminator: discriminators::SELL_IX,
|
||||
event_type: EventType::PumpFunSell,
|
||||
inner_instruction_parser: Some(parse_trade_inner_instruction),
|
||||
instruction_parser: Some(parse_sell_instruction),
|
||||
requires_inner_instruction: false,
|
||||
},
|
||||
GenericEventParseConfig {
|
||||
program_id: PUMPFUN_PROGRAM_ID,
|
||||
protocol_type: ProtocolType::PumpFun,
|
||||
inner_instruction_discriminator: discriminators::COMPLETE_PUMP_AMM_MIGRATION_EVENT,
|
||||
instruction_discriminator: discriminators::MIGRATE_IX,
|
||||
event_type: EventType::PumpFunMigrate,
|
||||
inner_instruction_parser: Some(parse_migrate_inner_instruction),
|
||||
instruction_parser: Some(parse_migrate_instruction),
|
||||
// Failed migrations lack inner instruction data (typically "Bonding curve already migrated")
|
||||
requires_inner_instruction: true,
|
||||
},
|
||||
];
|
||||
/// 解析 PumpFun instruction data
|
||||
///
|
||||
/// 根据判别器路由到具体的 instruction 解析函数
|
||||
pub fn parse_pumpfun_instruction_data(
|
||||
discriminator: &[u8],
|
||||
data: &[u8],
|
||||
accounts: &[Pubkey],
|
||||
metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
match discriminator {
|
||||
discriminators::CREATE_TOKEN_IX => {
|
||||
parse_create_token_instruction(data, accounts, metadata)
|
||||
}
|
||||
discriminators::BUY_IX => {
|
||||
parse_buy_instruction(data, accounts, metadata)
|
||||
}
|
||||
discriminators::SELL_IX => {
|
||||
parse_sell_instruction(data, accounts, metadata)
|
||||
}
|
||||
discriminators::MIGRATE_IX => {
|
||||
parse_migrate_instruction(data, accounts, metadata)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// 解析 PumpFun inner instruction data
|
||||
///
|
||||
/// 根据判别器路由到具体的 inner instruction 解析函数
|
||||
pub fn parse_pumpfun_inner_instruction_data(
|
||||
discriminator: &[u8],
|
||||
data: &[u8],
|
||||
metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
match discriminator {
|
||||
discriminators::CREATE_TOKEN_EVENT => {
|
||||
parse_create_token_inner_instruction(data, metadata)
|
||||
}
|
||||
discriminators::TRADE_EVENT => {
|
||||
parse_trade_inner_instruction(data, metadata)
|
||||
}
|
||||
discriminators::COMPLETE_PUMP_AMM_MIGRATION_EVENT => {
|
||||
parse_migrate_inner_instruction(data, metadata)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// 解析 PumpFun 账户数据
|
||||
///
|
||||
/// 根据判别器路由到具体的账户解析函数
|
||||
pub fn parse_pumpfun_account_data(
|
||||
discriminator: &[u8],
|
||||
account: &crate::streaming::grpc::AccountPretty,
|
||||
metadata: crate::streaming::event_parser::common::EventMetadata,
|
||||
) -> Option<crate::streaming::event_parser::DexEvent> {
|
||||
match discriminator {
|
||||
discriminators::BONDING_CURVE_ACCOUNT => {
|
||||
crate::streaming::event_parser::protocols::pumpfun::types::bonding_curve_parser(account, metadata)
|
||||
}
|
||||
discriminators::GLOBAL_ACCOUNT => {
|
||||
crate::streaming::event_parser::protocols::pumpfun::types::global_parser(account, metadata)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// 解析迁移事件
|
||||
fn parse_migrate_inner_instruction(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
|
||||
fn parse_migrate_inner_instruction(data: &[u8], mut metadata: EventMetadata) -> Option<DexEvent> {
|
||||
metadata.event_type = EventType::PumpFunMigrate;
|
||||
if let Some(event) = pumpfun_migrate_event_log_decode(data) {
|
||||
Some(DexEvent::PumpFunMigrateEvent(PumpFunMigrateEvent { metadata, ..event }))
|
||||
} else {
|
||||
@@ -71,8 +95,9 @@ fn parse_migrate_inner_instruction(data: &[u8], metadata: EventMetadata) -> Opti
|
||||
/// 解析创建代币日志事件
|
||||
fn parse_create_token_inner_instruction(
|
||||
data: &[u8],
|
||||
metadata: EventMetadata,
|
||||
mut metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
metadata.event_type = EventType::PumpFunCreateToken;
|
||||
if let Some(event) = pumpfun_create_token_event_log_decode(data) {
|
||||
Some(DexEvent::PumpFunCreateTokenEvent(PumpFunCreateTokenEvent { metadata, ..event }))
|
||||
} else {
|
||||
@@ -80,8 +105,10 @@ fn parse_create_token_inner_instruction(
|
||||
}
|
||||
}
|
||||
|
||||
/// 解析交易事件
|
||||
/// 解析交易事件 (inner instruction 不设置 event_type,因为不知道是 Buy 还是 Sell)
|
||||
fn parse_trade_inner_instruction(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
|
||||
// 注意:inner instruction 的 trade event 不设置 event_type
|
||||
// 因为它会被合并到 instruction event 中,而 instruction event 已经设置了正确的 event_type
|
||||
if let Some(event) = pumpfun_trade_event_log_decode(data) {
|
||||
Some(DexEvent::PumpFunTradeEvent(PumpFunTradeEvent { metadata, ..event }))
|
||||
} else {
|
||||
@@ -93,8 +120,10 @@ fn parse_trade_inner_instruction(data: &[u8], metadata: EventMetadata) -> Option
|
||||
fn parse_create_token_instruction(
|
||||
data: &[u8],
|
||||
accounts: &[Pubkey],
|
||||
metadata: EventMetadata,
|
||||
mut metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
metadata.event_type = EventType::PumpFunCreateToken;
|
||||
|
||||
if data.len() < 16 || accounts.len() < 11 {
|
||||
return None;
|
||||
}
|
||||
@@ -154,8 +183,10 @@ fn parse_create_token_instruction(
|
||||
fn parse_buy_instruction(
|
||||
data: &[u8],
|
||||
accounts: &[Pubkey],
|
||||
metadata: EventMetadata,
|
||||
mut metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
metadata.event_type = EventType::PumpFunBuy;
|
||||
|
||||
if data.len() < 16 || accounts.len() < 13 {
|
||||
return None;
|
||||
}
|
||||
@@ -188,8 +219,10 @@ fn parse_buy_instruction(
|
||||
fn parse_sell_instruction(
|
||||
data: &[u8],
|
||||
accounts: &[Pubkey],
|
||||
metadata: EventMetadata,
|
||||
mut metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
metadata.event_type = EventType::PumpFunSell;
|
||||
|
||||
if data.len() < 16 || accounts.len() < 11 {
|
||||
return None;
|
||||
}
|
||||
@@ -222,8 +255,10 @@ fn parse_sell_instruction(
|
||||
fn parse_migrate_instruction(
|
||||
_data: &[u8],
|
||||
accounts: &[Pubkey],
|
||||
metadata: EventMetadata,
|
||||
mut metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
metadata.event_type = EventType::PumpFunMigrate;
|
||||
|
||||
if accounts.len() < 24 {
|
||||
return None;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use crate::streaming::event_parser::{
|
||||
common::{read_u64_le, EventMetadata, EventType, ProtocolType},
|
||||
core::GenericEventParseConfig,
|
||||
common::{read_u64_le, EventMetadata, EventType},
|
||||
protocols::pumpswap::{
|
||||
discriminators, pump_swap_buy_event_log_decode, pump_swap_create_pool_event_log_decode,
|
||||
pump_swap_deposit_event_log_decode, pump_swap_sell_event_log_decode,
|
||||
@@ -15,62 +14,70 @@ use solana_sdk::pubkey::Pubkey;
|
||||
pub const PUMPSWAP_PROGRAM_ID: Pubkey =
|
||||
solana_sdk::pubkey!("pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA");
|
||||
|
||||
// 配置所有事件类型
|
||||
pub const CONFIGS: &[GenericEventParseConfig] = &[
|
||||
GenericEventParseConfig {
|
||||
program_id: PUMPSWAP_PROGRAM_ID,
|
||||
protocol_type: ProtocolType::PumpSwap,
|
||||
inner_instruction_discriminator: discriminators::BUY_EVENT,
|
||||
instruction_discriminator: discriminators::BUY_IX,
|
||||
event_type: EventType::PumpSwapBuy,
|
||||
inner_instruction_parser: Some(parse_buy_inner_instruction),
|
||||
instruction_parser: Some(parse_buy_instruction),
|
||||
requires_inner_instruction: false,
|
||||
},
|
||||
GenericEventParseConfig {
|
||||
program_id: PUMPSWAP_PROGRAM_ID,
|
||||
protocol_type: ProtocolType::PumpSwap,
|
||||
inner_instruction_discriminator: discriminators::SELL_EVENT,
|
||||
instruction_discriminator: discriminators::SELL_IX,
|
||||
event_type: EventType::PumpSwapSell,
|
||||
inner_instruction_parser: Some(parse_sell_inner_instruction),
|
||||
instruction_parser: Some(parse_sell_instruction),
|
||||
requires_inner_instruction: false,
|
||||
},
|
||||
GenericEventParseConfig {
|
||||
program_id: PUMPSWAP_PROGRAM_ID,
|
||||
protocol_type: ProtocolType::PumpSwap,
|
||||
inner_instruction_discriminator: discriminators::CREATE_POOL_EVENT,
|
||||
instruction_discriminator: discriminators::CREATE_POOL_IX,
|
||||
event_type: EventType::PumpSwapCreatePool,
|
||||
inner_instruction_parser: Some(parse_create_pool_inner_instruction),
|
||||
instruction_parser: Some(parse_create_pool_instruction),
|
||||
requires_inner_instruction: false,
|
||||
},
|
||||
GenericEventParseConfig {
|
||||
program_id: PUMPSWAP_PROGRAM_ID,
|
||||
protocol_type: ProtocolType::PumpSwap,
|
||||
inner_instruction_discriminator: discriminators::DEPOSIT_EVENT,
|
||||
instruction_discriminator: discriminators::DEPOSIT_IX,
|
||||
event_type: EventType::PumpSwapDeposit,
|
||||
inner_instruction_parser: Some(parse_deposit_inner_instruction),
|
||||
instruction_parser: Some(parse_deposit_instruction),
|
||||
requires_inner_instruction: false,
|
||||
},
|
||||
GenericEventParseConfig {
|
||||
program_id: PUMPSWAP_PROGRAM_ID,
|
||||
protocol_type: ProtocolType::PumpSwap,
|
||||
inner_instruction_discriminator: discriminators::WITHDRAW_EVENT,
|
||||
instruction_discriminator: discriminators::WITHDRAW_IX,
|
||||
event_type: EventType::PumpSwapWithdraw,
|
||||
inner_instruction_parser: Some(parse_withdraw_inner_instruction),
|
||||
instruction_parser: Some(parse_withdraw_instruction),
|
||||
requires_inner_instruction: false,
|
||||
},
|
||||
];
|
||||
/// 解析 PumpSwap instruction data
|
||||
///
|
||||
/// 根据判别器路由到具体的 instruction 解析函数
|
||||
pub fn parse_pumpswap_instruction_data(
|
||||
discriminator: &[u8],
|
||||
data: &[u8],
|
||||
accounts: &[Pubkey],
|
||||
metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
match discriminator {
|
||||
discriminators::BUY_IX => parse_buy_instruction(data, accounts, metadata),
|
||||
discriminators::SELL_IX => parse_sell_instruction(data, accounts, metadata),
|
||||
discriminators::CREATE_POOL_IX => {
|
||||
parse_create_pool_instruction(data, accounts, metadata)
|
||||
}
|
||||
discriminators::DEPOSIT_IX => parse_deposit_instruction(data, accounts, metadata),
|
||||
discriminators::WITHDRAW_IX => parse_withdraw_instruction(data, accounts, metadata),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// 解析 PumpSwap inner instruction data
|
||||
///
|
||||
/// 根据判别器路由到具体的 inner instruction 解析函数
|
||||
pub fn parse_pumpswap_inner_instruction_data(
|
||||
discriminator: &[u8],
|
||||
data: &[u8],
|
||||
metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
match discriminator {
|
||||
discriminators::BUY_EVENT => parse_buy_inner_instruction(data, metadata),
|
||||
discriminators::SELL_EVENT => parse_sell_inner_instruction(data, metadata),
|
||||
discriminators::CREATE_POOL_EVENT => {
|
||||
parse_create_pool_inner_instruction(data, metadata)
|
||||
}
|
||||
discriminators::DEPOSIT_EVENT => parse_deposit_inner_instruction(data, metadata),
|
||||
discriminators::WITHDRAW_EVENT => parse_withdraw_inner_instruction(data, metadata),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// 解析 PumpSwap 账户数据
|
||||
///
|
||||
/// 根据判别器路由到具体的账户解析函数
|
||||
pub fn parse_pumpswap_account_data(
|
||||
discriminator: &[u8],
|
||||
account: &crate::streaming::grpc::AccountPretty,
|
||||
metadata: crate::streaming::event_parser::common::EventMetadata,
|
||||
) -> Option<crate::streaming::event_parser::DexEvent> {
|
||||
match discriminator {
|
||||
discriminators::GLOBAL_CONFIG_ACCOUNT => {
|
||||
crate::streaming::event_parser::protocols::pumpswap::types::global_config_parser(account, metadata)
|
||||
}
|
||||
discriminators::POOL_ACCOUNT => {
|
||||
crate::streaming::event_parser::protocols::pumpswap::types::pool_parser(account, metadata)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// 解析买入日志事件
|
||||
fn parse_buy_inner_instruction(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
|
||||
// Note: event_type will be set by instruction parser
|
||||
if let Some(event) = pump_swap_buy_event_log_decode(data) {
|
||||
Some(DexEvent::PumpSwapBuyEvent(PumpSwapBuyEvent { metadata, ..event }))
|
||||
} else {
|
||||
@@ -80,6 +87,7 @@ fn parse_buy_inner_instruction(data: &[u8], metadata: EventMetadata) -> Option<D
|
||||
|
||||
/// 解析卖出日志事件
|
||||
fn parse_sell_inner_instruction(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
|
||||
// Note: event_type will be set by instruction parser
|
||||
if let Some(event) = pump_swap_sell_event_log_decode(data) {
|
||||
Some(DexEvent::PumpSwapSellEvent(PumpSwapSellEvent { metadata, ..event }))
|
||||
} else {
|
||||
@@ -92,6 +100,7 @@ fn parse_create_pool_inner_instruction(
|
||||
data: &[u8],
|
||||
metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
// Note: event_type will be set by instruction parser
|
||||
if let Some(event) = pump_swap_create_pool_event_log_decode(data) {
|
||||
Some(DexEvent::PumpSwapCreatePoolEvent(PumpSwapCreatePoolEvent { metadata, ..event }))
|
||||
} else {
|
||||
@@ -101,6 +110,7 @@ fn parse_create_pool_inner_instruction(
|
||||
|
||||
/// 解析存款日志事件
|
||||
fn parse_deposit_inner_instruction(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
|
||||
// Note: event_type will be set by instruction parser
|
||||
if let Some(event) = pump_swap_deposit_event_log_decode(data) {
|
||||
Some(DexEvent::PumpSwapDepositEvent(PumpSwapDepositEvent { metadata, ..event }))
|
||||
} else {
|
||||
@@ -110,6 +120,7 @@ fn parse_deposit_inner_instruction(data: &[u8], metadata: EventMetadata) -> Opti
|
||||
|
||||
/// 解析提款日志事件
|
||||
fn parse_withdraw_inner_instruction(data: &[u8], metadata: EventMetadata) -> Option<DexEvent> {
|
||||
// Note: event_type will be set by instruction parser
|
||||
if let Some(event) = pump_swap_withdraw_event_log_decode(data) {
|
||||
Some(DexEvent::PumpSwapWithdrawEvent(PumpSwapWithdrawEvent { metadata, ..event }))
|
||||
} else {
|
||||
@@ -121,8 +132,10 @@ fn parse_withdraw_inner_instruction(data: &[u8], metadata: EventMetadata) -> Opt
|
||||
fn parse_buy_instruction(
|
||||
data: &[u8],
|
||||
accounts: &[Pubkey],
|
||||
metadata: EventMetadata,
|
||||
mut metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
metadata.event_type = EventType::PumpSwapBuy;
|
||||
|
||||
if data.len() < 16 || accounts.len() < 11 {
|
||||
return None;
|
||||
}
|
||||
@@ -156,8 +169,10 @@ fn parse_buy_instruction(
|
||||
fn parse_sell_instruction(
|
||||
data: &[u8],
|
||||
accounts: &[Pubkey],
|
||||
metadata: EventMetadata,
|
||||
mut metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
metadata.event_type = EventType::PumpSwapSell;
|
||||
|
||||
if data.len() < 16 || accounts.len() < 11 {
|
||||
return None;
|
||||
}
|
||||
@@ -191,8 +206,10 @@ fn parse_sell_instruction(
|
||||
fn parse_create_pool_instruction(
|
||||
data: &[u8],
|
||||
accounts: &[Pubkey],
|
||||
metadata: EventMetadata,
|
||||
mut metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
metadata.event_type = EventType::PumpSwapCreatePool;
|
||||
|
||||
if data.len() < 18 || accounts.len() < 11 {
|
||||
return None;
|
||||
}
|
||||
@@ -230,8 +247,10 @@ fn parse_create_pool_instruction(
|
||||
fn parse_deposit_instruction(
|
||||
data: &[u8],
|
||||
accounts: &[Pubkey],
|
||||
metadata: EventMetadata,
|
||||
mut metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
metadata.event_type = EventType::PumpSwapDeposit;
|
||||
|
||||
if data.len() < 24 || accounts.len() < 11 {
|
||||
return None;
|
||||
}
|
||||
@@ -262,8 +281,10 @@ fn parse_deposit_instruction(
|
||||
fn parse_withdraw_instruction(
|
||||
data: &[u8],
|
||||
accounts: &[Pubkey],
|
||||
metadata: EventMetadata,
|
||||
mut metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
metadata.event_type = EventType::PumpSwapWithdraw;
|
||||
|
||||
if data.len() < 24 || accounts.len() < 11 {
|
||||
return None;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use crate::streaming::event_parser::{
|
||||
common::{read_u64_le, EventMetadata, EventType, ProtocolType},
|
||||
core::GenericEventParseConfig,
|
||||
common::{read_u64_le, EventMetadata, EventType},
|
||||
protocols::raydium_amm_v4::{
|
||||
discriminators, RaydiumAmmV4DepositEvent, RaydiumAmmV4Initialize2Event,
|
||||
RaydiumAmmV4SwapEvent, RaydiumAmmV4WithdrawEvent, RaydiumAmmV4WithdrawPnlEvent,
|
||||
@@ -9,80 +8,73 @@ use crate::streaming::event_parser::{
|
||||
};
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
|
||||
/// Raydium CPMM程序ID
|
||||
/// Raydium AMM V4程序ID
|
||||
pub const RAYDIUM_AMM_V4_PROGRAM_ID: Pubkey =
|
||||
solana_sdk::pubkey!("675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8");
|
||||
|
||||
// 配置所有事件类型
|
||||
pub const CONFIGS: &[GenericEventParseConfig] = &[
|
||||
GenericEventParseConfig {
|
||||
program_id: RAYDIUM_AMM_V4_PROGRAM_ID,
|
||||
protocol_type: ProtocolType::RaydiumAmmV4,
|
||||
inner_instruction_discriminator: &[],
|
||||
instruction_discriminator: discriminators::SWAP_BASE_IN,
|
||||
event_type: EventType::RaydiumAmmV4SwapBaseIn,
|
||||
inner_instruction_parser: None,
|
||||
instruction_parser: Some(parse_swap_base_input_instruction),
|
||||
requires_inner_instruction: false,
|
||||
},
|
||||
GenericEventParseConfig {
|
||||
program_id: RAYDIUM_AMM_V4_PROGRAM_ID,
|
||||
protocol_type: ProtocolType::RaydiumAmmV4,
|
||||
inner_instruction_discriminator: &[],
|
||||
instruction_discriminator: discriminators::SWAP_BASE_OUT,
|
||||
event_type: EventType::RaydiumAmmV4SwapBaseOut,
|
||||
inner_instruction_parser: None,
|
||||
instruction_parser: Some(parse_swap_base_output_instruction),
|
||||
requires_inner_instruction: false,
|
||||
},
|
||||
GenericEventParseConfig {
|
||||
program_id: RAYDIUM_AMM_V4_PROGRAM_ID,
|
||||
protocol_type: ProtocolType::RaydiumAmmV4,
|
||||
inner_instruction_discriminator: &[],
|
||||
instruction_discriminator: discriminators::DEPOSIT,
|
||||
event_type: EventType::RaydiumAmmV4Deposit,
|
||||
inner_instruction_parser: None,
|
||||
instruction_parser: Some(parse_deposit_instruction),
|
||||
requires_inner_instruction: false,
|
||||
},
|
||||
GenericEventParseConfig {
|
||||
program_id: RAYDIUM_AMM_V4_PROGRAM_ID,
|
||||
protocol_type: ProtocolType::RaydiumAmmV4,
|
||||
inner_instruction_discriminator: &[],
|
||||
instruction_discriminator: discriminators::INITIALIZE2,
|
||||
event_type: EventType::RaydiumAmmV4Initialize2,
|
||||
inner_instruction_parser: None,
|
||||
instruction_parser: Some(parse_initialize2_instruction),
|
||||
requires_inner_instruction: false,
|
||||
},
|
||||
GenericEventParseConfig {
|
||||
program_id: RAYDIUM_AMM_V4_PROGRAM_ID,
|
||||
protocol_type: ProtocolType::RaydiumAmmV4,
|
||||
inner_instruction_discriminator: &[],
|
||||
instruction_discriminator: discriminators::WITHDRAW,
|
||||
event_type: EventType::RaydiumAmmV4Withdraw,
|
||||
inner_instruction_parser: None,
|
||||
instruction_parser: Some(parse_withdraw_instruction),
|
||||
requires_inner_instruction: false,
|
||||
},
|
||||
GenericEventParseConfig {
|
||||
program_id: RAYDIUM_AMM_V4_PROGRAM_ID,
|
||||
protocol_type: ProtocolType::RaydiumAmmV4,
|
||||
inner_instruction_discriminator: &[],
|
||||
instruction_discriminator: discriminators::WITHDRAW_PNL,
|
||||
event_type: EventType::RaydiumAmmV4WithdrawPnl,
|
||||
inner_instruction_parser: None,
|
||||
instruction_parser: Some(parse_withdraw_pnl_instruction),
|
||||
requires_inner_instruction: false,
|
||||
},
|
||||
];
|
||||
/// 解析 Raydium AMM V4 instruction data
|
||||
///
|
||||
/// 根据判别器路由到具体的 instruction 解析函数
|
||||
pub fn parse_raydium_amm_v4_instruction_data(
|
||||
discriminator: &[u8],
|
||||
data: &[u8],
|
||||
accounts: &[Pubkey],
|
||||
metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
match discriminator {
|
||||
discriminators::SWAP_BASE_IN => {
|
||||
parse_swap_base_input_instruction(data, accounts, metadata)
|
||||
}
|
||||
discriminators::SWAP_BASE_OUT => {
|
||||
parse_swap_base_output_instruction(data, accounts, metadata)
|
||||
}
|
||||
discriminators::DEPOSIT => parse_deposit_instruction(data, accounts, metadata),
|
||||
discriminators::INITIALIZE2 => parse_initialize2_instruction(data, accounts, metadata),
|
||||
discriminators::WITHDRAW => parse_withdraw_instruction(data, accounts, metadata),
|
||||
discriminators::WITHDRAW_PNL => {
|
||||
parse_withdraw_pnl_instruction(data, accounts, metadata)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// 解析 Raydium AMM V4 inner instruction data
|
||||
///
|
||||
/// Raydium AMM V4 没有 inner instruction 事件
|
||||
pub fn parse_raydium_amm_v4_inner_instruction_data(
|
||||
_discriminator: &[u8],
|
||||
_data: &[u8],
|
||||
_metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
None
|
||||
}
|
||||
|
||||
|
||||
/// 解析 Raydium AMM V4 账户数据
|
||||
///
|
||||
/// 根据判别器路由到具体的账户解析函数
|
||||
pub fn parse_raydium_amm_v4_account_data(
|
||||
discriminator: &[u8],
|
||||
account: &crate::streaming::grpc::AccountPretty,
|
||||
metadata: crate::streaming::event_parser::common::EventMetadata,
|
||||
) -> Option<crate::streaming::event_parser::DexEvent> {
|
||||
match discriminator {
|
||||
discriminators::AMM_INFO => {
|
||||
crate::streaming::event_parser::protocols::raydium_amm_v4::types::amm_info_parser(account, metadata)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// 解析提现指令事件
|
||||
fn parse_withdraw_pnl_instruction(
|
||||
_data: &[u8],
|
||||
accounts: &[Pubkey],
|
||||
metadata: EventMetadata,
|
||||
mut metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
metadata.event_type = EventType::RaydiumAmmV4WithdrawPnl;
|
||||
|
||||
if accounts.len() < 17 {
|
||||
return None;
|
||||
}
|
||||
@@ -113,8 +105,10 @@ fn parse_withdraw_pnl_instruction(
|
||||
fn parse_withdraw_instruction(
|
||||
data: &[u8],
|
||||
accounts: &[Pubkey],
|
||||
metadata: EventMetadata,
|
||||
mut metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
metadata.event_type = EventType::RaydiumAmmV4Withdraw;
|
||||
|
||||
if data.len() < 8 || accounts.len() < 22 {
|
||||
return None;
|
||||
}
|
||||
@@ -153,8 +147,10 @@ fn parse_withdraw_instruction(
|
||||
fn parse_initialize2_instruction(
|
||||
data: &[u8],
|
||||
accounts: &[Pubkey],
|
||||
metadata: EventMetadata,
|
||||
mut metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
metadata.event_type = EventType::RaydiumAmmV4Initialize2;
|
||||
|
||||
if data.len() < 25 || accounts.len() < 21 {
|
||||
return None;
|
||||
}
|
||||
@@ -198,8 +194,10 @@ fn parse_initialize2_instruction(
|
||||
fn parse_deposit_instruction(
|
||||
data: &[u8],
|
||||
accounts: &[Pubkey],
|
||||
metadata: EventMetadata,
|
||||
mut metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
metadata.event_type = EventType::RaydiumAmmV4Deposit;
|
||||
|
||||
if data.len() < 24 || accounts.len() < 14 {
|
||||
return None;
|
||||
}
|
||||
@@ -234,8 +232,10 @@ fn parse_deposit_instruction(
|
||||
fn parse_swap_base_output_instruction(
|
||||
data: &[u8],
|
||||
accounts: &[Pubkey],
|
||||
metadata: EventMetadata,
|
||||
mut metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
metadata.event_type = EventType::RaydiumAmmV4SwapBaseOut;
|
||||
|
||||
if data.len() < 16 || accounts.len() < 17 {
|
||||
return None;
|
||||
}
|
||||
@@ -281,8 +281,10 @@ fn parse_swap_base_output_instruction(
|
||||
fn parse_swap_base_input_instruction(
|
||||
data: &[u8],
|
||||
accounts: &[Pubkey],
|
||||
metadata: EventMetadata,
|
||||
mut metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
metadata.event_type = EventType::RaydiumAmmV4SwapBaseIn;
|
||||
|
||||
if data.len() < 16 || accounts.len() < 17 {
|
||||
return None;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
use crate::streaming::event_parser::{
|
||||
common::{
|
||||
read_i32_le, read_option_bool, read_u128_le, read_u64_le, read_u8_le, EventMetadata,
|
||||
EventType, ProtocolType,
|
||||
EventType,
|
||||
},
|
||||
core::GenericEventParseConfig,
|
||||
protocols::raydium_clmm::{
|
||||
discriminators, RaydiumClmmClosePositionEvent, RaydiumClmmCreatePoolEvent,
|
||||
RaydiumClmmDecreaseLiquidityV2Event, RaydiumClmmIncreaseLiquidityV2Event,
|
||||
@@ -18,96 +17,80 @@ use solana_sdk::pubkey::Pubkey;
|
||||
pub const RAYDIUM_CLMM_PROGRAM_ID: Pubkey =
|
||||
solana_sdk::pubkey!("CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK");
|
||||
|
||||
// 配置所有事件类型
|
||||
pub const CONFIGS: &[GenericEventParseConfig] = &[
|
||||
GenericEventParseConfig {
|
||||
program_id: RAYDIUM_CLMM_PROGRAM_ID,
|
||||
protocol_type: ProtocolType::RaydiumClmm,
|
||||
inner_instruction_discriminator: &[],
|
||||
instruction_discriminator: discriminators::SWAP,
|
||||
event_type: EventType::RaydiumClmmSwap,
|
||||
inner_instruction_parser: None,
|
||||
instruction_parser: Some(parse_swap_instruction),
|
||||
requires_inner_instruction: false,
|
||||
},
|
||||
GenericEventParseConfig {
|
||||
program_id: RAYDIUM_CLMM_PROGRAM_ID,
|
||||
protocol_type: ProtocolType::RaydiumClmm,
|
||||
inner_instruction_discriminator: &[],
|
||||
instruction_discriminator: discriminators::SWAP_V2,
|
||||
event_type: EventType::RaydiumClmmSwapV2,
|
||||
inner_instruction_parser: None,
|
||||
instruction_parser: Some(parse_swap_v2_instruction),
|
||||
requires_inner_instruction: false,
|
||||
},
|
||||
GenericEventParseConfig {
|
||||
program_id: RAYDIUM_CLMM_PROGRAM_ID,
|
||||
protocol_type: ProtocolType::RaydiumClmm,
|
||||
inner_instruction_discriminator: &[],
|
||||
instruction_discriminator: discriminators::CLOSE_POSITION,
|
||||
event_type: EventType::RaydiumClmmClosePosition,
|
||||
inner_instruction_parser: None,
|
||||
instruction_parser: Some(parse_close_position_instruction),
|
||||
requires_inner_instruction: false,
|
||||
},
|
||||
GenericEventParseConfig {
|
||||
program_id: RAYDIUM_CLMM_PROGRAM_ID,
|
||||
protocol_type: ProtocolType::RaydiumClmm,
|
||||
inner_instruction_discriminator: &[],
|
||||
instruction_discriminator: discriminators::DECREASE_LIQUIDITY_V2,
|
||||
event_type: EventType::RaydiumClmmDecreaseLiquidityV2,
|
||||
inner_instruction_parser: None,
|
||||
instruction_parser: Some(parse_decrease_liquidity_v2_instruction),
|
||||
requires_inner_instruction: false,
|
||||
},
|
||||
GenericEventParseConfig {
|
||||
program_id: RAYDIUM_CLMM_PROGRAM_ID,
|
||||
protocol_type: ProtocolType::RaydiumClmm,
|
||||
inner_instruction_discriminator: &[],
|
||||
instruction_discriminator: discriminators::CREATE_POOL,
|
||||
event_type: EventType::RaydiumClmmCreatePool,
|
||||
inner_instruction_parser: None,
|
||||
instruction_parser: Some(parse_create_pool_instruction),
|
||||
requires_inner_instruction: false,
|
||||
},
|
||||
GenericEventParseConfig {
|
||||
program_id: RAYDIUM_CLMM_PROGRAM_ID,
|
||||
protocol_type: ProtocolType::RaydiumClmm,
|
||||
inner_instruction_discriminator: &[],
|
||||
instruction_discriminator: discriminators::INCREASE_LIQUIDITY_V2,
|
||||
event_type: EventType::RaydiumClmmIncreaseLiquidityV2,
|
||||
inner_instruction_parser: None,
|
||||
instruction_parser: Some(parse_increase_liquidity_v2_instruction),
|
||||
requires_inner_instruction: false,
|
||||
},
|
||||
GenericEventParseConfig {
|
||||
program_id: RAYDIUM_CLMM_PROGRAM_ID,
|
||||
protocol_type: ProtocolType::RaydiumClmm,
|
||||
inner_instruction_discriminator: &[],
|
||||
instruction_discriminator: discriminators::OPEN_POSITION_WITH_TOKEN_22_NFT,
|
||||
event_type: EventType::RaydiumClmmOpenPositionWithToken22Nft,
|
||||
inner_instruction_parser: None,
|
||||
instruction_parser: Some(parse_open_position_with_token_22_nft_instruction),
|
||||
requires_inner_instruction: false,
|
||||
},
|
||||
GenericEventParseConfig {
|
||||
program_id: RAYDIUM_CLMM_PROGRAM_ID,
|
||||
protocol_type: ProtocolType::RaydiumClmm,
|
||||
inner_instruction_discriminator: &[],
|
||||
instruction_discriminator: discriminators::OPEN_POSITION_V2,
|
||||
event_type: EventType::RaydiumClmmOpenPositionV2,
|
||||
inner_instruction_parser: None,
|
||||
instruction_parser: Some(parse_open_position_v2_instruction),
|
||||
requires_inner_instruction: false,
|
||||
},
|
||||
];
|
||||
/// 解析 Raydium CLMM instruction data
|
||||
///
|
||||
/// 根据判别器路由到具体的 instruction 解析函数
|
||||
pub fn parse_raydium_clmm_instruction_data(
|
||||
discriminator: &[u8],
|
||||
data: &[u8],
|
||||
accounts: &[Pubkey],
|
||||
metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
match discriminator {
|
||||
discriminators::SWAP => parse_swap_instruction(data, accounts, metadata),
|
||||
discriminators::SWAP_V2 => parse_swap_v2_instruction(data, accounts, metadata),
|
||||
discriminators::CLOSE_POSITION => {
|
||||
parse_close_position_instruction(data, accounts, metadata)
|
||||
}
|
||||
discriminators::DECREASE_LIQUIDITY_V2 => {
|
||||
parse_decrease_liquidity_v2_instruction(data, accounts, metadata)
|
||||
}
|
||||
discriminators::CREATE_POOL => parse_create_pool_instruction(data, accounts, metadata),
|
||||
discriminators::INCREASE_LIQUIDITY_V2 => {
|
||||
parse_increase_liquidity_v2_instruction(data, accounts, metadata)
|
||||
}
|
||||
discriminators::OPEN_POSITION_WITH_TOKEN_22_NFT => {
|
||||
parse_open_position_with_token_22_nft_instruction(data, accounts, metadata)
|
||||
}
|
||||
discriminators::OPEN_POSITION_V2 => {
|
||||
parse_open_position_v2_instruction(data, accounts, metadata)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// 解析 Raydium CLMM inner instruction data
|
||||
///
|
||||
/// Raydium CLMM 没有 inner instruction 事件
|
||||
pub fn parse_raydium_clmm_inner_instruction_data(
|
||||
_discriminator: &[u8],
|
||||
_data: &[u8],
|
||||
_metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
None
|
||||
}
|
||||
|
||||
|
||||
/// 解析 Raydium CLMM 账户数据
|
||||
///
|
||||
/// 根据判别器路由到具体的账户解析函数
|
||||
pub fn parse_raydium_clmm_account_data(
|
||||
discriminator: &[u8],
|
||||
account: &crate::streaming::grpc::AccountPretty,
|
||||
metadata: crate::streaming::event_parser::common::EventMetadata,
|
||||
) -> Option<crate::streaming::event_parser::DexEvent> {
|
||||
match discriminator {
|
||||
discriminators::AMM_CONFIG => {
|
||||
crate::streaming::event_parser::protocols::raydium_clmm::types::amm_config_parser(account, metadata)
|
||||
}
|
||||
discriminators::POOL_STATE => {
|
||||
crate::streaming::event_parser::protocols::raydium_clmm::types::pool_state_parser(account, metadata)
|
||||
}
|
||||
discriminators::TICK_ARRAY_STATE => {
|
||||
crate::streaming::event_parser::protocols::raydium_clmm::types::tick_array_state_parser(account, metadata)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// 解析打开仓位V2指令事件
|
||||
fn parse_open_position_v2_instruction(
|
||||
data: &[u8],
|
||||
accounts: &[Pubkey],
|
||||
metadata: EventMetadata,
|
||||
mut metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
metadata.event_type = EventType::RaydiumClmmOpenPositionV2;
|
||||
|
||||
if data.len() < 51 || accounts.len() < 22 {
|
||||
return None;
|
||||
}
|
||||
@@ -152,8 +135,10 @@ fn parse_open_position_v2_instruction(
|
||||
fn parse_open_position_with_token_22_nft_instruction(
|
||||
data: &[u8],
|
||||
accounts: &[Pubkey],
|
||||
metadata: EventMetadata,
|
||||
mut metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
metadata.event_type = EventType::RaydiumClmmOpenPositionWithToken22Nft;
|
||||
|
||||
if data.len() < 51 || accounts.len() < 20 {
|
||||
return None;
|
||||
}
|
||||
@@ -197,8 +182,10 @@ fn parse_open_position_with_token_22_nft_instruction(
|
||||
fn parse_increase_liquidity_v2_instruction(
|
||||
data: &[u8],
|
||||
accounts: &[Pubkey],
|
||||
metadata: EventMetadata,
|
||||
mut metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
metadata.event_type = EventType::RaydiumClmmIncreaseLiquidityV2;
|
||||
|
||||
if data.len() < 34 || accounts.len() < 15 {
|
||||
return None;
|
||||
}
|
||||
@@ -230,8 +217,10 @@ fn parse_increase_liquidity_v2_instruction(
|
||||
fn parse_create_pool_instruction(
|
||||
data: &[u8],
|
||||
accounts: &[Pubkey],
|
||||
metadata: EventMetadata,
|
||||
mut metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
metadata.event_type = EventType::RaydiumClmmCreatePool;
|
||||
|
||||
if data.len() < 24 || accounts.len() < 13 {
|
||||
return None;
|
||||
}
|
||||
@@ -259,8 +248,10 @@ fn parse_create_pool_instruction(
|
||||
fn parse_decrease_liquidity_v2_instruction(
|
||||
data: &[u8],
|
||||
accounts: &[Pubkey],
|
||||
metadata: EventMetadata,
|
||||
mut metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
metadata.event_type = EventType::RaydiumClmmDecreaseLiquidityV2;
|
||||
|
||||
if data.len() < 32 || accounts.len() < 16 {
|
||||
return None;
|
||||
}
|
||||
@@ -293,8 +284,10 @@ fn parse_decrease_liquidity_v2_instruction(
|
||||
fn parse_close_position_instruction(
|
||||
_data: &[u8],
|
||||
accounts: &[Pubkey],
|
||||
metadata: EventMetadata,
|
||||
mut metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
metadata.event_type = EventType::RaydiumClmmClosePosition;
|
||||
|
||||
if accounts.len() < 6 {
|
||||
return None;
|
||||
}
|
||||
@@ -313,8 +306,10 @@ fn parse_close_position_instruction(
|
||||
fn parse_swap_instruction(
|
||||
data: &[u8],
|
||||
accounts: &[Pubkey],
|
||||
metadata: EventMetadata,
|
||||
mut metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
metadata.event_type = EventType::RaydiumClmmSwap;
|
||||
|
||||
if data.len() < 33 || accounts.len() < 10 {
|
||||
return None;
|
||||
}
|
||||
@@ -347,8 +342,10 @@ fn parse_swap_instruction(
|
||||
fn parse_swap_v2_instruction(
|
||||
data: &[u8],
|
||||
accounts: &[Pubkey],
|
||||
metadata: EventMetadata,
|
||||
mut metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
metadata.event_type = EventType::RaydiumClmmSwapV2;
|
||||
|
||||
if data.len() < 33 || accounts.len() < 13 {
|
||||
return None;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
|
||||
use crate::streaming::event_parser::{
|
||||
common::{read_u64_le, EventMetadata, EventType, ProtocolType},
|
||||
core::GenericEventParseConfig,
|
||||
common::{read_u64_le, EventMetadata, EventType},
|
||||
protocols::raydium_cpmm::{
|
||||
discriminators, RaydiumCpmmDepositEvent, RaydiumCpmmInitializeEvent, RaydiumCpmmSwapEvent,
|
||||
RaydiumCpmmWithdrawEvent,
|
||||
@@ -14,66 +13,69 @@ use crate::streaming::event_parser::{
|
||||
pub const RAYDIUM_CPMM_PROGRAM_ID: Pubkey =
|
||||
solana_sdk::pubkey!("CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C");
|
||||
|
||||
// 配置所有事件类型
|
||||
pub const CONFIGS: &[GenericEventParseConfig] = &[
|
||||
GenericEventParseConfig {
|
||||
program_id: RAYDIUM_CPMM_PROGRAM_ID,
|
||||
protocol_type: ProtocolType::RaydiumCpmm,
|
||||
inner_instruction_discriminator: &[],
|
||||
instruction_discriminator: discriminators::SWAP_BASE_IN,
|
||||
event_type: EventType::RaydiumCpmmSwapBaseInput,
|
||||
inner_instruction_parser: None,
|
||||
instruction_parser: Some(parse_swap_base_input_instruction),
|
||||
requires_inner_instruction: false,
|
||||
},
|
||||
GenericEventParseConfig {
|
||||
program_id: RAYDIUM_CPMM_PROGRAM_ID,
|
||||
protocol_type: ProtocolType::RaydiumCpmm,
|
||||
inner_instruction_discriminator: &[],
|
||||
instruction_discriminator: discriminators::SWAP_BASE_OUT,
|
||||
event_type: EventType::RaydiumCpmmSwapBaseOutput,
|
||||
inner_instruction_parser: None,
|
||||
instruction_parser: Some(parse_swap_base_output_instruction),
|
||||
requires_inner_instruction: false,
|
||||
},
|
||||
GenericEventParseConfig {
|
||||
program_id: RAYDIUM_CPMM_PROGRAM_ID,
|
||||
protocol_type: ProtocolType::RaydiumCpmm,
|
||||
inner_instruction_discriminator: &[],
|
||||
instruction_discriminator: discriminators::DEPOSIT,
|
||||
event_type: EventType::RaydiumCpmmDeposit,
|
||||
inner_instruction_parser: None,
|
||||
instruction_parser: Some(parse_deposit_instruction),
|
||||
requires_inner_instruction: false,
|
||||
},
|
||||
GenericEventParseConfig {
|
||||
program_id: RAYDIUM_CPMM_PROGRAM_ID,
|
||||
protocol_type: ProtocolType::RaydiumCpmm,
|
||||
inner_instruction_discriminator: &[],
|
||||
instruction_discriminator: discriminators::INITIALIZE,
|
||||
event_type: EventType::RaydiumCpmmInitialize,
|
||||
inner_instruction_parser: None,
|
||||
instruction_parser: Some(parse_initialize_instruction),
|
||||
requires_inner_instruction: false,
|
||||
},
|
||||
GenericEventParseConfig {
|
||||
program_id: RAYDIUM_CPMM_PROGRAM_ID,
|
||||
protocol_type: ProtocolType::RaydiumCpmm,
|
||||
inner_instruction_discriminator: &[],
|
||||
instruction_discriminator: discriminators::WITHDRAW,
|
||||
event_type: EventType::RaydiumCpmmWithdraw,
|
||||
inner_instruction_parser: None,
|
||||
instruction_parser: Some(parse_withdraw_instruction),
|
||||
requires_inner_instruction: false,
|
||||
},
|
||||
];
|
||||
/// 解析 Raydium CPMM instruction data
|
||||
///
|
||||
/// 根据判别器路由到具体的 instruction 解析函数
|
||||
pub fn parse_raydium_cpmm_instruction_data(
|
||||
discriminator: &[u8],
|
||||
data: &[u8],
|
||||
accounts: &[Pubkey],
|
||||
metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
match discriminator {
|
||||
discriminators::SWAP_BASE_IN => {
|
||||
parse_swap_base_input_instruction(data, accounts, metadata)
|
||||
}
|
||||
discriminators::SWAP_BASE_OUT => {
|
||||
parse_swap_base_output_instruction(data, accounts, metadata)
|
||||
}
|
||||
discriminators::DEPOSIT => parse_deposit_instruction(data, accounts, metadata),
|
||||
discriminators::INITIALIZE => parse_initialize_instruction(data, accounts, metadata),
|
||||
discriminators::WITHDRAW => parse_withdraw_instruction(data, accounts, metadata),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// 解析 Raydium CPMM inner instruction data
|
||||
///
|
||||
/// Raydium CPMM 没有 inner instruction 事件
|
||||
pub fn parse_raydium_cpmm_inner_instruction_data(
|
||||
_discriminator: &[u8],
|
||||
_data: &[u8],
|
||||
_metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
None
|
||||
}
|
||||
|
||||
|
||||
/// 解析 Raydium CPMM 账户数据
|
||||
///
|
||||
/// 根据判别器路由到具体的账户解析函数
|
||||
pub fn parse_raydium_cpmm_account_data(
|
||||
discriminator: &[u8],
|
||||
account: &crate::streaming::grpc::AccountPretty,
|
||||
metadata: crate::streaming::event_parser::common::EventMetadata,
|
||||
) -> Option<crate::streaming::event_parser::DexEvent> {
|
||||
match discriminator {
|
||||
discriminators::AMM_CONFIG => {
|
||||
crate::streaming::event_parser::protocols::raydium_cpmm::types::amm_config_parser(account, metadata)
|
||||
}
|
||||
discriminators::POOL_STATE => {
|
||||
crate::streaming::event_parser::protocols::raydium_cpmm::types::pool_state_parser(account, metadata)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// 解析提款指令事件
|
||||
fn parse_withdraw_instruction(
|
||||
data: &[u8],
|
||||
accounts: &[Pubkey],
|
||||
metadata: EventMetadata,
|
||||
mut metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
metadata.event_type = EventType::RaydiumCpmmWithdraw;
|
||||
|
||||
if data.len() < 24 || accounts.len() < 14 {
|
||||
return None;
|
||||
}
|
||||
@@ -103,8 +105,10 @@ fn parse_withdraw_instruction(
|
||||
fn parse_initialize_instruction(
|
||||
data: &[u8],
|
||||
accounts: &[Pubkey],
|
||||
metadata: EventMetadata,
|
||||
mut metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
metadata.event_type = EventType::RaydiumCpmmInitialize;
|
||||
|
||||
if data.len() < 24 || accounts.len() < 20 {
|
||||
return None;
|
||||
}
|
||||
@@ -140,8 +144,10 @@ fn parse_initialize_instruction(
|
||||
fn parse_deposit_instruction(
|
||||
data: &[u8],
|
||||
accounts: &[Pubkey],
|
||||
metadata: EventMetadata,
|
||||
mut metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
metadata.event_type = EventType::RaydiumCpmmDeposit;
|
||||
|
||||
if data.len() < 24 || accounts.len() < 13 {
|
||||
return None;
|
||||
}
|
||||
@@ -170,8 +176,10 @@ fn parse_deposit_instruction(
|
||||
fn parse_swap_base_input_instruction(
|
||||
data: &[u8],
|
||||
accounts: &[Pubkey],
|
||||
metadata: EventMetadata,
|
||||
mut metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
metadata.event_type = EventType::RaydiumCpmmSwapBaseInput;
|
||||
|
||||
if data.len() < 16 || accounts.len() < 13 {
|
||||
return None;
|
||||
}
|
||||
@@ -203,8 +211,10 @@ fn parse_swap_base_input_instruction(
|
||||
fn parse_swap_base_output_instruction(
|
||||
data: &[u8],
|
||||
accounts: &[Pubkey],
|
||||
metadata: EventMetadata,
|
||||
mut metadata: EventMetadata,
|
||||
) -> Option<DexEvent> {
|
||||
metadata.event_type = EventType::RaydiumCpmmSwapBaseOutput;
|
||||
|
||||
if data.len() < 16 || accounts.len() < 13 {
|
||||
return None;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user