This commit is contained in:
2026-06-08 12:32:58 +02:00
parent f81e0f3bea
commit f2ea1a392f
55 changed files with 7993 additions and 306 deletions

View File

@@ -80,3 +80,7 @@
0.7.47 - Upstream Git Registry / DEX discovery preparation : registre générique `upstream_git`, extension Demo3 aux targets multi-surfaces, premiers decoders audit-only OpenBook v2 et Phoenix v1, matrices DEX/event coverage, revue DB et invariant maintenu : aucune entrée upstream ne produit trade/candle sans decoder spécialisé et corpus local. 0.7.47 - Upstream Git Registry / DEX discovery preparation : registre générique `upstream_git`, extension Demo3 aux targets multi-surfaces, premiers decoders audit-only OpenBook v2 et Phoenix v1, matrices DEX/event coverage, revue DB et invariant maintenu : aucune entrée upstream ne produit trade/candle sans decoder spécialisé et corpus local.
0.7.48 - Raydium CPMM event coverage clôturé : couverture instructions/events CPMM Carbon/Raydium/fnzero, table coverage synchronisée, `k_sol_instruction_observations`, recherche Demo3 par instruction/discriminant, matérialisation validée des swaps, lifecycle, fees, admin/config, deposit/withdraw et `lp_change_event`, `swap_event` audit-only, fallback upstream remplacé quand le decoder local couvre lentrée. 0.7.48 - Raydium CPMM event coverage clôturé : couverture instructions/events CPMM Carbon/Raydium/fnzero, table coverage synchronisée, `k_sol_instruction_observations`, recherche Demo3 par instruction/discriminant, matérialisation validée des swaps, lifecycle, fees, admin/config, deposit/withdraw et `lp_change_event`, `swap_event` audit-only, fallback upstream remplacé quand le decoder local couvre lentrée.
0.7.49 - Raydium CLMM event coverage clôturé : 45 entrées listées, 33 instructions locales observées/décodées, 25 entrées matérialisées, ajout `k_sol_orderbook_events`, matérialisation des limit orders, liquidity, fees, rewards, admin/config et lifecycle prouvés par corpus, préparation audit-only des 11 Anchor Program-data events non observés, nettoyage des `raydium_clmm.instruction_audit` et `upstream_git.instruction_match` redondants, validation des invariants failed transaction / non-swap / trade-candle. 0.7.49 - Raydium CLMM event coverage clôturé : 45 entrées listées, 33 instructions locales observées/décodées, 25 entrées matérialisées, ajout `k_sol_orderbook_events`, matérialisation des limit orders, liquidity, fees, rewards, admin/config et lifecycle prouvés par corpus, préparation audit-only des 11 Anchor Program-data events non observés, nettoyage des `raydium_clmm.instruction_audit` et `upstream_git.instruction_match` redondants, validation des invariants failed transaction / non-swap / trade-candle.
0.7.50-pre3 - Raydium Launchpad self-CPI/pool catalog correction : ajout du preset Demo3 `raydium_launchpad`, décodage direct des self-CPI Launchpad `trade_event` et `pool_create_event`, correction des indices `initialize*` (`pool_state=5`, `base_mint=6`, `quote_mint=7`) et routage des `initialize*` vers la matérialisation catalogue pool/pair Launchpad sans promotion trade/candle.
0.7.50 - Raydium Launchpad event coverage bootstrap : normalisation locale canonique vers `raydium_launchpad`, ajout de `RAYDIUM_LAUNCHPAD_PROGRAM_ID`, synchronisation des entrées Carbon Launchpad dans le registre upstream, fallback audit/mapped decoder pour discriminants Launchpad, enrichissement audit Anchor self-CPI, maintien conservatoire en `decoded_events_only`, rapport Launchpad et SQL de validation dédiés.
0.7.50-pre-r2 - Clôture CPMM/CLMM post-Launchpad : ajout des entrées Carbon `cpi_event` pour `raydium_cpmm` et `raydium_clmm`, ajout de `raydium_clmm.update_dynamic_fee_config`, normalisation des Program-data events CLMM, ajout de la table `k_sol_token_account_events` et de la matérialisation `create_support_mint_associated`, reclassement des familles ambiguës (`cpi_transport`, `liquidity_calculation`, `liquidity_change`, `position_open`, `pool_create`, `admin_config`, `account_create`, `idl_management`), codage du discriminant CPMM `40f4bc78a7e9690a` comme `raydium_cpmm.anchor_idl_instruction` decoded-only après inspection Solscan, et contexte de secours pour matérialisation liquidity CLMM via événements frères quand possible.
0.7.50-final - Clôture Raydium Launchpad et recheck Raydium : correction FK-safe du cleanup `raydium_cpmm.instruction_audit` pour le discriminant `40f4bc78a7e9690a`, conservation de `raydium_cpmm.anchor_idl_instruction` en decoded-only, suppression attendue des decoded events CPMM sans ligne coverage, documentation finale Launchpad/CPMM/CLMM et prompt de reprise `0.7.51 raydium_amm_v4`.

View File

@@ -8,7 +8,7 @@ members = [
] ]
[workspace.package] [workspace.package]
version = "0.7.49" version = "0.7.50"
edition = "2024" edition = "2024"
license = "MIT" license = "MIT"
repository = "https://git.sasedev.com/Sasedev/khadhroony-bobobot" repository = "https://git.sasedev.com/Sasedev/khadhroony-bobobot"

View File

@@ -29,7 +29,7 @@ non-swap CLMM avec trade_count > 0 = 0
Les 11 Anchor / `Program data` events CLMM restent listés en `upstream_git_unverified` car aucun corpus local ne les observe encore. Le code est préparé pour les accueillir en audit-only lorsquils apparaîtront dans un corpus local, sans créer de trade/candle par défaut. Les 11 Anchor / `Program data` events CLMM restent listés en `upstream_git_unverified` car aucun corpus local ne les observe encore. Le code est préparé pour les accueillir en audit-only lorsquils apparaîtront dans un corpus local, sans créer de trade/candle par défaut.
La prochaine tranche fonctionnelle est `0.7.50 raydium_launchpad`, avant `0.7.51 raydium_amm_v4` et `0.7.52 raydium_stable`. La tranche fonctionnelle ouverte est `0.7.50-pre-r2`, dédiée à la clôture Raydium Launchpad puis à la re-vérification CPMM/CLMM, avant `0.7.51 raydium_amm_v4` et `0.7.52 raydium_stable`. `raydium_pool_v4` reste un audit conditionnel `0.7.53` et ne doit pas être promu sans confirmation de program id/rôle/corpus.
## Organisation documentaire ## Organisation documentaire
@@ -257,7 +257,7 @@ Chaque DEX ou variante de DEX doit avoir sa propre étape de validation. Les fam
À reprendre après les DEX effectifs, sauf si une surface est indispensable pour comprendre une migration vers un pool tradable : À reprendre après les DEX effectifs, sauf si une surface est indispensable pour comprendre une migration vers un pool tradable :
- `pump_fun` ; - `pump_fun` ;
- `raydium_launchlab` ; - `raydium_launchpad` ;
- `letsbonk` / `bonk_fun` ; - `letsbonk` / `bonk_fun` ;
- `bags` ; - `bags` ;
- `moonshot` ; - `moonshot` ;
@@ -382,12 +382,13 @@ La priorité immédiate après le point de reprise `0.7.43-E5C` est :
1. `0.7.48` : `raydium_cpmm` — clôturé côté event coverage ; 1. `0.7.48` : `raydium_cpmm` — clôturé côté event coverage ;
2. `0.7.49` : `raydium_clmm` — clôturé côté instructions observées, matérialisation non-trade prouvée et nettoyage fallback ; 2. `0.7.49` : `raydium_clmm` — clôturé côté instructions observées, matérialisation non-trade prouvée et nettoyage fallback ;
3. `0.7.50` : `raydium_launchpad` ; 3. `0.7.50-pre-r2` : `raydium_launchpad` clos + re-vérification `raydium_cpmm` / `raydium_clmm` ;
4. `0.7.51` : `raydium_amm_v4` ; 4. `0.7.51` : `raydium_amm_v4` ;
5. `0.7.52` : `raydium_stable` ; 5. `0.7.52` : `raydium_stable` ;
6. `0.7.53` : `pump_swap` ; 6. `0.7.53` : `raydium_pool_v4` audit / program-id decision seulement si program id distinct et corpus exploitable ;
7. `0.7.54` : `pump_fun` ; 7. `0.7.54` : `pump_swap` ;
8. `0.7.55+` : Meteora, Phoenix/OpenBook, Orca puis validation progressive des autres DEX/surfaces issus du registre upstream Git. 8. `0.7.55` : `pump_fun` ;
9. `0.7.56+` : Meteora, Phoenix/OpenBook, Orca puis validation progressive des autres DEX/surfaces issus du registre upstream Git.
Garde-fous constants : Garde-fous constants :
@@ -494,10 +495,11 @@ La suite fonctionnelle reprend par Raydium avant Meteora :
1. `0.7.48``raydium_cpmm` ; 1. `0.7.48``raydium_cpmm` ;
2. `0.7.49``raydium_clmm` ; 2. `0.7.49``raydium_clmm` ;
3. `0.7.50``raydium_launchpad` ; 3. `0.7.50-pre-r2``raydium_launchpad` + clôture CPMM/CLMM ;
4. `0.7.51``raydium_amm_v4` ; 4. `0.7.51``raydium_amm_v4` ;
5. `0.7.52``raydium_stable` ; 5. `0.7.52``raydium_stable` ;
6. `0.7.53+`Pump, Meteora, Phoenix/OpenBook, Orca puis les autres DEX/surfaces. 6. `0.7.53``raydium_pool_v4` audit conditionnel, sans promotion automatique ;
7. `0.7.54+` — Pump, Meteora, Phoenix/OpenBook, Orca puis les autres DEX/surfaces.
## Note 0.7.48 — Raydium CPMM event coverage ## Note 0.7.48 — Raydium CPMM event coverage
@@ -553,3 +555,54 @@ Points finalisés :
La validation finale est dans `validation_sql/SQL_VALIDATION_RAYDIUM_CLMM_0_7_49.sql`. La validation finale est dans `validation_sql/SQL_VALIDATION_RAYDIUM_CLMM_0_7_49.sql`.
## Note 0.7.50 — Raydium Launchpad event coverage bootstrap
La tranche `0.7.50` ouvre `raydium_launchpad` comme troisième tranche Raydium après CPMM et CLMM. Le code local canonique est `raydium_launchpad`. Le program id canonique est `LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj`.
Points préparés dans le bootstrap :
- normalisation des entrées launch surface, DEX support matrix, catalogue et registre upstream vers `raydium_launchpad` ;
- ajout de `RAYDIUM_LAUNCHPAD_PROGRAM_ID` ;
- inventaire initial de `1` entrée programme et `26` entrées discriminées Carbon/IDL ;
- fallback `raydium_launchpad.instruction_audit` pour les instructions non mappées, avec enrichissement Anchor self-CPI (`e445a52e51cb9a1d`) ;
- mapping conservatoire des discriminants Launchpad vers `raydium_launchpad.<entry_name>` ;
- cible coverage initiale forcée à `decoded_events_only`, y compris pour buy/sell/trade/migration, afin d'éviter toute fausse trade/candle avant corpus local ;
- rapport `docs/reports/RAYDIUM_LAUNCHPAD_EVENT_COVERAGE_REPORT.md` ;
- SQL `validation_sql/SQL_VALIDATION_RAYDIUM_LAUNCHPAD_0_7_50.sql`.
- pre3 : Demo3 contient le preset `Raydium Launchpad`; les `initialize*` Launchpad peuvent créer le catalogue pool/pair local, tandis que `trade_event` reste non promu en trade/candle.
`raydium_pool_v4.json` reste un indice IDL annexe. Il n'est pas promu en surface métier tant que son program id, son rôle exact et un corpus local exploitable ne sont pas confirmés.
## Note 0.7.50-pre-r2 — CPMM/CLMM closure re-check
Cette tranche complète la clôture Raydium en ajoutant `cpi_event` pour CPMM/CLMM, `update_dynamic_fee_config` pour CLMM, le rattachement local des Program-data events CLMM et la table `k_sol_token_account_events` pour `create_support_mint_associated`.
Le discriminant CPMM `40f4bc78a7e9690a` est désormais codé comme `raydium_cpmm.anchor_idl_instruction` : les signatures inspectées correspondent aux instructions Anchor `IdlCreateAccount` / `IdlCloseAccount`, donc il reste `decoded_events_only` et ne matérialise aucune table métier.
Rapport de clôture : `docs/reports/RAYDIUM_CPMM_CLMM_RECHECK_REPORT_0_7_50_PRE_R2.md`.
## Note 0.7.50-final — Launchpad closure and Raydium recheck cleanup
The final `0.7.50` cleanup keeps the Raydium CPMM discriminator `40f4bc78a7e9690a` as `raydium_cpmm.anchor_idl_instruction` decoded-only and removes stale `raydium_cpmm.instruction_audit` duplicates in an FK-safe way by unlinking `k_sol_instruction_observations.decoded_event_id` before deletion.
Expected post-replay checks:
```text
raydium_cpmm.instruction_audit = 0
raydium_cpmm decoded events missing coverage row = 0
```
Validation helper:
```text
validation_sql/SQL_VALIDATION_RAYDIUM_CPMM_AUDIT_CLEANUP_0_7_50_FINAL.sql
```
Next-session handoff:
```text
docs/prompts/PROMPT_REPRISE_khadhroony-bobobot_0.7.51-raydium-amm-v4.md
```

View File

@@ -28,25 +28,26 @@ Règles de planification :
| `https://github.com/all-in-one-blockchain/phoenix-onchain-mm` | Source Phoenix/MM complémentaire. | | `https://github.com/all-in-one-blockchain/phoenix-onchain-mm` | Source Phoenix/MM complémentaire. |
| `https://docs.vybenetwork.com/docs/available-dexs-amms` | Source externe de découverte DEX/AMM, non vérifiante. | | `https://docs.vybenetwork.com/docs/available-dexs-amms` | Source externe de découverte DEX/AMM, non vérifiante. |
### Plan révisé `0.7.48` à `0.7.62+` ### Plan révisé `0.7.48` à `0.7.63+`
| Version cible | Scope | Objectif de clôture | | Version cible | Scope | Objectif de clôture |
|---|---|---| |---|---|---|
| `0.7.48` | `raydium_cpmm` | Clôturé : instructions/events CPMM, lifecycle, fees, admin/config, deposit/withdraw, `lp_change_event`, invariants trade/candle. | | `0.7.48` | `raydium_cpmm` | Clôturé : instructions/events CPMM, lifecycle, fees, admin/config, deposit/withdraw, `lp_change_event`, invariants trade/candle. |
| `0.7.49` | `raydium_clmm` | Clôturé : 33 instructions observées/décodées, orderbook CLMM, liquidity/fee/reward/admin/lifecycle, fallbacks upstream nettoyés, 11 Program-data events préparés mais non observés. | | `0.7.49` | `raydium_clmm` | Clôturé : 33 instructions observées/décodées, orderbook CLMM, liquidity/fee/reward/admin/lifecycle, fallbacks upstream nettoyés, 11 Program-data events préparés mais non observés. |
| `0.7.50` | `raydium_launchpad` | Reprendre Launchpad comme surface Raydium prioritaire : identifier les program ids/IDL, launch, pool creation, migration, bonding éventuel, fees/admin, et rattachement au DEX effectif. | | `0.7.50` | `raydium_launchpad` | Bootstrap ouvert : surface LaunchLab/Launchpad, discriminants Carbon/IDL, fallback audit, SQL de validation, aucune matérialisation métier sans corpus. |
| `0.7.51` | `raydium_amm_v4` | Reprendre AMM v4 legacy au même niveau de couverture que CPMM/CLMM : swaps, pool lifecycle, liquidity, fees/admin, side effects documentés. | | `0.7.51` | `raydium_amm_v4` | Reprendre AMM v4 legacy au même niveau de couverture que CPMM/CLMM : swaps, pool lifecycle, liquidity, fees/admin, side effects documentés. |
| `0.7.52` | `raydium_stable` | Reprendre Raydium Stable : program ids/IDL, swaps stables, pool lifecycle, liquidity, fees/admin, invariants pricing/candles. | | `0.7.52` | `raydium_stable` | Reprendre Raydium Stable : program ids/IDL, swaps stables, pool lifecycle, liquidity, fees/admin, invariants pricing/candles. |
| `0.7.53` | `pump_swap` | Couvrir `buy/sell` et tous les events auxiliaires disponibles : fees, cashback, volume accumulator, admin/config. | | `0.7.53` | `raydium_pool_v4` | Audit / program-id decision seulement : confirmer program id, rôle exact et corpus avant toute promotion métier. |
| `0.7.54` | `pump_fun` | Traiter launch/bonding/migration ; séparer création token, buy/sell bonding, migration vers DEX effectif. | | `0.7.54` | `pump_swap` | Couvrir `buy/sell` et tous les events auxiliaires disponibles : fees, cashback, volume accumulator, admin/config. |
| `0.7.55` | `meteora_dbc` | Couverture DBC : bonding curve, swap, migration, launch attribution, fees/admin, non-trade. | | `0.7.55` | `pump_fun` | Traiter launch/bonding/migration ; séparer création token, buy/sell bonding, migration vers DEX effectif. |
| `0.7.56` | `meteora_dlmm` | Audit final de parité avec sources Git/IDL ; fermer ou documenter les audits résiduels. | | `0.7.56` | `meteora_dbc` | Couverture DBC : bonding curve, swap, migration, launch attribution, fees/admin, non-trade. |
| `0.7.57` | `meteora_damm_v1` | Parité upstream complète ; résoudre les cas non matérialisés faute de pool/pair quand possible. | | `0.7.57` | `meteora_dlmm` | Audit final de parité avec sources Git/IDL ; fermer ou documenter les audits résiduels. |
| `0.7.58` | `meteora_damm_v2` | Couverture DAMM v2 complète : create, swap, liquidity, fees/admin/config ; décider trade actionability. | | `0.7.58` | `meteora_damm_v1` | Parité upstream complète ; résoudre les cas non matérialisés faute de pool/pair quand possible. |
| `0.7.59` | `phoenix_v1` | Finir tous les events Git disponibles en audit ; préparer mais ne pas activer trade materialization. | | `0.7.59` | `meteora_damm_v2` | Couverture DAMM v2 complète : create, swap, liquidity, fees/admin/config ; décider trade actionability. |
| `0.7.60` | `openbook_v2` | Finir layouts logs/events ; définir conditions futures de trade/candle sans les activer par défaut. | | `0.7.60` | `phoenix_v1` | Finir tous les events Git disponibles en audit ; préparer mais ne pas activer trade materialization. |
| `0.7.61` | `orca_whirlpools` | Reprendre Whirlpools depuis IDL/source : swaps, pools, positions, liquidity, fees/rewards. | | `0.7.61` | `openbook_v2` | Finir layouts logs/events ; définir conditions futures de trade/candle sans les activer par défaut. |
| `0.7.62+` | Launch surfaces / DEX candidats / validation consolidée | Moonshot/Moonit, Boop, Heaven, Bags, LetsBonk, FluxBeam, DexLab, Lifinity, Stabble, BonkSwap, GooseFX, Obric, SolFi puis base neuve multi-DEX. | | `0.7.62` | `orca_whirlpools` | Reprendre Whirlpools depuis IDL/source : swaps, pools, positions, liquidity, fees/rewards. |
| `0.7.63+` | Launch surfaces / DEX candidats / validation consolidée | Moonshot/Moonit, Boop, Heaven, Bags, LetsBonk, FluxBeam, DexLab, Lifinity, Stabble, BonkSwap, GooseFX, Obric, SolFi puis base neuve multi-DEX. |
Ce plan remplace les anciens regroupements larges `0.7.50+` qui mélangeaient plusieurs DEX dans une même version. Ce plan remplace les anciens regroupements larges `0.7.50+` qui mélangeaient plusieurs DEX dans une même version.
@@ -851,7 +852,7 @@ Matrice cible initiale :
| `pump_swap` | AMM / swap | supporté | conserver trades/candles | | `pump_swap` | AMM / swap | supporté | conserver trades/candles |
| `raydium_cpmm` | AMM | supporté | conserver trades/candles | | `raydium_cpmm` | AMM | supporté | conserver trades/candles |
| `raydium_clmm` | CLMM | supporté | conserver trades/candles | | `raydium_clmm` | CLMM | supporté | conserver trades/candles |
| `raydium_launchlab` | launch surface | planifié, program id local connu | ajouter decoder/materialization dédiée | | `raydium_launchpad` | launch surface | planifié, program id local connu | ajouter decoder/materialization dédiée |
| `raydium_amm_v4` | AMM legacy | partiel | corpus dédié après autres Raydium | | `raydium_amm_v4` | AMM legacy | partiel | corpus dédié après autres Raydium |
| `raydium_router` | router | partiel | ne pas matérialiser en trade direct avant preuve | | `raydium_router` | router | partiel | ne pas matérialiser en trade direct avant preuve |
| `raydium_stable_swap` | AMM legacy | planifié | traiter seulement si corpus pertinent | | `raydium_stable_swap` | AMM legacy | planifié | traiter seulement si corpus pertinent |
@@ -1231,7 +1232,7 @@ Objectif : accélérer la découverte multi-DEX en indexant les `program_id`, di
Familles prioritaires à indexer en premier : Familles prioritaires à indexer en premier :
- DEX / AMM / CLMM / orderbook : `meteora_damm_v2`, `meteora_dbc`, `meteora_dlmm`, `meteora_vault`, `raydium_amm_v4`, `raydium_clmm`, `raydium_cpmm`, `raydium_launchlab`, `raydium_liquidity_locking`, `raydium_stable_swap`, `orca_whirlpools`, `fluxbeam`, `lifinity_v2`, `phoenix_v1`, `openbook_v2`, `stabble_stable_swap`, `stabble_weighted_swap`, `bonkswap`, `boop`, `moonshot`, `heaven`, `okx_dex`, `pancake_swap`, `vertigo`, `virtuals`, `wavebreak`, `onchain_labs_dex_v1`, `onchain_labs_dex_v2` ; - DEX / AMM / CLMM / orderbook : `meteora_damm_v2`, `meteora_dbc`, `meteora_dlmm`, `meteora_vault`, `raydium_amm_v4`, `raydium_clmm`, `raydium_cpmm`, `raydium_launchpad`, `raydium_liquidity_locking`, `raydium_stable_swap`, `orca_whirlpools`, `fluxbeam`, `lifinity_v2`, `phoenix_v1`, `openbook_v2`, `stabble_stable_swap`, `stabble_weighted_swap`, `bonkswap`, `boop`, `moonshot`, `heaven`, `okx_dex`, `pancake_swap`, `vertigo`, `virtuals`, `wavebreak`, `onchain_labs_dex_v1`, `onchain_labs_dex_v2` ;
- agrégateurs / ordres / perps / lending utiles au routage ou à lanalyse : `jupiter_swap`, `jupiter_dca`, `jupiter_limit_order`, `jupiter_limit_order_2`, `jupiter_perpetuals`, `jupiter_lend`, `kamino_lending`, `kamino_vault`, `kamino_farms`, `kamino_limit_order`, `drift_v2`, `marginfi_v2`, `dflow_aggregator_v4`, `zeta` ; - agrégateurs / ordres / perps / lending utiles au routage ou à lanalyse : `jupiter_swap`, `jupiter_dca`, `jupiter_limit_order`, `jupiter_limit_order_2`, `jupiter_perpetuals`, `jupiter_lend`, `kamino_lending`, `kamino_vault`, `kamino_farms`, `kamino_limit_order`, `drift_v2`, `marginfi_v2`, `dflow_aggregator_v4`, `zeta` ;
- contexte transactionnel non DEX : `system_program`, `token_program`, `token_2022`, `associated_token_account`, `address_lookup_table`, `memo_program`, `stake_program`, `mpl_token_metadata`, `mpl_core`, `bubblegum`, `name_service`, `marinade_finance`, `solayer_restaking_program`, `swig`, `sharky`, `circle_message_transmitter_v2`, `circle_token_messenger_v2`. - contexte transactionnel non DEX : `system_program`, `token_program`, `token_2022`, `associated_token_account`, `address_lookup_table`, `memo_program`, `stake_program`, `mpl_token_metadata`, `mpl_core`, `bubblegum`, `name_service`, `marinade_finance`, `solayer_restaking_program`, `swig`, `sharky`, `circle_message_transmitter_v2`, `circle_token_messenger_v2`.
@@ -1291,10 +1292,18 @@ Réalisé :
- préparation audit-only des 11 Anchor / `Program data` events non encore observés ; - préparation audit-only des 11 Anchor / `Program data` events non encore observés ;
- invariants validés : aucun faux trade/candle, aucune matérialisation sur transaction échouée, `raydium_clmm.instruction_audit` résiduel à zéro. - invariants validés : aucun faux trade/candle, aucune matérialisation sur transaction échouée, `raydium_clmm.instruction_audit` résiduel à zéro.
### 6.082. Version `0.7.50` — `raydium_launchpad` event coverage ### 6.082. Version `0.7.50-pre-r2` — Raydium CPMM/CLMM coverage closure
Objectif : reprendre Raydium Launchpad comme prochaine surface Raydium, avant AMM v4 et Stable. Objectif : clôturer la vérification CPMM/CLMM après la tranche Launchpad, en comparant le code local avec Carbon, Solscan Program IDL et `sol-parser-sdk`, puis en supprimant les familles ambiguës restantes de la matrice coverage.
À faire : identifier les program ids/IDL depuis sources Git/IDL/Solscan, couvrir launch/pool creation, migration/rattachement au DEX effectif, fees/admin/config, éventuels side effects SPL/Token-2022, et matérialiser seulement les events prouvés par corpus local. Réalisé : ajout des entrées `cpi_event` CPMM/CLMM (`e445a52e51cb9a1d`), ajout de `update_dynamic_fee_config` CLMM (`0707500802c784f0`), rattachement local des Program-data events CLMM (`swap_event`, `pool_created_event`, `liquidity_change_event`, `create_personal_position_event`, `config_change_event`, `collect_protocol_fee_event`, `update_reward_infos_event`) et ajout de `k_sol_token_account_events` pour les événements type `create_support_mint_associated`. Les familles `unknown` restantes sont remplacées par `cpi_transport`, `liquidity_calculation`, `liquidity_change`, `position_open`, `pool_create`, `admin_config` ou `account_create` selon le cas.
Point audit résolu : le discriminant CPMM local `40f4bc78a7e9690a` est codé comme `raydium_cpmm.anchor_idl_instruction` avec `event_family=idl_management` et `expected_db_target=k_sol_dex_decoded_events_only`. Les signatures Solscan montrent `IdlCreateAccount` / `IdlCloseAccount` sur le compte `anchor:idl`; cette entrée reste donc informative et ne doit pas produire trade, candle, liquidity, fee ou admin métier.
Décisions de clôture CLMM : `swap_event` et `swap_router_base_in` restent `decoded_events_only` pour éviter le double comptage avec les instructions `swap` / `swap_v2`; `liquidity_calculate_event` reste diagnostic ; `close_position` / `close_protocol_position` restent décodés mais non matérialisés tant que le corpus ne fournit pas un rattachement pool/pair fiable. La matérialisation liquidity tente désormais un contexte de secours via événements frères de la même transaction quand un event CLMM porte les montants mais pas directement le pool/pair.
Suite locale : rebrancher les bases CPMM/CLMM, rejouer `forceDexDecode=yes`, vérifier que les requêtes `unknown`, fallback upstream, audit résiduel et matérialisation attendue ne remontent plus que des cas explicitement `decoded_events_only` ou des transactions failed.
Rapport associé : `docs/reports/RAYDIUM_CPMM_CLMM_RECHECK_REPORT_0_7_50_PRE_R2.md`.
### 6.083. Version `0.7.51` — `raydium_amm_v4` event coverage ### 6.083. Version `0.7.51` — `raydium_amm_v4` event coverage
Objectif : hisser AMM v4 legacy au niveau de couverture CPMM/CLMM. Objectif : hisser AMM v4 legacy au niveau de couverture CPMM/CLMM.
@@ -1306,52 +1315,57 @@ Objectif : reprendre Raydium Stable comme troisième tranche Raydium post-CLMM.
À faire : vérifier program ids/IDL, swaps stables, liquidity, pool lifecycle, fees/admin/config, cohérence des montants/prix et absence de faux trades/candles. À faire : vérifier program ids/IDL, swaps stables, liquidity, pool lifecycle, fees/admin/config, cohérence des montants/prix et absence de faux trades/candles.
### 6.085. Version `0.7.53` — `pump_swap` event coverage ### 6.085. Version `0.7.53` — `raydium_pool_v4` audit / program-id decision
Objectif : auditer `raydium_pool_v4.json` comme source IDL annexe, sans promotion métier automatique.
À faire : confirmer s'il correspond à un program id distinct, confirmer son rôle exact par rapport à `raydium_amm_v4`, chercher un corpus exploitable, puis décider seulement ensuite si une surface dédiée est nécessaire.
### 6.086. Version `0.7.54` — `pump_swap` event coverage
Objectif : compléter `pump_swap` au-delà de `buy/sell`. Objectif : compléter `pump_swap` au-delà de `buy/sell`.
À faire : couvrir fees, cashback, volume accumulator, admin/config et autres events upstream disponibles, tout en maintenant linvariant non-trade = zéro trade/candle. À faire : couvrir fees, cashback, volume accumulator, admin/config et autres events upstream disponibles, tout en maintenant linvariant non-trade = zéro trade/candle.
### 6.086. Version `0.7.54` — `pump_fun` launch/bonding/migration ### 6.087. Version `0.7.55` — `pump_fun` launch/bonding/migration
Objectif : séparer launch/bonding de DEX effectif et valider migration vers PumpSwap ou autre surface tradable. Objectif : séparer launch/bonding de DEX effectif et valider migration vers PumpSwap ou autre surface tradable.
À faire : traiter create, buy/sell bonding, update/config, mint/burn éventuels, migration/graduate et rattachement au pool tradable. À faire : traiter create, buy/sell bonding, update/config, mint/burn éventuels, migration/graduate et rattachement au pool tradable.
### 6.087. Version `0.7.55` — `meteora_dbc` séparé ### 6.088. Version `0.7.56` — `meteora_dbc` séparé
Objectif : reprendre Meteora après les tranches Raydium et Pump, en séparant bonding/launch, swap effectif, migration et attribution dorigine. Objectif : reprendre Meteora après les tranches Raydium et Pump, en séparant bonding/launch, swap effectif, migration et attribution dorigine.
À faire : vérifier swaps exploitables, migration, lifecycle, mint/burn éventuels, launch attribution, fees/admin, sans candle artificielle sur events non pricés. À faire : vérifier swaps exploitables, migration, lifecycle, mint/burn éventuels, launch attribution, fees/admin, sans candle artificielle sur events non pricés.
### 6.088. Version `0.7.56` — `meteora_dlmm` parité upstream finale ### 6.089. Version `0.7.57` — `meteora_dlmm` parité upstream finale
Objectif : comparer la couverture locale DLMM déjà avancée avec toutes les sources Git/IDL et documenter ou fermer les audits résiduels. Objectif : comparer la couverture locale DLMM déjà avancée avec toutes les sources Git/IDL et documenter ou fermer les audits résiduels.
À faire : revalider swaps, liquidity, positions, lifecycle, fees/rewards/admin, et garder les discriminants non mappés en audit documenté. À faire : revalider swaps, liquidity, positions, lifecycle, fees/rewards/admin, et garder les discriminants non mappés en audit documenté.
### 6.089. Version `0.7.57` — `meteora_damm_v1` parité upstream finale ### 6.090. Version `0.7.58` — `meteora_damm_v1` parité upstream finale
Objectif : compléter la tranche DAMM v1 déjà engagée, résoudre les surfaces non observées et améliorer le rattachement pool/pair quand possible. Objectif : compléter la tranche DAMM v1 déjà engagée, résoudre les surfaces non observées et améliorer le rattachement pool/pair quand possible.
À faire : vérifier toutes les instructions upstream restantes, matérialiser uniquement les events prouvés et documenter les cas sans pool/pair local. À faire : vérifier toutes les instructions upstream restantes, matérialiser uniquement les events prouvés et documenter les cas sans pool/pair local.
### 6.090. Version `0.7.58` — `meteora_damm_v2` séparé ### 6.091. Version `0.7.59` — `meteora_damm_v2` séparé
Objectif : reprendre DAMM v2 comme DEX effectif séparé après disponibilité du ledger de coverage. Objectif : reprendre DAMM v2 comme DEX effectif séparé après disponibilité du ledger de coverage.
À faire : consolider create_pool, swaps exploitables, configs dynamiques, liquidity, fees/admin, lifecycle ; conserver les swaps sans payload montant/prix fiable comme `non_actionable_trade`. À faire : consolider create_pool, swaps exploitables, configs dynamiques, liquidity, fees/admin, lifecycle ; conserver les swaps sans payload montant/prix fiable comme `non_actionable_trade`.
### 6.091. Version `0.7.59` — `phoenix_v1` audit-only complet ### 6.092. Version `0.7.60` — `phoenix_v1` audit-only complet
Objectif : finir tous les events Git disponibles en audit, sans activer de trade/candle. Objectif : finir tous les events Git disponibles en audit, sans activer de trade/candle.
À faire : couvrir `Fill`, `FillSummary`, `Fee`, `Evict`, `ExpiredOrder` et autres logs/events disponibles ; préparer le futur modèle orderbook sans matérialisation marché par défaut. À faire : couvrir `Fill`, `FillSummary`, `Fee`, `Evict`, `ExpiredOrder` et autres logs/events disponibles ; préparer le futur modèle orderbook sans matérialisation marché par défaut.
### 6.092. Version `0.7.60` — `openbook_v2` audit-only complet ### 6.093. Version `0.7.61` — `openbook_v2` audit-only complet
Objectif : finir les layouts logs/events OpenBook v2 et définir les conditions futures de matérialisation orderbook/trade. Objectif : finir les layouts logs/events OpenBook v2 et définir les conditions futures de matérialisation orderbook/trade.
À faire : vérifier fills, settle, consume events, open orders create/close, maker/taker, lots/decimals et sens économique avant toute promotion. À faire : vérifier fills, settle, consume events, open orders create/close, maker/taker, lots/decimals et sens économique avant toute promotion.
### 6.093. Version `0.7.61` — `orca_whirlpools` event coverage ### 6.094. Version `0.7.62` — `orca_whirlpools` event coverage
Objectif : reprendre Whirlpools depuis IDL/source avec corpus dédié. Objectif : reprendre Whirlpools depuis IDL/source avec corpus dédié.
À faire : swaps, pools, positions, liquidity, fees/rewards, tick arrays, mint/burn/Token-2022 si applicable. À faire : swaps, pools, positions, liquidity, fees/rewards, tick arrays, mint/burn/Token-2022 si applicable.
### 6.094. Version `0.7.62+` — Launch surfaces, DEX historiques/candidats et validation consolidée ### 6.095. Version `0.7.63+` — Launch surfaces, DEX historiques/candidats et validation consolidée
Objectif : traiter les surfaces restantes puis rejouer une base neuve multi-DEX. Objectif : traiter les surfaces restantes puis rejouer une base neuve multi-DEX.
À faire : Moonshot/Moonit, Boop, Heaven, Bags, LetsBonk, FluxBeam, DexLab, Lifinity, Stabble, BonkSwap, GooseFX, Obric, SolFi et autres entrées Vybe/registry ; rapport coverage par DEX/event, zéro faux trade/candle, corpus documentés, matrices cohérentes, diagnostics bloquants à zéro. À faire : Moonshot/Moonit, Boop, Heaven, Bags, LetsBonk, FluxBeam, DexLab, Lifinity, Stabble, BonkSwap, GooseFX, Obric, SolFi et autres entrées Vybe/registry ; rapport coverage par DEX/event, zéro faux trade/candle, corpus documentés, matrices cohérentes, diagnostics bloquants à zéro.
@@ -1550,19 +1564,20 @@ Ordre de travail recommandé pour la suite :
5. `0.7.48-pre` : event coverage + DB model checkpoint — clos après table, sync upstream, refresh counts, diagnostics et profil validation ; 5. `0.7.48-pre` : event coverage + DB model checkpoint — clos après table, sync upstream, refresh counts, diagnostics et profil validation ;
6. `0.7.48` : `raydium_cpmm` — clos ; 6. `0.7.48` : `raydium_cpmm` — clos ;
7. `0.7.49` : `raydium_clmm` — clos ; 7. `0.7.49` : `raydium_clmm` — clos ;
8. `0.7.50` : `raydium_launchpad` ; 8. `0.7.50-pre-r2` : `raydium_launchpad` clos + re-vérification CPMM/CLMM ;
9. `0.7.51` : `raydium_amm_v4` ; 9. `0.7.51` : `raydium_amm_v4` ;
10. `0.7.52` : `raydium_stable` ; 10. `0.7.52` : `raydium_stable` ;
11. `0.7.53` : `pump_swap` ; 11. `0.7.53` : `raydium_pool_v4` audit conditionnel ;
12. `0.7.54` : `pump_fun` ; 12. `0.7.54` : `pump_swap` ;
13. `0.7.55` : `meteora_dbc` ; 13. `0.7.55` : `pump_fun` ;
14. `0.7.56` : `meteora_dlmm` parité upstream finale ; 14. `0.7.56` : `meteora_dbc` ;
15. `0.7.57` : `meteora_damm_v1` parité upstream finale ; 15. `0.7.57` : `meteora_dlmm` parité upstream finale ;
16. `0.7.58` : `meteora_damm_v2` ; 16. `0.7.58` : `meteora_damm_v1` parité upstream finale ;
17. `0.7.59` : `phoenix_v1` audit-only complet ; 17. `0.7.59` : `meteora_damm_v2` ;
18. `0.7.60` : `openbook_v2` audit-only complet ; 18. `0.7.60` : `phoenix_v1` audit-only complet ;
19. `0.7.61` : `orca_whirlpools` ; 19. `0.7.61` : `openbook_v2` audit-only complet ;
20. `0.7.62+` : launch surfaces, DEX candidats/historiques et validation consolidée. 20. `0.7.62` : `orca_whirlpools` ;
21. `0.7.63+` : launch surfaces, DEX candidats/historiques et validation consolidée.
Garde-fous constants : Garde-fous constants :
@@ -1634,4 +1649,8 @@ La tranche CPMM reconnaît désormais tous les discriminants instruction-level l
`0.7.48` est clôturable côté `raydium_cpmm`. Le decoder couvre les instructions/events CPMM listés par Carbon/fnzero/Raydium CP-Swap, avec matérialisation locale validée pour trades, liquidity, lifecycle, fees et admin/config. `swap_event` reste audit-only pour éviter les doublons avec `swap_base_input` / `swap_base_output`. Les side effects SPL Token / Token-2022 observés via Solscan (`burn`, `transfer`, `transferChecked`, `closeAccount`) restent hors decoder CPMM direct et alimenteront une réflexion transversale future. `0.7.48` est clôturable côté `raydium_cpmm`. Le decoder couvre les instructions/events CPMM listés par Carbon/fnzero/Raydium CP-Swap, avec matérialisation locale validée pour trades, liquidity, lifecycle, fees et admin/config. `swap_event` reste audit-only pour éviter les doublons avec `swap_base_input` / `swap_base_output`. Les side effects SPL Token / Token-2022 observés via Solscan (`burn`, `transfer`, `transferChecked`, `closeAccount`) restent hors decoder CPMM direct et alimenteront une réflexion transversale future.
La suite après `0.7.49 raydium_clmm` reprend en `0.7.50` par `raydium_launchpad`, puis `0.7.51 raydium_amm_v4` et `0.7.52 raydium_stable`, en gardant la même discipline : sources Git/IDL + Solscan pour accélérer la découverte, mais corpus local obligatoire avant toute promotion métier. La suite après `0.7.49 raydium_clmm` reprend en `0.7.50-pre-r2` par la clôture Launchpad et la re-vérification CPMM/CLMM, puis `0.7.51 raydium_amm_v4`, `0.7.52 raydium_stable` et `0.7.53 raydium_pool_v4` uniquement comme audit conditionnel, en gardant la même discipline : sources Git/IDL + Solscan pour accélérer la découverte, mais corpus local obligatoire avant toute promotion métier.
### Note `0.7.50-final` — clôture Launchpad + recheck Raydium
`0.7.50` se clôture avec `raydium_launchpad` et la re-vérification CPMM/CLMM. Le dernier correctif cible le cleanup FK-safe des anciens `raydium_cpmm.instruction_audit` `40f4bc78a7e9690a`, maintenant remplacés par `raydium_cpmm.anchor_idl_instruction` decoded-only. La suite planifiée reste `0.7.51 raydium_amm_v4`, puis `0.7.52 raydium_stable`, avec découverte accélérée par Solscan `instruction=<discriminator>` et validation obligatoire par corpus local.

View File

@@ -320,3 +320,28 @@ Aucune nouvelle table transversale n'est ajoutée dans ce delta :
La table `k_sol_instruction_observations` reste technique : elle sert à trouver des signatures et discriminants observés localement, sans être une preuve métier. La table `k_sol_instruction_observations` reste technique : elle sert à trouver des signatures et discriminants observés localement, sans être une preuve métier.
## Note `0.7.50-pre-r2` — `k_sol_token_account_events`
La re-vérification Raydium CLMM introduit une table dédiée `k_sol_token_account_events` pour les événements de cycle de vie de comptes token qui ne sont ni des swaps, ni de la liquidité, ni du lifecycle pool. Le premier cas d'usage est `raydium_clmm.create_support_mint_associated`.
### Règle de matérialisation
- `create_support_mint_associated` cible `k_sol_token_account_events`.
- `cpi_event` reste `k_sol_dex_decoded_events_only` : c'est un transport Anchor/CPI, pas un event métier autonome.
- `liquidity_calculate_event` reste `k_sol_dex_decoded_events_only` : c'est un event de calcul/diagnostic, pas une mutation de liquidité fiable.
- `create_operation_account` et `update_operation_account` relèvent de `k_sol_pool_admin_events` quand le corpus le permet.
### Colonnes principales
`k_sol_token_account_events` conserve `transaction_id`, `decoded_event_id`, `dex_id`, `pool_id`, `pair_id`, `signature`, `instruction_index`, `slot`, `protocol_name`, `program_id`, `event_kind`, `token_account`, `token_mint`, `owner_wallet`, `account_action`, `payload_json`, `executed_at` et `created_at`.
Cette table permet de suivre les événements Token-2022/ATA significatifs sans les confondre avec les trades ou les liquidités.
## Note `0.7.50-final` — FK-safe cleanup for instruction observations
`k_sol_instruction_observations` is a technical index table. When a legacy `*.instruction_audit` decoded event is replaced by a local specialized event, existing observation rows can still point to the old decoded event id on already-created SQLite databases.
The final 0.7.50 cleanup therefore unlinks `k_sol_instruction_observations.decoded_event_id` before deleting replaced CPMM instruction-audit rows. New databases define the `decoded_event_id` foreign key with `ON DELETE SET NULL` for the same reason.
This is not a business-table promotion. It only keeps the technical observation index consistent with decoded event cleanup.

View File

@@ -1,4 +1,4 @@
# DEX Decoder Matrix — `khadhroony-bobobot` `0.7.47-1FE5` # DEX Decoder Matrix — `khadhroony-bobobot` `0.7.50-pre-r2`
Cette matrice complète `kb_lib/src/dex_support_matrix.rs`. Elle documente **ce qui est fait**, **ce qui reste à faire**, et **le niveau de preuve attendu** par DEX/version. Cette matrice complète `kb_lib/src/dex_support_matrix.rs`. Elle documente **ce qui est fait**, **ce qui reste à faire**, et **le niveau de preuve attendu** par DEX/version.
@@ -28,24 +28,25 @@ Cette matrice complète `kb_lib/src/dex_support_matrix.rs`. Elle documente **ce
| Ordre | DEX/version | État actuel | Fait | Reste à faire | | Ordre | DEX/version | État actuel | Fait | Reste à faire |
|---:|---|---|---|---| |---:|---|---|---|---|
| 1 | `raydium_cpmm` | `supported / 0.7.48 closed` | Couverture CPMM clôturée : swaps, lifecycle, fees, admin/config, deposit/withdraw, `lp_change_event`, `swap_event` audit-only. | Réouvrir seulement en cas de nouveau corpus ou divergence upstream. | | 1 | `raydium_cpmm` | `supported / 0.7.50-pre-r2 closure recheck` | Couverture CPMM clôturée : swaps, lifecycle, fees, admin/config, deposit/withdraw, `lp_change_event`, `swap_event` decoded-only, `cpi_event` transport Carbon et `anchor_idl_instruction` Solscan/manual pour `40f4bc78a7e9690a`. | Ne pas promouvoir `anchor_idl_instruction` : c'est de la gestion Anchor IDL, pas un événement AMM métier. |
| 2 | `raydium_clmm` | `supported / 0.7.49 closed` | Couverture CLMM clôturée : 45 entrées listées, 33 instructions observées/décodées, 25 matérialisées, orderbook events, fallback upstream nettoyé. | 11 Anchor Program-data events restent préparés mais `upstream_git_unverified` faute de corpus local. | | 2 | `raydium_clmm` | `supported / 0.7.50-pre-r2 closure recheck` | Couverture CLMM complétée : `cpi_event`, `update_dynamic_fee_config`, Program-data events locaux, `create_support_mint_associated` vers `k_sol_token_account_events`, familles sans `unknown`, router/swap Program-data en decoded-only. | Rejouer la base CLMM et confirmer que les seuls résidus sont `decoded_events_only`, transactions failed ou absence prouvée de contexte pool/pair. |
| 3 | `raydium_launchpad` | `planned / 0.7.50` | Prochaine tranche Raydium. | Identifier program ids/IDL, launch/pool creation, migration, fees/admin/config, corpus Solscan/Demo3 puis decoder spécialisé. | | 3 | `raydium_launchpad` | `bootstrap / 0.7.50` | Surface canonique normalisée, 1 entrée programme + 26 discriminants Carbon/IDL listés, fallback audit/mapped decoder, SQL dédié. | Créer DB neuve, backfill par discriminant, replay forcé, promouvoir seulement après corpus local. |
| 4 | `raydium_amm_v4` | `supported / 0.7.51 planned` | Swaps AMM v4 legacy matérialisés. | Reprendre AMM v4 au niveau CPMM/CLMM : pool lifecycle, liquidity, fees/admin, side effects, fallback cleanup. | | 4 | `raydium_amm_v4` | `supported / 0.7.51 planned` | Swaps AMM v4 legacy matérialisés. | Reprendre AMM v4 au niveau CPMM/CLMM : pool lifecycle, liquidity, fees/admin, side effects, fallback cleanup. |
| 5 | `raydium_stable_swap` | `planned / 0.7.52` | Entrée conservée. | Reprendre Stable séparément : swaps stables, pool lifecycle, liquidity, fees/admin, montants/prix exploitables. | | 5 | `raydium_stable_swap` | `planned / 0.7.52` | Entrée conservée. | Reprendre Stable séparément : swaps stables, pool lifecycle, liquidity, fees/admin, montants/prix exploitables. |
| 6 | `pump_swap` | `supported / 0.7.53 planned` | `buy`/`sell` décodés et matérialisés ; trade/candle OK. | Ajouter tous les events Carbon/Solana Streamer : cashback, fee, volume accumulator, admin/config ; conserver les non-trades hors candles. | | 6 | `raydium_pool_v4` | `to_verify / 0.7.53 conditional audit` | IDL annexe mentionnée par fnzero, non présente dans l'archive locale, pas de program id/rôle confirmé ici. | Ne pas promouvoir tant que program id distinct, rôle exact et corpus exploitable ne sont pas confirmés. |
| 7 | `pump_fun` | `partial / launch_surface` | Création/token launch partiellement décodée ; intégrée au pipeline de listings. | Traiter tous les events Pump.fun disponibles : buy/sell/migrate/create/update ; séparer bonding/launch de DEX effectif ; valider migration vers PumpSwap. | | 7 | `pump_swap` | `supported / 0.7.54 planned` | `buy`/`sell` décodés et matérialisés ; trade/candle OK. | Ajouter tous les events Carbon/Solana Streamer : cashback, fee, volume accumulator, admin/config ; conserver les non-trades hors candles. |
| 8 | `meteora_dbc` | `partial` | Swaps/instruction audits observés ; Demo3 donne du corpus. | Couverture complète DBC : launch/bonding curve, swap, migration, config/admin, fees ; matérialiser seulement ce qui est prouvé. | | 8 | `pump_fun` | `partial / 0.7.55 launch_surface` | Création/token launch partiellement décodée ; intégrée au pipeline de listings. | Traiter tous les events Pump.fun disponibles : buy/sell/migrate/create/update ; séparer bonding/launch de DEX effectif ; valider migration vers PumpSwap. |
| 9 | `meteora_dlmm` | `supported` | Couverture avancée validée en `0.7.45` : swaps, liquidity, positions, lifecycle, fees ; non-trade matérialisé. | Résoudre les audits résiduels non mappés ; comparer Carbon/IDL pour events rewards/admin restants ; revalidation base neuve. | | 9 | `meteora_dbc` | `partial / 0.7.56 planned` | Swaps/instruction audits observés ; Demo3 donne du corpus. | Couverture complète DBC : launch/bonding curve, swap, migration, config/admin, fees ; matérialiser seulement ce qui est prouvé. |
| 10 | `meteora_damm_v1` | `supported / partial events` | Couverture `0.7.46` : swap, create_pool, add/remove liquidity, claim_fee, create_lock_escrow, lock_liquidity. | Vérifier les surfaces upstream non observées ; améliorer rattachement pool/pair pour remove_liquidity non matérialisés ; revalidation stricte. | | 10 | `meteora_dlmm` | `supported / 0.7.57 parity` | Couverture avancée validée en `0.7.45` : swaps, liquidity, positions, lifecycle, fees ; non-trade matérialisé. | Résoudre les audits résiduels non mappés ; comparer Carbon/IDL pour events rewards/admin restants ; revalidation base neuve. |
| 11 | `meteora_damm_v2` | `partial` | `swap`, `instruction_audit`, registry/discriminants et corpus Demo3 existent. | Couvrir tous les events Carbon/source : create pool, liquidity, fees, dynamic config, admin ; déterminer actionability des swaps ; matérialiser si montants fiables. | | 11 | `meteora_damm_v1` | `supported / 0.7.58 parity` | Couverture `0.7.46` : swap, create_pool, add/remove liquidity, claim_fee, create_lock_escrow, lock_liquidity. | Vérifier les surfaces upstream non observées ; améliorer rattachement pool/pair pour remove_liquidity non matérialisés ; revalidation stricte. |
| 12 | `phoenix_v1` | `audit-only` | Decoder local audit-only ; `log_audit`, order place/cancel, withdraw ; parsing strict `0x0f`; events `Reduce`, `Place`, `TimeInForce` observés ; `trade_count=0`. | Terminer tous les events Git : `Fill`, `FillSummary`, `Fee`, `Evict`, `ExpiredOrder`, etc. ; ajouter counts/flags audit ; seulement ensuite étudier trade materialization. | | 12 | `meteora_damm_v2` | `partial / 0.7.59 planned` | `swap`, `instruction_audit`, registry/discriminants et corpus Demo3 existent. | Couvrir tous les events Carbon/source : create pool, liquidity, fees, dynamic config, admin ; déterminer actionability des swaps ; matérialiser si montants fiables. |
| 13 | `openbook_v2` | `audit-only` | Decoder local audit-only ; instructions order/cancel/consume/settle ; `Program data` mappé : `FillLog`, `OpenOrdersPositionLog`, `TotalOrderFillEvent`, `SettleFundsLog`; `trade_count=0`. | Vérifier layouts fill/out et sens maker/taker/base/quote ; ajouter table audit éventuelle ; ne matérialiser trades quaprès validation du sens économique. | | 13 | `phoenix_v1` | `audit-only / 0.7.60 planned` | Decoder local audit-only ; `log_audit`, order place/cancel, withdraw ; parsing strict `0x0f`; events `Reduce`, `Place`, `TimeInForce` observés ; `trade_count=0`. | Terminer tous les events Git : `Fill`, `FillSummary`, `Fee`, `Evict`, `ExpiredOrder`, etc. ; ajouter counts/flags audit ; seulement ensuite étudier trade materialization. |
| 14 | `orca_whirlpools` | `partial` | Premier decoder historique présent ; swaps/create_pool partiels. | Comparer Carbon/IDL complet ; couvrir liquidity, positions, fees/rewards, tick arrays ; valider swaps exploitables et non-trades. | | 14 | `openbook_v2` | `audit-only / 0.7.61 planned` | Decoder local audit-only ; instructions order/cancel/consume/settle ; `Program data` mappé : `FillLog`, `OpenOrdersPositionLog`, `TotalOrderFillEvent`, `SettleFundsLog`; `trade_count=0`. | Vérifier layouts fill/out et sens maker/taker/base/quote ; ajouter table audit éventuelle ; ne matérialiser trades quaprès validation du sens économique. |
| 15 | `legacy_launch_candidates` | `planned launch` | Anciennes entrées launch à réévaluer après `raydium_launchpad`. | Ne pas confondre Launchpad, LaunchLab, CPMM/CLMM/AMM v4 ; rattacher aux pools tradables seulement après corpus. | | 15 | `orca_whirlpools` | `partial / 0.7.62 planned` | Premier decoder historique présent ; swaps/create_pool partiels. | Comparer Carbon/IDL complet ; couvrir liquidity, positions, fees/rewards, tick arrays ; valider swaps exploitables et non-trades. |
| 16 | `meteora_vault` | `to_verify` | Présent comme indice upstream / compte associé. | Corpus direct obligatoire ; decoder séparé si events vault réels ; aucune promotion via DAMM indirect. | | 16 | `legacy_launch_candidates` | `planned launch` | Anciennes entrées launch à réévaluer après `raydium_launchpad`. | Ne pas confondre Launchpad, LaunchLab, CPMM/CLMM/AMM v4 ; rattacher aux pools tradables seulement après corpus. |
| 17 | `fluxbeam` | `partial/to_verify` | Decoder initial existant ; Demo3 peut produire des candidats. | Vérifier source/IDL ; compléter swap, pool, liquidity, fees/admin ; matérialisation uniquement après corpus. | | 17 | `meteora_vault` | `to_verify` | Présent comme indice upstream / compte associé. | Corpus direct obligatoire ; decoder séparé si events vault réels ; aucune promotion via DAMM indirect. |
| 18 | `dexlab` | `partial/to_verify` | Decoder initial historique ; ancienne entrée beta supprimée. | Reconfirmer program id/source ; décoder events disponibles ; distinguer DexLab natif et liens OpenBook/market. | | 18 | `fluxbeam` | `partial/to_verify` | Decoder initial existant ; Demo3 peut produire des candidats. | Vérifier source/IDL ; compléter swap, pool, liquidity, fees/admin ; matérialisation uniquement après corpus. |
| 19 | `dexlab` | `partial/to_verify` | Decoder initial historique ; ancienne entrée beta supprimée. | Reconfirmer program id/source ; décoder events disponibles ; distinguer DexLab natif et liens OpenBook/market. |
| 19 | `lifinity_v2` | `to_verify` | Program id listé par sources externes/Vybe ; pas de corpus concluant. | Trouver IDL/source ; Demo3 par program/market ; audit-only dabord. | | 19 | `lifinity_v2` | `to_verify` | Program id listé par sources externes/Vybe ; pas de corpus concluant. | Trouver IDL/source ; Demo3 par program/market ; audit-only dabord. |
| 20 | `stabble_stable_swap` / `stabble_weighted_swap` | `to_verify` | Program ids/indices via sources externes ; candidats Demo3 observables. | Source/IDL + corpus + decoder audit-only ; déterminer surface AMM et montants exploitables. | | 20 | `stabble_stable_swap` / `stabble_weighted_swap` | `to_verify` | Program ids/indices via sources externes ; candidats Demo3 observables. | Source/IDL + corpus + decoder audit-only ; déterminer surface AMM et montants exploitables. |
| 21 | `bonkswap` | `to_verify` | Program id/Carbon/Vybe selon registre ; swaps candidats possibles. | Vérifier program id, source et corpus ; décoder tous events ; pas de trade sans montants. | | 21 | `bonkswap` | `to_verify` | Program id/Carbon/Vybe selon registre ; swaps candidats possibles. | Vérifier program id, source et corpus ; décoder tous events ; pas de trade sans montants. |
@@ -95,7 +96,7 @@ Un event peut devenir `materialized` uniquement si :
| `raydium_cpmm` | `dex_effective` | `AMM` | `known` | oui | oui | oui | `supported` | | | `raydium_cpmm` | `dex_effective` | `AMM` | `known` | oui | oui | oui | `supported` | |
| `raydium_clmm` | `dex_effective` | `CLMM` | `known` | oui | oui | oui | `supported` | | | `raydium_clmm` | `dex_effective` | `CLMM` | `known` | oui | oui | oui | `supported` | |
| `raydium_amm_v4` | `dex_effective` | `AMM` | `known` | oui | oui | oui | `supported` | | | `raydium_amm_v4` | `dex_effective` | `AMM` | `known` | oui | oui | oui | `supported` | |
| `raydium_launchlab` | `launch_surface` | `launch` | `known` | non | non | non | `planned` | decoder_and_materialization_not_enabled | | `raydium_launchpad` | `launch_surface` | `launch` | `known` | non | oui | non | `bootstrap` | decoded_events_only_until_local_corpus |
| `raydium_liquidity_locking` | `to_verify` | `liquidity_locking` | `to_verify` | non | non | non | `to_verify` | upstream_git_program_id_requires_local_corpus_verification | | `raydium_liquidity_locking` | `to_verify` | `liquidity_locking` | `to_verify` | non | non | non | `to_verify` | upstream_git_program_id_requires_local_corpus_verification |
| `raydium_router` | `aggregator_router` | `router` | `known` | non | non | non | `partial` | router_not_materialized_as_direct_trade_surface | | `raydium_router` | `aggregator_router` | `router` | `known` | non | non | non | `partial` | router_not_materialized_as_direct_trade_surface |
| `raydium_stable_swap` | `dex_effective` | `AMM` | `known` | non | non | non | `planned` | deprecated_program_not_prioritized | | `raydium_stable_swap` | `dex_effective` | `AMM` | `known` | non | non | non | `planned` | deprecated_program_not_prioritized |
@@ -236,3 +237,18 @@ Le registre est complété avec les entrées issues de l'IDL officiel Raydium no
Règle de clôture : les positions CLMM, fees/rewards et surfaces limit-order ne doivent produire aucune ligne trade/candle tant que le sens économique, les montants, les comptes et les mints ne sont pas prouvés par replay local. Règle de clôture : les positions CLMM, fees/rewards et surfaces limit-order ne doivent produire aucune ligne trade/candle tant que le sens économique, les montants, les comptes et les mints ne sont pas prouvés par replay local.
## Note `0.7.50-pre-r2` — CPMM/CLMM source parity
La clôture `0.7.50-pre-r2` complète les tranches `0.7.48` et `0.7.49` sans rouvrir leur logique trade/candle :
- `raydium_cpmm.cpi_event` est ajouté comme transport Anchor/CPI decoded-only, distinct de `swap_base_input` / `swap_base_output`.
- Le discriminant CPMM `40f4bc78a7e9690a` est codé comme `raydium_cpmm.anchor_idl_instruction` decoded-only après inspection Solscan : gestion Anchor IDL, aucune matérialisation métier.
- `raydium_clmm.cpi_event` et `raydium_clmm.update_dynamic_fee_config` sont ajoutés depuis Carbon.
- Les Program-data events CLMM reçoivent des `local_event_kind` et familles explicites.
- `create_support_mint_associated` introduit une cible métier spécialisée : `k_sol_token_account_events`.
## Note `0.7.50-final` — Raydium CPMM post-Launchpad recheck
`raydium_cpmm` remains closed. The final post-Launchpad cleanup removes the three legacy `raydium_cpmm.instruction_audit` rows for discriminator `40f4bc78a7e9690a` after they have been replaced by the local decoded-only `raydium_cpmm.anchor_idl_instruction` entry. This does not promote the discriminator to a trade, liquidity, fee, admin or lifecycle event.

View File

@@ -1,4 +1,4 @@
# DEX Event Coverage Matrix — `khadhroony-bobobot` `0.7.49` # DEX Event Coverage Matrix — `khadhroony-bobobot` `0.7.50-pre-r2`
Cette matrice complète `docs/DEX_DECODER_MATRIX.md` avec une lecture par familles d'événements. Elle ne remplace pas la preuve locale : une entrée Git/IDL reste un indice tant qu'elle n'est pas observée dans le corpus local puis validée par replay et SQL. Cette matrice complète `docs/DEX_DECODER_MATRIX.md` avec une lecture par familles d'événements. Elle ne remplace pas la preuve locale : une entrée Git/IDL reste un indice tant qu'elle n'est pas observée dans le corpus local puis validée par replay et SQL.
@@ -96,7 +96,93 @@ Sources inventoriées : Carbon `raydium-clmm-decoder`, fnzero `sol-parser-sdk`,
Les 11 Anchor / `Program data` events restent `upstream_git_unverified` et préparés audit-only faute dobservation locale : `collect_personal_fee_event`, `collect_protocol_fee_event`, `config_change_event`, `create_personal_position_event`, `decrease_liquidity_event`, `increase_liquidity_event`, `liquidity_calculate_event`, `liquidity_change_event`, `pool_created_event`, `swap_event`, `update_reward_infos_event`. Les 11 Anchor / `Program data` events restent `upstream_git_unverified` et préparés audit-only faute dobservation locale : `collect_personal_fee_event`, `collect_protocol_fee_event`, `config_change_event`, `create_personal_position_event`, `decrease_liquidity_event`, `increase_liquidity_event`, `liquidity_calculate_event`, `liquidity_change_event`, `pool_created_event`, `swap_event`, `update_reward_infos_event`.
## `0.7.50` — `raydium_launchpad` planned ## `0.7.50` — `raydium_launchpad` bootstrap
Prochaine tranche : identifier program ids/IDL, lister instructions/events/discriminants, constituer corpus Demo3/Solscan/Demo2, puis appliquer les mêmes règles de coverage et matérialisation que CPMM/CLMM. Sources inventoriées : Carbon `raydium-launchpad-decoder`, Solscan Program IDL `LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj`, fnzero IDL listings, Raydium SDK Launchpad examples. Code local canonique : `raydium_launchpad`. Aucun alias Rust `raydium_launchlab` ne doit être conservé dans lAPI publique.
État de départ préparé : `1` entrée programme et `26` entrées discriminées listées depuis Carbon/IDL. Toutes les entrées Launchpad sont gardées `decoded_events_only` en bootstrap, même si leur famille inférée est `swap`, `pool_create`, `fee`, `admin_config`, `launch` ou `migration`. La matérialisation métier est volontairement différée jusqu'au corpus local.
| Famille | Entrées Raydium Launchpad | Statut `0.7.50` bootstrap | Cible DB initiale | Justification / règle |
|---|---|---|---|---|
| `swap` | `buy_exact_in`, `buy_exact_out`, `sell_exact_in`, `sell_exact_out`, `trade_event` | `upstream_git_mapped_unverified` puis `decoded/audit-only` si observé | `k_sol_dex_decoded_events_only` | Aucun trade/candle avant preuve locale de montants, sens et absence de doublon avec la surface DEX de migration. |
| `pool_create` | `initialize`, `initialize_v2`, `initialize_with_token_2022`, `pool_create_event` | `upstream_git_mapped_unverified` | `decoded_events_only` | Lifecycle launch/pool non promu tant que le compte pool/mint/quote n'est pas validé localement. |
| `add_liquidity` | `-` direct confirmé | `not_applicable` | `-` | Peut apparaître via DEX de destination ou SPL side effects, pas comme instruction Launchpad directe prouvée. |
| `remove_liquidity` | `-` direct confirmé | `not_applicable` | `-` | Même règle que `add_liquidity`. |
| `position_open` | `-` | `not_applicable` | `-` | Pas de position CLMM/LP NFT directe confirmée. |
| `position_close` | `-` | `not_applicable` | `-` | Pas de position CLMM/LP NFT directe confirmée. |
| `fee` | `claim_creator_fee`, `claim_platform_fee`, `claim_platform_fee_from_vault`, `claim_vested_event`, `claim_vested_token`, `collect_fee`, `collect_migrate_fee` | `upstream_git_mapped_unverified` puis `decoded/audit-only` si observé | `decoded_events_only` | Fee/vesting/migration fee utile pour stratégie, mais pas matérialisé sans corpus. |
| `reward` | `-` direct confirmé | `not_applicable` | `-` | Vesting n'est pas promu en reward transversal dans cette tranche. |
| `admin/config` | `create_config`, `create_platform_config`, `remove_platform_curve_param`, `update_config`, `update_platform_config`, `update_platform_curve_param` | `upstream_git_mapped_unverified` puis `decoded/audit-only` si observé | `decoded_events_only` | Admin/config utile pour audit, pas de table métier promue. |
| `mint` | SPL Token / Token-2022 side effects possibles | `indirect` | `decoded_events_only` | Ne devient pas `raydium_launchpad.*` sans instruction directe du programme. |
| `burn` | SPL Token / Token-2022 side effects possibles | `indirect` | `decoded_events_only` | Même règle que `mint`. |
| `transfer` | SPL Token / Token-2022 side effects attendus | `indirect` | `decoded_events_only` | Même règle que CPMM/CLMM : side effect transversal. |
| `account_create` | `create_vesting_account`, `create_vesting_event` | `upstream_git_mapped_unverified` | `decoded_events_only` | Vesting/account audit uniquement, pas de nouvelle table transversale. |
| `account_close` | `-` direct confirmé | `not_applicable` | `-` | Aucun close direct Launchpad confirmé. |
| `wrap_sol` | Side effect utilisateur/router possible | `indirect` | `decoded_events_only` | Hors programme Launchpad direct. |
| `unwrap_sol` | Side effect utilisateur/router possible | `indirect` | `decoded_events_only` | Hors programme Launchpad direct. |
| `order_place` | `-` | `not_applicable` | `-` | Launchpad n'est pas traité comme orderbook. |
| `order_cancel` | `-` | `not_applicable` | `-` | Launchpad n'est pas traité comme orderbook. |
| `order_fill` | `-` | `not_applicable` | `-` | Launchpad n'est pas traité comme orderbook. |
| `consume_events` | `-` | `not_applicable` | `-` | Launchpad n'est pas traité comme orderbook. |
| `settle_funds` | `-` | `not_applicable` | `-` | Launchpad n'est pas traité comme orderbook. |
| `vault_deposit` | `-` direct confirmé | `not_applicable` | `-` | Aucun vault direct Launchpad confirmé. |
| `vault_withdraw` | `-` direct confirmé | `not_applicable` | `-` | Aucun vault direct Launchpad confirmé. |
| `lock` | `-` direct confirmé | `not_applicable` | `-` | Liquidity locking reste une autre surface Raydium. |
| `unlock` | `-` direct confirmé | `not_applicable` | `-` | Liquidity locking reste une autre surface Raydium. |
| `launch` | `initialize*`, `pool_create_event` | `upstream_git_mapped_unverified` | `decoded_events_only` | La promotion `k_sol_launch_events` est différée. |
| `migration` | `migrate_to_amm`, `migrate_to_cpswap`, `collect_migrate_fee` | `upstream_git_mapped_unverified` | `decoded_events_only` | Destination AMM/CPMM à valider localement avant liaison métier. |
| `stake` | `-` | `not_applicable` | `-` | Aucun stake direct Launchpad confirmé. |
| `unstake` | `-` | `not_applicable` | `-` | Aucun unstake direct Launchpad confirmé. |
| `unknown/unmapped audit` | `raydium_launchpad.instruction_audit` | `audit-only` | `decoded_events_only` | Résidu à réduire par discriminant après backfill ciblé et replay. |
Rapport détaillé : `docs/reports/RAYDIUM_LAUNCHPAD_EVENT_COVERAGE_REPORT.md`.
SQL de validation : `validation_sql/SQL_VALIDATION_RAYDIUM_LAUNCHPAD_0_7_50.sql`.
### 0.7.50-pre3 Launchpad note
pre3 correction: Launchpad self-CPI selector `e445a52e51cb9a1d` is transport only. Known embedded event discriminators are decoded as `raydium_launchpad.trade_event` and `raydium_launchpad.pool_create_event`. The Launchpad `initialize*` instruction family now supplies pool/pair catalog context; `trade_event` remains decoded-only until trade/candle promotion is explicitly proven.
## Note `0.7.50-pre-r2` — Raydium CPMM/CLMM closure re-check
Sources ajoutées à la vérification CPMM/CLMM : Carbon `raydium-cpmm-decoder`, Carbon `raydium-clmm-decoder`, Solscan Program IDL CPMM/CLMM et `sol-parser-sdk` IDL Raydium.
### CPMM
- `cpi_event` est ajouté à la matrice CPMM avec `event_family=cpi_transport`, `expected_db_target=k_sol_dex_decoded_events_only`, `local_event_kind=raydium_cpmm.cpi_event` et discriminant `e445a52e51cb9a1d`.
- `swap_event` reste `decoded_events_only` pour éviter le double comptage avec `swap_base_input` / `swap_base_output`.
- Le discriminant local `40f4bc78a7e9690a` est codé comme `raydium_cpmm.anchor_idl_instruction`, `event_family=idl_management`, `expected_db_target=k_sol_dex_decoded_events_only`, après inspection Solscan des logs `IdlCreateAccount` / `IdlCloseAccount`.
### CLMM
- `cpi_event` est ajouté à la matrice CLMM avec `event_family=cpi_transport`, `expected_db_target=k_sol_dex_decoded_events_only`, `local_event_kind=raydium_clmm.cpi_event` et discriminant `e445a52e51cb9a1d`.
- `update_dynamic_fee_config` est ajouté avec `event_family=admin_config`, `expected_db_target=k_sol_pool_admin_events`, `local_event_kind=raydium_clmm.update_dynamic_fee_config` et discriminant `0707500802c784f0`.
- Les Program-data events CLMM sont maintenant rattachés localement : `swap_event`, `pool_created_event`, `liquidity_change_event`, `create_personal_position_event`, `decrease_liquidity_event`, `increase_liquidity_event`, `collect_protocol_fee_event`, `config_change_event`, `update_reward_infos_event`.
- `swap_event` et `swap_router_base_in` restent `decoded_events_only` : les trades canoniques sont `swap` / `swap_v2`, afin d'éviter le double comptage et la matérialisation de routes sans pool direct.
- `liquidity_calculate_event` est classé `liquidity_calculation` et reste `decoded_events_only`, car il sert au diagnostic/calcul et non à une mutation de liquidité fiable.
- `create_support_mint_associated` cible la nouvelle table `k_sol_token_account_events`.
- `create_operation_account` et `update_operation_account` sont normalisés en `admin_config`.
Validation attendue après replay : aucune entrée CPMM/CLMM ne doit rester en `event_family='unknown'` hors `program`, les fallbacks `upstream_git.instruction_match` ne doivent pas dupliquer une entrée locale couverte, et les transactions failed ne doivent matérialiser ni trade, ni liquidity, ni fee/admin/reward/orderbook/token-account.
Rapport associé : `docs/reports/RAYDIUM_CPMM_CLMM_RECHECK_REPORT_0_7_50_PRE_R2.md`.
## Note `0.7.50-final` — CPMM audit cleanup after Launchpad recheck
The `raydium_cpmm` recheck identified a legacy residual `raydium_cpmm.instruction_audit` row for discriminator `40f4bc78a7e9690a`. The discriminator is locally mapped as `raydium_cpmm.anchor_idl_instruction` and belongs to Anchor IDL management, not to AMM business activity.
Final rule:
| Decoder | Entry | Family | DB target | Decision |
|---|---|---|---|---|
| `raydium_cpmm` | `anchor_idl_instruction` / `40f4bc78a7e9690a` | `idl_management` | `k_sol_dex_decoded_events_only` | Keep decoded-only; remove legacy `raydium_cpmm.instruction_audit` duplicates after replay/coverage refresh. |
Expected residual checks after final replay:
```text
raydium_cpmm.instruction_audit = 0
raydium_cpmm decoded events missing coverage row = 0
```

View File

@@ -0,0 +1,211 @@
# Raydium Launchpad event coverage report — `0.7.50`
## Scope
`0.7.50` opens the `raydium_launchpad` tranche after the functional closure of `0.7.49 raydium_clmm`.
Local canonical decoder/surface code:
```text
raydium_launchpad
```
Canonical program id:
```text
LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj
```
The legacy local name `raydium_launchlab` is not kept in the public Rust API. Coverage rows, upstream registry rows, launch origin entries, and support matrix rows use `raydium_launchpad`.
## Sources used
Primary source hints for this tranche:
- Carbon decoder registry/source: `sevenlabs-hq/carbon/decoders/raydium-launchpad-decoder`.
- Solscan Program IDL/account page: `https://solscan.io/account/LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj#programIdl`.
- fnzero IDL sources: `sol-parser-sdk` / `solana-program-idls` listings, including `raydium_launchpad.json` and separate `raydium_pool_v4.json` as an audit-only source.
- Raydium SDK Launchpad examples for account-shape hints only.
These sources are not treated as final business proof. Promotion still requires local corpus observation and SQL validation.
## Bootstrap implementation delta
Implemented in this delta:
- `RAYDIUM_LAUNCHPAD_PROGRAM_ID` added as the canonical public constant.
- Upstream generated registry rows normalized from `raydium_launchlab` to `raydium_launchpad`.
- Built-in launch surface code normalized to `raydium_launchpad`.
- DEX support/catalog entries normalized to `raydium_launchpad`.
- Raydium instruction audit fallback now recognizes Launchpad program id.
- Launchpad mapped instruction fallback added for locally listed Launchpad discriminators.
- Coverage target override keeps Launchpad rows `decoded_events_only` until corpus promotion.
- SQL validation file added for the `0.7.50` tranche.
## Listed Launchpad entries
The local upstream registry now lists one program entry plus the following 26 discriminator entries.
| Entry kind | Entry name | Discriminator | Initial family | Initial DB target |
|---|---:|---:|---|---|
| instruction | `buy_exact_in` | `faea0d7bd59c13ec` | swap | decoded_events_only |
| instruction | `buy_exact_out` | `18d3742869039938` | swap | decoded_events_only |
| instruction | `claim_creator_fee` | `1a618acb84ab8dfc` | fee | decoded_events_only |
| instruction | `claim_platform_fee` | `9c27d0874ced3d48` | fee | decoded_events_only |
| instruction | `claim_platform_fee_from_vault` | `75f1c6a8f8da501d` | fee | decoded_events_only |
| event | `claim_vested_event` | `15c2725778d3e220` | fee/vesting audit | decoded_events_only |
| instruction | `claim_vested_token` | `3121681ebd9d4f23` | fee/vesting audit | decoded_events_only |
| instruction | `collect_fee` | `3cadf767045d8230` | fee | decoded_events_only |
| instruction | `collect_migrate_fee` | `ffba96dfeb76c9ba` | fee/migration audit | decoded_events_only |
| instruction | `create_config` | `c9cff3724b6f2fbd` | admin_config | decoded_events_only |
| instruction | `create_platform_config` | `b05ac4affd71dc14` | admin_config | decoded_events_only |
| instruction | `create_vesting_account` | `81b2020dd9ace6da` | account_create/vesting audit | decoded_events_only |
| event | `create_vesting_event` | `96980bb334d2bf7d` | account_create/vesting audit | decoded_events_only |
| instruction | `initialize` | `afaf6d1f0d989bed` | pool_create/launch | decoded_events_only |
| instruction | `initialize_v2` | `4399af27da102620` | pool_create/launch | decoded_events_only |
| instruction | `initialize_with_token_2022` | `25be7ede2c9aab11` | pool_create/launch | decoded_events_only |
| instruction | `migrate_to_amm` | `cf52c091fecf91df` | migration | decoded_events_only |
| instruction | `migrate_to_cpswap` | `885cc8671cda908c` | migration | decoded_events_only |
| event | `pool_create_event` | `97d7e20976a173ae` | pool_create | decoded_events_only |
| instruction | `remove_platform_curve_param` | `1b1e3ea95de01891` | admin_config | decoded_events_only |
| instruction | `sell_exact_in` | `9527de9bd37c981a` | swap | decoded_events_only |
| instruction | `sell_exact_out` | `5fc8472208090ba6` | swap | decoded_events_only |
| event | `trade_event` | `bddb7fd34ee661ee` | swap | decoded_events_only |
| instruction | `update_config` | `1d9efcbf0a53db63` | admin_config | decoded_events_only |
| instruction | `update_platform_config` | `c33c4c81922d438f` | admin_config | decoded_events_only |
| instruction | `update_platform_curve_param` | `8a908afadc800439` | admin_config | decoded_events_only |
Notes:
- The buy/sell instruction account hints currently use account index `4` as candidate pool account and indexes `9`/`10` as candidate token mints, based on Carbon/Raydium Launchpad account shape hints. This is an audit helper, not a materialization proof.
- Fee/admin/migration/vesting entries intentionally do not infer pool/token accounts until corpus confirms the account semantics.
- Program-data transport is represented by `cpi_event`; embedded events are decoded by their own discriminators and materialized only when their event family has a validated target.
## Family audit matrix
| Family | Launchpad status in `0.7.50` final | Decision |
|---|---|---|
| swap | `trade_event` materialized as trades/candles; buy/sell instructions materialized as launch breadcrumbs. | No duplicate trades from instruction breadcrumbs. |
| pool_create | `initialize`, `initialize_v2`, `initialize_with_token_2022`, `pool_create_event`. | Pool lifecycle/catalogue materialized when transaction succeeded. |
| add_liquidity | No direct Launchpad entry confirmed. | Non-applicable unless local corpus proves direct Launchpad liquidity instruction. |
| remove_liquidity | No direct Launchpad liquidity remove entry confirmed. | Non-applicable unless local corpus proves direct Launchpad liquidity instruction. |
| position_open | No direct Launchpad position instruction confirmed. | Non-applicable. |
| position_close | No direct Launchpad position instruction confirmed. | Non-applicable. |
| fee | claim/collect fee entries listed. | Fee table materialization enabled for observed successful transactions. |
| reward | No direct reward instruction confirmed. | Non-applicable unless local corpus proves otherwise. |
| admin/config | create/update config and platform curve/config entries listed. | Pool admin materialization enabled for observed successful transactions. |
| mint | Token minting may appear as SPL Token/Token-2022 side effect. | Not `raydium_launchpad.*` without direct program proof. |
| burn | Token burn may appear as SPL Token/Token-2022 side effect. | Not `raydium_launchpad.*` without direct program proof. |
| transfer | Transfers are expected as SPL Token/Token-2022 side effects. | Not `raydium_launchpad.*` without direct program proof. |
| account_create / vesting | `create_vesting_account`, `create_platform_vesting_account`, vesting events. | Launch event materialization enabled for observed successful transactions; unobserved events remain mapped. |
| account_close | No direct Launchpad account close confirmed. | Non-applicable. |
| wrap_sol | No direct Launchpad wrap SOL confirmed. | Side effect only unless corpus proves direct instruction. |
| unwrap_sol | No direct Launchpad unwrap SOL confirmed. | Side effect only unless corpus proves direct instruction. |
| order_place | No orderbook surface confirmed. | Non-applicable. |
| order_cancel | No orderbook surface confirmed. | Non-applicable. |
| order_fill | No orderbook surface confirmed. | Non-applicable. |
| consume_events | No orderbook surface confirmed. | Non-applicable. |
| settle_funds | No orderbook surface confirmed. | Non-applicable. |
| vault_deposit | No direct vault deposit confirmed. | Non-applicable. |
| vault_withdraw | No direct vault withdraw confirmed. | Non-applicable. |
| lock | No direct lock confirmed. | Non-applicable. |
| unlock | No direct unlock confirmed. | Non-applicable. |
| launch | initialize/pool_create path listed. | Decode/audit only. |
| migration | `migrate_to_amm`, `migrate_to_cpswap`, `collect_migrate_fee` listed. | Decode/audit only. Destination DEX materialization must be proven locally. |
| stake | No direct stake confirmed. | Non-applicable. |
| unstake | No direct unstake confirmed. | Non-applicable. |
| unknown/unmapped audit | `raydium_launchpad.instruction_audit` retained for unmatched program instructions. | Must trend toward zero for locally covered discriminators after backfill/replay. |
## SQL validation expectations
After targeted backfill and replay:
1. `k_sol_dex_event_coverage_entries` should contain the Launchpad program entry and discriminator entries.
2. Mapped entries should have `local_event_kind = raydium_launchpad.<entry_name>` and initial `proof_status = upstream_git_mapped_unverified` until observed.
3. Locally observed instructions should increment `k_sol_instruction_observations` for `decoder_code = raydium_launchpad`.
4. `upstream_git.instruction_match` fallback rows for `upstreamDecoderCode = raydium_launchpad` should be zero for locally covered instruction discriminators.
5. `raydium_launchpad.*` rows must not produce trades/candles unless a later corpus-backed patch explicitly promotes a specific event.
6. Failed transactions may be decoded/audited, but must not be materialized in trade/candle tables.
Validation file:
```text
validation_sql/SQL_VALIDATION_RAYDIUM_LAUNCHPAD_0_7_50.sql
```
## Suggested targeted Solscan discovery loop
For each discriminator:
```text
https://solscan.io/account/LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj?instruction=<DISCRIMINATOR>&hide_spam=true&hide_failed=true&show_related=false&sort=desc
```
Then:
1. copy a small batch of recent non-failed signatures;
2. backfill through Demo2 textarea batch;
3. replay with `forceDexDecode=yes` and `deferInstructionObservations=yes`;
4. run the validation SQL;
5. promote only entries whose local payload and account semantics are proven.
## `raydium_pool_v4.json` audit status
The current workspace archive does not contain a local `raydium_pool_v4.json` copy. External fnzero IDL listings expose a separate `raydium_pool_v4.json` beside `raydium_launchpad.json`, but this delta does not confirm its program id or business role.
Decision for `0.7.50`:
- do not promote `raydium_pool_v4` as a DEX/surface;
- keep `0.7.53 raydium_pool_v4 audit / program-id decision` conditional;
- require program id confirmation and local corpus before any roadmap promotion.
## Current limitations
This delta was prepared from the provided archive only. No live RPC backfill, fresh SQLite replay, `cargo fmt`, `cargo test`, or `cargo clippy` could be executed in the current environment because the Rust toolchain is unavailable here. The SQL and code paths are prepared for local validation in the normal project environment.
## Local corpus snapshot from first 0.7.50 backfill
Observed after targeted Demo2 backfills and pool backfill on a fresh 0.7.50 DB:
- coverage listed entries: `27`;
- decoded/local mapped entries: `26`;
- observed entries: `21`;
- materialized entries: `0`;
- total observed coverage count: `672`;
- total materialized count: `0`;
- trade count: `0`;
- residual `upstream_git.instruction_match` for `raydium_launchpad`: `0`;
- residual `raydium_launchpad.instruction_audit`: `287`;
- residual audit discriminators: `e445a52e51cb9a1d` (`276`), `9247ad4562130f6a` (`10`), `a25b92c75d85eaed` (`1`).
The `e445a52e51cb9a1d` selector is handled as Anchor self-CPI event transport. It is not promoted as a Raydium Launchpad business instruction. The two low-count residual discriminators remain local-corpus audit-only until an IDL/upstream mapping is confirmed.
## pre3 correction — Demo3 preset and Launchpad pool catalog
The first replay after pre2 confirmed that Anchor self-CPI selector `e445a52e51cb9a1d` carries Launchpad `trade_event` (`bddb7fd34ee661ee`) and `pool_create_event` (`97d7e20976a173ae`). pre3 therefore decodes those two self-CPI event rows as direct `raydium_launchpad.*` events instead of leaving them under `raydium_launchpad.instruction_audit`. `trade_event` remains audit/decoded-only and is still not promoted to `k_sol_trade_events` or candles.
pre3 also fixes the Launchpad `initialize`, `initialize_v2` and `initialize_with_token_2022` account mapping using the Carbon account shape: `pool_state` index 5, `base_mint` index 6 and `quote_mint` index 7. These initialize rows are now routed to business-level pool detection as `raydium_launchpad` bonding-curve pools with pending status, which should allow pool `6HLQPoLrzX6LqePRiXQ1GGs2Dd9K3dp9VhTSHBugYzzZ` to appear in the local catalog after a forced replay when its initialize transaction is present locally.
Demo3 now exposes a `Raydium Launchpad` preset with program id `LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj`.
## Final `0.7.50` closure snapshot
Validated closure state reported by local replay:
- `cargo test -p kb_lib`: 404 passed, 0 failed.
- Local replay: 437 replayed, 437 ledger upserts, 30 unsafe ledger rows, 256 trades, 115 lifecycle rows, 1024 candle upserts, 6205 instruction observations.
- Launchpad catalogue: 58 tokens, 58 pools, 58 pairs after replay.
- Coverage normalization: no ambiguous `unknown` family remains; only the synthetic `program` row may have an empty family.
- `trade_event`: 260 decoded, 250 successful materialized trades; 10 failed transactions intentionally not materialized.
- `buy_exact_*` / `sell_exact_*`: materialized as `k_sol_launch_events` swap-instruction breadcrumbs, not as trades.
- `cpi_event`: kept as `cpi_transport` / decoded-only; embedded events are decoded by direct event discriminator.
- Successful `trade_event` rows without materialized `k_sol_trade_events`: zero.
Post-closure recheck assets added:
- `validation_sql/SQL_VALIDATION_RAYDIUM_CPMM_0_7_50_PRE_R2.sql`
- `validation_sql/SQL_VALIDATION_RAYDIUM_CLMM_0_7_50_PRE_R2.sql`
- `docs/SOLSCAN_ACCOUNT_SOURCE_MATRIX.md`
- `kb_lib::SOLSCAN_ACCOUNT_SOURCES`

View File

@@ -0,0 +1,160 @@
# Solscan account source matrix
This file records the manual Solscan account inventory added during the `0.7.50` Raydium Launchpad closure. It is a source catalogue, not a support guarantee. Entries with `solscan_program_idl` can be used as IDL candidates; entries with `no_idl` require source/corpus work before decoder promotion.
| Label | Account id | IDL status | Source |
|---|---|---|---|
| `1Dex Program` | `DEXYosS6oEGvk8uCDayvwEZz4qEyDJRf9nFgYCaqPMTm` | `no_idl` | https://solscan.io/account/DEXYosS6oEGvk8uCDayvwEZz4qEyDJRf9nFgYCaqPMTm |
| `AlphaQ` | `ALPHAQmeA7bjrVuccPsYPiCvsi428SNwte66Srvs4pHA` | `no_idl` | https://solscan.io/account/ALPHAQmeA7bjrVuccPsYPiCvsi428SNwte66Srvs4pHA |
| `Aldrin AMM` | `AMM55ShdkoGRB5jVYPjWziwk8m5MpwyDgsMWHaMSQWH6` | `no_idl` | https://solscan.io/account/AMM55ShdkoGRB5jVYPjWziwk8m5MpwyDgsMWHaMSQWH6 |
| `Aldrin AMM V2` | `CURVGoZn8zycx6FXwwevgBTB2gVvdbGTEpvMJDbgs2t4` | `no_idl` | https://solscan.io/account/CURVGoZn8zycx6FXwwevgBTB2gVvdbGTEpvMJDbgs2t4 |
| `ApePro Smart Wallet Program` | `JSW99DKmxNyREQM14SQLDykeBvEUG63TeohrvmofEiw` | `solscan_program_idl` | https://solscan.io/account/JSW99DKmxNyREQM14SQLDykeBvEUG63TeohrvmofEiw#programIdl |
| `Aquifer` | `AQU1FRd7papthgdrwPTTq5JacJh8YtwEXaBfKU3bTz45` | `no_idl` | https://solscan.io/account/AQU1FRd7papthgdrwPTTq5JacJh8YtwEXaBfKU3bTz45 |
| `Arbitrage Bot (3s1rA)` | `3s1rAymURnacreXreMy718GfqW6kygQsLNka1xDyW8pC` | `no_idl` | https://solscan.io/account/3s1rAymURnacreXreMy718GfqW6kygQsLNka1xDyW8pC |
| `Arbitrage Bot (6MWVT)` | `6MWVTis8rmmk6Vt9zmAJJbmb3VuLpzoQ1aHH4N6wQEGh` | `no_idl` | https://solscan.io/account/6MWVTis8rmmk6Vt9zmAJJbmb3VuLpzoQ1aHH4N6wQEGh |
| `Arbitrage Bot (9Zzf9)` | `9Zzf9QqTy3TkyXysvJBsXyuRjda5aXCEJ9vXfL2HKSYv` | `no_idl` | https://solscan.io/account/9Zzf9QqTy3TkyXysvJBsXyuRjda5aXCEJ9vXfL2HKSYv |
| `Axiom Trade` | `FLASHX8DrLbgeR8FcfNV1F5krxYcYMUdBkrP1EPBtxB9` | `no_idl` | https://solscan.io/account/FLASHX8DrLbgeR8FcfNV1F5krxYcYMUdBkrP1EPBtxB9 |
| `Bags: Token Authority` | `BAGSB9TpGrZxQbEsrEznv5jXXdwyP6AXerN8aVRiAmcv` | `solscan_account` | https://solscan.io/account/BAGSB9TpGrZxQbEsrEznv5jXXdwyP6AXerN8aVRiAmcv |
| `Believe : Token Authority` | `5qWya6UjwWnGVhdSBL3hyZ7B45jbk6Byt1hwd7ohEGXE` | `no_idl` | https://solscan.io/account/5qWya6UjwWnGVhdSBL3hyZ7B45jbk6Byt1hwd7ohEGXE |
| `BisonFi` | `BiSoNHVpsVZW2F7rx2eQ59yQwKxzU5NvBcmKshCSUypi` | `no_idl` | https://solscan.io/account/BiSoNHVpsVZW2F7rx2eQ59yQwKxzU5NvBcmKshCSUypi |
| `BonkSwap` | `BSwp6bEBihVLdqJRKGgzjcGLHkcTuzmSo1TQkHepzH8p` | `solscan_program_idl` | https://solscan.io/account/BSwp6bEBihVLdqJRKGgzjcGLHkcTuzmSo1TQkHepzH8p#programIdl |
| `Boop.fun` | `boop8hVGQGqehUK2iVEMEnMrL5RbjywRzHKBmBE7ry4` | `solscan_program_idl` | https://solscan.io/account/boop8hVGQGqehUK2iVEMEnMrL5RbjywRzHKBmBE7ry4#programIdl |
| `Byreal: CLMM` | `REALQqNEomY6cQGZJUGwywTBD2UmDT32rZcNnfxQ5N2` | `solscan_program_idl` | https://solscan.io/account/REALQqNEomY6cQGZJUGwywTBD2UmDT32rZcNnfxQ5N2#programIdl |
| `Bubblegum` | `BGUMAp9Gq7iTEuizy4pqaxsTyUCBK68MDfK752saRPUY` | `solscan_program_idl` | https://solscan.io/account/BGUMAp9Gq7iTEuizy4pqaxsTyUCBK68MDfK752saRPUY#programIdl |
| `Carrot DeFi` | `CarrotwivhMpDnm27EHmRLeQ683Z1PufuqEmBZvD282s` | `solscan_program_idl` | https://solscan.io/account/CarrotwivhMpDnm27EHmRLeQ683Z1PufuqEmBZvD282s#programIdl |
| `CCTP TokenMessengerMinter` | `CCTPiPYPc6AsJuwueEnWgSgucamXDZwBd53dQ11YiKX3` | `solscan_program_idl` | https://solscan.io/account/CCTPiPYPc6AsJuwueEnWgSgucamXDZwBd53dQ11YiKX3#programIdl |
| `CCTP TokenMessengerMinterV2` | `CCTPV2vPZJS2u2BBsUoscuikbYjnpFmbFsvVuJdgUMQe` | `solscan_program_idl` | https://solscan.io/account/CCTPV2vPZJS2u2BBsUoscuikbYjnpFmbFsvVuJdgUMQe#programIdl |
| `Clone` | `C1onEW2kPetmHmwe74YC1ESx3LnFEpVau6g2pg4fHycr` | `solscan_program_idl` | https://solscan.io/account/C1onEW2kPetmHmwe74YC1ESx3LnFEpVau6g2pg4fHycr#programIdl |
| `Crema Finance Program` | `CLMM9tUoggJu2wagPkkqs9eFG4BWhVBZWkP1qv3Sp7tR` | `no_idl` | https://solscan.io/account/CLMM9tUoggJu2wagPkkqs9eFG4BWhVBZWkP1qv3Sp7tR |
| `Cropper Finance` | `CTMAxxk34HjKWxQ3QLZK1HpaLXmBveao3ESePXbiyfzh` | `no_idl` | https://solscan.io/account/CTMAxxk34HjKWxQ3QLZK1HpaLXmBveao3ESePXbiyfzh |
| `Cropper Whirlpool` | `H8W3ctz92svYg6mkn1UtGfu2aQr2fnUFHM1RhScEtQDt` | `no_idl` | https://solscan.io/account/H8W3ctz92svYg6mkn1UtGfu2aQr2fnUFHM1RhScEtQDt |
| `deBridge Destination` | `dst5MGcFPoBeREFAA5E3tU5ij8m5uVYwkzkSAbsLbNo` | `no_idl` | https://solscan.io/account/dst5MGcFPoBeREFAA5E3tU5ij8m5uVYwkzkSAbsLbNo |
| `deBridge Source` | `src5qyZHqTqecJV4aY6Cb6zDZLMDzrDKKezs22MPHr4` | `no_idl` | https://solscan.io/account/src5qyZHqTqecJV4aY6Cb6zDZLMDzrDKKezs22MPHr4 |
| `Dexlab Swap` | `DSwpgjMvXhtGn6BsbqmacdBZyfLj6jSWf3HJpdJtmg6N` | `no_idl` | https://solscan.io/account/DSwpgjMvXhtGn6BsbqmacdBZyfLj6jSWf3HJpdJtmg6N |
| `DFlow Aggregator v4` | `DF1ow4tspfHX9JwWJsAb9epbkA8hmpSEAtxXy1V27QBH` | `solscan_program_idl` | https://solscan.io/account/DF1ow4tspfHX9JwWJsAb9epbkA8hmpSEAtxXy1V27QBH#programIdl |
| `Drift V2 Program` | `dRiftyHA39MWEi3m9aunc5MzRF1JYuBsbn6VPcn33UH` | `solscan_program_idl` | https://solscan.io/account/dRiftyHA39MWEi3m9aunc5MzRF1JYuBsbn6VPcn33UH#programIdl |
| `Fluxbeam Program` | `FLUXubRmkEi2q6K3Y9kBPg9248ggaZVsoSFhtJHSrm1X` | `no_idl` | https://solscan.io/account/FLUXubRmkEi2q6K3Y9kBPg9248ggaZVsoSFhtJHSrm1X |
| `Fusion AMM` | `fUSioN9YKKSa3CUC2YUc4tPkHJ5Y6XW1yz8y6F7qWz9` | `solscan_program_idl` | https://solscan.io/account/fUSioN9YKKSa3CUC2YUc4tPkHJ5Y6XW1yz8y6F7qWz9#programIdl |
| `Futarchy AMM` | `FUTARELBfJfQ8RDGhg1wdhddq1odMAJUePHFuBYfUxKq` | `solscan_program_idl` | https://solscan.io/account/FUTARELBfJfQ8RDGhg1wdhddq1odMAJUePHFuBYfUxKq#programIdl |
| `Gavel` | `srAMMzfVHVAtgSJc8iH6CfKzuWuUTzLHVCE81QU1rgi` | `no_idl` | https://solscan.io/account/srAMMzfVHVAtgSJc8iH6CfKzuWuUTzLHVCE81QU1rgi |
| `GoonFi` | `goonERTdGsjnkZqWuVjs73BZ3Pb9qoCUdBUL17BnS5j` | `no_idl` | https://solscan.io/account/goonERTdGsjnkZqWuVjs73BZ3Pb9qoCUdBUL17BnS5j |
| `GoonFi V2` | `goonuddtQRrWqqn5nFyczVKaie28f3kDkHWkHtURSLE` | `no_idl` | https://solscan.io/account/goonuddtQRrWqqn5nFyczVKaie28f3kDkHWkHtURSLE |
| `GooseFX: GAMMA` | `GAMMA7meSFWaBXF25oSUgmGRwaW6sCMFLmBNiMSdbHVT` | `solscan_program_idl` | https://solscan.io/account/GAMMA7meSFWaBXF25oSUgmGRwaW6sCMFLmBNiMSdbHVT#programIdl |
| `GooseFX V2` | `GFXsSL5sSaDfNFQUYsHekbWBW1TsFdjDYzACh62tEHxn` | `solscan_program_idl` | https://solscan.io/account/GFXsSL5sSaDfNFQUYsHekbWBW1TsFdjDYzACh62tEHxn#programIdl |
| `Guac Swap` | `Gswppe6ERWKpUTXvRPfXdzHhiCyJvLadVvXGfdpBqcE1` | `solscan_program_idl` | https://solscan.io/account/Gswppe6ERWKpUTXvRPfXdzHhiCyJvLadVvXGfdpBqcE1#programIdl |
| `HawkFi Program` | `FqGg2Y1FNxMiGd51Q6UETixQWkF5fB92MysbYogRJb3P` | `no_idl` | https://solscan.io/account/FqGg2Y1FNxMiGd51Q6UETixQWkF5fB92MysbYogRJb3P |
| `Heaven DEX` | `HEAVENoP2qxoeuF8Dj2oT1GHEnu49U5mJYkdeC8BAX2o` | `no_idl` | https://solscan.io/account/HEAVENoP2qxoeuF8Dj2oT1GHEnu49U5mJYkdeC8BAX2o |
| `Helium Treasury Management` | `treaf4wWBBty3fHdyBpo35Mz84M8k3heKXmjmi9vFt5` | `solscan_program_idl` | https://solscan.io/account/treaf4wWBBty3fHdyBpo35Mz84M8k3heKXmjmi9vFt5#programIdl |
| `HumidiFi` | `9H6tua7jkLhdm3w8BvgpTn5LZNU7g4ZynDmCiNN3q6Rp` | `no_idl` | https://solscan.io/account/9H6tua7jkLhdm3w8BvgpTn5LZNU7g4ZynDmCiNN3q6Rp |
| `Hylo Exchange` | `HYEXCHtHkBagdStcJCp3xbbb9B7sdMdWXFNj6mdsG4hn` | `solscan_program_idl` | https://solscan.io/account/HYEXCHtHkBagdStcJCp3xbbb9B7sdMdWXFNj6mdsG4hn#programIdl |
| `Hylo Stability Pool` | `HysTabVUfmQBFcmzu1ctRd1Y1fxd66RBpboy1bmtDSQQ` | `solscan_program_idl` | https://solscan.io/account/HysTabVUfmQBFcmzu1ctRd1Y1fxd66RBpboy1bmtDSQQ#programIdl |
| `Invariant Swap` | `HyaB3W9q6XdA5xwpU4XnSZV94htfmbmqJXZcEbRaJutt` | `no_idl` | https://solscan.io/account/HyaB3W9q6XdA5xwpU4XnSZV94htfmbmqJXZcEbRaJutt |
| `Jito Tip Distribution` | `4R3gSG8BpU4t19KYj8CfnbtRpnT8gtk4dvTHxVRwc2r7` | `solscan_program_idl` | https://solscan.io/account/4R3gSG8BpU4t19KYj8CfnbtRpnT8gtk4dvTHxVRwc2r7#programIdl |
| `Jupiter Aggregator v6` | `JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4` | `solscan_program_idl` | https://solscan.io/account/JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4#programIdl |
| `Jupiter Aggregator v4` | `JUP4Fb2cqiRUcaTHdrPC8h2gNsA2ETXiPDD33WcGuJB` | `solscan_program_idl` | https://solscan.io/account/JUP4Fb2cqiRUcaTHdrPC8h2gNsA2ETXiPDD33WcGuJB#programIdl |
| `Jupiter DCA program` | `DCA265Vj8a9CEuX1eb1LWRnDT7uK6q1xMipnNyatn23M` | `solscan_program_idl` | https://solscan.io/account/DCA265Vj8a9CEuX1eb1LWRnDT7uK6q1xMipnNyatn23M#programIdl |
| `Jupiter Lend Borrow` | `jupr81YtYssSyPt8jbnGuiWon5f6x9TcDEFxYe3Bdzi` | `no_idl` | https://solscan.io/account/jupr81YtYssSyPt8jbnGuiWon5f6x9TcDEFxYe3Bdzi |
| `Jupiter Lend Earn` | `jup3YeL8QhtSx1e253b2FDvsMNC87fDrgQZivbrndc9` | `solscan_program_idl` | https://solscan.io/account/jup3YeL8QhtSx1e253b2FDvsMNC87fDrgQZivbrndc9#programIdl |
| `Jupiter Lend Flash Loan` | `jupgfSgfuAXv4B6R2Uxu85Z1qdzgju79s6MfZekN6XS` | `no_idl` | https://solscan.io/account/jupgfSgfuAXv4B6R2Uxu85Z1qdzgju79s6MfZekN6XS |
| `Jupiter Lend Liquidity` | `jupeiUmn818Jg1ekPURTpr4mFo29p46vygyykFJ3wZC` | `no_idl` | https://solscan.io/account/jupeiUmn818Jg1ekPURTpr4mFo29p46vygyykFJ3wZC |
| `Jupiter Limit Order` | `jupoNjAxXgZ4rjzxzPMP4oxduvQsQtZzyknqvzYNrNu` | `solscan_program_idl` | https://solscan.io/account/jupoNjAxXgZ4rjzxzPMP4oxduvQsQtZzyknqvzYNrNu#programIdl |
| `Jupiter Limit Order V2` | `j1o2qRpjcyUwEvwtcfhEQefh773ZgjxcVRry7LDqg5X` | `solscan_program_idl` | https://solscan.io/account/j1o2qRpjcyUwEvwtcfhEQefh773ZgjxcVRry7LDqg5X#programIdl |
| `Jupiter Lock` | `LocpQgucEQHbqNABEYvBvwoxCPsSbG91A1QaQhQQqjn` | `solscan_program_idl` | https://solscan.io/account/LocpQgucEQHbqNABEYvBvwoxCPsSbG91A1QaQhQQqjn#programIdl |
| `Jupiter Perpetuals` | `PERPHjGBqRHArX4DySjwM6UJHiR3sWAatqfdBS2qQJu` | `solscan_program_idl` | https://solscan.io/account/PERPHjGBqRHArX4DySjwM6UJHiR3sWAatqfdBS2qQJu#programIdl |
| `Jupiter Prediction Market` | `3ZZuTbwC6aJbvteyVxXUS7gtFYdf7AuXeitx6VyvjvUp` | `no_idl` | https://solscan.io/account/3ZZuTbwC6aJbvteyVxXUS7gtFYdf7AuXeitx6VyvjvUp |
| `Jupiter Stable Program` | `JUPUSDecMzAVgztLe6eGhwUBj1Pn3j9WAXwmtHmfbRr` | `solscan_program_idl` | https://solscan.io/account/JUPUSDecMzAVgztLe6eGhwUBj1Pn3j9WAXwmtHmfbRr#programIdl |
| `Jup Studio: Authority` | `8rE9CtCjwhSmbwL5fbJBtRFsS3ohfMcDFeTTC7t4ciUA` | `no_idl` | https://solscan.io/account/8rE9CtCjwhSmbwL5fbJBtRFsS3ohfMcDFeTTC7t4ciUA |
| `Kamino Program` | `6LtLpnUFNByNXLyCoK9wA2MykKAmQNZKBdY8s47dehDc` | `solscan_program_idl` | https://solscan.io/account/6LtLpnUFNByNXLyCoK9wA2MykKAmQNZKBdY8s47dehDc#programIdl |
| `Kamino Lending Program` | `KLend2g3cP87fffoy8q1mQqGKjrxjC8boSyAYavgmjD` | `solscan_program_idl` | https://solscan.io/account/KLend2g3cP87fffoy8q1mQqGKjrxjC8boSyAYavgmjD#programIdl |
| `Kamino Farm` | `FarmsPZpWu9i7Kky8tPN37rs2TpmMrAZrC7S7vJa91Hr` | `solscan_program_idl` | https://solscan.io/account/FarmsPZpWu9i7Kky8tPN37rs2TpmMrAZrC7S7vJa91Hr#programIdl |
| `Kamino Vault Program` | `kvauTFR8qm1dhniz6pYuBZkuene3Hfrs1VQhVRgCNrr` | `solscan_program_idl` | https://solscan.io/account/kvauTFR8qm1dhniz6pYuBZkuene3Hfrs1VQhVRgCNrr#programIdl |
| `Kvault Program` | `KvauGMspG5k6rtzrqqn7WNn3oZdyKqLKwK2XWQ8FLjd` | `solscan_program_idl` | https://solscan.io/account/KvauGMspG5k6rtzrqqn7WNn3oZdyKqLKwK2XWQ8FLjd#programIdl |
| `LayerZero Endpoint` | `76y77prsiCMvXMjuoZ5VRrhG5qYBrUMYTE5WgHqgjEn6` | `solscan_program_idl` | https://solscan.io/account/76y77prsiCMvXMjuoZ5VRrhG5qYBrUMYTE5WgHqgjEn6#programIdl |
| `LayerZero Executor` | `6doghB248px58JSSwG4qejQ46kFMW4AMj7vzJnWZHNZn` | `solscan_program_idl` | https://solscan.io/account/6doghB248px58JSSwG4qejQ46kFMW4AMj7vzJnWZHNZn#programIdl |
| `letsbonk.fun: PlatformConfig` | `FfYek5vEz23cMkWsdJwG2oa6EphsvXSHrGpdALN4g6W1` | `no_idl` | https://solscan.io/account/FfYek5vEz23cMkWsdJwG2oa6EphsvXSHrGpdALN4g6W1 |
| `Lifinity Swap` | `EewxydAPCCVuNEyrVN68PuSYdQ7wKn27V9Gjeoi8dy3S` | `no_idl` | https://solscan.io/account/EewxydAPCCVuNEyrVN68PuSYdQ7wKn27V9Gjeoi8dy3S |
| `Lifinity Swap V2` | `2wT8Yq49kHgDzXuPxZSaeLaH1qbmGXtEyPy64bL7aD3c` | `solscan_program_idl` | https://solscan.io/account/2wT8Yq49kHgDzXuPxZSaeLaH1qbmGXtEyPy64bL7aD3c#programIdl |
| `Manifest` | `MNFSTqtC93rEfYHB6hF82sKdZpUDFWkViLByLd1k1Ms` | `no_idl` | https://solscan.io/account/MNFSTqtC93rEfYHB6hF82sKdZpUDFWkViLByLd1k1Ms |
| `Marcopolo Swap` | `9tKE7Mbmj4mxDjWatikzGAtkoWosiiZX9y6J4Hfm2R8H` | `no_idl` | https://solscan.io/account/9tKE7Mbmj4mxDjWatikzGAtkoWosiiZX9y6J4Hfm2R8H |
| `Marginfi` | `MFLQPPPPjNinkdKoy2odNFBhvpY43XtCDZjBwG2fwn5` | `no_idl` | https://solscan.io/account/MFLQPPPPjNinkdKoy2odNFBhvpY43XtCDZjBwG2fwn5 |
| `Marginfi V2` | `MFv2hWf31Z9kbCa1snEPYctwafyhdvnV7FZnsebVacA` | `solscan_program_idl` | https://solscan.io/account/MFv2hWf31Z9kbCa1snEPYctwafyhdvnV7FZnsebVacA#programIdl |
| `Marinade Finance` | `MarBmsSgKXdrN1egZf5sqe1TMai9K1rChYNDJgjq7aD` | `solscan_program_idl` | https://solscan.io/account/MarBmsSgKXdrN1egZf5sqe1TMai9K1rChYNDJgjq7aD#programIdl |
| `Mercurial Stable Swap` | `MERLuDFBMmsHnsBPZw2sDQZHvXFMwp8EdjudcU2HKky` | `no_idl` | https://solscan.io/account/MERLuDFBMmsHnsBPZw2sDQZHvXFMwp8EdjudcU2HKky |
| `MetaDAO AMM Program v0.5` | `AMMJdEiCCa8mdugg6JPF7gFirmmxisTfDJoSNSUi5zDJ` | `solscan_program_idl` | https://solscan.io/account/AMMJdEiCCa8mdugg6JPF7gFirmmxisTfDJoSNSUi5zDJ#programIdl |
| `MetaDAO Bid Wall Program` | `WALL8ucBuUyL46QYxwYJjidaFYhdvxUFrgvBxPshERx` | `solscan_program_idl` | https://solscan.io/account/WALL8ucBuUyL46QYxwYJjidaFYhdvxUFrgvBxPshERx#programIdl |
| `MetaDAO ICO` | `moontUzsdepotRGe5xsfip7vLPTJnVuafqdUWexVnPM` | `solscan_program_idl` | https://solscan.io/account/moontUzsdepotRGe5xsfip7vLPTJnVuafqdUWexVnPM#programIdl |
| `Metaplex Token Metadata` | `metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s` | `no_idl` | https://solscan.io/account/metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s |
| `Meteora DLMM Program` | `LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo` | `solscan_program_idl` | https://solscan.io/account/LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo#programIdl |
| `Meteora Pools Program` | `Eo7WjKq67rjJQSZxS6z3YkapzY3eMj6Xy8X5EQVn5UaB` | `solscan_program_idl` | https://solscan.io/account/Eo7WjKq67rjJQSZxS6z3YkapzY3eMj6Xy8X5EQVn5UaB#programIdl |
| `Meteora Dynamic Bonding Curve` | `dbcij3LWUppWqq96dh6gJWwBifmcGfLSB5D4DuSMaqN` | `solscan_program_idl` | https://solscan.io/account/dbcij3LWUppWqq96dh6gJWwBifmcGfLSB5D4DuSMaqN#programIdl |
| `Meteora DAMM v2` | `cpamdpZCGKUy5JxQXB4dcpGPiikHawvSWAd6mEn1sGG` | `solscan_program_idl` | https://solscan.io/account/cpamdpZCGKUy5JxQXB4dcpGPiikHawvSWAd6mEn1sGG#programIdl |
| `Meteora Vault Program` | `24Uqj9JCLxUeoC3hGfh5W3s9FM9uCHDS2SG3LYwBpyTi` | `solscan_program_idl` | https://solscan.io/account/24Uqj9JCLxUeoC3hGfh5W3s9FM9uCHDS2SG3LYwBpyTi#programIdl |
| `Moonit` | `MoonCVVNZFSYkqNXP6bxHLPL6QQJiMagDL3qcqUQTrG` | `solscan_program_idl` | https://solscan.io/account/MoonCVVNZFSYkqNXP6bxHLPL6QQJiMagDL3qcqUQTrG#programIdl |
| `Moonshot : Token Authority` | `7rtiKSUDLBm59b1SBmD9oajcP8xE64vAGSMbAN5CXy1q` | `no_idl` | https://solscan.io/account/7rtiKSUDLBm59b1SBmD9oajcP8xE64vAGSMbAN5CXy1q |
| `Mpl Core` | `CoREENxT6tW1HoK8ypY1SxRMZTcVPm7R94rH4PZNhX7d` | `no_idl` | https://solscan.io/account/CoREENxT6tW1HoK8ypY1SxRMZTcVPm7R94rH4PZNhX7d |
| `Name Service Program` | `namesLPneVptA9Z5rqUDD9tMTWEJwofgaYwp8cawRkX` | `no_idl` | https://solscan.io/account/namesLPneVptA9Z5rqUDD9tMTWEJwofgaYwp8cawRkX |
| `Numeraire` | `NUMERUNsFCP3kuNmWZuXtm1AaQCPj9uw6Guv2Ekoi5P` | `solscan_program_idl` | https://solscan.io/account/NUMERUNsFCP3kuNmWZuXtm1AaQCPj9uw6Guv2Ekoi5P#programIdl |
| `Obric V2` | `obriQD1zbpyLz95G5n7nJe6a4DPjpFwa5XYPoNm113y` | `no_idl` | https://solscan.io/account/obriQD1zbpyLz95G5n7nJe6a4DPjpFwa5XYPoNm113y |
| `OKX Labs 1` | `6m2CDdhRgxpH4WjvdzxAYbGxwdGUz5MziiL5jek2kBma` | `solscan_program_idl` | https://solscan.io/account/6m2CDdhRgxpH4WjvdzxAYbGxwdGUz5MziiL5jek2kBma#programIdl |
| `OKX: DEX Router` | `proVF4pMXVaYqmy4NjniPh4pqKNfMmsihgd4wdkCX3u` | `solscan_program_idl` | https://solscan.io/account/proVF4pMXVaYqmy4NjniPh4pqKNfMmsihgd4wdkCX3u#programIdl |
| `Ondo Global Markets` | `XzTT4XB8m7sLD2xi6snefSasaswsKCxx5Tifjondogm` | `solscan_program_idl` | https://solscan.io/account/XzTT4XB8m7sLD2xi6snefSasaswsKCxx5Tifjondogm#programIdl |
| `Openbook V2` | `opnb2LAfJYbRMAHHvqjCwQxanZn7ReEHp1k81EohpZb` | `solscan_program_idl` | https://solscan.io/account/opnb2LAfJYbRMAHHvqjCwQxanZn7ReEHp1k81EohpZb#programIdl |
| `Orca Whirlpools Program` | `whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc` | `solscan_program_idl` | https://solscan.io/account/whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc#programIdl |
| `Orca Wavebreak` | `waveQX2yP3H1pVU8djGvEHmYg8uamQ84AuyGtpsrXTF` | `solscan_program_idl` | https://solscan.io/account/waveQX2yP3H1pVU8djGvEHmYg8uamQ84AuyGtpsrXTF#programIdl |
| `Orca Token Swap` | `DjVE6JNiYqPL2QXyCUUh8rNjHrbz9hXHNYt99MQ59qw1` | `no_idl` | https://solscan.io/account/DjVE6JNiYqPL2QXyCUUh8rNjHrbz9hXHNYt99MQ59qw1 |
| `Orca Token Swap V2` | `9W959DqEETiGZocYWCQPaJ6sBmUzgfxXfqGeTEdp3aQP` | `no_idl` | https://solscan.io/account/9W959DqEETiGZocYWCQPaJ6sBmUzgfxXfqGeTEdp3aQP |
| `Ore V3 Program` | `oreV3EG1i9BEgiAJ8b177Z2S2rMarzak4NMv1kULvWv` | `no_idl` | https://solscan.io/account/oreV3EG1i9BEgiAJ8b177Z2S2rMarzak4NMv1kULvWv |
| `PancakeSwap` | `HpNfyc2Saw7RKkQd8nEL4khUcuPhQ7WwY1B2qjx8jxFq` | `solscan_program_idl` | https://solscan.io/account/HpNfyc2Saw7RKkQd8nEL4khUcuPhQ7WwY1B2qjx8jxFq#programIdl |
| `Penguin Finance` | `PSwapMdSai8tjrEXcxFeQth87xC4rRsa4VA5mhGhXkP` | `no_idl` | https://solscan.io/account/PSwapMdSai8tjrEXcxFeQth87xC4rRsa4VA5mhGhXkP |
| `Phoenix` | `PhoeNiXZ8ByJGLkxNfZRnkUfjvmuYqLR89jjFHGqdXY` | `no_idl` | https://solscan.io/account/PhoeNiXZ8ByJGLkxNfZRnkUfjvmuYqLR89jjFHGqdXY |
| `Printr` | `T8HsGYv7sMk3kTnyaRqZrbRPuntYzdh12evXBkprint` | `solscan_program_idl` | https://solscan.io/account/T8HsGYv7sMk3kTnyaRqZrbRPuntYzdh12evXBkprint#programIdl |
| `Pump.fun` | `6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P` | `solscan_program_idl` | https://solscan.io/account/6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P#programIdl |
| `Pump.fun AMM` | `pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA` | `solscan_program_idl` | https://solscan.io/account/pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA#programIdl |
| `Pump Fees Program` | `pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ` | `solscan_program_idl` | https://solscan.io/account/pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ#programIdl |
| `pumpup.ai` | `PdMDrKEMaX8q7CCJb7NvUCxerBCcsFUa4LjBEynTtEd` | `solscan_program_idl` | https://solscan.io/account/PdMDrKEMaX8q7CCJb7NvUCxerBCcsFUa4LjBEynTtEd#programIdl |
| `Raydium AMM Routing` | `routeUGWgWzqBWFcrCfv8tritsqukccJPu3q5GPP3xS` | `no_idl` | https://solscan.io/account/routeUGWgWzqBWFcrCfv8tritsqukccJPu3q5GPP3xS |
| `Raydium Concentrated Liquidity` | `CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK` | `solscan_program_idl` | https://solscan.io/account/CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK#programIdl |
| `Raydium CPMM` | `CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C` | `solscan_program_idl` | https://solscan.io/account/CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C#programIdl |
| `Raydium LaunchLab` | `LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj` | `solscan_program_idl` | https://solscan.io/account/LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj#programIdl |
| `Raydium LaunchLab: PlatformConfig` | `4Bu96XjU84XjPDSpveTVf6LYGCkfW5FK7SNkREWcEfV4` | `no_idl` | https://solscan.io/account/4Bu96XjU84XjPDSpveTVf6LYGCkfW5FK7SNkREWcEfV4 |
| `Raydium liquidity pool AMM` | `5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h` | `no_idl` | https://solscan.io/account/5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h |
| `Raydium Liquidity Pool V2` | `RVKd61ztZW9GUwhRbbLoYVRE5Xf1B2tVscKqwZqXgEr` | `no_idl` | https://solscan.io/account/RVKd61ztZW9GUwhRbbLoYVRE5Xf1B2tVscKqwZqXgEr |
| `Raydium Liquidity Pool V3` | `27haf8L6oxUeXrHrgEgsexjSY5hbVUWEmvv9Nyxg8vQv` | `no_idl` | https://solscan.io/account/27haf8L6oxUeXrHrgEgsexjSY5hbVUWEmvv9Nyxg8vQv |
| `Raydium Liquidity Pool V4` | `675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8` | `no_idl` | https://solscan.io/account/675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8 |
| `Raydium Lock LP` | `LockrWmn6K5twhz3y9w1dQERbmgSaRkfnTeTKbpofwE` | `solscan_program_idl` | https://solscan.io/account/LockrWmn6K5twhz3y9w1dQERbmgSaRkfnTeTKbpofwE#programIdl |
| `Saber Decimal Wrapper` | `DecZY86MU5Gj7kppfUCEmd4LbXXuyZH1yHaP2NTqdiZB` | `solscan_program_idl` | https://solscan.io/account/DecZY86MU5Gj7kppfUCEmd4LbXXuyZH1yHaP2NTqdiZB#programIdl |
| `Saber Stable Swap` | `SSwpkEEcbUqx4vtoEByFjSkhKdCT862DNVb52nZg1UZ` | `no_idl` | https://solscan.io/account/SSwpkEEcbUqx4vtoEByFjSkhKdCT862DNVb52nZg1UZ |
| `Saros AMM` | `SSwapUtytfBdBn1b9NUGG6foMVPtcWgpRU32HToDUZr` | `no_idl` | https://solscan.io/account/SSwapUtytfBdBn1b9NUGG6foMVPtcWgpRU32HToDUZr |
| `Sanctum Multi-Validator SPL Stake Pool Program` | `SPMBzsVUuoHA4Jm6KunbsotaahvVikZs1JyTW6iJvbn` | `no_idl` | https://solscan.io/account/SPMBzsVUuoHA4Jm6KunbsotaahvVikZs1JyTW6iJvbn |
| `Sanctum Router Program` | `stkitrT1Uoy18Dk1fTrgPw8W6MVzoCfYoAFT4MLsmhq` | `no_idl` | https://solscan.io/account/stkitrT1Uoy18Dk1fTrgPw8W6MVzoCfYoAFT4MLsmhq |
| `Sanctum: S Controller` | `5ocnV1qiCgaQR8Jb8xWnVbApfaygJ8tNoZfgPwsgx9kx` | `no_idl` | https://solscan.io/account/5ocnV1qiCgaQR8Jb8xWnVbApfaygJ8tNoZfgPwsgx9kx |
| `Sanctum Single Validator SPL Stake Pool Program` | `SP12tWFxD9oJsVWNavTTBZvMbA6gkAmxtVgxdqvyvhY` | `solscan_account` | https://solscan.io/account/SP12tWFxD9oJsVWNavTTBZvMbA6gkAmxtVgxdqvyvhY |
| `SharkyFi` | `SHARKobtfF1bHhxD2eqftjHBdVSCbKo9JtgK71FhELP` | `no_idl` | https://solscan.io/account/SHARKobtfF1bHhxD2eqftjHBdVSCbKo9JtgK71FhELP |
| `Solayer` | `sSo1iU21jBrU9VaJ8PJib1MtorefUV4fzC9GURa2KNn` | `no_idl` | https://solscan.io/account/sSo1iU21jBrU9VaJ8PJib1MtorefUV4fzC9GURa2KNn |
| `Solend Protocol` | `So1endDq2YkqhipRh3WViPa8hdiSpxWy6z3Z6tMCpAo` | `no_idl` | https://solscan.io/account/So1endDq2YkqhipRh3WViPa8hdiSpxWy6z3Z6tMCpAo |
| `SolFi` | `SoLFiHG9TfgtdUXUjWAxi3LtvYuFyDLVhBWxdMZxyCe` | `no_idl` | https://solscan.io/account/SoLFiHG9TfgtdUXUjWAxi3LtvYuFyDLVhBWxdMZxyCe |
| `SolFi V2` | `SV2EYYJyRz2YhfXwXnhNAevDEui5Q6yrfyo13WtupPF` | `no_idl` | https://solscan.io/account/SV2EYYJyRz2YhfXwXnhNAevDEui5Q6yrfyo13WtupPF |
| `stabble CLMM` | `6dMXqGZ3ga2dikrYS9ovDXgHGh5RUsb2RTUj6hrQXhk6` | `solscan_program_idl` | https://solscan.io/account/6dMXqGZ3ga2dikrYS9ovDXgHGh5RUsb2RTUj6hrQXhk6#programIdl |
| `stabble Stable Swap` | `swapNyd8XiQwJ6ianp9snpu4brUqFxadzvHebnAXjJZ` | `solscan_program_idl` | https://solscan.io/account/swapNyd8XiQwJ6ianp9snpu4brUqFxadzvHebnAXjJZ#programIdl |
| `stabble Weighted Swap` | `swapFpHZwjELNnjvThjajtiVmkz3yPQEHjLtka2fwHW` | `solscan_program_idl` | https://solscan.io/account/swapFpHZwjELNnjvThjajtiVmkz3yPQEHjLtka2fwHW#programIdl |
| `Stake Pool` | `SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy` | `no_idl` | https://solscan.io/account/SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy |
| `Stake Program` | `Stake11111111111111111111111111111111111111` | `no_idl` | https://solscan.io/account/Stake11111111111111111111111111111111111111 |
| `Step Finance Swap Program` | `SSwpMgqNDsyV7mAgN9ady4bDVu5ySjmmXejXvy2vLt1` | `no_idl` | https://solscan.io/account/SSwpMgqNDsyV7mAgN9ady4bDVu5ySjmmXejXvy2vLt1 |
| `StepN DOOAR Swap` | `Dooar9JkhdZ7J3LHN3A7YCuoGRUggXhQaG4kijfLGU2j` | `no_idl` | https://solscan.io/account/Dooar9JkhdZ7J3LHN3A7YCuoGRUggXhQaG4kijfLGU2j |
| `Scorch` | `SCoRcH8c2dpjvcJD6FiPbCSQyQgu3PcUAWj2Xxx3mqn` | `no_idl` | https://solscan.io/account/SCoRcH8c2dpjvcJD6FiPbCSQyQgu3PcUAWj2Xxx3mqn |
| `Streamflow` | `strmRqUCoQUgGUan5YhzUZa6KqdzwX5L6FpUxfmKg5m` | `solscan_program_idl` | https://solscan.io/account/strmRqUCoQUgGUan5YhzUZa6KqdzwX5L6FpUxfmKg5m#programIdl |
| `Swap Program` | `SwaPpA9LAaLfeLi3a68M4DjnLqgtticKg6CnyNwgAC8` | `no_idl` | https://solscan.io/account/SwaPpA9LAaLfeLi3a68M4DjnLqgtticKg6CnyNwgAC8 |
| `Swig Program` | `swigypWHEksbC64pWKwah1WTeh9JXwx8H1rJHLdbQMB` | `no_idl` | https://solscan.io/account/swigypWHEksbC64pWKwah1WTeh9JXwx8H1rJHLdbQMB |
| `System Program` | `11111111111111111111111111111111` | `no_idl` | https://solscan.io/account/11111111111111111111111111111111 |
| `Tessera V` | `TessVdML9pBGgG9yGks7o4HewRaXVAMuoVj4x83GLQH` | `no_idl` | https://solscan.io/account/TessVdML9pBGgG9yGks7o4HewRaXVAMuoVj4x83GLQH |
| `Titan Exchange Router` | `T1TANpTeScyeqVzzgNViGDNrkQ6qHz9KrSBS4aNXvGT` | `no_idl` | https://solscan.io/account/T1TANpTeScyeqVzzgNViGDNrkQ6qHz9KrSBS4aNXvGT |
| `Token 2022 Program` | `TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb` | `no_idl` | https://solscan.io/account/TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb |
| `Token Program` | `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA` | `no_idl` | https://solscan.io/account/TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA |
| `Vertigo Program` | `vrTGoBuy5rYSxAfV3jaRJWHH6nN9WK4NRExGxsk1bCJ` | `solscan_program_idl` | https://solscan.io/account/vrTGoBuy5rYSxAfV3jaRJWHH6nN9WK4NRExGxsk1bCJ#programIdl |
| `Virtuals` | `5U3EU2ubXtK84QcRjWVmYt9RaDyA8gKxdUrPFXmZyaki` | `solscan_program_idl` | https://solscan.io/account/5U3EU2ubXtK84QcRjWVmYt9RaDyA8gKxdUrPFXmZyaki#programIdl |
| `Woofi` | `WooFif76YGRNjk1pA8wCsN67aQsD9f9iLsz4NcJ1AVb` | `solscan_program_idl` | https://solscan.io/account/WooFif76YGRNjk1pA8wCsN67aQsD9f9iLsz4NcJ1AVb#programIdl |
| `Wormhole: Bridge` | `wormDTUJ6AWPNvk59vGQbDvGJmqbDTdgWgAqcLBCgUb` | `no_idl` | https://solscan.io/account/wormDTUJ6AWPNvk59vGQbDvGJmqbDTdgWgAqcLBCgUb |
| `ZeroFi` | `ZERor4xhbUycZ6gb9ntrhqscUcZmAbQDjEAtCf4hbZY` | `no_idl` | https://solscan.io/account/ZERor4xhbUycZ6gb9ntrhqscUcZmAbQDjEAtCf4hbZY |
| `Zeta Matching Engine` | `zDEXqXEG7gAyxb1Kg9mK5fPnUdENCGKzWrM21RMdWRq` | `no_idl` | https://solscan.io/account/zDEXqXEG7gAyxb1Kg9mK5fPnUdENCGKzWrM21RMdWRq |
| `Zeta Program` | `ZETAxsqBRek56DhiGXrn75yj2NHU3aYUnxvHXpkf3aD` | `solscan_program_idl` | https://solscan.io/account/ZETAxsqBRek56DhiGXrn75yj2NHU3aYUnxvHXpkf3aD#programIdl |
| `Zora Program` | `zoRabwLGd5zXaV7Gxacppw8tcceXEiTrSKyNLSaSTUc` | `no_idl` | https://solscan.io/account/zoRabwLGd5zXaV7Gxacppw8tcceXEiTrSKyNLSaSTUc |

View File

@@ -0,0 +1,193 @@
<!-- file: docs/prompts/PROMPT_REPRISE_khadhroony-bobobot_0.7.51-raydium-amm-v4.md -->
# Prompt de reprise — khadhroony-bobobot `0.7.51` / Raydium AMM v4 event coverage
Reprise du projet `khadhroony-bobobot` après clôture de `0.7.50 raydium_launchpad` et re-vérification finale CPMM/CLMM.
## Archive de départ
Utiliser la dernière archive complète du workspace intégrant les deltas validés jusqu'à :
0.7.50-raydium-launchpad-final
Joindre aussi les docs et SQL de validation à jour :
```text
README.md
ROADMAP.md
CHANGELOG.md
docs/DEX_DECODER_MATRIX.md
docs/DEX_EVENT_COVERAGE_MATRIX.md
docs/DB_EVENT_MODEL_REVIEW.md
docs/reports/RAYDIUM_LAUNCHPAD_EVENT_COVERAGE_REPORT.md
validation_sql/SQL_VALIDATION_RAYDIUM_LAUNCHPAD_0_7_50.sql
validation_sql/SQL_VALIDATION_RAYDIUM_CPMM_AUDIT_CLEANUP_0_7_50_FINAL.sql
validation_sql/SQL_VALIDATION_RAYDIUM_CPMM_0_7_50_RECHECK.sql
validation_sql/SQL_VALIDATION_RAYDIUM_CLMM_0_7_50_RECHECK.sql
```
## État validé avant reprise
`0.7.50` a clôturé `raydium_launchpad` et consolidé les rechecks CPMM/CLMM.
Dernier replay local rapporté avant clôture :
```text
1103 replayed
0 decode skipped
1124 ledger upserts
542 unsafe ledger rows
561 trades
50 liquidity
13 lifecycle
0 tokenAccount
2224 candle upserts
instructionObservations = 7013
resetDeleted = 1182
```
Points de clôture à préserver :
```text
raydium_launchpad : surface canonique, program id LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj
Launchpad trade_event matérialisé seulement quand corpus + successful tx le prouvent
Launchpad initialize* fournit le catalogue pool/pair, pas de faux trade/candle
CPMM 40f4bc78a7e9690a est raydium_cpmm.anchor_idl_instruction decoded-only
CPMM residual raydium_cpmm.instruction_audit 40f4bc78a7e9690a doit être nettoyé après replay final
CLMM residual instruction_audit / upstream fallback doivent rester vides
k_sol_instruction_observations reste une table technique, pas une table métier
Solscan instruction=<discriminator> est une aide de découverte, pas une preuve métier
```
Requête CPMM post-fix obligatoire :
```sql
SELECT
json_extract(payload_json, '$.discriminatorHex') AS discriminator_hex,
COUNT(*) AS audit_count,
COUNT(DISTINCT transaction_id) AS tx_count
FROM k_sol_dex_decoded_events
WHERE protocol_name = 'raydium_cpmm'
AND event_kind = 'raydium_cpmm.instruction_audit'
GROUP BY discriminator_hex
ORDER BY audit_count DESC, discriminator_hex;
```
Cette requête doit être vide après replay `forceDexDecode=yes`.
## Objectif `0.7.51` — `raydium_amm_v4`
Reprendre Raydium AMM v4 legacy au même niveau de couverture que CPMM/CLMM :
```text
swaps
pool lifecycle / pool_create
add_liquidity / remove_liquidity
fees / admin/config
side effects SPL Token / Token-2022 documentés mais non promus comme raydium_amm_v4.* directs
fallback instruction_audit nettoyé quand une entrée locale spécialisée couvre l'instruction
coverage entries synchronisées et rafraîchies
```
Code local canonique :
```text
raydium_amm_v4
```
Program id canonique connu :
```text
675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8
```
Solscan Program IDL / recherche par instruction :
```text
https://solscan.io/account/675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8#programIdl
https://solscan.io/account/675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8?instruction=<DISCRIMINATOR>&hide_spam=true&hide_failed=true&show_related=false&sort=desc
```
## Sources Git/IDL à utiliser systématiquement
```text
https://github.com/sevenlabs-hq/carbon/tree/main/decoders
https://github.com/0xfnzero/solana-streamer
https://github.com/0xfnzero/sol-parser-sdk/tree/main/idl
https://github.com/pinax-network/substreams-solana-idls/tree/main/src
https://github.com/hodlwarden/solana-tx-parser/tree/main/src
https://docs.vybenetwork.com/docs/available-dexs-amms
```
Pour AMM v4, vérifier aussi les IDL/JSON Raydium legacy présents dans fnzero, notamment les fichiers autour de `raydium_amm_v4` / `raydium_pool_v4`, sans promouvoir `raydium_pool_v4` tant que son program id et son rôle métier ne sont pas prouvés localement.
## Règles fixes
```text
Rust 2024
pas de mod.rs
fichiers Rust avec // file: ...
pas de anyhow
pas de thiserror
pas de ? / unwrap / expect dans kb_lib applicatif
match / if let Err / let Err = ... else
rustdoc sur API publique
re-exports db.rs puis lib.rs si DB modifiée
```
## Invariants métier
```text
non-trade event = jamais trade/candle
failed transaction = audit-only / jamais matérialisée métier
upstream Git/IDL/Solscan = indice, pas preuve métier
program id upstream non promu sans corpus local
side effects SPL Token / Token-2022 restent transversaux sauf preuve multi-DEX et décision DB
instruction_audit et upstream_git.instruction_match doivent être nettoyés quand une entrée locale spécialisée couvre le discriminant
```
## Workflow conseillé
1. Créer une nouvelle base SQLite dédiée `0.7.51`.
2. Inventorier Carbon/fnzero/Pinax/Solscan Program IDL pour `raydium_amm_v4`.
3. Synchroniser `k_sol_dex_event_coverage_entries` avec `decoder_code = raydium_amm_v4`.
4. Utiliser Solscan `instruction=<discriminator>` pour obtenir rapidement des signatures non failed.
5. Backfill Demo2 signature/pool.
6. Replay local avec :
```text
skipDexDecode = no
forceDexDecode = yes
deferInstructionObservations = yes
```
7. Vérifier :
```text
coverage listed/observed/materialized
residual instruction_audit
residual upstream_git.instruction_match
failed tx materialization = 0
non-trade trade_count = 0
trade/candle only for swap events validés
```
## Livrables attendus
```text
archive delta fichiers modifiés/ajoutés
README.md / ROADMAP.md / CHANGELOG.md mis à jour
docs/DEX_DECODER_MATRIX.md
docs/DEX_EVENT_COVERAGE_MATRIX.md
docs/DB_EVENT_MODEL_REVIEW.md
docs/reports/RAYDIUM_AMM_V4_EVENT_COVERAGE_REPORT.md
validation_sql/SQL_VALIDATION_RAYDIUM_AMM_V4_0_7_51.sql
```
Validation finale locale :
```bash
cargo fmt
cargo test -p kb_lib
cargo clippy -p kb_lib --all-targets -- -D warnings
```

View File

@@ -132,3 +132,9 @@ La validation finale est dans :
```text ```text
validation_sql/SQL_VALIDATION_RAYDIUM_CLMM_0_7_49.sql validation_sql/SQL_VALIDATION_RAYDIUM_CLMM_0_7_49.sql
``` ```
## Addendum `0.7.50-pre-r2` — source parity CLMM
La re-vérification CLMM ajoute `cpi_event` (`e445a52e51cb9a1d`) et `update_dynamic_fee_config` (`0707500802c784f0`) depuis Carbon. Les Program-data events CLMM reçoivent maintenant un `local_event_kind` et une famille explicite quand ils sont observables localement : `swap_event`, `pool_created_event`, `liquidity_change_event`, `create_personal_position_event`, `decrease_liquidity_event`, `increase_liquidity_event`, `collect_protocol_fee_event`, `config_change_event` et `update_reward_infos_event`.
`create_support_mint_associated` est matérialisable dans la nouvelle table `k_sol_token_account_events`. `liquidity_calculate_event` reste decoded-only car il représente un calcul/diagnostic et non une mutation de liquidité fiable. `swap_event` et `swap_router_base_in` restent également decoded-only : les trades matérialisés proviennent des instructions `swap` et `swap_v2`, ce qui évite les doublons de Program-data events et les routes sans pool direct.

View File

@@ -0,0 +1,82 @@
# Raydium CPMM/CLMM re-check report — `0.7.50-pre-r2`
## Scope
This report closes the post-Launchpad re-check for `raydium_cpmm` and `raydium_clmm` using the same discipline applied to `raydium_launchpad`:
- every observed discriminator must have a named local event kind or an explicit decoded-only decision;
- `event_family='unknown'` is not acceptable outside synthetic `program` rows;
- materializable events must target the matching business table;
- duplicate, transport-only or context-incomplete events remain `k_sol_dex_decoded_events_only` by design;
- failed transactions must not produce business materialization.
## Sources
The source comparison for this tranche is based on:
- Carbon `raydium-cpmm-decoder`;
- Carbon `raydium-clmm-decoder`;
- Pinax `substreams-solana-idls` Raydium CPMM/CLMM trees;
- Solscan Program IDL pages for CPMM and CLMM;
- `0xfnzero/sol-parser-sdk` Raydium IDL snapshots;
- local corpus replay results from the dedicated CPMM and CLMM databases.
## CPMM decision
`40f4bc78a7e9690a` is now coded as:
```text
local_event_kind = raydium_cpmm.anchor_idl_instruction
event_family = idl_management
expected_db_target = k_sol_dex_decoded_events_only
```
Manual inspection of the three local signatures showed Anchor IDL management logs:
- `IdlCreateAccount` on `Hi6MkRTkcgwBi1WpiiudGPHKLuaKXKamNgVsy6YqoQeMRnrkpGjNx75ymrY59tJ3NN1GCn6nrndz9thMmwALLcY`;
- `IdlCloseAccount` on `Kch9bYneKzyPg13txxpu151QHX4EgQhFqXUHxqYLXE3BbSrMt56bNMx9JbMAZzs4fbuCLLibHAtrRHdrn7u2VUD`;
- `IdlCreateAccount` on `fsKqwEAiRCQyXvCBjBX4XGzkZXyz4DeNL1Kdw9BeyGYYAcTKPEP9sP4WXVNB2FRkvBXc3YjuGhUcihLZm3Y7Znu`.
This is not a CPMM business instruction. It must not produce trade, candle, liquidity, fee, admin or lifecycle rows.
## CPMM expected post-replay invariants
After replay on the CPMM database:
- observed discriminator coverage gap should be empty;
- residual `raydium_cpmm.instruction_audit` should be empty;
- decoded event kinds without coverage should be empty;
- materialization shortfall should be empty after excluding `k_sol_dex_decoded_events_only` and failed transactions;
- `swap_event` remains decoded-only because canonical trades come from `swap_base_input` / `swap_base_output`.
## CLMM decision
CLMM has no remaining unknown family in the coverage matrix. The re-check keeps the following entries decoded-only by design:
- `raydium_clmm.swap_event`: Program-data corroboration of swaps; canonical trade materialization remains on `swap` / `swap_v2`.
- `raydium_clmm.swap_router_base_in`: router instruction; no single direct pool surface should be inferred without hop-level resolution.
- `raydium_clmm.liquidity_calculate_event`: calculation/diagnostic event.
- `raydium_clmm.close_position` and `raydium_clmm.close_protocol_position`: decoded, but not materialized unless a reliable pool/pair context is available.
- `raydium_clmm.cpi_event`: Anchor transport only.
Materialization was strengthened for CLMM liquidity events by accepting snake_case amount keys (`amount0_raw`, `amount1_raw`, `liquidity_raw`) and by resolving pool/pair context from sibling decoded events in the same transaction when the current decoded event carries useful amounts but lacks direct pair context.
## CLMM expected post-replay invariants
After replay on the CLMM database:
- observed discriminator coverage gap should be empty;
- residual `raydium_clmm.instruction_audit` should be empty;
- decoded event kinds without coverage should be empty;
- failed transactions should not produce business rows;
- the validation SQL must count `k_sol_token_account_events`, otherwise `create_support_mint_associated` is falsely reported as a materialization gap.
## Validation files
Use:
```text
validation_sql/SQL_VALIDATION_RAYDIUM_CPMM_0_7_50_PRE_R2.sql
validation_sql/SQL_VALIDATION_RAYDIUM_CLMM_0_7_50_PRE_R2.sql
validation_sql/SQL_TRACE_RAYDIUM_CPMM_AUDIT_40F_0_7_50_PRE_R2.sql
```

View File

@@ -202,3 +202,11 @@ update_pool_status
``` ```
La prochaine tranche fonctionnelle est `0.7.49 raydium_clmm`. La prochaine tranche fonctionnelle est `0.7.49 raydium_clmm`.
## Addendum `0.7.50-pre-r2` — cpi_event et audit `40f4bc78a7e9690a`
La re-vérification CPMM ajoute explicitement `cpi_event` à la matrice coverage locale avec le discriminant Carbon `e445a52e51cb9a1d`. Cette entrée est un transport Anchor/CPI et reste `k_sol_dex_decoded_events_only`.
Le discriminant observé localement `40f4bc78a7e9690a` est classé comme `raydium_cpmm.anchor_idl_instruction`, avec `event_family=idl_management` et `expected_db_target=k_sol_dex_decoded_events_only`. Les signatures inspectées montrent `Program log: Instruction: IdlCreateAccount` et `Program log: Instruction: IdlCloseAccount` sur le compte `anchor:idl`; il ne correspond donc pas au `cpi_event` Carbon et ne doit pas être matérialisé dans les tables métier.
Trace SQL ajouté : `validation_sql/SQL_TRACE_RAYDIUM_CPMM_AUDIT_40F_0_7_50_PRE_R2.sql` liste les signatures, slots, index d'instruction, comptes et données associées à `40f4bc78a7e9690a`.

View File

@@ -0,0 +1,231 @@
# Raydium Launchpad event coverage report — `0.7.50`
## Scope
`0.7.50` opens the `raydium_launchpad` tranche after the functional closure of `0.7.49 raydium_clmm`.
Local canonical decoder/surface code:
```text
raydium_launchpad
```
Canonical program id:
```text
LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj
```
The legacy local name `raydium_launchlab` is not kept in the public Rust API. Coverage rows, upstream registry rows, launch origin entries, and support matrix rows use `raydium_launchpad`.
## Sources used
Primary source hints for this tranche:
- Carbon decoder registry/source: `sevenlabs-hq/carbon/decoders/raydium-launchpad-decoder`.
- Solscan Program IDL/account page: `https://solscan.io/account/LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj#programIdl`.
- fnzero IDL sources: `sol-parser-sdk` / `solana-program-idls` listings, including `raydium_launchpad.json` and separate `raydium_pool_v4.json` as an audit-only source.
- Raydium SDK Launchpad examples for account-shape hints only.
These sources are not treated as final business proof. Promotion still requires local corpus observation and SQL validation.
## Bootstrap implementation delta
Implemented in this delta:
- `RAYDIUM_LAUNCHPAD_PROGRAM_ID` added as the canonical public constant.
- Upstream generated registry rows normalized from `raydium_launchlab` to `raydium_launchpad`.
- Built-in launch surface code normalized to `raydium_launchpad`.
- DEX support/catalog entries normalized to `raydium_launchpad`.
- Raydium instruction audit fallback now recognizes Launchpad program id.
- Launchpad mapped instruction fallback added for locally listed Launchpad discriminators.
- Coverage target override keeps Launchpad rows `decoded_events_only` until corpus promotion.
- SQL validation file added for the `0.7.50` tranche.
## Listed Launchpad entries
The local upstream registry now lists one program entry plus the following 26 discriminator entries.
| Entry kind | Entry name | Discriminator | Initial family | Initial DB target |
|---|---:|---:|---|---|
| instruction | `buy_exact_in` | `faea0d7bd59c13ec` | swap | decoded_events_only |
| instruction | `buy_exact_out` | `18d3742869039938` | swap | decoded_events_only |
| instruction | `claim_creator_fee` | `1a618acb84ab8dfc` | fee | decoded_events_only |
| instruction | `claim_platform_fee` | `9c27d0874ced3d48` | fee | decoded_events_only |
| instruction | `claim_platform_fee_from_vault` | `75f1c6a8f8da501d` | fee | decoded_events_only |
| event | `claim_vested_event` | `15c2725778d3e220` | fee/vesting audit | decoded_events_only |
| instruction | `claim_vested_token` | `3121681ebd9d4f23` | fee/vesting audit | decoded_events_only |
| instruction | `collect_fee` | `3cadf767045d8230` | fee | decoded_events_only |
| instruction | `collect_migrate_fee` | `ffba96dfeb76c9ba` | fee/migration audit | decoded_events_only |
| instruction | `create_config` | `c9cff3724b6f2fbd` | admin_config | decoded_events_only |
| instruction | `create_platform_config` | `b05ac4affd71dc14` | admin_config | decoded_events_only |
| instruction | `create_vesting_account` | `81b2020dd9ace6da` | account_create/vesting audit | decoded_events_only |
| event | `create_vesting_event` | `96980bb334d2bf7d` | account_create/vesting audit | decoded_events_only |
| instruction | `initialize` | `afaf6d1f0d989bed` | pool_create/launch | decoded_events_only |
| instruction | `initialize_v2` | `4399af27da102620` | pool_create/launch | decoded_events_only |
| instruction | `initialize_with_token_2022` | `25be7ede2c9aab11` | pool_create/launch | decoded_events_only |
| instruction | `migrate_to_amm` | `cf52c091fecf91df` | migration | decoded_events_only |
| instruction | `migrate_to_cpswap` | `885cc8671cda908c` | migration | decoded_events_only |
| event | `pool_create_event` | `97d7e20976a173ae` | pool_create | decoded_events_only |
| instruction | `remove_platform_curve_param` | `1b1e3ea95de01891` | admin_config | decoded_events_only |
| instruction | `sell_exact_in` | `9527de9bd37c981a` | swap | decoded_events_only |
| instruction | `sell_exact_out` | `5fc8472208090ba6` | swap | decoded_events_only |
| event | `trade_event` | `bddb7fd34ee661ee` | swap | decoded_events_only |
| instruction | `update_config` | `1d9efcbf0a53db63` | admin_config | decoded_events_only |
| instruction | `update_platform_config` | `c33c4c81922d438f` | admin_config | decoded_events_only |
| instruction | `update_platform_curve_param` | `8a908afadc800439` | admin_config | decoded_events_only |
Notes:
- The buy/sell instruction account hints currently use account index `4` as candidate pool account and indexes `9`/`10` as candidate token mints, based on Carbon/Raydium Launchpad account shape hints. This is an audit helper, not a materialization proof.
- Fee/admin/migration/vesting entries intentionally do not infer pool/token accounts until corpus confirms the account semantics.
- Program-data transport is represented by `cpi_event`; embedded events are decoded by their own discriminators and materialized only when their event family has a validated target.
## Family audit matrix
| Family | Launchpad status in `0.7.50` final | Decision |
|---|---|---|
| swap | `trade_event` materialized as trades/candles; buy/sell instructions materialized as launch breadcrumbs. | No duplicate trades from instruction breadcrumbs. |
| pool_create | `initialize`, `initialize_v2`, `initialize_with_token_2022`, `pool_create_event`. | Pool lifecycle/catalogue materialized when transaction succeeded. |
| add_liquidity | No direct Launchpad entry confirmed. | Non-applicable unless local corpus proves direct Launchpad liquidity instruction. |
| remove_liquidity | No direct Launchpad liquidity remove entry confirmed. | Non-applicable unless local corpus proves direct Launchpad liquidity instruction. |
| position_open | No direct Launchpad position instruction confirmed. | Non-applicable. |
| position_close | No direct Launchpad position instruction confirmed. | Non-applicable. |
| fee | claim/collect fee entries listed. | Fee table materialization enabled for observed successful transactions. |
| reward | No direct reward instruction confirmed. | Non-applicable unless local corpus proves otherwise. |
| admin/config | create/update config and platform curve/config entries listed. | Pool admin materialization enabled for observed successful transactions. |
| mint | Token minting may appear as SPL Token/Token-2022 side effect. | Not `raydium_launchpad.*` without direct program proof. |
| burn | Token burn may appear as SPL Token/Token-2022 side effect. | Not `raydium_launchpad.*` without direct program proof. |
| transfer | Transfers are expected as SPL Token/Token-2022 side effects. | Not `raydium_launchpad.*` without direct program proof. |
| account_create / vesting | `create_vesting_account`, `create_platform_vesting_account`, vesting events. | Launch event materialization enabled for observed successful transactions; unobserved events remain mapped. |
| account_close | No direct Launchpad account close confirmed. | Non-applicable. |
| wrap_sol | No direct Launchpad wrap SOL confirmed. | Side effect only unless corpus proves direct instruction. |
| unwrap_sol | No direct Launchpad unwrap SOL confirmed. | Side effect only unless corpus proves direct instruction. |
| order_place | No orderbook surface confirmed. | Non-applicable. |
| order_cancel | No orderbook surface confirmed. | Non-applicable. |
| order_fill | No orderbook surface confirmed. | Non-applicable. |
| consume_events | No orderbook surface confirmed. | Non-applicable. |
| settle_funds | No orderbook surface confirmed. | Non-applicable. |
| vault_deposit | No direct vault deposit confirmed. | Non-applicable. |
| vault_withdraw | No direct vault withdraw confirmed. | Non-applicable. |
| lock | No direct lock confirmed. | Non-applicable. |
| unlock | No direct unlock confirmed. | Non-applicable. |
| launch | initialize/pool_create path listed. | Decode/audit only. |
| migration | `migrate_to_amm`, `migrate_to_cpswap`, `collect_migrate_fee` listed. | Decode/audit only. Destination DEX materialization must be proven locally. |
| stake | No direct stake confirmed. | Non-applicable. |
| unstake | No direct unstake confirmed. | Non-applicable. |
| unknown/unmapped audit | `raydium_launchpad.instruction_audit` retained for unmatched program instructions. | Must trend toward zero for locally covered discriminators after backfill/replay. |
## SQL validation expectations
After targeted backfill and replay:
1. `k_sol_dex_event_coverage_entries` should contain the Launchpad program entry and discriminator entries.
2. Mapped entries should have `local_event_kind = raydium_launchpad.<entry_name>` and initial `proof_status = upstream_git_mapped_unverified` until observed.
3. Locally observed instructions should increment `k_sol_instruction_observations` for `decoder_code = raydium_launchpad`.
4. `upstream_git.instruction_match` fallback rows for `upstreamDecoderCode = raydium_launchpad` should be zero for locally covered instruction discriminators.
5. `raydium_launchpad.*` rows must not produce trades/candles unless a later corpus-backed patch explicitly promotes a specific event.
6. Failed transactions may be decoded/audited, but must not be materialized in trade/candle tables.
Validation file:
```text
validation_sql/SQL_VALIDATION_RAYDIUM_LAUNCHPAD_0_7_50.sql
```
## Suggested targeted Solscan discovery loop
For each discriminator:
```text
https://solscan.io/account/LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj?instruction=<DISCRIMINATOR>&hide_spam=true&hide_failed=true&show_related=false&sort=desc
```
Then:
1. copy a small batch of recent non-failed signatures;
2. backfill through Demo2 textarea batch;
3. replay with `forceDexDecode=yes` and `deferInstructionObservations=yes`;
4. run the validation SQL;
5. promote only entries whose local payload and account semantics are proven.
## `raydium_pool_v4.json` audit status
The current workspace archive does not contain a local `raydium_pool_v4.json` copy. External fnzero IDL listings expose a separate `raydium_pool_v4.json` beside `raydium_launchpad.json`, but this delta does not confirm its program id or business role.
Decision for `0.7.50`:
- do not promote `raydium_pool_v4` as a DEX/surface;
- keep `0.7.53 raydium_pool_v4 audit / program-id decision` conditional;
- require program id confirmation and local corpus before any roadmap promotion.
## Current limitations
This delta was prepared from the provided archive only. No live RPC backfill, fresh SQLite replay, `cargo fmt`, `cargo test`, or `cargo clippy` could be executed in the current environment because the Rust toolchain is unavailable here. The SQL and code paths are prepared for local validation in the normal project environment.
## Local corpus snapshot from first 0.7.50 backfill
Observed after targeted Demo2 backfills and pool backfill on a fresh 0.7.50 DB:
- coverage listed entries: `27`;
- decoded/local mapped entries: `26`;
- observed entries: `21`;
- materialized entries: `0`;
- total observed coverage count: `672`;
- total materialized count: `0`;
- trade count: `0`;
- residual `upstream_git.instruction_match` for `raydium_launchpad`: `0`;
- residual `raydium_launchpad.instruction_audit`: `287`;
- residual audit discriminators: `e445a52e51cb9a1d` (`276`), `9247ad4562130f6a` (`10`), `a25b92c75d85eaed` (`1`).
The `e445a52e51cb9a1d` selector is handled as Anchor self-CPI event transport. It is not promoted as a Raydium Launchpad business instruction. The two low-count residual discriminators remain local-corpus audit-only until an IDL/upstream mapping is confirmed.
## pre3 correction — Demo3 preset and Launchpad pool catalog
The first replay after pre2 confirmed that Anchor self-CPI selector `e445a52e51cb9a1d` carries Launchpad `trade_event` (`bddb7fd34ee661ee`) and `pool_create_event` (`97d7e20976a173ae`). pre3 therefore decodes those two self-CPI event rows as direct `raydium_launchpad.*` events instead of leaving them under `raydium_launchpad.instruction_audit`. `trade_event` remains audit/decoded-only and is still not promoted to `k_sol_trade_events` or candles.
pre3 also fixes the Launchpad `initialize`, `initialize_v2` and `initialize_with_token_2022` account mapping using the Carbon account shape: `pool_state` index 5, `base_mint` index 6 and `quote_mint` index 7. These initialize rows are now routed to business-level pool detection as `raydium_launchpad` bonding-curve pools with pending status, which should allow pool `6HLQPoLrzX6LqePRiXQ1GGs2Dd9K3dp9VhTSHBugYzzZ` to appear in the local catalog after a forced replay when its initialize transaction is present locally.
Demo3 now exposes a `Raydium Launchpad` preset with program id `LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj`.
## Final `0.7.50` closure snapshot
Validated closure state reported by local replay:
- `cargo test -p kb_lib`: 404 passed, 0 failed.
- Local replay: 437 replayed, 437 ledger upserts, 30 unsafe ledger rows, 256 trades, 115 lifecycle rows, 1024 candle upserts, 6205 instruction observations.
- Launchpad catalogue: 58 tokens, 58 pools, 58 pairs after replay.
- Coverage normalization: no ambiguous `unknown` family remains; only the synthetic `program` row may have an empty family.
- `trade_event`: 260 decoded, 250 successful materialized trades; 10 failed transactions intentionally not materialized.
- `buy_exact_*` / `sell_exact_*`: materialized as `k_sol_launch_events` swap-instruction breadcrumbs, not as trades.
- `cpi_event`: kept as `cpi_transport` / decoded-only; embedded events are decoded by direct event discriminator.
- Successful `trade_event` rows without materialized `k_sol_trade_events`: zero.
Post-closure recheck assets added:
- `validation_sql/SQL_VALIDATION_RAYDIUM_CPMM_0_7_50_PRE_R2.sql`
- `validation_sql/SQL_VALIDATION_RAYDIUM_CLMM_0_7_50_PRE_R2.sql`
- `docs/SOLSCAN_ACCOUNT_SOURCE_MATRIX.md`
- `kb_lib::SOLSCAN_ACCOUNT_SOURCES`
## Final cleanup note — CPMM residual audit after 0.7.50 recheck
During the 0.7.50 post-Launchpad recheck, the CPMM residual audit query still showed three `raydium_cpmm.instruction_audit` rows for discriminator `40f4bc78a7e9690a` even though the same discriminator is now locally mapped as `raydium_cpmm.anchor_idl_instruction`.
The final cleanup patch makes the deletion FK-safe by unlinking `k_sol_instruction_observations.decoded_event_id` before deleting the legacy audit rows. It also repeats the CPMM cleanup after coverage refresh and refreshes coverage again if rows were removed.
Expected final state after replay:
```text
raydium_cpmm.instruction_audit / 40f4bc78a7e9690a = 0
raydium_cpmm decoded events without coverage row = 0
raydium_cpmm.anchor_idl_instruction remains decoded-only / idl_management
```
Validation SQL:
```text
validation_sql/SQL_VALIDATION_RAYDIUM_CPMM_AUDIT_CLEANUP_0_7_50_FINAL.sql
```

View File

@@ -28,6 +28,7 @@ const presets: Demo3Preset[] = [
{ label: "PumpSwap", dexCode: "pump_swap", programId: "pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA", description: "DEX effectif PumpSwap." }, { label: "PumpSwap", dexCode: "pump_swap", programId: "pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA", description: "DEX effectif PumpSwap." },
{ label: "Raydium CPMM", dexCode: "raydium_cpmm", programId: "CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C", description: "Raydium CPMM." }, { label: "Raydium CPMM", dexCode: "raydium_cpmm", programId: "CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C", description: "Raydium CPMM." },
{ label: "Raydium CLMM", dexCode: "raydium_clmm", programId: "CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK", description: "Raydium CLMM." }, { label: "Raydium CLMM", dexCode: "raydium_clmm", programId: "CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK", description: "Raydium CLMM." },
{ label: "Raydium Launchpad", dexCode: "raydium_launchpad", programId: "LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj", description: "Raydium Launchpad / LaunchLab. Surface de lancement Raydium 0.7.50." },
{ label: "Raydium AMM v4", dexCode: "raydium_amm_v4", programId: "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8", description: "Raydium AMM v4 legacy. À prouver par corpus avant décodage swap." }, { label: "Raydium AMM v4", dexCode: "raydium_amm_v4", programId: "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8", description: "Raydium AMM v4 legacy. À prouver par corpus avant décodage swap." },
{ label: "Raydium Stable Swap", dexCode: "raydium_stable_swap", programId: "5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h", description: "Stable Swap Raydium à vérifier par corpus." }, { label: "Raydium Stable Swap", dexCode: "raydium_stable_swap", programId: "5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h", description: "Stable Swap Raydium à vérifier par corpus." },
{ label: "Meteora DLMM", dexCode: "meteora_dlmm", programId: "LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo", description: "Meteora DLMM." }, { label: "Meteora DLMM", dexCode: "meteora_dlmm", programId: "LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo", description: "Meteora DLMM." },

View File

@@ -69,6 +69,7 @@ interface LocalPipelineReplayResult {
feeEventCount: number; feeEventCount: number;
rewardEventCount: number; rewardEventCount: number;
poolAdminEventCount: number; poolAdminEventCount: number;
tokenAccountEventCount: number;
pairCandleUpsertCount: number; pairCandleUpsertCount: number;
analyticSignalUpsertCount: number; analyticSignalUpsertCount: number;
transactionClassificationCount: number; transactionClassificationCount: number;
@@ -805,7 +806,7 @@ document.addEventListener("DOMContentLoaded", async () => {
appendLogLine( appendLogLine(
logTextarea, logTextarea,
`[ui] local pipeline replay completed: ${result.replayedTransactionCount.toString()} replayed, ${result.decodeSkippedCount.toString()} decode skipped, ${result.decodeLedgerUpsertCount.toString()} ledger upserts, ${result.decodeLedgerUnsafeCount.toString()} unsafe ledger rows, ${result.tradeEventCount.toString()} trades, ${result.liquidityEventCount.toString()} liquidity, ${result.poolLifecycleEventCount.toString()} lifecycle, ${result.pairCandleUpsertCount.toString()} candle upserts, instructionObservations='${result.instructionObservationUpsertedCount.toString()}', resetDeleted='${result.resetMarketMaterializationDeletedCount.toString()}'`, `[ui] local pipeline replay completed: ${result.replayedTransactionCount.toString()} replayed, ${result.decodeSkippedCount.toString()} decode skipped, ${result.decodeLedgerUpsertCount.toString()} ledger upserts, ${result.decodeLedgerUnsafeCount.toString()} unsafe ledger rows, ${result.tradeEventCount.toString()} trades, ${result.liquidityEventCount.toString()} liquidity, ${result.poolLifecycleEventCount.toString()} lifecycle, ${result.tokenAccountEventCount.toString()} tokenAccount, ${result.pairCandleUpsertCount.toString()} candle upserts, instructionObservations='${result.instructionObservationUpsertedCount.toString()}', resetDeleted='${result.resetMarketMaterializationDeletedCount.toString()}'`,
); );
await refreshCatalog(); await refreshCatalog();

View File

@@ -1,7 +1,7 @@
{ {
"name": "kb-demo-app", "name": "kb-demo-app",
"private": true, "private": true,
"version": "0.7.49", "version": "0.7.50",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
@@ -14,15 +14,15 @@
"@fortawesome/fontawesome-free": "^7.2", "@fortawesome/fontawesome-free": "^7.2",
"@tauri-apps/api": "^2.11", "@tauri-apps/api": "^2.11",
"bootstrap": "^5.3", "bootstrap": "^5.3",
"echarts": "^6.0", "echarts": "^6.1",
"resize-observer-polyfill": "^1.5", "resize-observer-polyfill": "^1.5",
"simplebar": "^6.3" "simplebar": "^6.3"
}, },
"devDependencies": { "devDependencies": {
"@tauri-apps/cli": "^2.11", "@tauri-apps/cli": "^2.11",
"@types/bootstrap": "^5.2", "@types/bootstrap": "^5.2",
"@types/node": "^25.6", "@types/node": "^25.9",
"sass-embedded": "^1.99", "sass-embedded": "^1.100",
"typescript": "^5.9", "typescript": "^5.9",
"vite": "^8.0" "vite": "^8.0"
} }

View File

@@ -1,7 +1,7 @@
{ {
"$schema": "https://schema.tauri.app/config/2", "$schema": "https://schema.tauri.app/config/2",
"productName": "kb-demo-app", "productName": "kb-demo-app",
"version": "0.7.49", "version": "0.7.50",
"identifier": "com.sasedev.kb-demo-app", "identifier": "com.sasedev.kb-demo-app",
"build": { "build": {
"beforeDevCommand": "npm run dev", "beforeDevCommand": "npm run dev",

View File

@@ -276,7 +276,13 @@ pub const RAYDIUM_CLMM_PROGRAM_ID: &str = "CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7gr
pub const RAYDIUM_CPMM_PROGRAM_ID: &str = "CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C"; pub const RAYDIUM_CPMM_PROGRAM_ID: &str = "CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C";
/// Raydium LaunchLab / Launchpad program id. ("LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj"). /// Raydium LaunchLab / Launchpad program id. ("LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj").
pub const RAYDIUM_LAUNCHLAB_PROGRAM_ID: &str = "LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj"; pub const RAYDIUM_LAUNCHPAD_PROGRAM_ID: &str = "LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj";
/// Raydium LaunchLab platform config account observed on Solscan.
///
/// This is an account source, not a decoder program id.
pub const RAYDIUM_LAUNCHPAD_PLATFORM_CONFIG_ACCOUNT_ID: &str =
"4Bu96XjU84XjPDSpveTVf6LYGCkfW5FK7SNkREWcEfV4";
/// Raydium AMM routing program id. ("routeUGWgWzqBWFcrCfv8tritsqukccJPu3q5GPP3xS"). /// Raydium AMM routing program id. ("routeUGWgWzqBWFcrCfv8tritsqukccJPu3q5GPP3xS").
pub const RAYDIUM_AMM_ROUTING_PROGRAM_ID: &str = "routeUGWgWzqBWFcrCfv8tritsqukccJPu3q5GPP3xS"; pub const RAYDIUM_AMM_ROUTING_PROGRAM_ID: &str = "routeUGWgWzqBWFcrCfv8tritsqukccJPu3q5GPP3xS";
@@ -341,9 +347,14 @@ pub const MARINADE_FINANCE_PROGRAM_ID: &str = "MarBmsSgKXdrN1egZf5sqe1TMai9K1rCh
/// Meteora Vault program id extracted from upstream Git decoder source. /// Meteora Vault program id extracted from upstream Git decoder source.
pub const METEORA_VAULT_PROGRAM_ID: &str = "24Uqj9JCLxUeoC3hGfh5W3s9FM9uCHDS2SG3LYwBpyTi"; pub const METEORA_VAULT_PROGRAM_ID: &str = "24Uqj9JCLxUeoC3hGfh5W3s9FM9uCHDS2SG3LYwBpyTi";
/// Moonshot program id extracted from upstream Git decoder source. /// Moonshot program id kept for upstream `moonshot` decoder compatibility.
///
/// Moonit / Moonshot-family program id observed with a Solscan Program IDL.
pub const MOONSHOT_PROGRAM_ID: &str = "MoonCVVNZFSYkqNXP6bxHLPL6QQJiMagDL3qcqUQTrG"; pub const MOONSHOT_PROGRAM_ID: &str = "MoonCVVNZFSYkqNXP6bxHLPL6QQJiMagDL3qcqUQTrG";
/// Moonshot token authority account observed on Solscan, not a decoder program.
pub const MOONSHOT_TOKEN_AUTHORITY_ID: &str = "7rtiKSUDLBm59b1SBmD9oajcP8xE64vAGSMbAN5CXy1q";
/// OKX DEX program id extracted from upstream Git decoder source. /// OKX DEX program id extracted from upstream Git decoder source.
pub const OKX_DEX_PROGRAM_ID: &str = "6m2CDdhRgxpH4WjvdzxAYbGxwdGUz5MziiL5jek2kBma"; pub const OKX_DEX_PROGRAM_ID: &str = "6m2CDdhRgxpH4WjvdzxAYbGxwdGUz5MziiL5jek2kBma";
@@ -415,3 +426,953 @@ pub const NAME_SERVICE_PROGRAM_ID: &str = "namesLPneVptA9Z5rqUDD9tMTWEJwofgaYwp8
/// This is not treated as a DEX program. It is used only to tag protocol /// This is not treated as a DEX program. It is used only to tag protocol
/// candidates with `candidate_surface = "arbitrage_bot"`. /// candidates with `candidate_surface = "arbitrage_bot"`.
pub const ARBITRAGE_BOT_6MWVT_PROGRAM_ID: &str = "6MWVTis8rmmk6Vt9zmAJJbmb3VuLpzoQ1aHH4N6wQEGh"; pub const ARBITRAGE_BOT_6MWVT_PROGRAM_ID: &str = "6MWVTis8rmmk6Vt9zmAJJbmb3VuLpzoQ1aHH4N6wQEGh";
/// One Solscan account source collected during manual DEX/program inventory.
///
/// This catalogue is intentionally broader than supported DEXes: it also contains
/// routers, token authorities, bot programs, lending programs and system programs.
/// Promotion into a decoder/support-matrix entry still requires source review and
/// local corpus verification.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct SolscanAccountSource {
/// Human-readable label used in the manual source inventory.
pub label: &'static str,
/// Solana account or program id shown by Solscan.
pub account_id: &'static str,
/// Solscan account URL used as the discovery source.
pub solscan_url: &'static str,
/// IDL status observed in the manual Solscan pass.
///
/// Values currently used: `solscan_program_idl`, `no_idl`, `solscan_account`.
pub idl_status: &'static str,
}
/// Manual Solscan account-source inventory collected for post-`0.7.50` DEX discovery.
///
/// This is a source catalogue only. It must not be interpreted as decoder support.
pub const SOLSCAN_ACCOUNT_SOURCES: &[SolscanAccountSource] = &[
SolscanAccountSource {
label: "1Dex Program",
account_id: "DEXYosS6oEGvk8uCDayvwEZz4qEyDJRf9nFgYCaqPMTm",
solscan_url: "https://solscan.io/account/DEXYosS6oEGvk8uCDayvwEZz4qEyDJRf9nFgYCaqPMTm",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "AlphaQ",
account_id: "ALPHAQmeA7bjrVuccPsYPiCvsi428SNwte66Srvs4pHA",
solscan_url: "https://solscan.io/account/ALPHAQmeA7bjrVuccPsYPiCvsi428SNwte66Srvs4pHA",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Aldrin AMM",
account_id: "AMM55ShdkoGRB5jVYPjWziwk8m5MpwyDgsMWHaMSQWH6",
solscan_url: "https://solscan.io/account/AMM55ShdkoGRB5jVYPjWziwk8m5MpwyDgsMWHaMSQWH6",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Aldrin AMM V2",
account_id: "CURVGoZn8zycx6FXwwevgBTB2gVvdbGTEpvMJDbgs2t4",
solscan_url: "https://solscan.io/account/CURVGoZn8zycx6FXwwevgBTB2gVvdbGTEpvMJDbgs2t4",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "ApePro Smart Wallet Program",
account_id: "JSW99DKmxNyREQM14SQLDykeBvEUG63TeohrvmofEiw",
solscan_url: "https://solscan.io/account/JSW99DKmxNyREQM14SQLDykeBvEUG63TeohrvmofEiw#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Aquifer",
account_id: "AQU1FRd7papthgdrwPTTq5JacJh8YtwEXaBfKU3bTz45",
solscan_url: "https://solscan.io/account/AQU1FRd7papthgdrwPTTq5JacJh8YtwEXaBfKU3bTz45",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Arbitrage Bot (3s1rA)",
account_id: "3s1rAymURnacreXreMy718GfqW6kygQsLNka1xDyW8pC",
solscan_url: "https://solscan.io/account/3s1rAymURnacreXreMy718GfqW6kygQsLNka1xDyW8pC",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Arbitrage Bot (6MWVT)",
account_id: "6MWVTis8rmmk6Vt9zmAJJbmb3VuLpzoQ1aHH4N6wQEGh",
solscan_url: "https://solscan.io/account/6MWVTis8rmmk6Vt9zmAJJbmb3VuLpzoQ1aHH4N6wQEGh",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Arbitrage Bot (9Zzf9)",
account_id: "9Zzf9QqTy3TkyXysvJBsXyuRjda5aXCEJ9vXfL2HKSYv",
solscan_url: "https://solscan.io/account/9Zzf9QqTy3TkyXysvJBsXyuRjda5aXCEJ9vXfL2HKSYv",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Axiom Trade",
account_id: "FLASHX8DrLbgeR8FcfNV1F5krxYcYMUdBkrP1EPBtxB9",
solscan_url: "https://solscan.io/account/FLASHX8DrLbgeR8FcfNV1F5krxYcYMUdBkrP1EPBtxB9",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Bags: Token Authority",
account_id: "BAGSB9TpGrZxQbEsrEznv5jXXdwyP6AXerN8aVRiAmcv",
solscan_url: "https://solscan.io/account/BAGSB9TpGrZxQbEsrEznv5jXXdwyP6AXerN8aVRiAmcv",
idl_status: "solscan_account",
},
SolscanAccountSource {
label: "Believe : Token Authority",
account_id: "5qWya6UjwWnGVhdSBL3hyZ7B45jbk6Byt1hwd7ohEGXE",
solscan_url: "https://solscan.io/account/5qWya6UjwWnGVhdSBL3hyZ7B45jbk6Byt1hwd7ohEGXE",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "BisonFi",
account_id: "BiSoNHVpsVZW2F7rx2eQ59yQwKxzU5NvBcmKshCSUypi",
solscan_url: "https://solscan.io/account/BiSoNHVpsVZW2F7rx2eQ59yQwKxzU5NvBcmKshCSUypi",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "BonkSwap",
account_id: "BSwp6bEBihVLdqJRKGgzjcGLHkcTuzmSo1TQkHepzH8p",
solscan_url: "https://solscan.io/account/BSwp6bEBihVLdqJRKGgzjcGLHkcTuzmSo1TQkHepzH8p#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Boop.fun",
account_id: "boop8hVGQGqehUK2iVEMEnMrL5RbjywRzHKBmBE7ry4",
solscan_url: "https://solscan.io/account/boop8hVGQGqehUK2iVEMEnMrL5RbjywRzHKBmBE7ry4#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Byreal: CLMM",
account_id: "REALQqNEomY6cQGZJUGwywTBD2UmDT32rZcNnfxQ5N2",
solscan_url: "https://solscan.io/account/REALQqNEomY6cQGZJUGwywTBD2UmDT32rZcNnfxQ5N2#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Bubblegum",
account_id: "BGUMAp9Gq7iTEuizy4pqaxsTyUCBK68MDfK752saRPUY",
solscan_url: "https://solscan.io/account/BGUMAp9Gq7iTEuizy4pqaxsTyUCBK68MDfK752saRPUY#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Carrot DeFi",
account_id: "CarrotwivhMpDnm27EHmRLeQ683Z1PufuqEmBZvD282s",
solscan_url: "https://solscan.io/account/CarrotwivhMpDnm27EHmRLeQ683Z1PufuqEmBZvD282s#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "CCTP TokenMessengerMinter",
account_id: "CCTPiPYPc6AsJuwueEnWgSgucamXDZwBd53dQ11YiKX3",
solscan_url: "https://solscan.io/account/CCTPiPYPc6AsJuwueEnWgSgucamXDZwBd53dQ11YiKX3#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "CCTP TokenMessengerMinterV2",
account_id: "CCTPV2vPZJS2u2BBsUoscuikbYjnpFmbFsvVuJdgUMQe",
solscan_url: "https://solscan.io/account/CCTPV2vPZJS2u2BBsUoscuikbYjnpFmbFsvVuJdgUMQe#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Clone",
account_id: "C1onEW2kPetmHmwe74YC1ESx3LnFEpVau6g2pg4fHycr",
solscan_url: "https://solscan.io/account/C1onEW2kPetmHmwe74YC1ESx3LnFEpVau6g2pg4fHycr#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Crema Finance Program",
account_id: "CLMM9tUoggJu2wagPkkqs9eFG4BWhVBZWkP1qv3Sp7tR",
solscan_url: "https://solscan.io/account/CLMM9tUoggJu2wagPkkqs9eFG4BWhVBZWkP1qv3Sp7tR",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Cropper Finance",
account_id: "CTMAxxk34HjKWxQ3QLZK1HpaLXmBveao3ESePXbiyfzh",
solscan_url: "https://solscan.io/account/CTMAxxk34HjKWxQ3QLZK1HpaLXmBveao3ESePXbiyfzh",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Cropper Whirlpool",
account_id: "H8W3ctz92svYg6mkn1UtGfu2aQr2fnUFHM1RhScEtQDt",
solscan_url: "https://solscan.io/account/H8W3ctz92svYg6mkn1UtGfu2aQr2fnUFHM1RhScEtQDt",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "deBridge Destination",
account_id: "dst5MGcFPoBeREFAA5E3tU5ij8m5uVYwkzkSAbsLbNo",
solscan_url: "https://solscan.io/account/dst5MGcFPoBeREFAA5E3tU5ij8m5uVYwkzkSAbsLbNo",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "deBridge Source",
account_id: "src5qyZHqTqecJV4aY6Cb6zDZLMDzrDKKezs22MPHr4",
solscan_url: "https://solscan.io/account/src5qyZHqTqecJV4aY6Cb6zDZLMDzrDKKezs22MPHr4",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Dexlab Swap",
account_id: "DSwpgjMvXhtGn6BsbqmacdBZyfLj6jSWf3HJpdJtmg6N",
solscan_url: "https://solscan.io/account/DSwpgjMvXhtGn6BsbqmacdBZyfLj6jSWf3HJpdJtmg6N",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "DFlow Aggregator v4",
account_id: "DF1ow4tspfHX9JwWJsAb9epbkA8hmpSEAtxXy1V27QBH",
solscan_url: "https://solscan.io/account/DF1ow4tspfHX9JwWJsAb9epbkA8hmpSEAtxXy1V27QBH#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Drift V2 Program",
account_id: "dRiftyHA39MWEi3m9aunc5MzRF1JYuBsbn6VPcn33UH",
solscan_url: "https://solscan.io/account/dRiftyHA39MWEi3m9aunc5MzRF1JYuBsbn6VPcn33UH#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Fluxbeam Program",
account_id: "FLUXubRmkEi2q6K3Y9kBPg9248ggaZVsoSFhtJHSrm1X",
solscan_url: "https://solscan.io/account/FLUXubRmkEi2q6K3Y9kBPg9248ggaZVsoSFhtJHSrm1X",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Fusion AMM",
account_id: "fUSioN9YKKSa3CUC2YUc4tPkHJ5Y6XW1yz8y6F7qWz9",
solscan_url: "https://solscan.io/account/fUSioN9YKKSa3CUC2YUc4tPkHJ5Y6XW1yz8y6F7qWz9#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Futarchy AMM",
account_id: "FUTARELBfJfQ8RDGhg1wdhddq1odMAJUePHFuBYfUxKq",
solscan_url: "https://solscan.io/account/FUTARELBfJfQ8RDGhg1wdhddq1odMAJUePHFuBYfUxKq#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Gavel",
account_id: "srAMMzfVHVAtgSJc8iH6CfKzuWuUTzLHVCE81QU1rgi",
solscan_url: "https://solscan.io/account/srAMMzfVHVAtgSJc8iH6CfKzuWuUTzLHVCE81QU1rgi",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "GoonFi",
account_id: "goonERTdGsjnkZqWuVjs73BZ3Pb9qoCUdBUL17BnS5j",
solscan_url: "https://solscan.io/account/goonERTdGsjnkZqWuVjs73BZ3Pb9qoCUdBUL17BnS5j",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "GoonFi V2",
account_id: "goonuddtQRrWqqn5nFyczVKaie28f3kDkHWkHtURSLE",
solscan_url: "https://solscan.io/account/goonuddtQRrWqqn5nFyczVKaie28f3kDkHWkHtURSLE",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "GooseFX: GAMMA",
account_id: "GAMMA7meSFWaBXF25oSUgmGRwaW6sCMFLmBNiMSdbHVT",
solscan_url: "https://solscan.io/account/GAMMA7meSFWaBXF25oSUgmGRwaW6sCMFLmBNiMSdbHVT#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "GooseFX V2",
account_id: "GFXsSL5sSaDfNFQUYsHekbWBW1TsFdjDYzACh62tEHxn",
solscan_url: "https://solscan.io/account/GFXsSL5sSaDfNFQUYsHekbWBW1TsFdjDYzACh62tEHxn#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Guac Swap",
account_id: "Gswppe6ERWKpUTXvRPfXdzHhiCyJvLadVvXGfdpBqcE1",
solscan_url: "https://solscan.io/account/Gswppe6ERWKpUTXvRPfXdzHhiCyJvLadVvXGfdpBqcE1#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "HawkFi Program",
account_id: "FqGg2Y1FNxMiGd51Q6UETixQWkF5fB92MysbYogRJb3P",
solscan_url: "https://solscan.io/account/FqGg2Y1FNxMiGd51Q6UETixQWkF5fB92MysbYogRJb3P",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Heaven DEX",
account_id: "HEAVENoP2qxoeuF8Dj2oT1GHEnu49U5mJYkdeC8BAX2o",
solscan_url: "https://solscan.io/account/HEAVENoP2qxoeuF8Dj2oT1GHEnu49U5mJYkdeC8BAX2o",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Helium Treasury Management",
account_id: "treaf4wWBBty3fHdyBpo35Mz84M8k3heKXmjmi9vFt5",
solscan_url: "https://solscan.io/account/treaf4wWBBty3fHdyBpo35Mz84M8k3heKXmjmi9vFt5#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "HumidiFi",
account_id: "9H6tua7jkLhdm3w8BvgpTn5LZNU7g4ZynDmCiNN3q6Rp",
solscan_url: "https://solscan.io/account/9H6tua7jkLhdm3w8BvgpTn5LZNU7g4ZynDmCiNN3q6Rp",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Hylo Exchange",
account_id: "HYEXCHtHkBagdStcJCp3xbbb9B7sdMdWXFNj6mdsG4hn",
solscan_url: "https://solscan.io/account/HYEXCHtHkBagdStcJCp3xbbb9B7sdMdWXFNj6mdsG4hn#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Hylo Stability Pool",
account_id: "HysTabVUfmQBFcmzu1ctRd1Y1fxd66RBpboy1bmtDSQQ",
solscan_url: "https://solscan.io/account/HysTabVUfmQBFcmzu1ctRd1Y1fxd66RBpboy1bmtDSQQ#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Invariant Swap",
account_id: "HyaB3W9q6XdA5xwpU4XnSZV94htfmbmqJXZcEbRaJutt",
solscan_url: "https://solscan.io/account/HyaB3W9q6XdA5xwpU4XnSZV94htfmbmqJXZcEbRaJutt",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Jito Tip Distribution",
account_id: "4R3gSG8BpU4t19KYj8CfnbtRpnT8gtk4dvTHxVRwc2r7",
solscan_url: "https://solscan.io/account/4R3gSG8BpU4t19KYj8CfnbtRpnT8gtk4dvTHxVRwc2r7#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Jupiter Aggregator v6",
account_id: "JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4",
solscan_url: "https://solscan.io/account/JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Jupiter Aggregator v4",
account_id: "JUP4Fb2cqiRUcaTHdrPC8h2gNsA2ETXiPDD33WcGuJB",
solscan_url: "https://solscan.io/account/JUP4Fb2cqiRUcaTHdrPC8h2gNsA2ETXiPDD33WcGuJB#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Jupiter DCA program",
account_id: "DCA265Vj8a9CEuX1eb1LWRnDT7uK6q1xMipnNyatn23M",
solscan_url: "https://solscan.io/account/DCA265Vj8a9CEuX1eb1LWRnDT7uK6q1xMipnNyatn23M#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Jupiter Lend Borrow",
account_id: "jupr81YtYssSyPt8jbnGuiWon5f6x9TcDEFxYe3Bdzi",
solscan_url: "https://solscan.io/account/jupr81YtYssSyPt8jbnGuiWon5f6x9TcDEFxYe3Bdzi",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Jupiter Lend Earn",
account_id: "jup3YeL8QhtSx1e253b2FDvsMNC87fDrgQZivbrndc9",
solscan_url: "https://solscan.io/account/jup3YeL8QhtSx1e253b2FDvsMNC87fDrgQZivbrndc9#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Jupiter Lend Flash Loan",
account_id: "jupgfSgfuAXv4B6R2Uxu85Z1qdzgju79s6MfZekN6XS",
solscan_url: "https://solscan.io/account/jupgfSgfuAXv4B6R2Uxu85Z1qdzgju79s6MfZekN6XS",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Jupiter Lend Liquidity",
account_id: "jupeiUmn818Jg1ekPURTpr4mFo29p46vygyykFJ3wZC",
solscan_url: "https://solscan.io/account/jupeiUmn818Jg1ekPURTpr4mFo29p46vygyykFJ3wZC",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Jupiter Limit Order",
account_id: "jupoNjAxXgZ4rjzxzPMP4oxduvQsQtZzyknqvzYNrNu",
solscan_url: "https://solscan.io/account/jupoNjAxXgZ4rjzxzPMP4oxduvQsQtZzyknqvzYNrNu#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Jupiter Limit Order V2",
account_id: "j1o2qRpjcyUwEvwtcfhEQefh773ZgjxcVRry7LDqg5X",
solscan_url: "https://solscan.io/account/j1o2qRpjcyUwEvwtcfhEQefh773ZgjxcVRry7LDqg5X#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Jupiter Lock",
account_id: "LocpQgucEQHbqNABEYvBvwoxCPsSbG91A1QaQhQQqjn",
solscan_url: "https://solscan.io/account/LocpQgucEQHbqNABEYvBvwoxCPsSbG91A1QaQhQQqjn#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Jupiter Perpetuals",
account_id: "PERPHjGBqRHArX4DySjwM6UJHiR3sWAatqfdBS2qQJu",
solscan_url: "https://solscan.io/account/PERPHjGBqRHArX4DySjwM6UJHiR3sWAatqfdBS2qQJu#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Jupiter Prediction Market",
account_id: "3ZZuTbwC6aJbvteyVxXUS7gtFYdf7AuXeitx6VyvjvUp",
solscan_url: "https://solscan.io/account/3ZZuTbwC6aJbvteyVxXUS7gtFYdf7AuXeitx6VyvjvUp",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Jupiter Stable Program",
account_id: "JUPUSDecMzAVgztLe6eGhwUBj1Pn3j9WAXwmtHmfbRr",
solscan_url: "https://solscan.io/account/JUPUSDecMzAVgztLe6eGhwUBj1Pn3j9WAXwmtHmfbRr#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Jup Studio: Authority",
account_id: "8rE9CtCjwhSmbwL5fbJBtRFsS3ohfMcDFeTTC7t4ciUA",
solscan_url: "https://solscan.io/account/8rE9CtCjwhSmbwL5fbJBtRFsS3ohfMcDFeTTC7t4ciUA",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Kamino Program",
account_id: "6LtLpnUFNByNXLyCoK9wA2MykKAmQNZKBdY8s47dehDc",
solscan_url: "https://solscan.io/account/6LtLpnUFNByNXLyCoK9wA2MykKAmQNZKBdY8s47dehDc#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Kamino Lending Program",
account_id: "KLend2g3cP87fffoy8q1mQqGKjrxjC8boSyAYavgmjD",
solscan_url: "https://solscan.io/account/KLend2g3cP87fffoy8q1mQqGKjrxjC8boSyAYavgmjD#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Kamino Farm",
account_id: "FarmsPZpWu9i7Kky8tPN37rs2TpmMrAZrC7S7vJa91Hr",
solscan_url: "https://solscan.io/account/FarmsPZpWu9i7Kky8tPN37rs2TpmMrAZrC7S7vJa91Hr#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Kamino Vault Program",
account_id: "kvauTFR8qm1dhniz6pYuBZkuene3Hfrs1VQhVRgCNrr",
solscan_url: "https://solscan.io/account/kvauTFR8qm1dhniz6pYuBZkuene3Hfrs1VQhVRgCNrr#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Kvault Program",
account_id: "KvauGMspG5k6rtzrqqn7WNn3oZdyKqLKwK2XWQ8FLjd",
solscan_url: "https://solscan.io/account/KvauGMspG5k6rtzrqqn7WNn3oZdyKqLKwK2XWQ8FLjd#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "LayerZero Endpoint",
account_id: "76y77prsiCMvXMjuoZ5VRrhG5qYBrUMYTE5WgHqgjEn6",
solscan_url: "https://solscan.io/account/76y77prsiCMvXMjuoZ5VRrhG5qYBrUMYTE5WgHqgjEn6#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "LayerZero Executor",
account_id: "6doghB248px58JSSwG4qejQ46kFMW4AMj7vzJnWZHNZn",
solscan_url: "https://solscan.io/account/6doghB248px58JSSwG4qejQ46kFMW4AMj7vzJnWZHNZn#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "letsbonk.fun: PlatformConfig",
account_id: "FfYek5vEz23cMkWsdJwG2oa6EphsvXSHrGpdALN4g6W1",
solscan_url: "https://solscan.io/account/FfYek5vEz23cMkWsdJwG2oa6EphsvXSHrGpdALN4g6W1",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Lifinity Swap",
account_id: "EewxydAPCCVuNEyrVN68PuSYdQ7wKn27V9Gjeoi8dy3S",
solscan_url: "https://solscan.io/account/EewxydAPCCVuNEyrVN68PuSYdQ7wKn27V9Gjeoi8dy3S",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Lifinity Swap V2",
account_id: "2wT8Yq49kHgDzXuPxZSaeLaH1qbmGXtEyPy64bL7aD3c",
solscan_url: "https://solscan.io/account/2wT8Yq49kHgDzXuPxZSaeLaH1qbmGXtEyPy64bL7aD3c#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Manifest",
account_id: "MNFSTqtC93rEfYHB6hF82sKdZpUDFWkViLByLd1k1Ms",
solscan_url: "https://solscan.io/account/MNFSTqtC93rEfYHB6hF82sKdZpUDFWkViLByLd1k1Ms",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Marcopolo Swap",
account_id: "9tKE7Mbmj4mxDjWatikzGAtkoWosiiZX9y6J4Hfm2R8H",
solscan_url: "https://solscan.io/account/9tKE7Mbmj4mxDjWatikzGAtkoWosiiZX9y6J4Hfm2R8H",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Marginfi",
account_id: "MFLQPPPPjNinkdKoy2odNFBhvpY43XtCDZjBwG2fwn5",
solscan_url: "https://solscan.io/account/MFLQPPPPjNinkdKoy2odNFBhvpY43XtCDZjBwG2fwn5",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Marginfi V2",
account_id: "MFv2hWf31Z9kbCa1snEPYctwafyhdvnV7FZnsebVacA",
solscan_url: "https://solscan.io/account/MFv2hWf31Z9kbCa1snEPYctwafyhdvnV7FZnsebVacA#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Marinade Finance",
account_id: "MarBmsSgKXdrN1egZf5sqe1TMai9K1rChYNDJgjq7aD",
solscan_url: "https://solscan.io/account/MarBmsSgKXdrN1egZf5sqe1TMai9K1rChYNDJgjq7aD#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Mercurial Stable Swap",
account_id: "MERLuDFBMmsHnsBPZw2sDQZHvXFMwp8EdjudcU2HKky",
solscan_url: "https://solscan.io/account/MERLuDFBMmsHnsBPZw2sDQZHvXFMwp8EdjudcU2HKky",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "MetaDAO AMM Program v0.5",
account_id: "AMMJdEiCCa8mdugg6JPF7gFirmmxisTfDJoSNSUi5zDJ",
solscan_url: "https://solscan.io/account/AMMJdEiCCa8mdugg6JPF7gFirmmxisTfDJoSNSUi5zDJ#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "MetaDAO Bid Wall Program",
account_id: "WALL8ucBuUyL46QYxwYJjidaFYhdvxUFrgvBxPshERx",
solscan_url: "https://solscan.io/account/WALL8ucBuUyL46QYxwYJjidaFYhdvxUFrgvBxPshERx#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "MetaDAO ICO",
account_id: "moontUzsdepotRGe5xsfip7vLPTJnVuafqdUWexVnPM",
solscan_url: "https://solscan.io/account/moontUzsdepotRGe5xsfip7vLPTJnVuafqdUWexVnPM#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Metaplex Token Metadata",
account_id: "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s",
solscan_url: "https://solscan.io/account/metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Meteora DLMM Program",
account_id: "LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo",
solscan_url: "https://solscan.io/account/LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Meteora Pools Program",
account_id: "Eo7WjKq67rjJQSZxS6z3YkapzY3eMj6Xy8X5EQVn5UaB",
solscan_url: "https://solscan.io/account/Eo7WjKq67rjJQSZxS6z3YkapzY3eMj6Xy8X5EQVn5UaB#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Meteora Dynamic Bonding Curve",
account_id: "dbcij3LWUppWqq96dh6gJWwBifmcGfLSB5D4DuSMaqN",
solscan_url: "https://solscan.io/account/dbcij3LWUppWqq96dh6gJWwBifmcGfLSB5D4DuSMaqN#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Meteora DAMM v2",
account_id: "cpamdpZCGKUy5JxQXB4dcpGPiikHawvSWAd6mEn1sGG",
solscan_url: "https://solscan.io/account/cpamdpZCGKUy5JxQXB4dcpGPiikHawvSWAd6mEn1sGG#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Meteora Vault Program",
account_id: "24Uqj9JCLxUeoC3hGfh5W3s9FM9uCHDS2SG3LYwBpyTi",
solscan_url: "https://solscan.io/account/24Uqj9JCLxUeoC3hGfh5W3s9FM9uCHDS2SG3LYwBpyTi#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Moonit",
account_id: "MoonCVVNZFSYkqNXP6bxHLPL6QQJiMagDL3qcqUQTrG",
solscan_url: "https://solscan.io/account/MoonCVVNZFSYkqNXP6bxHLPL6QQJiMagDL3qcqUQTrG#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Moonshot : Token Authority",
account_id: "7rtiKSUDLBm59b1SBmD9oajcP8xE64vAGSMbAN5CXy1q",
solscan_url: "https://solscan.io/account/7rtiKSUDLBm59b1SBmD9oajcP8xE64vAGSMbAN5CXy1q",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Mpl Core",
account_id: "CoREENxT6tW1HoK8ypY1SxRMZTcVPm7R94rH4PZNhX7d",
solscan_url: "https://solscan.io/account/CoREENxT6tW1HoK8ypY1SxRMZTcVPm7R94rH4PZNhX7d",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Name Service Program",
account_id: "namesLPneVptA9Z5rqUDD9tMTWEJwofgaYwp8cawRkX",
solscan_url: "https://solscan.io/account/namesLPneVptA9Z5rqUDD9tMTWEJwofgaYwp8cawRkX",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Numeraire",
account_id: "NUMERUNsFCP3kuNmWZuXtm1AaQCPj9uw6Guv2Ekoi5P",
solscan_url: "https://solscan.io/account/NUMERUNsFCP3kuNmWZuXtm1AaQCPj9uw6Guv2Ekoi5P#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Obric V2",
account_id: "obriQD1zbpyLz95G5n7nJe6a4DPjpFwa5XYPoNm113y",
solscan_url: "https://solscan.io/account/obriQD1zbpyLz95G5n7nJe6a4DPjpFwa5XYPoNm113y",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "OKX Labs 1",
account_id: "6m2CDdhRgxpH4WjvdzxAYbGxwdGUz5MziiL5jek2kBma",
solscan_url: "https://solscan.io/account/6m2CDdhRgxpH4WjvdzxAYbGxwdGUz5MziiL5jek2kBma#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "OKX: DEX Router",
account_id: "proVF4pMXVaYqmy4NjniPh4pqKNfMmsihgd4wdkCX3u",
solscan_url: "https://solscan.io/account/proVF4pMXVaYqmy4NjniPh4pqKNfMmsihgd4wdkCX3u#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Ondo Global Markets",
account_id: "XzTT4XB8m7sLD2xi6snefSasaswsKCxx5Tifjondogm",
solscan_url: "https://solscan.io/account/XzTT4XB8m7sLD2xi6snefSasaswsKCxx5Tifjondogm#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Openbook V2",
account_id: "opnb2LAfJYbRMAHHvqjCwQxanZn7ReEHp1k81EohpZb",
solscan_url: "https://solscan.io/account/opnb2LAfJYbRMAHHvqjCwQxanZn7ReEHp1k81EohpZb#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Orca Whirlpools Program",
account_id: "whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc",
solscan_url: "https://solscan.io/account/whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Orca Wavebreak",
account_id: "waveQX2yP3H1pVU8djGvEHmYg8uamQ84AuyGtpsrXTF",
solscan_url: "https://solscan.io/account/waveQX2yP3H1pVU8djGvEHmYg8uamQ84AuyGtpsrXTF#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Orca Token Swap",
account_id: "DjVE6JNiYqPL2QXyCUUh8rNjHrbz9hXHNYt99MQ59qw1",
solscan_url: "https://solscan.io/account/DjVE6JNiYqPL2QXyCUUh8rNjHrbz9hXHNYt99MQ59qw1",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Orca Token Swap V2",
account_id: "9W959DqEETiGZocYWCQPaJ6sBmUzgfxXfqGeTEdp3aQP",
solscan_url: "https://solscan.io/account/9W959DqEETiGZocYWCQPaJ6sBmUzgfxXfqGeTEdp3aQP",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Ore V3 Program",
account_id: "oreV3EG1i9BEgiAJ8b177Z2S2rMarzak4NMv1kULvWv",
solscan_url: "https://solscan.io/account/oreV3EG1i9BEgiAJ8b177Z2S2rMarzak4NMv1kULvWv",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "PancakeSwap",
account_id: "HpNfyc2Saw7RKkQd8nEL4khUcuPhQ7WwY1B2qjx8jxFq",
solscan_url: "https://solscan.io/account/HpNfyc2Saw7RKkQd8nEL4khUcuPhQ7WwY1B2qjx8jxFq#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Penguin Finance",
account_id: "PSwapMdSai8tjrEXcxFeQth87xC4rRsa4VA5mhGhXkP",
solscan_url: "https://solscan.io/account/PSwapMdSai8tjrEXcxFeQth87xC4rRsa4VA5mhGhXkP",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Phoenix",
account_id: "PhoeNiXZ8ByJGLkxNfZRnkUfjvmuYqLR89jjFHGqdXY",
solscan_url: "https://solscan.io/account/PhoeNiXZ8ByJGLkxNfZRnkUfjvmuYqLR89jjFHGqdXY",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Printr",
account_id: "T8HsGYv7sMk3kTnyaRqZrbRPuntYzdh12evXBkprint",
solscan_url: "https://solscan.io/account/T8HsGYv7sMk3kTnyaRqZrbRPuntYzdh12evXBkprint#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Pump.fun",
account_id: "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P",
solscan_url: "https://solscan.io/account/6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Pump.fun AMM",
account_id: "pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA",
solscan_url: "https://solscan.io/account/pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Pump Fees Program",
account_id: "pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ",
solscan_url: "https://solscan.io/account/pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "pumpup.ai",
account_id: "PdMDrKEMaX8q7CCJb7NvUCxerBCcsFUa4LjBEynTtEd",
solscan_url: "https://solscan.io/account/PdMDrKEMaX8q7CCJb7NvUCxerBCcsFUa4LjBEynTtEd#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Raydium AMM Routing",
account_id: "routeUGWgWzqBWFcrCfv8tritsqukccJPu3q5GPP3xS",
solscan_url: "https://solscan.io/account/routeUGWgWzqBWFcrCfv8tritsqukccJPu3q5GPP3xS",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Raydium Concentrated Liquidity",
account_id: "CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK",
solscan_url: "https://solscan.io/account/CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Raydium CPMM",
account_id: "CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C",
solscan_url: "https://solscan.io/account/CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Raydium LaunchLab",
account_id: "LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj",
solscan_url: "https://solscan.io/account/LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Raydium LaunchLab: PlatformConfig",
account_id: "4Bu96XjU84XjPDSpveTVf6LYGCkfW5FK7SNkREWcEfV4",
solscan_url: "https://solscan.io/account/4Bu96XjU84XjPDSpveTVf6LYGCkfW5FK7SNkREWcEfV4",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Raydium liquidity pool AMM",
account_id: "5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h",
solscan_url: "https://solscan.io/account/5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Raydium Liquidity Pool V2",
account_id: "RVKd61ztZW9GUwhRbbLoYVRE5Xf1B2tVscKqwZqXgEr",
solscan_url: "https://solscan.io/account/RVKd61ztZW9GUwhRbbLoYVRE5Xf1B2tVscKqwZqXgEr",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Raydium Liquidity Pool V3",
account_id: "27haf8L6oxUeXrHrgEgsexjSY5hbVUWEmvv9Nyxg8vQv",
solscan_url: "https://solscan.io/account/27haf8L6oxUeXrHrgEgsexjSY5hbVUWEmvv9Nyxg8vQv",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Raydium Liquidity Pool V4",
account_id: "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8",
solscan_url: "https://solscan.io/account/675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Raydium Lock LP",
account_id: "LockrWmn6K5twhz3y9w1dQERbmgSaRkfnTeTKbpofwE",
solscan_url: "https://solscan.io/account/LockrWmn6K5twhz3y9w1dQERbmgSaRkfnTeTKbpofwE#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Saber Decimal Wrapper",
account_id: "DecZY86MU5Gj7kppfUCEmd4LbXXuyZH1yHaP2NTqdiZB",
solscan_url: "https://solscan.io/account/DecZY86MU5Gj7kppfUCEmd4LbXXuyZH1yHaP2NTqdiZB#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Saber Stable Swap",
account_id: "SSwpkEEcbUqx4vtoEByFjSkhKdCT862DNVb52nZg1UZ",
solscan_url: "https://solscan.io/account/SSwpkEEcbUqx4vtoEByFjSkhKdCT862DNVb52nZg1UZ",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Saros AMM",
account_id: "SSwapUtytfBdBn1b9NUGG6foMVPtcWgpRU32HToDUZr",
solscan_url: "https://solscan.io/account/SSwapUtytfBdBn1b9NUGG6foMVPtcWgpRU32HToDUZr",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Sanctum Multi-Validator SPL Stake Pool Program",
account_id: "SPMBzsVUuoHA4Jm6KunbsotaahvVikZs1JyTW6iJvbn",
solscan_url: "https://solscan.io/account/SPMBzsVUuoHA4Jm6KunbsotaahvVikZs1JyTW6iJvbn",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Sanctum Router Program",
account_id: "stkitrT1Uoy18Dk1fTrgPw8W6MVzoCfYoAFT4MLsmhq",
solscan_url: "https://solscan.io/account/stkitrT1Uoy18Dk1fTrgPw8W6MVzoCfYoAFT4MLsmhq",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Sanctum: S Controller",
account_id: "5ocnV1qiCgaQR8Jb8xWnVbApfaygJ8tNoZfgPwsgx9kx",
solscan_url: "https://solscan.io/account/5ocnV1qiCgaQR8Jb8xWnVbApfaygJ8tNoZfgPwsgx9kx",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Sanctum Single Validator SPL Stake Pool Program",
account_id: "SP12tWFxD9oJsVWNavTTBZvMbA6gkAmxtVgxdqvyvhY",
solscan_url: "https://solscan.io/account/SP12tWFxD9oJsVWNavTTBZvMbA6gkAmxtVgxdqvyvhY",
idl_status: "solscan_account",
},
SolscanAccountSource {
label: "SharkyFi",
account_id: "SHARKobtfF1bHhxD2eqftjHBdVSCbKo9JtgK71FhELP",
solscan_url: "https://solscan.io/account/SHARKobtfF1bHhxD2eqftjHBdVSCbKo9JtgK71FhELP",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Solayer",
account_id: "sSo1iU21jBrU9VaJ8PJib1MtorefUV4fzC9GURa2KNn",
solscan_url: "https://solscan.io/account/sSo1iU21jBrU9VaJ8PJib1MtorefUV4fzC9GURa2KNn",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Solend Protocol",
account_id: "So1endDq2YkqhipRh3WViPa8hdiSpxWy6z3Z6tMCpAo",
solscan_url: "https://solscan.io/account/So1endDq2YkqhipRh3WViPa8hdiSpxWy6z3Z6tMCpAo",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "SolFi",
account_id: "SoLFiHG9TfgtdUXUjWAxi3LtvYuFyDLVhBWxdMZxyCe",
solscan_url: "https://solscan.io/account/SoLFiHG9TfgtdUXUjWAxi3LtvYuFyDLVhBWxdMZxyCe",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "SolFi V2",
account_id: "SV2EYYJyRz2YhfXwXnhNAevDEui5Q6yrfyo13WtupPF",
solscan_url: "https://solscan.io/account/SV2EYYJyRz2YhfXwXnhNAevDEui5Q6yrfyo13WtupPF",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "stabble CLMM",
account_id: "6dMXqGZ3ga2dikrYS9ovDXgHGh5RUsb2RTUj6hrQXhk6",
solscan_url: "https://solscan.io/account/6dMXqGZ3ga2dikrYS9ovDXgHGh5RUsb2RTUj6hrQXhk6#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "stabble Stable Swap",
account_id: "swapNyd8XiQwJ6ianp9snpu4brUqFxadzvHebnAXjJZ",
solscan_url: "https://solscan.io/account/swapNyd8XiQwJ6ianp9snpu4brUqFxadzvHebnAXjJZ#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "stabble Weighted Swap",
account_id: "swapFpHZwjELNnjvThjajtiVmkz3yPQEHjLtka2fwHW",
solscan_url: "https://solscan.io/account/swapFpHZwjELNnjvThjajtiVmkz3yPQEHjLtka2fwHW#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Stake Pool",
account_id: "SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy",
solscan_url: "https://solscan.io/account/SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Stake Program",
account_id: "Stake11111111111111111111111111111111111111",
solscan_url: "https://solscan.io/account/Stake11111111111111111111111111111111111111",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Step Finance Swap Program",
account_id: "SSwpMgqNDsyV7mAgN9ady4bDVu5ySjmmXejXvy2vLt1",
solscan_url: "https://solscan.io/account/SSwpMgqNDsyV7mAgN9ady4bDVu5ySjmmXejXvy2vLt1",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "StepN DOOAR Swap",
account_id: "Dooar9JkhdZ7J3LHN3A7YCuoGRUggXhQaG4kijfLGU2j",
solscan_url: "https://solscan.io/account/Dooar9JkhdZ7J3LHN3A7YCuoGRUggXhQaG4kijfLGU2j",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Scorch",
account_id: "SCoRcH8c2dpjvcJD6FiPbCSQyQgu3PcUAWj2Xxx3mqn",
solscan_url: "https://solscan.io/account/SCoRcH8c2dpjvcJD6FiPbCSQyQgu3PcUAWj2Xxx3mqn",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Streamflow",
account_id: "strmRqUCoQUgGUan5YhzUZa6KqdzwX5L6FpUxfmKg5m",
solscan_url: "https://solscan.io/account/strmRqUCoQUgGUan5YhzUZa6KqdzwX5L6FpUxfmKg5m#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Swap Program",
account_id: "SwaPpA9LAaLfeLi3a68M4DjnLqgtticKg6CnyNwgAC8",
solscan_url: "https://solscan.io/account/SwaPpA9LAaLfeLi3a68M4DjnLqgtticKg6CnyNwgAC8",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Swig Program",
account_id: "swigypWHEksbC64pWKwah1WTeh9JXwx8H1rJHLdbQMB",
solscan_url: "https://solscan.io/account/swigypWHEksbC64pWKwah1WTeh9JXwx8H1rJHLdbQMB",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "System Program",
account_id: "11111111111111111111111111111111",
solscan_url: "https://solscan.io/account/11111111111111111111111111111111",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Tessera V",
account_id: "TessVdML9pBGgG9yGks7o4HewRaXVAMuoVj4x83GLQH",
solscan_url: "https://solscan.io/account/TessVdML9pBGgG9yGks7o4HewRaXVAMuoVj4x83GLQH",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Titan Exchange Router",
account_id: "T1TANpTeScyeqVzzgNViGDNrkQ6qHz9KrSBS4aNXvGT",
solscan_url: "https://solscan.io/account/T1TANpTeScyeqVzzgNViGDNrkQ6qHz9KrSBS4aNXvGT",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Token 2022 Program",
account_id: "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb",
solscan_url: "https://solscan.io/account/TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Token Program",
account_id: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
solscan_url: "https://solscan.io/account/TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Vertigo Program",
account_id: "vrTGoBuy5rYSxAfV3jaRJWHH6nN9WK4NRExGxsk1bCJ",
solscan_url: "https://solscan.io/account/vrTGoBuy5rYSxAfV3jaRJWHH6nN9WK4NRExGxsk1bCJ#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Virtuals",
account_id: "5U3EU2ubXtK84QcRjWVmYt9RaDyA8gKxdUrPFXmZyaki",
solscan_url: "https://solscan.io/account/5U3EU2ubXtK84QcRjWVmYt9RaDyA8gKxdUrPFXmZyaki#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Woofi",
account_id: "WooFif76YGRNjk1pA8wCsN67aQsD9f9iLsz4NcJ1AVb",
solscan_url: "https://solscan.io/account/WooFif76YGRNjk1pA8wCsN67aQsD9f9iLsz4NcJ1AVb#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Wormhole: Bridge",
account_id: "wormDTUJ6AWPNvk59vGQbDvGJmqbDTdgWgAqcLBCgUb",
solscan_url: "https://solscan.io/account/wormDTUJ6AWPNvk59vGQbDvGJmqbDTdgWgAqcLBCgUb",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "ZeroFi",
account_id: "ZERor4xhbUycZ6gb9ntrhqscUcZmAbQDjEAtCf4hbZY",
solscan_url: "https://solscan.io/account/ZERor4xhbUycZ6gb9ntrhqscUcZmAbQDjEAtCf4hbZY",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Zeta Matching Engine",
account_id: "zDEXqXEG7gAyxb1Kg9mK5fPnUdENCGKzWrM21RMdWRq",
solscan_url: "https://solscan.io/account/zDEXqXEG7gAyxb1Kg9mK5fPnUdENCGKzWrM21RMdWRq",
idl_status: "no_idl",
},
SolscanAccountSource {
label: "Zeta Program",
account_id: "ZETAxsqBRek56DhiGXrn75yj2NHU3aYUnxvHXpkf3aD",
solscan_url: "https://solscan.io/account/ZETAxsqBRek56DhiGXrn75yj2NHU3aYUnxvHXpkf3aD#programIdl",
idl_status: "solscan_program_idl",
},
SolscanAccountSource {
label: "Zora Program",
account_id: "zoRabwLGd5zXaV7Gxacppw8tcceXEiTrSKyNLSaSTUc",
solscan_url: "https://solscan.io/account/zoRabwLGd5zXaV7Gxacppw8tcceXEiTrSKyNLSaSTUc",
idl_status: "no_idl",
},
];

View File

@@ -78,6 +78,7 @@ pub use dtos::ProtocolCandidateDto;
pub use dtos::ProtocolCandidateSummaryDto; pub use dtos::ProtocolCandidateSummaryDto;
pub use dtos::RewardEventDto; pub use dtos::RewardEventDto;
pub use dtos::SwapDto; pub use dtos::SwapDto;
pub use dtos::TokenAccountEventDto;
pub use dtos::TokenBurnEventDto; pub use dtos::TokenBurnEventDto;
pub use dtos::TokenDto; pub use dtos::TokenDto;
pub use dtos::TokenMintEventDto; pub use dtos::TokenMintEventDto;
@@ -124,6 +125,7 @@ pub use entities::ProtocolCandidateEntity;
pub use entities::ProtocolCandidateSummaryEntity; pub use entities::ProtocolCandidateSummaryEntity;
pub use entities::RewardEventEntity; pub use entities::RewardEventEntity;
pub use entities::SwapEntity; pub use entities::SwapEntity;
pub use entities::TokenAccountEventEntity;
pub use entities::TokenBurnEventEntity; pub use entities::TokenBurnEventEntity;
pub use entities::TokenEntity; pub use entities::TokenEntity;
pub use entities::TokenMintEventEntity; pub use entities::TokenMintEventEntity;
@@ -155,6 +157,7 @@ pub use queries::query_dex_decode_replay_ledger_get_by_transaction;
pub use queries::query_dex_decode_replay_ledger_upsert; pub use queries::query_dex_decode_replay_ledger_upsert;
pub use queries::query_dex_decoded_events_delete_by_key; pub use queries::query_dex_decoded_events_delete_by_key;
pub use queries::query_dex_decoded_events_delete_locally_covered_upstream_instruction_matches; pub use queries::query_dex_decoded_events_delete_locally_covered_upstream_instruction_matches;
pub use queries::query_dex_decoded_events_delete_replaced_raydium_cpmm_instruction_audits;
pub use queries::query_dex_decoded_events_delete_meteora_dlmm_anchor_swap_instruction_audits; pub use queries::query_dex_decoded_events_delete_meteora_dlmm_anchor_swap_instruction_audits;
pub use queries::query_dex_decoded_events_delete_related_instruction_audit; pub use queries::query_dex_decoded_events_delete_related_instruction_audit;
pub use queries::query_dex_decoded_events_delete_replaced_raydium_clmm_instruction_audits; pub use queries::query_dex_decoded_events_delete_replaced_raydium_clmm_instruction_audits;
@@ -264,6 +267,7 @@ pub use queries::query_reward_events_list_recent;
pub use queries::query_reward_events_upsert; pub use queries::query_reward_events_upsert;
pub use queries::query_swaps_list_recent; pub use queries::query_swaps_list_recent;
pub use queries::query_swaps_upsert; pub use queries::query_swaps_upsert;
pub use queries::query_token_account_events_upsert;
pub use queries::query_token_burn_events_list_recent; pub use queries::query_token_burn_events_list_recent;
pub use queries::query_token_burn_events_upsert; pub use queries::query_token_burn_events_upsert;
pub use queries::query_token_mint_events_list_recent; pub use queries::query_token_mint_events_list_recent;

View File

@@ -42,6 +42,7 @@ mod protocol_candidate_summary;
mod reward_event; mod reward_event;
mod swap; mod swap;
mod token; mod token;
mod token_account_event;
mod token_burn_event; mod token_burn_event;
mod token_mint_event; mod token_mint_event;
mod trade_event; mod trade_event;
@@ -136,6 +137,7 @@ pub use protocol_candidate_summary::ProtocolCandidateSummaryDto;
pub use reward_event::RewardEventDto; pub use reward_event::RewardEventDto;
pub use swap::SwapDto; pub use swap::SwapDto;
pub use token::TokenDto; pub use token::TokenDto;
pub use token_account_event::TokenAccountEventDto;
pub use token_burn_event::TokenBurnEventDto; pub use token_burn_event::TokenBurnEventDto;
pub use token_mint_event::TokenMintEventDto; pub use token_mint_event::TokenMintEventDto;
pub use trade_event::TradeEventDto; pub use trade_event::TradeEventDto;

View File

@@ -0,0 +1,140 @@
// file: kb_lib/src/db/dtos/token_account_event.rs
//! Token account event DTO.
/// Application-facing normalized token-account event DTO.
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct TokenAccountEventDto {
/// Optional numeric primary key.
pub id: std::option::Option<i64>,
/// Related transaction id.
pub transaction_id: std::option::Option<i64>,
/// Related decoded event id.
pub decoded_event_id: std::option::Option<i64>,
/// Related DEX id.
pub dex_id: std::option::Option<i64>,
/// Related pool id, when known.
pub pool_id: std::option::Option<i64>,
/// Related pair id, when known.
pub pair_id: std::option::Option<i64>,
/// Transaction signature.
pub signature: std::string::String,
/// Instruction index inside the transaction.
pub instruction_index: i64,
/// Optional slot number.
pub slot: std::option::Option<u64>,
/// Protocol name.
pub protocol_name: std::string::String,
/// Program id.
pub program_id: std::option::Option<std::string::String>,
/// Event kind.
pub event_kind: std::string::String,
/// Token account, when known.
pub token_account: std::option::Option<std::string::String>,
/// Token mint, when known.
pub token_mint: std::option::Option<std::string::String>,
/// Owner wallet, when known.
pub owner_wallet: std::option::Option<std::string::String>,
/// Token-account action.
pub account_action: std::option::Option<std::string::String>,
/// Raw decoded payload.
pub payload_json: std::option::Option<std::string::String>,
/// Execution timestamp.
pub executed_at: chrono::DateTime<chrono::Utc>,
}
impl TokenAccountEventDto {
/// Creates a new token-account event DTO.
#[allow(clippy::too_many_arguments)]
pub fn new(
transaction_id: std::option::Option<i64>,
decoded_event_id: std::option::Option<i64>,
dex_id: std::option::Option<i64>,
pool_id: std::option::Option<i64>,
pair_id: std::option::Option<i64>,
signature: std::string::String,
instruction_index: i64,
slot: std::option::Option<u64>,
protocol_name: std::string::String,
program_id: std::option::Option<std::string::String>,
event_kind: std::string::String,
token_account: std::option::Option<std::string::String>,
token_mint: std::option::Option<std::string::String>,
owner_wallet: std::option::Option<std::string::String>,
account_action: std::option::Option<std::string::String>,
payload_json: std::option::Option<std::string::String>,
) -> Self {
return Self {
id: None,
transaction_id,
decoded_event_id,
dex_id,
pool_id,
pair_id,
signature,
instruction_index,
slot,
protocol_name,
program_id,
event_kind,
token_account,
token_mint,
owner_wallet,
account_action,
payload_json,
executed_at: chrono::Utc::now(),
};
}
}
impl TryFrom<crate::TokenAccountEventEntity> for TokenAccountEventDto {
type Error = crate::Error;
fn try_from(entity: crate::TokenAccountEventEntity) -> Result<Self, Self::Error> {
let executed_at_result = chrono::DateTime::parse_from_rfc3339(&entity.executed_at);
let executed_at = match executed_at_result {
Ok(executed_at) => executed_at.with_timezone(&chrono::Utc),
Err(error) => {
return Err(crate::Error::Db(format!(
"cannot parse token account event executed_at '{}': {}",
entity.executed_at, error
)));
},
};
let slot = match entity.slot {
Some(slot) => {
let slot_result = u64::try_from(slot);
match slot_result {
Ok(slot) => Some(slot),
Err(error) => {
return Err(crate::Error::Db(format!(
"cannot convert token account event slot '{}' to u64: {}",
slot, error
)));
},
}
},
None => None,
};
return Ok(Self {
id: Some(entity.id),
transaction_id: entity.transaction_id,
decoded_event_id: entity.decoded_event_id,
dex_id: entity.dex_id,
pool_id: entity.pool_id,
pair_id: entity.pair_id,
signature: entity.signature,
instruction_index: entity.instruction_index,
slot,
protocol_name: entity.protocol_name,
program_id: entity.program_id,
event_kind: entity.event_kind,
token_account: entity.token_account,
token_mint: entity.token_mint,
owner_wallet: entity.owner_wallet,
account_action: entity.account_action,
payload_json: entity.payload_json,
executed_at,
});
}
}

View File

@@ -42,6 +42,7 @@ mod protocol_candidate_summary;
mod reward_event; mod reward_event;
mod swap; mod swap;
mod token; mod token;
mod token_account_event;
mod token_burn_event; mod token_burn_event;
mod token_mint_event; mod token_mint_event;
mod trade_event; mod trade_event;
@@ -89,6 +90,7 @@ pub use protocol_candidate_summary::ProtocolCandidateSummaryEntity;
pub use reward_event::RewardEventEntity; pub use reward_event::RewardEventEntity;
pub use swap::SwapEntity; pub use swap::SwapEntity;
pub use token::TokenEntity; pub use token::TokenEntity;
pub use token_account_event::TokenAccountEventEntity;
pub use token_burn_event::TokenBurnEventEntity; pub use token_burn_event::TokenBurnEventEntity;
pub use token_mint_event::TokenMintEventEntity; pub use token_mint_event::TokenMintEventEntity;
pub use trade_event::TradeEventEntity; pub use trade_event::TradeEventEntity;

View File

@@ -0,0 +1,46 @@
// file: kb_lib/src/db/entities/token_account_event.rs
//! Token account event entity.
/// Persisted normalized token-account event row.
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, sqlx::FromRow)]
pub struct TokenAccountEventEntity {
/// Numeric primary key.
pub id: i64,
/// Related transaction id.
pub transaction_id: std::option::Option<i64>,
/// Related decoded event id.
pub decoded_event_id: std::option::Option<i64>,
/// Related DEX id.
pub dex_id: std::option::Option<i64>,
/// Related pool id, when known.
pub pool_id: std::option::Option<i64>,
/// Related pair id, when known.
pub pair_id: std::option::Option<i64>,
/// Transaction signature.
pub signature: std::string::String,
/// Instruction index inside the transaction.
pub instruction_index: i64,
/// Optional slot number.
pub slot: std::option::Option<i64>,
/// Protocol name.
pub protocol_name: std::string::String,
/// Program id.
pub program_id: std::option::Option<std::string::String>,
/// Event kind.
pub event_kind: std::string::String,
/// Token account, when known.
pub token_account: std::option::Option<std::string::String>,
/// Token mint, when known.
pub token_mint: std::option::Option<std::string::String>,
/// Owner wallet, when known.
pub owner_wallet: std::option::Option<std::string::String>,
/// Token-account action.
pub account_action: std::option::Option<std::string::String>,
/// Raw decoded payload.
pub payload_json: std::option::Option<std::string::String>,
/// Execution timestamp encoded as RFC3339 UTC text.
pub executed_at: std::string::String,
/// Creation timestamp encoded as RFC3339 UTC text.
pub created_at: std::option::Option<std::string::String>,
}

View File

@@ -40,6 +40,7 @@ mod protocol_candidate;
mod reward_event; mod reward_event;
mod swap; mod swap;
mod token; mod token;
mod token_account_event;
mod token_burn_event; mod token_burn_event;
mod token_mint_event; mod token_mint_event;
mod trade_event; mod trade_event;
@@ -77,6 +78,7 @@ pub use dex_decoded_event::query_dex_decoded_events_delete_locally_covered_upstr
pub use dex_decoded_event::query_dex_decoded_events_delete_meteora_dlmm_anchor_swap_instruction_audits; pub use dex_decoded_event::query_dex_decoded_events_delete_meteora_dlmm_anchor_swap_instruction_audits;
pub use dex_decoded_event::query_dex_decoded_events_delete_related_instruction_audit; pub use dex_decoded_event::query_dex_decoded_events_delete_related_instruction_audit;
pub use dex_decoded_event::query_dex_decoded_events_delete_replaced_raydium_clmm_instruction_audits; pub use dex_decoded_event::query_dex_decoded_events_delete_replaced_raydium_clmm_instruction_audits;
pub use dex_decoded_event::query_dex_decoded_events_delete_replaced_raydium_cpmm_instruction_audits;
pub use dex_decoded_event::query_dex_decoded_events_get_by_key; pub use dex_decoded_event::query_dex_decoded_events_get_by_key;
pub use dex_decoded_event::query_dex_decoded_events_get_latest_pump_fun_create_payload_by_mint; pub use dex_decoded_event::query_dex_decoded_events_get_latest_pump_fun_create_payload_by_mint;
pub use dex_decoded_event::query_dex_decoded_events_list_by_transaction_id; pub use dex_decoded_event::query_dex_decoded_events_list_by_transaction_id;
@@ -185,6 +187,7 @@ pub use token::query_tokens_get_by_mint;
pub use token::query_tokens_list; pub use token::query_tokens_list;
pub use token::query_tokens_list_missing_metadata; pub use token::query_tokens_list_missing_metadata;
pub use token::query_tokens_upsert; pub use token::query_tokens_upsert;
pub use token_account_event::query_token_account_events_upsert;
pub use token_burn_event::query_token_burn_events_list_recent; pub use token_burn_event::query_token_burn_events_list_recent;
pub use token_burn_event::query_token_burn_events_upsert; pub use token_burn_event::query_token_burn_events_upsert;
pub use token_mint_event::query_token_mint_events_list_recent; pub use token_mint_event::query_token_mint_events_list_recent;

View File

@@ -191,6 +191,136 @@ WHERE transaction_id = ?
} }
} }
/// Deletes Raydium CPMM instruction-audit rows for locally mapped CPMM instructions.
///
/// CPMM has one Anchor IDL-management instruction (`40f4bc78a7e9690a`) that is
/// decoded by the local Raydium audit-preservation pass rather than by the
/// CPMM instruction decoder itself because its payload is shorter than normal
/// CPMM instruction layouts. Once the named `raydium_cpmm.*` row exists, the
/// old `raydium_cpmm.instruction_audit` row is redundant and must be removed.
/// The allow-list also includes the regular CPMM instruction discriminators so
/// future replays do not leave duplicate audit rows for already covered entries.
pub async fn query_dex_decoded_events_delete_replaced_raydium_cpmm_instruction_audits(
database: &crate::Database,
transaction_id: std::option::Option<i64>,
) -> Result<u64, crate::Error> {
match database.connection() {
crate::DatabaseConnection::Sqlite(pool) => {
let unlink_result = sqlx::query(
r#"
UPDATE k_sol_instruction_observations
SET decoded_event_id = NULL
WHERE decoded_event_id IN (
SELECT id
FROM k_sol_dex_decoded_events
WHERE protocol_name = 'raydium_cpmm'
AND event_kind = 'raydium_cpmm.instruction_audit'
AND (? IS NULL OR transaction_id = ?)
AND (
COALESCE(
json_extract(payload_json, '$.discriminatorHex'),
json_extract(payload_json, '$.discriminator_hex'),
json_extract(payload_json, '$.instructionDiscriminatorHex'),
json_extract(payload_json, '$.instruction_discriminator_hex')
) IN (
'40f4bc78a7e9690a',
'9c5420764587467b',
'1416567bc61cdb84',
'a78a4e95dfc2067e',
'8888fcddc2427e59',
'e445a52e51cb9a1d',
'8934edd4d7756c68',
'878802d889a9b5ca',
'f223c68952e1f2b6',
'afaf6d1f0d989bed',
'3f37fe4131b25979',
'8fbe5adac41e33de',
'37d96256a34ab4ad',
'313cae889a1c74c8',
'82576c062ee0757b',
'b712469c946da122'
)
OR instr(lower(COALESCE(payload_json, '')), '40f4bc78a7e9690a') > 0
OR EXISTS (
SELECT 1
FROM k_sol_dex_decoded_events named
WHERE named.transaction_id = k_sol_dex_decoded_events.transaction_id
AND named.protocol_name = 'raydium_cpmm'
AND named.event_kind = 'raydium_cpmm.anchor_idl_instruction'
)
)
)
"#,
)
.bind(transaction_id)
.bind(transaction_id)
.execute(pool)
.await;
if let Err(error) = unlink_result {
return Err(crate::Error::Db(format!(
"cannot unlink mapped Raydium CPMM instruction audit observations on sqlite: {}",
error
)));
}
let query_result = sqlx::query(
r#"
DELETE FROM k_sol_dex_decoded_events
WHERE protocol_name = 'raydium_cpmm'
AND event_kind = 'raydium_cpmm.instruction_audit'
AND (? IS NULL OR transaction_id = ?)
AND (
COALESCE(
json_extract(payload_json, '$.discriminatorHex'),
json_extract(payload_json, '$.discriminator_hex'),
json_extract(payload_json, '$.instructionDiscriminatorHex'),
json_extract(payload_json, '$.instruction_discriminator_hex')
) IN (
'40f4bc78a7e9690a',
'9c5420764587467b',
'1416567bc61cdb84',
'a78a4e95dfc2067e',
'8888fcddc2427e59',
'e445a52e51cb9a1d',
'8934edd4d7756c68',
'878802d889a9b5ca',
'f223c68952e1f2b6',
'afaf6d1f0d989bed',
'3f37fe4131b25979',
'8fbe5adac41e33de',
'37d96256a34ab4ad',
'313cae889a1c74c8',
'82576c062ee0757b',
'b712469c946da122'
)
OR instr(lower(COALESCE(payload_json, '')), '40f4bc78a7e9690a') > 0
OR EXISTS (
SELECT 1
FROM k_sol_dex_decoded_events named
WHERE named.transaction_id = k_sol_dex_decoded_events.transaction_id
AND named.protocol_name = 'raydium_cpmm'
AND named.event_kind = 'raydium_cpmm.anchor_idl_instruction'
)
)
"#,
)
.bind(transaction_id)
.bind(transaction_id)
.execute(pool)
.await;
match query_result {
Ok(result) => return Ok(result.rows_affected()),
Err(error) => {
return Err(crate::Error::Db(format!(
"cannot delete mapped Raydium CPMM instruction audit events on sqlite: {}",
error
)));
},
}
},
}
}
/// Deletes Raydium CLMM instruction-audit rows for locally mapped CLMM instructions. /// Deletes Raydium CLMM instruction-audit rows for locally mapped CLMM instructions.
/// ///
/// The CLMM specialized decoder now emits named `raydium_clmm.*` rows for all /// The CLMM specialized decoder now emits named `raydium_clmm.*` rows for all

View File

@@ -323,7 +323,8 @@ SET
) )
) )
), ),
trade_count = ( trade_count = CASE
WHEN expected_db_target = 'k_sol_trade_events' THEN (
SELECT COUNT(te.id) SELECT COUNT(te.id)
FROM k_sol_dex_decoded_events de FROM k_sol_dex_decoded_events de
JOIN k_sol_trade_events te ON te.decoded_event_id = de.id JOIN k_sol_trade_events te ON te.decoded_event_id = de.id
@@ -357,7 +358,10 @@ SET
) )
) )
) )
), )
ELSE 0
END,
materialized_count = CASE materialized_count = CASE
WHEN expected_db_target = 'k_sol_trade_events' THEN ( WHEN expected_db_target = 'k_sol_trade_events' THEN (
SELECT COUNT(te.id) SELECT COUNT(te.id)
@@ -604,6 +608,41 @@ SET
) )
) )
) )
WHEN expected_db_target = 'k_sol_launch_events' THEN (
SELECT COUNT(le.id)
FROM k_sol_dex_decoded_events de
JOIN k_sol_launch_events le ON le.decoded_event_id = de.id
WHERE (
(k_sol_dex_event_coverage_entries.program_id IS NULL OR de.program_id = k_sol_dex_event_coverage_entries.program_id)
AND (
(
k_sol_dex_event_coverage_entries.local_event_kind IS NOT NULL
AND k_sol_dex_event_coverage_entries.local_event_kind <> ''
AND de.event_kind = k_sol_dex_event_coverage_entries.local_event_kind
)
OR (
k_sol_dex_event_coverage_entries.entry_name IS NOT NULL
AND (
json_extract(de.payload_json, '$.upstreamEntryName') = k_sol_dex_event_coverage_entries.entry_name
OR json_extract(de.payload_json, '$.upstreamInstructionName') = k_sol_dex_event_coverage_entries.entry_name
OR json_extract(de.payload_json, '$.upstreamEventName') = k_sol_dex_event_coverage_entries.entry_name
OR json_extract(de.payload_json, '$.entryName') = k_sol_dex_event_coverage_entries.entry_name
)
)
OR (
k_sol_dex_event_coverage_entries.discriminator_hex IS NOT NULL
AND k_sol_dex_event_coverage_entries.discriminator_hex <> ''
AND (
json_extract(de.payload_json, '$.upstreamDiscriminatorHex') = k_sol_dex_event_coverage_entries.discriminator_hex
OR json_extract(de.payload_json, '$.instructionDiscriminatorHex') = k_sol_dex_event_coverage_entries.discriminator_hex
OR json_extract(de.payload_json, '$.anchorEventDiscriminatorHex') = k_sol_dex_event_coverage_entries.discriminator_hex
OR json_extract(de.payload_json, '$.anchorEventDiscriminator') = k_sol_dex_event_coverage_entries.discriminator_hex
OR json_extract(de.payload_json, '$.discriminatorHex') = k_sol_dex_event_coverage_entries.discriminator_hex
)
)
)
)
)
ELSE materialized_count ELSE materialized_count
END, END,
first_signature = ( first_signature = (

View File

@@ -0,0 +1,176 @@
// file: kb_lib/src/db/queries/token_account_event.rs
//! Queries for `k_sol_token_account_events`.
/// Inserts or updates one normalized token-account event row.
pub async fn query_token_account_events_upsert(
database: &crate::Database,
dto: &crate::TokenAccountEventDto,
) -> Result<i64, crate::Error> {
let slot_i64 = match dto.slot {
Some(slot) => {
let slot_result = i64::try_from(slot);
match slot_result {
Ok(slot) => Some(slot),
Err(error) => {
return Err(crate::Error::Db(format!(
"cannot convert token account event slot '{}' to i64: {}",
slot, error
)));
},
}
},
None => None,
};
match database.connection() {
crate::DatabaseConnection::Sqlite(pool) => {
let existing_id = match dto.decoded_event_id {
Some(decoded_event_id) => {
let existing_result = sqlx::query_scalar::<sqlx::Sqlite, i64>(
r#"
SELECT id
FROM k_sol_token_account_events
WHERE decoded_event_id = ?
LIMIT 1
"#,
)
.bind(decoded_event_id)
.fetch_optional(pool)
.await;
match existing_result {
Ok(existing_id) => existing_id,
Err(error) => {
return Err(crate::Error::Db(format!(
"cannot fetch k_sol_token_account_events id for decoded_event_id '{}' on sqlite: {}",
decoded_event_id, error
)));
},
}
},
None => None,
};
if let Some(id) = existing_id {
let update_result = sqlx::query(
r#"
UPDATE k_sol_token_account_events
SET
transaction_id = ?,
dex_id = ?,
pool_id = ?,
pair_id = ?,
signature = ?,
instruction_index = ?,
slot = ?,
protocol_name = ?,
program_id = ?,
event_kind = ?,
token_account = ?,
token_mint = ?,
owner_wallet = ?,
account_action = ?,
payload_json = ?,
executed_at = ?
WHERE id = ?
"#,
)
.bind(dto.transaction_id)
.bind(dto.dex_id)
.bind(dto.pool_id)
.bind(dto.pair_id)
.bind(dto.signature.clone())
.bind(dto.instruction_index)
.bind(slot_i64)
.bind(dto.protocol_name.clone())
.bind(dto.program_id.clone())
.bind(dto.event_kind.clone())
.bind(dto.token_account.clone())
.bind(dto.token_mint.clone())
.bind(dto.owner_wallet.clone())
.bind(dto.account_action.clone())
.bind(dto.payload_json.clone())
.bind(dto.executed_at.to_rfc3339())
.bind(id)
.execute(pool)
.await;
if let Err(error) = update_result {
return Err(crate::Error::Db(format!(
"cannot update k_sol_token_account_events id '{}' on sqlite: {}",
id, error
)));
}
return Ok(id);
}
let query_result = sqlx::query(
r#"
INSERT INTO k_sol_token_account_events (
transaction_id,
decoded_event_id,
dex_id,
pool_id,
pair_id,
signature,
instruction_index,
slot,
protocol_name,
program_id,
event_kind,
token_account,
token_mint,
owner_wallet,
account_action,
payload_json,
executed_at,
created_at
)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
"#,
)
.bind(dto.transaction_id)
.bind(dto.decoded_event_id)
.bind(dto.dex_id)
.bind(dto.pool_id)
.bind(dto.pair_id)
.bind(dto.signature.clone())
.bind(dto.instruction_index)
.bind(slot_i64)
.bind(dto.protocol_name.clone())
.bind(dto.program_id.clone())
.bind(dto.event_kind.clone())
.bind(dto.token_account.clone())
.bind(dto.token_mint.clone())
.bind(dto.owner_wallet.clone())
.bind(dto.account_action.clone())
.bind(dto.payload_json.clone())
.bind(dto.executed_at.to_rfc3339())
.bind(dto.executed_at.to_rfc3339())
.execute(pool)
.await;
if let Err(error) = query_result {
return Err(crate::Error::Db(format!(
"cannot insert k_sol_token_account_events on sqlite: {}",
error
)));
}
let id_result = sqlx::query_scalar::<sqlx::Sqlite, i64>(
r#"
SELECT id
FROM k_sol_token_account_events
WHERE decoded_event_id = ?
LIMIT 1
"#,
)
.bind(dto.decoded_event_id)
.fetch_one(pool)
.await;
match id_result {
Ok(id) => return Ok(id),
Err(error) => {
return Err(crate::Error::Db(format!(
"cannot fetch k_sol_token_account_events id for decoded_event_id '{:?}' on sqlite: {}",
dto.decoded_event_id, error
)));
},
}
},
}
}

View File

@@ -390,6 +390,42 @@ pub(crate) async fn ensure_schema(database: &crate::Database) -> Result<(), crat
if let Err(error) = result { if let Err(error) = result {
return Err(error); return Err(error);
} }
let result = create_tbl_token_account_events(pool).await;
if let Err(error) = result {
return Err(error);
}
let result = create_idx_token_account_events_transaction_id(pool).await;
if let Err(error) = result {
return Err(error);
}
let result = create_idx_token_account_events_pool_id(pool).await;
if let Err(error) = result {
return Err(error);
}
let result = create_uix_token_account_events_decoded_event_id(pool).await;
if let Err(error) = result {
return Err(error);
}
let result = create_tbl_launch_events(pool).await;
if let Err(error) = result {
return Err(error);
}
let result = create_idx_launch_events_transaction_id(pool).await;
if let Err(error) = result {
return Err(error);
}
let result = create_idx_launch_events_pool_id(pool).await;
if let Err(error) = result {
return Err(error);
}
let result = create_idx_launch_events_event_kind(pool).await;
if let Err(error) = result {
return Err(error);
}
let result = create_uix_launch_events_decoded_event_id(pool).await;
if let Err(error) = result {
return Err(error);
}
let result = create_tbl_launch_surfaces(pool).await; let result = create_tbl_launch_surfaces(pool).await;
if let Err(error) = result { if let Err(error) = result {
return Err(error); return Err(error);
@@ -1490,7 +1526,7 @@ CREATE TABLE IF NOT EXISTS k_sol_instruction_observations (
updated_at TEXT NOT NULL, updated_at TEXT NOT NULL,
FOREIGN KEY(transaction_id) REFERENCES k_sol_chain_transactions(id), FOREIGN KEY(transaction_id) REFERENCES k_sol_chain_transactions(id),
FOREIGN KEY(instruction_id) REFERENCES k_sol_chain_instructions(id), FOREIGN KEY(instruction_id) REFERENCES k_sol_chain_instructions(id),
FOREIGN KEY(decoded_event_id) REFERENCES k_sol_dex_decoded_events(id) FOREIGN KEY(decoded_event_id) REFERENCES k_sol_dex_decoded_events(id) ON DELETE SET NULL
) )
"#, "#,
) )
@@ -1786,6 +1822,94 @@ ON k_sol_dex_event_coverage_entries (event_family, expected_db_target)
.await; .await;
} }
async fn create_tbl_launch_events(pool: &sqlx::SqlitePool) -> Result<(), crate::Error> {
return execute_sqlite_schema_statement(
pool,
"create_tbl_launch_events",
r#"
CREATE TABLE IF NOT EXISTS k_sol_launch_events (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
transaction_id INTEGER NOT NULL,
decoded_event_id INTEGER NOT NULL UNIQUE,
dex_id INTEGER NULL,
pool_id INTEGER NULL,
pair_id INTEGER NULL,
signature TEXT NOT NULL,
slot INTEGER NULL,
protocol_name TEXT NOT NULL,
program_id TEXT NULL,
event_kind TEXT NOT NULL,
pool_account TEXT NULL,
actor_wallet TEXT NULL,
event_role TEXT NOT NULL,
related_account TEXT NULL,
related_mint TEXT NULL,
payload_json TEXT NOT NULL,
executed_at TEXT NOT NULL,
created_at TEXT NOT NULL,
FOREIGN KEY(transaction_id) REFERENCES k_sol_chain_transactions(id) ON DELETE CASCADE,
FOREIGN KEY(decoded_event_id) REFERENCES k_sol_dex_decoded_events(id) ON DELETE CASCADE,
FOREIGN KEY(dex_id) REFERENCES k_sol_dexes(id) ON DELETE SET NULL,
FOREIGN KEY(pool_id) REFERENCES k_sol_pools(id) ON DELETE SET NULL,
FOREIGN KEY(pair_id) REFERENCES k_sol_pairs(id) ON DELETE SET NULL
)
"#,
)
.await;
}
async fn create_idx_launch_events_transaction_id(
pool: &sqlx::SqlitePool,
) -> Result<(), crate::Error> {
return execute_sqlite_schema_statement(
pool,
"create_idx_launch_events_transaction_id",
r#"
CREATE INDEX IF NOT EXISTS idx_launch_events_transaction_id
ON k_sol_launch_events (transaction_id)
"#,
)
.await;
}
async fn create_idx_launch_events_pool_id(pool: &sqlx::SqlitePool) -> Result<(), crate::Error> {
return execute_sqlite_schema_statement(
pool,
"create_idx_launch_events_pool_id",
r#"
CREATE INDEX IF NOT EXISTS idx_launch_events_pool_id
ON k_sol_launch_events (pool_id)
"#,
)
.await;
}
async fn create_idx_launch_events_event_kind(pool: &sqlx::SqlitePool) -> Result<(), crate::Error> {
return execute_sqlite_schema_statement(
pool,
"create_idx_launch_events_event_kind",
r#"
CREATE INDEX IF NOT EXISTS idx_launch_events_event_kind
ON k_sol_launch_events (event_kind)
"#,
)
.await;
}
async fn create_uix_launch_events_decoded_event_id(
pool: &sqlx::SqlitePool,
) -> Result<(), crate::Error> {
return execute_sqlite_schema_statement(
pool,
"create_uix_launch_events_decoded_event_id",
r#"
CREATE UNIQUE INDEX IF NOT EXISTS uix_launch_events_decoded_event_id
ON k_sol_launch_events (decoded_event_id)
"#,
)
.await;
}
async fn create_tbl_launch_surfaces(pool: &sqlx::SqlitePool) -> Result<(), crate::Error> { async fn create_tbl_launch_surfaces(pool: &sqlx::SqlitePool) -> Result<(), crate::Error> {
return execute_sqlite_schema_statement( return execute_sqlite_schema_statement(
pool, pool,
@@ -2808,3 +2932,86 @@ WHERE decoded_event_id IS NOT NULL
) )
.await; .await;
} }
/// Creates `k_sol_token_account_events`.
async fn create_tbl_token_account_events(pool: &sqlx::SqlitePool) -> Result<(), crate::Error> {
return execute_sqlite_schema_statement(
pool,
"create_tbl_token_account_events",
r#"
CREATE TABLE IF NOT EXISTS k_sol_token_account_events (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
transaction_id INTEGER NULL,
decoded_event_id INTEGER NULL,
dex_id INTEGER NULL,
pool_id INTEGER NULL,
pair_id INTEGER NULL,
signature TEXT NOT NULL,
instruction_index INTEGER NOT NULL,
slot INTEGER NULL,
protocol_name TEXT NOT NULL,
program_id TEXT NULL,
event_kind TEXT NOT NULL,
token_account TEXT NULL,
token_mint TEXT NULL,
owner_wallet TEXT NULL,
account_action TEXT NULL,
payload_json TEXT NULL,
executed_at TEXT NOT NULL,
created_at TEXT NULL,
FOREIGN KEY(transaction_id) REFERENCES k_sol_chain_transactions(id),
FOREIGN KEY(decoded_event_id) REFERENCES k_sol_dex_decoded_events(id),
FOREIGN KEY(dex_id) REFERENCES k_sol_dexes(id),
FOREIGN KEY(pool_id) REFERENCES k_sol_pools(id),
FOREIGN KEY(pair_id) REFERENCES k_sol_pairs(id)
)
"#,
)
.await;
}
/// Creates index on `k_sol_token_account_events(transaction_id)`.
async fn create_idx_token_account_events_transaction_id(
pool: &sqlx::SqlitePool,
) -> Result<(), crate::Error> {
return execute_sqlite_schema_statement(
pool,
"create_idx_token_account_events_transaction_id",
r#"
CREATE INDEX IF NOT EXISTS idx_token_account_events_transaction_id
ON k_sol_token_account_events (transaction_id)
"#,
)
.await;
}
/// Creates index on `k_sol_token_account_events(pool_id)`.
async fn create_idx_token_account_events_pool_id(
pool: &sqlx::SqlitePool,
) -> Result<(), crate::Error> {
return execute_sqlite_schema_statement(
pool,
"create_idx_token_account_events_pool_id",
r#"
CREATE INDEX IF NOT EXISTS idx_token_account_events_pool_id
ON k_sol_token_account_events (pool_id)
"#,
)
.await;
}
/// Creates unique index on `k_sol_token_account_events(decoded_event_id)`.
async fn create_uix_token_account_events_decoded_event_id(
pool: &sqlx::SqlitePool,
) -> Result<(), crate::Error> {
return execute_sqlite_schema_statement(
pool,
"create_uix_token_account_events_decoded_event_id",
r#"
CREATE UNIQUE INDEX IF NOT EXISTS uix_token_account_events_decoded_event_id
ON k_sol_token_account_events (decoded_event_id)
WHERE decoded_event_id IS NOT NULL
"#,
)
.await;
}

View File

@@ -16,6 +16,7 @@ mod pump_swap;
mod raydium_amm_v4; mod raydium_amm_v4;
mod raydium_clmm; mod raydium_clmm;
mod raydium_cpmm; mod raydium_cpmm;
pub(crate) mod raydium_launchpad;
pub use dexlab::DexlabCreatePoolDecoded; pub use dexlab::DexlabCreatePoolDecoded;
pub use dexlab::DexlabDecodedEvent; pub use dexlab::DexlabDecodedEvent;
@@ -74,8 +75,8 @@ pub use raydium_clmm::RaydiumClmmCollectProtocolFeeDecoded;
pub use raydium_clmm::RaydiumClmmCreatePoolDecoded; pub use raydium_clmm::RaydiumClmmCreatePoolDecoded;
pub use raydium_clmm::RaydiumClmmDecodedEvent; pub use raydium_clmm::RaydiumClmmDecodedEvent;
pub use raydium_clmm::RaydiumClmmDecodedInstructionEvent; pub use raydium_clmm::RaydiumClmmDecodedInstructionEvent;
pub use raydium_clmm::RaydiumClmmProgramDataEventDecoded;
pub use raydium_clmm::RaydiumClmmDecoder; pub use raydium_clmm::RaydiumClmmDecoder;
pub use raydium_clmm::RaydiumClmmProgramDataEventDecoded;
pub use raydium_clmm::RaydiumClmmSwapLegacyDecoded; pub use raydium_clmm::RaydiumClmmSwapLegacyDecoded;
pub use raydium_clmm::RaydiumClmmSwapV2Decoded; pub use raydium_clmm::RaydiumClmmSwapV2Decoded;
pub use raydium_clmm::decode_raydium_clmm_instruction; pub use raydium_clmm::decode_raydium_clmm_instruction;

View File

@@ -56,6 +56,10 @@ const RAYDIUM_CPMM_UPDATE_POOL_STATUS_DISCRIMINATOR: [u8; 8] = [130, 87, 108, 6,
/// Anchor self-CPI log selector used by Raydium CPMM events. /// Anchor self-CPI log selector used by Raydium CPMM events.
const RAYDIUM_CPMM_ANCHOR_SELF_CPI_LOG_SELECTOR: [u8; 8] = [228, 69, 165, 46, 81, 203, 154, 29]; const RAYDIUM_CPMM_ANCHOR_SELF_CPI_LOG_SELECTOR: [u8; 8] = [228, 69, 165, 46, 81, 203, 154, 29];
/// Anchor IDL management discriminator observed on Raydium CPMM (`IdlCreateAccount` / `IdlCloseAccount`).
const RAYDIUM_CPMM_ANCHOR_IDL_INSTRUCTION_DISCRIMINATOR: [u8; 8] =
[64, 244, 188, 120, 167, 233, 105, 10];
/// Raydium CPMM `LpChangeEvent` Anchor event discriminator. /// Raydium CPMM `LpChangeEvent` Anchor event discriminator.
const RAYDIUM_CPMM_LP_CHANGE_EVENT_DISCRIMINATOR: [u8; 8] = [121, 163, 205, 201, 57, 218, 117, 60]; const RAYDIUM_CPMM_LP_CHANGE_EVENT_DISCRIMINATOR: [u8; 8] = [121, 163, 205, 201, 57, 218, 117, 60];
@@ -766,6 +770,9 @@ pub fn classify_raydium_cpmm_instruction_data(
if discriminator == RAYDIUM_CPMM_UPDATE_POOL_STATUS_DISCRIMINATOR { if discriminator == RAYDIUM_CPMM_UPDATE_POOL_STATUS_DISCRIMINATOR {
return Some("update_pool_status"); return Some("update_pool_status");
} }
if discriminator == RAYDIUM_CPMM_ANCHOR_IDL_INSTRUCTION_DISCRIMINATOR {
return Some("anchor_idl_instruction");
}
return None; return None;
} }
@@ -1172,7 +1179,6 @@ fn build_raydium_cpmm_swap(
}); });
} }
fn normalize_raydium_cpmm_mints( fn normalize_raydium_cpmm_mints(
mint_a: &str, mint_a: &str,
mint_b: &str, mint_b: &str,

View File

@@ -0,0 +1,316 @@
// file: kb_lib/src/dex/raydium_launchpad.rs
//! Raydium Launchpad instruction and event helper metadata.
//!
//! The specialized `0.7.50` implementation still decodes Launchpad through
//! the shared persistence-oriented decoder. This module centralizes the stable
//! Launchpad account-layout hints so they do not remain hidden inside the
//! generic Raydium audit fallback.
/// Static account layout for a locally mapped Raydium Launchpad instruction.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub(crate) struct RaydiumLaunchpadAccountLayout {
/// IDL instruction name.
pub(crate) instruction_name: &'static str,
/// Local decoded event kind.
pub(crate) event_kind: &'static str,
/// Minimum projected account count required before applying account hints.
pub(crate) minimum_account_count: usize,
/// Candidate pool-state account index in the projected instruction account list.
pub(crate) pool_account_index: std::option::Option<usize>,
/// Candidate base mint account index in the projected instruction account list.
pub(crate) base_mint_index: std::option::Option<usize>,
/// Candidate quote mint account index in the projected instruction account list.
pub(crate) quote_mint_index: std::option::Option<usize>,
/// Whether this instruction creates a Launchpad pool/bonding curve.
pub(crate) creates_pool: bool,
}
/// Returns local account-layout hints for one Raydium Launchpad instruction discriminator.
pub(crate) fn account_layout(
discriminator_hex: &str,
account_count: usize,
) -> std::option::Option<RaydiumLaunchpadAccountLayout> {
let layout = match discriminator_hex {
"faea0d7bd59c13ec" => RaydiumLaunchpadAccountLayout {
instruction_name: "buy_exact_in",
event_kind: "raydium_launchpad.buy_exact_in",
minimum_account_count: 11,
pool_account_index: Some(4),
base_mint_index: Some(9),
quote_mint_index: Some(10),
creates_pool: false,
},
"18d3742869039938" => RaydiumLaunchpadAccountLayout {
instruction_name: "buy_exact_out",
event_kind: "raydium_launchpad.buy_exact_out",
minimum_account_count: 11,
pool_account_index: Some(4),
base_mint_index: Some(9),
quote_mint_index: Some(10),
creates_pool: false,
},
"7bb4b8816fb9bb3b" => RaydiumLaunchpadAccountLayout {
instruction_name: "close_platform_global_access",
event_kind: "raydium_launchpad.close_platform_global_access",
minimum_account_count: 4,
pool_account_index: None,
base_mint_index: None,
quote_mint_index: None,
creates_pool: false,
},
"a25b92c75d85eaed" => RaydiumLaunchpadAccountLayout {
instruction_name: "create_platform_global_access",
event_kind: "raydium_launchpad.create_platform_global_access",
minimum_account_count: 5,
pool_account_index: None,
base_mint_index: None,
quote_mint_index: None,
creates_pool: false,
},
"9247ad4562130f6a" => RaydiumLaunchpadAccountLayout {
instruction_name: "create_platform_vesting_account",
event_kind: "raydium_launchpad.create_platform_vesting_account",
minimum_account_count: 6,
pool_account_index: Some(3),
base_mint_index: None,
quote_mint_index: None,
creates_pool: false,
},
"e445a52e51cb9a1d" => no_account_layout("cpi_event", "raydium_launchpad.cpi_event"),
"1a618acb84ab8dfc" => {
no_account_layout("claim_creator_fee", "raydium_launchpad.claim_creator_fee")
},
"9c27d0874ced3d48" => RaydiumLaunchpadAccountLayout {
instruction_name: "claim_platform_fee",
event_kind: "raydium_launchpad.claim_platform_fee",
minimum_account_count: 7,
pool_account_index: Some(2),
base_mint_index: None,
quote_mint_index: Some(6),
creates_pool: false,
},
"75f1c6a8f8da501d" => no_account_layout(
"claim_platform_fee_from_vault",
"raydium_launchpad.claim_platform_fee_from_vault",
),
"3121681ebd9d4f23" => RaydiumLaunchpadAccountLayout {
instruction_name: "claim_vested_token",
event_kind: "raydium_launchpad.claim_vested_token",
minimum_account_count: 7,
pool_account_index: Some(2),
base_mint_index: Some(6),
quote_mint_index: None,
creates_pool: false,
},
"3cadf767045d8230" => RaydiumLaunchpadAccountLayout {
instruction_name: "collect_fee",
event_kind: "raydium_launchpad.collect_fee",
minimum_account_count: 6,
pool_account_index: Some(2),
base_mint_index: None,
quote_mint_index: Some(5),
creates_pool: false,
},
"ffba96dfeb76c9ba" => RaydiumLaunchpadAccountLayout {
instruction_name: "collect_migrate_fee",
event_kind: "raydium_launchpad.collect_migrate_fee",
minimum_account_count: 6,
pool_account_index: Some(2),
base_mint_index: None,
quote_mint_index: Some(5),
creates_pool: false,
},
"c9cff3724b6f2fbd" => no_account_layout("create_config", "raydium_launchpad.create_config"),
"b05ac4affd71dc14" => {
no_account_layout("create_platform_config", "raydium_launchpad.create_platform_config")
},
"81b2020dd9ace6da" => RaydiumLaunchpadAccountLayout {
instruction_name: "create_vesting_account",
event_kind: "raydium_launchpad.create_vesting_account",
minimum_account_count: 5,
pool_account_index: Some(2),
base_mint_index: None,
quote_mint_index: None,
creates_pool: false,
},
"afaf6d1f0d989bed" => initialize_layout("initialize", "raydium_launchpad.initialize"),
"4399af27da102620" => initialize_layout("initialize_v2", "raydium_launchpad.initialize_v2"),
"25be7ede2c9aab11" => initialize_layout(
"initialize_with_token_2022",
"raydium_launchpad.initialize_with_token_2022",
),
"cf52c091fecf91df" => RaydiumLaunchpadAccountLayout {
instruction_name: "migrate_to_amm",
event_kind: "raydium_launchpad.migrate_to_amm",
minimum_account_count: 28,
pool_account_index: Some(23),
base_mint_index: Some(1),
quote_mint_index: Some(2),
creates_pool: false,
},
"885cc8671cda908c" => RaydiumLaunchpadAccountLayout {
instruction_name: "migrate_to_cpswap",
event_kind: "raydium_launchpad.migrate_to_cpswap",
minimum_account_count: 22,
pool_account_index: Some(17),
base_mint_index: Some(1),
quote_mint_index: Some(2),
creates_pool: false,
},
"1b1e3ea95de01891" => no_account_layout(
"remove_platform_curve_param",
"raydium_launchpad.remove_platform_curve_param",
),
"9527de9bd37c981a" => RaydiumLaunchpadAccountLayout {
instruction_name: "sell_exact_in",
event_kind: "raydium_launchpad.sell_exact_in",
minimum_account_count: 11,
pool_account_index: Some(4),
base_mint_index: Some(9),
quote_mint_index: Some(10),
creates_pool: false,
},
"5fc8472208090ba6" => RaydiumLaunchpadAccountLayout {
instruction_name: "sell_exact_out",
event_kind: "raydium_launchpad.sell_exact_out",
minimum_account_count: 11,
pool_account_index: Some(4),
base_mint_index: Some(9),
quote_mint_index: Some(10),
creates_pool: false,
},
"1d9efcbf0a53db63" => no_account_layout("update_config", "raydium_launchpad.update_config"),
"c33c4c81922d438f" => {
no_account_layout("update_platform_config", "raydium_launchpad.update_platform_config")
},
"8a908afadc800439" => no_account_layout(
"update_platform_curve_param",
"raydium_launchpad.update_platform_curve_param",
),
_ => return None,
};
return Some(sanitize_account_layout(layout, account_count));
}
fn sanitize_account_layout(
layout: RaydiumLaunchpadAccountLayout,
account_count: usize,
) -> RaydiumLaunchpadAccountLayout {
let pool_account_index = retain_existing_index(layout.pool_account_index, account_count);
let base_mint_index = retain_existing_index(layout.base_mint_index, account_count);
let quote_mint_index = retain_existing_index(layout.quote_mint_index, account_count);
return RaydiumLaunchpadAccountLayout {
instruction_name: layout.instruction_name,
event_kind: layout.event_kind,
minimum_account_count: layout.minimum_account_count,
pool_account_index,
base_mint_index,
quote_mint_index,
creates_pool: layout.creates_pool
&& pool_account_index.is_some()
&& base_mint_index.is_some()
&& quote_mint_index.is_some(),
};
}
fn retain_existing_index(
index: std::option::Option<usize>,
account_count: usize,
) -> std::option::Option<usize> {
let index = match index {
Some(index) => index,
None => return None,
};
if index < account_count {
return Some(index);
}
return None;
}
fn no_account_layout(
instruction_name: &'static str,
event_kind: &'static str,
) -> RaydiumLaunchpadAccountLayout {
return RaydiumLaunchpadAccountLayout {
instruction_name,
event_kind,
minimum_account_count: 1,
pool_account_index: None,
base_mint_index: None,
quote_mint_index: None,
creates_pool: false,
};
}
fn initialize_layout(
instruction_name: &'static str,
event_kind: &'static str,
) -> RaydiumLaunchpadAccountLayout {
return RaydiumLaunchpadAccountLayout {
instruction_name,
event_kind,
minimum_account_count: 18,
pool_account_index: Some(5),
base_mint_index: Some(6),
quote_mint_index: Some(7),
creates_pool: true,
};
}
#[cfg(test)]
mod tests {
#[test]
fn initialize_layout_exposes_carbon_account_order() {
let layout = super::account_layout("afaf6d1f0d989bed", 18);
let layout = match layout {
Some(layout) => layout,
None => panic!("initialize layout must resolve"),
};
assert_eq!(layout.instruction_name, "initialize");
assert_eq!(layout.pool_account_index, Some(5));
assert_eq!(layout.base_mint_index, Some(6));
assert_eq!(layout.quote_mint_index, Some(7));
assert!(layout.creates_pool);
}
#[test]
fn platform_vesting_layout_exposes_pool_state() {
let layout = super::account_layout("9247ad4562130f6a", 6);
let layout = match layout {
Some(layout) => layout,
None => panic!("create_platform_vesting_account layout must resolve"),
};
assert_eq!(layout.instruction_name, "create_platform_vesting_account");
assert_eq!(layout.pool_account_index, Some(3));
}
#[test]
fn buy_layout_keeps_audit_only_pool_hints() {
let layout = super::account_layout("faea0d7bd59c13ec", 11);
let layout = match layout {
Some(layout) => layout,
None => panic!("buy layout must resolve"),
};
assert_eq!(layout.event_kind, "raydium_launchpad.buy_exact_in");
assert_eq!(layout.pool_account_index, Some(4));
assert_eq!(layout.base_mint_index, Some(9));
assert_eq!(layout.quote_mint_index, Some(10));
assert!(!layout.creates_pool);
}
#[test]
fn known_discriminator_still_maps_when_account_list_is_truncated() {
let layout = super::account_layout("cf52c091fecf91df", 1);
let layout = match layout {
Some(layout) => layout,
None => panic!("migrate_to_amm layout must resolve"),
};
assert_eq!(layout.instruction_name, "migrate_to_amm");
assert_eq!(layout.event_kind, "raydium_launchpad.migrate_to_amm");
assert_eq!(layout.pool_account_index, None);
assert_eq!(layout.base_mint_index, None);
assert_eq!(layout.quote_mint_index, None);
assert!(!layout.creates_pool);
}
}

View File

@@ -123,7 +123,7 @@ mod tests {
#[test] #[test]
fn planned_launch_surfaces_are_present_but_disabled() { fn planned_launch_surfaces_are_present_but_disabled() {
let codes = [ let codes = [
"raydium_launchlab", "raydium_launchpad",
"letsbonk", "letsbonk",
"boop_fun", "boop_fun",
"moonshot", "moonshot",

File diff suppressed because it is too large Load Diff

View File

@@ -111,6 +111,9 @@ impl DexDetectService {
crate::dex_detection_route::DexDetectionRoute::RaydiumClmmTrade => { crate::dex_detection_route::DexDetectionRoute::RaydiumClmmTrade => {
self.detect_raydium_clmm_trade(&transaction, decoded_event).await self.detect_raydium_clmm_trade(&transaction, decoded_event).await
}, },
crate::dex_detection_route::DexDetectionRoute::RaydiumLaunchpadPool => {
self.detect_raydium_launchpad_pool(&transaction, decoded_event).await
},
crate::dex_detection_route::DexDetectionRoute::PumpFunCreateV2Token => { crate::dex_detection_route::DexDetectionRoute::PumpFunCreateV2Token => {
self.detect_pump_fun_create_v2_token(&transaction, decoded_event).await self.detect_pump_fun_create_v2_token(&transaction, decoded_event).await
}, },
@@ -647,6 +650,24 @@ impl DexDetectService {
return Ok(detection_result); return Ok(detection_result);
} }
async fn detect_raydium_launchpad_pool(
&self,
transaction: &crate::ChainTransactionDto,
decoded_event: &crate::DexDecodedEventDto,
) -> Result<crate::DexPoolDetectionResult, crate::Error> {
return self
.detect_materialized_pool_from_decoded_event(
transaction,
decoded_event,
"raydium_launchpad",
crate::PoolKind::BondingCurve,
crate::PoolStatus::Pending,
"signal.dex.raydium_launchpad",
)
.await;
}
async fn detect_raydium_cpmm_trade( async fn detect_raydium_cpmm_trade(
&self, &self,
transaction: &crate::ChainTransactionDto, transaction: &crate::ChainTransactionDto,

View File

@@ -13,6 +13,8 @@ pub(crate) enum DexDetectionRoute {
RaydiumCpmmTrade, RaydiumCpmmTrade,
/// Raydium CLMM trade route. /// Raydium CLMM trade route.
RaydiumClmmTrade, RaydiumClmmTrade,
/// Raydium Launchpad pool or bonding-curve creation route.
RaydiumLaunchpadPool,
/// Pump.fun create token route. /// Pump.fun create token route.
PumpFunCreateV2Token, PumpFunCreateV2Token,
/// Pump.fun trade route. /// Pump.fun trade route.
@@ -62,6 +64,27 @@ pub(crate) fn dex_detection_route(
("raydium_clmm", "raydium_clmm.swap_v2") => { ("raydium_clmm", "raydium_clmm.swap_v2") => {
return Some(crate::dex_detection_route::DexDetectionRoute::RaydiumClmmTrade); return Some(crate::dex_detection_route::DexDetectionRoute::RaydiumClmmTrade);
}, },
("raydium_launchpad", "raydium_launchpad.initialize") => {
return Some(crate::dex_detection_route::DexDetectionRoute::RaydiumLaunchpadPool);
},
("raydium_launchpad", "raydium_launchpad.initialize_v2") => {
return Some(crate::dex_detection_route::DexDetectionRoute::RaydiumLaunchpadPool);
},
("raydium_launchpad", "raydium_launchpad.initialize_with_token_2022") => {
return Some(crate::dex_detection_route::DexDetectionRoute::RaydiumLaunchpadPool);
},
("raydium_launchpad", "raydium_launchpad.buy_exact_in") => {
return Some(crate::dex_detection_route::DexDetectionRoute::RaydiumLaunchpadPool);
},
("raydium_launchpad", "raydium_launchpad.buy_exact_out") => {
return Some(crate::dex_detection_route::DexDetectionRoute::RaydiumLaunchpadPool);
},
("raydium_launchpad", "raydium_launchpad.sell_exact_in") => {
return Some(crate::dex_detection_route::DexDetectionRoute::RaydiumLaunchpadPool);
},
("raydium_launchpad", "raydium_launchpad.sell_exact_out") => {
return Some(crate::dex_detection_route::DexDetectionRoute::RaydiumLaunchpadPool);
},
("pump_fun", "pump_fun.create_v2_token") => { ("pump_fun", "pump_fun.create_v2_token") => {
return Some(crate::dex_detection_route::DexDetectionRoute::PumpFunCreateV2Token); return Some(crate::dex_detection_route::DexDetectionRoute::PumpFunCreateV2Token);
}, },
@@ -233,6 +256,26 @@ mod tests {
assert!(!crate::dex_detection_route::decoded_event_has_full_pool_context(&event)); assert!(!crate::dex_detection_route::decoded_event_has_full_pool_context(&event));
} }
#[test]
fn raydium_launchpad_initialize_route_requires_full_pool_context() {
let event = make_decoded_event(
"raydium_launchpad",
"raydium_launchpad.initialize",
Some("Pool111"),
Some("TokenA111"),
Some("TokenB111"),
);
let route_option = crate::dex_detection_route::dex_detection_route(&event);
let route = match route_option {
Some(route) => route,
None => panic!("route must be selected"),
};
assert_eq!(route, crate::dex_detection_route::DexDetectionRoute::RaydiumLaunchpadPool);
assert!(crate::dex_detection_route::dex_detection_route_requires_full_pool_context(
route
));
}
#[test] #[test]
fn pump_fun_create_token_route_does_not_require_full_pool_context() { fn pump_fun_create_token_route_does_not_require_full_pool_context() {
let event = make_decoded_event( let event = make_decoded_event(

View File

@@ -23,6 +23,8 @@ pub enum DexEventCategory {
PoolLifecycle, PoolLifecycle,
/// Protocol administration, configuration or permission update event. /// Protocol administration, configuration or permission update event.
Admin, Admin,
/// Token-account creation, close, wrap or unwrap event.
TokenAccount,
/// Informational or audit-only decoded event retained for corpus analysis. /// Informational or audit-only decoded event retained for corpus analysis.
Informational, Informational,
/// Event kind that is not classified yet. /// Event kind that is not classified yet.
@@ -39,6 +41,7 @@ impl DexEventCategory {
Self::Reward => return "reward", Self::Reward => return "reward",
Self::PoolLifecycle => return "pool_lifecycle", Self::PoolLifecycle => return "pool_lifecycle",
Self::Admin => return "admin", Self::Admin => return "admin",
Self::TokenAccount => return "token_account",
Self::Informational => return "informational", Self::Informational => return "informational",
Self::Unknown => return "unknown", Self::Unknown => return "unknown",
} }
@@ -76,6 +79,10 @@ pub enum DexEventLifecycleKind {
Reward, Reward,
/// Administration, configuration or permission update event. /// Administration, configuration or permission update event.
AdminConfig, AdminConfig,
/// Token-account creation event.
TokenAccountCreate,
/// Token-account close event.
TokenAccountClose,
/// Instruction-level audit event retained for corpus analysis. /// Instruction-level audit event retained for corpus analysis.
InstructionAudit, InstructionAudit,
/// Event kind that is not classified yet. /// Event kind that is not classified yet.
@@ -100,6 +107,8 @@ impl DexEventLifecycleKind {
Self::FeeCollection => return "fee_collection", Self::FeeCollection => return "fee_collection",
Self::Reward => return "reward", Self::Reward => return "reward",
Self::AdminConfig => return "admin_config", Self::AdminConfig => return "admin_config",
Self::TokenAccountCreate => return "token_account_create",
Self::TokenAccountClose => return "token_account_close",
Self::InstructionAudit => return "instruction_audit", Self::InstructionAudit => return "instruction_audit",
Self::Unknown => return "unknown", Self::Unknown => return "unknown",
} }
@@ -157,6 +166,9 @@ pub fn classify_dex_event_category(event_kind: &str) -> DexEventCategory {
if is_dex_admin_event_kind(event_kind) { if is_dex_admin_event_kind(event_kind) {
return DexEventCategory::Admin; return DexEventCategory::Admin;
} }
if is_dex_token_account_event_kind(event_kind) {
return DexEventCategory::TokenAccount;
}
if is_dex_trade_event_kind(event_kind) { if is_dex_trade_event_kind(event_kind) {
return DexEventCategory::Trade; return DexEventCategory::Trade;
} }
@@ -215,6 +227,12 @@ pub fn classify_dex_event_lifecycle_kind(event_kind: &str) -> DexEventLifecycleK
if is_dex_admin_event_kind(event_kind) { if is_dex_admin_event_kind(event_kind) {
return DexEventLifecycleKind::AdminConfig; return DexEventLifecycleKind::AdminConfig;
} }
if is_dex_token_account_close_event_kind(event_kind) {
return DexEventLifecycleKind::TokenAccountClose;
}
if is_dex_token_account_create_event_kind(event_kind) {
return DexEventLifecycleKind::TokenAccountCreate;
}
if is_dex_trade_event_kind(event_kind) { if is_dex_trade_event_kind(event_kind) {
return DexEventLifecycleKind::TradeSwap; return DexEventLifecycleKind::TradeSwap;
} }
@@ -254,6 +272,7 @@ pub fn classify_dex_event_actionability(
DexEventCategory::Reward => return DexEventActionability::NonTradeUseful, DexEventCategory::Reward => return DexEventActionability::NonTradeUseful,
DexEventCategory::PoolLifecycle => return DexEventActionability::NonTradeUseful, DexEventCategory::PoolLifecycle => return DexEventActionability::NonTradeUseful,
DexEventCategory::Admin => return DexEventActionability::NonTradeUseful, DexEventCategory::Admin => return DexEventActionability::NonTradeUseful,
DexEventCategory::TokenAccount => return DexEventActionability::NonTradeUseful,
DexEventCategory::Informational => return DexEventActionability::Informational, DexEventCategory::Informational => return DexEventActionability::Informational,
DexEventCategory::Trade => return DexEventActionability::NonActionableTrade, DexEventCategory::Trade => return DexEventActionability::NonActionableTrade,
DexEventCategory::Unknown => return DexEventActionability::Unknown, DexEventCategory::Unknown => return DexEventActionability::Unknown,
@@ -278,6 +297,18 @@ pub fn is_dex_informational_event_kind(event_kind: &str) -> bool {
if event_kind.contains(".instruction_audit") { if event_kind.contains(".instruction_audit") {
return true; return true;
} }
if event_kind.ends_with(".cpi_event") {
return true;
}
if event_kind.ends_with(".anchor_idl_instruction") {
return true;
}
if event_kind.contains(".idl_") {
return true;
}
if event_kind.contains(".liquidity_calculate_event") {
return true;
}
if event_kind.ends_with("_audit") { if event_kind.ends_with("_audit") {
return true; return true;
} }
@@ -289,6 +320,9 @@ pub fn is_dex_informational_event_kind(event_kind: &str) -> bool {
/// Returns true when the event kind represents a swap-like event. /// Returns true when the event kind represents a swap-like event.
pub fn is_dex_trade_event_kind(event_kind: &str) -> bool { pub fn is_dex_trade_event_kind(event_kind: &str) -> bool {
if event_kind == "raydium_launchpad.trade_event" {
return true;
}
if event_kind.ends_with(".buy") { if event_kind.ends_with(".buy") {
return true; return true;
} }
@@ -332,9 +366,6 @@ pub fn is_dex_liquidity_event_kind(event_kind: &str) -> bool {
if event_kind.contains(".liquidity_change_event") { if event_kind.contains(".liquidity_change_event") {
return true; return true;
} }
if event_kind.contains(".liquidity_calculate_event") {
return true;
}
if event_kind.contains(".withdraw") { if event_kind.contains(".withdraw") {
return true; return true;
} }
@@ -362,6 +393,9 @@ pub fn is_dex_liquidity_event_kind(event_kind: &str) -> bool {
if event_kind.contains(".close_position") { if event_kind.contains(".close_position") {
return true; return true;
} }
if event_kind.contains(".close_protocol_position") {
return true;
}
if event_kind.contains(".position_close") { if event_kind.contains(".position_close") {
return true; return true;
} }
@@ -404,6 +438,9 @@ pub fn is_dex_position_open_event_kind(event_kind: &str) -> bool {
if event_kind.contains(".open_position") { if event_kind.contains(".open_position") {
return true; return true;
} }
if event_kind.contains(".create_personal_position_event") {
return true;
}
if event_kind.contains(".position_create") { if event_kind.contains(".position_create") {
return true; return true;
} }
@@ -415,11 +452,23 @@ pub fn is_dex_position_close_event_kind(event_kind: &str) -> bool {
if event_kind.contains(".close_position") { if event_kind.contains(".close_position") {
return true; return true;
} }
if event_kind.contains(".close_protocol_position") {
return true;
}
return false; return false;
} }
/// Returns true for fee collection events. /// Returns true for fee collection events.
pub fn is_dex_fee_event_kind(event_kind: &str) -> bool { pub fn is_dex_fee_event_kind(event_kind: &str) -> bool {
if event_kind.contains("claim_creator_fee") {
return true;
}
if event_kind.contains("claim_platform_fee") {
return true;
}
if event_kind.contains("collect_migrate_fee") {
return true;
}
if event_kind.contains("collect_creator_fee") { if event_kind.contains("collect_creator_fee") {
return true; return true;
} }
@@ -518,6 +567,21 @@ pub fn is_dex_pool_lifecycle_event_kind(event_kind: &str) -> bool {
/// Returns true for launch or bonding-curve creation events. /// Returns true for launch or bonding-curve creation events.
pub fn is_dex_launch_event_kind(event_kind: &str) -> bool { pub fn is_dex_launch_event_kind(event_kind: &str) -> bool {
if event_kind.contains(".claim_vested_event") {
return true;
}
if event_kind.contains(".claim_vested_token") {
return true;
}
if event_kind.contains(".create_platform_vesting_account") {
return true;
}
if event_kind.contains(".create_vesting_account") {
return true;
}
if event_kind.contains(".create_vesting_event") {
return true;
}
if event_kind.contains("pump_fun.create") { if event_kind.contains("pump_fun.create") {
return true; return true;
} }
@@ -586,9 +650,15 @@ pub fn is_dex_pool_creation_event_kind(event_kind: &str) -> bool {
if event_kind.contains(".create_pool") { if event_kind.contains(".create_pool") {
return true; return true;
} }
if event_kind.contains(".create_customizable_pool") {
return true;
}
if event_kind.contains(".pool_created_event") { if event_kind.contains(".pool_created_event") {
return true; return true;
} }
if event_kind.contains(".pool_create_event") {
return true;
}
if event_kind.contains(".create_amm") { if event_kind.contains(".create_amm") {
return true; return true;
} }
@@ -606,8 +676,53 @@ pub fn is_dex_pair_creation_event_kind(event_kind: &str) -> bool {
return false; return false;
} }
/// Returns true for token-account lifecycle events detected by DEX decoders.
pub fn is_dex_token_account_event_kind(event_kind: &str) -> bool {
if is_dex_token_account_create_event_kind(event_kind) {
return true;
}
if is_dex_token_account_close_event_kind(event_kind) {
return true;
}
return false;
}
/// Returns true for token-account creation events detected by DEX decoders.
pub fn is_dex_token_account_create_event_kind(event_kind: &str) -> bool {
if event_kind.contains(".create_support_mint_associated") {
return true;
}
if event_kind.contains(".create_ata") {
return true;
}
if event_kind.contains(".init_account") {
return true;
}
return false;
}
/// Returns true for token-account close events detected by DEX decoders.
pub fn is_dex_token_account_close_event_kind(event_kind: &str) -> bool {
if event_kind.contains(".close_account") {
return true;
}
return false;
}
/// Returns true for admin, configuration or permission changes. /// Returns true for admin, configuration or permission changes.
pub fn is_dex_admin_event_kind(event_kind: &str) -> bool { pub fn is_dex_admin_event_kind(event_kind: &str) -> bool {
if event_kind.contains(".close_platform_global_access") {
return true;
}
if event_kind.contains(".create_platform_global_access") {
return true;
}
if event_kind.contains(".create_operation_account") {
return true;
}
if event_kind.contains("platform_curve_param") {
return true;
}
if event_kind.contains(".initialize_with_permission") { if event_kind.contains(".initialize_with_permission") {
return false; return false;
} }

View File

@@ -183,7 +183,11 @@ impl DexEventCoverageService {
fn build_coverage_entry_from_upstream( fn build_coverage_entry_from_upstream(
entry: &crate::UpstreamRegistryEntryDto, entry: &crate::UpstreamRegistryEntryDto,
) -> crate::DexEventCoverageEntryDto { ) -> crate::DexEventCoverageEntryDto {
let event_family = infer_event_family(entry.entry_name.as_str(), entry.entry_kind.as_str()); let event_family = infer_event_family_for_entry(
entry.decoder_code.as_str(),
entry.entry_name.as_str(),
entry.entry_kind.as_str(),
);
let expected_db_target = infer_expected_db_target_for_entry( let expected_db_target = infer_expected_db_target_for_entry(
entry.decoder_code.as_str(), entry.decoder_code.as_str(),
entry.entry_name.as_str(), entry.entry_name.as_str(),
@@ -211,12 +215,80 @@ fn infer_expected_db_target_for_entry(
event_family: std::option::Option<&str>, event_family: std::option::Option<&str>,
entry_kind: &str, entry_kind: &str,
) -> std::option::Option<std::string::String> { ) -> std::option::Option<std::string::String> {
if decoder_code == "raydium_cpmm" && entry_name == "swap_event" { if decoder_code == "raydium_cpmm"
&& (entry_name == "swap_event" || entry_name == "anchor_idl_instruction")
{
return Some(crate::DexEventCoverageEntryDto::DB_TARGET_DECODED_EVENTS_ONLY.to_string()); return Some(crate::DexEventCoverageEntryDto::DB_TARGET_DECODED_EVENTS_ONLY.to_string());
} }
if decoder_code == "raydium_clmm" && entry_name == "initialize_reward" { if decoder_code == "raydium_clmm" {
if entry_name == "initialize_reward" {
return Some(crate::DexEventCoverageEntryDto::DB_TARGET_REWARD_EVENTS.to_string()); return Some(crate::DexEventCoverageEntryDto::DB_TARGET_REWARD_EVENTS.to_string());
} }
if entry_name == "swap_event" || entry_name == "swap_router_base_in" {
return Some(
crate::DexEventCoverageEntryDto::DB_TARGET_DECODED_EVENTS_ONLY.to_string(),
);
}
if entry_name == "open_position"
|| entry_name == "close_position"
|| entry_name == "close_protocol_position"
{
return Some(
crate::DexEventCoverageEntryDto::DB_TARGET_DECODED_EVENTS_ONLY.to_string(),
);
}
}
if decoder_code == "raydium_launchpad" {
if entry_name == "trade_event" {
return Some(crate::DexEventCoverageEntryDto::DB_TARGET_TRADE_EVENTS.to_string());
}
if entry_name == "buy_exact_in"
|| entry_name == "buy_exact_out"
|| entry_name == "sell_exact_in"
|| entry_name == "sell_exact_out"
{
return Some(crate::DexEventCoverageEntryDto::DB_TARGET_LAUNCH_EVENTS.to_string());
}
if entry_name == "initialize"
|| entry_name == "initialize_v2"
|| entry_name == "initialize_with_token_2022"
|| entry_name == "pool_create_event"
{
return Some(
crate::DexEventCoverageEntryDto::DB_TARGET_POOL_LIFECYCLE_EVENTS.to_string(),
);
}
if entry_name == "claim_creator_fee"
|| entry_name == "claim_platform_fee"
|| entry_name == "claim_platform_fee_from_vault"
|| entry_name == "collect_fee"
|| entry_name == "collect_migrate_fee"
{
return Some(crate::DexEventCoverageEntryDto::DB_TARGET_FEE_EVENTS.to_string());
}
if entry_name == "close_platform_global_access"
|| entry_name == "create_config"
|| entry_name == "create_platform_config"
|| entry_name == "create_platform_global_access"
|| entry_name == "remove_platform_curve_param"
|| entry_name == "update_config"
|| entry_name == "update_platform_config"
|| entry_name == "update_platform_curve_param"
{
return Some(crate::DexEventCoverageEntryDto::DB_TARGET_POOL_ADMIN_EVENTS.to_string());
}
if entry_name == "claim_vested_event"
|| entry_name == "claim_vested_token"
|| entry_name == "create_platform_vesting_account"
|| entry_name == "create_vesting_account"
|| entry_name == "create_vesting_event"
|| entry_name == "migrate_to_amm"
|| entry_name == "migrate_to_cpswap"
{
return Some(crate::DexEventCoverageEntryDto::DB_TARGET_LAUNCH_EVENTS.to_string());
}
return Some(crate::DexEventCoverageEntryDto::DB_TARGET_DECODED_EVENTS_ONLY.to_string());
}
return infer_expected_db_target(event_family, entry_kind); return infer_expected_db_target(event_family, entry_kind);
} }
@@ -241,6 +313,7 @@ fn infer_expected_db_target(
"liquidity" => crate::DexEventCoverageEntryDto::DB_TARGET_LIQUIDITY_EVENTS, "liquidity" => crate::DexEventCoverageEntryDto::DB_TARGET_LIQUIDITY_EVENTS,
"liquidity_add" => crate::DexEventCoverageEntryDto::DB_TARGET_LIQUIDITY_EVENTS, "liquidity_add" => crate::DexEventCoverageEntryDto::DB_TARGET_LIQUIDITY_EVENTS,
"liquidity_remove" => crate::DexEventCoverageEntryDto::DB_TARGET_LIQUIDITY_EVENTS, "liquidity_remove" => crate::DexEventCoverageEntryDto::DB_TARGET_LIQUIDITY_EVENTS,
"liquidity_change" => crate::DexEventCoverageEntryDto::DB_TARGET_LIQUIDITY_EVENTS,
"position_open" => crate::DexEventCoverageEntryDto::DB_TARGET_LIQUIDITY_EVENTS, "position_open" => crate::DexEventCoverageEntryDto::DB_TARGET_LIQUIDITY_EVENTS,
"position_close" => crate::DexEventCoverageEntryDto::DB_TARGET_LIQUIDITY_EVENTS, "position_close" => crate::DexEventCoverageEntryDto::DB_TARGET_LIQUIDITY_EVENTS,
"fee" => crate::DexEventCoverageEntryDto::DB_TARGET_FEE_EVENTS, "fee" => crate::DexEventCoverageEntryDto::DB_TARGET_FEE_EVENTS,
@@ -264,6 +337,10 @@ fn infer_expected_db_target(
"unlock" => crate::DexEventCoverageEntryDto::DB_TARGET_LIQUIDITY_LOCK_EVENTS, "unlock" => crate::DexEventCoverageEntryDto::DB_TARGET_LIQUIDITY_LOCK_EVENTS,
"launch" => crate::DexEventCoverageEntryDto::DB_TARGET_LAUNCH_EVENTS, "launch" => crate::DexEventCoverageEntryDto::DB_TARGET_LAUNCH_EVENTS,
"migration" => crate::DexEventCoverageEntryDto::DB_TARGET_LAUNCH_EVENTS, "migration" => crate::DexEventCoverageEntryDto::DB_TARGET_LAUNCH_EVENTS,
"vesting" => crate::DexEventCoverageEntryDto::DB_TARGET_LAUNCH_EVENTS,
"liquidity_calculation" => crate::DexEventCoverageEntryDto::DB_TARGET_DECODED_EVENTS_ONLY,
"cpi_transport" => crate::DexEventCoverageEntryDto::DB_TARGET_DECODED_EVENTS_ONLY,
"idl_management" => crate::DexEventCoverageEntryDto::DB_TARGET_DECODED_EVENTS_ONLY,
"stake" => crate::DexEventCoverageEntryDto::DB_TARGET_DECODED_EVENTS_ONLY, "stake" => crate::DexEventCoverageEntryDto::DB_TARGET_DECODED_EVENTS_ONLY,
"unstake" => crate::DexEventCoverageEntryDto::DB_TARGET_DECODED_EVENTS_ONLY, "unstake" => crate::DexEventCoverageEntryDto::DB_TARGET_DECODED_EVENTS_ONLY,
_ => crate::DexEventCoverageEntryDto::DB_TARGET_DECODED_EVENTS_ONLY, _ => crate::DexEventCoverageEntryDto::DB_TARGET_DECODED_EVENTS_ONLY,
@@ -271,6 +348,99 @@ fn infer_expected_db_target(
return Some(target.to_string()); return Some(target.to_string());
} }
fn infer_event_family_for_entry(
decoder_code: &str,
entry_name: &str,
entry_kind: &str,
) -> std::option::Option<std::string::String> {
if decoder_code == "raydium_launchpad" {
return infer_raydium_launchpad_event_family(entry_name, entry_kind);
}
if decoder_code == "raydium_clmm" {
return infer_raydium_clmm_event_family(entry_name, entry_kind);
}
if decoder_code == "raydium_cpmm" {
return infer_raydium_cpmm_event_family(entry_name, entry_kind);
}
return infer_event_family(entry_name, entry_kind);
}
fn infer_raydium_cpmm_event_family(
entry_name: &str,
entry_kind: &str,
) -> std::option::Option<std::string::String> {
if entry_kind == crate::ENTRY_KIND_PROGRAM {
return None;
}
match entry_name {
"anchor_idl_instruction" => return Some("idl_management".to_string()),
"cpi_event" => return Some("cpi_transport".to_string()),
_ => return infer_event_family(entry_name, entry_kind),
}
}
fn infer_raydium_clmm_event_family(
entry_name: &str,
entry_kind: &str,
) -> std::option::Option<std::string::String> {
if entry_kind == crate::ENTRY_KIND_PROGRAM {
return None;
}
match entry_name {
"cpi_event" => return Some("cpi_transport".to_string()),
"create_personal_position_event" => return Some("position_open".to_string()),
"liquidity_calculate_event" => return Some("liquidity_calculation".to_string()),
"liquidity_change_event" => return Some("liquidity_change".to_string()),
"pool_created_event" => return Some("pool_create".to_string()),
"create_operation_account" => return Some("admin_config".to_string()),
"update_operation_account" => return Some("admin_config".to_string()),
"update_dynamic_fee_config" => return Some("admin_config".to_string()),
_ => return infer_event_family(entry_name, entry_kind),
}
}
fn infer_raydium_launchpad_event_family(
entry_name: &str,
entry_kind: &str,
) -> std::option::Option<std::string::String> {
if entry_kind == crate::ENTRY_KIND_PROGRAM {
return None;
}
match entry_name {
"buy_exact_in" => return Some("swap".to_string()),
"buy_exact_out" => return Some("swap".to_string()),
"sell_exact_in" => return Some("swap".to_string()),
"sell_exact_out" => return Some("swap".to_string()),
"trade_event" => return Some("swap".to_string()),
"pool_create_event" => return Some("pool_create".to_string()),
"initialize" => return Some("pool_create".to_string()),
"initialize_v2" => return Some("pool_create".to_string()),
"initialize_with_token_2022" => return Some("pool_create".to_string()),
"claim_creator_fee" => return Some("fee".to_string()),
"claim_platform_fee" => return Some("fee".to_string()),
"claim_platform_fee_from_vault" => return Some("fee".to_string()),
"collect_fee" => return Some("fee".to_string()),
"collect_migrate_fee" => return Some("fee".to_string()),
"claim_vested_event" => return Some("vesting".to_string()),
"claim_vested_token" => return Some("vesting".to_string()),
"create_platform_vesting_account" => return Some("vesting".to_string()),
"create_vesting_account" => return Some("vesting".to_string()),
"create_vesting_event" => return Some("vesting".to_string()),
"migrate_to_amm" => return Some("migration".to_string()),
"migrate_to_cpswap" => return Some("migration".to_string()),
"close_platform_global_access" => return Some("account_close".to_string()),
"create_config" => return Some("admin_config".to_string()),
"create_platform_config" => return Some("admin_config".to_string()),
"create_platform_global_access" => return Some("admin_config".to_string()),
"remove_platform_curve_param" => return Some("admin_config".to_string()),
"update_config" => return Some("admin_config".to_string()),
"update_platform_config" => return Some("admin_config".to_string()),
"update_platform_curve_param" => return Some("admin_config".to_string()),
"cpi_event" => return Some("cpi_transport".to_string()),
_ => return infer_event_family(entry_name, entry_kind),
}
}
fn infer_event_family( fn infer_event_family(
entry_name: &str, entry_name: &str,
entry_kind: &str, entry_kind: &str,
@@ -282,6 +452,12 @@ fn infer_event_family(
if normalized == "lp_change_event" { if normalized == "lp_change_event" {
return Some("liquidity".to_string()); return Some("liquidity".to_string());
} }
if normalized == "cpi_event" {
return Some("cpi_transport".to_string());
}
if contains_any(normalized.as_str(), &["migrate", "migration", "graduate"]) {
return Some("migration".to_string());
}
if contains_any(normalized.as_str(), &["swap", "buy", "sell", "trade"]) { if contains_any(normalized.as_str(), &["swap", "buy", "sell", "trade"]) {
return Some("swap".to_string()); return Some("swap".to_string());
} }
@@ -416,10 +592,49 @@ fn contains_any(value: &str, needles: &[&str]) -> bool {
return false; return false;
} }
fn raydium_launchpad_local_entry_is_known(entry_name: &str) -> bool {
match entry_name {
"buy_exact_in" => return true,
"buy_exact_out" => return true,
"close_platform_global_access" => return true,
"claim_creator_fee" => return true,
"claim_platform_fee" => return true,
"claim_platform_fee_from_vault" => return true,
"claim_vested_event" => return true,
"claim_vested_token" => return true,
"collect_fee" => return true,
"collect_migrate_fee" => return true,
"create_config" => return true,
"create_platform_config" => return true,
"cpi_event" => return true,
"create_platform_vesting_account" => return true,
"create_platform_global_access" => return true,
"create_vesting_account" => return true,
"create_vesting_event" => return true,
"initialize" => return true,
"initialize_v2" => return true,
"initialize_with_token_2022" => return true,
"migrate_to_amm" => return true,
"migrate_to_cpswap" => return true,
"pool_create_event" => return true,
"remove_platform_curve_param" => return true,
"sell_exact_in" => return true,
"sell_exact_out" => return true,
"trade_event" => return true,
"update_config" => return true,
"update_platform_config" => return true,
"update_platform_curve_param" => return true,
_ => return false,
}
}
pub(crate) fn known_local_event_kind( pub(crate) fn known_local_event_kind(
decoder_code: &str, decoder_code: &str,
entry_name: &str, entry_name: &str,
) -> std::option::Option<std::string::String> { ) -> std::option::Option<std::string::String> {
if decoder_code == "raydium_launchpad" && raydium_launchpad_local_entry_is_known(entry_name) {
return Some(format!("raydium_launchpad.{}", entry_name));
}
match (decoder_code, entry_name) { match (decoder_code, entry_name) {
("raydium_cpmm", "swap_base_input") => { ("raydium_cpmm", "swap_base_input") => {
return Some("raydium_cpmm.swap_base_input".to_string()); return Some("raydium_cpmm.swap_base_input".to_string());
@@ -453,6 +668,10 @@ pub(crate) fn known_local_event_kind(
("raydium_cpmm", "lp_change_event") => { ("raydium_cpmm", "lp_change_event") => {
return Some("raydium_cpmm.lp_change_event".to_string()); return Some("raydium_cpmm.lp_change_event".to_string());
}, },
("raydium_cpmm", "cpi_event") => return Some("raydium_cpmm.cpi_event".to_string()),
("raydium_cpmm", "anchor_idl_instruction") => {
return Some("raydium_cpmm.anchor_idl_instruction".to_string());
},
("raydium_cpmm", "swap_event") => return Some("raydium_cpmm.swap_event".to_string()), ("raydium_cpmm", "swap_event") => return Some("raydium_cpmm.swap_event".to_string()),
("raydium_cpmm", "update_amm_config") => { ("raydium_cpmm", "update_amm_config") => {
return Some("raydium_cpmm.update_amm_config".to_string()); return Some("raydium_cpmm.update_amm_config".to_string());
@@ -461,6 +680,38 @@ pub(crate) fn known_local_event_kind(
return Some("raydium_cpmm.update_pool_status".to_string()); return Some("raydium_cpmm.update_pool_status".to_string());
}, },
("raydium_cpmm", "withdraw") => return Some("raydium_cpmm.withdraw".to_string()), ("raydium_cpmm", "withdraw") => return Some("raydium_cpmm.withdraw".to_string()),
("raydium_clmm", "cpi_event") => return Some("raydium_clmm.cpi_event".to_string()),
("raydium_clmm", "collect_personal_fee_event") => {
return Some("raydium_clmm.collect_personal_fee_event".to_string());
},
("raydium_clmm", "collect_protocol_fee_event") => {
return Some("raydium_clmm.collect_protocol_fee_event".to_string());
},
("raydium_clmm", "config_change_event") => {
return Some("raydium_clmm.config_change_event".to_string());
},
("raydium_clmm", "create_personal_position_event") => {
return Some("raydium_clmm.create_personal_position_event".to_string());
},
("raydium_clmm", "decrease_liquidity_event") => {
return Some("raydium_clmm.decrease_liquidity_event".to_string());
},
("raydium_clmm", "increase_liquidity_event") => {
return Some("raydium_clmm.increase_liquidity_event".to_string());
},
("raydium_clmm", "liquidity_calculate_event") => {
return Some("raydium_clmm.liquidity_calculate_event".to_string());
},
("raydium_clmm", "liquidity_change_event") => {
return Some("raydium_clmm.liquidity_change_event".to_string());
},
("raydium_clmm", "pool_created_event") => {
return Some("raydium_clmm.pool_created_event".to_string());
},
("raydium_clmm", "swap_event") => return Some("raydium_clmm.swap_event".to_string()),
("raydium_clmm", "update_reward_infos_event") => {
return Some("raydium_clmm.update_reward_infos_event".to_string());
},
("raydium_clmm", "close_limit_order") => { ("raydium_clmm", "close_limit_order") => {
return Some("raydium_clmm.close_limit_order".to_string()); return Some("raydium_clmm.close_limit_order".to_string());
}, },
@@ -545,6 +796,9 @@ pub(crate) fn known_local_event_kind(
("raydium_clmm", "update_amm_config") => { ("raydium_clmm", "update_amm_config") => {
return Some("raydium_clmm.update_amm_config".to_string()); return Some("raydium_clmm.update_amm_config".to_string());
}, },
("raydium_clmm", "update_dynamic_fee_config") => {
return Some("raydium_clmm.update_dynamic_fee_config".to_string());
},
("raydium_clmm", "update_operation_account") => { ("raydium_clmm", "update_operation_account") => {
return Some("raydium_clmm.update_operation_account".to_string()); return Some("raydium_clmm.update_operation_account".to_string());
}, },
@@ -605,6 +859,23 @@ mod tests {
super::infer_event_family("collect_creator_fee", crate::ENTRY_KIND_INSTRUCTION), super::infer_event_family("collect_creator_fee", crate::ENTRY_KIND_INSTRUCTION),
Some("fee".to_string()) Some("fee".to_string())
); );
assert_eq!(
super::infer_event_family_for_entry(
"raydium_cpmm",
"anchor_idl_instruction",
crate::ENTRY_KIND_INSTRUCTION,
),
Some("idl_management".to_string())
);
assert_eq!(
super::infer_expected_db_target_for_entry(
"raydium_cpmm",
"anchor_idl_instruction",
Some("idl_management"),
crate::ENTRY_KIND_INSTRUCTION,
),
Some(crate::DexEventCoverageEntryDto::DB_TARGET_DECODED_EVENTS_ONLY.to_string())
);
} }
#[test] #[test]
@@ -617,6 +888,38 @@ mod tests {
super::infer_event_family("create_dynamic_fee_config", crate::ENTRY_KIND_INSTRUCTION), super::infer_event_family("create_dynamic_fee_config", crate::ENTRY_KIND_INSTRUCTION),
Some("admin_config".to_string()) Some("admin_config".to_string())
); );
assert_eq!(
super::infer_event_family_for_entry(
"raydium_clmm",
"update_dynamic_fee_config",
crate::ENTRY_KIND_INSTRUCTION,
),
Some("admin_config".to_string())
);
assert_eq!(
super::infer_event_family_for_entry(
"raydium_clmm",
"create_personal_position_event",
crate::ENTRY_KIND_EVENT,
),
Some("position_open".to_string())
);
assert_eq!(
super::infer_event_family_for_entry(
"raydium_clmm",
"liquidity_calculate_event",
crate::ENTRY_KIND_EVENT,
),
Some("liquidity_calculation".to_string())
);
assert_eq!(
super::infer_event_family_for_entry(
"raydium_clmm",
"liquidity_change_event",
crate::ENTRY_KIND_EVENT,
),
Some("liquidity_change".to_string())
);
assert_eq!( assert_eq!(
super::infer_event_family( super::infer_event_family(
"create_support_mint_associated", "create_support_mint_associated",
@@ -652,6 +955,15 @@ mod tests {
super::infer_expected_db_target(Some("position_open"), crate::ENTRY_KIND_INSTRUCTION), super::infer_expected_db_target(Some("position_open"), crate::ENTRY_KIND_INSTRUCTION),
Some(crate::DexEventCoverageEntryDto::DB_TARGET_LIQUIDITY_EVENTS.to_string()) Some(crate::DexEventCoverageEntryDto::DB_TARGET_LIQUIDITY_EVENTS.to_string())
); );
assert_eq!(
super::infer_expected_db_target_for_entry(
"raydium_clmm",
"open_position",
Some("position_open"),
crate::ENTRY_KIND_INSTRUCTION,
),
Some(crate::DexEventCoverageEntryDto::DB_TARGET_DECODED_EVENTS_ONLY.to_string())
);
assert_eq!( assert_eq!(
super::infer_expected_db_target(Some("position_close"), crate::ENTRY_KIND_INSTRUCTION), super::infer_expected_db_target(Some("position_close"), crate::ENTRY_KIND_INSTRUCTION),
Some(crate::DexEventCoverageEntryDto::DB_TARGET_LIQUIDITY_EVENTS.to_string()) Some(crate::DexEventCoverageEntryDto::DB_TARGET_LIQUIDITY_EVENTS.to_string())
@@ -676,6 +988,79 @@ mod tests {
super::known_local_event_kind("raydium_clmm", "decrease_limit_order"), super::known_local_event_kind("raydium_clmm", "decrease_limit_order"),
Some("raydium_clmm.decrease_limit_order".to_string()) Some("raydium_clmm.decrease_limit_order".to_string())
); );
assert_eq!(
super::known_local_event_kind("raydium_clmm", "update_dynamic_fee_config"),
Some("raydium_clmm.update_dynamic_fee_config".to_string())
);
assert_eq!(
super::known_local_event_kind("raydium_clmm", "cpi_event"),
Some("raydium_clmm.cpi_event".to_string())
);
assert_eq!(
super::known_local_event_kind("raydium_clmm", "pool_created_event"),
Some("raydium_clmm.pool_created_event".to_string())
);
}
#[test]
fn launchpad_swap_instructions_materialize_as_launch_events_without_duplicate_trades() {
assert_eq!(
super::known_local_event_kind("raydium_launchpad", "buy_exact_in"),
Some("raydium_launchpad.buy_exact_in".to_string())
);
assert_eq!(
super::known_local_event_kind("raydium_launchpad", "trade_event"),
Some("raydium_launchpad.trade_event".to_string())
);
assert_eq!(super::known_local_event_kind("raydium_launchpad", "program"), None);
assert_eq!(
super::infer_event_family_for_entry(
"raydium_launchpad",
"pool_create_event",
crate::ENTRY_KIND_EVENT,
),
Some("pool_create".to_string())
);
assert_eq!(
super::infer_event_family_for_entry(
"raydium_launchpad",
"claim_vested_event",
crate::ENTRY_KIND_EVENT,
),
Some("vesting".to_string())
);
assert_eq!(
super::infer_event_family_for_entry(
"raydium_launchpad",
"create_platform_vesting_account",
crate::ENTRY_KIND_INSTRUCTION,
),
Some("vesting".to_string())
);
assert_eq!(
super::infer_event_family_for_entry(
"raydium_launchpad",
"remove_platform_curve_param",
crate::ENTRY_KIND_INSTRUCTION,
),
Some("admin_config".to_string())
);
assert_eq!(
super::infer_event_family_for_entry(
"raydium_launchpad",
"cpi_event",
crate::ENTRY_KIND_INSTRUCTION,
),
Some("cpi_transport".to_string())
);
assert_eq!(
super::infer_expected_db_target_for_entry(
"raydium_launchpad",
"buy_exact_in",
Some("swap"),
crate::ENTRY_KIND_INSTRUCTION,
),
Some(crate::DexEventCoverageEntryDto::DB_TARGET_LAUNCH_EVENTS.to_string())
);
} }
#[tokio::test] #[tokio::test]
@@ -716,6 +1101,24 @@ mod tests {
== Some(crate::DexEventCoverageEntryDto::DB_TARGET_LIQUIDITY_EVENTS.to_string()) == Some(crate::DexEventCoverageEntryDto::DB_TARGET_LIQUIDITY_EVENTS.to_string())
&& row.local_event_kind == Some("raydium_cpmm.lp_change_event".to_string()) && row.local_event_kind == Some("raydium_cpmm.lp_change_event".to_string())
})); }));
assert!(rows.iter().any(|row| return {
row.entry_name == "cpi_event"
&& row.event_family == Some("cpi_transport".to_string())
&& row.expected_db_target
== Some(
crate::DexEventCoverageEntryDto::DB_TARGET_DECODED_EVENTS_ONLY.to_string(),
)
&& row.local_event_kind == Some("raydium_cpmm.cpi_event".to_string())
}));
assert!(rows.iter().any(|row| return {
row.entry_name == "anchor_idl_instruction"
&& row.event_family == Some("idl_management".to_string())
&& row.expected_db_target
== Some(
crate::DexEventCoverageEntryDto::DB_TARGET_DECODED_EVENTS_ONLY.to_string(),
)
&& row.local_event_kind == Some("raydium_cpmm.anchor_idl_instruction".to_string())
}));
assert!(rows.iter().any(|row| return { assert!(rows.iter().any(|row| return {
row.entry_name == "swap_event" row.entry_name == "swap_event"
&& row.event_family == Some("swap".to_string()) && row.event_family == Some("swap".to_string())

View File

@@ -248,25 +248,25 @@ const DEX_SUPPORT_MATRIX_ENTRIES: &[DexSupportMatrixEntry] = &[
catalog_enabled: true, catalog_enabled: true,
}, },
DexSupportMatrixEntry { DexSupportMatrixEntry {
code: "raydium_launchlab", code: "raydium_launchpad",
display_name: "Raydium LaunchLab / Launchpad", display_name: "Raydium LaunchLab / Launchpad",
family: "raydium", family: "raydium",
version: "launchlab", version: "launchpad",
surface_type: "launch", surface_type: "launch",
surface_role: "launch_surface", surface_role: "launch_surface",
program_id: Some(crate::RAYDIUM_LAUNCHLAB_PROGRAM_ID), program_id: Some(crate::RAYDIUM_LAUNCHPAD_PROGRAM_ID),
router_program_id: None, router_program_id: None,
program_id_status: "known", program_id_status: "known",
observed: false, observed: false,
decoded: false, decoded: true,
materialized: false, materialized: false,
trade_candidate: false, trade_candidate: false,
candle_candidate: false, candle_candidate: false,
pair_candidate: true, pair_candidate: true,
pool_candidate: true, pool_candidate: true,
status: "planned", status: "bootstrap",
confidence: "medium", confidence: "medium",
skip_reason: Some("decoder_and_materialization_not_enabled"), skip_reason: Some("decoded_events_only_until_local_corpus"),
catalog_enabled: false, catalog_enabled: false,
}, },
DexSupportMatrixEntry { DexSupportMatrixEntry {
@@ -2736,7 +2736,7 @@ mod tests {
"raydium_cpmm", "raydium_cpmm",
"raydium_clmm", "raydium_clmm",
"raydium_amm_v4", "raydium_amm_v4",
"raydium_launchlab", "raydium_launchpad",
"raydium_liquidity_locking", "raydium_liquidity_locking",
"meteora_dlmm", "meteora_dlmm",
"meteora_dlc", "meteora_dlc",
@@ -2832,11 +2832,25 @@ mod tests {
assert_eq!(entry.skip_reason, Some("meteora_damm_v1_swap_without_amount_payload")); assert_eq!(entry.skip_reason, Some("meteora_damm_v1_swap_without_amount_payload"));
} }
#[test]
fn matrix_marks_raydium_launchpad_bootstrap_conservatively() {
let entry = match crate::dex_support_matrix_entry_by_code("raydium_launchpad") {
Some(entry) => entry,
None => panic!("expected raydium_launchpad matrix entry"),
};
assert_eq!(entry.status, "bootstrap");
assert!(entry.decoded);
assert!(!entry.materialized);
assert!(!entry.trade_candidate);
assert!(!entry.candle_candidate);
assert_eq!(entry.skip_reason, Some("decoded_events_only_until_local_corpus"));
}
#[test] #[test]
fn matrix_marks_launch_surfaces_as_launch_or_bonding_curve() { fn matrix_marks_launch_surfaces_as_launch_or_bonding_curve() {
let codes = [ let codes = [
"pump_fun", "pump_fun",
"raydium_launchlab", "raydium_launchpad",
"letsbonk", "letsbonk",
"bonk_fun", "bonk_fun",
"bags", "bags",
@@ -2863,15 +2877,7 @@ mod tests {
#[test] #[test]
fn matrix_keeps_0_7_39_deferred_surfaces_non_trade_materialized() { fn matrix_keeps_0_7_39_deferred_surfaces_non_trade_materialized() {
let codes = [ let codes = [
"raydium_launchlab", "letsbonk", "bonk_fun", "bags", "moonshot", "moonit", "boop_fun", "believe", "heaven",
"letsbonk",
"bonk_fun",
"bags",
"moonshot",
"moonit",
"boop_fun",
"believe",
"heaven",
]; ];
for code in codes { for code in codes {
let entry = match crate::dex_support_matrix_entry_by_code(code) { let entry = match crate::dex_support_matrix_entry_by_code(code) {

View File

@@ -399,6 +399,20 @@ fn resolve_instruction_name(
}; };
return Some(name.to_string()); return Some(name.to_string());
} }
if program_id == crate::RAYDIUM_LAUNCHPAD_PROGRAM_ID
|| decoder_code == Some("raydium_launchpad")
{
if discriminator_hex == "e445a52e51cb9a1d" {
return Some("raydium_launchpad.anchor_self_cpi_log".to_string());
}
let layout = crate::dex::raydium_launchpad::account_layout(discriminator_hex, usize::MAX);
let layout = match layout {
Some(layout) => layout,
None => return None,
};
return Some(format!("raydium_launchpad.{}", layout.instruction_name));
}
return None; return None;
} }

View File

@@ -12,7 +12,7 @@ struct BuiltinLaunchSurfaceSpec {
const BUILTIN_LAUNCH_SURFACE_SPECS: &[BuiltinLaunchSurfaceSpec] = &[ const BUILTIN_LAUNCH_SURFACE_SPECS: &[BuiltinLaunchSurfaceSpec] = &[
BuiltinLaunchSurfaceSpec { BuiltinLaunchSurfaceSpec {
code: "raydium_launchlab", code: "raydium_launchpad",
name: "Raydium LaunchLab / Launchpad", name: "Raydium LaunchLab / Launchpad",
protocol_family: "raydium", protocol_family: "raydium",
enabled: true, enabled: true,
@@ -984,7 +984,7 @@ mod tests {
}; };
assert_eq!(surface_ids.len(), 9); assert_eq!(surface_ids.len(), 9);
let required_codes = [ let required_codes = [
"raydium_launchlab", "raydium_launchpad",
"letsbonk", "letsbonk",
"bonk_fun", "bonk_fun",
"bags", "bags",
@@ -1018,7 +1018,7 @@ mod tests {
let service = crate::LaunchOriginService::new(database.clone()); let service = crate::LaunchOriginService::new(database.clone());
let register_result = service let register_result = service
.register_launch_surface_mapping( .register_launch_surface_mapping(
"raydium_launchlab", "raydium_launchpad",
Some("DbcDetectTokenA111"), Some("DbcDetectTokenA111"),
Some("DbcDetectConfig111"), Some("DbcDetectConfig111"),
None, None,
@@ -1026,23 +1026,23 @@ mod tests {
) )
.await; .await;
if let Err(error) = register_result { if let Err(error) = register_result {
panic!("launchlab mapping registration must succeed: {}", error); panic!("launchpad mapping registration must succeed: {}", error);
} }
seed_decoded_meteora_dbc_event(database.clone(), "sig-launch-origin-launchlab-1").await; seed_decoded_meteora_dbc_event(database.clone(), "sig-launch-origin-launchpad-1").await;
let result = service let result = service
.attribute_transaction_by_signature("sig-launch-origin-launchlab-1") .attribute_transaction_by_signature("sig-launch-origin-launchpad-1")
.await; .await;
let results = match result { let results = match result {
Ok(results) => results, Ok(results) => results,
Err(error) => panic!("launchlab attribution must succeed: {}", error), Err(error) => panic!("launchpad attribution must succeed: {}", error),
}; };
assert_eq!(results.len(), 1); assert_eq!(results.len(), 1);
assert!(results[0].created_attribution); assert!(results[0].created_attribution);
let surface_result = let surface_result =
crate::query_launch_surfaces_get_by_code(database.as_ref(), "raydium_launchlab").await; crate::query_launch_surfaces_get_by_code(database.as_ref(), "raydium_launchpad").await;
let surface = match surface_result { let surface = match surface_result {
Ok(Some(surface)) => surface, Ok(Some(surface)) => surface,
Ok(None) => panic!("raydium_launchlab surface must exist"), Ok(None) => panic!("raydium_launchpad surface must exist"),
Err(error) => panic!("surface fetch must succeed: {}", error), Err(error) => panic!("surface fetch must succeed: {}", error),
}; };
assert_eq!(surface.id, Some(results[0].launch_surface_id)); assert_eq!(surface.id, Some(results[0].launch_surface_id));

View File

@@ -208,7 +208,7 @@ pub use constants::ED25519_PROGRAM_ID;
/// Feature program identifier. ("Feature111111111111111111111111111111111111"). /// Feature program identifier. ("Feature111111111111111111111111111111111111").
/// @see solana_sdk::pubkey::Pubkey = solana_sdk_ids::feature::ID /// @see solana_sdk::pubkey::Pubkey = solana_sdk_ids::feature::ID
pub use constants::FEATURE_PROGRAM_ID; pub use constants::FEATURE_PROGRAM_ID;
/// FluxBeam program id. ("FLUXubRmkEi2q6K3Y9kBPg9248ggaZVsoSFhtJHSrm1X"). /// Moonshot token authority account observed on Solscan program id. ("FLUXubRmkEi2q6K3Y9kBPg9248ggaZVsoSFhtJHSrm1X").
pub use constants::FLUXBEAM_PROGRAM_ID; pub use constants::FLUXBEAM_PROGRAM_ID;
/// FusionAMM program id from Vybe supported DEX/AMM documentation. /// FusionAMM program id from Vybe supported DEX/AMM documentation.
pub use constants::FUSIONAMM_PROGRAM_ID; pub use constants::FUSIONAMM_PROGRAM_ID;
@@ -278,10 +278,12 @@ pub use constants::METEORA_DAMM_V2_PROGRAM_ID;
pub use constants::METEORA_DBC_PROGRAM_ID; pub use constants::METEORA_DBC_PROGRAM_ID;
/// Meteora DLMM program id. ("LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo"). /// Meteora DLMM program id. ("LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo").
pub use constants::METEORA_DLMM_PROGRAM_ID; pub use constants::METEORA_DLMM_PROGRAM_ID;
/// Meteora Vault program id extracted from upstream Git decoder source. /// Meteora Vault program id. ("MoonCVVNZFSYkqNXP6bxHLPL6QQJiMagDL3qcqUQTrG").
pub use constants::METEORA_VAULT_PROGRAM_ID; pub use constants::METEORA_VAULT_PROGRAM_ID;
/// Moonshot program id extracted from upstream Git decoder source. /// Moonshot program id extracted from upstream Git decoder source.
pub use constants::MOONSHOT_PROGRAM_ID; pub use constants::MOONSHOT_PROGRAM_ID;
/// FluxBeam program id. ("7rtiKSUDLBm59b1SBmD9oajcP8xE64vAGSMbAN5CXy1q").
pub use constants::MOONSHOT_TOKEN_AUTHORITY_ID;
/// MPL Core program id extracted from upstream Git decoder source. /// MPL Core program id extracted from upstream Git decoder source.
pub use constants::MPL_CORE_PROGRAM_ID; pub use constants::MPL_CORE_PROGRAM_ID;
/// MPL Token Metadata program id extracted from upstream Git decoder source. /// MPL Token Metadata program id extracted from upstream Git decoder source.
@@ -325,8 +327,10 @@ pub use constants::RAYDIUM_AMM_V4_PROGRAM_ID;
pub use constants::RAYDIUM_CLMM_PROGRAM_ID; pub use constants::RAYDIUM_CLMM_PROGRAM_ID;
/// Raydium CPMM mainnet program id. ("CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C"). /// Raydium CPMM mainnet program id. ("CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C").
pub use constants::RAYDIUM_CPMM_PROGRAM_ID; pub use constants::RAYDIUM_CPMM_PROGRAM_ID;
/// Raydium LaunchLab platform config account observed on Solscan. ("4Bu96XjU84XjPDSpveTVf6LYGCkfW5FK7SNkREWcEfV4").
pub use constants::RAYDIUM_LAUNCHPAD_PLATFORM_CONFIG_ACCOUNT_ID;
/// Raydium LaunchLab / Launchpad program id. ("LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj"). /// Raydium LaunchLab / Launchpad program id. ("LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj").
pub use constants::RAYDIUM_LAUNCHLAB_PROGRAM_ID; pub use constants::RAYDIUM_LAUNCHPAD_PROGRAM_ID;
/// Raydium Liquidity Locking program id extracted from upstream Git decoder source. /// Raydium Liquidity Locking program id extracted from upstream Git decoder source.
pub use constants::RAYDIUM_LIQUIDITY_LOCKING_PROGRAM_ID; pub use constants::RAYDIUM_LIQUIDITY_LOCKING_PROGRAM_ID;
/// Raydium Stable Swap AMM program id, deprecated. ("5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h"). /// Raydium Stable Swap AMM program id, deprecated. ("5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h").
@@ -345,6 +349,8 @@ pub use constants::SHARKY_PROGRAM_ID;
pub use constants::SOLAYER_RESTAKING_PROGRAM_ID; pub use constants::SOLAYER_RESTAKING_PROGRAM_ID;
/// SolFi v2 program id from Vybe supported DEX/AMM documentation. /// SolFi v2 program id from Vybe supported DEX/AMM documentation.
pub use constants::SOLFI_V2_PROGRAM_ID; pub use constants::SOLFI_V2_PROGRAM_ID;
/// Manual Solscan account-source inventory collected for post-`0.7.50` DEX discovery.
pub use constants::SOLSCAN_ACCOUNT_SOURCES;
/// SPL Token-2022 program identifier. ("TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb"). /// SPL Token-2022 program identifier. ("TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb").
/// @see solana_sdk::pubkey::Pubkey = spl_token_2022_interface::ID /// @see solana_sdk::pubkey::Pubkey = spl_token_2022_interface::ID
pub use constants::SPL_TOKEN_2022_PROGRAM_ID; pub use constants::SPL_TOKEN_2022_PROGRAM_ID;
@@ -405,6 +411,8 @@ pub use constants::SYSVAR_SLOT_HISTORY_PROGRAM_ID;
/// Sysvar Stake History program identifier. ("SysvarStakeHistory1111111111111111111111111"). /// Sysvar Stake History program identifier. ("SysvarStakeHistory1111111111111111111111111").
/// @see solana_sdk::pubkey::Pubkey = solana_sdk_ids::sysvar::stake_history::ID /// @see solana_sdk::pubkey::Pubkey = solana_sdk_ids::sysvar::stake_history::ID
pub use constants::SYSVAR_STAKE_HISTORY_PROGRAM_ID; pub use constants::SYSVAR_STAKE_HISTORY_PROGRAM_ID;
/// One Solscan account source collected during manual DEX/program inventory.
pub use constants::SolscanAccountSource;
/// Canonical Solana USDC mint identifier. /// Canonical Solana USDC mint identifier.
pub use constants::USDC_MINT_ID; pub use constants::USDC_MINT_ID;
/// Canonical Solana USDT mint identifier. /// Canonical Solana USDT mint identifier.
@@ -664,6 +672,10 @@ pub use db::SwapDto;
pub use db::SwapEntity; pub use db::SwapEntity;
/// Swap side relative to the normalized base token of the pair. /// Swap side relative to the normalized base token of the pair.
pub use db::SwapTradeSide; pub use db::SwapTradeSide;
/// Application-facing normalized token-account event DTO.
pub use db::TokenAccountEventDto;
/// Persisted normalized token-account event row.
pub use db::TokenAccountEventEntity;
/// Application-facing normalized token burn event DTO. /// Application-facing normalized token burn event DTO.
pub use db::TokenBurnEventDto; pub use db::TokenBurnEventDto;
/// Persisted normalized token burn event row. /// Persisted normalized token burn event row.
@@ -746,7 +758,10 @@ pub use db::query_dex_decoded_events_delete_locally_covered_upstream_instruction
pub use db::query_dex_decoded_events_delete_meteora_dlmm_anchor_swap_instruction_audits; pub use db::query_dex_decoded_events_delete_meteora_dlmm_anchor_swap_instruction_audits;
/// Deletes decoded DEX instruction audit rows related to one decoded instruction. /// Deletes decoded DEX instruction audit rows related to one decoded instruction.
pub use db::query_dex_decoded_events_delete_related_instruction_audit; pub use db::query_dex_decoded_events_delete_related_instruction_audit;
/// Deletes Raydium CLMM instruction-audit rows for locally mapped CLMM instructions.
pub use db::query_dex_decoded_events_delete_replaced_raydium_clmm_instruction_audits; pub use db::query_dex_decoded_events_delete_replaced_raydium_clmm_instruction_audits;
/// Deletes Raydium CPMM instruction-audit rows already covered by local named rows.
pub use db::query_dex_decoded_events_delete_replaced_raydium_cpmm_instruction_audits;
/// Reads one decoded DEX event by its natural key. /// Reads one decoded DEX event by its natural key.
pub use db::query_dex_decoded_events_get_by_key; pub use db::query_dex_decoded_events_get_by_key;
/// Returns the latest Pump.fun create payload associated with a token mint. /// Returns the latest Pump.fun create payload associated with a token mint.
@@ -960,6 +975,8 @@ pub use db::query_reward_events_upsert;
pub use db::query_swaps_list_recent; pub use db::query_swaps_list_recent;
/// Inserts or updates one normalized swap row. /// Inserts or updates one normalized swap row.
pub use db::query_swaps_upsert; pub use db::query_swaps_upsert;
/// Inserts or updates one normalized token-account event row.
pub use db::query_token_account_events_upsert;
/// Lists recent token burn events ordered from newest to oldest. /// Lists recent token burn events ordered from newest to oldest.
pub use db::query_token_burn_events_list_recent; pub use db::query_token_burn_events_list_recent;
/// Inserts or updates one normalized token burn event row. /// Inserts or updates one normalized token burn event row.
@@ -1247,6 +1264,12 @@ pub use dex_event_classification::is_dex_position_close_event_kind;
pub use dex_event_classification::is_dex_position_open_event_kind; pub use dex_event_classification::is_dex_position_open_event_kind;
/// Returns true for reward or emission DEX events. /// Returns true for reward or emission DEX events.
pub use dex_event_classification::is_dex_reward_event_kind; pub use dex_event_classification::is_dex_reward_event_kind;
/// Returns true for token-account close events detected by DEX decoders.
pub use dex_event_classification::is_dex_token_account_close_event_kind;
/// Returns true for token-account creation events detected by DEX decoders.
pub use dex_event_classification::is_dex_token_account_create_event_kind;
/// Returns true for token-account lifecycle events detected by DEX decoders.
pub use dex_event_classification::is_dex_token_account_event_kind;
/// Returns true for token burn DEX events. /// Returns true for token burn DEX events.
pub use dex_event_classification::is_dex_token_burn_event_kind; pub use dex_event_classification::is_dex_token_burn_event_kind;
/// Returns true for token mint DEX events. /// Returns true for token mint DEX events.

View File

@@ -100,6 +100,8 @@ pub struct LocalPipelineReplayResult {
pub pool_admin_event_count: usize, pub pool_admin_event_count: usize,
/// Total orderbook event materialization results returned by replayed non-trade calls. /// Total orderbook event materialization results returned by replayed non-trade calls.
pub orderbook_event_count: usize, pub orderbook_event_count: usize,
/// Total token-account event materialization results returned by replayed non-trade calls.
pub token_account_event_count: usize,
/// Total candle upsert results returned by replayed candle calls. /// Total candle upsert results returned by replayed candle calls.
/// ///
/// This is a replay write/result counter, not the number of distinct rows /// This is a replay write/result counter, not the number of distinct rows
@@ -367,6 +369,7 @@ impl LocalPipelineReplayService {
result.reward_event_count += non_trade_result.reward_event_count; result.reward_event_count += non_trade_result.reward_event_count;
result.pool_admin_event_count += non_trade_result.pool_admin_event_count; result.pool_admin_event_count += non_trade_result.pool_admin_event_count;
result.orderbook_event_count += non_trade_result.orderbook_event_count; result.orderbook_event_count += non_trade_result.orderbook_event_count;
result.token_account_event_count += non_trade_result.token_account_event_count;
}, },
Err(error) => { Err(error) => {
result.non_trade_materialization_error_count += 1; result.non_trade_materialization_error_count += 1;
@@ -521,6 +524,29 @@ impl LocalPipelineReplayService {
} }
async fn refresh_event_coverage_best_effort(&self) { async fn refresh_event_coverage_best_effort(&self) {
let cpmm_cleanup_result =
crate::query_dex_decoded_events_delete_replaced_raydium_cpmm_instruction_audits(
self.database.as_ref(),
None,
)
.await;
match cpmm_cleanup_result {
Ok(deleted_count) => {
if deleted_count > 0 {
tracing::info!(
deleted_count = deleted_count,
"replaced Raydium CPMM instruction audits cleaned before dex event coverage refresh"
);
}
},
Err(error) => {
tracing::warn!(
error = %error,
"Raydium CPMM replaced instruction-audit cleanup failed before dex event coverage refresh"
);
},
}
let cleanup_result = let cleanup_result =
crate::query_dex_decoded_events_delete_replaced_raydium_clmm_instruction_audits( crate::query_dex_decoded_events_delete_replaced_raydium_clmm_instruction_audits(
self.database.as_ref(), self.database.as_ref(),
@@ -586,6 +612,46 @@ impl LocalPipelineReplayService {
}, },
} }
let post_refresh_cpmm_cleanup_result =
crate::query_dex_decoded_events_delete_replaced_raydium_cpmm_instruction_audits(
self.database.as_ref(),
None,
)
.await;
match post_refresh_cpmm_cleanup_result {
Ok(deleted_count) => {
if deleted_count > 0 {
tracing::info!(
deleted_count = deleted_count,
"replaced Raydium CPMM instruction audits cleaned after dex event coverage refresh"
);
let second_refresh_result = coverage_service.refresh_local_counts(None).await;
match second_refresh_result {
Ok(second_refresh_result) => {
tracing::debug!(
upserted_entry_count = second_refresh_result.upserted_entry_count,
refreshed_entry_count = second_refresh_result.refreshed_entry_count,
summary_count = second_refresh_result.summaries.len(),
"dex event coverage refreshed after Raydium CPMM instruction-audit cleanup"
);
},
Err(error) => {
tracing::warn!(
error = %error,
"dex event coverage refresh failed after Raydium CPMM instruction-audit cleanup"
);
},
}
}
},
Err(error) => {
tracing::warn!(
error = %error,
"Raydium CPMM replaced instruction-audit cleanup failed after dex event coverage refresh"
);
},
}
let post_refresh_upstream_cleanup_result = let post_refresh_upstream_cleanup_result =
crate::query_dex_decoded_events_delete_locally_covered_upstream_instruction_matches( crate::query_dex_decoded_events_delete_locally_covered_upstream_instruction_matches(
self.database.as_ref(), self.database.as_ref(),

File diff suppressed because it is too large Load Diff

View File

@@ -115,6 +115,44 @@ pub(crate) async fn resolve_trade_amounts(
return Err(error); return Err(error);
} }
} }
let has_payload_trade_side = crate::trade_amount_resolution::extract_string_by_candidate_keys(
input.payload,
&["tradeSide", "trade_side"],
)
.is_some();
if input.decoded_event.event_kind == "raydium_launchpad.trade_event"
&& (base_amount_raw.is_none()
|| quote_amount_raw.is_none()
|| (!has_payload_trade_side && resolved_trade_side.is_none()))
{
let resolution_result =
crate::trade_amount_resolution::apply_raydium_launchpad_sibling_instruction_amount_fallback(
input,
&mut base_amount_raw,
&mut quote_amount_raw,
&mut resolved_trade_side,
)
.await;
if let Err(error) = resolution_result {
return Err(error);
}
}
if input.decoded_event.event_kind.starts_with("raydium_launchpad.")
&& (base_amount_raw.is_none()
|| quote_amount_raw.is_none()
|| price_quote_per_base.is_none())
{
let resolution_result =
crate::trade_amount_resolution::apply_raydium_launchpad_amount_fallback(
input,
&mut base_amount_raw,
&mut quote_amount_raw,
&mut price_quote_per_base,
);
if let Err(error) = resolution_result {
return Err(error);
}
}
if input.decoded_event.event_kind.starts_with("raydium_amm_v4.") if input.decoded_event.event_kind.starts_with("raydium_amm_v4.")
&& (base_amount_raw.is_none() || quote_amount_raw.is_none()) && (base_amount_raw.is_none() || quote_amount_raw.is_none())
{ {
@@ -504,6 +542,223 @@ async fn apply_pump_swap_amount_fallbacks(
return Ok(()); return Ok(());
} }
fn apply_raydium_launchpad_amount_fallback(
input: &crate::trade_amount_resolution::TradeAmountResolutionInput<'_>,
base_amount_raw: &mut std::option::Option<std::string::String>,
quote_amount_raw: &mut std::option::Option<std::string::String>,
price_quote_per_base: &mut std::option::Option<f64>,
) -> Result<(), crate::Error> {
if base_amount_raw.is_some() && quote_amount_raw.is_some() && price_quote_per_base.is_some() {
return Ok(());
}
let transaction_value_result =
crate::trade_pump_swap_amounts::build_transaction_value_with_meta_json(
input.transaction.transaction_json.as_str(),
input.transaction.meta_json.as_deref(),
);
let transaction_value = match transaction_value_result {
Ok(transaction_value) => transaction_value,
Err(error) => return Err(error),
};
let fallback_amounts = match (input.base_token_mint, input.quote_token_mint) {
(Some(base_mint), Some(quote_mint)) => {
crate::trade_pump_swap_amounts::try_build_pump_swap_trade_amounts_from_token_balance_deltas(
&transaction_value,
base_mint,
quote_mint,
)
},
_ => None,
};
let fallback_amounts = match fallback_amounts {
Some(fallback_amounts) => fallback_amounts,
None => return Ok(()),
};
if base_amount_raw.is_none() {
*base_amount_raw = crate::trade_pump_swap_amounts::convert_ui_amount_to_raw_string(
fallback_amounts.base_amount,
input.base_token_decimals,
);
}
if quote_amount_raw.is_none() {
*quote_amount_raw = crate::trade_pump_swap_amounts::convert_ui_amount_to_raw_string(
fallback_amounts.quote_amount,
input.quote_token_decimals,
);
}
if price_quote_per_base.is_none() {
*price_quote_per_base = Some(fallback_amounts.price_quote_per_base);
}
tracing::debug!(
event_kind = %input.decoded_event.event_kind,
pool_account = ?input.decoded_event.pool_account,
decoded_event_id = ?input.decoded_event.id,
base_mint = ?input.base_token_mint,
quote_mint = ?input.quote_token_mint,
base_amount_raw = ?base_amount_raw,
quote_amount_raw = ?quote_amount_raw,
price_quote_per_base = ?price_quote_per_base,
"raydium_launchpad trade amounts recovered from transaction token balance deltas"
);
return Ok(());
}
async fn apply_raydium_launchpad_sibling_instruction_amount_fallback(
input: &crate::trade_amount_resolution::TradeAmountResolutionInput<'_>,
base_amount_raw: &mut std::option::Option<std::string::String>,
quote_amount_raw: &mut std::option::Option<std::string::String>,
resolved_trade_side: &mut std::option::Option<crate::SwapTradeSide>,
) -> Result<(), crate::Error> {
if base_amount_raw.is_some() && quote_amount_raw.is_some() && resolved_trade_side.is_some() {
return Ok(());
}
let amount_in_raw = crate::trade_amount_resolution::extract_amount_string(
input.payload,
&["amountInRaw", "amount_in_raw", "amountIn", "amount_in"],
);
let amount_out_raw = crate::trade_amount_resolution::extract_amount_string(
input.payload,
&["amountOutRaw", "amount_out_raw", "amountOut", "amount_out"],
);
let amount_in_raw = match amount_in_raw {
Some(amount_in_raw) => amount_in_raw,
None => return Ok(()),
};
let amount_out_raw = match amount_out_raw {
Some(amount_out_raw) => amount_out_raw,
None => return Ok(()),
};
let sibling_side_result =
crate::trade_amount_resolution::resolve_raydium_launchpad_sibling_instruction_side(input)
.await;
let sibling_side = match sibling_side_result {
Ok(sibling_side) => sibling_side,
Err(error) => return Err(error),
};
let sibling_side = match sibling_side {
Some(sibling_side) => sibling_side,
None => return Ok(()),
};
crate::trade_amount_resolution::apply_raydium_launchpad_side_amount_mapping(
sibling_side,
amount_in_raw.as_str(),
amount_out_raw.as_str(),
base_amount_raw,
quote_amount_raw,
resolved_trade_side,
);
tracing::debug!(
event_kind = %input.decoded_event.event_kind,
pool_account = ?input.decoded_event.pool_account,
decoded_event_id = ?input.decoded_event.id,
transaction_signature = %input.transaction.signature,
base_amount_raw = ?base_amount_raw,
quote_amount_raw = ?quote_amount_raw,
resolved_trade_side = ?resolved_trade_side,
"raydium_launchpad trade amounts recovered from sibling swap instruction"
);
return Ok(());
}
async fn resolve_raydium_launchpad_sibling_instruction_side(
input: &crate::trade_amount_resolution::TradeAmountResolutionInput<'_>,
) -> Result<std::option::Option<crate::SwapTradeSide>, crate::Error> {
let decoded_events_result = crate::query_dex_decoded_events_list_by_transaction_id(
input.database,
input.decoded_event.transaction_id,
)
.await;
let decoded_events = match decoded_events_result {
Ok(decoded_events) => decoded_events,
Err(error) => return Err(error),
};
let mut resolved_side = None;
for decoded_event in decoded_events {
if decoded_event.id == input.decoded_event.id {
continue;
}
if decoded_event.protocol_name != "raydium_launchpad" {
continue;
}
if decoded_event.pool_account.as_deref() != Some(input.pool_address) {
continue;
}
let side = crate::trade_amount_resolution::raydium_launchpad_instruction_side(
decoded_event.event_kind.as_str(),
);
let side = match side {
Some(side) => side,
None => continue,
};
match resolved_side {
Some(existing_side) => {
if existing_side != side {
tracing::debug!(
transaction_signature = %input.transaction.signature,
pool_account = %input.pool_address,
decoded_event_id = ?input.decoded_event.id,
existing_side = ?existing_side,
conflicting_side = ?side,
"raydium_launchpad sibling swap instruction side is ambiguous"
);
return Ok(None);
}
},
None => resolved_side = Some(side),
}
}
return Ok(resolved_side);
}
fn raydium_launchpad_instruction_side(
event_kind: &str,
) -> std::option::Option<crate::SwapTradeSide> {
match event_kind {
"raydium_launchpad.buy_exact_in" | "raydium_launchpad.buy_exact_out" => {
return Some(crate::SwapTradeSide::BuyBase);
},
"raydium_launchpad.sell_exact_in" | "raydium_launchpad.sell_exact_out" => {
return Some(crate::SwapTradeSide::SellBase);
},
_ => return None,
}
}
fn apply_raydium_launchpad_side_amount_mapping(
side: crate::SwapTradeSide,
amount_in_raw: &str,
amount_out_raw: &str,
base_amount_raw: &mut std::option::Option<std::string::String>,
quote_amount_raw: &mut std::option::Option<std::string::String>,
resolved_trade_side: &mut std::option::Option<crate::SwapTradeSide>,
) {
match side {
crate::SwapTradeSide::BuyBase => {
if base_amount_raw.is_none() {
*base_amount_raw = Some(amount_out_raw.to_string());
}
if quote_amount_raw.is_none() {
*quote_amount_raw = Some(amount_in_raw.to_string());
}
if resolved_trade_side.is_none() {
*resolved_trade_side = Some(crate::SwapTradeSide::BuyBase);
}
},
crate::SwapTradeSide::SellBase => {
if base_amount_raw.is_none() {
*base_amount_raw = Some(amount_in_raw.to_string());
}
if quote_amount_raw.is_none() {
*quote_amount_raw = Some(amount_out_raw.to_string());
}
if resolved_trade_side.is_none() {
*resolved_trade_side = Some(crate::SwapTradeSide::SellBase);
}
},
crate::SwapTradeSide::Unknown => {},
}
}
fn apply_pump_fun_amount_fallback( fn apply_pump_fun_amount_fallback(
input: &crate::trade_amount_resolution::TradeAmountResolutionInput<'_>, input: &crate::trade_amount_resolution::TradeAmountResolutionInput<'_>,
base_amount_raw: &mut std::option::Option<std::string::String>, base_amount_raw: &mut std::option::Option<std::string::String>,
@@ -1676,6 +1931,66 @@ mod tests {
assert_eq!(side, Some(crate::SwapTradeSide::SellBase)); assert_eq!(side, Some(crate::SwapTradeSide::SellBase));
} }
#[test]
fn raydium_launchpad_buy_instruction_maps_amount_in_out_to_base_quote() {
let mut base_amount_raw = None;
let mut quote_amount_raw = None;
let mut resolved_trade_side = None;
super::apply_raydium_launchpad_side_amount_mapping(
crate::SwapTradeSide::BuyBase,
"15000",
"262584872",
&mut base_amount_raw,
&mut quote_amount_raw,
&mut resolved_trade_side,
);
assert_eq!(base_amount_raw, Some("262584872".to_string()));
assert_eq!(quote_amount_raw, Some("15000".to_string()));
assert_eq!(resolved_trade_side, Some(crate::SwapTradeSide::BuyBase));
}
#[test]
fn raydium_launchpad_sell_instruction_maps_amount_in_out_to_base_quote() {
let mut base_amount_raw = None;
let mut quote_amount_raw = None;
let mut resolved_trade_side = None;
super::apply_raydium_launchpad_side_amount_mapping(
crate::SwapTradeSide::SellBase,
"11093407717995",
"43968050",
&mut base_amount_raw,
&mut quote_amount_raw,
&mut resolved_trade_side,
);
assert_eq!(base_amount_raw, Some("11093407717995".to_string()));
assert_eq!(quote_amount_raw, Some("43968050".to_string()));
assert_eq!(resolved_trade_side, Some(crate::SwapTradeSide::SellBase));
}
#[test]
fn raydium_launchpad_instruction_side_maps_exact_in_and_exact_out_variants() {
assert_eq!(
super::raydium_launchpad_instruction_side("raydium_launchpad.buy_exact_in"),
Some(crate::SwapTradeSide::BuyBase)
);
assert_eq!(
super::raydium_launchpad_instruction_side("raydium_launchpad.buy_exact_out"),
Some(crate::SwapTradeSide::BuyBase)
);
assert_eq!(
super::raydium_launchpad_instruction_side("raydium_launchpad.sell_exact_in"),
Some(crate::SwapTradeSide::SellBase)
);
assert_eq!(
super::raydium_launchpad_instruction_side("raydium_launchpad.sell_exact_out"),
Some(crate::SwapTradeSide::SellBase)
);
assert_eq!(
super::raydium_launchpad_instruction_side("raydium_launchpad.collect_fee"),
None
);
}
#[test] #[test]
fn failed_transaction_does_not_infer_trade_side() { fn failed_transaction_does_not_infer_trade_side() {
let transaction_json = transaction_json_with_vaults("base_vault", "quote_vault"); let transaction_json = transaction_json_with_vaults("base_vault", "quote_vault");

View File

@@ -13,8 +13,37 @@ const UPSTREAM_GIT_DISCRIMINATOR_NOTES: &str = "entry name and discriminator ext
const UPSTREAM_GIT_ALIAS_PROGRAM_NOTES: &str = "upstream Git decoder name kept as a discovery alias; program id and discriminator rows are represented by the canonical decoder entry to avoid duplicate registry keys"; const UPSTREAM_GIT_ALIAS_PROGRAM_NOTES: &str = "upstream Git decoder name kept as a discovery alias; program id and discriminator rows are represented by the canonical decoder entry to avoid duplicate registry keys";
const RAYDIUM_IDL_SOURCE_REPO: &str = "raydium-io/raydium-idl"; const RAYDIUM_IDL_SOURCE_REPO: &str = "raydium-io/raydium-idl";
const MANUAL_SOLSCAN_SOURCE_REPO: &str = "manual-solscan";
const RAYDIUM_IDL_DISCRIMINATOR_NOTES: &str = "entry name and discriminator extracted from Raydium official IDL snapshot; not corpus-verified; no trade/candle/materialization proof"; const RAYDIUM_IDL_DISCRIMINATOR_NOTES: &str = "entry name and discriminator extracted from Raydium official IDL snapshot; not corpus-verified; no trade/candle/materialization proof";
const MANUAL_SOLSCAN_DISCRIMINATOR_NOTES: &str = "entry name and discriminator derived from local corpus plus manual Solscan transaction-log inspection; no trade/candle/materialization proof";
const fn manual_solscan_discriminator_entry(
decoder_code: &'static str,
program_id: std::option::Option<&'static str>,
program_family: &'static str,
surface_kind: &'static str,
entry_kind: &'static str,
entry_name: &'static str,
discriminator_hex: &'static str,
discriminator_len: u16,
source_path: &'static str,
) -> crate::UpstreamRegistryEntry {
return crate::UpstreamRegistryEntry {
source_repo: Some(MANUAL_SOLSCAN_SOURCE_REPO),
source_path: Some(source_path),
decoder_code,
program_id,
program_family,
surface_kind,
entry_kind,
entry_name,
discriminator_hex: Some(discriminator_hex),
discriminator_len: Some(discriminator_len),
proof_status: crate::PROOF_STATUS_UPSTREAM_GIT_UNVERIFIED,
notes: MANUAL_SOLSCAN_DISCRIMINATOR_NOTES,
};
}
const fn raydium_idl_discriminator_entry( const fn raydium_idl_discriminator_entry(
decoder_code: &'static str, decoder_code: &'static str,
@@ -453,8 +482,8 @@ pub(crate) const UPSTREAM_REGISTRY_ENTRIES: &[crate::UpstreamRegistryEntry] = &[
"decoders/raydium-cpmm-decoder/src/lib.rs", "decoders/raydium-cpmm-decoder/src/lib.rs",
), ),
upstream_git_program_entry( upstream_git_program_entry(
"raydium_launchlab", "raydium_launchpad",
Some(crate::RAYDIUM_LAUNCHLAB_PROGRAM_ID), Some(crate::RAYDIUM_LAUNCHPAD_PROGRAM_ID),
"raydium", "raydium",
"launch", "launch",
"decoders/raydium-launchpad-decoder/src/lib.rs", "decoders/raydium-launchpad-decoder/src/lib.rs",
@@ -619,6 +648,17 @@ pub(crate) const UPSTREAM_REGISTRY_ENTRIES: &[crate::UpstreamRegistryEntry] = &[
8, 8,
"decoders/meteora-damm-v2-decoder/src/instructions/claim_reward.rs", "decoders/meteora-damm-v2-decoder/src/instructions/claim_reward.rs",
), ),
upstream_git_discriminator_entry(
"meteora_damm_v2",
Some(crate::METEORA_DAMM_V2_PROGRAM_ID),
"meteora",
"amm",
crate::ENTRY_KIND_INSTRUCTION,
"cpi_event",
"bcd8a66c1aa68eb6",
8,
"decoders/meteora-damm-v2-decoder/src/instructions/cpi_event.rs",
),
upstream_git_discriminator_entry( upstream_git_discriminator_entry(
"meteora_damm_v2", "meteora_damm_v2",
Some(crate::METEORA_DAMM_V2_PROGRAM_ID), Some(crate::METEORA_DAMM_V2_PROGRAM_ID),
@@ -663,17 +703,6 @@ pub(crate) const UPSTREAM_REGISTRY_ENTRIES: &[crate::UpstreamRegistryEntry] = &[
8, 8,
"decoders/meteora-damm-v2-decoder/src/instructions/close_token_badge.rs", "decoders/meteora-damm-v2-decoder/src/instructions/close_token_badge.rs",
), ),
upstream_git_discriminator_entry(
"meteora_damm_v2",
Some(crate::METEORA_DAMM_V2_PROGRAM_ID),
"meteora",
"amm",
crate::ENTRY_KIND_INSTRUCTION,
"cpi_event",
"bcd8a66c1aa68eb6",
8,
"decoders/meteora-damm-v2-decoder/src/instructions/cpi_event.rs",
),
upstream_git_discriminator_entry( upstream_git_discriminator_entry(
"meteora_damm_v2", "meteora_damm_v2",
Some(crate::METEORA_DAMM_V2_PROGRAM_ID), Some(crate::METEORA_DAMM_V2_PROGRAM_ID),
@@ -1961,17 +1990,6 @@ pub(crate) const UPSTREAM_REGISTRY_ENTRIES: &[crate::UpstreamRegistryEntry] = &[
8, 8,
"decoders/dflow-aggregator-v4-decoder/src/instructions/close_order.rs", "decoders/dflow-aggregator-v4-decoder/src/instructions/close_order.rs",
), ),
upstream_git_discriminator_entry(
"dflow_aggregator_v4",
Some(crate::DFLOW_AGGREGATOR_V4_PROGRAM_ID),
"dflow",
"aggregator",
crate::ENTRY_KIND_INSTRUCTION,
"cpi_event",
"e445a52e51cb9a1d",
8,
"decoders/dflow-aggregator-v4-decoder/src/instructions/cpi_event.rs",
),
upstream_git_discriminator_entry( upstream_git_discriminator_entry(
"dflow_aggregator_v4", "dflow_aggregator_v4",
Some(crate::DFLOW_AGGREGATOR_V4_PROGRAM_ID), Some(crate::DFLOW_AGGREGATOR_V4_PROGRAM_ID),
@@ -5030,17 +5048,6 @@ pub(crate) const UPSTREAM_REGISTRY_ENTRIES: &[crate::UpstreamRegistryEntry] = &[
8, 8,
"decoders/jupiter-lend-decoder/src/instructions/collect_revenue.rs", "decoders/jupiter-lend-decoder/src/instructions/collect_revenue.rs",
), ),
upstream_git_discriminator_entry(
"jupiter_lend",
Some(crate::JUPITER_LEND_PROGRAM_ID),
"jupiter",
"lending",
crate::ENTRY_KIND_INSTRUCTION,
"cpi_event",
"e445a52e51cb9a1d",
8,
"decoders/jupiter-lend-decoder/src/instructions/cpi_event.rs",
),
upstream_git_discriminator_entry( upstream_git_discriminator_entry(
"jupiter_lend", "jupiter_lend",
Some(crate::JUPITER_LEND_PROGRAM_ID), Some(crate::JUPITER_LEND_PROGRAM_ID),
@@ -5503,17 +5510,6 @@ pub(crate) const UPSTREAM_REGISTRY_ENTRIES: &[crate::UpstreamRegistryEntry] = &[
8, 8,
"decoders/jupiter-swap-decoder/src/instructions/close_token.rs", "decoders/jupiter-swap-decoder/src/instructions/close_token.rs",
), ),
upstream_git_discriminator_entry(
"jupiter_swap",
Some(crate::JUPITER_SWAP_PROGRAM_ID),
"jupiter",
"aggregator",
crate::ENTRY_KIND_INSTRUCTION,
"cpi_event",
"e445a52e51cb9a1d",
8,
"decoders/jupiter-swap-decoder/src/instructions/cpi_event.rs",
),
upstream_git_discriminator_entry( upstream_git_discriminator_entry(
"jupiter_swap", "jupiter_swap",
Some(crate::JUPITER_SWAP_PROGRAM_ID), Some(crate::JUPITER_SWAP_PROGRAM_ID),
@@ -8110,17 +8106,6 @@ pub(crate) const UPSTREAM_REGISTRY_ENTRIES: &[crate::UpstreamRegistryEntry] = &[
8, 8,
"decoders/onchain-labs-dex-v2-decoder/src/instructions/claim.rs", "decoders/onchain-labs-dex-v2-decoder/src/instructions/claim.rs",
), ),
upstream_git_discriminator_entry(
"onchain_labs_dex_v2",
Some(crate::ONCHAIN_LABS_DEX_V2_PROGRAM_ID),
"onchain_labs",
"amm",
crate::ENTRY_KIND_INSTRUCTION,
"cpi_event",
"e445a52e51cb9a1d",
8,
"decoders/onchain-labs-dex-v2-decoder/src/instructions/cpi_event.rs",
),
upstream_git_discriminator_entry( upstream_git_discriminator_entry(
"onchain_labs_dex_v2", "onchain_labs_dex_v2",
Some(crate::ONCHAIN_LABS_DEX_V2_PROGRAM_ID), Some(crate::ONCHAIN_LABS_DEX_V2_PROGRAM_ID),
@@ -10123,17 +10108,6 @@ pub(crate) const UPSTREAM_REGISTRY_ENTRIES: &[crate::UpstreamRegistryEntry] = &[
8, 8,
"decoders/pump-fees-decoder/src/instructions/claim_social_fee_pda.rs", "decoders/pump-fees-decoder/src/instructions/claim_social_fee_pda.rs",
), ),
upstream_git_discriminator_entry(
"pump_fees",
Some(crate::PUMP_FEES_PROGRAM_ID),
"pump",
"fee_program",
crate::ENTRY_KIND_INSTRUCTION,
"cpi_event",
"e445a52e51cb9a1d",
8,
"decoders/pump-fees-decoder/src/instructions/cpi_event.rs",
),
upstream_git_discriminator_entry( upstream_git_discriminator_entry(
"pump_fees", "pump_fees",
Some(crate::PUMP_FEES_PROGRAM_ID), Some(crate::PUMP_FEES_PROGRAM_ID),
@@ -10574,17 +10548,6 @@ pub(crate) const UPSTREAM_REGISTRY_ENTRIES: &[crate::UpstreamRegistryEntry] = &[
8, 8,
"decoders/pump-swap-decoder/src/instructions/collect_coin_creator_fee.rs", "decoders/pump-swap-decoder/src/instructions/collect_coin_creator_fee.rs",
), ),
upstream_git_discriminator_entry(
"pump_swap",
Some(crate::PUMP_SWAP_PROGRAM_ID),
"pump",
"amm",
crate::ENTRY_KIND_INSTRUCTION,
"cpi_event",
"e445a52e51cb9a1d",
8,
"decoders/pump-swap-decoder/src/instructions/cpi_event.rs",
),
upstream_git_discriminator_entry( upstream_git_discriminator_entry(
"pump_swap", "pump_swap",
Some(crate::PUMP_SWAP_PROGRAM_ID), Some(crate::PUMP_SWAP_PROGRAM_ID),
@@ -11113,17 +11076,6 @@ pub(crate) const UPSTREAM_REGISTRY_ENTRIES: &[crate::UpstreamRegistryEntry] = &[
8, 8,
"decoders/pumpfun-decoder/src/instructions/collect_creator_fee.rs", "decoders/pumpfun-decoder/src/instructions/collect_creator_fee.rs",
), ),
upstream_git_discriminator_entry(
"pump_fun",
Some(crate::PUMP_FUN_PROGRAM_ID),
"pump",
"launch",
crate::ENTRY_KIND_INSTRUCTION,
"cpi_event",
"e445a52e51cb9a1d",
8,
"decoders/pumpfun-decoder/src/instructions/cpi_event.rs",
),
upstream_git_discriminator_entry( upstream_git_discriminator_entry(
"pump_fun", "pump_fun",
Some(crate::PUMP_FUN_PROGRAM_ID), Some(crate::PUMP_FUN_PROGRAM_ID),
@@ -11795,6 +11747,17 @@ pub(crate) const UPSTREAM_REGISTRY_ENTRIES: &[crate::UpstreamRegistryEntry] = &[
1, 1,
"decoders/raydium-amm-v4-decoder/src/instructions/withdraw_srm.rs", "decoders/raydium-amm-v4-decoder/src/instructions/withdraw_srm.rs",
), ),
upstream_git_discriminator_entry(
"raydium_clmm",
Some(crate::RAYDIUM_CLMM_PROGRAM_ID),
"raydium",
"clmm",
crate::ENTRY_KIND_INSTRUCTION,
"cpi_event",
"e445a52e51cb9a1d",
8,
"decoders/raydium-clmm-decoder/src/instructions/cpi_event.rs",
),
upstream_git_discriminator_entry( upstream_git_discriminator_entry(
"raydium_clmm", "raydium_clmm",
Some(crate::RAYDIUM_CLMM_PROGRAM_ID), Some(crate::RAYDIUM_CLMM_PROGRAM_ID),
@@ -12235,6 +12198,17 @@ pub(crate) const UPSTREAM_REGISTRY_ENTRIES: &[crate::UpstreamRegistryEntry] = &[
8, 8,
"decoders/raydium-clmm-decoder/src/instructions/update_amm_config.rs", "decoders/raydium-clmm-decoder/src/instructions/update_amm_config.rs",
), ),
upstream_git_discriminator_entry(
"raydium_clmm",
Some(crate::RAYDIUM_CLMM_PROGRAM_ID),
"raydium",
"clmm",
crate::ENTRY_KIND_INSTRUCTION,
"update_dynamic_fee_config",
"0707500802c784f0",
8,
"decoders/raydium-clmm-decoder/src/instructions/update_dynamic_fee_config.rs",
),
upstream_git_discriminator_entry( upstream_git_discriminator_entry(
"raydium_clmm", "raydium_clmm",
Some(crate::RAYDIUM_CLMM_PROGRAM_ID), Some(crate::RAYDIUM_CLMM_PROGRAM_ID),
@@ -12279,6 +12253,17 @@ pub(crate) const UPSTREAM_REGISTRY_ENTRIES: &[crate::UpstreamRegistryEntry] = &[
8, 8,
"decoders/raydium-clmm-decoder/src/instructions/update_reward_infos_event.rs", "decoders/raydium-clmm-decoder/src/instructions/update_reward_infos_event.rs",
), ),
manual_solscan_discriminator_entry(
"raydium_cpmm",
Some(crate::RAYDIUM_CPMM_PROGRAM_ID),
"raydium",
"amm",
crate::ENTRY_KIND_INSTRUCTION,
"anchor_idl_instruction",
"40f4bc78a7e9690a",
8,
"solscan/tx/Hi6MkRTkcgwBi1WpiiudGPHKLuaKXKamNgVsy6YqoQeMRnrkpGjNx75ymrY59tJ3NN1GCn6nrndz9thMmwALLcY",
),
upstream_git_discriminator_entry( upstream_git_discriminator_entry(
"raydium_cpmm", "raydium_cpmm",
Some(crate::RAYDIUM_CPMM_PROGRAM_ID), Some(crate::RAYDIUM_CPMM_PROGRAM_ID),
@@ -12323,6 +12308,17 @@ pub(crate) const UPSTREAM_REGISTRY_ENTRIES: &[crate::UpstreamRegistryEntry] = &[
8, 8,
"decoders/raydium-cpmm-decoder/src/instructions/collect_protocol_fee.rs", "decoders/raydium-cpmm-decoder/src/instructions/collect_protocol_fee.rs",
), ),
upstream_git_discriminator_entry(
"raydium_cpmm",
Some(crate::RAYDIUM_CPMM_PROGRAM_ID),
"raydium",
"amm",
crate::ENTRY_KIND_INSTRUCTION,
"cpi_event",
"e445a52e51cb9a1d",
8,
"decoders/raydium-cpmm-decoder/src/instructions/cpi_event.rs",
),
upstream_git_discriminator_entry( upstream_git_discriminator_entry(
"raydium_cpmm", "raydium_cpmm",
Some(crate::RAYDIUM_CPMM_PROGRAM_ID), Some(crate::RAYDIUM_CPMM_PROGRAM_ID),
@@ -12456,8 +12452,8 @@ pub(crate) const UPSTREAM_REGISTRY_ENTRIES: &[crate::UpstreamRegistryEntry] = &[
"decoders/raydium-cpmm-decoder/src/instructions/withdraw.rs", "decoders/raydium-cpmm-decoder/src/instructions/withdraw.rs",
), ),
upstream_git_discriminator_entry( upstream_git_discriminator_entry(
"raydium_launchlab", "raydium_launchpad",
Some(crate::RAYDIUM_LAUNCHLAB_PROGRAM_ID), Some(crate::RAYDIUM_LAUNCHPAD_PROGRAM_ID),
"raydium", "raydium",
"launch", "launch",
crate::ENTRY_KIND_INSTRUCTION, crate::ENTRY_KIND_INSTRUCTION,
@@ -12467,8 +12463,8 @@ pub(crate) const UPSTREAM_REGISTRY_ENTRIES: &[crate::UpstreamRegistryEntry] = &[
"decoders/raydium-launchpad-decoder/src/instructions/buy_exact_in.rs", "decoders/raydium-launchpad-decoder/src/instructions/buy_exact_in.rs",
), ),
upstream_git_discriminator_entry( upstream_git_discriminator_entry(
"raydium_launchlab", "raydium_launchpad",
Some(crate::RAYDIUM_LAUNCHLAB_PROGRAM_ID), Some(crate::RAYDIUM_LAUNCHPAD_PROGRAM_ID),
"raydium", "raydium",
"launch", "launch",
crate::ENTRY_KIND_INSTRUCTION, crate::ENTRY_KIND_INSTRUCTION,
@@ -12478,8 +12474,8 @@ pub(crate) const UPSTREAM_REGISTRY_ENTRIES: &[crate::UpstreamRegistryEntry] = &[
"decoders/raydium-launchpad-decoder/src/instructions/buy_exact_out.rs", "decoders/raydium-launchpad-decoder/src/instructions/buy_exact_out.rs",
), ),
upstream_git_discriminator_entry( upstream_git_discriminator_entry(
"raydium_launchlab", "raydium_launchpad",
Some(crate::RAYDIUM_LAUNCHLAB_PROGRAM_ID), Some(crate::RAYDIUM_LAUNCHPAD_PROGRAM_ID),
"raydium", "raydium",
"launch", "launch",
crate::ENTRY_KIND_INSTRUCTION, crate::ENTRY_KIND_INSTRUCTION,
@@ -12489,8 +12485,8 @@ pub(crate) const UPSTREAM_REGISTRY_ENTRIES: &[crate::UpstreamRegistryEntry] = &[
"decoders/raydium-launchpad-decoder/src/instructions/claim_creator_fee.rs", "decoders/raydium-launchpad-decoder/src/instructions/claim_creator_fee.rs",
), ),
upstream_git_discriminator_entry( upstream_git_discriminator_entry(
"raydium_launchlab", "raydium_launchpad",
Some(crate::RAYDIUM_LAUNCHLAB_PROGRAM_ID), Some(crate::RAYDIUM_LAUNCHPAD_PROGRAM_ID),
"raydium", "raydium",
"launch", "launch",
crate::ENTRY_KIND_INSTRUCTION, crate::ENTRY_KIND_INSTRUCTION,
@@ -12500,8 +12496,8 @@ pub(crate) const UPSTREAM_REGISTRY_ENTRIES: &[crate::UpstreamRegistryEntry] = &[
"decoders/raydium-launchpad-decoder/src/instructions/claim_platform_fee.rs", "decoders/raydium-launchpad-decoder/src/instructions/claim_platform_fee.rs",
), ),
upstream_git_discriminator_entry( upstream_git_discriminator_entry(
"raydium_launchlab", "raydium_launchpad",
Some(crate::RAYDIUM_LAUNCHLAB_PROGRAM_ID), Some(crate::RAYDIUM_LAUNCHPAD_PROGRAM_ID),
"raydium", "raydium",
"launch", "launch",
crate::ENTRY_KIND_INSTRUCTION, crate::ENTRY_KIND_INSTRUCTION,
@@ -12511,8 +12507,8 @@ pub(crate) const UPSTREAM_REGISTRY_ENTRIES: &[crate::UpstreamRegistryEntry] = &[
"decoders/raydium-launchpad-decoder/src/instructions/claim_platform_fee_from_vault.rs", "decoders/raydium-launchpad-decoder/src/instructions/claim_platform_fee_from_vault.rs",
), ),
upstream_git_discriminator_entry( upstream_git_discriminator_entry(
"raydium_launchlab", "raydium_launchpad",
Some(crate::RAYDIUM_LAUNCHLAB_PROGRAM_ID), Some(crate::RAYDIUM_LAUNCHPAD_PROGRAM_ID),
"raydium", "raydium",
"launch", "launch",
crate::ENTRY_KIND_EVENT, crate::ENTRY_KIND_EVENT,
@@ -12522,8 +12518,8 @@ pub(crate) const UPSTREAM_REGISTRY_ENTRIES: &[crate::UpstreamRegistryEntry] = &[
"decoders/raydium-launchpad-decoder/src/instructions/claim_vested_event.rs", "decoders/raydium-launchpad-decoder/src/instructions/claim_vested_event.rs",
), ),
upstream_git_discriminator_entry( upstream_git_discriminator_entry(
"raydium_launchlab", "raydium_launchpad",
Some(crate::RAYDIUM_LAUNCHLAB_PROGRAM_ID), Some(crate::RAYDIUM_LAUNCHPAD_PROGRAM_ID),
"raydium", "raydium",
"launch", "launch",
crate::ENTRY_KIND_INSTRUCTION, crate::ENTRY_KIND_INSTRUCTION,
@@ -12533,8 +12529,8 @@ pub(crate) const UPSTREAM_REGISTRY_ENTRIES: &[crate::UpstreamRegistryEntry] = &[
"decoders/raydium-launchpad-decoder/src/instructions/claim_vested_token.rs", "decoders/raydium-launchpad-decoder/src/instructions/claim_vested_token.rs",
), ),
upstream_git_discriminator_entry( upstream_git_discriminator_entry(
"raydium_launchlab", "raydium_launchpad",
Some(crate::RAYDIUM_LAUNCHLAB_PROGRAM_ID), Some(crate::RAYDIUM_LAUNCHPAD_PROGRAM_ID),
"raydium", "raydium",
"launch", "launch",
crate::ENTRY_KIND_INSTRUCTION, crate::ENTRY_KIND_INSTRUCTION,
@@ -12544,8 +12540,8 @@ pub(crate) const UPSTREAM_REGISTRY_ENTRIES: &[crate::UpstreamRegistryEntry] = &[
"decoders/raydium-launchpad-decoder/src/instructions/collect_fee.rs", "decoders/raydium-launchpad-decoder/src/instructions/collect_fee.rs",
), ),
upstream_git_discriminator_entry( upstream_git_discriminator_entry(
"raydium_launchlab", "raydium_launchpad",
Some(crate::RAYDIUM_LAUNCHLAB_PROGRAM_ID), Some(crate::RAYDIUM_LAUNCHPAD_PROGRAM_ID),
"raydium", "raydium",
"launch", "launch",
crate::ENTRY_KIND_INSTRUCTION, crate::ENTRY_KIND_INSTRUCTION,
@@ -12555,8 +12551,8 @@ pub(crate) const UPSTREAM_REGISTRY_ENTRIES: &[crate::UpstreamRegistryEntry] = &[
"decoders/raydium-launchpad-decoder/src/instructions/collect_migrate_fee.rs", "decoders/raydium-launchpad-decoder/src/instructions/collect_migrate_fee.rs",
), ),
upstream_git_discriminator_entry( upstream_git_discriminator_entry(
"raydium_launchlab", "raydium_launchpad",
Some(crate::RAYDIUM_LAUNCHLAB_PROGRAM_ID), Some(crate::RAYDIUM_LAUNCHPAD_PROGRAM_ID),
"raydium", "raydium",
"launch", "launch",
crate::ENTRY_KIND_INSTRUCTION, crate::ENTRY_KIND_INSTRUCTION,
@@ -12566,8 +12562,8 @@ pub(crate) const UPSTREAM_REGISTRY_ENTRIES: &[crate::UpstreamRegistryEntry] = &[
"decoders/raydium-launchpad-decoder/src/instructions/create_config.rs", "decoders/raydium-launchpad-decoder/src/instructions/create_config.rs",
), ),
upstream_git_discriminator_entry( upstream_git_discriminator_entry(
"raydium_launchlab", "raydium_launchpad",
Some(crate::RAYDIUM_LAUNCHLAB_PROGRAM_ID), Some(crate::RAYDIUM_LAUNCHPAD_PROGRAM_ID),
"raydium", "raydium",
"launch", "launch",
crate::ENTRY_KIND_INSTRUCTION, crate::ENTRY_KIND_INSTRUCTION,
@@ -12577,8 +12573,8 @@ pub(crate) const UPSTREAM_REGISTRY_ENTRIES: &[crate::UpstreamRegistryEntry] = &[
"decoders/raydium-launchpad-decoder/src/instructions/create_platform_config.rs", "decoders/raydium-launchpad-decoder/src/instructions/create_platform_config.rs",
), ),
upstream_git_discriminator_entry( upstream_git_discriminator_entry(
"raydium_launchlab", "raydium_launchpad",
Some(crate::RAYDIUM_LAUNCHLAB_PROGRAM_ID), Some(crate::RAYDIUM_LAUNCHPAD_PROGRAM_ID),
"raydium", "raydium",
"launch", "launch",
crate::ENTRY_KIND_INSTRUCTION, crate::ENTRY_KIND_INSTRUCTION,
@@ -12588,8 +12584,8 @@ pub(crate) const UPSTREAM_REGISTRY_ENTRIES: &[crate::UpstreamRegistryEntry] = &[
"decoders/raydium-launchpad-decoder/src/instructions/create_vesting_account.rs", "decoders/raydium-launchpad-decoder/src/instructions/create_vesting_account.rs",
), ),
upstream_git_discriminator_entry( upstream_git_discriminator_entry(
"raydium_launchlab", "raydium_launchpad",
Some(crate::RAYDIUM_LAUNCHLAB_PROGRAM_ID), Some(crate::RAYDIUM_LAUNCHPAD_PROGRAM_ID),
"raydium", "raydium",
"launch", "launch",
crate::ENTRY_KIND_EVENT, crate::ENTRY_KIND_EVENT,
@@ -12599,8 +12595,8 @@ pub(crate) const UPSTREAM_REGISTRY_ENTRIES: &[crate::UpstreamRegistryEntry] = &[
"decoders/raydium-launchpad-decoder/src/instructions/create_vesting_event.rs", "decoders/raydium-launchpad-decoder/src/instructions/create_vesting_event.rs",
), ),
upstream_git_discriminator_entry( upstream_git_discriminator_entry(
"raydium_launchlab", "raydium_launchpad",
Some(crate::RAYDIUM_LAUNCHLAB_PROGRAM_ID), Some(crate::RAYDIUM_LAUNCHPAD_PROGRAM_ID),
"raydium", "raydium",
"launch", "launch",
crate::ENTRY_KIND_INSTRUCTION, crate::ENTRY_KIND_INSTRUCTION,
@@ -12610,8 +12606,8 @@ pub(crate) const UPSTREAM_REGISTRY_ENTRIES: &[crate::UpstreamRegistryEntry] = &[
"decoders/raydium-launchpad-decoder/src/instructions/initialize.rs", "decoders/raydium-launchpad-decoder/src/instructions/initialize.rs",
), ),
upstream_git_discriminator_entry( upstream_git_discriminator_entry(
"raydium_launchlab", "raydium_launchpad",
Some(crate::RAYDIUM_LAUNCHLAB_PROGRAM_ID), Some(crate::RAYDIUM_LAUNCHPAD_PROGRAM_ID),
"raydium", "raydium",
"launch", "launch",
crate::ENTRY_KIND_INSTRUCTION, crate::ENTRY_KIND_INSTRUCTION,
@@ -12621,8 +12617,8 @@ pub(crate) const UPSTREAM_REGISTRY_ENTRIES: &[crate::UpstreamRegistryEntry] = &[
"decoders/raydium-launchpad-decoder/src/instructions/initialize_v2.rs", "decoders/raydium-launchpad-decoder/src/instructions/initialize_v2.rs",
), ),
upstream_git_discriminator_entry( upstream_git_discriminator_entry(
"raydium_launchlab", "raydium_launchpad",
Some(crate::RAYDIUM_LAUNCHLAB_PROGRAM_ID), Some(crate::RAYDIUM_LAUNCHPAD_PROGRAM_ID),
"raydium", "raydium",
"launch", "launch",
crate::ENTRY_KIND_INSTRUCTION, crate::ENTRY_KIND_INSTRUCTION,
@@ -12632,8 +12628,8 @@ pub(crate) const UPSTREAM_REGISTRY_ENTRIES: &[crate::UpstreamRegistryEntry] = &[
"decoders/raydium-launchpad-decoder/src/instructions/initialize_with_token_2022.rs", "decoders/raydium-launchpad-decoder/src/instructions/initialize_with_token_2022.rs",
), ),
upstream_git_discriminator_entry( upstream_git_discriminator_entry(
"raydium_launchlab", "raydium_launchpad",
Some(crate::RAYDIUM_LAUNCHLAB_PROGRAM_ID), Some(crate::RAYDIUM_LAUNCHPAD_PROGRAM_ID),
"raydium", "raydium",
"launch", "launch",
crate::ENTRY_KIND_INSTRUCTION, crate::ENTRY_KIND_INSTRUCTION,
@@ -12643,8 +12639,8 @@ pub(crate) const UPSTREAM_REGISTRY_ENTRIES: &[crate::UpstreamRegistryEntry] = &[
"decoders/raydium-launchpad-decoder/src/instructions/migrate_to_amm.rs", "decoders/raydium-launchpad-decoder/src/instructions/migrate_to_amm.rs",
), ),
upstream_git_discriminator_entry( upstream_git_discriminator_entry(
"raydium_launchlab", "raydium_launchpad",
Some(crate::RAYDIUM_LAUNCHLAB_PROGRAM_ID), Some(crate::RAYDIUM_LAUNCHPAD_PROGRAM_ID),
"raydium", "raydium",
"launch", "launch",
crate::ENTRY_KIND_INSTRUCTION, crate::ENTRY_KIND_INSTRUCTION,
@@ -12654,8 +12650,8 @@ pub(crate) const UPSTREAM_REGISTRY_ENTRIES: &[crate::UpstreamRegistryEntry] = &[
"decoders/raydium-launchpad-decoder/src/instructions/migrate_to_cpswap.rs", "decoders/raydium-launchpad-decoder/src/instructions/migrate_to_cpswap.rs",
), ),
upstream_git_discriminator_entry( upstream_git_discriminator_entry(
"raydium_launchlab", "raydium_launchpad",
Some(crate::RAYDIUM_LAUNCHLAB_PROGRAM_ID), Some(crate::RAYDIUM_LAUNCHPAD_PROGRAM_ID),
"raydium", "raydium",
"launch", "launch",
crate::ENTRY_KIND_EVENT, crate::ENTRY_KIND_EVENT,
@@ -12665,8 +12661,8 @@ pub(crate) const UPSTREAM_REGISTRY_ENTRIES: &[crate::UpstreamRegistryEntry] = &[
"decoders/raydium-launchpad-decoder/src/instructions/pool_create_event.rs", "decoders/raydium-launchpad-decoder/src/instructions/pool_create_event.rs",
), ),
upstream_git_discriminator_entry( upstream_git_discriminator_entry(
"raydium_launchlab", "raydium_launchpad",
Some(crate::RAYDIUM_LAUNCHLAB_PROGRAM_ID), Some(crate::RAYDIUM_LAUNCHPAD_PROGRAM_ID),
"raydium", "raydium",
"launch", "launch",
crate::ENTRY_KIND_INSTRUCTION, crate::ENTRY_KIND_INSTRUCTION,
@@ -12676,8 +12672,8 @@ pub(crate) const UPSTREAM_REGISTRY_ENTRIES: &[crate::UpstreamRegistryEntry] = &[
"decoders/raydium-launchpad-decoder/src/instructions/remove_platform_curve_param.rs", "decoders/raydium-launchpad-decoder/src/instructions/remove_platform_curve_param.rs",
), ),
upstream_git_discriminator_entry( upstream_git_discriminator_entry(
"raydium_launchlab", "raydium_launchpad",
Some(crate::RAYDIUM_LAUNCHLAB_PROGRAM_ID), Some(crate::RAYDIUM_LAUNCHPAD_PROGRAM_ID),
"raydium", "raydium",
"launch", "launch",
crate::ENTRY_KIND_INSTRUCTION, crate::ENTRY_KIND_INSTRUCTION,
@@ -12687,8 +12683,8 @@ pub(crate) const UPSTREAM_REGISTRY_ENTRIES: &[crate::UpstreamRegistryEntry] = &[
"decoders/raydium-launchpad-decoder/src/instructions/sell_exact_in.rs", "decoders/raydium-launchpad-decoder/src/instructions/sell_exact_in.rs",
), ),
upstream_git_discriminator_entry( upstream_git_discriminator_entry(
"raydium_launchlab", "raydium_launchpad",
Some(crate::RAYDIUM_LAUNCHLAB_PROGRAM_ID), Some(crate::RAYDIUM_LAUNCHPAD_PROGRAM_ID),
"raydium", "raydium",
"launch", "launch",
crate::ENTRY_KIND_INSTRUCTION, crate::ENTRY_KIND_INSTRUCTION,
@@ -12698,8 +12694,8 @@ pub(crate) const UPSTREAM_REGISTRY_ENTRIES: &[crate::UpstreamRegistryEntry] = &[
"decoders/raydium-launchpad-decoder/src/instructions/sell_exact_out.rs", "decoders/raydium-launchpad-decoder/src/instructions/sell_exact_out.rs",
), ),
upstream_git_discriminator_entry( upstream_git_discriminator_entry(
"raydium_launchlab", "raydium_launchpad",
Some(crate::RAYDIUM_LAUNCHLAB_PROGRAM_ID), Some(crate::RAYDIUM_LAUNCHPAD_PROGRAM_ID),
"raydium", "raydium",
"launch", "launch",
crate::ENTRY_KIND_EVENT, crate::ENTRY_KIND_EVENT,
@@ -12709,8 +12705,8 @@ pub(crate) const UPSTREAM_REGISTRY_ENTRIES: &[crate::UpstreamRegistryEntry] = &[
"decoders/raydium-launchpad-decoder/src/instructions/trade_event.rs", "decoders/raydium-launchpad-decoder/src/instructions/trade_event.rs",
), ),
upstream_git_discriminator_entry( upstream_git_discriminator_entry(
"raydium_launchlab", "raydium_launchpad",
Some(crate::RAYDIUM_LAUNCHLAB_PROGRAM_ID), Some(crate::RAYDIUM_LAUNCHPAD_PROGRAM_ID),
"raydium", "raydium",
"launch", "launch",
crate::ENTRY_KIND_INSTRUCTION, crate::ENTRY_KIND_INSTRUCTION,
@@ -12720,8 +12716,8 @@ pub(crate) const UPSTREAM_REGISTRY_ENTRIES: &[crate::UpstreamRegistryEntry] = &[
"decoders/raydium-launchpad-decoder/src/instructions/update_config.rs", "decoders/raydium-launchpad-decoder/src/instructions/update_config.rs",
), ),
upstream_git_discriminator_entry( upstream_git_discriminator_entry(
"raydium_launchlab", "raydium_launchpad",
Some(crate::RAYDIUM_LAUNCHLAB_PROGRAM_ID), Some(crate::RAYDIUM_LAUNCHPAD_PROGRAM_ID),
"raydium", "raydium",
"launch", "launch",
crate::ENTRY_KIND_INSTRUCTION, crate::ENTRY_KIND_INSTRUCTION,
@@ -12731,8 +12727,8 @@ pub(crate) const UPSTREAM_REGISTRY_ENTRIES: &[crate::UpstreamRegistryEntry] = &[
"decoders/raydium-launchpad-decoder/src/instructions/update_platform_config.rs", "decoders/raydium-launchpad-decoder/src/instructions/update_platform_config.rs",
), ),
upstream_git_discriminator_entry( upstream_git_discriminator_entry(
"raydium_launchlab", "raydium_launchpad",
Some(crate::RAYDIUM_LAUNCHLAB_PROGRAM_ID), Some(crate::RAYDIUM_LAUNCHPAD_PROGRAM_ID),
"raydium", "raydium",
"launch", "launch",
crate::ENTRY_KIND_INSTRUCTION, crate::ENTRY_KIND_INSTRUCTION,
@@ -12741,6 +12737,50 @@ pub(crate) const UPSTREAM_REGISTRY_ENTRIES: &[crate::UpstreamRegistryEntry] = &[
8, 8,
"decoders/raydium-launchpad-decoder/src/instructions/update_platform_curve_param.rs", "decoders/raydium-launchpad-decoder/src/instructions/update_platform_curve_param.rs",
), ),
upstream_git_discriminator_entry(
"raydium_launchpad",
Some(crate::RAYDIUM_LAUNCHPAD_PROGRAM_ID),
"raydium",
"launch",
crate::ENTRY_KIND_INSTRUCTION,
"close_platform_global_access",
"7bb4b8816fb9bb3b",
8,
"decoders/raydium-launchpad-decoder/src/instructions/close_platform_global_access.rs",
),
upstream_git_discriminator_entry(
"raydium_launchpad",
Some(crate::RAYDIUM_LAUNCHPAD_PROGRAM_ID),
"raydium",
"launch",
crate::ENTRY_KIND_INSTRUCTION,
"create_platform_global_access",
"a25b92c75d85eaed",
8,
"decoders/raydium-launchpad-decoder/src/instructions/create_platform_global_access.rs",
),
upstream_git_discriminator_entry(
"raydium_launchpad",
Some(crate::RAYDIUM_LAUNCHPAD_PROGRAM_ID),
"raydium",
"launch",
crate::ENTRY_KIND_INSTRUCTION,
"create_platform_vesting_account",
"9247ad4562130f6a",
8,
"decoders/raydium-launchpad-decoder/src/instructions/create_platform_vesting_account.rs",
),
upstream_git_discriminator_entry(
"raydium_launchpad",
Some(crate::RAYDIUM_LAUNCHPAD_PROGRAM_ID),
"raydium",
"launch",
crate::ENTRY_KIND_INSTRUCTION,
"cpi_event",
"e445a52e51cb9a1d",
8,
"decoders/raydium-launchpad-decoder/src/instructions/cpi_event.rs",
),
upstream_git_discriminator_entry( upstream_git_discriminator_entry(
"raydium_liquidity_locking", "raydium_liquidity_locking",
Some(crate::RAYDIUM_LIQUIDITY_LOCKING_PROGRAM_ID), Some(crate::RAYDIUM_LIQUIDITY_LOCKING_PROGRAM_ID),

View File

@@ -327,7 +327,7 @@ mod tests {
"raydium_amm_v4", "raydium_amm_v4",
"raydium_clmm", "raydium_clmm",
"raydium_cpmm", "raydium_cpmm",
"raydium_launchlab", "raydium_launchpad",
"raydium_liquidity_locking", "raydium_liquidity_locking",
"raydium_stable_swap", "raydium_stable_swap",
"orca_whirlpools", "orca_whirlpools",

View File

@@ -0,0 +1,48 @@
-- file: validation_sql/SQL_TRACE_RAYDIUM_CPMM_AUDIT_40F_0_7_50_PRE_R2.sql
-- Purpose: locate the Raydium CPMM audit-only discriminator 40f4bc78a7e9690a
-- so the instruction can be inspected manually on Solscan or decoded from local meta_json.
SELECT
tx.signature,
tx.slot,
de.id AS decoded_event_id,
de.pool_account,
de.token_a_mint,
de.token_b_mint,
json_extract(de.payload_json, '$.instructionIndex') AS instruction_index,
json_extract(de.payload_json, '$.innerInstructionIndex') AS inner_instruction_index,
json_extract(de.payload_json, '$.programId') AS program_id,
json_extract(de.payload_json, '$.discriminatorHex') AS discriminator_hex,
json_extract(de.payload_json, '$.accountCount') AS account_count,
json_extract(de.payload_json, '$.accounts') AS accounts_json,
json_extract(de.payload_json, '$.data') AS instruction_data,
de.payload_json
FROM k_sol_dex_decoded_events de
JOIN k_sol_chain_transactions tx
ON tx.id = de.transaction_id
WHERE de.protocol_name = 'raydium_cpmm'
AND de.event_kind = 'raydium_cpmm.instruction_audit'
AND json_extract(de.payload_json, '$.discriminatorHex') = '40f4bc78a7e9690a'
ORDER BY tx.slot, tx.signature, instruction_index, inner_instruction_index;
-- Optional: include the raw projected instruction row if decoded_event.instruction_id is populated.
SELECT
tx.signature,
tx.slot,
de.id AS decoded_event_id,
ci.id AS chain_instruction_id,
ci.instruction_index,
ci.inner_instruction_index,
ci.program_id,
ci.accounts_json,
ci.data_json,
de.payload_json
FROM k_sol_dex_decoded_events de
JOIN k_sol_chain_transactions tx
ON tx.id = de.transaction_id
LEFT JOIN k_sol_chain_instructions ci
ON ci.id = de.instruction_id
WHERE de.protocol_name = 'raydium_cpmm'
AND de.event_kind = 'raydium_cpmm.instruction_audit'
AND json_extract(de.payload_json, '$.discriminatorHex') = '40f4bc78a7e9690a'
ORDER BY tx.slot, tx.signature, ci.instruction_index, ci.inner_instruction_index;

View File

@@ -0,0 +1,399 @@
-- file: validation_sql/SQL_VALIDATION_RAYDIUM_CLMM_0_7_50_PRE_R2.sql
-- Raydium CLMM 0.7.50-pre-r2 re-verification pack.
-- Goal: repeat the Launchpad-style closure checks on a dedicated CLMM
-- database, after replay with skipDexDecode='no' and forceDexDecode='yes'.
-- Expected invariants:
-- - no `unknown` or empty event_family except the synthetic `program` row;
-- - no observed discriminator missing from coverage;
-- - no residual upstream fallback for locally-covered entries;
-- - no successful, actionable decoded event left without its materialized row;
-- - no failed transaction materialized into business tables;
-- - decoded-only entries such as CPMM anchor IDL management and CLMM router/program-data
-- corroboration events are excluded from materialization shortfall checks.
-- 01. Coverage detail.
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 = 'raydium_clmm'
ORDER BY entry_kind, entry_name, discriminator_hex;
->
collect_personal_fee_event event fee k_sol_fee_events upstream_git_mapped_unverified raydium_clmm.collect_personal_fee_event a6ae69c051a15369 0 0 0
collect_protocol_fee_event event fee k_sol_fee_events upstream_git_local_corpus_materialized raydium_clmm.collect_protocol_fee_event ce57114f2d29d53d 4 4 0
config_change_event event admin_config k_sol_pool_admin_events upstream_git_local_corpus_materialized raydium_clmm.config_change_event f7bd07776a705f97 4 4 0
create_personal_position_event event position_open k_sol_liquidity_events upstream_git_local_corpus_materialized raydium_clmm.create_personal_position_event 641e57f9c4df9ace 26 23 0
decrease_liquidity_event event liquidity_remove k_sol_liquidity_events upstream_git_local_corpus_materialized raydium_clmm.decrease_liquidity_event 3ade563a44325538 16 16 0
increase_liquidity_event event liquidity_add k_sol_liquidity_events upstream_git_local_corpus_materialized raydium_clmm.increase_liquidity_event 314f69d420221e54 9 8 0
liquidity_calculate_event event liquidity_calculation k_sol_dex_decoded_events_only upstream_git_local_corpus_observed raydium_clmm.liquidity_calculate_event ed7094e63954b4a2 58 0 0
liquidity_change_event event liquidity_change k_sol_liquidity_events upstream_git_local_corpus_materialized raydium_clmm.liquidity_change_event 7ef0afce9e58996b 50 45 0
pool_created_event event pool_create k_sol_pool_lifecycle_events upstream_git_local_corpus_materialized raydium_clmm.pool_created_event 195e4b2f7063353f 14 13 0
swap_event event swap k_sol_dex_decoded_events_only upstream_git_local_corpus_observed raydium_clmm.swap_event 40c6cde8260871e2 1456 0 0
update_reward_infos_event event reward k_sol_reward_events upstream_git_local_corpus_materialized raydium_clmm.update_reward_infos_event 6d7fba4e724125ec 7 7 0
close_limit_order instruction order_cancel k_sol_orderbook_events upstream_git_local_corpus_materialized raydium_clmm.close_limit_order 4c7c800fd55725fa 24 22 0
close_position instruction position_close k_sol_dex_decoded_events_only upstream_git_local_corpus_observed raydium_clmm.close_position 7b86510031446262 16 0 0
close_protocol_position instruction position_close k_sol_dex_decoded_events_only upstream_git_local_corpus_observed raydium_clmm.close_protocol_position c975989055556cb2 3 0 0
collect_fund_fee instruction fee k_sol_fee_events upstream_git_local_corpus_materialized raydium_clmm.collect_fund_fee a78a4e95dfc2067e 5 3 0
collect_protocol_fee instruction fee k_sol_fee_events upstream_git_local_corpus_materialized raydium_clmm.collect_protocol_fee 8888fcddc2427e59 11 11 0
collect_remaining_rewards instruction reward k_sol_reward_events upstream_git_local_corpus_materialized raydium_clmm.collect_remaining_rewards 12eda6c52210d590 10 6 0
cpi_event instruction cpi_transport k_sol_dex_decoded_events_only upstream_git_mapped_unverified raydium_clmm.cpi_event e445a52e51cb9a1d 0 0 0
create_amm_config instruction admin_config k_sol_pool_admin_events upstream_git_local_corpus_materialized raydium_clmm.create_amm_config 8934edd4d7756c68 9 7 0
create_customizable_pool instruction pool_create k_sol_pool_lifecycle_events upstream_git_local_corpus_materialized raydium_clmm.create_customizable_pool 2b44d4a7592fa401 5 3 0
create_dynamic_fee_config instruction admin_config k_sol_pool_admin_events upstream_git_local_corpus_materialized raydium_clmm.create_dynamic_fee_config bd0eb5785576e33e 1 1 0
create_operation_account instruction admin_config k_sol_pool_admin_events upstream_git_local_corpus_materialized raydium_clmm.create_operation_account 3f5794216d230868 4 1 0
create_pool instruction pool_create k_sol_pool_lifecycle_events upstream_git_local_corpus_materialized raydium_clmm.create_pool e992d18ecf6840bc 8 8 0
create_support_mint_associated instruction account_create k_sol_token_account_events upstream_git_local_corpus_observed raydium_clmm.create_support_mint_associated 11fb415c88f20ea9 5 0 0
decrease_limit_order instruction order_cancel k_sol_orderbook_events upstream_git_local_corpus_materialized raydium_clmm.decrease_limit_order 759d3c674231a300 24 22 0
decrease_liquidity instruction liquidity_remove k_sol_liquidity_events upstream_git_local_corpus_materialized raydium_clmm.decrease_liquidity a026d06f685b2c01 16 1 0
decrease_liquidity_v2 instruction liquidity_remove k_sol_liquidity_events upstream_git_local_corpus_materialized raydium_clmm.decrease_liquidity_v2 3a7fbc3e4f52c460 25 23 0
increase_limit_order instruction order_place k_sol_orderbook_events upstream_git_local_corpus_materialized raydium_clmm.increase_limit_order b19059ecfaba7d63 6 6 0
increase_liquidity instruction liquidity_add k_sol_liquidity_events upstream_git_local_corpus_materialized raydium_clmm.increase_liquidity 2e9cf3760dcdfbb2 6 2 0
increase_liquidity_v2 instruction liquidity_add k_sol_liquidity_events upstream_git_local_corpus_materialized raydium_clmm.increase_liquidity_v2 851d59df45eeb00a 7 6 0
initialize_reward instruction pool_create k_sol_reward_events upstream_git_local_corpus_materialized raydium_clmm.initialize_reward 5f87c0c4f281e644 7 4 0
open_limit_order instruction order_place k_sol_orderbook_events upstream_git_local_corpus_materialized raydium_clmm.open_limit_order 9d20dab7471d1293 10 5 0
open_position instruction position_open k_sol_liquidity_events upstream_git_local_corpus_materialized raydium_clmm.open_position 87802f4d0f98f031 9 1 0
open_position_v2 instruction position_open k_sol_liquidity_events upstream_git_local_corpus_materialized raydium_clmm.open_position_v2 4db84ad67056f1c7 11 7 0
open_position_with_token22_nft instruction position_open k_sol_liquidity_events upstream_git_local_corpus_materialized raydium_clmm.open_position_with_token22_nft 4dffae527d1dc92e 19 15 0
set_reward_params instruction reward k_sol_reward_events upstream_git_local_corpus_materialized raydium_clmm.set_reward_params 7034a74b20c9d389 6 4 0
settle_limit_order instruction settle_funds k_sol_orderbook_events upstream_git_local_corpus_materialized raydium_clmm.settle_limit_order cd4e74215c691a60 9 9 0
swap instruction swap k_sol_trade_events upstream_git_local_corpus_materialized raydium_clmm.swap f8c69e91e17587c8 1464 910 910
swap_router_base_in instruction swap k_sol_dex_decoded_events_only upstream_git_local_corpus_observed raydium_clmm.swap_router_base_in 457d73daf5baf2c4 90 0 0
swap_v2 instruction swap k_sol_trade_events upstream_git_local_corpus_materialized raydium_clmm.swap_v2 2b04ed0b1ac91e62 715 276 276
transfer_reward_owner instruction reward k_sol_reward_events upstream_git_local_corpus_materialized raydium_clmm.transfer_reward_owner 07160c53f22b3079 7 5 0
update_amm_config instruction admin_config k_sol_pool_admin_events upstream_git_local_corpus_materialized raydium_clmm.update_amm_config 313cae889a1c74c8 11 8 0
update_dynamic_fee_config instruction admin_config k_sol_pool_admin_events upstream_git_mapped_unverified raydium_clmm.update_dynamic_fee_config 0707500802c784f0 0 0 0
update_operation_account instruction admin_config k_sol_pool_admin_events upstream_git_local_corpus_materialized raydium_clmm.update_operation_account 7f467728bce33d07 4 3 0
update_pool_status instruction admin_config k_sol_pool_admin_events upstream_git_local_corpus_materialized raydium_clmm.update_pool_status 82576c062ee0757b 6 4 0
update_reward_infos instruction reward k_sol_reward_events upstream_git_local_corpus_materialized raydium_clmm.update_reward_infos a3ace0340b9a6adf 7 7 0
program program k_sol_dex_decoded_events_only upstream_git_unverified 0 0 0
SELECT
decoder_code,
COUNT(*) AS listed_entry_count,
SUM(CASE WHEN local_event_kind IS NOT NULL AND local_event_kind <> '' THEN 1 ELSE 0 END) AS decoded_entry_count,
SUM(CASE WHEN observed_count > 0 THEN 1 ELSE 0 END) AS observed_entry_count,
SUM(CASE WHEN materialized_count > 0 THEN 1 ELSE 0 END) AS materialized_entry_count,
COALESCE(SUM(observed_count), 0) AS total_observed_count,
COALESCE(SUM(materialized_count), 0) AS total_materialized_count,
COALESCE(SUM(trade_count), 0) AS trade_count
FROM k_sol_dex_event_coverage_entries
WHERE decoder_code = 'raydium_clmm'
GROUP BY decoder_code;
->
raydium_clmm 47 46 43 37 4204 1500 1186
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 = 'raydium_clmm'
AND (
event_family IS NULL
OR event_family = ''
OR event_family = 'unknown'
)
AND entry_kind <> 'program'
ORDER BY entry_kind, entry_name;
-> vide
SELECT
instruction_name,
discriminator_hex,
COUNT(*) AS observed_count,
COUNT(DISTINCT signature) AS tx_count
FROM k_sol_instruction_observations
WHERE decoder_code = 'raydium_clmm'
GROUP BY instruction_name, discriminator_hex
ORDER BY observed_count DESC, instruction_name, discriminator_hex;
->
raydium_clmm.swap f8c69e91e17587c8 1464 1327
raydium_clmm.swap_v2 2b04ed0b1ac91e62 715 459
raydium_clmm.swap_router_base_in 457d73daf5baf2c4 90 88
raydium_clmm.close_limit_order 4c7c800fd55725fa 28 24
raydium_clmm.decrease_limit_order 759d3c674231a300 28 24
raydium_clmm.decrease_liquidity_v2 3a7fbc3e4f52c460 25 18
raydium_clmm.create_support_mint_associated 11fb415c88f20ea9 22 5
raydium_clmm.update_amm_config 313cae889a1c74c8 20 11
raydium_clmm.open_position_with_token22_nft 4dffae527d1dc92e 19 19
raydium_clmm.collect_fund_fee a78a4e95dfc2067e 18 5
raydium_clmm.close_position 7b86510031446262 16 16
raydium_clmm.decrease_liquidity a026d06f685b2c01 16 16
raydium_clmm.create_amm_config 8934edd4d7756c68 12 9
raydium_clmm.collect_protocol_fee 8888fcddc2427e59 11 4
raydium_clmm.open_position_v2 4db84ad67056f1c7 11 11
raydium_clmm.collect_remaining_rewards 12eda6c52210d590 10 10
raydium_clmm.create_pool e992d18ecf6840bc 10 10
raydium_clmm.open_limit_order 9d20dab7471d1293 10 10
raydium_clmm.open_position 87802f4d0f98f031 9 9
raydium_clmm.set_reward_params 7034a74b20c9d389 9 6
raydium_clmm.settle_limit_order cd4e74215c691a60 9 9
raydium_clmm.transfer_reward_owner 07160c53f22b3079 9 7
raydium_clmm.increase_liquidity_v2 851d59df45eeb00a 7 7
raydium_clmm.initialize_reward 5f87c0c4f281e644 7 7
raydium_clmm.update_reward_infos a3ace0340b9a6adf 7 7
raydium_clmm.increase_limit_order b19059ecfaba7d63 6 6
raydium_clmm.increase_liquidity 2e9cf3760dcdfbb2 6 6
raydium_clmm.update_pool_status 82576c062ee0757b 6 6
raydium_clmm.close_protocol_position c975989055556cb2 5 3
raydium_clmm.create_customizable_pool 2b44d4a7592fa401 5 5
raydium_clmm.update_operation_account 7f467728bce33d07 5 4
raydium_clmm.create_dynamic_fee_config bd0eb5785576e33e 4 1
raydium_clmm.create_operation_account 3f5794216d230868 4 4
SELECT
io.discriminator_hex,
MIN(io.instruction_name) AS sample_instruction_name,
MIN(io.decoded_event_kind) AS sample_decoded_event_kind,
COUNT(*) AS observed_count,
COUNT(DISTINCT io.signature) AS tx_count
FROM k_sol_instruction_observations io
LEFT JOIN k_sol_dex_event_coverage_entries ce
ON ce.decoder_code = 'raydium_clmm'
AND ce.discriminator_hex = io.discriminator_hex
WHERE io.decoder_code = 'raydium_clmm'
AND io.discriminator_hex IS NOT NULL
AND io.discriminator_hex <> ''
AND ce.id IS NULL
GROUP BY io.discriminator_hex
ORDER BY observed_count DESC, io.discriminator_hex;
-> vide
SELECT
de.event_kind,
COUNT(*) AS decoded_count,
COUNT(le.id) AS liquidity_count,
COUNT(fe.id) AS fee_count,
COUNT(re.id) AS reward_count,
COUNT(ae.id) AS admin_count,
COUNT(la.id) AS launch_count,
COUNT(pe.id) AS lifecycle_count,
COUNT(oe.id) AS orderbook_count,
COUNT(ta.id) AS token_account_count,
COUNT(te.id) AS trade_count
FROM k_sol_dex_decoded_events de
LEFT JOIN k_sol_liquidity_events le ON le.decoded_event_id = de.id
LEFT JOIN k_sol_fee_events fe ON fe.decoded_event_id = de.id
LEFT JOIN k_sol_reward_events re ON re.decoded_event_id = de.id
LEFT JOIN k_sol_pool_admin_events ae ON ae.decoded_event_id = de.id
LEFT JOIN k_sol_launch_events la ON la.decoded_event_id = de.id
LEFT JOIN k_sol_pool_lifecycle_events pe ON pe.decoded_event_id = de.id
LEFT JOIN k_sol_orderbook_events oe ON oe.decoded_event_id = de.id
LEFT JOIN k_sol_token_account_events ta ON ta.decoded_event_id = de.id
LEFT JOIN k_sol_trade_events te ON te.decoded_event_id = de.id
WHERE de.protocol_name = 'raydium_clmm'
GROUP BY de.event_kind
ORDER BY decoded_count DESC, de.event_kind;
->
raydium_clmm.swap 1464 0 0 0 0 0 0 0 0 910
raydium_clmm.swap_event 1456 0 0 0 0 0 0 0 0 0
raydium_clmm.swap_v2 715 0 0 0 0 0 0 0 0 276
raydium_clmm.swap_router_base_in 90 0 0 0 0 0 0 0 0 0
raydium_clmm.liquidity_calculate_event 58 0 0 0 0 0 0 0 0 0
raydium_clmm.liquidity_change_event 50 45 0 0 0 0 0 0 0 0
raydium_clmm.create_personal_position_event 26 23 0 0 0 0 0 0 0 0
raydium_clmm.decrease_liquidity_v2 25 23 0 0 0 0 0 0 0 0
raydium_clmm.close_limit_order 24 0 0 0 0 0 0 22 0 0
raydium_clmm.decrease_limit_order 24 0 0 0 0 0 0 22 0 0
raydium_clmm.open_position_with_token22_nft 19 15 0 0 0 0 0 0 0 0
raydium_clmm.close_position 16 7 0 0 0 0 0 0 0 0
raydium_clmm.decrease_liquidity 16 1 0 0 0 0 0 0 0 0
raydium_clmm.decrease_liquidity_event 16 16 0 0 0 0 0 0 0 0
raydium_clmm.pool_created_event 14 0 0 0 0 0 13 0 0 0
raydium_clmm.collect_protocol_fee 11 0 11 0 0 0 0 0 0 0
raydium_clmm.open_position_v2 11 7 0 0 0 0 0 0 0 0
raydium_clmm.update_amm_config 11 0 0 0 8 0 0 0 0 0
raydium_clmm.collect_remaining_rewards 10 0 0 6 0 0 0 0 0 0
raydium_clmm.open_limit_order 10 0 0 0 0 0 0 5 0 0
raydium_clmm.create_amm_config 9 0 0 0 7 0 0 0 0 0
raydium_clmm.increase_liquidity_event 9 8 0 0 0 0 0 0 0 0
raydium_clmm.open_position 9 1 0 0 0 0 0 0 0 0
raydium_clmm.settle_limit_order 9 0 0 0 0 0 0 9 0 0
raydium_clmm.create_pool 8 0 0 0 0 0 8 0 0 0
raydium_clmm.increase_liquidity_v2 7 6 0 0 0 0 0 0 0 0
raydium_clmm.initialize_reward 7 0 0 4 0 0 4 0 0 0
raydium_clmm.transfer_reward_owner 7 0 0 5 0 0 0 0 0 0
raydium_clmm.update_reward_infos 7 0 0 7 7 0 0 0 0 0
raydium_clmm.update_reward_infos_event 7 0 0 7 7 0 0 0 0 0
raydium_clmm.increase_limit_order 6 0 0 0 0 0 0 6 0 0
raydium_clmm.increase_liquidity 6 2 0 0 0 0 0 0 0 0
raydium_clmm.set_reward_params 6 0 0 4 4 0 0 0 0 0
raydium_clmm.update_pool_status 6 0 0 0 4 0 0 0 0 0
raydium_clmm.collect_fund_fee 5 0 3 0 0 0 0 0 0 0
raydium_clmm.create_customizable_pool 5 0 0 0 0 0 3 0 0 0
raydium_clmm.create_support_mint_associated 5 0 0 0 0 0 0 0 5 0
raydium_clmm.collect_protocol_fee_event 4 0 4 0 0 0 0 0 0 0
raydium_clmm.config_change_event 4 0 0 0 4 0 0 0 0 0
raydium_clmm.create_operation_account 4 0 0 0 1 0 0 0 0 0
raydium_clmm.update_operation_account 4 0 0 0 3 0 0 0 0 0
raydium_clmm.close_protocol_position 3 0 0 0 0 0 0 0 0 0
raydium_clmm.create_dynamic_fee_config 1 0 0 0 1 0 0 0 0 0
SELECT
de.event_kind,
ce.entry_name,
ce.entry_kind,
ce.event_family,
ce.expected_db_target,
COUNT(*) AS decoded_count,
COUNT(CASE WHEN tx.err_json IS NOT NULL AND tx.err_json <> '' AND tx.err_json <> 'null' THEN de.id END) AS failed_tx_count,
COUNT(le.id) AS liquidity_count,
COUNT(fe.id) AS fee_count,
COUNT(re.id) AS reward_count,
COUNT(ae.id) AS admin_count,
COUNT(la.id) AS launch_count,
COUNT(pe.id) AS lifecycle_count,
COUNT(oe.id) AS orderbook_count,
COUNT(ta.id) AS token_account_count,
COUNT(te.id) AS trade_count
FROM k_sol_dex_decoded_events de
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 = 'raydium_clmm'
AND ce.local_event_kind = de.event_kind
LEFT JOIN k_sol_liquidity_events le ON le.decoded_event_id = de.id
LEFT JOIN k_sol_fee_events fe ON fe.decoded_event_id = de.id
LEFT JOIN k_sol_reward_events re ON re.decoded_event_id = de.id
LEFT JOIN k_sol_pool_admin_events ae ON ae.decoded_event_id = de.id
LEFT JOIN k_sol_launch_events la ON la.decoded_event_id = de.id
LEFT JOIN k_sol_pool_lifecycle_events pe ON pe.decoded_event_id = de.id
LEFT JOIN k_sol_orderbook_events oe ON oe.decoded_event_id = de.id
LEFT JOIN k_sol_token_account_events ta ON ta.decoded_event_id = de.id
LEFT JOIN k_sol_trade_events te ON te.decoded_event_id = de.id
WHERE de.protocol_name = 'raydium_clmm'
GROUP BY de.event_kind, ce.entry_name, ce.entry_kind, ce.event_family, ce.expected_db_target
HAVING
COALESCE(ce.expected_db_target, '') <> 'k_sol_dex_decoded_events_only'
AND (liquidity_count + fee_count + reward_count + admin_count + launch_count + lifecycle_count + orderbook_count + token_account_count + trade_count + failed_tx_count) < decoded_count
ORDER BY decoded_count DESC, de.event_kind;
->
raydium_clmm.liquidity_change_event liquidity_change_event event liquidity_change k_sol_liquidity_events 50 1 45 0 0 0 0 0 0 0 0
raydium_clmm.create_personal_position_event create_personal_position_event event position_open k_sol_liquidity_events 26 0 23 0 0 0 0 0 0 0 0
raydium_clmm.decrease_liquidity decrease_liquidity instruction liquidity_remove k_sol_liquidity_events 16 5 1 0 0 0 0 0 0 0 0
raydium_clmm.open_position_v2 open_position_v2 instruction position_open k_sol_liquidity_events 11 3 7 0 0 0 0 0 0 0 0
raydium_clmm.increase_liquidity_event increase_liquidity_event event liquidity_add k_sol_liquidity_events 9 0 8 0 0 0 0 0 0 0 0
raydium_clmm.open_position open_position instruction position_open k_sol_liquidity_events 9 5 1 0 0 0 0 0 0 0 0
raydium_clmm.increase_liquidity increase_liquidity instruction liquidity_add k_sol_liquidity_events 6 3 2 0 0 0 0 0 0 0 0
SELECT
de.event_kind,
COUNT(*) AS decoded_count,
COUNT(le.id) AS liquidity_count,
COUNT(fe.id) AS fee_count,
COUNT(re.id) AS reward_count,
COUNT(ae.id) AS admin_count,
COUNT(la.id) AS launch_count,
COUNT(pe.id) AS lifecycle_count,
COUNT(oe.id) AS orderbook_count,
COUNT(ta.id) AS token_account_count,
COUNT(te.id) AS trade_count
FROM k_sol_dex_decoded_events de
JOIN k_sol_chain_transactions tx ON tx.id = de.transaction_id
LEFT JOIN k_sol_liquidity_events le ON le.decoded_event_id = de.id
LEFT JOIN k_sol_fee_events fe ON fe.decoded_event_id = de.id
LEFT JOIN k_sol_reward_events re ON re.decoded_event_id = de.id
LEFT JOIN k_sol_pool_admin_events ae ON ae.decoded_event_id = de.id
LEFT JOIN k_sol_launch_events la ON la.decoded_event_id = de.id
LEFT JOIN k_sol_pool_lifecycle_events pe ON pe.decoded_event_id = de.id
LEFT JOIN k_sol_orderbook_events oe ON oe.decoded_event_id = de.id
LEFT JOIN k_sol_token_account_events ta ON ta.decoded_event_id = de.id
LEFT JOIN k_sol_trade_events te ON te.decoded_event_id = de.id
WHERE de.protocol_name = 'raydium_clmm'
AND tx.err_json IS NOT NULL
AND tx.err_json <> ''
AND tx.err_json <> 'null'
GROUP BY de.event_kind
HAVING
COUNT(le.id) > 0
OR COUNT(fe.id) > 0
OR COUNT(re.id) > 0
OR COUNT(ae.id) > 0
OR COUNT(la.id) > 0
OR COUNT(pe.id) > 0
OR COUNT(oe.id) > 0
OR COUNT(ta.id) > 0
OR COUNT(te.id) > 0
ORDER BY de.event_kind;
-> vide
-- 09. Residual instruction audit rows.
-- Expected: zero rows after full direct mapping.
SELECT
json_extract(payload_json, '$.discriminatorHex') AS discriminator_hex,
COUNT(*) AS audit_count,
COUNT(DISTINCT transaction_id) AS tx_count
FROM k_sol_dex_decoded_events
WHERE protocol_name = 'raydium_clmm'
AND event_kind = 'raydium_clmm.instruction_audit'
GROUP BY discriminator_hex
ORDER BY audit_count DESC, discriminator_hex;
-- 10. Redundant upstream fallback matches for locally covered entries.
-- Expected: zero rows.
SELECT
json_extract(ug.payload_json, '$.upstreamDecoderCode') AS upstream_decoder_code,
json_extract(ug.payload_json, '$.upstreamEntryName') AS entry_name,
json_extract(ug.payload_json, '$.upstreamDiscriminatorHex') AS discriminator_hex,
json_extract(ug.payload_json, '$.upstreamSourceRepo') AS source_repo,
COUNT(*) AS fallback_count,
COUNT(DISTINCT ug.transaction_id) AS tx_count
FROM k_sol_dex_decoded_events ug
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') = 'raydium_clmm'
GROUP BY upstream_decoder_code, entry_name, discriminator_hex, source_repo
ORDER BY fallback_count DESC, entry_name;
-- 11. Decoded event kinds without a coverage entry.
-- Expected: zero rows, excluding explicit `.instruction_audit` if it remains by design.
SELECT
de.event_kind,
COUNT(*) AS decoded_count
FROM k_sol_dex_decoded_events de
LEFT JOIN k_sol_dex_event_coverage_entries ce
ON ce.decoder_code = 'raydium_clmm'
AND ce.local_event_kind = de.event_kind
WHERE de.protocol_name = 'raydium_clmm'
AND ce.id IS NULL
GROUP BY de.event_kind
ORDER BY decoded_count DESC, de.event_kind;
-- 12. Non-swap decoded events that created trades.
-- Expected: zero rows.
SELECT
de.event_kind,
ce.event_family,
COUNT(*) AS decoded_count,
COUNT(te.id) AS trade_count
FROM k_sol_dex_decoded_events de
LEFT JOIN k_sol_dex_event_coverage_entries ce
ON ce.decoder_code = 'raydium_clmm'
AND ce.local_event_kind = de.event_kind
LEFT JOIN k_sol_trade_events te
ON te.decoded_event_id = de.id
WHERE de.protocol_name = 'raydium_clmm'
GROUP BY de.event_kind, ce.event_family
HAVING ce.event_family <> 'swap'
AND COUNT(te.id) > 0
ORDER BY trade_count DESC, de.event_kind;

View File

@@ -0,0 +1,272 @@
-- file: validation_sql/SQL_VALIDATION_RAYDIUM_CLMM_0_7_50_RECHECK.sql
-- Raydium CLMM 0.7.50 re-verification pack.
-- Goal: repeat the Launchpad-style closure checks on a dedicated CLMM
-- database, after replay with skipDexDecode='no' and forceDexDecode='yes'.
-- Expected invariants:
-- - no `unknown` or empty event_family except the synthetic `program` row;
-- - no observed discriminator missing from coverage;
-- - no residual upstream fallback for locally-covered entries;
-- - no successful, actionable decoded event left without its materialized row;
-- - no failed transaction materialized into business tables;
-- - decoded-only entries such as CPMM anchor IDL management and CLMM router/program-data
-- corroboration events are excluded from materialization shortfall checks.
-- 01. Coverage detail.
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 = 'raydium_clmm'
ORDER BY entry_kind, entry_name, discriminator_hex;
-- 02. Coverage summary.
SELECT
decoder_code,
COUNT(*) AS listed_entry_count,
SUM(CASE WHEN local_event_kind IS NOT NULL AND local_event_kind <> '' THEN 1 ELSE 0 END) AS decoded_entry_count,
SUM(CASE WHEN observed_count > 0 THEN 1 ELSE 0 END) AS observed_entry_count,
SUM(CASE WHEN materialized_count > 0 THEN 1 ELSE 0 END) AS materialized_entry_count,
COALESCE(SUM(observed_count), 0) AS total_observed_count,
COALESCE(SUM(materialized_count), 0) AS total_materialized_count,
COALESCE(SUM(trade_count), 0) AS trade_count
FROM k_sol_dex_event_coverage_entries
WHERE decoder_code = 'raydium_clmm'
GROUP BY decoder_code;
-- 03. Coverage family normalization guard.
-- Expected: zero rows, or only the synthetic `program` row if it intentionally has no family.
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 = 'raydium_clmm'
AND (
event_family IS NULL
OR event_family = ''
OR event_family = 'unknown'
)
AND entry_kind <> 'program'
ORDER BY entry_kind, entry_name;
-- 04. Instruction observations by discriminator.
SELECT
instruction_name,
discriminator_hex,
COUNT(*) AS observed_count,
COUNT(DISTINCT signature) AS tx_count
FROM k_sol_instruction_observations
WHERE decoder_code = 'raydium_clmm'
GROUP BY instruction_name, discriminator_hex
ORDER BY observed_count DESC, instruction_name, discriminator_hex;
-- 05. Observed discriminators absent from coverage.
-- Expected: zero rows.
SELECT
io.discriminator_hex,
MIN(io.instruction_name) AS sample_instruction_name,
MIN(io.decoded_event_kind) AS sample_decoded_event_kind,
COUNT(*) AS observed_count,
COUNT(DISTINCT io.signature) AS tx_count
FROM k_sol_instruction_observations io
LEFT JOIN k_sol_dex_event_coverage_entries ce
ON ce.decoder_code = 'raydium_clmm'
AND ce.discriminator_hex = io.discriminator_hex
WHERE io.decoder_code = 'raydium_clmm'
AND io.discriminator_hex IS NOT NULL
AND io.discriminator_hex <> ''
AND ce.id IS NULL
GROUP BY io.discriminator_hex
ORDER BY observed_count DESC, io.discriminator_hex;
-- 06. Decoded event distribution and materialization links.
SELECT
de.event_kind,
COUNT(*) AS decoded_count,
COUNT(le.id) AS liquidity_count,
COUNT(fe.id) AS fee_count,
COUNT(re.id) AS reward_count,
COUNT(ae.id) AS admin_count,
COUNT(la.id) AS launch_count,
COUNT(pe.id) AS lifecycle_count,
COUNT(oe.id) AS orderbook_count,
COUNT(ta.id) AS token_account_count,
COUNT(te.id) AS trade_count
FROM k_sol_dex_decoded_events de
LEFT JOIN k_sol_liquidity_events le ON le.decoded_event_id = de.id
LEFT JOIN k_sol_fee_events fe ON fe.decoded_event_id = de.id
LEFT JOIN k_sol_reward_events re ON re.decoded_event_id = de.id
LEFT JOIN k_sol_pool_admin_events ae ON ae.decoded_event_id = de.id
LEFT JOIN k_sol_launch_events la ON la.decoded_event_id = de.id
LEFT JOIN k_sol_pool_lifecycle_events pe ON pe.decoded_event_id = de.id
LEFT JOIN k_sol_orderbook_events oe ON oe.decoded_event_id = de.id
LEFT JOIN k_sol_token_account_events ta ON ta.decoded_event_id = de.id
LEFT JOIN k_sol_trade_events te ON te.decoded_event_id = de.id
WHERE de.protocol_name = 'raydium_clmm'
GROUP BY de.event_kind
ORDER BY decoded_count DESC, de.event_kind;
-- 07. Successful decoded events not materialized where coverage target says they should be.
-- Expected: zero rows, except expected_db_target='k_sol_dex_decoded_events_only' and failed tx rows.
SELECT
de.event_kind,
ce.entry_name,
ce.entry_kind,
ce.event_family,
ce.expected_db_target,
COUNT(*) AS decoded_count,
COUNT(CASE WHEN tx.err_json IS NOT NULL AND tx.err_json <> '' AND tx.err_json <> 'null' THEN de.id END) AS failed_tx_count,
COUNT(le.id) AS liquidity_count,
COUNT(fe.id) AS fee_count,
COUNT(re.id) AS reward_count,
COUNT(ae.id) AS admin_count,
COUNT(la.id) AS launch_count,
COUNT(pe.id) AS lifecycle_count,
COUNT(oe.id) AS orderbook_count,
COUNT(ta.id) AS token_account_count,
COUNT(te.id) AS trade_count
FROM k_sol_dex_decoded_events de
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 = 'raydium_clmm'
AND ce.local_event_kind = de.event_kind
LEFT JOIN k_sol_liquidity_events le ON le.decoded_event_id = de.id
LEFT JOIN k_sol_fee_events fe ON fe.decoded_event_id = de.id
LEFT JOIN k_sol_reward_events re ON re.decoded_event_id = de.id
LEFT JOIN k_sol_pool_admin_events ae ON ae.decoded_event_id = de.id
LEFT JOIN k_sol_launch_events la ON la.decoded_event_id = de.id
LEFT JOIN k_sol_pool_lifecycle_events pe ON pe.decoded_event_id = de.id
LEFT JOIN k_sol_orderbook_events oe ON oe.decoded_event_id = de.id
LEFT JOIN k_sol_token_account_events ta ON ta.decoded_event_id = de.id
LEFT JOIN k_sol_trade_events te ON te.decoded_event_id = de.id
WHERE de.protocol_name = 'raydium_clmm'
GROUP BY de.event_kind, ce.entry_name, ce.entry_kind, ce.event_family, ce.expected_db_target
HAVING
COALESCE(ce.expected_db_target, '') <> 'k_sol_dex_decoded_events_only'
AND (liquidity_count + fee_count + reward_count + admin_count + launch_count + lifecycle_count + orderbook_count + token_account_count + trade_count + failed_tx_count) < decoded_count
ORDER BY decoded_count DESC, de.event_kind;
-- 08. Failed transaction materialization guard.
-- Expected: zero rows.
SELECT
de.event_kind,
COUNT(*) AS decoded_count,
COUNT(le.id) AS liquidity_count,
COUNT(fe.id) AS fee_count,
COUNT(re.id) AS reward_count,
COUNT(ae.id) AS admin_count,
COUNT(la.id) AS launch_count,
COUNT(pe.id) AS lifecycle_count,
COUNT(oe.id) AS orderbook_count,
COUNT(ta.id) AS token_account_count,
COUNT(te.id) AS trade_count
FROM k_sol_dex_decoded_events de
JOIN k_sol_chain_transactions tx ON tx.id = de.transaction_id
LEFT JOIN k_sol_liquidity_events le ON le.decoded_event_id = de.id
LEFT JOIN k_sol_fee_events fe ON fe.decoded_event_id = de.id
LEFT JOIN k_sol_reward_events re ON re.decoded_event_id = de.id
LEFT JOIN k_sol_pool_admin_events ae ON ae.decoded_event_id = de.id
LEFT JOIN k_sol_launch_events la ON la.decoded_event_id = de.id
LEFT JOIN k_sol_pool_lifecycle_events pe ON pe.decoded_event_id = de.id
LEFT JOIN k_sol_orderbook_events oe ON oe.decoded_event_id = de.id
LEFT JOIN k_sol_token_account_events ta ON ta.decoded_event_id = de.id
LEFT JOIN k_sol_trade_events te ON te.decoded_event_id = de.id
WHERE de.protocol_name = 'raydium_clmm'
AND tx.err_json IS NOT NULL
AND tx.err_json <> ''
AND tx.err_json <> 'null'
GROUP BY de.event_kind
HAVING
COUNT(le.id) > 0
OR COUNT(fe.id) > 0
OR COUNT(re.id) > 0
OR COUNT(ae.id) > 0
OR COUNT(la.id) > 0
OR COUNT(pe.id) > 0
OR COUNT(oe.id) > 0
OR COUNT(ta.id) > 0
OR COUNT(te.id) > 0
ORDER BY de.event_kind;
-- 09. Residual instruction audit rows.
-- Expected: zero rows after full direct mapping.
SELECT
json_extract(payload_json, '$.discriminatorHex') AS discriminator_hex,
COUNT(*) AS audit_count,
COUNT(DISTINCT transaction_id) AS tx_count
FROM k_sol_dex_decoded_events
WHERE protocol_name = 'raydium_clmm'
AND event_kind = 'raydium_clmm.instruction_audit'
GROUP BY discriminator_hex
ORDER BY audit_count DESC, discriminator_hex;
-- 10. Redundant upstream fallback matches for locally covered entries.
-- Expected: zero rows.
SELECT
json_extract(ug.payload_json, '$.upstreamDecoderCode') AS upstream_decoder_code,
json_extract(ug.payload_json, '$.upstreamEntryName') AS entry_name,
json_extract(ug.payload_json, '$.upstreamDiscriminatorHex') AS discriminator_hex,
json_extract(ug.payload_json, '$.upstreamSourceRepo') AS source_repo,
COUNT(*) AS fallback_count,
COUNT(DISTINCT ug.transaction_id) AS tx_count
FROM k_sol_dex_decoded_events ug
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') = 'raydium_clmm'
GROUP BY upstream_decoder_code, entry_name, discriminator_hex, source_repo
ORDER BY fallback_count DESC, entry_name;
-- 11. Decoded event kinds without a coverage entry.
-- Expected: zero rows, excluding explicit `.instruction_audit` if it remains by design.
SELECT
de.event_kind,
COUNT(*) AS decoded_count
FROM k_sol_dex_decoded_events de
LEFT JOIN k_sol_dex_event_coverage_entries ce
ON ce.decoder_code = 'raydium_clmm'
AND ce.local_event_kind = de.event_kind
WHERE de.protocol_name = 'raydium_clmm'
AND ce.id IS NULL
GROUP BY de.event_kind
ORDER BY decoded_count DESC, de.event_kind;
-- 12. Non-swap decoded events that created trades.
-- Expected: zero rows.
SELECT
de.event_kind,
ce.event_family,
COUNT(*) AS decoded_count,
COUNT(te.id) AS trade_count
FROM k_sol_dex_decoded_events de
LEFT JOIN k_sol_dex_event_coverage_entries ce
ON ce.decoder_code = 'raydium_clmm'
AND ce.local_event_kind = de.event_kind
LEFT JOIN k_sol_trade_events te
ON te.decoded_event_id = de.id
WHERE de.protocol_name = 'raydium_clmm'
GROUP BY de.event_kind, ce.event_family
HAVING ce.event_family <> 'swap'
AND COUNT(te.id) > 0
ORDER BY trade_count DESC, de.event_kind;

View File

@@ -0,0 +1,315 @@
-- file: validation_sql/SQL_VALIDATION_RAYDIUM_CPMM_0_7_50_PRE_R2.sql
-- Raydium CPMM 0.7.50-pre-r2 re-verification pack.
-- Goal: repeat the Launchpad-style closure checks on a dedicated CPMM
-- database, after replay with skipDexDecode='no' and forceDexDecode='yes'.
-- Expected invariants:
-- - no `unknown` or empty event_family except the synthetic `program` row;
-- - no observed discriminator missing from coverage;
-- - no residual upstream fallback for locally-covered entries;
-- - no successful, actionable decoded event left without its materialized row;
-- - no failed transaction materialized into business tables;
-- - decoded-only entries such as CPMM anchor IDL management and CLMM router/program-data
-- corroboration events are excluded from materialization shortfall checks.
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 = 'raydium_cpmm'
ORDER BY entry_kind, entry_name, discriminator_hex;
->
lp_change_event event liquidity k_sol_liquidity_events upstream_git_local_corpus_materialized raydium_cpmm.lp_change_event 79a3cdc939da753c 25 25 0
swap_event event swap k_sol_dex_decoded_events_only upstream_git_local_corpus_observed raydium_cpmm.swap_event 40c6cde8260871e2 529 0 0
anchor_idl_instruction instruction idl_management k_sol_dex_decoded_events_only upstream_git_local_corpus_observed raydium_cpmm.anchor_idl_instruction 40f4bc78a7e9690a 6 0 0
close_permission_pda instruction admin_config k_sol_pool_admin_events upstream_git_mapped_unverified raydium_cpmm.close_permission_pda 9c5420764587467b 0 0 0
collect_creator_fee instruction fee k_sol_fee_events upstream_git_local_corpus_materialized raydium_cpmm.collect_creator_fee 1416567bc61cdb84 4 4 0
collect_fund_fee instruction fee k_sol_fee_events upstream_git_local_corpus_materialized raydium_cpmm.collect_fund_fee a78a4e95dfc2067e 7 7 0
collect_protocol_fee instruction fee k_sol_fee_events upstream_git_local_corpus_materialized raydium_cpmm.collect_protocol_fee 8888fcddc2427e59 15 15 0
cpi_event instruction cpi_transport k_sol_dex_decoded_events_only upstream_git_mapped_unverified raydium_cpmm.cpi_event e445a52e51cb9a1d 0 0 0
create_amm_config instruction admin_config k_sol_pool_admin_events upstream_git_local_corpus_materialized raydium_cpmm.create_amm_config 8934edd4d7756c68 6 6 0
create_permission_pda instruction admin_config k_sol_pool_admin_events upstream_git_local_corpus_materialized raydium_cpmm.create_permission_pda 878802d889a9b5ca 4 4 0
deposit instruction liquidity_add k_sol_liquidity_events upstream_git_local_corpus_materialized raydium_cpmm.deposit f223c68952e1f2b6 11 11 0
initialize instruction pool_create k_sol_pool_lifecycle_events upstream_git_local_corpus_materialized raydium_cpmm.initialize afaf6d1f0d989bed 5 5 0
initialize_with_permission instruction pool_create k_sol_pool_lifecycle_events upstream_git_local_corpus_materialized raydium_cpmm.initialize_with_permission 3f37fe4131b25979 4 4 0
swap_base_input instruction swap k_sol_trade_events upstream_git_local_corpus_materialized raydium_cpmm.swap_base_input 8fbe5adac41e33de 750 482 482
swap_base_output instruction swap k_sol_trade_events upstream_git_local_corpus_materialized raydium_cpmm.swap_base_output 37d96256a34ab4ad 25 17 17
update_amm_config instruction admin_config k_sol_pool_admin_events upstream_git_local_corpus_materialized raydium_cpmm.update_amm_config 313cae889a1c74c8 13 13 0
update_pool_status instruction admin_config k_sol_pool_admin_events upstream_git_mapped_unverified raydium_cpmm.update_pool_status 82576c062ee0757b 0 0 0
withdraw instruction liquidity_remove k_sol_liquidity_events upstream_git_local_corpus_materialized raydium_cpmm.withdraw b712469c946da122 14 14 0
program program k_sol_dex_decoded_events_only upstream_git_unverified 0 0 0
SELECT
decoder_code,
COUNT(*) AS listed_entry_count,
SUM(CASE WHEN local_event_kind IS NOT NULL AND local_event_kind <> '' THEN 1 ELSE 0 END) AS decoded_entry_count,
SUM(CASE WHEN observed_count > 0 THEN 1 ELSE 0 END) AS observed_entry_count,
SUM(CASE WHEN materialized_count > 0 THEN 1 ELSE 0 END) AS materialized_entry_count,
COALESCE(SUM(observed_count), 0) AS total_observed_count,
COALESCE(SUM(materialized_count), 0) AS total_materialized_count,
COALESCE(SUM(trade_count), 0) AS trade_count
FROM k_sol_dex_event_coverage_entries
WHERE decoder_code = 'raydium_cpmm'
GROUP BY decoder_code;
->
raydium_cpmm 19 18 15 13 1418 607 499
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 = 'raydium_cpmm'
AND (
event_family IS NULL
OR event_family = ''
OR event_family = 'unknown'
)
AND entry_kind <> 'program'
ORDER BY entry_kind, entry_name;
-> vide
SELECT
instruction_name,
discriminator_hex,
COUNT(*) AS observed_count,
COUNT(DISTINCT signature) AS tx_count
FROM k_sol_instruction_observations
WHERE decoder_code = 'raydium_cpmm'
GROUP BY instruction_name, discriminator_hex
ORDER BY observed_count DESC, instruction_name, discriminator_hex;
->
raydium_cpmm.swap_base_input 8fbe5adac41e33de 750 741
raydium_cpmm.swap_base_output 37d96256a34ab4ad 25 25
raydium_cpmm.collect_protocol_fee 8888fcddc2427e59 15 15
raydium_cpmm.withdraw b712469c946da122 14 13
raydium_cpmm.update_amm_config 313cae889a1c74c8 13 5
raydium_cpmm.deposit f223c68952e1f2b6 11 11
raydium_cpmm.collect_fund_fee a78a4e95dfc2067e 7 7
raydium_cpmm.create_amm_config 8934edd4d7756c68 6 4
raydium_cpmm.initialize afaf6d1f0d989bed 5 5
raydium_cpmm.collect_creator_fee 1416567bc61cdb84 4 4
raydium_cpmm.create_permission_pda 878802d889a9b5ca 4 4
raydium_cpmm.initialize_with_permission 3f37fe4131b25979 4 4
40f4bc78a7e9690a 3 3
SELECT
io.discriminator_hex,
MIN(io.instruction_name) AS sample_instruction_name,
MIN(io.decoded_event_kind) AS sample_decoded_event_kind,
COUNT(*) AS observed_count,
COUNT(DISTINCT io.signature) AS tx_count
FROM k_sol_instruction_observations io
LEFT JOIN k_sol_dex_event_coverage_entries ce
ON ce.decoder_code = 'raydium_cpmm'
AND ce.discriminator_hex = io.discriminator_hex
WHERE io.decoder_code = 'raydium_cpmm'
AND io.discriminator_hex IS NOT NULL
AND io.discriminator_hex <> ''
AND ce.id IS NULL
GROUP BY io.discriminator_hex
ORDER BY observed_count DESC, io.discriminator_hex;
-> vide
SELECT
de.event_kind,
COUNT(*) AS decoded_count,
COUNT(le.id) AS liquidity_count,
COUNT(fe.id) AS fee_count,
COUNT(re.id) AS reward_count,
COUNT(ae.id) AS admin_count,
COUNT(la.id) AS launch_count,
COUNT(pe.id) AS lifecycle_count,
COUNT(oe.id) AS orderbook_count,
COUNT(ta.id) AS token_account_count,
COUNT(te.id) AS trade_count
FROM k_sol_dex_decoded_events de
LEFT JOIN k_sol_liquidity_events le ON le.decoded_event_id = de.id
LEFT JOIN k_sol_fee_events fe ON fe.decoded_event_id = de.id
LEFT JOIN k_sol_reward_events re ON re.decoded_event_id = de.id
LEFT JOIN k_sol_pool_admin_events ae ON ae.decoded_event_id = de.id
LEFT JOIN k_sol_launch_events la ON la.decoded_event_id = de.id
LEFT JOIN k_sol_pool_lifecycle_events pe ON pe.decoded_event_id = de.id
LEFT JOIN k_sol_orderbook_events oe ON oe.decoded_event_id = de.id
LEFT JOIN k_sol_token_account_events ta ON ta.decoded_event_id = de.id
LEFT JOIN k_sol_trade_events te ON te.decoded_event_id = de.id
WHERE de.protocol_name = 'raydium_cpmm'
GROUP BY de.event_kind
ORDER BY decoded_count DESC, de.event_kind;
->
raydium_cpmm.swap_base_input 750 0 0 0 0 0 0 0 0 482
raydium_cpmm.swap_event 529 0 0 0 0 0 0 0 0 0
raydium_cpmm.lp_change_event 25 25 0 0 0 0 0 0 0 0
raydium_cpmm.swap_base_output 25 0 0 0 0 0 0 0 0 17
raydium_cpmm.collect_protocol_fee 15 0 15 0 0 0 0 0 0 0
raydium_cpmm.withdraw 14 14 0 0 0 0 0 0 0 0
raydium_cpmm.update_amm_config 13 0 0 0 13 0 0 0 0 0
raydium_cpmm.deposit 11 11 0 0 0 0 0 0 0 0
raydium_cpmm.collect_fund_fee 7 0 7 0 0 0 0 0 0 0
raydium_cpmm.create_amm_config 6 0 0 0 6 0 0 0 0 0
raydium_cpmm.initialize 5 0 0 0 0 0 5 0 0 0
raydium_cpmm.collect_creator_fee 4 0 4 0 0 0 0 0 0 0
raydium_cpmm.create_permission_pda 4 0 0 0 4 0 0 0 0 0
raydium_cpmm.initialize_with_permission 4 0 0 0 0 0 4 0 0 0
raydium_cpmm.anchor_idl_instruction 3 0 0 0 0 0 0 0 0 0
raydium_cpmm.instruction_audit 3 0 0 0 0 0 0 0 0 0
SELECT
de.event_kind,
ce.entry_name,
ce.entry_kind,
ce.event_family,
ce.expected_db_target,
COUNT(*) AS decoded_count,
COUNT(CASE WHEN tx.err_json IS NOT NULL AND tx.err_json <> '' AND tx.err_json <> 'null' THEN de.id END) AS failed_tx_count,
COUNT(le.id) AS liquidity_count,
COUNT(fe.id) AS fee_count,
COUNT(re.id) AS reward_count,
COUNT(ae.id) AS admin_count,
COUNT(la.id) AS launch_count,
COUNT(pe.id) AS lifecycle_count,
COUNT(oe.id) AS orderbook_count,
COUNT(ta.id) AS token_account_count,
COUNT(te.id) AS trade_count
FROM k_sol_dex_decoded_events de
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 = 'raydium_cpmm'
AND ce.local_event_kind = de.event_kind
LEFT JOIN k_sol_liquidity_events le ON le.decoded_event_id = de.id
LEFT JOIN k_sol_fee_events fe ON fe.decoded_event_id = de.id
LEFT JOIN k_sol_reward_events re ON re.decoded_event_id = de.id
LEFT JOIN k_sol_pool_admin_events ae ON ae.decoded_event_id = de.id
LEFT JOIN k_sol_launch_events la ON la.decoded_event_id = de.id
LEFT JOIN k_sol_pool_lifecycle_events pe ON pe.decoded_event_id = de.id
LEFT JOIN k_sol_orderbook_events oe ON oe.decoded_event_id = de.id
LEFT JOIN k_sol_token_account_events ta ON ta.decoded_event_id = de.id
LEFT JOIN k_sol_trade_events te ON te.decoded_event_id = de.id
WHERE de.protocol_name = 'raydium_cpmm'
GROUP BY de.event_kind, ce.entry_name, ce.entry_kind, ce.event_family, ce.expected_db_target
HAVING
COALESCE(ce.expected_db_target, '') <> 'k_sol_dex_decoded_events_only'
AND (liquidity_count + fee_count + reward_count + admin_count + launch_count + lifecycle_count + orderbook_count + token_account_count + trade_count + failed_tx_count) < decoded_count
ORDER BY decoded_count DESC, de.event_kind;
-> vide
SELECT
de.event_kind,
COUNT(*) AS decoded_count,
COUNT(le.id) AS liquidity_count,
COUNT(fe.id) AS fee_count,
COUNT(re.id) AS reward_count,
COUNT(ae.id) AS admin_count,
COUNT(la.id) AS launch_count,
COUNT(pe.id) AS lifecycle_count,
COUNT(oe.id) AS orderbook_count,
COUNT(ta.id) AS token_account_count,
COUNT(te.id) AS trade_count
FROM k_sol_dex_decoded_events de
JOIN k_sol_chain_transactions tx ON tx.id = de.transaction_id
LEFT JOIN k_sol_liquidity_events le ON le.decoded_event_id = de.id
LEFT JOIN k_sol_fee_events fe ON fe.decoded_event_id = de.id
LEFT JOIN k_sol_reward_events re ON re.decoded_event_id = de.id
LEFT JOIN k_sol_pool_admin_events ae ON ae.decoded_event_id = de.id
LEFT JOIN k_sol_launch_events la ON la.decoded_event_id = de.id
LEFT JOIN k_sol_pool_lifecycle_events pe ON pe.decoded_event_id = de.id
LEFT JOIN k_sol_orderbook_events oe ON oe.decoded_event_id = de.id
LEFT JOIN k_sol_token_account_events ta ON ta.decoded_event_id = de.id
LEFT JOIN k_sol_trade_events te ON te.decoded_event_id = de.id
WHERE de.protocol_name = 'raydium_cpmm'
AND tx.err_json IS NOT NULL
AND tx.err_json <> ''
AND tx.err_json <> 'null'
GROUP BY de.event_kind
HAVING
COUNT(le.id) > 0
OR COUNT(fe.id) > 0
OR COUNT(re.id) > 0
OR COUNT(ae.id) > 0
OR COUNT(la.id) > 0
OR COUNT(pe.id) > 0
OR COUNT(oe.id) > 0
OR COUNT(ta.id) > 0
OR COUNT(te.id) > 0
ORDER BY de.event_kind;
-> vide
SELECT
json_extract(payload_json, '$.discriminatorHex') AS discriminator_hex,
COUNT(*) AS audit_count,
COUNT(DISTINCT transaction_id) AS tx_count
FROM k_sol_dex_decoded_events
WHERE protocol_name = 'raydium_cpmm'
AND event_kind = 'raydium_cpmm.instruction_audit'
GROUP BY discriminator_hex
ORDER BY audit_count DESC, discriminator_hex;
->
40f4bc78a7e9690a 3 3
SELECT
json_extract(ug.payload_json, '$.upstreamDecoderCode') AS upstream_decoder_code,
json_extract(ug.payload_json, '$.upstreamEntryName') AS entry_name,
json_extract(ug.payload_json, '$.upstreamDiscriminatorHex') AS discriminator_hex,
json_extract(ug.payload_json, '$.upstreamSourceRepo') AS source_repo,
COUNT(*) AS fallback_count,
COUNT(DISTINCT ug.transaction_id) AS tx_count
FROM k_sol_dex_decoded_events ug
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') = 'raydium_cpmm'
GROUP BY upstream_decoder_code, entry_name, discriminator_hex, source_repo
ORDER BY fallback_count DESC, entry_name;
-> vide
SELECT
de.event_kind,
COUNT(*) AS decoded_count
FROM k_sol_dex_decoded_events de
LEFT JOIN k_sol_dex_event_coverage_entries ce
ON ce.decoder_code = 'raydium_cpmm'
AND ce.local_event_kind = de.event_kind
WHERE de.protocol_name = 'raydium_cpmm'
AND ce.id IS NULL
GROUP BY de.event_kind
ORDER BY decoded_count DESC, de.event_kind;
->
raydium_cpmm.instruction_audit 3
SELECT
de.event_kind,
ce.event_family,
COUNT(*) AS decoded_count,
COUNT(te.id) AS trade_count
FROM k_sol_dex_decoded_events de
LEFT JOIN k_sol_dex_event_coverage_entries ce
ON ce.decoder_code = 'raydium_cpmm'
AND ce.local_event_kind = de.event_kind
LEFT JOIN k_sol_trade_events te
ON te.decoded_event_id = de.id
WHERE de.protocol_name = 'raydium_cpmm'
GROUP BY de.event_kind, ce.event_family
HAVING ce.event_family <> 'swap'
AND COUNT(te.id) > 0
ORDER BY trade_count DESC, de.event_kind;
-> vide

View File

@@ -0,0 +1,273 @@
-- file: validation_sql/SQL_VALIDATION_RAYDIUM_CPMM_0_7_50_RECHECK.sql
-- Raydium CPMM 0.7.50 re-verification pack.
-- Goal: repeat the Launchpad-style closure checks on a dedicated CPMM
-- database, after replay with skipDexDecode='no' and forceDexDecode='yes'.
-- Expected invariants:
-- - no `unknown` or empty event_family except the synthetic `program` row;
-- - no observed discriminator missing from coverage;
-- - no residual upstream fallback for locally-covered entries;
-- - no successful, actionable decoded event left without its materialized row;
-- - no failed transaction materialized into business tables;
-- - decoded-only entries such as CPMM anchor IDL management and CLMM router/program-data
-- corroboration events are excluded from materialization shortfall checks.
-- 01. Coverage detail.
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 = 'raydium_cpmm'
ORDER BY entry_kind, entry_name, discriminator_hex;
-- 02. Coverage summary.
SELECT
decoder_code,
COUNT(*) AS listed_entry_count,
SUM(CASE WHEN local_event_kind IS NOT NULL AND local_event_kind <> '' THEN 1 ELSE 0 END) AS decoded_entry_count,
SUM(CASE WHEN observed_count > 0 THEN 1 ELSE 0 END) AS observed_entry_count,
SUM(CASE WHEN materialized_count > 0 THEN 1 ELSE 0 END) AS materialized_entry_count,
COALESCE(SUM(observed_count), 0) AS total_observed_count,
COALESCE(SUM(materialized_count), 0) AS total_materialized_count,
COALESCE(SUM(trade_count), 0) AS trade_count
FROM k_sol_dex_event_coverage_entries
WHERE decoder_code = 'raydium_cpmm'
GROUP BY decoder_code;
-- 03. Coverage family normalization guard.
-- Expected: zero rows, or only the synthetic `program` row if it intentionally has no family.
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 = 'raydium_cpmm'
AND (
event_family IS NULL
OR event_family = ''
OR event_family = 'unknown'
)
AND entry_kind <> 'program'
ORDER BY entry_kind, entry_name;
-- 04. Instruction observations by discriminator.
SELECT
instruction_name,
discriminator_hex,
COUNT(*) AS observed_count,
COUNT(DISTINCT signature) AS tx_count
FROM k_sol_instruction_observations
WHERE decoder_code = 'raydium_cpmm'
GROUP BY instruction_name, discriminator_hex
ORDER BY observed_count DESC, instruction_name, discriminator_hex;
-- 05. Observed discriminators absent from coverage.
-- Expected: zero rows.
SELECT
io.discriminator_hex,
MIN(io.instruction_name) AS sample_instruction_name,
MIN(io.decoded_event_kind) AS sample_decoded_event_kind,
COUNT(*) AS observed_count,
COUNT(DISTINCT io.signature) AS tx_count
FROM k_sol_instruction_observations io
LEFT JOIN k_sol_dex_event_coverage_entries ce
ON ce.decoder_code = 'raydium_cpmm'
AND ce.discriminator_hex = io.discriminator_hex
WHERE io.decoder_code = 'raydium_cpmm'
AND io.discriminator_hex IS NOT NULL
AND io.discriminator_hex <> ''
AND ce.id IS NULL
GROUP BY io.discriminator_hex
ORDER BY observed_count DESC, io.discriminator_hex;
-- 06. Decoded event distribution and materialization links.
SELECT
de.event_kind,
COUNT(*) AS decoded_count,
COUNT(le.id) AS liquidity_count,
COUNT(fe.id) AS fee_count,
COUNT(re.id) AS reward_count,
COUNT(ae.id) AS admin_count,
COUNT(la.id) AS launch_count,
COUNT(pe.id) AS lifecycle_count,
COUNT(oe.id) AS orderbook_count,
COUNT(ta.id) AS token_account_count,
COUNT(te.id) AS trade_count
FROM k_sol_dex_decoded_events de
LEFT JOIN k_sol_liquidity_events le ON le.decoded_event_id = de.id
LEFT JOIN k_sol_fee_events fe ON fe.decoded_event_id = de.id
LEFT JOIN k_sol_reward_events re ON re.decoded_event_id = de.id
LEFT JOIN k_sol_pool_admin_events ae ON ae.decoded_event_id = de.id
LEFT JOIN k_sol_launch_events la ON la.decoded_event_id = de.id
LEFT JOIN k_sol_pool_lifecycle_events pe ON pe.decoded_event_id = de.id
LEFT JOIN k_sol_orderbook_events oe ON oe.decoded_event_id = de.id
LEFT JOIN k_sol_token_account_events ta ON ta.decoded_event_id = de.id
LEFT JOIN k_sol_trade_events te ON te.decoded_event_id = de.id
WHERE de.protocol_name = 'raydium_cpmm'
GROUP BY de.event_kind
ORDER BY decoded_count DESC, de.event_kind;
-- 07. Successful decoded events not materialized where coverage target says they should be.
-- Expected: zero rows, except expected_db_target='k_sol_dex_decoded_events_only' and failed tx rows.
SELECT
de.event_kind,
ce.entry_name,
ce.entry_kind,
ce.event_family,
ce.expected_db_target,
COUNT(*) AS decoded_count,
COUNT(CASE WHEN tx.err_json IS NOT NULL AND tx.err_json <> '' AND tx.err_json <> 'null' THEN de.id END) AS failed_tx_count,
COUNT(le.id) AS liquidity_count,
COUNT(fe.id) AS fee_count,
COUNT(re.id) AS reward_count,
COUNT(ae.id) AS admin_count,
COUNT(la.id) AS launch_count,
COUNT(pe.id) AS lifecycle_count,
COUNT(oe.id) AS orderbook_count,
COUNT(ta.id) AS token_account_count,
COUNT(te.id) AS trade_count
FROM k_sol_dex_decoded_events de
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 = 'raydium_cpmm'
AND ce.local_event_kind = de.event_kind
LEFT JOIN k_sol_liquidity_events le ON le.decoded_event_id = de.id
LEFT JOIN k_sol_fee_events fe ON fe.decoded_event_id = de.id
LEFT JOIN k_sol_reward_events re ON re.decoded_event_id = de.id
LEFT JOIN k_sol_pool_admin_events ae ON ae.decoded_event_id = de.id
LEFT JOIN k_sol_launch_events la ON la.decoded_event_id = de.id
LEFT JOIN k_sol_pool_lifecycle_events pe ON pe.decoded_event_id = de.id
LEFT JOIN k_sol_orderbook_events oe ON oe.decoded_event_id = de.id
LEFT JOIN k_sol_token_account_events ta ON ta.decoded_event_id = de.id
LEFT JOIN k_sol_trade_events te ON te.decoded_event_id = de.id
WHERE de.protocol_name = 'raydium_cpmm'
GROUP BY de.event_kind, ce.entry_name, ce.entry_kind, ce.event_family, ce.expected_db_target
HAVING
COALESCE(ce.expected_db_target, '') <> 'k_sol_dex_decoded_events_only'
AND (liquidity_count + fee_count + reward_count + admin_count + launch_count + lifecycle_count + orderbook_count + token_account_count + trade_count + failed_tx_count) < decoded_count
ORDER BY decoded_count DESC, de.event_kind;
-- 08. Failed transaction materialization guard.
-- Expected: zero rows.
SELECT
de.event_kind,
COUNT(*) AS decoded_count,
COUNT(le.id) AS liquidity_count,
COUNT(fe.id) AS fee_count,
COUNT(re.id) AS reward_count,
COUNT(ae.id) AS admin_count,
COUNT(la.id) AS launch_count,
COUNT(pe.id) AS lifecycle_count,
COUNT(oe.id) AS orderbook_count,
COUNT(ta.id) AS token_account_count,
COUNT(te.id) AS trade_count
FROM k_sol_dex_decoded_events de
JOIN k_sol_chain_transactions tx ON tx.id = de.transaction_id
LEFT JOIN k_sol_liquidity_events le ON le.decoded_event_id = de.id
LEFT JOIN k_sol_fee_events fe ON fe.decoded_event_id = de.id
LEFT JOIN k_sol_reward_events re ON re.decoded_event_id = de.id
LEFT JOIN k_sol_pool_admin_events ae ON ae.decoded_event_id = de.id
LEFT JOIN k_sol_launch_events la ON la.decoded_event_id = de.id
LEFT JOIN k_sol_pool_lifecycle_events pe ON pe.decoded_event_id = de.id
LEFT JOIN k_sol_orderbook_events oe ON oe.decoded_event_id = de.id
LEFT JOIN k_sol_token_account_events ta ON ta.decoded_event_id = de.id
LEFT JOIN k_sol_trade_events te ON te.decoded_event_id = de.id
WHERE de.protocol_name = 'raydium_cpmm'
AND tx.err_json IS NOT NULL
AND tx.err_json <> ''
AND tx.err_json <> 'null'
GROUP BY de.event_kind
HAVING
COUNT(le.id) > 0
OR COUNT(fe.id) > 0
OR COUNT(re.id) > 0
OR COUNT(ae.id) > 0
OR COUNT(la.id) > 0
OR COUNT(pe.id) > 0
OR COUNT(oe.id) > 0
OR COUNT(ta.id) > 0
OR COUNT(te.id) > 0
ORDER BY de.event_kind;
-- 09. Residual instruction audit rows.
-- Expected: zero rows after full direct mapping. `40f4bc78a7e9690a` should now
-- appear as `raydium_cpmm.anchor_idl_instruction`, not instruction_audit.
SELECT
json_extract(payload_json, '$.discriminatorHex') AS discriminator_hex,
COUNT(*) AS audit_count,
COUNT(DISTINCT transaction_id) AS tx_count
FROM k_sol_dex_decoded_events
WHERE protocol_name = 'raydium_cpmm'
AND event_kind = 'raydium_cpmm.instruction_audit'
GROUP BY discriminator_hex
ORDER BY audit_count DESC, discriminator_hex;
-- 10. Redundant upstream fallback matches for locally covered entries.
-- Expected: zero rows.
SELECT
json_extract(ug.payload_json, '$.upstreamDecoderCode') AS upstream_decoder_code,
json_extract(ug.payload_json, '$.upstreamEntryName') AS entry_name,
json_extract(ug.payload_json, '$.upstreamDiscriminatorHex') AS discriminator_hex,
json_extract(ug.payload_json, '$.upstreamSourceRepo') AS source_repo,
COUNT(*) AS fallback_count,
COUNT(DISTINCT ug.transaction_id) AS tx_count
FROM k_sol_dex_decoded_events ug
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') = 'raydium_cpmm'
GROUP BY upstream_decoder_code, entry_name, discriminator_hex, source_repo
ORDER BY fallback_count DESC, entry_name;
-- 11. Decoded event kinds without a coverage entry.
-- Expected: zero rows, excluding explicit `.instruction_audit` if it remains by design.
SELECT
de.event_kind,
COUNT(*) AS decoded_count
FROM k_sol_dex_decoded_events de
LEFT JOIN k_sol_dex_event_coverage_entries ce
ON ce.decoder_code = 'raydium_cpmm'
AND ce.local_event_kind = de.event_kind
WHERE de.protocol_name = 'raydium_cpmm'
AND ce.id IS NULL
GROUP BY de.event_kind
ORDER BY decoded_count DESC, de.event_kind;
-- 12. Non-swap decoded events that created trades.
-- Expected: zero rows.
SELECT
de.event_kind,
ce.event_family,
COUNT(*) AS decoded_count,
COUNT(te.id) AS trade_count
FROM k_sol_dex_decoded_events de
LEFT JOIN k_sol_dex_event_coverage_entries ce
ON ce.decoder_code = 'raydium_cpmm'
AND ce.local_event_kind = de.event_kind
LEFT JOIN k_sol_trade_events te
ON te.decoded_event_id = de.id
WHERE de.protocol_name = 'raydium_cpmm'
GROUP BY de.event_kind, ce.event_family
HAVING ce.event_family <> 'swap'
AND COUNT(te.id) > 0
ORDER BY trade_count DESC, de.event_kind;

View File

@@ -0,0 +1,46 @@
-- file: validation_sql/SQL_VALIDATION_RAYDIUM_CPMM_AUDIT_CLEANUP_0_7_50_FINAL.sql
-- Raydium CPMM residual audit cleanup validation for 0.7.50 final.
-- These queries must be empty after applying the final cleanup patch and replaying with
-- skipDexDecode=no, forceDexDecode=yes, deferInstructionObservations=yes.
SELECT
json_extract(payload_json, '$.discriminatorHex') AS discriminator_hex,
COUNT(*) AS audit_count,
COUNT(DISTINCT transaction_id) AS tx_count
FROM k_sol_dex_decoded_events
WHERE protocol_name = 'raydium_cpmm'
AND event_kind = 'raydium_cpmm.instruction_audit'
GROUP BY discriminator_hex
ORDER BY audit_count DESC, discriminator_hex;
SELECT
de.event_kind,
COUNT(*) AS decoded_count
FROM k_sol_dex_decoded_events de
LEFT JOIN k_sol_dex_event_coverage_entries ce
ON ce.decoder_code = 'raydium_cpmm'
AND ce.local_event_kind = de.event_kind
WHERE de.protocol_name = 'raydium_cpmm'
AND ce.id IS NULL
GROUP BY de.event_kind
ORDER BY decoded_count DESC, de.event_kind;
-- Manual emergency cleanup only if the application replay still leaves the legacy audit rows.
-- It intentionally unlinks k_sol_instruction_observations first, because existing DBs created
-- before ON DELETE SET NULL may otherwise retain decoded_event_id references.
UPDATE k_sol_instruction_observations
SET decoded_event_id = NULL
WHERE decoded_event_id IN (
SELECT id
FROM k_sol_dex_decoded_events
WHERE protocol_name = 'raydium_cpmm'
AND event_kind = 'raydium_cpmm.instruction_audit'
AND instr(lower(COALESCE(payload_json, '')), '40f4bc78a7e9690a') > 0
);
DELETE FROM k_sol_dex_decoded_events
WHERE protocol_name = 'raydium_cpmm'
AND event_kind = 'raydium_cpmm.instruction_audit'
AND instr(lower(COALESCE(payload_json, '')), '40f4bc78a7e9690a') > 0;

View File

@@ -0,0 +1,347 @@
-- file: validation_sql/SQL_VALIDATION_RAYDIUM_LAUNCHPAD_0_7_50.sql
-- Raydium Launchpad 0.7.50 validation pack.
-- Notes:
-- - k_sol_pools uses column `address`, not `pool_address`.
-- - raydium_pool_v4 is deliberately excluded from runtime validation until its
-- program id and role are confirmed from source/corpus audit.
-- 01. Coverage detail.
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 = 'raydium_launchpad'
ORDER BY entry_kind, entry_name, discriminator_hex;
-- 02. Coverage summary.
SELECT
decoder_code,
COUNT(*) AS listed_entry_count,
SUM(CASE WHEN local_event_kind IS NOT NULL AND local_event_kind <> '' THEN 1 ELSE 0 END) AS decoded_entry_count,
SUM(CASE WHEN observed_count > 0 THEN 1 ELSE 0 END) AS observed_entry_count,
SUM(CASE WHEN materialized_count > 0 THEN 1 ELSE 0 END) AS materialized_entry_count,
COALESCE(SUM(observed_count), 0) AS total_observed_count,
COALESCE(SUM(materialized_count), 0) AS total_materialized_count,
COALESCE(SUM(trade_count), 0) AS trade_count
FROM k_sol_dex_event_coverage_entries
WHERE decoder_code = 'raydium_launchpad'
GROUP BY decoder_code;
-- 03. Instruction observations.
SELECT
instruction_name,
discriminator_hex,
COUNT(*) AS observed_count,
COUNT(DISTINCT signature) AS tx_count
FROM k_sol_instruction_observations
WHERE decoder_code = 'raydium_launchpad'
GROUP BY instruction_name, discriminator_hex
ORDER BY observed_count DESC, instruction_name;
-- 04. Decoded event distribution.
SELECT
de.event_kind,
COUNT(*) AS decoded_count,
COUNT(te.id) AS trade_count
FROM k_sol_dex_decoded_events de
LEFT JOIN k_sol_trade_events te
ON te.decoded_event_id = de.id
WHERE de.protocol_name = 'raydium_launchpad'
GROUP BY de.event_kind
ORDER BY decoded_count DESC, de.event_kind;
-- 05. Upstream fallback residual. Expected: empty.
SELECT
json_extract(payload_json, '$.upstreamDecoderCode') AS upstream_decoder_code,
json_extract(payload_json, '$.upstreamEntryName') AS entry_name,
json_extract(payload_json, '$.upstreamDiscriminatorHex') AS discriminator_hex,
COUNT(*) AS fallback_count
FROM k_sol_dex_decoded_events
WHERE protocol_name = 'upstream_git'
AND event_kind = 'upstream_git.instruction_match'
AND json_extract(payload_json, '$.upstreamDecoderCode') = 'raydium_launchpad'
GROUP BY upstream_decoder_code, entry_name, discriminator_hex
ORDER BY fallback_count DESC, entry_name;
-- 06. Failed transaction materialization guard. Expected: trade_count = 0.
SELECT
de.event_kind,
COUNT(*) AS decoded_count,
COUNT(te.id) AS trade_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
WHERE de.protocol_name = 'raydium_launchpad'
AND tx.err_json IS NOT NULL
AND tx.err_json <> ''
AND tx.err_json <> 'null'
GROUP BY de.event_kind
ORDER BY trade_count DESC, decoded_count DESC;
-- 07. Residual audit discriminators.
-- Expected after pre5: e445a52e51cb9a1d should no longer remain in decoded audit rows.
SELECT
json_extract(payload_json, '$.discriminatorHex') AS discriminator_hex,
COUNT(*) AS audit_count,
COUNT(DISTINCT transaction_id) AS tx_count
FROM k_sol_dex_decoded_events
WHERE protocol_name = 'raydium_launchpad'
AND event_kind = 'raydium_launchpad.instruction_audit'
GROUP BY discriminator_hex
ORDER BY audit_count DESC, discriminator_hex;
-- 08. Self-CPI transport still present inside residual audit rows.
-- Expected after pre5: empty for known embedded event discriminators.
SELECT
json_extract(payload_json, '$.anchorSelfCpiLog') AS anchor_self_cpi_log,
json_extract(payload_json, '$.anchorSelfCpiLogSelectorHex') AS cpi_selector_hex,
json_extract(payload_json, '$.anchorEventDiscriminatorHex') AS anchor_event_discriminator_hex,
COUNT(*) AS decoded_count,
COUNT(DISTINCT transaction_id) AS tx_count
FROM k_sol_dex_decoded_events
WHERE protocol_name = 'raydium_launchpad'
AND event_kind = 'raydium_launchpad.instruction_audit'
AND json_extract(payload_json, '$.anchorSelfCpiLog') = 1
GROUP BY
anchor_self_cpi_log,
cpi_selector_hex,
anchor_event_discriminator_hex
ORDER BY decoded_count DESC, anchor_event_discriminator_hex;
-- 09. Direct Launchpad self-CPI events.
SELECT
event_kind,
json_extract(payload_json, '$.anchorEventDiscriminatorHex') AS anchor_event_discriminator_hex,
COUNT(*) AS decoded_count,
COUNT(DISTINCT transaction_id) AS tx_count
FROM k_sol_dex_decoded_events
WHERE protocol_name = 'raydium_launchpad'
AND event_kind IN (
'raydium_launchpad.trade_event',
'raydium_launchpad.pool_create_event',
'raydium_launchpad.claim_vested_event',
'raydium_launchpad.create_vesting_event'
)
GROUP BY event_kind, anchor_event_discriminator_hex
ORDER BY decoded_count DESC, event_kind;
-- 10. Launchpad initialize* pool hints.
SELECT
de.event_kind,
de.pool_account,
de.token_a_mint,
de.token_b_mint,
json_extract(de.payload_json, '$.instructionName') AS instruction_name,
COUNT(*) AS decoded_count,
COUNT(DISTINCT de.transaction_id) AS tx_count
FROM k_sol_dex_decoded_events de
WHERE de.protocol_name = 'raydium_launchpad'
AND de.event_kind IN (
'raydium_launchpad.initialize',
'raydium_launchpad.initialize_v2',
'raydium_launchpad.initialize_with_token_2022'
)
GROUP BY
de.event_kind,
de.pool_account,
de.token_a_mint,
de.token_b_mint,
instruction_name
ORDER BY decoded_count DESC, de.event_kind;
-- 11. Launchpad pool/pair catalog materialized from initialize*.
SELECT
p.address AS pool_address,
pa.id AS pair_id,
d.code AS dex_code,
bt.mint AS base_mint,
bt.symbol AS base_symbol,
qt.mint AS quote_mint,
qt.symbol AS quote_symbol,
p.pool_kind,
p.status
FROM k_sol_pools p
JOIN k_sol_dexes d
ON d.id = p.dex_id
LEFT JOIN k_sol_pairs pa
ON pa.pool_id = p.id
LEFT JOIN k_sol_tokens bt
ON bt.id = pa.base_token_id
LEFT JOIN k_sol_tokens qt
ON qt.id = pa.quote_token_id
WHERE d.code = 'raydium_launchpad'
ORDER BY p.id DESC;
-- 12. Specific pool/pair probe.
SELECT
p.address AS pool_address,
pa.id AS pair_id,
d.code AS dex_code
FROM k_sol_pools p
JOIN k_sol_dexes d
ON d.id = p.dex_id
LEFT JOIN k_sol_pairs pa
ON pa.pool_id = p.id
WHERE p.address = '6HLQPoLrzX6LqePRiXQ1GGs2Dd9K3dp9VhTSHBugYzzZ';
-- 13. Pool-create events that do not yet have normalized local catalog rows.
SELECT
de.pool_account,
COUNT(*) AS decoded_count,
COUNT(DISTINCT de.transaction_id) AS tx_count
FROM k_sol_dex_decoded_events de
LEFT JOIN k_sol_pools p
ON p.address = de.pool_account
WHERE de.protocol_name = 'raydium_launchpad'
AND de.event_kind = 'raydium_launchpad.pool_create_event'
AND p.id IS NULL
GROUP BY de.pool_account
ORDER BY decoded_count DESC, de.pool_account;
-- 14. Launchpad buy/sell instruction pool hints used to backfill catalog rows.
SELECT
de.event_kind,
de.pool_account,
de.token_a_mint,
de.token_b_mint,
json_extract(de.payload_json, '$.instructionName') AS instruction_name,
COUNT(*) AS decoded_count,
COUNT(DISTINCT de.transaction_id) AS tx_count
FROM k_sol_dex_decoded_events de
WHERE de.protocol_name = 'raydium_launchpad'
AND de.event_kind IN (
'raydium_launchpad.buy_exact_in',
'raydium_launchpad.buy_exact_out',
'raydium_launchpad.sell_exact_in',
'raydium_launchpad.sell_exact_out'
)
GROUP BY
de.event_kind,
de.pool_account,
de.token_a_mint,
de.token_b_mint,
instruction_name
ORDER BY decoded_count DESC, de.event_kind;
-- 15. Direct Launchpad trade-event materialization readiness.
SELECT
de.pool_account,
json_extract(de.payload_json, '$.tradeSide') AS trade_side,
json_extract(de.payload_json, '$.baseAmountRaw') AS base_amount_raw,
json_extract(de.payload_json, '$.quoteAmountRaw') AS quote_amount_raw,
json_extract(de.payload_json, '$.tradeCandidate') AS trade_candidate,
json_extract(de.payload_json, '$.candleCandidate') AS candle_candidate,
COUNT(*) AS decoded_count,
COUNT(te.id) AS trade_count,
COUNT(DISTINCT de.transaction_id) AS tx_count
FROM k_sol_dex_decoded_events de
LEFT JOIN k_sol_trade_events te
ON te.decoded_event_id = de.id
WHERE de.protocol_name = 'raydium_launchpad'
AND de.event_kind = 'raydium_launchpad.trade_event'
GROUP BY
de.pool_account,
trade_side,
base_amount_raw,
quote_amount_raw,
trade_candidate,
candle_candidate
ORDER BY decoded_count DESC, de.pool_account;
-- 16. Launchpad pairs with decoded trade events but no materialized trade rows.
SELECT
p.address AS pool_address,
pa.id AS pair_id,
COUNT(de.id) AS decoded_trade_event_count,
COUNT(te.id) AS materialized_trade_count
FROM k_sol_pools p
JOIN k_sol_dexes d
ON d.id = p.dex_id
JOIN k_sol_pairs pa
ON pa.pool_id = p.id
LEFT JOIN k_sol_dex_decoded_events de
ON de.pool_account = p.address
AND de.protocol_name = 'raydium_launchpad'
AND de.event_kind = 'raydium_launchpad.trade_event'
LEFT JOIN k_sol_trade_events te
ON te.decoded_event_id = de.id
WHERE d.code = 'raydium_launchpad'
GROUP BY p.address, pa.id
HAVING decoded_trade_event_count > 0
ORDER BY decoded_trade_event_count DESC, p.address;
-- 17. Launchpad candles by pair after trade-event promotion.
SELECT
pair_id,
timeframe_seconds,
COUNT(*) AS candle_count,
SUM(trade_count) AS trade_count,
MIN(bucket_start_unix) AS first_bucket_start_unix,
MAX(bucket_start_unix) AS last_bucket_start_unix
FROM k_sol_pair_candles
WHERE pair_id IN (
SELECT pa.id
FROM k_sol_pairs pa
JOIN k_sol_pools p ON p.id = pa.pool_id
JOIN k_sol_dexes d ON d.id = p.dex_id
WHERE d.code = 'raydium_launchpad'
)
GROUP BY pair_id, timeframe_seconds
ORDER BY pair_id, timeframe_seconds;
-- 18. Launchpad trade events still not materializable after pre7.
-- Expected after pre7: rows should be limited to failed transactions or missing token balance metadata.
SELECT
de.pool_account,
COUNT(*) AS decoded_count,
COUNT(CASE WHEN tx.err_json IS NOT NULL AND tx.err_json <> '' AND tx.err_json <> 'null' THEN de.id END) AS failed_tx_count,
COUNT(CASE WHEN json_extract(de.payload_json, '$.tradeCandidate') = 1 THEN de.id END) AS trade_candidate_count,
COUNT(CASE WHEN json_extract(de.payload_json, '$.baseAmountRaw') IS NULL THEN de.id END) AS missing_base_amount_count,
COUNT(CASE WHEN json_extract(de.payload_json, '$.quoteAmountRaw') IS NULL THEN de.id END) AS missing_quote_amount_count,
COUNT(te.id) AS materialized_trade_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
WHERE de.protocol_name = 'raydium_launchpad'
AND de.event_kind = 'raydium_launchpad.trade_event'
GROUP BY de.pool_account
HAVING materialized_trade_count = 0
ORDER BY decoded_count DESC, de.pool_account;
-- 19. Launchpad event payload parser health.
-- Expected after pre7: direct trade_event rows should expose raw amount fields for successful self-CPI events.
SELECT
json_extract(payload_json, '$.anchorSelfCpiDataLength') AS anchor_self_cpi_data_length,
json_extract(payload_json, '$.anchorEventPayloadSize') AS anchor_event_payload_size,
json_extract(payload_json, '$.tradeDirectionRaw') AS trade_direction_raw,
json_extract(payload_json, '$.amountInRaw') AS amount_in_raw,
json_extract(payload_json, '$.amountOutRaw') AS amount_out_raw,
json_extract(payload_json, '$.baseAmountRaw') AS base_amount_raw,
json_extract(payload_json, '$.quoteAmountRaw') AS quote_amount_raw,
COUNT(*) AS decoded_count,
COUNT(DISTINCT transaction_id) AS tx_count
FROM k_sol_dex_decoded_events
WHERE protocol_name = 'raydium_launchpad'
AND event_kind = 'raydium_launchpad.trade_event'
GROUP BY
anchor_self_cpi_data_length,
anchor_event_payload_size,
trade_direction_raw,
amount_in_raw,
amount_out_raw,
base_amount_raw,
quote_amount_raw
ORDER BY decoded_count DESC;

View File

@@ -0,0 +1,112 @@
-- file: validation_sql/SQL_VALIDATION_RAYDIUM_LAUNCHPAD_0_7_50_PRE9.sql
-- Raydium Launchpad pre9 validation additions.
-- 1. Coverage entries, including late Carbon instructions and launch-event target table.
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 = 'raydium_launchpad'
ORDER BY entry_kind, entry_name, discriminator_hex;
-- 2. Launchpad-specific materialized events.
SELECT
le.event_kind,
le.event_role,
le.pool_account,
COUNT(*) AS launch_event_count,
COUNT(DISTINCT le.signature) AS tx_count
FROM k_sol_launch_events le
WHERE le.protocol_name = 'raydium_launchpad'
GROUP BY le.event_kind, le.event_role, le.pool_account
ORDER BY launch_event_count DESC, le.event_kind, le.pool_account;
-- 3. Fee materialization for Launchpad fee instructions.
SELECT
fe.event_kind,
fe.pool_account,
COUNT(*) AS fee_event_count,
COUNT(DISTINCT fe.signature) AS tx_count
FROM k_sol_fee_events fe
WHERE fe.protocol_name = 'raydium_launchpad'
GROUP BY fe.event_kind, fe.pool_account
ORDER BY fee_event_count DESC, fe.event_kind;
-- 4. Admin/config/access materialization for Launchpad admin instructions.
SELECT
ae.event_kind,
ae.admin_action,
ae.pool_account,
COUNT(*) AS admin_event_count,
COUNT(DISTINCT ae.signature) AS tx_count
FROM k_sol_pool_admin_events ae
WHERE ae.protocol_name = 'raydium_launchpad'
GROUP BY ae.event_kind, ae.admin_action, ae.pool_account
ORDER BY admin_event_count DESC, ae.event_kind;
-- 5. Late Carbon instruction corpus identifiers.
SELECT
instruction_name,
discriminator_hex,
COUNT(*) AS observed_count,
COUNT(DISTINCT signature) AS tx_count
FROM k_sol_instruction_observations
WHERE decoder_code = 'raydium_launchpad'
AND discriminator_hex IN (
'7bb4b8816fb9bb3b', -- close_platform_global_access
'a25b92c75d85eaed', -- create_platform_global_access
'9247ad4562130f6a', -- create_platform_vesting_account
'e445a52e51cb9a1d' -- cpi_event / Anchor self-CPI transport
)
GROUP BY instruction_name, discriminator_hex
ORDER BY observed_count DESC, discriminator_hex;
-- 6. Residual Launchpad decoded events that are still only decoded, not materialized.
SELECT
de.event_kind,
COUNT(*) AS decoded_count,
COUNT(fe.id) AS fee_count,
COUNT(ae.id) AS admin_count,
COUNT(le.id) AS launch_count,
COUNT(pe.id) AS lifecycle_count,
COUNT(te.id) AS trade_count
FROM k_sol_dex_decoded_events de
LEFT JOIN k_sol_fee_events fe ON fe.decoded_event_id = de.id
LEFT JOIN k_sol_pool_admin_events ae ON ae.decoded_event_id = de.id
LEFT JOIN k_sol_launch_events le ON le.decoded_event_id = de.id
LEFT JOIN k_sol_pool_lifecycle_events pe ON pe.decoded_event_id = de.id
LEFT JOIN k_sol_trade_events te ON te.decoded_event_id = de.id
WHERE de.protocol_name = 'raydium_launchpad'
GROUP BY de.event_kind
ORDER BY decoded_count DESC, de.event_kind;
-- 7. Residual decoded-only Launchpad events split by failed/success transaction.
SELECT
de.event_kind,
COUNT(*) AS decoded_count,
COUNT(CASE WHEN tx.err_json IS NOT NULL AND tx.err_json <> '' AND tx.err_json <> 'null' THEN de.id END) AS failed_tx_count,
COUNT(fe.id) AS fee_count,
COUNT(ae.id) AS admin_count,
COUNT(le.id) AS launch_count,
COUNT(pe.id) AS lifecycle_count,
COUNT(te.id) AS trade_count
FROM k_sol_dex_decoded_events de
JOIN k_sol_chain_transactions tx
ON tx.id = de.transaction_id
LEFT JOIN k_sol_fee_events fe ON fe.decoded_event_id = de.id
LEFT JOIN k_sol_pool_admin_events ae ON ae.decoded_event_id = de.id
LEFT JOIN k_sol_launch_events le ON le.decoded_event_id = de.id
LEFT JOIN k_sol_pool_lifecycle_events pe ON pe.decoded_event_id = de.id
LEFT JOIN k_sol_trade_events te ON te.decoded_event_id = de.id
WHERE de.protocol_name = 'raydium_launchpad'
GROUP BY de.event_kind
HAVING (fee_count + admin_count + launch_count + lifecycle_count + trade_count) < decoded_count
ORDER BY decoded_count DESC, de.event_kind;