release: prepare solana-streamer-sdk 3.0.2

This commit is contained in:
0xfnzero
2026-09-08 19:18:38 +08:00
parent 0a0beb2092
commit 2032d7c0b7
15 changed files with 591 additions and 466 deletions
+2 -2
View File
@@ -1,6 +1,6 @@
[package]
name = "solana-streamer-sdk"
version = "3.0.1"
version = "3.0.2"
edition = "2021"
rust-version = "1.91"
authors = ["William <byteblock6@gmail.com>", "sgxiang <sgxiang@gmail.com>", "wei <1415121722@qq.com>"]
@@ -22,7 +22,7 @@ sdk-perf-stats = ["sol-parser-sdk/perf-stats"]
sdk-ultra-perf = ["sol-parser-sdk/ultra-perf"]
[dependencies]
sol-parser-sdk = { path = "../sol-parser-sdk", version = "0.7.1", default-features = false }
sol-parser-sdk = { path = "../sol-parser-sdk", version = "0.7.2", default-features = false }
solana-sdk = "=4.0.1"
solana-client = "=4.2.2"
solana-transaction-status = { version = "=4.2.2", features = ["agave-unstable-api"] }
+8 -4
View File
@@ -129,30 +129,34 @@ Add the dependency to your `Cargo.toml`:
```toml
# Add to your Cargo.toml
solana-streamer-sdk = { path = "./solana-streamer", version = "3.0.1" }
solana-streamer-sdk = { path = "./solana-streamer", version = "3.0.2" }
```
### Use crates.io
```toml
# Add to your Cargo.toml
solana-streamer-sdk = "3.0.1"
solana-streamer-sdk = "3.0.2"
```
Parser backend features:
```toml
# Default: sol-parser-sdk parse-borsh backend
solana-streamer-sdk = "3.0.1"
solana-streamer-sdk = "3.0.2"
# Zero-copy parser backend for latency-sensitive bots
solana-streamer-sdk = { version = "3.0.1", default-features = false, features = ["sdk-parse-zero-copy"] }
solana-streamer-sdk = { version = "3.0.2", default-features = false, features = ["sdk-parse-zero-copy"] }
```
If both `sdk-parse-borsh` and `sdk-parse-zero-copy` are enabled, `sol-parser-sdk 0.6.1+` uses the zero-copy backend.
## 🔄 Migration Guide
### Upgrading to v3.0.2
Version 3.0.2 uses `sol-parser-sdk 0.7.2` and forwards the new Meteora DAMM v2 events: `UpdateDelegatePermission`, `WithdrawDeadLiquidityReward`, `CreateConfig`, and `CreateDynamicConfig`. Transaction-cost events preserve all four Solana V1 config requests, and Yellowstone V1 messages are distinguished from V0 through `Message.config`. V1 ingestion requires a Yellowstone geyser server plugin version of at least `15.1.1`; older servers silently discard the config while downgrading V1 to V0.
### Upgrading to v3.0.1
Version 3.0.1 uses `sol-parser-sdk 0.7.1` and fixes current Meteora DAMM v2 Swap and AddLiquidity delivery. The bridge now preserves all current swap fee, transfer-fee, reserve, mode, and liquidity fields; exact AddLiquidity filtering follows the unified on-chain `EvtLiquidityChange` event. Streamer no longer maintains a separate DAMM swap payload decoder, keeping `sol-parser-sdk` as the single parsing implementation. Mainnet RPC regression tests cover both reported event types.
+8 -4
View File
@@ -128,30 +128,34 @@ git clone https://github.com/0xfnzero/solana-streamer
```toml
# 添加到您的 Cargo.toml
solana-streamer-sdk = { path = "./solana-streamer", version = "3.0.1" }
solana-streamer-sdk = { path = "./solana-streamer", version = "3.0.2" }
```
### 使用 crates.io
```toml
# 添加到您的 Cargo.toml
solana-streamer-sdk = "3.0.1"
solana-streamer-sdk = "3.0.2"
```
解析后端 feature:
```toml
# 默认:sol-parser-sdk parse-borsh 后端
solana-streamer-sdk = "3.0.1"
solana-streamer-sdk = "3.0.2"
# 面向低延迟 Bot 的 zero-copy 解析后端
solana-streamer-sdk = { version = "3.0.1", default-features = false, features = ["sdk-parse-zero-copy"] }
solana-streamer-sdk = { version = "3.0.2", default-features = false, features = ["sdk-parse-zero-copy"] }
```
如果同时启用 `sdk-parse-borsh` 和 `sdk-parse-zero-copy`,`sol-parser-sdk 0.6.1+` 会优先使用 zero-copy 后端。
## 🔄 迁移指南
### 升级到 v3.0.2
v3.0.2 使用 `sol-parser-sdk 0.7.2`,并转发新增的 Meteora DAMM v2 事件:`UpdateDelegatePermission`、`WithdrawDeadLiquidityReward`、`CreateConfig`、`CreateDynamicConfig`。TransactionCost 事件会完整保留 Solana V1 的四项 config 请求,并通过 `Message.config` 区分 V1 与 V0。接入 V1 要求 Yellowstone geyser 服务端插件至少为 `15.1.1`;更旧的服务端会静默丢弃 config 并把 V1 降级成 V0。
### 升级到 v3.0.1
v3.0.1 使用 `sol-parser-sdk 0.7.1`,修复当前 Meteora DAMM v2 Swap 与 AddLiquidity 的投递。bridge 现在会完整保留 swap fee、transfer fee、reserve、mode 和流动性字段;AddLiquidity 精确过滤会跟随链上统一的 `EvtLiquidityChange` 事件。Streamer 不再维护独立的 DAMM swap payload 解码器,由 `sol-parser-sdk` 作为唯一解析实现,并增加两类问题事件的主网 RPC 回归测试。
+48 -210
View File
@@ -2,7 +2,7 @@
"address": "cpamdpZCGKUy5JxQXB4dcpGPiikHawvSWAd6mEn1sGG",
"metadata": {
"name": "cp_amm",
"version": "0.2.2",
"version": "0.2.4",
"spec": "0.1.0",
"description": "Created with Anchor"
},
@@ -239,116 +239,6 @@
],
"args": []
},
{
"name": "claim_protocol_fee",
"discriminator": [
165,
228,
133,
48,
99,
249,
255,
33
],
"accounts": [
{
"name": "pool_authority",
"address": "HLnpSz9h2S4hiLQ43rnSD9XkcUThA7B8hQMKmDaiTLcC"
},
{
"name": "pool",
"writable": true
},
{
"name": "token_a_vault",
"docs": [
"The vault token account for input token"
],
"writable": true,
"relations": [
"pool"
]
},
{
"name": "token_b_vault",
"docs": [
"The vault token account for output token"
],
"writable": true,
"relations": [
"pool"
]
},
{
"name": "token_a_mint",
"docs": [
"The mint of token a"
],
"relations": [
"pool"
]
},
{
"name": "token_b_mint",
"docs": [
"The mint of token b"
],
"relations": [
"pool"
]
},
{
"name": "token_a_account",
"writable": true
},
{
"name": "token_b_account",
"writable": true
},
{
"name": "operator",
"docs": [
"Claim fee operator"
]
},
{
"name": "signer",
"docs": [
"Operator"
],
"signer": true
},
{
"name": "token_a_program",
"docs": [
"Token a program"
]
},
{
"name": "token_b_program",
"docs": [
"Token b program"
]
},
{
"name": "event_authority"
},
{
"name": "program"
}
],
"args": [
{
"name": "max_amount_a",
"type": "u64"
},
{
"name": "max_amount_b",
"type": "u64"
}
]
},
{
"name": "claim_protocol_fee2",
"discriminator": [
@@ -3275,69 +3165,6 @@
"type": "u8"
}
]
},
{
"name": "zap_protocol_fee",
"discriminator": [
213,
155,
187,
34,
56,
182,
91,
240
],
"accounts": [
{
"name": "pool_authority",
"address": "HLnpSz9h2S4hiLQ43rnSD9XkcUThA7B8hQMKmDaiTLcC"
},
{
"name": "pool",
"writable": true
},
{
"name": "token_vault",
"writable": true
},
{
"name": "token_mint"
},
{
"name": "receiver_token",
"writable": true
},
{
"name": "operator",
"docs": [
"zap claim fee operator"
]
},
{
"name": "signer",
"docs": [
"Operator"
],
"signer": true
},
{
"name": "token_program",
"docs": [
"Token program"
]
},
{
"name": "sysvar_instructions",
"address": "Sysvar1nstructions1111111111111111111111111"
}
],
"args": [
{
"name": "max_amount",
"type": "u64"
}
]
}
],
"accounts": [
@@ -3473,19 +3300,6 @@
56
]
},
{
"name": "EvtClaimProtocolFee",
"discriminator": [
186,
244,
75,
251,
188,
13,
25,
33
]
},
{
"name": "EvtClaimProtocolFee2",
"discriminator": [
@@ -4154,6 +3968,16 @@
"code": 6070,
"name": "DelegatedAmountNonZero",
"msg": "Delegated amount is not zero"
},
{
"code": 6071,
"name": "DeprecatedBaseFeeMode",
"msg": "Deprecated base fee mode"
},
{
"code": 6072,
"name": "InvalidConfigPermission",
"msg": "Invalid config permission"
}
],
"types": [
@@ -4441,16 +4265,22 @@
],
"type": "u128"
},
{
"name": "permission",
"docs": [
"config permission bitmask"
],
"type": "u128"
},
{
"name": "_padding_1",
"docs": [
"Fee curve point",
"Padding for further use"
],
"type": {
"array": [
"u64",
10
8
]
}
}
@@ -4497,6 +4327,10 @@
{
"name": "pool_creator_authority",
"type": "pubkey"
},
{
"name": "permission",
"type": "u128"
}
]
}
@@ -4696,26 +4530,6 @@
]
}
},
{
"name": "EvtClaimProtocolFee",
"type": {
"kind": "struct",
"fields": [
{
"name": "pool",
"type": "pubkey"
},
{
"name": "token_a_amount",
"type": "u64"
},
{
"name": "token_b_amount",
"type": "u64"
}
]
}
},
{
"name": "EvtClaimProtocolFee2",
"type": {
@@ -4868,6 +4682,10 @@
{
"name": "config",
"type": "pubkey"
},
{
"name": "permission",
"type": "u128"
}
]
}
@@ -4891,6 +4709,10 @@
{
"name": "index",
"type": "u64"
},
{
"name": "permission",
"type": "u128"
}
]
}
@@ -5988,9 +5810,21 @@
],
"type": "u64"
},
{
"name": "dead_liquidity_fee_checkpoint",
"docs": [
"Cumulative dead-liquidity fee (Compounding Pool only)"
],
"type": "u64"
},
{
"name": "padding_2",
"type": "u128"
"type": {
"array": [
"u8",
8
]
}
},
{
"name": "sqrt_min_price",
@@ -7044,6 +6878,10 @@
{
"name": "collect_fee_mode",
"type": "u8"
},
{
"name": "permission",
"type": "u128"
}
]
}
+237 -222
View File
@@ -2,7 +2,7 @@
"address": "dbcij3LWUppWqq96dh6gJWwBifmcGfLSB5D4DuSMaqN",
"metadata": {
"name": "dynamic_bonding_curve",
"version": "0.2.0",
"version": "0.2.1",
"spec": "0.1.0",
"description": "Created with Anchor"
},
@@ -251,122 +251,6 @@
],
"args": []
},
{
"name": "claim_protocol_fee",
"docs": [
"Accepts: VirtualPool only."
],
"discriminator": [
165,
228,
133,
48,
99,
249,
255,
33
],
"accounts": [
{
"name": "pool_authority",
"address": "FhVo3mqL8PW5pH5U2CN4XE33DokiyZnUwuGpH2hmHLuM"
},
{
"name": "config",
"relations": [
"pool"
]
},
{
"name": "pool",
"writable": true
},
{
"name": "base_vault",
"docs": [
"The vault token account for input token"
],
"writable": true,
"relations": [
"pool"
]
},
{
"name": "quote_vault",
"docs": [
"The vault token account for output token"
],
"writable": true,
"relations": [
"pool"
]
},
{
"name": "base_mint",
"docs": [
"The mint of token a"
],
"relations": [
"pool"
]
},
{
"name": "quote_mint",
"docs": [
"The mint of token b"
],
"relations": [
"config"
]
},
{
"name": "token_base_account",
"writable": true
},
{
"name": "token_quote_account",
"writable": true
},
{
"name": "operator"
},
{
"name": "signer",
"docs": [
"Signer"
],
"signer": true
},
{
"name": "token_base_program",
"docs": [
"Token a program"
]
},
{
"name": "token_quote_program",
"docs": [
"Token b program"
]
},
{
"name": "event_authority"
},
{
"name": "program"
}
],
"args": [
{
"name": "max_base_amount",
"type": "u64"
},
{
"name": "max_quote_amount",
"type": "u64"
}
]
},
{
"name": "claim_protocol_fee2",
"docs": [
@@ -753,6 +637,43 @@
],
"args": []
},
{
"name": "close_token_badge",
"discriminator": [
108,
146,
86,
110,
179,
254,
10,
104
],
"accounts": [
{
"name": "token_badge",
"writable": true
},
{
"name": "operator"
},
{
"name": "signer",
"signer": true
},
{
"name": "rent_receiver",
"writable": true
},
{
"name": "event_authority"
},
{
"name": "program"
}
],
"args": []
},
{
"name": "create_config",
"discriminator": [
@@ -1132,6 +1053,78 @@
}
]
},
{
"name": "create_token_badge",
"discriminator": [
88,
206,
0,
91,
60,
175,
151,
118
],
"accounts": [
{
"name": "token_badge",
"writable": true,
"pda": {
"seeds": [
{
"kind": "const",
"value": [
116,
111,
107,
101,
110,
95,
98,
97,
100,
103,
101
]
},
{
"kind": "account",
"path": "token_mint"
}
]
}
},
{
"name": "token_mint"
},
{
"name": "operator"
},
{
"name": "signer",
"docs": [
"Operator"
],
"signer": true
},
{
"name": "payer",
"writable": true,
"signer": true
},
{
"name": "system_program",
"address": "11111111111111111111111111111111"
},
{
"name": "event_authority"
},
{
"name": "program"
}
],
"args": []
},
{
"name": "create_virtual_pool_metadata",
"docs": [
@@ -3224,78 +3217,6 @@
"type": "u8"
}
]
},
{
"name": "zap_protocol_fee",
"docs": [
"Accepts: VirtualPool only."
],
"discriminator": [
213,
155,
187,
34,
56,
182,
91,
240
],
"accounts": [
{
"name": "pool_authority",
"address": "FhVo3mqL8PW5pH5U2CN4XE33DokiyZnUwuGpH2hmHLuM"
},
{
"name": "config",
"relations": [
"pool"
]
},
{
"name": "pool",
"writable": true
},
{
"name": "token_vault",
"writable": true
},
{
"name": "token_mint"
},
{
"name": "receiver_token",
"writable": true
},
{
"name": "operator",
"docs": [
"zap claim fee operator"
]
},
{
"name": "signer",
"docs": [
"Operator"
],
"signer": true
},
{
"name": "token_program",
"docs": [
"Token program"
]
},
{
"name": "sysvar_instructions",
"address": "Sysvar1nstructions1111111111111111111111111"
}
],
"args": [
{
"name": "max_amount",
"type": "u64"
}
]
}
],
"accounts": [
@@ -3377,6 +3298,19 @@
43
]
},
{
"name": "TokenBadge",
"discriminator": [
116,
219,
204,
229,
249,
116,
255,
150
]
},
{
"name": "TransferHookPool",
"discriminator": [
@@ -3444,19 +3378,6 @@
62
]
},
{
"name": "EvtClaimProtocolFee",
"discriminator": [
186,
244,
75,
251,
188,
13,
25,
33
]
},
{
"name": "EvtClaimProtocolFee2",
"discriminator": [
@@ -3496,6 +3417,19 @@
23
]
},
{
"name": "EvtCloseTokenBadge",
"discriminator": [
60,
217,
34,
82,
183,
10,
89,
188
]
},
{
"name": "EvtCreateClaimFeeOperator",
"discriminator": [
@@ -3561,6 +3495,19 @@
139
]
},
{
"name": "EvtCreateTokenBadge",
"discriminator": [
141,
120,
134,
116,
34,
28,
114,
160
]
},
{
"name": "EvtCreatorWithdrawSurplus",
"discriminator": [
@@ -4142,6 +4089,36 @@
"code": 6076,
"name": "PoolTypeMismatch",
"msg": "Pool type does not match instruction"
},
{
"code": 6077,
"name": "InvalidRemainingAccountSliceType",
"msg": "Invalid remaining account slice type for this instruction"
},
{
"code": 6078,
"name": "DeprecatedBaseFeeMode",
"msg": "Deprecated base fee mode"
},
{
"code": 6079,
"name": "CannotCreateTokenBadgeOnSupportedMint",
"msg": "Cannot create token badge on supported mint"
},
{
"code": 6080,
"name": "InvalidTokenBadge",
"msg": "Invalid token badge"
},
{
"code": 6081,
"name": "QuoteMintHasNonZeroTransferFee",
"msg": "Quote mint has a non zero transfer fee"
},
{
"code": 6082,
"name": "DeprecatedMigrationOption",
"msg": "Deprecated migration option"
}
],
"types": [
@@ -4710,26 +4687,6 @@
]
}
},
{
"name": "EvtClaimProtocolFee",
"type": {
"kind": "struct",
"fields": [
{
"name": "pool",
"type": "pubkey"
},
{
"name": "token_base_amount",
"type": "u64"
},
{
"name": "token_quote_amount",
"type": "u64"
}
]
}
},
{
"name": "EvtClaimProtocolFee2",
"type": {
@@ -4793,6 +4750,18 @@
]
}
},
{
"name": "EvtCloseTokenBadge",
"type": {
"kind": "struct",
"fields": [
{
"name": "token_mint",
"type": "pubkey"
}
]
}
},
{
"name": "EvtCreateClaimFeeOperator",
"docs": [
@@ -5009,6 +4978,18 @@
]
}
},
{
"name": "EvtCreateTokenBadge",
"type": {
"kind": "struct",
"fields": [
{
"name": "token_mint",
"type": "pubkey"
}
]
}
},
{
"name": "EvtCreatorWithdrawSurplus",
"type": {
@@ -6790,6 +6771,40 @@
]
}
},
{
"name": "TokenBadge",
"docs": [
"Parameter that set by the protocol"
],
"serialization": "bytemuck",
"repr": {
"kind": "c"
},
"type": {
"kind": "struct",
"fields": [
{
"name": "token_mint",
"docs": [
"token mint"
],
"type": "pubkey"
},
{
"name": "_padding",
"docs": [
"Reserve"
],
"type": {
"array": [
"u8",
128
]
}
}
]
}
},
{
"name": "TokenSupplyParams",
"type": {
@@ -310,6 +310,14 @@ fn push_streamer_event_sdk_grpc_types(
St::MeteoraDammV2InitializePool => out.push(Sdk::MeteoraDammV2InitializePool),
St::MeteoraDammV2CreatePosition => out.push(Sdk::MeteoraDammV2CreatePosition),
St::MeteoraDammV2ClosePosition => out.push(Sdk::MeteoraDammV2ClosePosition),
St::MeteoraDammV2UpdateDelegatePermission => {
out.push(Sdk::MeteoraDammV2UpdateDelegatePermission)
}
St::MeteoraDammV2WithdrawDeadLiquidityReward => {
out.push(Sdk::MeteoraDammV2WithdrawDeadLiquidityReward)
}
St::MeteoraDammV2CreateConfig => out.push(Sdk::MeteoraDammV2CreateConfig),
St::MeteoraDammV2CreateDynamicConfig => out.push(Sdk::MeteoraDammV2CreateDynamicConfig),
St::MeteoraDbcSwap => out.push(Sdk::MeteoraDbcSwap),
St::MeteoraDbcInitializePool => out.push(Sdk::MeteoraDbcInitializePool),
St::MeteoraDbcCurveComplete => out.push(Sdk::MeteoraDbcCurveComplete),
@@ -438,6 +446,10 @@ fn push_protocol_sdk_grpc_event_types(protocol: &Protocol, out: &mut Vec<SdkGrpc
Sdk::MeteoraDammV2InitializePool,
Sdk::MeteoraDammV2CreatePosition,
Sdk::MeteoraDammV2ClosePosition,
Sdk::MeteoraDammV2UpdateDelegatePermission,
Sdk::MeteoraDammV2WithdrawDeadLiquidityReward,
Sdk::MeteoraDammV2CreateConfig,
Sdk::MeteoraDammV2CreateDynamicConfig,
]),
StProtocol::MeteoraDbc => out.extend_from_slice(&[
Sdk::MeteoraDbcSwap,
@@ -831,6 +843,10 @@ mod tests {
EventType::MeteoraDammV2InitializePool,
EventType::MeteoraDammV2CreatePosition,
EventType::MeteoraDammV2ClosePosition,
EventType::MeteoraDammV2UpdateDelegatePermission,
EventType::MeteoraDammV2WithdrawDeadLiquidityReward,
EventType::MeteoraDammV2CreateConfig,
EventType::MeteoraDammV2CreateDynamicConfig,
EventType::MeteoraDbcSwap,
EventType::MeteoraDbcInitializePool,
EventType::MeteoraDbcCurveComplete,
@@ -154,6 +154,10 @@ pub enum EventType {
MeteoraDammV2ClosePosition,
MeteoraDammV2AddLiquidity,
MeteoraDammV2RemoveLiquidity,
MeteoraDammV2UpdateDelegatePermission,
MeteoraDammV2WithdrawDeadLiquidityReward,
MeteoraDammV2CreateConfig,
MeteoraDammV2CreateDynamicConfig,
// Meteora DBC
MeteoraDbcSwap,
@@ -124,6 +124,10 @@ pub enum DexEvent {
MeteoraDammV2RemoveLiquidityEvent(MeteoraDammV2RemoveLiquidityEvent),
MeteoraDammV2CreatePositionEvent(MeteoraDammV2CreatePositionEvent),
MeteoraDammV2ClosePositionEvent(MeteoraDammV2ClosePositionEvent),
MeteoraDammV2UpdateDelegatePermissionEvent(MeteoraDammV2UpdateDelegatePermissionEvent),
MeteoraDammV2WithdrawDeadLiquidityRewardEvent(MeteoraDammV2WithdrawDeadLiquidityRewardEvent),
MeteoraDammV2CreateConfigEvent(MeteoraDammV2CreateConfigEvent),
MeteoraDammV2CreateDynamicConfigEvent(MeteoraDammV2CreateDynamicConfigEvent),
MeteoraDbcSwapEvent(MeteoraDbcSwapEvent),
MeteoraDbcInitializePoolEvent(MeteoraDbcInitializePoolEvent),
@@ -270,6 +274,10 @@ impl_dex_event_metadata!(
MeteoraDammV2RemoveLiquidityEvent,
MeteoraDammV2CreatePositionEvent,
MeteoraDammV2ClosePositionEvent,
MeteoraDammV2UpdateDelegatePermissionEvent,
MeteoraDammV2WithdrawDeadLiquidityRewardEvent,
MeteoraDammV2CreateConfigEvent,
MeteoraDammV2CreateDynamicConfigEvent,
MeteoraDbcSwapEvent,
MeteoraDbcInitializePoolEvent,
MeteoraDbcCurveCompleteEvent,
@@ -13,6 +13,10 @@ pub struct TransactionCostEvent {
pub compute_units_consumed: Option<u64>,
pub compute_unit_limit: Option<u32>,
pub compute_unit_price_micro_lamports: Option<u64>,
#[serde(default)]
pub loaded_accounts_data_size_limit: Option<u32>,
#[serde(default)]
pub heap_size: Option<u32>,
pub priority_fee_lamports: Option<u64>,
pub tip_payments_confirmed: bool,
pub tip_lamports: u64,
@@ -51,6 +55,8 @@ impl TransactionCostEvent {
compute_units_consumed: cost.compute_units_consumed,
compute_unit_limit: cost.compute_unit_limit,
compute_unit_price_micro_lamports: cost.compute_unit_price_micro_lamports,
loaded_accounts_data_size_limit: cost.loaded_accounts_data_size_limit,
heap_size: cost.heap_size,
priority_fee_lamports: cost.priority_fee_lamports,
tip_payments_confirmed: cost.tip_payments_confirmed,
tip_lamports: cost.tip_lamports,
@@ -66,3 +72,54 @@ impl TransactionCostEvent {
.fold(0u64, |total, payment| total.saturating_add(payment.lamports))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn preserves_all_v1_transaction_config_fields() {
let event = TransactionCostEvent::from_parser(
TransactionCost {
compute_unit_limit: Some(234_567),
priority_fee_lamports: Some(4_321),
loaded_accounts_data_size_limit: Some(1_048_576),
heap_size: Some(65_536),
..TransactionCost::default()
},
Signature::default(),
42,
Some(3),
None,
0,
None,
);
assert_eq!(event.compute_unit_limit, Some(234_567));
assert_eq!(event.priority_fee_lamports, Some(4_321));
assert_eq!(event.loaded_accounts_data_size_limit, Some(1_048_576));
assert_eq!(event.heap_size, Some(65_536));
}
#[test]
fn deserializes_event_json_from_before_v1_resource_fields() {
let event = TransactionCostEvent::from_parser(
TransactionCost::default(),
Signature::default(),
42,
None,
None,
0,
None,
);
let mut value = serde_json::to_value(event).expect("serialize event");
let object = value.as_object_mut().expect("event object");
object.remove("loaded_accounts_data_size_limit");
object.remove("heap_size");
let decoded: TransactionCostEvent =
serde_json::from_value(value).expect("legacy TransactionCostEvent JSON");
assert_eq!(decoded.loaded_accounts_data_size_limit, None);
assert_eq!(decoded.heap_size, None);
}
}
@@ -429,6 +429,61 @@ pub struct MeteoraDammV2ClosePositionEvent {
pub position_nft_mint: Pubkey,
}
/// Nested dynamic fee parameters matching sol-parser-sdk naming.
pub type MeteoraDammV2DynamicFeeParameters = DynamicFeeParameters;
/// DAMM v2 Update Delegate Permission (IDL `EvtUpdateDelegatePermission`)
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, BorshDeserialize)]
pub struct MeteoraDammV2UpdateDelegatePermissionEvent {
#[borsh(skip)]
pub metadata: EventMetadata,
pub position: Pubkey,
pub owner: Pubkey,
pub permission: u32,
pub delegate: Option<Pubkey>,
}
/// DAMM v2 Withdraw Dead Liquidity Reward (IDL `EvtWithdrawDeadLiquidityReward`)
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, BorshDeserialize)]
pub struct MeteoraDammV2WithdrawDeadLiquidityRewardEvent {
#[borsh(skip)]
pub metadata: EventMetadata,
pub pool: Pubkey,
pub reward_mint: Pubkey,
pub amount: u64,
}
/// DAMM v2 Create Config (IDL `EvtCreateConfig`, includes 0.2.4 `permission`)
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, BorshDeserialize)]
pub struct MeteoraDammV2CreateConfigEvent {
#[borsh(skip)]
pub metadata: EventMetadata,
pub base_fee_data: [u8; 27],
pub compounding_fee_bps: u16,
pub padding: u8,
pub dynamic_fee: Option<MeteoraDammV2DynamicFeeParameters>,
pub vault_config_key: Pubkey,
pub pool_creator_authority: Pubkey,
pub activation_type: u8,
pub sqrt_min_price: u128,
pub sqrt_max_price: u128,
pub collect_fee_mode: u8,
pub index: u64,
pub config: Pubkey,
pub permission: u128,
}
/// DAMM v2 Create Dynamic Config (IDL `EvtCreateDynamicConfig`)
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, BorshDeserialize)]
pub struct MeteoraDammV2CreateDynamicConfigEvent {
#[borsh(skip)]
pub metadata: EventMetadata,
pub config: Pubkey,
pub pool_creator_authority: Pubkey,
pub index: u64,
pub permission: u128,
}
/// Event discriminators
pub mod discriminators {
// Instruction discriminators
@@ -237,16 +237,14 @@ pub struct PumpFunTradeEvent {
pub spendable_quote_in: u64,
#[borsh(skip)]
pub min_tokens_out: u64,
/// User token balance before/after the transaction, in raw mint units.
/// User token-account balance after the transaction, in raw mint units.
#[borsh(skip)]
pub pre_token_balance: Option<u64>,
#[serde(default, alias = "post_token_balance")]
pub token_balance: Option<u64>,
/// User SOL balance after the transaction, in lamports.
#[borsh(skip)]
pub post_token_balance: Option<u64>,
/// User SOL balance before/after the transaction, in lamports.
#[borsh(skip)]
pub pre_sol_balance: Option<u64>,
#[borsh(skip)]
pub post_sol_balance: Option<u64>,
#[serde(default, alias = "post_sol_balance")]
pub sol_balance: Option<u64>,
#[borsh(skip)]
pub quote_token_program: Pubkey,
#[borsh(skip)]
@@ -854,6 +854,58 @@ pub(crate) fn convert_parser_event(
e, meta,
)))
}
PbDexEvent::MeteoraDammV2UpdateDelegatePermission(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::MeteoraDammV2,
EventType::MeteoraDammV2UpdateDelegatePermission,
meteora_damm_program(),
);
Some(DexEvent::MeteoraDammV2UpdateDelegatePermissionEvent(
meteora_damm_v2_update_delegate_permission_from_pb(e, meta),
))
}
PbDexEvent::MeteoraDammV2WithdrawDeadLiquidityReward(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::MeteoraDammV2,
EventType::MeteoraDammV2WithdrawDeadLiquidityReward,
meteora_damm_program(),
);
Some(DexEvent::MeteoraDammV2WithdrawDeadLiquidityRewardEvent(
meteora_damm_v2_withdraw_dead_liquidity_reward_from_pb(e, meta),
))
}
PbDexEvent::MeteoraDammV2CreateConfig(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::MeteoraDammV2,
EventType::MeteoraDammV2CreateConfig,
meteora_damm_program(),
);
Some(DexEvent::MeteoraDammV2CreateConfigEvent(meteora_damm_v2_create_config_from_pb(
e, meta,
)))
}
PbDexEvent::MeteoraDammV2CreateDynamicConfig(e) => {
let meta = adapt_pm(
e.metadata.clone(),
bt,
recv_wall_us,
ProtocolType::MeteoraDammV2,
EventType::MeteoraDammV2CreateDynamicConfig,
meteora_damm_program(),
);
Some(DexEvent::MeteoraDammV2CreateDynamicConfigEvent(
meteora_damm_v2_create_dynamic_config_from_pb(e, meta),
))
}
PbDexEvent::MeteoraDbcSwap(e) => {
let meta = adapt_pm(
+5 -1
View File
@@ -123,7 +123,11 @@ fn protocol_matches_event(p: &Protocol, ev: &DexEvent) -> bool {
| (Protocol::MeteoraDammV2, DexEvent::MeteoraDammV2AddLiquidityEvent(_))
| (Protocol::MeteoraDammV2, DexEvent::MeteoraDammV2RemoveLiquidityEvent(_))
| (Protocol::MeteoraDammV2, DexEvent::MeteoraDammV2CreatePositionEvent(_))
| (Protocol::MeteoraDammV2, DexEvent::MeteoraDammV2ClosePositionEvent(_)) => true,
| (Protocol::MeteoraDammV2, DexEvent::MeteoraDammV2ClosePositionEvent(_))
| (Protocol::MeteoraDammV2, DexEvent::MeteoraDammV2UpdateDelegatePermissionEvent(_))
| (Protocol::MeteoraDammV2, DexEvent::MeteoraDammV2WithdrawDeadLiquidityRewardEvent(_))
| (Protocol::MeteoraDammV2, DexEvent::MeteoraDammV2CreateConfigEvent(_))
| (Protocol::MeteoraDammV2, DexEvent::MeteoraDammV2CreateDynamicConfigEvent(_)) => true,
(Protocol::MeteoraDbc, DexEvent::MeteoraDbcSwapEvent(_))
| (Protocol::MeteoraDbc, DexEvent::MeteoraDbcInitializePoolEvent(_))
| (Protocol::MeteoraDbc, DexEvent::MeteoraDbcCurveCompleteEvent(_)) => true,
@@ -753,10 +753,8 @@ pub(crate) fn pumpfun_trade_from_parser_with_event_type(
spendable_sol_in: t.spendable_sol_in,
spendable_quote_in: t.spendable_quote_in,
min_tokens_out: t.min_tokens_out,
pre_token_balance: t.pre_token_balance,
post_token_balance: t.post_token_balance,
pre_sol_balance: t.pre_sol_balance,
post_sol_balance: t.post_sol_balance,
token_balance: t.token_balance,
sol_balance: t.sol_balance,
..Default::default()
};
DexEvent::PumpFunTradeEvent(st)
@@ -894,13 +892,11 @@ mod tests {
}
#[test]
fn pumpfun_balance_snapshots_are_preserved() {
fn pumpfun_final_balances_are_preserved() {
let ev = pumpfun_trade_from_parser_with_event_type(
sol_parser_sdk::core::events::PumpFunTradeEvent {
pre_token_balance: Some(10),
post_token_balance: Some(25),
pre_sol_balance: Some(1_000),
post_sol_balance: Some(900),
token_balance: Some(25),
sol_balance: Some(900),
..Default::default()
},
None,
@@ -910,10 +906,8 @@ mod tests {
match ev {
DexEvent::PumpFunTradeEvent(t) => {
assert_eq!(t.pre_token_balance, Some(10));
assert_eq!(t.post_token_balance, Some(25));
assert_eq!(t.pre_sol_balance, Some(1_000));
assert_eq!(t.post_sol_balance, Some(900));
assert_eq!(t.token_balance, Some(25));
assert_eq!(t.sol_balance, Some(900));
}
_ => panic!("expected PumpFunTradeEvent"),
}
@@ -2,8 +2,10 @@
use crate::streaming::event_parser::common::EventMetadata;
use crate::streaming::event_parser::protocols::meteora_damm_v2::events::{
MeteoraDammV2AddLiquidityEvent, MeteoraDammV2ClosePositionEvent,
MeteoraDammV2CreatePositionEvent, MeteoraDammV2InitializePoolEvent,
MeteoraDammV2RemoveLiquidityEvent, MeteoraDammV2SwapEvent,
MeteoraDammV2CreateConfigEvent, MeteoraDammV2CreateDynamicConfigEvent,
MeteoraDammV2CreatePositionEvent, MeteoraDammV2DynamicFeeParameters,
MeteoraDammV2InitializePoolEvent, MeteoraDammV2RemoveLiquidityEvent, MeteoraDammV2SwapEvent,
MeteoraDammV2UpdateDelegatePermissionEvent, MeteoraDammV2WithdrawDeadLiquidityRewardEvent,
};
use crate::streaming::event_parser::protocols::raydium_amm_v4::events::{
RaydiumAmmV4DepositEvent, RaydiumAmmV4Initialize2Event, RaydiumAmmV4SwapEvent,
@@ -962,3 +964,77 @@ pub(crate) fn meteora_damm_v2_close_position_from_pb(
position_nft_mint: e.position_nft_mint,
}
}
fn meteora_damm_v2_dynamic_fee_from_pb(
e: sol_parser_sdk::core::events::MeteoraDammV2DynamicFeeParameters,
) -> MeteoraDammV2DynamicFeeParameters {
MeteoraDammV2DynamicFeeParameters {
bin_step: e.bin_step,
bin_step_u128: e.bin_step_u128,
filter_period: e.filter_period,
decay_period: e.decay_period,
reduction_factor: e.reduction_factor,
max_volatility_accumulator: e.max_volatility_accumulator,
variable_fee_control: e.variable_fee_control,
}
}
pub(crate) fn meteora_damm_v2_update_delegate_permission_from_pb(
e: sol_parser_sdk::core::events::MeteoraDammV2UpdateDelegatePermissionEvent,
meta: EventMetadata,
) -> MeteoraDammV2UpdateDelegatePermissionEvent {
MeteoraDammV2UpdateDelegatePermissionEvent {
metadata: meta,
position: e.position,
owner: e.owner,
permission: e.permission,
delegate: e.delegate,
}
}
pub(crate) fn meteora_damm_v2_withdraw_dead_liquidity_reward_from_pb(
e: sol_parser_sdk::core::events::MeteoraDammV2WithdrawDeadLiquidityRewardEvent,
meta: EventMetadata,
) -> MeteoraDammV2WithdrawDeadLiquidityRewardEvent {
MeteoraDammV2WithdrawDeadLiquidityRewardEvent {
metadata: meta,
pool: e.pool,
reward_mint: e.reward_mint,
amount: e.amount,
}
}
pub(crate) fn meteora_damm_v2_create_config_from_pb(
e: sol_parser_sdk::core::events::MeteoraDammV2CreateConfigEvent,
meta: EventMetadata,
) -> MeteoraDammV2CreateConfigEvent {
MeteoraDammV2CreateConfigEvent {
metadata: meta,
base_fee_data: e.base_fee_data,
compounding_fee_bps: e.compounding_fee_bps,
padding: e.padding,
dynamic_fee: e.dynamic_fee.map(meteora_damm_v2_dynamic_fee_from_pb),
vault_config_key: e.vault_config_key,
pool_creator_authority: e.pool_creator_authority,
activation_type: e.activation_type,
sqrt_min_price: e.sqrt_min_price,
sqrt_max_price: e.sqrt_max_price,
collect_fee_mode: e.collect_fee_mode,
index: e.index,
config: e.config,
permission: e.permission,
}
}
pub(crate) fn meteora_damm_v2_create_dynamic_config_from_pb(
e: sol_parser_sdk::core::events::MeteoraDammV2CreateDynamicConfigEvent,
meta: EventMetadata,
) -> MeteoraDammV2CreateDynamicConfigEvent {
MeteoraDammV2CreateDynamicConfigEvent {
metadata: meta,
config: e.config,
pool_creator_authority: e.pool_creator_authority,
index: e.index,
permission: e.permission,
}
}