0.7.52
This commit is contained in:
@@ -84,3 +84,4 @@
|
|||||||
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 - 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-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.51 - Raydium AMM v4 event coverage clôturé : decoder maximal local pour tous les discriminants officiels AMM v4 `00..11`, spécialisation des swaps `swap_base_in/out` et `swap_base_in/out_v2`, suppression durable du `raydium_amm_v4.swap` legacy, index AMM v4 en discriminant 1 octet, matérialisation validée des swaps, liquidity, lifecycle, fees, admin/config et side effects orderbook, `pre_initialize` conservé comme lifecycle audit deprecated/partial, `simulate_info` decoded-only, reset replay renforcé par `protocol_name`, validation des invariants failed/non-swap/single-target/unexplained gaps et maintien de `raydium_pool_v4` en audit conditionnel sans decoder autonome.
|
0.7.51 - Raydium AMM v4 event coverage clôturé : decoder maximal local pour tous les discriminants officiels AMM v4 `00..11`, spécialisation des swaps `swap_base_in/out` et `swap_base_in/out_v2`, suppression durable du `raydium_amm_v4.swap` legacy, index AMM v4 en discriminant 1 octet, matérialisation validée des swaps, liquidity, lifecycle, fees, admin/config et side effects orderbook, `pre_initialize` conservé comme lifecycle audit deprecated/partial, `simulate_info` decoded-only, reset replay renforcé par `protocol_name`, validation des invariants failed/non-swap/single-target/unexplained gaps et maintien de `raydium_pool_v4` en audit conditionnel sans decoder autonome.
|
||||||
|
0.7.52 - Raydium Stable Swap event coverage clôturé : decoder legacy 1 octet pour la surface locale `00..0d`, matérialisation lifecycle/liquidity/admin/fee/orderbook selon contexte, swaps `swap_base_in/out` matérialisés uniquement depuis deltas de vaults exacts (`stable_swap_vault_balance_delta`), conservation des bornes d’instruction comme audit-only, failed transactions decoded-only avec skip reasons, validation locale 407 tests et clippy `-D warnings` OK.
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ members = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
version = "0.7.51"
|
version = "0.7.52"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
repository = "https://git.sasedev.com/Sasedev/khadhroony-bobobot"
|
repository = "https://git.sasedev.com/Sasedev/khadhroony-bobobot"
|
||||||
|
|||||||
41
README.md
41
README.md
@@ -78,7 +78,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 lorsqu’ils 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 lorsqu’ils apparaîtront dans un corpus local, sans créer de trade/candle par défaut.
|
||||||
|
|
||||||
La tranche `0.7.51 raydium_amm_v4` est maintenant validée côté `kb_lib`. La suite de roadmap reprend avec `0.7.52 raydium_stable`, tandis que `raydium_pool_v4` reste un audit conditionnel ultérieur et ne doit pas être promu sans confirmation de program id/rôle/corpus.
|
Les tranches `0.7.51 raydium_amm_v4` et `0.7.52 raydium_stable_swap` sont maintenant validées côté `kb_lib`. La suite de roadmap reprend avec les rechecks conditionnels et les surfaces restantes, tandis que `raydium_pool_v4` reste un audit conditionnel ultérieur et ne doit pas être promu sans confirmation de program id/rôle/corpus.
|
||||||
|
|
||||||
## Organisation documentaire
|
## Organisation documentaire
|
||||||
|
|
||||||
@@ -320,7 +320,7 @@ Chaque DEX ou variante de DEX doit avoir sa propre étape de validation. Les fam
|
|||||||
|
|
||||||
À garder dans la matrice mais sans bloquer les versions immédiates :
|
À garder dans la matrice mais sans bloquer les versions immédiates :
|
||||||
|
|
||||||
- `raydium_stable_swap` tant que son usage réel n’est pas démontré par corpus local ;
|
- `raydium_stable_swap` est désormais démontré par corpus local en `0.7.52` ; le garder comme DEX effectif supporté, avec surveillance des nouveaux discriminants ;
|
||||||
- vieux programmes legacy uniquement utiles pour compatibilité ou replay historique ;
|
- vieux programmes legacy uniquement utiles pour compatibilité ou replay historique ;
|
||||||
- agrégateurs/routeurs comme `okx_dex` tant qu’ils ne correspondent pas à un DEX direct matérialisable ;
|
- agrégateurs/routeurs comme `okx_dex` tant qu’ils ne correspondent pas à un DEX direct matérialisable ;
|
||||||
- entrées ambiguës comme `zora` tant qu’aucun programme Solana pertinent n’est prouvé.
|
- entrées ambiguës comme `zora` tant qu’aucun programme Solana pertinent n’est prouvé.
|
||||||
@@ -433,7 +433,7 @@ La priorité immédiate après le point de reprise `0.7.43-E5C` est :
|
|||||||
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-pre-r2` : `raydium_launchpad` clos + re-vérification `raydium_cpmm` / `raydium_clmm` ;
|
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_swap` — clôturé ;
|
||||||
6. `0.7.53` : `raydium_pool_v4` audit / program-id decision seulement si program id distinct et corpus exploitable ;
|
6. `0.7.53` : `raydium_pool_v4` audit / program-id decision seulement si program id distinct et corpus exploitable ;
|
||||||
7. `0.7.54` : `pump_swap` ;
|
7. `0.7.54` : `pump_swap` ;
|
||||||
8. `0.7.55` : `pump_fun` ;
|
8. `0.7.55` : `pump_fun` ;
|
||||||
@@ -546,7 +546,7 @@ La suite fonctionnelle reprend par Raydium avant Meteora :
|
|||||||
2. `0.7.49` — `raydium_clmm` ;
|
2. `0.7.49` — `raydium_clmm` ;
|
||||||
3. `0.7.50-pre-r2` — `raydium_launchpad` + clôture CPMM/CLMM ;
|
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_swap` — clôturé ;
|
||||||
6. `0.7.53` — `raydium_pool_v4` audit conditionnel, sans promotion automatique ;
|
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.
|
7. `0.7.54+` — Pump, Meteora, Phoenix/OpenBook, Orca puis les autres DEX/surfaces.
|
||||||
|
|
||||||
@@ -632,3 +632,36 @@ Cette tranche complète la clôture Raydium en ajoutant `cpi_event` pour CPMM/CL
|
|||||||
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.
|
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`.
|
Rapport de clôture : `docs/reports/RAYDIUM_CPMM_CLMM_RECHECK_REPORT_0_7_50_PRE_R2.md`.
|
||||||
|
## Tranche clôturée — 0.7.52 raydium_stable_swap
|
||||||
|
|
||||||
|
`0.7.52` clôture Raydium Stable Swap avec le code local canonique `raydium_stable_swap` et le program id `5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h`.
|
||||||
|
|
||||||
|
Décisions finales :
|
||||||
|
|
||||||
|
- Stable Swap est décodé en layout legacy **1 octet**.
|
||||||
|
- La surface locale observée `00..0d` est couverte : lifecycle, model setup, admin/config, liquidity, orderbook side effects, fees et swaps.
|
||||||
|
- `swap_base_in` / `swap_base_out` produisent trades/candles uniquement avec des montants exacts dérivés des deltas de vaults (`amountSource=stable_swap_vault_balance_delta`).
|
||||||
|
- Les arguments d’instruction `amountInRaw`, `minimumAmountOutRaw`, `maxAmountInRaw`, `amountOutRaw` sont conservés comme bornes d’instruction, mais ne sont pas utilisés comme prix/montants exacts.
|
||||||
|
- Les transactions failed restent decoded-only avec `skipTradeReason=failed_transaction` et `skipCandleReason=failed_transaction`.
|
||||||
|
|
||||||
|
Livrables de clôture :
|
||||||
|
|
||||||
|
- `kb_lib/src/dex/raydium_stable_swap.rs`
|
||||||
|
- `docs/reports/RAYDIUM_STABLE_SWAP_EVENT_COVERAGE_REPORT.md`
|
||||||
|
- `validation_sql/SQL_VALIDATION_RAYDIUM_STABLE_SWAP_0_7_52.sql`
|
||||||
|
|
||||||
|
Validation locale finale :
|
||||||
|
|
||||||
|
```text
|
||||||
|
cargo test -p kb_lib -> 407 passed, 0 failed
|
||||||
|
cargo clippy -p kb_lib --all-targets -- -D warnings -> ok
|
||||||
|
```
|
||||||
|
|
||||||
|
Replay final observé :
|
||||||
|
|
||||||
|
```text
|
||||||
|
replayed=298, trades=290, liquidity=16, lifecycle=4, candle_upserts=1160,
|
||||||
|
instructionObservations=5317, catalog=40 tokens / 59 pools / 59 pairs
|
||||||
|
```
|
||||||
|
|
||||||
|
Statut : **clôturé côté code et validation locale**.
|
||||||
|
|||||||
66
ROADMAP.md
66
ROADMAP.md
@@ -36,7 +36,7 @@ Règles de planification :
|
|||||||
| `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` | Bootstrap ouvert : surface LaunchLab/Launchpad, discriminants Carbon/IDL, fallback audit, SQL de validation, aucune matérialisation métier sans corpus. |
|
| `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` | Clôturé : decoder maximal `00..11`, swaps spécialisés, lifecycle/liquidity/fees/admin/orderbook, `pre_initialize` audit, `simulate_info` decoded-only, cleanup legacy/fallback. |
|
| `0.7.51` | `raydium_amm_v4` | Clôturé : decoder maximal `00..11`, swaps spécialisés, lifecycle/liquidity/fees/admin/orderbook, `pre_initialize` audit, `simulate_info` decoded-only, cleanup legacy/fallback. |
|
||||||
| `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_swap` | Clôturé : surface legacy `00..0d`, swaps via deltas vault exacts, failed tx decoded-only, invariants trade/candle propres. |
|
||||||
| `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.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_swap` | Couvrir `buy/sell` et tous les events auxiliaires disponibles : fees, cashback, volume accumulator, admin/config. |
|
| `0.7.54` | `pump_swap` | Couvrir `buy/sell` et tous les events auxiliaires disponibles : fees, cashback, volume accumulator, admin/config. |
|
||||||
| `0.7.55` | `pump_fun` | Traiter launch/bonding/migration ; séparer création token, buy/sell bonding, migration vers DEX effectif. |
|
| `0.7.55` | `pump_fun` | Traiter launch/bonding/migration ; séparer création token, buy/sell bonding, migration vers DEX effectif. |
|
||||||
@@ -855,7 +855,7 @@ Matrice cible initiale :
|
|||||||
| `raydium_launchpad` | 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 | supporté / 0.7.52 clos | swaps depuis deltas vault exacts ; failed tx decoded-only |
|
||||||
| `meteora_dlmm` | DLMM | supporté | verrouiller corpus et non-régression |
|
| `meteora_dlmm` | DLMM | supporté | verrouiller corpus et non-régression |
|
||||||
| `meteora_damm_v1` | AMM legacy | partiel | garder skip explicite sans payload montant/prix |
|
| `meteora_damm_v1` | AMM legacy | partiel | garder skip explicite sans payload montant/prix |
|
||||||
| `meteora_damm_v2` | AMM | partiel | corpus et séparation events |
|
| `meteora_damm_v2` | AMM | partiel | corpus et séparation events |
|
||||||
@@ -1006,7 +1006,7 @@ Réalisé :
|
|||||||
- maintien des launch surfaces comme surfaces reportées et non prioritaires ;
|
- maintien des launch surfaces comme surfaces reportées et non prioritaires ;
|
||||||
- ajout du profil `0.7.39_dex_first_effective_swap_surfaces` ;
|
- ajout du profil `0.7.39_dex_first_effective_swap_surfaces` ;
|
||||||
- validation locale confirmée avec `validationPassed = true`, `blockingIssueCount = 0`, `actionableMissingTradeEventCount = 0` et `missingTradeEventCount = 0` ;
|
- validation locale confirmée avec `validationPassed = true`, `blockingIssueCount = 0`, `actionableMissingTradeEventCount = 0` et `missingTradeEventCount = 0` ;
|
||||||
- confirmation par corpus local initial que Raydium CLMM est observé, tandis que Raydium AMM v4 et Stable Swap ne sont pas encore exploitables sans constitution de corpus dédiée.
|
- confirmation par corpus local initial que Raydium CLMM est observé ; les tranches ultérieures ont ensuite clôturé Raydium AMM v4 en `0.7.51` et Stable Swap en `0.7.52`.
|
||||||
|
|
||||||
Décision : `0.7.39` est clos. La suite immédiate ne doit pas commencer par un décodeur Raydium AMM v4 sans corpus. Il faut d’abord ajouter les outils de découverte on-chain et de backfill ciblé afin d’obtenir des signatures, pools/state accounts, token mints et instructions exploitables.
|
Décision : `0.7.39` est clos. La suite immédiate ne doit pas commencer par un décodeur Raydium AMM v4 sans corpus. Il faut d’abord ajouter les outils de découverte on-chain et de backfill ciblé afin d’obtenir des signatures, pools/state accounts, token mints et instructions exploitables.
|
||||||
|
|
||||||
@@ -1310,10 +1310,10 @@ Objectif : hisser AMM v4 legacy au niveau de couverture CPMM/CLMM.
|
|||||||
|
|
||||||
Réalisé : decoder maximal AMM v4 pour tous les discriminants officiels `00..11`, spécialisation des swaps (`swap_base_in`, `swap_base_out`, `swap_base_in_v2`, `swap_base_out_v2`), suppression du legacy `raydium_amm_v4.swap`, observation locale de tous les discriminants, matérialisation validée des familles trade, liquidity, lifecycle, fee, admin/config et orderbook, `pre_initialize` conservé comme lifecycle audit deprecated/partial, `simulate_info` conservé en decoded-only, gaps successful non matérialisés expliqués, et validation des invariants failed/non-swap/single-target.
|
Réalisé : decoder maximal AMM v4 pour tous les discriminants officiels `00..11`, spécialisation des swaps (`swap_base_in`, `swap_base_out`, `swap_base_in_v2`, `swap_base_out_v2`), suppression du legacy `raydium_amm_v4.swap`, observation locale de tous les discriminants, matérialisation validée des familles trade, liquidity, lifecycle, fee, admin/config et orderbook, `pre_initialize` conservé comme lifecycle audit deprecated/partial, `simulate_info` conservé en decoded-only, gaps successful non matérialisés expliqués, et validation des invariants failed/non-swap/single-target.
|
||||||
|
|
||||||
### 6.084. Version `0.7.52` — `raydium_stable` event coverage
|
### 6.084. Version `0.7.52` — `raydium_stable_swap` event coverage
|
||||||
Objectif : reprendre Raydium Stable comme troisième tranche Raydium post-CLMM.
|
Objectif : reprendre Raydium Stable comme tranche Raydium dédiée après AMM v4.
|
||||||
|
|
||||||
À 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.
|
Réalisé : decoder legacy 1 octet, surface locale `00..0d`, matérialisation lifecycle/liquidity/admin/fee/orderbook selon contexte, swaps `swap_base_in/out` matérialisés uniquement depuis deltas vault exacts (`stable_swap_vault_balance_delta`), transactions failed decoded-only, invariants trade/candle propres.
|
||||||
|
|
||||||
### 6.085. Version `0.7.53` — `raydium_pool_v4` audit / program-id decision
|
### 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.
|
Objectif : auditer `raydium_pool_v4.json` comme source IDL annexe, sans promotion métier automatique.
|
||||||
@@ -1566,7 +1566,7 @@ Ordre de travail recommandé pour la suite :
|
|||||||
7. `0.7.49` : `raydium_clmm` — clos ;
|
7. `0.7.49` : `raydium_clmm` — clos ;
|
||||||
8. `0.7.50-pre-r2` : `raydium_launchpad` clos + re-vérification CPMM/CLMM ;
|
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_swap` — clôturé ;
|
||||||
11. `0.7.53` : `raydium_pool_v4` audit conditionnel ;
|
11. `0.7.53` : `raydium_pool_v4` audit conditionnel ;
|
||||||
12. `0.7.54` : `pump_swap` ;
|
12. `0.7.54` : `pump_swap` ;
|
||||||
13. `0.7.55` : `pump_fun` ;
|
13. `0.7.55` : `pump_fun` ;
|
||||||
@@ -1649,7 +1649,7 @@ 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-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.
|
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_swap` 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.
|
||||||
|
|
||||||
## Clôture `0.7.51` — Raydium AMM v4
|
## Clôture `0.7.51` — Raydium AMM v4
|
||||||
|
|
||||||
@@ -1674,4 +1674,52 @@ Décision `raydium_pool_v4` : ne pas ouvrir de decoder autonome dans cette tranc
|
|||||||
|
|
||||||
Le rapport de décision est `docs/reports/RAYDIUM_POOL_V4_DECISION_NOTE.md`.
|
Le rapport de décision est `docs/reports/RAYDIUM_POOL_V4_DECISION_NOTE.md`.
|
||||||
|
|
||||||
La suite reprend `0.7.52 raydium_stable`, après rechecks CPMM/CLMM/Launchpad si la base de validation les contient.
|
La tranche `0.7.52 raydium_stable_swap` est clôturée ; la suite reprend sur les surfaces restantes ou les audits conditionnels selon le corpus disponible.
|
||||||
|
|
||||||
|
### Addendum final — `0.7.52 raydium_stable_swap`
|
||||||
|
|
||||||
|
Statut : **clôturé**.
|
||||||
|
|
||||||
|
Décision finale : `raydium_stable_swap` est le code local canonique pour le program id `5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h`. Le decoder utilise un layout legacy 1 octet et couvre la surface localement observée `00..0d`.
|
||||||
|
|
||||||
|
Résultat de tranche :
|
||||||
|
|
||||||
|
- `initialize` matérialise le lifecycle quand le contexte est complet ;
|
||||||
|
- `init_model_data` reste decoded-only expliqué ;
|
||||||
|
- `update_model_data` matérialise `k_sol_pool_admin_events` ;
|
||||||
|
- `deposit` / `withdraw` matérialisent `k_sol_liquidity_events` ;
|
||||||
|
- `monitor_step` / `admin_cancel_orders` matérialisent `k_sol_orderbook_events` quand le contexte est complet ;
|
||||||
|
- `set_params` matérialise `k_sol_pool_admin_events` ;
|
||||||
|
- `withdraw_pnl` / `withdraw_srm` matérialisent `k_sol_fee_events` quand le contexte est complet ;
|
||||||
|
- `simulate_info` reste decoded-only ;
|
||||||
|
- `swap_base_in` / `swap_base_out` matérialisent trades/candles uniquement depuis `amountSource=stable_swap_vault_balance_delta` ;
|
||||||
|
- `stable_swap_instruction_bounds_only` reste decoded-only et ne matérialise pas de trade/candle ;
|
||||||
|
- les transactions failed restent decoded-only avec `failed_transaction`.
|
||||||
|
|
||||||
|
Validation finale :
|
||||||
|
|
||||||
|
```text
|
||||||
|
cargo test -p kb_lib -> 407 passed, 0 failed
|
||||||
|
cargo clippy -p kb_lib --all-targets -- -D warnings -> ok
|
||||||
|
```
|
||||||
|
|
||||||
|
Replay final observé :
|
||||||
|
|
||||||
|
```text
|
||||||
|
replayed=298, trades=290, liquidity=16, lifecycle=4, candle_upserts=1160,
|
||||||
|
instructionObservations=5317, catalog=40 tokens / 59 pools / 59 pairs
|
||||||
|
```
|
||||||
|
|
||||||
|
Clôture swap spécifique :
|
||||||
|
|
||||||
|
```text
|
||||||
|
swap_base_in stable_swap_vault_balance_delta success 171 decoded / 171 trades
|
||||||
|
swap_base_in stable_swap_instruction_bounds_only failed 27 decoded / 0 trades
|
||||||
|
swap_base_out stable_swap_vault_balance_delta success 4 decoded / 4 trades
|
||||||
|
swap_base_out stable_swap_instruction_bounds_only failed 2 decoded / 0 trades
|
||||||
|
```
|
||||||
|
|
||||||
|
SQL de validation : `validation_sql/SQL_VALIDATION_RAYDIUM_STABLE_SWAP_0_7_52.sql`.
|
||||||
|
|
||||||
|
Rapport : `docs/reports/RAYDIUM_STABLE_SWAP_EVENT_COVERAGE_REPORT.md`.
|
||||||
|
|
||||||
|
|||||||
@@ -369,3 +369,16 @@ Règles validées :
|
|||||||
- les side effects SPL Token / Token-2022 restent transversaux.
|
- les side effects SPL Token / Token-2022 restent transversaux.
|
||||||
|
|
||||||
Contrôle final AMM v4 : le SQL `materialized_target_count > 1` doit rester vide.
|
Contrôle final AMM v4 : le SQL `materialized_target_count > 1` doit rester vide.
|
||||||
|
|
||||||
|
## 0.7.52 — Raydium Stable Swap DB model decision
|
||||||
|
|
||||||
|
No schema migration is introduced for `raydium_stable_swap` at tranche opening.
|
||||||
|
|
||||||
|
Stable Swap maps to existing DB targets:
|
||||||
|
|
||||||
|
- `initialize` / `pre_initialize` → `k_sol_pool_lifecycle_events` when pool context is sufficient;
|
||||||
|
- `deposit` / `withdraw` → `k_sol_liquidity_events` when pool/pair context is sufficient;
|
||||||
|
- `swap_base_in` / `swap_base_out` → `k_sol_trade_events` and candles only when mints and amounts are reliable;
|
||||||
|
- `swap_event` → `k_sol_dex_decoded_events` only until a corpus-backed materialization decision exists.
|
||||||
|
|
||||||
|
Side effects from SPL Token, Token-2022, Serum/OpenBook-style accounts or router transport remain transverse evidence and are not promoted as direct `raydium_stable_swap.*` business events without an explicit later DB decision.
|
||||||
|
|||||||
@@ -31,8 +31,8 @@ Cette matrice complète `kb_lib/src/dex_support_matrix.rs`. Elle documente **ce
|
|||||||
| 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. |
|
| 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.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. |
|
| 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` | `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. |
|
| 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 closed` | Decoder maximal AMM v4 `00..11`, swaps spécialisés, lifecycle/liquidity/fees/admin/orderbook validés. | Rechecks CPMM/CLMM/Launchpad puis `raydium_stable`. |
|
| 4 | `raydium_amm_v4` | `supported / 0.7.51 closed` | Decoder maximal AMM v4 `00..11`, swaps spécialisés, lifecycle/liquidity/fees/admin/orderbook validés. | Stable Swap clôturé ensuite en `0.7.52`; surveiller les surfaces restantes. |
|
||||||
| 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` | `supported / 0.7.52 closed` | Decoder legacy 1 octet, surface `00..0d`, swaps matérialisés depuis deltas vault exacts. | Surveiller seulement de nouveaux discriminants ou `swap_event` observé. |
|
||||||
| 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. |
|
| 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_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. |
|
| 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 | `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. |
|
| 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. |
|
||||||
@@ -99,7 +99,7 @@ Un event peut devenir `materialized` uniquement si :
|
|||||||
| `raydium_launchpad` | `launch_surface` | `launch` | `known` | non | oui | non | `bootstrap` | decoded_events_only_until_local_corpus |
|
| `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` | oui | oui | oui | `supported` | 0.7.52 closed; swaps via `stable_swap_vault_balance_delta` uniquement |
|
||||||
| `meteora_dlmm` | `dex_effective` | `DLMM` | `known` | oui | oui | oui | `supported` | |
|
| `meteora_dlmm` | `dex_effective` | `DLMM` | `known` | oui | oui | oui | `supported` | |
|
||||||
| `meteora_dlc` | `to_verify` | `unknown` | `to_verify` | non | non | non | `to_verify` | surface_and_program_id_to_verify |
|
| `meteora_dlc` | `to_verify` | `unknown` | `to_verify` | non | non | non | `to_verify` | surface_and_program_id_to_verify |
|
||||||
| `meteora_damm_v1` | `dex_effective` | `AMM` | `known` | oui | oui | non | `partial` | meteora_damm_v1_swap_without_amount_payload |
|
| `meteora_damm_v1` | `dex_effective` | `AMM` | `known` | oui | oui | non | `partial` | meteora_damm_v1_swap_without_amount_payload |
|
||||||
@@ -266,3 +266,10 @@ La clôture `0.7.50-pre-r2` complète les tranches `0.7.48` et `0.7.49` sans rou
|
|||||||
|
|
||||||
La tranche a été validée sur base SQLite dédiée : tous les discriminants `00..11` sont observés localement. Les gaps de matérialisation restants sont expliqués par decoded-only, transaction failed ou absence de catalogue/deltas exploitables.
|
La tranche a été validée sur base SQLite dédiée : tous les discriminants `00..11` sont observés localement. Les gaps de matérialisation restants sont expliqués par decoded-only, transaction failed ou absence de catalogue/deltas exploitables.
|
||||||
|
|
||||||
|
|
||||||
|
## 0.7.52 — Raydium Stable Swap
|
||||||
|
|
||||||
|
| decoder_code | program id | status | layout | notes |
|
||||||
|
|---|---|---|---|---|
|
||||||
|
| `raydium_stable_swap` | `5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h` | supported / closed | legacy 1 octet | Surface locale `00..0d` couverte ; swaps `swap_base_in/out` matérialisés uniquement depuis deltas vault exacts ; instruction bounds et failed tx restent decoded-only. |
|
||||||
|
|
||||||
|
|||||||
@@ -189,3 +189,28 @@ Validation locale finale : tous les discriminants AMM v4 officiels `00..11` sont
|
|||||||
| `cpi/informational` | `simulate_info` | observed decoded-only | `k_sol_dex_decoded_events_only` | Audit technique uniquement. |
|
| `cpi/informational` | `simulate_info` | observed decoded-only | `k_sol_dex_decoded_events_only` | Audit technique uniquement. |
|
||||||
| `token side effects` | SPL Token / Token-2022 inner instructions | transversal | decoded-only actuellement | Ne pas promouvoir comme AMM v4 direct. |
|
| `token side effects` | SPL Token / Token-2022 inner instructions | transversal | decoded-only actuellement | Ne pas promouvoir comme AMM v4 direct. |
|
||||||
| `unknown/unmapped audit` | residual `raydium_amm_v4.instruction_audit` | vide | decoded-only si futur inconnu | Tout residual doit être expliqué avant promotion. |
|
| `unknown/unmapped audit` | residual `raydium_amm_v4.instruction_audit` | vide | decoded-only si futur inconnu | Tout residual doit être expliqué avant promotion. |
|
||||||
|
|
||||||
|
## 0.7.52 — `raydium_stable_swap`
|
||||||
|
|
||||||
|
Status: **closed on local corpus**.
|
||||||
|
|
||||||
|
| entry | discriminator | family | expected target | local event kind | status |
|
||||||
|
|---|---:|---|---|---|---|
|
||||||
|
| `initialize` | `00` | `pool_create` | `k_sol_pool_lifecycle_events` | `raydium_stable_swap.initialize` | observed/materialized when context complete |
|
||||||
|
| `init_model_data` | `01` | `model_setup` | decoded-only | `raydium_stable_swap.init_model_data` | observed decoded-only / explained |
|
||||||
|
| `update_model_data` | `02` | `admin_config` | `k_sol_pool_admin_events` | `raydium_stable_swap.update_model_data` | observed/materialized |
|
||||||
|
| `deposit` | `03` | `liquidity_add` | `k_sol_liquidity_events` | `raydium_stable_swap.deposit` | observed/materialized |
|
||||||
|
| `withdraw` | `04` | `liquidity_remove` | `k_sol_liquidity_events` | `raydium_stable_swap.withdraw` | observed/materialized |
|
||||||
|
| `monitor_step` | `05` | `order_place` | `k_sol_orderbook_events` | `raydium_stable_swap.monitor_step` | observed/materialized |
|
||||||
|
| `set_params` | `06` | `admin_config` | `k_sol_pool_admin_events` | `raydium_stable_swap.set_params` | observed/materialized |
|
||||||
|
| `withdraw_pnl` | `07` | `fee` | `k_sol_fee_events` | `raydium_stable_swap.withdraw_pnl` | observed/materialized |
|
||||||
|
| `withdraw_srm` | `08` | `fee` | `k_sol_fee_events` | `raydium_stable_swap.withdraw_srm` | observed/materialized when context complete |
|
||||||
|
| `swap_base_in` | `09` | `swap` | `k_sol_trade_events` from vault deltas only | `raydium_stable_swap.swap_base_in` | success/vault-delta materialized; failed decoded-only |
|
||||||
|
| `pre_initialize` | `0a` | `pool_create` | lifecycle or decoded-only | `raydium_stable_swap.pre_initialize` | observed decoded-only / explained in current corpus |
|
||||||
|
| `swap_base_out` | `0b` | `swap` | `k_sol_trade_events` from vault deltas only | `raydium_stable_swap.swap_base_out` | success/vault-delta materialized; failed decoded-only |
|
||||||
|
| `simulate_info` | `0c` | `cpi_transport` | decoded-only | `raydium_stable_swap.simulate_info` | observed decoded-only / explained |
|
||||||
|
| `admin_cancel_orders` | `0d` | `orderbook_admin` | `k_sol_orderbook_events` | `raydium_stable_swap.admin_cancel_orders` | observed/materialized when context complete |
|
||||||
|
| `swap_event` | `40c6cde8260871e2` | `cpi_transport` | decoded-only | `raydium_stable_swap.swap_event` | upstream mapped; not observed locally |
|
||||||
|
|
||||||
|
Stable Swap swaps are not materialized from instruction min/max bounds. `swap_base_in/out` require `amountSource=stable_swap_vault_balance_delta`; `stable_swap_instruction_bounds_only` remains decoded-only and, in the final corpus, appears only on failed transactions.
|
||||||
|
|
||||||
|
|||||||
@@ -10,9 +10,6 @@ This file records the manual Solscan account inventory added during the `0.7.50`
|
|||||||
| `Aldrin AMM V2` | `CURVGoZn8zycx6FXwwevgBTB2gVvdbGTEpvMJDbgs2t4` | `no_idl` | https://solscan.io/account/CURVGoZn8zycx6FXwwevgBTB2gVvdbGTEpvMJDbgs2t4 |
|
| `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 |
|
| `ApePro Smart Wallet Program` | `JSW99DKmxNyREQM14SQLDykeBvEUG63TeohrvmofEiw` | `solscan_program_idl` | https://solscan.io/account/JSW99DKmxNyREQM14SQLDykeBvEUG63TeohrvmofEiw#programIdl |
|
||||||
| `Aquifer` | `AQU1FRd7papthgdrwPTTq5JacJh8YtwEXaBfKU3bTz45` | `no_idl` | https://solscan.io/account/AQU1FRd7papthgdrwPTTq5JacJh8YtwEXaBfKU3bTz45 |
|
| `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 |
|
| `Axiom Trade` | `FLASHX8DrLbgeR8FcfNV1F5krxYcYMUdBkrP1EPBtxB9` | `no_idl` | https://solscan.io/account/FLASHX8DrLbgeR8FcfNV1F5krxYcYMUdBkrP1EPBtxB9 |
|
||||||
| `Bags: Token Authority` | `BAGSB9TpGrZxQbEsrEznv5jXXdwyP6AXerN8aVRiAmcv` | `solscan_account` | https://solscan.io/account/BAGSB9TpGrZxQbEsrEznv5jXXdwyP6AXerN8aVRiAmcv |
|
| `Bags: Token Authority` | `BAGSB9TpGrZxQbEsrEznv5jXXdwyP6AXerN8aVRiAmcv` | `solscan_account` | https://solscan.io/account/BAGSB9TpGrZxQbEsrEznv5jXXdwyP6AXerN8aVRiAmcv |
|
||||||
| `Believe : Token Authority` | `5qWya6UjwWnGVhdSBL3hyZ7B45jbk6Byt1hwd7ohEGXE` | `no_idl` | https://solscan.io/account/5qWya6UjwWnGVhdSBL3hyZ7B45jbk6Byt1hwd7ohEGXE |
|
| `Believe : Token Authority` | `5qWya6UjwWnGVhdSBL3hyZ7B45jbk6Byt1hwd7ohEGXE` | `no_idl` | https://solscan.io/account/5qWya6UjwWnGVhdSBL3hyZ7B45jbk6Byt1hwd7ohEGXE |
|
||||||
|
|||||||
67
docs/VALIDATION_STATUS_0_7_52_FINAL.md
Normal file
67
docs/VALIDATION_STATUS_0_7_52_FINAL.md
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
# Validation status — 0.7.52 Raydium Stable Swap final
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
Decoder: `raydium_stable_swap`
|
||||||
|
|
||||||
|
Program id:
|
||||||
|
|
||||||
|
```text
|
||||||
|
5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h
|
||||||
|
```
|
||||||
|
|
||||||
|
## Local commands
|
||||||
|
|
||||||
|
```text
|
||||||
|
cargo test -p kb_lib
|
||||||
|
407 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
|
||||||
|
|
||||||
|
cargo clippy -p kb_lib --all-targets -- -D warnings
|
||||||
|
ok
|
||||||
|
```
|
||||||
|
|
||||||
|
## Final replay snapshot
|
||||||
|
|
||||||
|
```text
|
||||||
|
replayed=298
|
||||||
|
decode_skipped=0
|
||||||
|
ledger_upserts=298
|
||||||
|
unsafe_ledger_rows=258
|
||||||
|
trades=290
|
||||||
|
liquidity=16
|
||||||
|
lifecycle=4
|
||||||
|
tokenAccount=0
|
||||||
|
candle_upserts=1160
|
||||||
|
instructionObservations=5317
|
||||||
|
resetDeleted=1059
|
||||||
|
catalog=40 tokens / 59 pools / 59 pairs
|
||||||
|
```
|
||||||
|
|
||||||
|
## Stable Swap swap closure
|
||||||
|
|
||||||
|
```text
|
||||||
|
raydium_stable_swap.swap_base_in stable_swap_instruction_bounds_only failed decoded=27 trades=0
|
||||||
|
raydium_stable_swap.swap_base_in stable_swap_vault_balance_delta success decoded=171 trades=171
|
||||||
|
raydium_stable_swap.swap_base_out stable_swap_instruction_bounds_only failed decoded=2 trades=0
|
||||||
|
raydium_stable_swap.swap_base_out stable_swap_vault_balance_delta success decoded=4 trades=4
|
||||||
|
```
|
||||||
|
|
||||||
|
No successful Stable Swap swap remains without trade or skip reason.
|
||||||
|
|
||||||
|
## Invariants
|
||||||
|
|
||||||
|
| invariant | status |
|
||||||
|
|---|---|
|
||||||
|
| residual local `instruction_audit` | empty |
|
||||||
|
| residual `upstream_git.instruction_match` for covered entries | empty |
|
||||||
|
| decoded without coverage | empty |
|
||||||
|
| non-swap materialized as trade | empty |
|
||||||
|
| failed tx materialized as trade | empty |
|
||||||
|
| multi-target materialization | empty |
|
||||||
|
| unexplained successful non-materialized event | empty |
|
||||||
|
| successful swap via vault deltas | `trade_count = decoded_count` |
|
||||||
|
| failed swap instruction bounds only | `trade_count = 0` |
|
||||||
|
|
||||||
|
## Decision
|
||||||
|
|
||||||
|
`0.7.52 raydium_stable_swap` is closed for the current local corpus.
|
||||||
162
docs/reports/RAYDIUM_STABLE_SWAP_EVENT_COVERAGE_REPORT.md
Normal file
162
docs/reports/RAYDIUM_STABLE_SWAP_EVENT_COVERAGE_REPORT.md
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
# Raydium Stable Swap event coverage report — 0.7.52 final
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
`0.7.52` closes the `raydium_stable_swap` tranche after `0.7.51 raydium_amm_v4`.
|
||||||
|
|
||||||
|
Canonical local decoder code:
|
||||||
|
|
||||||
|
```text
|
||||||
|
raydium_stable_swap
|
||||||
|
```
|
||||||
|
|
||||||
|
Canonical program id validated by local corpus:
|
||||||
|
|
||||||
|
```text
|
||||||
|
5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h
|
||||||
|
```
|
||||||
|
|
||||||
|
Stable Swap is handled as a Raydium legacy AMM-style program with a one-byte instruction discriminator layout. Anchor-like 8-byte discriminants remain upstream discovery evidence only and are not business proof.
|
||||||
|
|
||||||
|
## Final implementation status
|
||||||
|
|
||||||
|
Implemented and locally validated:
|
||||||
|
|
||||||
|
- `kb_lib/src/dex/raydium_stable_swap.rs`.
|
||||||
|
- `RaydiumStableSwapDecoder` re-exported through `kb_lib/src/dex.rs` and `kb_lib/src/lib.rs`.
|
||||||
|
- Stable Swap route in `DexDecodeService` before generic Raydium instruction-audit preservation.
|
||||||
|
- One-byte Stable Swap instruction observation support.
|
||||||
|
- Coverage entries for all locally observed Stable Swap discriminants `00..0d`.
|
||||||
|
- Materialization into lifecycle/liquidity/fee/admin/orderbook/trade tables when the local corpus proves a safe target.
|
||||||
|
- Swap materialization from exact vault balance deltas only.
|
||||||
|
- Validation SQL in `validation_sql/SQL_VALIDATION_RAYDIUM_STABLE_SWAP_0_7_52.sql`.
|
||||||
|
|
||||||
|
## Instruction surface
|
||||||
|
|
||||||
|
| entry | discriminator | family | final target | local event kind | final status |
|
||||||
|
|---|---:|---|---|---|---|
|
||||||
|
| `initialize` | `00` | `pool_create` | `k_sol_pool_lifecycle_events` | `raydium_stable_swap.initialize` | observed/materialized when context complete |
|
||||||
|
| `init_model_data` | `01` | `model_setup` | decoded-only | `raydium_stable_swap.init_model_data` | observed decoded-only / explained |
|
||||||
|
| `update_model_data` | `02` | `admin_config` | `k_sol_pool_admin_events` | `raydium_stable_swap.update_model_data` | observed/materialized |
|
||||||
|
| `deposit` | `03` | `liquidity_add` | `k_sol_liquidity_events` | `raydium_stable_swap.deposit` | observed/materialized |
|
||||||
|
| `withdraw` | `04` | `liquidity_remove` | `k_sol_liquidity_events` | `raydium_stable_swap.withdraw` | observed/materialized |
|
||||||
|
| `monitor_step` | `05` | `order_place` | `k_sol_orderbook_events` | `raydium_stable_swap.monitor_step` | observed/materialized |
|
||||||
|
| `set_params` | `06` | `admin_config` | `k_sol_pool_admin_events` | `raydium_stable_swap.set_params` | observed/materialized |
|
||||||
|
| `withdraw_pnl` | `07` | `fee` | `k_sol_fee_events` | `raydium_stable_swap.withdraw_pnl` | observed/materialized |
|
||||||
|
| `withdraw_srm` | `08` | `fee` | `k_sol_fee_events` | `raydium_stable_swap.withdraw_srm` | observed/materialized when context complete |
|
||||||
|
| `swap_base_in` | `09` | `swap` | `k_sol_trade_events` only from vault deltas | `raydium_stable_swap.swap_base_in` | observed, materialized for successful swaps with exact deltas |
|
||||||
|
| `pre_initialize` | `0a` | `pool_create` | decoded-only or lifecycle when complete | `raydium_stable_swap.pre_initialize` | observed decoded-only / explained in current corpus |
|
||||||
|
| `swap_base_out` | `0b` | `swap` | `k_sol_trade_events` only from vault deltas | `raydium_stable_swap.swap_base_out` | observed, materialized for successful swaps with exact deltas |
|
||||||
|
| `simulate_info` | `0c` | `cpi_transport` | decoded-only | `raydium_stable_swap.simulate_info` | observed decoded-only / explained |
|
||||||
|
| `admin_cancel_orders` | `0d` | `orderbook_admin` | `k_sol_orderbook_events` | `raydium_stable_swap.admin_cancel_orders` | observed/materialized when context complete |
|
||||||
|
| `swap_event` | `40c6cde8260871e2` | `cpi_transport` | decoded-only | `raydium_stable_swap.swap_event` | upstream mapped, not observed in local corpus |
|
||||||
|
|
||||||
|
## Swap amount policy
|
||||||
|
|
||||||
|
Stable Swap instruction arguments are retained as instruction bounds, but they are not sufficient for trade/candle materialization:
|
||||||
|
|
||||||
|
```text
|
||||||
|
swap_base_in:
|
||||||
|
amountInRaw = exact input argument
|
||||||
|
minimumAmountOutRaw = slippage lower bound, not exact output
|
||||||
|
|
||||||
|
swap_base_out:
|
||||||
|
amountOutRaw = requested output argument
|
||||||
|
maxAmountInRaw = slippage upper bound, not exact input
|
||||||
|
```
|
||||||
|
|
||||||
|
Therefore, `swap_base_in` and `swap_base_out` materialize as trades/candles only when exact base/quote amounts are inferred from vault balance deltas:
|
||||||
|
|
||||||
|
```text
|
||||||
|
amountSource = stable_swap_vault_balance_delta
|
||||||
|
```
|
||||||
|
|
||||||
|
Instruction-bound-only swaps remain decoded-only:
|
||||||
|
|
||||||
|
```text
|
||||||
|
amountSource = stable_swap_instruction_bounds_only
|
||||||
|
tradeCandidate = false
|
||||||
|
candleCandidate = false
|
||||||
|
```
|
||||||
|
|
||||||
|
For failed transactions the skip reasons are:
|
||||||
|
|
||||||
|
```text
|
||||||
|
skipTradeReason = failed_transaction
|
||||||
|
skipCandleReason = failed_transaction
|
||||||
|
```
|
||||||
|
|
||||||
|
For successful transactions where exact vault deltas cannot be proven, the expected skip reason is:
|
||||||
|
|
||||||
|
```text
|
||||||
|
stable_swap_exact_amounts_unresolved
|
||||||
|
```
|
||||||
|
|
||||||
|
The final local corpus has no successful unresolved Stable Swap swap.
|
||||||
|
|
||||||
|
## Final local validation snapshot
|
||||||
|
|
||||||
|
Latest confirmed local commands:
|
||||||
|
|
||||||
|
```text
|
||||||
|
cargo test -p kb_lib
|
||||||
|
407 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
|
||||||
|
|
||||||
|
cargo clippy -p kb_lib --all-targets -- -D warnings
|
||||||
|
ok
|
||||||
|
```
|
||||||
|
|
||||||
|
Latest replay snapshot:
|
||||||
|
|
||||||
|
```text
|
||||||
|
replayed=298
|
||||||
|
decode_skipped=0
|
||||||
|
ledger_upserts=298
|
||||||
|
unsafe_ledger_rows=258
|
||||||
|
trades=290
|
||||||
|
liquidity=16
|
||||||
|
lifecycle=4
|
||||||
|
token_account=0
|
||||||
|
candle_upserts=1160
|
||||||
|
instructionObservations=5317
|
||||||
|
resetDeleted=1059
|
||||||
|
catalog=40 tokens / 59 pools / 59 pairs
|
||||||
|
```
|
||||||
|
|
||||||
|
Stable Swap swap closure:
|
||||||
|
|
||||||
|
| event kind | amount source | tx status | decoded | trades |
|
||||||
|
|---|---|---|---:|---:|
|
||||||
|
| `raydium_stable_swap.swap_base_in` | `stable_swap_instruction_bounds_only` | failed | 27 | 0 |
|
||||||
|
| `raydium_stable_swap.swap_base_in` | `stable_swap_vault_balance_delta` | success | 171 | 171 |
|
||||||
|
| `raydium_stable_swap.swap_base_out` | `stable_swap_instruction_bounds_only` | failed | 2 | 0 |
|
||||||
|
| `raydium_stable_swap.swap_base_out` | `stable_swap_vault_balance_delta` | success | 4 | 4 |
|
||||||
|
|
||||||
|
UI smoke evidence after the vault-delta correction:
|
||||||
|
|
||||||
|
```text
|
||||||
|
pair 27, timeframe 60s -> 70 candles
|
||||||
|
pair 30, timeframe 60s -> 44 candles
|
||||||
|
```
|
||||||
|
|
||||||
|
## Final invariant status
|
||||||
|
|
||||||
|
Validated as clean on the local corpus:
|
||||||
|
|
||||||
|
- residual `raydium_stable_swap.instruction_audit`: empty;
|
||||||
|
- residual `upstream_git.instruction_match` for covered local entries: empty;
|
||||||
|
- decoded-without-coverage: empty;
|
||||||
|
- non-swap materialized as trade: empty;
|
||||||
|
- failed transaction materialized as business trade: empty;
|
||||||
|
- multi-target materialization: empty;
|
||||||
|
- successful non-materialized swaps without skip reason: empty;
|
||||||
|
- Stable Swap successful swaps with `stable_swap_vault_balance_delta`: `trade_count = decoded_count`;
|
||||||
|
- Stable Swap instruction-bound-only swaps: failed only, `trade_count = 0`.
|
||||||
|
|
||||||
|
## Closure decision
|
||||||
|
|
||||||
|
`0.7.52 raydium_stable_swap` is closed for the currently observed local corpus.
|
||||||
|
|
||||||
|
The decoder has detected all locally observed Stable Swap instruction discriminants, materialized every event that can safely be materialized, and preserved non-materializable/failed events as decoded-only with explicit reasons.
|
||||||
|
|
||||||
|
Future work is not a blocker for `0.7.52` and should be handled as a later tranche if a new local corpus reveals additional discriminants or a direct, reliable `swap_event` path.
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "kb-demo-app",
|
"name": "kb-demo-app",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.7.51",
|
"version": "0.7.52",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
|
|||||||
@@ -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.51",
|
"version": "0.7.52",
|
||||||
"identifier": "com.sasedev.kb-demo-app",
|
"identifier": "com.sasedev.kb-demo-app",
|
||||||
"build": {
|
"build": {
|
||||||
"beforeDevCommand": "npm run dev",
|
"beforeDevCommand": "npm run dev",
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ mod raydium_amm_v4;
|
|||||||
mod raydium_clmm;
|
mod raydium_clmm;
|
||||||
mod raydium_cpmm;
|
mod raydium_cpmm;
|
||||||
pub(crate) mod raydium_launchpad;
|
pub(crate) mod raydium_launchpad;
|
||||||
|
mod raydium_stable_swap;
|
||||||
|
|
||||||
pub use dexlab::DexlabCreatePoolDecoded;
|
pub use dexlab::DexlabCreatePoolDecoded;
|
||||||
pub use dexlab::DexlabDecodedEvent;
|
pub use dexlab::DexlabDecodedEvent;
|
||||||
@@ -90,3 +91,9 @@ pub use raydium_cpmm::RaydiumCpmmSwapMode;
|
|||||||
pub use raydium_cpmm::classify_raydium_cpmm_instruction_data;
|
pub use raydium_cpmm::classify_raydium_cpmm_instruction_data;
|
||||||
pub use raydium_cpmm::decode_raydium_cpmm_instruction;
|
pub use raydium_cpmm::decode_raydium_cpmm_instruction;
|
||||||
pub use raydium_cpmm::decode_raydium_cpmm_program_data_event;
|
pub use raydium_cpmm::decode_raydium_cpmm_program_data_event;
|
||||||
|
pub use raydium_stable_swap::RaydiumStableSwapDecodedEvent;
|
||||||
|
pub use raydium_stable_swap::RaydiumStableSwapDecoder;
|
||||||
|
pub use raydium_stable_swap::RaydiumStableSwapInstructionDecoded;
|
||||||
|
pub use raydium_stable_swap::RaydiumStableSwapSwapEventDecoded;
|
||||||
|
pub use raydium_stable_swap::classify_raydium_stable_swap_instruction_data;
|
||||||
|
pub use raydium_stable_swap::decode_raydium_stable_swap_program_data_event;
|
||||||
|
|||||||
1524
kb_lib/src/dex/raydium_stable_swap.rs
Normal file
1524
kb_lib/src/dex/raydium_stable_swap.rs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -11,6 +11,7 @@ pub struct DexDecodeService {
|
|||||||
persistence: crate::DetectionPersistenceService,
|
persistence: crate::DetectionPersistenceService,
|
||||||
raydium_amm_v4_decoder: crate::RaydiumAmmV4Decoder,
|
raydium_amm_v4_decoder: crate::RaydiumAmmV4Decoder,
|
||||||
raydium_clmm_decoder: crate::RaydiumClmmDecoder,
|
raydium_clmm_decoder: crate::RaydiumClmmDecoder,
|
||||||
|
raydium_stable_swap_decoder: crate::RaydiumStableSwapDecoder,
|
||||||
pump_fun_decoder: crate::PumpFunDecoder,
|
pump_fun_decoder: crate::PumpFunDecoder,
|
||||||
pump_swap_decoder: crate::PumpSwapDecoder,
|
pump_swap_decoder: crate::PumpSwapDecoder,
|
||||||
orca_whirlpools_decoder: crate::OrcaWhirlpoolsDecoder,
|
orca_whirlpools_decoder: crate::OrcaWhirlpoolsDecoder,
|
||||||
@@ -33,6 +34,7 @@ impl DexDecodeService {
|
|||||||
persistence,
|
persistence,
|
||||||
raydium_amm_v4_decoder: crate::RaydiumAmmV4Decoder::new(),
|
raydium_amm_v4_decoder: crate::RaydiumAmmV4Decoder::new(),
|
||||||
raydium_clmm_decoder: crate::RaydiumClmmDecoder::new(),
|
raydium_clmm_decoder: crate::RaydiumClmmDecoder::new(),
|
||||||
|
raydium_stable_swap_decoder: crate::RaydiumStableSwapDecoder::new(),
|
||||||
pump_fun_decoder: crate::PumpFunDecoder::new(),
|
pump_fun_decoder: crate::PumpFunDecoder::new(),
|
||||||
pump_swap_decoder: crate::PumpSwapDecoder::new(),
|
pump_swap_decoder: crate::PumpSwapDecoder::new(),
|
||||||
orca_whirlpools_decoder: crate::OrcaWhirlpoolsDecoder::new(),
|
orca_whirlpools_decoder: crate::OrcaWhirlpoolsDecoder::new(),
|
||||||
@@ -78,6 +80,13 @@ impl DexDecodeService {
|
|||||||
if let Err(error) = append_result {
|
if let Err(error) = append_result {
|
||||||
return Err(error);
|
return Err(error);
|
||||||
}
|
}
|
||||||
|
let append_result = append_persisted_events_result(
|
||||||
|
&mut persisted,
|
||||||
|
self.decode_and_persist_raydium_stable_swap_events(&transaction, &instructions).await,
|
||||||
|
);
|
||||||
|
if let Err(error) = append_result {
|
||||||
|
return Err(error);
|
||||||
|
}
|
||||||
let append_result = append_persisted_events_result(
|
let append_result = append_persisted_events_result(
|
||||||
&mut persisted,
|
&mut persisted,
|
||||||
self.decode_and_persist_raydium_clmm_events(&transaction, &instructions).await,
|
self.decode_and_persist_raydium_clmm_events(&transaction, &instructions).await,
|
||||||
@@ -1512,6 +1521,65 @@ impl DexDecodeService {
|
|||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn persist_raydium_stable_swap_event(
|
||||||
|
&self,
|
||||||
|
transaction: &crate::ChainTransactionDto,
|
||||||
|
decoded_event: &crate::RaydiumStableSwapDecodedEvent,
|
||||||
|
) -> Result<crate::DexDecodedEventDto, crate::Error> {
|
||||||
|
let transaction_id = match transaction.id {
|
||||||
|
Some(transaction_id) => transaction_id,
|
||||||
|
None => {
|
||||||
|
return Err(crate::Error::InvalidState(format!(
|
||||||
|
"transaction '{}' has no internal id",
|
||||||
|
transaction.signature
|
||||||
|
)));
|
||||||
|
},
|
||||||
|
};
|
||||||
|
let instruction_id = match decoded_event.instruction_id() {
|
||||||
|
Some(instruction_id) => instruction_id,
|
||||||
|
None => {
|
||||||
|
return Err(crate::Error::InvalidState(format!(
|
||||||
|
"raydium stable swap decoded event for transaction '{}' has no instruction id",
|
||||||
|
transaction.signature
|
||||||
|
)));
|
||||||
|
},
|
||||||
|
};
|
||||||
|
let event_kind = decoded_event.event_kind().to_string();
|
||||||
|
let raw_payload_json = match decoded_event.to_payload_json() {
|
||||||
|
Some(payload_json) => payload_json,
|
||||||
|
None => {
|
||||||
|
return Err(crate::Error::Json(
|
||||||
|
"cannot serialize decoded raydium stable swap payload".to_string(),
|
||||||
|
));
|
||||||
|
},
|
||||||
|
};
|
||||||
|
let payload_value_result = enriched_raydium_payload_value(
|
||||||
|
"raydium_stable_swap",
|
||||||
|
event_kind.as_str(),
|
||||||
|
raw_payload_json.as_str(),
|
||||||
|
);
|
||||||
|
let payload_value = match payload_value_result {
|
||||||
|
Ok(payload_value) => payload_value,
|
||||||
|
Err(error) => return Err(error),
|
||||||
|
};
|
||||||
|
return self
|
||||||
|
.materialize_named_dex_event(
|
||||||
|
transaction,
|
||||||
|
transaction_id,
|
||||||
|
instruction_id,
|
||||||
|
"raydium_stable_swap",
|
||||||
|
crate::RAYDIUM_STABLE_SWAP_AMM_PROGRAM_ID.to_string(),
|
||||||
|
event_kind.as_str(),
|
||||||
|
decoded_event.pool_account().map(|value| return value.to_string()),
|
||||||
|
decoded_event.market_account().map(|value| return value.to_string()),
|
||||||
|
decoded_event.base_mint().map(|value| return value.to_string()),
|
||||||
|
decoded_event.quote_mint().map(|value| return value.to_string()),
|
||||||
|
decoded_event.lp_mint().map(|value| return value.to_string()),
|
||||||
|
payload_value,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
|
||||||
async fn persist_pump_fun_event(
|
async fn persist_pump_fun_event(
|
||||||
&self,
|
&self,
|
||||||
transaction: &crate::ChainTransactionDto,
|
transaction: &crate::ChainTransactionDto,
|
||||||
@@ -1708,6 +1776,32 @@ impl DexDecodeService {
|
|||||||
return Ok(persisted);
|
return Ok(persisted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn decode_and_persist_raydium_stable_swap_events(
|
||||||
|
&self,
|
||||||
|
transaction: &crate::ChainTransactionDto,
|
||||||
|
instructions: &[crate::ChainInstructionDto],
|
||||||
|
) -> Result<std::vec::Vec<crate::DexDecodedEventDto>, crate::Error> {
|
||||||
|
let decoded_result = self
|
||||||
|
.raydium_stable_swap_decoder
|
||||||
|
.decode_transaction(transaction, instructions);
|
||||||
|
let decoded_events = match decoded_result {
|
||||||
|
Ok(decoded_events) => decoded_events,
|
||||||
|
Err(error) => return Err(error),
|
||||||
|
};
|
||||||
|
let mut persisted = std::vec::Vec::new();
|
||||||
|
for decoded_event in &decoded_events {
|
||||||
|
let persist_result = self
|
||||||
|
.persist_raydium_stable_swap_event(transaction, decoded_event)
|
||||||
|
.await;
|
||||||
|
let persisted_event = match persist_result {
|
||||||
|
Ok(persisted_event) => persisted_event,
|
||||||
|
Err(error) => return Err(error),
|
||||||
|
};
|
||||||
|
persisted.push(persisted_event);
|
||||||
|
}
|
||||||
|
return Ok(persisted);
|
||||||
|
}
|
||||||
|
|
||||||
async fn decode_and_persist_raydium_clmm_events(
|
async fn decode_and_persist_raydium_clmm_events(
|
||||||
&self,
|
&self,
|
||||||
transaction: &crate::ChainTransactionDto,
|
transaction: &crate::ChainTransactionDto,
|
||||||
@@ -2509,6 +2603,13 @@ fn raydium_instruction_audit_spec(
|
|||||||
candidate_pool_account_index: 3,
|
candidate_pool_account_index: 3,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if program_id == crate::RAYDIUM_STABLE_SWAP_AMM_PROGRAM_ID {
|
||||||
|
return Some(RaydiumInstructionAuditSpec {
|
||||||
|
protocol_name: "raydium_stable_swap",
|
||||||
|
event_kind: "raydium_stable_swap.instruction_audit",
|
||||||
|
candidate_pool_account_index: 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
if program_id == crate::RAYDIUM_LAUNCHPAD_PROGRAM_ID {
|
if program_id == crate::RAYDIUM_LAUNCHPAD_PROGRAM_ID {
|
||||||
return Some(RaydiumInstructionAuditSpec {
|
return Some(RaydiumInstructionAuditSpec {
|
||||||
protocol_name: "raydium_launchpad",
|
protocol_name: "raydium_launchpad",
|
||||||
@@ -4234,6 +4335,7 @@ fn instruction_audit_event_kind_by_protocol(
|
|||||||
"raydium_amm_v4" => return Some("raydium_amm_v4.instruction_audit"),
|
"raydium_amm_v4" => return Some("raydium_amm_v4.instruction_audit"),
|
||||||
"raydium_clmm" => return Some("raydium_clmm.instruction_audit"),
|
"raydium_clmm" => return Some("raydium_clmm.instruction_audit"),
|
||||||
"raydium_cpmm" => return Some("raydium_cpmm.instruction_audit"),
|
"raydium_cpmm" => return Some("raydium_cpmm.instruction_audit"),
|
||||||
|
"raydium_stable_swap" => return Some("raydium_stable_swap.instruction_audit"),
|
||||||
"raydium_launchpad" => return Some("raydium_launchpad.instruction_audit"),
|
"raydium_launchpad" => return Some("raydium_launchpad.instruction_audit"),
|
||||||
"meteora_dlmm" => return Some("meteora_dlmm.instruction_audit"),
|
"meteora_dlmm" => return Some("meteora_dlmm.instruction_audit"),
|
||||||
"meteora_damm_v1" => return Some("meteora_damm_v1.instruction_audit"),
|
"meteora_damm_v1" => return Some("meteora_damm_v1.instruction_audit"),
|
||||||
@@ -4719,7 +4821,7 @@ fn raydium_instruction_discriminator_hex(
|
|||||||
bytes: std::option::Option<&[u8]>,
|
bytes: std::option::Option<&[u8]>,
|
||||||
offset: usize,
|
offset: usize,
|
||||||
) -> std::option::Option<std::string::String> {
|
) -> std::option::Option<std::string::String> {
|
||||||
if protocol_name == "raydium_amm_v4" {
|
if protocol_name == "raydium_amm_v4" || protocol_name == "raydium_stable_swap" {
|
||||||
return discriminator_hex_from_bytes_with_len(bytes, offset, 1);
|
return discriminator_hex_from_bytes_with_len(bytes, offset, 1);
|
||||||
}
|
}
|
||||||
return discriminator_hex_from_bytes(bytes, offset);
|
return discriminator_hex_from_bytes(bytes, offset);
|
||||||
|
|||||||
@@ -108,6 +108,12 @@ impl DexDetectService {
|
|||||||
crate::dex_detection_route::DexDetectionRoute::RaydiumCpmmTrade => {
|
crate::dex_detection_route::DexDetectionRoute::RaydiumCpmmTrade => {
|
||||||
self.detect_raydium_cpmm_trade(&transaction, decoded_event).await
|
self.detect_raydium_cpmm_trade(&transaction, decoded_event).await
|
||||||
},
|
},
|
||||||
|
crate::dex_detection_route::DexDetectionRoute::RaydiumStableSwapTrade => {
|
||||||
|
self.detect_raydium_stable_swap_trade(&transaction, decoded_event).await
|
||||||
|
},
|
||||||
|
crate::dex_detection_route::DexDetectionRoute::RaydiumStableSwapPool => {
|
||||||
|
self.detect_raydium_stable_swap_pool(&transaction, decoded_event).await
|
||||||
|
},
|
||||||
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
|
||||||
},
|
},
|
||||||
@@ -668,6 +674,78 @@ impl DexDetectService {
|
|||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async fn detect_raydium_stable_swap_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_stable_swap",
|
||||||
|
crate::PoolKind::Amm,
|
||||||
|
crate::PoolStatus::Active,
|
||||||
|
"signal.dex.raydium_stable_swap",
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn detect_raydium_stable_swap_trade(
|
||||||
|
&self,
|
||||||
|
transaction: &crate::ChainTransactionDto,
|
||||||
|
decoded_event: &crate::DexDecodedEventDto,
|
||||||
|
) -> Result<crate::DexPoolDetectionResult, crate::Error> {
|
||||||
|
let dex_id_result =
|
||||||
|
crate::dex_catalog::ensure_known_dex(self.database.as_ref(), "raydium_stable_swap").await;
|
||||||
|
let dex_id = match dex_id_result {
|
||||||
|
Ok(dex_id) => dex_id,
|
||||||
|
Err(error) => return Err(error),
|
||||||
|
};
|
||||||
|
let payload_value_result = parse_payload_json(decoded_event.payload_json.as_str());
|
||||||
|
let payload_value = match payload_value_result {
|
||||||
|
Ok(payload_value) => payload_value,
|
||||||
|
Err(error) => return Err(error),
|
||||||
|
};
|
||||||
|
let base_vault_address = extract_payload_string_field(&payload_value, "baseVault");
|
||||||
|
let quote_vault_address = extract_payload_string_field(&payload_value, "quoteVault");
|
||||||
|
let input_result =
|
||||||
|
crate::dex_pool_materialization::DexPoolMaterializationInput::from_decoded_event(
|
||||||
|
decoded_event,
|
||||||
|
dex_id,
|
||||||
|
crate::PoolKind::Amm,
|
||||||
|
crate::PoolStatus::Active,
|
||||||
|
crate::dex_pool_materialization::DexPoolTokenOrder::AlreadyBaseQuote,
|
||||||
|
base_vault_address,
|
||||||
|
quote_vault_address,
|
||||||
|
transaction.source_endpoint_name.clone(),
|
||||||
|
);
|
||||||
|
let input = match input_result {
|
||||||
|
Ok(input) => input,
|
||||||
|
Err(error) => return Err(error),
|
||||||
|
};
|
||||||
|
let detection_result =
|
||||||
|
crate::dex_pool_materialization::materialize_dex_pool(self.database.as_ref(), &input)
|
||||||
|
.await;
|
||||||
|
let detection_result = match detection_result {
|
||||||
|
Ok(detection_result) => detection_result,
|
||||||
|
Err(error) => return Err(error),
|
||||||
|
};
|
||||||
|
let signal_result = self
|
||||||
|
.record_pool_detection_signals(
|
||||||
|
transaction,
|
||||||
|
"signal.dex.raydium_stable_swap",
|
||||||
|
&detection_result,
|
||||||
|
payload_value,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
if let Err(error) = signal_result {
|
||||||
|
return Err(error);
|
||||||
|
}
|
||||||
|
return Ok(detection_result);
|
||||||
|
}
|
||||||
|
|
||||||
async fn detect_raydium_cpmm_trade(
|
async fn detect_raydium_cpmm_trade(
|
||||||
&self,
|
&self,
|
||||||
transaction: &crate::ChainTransactionDto,
|
transaction: &crate::ChainTransactionDto,
|
||||||
|
|||||||
@@ -11,6 +11,10 @@ pub(crate) enum DexDetectionRoute {
|
|||||||
RaydiumAmmV4Trade,
|
RaydiumAmmV4Trade,
|
||||||
/// Raydium CPMM trade route.
|
/// Raydium CPMM trade route.
|
||||||
RaydiumCpmmTrade,
|
RaydiumCpmmTrade,
|
||||||
|
/// Raydium Stable Swap trade route.
|
||||||
|
RaydiumStableSwapTrade,
|
||||||
|
/// Raydium Stable Swap pool lifecycle route.
|
||||||
|
RaydiumStableSwapPool,
|
||||||
/// Raydium CLMM trade route.
|
/// Raydium CLMM trade route.
|
||||||
RaydiumClmmTrade,
|
RaydiumClmmTrade,
|
||||||
/// Raydium Launchpad pool or bonding-curve creation route.
|
/// Raydium Launchpad pool or bonding-curve creation route.
|
||||||
@@ -67,6 +71,18 @@ pub(crate) fn dex_detection_route(
|
|||||||
("raydium_cpmm", "raydium_cpmm.swap_base_output") => {
|
("raydium_cpmm", "raydium_cpmm.swap_base_output") => {
|
||||||
return Some(crate::dex_detection_route::DexDetectionRoute::RaydiumCpmmTrade);
|
return Some(crate::dex_detection_route::DexDetectionRoute::RaydiumCpmmTrade);
|
||||||
},
|
},
|
||||||
|
("raydium_stable_swap", "raydium_stable_swap.initialize") => {
|
||||||
|
return Some(crate::dex_detection_route::DexDetectionRoute::RaydiumStableSwapPool);
|
||||||
|
},
|
||||||
|
("raydium_stable_swap", "raydium_stable_swap.pre_initialize") => {
|
||||||
|
return Some(crate::dex_detection_route::DexDetectionRoute::RaydiumStableSwapPool);
|
||||||
|
},
|
||||||
|
("raydium_stable_swap", "raydium_stable_swap.swap_base_in") => {
|
||||||
|
return Some(crate::dex_detection_route::DexDetectionRoute::RaydiumStableSwapTrade);
|
||||||
|
},
|
||||||
|
("raydium_stable_swap", "raydium_stable_swap.swap_base_out") => {
|
||||||
|
return Some(crate::dex_detection_route::DexDetectionRoute::RaydiumStableSwapTrade);
|
||||||
|
},
|
||||||
("raydium_clmm", "raydium_clmm.swap") => {
|
("raydium_clmm", "raydium_clmm.swap") => {
|
||||||
return Some(crate::dex_detection_route::DexDetectionRoute::RaydiumClmmTrade);
|
return Some(crate::dex_detection_route::DexDetectionRoute::RaydiumClmmTrade);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -260,6 +260,39 @@ fn infer_expected_db_target_for_entry(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if decoder_code == "raydium_stable_swap" {
|
||||||
|
if entry_name == "initialize" || entry_name == "pre_initialize" {
|
||||||
|
return Some(
|
||||||
|
crate::DexEventCoverageEntryDto::DB_TARGET_POOL_LIFECYCLE_EVENTS.to_string(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if entry_name == "deposit" || entry_name == "withdraw" {
|
||||||
|
return Some(crate::DexEventCoverageEntryDto::DB_TARGET_LIQUIDITY_EVENTS.to_string());
|
||||||
|
}
|
||||||
|
if entry_name == "swap_base_in" || entry_name == "swap_base_out" {
|
||||||
|
return Some(crate::DexEventCoverageEntryDto::DB_TARGET_TRADE_EVENTS.to_string());
|
||||||
|
}
|
||||||
|
if entry_name == "withdraw_pnl" || entry_name == "withdraw_srm" {
|
||||||
|
return Some(crate::DexEventCoverageEntryDto::DB_TARGET_FEE_EVENTS.to_string());
|
||||||
|
}
|
||||||
|
if entry_name == "set_params" {
|
||||||
|
return Some(crate::DexEventCoverageEntryDto::DB_TARGET_POOL_ADMIN_EVENTS.to_string());
|
||||||
|
}
|
||||||
|
if entry_name == "monitor_step" || entry_name == "admin_cancel_orders" {
|
||||||
|
return Some(crate::DexEventCoverageEntryDto::DB_TARGET_ORDERBOOK_EVENTS.to_string());
|
||||||
|
}
|
||||||
|
if entry_name == "update_model_data" {
|
||||||
|
return Some(crate::DexEventCoverageEntryDto::DB_TARGET_POOL_ADMIN_EVENTS.to_string());
|
||||||
|
}
|
||||||
|
if entry_name == "init_model_data"
|
||||||
|
|| entry_name == "simulate_info"
|
||||||
|
|| entry_name == "swap_event"
|
||||||
|
{
|
||||||
|
return Some(
|
||||||
|
crate::DexEventCoverageEntryDto::DB_TARGET_DECODED_EVENTS_ONLY.to_string(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
if decoder_code == "raydium_clmm" {
|
if decoder_code == "raydium_clmm" {
|
||||||
if entry_name == "initialize_reward" {
|
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());
|
||||||
@@ -405,6 +438,9 @@ fn infer_event_family_for_entry(
|
|||||||
if decoder_code == "raydium_cpmm" {
|
if decoder_code == "raydium_cpmm" {
|
||||||
return infer_raydium_cpmm_event_family(entry_name, entry_kind);
|
return infer_raydium_cpmm_event_family(entry_name, entry_kind);
|
||||||
}
|
}
|
||||||
|
if decoder_code == "raydium_stable_swap" {
|
||||||
|
return infer_raydium_stable_swap_event_family(entry_name, entry_kind);
|
||||||
|
}
|
||||||
return infer_event_family(entry_name, entry_kind);
|
return infer_event_family(entry_name, entry_kind);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -452,6 +488,34 @@ fn infer_raydium_cpmm_event_family(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn infer_raydium_stable_swap_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 {
|
||||||
|
"initialize" => return Some("pool_create".to_string()),
|
||||||
|
"pre_initialize" => return Some("pool_create".to_string()),
|
||||||
|
"init_model_data" => return Some("model_setup".to_string()),
|
||||||
|
"update_model_data" => return Some("admin_config".to_string()),
|
||||||
|
"deposit" => return Some("liquidity_add".to_string()),
|
||||||
|
"withdraw" => return Some("liquidity_remove".to_string()),
|
||||||
|
"monitor_step" => return Some("order_place".to_string()),
|
||||||
|
"set_params" => return Some("admin_config".to_string()),
|
||||||
|
"withdraw_pnl" => return Some("fee".to_string()),
|
||||||
|
"withdraw_srm" => return Some("fee".to_string()),
|
||||||
|
"swap_base_in" => return Some("swap".to_string()),
|
||||||
|
"swap_base_out" => return Some("swap".to_string()),
|
||||||
|
"simulate_info" => return Some("cpi_transport".to_string()),
|
||||||
|
"admin_cancel_orders" => return Some("orderbook_admin".to_string()),
|
||||||
|
"swap_event" => return Some("cpi_transport".to_string()),
|
||||||
|
_ => return infer_event_family(entry_name, entry_kind),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn infer_raydium_clmm_event_family(
|
fn infer_raydium_clmm_event_family(
|
||||||
entry_name: &str,
|
entry_name: &str,
|
||||||
entry_kind: &str,
|
entry_kind: &str,
|
||||||
@@ -725,6 +789,32 @@ fn raydium_amm_v4_local_event_kind(entry_name: &str) -> std::option::Option<std:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn raydium_stable_swap_local_event_kind(
|
||||||
|
entry_name: &str,
|
||||||
|
) -> std::option::Option<std::string::String> {
|
||||||
|
match entry_name {
|
||||||
|
"initialize" => return Some("raydium_stable_swap.initialize".to_string()),
|
||||||
|
"init_model_data" => return Some("raydium_stable_swap.init_model_data".to_string()),
|
||||||
|
"update_model_data" => return Some("raydium_stable_swap.update_model_data".to_string()),
|
||||||
|
"pre_initialize" => return Some("raydium_stable_swap.pre_initialize".to_string()),
|
||||||
|
"deposit" => return Some("raydium_stable_swap.deposit".to_string()),
|
||||||
|
"withdraw" => return Some("raydium_stable_swap.withdraw".to_string()),
|
||||||
|
"monitor_step" => return Some("raydium_stable_swap.monitor_step".to_string()),
|
||||||
|
"set_params" => return Some("raydium_stable_swap.set_params".to_string()),
|
||||||
|
"withdraw_pnl" => return Some("raydium_stable_swap.withdraw_pnl".to_string()),
|
||||||
|
"withdraw_srm" => return Some("raydium_stable_swap.withdraw_srm".to_string()),
|
||||||
|
"swap_base_in" => return Some("raydium_stable_swap.swap_base_in".to_string()),
|
||||||
|
"swap_base_out" => return Some("raydium_stable_swap.swap_base_out".to_string()),
|
||||||
|
"simulate_info" => return Some("raydium_stable_swap.simulate_info".to_string()),
|
||||||
|
"admin_cancel_orders" => {
|
||||||
|
return Some("raydium_stable_swap.admin_cancel_orders".to_string());
|
||||||
|
},
|
||||||
|
"swap_event" => return Some("raydium_stable_swap.swap_event".to_string()),
|
||||||
|
_ => return None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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,
|
||||||
@@ -732,6 +822,9 @@ pub(crate) fn known_local_event_kind(
|
|||||||
if decoder_code == "raydium_amm_v4" {
|
if decoder_code == "raydium_amm_v4" {
|
||||||
return raydium_amm_v4_local_event_kind(entry_name);
|
return raydium_amm_v4_local_event_kind(entry_name);
|
||||||
}
|
}
|
||||||
|
if decoder_code == "raydium_stable_swap" {
|
||||||
|
return raydium_stable_swap_local_event_kind(entry_name);
|
||||||
|
}
|
||||||
if decoder_code == "raydium_launchpad" && raydium_launchpad_local_entry_is_known(entry_name) {
|
if decoder_code == "raydium_launchpad" && raydium_launchpad_local_entry_is_known(entry_name) {
|
||||||
return Some(format!("raydium_launchpad.{}", entry_name));
|
return Some(format!("raydium_launchpad.{}", entry_name));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -224,7 +224,29 @@ fn resolve_instruction_name(
|
|||||||
};
|
};
|
||||||
return Some(name.to_string());
|
return Some(name.to_string());
|
||||||
}
|
}
|
||||||
|
if program_id == crate::RAYDIUM_STABLE_SWAP_AMM_PROGRAM_ID
|
||||||
|
|| decoder_code == Some("raydium_stable_swap")
|
||||||
|
{
|
||||||
|
let name = match discriminator_hex {
|
||||||
|
"00" => "raydium_stable_swap.initialize",
|
||||||
|
"01" => "raydium_stable_swap.init_model_data",
|
||||||
|
"02" => "raydium_stable_swap.update_model_data",
|
||||||
|
"03" => "raydium_stable_swap.deposit",
|
||||||
|
"04" => "raydium_stable_swap.withdraw",
|
||||||
|
"05" => "raydium_stable_swap.monitor_step",
|
||||||
|
"06" => "raydium_stable_swap.set_params",
|
||||||
|
"07" => "raydium_stable_swap.withdraw_pnl",
|
||||||
|
"08" => "raydium_stable_swap.withdraw_srm",
|
||||||
|
"09" => "raydium_stable_swap.swap_base_in",
|
||||||
|
"0a" => "raydium_stable_swap.pre_initialize",
|
||||||
|
"0b" => "raydium_stable_swap.swap_base_out",
|
||||||
|
"0c" => "raydium_stable_swap.simulate_info",
|
||||||
|
"0d" => "raydium_stable_swap.admin_cancel_orders",
|
||||||
|
"40c6cde8260871e2" => "raydium_stable_swap.swap_event",
|
||||||
|
_ => return None,
|
||||||
|
};
|
||||||
|
return Some(name.to_string());
|
||||||
|
}
|
||||||
if program_id == crate::RAYDIUM_CPMM_PROGRAM_ID || decoder_code == Some("raydium_cpmm") {
|
if program_id == crate::RAYDIUM_CPMM_PROGRAM_ID || decoder_code == Some("raydium_cpmm") {
|
||||||
let name = match discriminator_hex {
|
let name = match discriminator_hex {
|
||||||
"9c5420764587467b" => "raydium_cpmm.close_permission_pda",
|
"9c5420764587467b" => "raydium_cpmm.close_permission_pda",
|
||||||
@@ -284,7 +306,6 @@ fn resolve_instruction_name(
|
|||||||
};
|
};
|
||||||
return Some(name.to_string());
|
return Some(name.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
if program_id == crate::RAYDIUM_LAUNCHPAD_PROGRAM_ID
|
if program_id == crate::RAYDIUM_LAUNCHPAD_PROGRAM_ID
|
||||||
|| decoder_code == Some("raydium_launchpad")
|
|| decoder_code == Some("raydium_launchpad")
|
||||||
{
|
{
|
||||||
@@ -309,7 +330,9 @@ fn discriminator_hex_from_data_json(
|
|||||||
Some(decoded) => decoded,
|
Some(decoded) => decoded,
|
||||||
None => return None,
|
None => return None,
|
||||||
};
|
};
|
||||||
let discriminator_len = if program_id == crate::RAYDIUM_AMM_V4_PROGRAM_ID {
|
let discriminator_len = if program_id == crate::RAYDIUM_AMM_V4_PROGRAM_ID
|
||||||
|
|| program_id == crate::RAYDIUM_STABLE_SWAP_AMM_PROGRAM_ID
|
||||||
|
{
|
||||||
1_usize
|
1_usize
|
||||||
} else {
|
} else {
|
||||||
8_usize
|
8_usize
|
||||||
|
|||||||
@@ -505,6 +505,8 @@ pub use db::FeeEventEntity;
|
|||||||
pub use db::InstructionObservationDto;
|
pub use db::InstructionObservationDto;
|
||||||
/// Persisted technical observation for one Solana instruction.
|
/// Persisted technical observation for one Solana instruction.
|
||||||
pub use db::InstructionObservationEntity;
|
pub use db::InstructionObservationEntity;
|
||||||
|
/// Raw source row used to rebuild the technical instruction-observation index.
|
||||||
|
pub use db::InstructionObservationSourceRow;
|
||||||
/// Application-facing known HTTP endpoint DTO.
|
/// Application-facing known HTTP endpoint DTO.
|
||||||
pub use db::KnownHttpEndpointDto;
|
pub use db::KnownHttpEndpointDto;
|
||||||
/// Application-facing known WebSocket endpoint DTO.
|
/// Application-facing known WebSocket endpoint DTO.
|
||||||
@@ -517,6 +519,8 @@ pub use db::KnownWsEndpointEntity;
|
|||||||
pub use db::LaunchAttributionDto;
|
pub use db::LaunchAttributionDto;
|
||||||
/// Persisted launch attribution row.
|
/// Persisted launch attribution row.
|
||||||
pub use db::LaunchAttributionEntity;
|
pub use db::LaunchAttributionEntity;
|
||||||
|
/// Input used to upsert one launch event row.
|
||||||
|
pub use db::LaunchEventUpsertInput;
|
||||||
/// Application-facing launch surface DTO.
|
/// Application-facing launch surface DTO.
|
||||||
pub use db::LaunchSurfaceDto;
|
pub use db::LaunchSurfaceDto;
|
||||||
/// Persisted launch surface row.
|
/// Persisted launch surface row.
|
||||||
@@ -762,12 +766,12 @@ pub use db::query_dex_decoded_events_delete_local_replay_scope_by_transaction_id
|
|||||||
pub use db::query_dex_decoded_events_delete_locally_covered_upstream_instruction_matches;
|
pub use db::query_dex_decoded_events_delete_locally_covered_upstream_instruction_matches;
|
||||||
/// Deletes Meteora DLMM Anchor self-CPI swap audit rows already covered by decoded swaps.
|
/// Deletes Meteora DLMM Anchor self-CPI swap audit rows already covered by decoded swaps.
|
||||||
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.
|
|
||||||
pub use db::query_dex_decoded_events_delete_related_instruction_audit;
|
|
||||||
/// Deletes one Raydium CLMM instruction-audit row by discriminator.
|
/// Deletes one Raydium CLMM instruction-audit row by discriminator.
|
||||||
pub use db::query_dex_decoded_events_delete_raydium_clmm_instruction_audit_by_discriminator;
|
pub use db::query_dex_decoded_events_delete_raydium_clmm_instruction_audit_by_discriminator;
|
||||||
/// Deletes one Raydium Launchpad self-CPI audit row by discriminator.
|
/// Deletes one Raydium Launchpad self-CPI audit row by discriminator.
|
||||||
pub use db::query_dex_decoded_events_delete_raydium_launchpad_anchor_self_cpi_audit;
|
pub use db::query_dex_decoded_events_delete_raydium_launchpad_anchor_self_cpi_audit;
|
||||||
|
/// Deletes decoded DEX instruction audit rows related to one decoded instruction.
|
||||||
|
pub use db::query_dex_decoded_events_delete_related_instruction_audit;
|
||||||
/// Deletes Raydium CLMM instruction-audit rows for locally mapped CLMM instructions.
|
/// 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.
|
/// Deletes Raydium CPMM instruction-audit rows already covered by local named rows.
|
||||||
@@ -778,10 +782,10 @@ pub use db::query_dex_decoded_events_get_by_key;
|
|||||||
pub use db::query_dex_decoded_events_get_latest_pump_fun_create_payload_by_mint;
|
pub use db::query_dex_decoded_events_get_latest_pump_fun_create_payload_by_mint;
|
||||||
/// Lists decoded DEX events for one transaction.
|
/// Lists decoded DEX events for one transaction.
|
||||||
pub use db::query_dex_decoded_events_list_by_transaction_id;
|
pub use db::query_dex_decoded_events_list_by_transaction_id;
|
||||||
/// Inserts or updates one decoded DEX event row.
|
|
||||||
pub use db::query_dex_decoded_events_upsert;
|
|
||||||
/// Updates the persisted payload of one decoded DEX event row.
|
/// Updates the persisted payload of one decoded DEX event row.
|
||||||
pub use db::query_dex_decoded_events_update_payload_json_by_id;
|
pub use db::query_dex_decoded_events_update_payload_json_by_id;
|
||||||
|
/// Inserts or updates one decoded DEX event row.
|
||||||
|
pub use db::query_dex_decoded_events_upsert;
|
||||||
/// Deletes DEX event coverage entries for one decoder.
|
/// Deletes DEX event coverage entries for one decoder.
|
||||||
pub use db::query_dex_event_coverage_entries_delete_by_decoder;
|
pub use db::query_dex_event_coverage_entries_delete_by_decoder;
|
||||||
/// Lists DEX event coverage entries for one decoder.
|
/// Lists DEX event coverage entries for one decoder.
|
||||||
@@ -819,8 +823,6 @@ pub use db::query_instruction_observations_delete_by_transaction_ids;
|
|||||||
pub use db::query_instruction_observations_list_by_filter;
|
pub use db::query_instruction_observations_list_by_filter;
|
||||||
/// Upserts one instruction observation row.
|
/// Upserts one instruction observation row.
|
||||||
pub use db::query_instruction_observations_upsert;
|
pub use db::query_instruction_observations_upsert;
|
||||||
/// Raw source row used to rebuild the technical instruction-observation index.
|
|
||||||
pub use db::InstructionObservationSourceRow;
|
|
||||||
/// Reads one known HTTP endpoint by name.
|
/// Reads one known HTTP endpoint by name.
|
||||||
pub use db::query_known_http_endpoints_get;
|
pub use db::query_known_http_endpoints_get;
|
||||||
/// Lists all known HTTP endpoints.
|
/// Lists all known HTTP endpoints.
|
||||||
@@ -841,8 +843,6 @@ pub use db::query_launch_attributions_list_by_pool_id;
|
|||||||
pub use db::query_launch_attributions_upsert;
|
pub use db::query_launch_attributions_upsert;
|
||||||
/// Inserts or updates one launch event row.
|
/// Inserts or updates one launch event row.
|
||||||
pub use db::query_launch_events_upsert;
|
pub use db::query_launch_events_upsert;
|
||||||
/// Input used to upsert one launch event row.
|
|
||||||
pub use db::LaunchEventUpsertInput;
|
|
||||||
/// Returns one launch-surface matching key identified by its kind and value, if it exists.
|
/// Returns one launch-surface matching key identified by its kind and value, if it exists.
|
||||||
pub use db::query_launch_surface_keys_get_by_match;
|
pub use db::query_launch_surface_keys_get_by_match;
|
||||||
/// Lists all launch-surface matching keys attached to one launch surface id.
|
/// Lists all launch-surface matching keys attached to one launch surface id.
|
||||||
@@ -1221,8 +1221,18 @@ pub use dex::RaydiumCpmmSwapDecoded;
|
|||||||
pub use dex::RaydiumCpmmSwapEventDecoded;
|
pub use dex::RaydiumCpmmSwapEventDecoded;
|
||||||
/// Raydium CPMM swap mode.
|
/// Raydium CPMM swap mode.
|
||||||
pub use dex::RaydiumCpmmSwapMode;
|
pub use dex::RaydiumCpmmSwapMode;
|
||||||
|
/// Raydium Stable Swap decoded event.
|
||||||
|
pub use dex::RaydiumStableSwapDecodedEvent;
|
||||||
|
/// Raydium Stable Swap decoder.
|
||||||
|
pub use dex::RaydiumStableSwapDecoder;
|
||||||
|
/// Decoded Raydium Stable Swap instruction.
|
||||||
|
pub use dex::RaydiumStableSwapInstructionDecoded;
|
||||||
|
/// Decoded Raydium Stable Swap program-data swap event.
|
||||||
|
pub use dex::RaydiumStableSwapSwapEventDecoded;
|
||||||
/// Decodes one Raydium CPMM instruction from projected instruction fields.
|
/// Decodes one Raydium CPMM instruction from projected instruction fields.
|
||||||
pub use dex::classify_raydium_cpmm_instruction_data;
|
pub use dex::classify_raydium_cpmm_instruction_data;
|
||||||
|
/// Classifies one Raydium Stable Swap instruction data payload.
|
||||||
|
pub use dex::classify_raydium_stable_swap_instruction_data;
|
||||||
/// Decodes a Raydium CLMM instruction.
|
/// Decodes a Raydium CLMM instruction.
|
||||||
pub use dex::decode_raydium_clmm_instruction;
|
pub use dex::decode_raydium_clmm_instruction;
|
||||||
/// Decodes one Raydium CLMM Anchor Program data event.
|
/// Decodes one Raydium CLMM Anchor Program data event.
|
||||||
@@ -1231,6 +1241,8 @@ pub use dex::decode_raydium_clmm_program_data_event;
|
|||||||
pub use dex::decode_raydium_cpmm_instruction;
|
pub use dex::decode_raydium_cpmm_instruction;
|
||||||
/// Decodes Raydium CPMM Anchor events emitted in `Program data:` logs.
|
/// Decodes Raydium CPMM Anchor events emitted in `Program data:` logs.
|
||||||
pub use dex::decode_raydium_cpmm_program_data_event;
|
pub use dex::decode_raydium_cpmm_program_data_event;
|
||||||
|
/// Decodes Raydium Stable Swap `Program data:` event payloads.
|
||||||
|
pub use dex::decode_raydium_stable_swap_program_data_event;
|
||||||
/// DEX decode service.
|
/// DEX decode service.
|
||||||
pub use dex_decode::DexDecodeService;
|
pub use dex_decode::DexDecodeService;
|
||||||
/// Business-level DEX detection service.
|
/// Business-level DEX detection service.
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ pub(crate) async fn resolve_trade_amounts(
|
|||||||
}
|
}
|
||||||
if (input.decoded_event.event_kind.starts_with("raydium_amm_v4.")
|
if (input.decoded_event.event_kind.starts_with("raydium_amm_v4.")
|
||||||
|| input.decoded_event.event_kind.starts_with("raydium_cpmm.")
|
|| input.decoded_event.event_kind.starts_with("raydium_cpmm.")
|
||||||
|
|| input.decoded_event.event_kind.starts_with("raydium_stable_swap.")
|
||||||
|| input.decoded_event.event_kind.starts_with("raydium_clmm."))
|
|| input.decoded_event.event_kind.starts_with("raydium_clmm."))
|
||||||
&& (base_amount_raw.is_none()
|
&& (base_amount_raw.is_none()
|
||||||
|| quote_amount_raw.is_none()
|
|| quote_amount_raw.is_none()
|
||||||
@@ -183,6 +184,21 @@ pub(crate) async fn resolve_trade_amounts(
|
|||||||
return Err(error);
|
return Err(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if input.decoded_event.event_kind.starts_with("raydium_stable_swap.")
|
||||||
|
&& (base_amount_raw.is_none() || quote_amount_raw.is_none())
|
||||||
|
{
|
||||||
|
let resolution_result = crate::trade_amount_resolution::apply_vault_balance_delta_fallback(
|
||||||
|
input,
|
||||||
|
input.base_vault_address,
|
||||||
|
input.quote_vault_address,
|
||||||
|
&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_clmm.")
|
if input.decoded_event.event_kind.starts_with("raydium_clmm.")
|
||||||
&& (base_amount_raw.is_none() || quote_amount_raw.is_none())
|
&& (base_amount_raw.is_none() || quote_amount_raw.is_none())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -12836,6 +12836,28 @@ pub(crate) const UPSTREAM_REGISTRY_ENTRIES: &[crate::UpstreamRegistryEntry] = &[
|
|||||||
8,
|
8,
|
||||||
"decoders/raydium-liquidity-locking-decoder/src/instructions/settle_cp_fee_event.rs",
|
"decoders/raydium-liquidity-locking-decoder/src/instructions/settle_cp_fee_event.rs",
|
||||||
),
|
),
|
||||||
|
manual_solscan_discriminator_entry(
|
||||||
|
"raydium_stable_swap",
|
||||||
|
Some(crate::RAYDIUM_STABLE_SWAP_AMM_PROGRAM_ID),
|
||||||
|
"raydium",
|
||||||
|
"stable_swap",
|
||||||
|
crate::ENTRY_KIND_INSTRUCTION,
|
||||||
|
"init_model_data",
|
||||||
|
"01",
|
||||||
|
1,
|
||||||
|
"docs.raydium.io/products/stable/instructions#initmodeldata-local-corpus-observed",
|
||||||
|
),
|
||||||
|
manual_solscan_discriminator_entry(
|
||||||
|
"raydium_stable_swap",
|
||||||
|
Some(crate::RAYDIUM_STABLE_SWAP_AMM_PROGRAM_ID),
|
||||||
|
"raydium",
|
||||||
|
"stable_swap",
|
||||||
|
crate::ENTRY_KIND_INSTRUCTION,
|
||||||
|
"update_model_data",
|
||||||
|
"02",
|
||||||
|
1,
|
||||||
|
"docs.raydium.io/products/stable/instructions#updatemodeldata-local-corpus-observed",
|
||||||
|
),
|
||||||
upstream_git_discriminator_entry(
|
upstream_git_discriminator_entry(
|
||||||
"raydium_stable_swap",
|
"raydium_stable_swap",
|
||||||
Some(crate::RAYDIUM_STABLE_SWAP_AMM_PROGRAM_ID),
|
Some(crate::RAYDIUM_STABLE_SWAP_AMM_PROGRAM_ID),
|
||||||
@@ -12869,6 +12891,50 @@ pub(crate) const UPSTREAM_REGISTRY_ENTRIES: &[crate::UpstreamRegistryEntry] = &[
|
|||||||
1,
|
1,
|
||||||
"decoders/raydium-stable-swap-decoder/src/instructions/pre_initialize.rs",
|
"decoders/raydium-stable-swap-decoder/src/instructions/pre_initialize.rs",
|
||||||
),
|
),
|
||||||
|
manual_solscan_discriminator_entry(
|
||||||
|
"raydium_stable_swap",
|
||||||
|
Some(crate::RAYDIUM_STABLE_SWAP_AMM_PROGRAM_ID),
|
||||||
|
"raydium",
|
||||||
|
"stable_swap",
|
||||||
|
crate::ENTRY_KIND_INSTRUCTION,
|
||||||
|
"monitor_step",
|
||||||
|
"05",
|
||||||
|
1,
|
||||||
|
"docs.raydium.io/products/stable/instructions#monitorstep-local-corpus-observed",
|
||||||
|
),
|
||||||
|
manual_solscan_discriminator_entry(
|
||||||
|
"raydium_stable_swap",
|
||||||
|
Some(crate::RAYDIUM_STABLE_SWAP_AMM_PROGRAM_ID),
|
||||||
|
"raydium",
|
||||||
|
"stable_swap",
|
||||||
|
crate::ENTRY_KIND_INSTRUCTION,
|
||||||
|
"set_params",
|
||||||
|
"06",
|
||||||
|
1,
|
||||||
|
"docs.raydium.io/products/stable/instructions#setparams-local-corpus-observed",
|
||||||
|
),
|
||||||
|
manual_solscan_discriminator_entry(
|
||||||
|
"raydium_stable_swap",
|
||||||
|
Some(crate::RAYDIUM_STABLE_SWAP_AMM_PROGRAM_ID),
|
||||||
|
"raydium",
|
||||||
|
"stable_swap",
|
||||||
|
crate::ENTRY_KIND_INSTRUCTION,
|
||||||
|
"withdraw_pnl",
|
||||||
|
"07",
|
||||||
|
1,
|
||||||
|
"docs.raydium.io/products/stable/instructions#withdrawpnl-local-corpus-observed",
|
||||||
|
),
|
||||||
|
manual_solscan_discriminator_entry(
|
||||||
|
"raydium_stable_swap",
|
||||||
|
Some(crate::RAYDIUM_STABLE_SWAP_AMM_PROGRAM_ID),
|
||||||
|
"raydium",
|
||||||
|
"stable_swap",
|
||||||
|
crate::ENTRY_KIND_INSTRUCTION,
|
||||||
|
"withdraw_srm",
|
||||||
|
"08",
|
||||||
|
1,
|
||||||
|
"docs.raydium.io/products/stable/instructions#withdrawsrm-local-corpus-observed",
|
||||||
|
),
|
||||||
upstream_git_discriminator_entry(
|
upstream_git_discriminator_entry(
|
||||||
"raydium_stable_swap",
|
"raydium_stable_swap",
|
||||||
Some(crate::RAYDIUM_STABLE_SWAP_AMM_PROGRAM_ID),
|
Some(crate::RAYDIUM_STABLE_SWAP_AMM_PROGRAM_ID),
|
||||||
@@ -12902,6 +12968,39 @@ pub(crate) const UPSTREAM_REGISTRY_ENTRIES: &[crate::UpstreamRegistryEntry] = &[
|
|||||||
1,
|
1,
|
||||||
"decoders/raydium-stable-swap-decoder/src/instructions/withdraw.rs",
|
"decoders/raydium-stable-swap-decoder/src/instructions/withdraw.rs",
|
||||||
),
|
),
|
||||||
|
manual_solscan_discriminator_entry(
|
||||||
|
"raydium_stable_swap",
|
||||||
|
Some(crate::RAYDIUM_STABLE_SWAP_AMM_PROGRAM_ID),
|
||||||
|
"raydium",
|
||||||
|
"stable_swap",
|
||||||
|
crate::ENTRY_KIND_INSTRUCTION,
|
||||||
|
"simulate_info",
|
||||||
|
"0c",
|
||||||
|
1,
|
||||||
|
"docs.raydium.io/products/stable/instructions#simulateinfo-local-corpus-observed",
|
||||||
|
),
|
||||||
|
manual_solscan_discriminator_entry(
|
||||||
|
"raydium_stable_swap",
|
||||||
|
Some(crate::RAYDIUM_STABLE_SWAP_AMM_PROGRAM_ID),
|
||||||
|
"raydium",
|
||||||
|
"stable_swap",
|
||||||
|
crate::ENTRY_KIND_INSTRUCTION,
|
||||||
|
"admin_cancel_orders",
|
||||||
|
"0d",
|
||||||
|
1,
|
||||||
|
"raydium-amm/program/src/instruction.rs#admincancelorders-stable-local-corpus-observed",
|
||||||
|
),
|
||||||
|
manual_solscan_discriminator_entry(
|
||||||
|
"raydium_stable_swap",
|
||||||
|
Some(crate::RAYDIUM_STABLE_SWAP_AMM_PROGRAM_ID),
|
||||||
|
"raydium",
|
||||||
|
"stable_swap",
|
||||||
|
crate::ENTRY_KIND_EVENT,
|
||||||
|
"swap_event",
|
||||||
|
"40c6cde8260871e2",
|
||||||
|
8,
|
||||||
|
"docs.raydium.io/products/stable/instructions#program-data-swap-event-decoded-only",
|
||||||
|
),
|
||||||
upstream_git_discriminator_entry(
|
upstream_git_discriminator_entry(
|
||||||
"stabble_stable_swap",
|
"stabble_stable_swap",
|
||||||
Some(crate::STABBLE_STABLE_SWAP_PROGRAM_ID),
|
Some(crate::STABBLE_STABLE_SWAP_PROGRAM_ID),
|
||||||
|
|||||||
292
validation_sql/SQL_VALIDATION_RAYDIUM_STABLE_SWAP_0_7_52.sql
Normal file
292
validation_sql/SQL_VALIDATION_RAYDIUM_STABLE_SWAP_0_7_52.sql
Normal file
@@ -0,0 +1,292 @@
|
|||||||
|
-- file: validation_sql/SQL_VALIDATION_RAYDIUM_STABLE_SWAP_0_7_52.sql
|
||||||
|
|
||||||
|
-- 0.7.52 raydium_stable_swap validation checklist.
|
||||||
|
-- Run on a dedicated fresh SQLite database after corpus construction and replay with:
|
||||||
|
-- skipDexDecode=no, forceDexDecode=yes, deferInstructionObservations=yes.
|
||||||
|
|
||||||
|
-- 01. Coverage stable swap.
|
||||||
|
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_stable_swap'
|
||||||
|
ORDER BY entry_kind, entry_name, discriminator_hex;
|
||||||
|
|
||||||
|
-- 02. 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_stable_swap'
|
||||||
|
GROUP BY instruction_name, discriminator_hex
|
||||||
|
ORDER BY observed_count DESC, instruction_name, discriminator_hex;
|
||||||
|
|
||||||
|
-- 03. Residual local 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_stable_swap'
|
||||||
|
AND event_kind = 'raydium_stable_swap.instruction_audit'
|
||||||
|
GROUP BY discriminator_hex
|
||||||
|
ORDER BY audit_count DESC, discriminator_hex;
|
||||||
|
|
||||||
|
-- 04. Residual upstream fallback for covered local entries.
|
||||||
|
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_stable_swap'
|
||||||
|
GROUP BY upstream_decoder_code, entry_name, discriminator_hex, source_repo
|
||||||
|
ORDER BY fallback_count DESC, entry_name;
|
||||||
|
|
||||||
|
-- 05. Non-swap safety: non-swap event must not materialize as trade.
|
||||||
|
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_stable_swap'
|
||||||
|
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_stable_swap'
|
||||||
|
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;
|
||||||
|
|
||||||
|
-- 06. Failed transaction safety: failed tx must not materialize as business trade.
|
||||||
|
SELECT
|
||||||
|
de.event_kind,
|
||||||
|
COUNT(*) AS decoded_failed_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_stable_swap'
|
||||||
|
AND tx.err_json IS NOT NULL
|
||||||
|
AND tx.err_json <> ''
|
||||||
|
AND tx.err_json <> 'null'
|
||||||
|
GROUP BY de.event_kind
|
||||||
|
HAVING COUNT(te.id) > 0
|
||||||
|
ORDER BY trade_count DESC, de.event_kind;
|
||||||
|
|
||||||
|
-- 07. Decoded without coverage entry.
|
||||||
|
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_stable_swap'
|
||||||
|
AND ce.local_event_kind = de.event_kind
|
||||||
|
WHERE de.protocol_name = 'raydium_stable_swap'
|
||||||
|
AND ce.id IS NULL
|
||||||
|
GROUP BY de.event_kind
|
||||||
|
ORDER BY decoded_count DESC, de.event_kind;
|
||||||
|
|
||||||
|
-- 08. Multi-target materialization.
|
||||||
|
SELECT
|
||||||
|
de.event_kind,
|
||||||
|
COUNT(DISTINCT de.id) AS decoded_count,
|
||||||
|
COUNT(DISTINCT te.id) AS trade_count,
|
||||||
|
COUNT(DISTINCT le.id) AS liquidity_count,
|
||||||
|
COUNT(DISTINCT pe.id) AS lifecycle_count,
|
||||||
|
COUNT(DISTINCT fe.id) AS fee_count,
|
||||||
|
COUNT(DISTINCT ae.id) AS admin_count,
|
||||||
|
COUNT(DISTINCT oe.id) AS orderbook_count,
|
||||||
|
(
|
||||||
|
CASE WHEN COUNT(DISTINCT te.id) > 0 THEN 1 ELSE 0 END
|
||||||
|
+ CASE WHEN COUNT(DISTINCT le.id) > 0 THEN 1 ELSE 0 END
|
||||||
|
+ CASE WHEN COUNT(DISTINCT pe.id) > 0 THEN 1 ELSE 0 END
|
||||||
|
+ CASE WHEN COUNT(DISTINCT fe.id) > 0 THEN 1 ELSE 0 END
|
||||||
|
+ CASE WHEN COUNT(DISTINCT ae.id) > 0 THEN 1 ELSE 0 END
|
||||||
|
+ CASE WHEN COUNT(DISTINCT oe.id) > 0 THEN 1 ELSE 0 END
|
||||||
|
) AS materialized_target_count
|
||||||
|
FROM k_sol_dex_decoded_events de
|
||||||
|
LEFT JOIN k_sol_trade_events te
|
||||||
|
ON te.decoded_event_id = de.id
|
||||||
|
LEFT JOIN k_sol_liquidity_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_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_orderbook_events oe
|
||||||
|
ON oe.decoded_event_id = de.id
|
||||||
|
WHERE de.protocol_name = 'raydium_stable_swap'
|
||||||
|
GROUP BY de.event_kind
|
||||||
|
HAVING materialized_target_count > 1
|
||||||
|
ORDER BY materialized_target_count DESC, de.event_kind;
|
||||||
|
|
||||||
|
-- 09. Unexplained successful non-materialized events.
|
||||||
|
SELECT
|
||||||
|
de.event_kind,
|
||||||
|
COUNT(*) AS unexplained_count
|
||||||
|
FROM k_sol_dex_decoded_events de
|
||||||
|
JOIN k_sol_chain_transactions tx
|
||||||
|
ON tx.id = de.transaction_id
|
||||||
|
LEFT JOIN k_sol_trade_events te
|
||||||
|
ON te.decoded_event_id = de.id
|
||||||
|
LEFT JOIN k_sol_liquidity_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_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_orderbook_events oe
|
||||||
|
ON oe.decoded_event_id = de.id
|
||||||
|
LEFT JOIN k_sol_token_account_events tae
|
||||||
|
ON tae.decoded_event_id = de.id
|
||||||
|
WHERE de.protocol_name = 'raydium_stable_swap'
|
||||||
|
AND (
|
||||||
|
tx.err_json IS NULL
|
||||||
|
OR tx.err_json = ''
|
||||||
|
OR tx.err_json = 'null'
|
||||||
|
)
|
||||||
|
AND te.id IS NULL
|
||||||
|
AND le.id IS NULL
|
||||||
|
AND pe.id IS NULL
|
||||||
|
AND fe.id IS NULL
|
||||||
|
AND ae.id IS NULL
|
||||||
|
AND oe.id IS NULL
|
||||||
|
AND tae.id IS NULL
|
||||||
|
AND COALESCE(TRIM(json_extract(de.payload_json, '$.skipTradeReason')), '') = ''
|
||||||
|
AND COALESCE(TRIM(json_extract(de.payload_json, '$.skipLiquidityReason')), '') = ''
|
||||||
|
AND COALESCE(TRIM(json_extract(de.payload_json, '$.skipLifecycleReason')), '') = ''
|
||||||
|
AND COALESCE(TRIM(json_extract(de.payload_json, '$.skipCatalogReason')), '') = ''
|
||||||
|
GROUP BY de.event_kind
|
||||||
|
ORDER BY unexplained_count DESC, de.event_kind;
|
||||||
|
|
||||||
|
-- 10. Materialization summary.
|
||||||
|
SELECT
|
||||||
|
de.event_kind,
|
||||||
|
COUNT(DISTINCT de.id) AS decoded_count,
|
||||||
|
COUNT(DISTINCT te.id) AS trade_count,
|
||||||
|
COUNT(DISTINCT le.id) AS liquidity_count,
|
||||||
|
COUNT(DISTINCT pe.id) AS lifecycle_count,
|
||||||
|
COUNT(DISTINCT fe.id) AS fee_count,
|
||||||
|
COUNT(DISTINCT ae.id) AS admin_count,
|
||||||
|
COUNT(DISTINCT oe.id) AS orderbook_count
|
||||||
|
FROM k_sol_dex_decoded_events de
|
||||||
|
LEFT JOIN k_sol_trade_events te
|
||||||
|
ON te.decoded_event_id = de.id
|
||||||
|
LEFT JOIN k_sol_liquidity_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_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_orderbook_events oe
|
||||||
|
ON oe.decoded_event_id = de.id
|
||||||
|
WHERE de.protocol_name = 'raydium_stable_swap'
|
||||||
|
GROUP BY de.event_kind
|
||||||
|
ORDER BY de.event_kind;
|
||||||
|
|
||||||
|
|
||||||
|
-- 11. Stable Swap swap amount-source closure.
|
||||||
|
-- Successful swaps must materialize from exact vault deltas.
|
||||||
|
-- Failed swaps may remain instruction-bounds-only and must not materialize as trades.
|
||||||
|
SELECT
|
||||||
|
de.event_kind,
|
||||||
|
json_extract(de.payload_json, '$.amountSource') AS amount_source,
|
||||||
|
CASE
|
||||||
|
WHEN tx.err_json IS NOT NULL
|
||||||
|
AND tx.err_json <> ''
|
||||||
|
AND tx.err_json <> 'null'
|
||||||
|
THEN 'failed'
|
||||||
|
ELSE 'success'
|
||||||
|
END AS tx_status,
|
||||||
|
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_stable_swap'
|
||||||
|
AND de.event_kind IN (
|
||||||
|
'raydium_stable_swap.swap_base_in',
|
||||||
|
'raydium_stable_swap.swap_base_out'
|
||||||
|
)
|
||||||
|
GROUP BY de.event_kind, amount_source, tx_status
|
||||||
|
ORDER BY de.event_kind, amount_source, tx_status;
|
||||||
|
|
||||||
|
-- 12. Stable Swap successful swap without trade and without explanation.
|
||||||
|
-- Expected result: empty.
|
||||||
|
SELECT
|
||||||
|
de.event_kind,
|
||||||
|
COUNT(*) AS unexplained_success_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_stable_swap'
|
||||||
|
AND de.event_kind IN (
|
||||||
|
'raydium_stable_swap.swap_base_in',
|
||||||
|
'raydium_stable_swap.swap_base_out'
|
||||||
|
)
|
||||||
|
AND (
|
||||||
|
tx.err_json IS NULL
|
||||||
|
OR tx.err_json = ''
|
||||||
|
OR tx.err_json = 'null'
|
||||||
|
)
|
||||||
|
AND te.id IS NULL
|
||||||
|
AND COALESCE(TRIM(json_extract(de.payload_json, '$.skipTradeReason')), '') = ''
|
||||||
|
GROUP BY de.event_kind;
|
||||||
|
|
||||||
|
-- 13. Stable Swap failed swap safety.
|
||||||
|
-- Expected result: empty.
|
||||||
|
SELECT
|
||||||
|
de.event_kind,
|
||||||
|
json_extract(de.payload_json, '$.amountSource') AS amount_source,
|
||||||
|
COUNT(*) AS failed_trade_count
|
||||||
|
FROM k_sol_dex_decoded_events de
|
||||||
|
JOIN k_sol_chain_transactions tx
|
||||||
|
ON tx.id = de.transaction_id
|
||||||
|
JOIN k_sol_trade_events te
|
||||||
|
ON te.decoded_event_id = de.id
|
||||||
|
WHERE de.protocol_name = 'raydium_stable_swap'
|
||||||
|
AND de.event_kind IN (
|
||||||
|
'raydium_stable_swap.swap_base_in',
|
||||||
|
'raydium_stable_swap.swap_base_out'
|
||||||
|
)
|
||||||
|
AND tx.err_json IS NOT NULL
|
||||||
|
AND tx.err_json <> ''
|
||||||
|
AND tx.err_json <> 'null'
|
||||||
|
GROUP BY de.event_kind, amount_source
|
||||||
|
ORDER BY de.event_kind, amount_source;
|
||||||
Reference in New Issue
Block a user