-- file: validation_sql/SQL_VALIDATION_PUMP_FEES_0_7_55.sql -- 0.7.55 pump_fees validation and corpus-seed checklist. -- Run on a dedicated fresh SQLite database for the Pump Fees tranche. -- Recommended replay settings after each backfill group: -- skipDexDecode=no, forceDexDecode=yes, deferInstructionObservations=yes. -- This file is intentionally read-only: it never mutates the database. -- 00. Corpus seed: upstream fallback samples to backfill first. SELECT json_extract(de.payload_json, '$.upstreamEntryName') AS upstream_entry_name, json_extract(de.payload_json, '$.upstreamDiscriminatorHex') AS upstream_discriminator_hex, COUNT(*) AS fallback_count, COUNT(DISTINCT de.transaction_id) AS tx_count, MIN(tx.signature) AS sample_signature FROM k_sol_dex_decoded_events de LEFT JOIN k_sol_chain_transactions tx ON tx.id = de.transaction_id WHERE de.protocol_name = 'upstream_git' AND de.event_kind = 'upstream_git.instruction_match' AND json_extract(de.payload_json, '$.upstreamDecoderCode') = 'pump_fees' GROUP BY upstream_entry_name, upstream_discriminator_hex ORDER BY fallback_count DESC, upstream_entry_name, upstream_discriminator_hex; -- 01. Corpus seed: local instruction observations. SELECT instruction_name, discriminator_hex, COUNT(*) AS observed_count, COUNT(DISTINCT signature) AS tx_count, MIN(signature) AS sample_signature FROM k_sol_instruction_observations WHERE decoder_code = 'pump_fees' GROUP BY instruction_name, discriminator_hex ORDER BY observed_count DESC, instruction_name, discriminator_hex; -- 01b. Local instruction observations with missing Pump Fees instruction name. -- Target after closure: empty, including the Anchor self-CPI log discriminator. SELECT decoder_code, discriminator_hex, COUNT(*) AS observed_count, COUNT(DISTINCT signature) AS tx_count, MIN(signature) AS sample_signature FROM k_sol_instruction_observations WHERE decoder_code = 'pump_fees' AND ( instruction_name IS NULL OR TRIM(instruction_name) = '' ) GROUP BY decoder_code, discriminator_hex ORDER BY observed_count DESC, discriminator_hex; -- 02. Coverage pump_fees. SELECT entry_name, entry_kind, event_family, expected_db_target, proof_status, local_event_kind, discriminator_hex, observed_count, materialized_count, trade_count FROM k_sol_dex_event_coverage_entries WHERE decoder_code = 'pump_fees' ORDER BY entry_kind, entry_name, discriminator_hex; -- 02b. Coverage rows with unknown or blank event_family. -- Target after closure: empty for pump_fees. Program/account rows may be NULL, but must not be unknown. SELECT entry_name, entry_kind, event_family, expected_db_target, proof_status, local_event_kind, discriminator_hex FROM k_sol_dex_event_coverage_entries WHERE decoder_code = 'pump_fees' AND ( LOWER(COALESCE(TRIM(event_family), '')) = 'unknown' OR (entry_kind NOT IN ('program', 'account') AND COALESCE(TRIM(event_family), '') = '') ) ORDER BY entry_kind, entry_name, discriminator_hex; -- 03. Decoded events summary. SELECT de.event_kind, COUNT(*) AS decoded_count, COUNT(DISTINCT de.transaction_id) AS tx_count, MIN(tx.signature) AS sample_signature FROM k_sol_dex_decoded_events de LEFT JOIN k_sol_chain_transactions tx ON tx.id = de.transaction_id WHERE de.protocol_name = 'pump_fees' GROUP BY de.event_kind ORDER BY decoded_count DESC, de.event_kind; -- 04. Decoded pump_fees events without coverage. -- Target after closure: empty for all locally decoded pump_fees rows. SELECT de.event_kind, COUNT(*) AS decoded_count, COUNT(DISTINCT de.transaction_id) AS tx_count, MIN(tx.signature) AS sample_signature FROM k_sol_dex_decoded_events de LEFT JOIN k_sol_chain_transactions tx ON tx.id = de.transaction_id LEFT JOIN k_sol_dex_event_coverage_entries ce ON ce.decoder_code = 'pump_fees' AND ce.local_event_kind = de.event_kind WHERE de.protocol_name = 'pump_fees' AND ce.id IS NULL GROUP BY de.event_kind ORDER BY decoded_count DESC, de.event_kind; -- 05. Residual upstream fallback for covered local entries. -- Target after local promotion: empty for every entry that has a local_event_kind. SELECT json_extract(ug.payload_json, '$.upstreamEntryName') AS upstream_entry_name, json_extract(ug.payload_json, '$.upstreamDiscriminatorHex') AS upstream_discriminator_hex, json_extract(ug.payload_json, '$.upstreamSourceRepo') AS source_repo, ce.local_event_kind, ce.expected_db_target, ce.proof_status, COUNT(*) AS fallback_count, COUNT(DISTINCT ug.transaction_id) AS tx_count, MIN(tx.signature) AS sample_signature FROM k_sol_dex_decoded_events ug LEFT JOIN k_sol_chain_transactions tx ON tx.id = ug.transaction_id JOIN k_sol_dex_event_coverage_entries ce ON ce.decoder_code = json_extract(ug.payload_json, '$.upstreamDecoderCode') AND ce.entry_name = json_extract(ug.payload_json, '$.upstreamEntryName') AND ce.discriminator_hex = json_extract(ug.payload_json, '$.upstreamDiscriminatorHex') AND ce.local_event_kind IS NOT NULL AND ce.local_event_kind <> '' WHERE ug.protocol_name = 'upstream_git' AND ug.event_kind = 'upstream_git.instruction_match' AND json_extract(ug.payload_json, '$.upstreamDecoderCode') = 'pump_fees' GROUP BY upstream_entry_name, upstream_discriminator_hex, source_repo, ce.local_event_kind, ce.expected_db_target, ce.proof_status ORDER BY fallback_count DESC, upstream_entry_name; -- 06. Successful non-materialized events without explicit skip reason. -- Target after closure: empty, except decoded-only/audit-only rows with informational policy. SELECT de.event_kind, json_extract(de.payload_json, '$.pumpFeesMaterializationPolicy') AS pump_fees_policy, COUNT(*) AS unexplained_count, MIN(tx.signature) AS sample_signature FROM k_sol_dex_decoded_events de JOIN k_sol_chain_transactions tx ON tx.id = de.transaction_id LEFT JOIN k_sol_trade_events te ON te.decoded_event_id = de.id LEFT JOIN k_sol_launch_events lae ON lae.decoded_event_id = de.id LEFT JOIN k_sol_liquidity_events lie ON lie.decoded_event_id = de.id LEFT JOIN k_sol_pool_lifecycle_events ple ON ple.decoded_event_id = de.id LEFT JOIN k_sol_fee_events fee ON fee.decoded_event_id = de.id LEFT JOIN k_sol_reward_events rew ON rew.decoded_event_id = de.id LEFT JOIN k_sol_pool_admin_events adm ON adm.decoded_event_id = de.id LEFT JOIN k_sol_orderbook_events obe ON obe.decoded_event_id = de.id LEFT JOIN k_sol_token_account_events tae ON tae.decoded_event_id = de.id WHERE de.protocol_name = 'pump_fees' AND ( tx.err_json IS NULL OR tx.err_json = '' OR tx.err_json = 'null' ) AND COALESCE(json_extract(de.payload_json, '$.eventActionability'), '') <> 'informational' AND COALESCE(json_extract(de.payload_json, '$.pumpFeesMaterializationPolicy'), '') NOT IN ( 'decoded_only_fee_calculation', 'decoded_only_audit' ) AND te.id IS NULL AND lae.id IS NULL AND lie.id IS NULL AND ple.id IS NULL AND fee.id IS NULL AND rew.id IS NULL AND adm.id IS NULL AND obe.id IS NULL AND tae.id IS NULL AND COALESCE(TRIM(json_extract(de.payload_json, '$.skipTradeReason')), '') = '' AND COALESCE(TRIM(json_extract(de.payload_json, '$.skipCandleReason')), '') = '' AND COALESCE(TRIM(json_extract(de.payload_json, '$.skipLiquidityReason')), '') = '' AND COALESCE(TRIM(json_extract(de.payload_json, '$.skipLifecycleReason')), '') = '' AND COALESCE(TRIM(json_extract(de.payload_json, '$.skipCatalogReason')), '') = '' GROUP BY de.event_kind, pump_fees_policy ORDER BY unexplained_count DESC, de.event_kind; -- 07. Failed transaction materialization safety. -- Target after closure: empty. Failed transactions may be decoded for audit, but must not be business-materialized. SELECT de.event_kind, COUNT(DISTINCT de.id) AS decoded_failed_count, COUNT(DISTINCT te.id) AS trade_count, COUNT(DISTINCT lae.id) AS launch_count, COUNT(DISTINCT lie.id) AS liquidity_count, COUNT(DISTINCT ple.id) AS lifecycle_count, COUNT(DISTINCT fee.id) AS fee_count, COUNT(DISTINCT rew.id) AS reward_count, COUNT(DISTINCT adm.id) AS admin_count, COUNT(DISTINCT obe.id) AS orderbook_count, COUNT(DISTINCT tae.id) AS token_account_count, MIN(tx.signature) AS sample_signature FROM k_sol_dex_decoded_events de JOIN k_sol_chain_transactions tx ON tx.id = de.transaction_id LEFT JOIN k_sol_trade_events te ON te.decoded_event_id = de.id LEFT JOIN k_sol_launch_events lae ON lae.decoded_event_id = de.id LEFT JOIN k_sol_liquidity_events lie ON lie.decoded_event_id = de.id LEFT JOIN k_sol_pool_lifecycle_events ple ON ple.decoded_event_id = de.id LEFT JOIN k_sol_fee_events fee ON fee.decoded_event_id = de.id LEFT JOIN k_sol_reward_events rew ON rew.decoded_event_id = de.id LEFT JOIN k_sol_pool_admin_events adm ON adm.decoded_event_id = de.id LEFT JOIN k_sol_orderbook_events obe ON obe.decoded_event_id = de.id LEFT JOIN k_sol_token_account_events tae ON tae.decoded_event_id = de.id WHERE de.protocol_name = 'pump_fees' AND tx.err_json IS NOT NULL AND tx.err_json <> '' AND tx.err_json <> 'null' GROUP BY de.event_kind HAVING trade_count > 0 OR launch_count > 0 OR liquidity_count > 0 OR lifecycle_count > 0 OR fee_count > 0 OR reward_count > 0 OR admin_count > 0 OR orderbook_count > 0 OR token_account_count > 0 ORDER BY de.event_kind; -- 08. Multi-target materialization safety. -- Target after closure: empty. One decoded event must not feed multiple business targets. SELECT de.event_kind, COUNT(DISTINCT de.id) AS decoded_count, COUNT(DISTINCT te.id) AS trade_count, COUNT(DISTINCT lae.id) AS launch_count, COUNT(DISTINCT lie.id) AS liquidity_count, COUNT(DISTINCT ple.id) AS lifecycle_count, COUNT(DISTINCT fee.id) AS fee_count, COUNT(DISTINCT rew.id) AS reward_count, COUNT(DISTINCT adm.id) AS admin_count, COUNT(DISTINCT obe.id) AS orderbook_count, COUNT(DISTINCT tae.id) AS token_account_count, ( CASE WHEN COUNT(DISTINCT te.id) > 0 THEN 1 ELSE 0 END + CASE WHEN COUNT(DISTINCT lae.id) > 0 THEN 1 ELSE 0 END + CASE WHEN COUNT(DISTINCT lie.id) > 0 THEN 1 ELSE 0 END + CASE WHEN COUNT(DISTINCT ple.id) > 0 THEN 1 ELSE 0 END + CASE WHEN COUNT(DISTINCT fee.id) > 0 THEN 1 ELSE 0 END + CASE WHEN COUNT(DISTINCT rew.id) > 0 THEN 1 ELSE 0 END + CASE WHEN COUNT(DISTINCT adm.id) > 0 THEN 1 ELSE 0 END + CASE WHEN COUNT(DISTINCT obe.id) > 0 THEN 1 ELSE 0 END + CASE WHEN COUNT(DISTINCT tae.id) > 0 THEN 1 ELSE 0 END ) AS materialized_target_count FROM k_sol_dex_decoded_events de LEFT JOIN k_sol_trade_events te ON te.decoded_event_id = de.id LEFT JOIN k_sol_launch_events lae ON lae.decoded_event_id = de.id LEFT JOIN k_sol_liquidity_events lie ON lie.decoded_event_id = de.id LEFT JOIN k_sol_pool_lifecycle_events ple ON ple.decoded_event_id = de.id LEFT JOIN k_sol_fee_events fee ON fee.decoded_event_id = de.id LEFT JOIN k_sol_reward_events rew ON rew.decoded_event_id = de.id LEFT JOIN k_sol_pool_admin_events adm ON adm.decoded_event_id = de.id LEFT JOIN k_sol_orderbook_events obe ON obe.decoded_event_id = de.id LEFT JOIN k_sol_token_account_events tae ON tae.decoded_event_id = de.id WHERE de.protocol_name = 'pump_fees' GROUP BY de.event_kind HAVING materialized_target_count > 1 ORDER BY materialized_target_count DESC, de.event_kind; -- 09. Materialization summary by table. -- Failed transaction columns explain observed/materialized gaps without reopening failed-tx rows. SELECT de.event_kind, COUNT(DISTINCT de.id) AS decoded_count, COUNT(DISTINCT CASE WHEN tx.err_json IS NULL OR tx.err_json = '' OR tx.err_json = 'null' THEN de.transaction_id END) AS successful_tx_count, COUNT(DISTINCT CASE WHEN tx.err_json IS NOT NULL AND tx.err_json <> '' AND tx.err_json <> 'null' THEN de.transaction_id END) AS failed_tx_count, COUNT(DISTINCT te.id) AS trade_count, COUNT(DISTINCT lae.id) AS launch_count, COUNT(DISTINCT lie.id) AS liquidity_count, COUNT(DISTINCT ple.id) AS lifecycle_count, COUNT(DISTINCT fee.id) AS fee_count, COUNT(DISTINCT rew.id) AS reward_count, COUNT(DISTINCT adm.id) AS admin_count, COUNT(DISTINCT obe.id) AS orderbook_count, COUNT(DISTINCT tae.id) AS token_account_count, COUNT(DISTINCT CASE WHEN te.id IS NOT NULL OR lae.id IS NOT NULL OR lie.id IS NOT NULL OR ple.id IS NOT NULL OR fee.id IS NOT NULL OR rew.id IS NOT NULL OR adm.id IS NOT NULL OR obe.id IS NOT NULL OR tae.id IS NOT NULL THEN de.id END) AS business_materialized_count, COUNT(DISTINCT CASE WHEN (tx.err_json IS NULL OR tx.err_json = '' OR tx.err_json = 'null') AND te.id IS NULL AND lae.id IS NULL AND lie.id IS NULL AND ple.id IS NULL AND fee.id IS NULL AND rew.id IS NULL AND adm.id IS NULL AND obe.id IS NULL AND tae.id IS NULL THEN de.id END) AS successful_non_materialized_count, COUNT(DISTINCT CASE WHEN tx.err_json IS NOT NULL AND tx.err_json <> '' AND tx.err_json <> 'null' AND te.id IS NULL AND lae.id IS NULL AND lie.id IS NULL AND ple.id IS NULL AND fee.id IS NULL AND rew.id IS NULL AND adm.id IS NULL AND obe.id IS NULL AND tae.id IS NULL THEN de.id END) AS failed_non_materialized_count FROM k_sol_dex_decoded_events de JOIN k_sol_chain_transactions tx ON tx.id = de.transaction_id LEFT JOIN k_sol_trade_events te ON te.decoded_event_id = de.id LEFT JOIN k_sol_launch_events lae ON lae.decoded_event_id = de.id LEFT JOIN k_sol_liquidity_events lie ON lie.decoded_event_id = de.id LEFT JOIN k_sol_pool_lifecycle_events ple ON ple.decoded_event_id = de.id LEFT JOIN k_sol_fee_events fee ON fee.decoded_event_id = de.id LEFT JOIN k_sol_reward_events rew ON rew.decoded_event_id = de.id LEFT JOIN k_sol_pool_admin_events adm ON adm.decoded_event_id = de.id LEFT JOIN k_sol_orderbook_events obe ON obe.decoded_event_id = de.id LEFT JOIN k_sol_token_account_events tae ON tae.decoded_event_id = de.id WHERE de.protocol_name = 'pump_fees' GROUP BY de.event_kind ORDER BY de.event_kind; -- 09b. Coverage rows with observed/materialized gaps explained by failed transactions. -- Target after closure: any remaining successful_non_materialized_count is policy/skip-explained by query 06. SELECT ce.entry_name, ce.entry_kind, ce.local_event_kind, ce.expected_db_target, ce.proof_status, ce.observed_count AS coverage_observed_count, ce.materialized_count AS coverage_materialized_count, COUNT(DISTINCT de.id) AS decoded_count, COUNT(DISTINCT CASE WHEN tx.err_json IS NULL OR tx.err_json = '' OR tx.err_json = 'null' THEN de.id END) AS successful_decoded_count, COUNT(DISTINCT CASE WHEN tx.err_json IS NOT NULL AND tx.err_json <> '' AND tx.err_json <> 'null' THEN de.id END) AS failed_decoded_count, COUNT(DISTINCT CASE WHEN te.id IS NOT NULL OR lae.id IS NOT NULL OR lie.id IS NOT NULL OR ple.id IS NOT NULL OR fee.id IS NOT NULL OR rew.id IS NOT NULL OR adm.id IS NOT NULL OR obe.id IS NOT NULL OR tae.id IS NOT NULL THEN de.id END) AS business_materialized_count, COUNT(DISTINCT CASE WHEN (tx.err_json IS NULL OR tx.err_json = '' OR tx.err_json = 'null') AND te.id IS NULL AND lae.id IS NULL AND lie.id IS NULL AND ple.id IS NULL AND fee.id IS NULL AND rew.id IS NULL AND adm.id IS NULL AND obe.id IS NULL AND tae.id IS NULL THEN de.id END) AS successful_non_materialized_count, MIN(tx.signature) AS sample_signature FROM k_sol_dex_event_coverage_entries ce LEFT JOIN k_sol_dex_decoded_events de ON de.protocol_name = 'pump_fees' AND de.event_kind = ce.local_event_kind LEFT JOIN k_sol_chain_transactions tx ON tx.id = de.transaction_id LEFT JOIN k_sol_trade_events te ON te.decoded_event_id = de.id LEFT JOIN k_sol_launch_events lae ON lae.decoded_event_id = de.id LEFT JOIN k_sol_liquidity_events lie ON lie.decoded_event_id = de.id LEFT JOIN k_sol_pool_lifecycle_events ple ON ple.decoded_event_id = de.id LEFT JOIN k_sol_fee_events fee ON fee.decoded_event_id = de.id LEFT JOIN k_sol_reward_events rew ON rew.decoded_event_id = de.id LEFT JOIN k_sol_pool_admin_events adm ON adm.decoded_event_id = de.id LEFT JOIN k_sol_orderbook_events obe ON obe.decoded_event_id = de.id LEFT JOIN k_sol_token_account_events tae ON tae.decoded_event_id = de.id WHERE ce.decoder_code = 'pump_fees' AND ce.entry_kind IN ('instruction', 'event') AND ce.local_event_kind IS NOT NULL AND ce.local_event_kind <> '' GROUP BY ce.entry_name, ce.entry_kind, ce.local_event_kind, ce.expected_db_target, ce.proof_status, ce.observed_count, ce.materialized_count HAVING coverage_observed_count <> coverage_materialized_count OR successful_non_materialized_count > 0 OR failed_decoded_count > 0 ORDER BY successful_non_materialized_count DESC, failed_decoded_count DESC, ce.entry_kind, ce.entry_name; -- 10. Instruction observation versus coverage. -- Target after closure: every observed non-transport discriminator is covered or documented. WITH normalized_io AS ( SELECT io.decoder_code, io.instruction_name, CASE WHEN io.instruction_name LIKE 'pump_fees.%' THEN SUBSTR(io.instruction_name, LENGTH('pump_fees') + 2) ELSE io.instruction_name END AS normalized_entry_name, io.discriminator_hex, io.signature FROM k_sol_instruction_observations io WHERE io.decoder_code = 'pump_fees' AND io.discriminator_hex IS NOT NULL AND io.discriminator_hex <> '' AND io.discriminator_hex <> 'e445a52e51cb9a1d' ) SELECT nio.instruction_name, nio.normalized_entry_name, nio.discriminator_hex, COUNT(*) AS observed_count, COUNT(DISTINCT nio.signature) AS tx_count, MIN(nio.signature) AS sample_signature, CASE WHEN ce.id IS NULL THEN 'coverage_gap' ELSE 'covered' END AS observation_coverage_status, ce.local_event_kind, ce.expected_db_target, ce.proof_status FROM normalized_io nio LEFT JOIN k_sol_dex_event_coverage_entries ce ON ce.decoder_code = 'pump_fees' AND COALESCE(ce.discriminator_hex, '') = COALESCE(nio.discriminator_hex, '') AND ( COALESCE(TRIM(nio.instruction_name), '') = '' OR ce.entry_name = nio.instruction_name OR ce.entry_name = nio.normalized_entry_name OR ce.local_event_kind = nio.instruction_name OR ce.local_event_kind = ('pump_fees.' || nio.normalized_entry_name) ) GROUP BY nio.instruction_name, nio.normalized_entry_name, nio.discriminator_hex, observation_coverage_status, ce.local_event_kind, ce.expected_db_target, ce.proof_status ORDER BY observed_count DESC, nio.instruction_name, nio.discriminator_hex; -- 11. Anti-trade/candle direct pump_fees control. -- Target after closure: empty. pump_fees must not create trade/candle rows without strict proof. SELECT de.event_kind, COUNT(DISTINCT te.id) AS trade_count, MIN(tx.signature) AS sample_signature FROM k_sol_dex_decoded_events de LEFT JOIN k_sol_chain_transactions tx ON tx.id = de.transaction_id LEFT JOIN k_sol_trade_events te ON te.decoded_event_id = de.id WHERE de.protocol_name = 'pump_fees' GROUP BY de.event_kind HAVING trade_count > 0 ORDER BY trade_count DESC, de.event_kind; -- 12. Global watchlist after pump_fees replay. -- Expected after local promotion: pump_fees rows should no longer dominate this list unless explicitly deferred. SELECT json_extract(de.payload_json, '$.upstreamDecoderCode') AS upstream_decoder_code, json_extract(de.payload_json, '$.upstreamEntryName') AS upstream_entry_name, json_extract(de.payload_json, '$.upstreamDiscriminatorHex') AS upstream_discriminator_hex, COUNT(*) AS decoded_count, COUNT(DISTINCT de.transaction_id) AS tx_count, MIN(tx.signature) AS sample_signature FROM k_sol_dex_decoded_events de LEFT JOIN k_sol_chain_transactions tx ON tx.id = de.transaction_id WHERE de.protocol_name = 'upstream_git' AND de.event_kind = 'upstream_git.instruction_match' GROUP BY upstream_decoder_code, upstream_entry_name, upstream_discriminator_hex ORDER BY decoded_count DESC, upstream_decoder_code, upstream_entry_name; -- 13. Local-IDL-only pump_fees entries. -- Target after coverage sync: these local IDL rows are present and mapped to local_event_kind. SELECT ce.entry_name, ce.entry_kind, ce.discriminator_hex, ce.source_repo, ce.source_path, ce.local_event_kind, ce.expected_db_target, ce.proof_status, ce.observed_count, ce.materialized_count, ce.trade_count FROM k_sol_dex_event_coverage_entries ce WHERE ce.decoder_code = 'pump_fees' AND ce.source_repo = 'local-idl' ORDER BY ce.entry_kind, ce.entry_name; -- 14. Anchor event coverage local kind check. -- Target after decoder delta: every Pump Fees event registry row has a local_event_kind. SELECT ce.entry_name, ce.discriminator_hex, ce.local_event_kind, ce.expected_db_target, ce.proof_status, ce.observed_count, ce.materialized_count FROM k_sol_dex_event_coverage_entries ce WHERE ce.decoder_code = 'pump_fees' AND ce.entry_kind = 'event' AND ( ce.local_event_kind IS NULL OR TRIM(ce.local_event_kind) = '' ) ORDER BY ce.entry_name; -- 15. Decoded Anchor events summary. SELECT de.event_kind, json_extract(de.payload_json, '$.eventName') AS anchor_event_name, json_extract(de.payload_json, '$.discriminatorHex') AS anchor_event_discriminator_hex, COUNT(*) AS decoded_count, COUNT(DISTINCT de.transaction_id) AS tx_count, MIN(tx.signature) AS sample_signature FROM k_sol_dex_decoded_events de LEFT JOIN k_sol_chain_transactions tx ON tx.id = de.transaction_id WHERE de.protocol_name = 'pump_fees' AND COALESCE(TRIM(json_extract(de.payload_json, '$.eventName')), '') <> '' GROUP BY de.event_kind, anchor_event_name, anchor_event_discriminator_hex ORDER BY decoded_count DESC, de.event_kind;