0.7.51
This commit is contained in:
@@ -0,0 +1,626 @@
|
||||
<!-- file: docs/prompts/PROMPT_REPRISE_khadhroony-bobobot_0.7.52-raydium-stable.md -->
|
||||
|
||||
# Prompt de reprise — `khadhroony-bobobot` — `0.7.52 raydium_stable_swap`
|
||||
|
||||
Reprise du projet `khadhroony-bobobot` après clôture de `0.7.51 raydium_amm_v4`.
|
||||
|
||||
## Archive de départ
|
||||
|
||||
Utiliser la dernière archive complète du workspace intégrant les deltas validés jusqu’à :
|
||||
|
||||
```text
|
||||
0.7.51-raydium-amm-v4-final
|
||||
```
|
||||
|
||||
Joindre aussi les docs et SQL de validation à jour :
|
||||
|
||||
```text
|
||||
README.md
|
||||
ROADMAP.md
|
||||
CHANGELOG.md
|
||||
docs/DEX_DECODER_MATRIX.md
|
||||
docs/DEX_EVENT_COVERAGE_MATRIX.md
|
||||
docs/DB_EVENT_MODEL_REVIEW.md
|
||||
docs/reports/RAYDIUM_AMM_V4_EVENT_COVERAGE_REPORT.md
|
||||
docs/reports/RAYDIUM_POOL_V4_DECISION_NOTE.md
|
||||
docs/VALIDATION_STATUS_0_7_51_FINAL.md
|
||||
validation_sql/SQL_VALIDATION_RAYDIUM_AMM_V4_0_7_51.sql
|
||||
```
|
||||
|
||||
## État validé avant reprise
|
||||
|
||||
`0.7.51` a clôturé `raydium_amm_v4`.
|
||||
|
||||
Validation locale finale rapportée :
|
||||
|
||||
```text
|
||||
cargo test -p kb_lib
|
||||
405 passed / 0 failed
|
||||
|
||||
cargo clippy -p kb_lib --all-targets -- -D warnings
|
||||
OK
|
||||
```
|
||||
|
||||
Dernier replay local `0.7.51` :
|
||||
|
||||
```text
|
||||
195 replayed
|
||||
0 decode skipped
|
||||
195 ledger upserts
|
||||
70 unsafe ledger rows
|
||||
168 trades
|
||||
7 liquidity
|
||||
15 lifecycle
|
||||
0 tokenAccount
|
||||
668 candle upserts
|
||||
instructionObservations = 2599
|
||||
resetDeleted = 1578
|
||||
catalog = 61 tokens / 65 pools / 65 pairs
|
||||
```
|
||||
|
||||
Points de clôture AMM v4 à préserver :
|
||||
|
||||
```text
|
||||
raydium_amm_v4.swap legacy = vide
|
||||
decoded without coverage entry = vide
|
||||
instruction_observations > 1 octet = vide
|
||||
non-swap -> trade = vide
|
||||
failed tx -> trade = vide
|
||||
unexplained successful non-materialized events = vide
|
||||
multi-target materialization = vide
|
||||
pre_initialize lifecycle audit = 7 / 7
|
||||
migrate_to_open_book = orderbook only
|
||||
simulate_info = decoded-only
|
||||
raydium_pool_v4 = audit-only / pas de decoder autonome
|
||||
```
|
||||
|
||||
## Décision de reprise
|
||||
|
||||
Ouvrir une nouvelle tranche :
|
||||
|
||||
```text
|
||||
0.7.52 raydium_stable_swap
|
||||
```
|
||||
|
||||
Code local canonique :
|
||||
|
||||
```text
|
||||
raydium_stable_swap
|
||||
```
|
||||
|
||||
Program id canonique à utiliser comme hypothèse de départ :
|
||||
|
||||
```text
|
||||
5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h
|
||||
```
|
||||
|
||||
Important : upstream Git/IDL/Solscan est un indice, pas une preuve métier. Le program id doit être confirmé par corpus local via `k_sol_instruction_observations`, decoded events, coverage entries et absence de fallback upstream.
|
||||
|
||||
## Nouvelle base de travail
|
||||
|
||||
Démarrer `0.7.52` sur une base SQLite vide dédiée.
|
||||
|
||||
Avant le replay de validation complet, construire volontairement un corpus initial :
|
||||
|
||||
```text
|
||||
1. Demo3 program_id = 5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h
|
||||
2. Solscan non filtré + essais instruction=<DISCRIMINATOR>
|
||||
3. backfill Demo2 de signatures contenant des instructions stable swap variées
|
||||
4. backfill de pools stable swap quand Demo3/Solscan fournit un AMM/pool account fiable
|
||||
```
|
||||
|
||||
Ne pas interpréter l’absence de résultat Solscan comme absence on-chain définitive.
|
||||
|
||||
## Note Solscan importante
|
||||
|
||||
Pour `raydium_stable_swap`, il semble que Solscan ne dispose pas d’un Program IDL exploitable sur :
|
||||
|
||||
```text
|
||||
https://solscan.io/account/5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h#programIdl
|
||||
```
|
||||
|
||||
Donc le filtrage Solscan par instruction peut ne pas fonctionner avec les discriminants 8 octets Carbon/Pinax.
|
||||
|
||||
Il faut tester deux approches :
|
||||
|
||||
```text
|
||||
1. Liens exploratoires courts : instruction=00, 01, 02, ...
|
||||
2. Liens discriminants upstream 8 octets : instruction=<DISCRIMINATOR_HEX>
|
||||
```
|
||||
|
||||
Solscan est une aide de découverte uniquement. La preuve métier reste locale : signatures backfillées, decoded events, instruction observations et coverage DB.
|
||||
|
||||
## Sources Git/IDL à utiliser systématiquement
|
||||
|
||||
Sources globales :
|
||||
|
||||
```text
|
||||
https://github.com/sevenlabs-hq/carbon/tree/main/decoders
|
||||
https://github.com/0xfnzero/solana-streamer
|
||||
https://github.com/0xfnzero/sol-parser-sdk/tree/main/idl
|
||||
https://github.com/0xfnzero/sol-parser-sdk/tree/main/idls
|
||||
https://github.com/pinax-network/substreams-solana-idls/tree/main/src
|
||||
https://github.com/hodlwarden/solana-tx-parser/tree/main/src
|
||||
https://docs.vybenetwork.com/docs/available-dexs-amms
|
||||
```
|
||||
|
||||
Sources spécifiques `raydium_stable_swap` à vérifier en priorité :
|
||||
|
||||
```text
|
||||
https://github.com/sevenlabs-hq/carbon/tree/main/decoders/raydium-stable-swap-decoder
|
||||
https://github.com/pinax-network/substreams-solana-idls/tree/main/src/raydium/stable
|
||||
https://github.com/pinax-network/substreams-solana-idls/tree/main/src/raydium/stable/idl.json
|
||||
https://github.com/pinax-network/substreams-solana-idls/tree/main/src/raydium/stable/instructions.rs
|
||||
https://github.com/pinax-network/substreams-solana-idls/tree/main/src/raydium/stable/events.rs
|
||||
https://github.com/pinax-network/substreams-solana-idls/tree/main/src/raydium/stable/accounts.rs
|
||||
```
|
||||
|
||||
## Solscan — liens exploratoires
|
||||
|
||||
Base non filtrée :
|
||||
|
||||
```text
|
||||
https://solscan.io/account/5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h?hide_spam=false&hide_failed=false&show_related=true&sort=desc
|
||||
```
|
||||
|
||||
Base non filtrée sans related :
|
||||
|
||||
```text
|
||||
https://solscan.io/account/5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h?hide_spam=false&hide_failed=false&show_related=false&sort=desc
|
||||
```
|
||||
|
||||
### Essais courts `instruction=00..11`
|
||||
|
||||
Ces liens sont exploratoires. Ils ne prouvent pas que le program utilise des discriminants 1 octet ; ils servent seulement à tester le comportement Solscan quand aucun IDL n’est présent.
|
||||
|
||||
```text
|
||||
instruction=00
|
||||
https://solscan.io/account/5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h?instruction=00&hide_spam=false&hide_failed=false&show_related=false&sort=desc
|
||||
|
||||
instruction=01
|
||||
https://solscan.io/account/5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h?instruction=01&hide_spam=false&hide_failed=false&show_related=false&sort=desc
|
||||
|
||||
instruction=02
|
||||
https://solscan.io/account/5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h?instruction=02&hide_spam=false&hide_failed=false&show_related=false&sort=desc
|
||||
|
||||
instruction=03
|
||||
https://solscan.io/account/5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h?instruction=03&hide_spam=false&hide_failed=false&show_related=false&sort=desc
|
||||
|
||||
instruction=04
|
||||
https://solscan.io/account/5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h?instruction=04&hide_spam=false&hide_failed=false&show_related=false&sort=desc
|
||||
|
||||
instruction=05
|
||||
https://solscan.io/account/5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h?instruction=05&hide_spam=false&hide_failed=false&show_related=false&sort=desc
|
||||
|
||||
instruction=06
|
||||
https://solscan.io/account/5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h?instruction=06&hide_spam=false&hide_failed=false&show_related=false&sort=desc
|
||||
|
||||
instruction=07
|
||||
https://solscan.io/account/5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h?instruction=07&hide_spam=false&hide_failed=false&show_related=false&sort=desc
|
||||
|
||||
instruction=08
|
||||
https://solscan.io/account/5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h?instruction=08&hide_spam=false&hide_failed=false&show_related=false&sort=desc
|
||||
|
||||
instruction=09
|
||||
https://solscan.io/account/5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h?instruction=09&hide_spam=false&hide_failed=false&show_related=false&sort=desc
|
||||
|
||||
instruction=0a
|
||||
https://solscan.io/account/5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h?instruction=0a&hide_spam=false&hide_failed=false&show_related=false&sort=desc
|
||||
|
||||
instruction=0b
|
||||
https://solscan.io/account/5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h?instruction=0b&hide_spam=false&hide_failed=false&show_related=false&sort=desc
|
||||
|
||||
instruction=0c
|
||||
https://solscan.io/account/5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h?instruction=0c&hide_spam=false&hide_failed=false&show_related=false&sort=desc
|
||||
|
||||
instruction=0d
|
||||
https://solscan.io/account/5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h?instruction=0d&hide_spam=false&hide_failed=false&show_related=false&sort=desc
|
||||
|
||||
instruction=0e
|
||||
https://solscan.io/account/5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h?instruction=0e&hide_spam=false&hide_failed=false&show_related=false&sort=desc
|
||||
|
||||
instruction=0f
|
||||
https://solscan.io/account/5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h?instruction=0f&hide_spam=false&hide_failed=false&show_related=false&sort=desc
|
||||
|
||||
instruction=10
|
||||
https://solscan.io/account/5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h?instruction=10&hide_spam=false&hide_failed=false&show_related=false&sort=desc
|
||||
|
||||
instruction=11
|
||||
https://solscan.io/account/5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h?instruction=11&hide_spam=false&hide_failed=false&show_related=false&sort=desc
|
||||
```
|
||||
|
||||
### Essais discriminants 8 octets Carbon/Pinax
|
||||
|
||||
À tester aussi, mais ne pas bloquer si Solscan ne filtre rien.
|
||||
|
||||
```text
|
||||
initialize / afaf6d1f0d989bed
|
||||
https://solscan.io/account/5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h?instruction=afaf6d1f0d989bed&hide_spam=false&hide_failed=false&show_related=false&sort=desc
|
||||
|
||||
pre_initialize / ff5c572dc6acec02
|
||||
https://solscan.io/account/5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h?instruction=ff5c572dc6acec02&hide_spam=false&hide_failed=false&show_related=false&sort=desc
|
||||
|
||||
deposit / f223c68952e1f2b6
|
||||
https://solscan.io/account/5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h?instruction=f223c68952e1f2b6&hide_spam=false&hide_failed=false&show_related=false&sort=desc
|
||||
|
||||
withdraw / b712469c946da122
|
||||
https://solscan.io/account/5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h?instruction=b712469c946da122&hide_spam=false&hide_failed=false&show_related=false&sort=desc
|
||||
|
||||
swap_base_in / 2aec48a2f2182754
|
||||
https://solscan.io/account/5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h?instruction=2aec48a2f2182754&hide_spam=false&hide_failed=false&show_related=false&sort=desc
|
||||
|
||||
swap_base_out / a3d29bd0af92d596
|
||||
https://solscan.io/account/5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h?instruction=a3d29bd0af92d596&hide_spam=false&hide_failed=false&show_related=false&sort=desc
|
||||
```
|
||||
|
||||
## Instructions/discriminants de départ à couvrir
|
||||
|
||||
À partir de Carbon stable swap, à vérifier contre Pinax :
|
||||
|
||||
```text
|
||||
initialize afaf6d1f0d989bed pool_create / k_sol_pool_lifecycle_events
|
||||
pre_initialize ff5c572dc6acec02 pool_create deprecated/partial / k_sol_pool_lifecycle_events si pool context suffisant
|
||||
deposit f223c68952e1f2b6 liquidity_add / k_sol_liquidity_events
|
||||
withdraw b712469c946da122 liquidity_remove / k_sol_liquidity_events
|
||||
swap_base_in 2aec48a2f2182754 swap / k_sol_trade_events
|
||||
swap_base_out a3d29bd0af92d596 swap / k_sol_trade_events
|
||||
```
|
||||
|
||||
Si Pinax expose des discriminants numériques ou une ABI non Anchor, ne pas forcer les discriminants 8 octets. Le decoder local doit suivre le layout prouvé par corpus local.
|
||||
|
||||
## Objectif `0.7.52` — `raydium_stable_swap`
|
||||
|
||||
Reprendre Raydium Stable Swap au même niveau de couverture que CPMM/CLMM/AMM v4 :
|
||||
|
||||
```text
|
||||
initialize / pre_initialize
|
||||
pool lifecycle / pool_create
|
||||
deposit / withdraw
|
||||
swap_base_in / swap_base_out
|
||||
fees / admin/config si présents dans IDL/events/accounts
|
||||
OpenBook/Serum side effects documentés si présents
|
||||
side effects SPL Token / Token-2022 documentés mais non promus comme raydium_stable_swap.* directs
|
||||
fallback instruction_audit nettoyé quand une entrée locale spécialisée couvre l’instruction
|
||||
coverage entries synchronisées et rafraîchies
|
||||
decoded-only explicitement expliqué quand la matérialisation métier est impossible
|
||||
```
|
||||
|
||||
## Règles fixes
|
||||
|
||||
```text
|
||||
Rust 2024
|
||||
pas de mod.rs
|
||||
fichiers Rust avec // file: ...
|
||||
pas de anyhow
|
||||
pas de thiserror
|
||||
pas de ? / unwrap / expect dans kb_lib applicatif
|
||||
match / if let Err / let Err = ... else
|
||||
rustdoc sur API publique
|
||||
re-exports db.rs puis lib.rs si DB modifiée
|
||||
```
|
||||
|
||||
## Invariants métier
|
||||
|
||||
```text
|
||||
non-trade event = jamais trade/candle
|
||||
failed transaction = audit-only / jamais matérialisée métier
|
||||
upstream Git/IDL/Solscan = indice, pas preuve métier
|
||||
program id upstream non promu sans corpus local
|
||||
side effects SPL Token / Token-2022 restent transversaux sauf preuve multi-DEX et décision DB
|
||||
instruction_audit et upstream_git.instruction_match doivent être nettoyés quand une entrée locale spécialisée couvre le discriminant
|
||||
observed_count ne doit pas obligatoirement égaler materialized_count
|
||||
règle de clôture : observed_count = materialized_count + decoded_only_explained_count + failed_count
|
||||
```
|
||||
|
||||
## Workflow conseillé
|
||||
|
||||
1. Créer une nouvelle base SQLite dédiée `0.7.52`.
|
||||
2. Inventorier Carbon + Pinax pour `raydium_stable_swap`.
|
||||
3. Vérifier explicitement le program id `5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h`.
|
||||
4. Vérifier si les discriminants sont 8 octets Anchor-like, 1 octet, ou autre layout.
|
||||
5. Synchroniser `k_sol_dex_event_coverage_entries` avec `decoder_code = raydium_stable_swap`.
|
||||
6. Utiliser Solscan seulement comme aide exploratoire ; si le filtre instruction échoue, utiliser Demo3 program_id + signatures récentes/non filtrées.
|
||||
7. Backfill Demo2 signature/pool sur corpus varié.
|
||||
8. Replay local avec :
|
||||
|
||||
```text
|
||||
skipDexDecode = no
|
||||
forceDexDecode = yes
|
||||
deferInstructionObservations = yes
|
||||
```
|
||||
|
||||
9. Vérifier :
|
||||
|
||||
```text
|
||||
coverage listed/observed/materialized
|
||||
residual instruction_audit
|
||||
residual upstream_git.instruction_match
|
||||
decoded without coverage entry
|
||||
failed tx materialization = 0
|
||||
non-trade trade_count = 0
|
||||
single-target materialization
|
||||
trade/candle only for swap events validés
|
||||
decoded-only explanations
|
||||
```
|
||||
|
||||
## SQL de contrôle minimal `0.7.52`
|
||||
|
||||
Coverage stable swap :
|
||||
|
||||
```sql
|
||||
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;
|
||||
```
|
||||
|
||||
Instruction observations :
|
||||
|
||||
```sql
|
||||
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;
|
||||
```
|
||||
|
||||
Residual audit :
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
json_extract(payload_json, '$.discriminatorHex') AS discriminator_hex,
|
||||
COUNT(*) AS audit_count,
|
||||
COUNT(DISTINCT transaction_id) AS tx_count
|
||||
FROM k_sol_dex_decoded_events
|
||||
WHERE protocol_name = 'raydium_stable_swap'
|
||||
AND event_kind = 'raydium_stable_swap.instruction_audit'
|
||||
GROUP BY discriminator_hex
|
||||
ORDER BY audit_count DESC, discriminator_hex;
|
||||
```
|
||||
|
||||
Fallback upstream :
|
||||
|
||||
```sql
|
||||
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;
|
||||
```
|
||||
|
||||
Non-swap safety :
|
||||
|
||||
```sql
|
||||
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;
|
||||
```
|
||||
|
||||
Failed tx safety :
|
||||
|
||||
```sql
|
||||
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;
|
||||
```
|
||||
|
||||
Decoded without coverage :
|
||||
|
||||
```sql
|
||||
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;
|
||||
```
|
||||
|
||||
Multi-target materialization :
|
||||
|
||||
```sql
|
||||
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;
|
||||
```
|
||||
|
||||
Unexplained successful non-materialized events :
|
||||
|
||||
```sql
|
||||
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;
|
||||
```
|
||||
|
||||
Materialization summary :
|
||||
|
||||
```sql
|
||||
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;
|
||||
```
|
||||
|
||||
## Livrables attendus
|
||||
|
||||
```text
|
||||
archive delta fichiers modifiés/ajoutés
|
||||
README.md / ROADMAP.md / CHANGELOG.md mis à jour
|
||||
docs/DEX_DECODER_MATRIX.md
|
||||
docs/DEX_EVENT_COVERAGE_MATRIX.md
|
||||
docs/DB_EVENT_MODEL_REVIEW.md
|
||||
docs/reports/RAYDIUM_STABLE_SWAP_EVENT_COVERAGE_REPORT.md
|
||||
validation_sql/SQL_VALIDATION_RAYDIUM_STABLE_SWAP_0_7_52.sql
|
||||
```
|
||||
|
||||
Validation finale locale :
|
||||
|
||||
```bash
|
||||
cargo fmt
|
||||
cargo test -p kb_lib
|
||||
cargo clippy -p kb_lib --all-targets -- -D warnings
|
||||
```
|
||||
|
||||
## Critères de clôture `0.7.52`
|
||||
|
||||
```text
|
||||
tous les discriminants stable swap connus sont listés en coverage
|
||||
tous les discriminants stable swap connus sont observés localement ou explicitement marqués mapped_unverified
|
||||
instruction_audit résiduel vide pour les discriminants couverts
|
||||
fallback upstream_git.instruction_match résiduel vide pour les discriminants couverts
|
||||
decoded without coverage vide
|
||||
non-swap -> trade vide
|
||||
failed tx -> trade vide
|
||||
multi-target materialization vide
|
||||
successful decoded-only events expliqués par skip*Reason
|
||||
trade/candle uniquement pour swaps avec montants fiables
|
||||
deposit/withdraw uniquement vers liquidity
|
||||
initialize/pre_initialize uniquement vers lifecycle
|
||||
simulate/transport éventuel reste decoded-only sauf preuve métier
|
||||
```
|
||||
Reference in New Issue
Block a user