v0.1.0-pre.073
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
<!-- file: docs/reports/DEX_COVERAGE_GLOBAL_WATCHLIST_0_7_53.md -->
|
||||
|
||||
# DEX coverage global watchlist — `0.7.53`
|
||||
|
||||
## Objet
|
||||
|
||||
Ce rapport accompagne la clôture `0.7.53 pump_swap`. Il sépare les anomalies bloquantes des files de travail futures.
|
||||
|
||||
`pump_swap` est clos côté transaction/log decoder et matérialisation métier. Les lignes restantes de surveillance globale ne sont pas des erreurs PumpSwap.
|
||||
|
||||
## Résultat de clôture PumpSwap
|
||||
|
||||
Validation rapportée :
|
||||
|
||||
```text
|
||||
cargo test -p kb_lib -> 421 passed / 0 failed
|
||||
cargo clippy -p kb_lib --all-targets -- -D warnings -> OK
|
||||
```
|
||||
|
||||
Replay élargi rapporté :
|
||||
|
||||
```text
|
||||
1189 replayed
|
||||
0 decode skipped
|
||||
1189 ledger upserts
|
||||
967 unsafe ledger rows
|
||||
928 trades
|
||||
13 liquidity
|
||||
8 lifecycle
|
||||
0 tokenAccount
|
||||
3700 candle upserts
|
||||
instructionObservations = 25724
|
||||
resetDeleted = 5622
|
||||
catalog = 76 tokens / 80 pools / 80 pairs
|
||||
```
|
||||
|
||||
Checks PumpSwap attendus vides :
|
||||
|
||||
- decoded events sans coverage ;
|
||||
- fallback `upstream_git` couvert localement ;
|
||||
- successful trade candidates sans trade et sans raison explicite ;
|
||||
- failed transaction matérialisée en business trade ;
|
||||
- non-swap matérialisé en trade ;
|
||||
- multi-target materialization.
|
||||
|
||||
`buy_exact_quote_in` :
|
||||
|
||||
```text
|
||||
pump_swap_anchor_buy_event -> 168 decoded / 167 trades / 1 failed tx
|
||||
instruction_bounds_only -> decoded-only, sans trade
|
||||
```
|
||||
|
||||
## Non-régression Raydium
|
||||
|
||||
Les checks ciblés Raydium AMM v4 / CLMM / CPMM normalisés sont vides. Il n'y a pas de correction Raydium à inclure dans `0.7.53`.
|
||||
|
||||
Lecture correcte :
|
||||
|
||||
- `raydium_amm_v4.swap_base_in_v2` : observé et matérialisé dans le corpus courant ;
|
||||
- `raydium_clmm.swap_v2` : observé et matérialisé dans le corpus courant ;
|
||||
- `raydium_cpmm.swap_base_input` : observé et matérialisé dans le corpus courant ;
|
||||
- les entrées `upstream_git_mapped_unverified` avec `observed_count=0` sont des entrées registry non observées, pas des régressions.
|
||||
|
||||
## Gaps locaux reportés
|
||||
|
||||
La requête globale `local decoded events without coverage` retourne des gaps Meteora connus et reportés :
|
||||
|
||||
```text
|
||||
meteora_dlmm.swap
|
||||
meteora_damm_v2.instruction_audit
|
||||
meteora_damm_v2.swap
|
||||
```
|
||||
|
||||
Décision : ne pas les corriger dans `0.7.53`. Ils seront repris dans les tranches Meteora futures.
|
||||
|
||||
## Backlog upstream observé
|
||||
|
||||
La file `upstream_git.instruction_match` indique les prochaines surfaces à prioriser. Au moment de la clôture :
|
||||
|
||||
| Priorité | Surface | Indice principal | Décision |
|
||||
|---:|---|---|---|
|
||||
| 1 | `pump_fees` | `get_fees` très fréquent | Prochaine tranche recommandée ; aucun trade/candle direct attendu. |
|
||||
| 2 | `pump_fun` | creator fees, migrate, set/admin creator | Tranche launch/bonding séparée. |
|
||||
| 3 | `jupiter_swap` | `route_v2`, `create_token_account`, `route` | Agrégateur/router ; éviter double-count DEX effectifs. |
|
||||
| 4 | `dflow_aggregator_v4`, `onchain_labs_dex_v2` | swaps/route helpers | Surfaces secondaires après Pump/Meteora. |
|
||||
| 5 | `orca_whirlpools` | faibles occurrences | À reprendre plus tard avec corpus dédié. |
|
||||
|
||||
## Observations non attribuées
|
||||
|
||||
Les observations avec `decoder_code` vide ne doivent pas être traitées comme des discriminants Anchor confirmés. Elles exigent d'abord :
|
||||
|
||||
1. inspection de `sample_signature` ;
|
||||
2. extraction du `program_id` effectif ;
|
||||
3. comparaison aux IDL locales `idls/` et aux sources Git ;
|
||||
4. ajout d'un decoder ou d'un statut explicite seulement si le programme est identifié.
|
||||
|
||||
## Source IDL locale
|
||||
|
||||
Le répertoire `idls/` est désormais une source locale de savoir. Les IDL téléchargées depuis Solscan doivent être utilisées en plus des liens Git, avec la règle suivante : une IDL donne une surface possible, mais la matérialisation métier exige corpus, replay et SQL.
|
||||
|
||||
## Vérification `raydium_pool_v4.json`
|
||||
|
||||
Fichier Git vérifié : `0xfnzero/sol-parser-sdk/idls/raydium_pool_v4.json`.
|
||||
|
||||
Constats :
|
||||
|
||||
- la page GitHub annonce `3400` lignes / environ `101 KB` ;
|
||||
- le fichier expose notamment `swapBaseIn`, `addLiquidity` et des comptes OpenBook/Serum (`OpenBookMarket`, `OpenBookBids`, `OpenBookAsks`, etc.) ;
|
||||
- la chaîne du program id AMM v4 `675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8` n'apparaît pas dans la page GitHub consultée ;
|
||||
- aucun fichier local `idls/raydium_*.json` ne porte le nom `raydium_pool_v4` ;
|
||||
- les fichiers Raydium locaux présents sont `raydium_clmm`, `raydium_cpmm`, `raydium_launchlab` et `raydium_lock`.
|
||||
|
||||
Table locale :
|
||||
|
||||
| Fichier local | Name IDL | Address IDL | Taille | SHA-256 |
|
||||
|---|---|---|---:|---|
|
||||
| `idls/raydium_clmm.CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK.json` | `raydium_clmm` | `CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK` | 86240 | `d3f265adc9e4d7b1a28641444800a60bcdeb921ef136855fe8dea4532afa18bd` |
|
||||
| `idls/raydium_cpmm.CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C.json` | `raydium_cp_swap` | `CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C` | 32066 | `5b709dfe7b0df67c9e29655307ae877244d3bb8022056ee01c754f0e36264d9c` |
|
||||
| `idls/raydium_launchlab.LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj.json` | `raydium_launchpad` | `LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj` | 68052 | `c1465a10f38912413f55f04a68536c989992add1b3d48cba86dca97212a482da` |
|
||||
| `idls/raydium_lock.LockrWmn6K5twhz3y9w1dQERbmgSaRkfnTeTKbpofwE.json` | `raydium_liquidity_locking` | absent | 10621 | `da45fd5eaf726e5e2ead7280c04588ebd4224d203304cdc8217b012b8130e1f1` |
|
||||
|
||||
Décision : `raydium_pool_v4.json` ne correspond à aucun fichier JSON local actuel. Il reste une source annexe d'audit AMM v4/strategy/wrapper à traiter plus tard, sans bloquer `0.7.53`.
|
||||
|
||||
## SQL associé
|
||||
|
||||
Voir :
|
||||
|
||||
```text
|
||||
validation_sql/SQL_VALIDATION_DEX_COVERAGE_GLOBAL_0_7_53.sql
|
||||
```
|
||||
@@ -0,0 +1,151 @@
|
||||
<!-- file: docs/reports/FEE_EVENT_AMOUNTS_MODEL_NOTE_0_7_56.md -->
|
||||
|
||||
# Note technique — `k_sol_fee_event_amounts` et policy fees — `0.7.56`
|
||||
|
||||
## Objectif
|
||||
|
||||
La table `k_sol_fee_events` était suffisante pour un fee mono-montant, mais insuffisante pour les cas multi-mint, multi-destination ou multi-composant. `0.7.56` ajoute donc `k_sol_fee_event_amounts` comme table de legs rattachée au parent fee.
|
||||
|
||||
## Modèle
|
||||
|
||||
```text
|
||||
k_sol_fee_events
|
||||
id
|
||||
transaction_id
|
||||
decoded_event_id
|
||||
fee_token_mint nullable / vide si multi-leg
|
||||
fee_amount_raw nullable / vide si multi-leg
|
||||
payload_json
|
||||
|
||||
k_sol_fee_event_amounts
|
||||
id
|
||||
fee_event_id
|
||||
transaction_id
|
||||
decoded_event_id
|
||||
leg_index
|
||||
fee_component_kind
|
||||
token_mint
|
||||
amount_raw
|
||||
source_account
|
||||
destination_account
|
||||
amount_source
|
||||
payload_json
|
||||
```
|
||||
|
||||
## Règles invariantes
|
||||
|
||||
1. Un parent fee scalaire avec `fee_token_mint + fee_amount_raw` doit toujours avoir un leg `0`.
|
||||
2. Un parent multi-leg ou multi-mint ne doit pas agréger artificiellement ses montants dans le parent.
|
||||
3. Les legs doivent pointer vers le même `transaction_id` et `decoded_event_id` que le parent.
|
||||
4. Les legs doivent être supprimés/remplacés lors du replay/cleanup parent.
|
||||
5. Les transactions failed ne doivent pas créer de parent ou leg fee métier.
|
||||
6. Les bornes d'instruction (`maxAmount`, `minAmount`, `u64::MAX`) ne sont pas des montants exécutés.
|
||||
|
||||
## Sources de montant acceptées
|
||||
|
||||
| `amount_source` | Usage |
|
||||
|---|---|
|
||||
| `parent_fee_event_amount` | Leg généré automatiquement depuis un parent scalaire déjà fiable. |
|
||||
| `fee_event_amounts` | Source explicite reconstruite par un matérialisateur spécialisé. |
|
||||
| `inner_spl_transfer` | CPI SPL vérifié dans un matérialisateur spécialisé. |
|
||||
| `lamport_balance_delta` | Delta lamports prouvé et contextualisé. |
|
||||
| `allowlisted_inner_spl_transfer` | Recovery générique mais strictement allowlistée pour event kinds déjà validés. |
|
||||
|
||||
## Recovery allowlistée
|
||||
|
||||
La recovery `allowlisted_inner_spl_transfer` n'est pas une règle globale. Elle s'applique seulement aux event kinds explicitement autorisés dans le code. Cette restriction protège les futurs décodeurs : une nouvelle surface ne doit jamais créer des legs fee à partir de transferts internes tant que la sémantique n'a pas été inspectée.
|
||||
|
||||
Résultats de validation croisée en `0.7.56` :
|
||||
|
||||
| Base / surface | Effet observé |
|
||||
|---|---|
|
||||
| `meteora_dbc` | Aucun usage de l'allowlist générique ; chemins spécialisés DBC conservés. |
|
||||
| `raydium_launchpad` | `212` parents enrichis en legs : `claim_creator_fee`, `claim_platform_fee`, `claim_platform_fee_from_vault`, `collect_fee`. |
|
||||
| `raydium_cpmm` | `collect_creator_fee` enrichi ; `collect_fund_fee` / `collect_protocol_fee` explicités sans transfert exploitable. |
|
||||
| `pump_swap` | `collect_coin_creator_fee` et un `transfer_creator_fees_to_pump_v2` enrichis ; autres cas zero/no-transfer explicités. |
|
||||
| `pump_fees` | `crank_donation_fee_pda` et `sweep_buyback` enrichis ; events déjà scalaires conservés. |
|
||||
|
||||
## Contrôles SQL obligatoires
|
||||
|
||||
### Parent scalaire sans leg
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
de.protocol_name,
|
||||
de.event_kind,
|
||||
tx.signature,
|
||||
fee.id AS fee_event_id,
|
||||
fee.fee_token_mint,
|
||||
fee.fee_amount_raw,
|
||||
fee.payload_json
|
||||
FROM k_sol_fee_events fee
|
||||
JOIN k_sol_dex_decoded_events de
|
||||
ON de.id = fee.decoded_event_id
|
||||
JOIN k_sol_chain_transactions tx
|
||||
ON tx.id = fee.transaction_id
|
||||
LEFT JOIN k_sol_fee_event_amounts fea
|
||||
ON fea.fee_event_id = fee.id
|
||||
WHERE COALESCE(TRIM(fee.fee_token_mint), '') <> ''
|
||||
AND COALESCE(TRIM(fee.fee_amount_raw), '') <> ''
|
||||
AND fea.id IS NULL
|
||||
ORDER BY
|
||||
de.protocol_name,
|
||||
de.event_kind,
|
||||
tx.signature
|
||||
LIMIT 100;
|
||||
```
|
||||
|
||||
Attendu : vide.
|
||||
|
||||
### Legs orphelins
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
fea.id,
|
||||
fea.fee_event_id,
|
||||
fea.transaction_id,
|
||||
fea.decoded_event_id
|
||||
FROM k_sol_fee_event_amounts fea
|
||||
LEFT JOIN k_sol_fee_events fee
|
||||
ON fee.id = fea.fee_event_id
|
||||
WHERE fee.id IS NULL;
|
||||
```
|
||||
|
||||
Attendu : vide.
|
||||
|
||||
### Résumé parent/legs par event
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
de.protocol_name,
|
||||
de.event_kind,
|
||||
COUNT(DISTINCT fee.id) AS fee_parent_count,
|
||||
COUNT(DISTINCT CASE
|
||||
WHEN COALESCE(TRIM(fee.fee_token_mint), '') <> ''
|
||||
AND COALESCE(TRIM(fee.fee_amount_raw), '') <> ''
|
||||
THEN fee.id
|
||||
ELSE NULL
|
||||
END) AS parent_with_scalar_amount_count,
|
||||
COUNT(DISTINCT fea.id) AS fee_amount_leg_count,
|
||||
MIN(tx.signature) AS sample_signature
|
||||
FROM k_sol_fee_events fee
|
||||
JOIN k_sol_dex_decoded_events de
|
||||
ON de.id = fee.decoded_event_id
|
||||
JOIN k_sol_chain_transactions tx
|
||||
ON tx.id = fee.transaction_id
|
||||
LEFT JOIN k_sol_fee_event_amounts fea
|
||||
ON fea.fee_event_id = fee.id
|
||||
GROUP BY
|
||||
de.protocol_name,
|
||||
de.event_kind
|
||||
ORDER BY
|
||||
de.protocol_name,
|
||||
de.event_kind;
|
||||
```
|
||||
|
||||
## Règles pour `0.7.57 meteora_dlmm`
|
||||
|
||||
- Les instructions `claim_fee`, `claim_fee2`, `withdraw_protocol_fee`, `zap_protocol_fee`, `CompositionFee`, `ClaimFee`, `ClaimFee2` doivent utiliser `k_sol_fee_event_amounts` dès qu'un montant/mint fiable est disponible.
|
||||
- Les rewards (`claim_reward*`, `fund_reward`, `withdraw_ineligible_reward`) vont vers `k_sol_reward_events`, pas vers fees, sauf sémantique contraire prouvée.
|
||||
- Les `composition_fee` de swap/liquidity ne doivent pas être double-comptés si déjà inclus dans le trade/liquidity effectif.
|
||||
- Toute recovery générique doit être déclarée par policy explicite et tests synthétiques ; ne pas ajouter DLMM à l'allowlist sans audit par event kind.
|
||||
@@ -0,0 +1,161 @@
|
||||
<!-- file: docs/reports/METEORA_DBC_EVENT_COVERAGE_REPORT.md -->
|
||||
|
||||
# Meteora DBC Event Coverage Report — `0.7.56 final`
|
||||
|
||||
## Statut final
|
||||
|
||||
La tranche `0.7.56 meteora_dbc` est clôturée.
|
||||
|
||||
Program id :
|
||||
|
||||
```text
|
||||
dbcij3LWUppWqq96dh6gJWwBifmcGfLSB5D4DuSMaqN
|
||||
```
|
||||
|
||||
Source locale prioritaire :
|
||||
|
||||
```text
|
||||
idls/meteora_dbc.dbcij3LWUppWqq96dh6gJWwBifmcGfLSB5D4DuSMaqN.json
|
||||
```
|
||||
|
||||
Surface IDL : `28` instructions, `23` events Anchor, `9` accounts, `59` types.
|
||||
|
||||
## Résultat build/replay final
|
||||
|
||||
```text
|
||||
cargo test -p kb_lib -> 446 passed / 0 failed
|
||||
cargo clippy -p kb_lib --all-targets -- -D warnings -> OK
|
||||
480 replayed
|
||||
0 decode skipped
|
||||
480 ledger upserts
|
||||
454 unsafe ledger rows
|
||||
264 trades
|
||||
1 liquidity
|
||||
122 lifecycle
|
||||
0 tokenAccount
|
||||
1056 candle upserts
|
||||
instructionObservations = 7167
|
||||
resetDeleted = 3583
|
||||
catalog = 86 tokens / 60 pools / 60 pairs
|
||||
```
|
||||
|
||||
Replay final recommandé pour reproduire :
|
||||
|
||||
```text
|
||||
skipDexDecode=no
|
||||
forceDexDecode=yes
|
||||
deferInstructionObservations=yes
|
||||
```
|
||||
|
||||
## Décisions métier verrouillées
|
||||
|
||||
### Swaps
|
||||
|
||||
- `meteora_dbc.swap` et `meteora_dbc.swap2` sont les seules entrées candidates trade/candle directes.
|
||||
- Les trades/candles ne sont produits que si les montants exécutés et les mints base/quote sont fiables.
|
||||
- Les montants de `swap2` doivent être dérivés du layout et/ou des CPI SPL effectifs ; ne pas utiliser naïvement les bornes d'instruction.
|
||||
- Les events Anchor `EvtSwap` / `EvtSwap2` restent decoded-only s'ils ne portent pas un contexte mint/pair suffisant ou s'ils doublonnent l'instruction matérialisée.
|
||||
|
||||
### Lifecycle / migration / lockers
|
||||
|
||||
- `initialize_virtual_pool_with_spl_token` et `initialize_virtual_pool_with_token2022` alimentent lifecycle/catalog lorsque les comptes pool/base/quote/config sont fiables.
|
||||
- `create_locker`, `migrate_meteora_damm_claim_lp_token`, `migrate_meteora_damm_lock_lp_token`, `migration_damm_v2*` et `migrate_meteora_damm*` sont lifecycle, pas liquidity artificielle.
|
||||
- Les metadata-only restent decoded-only avec raison explicite si elles n'apportent pas de cible métier fiable.
|
||||
|
||||
### Admin/config
|
||||
|
||||
- `create_config`, `create_operator_account`, `close_*operator*`, metadata, `transfer_pool_creator` et events config/admin alimentent `k_sol_pool_admin_events` uniquement si l'acteur et la cible sont fiables.
|
||||
- Les payloads génériques ou incomplets restent audit/decoded-only.
|
||||
|
||||
### Fees
|
||||
|
||||
- Les fees DBC utilisent le modèle parent+legs : `k_sol_fee_events` + `k_sol_fee_event_amounts`.
|
||||
- Les maxima d'instruction (`maxAmount*`, `u64::MAX`, bornes de claim) ne sont pas des montants exécutés.
|
||||
- Les montants fiables proviennent des CPI SPL, des legs explicitement reconstruits ou des lamport balance deltas prouvés.
|
||||
- Les events Anchor fee sans mint restent decoded-only avec `skipFeeReason`.
|
||||
- Les cas sans transfert réel portent `fee_instruction_has_no_actual_transfer` ou `fee_instruction_has_only_zero_amount_transfers`.
|
||||
|
||||
## Matérialisation fee finale
|
||||
|
||||
| Event kind | Fee parents | Parents scalaires | Amount legs | Décision |
|
||||
|---|---:|---:|---:|---|
|
||||
| `meteora_dbc.claim_creator_trading_fee` | 8 | 8 | 8 | Mono-leg fiable. |
|
||||
| `meteora_dbc.claim_partner_pool_creation_fee` | 10 | 10 | 10 | Mono-leg fiable. |
|
||||
| `meteora_dbc.claim_protocol_fee` | 10 | 10 | 10 | Mono-leg fiable. |
|
||||
| `meteora_dbc.claim_protocol_pool_creation_fee` | 10 | 10 | 10 | Mono-leg/lamport delta fiable. |
|
||||
| `meteora_dbc.claim_trading_fee` | 11 | 6 | 18 | Mix mono-leg et multi-leg ; parent non agrégé pour multi-leg. |
|
||||
| `meteora_dbc.creator_withdraw_surplus` | 2 | 2 | 2 | Mono-leg fiable ; résiduels sans transfert réel explicités. |
|
||||
| `meteora_dbc.partner_withdraw_surplus` | 9 | 9 | 9 | Mono-leg fiable. |
|
||||
| `meteora_dbc.withdraw_leftover` | 10 | 10 | 10 | Mono-leg fiable. |
|
||||
| `meteora_dbc.withdraw_migration_fee` | 9 | 9 | 9 | Fee, pas migration target ; mono-leg fiable. |
|
||||
| `meteora_dbc.zap_protocol_fee` | 10 | 10 | 10 | Mono-leg fiable. |
|
||||
| **Total `meteora_dbc`** | **89** | n/a | **96** | Parent+legs validé. |
|
||||
|
||||
## Socle `k_sol_fee_event_amounts`
|
||||
|
||||
La version `0.7.56` ajoute un modèle durable pour les fees composés :
|
||||
|
||||
- `k_sol_fee_events` est le parent logique unique lié au `decoded_event_id` ;
|
||||
- `k_sol_fee_event_amounts` contient les legs de montants, avec `leg_index`, `fee_component_kind`, `token_mint`, `amount_raw`, comptes source/destination et `amount_source` ;
|
||||
- un parent avec `fee_token_mint + fee_amount_raw` crée automatiquement un leg scalaire ;
|
||||
- un parent multi-leg/multi-mint laisse les champs scalaires du parent vides et stocke tout dans les legs ;
|
||||
- les deletes/replays nettoient les legs avant ou avec le parent ;
|
||||
- la requête de contrôle `parent scalar without leg` doit rester vide.
|
||||
|
||||
Sources `amount_source` connues en fin de tranche :
|
||||
|
||||
```text
|
||||
parent_fee_event_amount
|
||||
fee_event_amounts
|
||||
inner_spl_transfer
|
||||
lamport_balance_delta
|
||||
allowlisted_inner_spl_transfer
|
||||
```
|
||||
|
||||
## Recovery fee allowlistée
|
||||
|
||||
La recovery `allowlisted_inner_spl_transfer` est volontairement non globale.
|
||||
|
||||
Elle a été testée sur anciennes bases pour enrichir les surfaces déjà connues :
|
||||
|
||||
| Surface testée | Résultat |
|
||||
|---|---|
|
||||
| `raydium_launchpad` | `claim_creator_fee`, `claim_platform_fee`, `claim_platform_fee_from_vault`, `collect_fee` enrichis en legs depuis CPI SPL. |
|
||||
| `raydium_cpmm` | `collect_creator_fee` enrichi ; `collect_fund_fee` et `collect_protocol_fee` restent sans transfert réel exploitable dans le corpus testé. |
|
||||
| `pump_swap` | `collect_coin_creator_fee` et certains `transfer_creator_fees_to_pump_v2` enrichis ; cas zero/no-transfer explicités. |
|
||||
| `pump_fees` | `crank_donation_fee_pda` et `sweep_buyback` enrichis ; events déjà scalaires conservés. |
|
||||
| `meteora_dbc` | Non concerné par l'allowlist générique ; DBC conserve ses chemins spécifiques. |
|
||||
|
||||
Règle pour les prochaines versions : tout nouveau decoder doit déclarer explicitement sa policy de récupération des montants fee. Aucun futur decoder ne doit hériter automatiquement de la recovery CPI SPL.
|
||||
|
||||
## Checks de fermeture
|
||||
|
||||
Les contrôles de fermeture exigés sont propres :
|
||||
|
||||
- fallback `upstream_git` `meteora_dbc` pour entrées couvertes localement : vide ;
|
||||
- decoded `meteora_dbc` sans coverage : vide ;
|
||||
- successful non-materialized sans `skip*Reason` ou policy explicite : vide ;
|
||||
- failed tx avec materialization métier : vide ;
|
||||
- multi-target materialization : vide ;
|
||||
- non-swap DBC vers trade/candle : vide ;
|
||||
- parent fee scalaire sans leg : vide ;
|
||||
- legs fee orphelins : vide ;
|
||||
- watchlist globale sans backlog dominant `meteora_dbc`.
|
||||
|
||||
## Fichiers de référence
|
||||
|
||||
```text
|
||||
kb_lib/src/dex/meteora_dbc.rs
|
||||
kb_lib/src/non_trade_event_materialization.rs
|
||||
kb_lib/src/db/queries/fee_event_amount.rs
|
||||
kb_lib/src/db/entities/fee_event_amount.rs
|
||||
kb_lib/src/db/dtos/fee_event_amount.rs
|
||||
validation_sql/SQL_VALIDATION_METEORA_DBC_0_7_56.sql
|
||||
docs/reports/FEE_EVENT_AMOUNTS_MODEL_NOTE_0_7_56.md
|
||||
docs/VALIDATION_STATUS_0_7_56_FINAL.md
|
||||
docs/prompts/PROMPT_0_7_57_METEORA_DLMM_FULL_DECODE_MATERIALIZATION.md
|
||||
```
|
||||
|
||||
## Décision
|
||||
|
||||
`0.7.56 meteora_dbc` est clôturé. La prochaine tranche est `0.7.57 meteora_dlmm` en full decode + full materialization.
|
||||
@@ -0,0 +1,182 @@
|
||||
# Meteora DLMM event coverage report — 0.7.57 final
|
||||
|
||||
## Scope
|
||||
|
||||
Version `0.7.57` closes `meteora_dlmm` from the local IDL and the dedicated local corpus.
|
||||
|
||||
Target program:
|
||||
|
||||
```text
|
||||
LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo
|
||||
```
|
||||
|
||||
Local IDL:
|
||||
|
||||
```text
|
||||
idls/meteora_dlmm.LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo.json
|
||||
```
|
||||
|
||||
Final inventoried surface:
|
||||
|
||||
```text
|
||||
76 IDL instructions
|
||||
30 Anchor events
|
||||
12 accounts
|
||||
```
|
||||
|
||||
The local corpus additionally identified discriminator `75c73e67068e1fcb` as `initialize_preset_parameter_v2`. This discriminator was not present in the local IDL under that spelling, but the transaction logs contain `Instruction: InitializePresetParameterV2`, the account layout is stable, and the instruction creates a 36-byte DLMM-owned preset parameter account through the system program.
|
||||
|
||||
## Final validation summary
|
||||
|
||||
```text
|
||||
cargo test -p kb_lib -> 460 passed / 0 failed
|
||||
cargo clippy -p kb_lib --all-targets -- -D warnings -> OK
|
||||
769 replayed
|
||||
0 decode skipped
|
||||
769 ledger upserts
|
||||
646 unsafe ledger rows
|
||||
106 trades
|
||||
664 liquidity
|
||||
1107 lifecycle
|
||||
0 tokenAccount
|
||||
424 candle upserts
|
||||
instructionObservations = 8062
|
||||
resetDeleted = 9898
|
||||
catalog = 169 tokens / 218 pools / 218 pairs
|
||||
```
|
||||
|
||||
## Closure checks
|
||||
|
||||
All blocking checks are clean:
|
||||
|
||||
```text
|
||||
upstream_git fallback for locally covered meteora_dlmm entries -> empty
|
||||
local instruction_audit observed -> 0
|
||||
DLMM decoded events without coverage -> empty
|
||||
successful non-materialized DLMM without explicit skip/policy -> empty
|
||||
failed transaction business materialization -> empty
|
||||
multi-target materialization -> empty
|
||||
non-swap trade/candle safety -> empty
|
||||
fee parent scalar without fee amount leg -> empty
|
||||
orphan fee amount legs -> empty
|
||||
limit/orderbook trade/candle double-count -> empty
|
||||
logical duplicate coverage rows -> empty
|
||||
```
|
||||
|
||||
The only coverage difference left is explained and non-blocking:
|
||||
|
||||
```text
|
||||
close_bin_array observed 16 / materialized 14
|
||||
14 successful transactions -> lifecycle materialized
|
||||
2 failed transactions Custom 6015 -> decoded/audit only, no business materialization
|
||||
```
|
||||
|
||||
## Materialization policy
|
||||
|
||||
### Trades and candles
|
||||
|
||||
Only instruction-level DLMM swaps can produce trades/candles:
|
||||
|
||||
```text
|
||||
meteora_dlmm.swap
|
||||
meteora_dlmm.swap2
|
||||
meteora_dlmm.swap_exact_out
|
||||
meteora_dlmm.swap_exact_out2
|
||||
meteora_dlmm.swap_with_price_impact
|
||||
meteora_dlmm.swap_with_price_impact2
|
||||
```
|
||||
|
||||
Anchor `swap_event` and `swap2_evt` are materialized as lifecycle `swap_log` rows and never as trades/candles. This prevents double-counting when an instruction swap and an Anchor log describe the same user-visible swap.
|
||||
|
||||
### Liquidity and lifecycle
|
||||
|
||||
The following families are materialized when transactions are successful and context is reliable:
|
||||
|
||||
```text
|
||||
add_liquidity*
|
||||
remove_liquidity*
|
||||
remove_all_liquidity
|
||||
rebalance_liquidity
|
||||
initialize_bin_array*
|
||||
close_bin_array
|
||||
go_to_a_bin*
|
||||
initialize_position*
|
||||
close_position*
|
||||
increase_position_length*
|
||||
decrease_position_length*
|
||||
update_position_operator*
|
||||
lb_pair_create_event
|
||||
position_create_event
|
||||
position_close_event
|
||||
```
|
||||
|
||||
Position and bin lifecycle events are routed to `k_sol_pool_lifecycle_events` when the operation is structural rather than a direct liquidity amount delta.
|
||||
|
||||
### Fees
|
||||
|
||||
Fee parents are written to `k_sol_fee_events`. Amount legs are written to `k_sol_fee_event_amounts`.
|
||||
|
||||
Final observed amount-leg summary:
|
||||
|
||||
```text
|
||||
claim_fee 64 parents / 64 legs
|
||||
claim_fee2 63 parents / 88 legs
|
||||
claim_fee_event 127 parents / 187 legs
|
||||
claim_fee2_event 78 parents / 118 legs
|
||||
composition_fee_event 51 parents / 63 legs
|
||||
withdraw_protocol_fee 14 parents / 20 legs
|
||||
zap_protocol_fee 13 parents / 13 legs
|
||||
```
|
||||
|
||||
The inner SPL transfer recovery is explicitly allowlisted for DLMM fee event kinds. It is not inherited globally by future decoders.
|
||||
|
||||
### Rewards
|
||||
|
||||
Reward parents are written to `k_sol_reward_events`. Amounts are recovered only when a reliable inner SPL transfer or decoded amount is present.
|
||||
|
||||
Final observed scalar amount summary:
|
||||
|
||||
```text
|
||||
claim_reward 15 parents / 1 scalar amount
|
||||
claim_reward2 19 parents / 10 scalar amounts
|
||||
claim_reward_event 34 parents / 25 scalar amounts
|
||||
claim_reward2_event 19 parents / 10 scalar amounts
|
||||
fund_reward 10 parents / 10 scalar amounts
|
||||
fund_reward_event 10 parents / 10 scalar amounts
|
||||
initialize_reward 9 parents / 0 amount
|
||||
initialize_reward_event 9 parents / 0 amount
|
||||
```
|
||||
|
||||
`initialize_reward` and `initialize_reward_event` remain without amount because they are configuration/initialization events, not executed reward transfers. No amount is fabricated from limits, bounds or configuration fields.
|
||||
|
||||
### Admin/config and orderbook
|
||||
|
||||
Admin/config events materialize to `k_sol_pool_admin_events`. Limit-order operations materialize to `k_sol_orderbook_events` and never to trade/candle tables.
|
||||
|
||||
Important promoted local corpus entry:
|
||||
|
||||
```text
|
||||
75c73e67068e1fcb -> meteora_dlmm.initialize_preset_parameter_v2 -> k_sol_pool_admin_events
|
||||
```
|
||||
|
||||
## Remaining non-observed surfaces
|
||||
|
||||
Non-observed IDL/account rows remain in coverage with `observed_count = 0` and `materialized_count = 0`. They are not blockers.
|
||||
|
||||
Examples:
|
||||
|
||||
```text
|
||||
update_reward_duration
|
||||
update_reward_funder
|
||||
withdraw_ineligible_reward
|
||||
migrate_position
|
||||
account metadata rows
|
||||
for_idl_type_generation_do_not_call
|
||||
anchor_self_cpi_log registry row
|
||||
```
|
||||
|
||||
## Decision
|
||||
|
||||
`0.7.57 meteora_dlmm` is closed. Do not add further DLMM Rust patches unless a new corpus proves a successful transaction that is decoded but not materialized and lacks an explicit skip/policy reason.
|
||||
|
||||
Next recommended work is not another DLMM patch: implement `0.7.58 sqlite_db_transaction_merger` first, then move `demo4_program_surface_discovery` to `0.7.59`. The merger is required to build a consolidated cross-DEX regression corpus before new surface discovery work.
|
||||
@@ -0,0 +1,134 @@
|
||||
<!-- file: docs/reports/PUMP_FEES_EVENT_COVERAGE_REPORT.md -->
|
||||
|
||||
# Pump Fees event coverage report — 0.7.55 final
|
||||
|
||||
## Portée
|
||||
|
||||
Programme cible : `pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ`.
|
||||
|
||||
Source locale prioritaire : `idls/pump_fees.pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ.json`.
|
||||
|
||||
L'IDL locale couvre `29` instructions, `20` events Anchor, `9` accounts et `34` types. La tranche ajoute un decoder local maximal `pump_fees` depuis l'IDL locale, le registre Carbon partiel et les discriminators observés via Solscan/corpus.
|
||||
|
||||
## Décisions métier
|
||||
|
||||
- `pump_fees` est traité comme programme fee/config/accounting.
|
||||
- Aucun `k_sol_trade_events` ni candle ne doit être créé pour `pump_fees` sans preuve transactionnelle stricte d'un swap autonome.
|
||||
- `get_fees` reste decoded-only : il décrit un calcul/preview de fees, pas un paiement réalisé.
|
||||
- Les claims social fee alimentent `k_sol_reward_events` seulement si transaction OK et montant/acteur/mint exploitables.
|
||||
- Les flux donation/buyback alimentent `k_sol_fee_events` seulement si transaction OK et montant fiable.
|
||||
- Les créations/configurations/autorités/tiers alimentent `k_sol_pool_lifecycle_events` ou `k_sol_pool_admin_events` selon classification.
|
||||
- Les transactions failed restent decoded-only/audit-only.
|
||||
|
||||
## Résultat build/test
|
||||
|
||||
```text
|
||||
cargo test -p kb_lib -> 431 passed / 0 failed
|
||||
cargo clippy -p kb_lib --all-targets -- -D warnings -> OK
|
||||
```
|
||||
|
||||
## Replay final rapporté
|
||||
|
||||
```text
|
||||
127 replayed
|
||||
0 decode skipped
|
||||
150 ledger upserts
|
||||
125 unsafe ledger rows
|
||||
4 trades
|
||||
0 liquidity
|
||||
115 lifecycle
|
||||
0 tokenAccount
|
||||
16 candle upserts
|
||||
instructionObservations = 2234
|
||||
resetDeleted = 1644
|
||||
catalog = 11 tokens / 10 pools / 10 pairs
|
||||
```
|
||||
|
||||
Les `4 trades` et `16 candle upserts` du replay proviennent d'autres surfaces du corpus local ; le contrôle anti-trade `pump_fees` est vide.
|
||||
|
||||
## Coverage local
|
||||
|
||||
### Instructions observées et couvertes
|
||||
|
||||
| Instruction | Discriminator | Observation principale | Matérialisation |
|
||||
|---|---:|---:|---|
|
||||
| `sweep_buyback` | `8a21cc26cfa19fe2` | `96` | `k_sol_fee_events` |
|
||||
| `create_fee_sharing_config` | `c34e564c6f34fbd5` | `42` observations / `36` decoded | `k_sol_pool_lifecycle_events` |
|
||||
| `update_fee_shares` | `bd0d8863bba4ed23` | `26` observations / `16` decoded | `k_sol_pool_admin_events` |
|
||||
| `claim_social_fee_pda_v2` | `114df0863abc3595` | `25` | `k_sol_reward_events` |
|
||||
| `update_fee_shares_v2` | `6ffb31064e4e6a12` | `19` | `k_sol_pool_admin_events` |
|
||||
| `claim_social_fee_pda` | `e115fb85a11ec7e2` | `15` observations / `10` decoded | `k_sol_reward_events` |
|
||||
| `crank_donation_fee_pda` | `dc0abda7a9111945` | `14` | `k_sol_fee_events` |
|
||||
| `get_fees` | `e7257e55cf5b3f34` | `13` observations / `5` decoded | decoded-only |
|
||||
| `transfer_fee_sharing_authority` | `ca0a4bc8a422d260` | `12` | `k_sol_pool_admin_events` |
|
||||
| `initialize_fee_program_global` | `23d78254e9387ca7` | `1` | `k_sol_pool_lifecycle_events` |
|
||||
|
||||
Le discriminator `e445a52e51cb9a1d` est classé comme `pump_fees.anchor_self_cpi_log` transport Anchor self-CPI : `271` observations / `119` tx.
|
||||
|
||||
### Instructions IDL non observées mais programmées
|
||||
|
||||
Ces entrées n'ont pas de signature Solscan/corpus au moment de la clôture, mais restent décodables si des transactions futures apparaissent :
|
||||
|
||||
| Instruction | Discriminator | Classification | Target prévu |
|
||||
|---|---:|---|---|
|
||||
| `reset_fee_sharing_config_v2` | `a9f511d15e5bf880` | admin_config | `k_sol_pool_admin_events` |
|
||||
| `set_authority` | `85fa25156ea31a79` | admin_config | `k_sol_pool_admin_events` |
|
||||
| `set_claim_rate_limit` | `b9d39faed4315804` | audit | decoded-only |
|
||||
| `set_disable_flags` | `c2d9702372de33be` | admin_config | `k_sol_pool_admin_events` |
|
||||
| `set_social_claim_authority` | `9336b89a88edb999` | admin_config | `k_sol_pool_admin_events` |
|
||||
|
||||
### Anchor events IDL non observés mais testés synthétiquement
|
||||
|
||||
| Event Anchor | Discriminator | Statut |
|
||||
|---|---:|---|
|
||||
| `SetAuthorityEvent` | `12af8442d0c957f2` | decoder + test synthétique |
|
||||
| `SetClaimRateLimitEvent` | `0d8f8febb5133328` | decoder + test synthétique |
|
||||
| `SetDisableFlagsEvent` | `0508b3413137917e` | decoder + test synthétique |
|
||||
| `SetSocialClaimAuthorityEvent` | `3c767f84ef34fe0e` | decoder + test synthétique |
|
||||
|
||||
### Discriminators Solscan hors IDL locale
|
||||
|
||||
Ces discriminators ont été trouvés par filtres Solscan, mais ne sont pas observés dans le corpus local final et ne sont pas dans l'IDL locale fournie. Ils restent conservés en coverage comme surfaces futures :
|
||||
|
||||
| Event | Discriminator | Statut |
|
||||
|---|---:|---|
|
||||
| `revoke_fee_sharing_authority_event` | `7217653c0ebe993e` | `upstream_git_mapped_unverified` |
|
||||
| `transfer_fee_sharing_authority_event` | `7c8fc6f54db808ec` | `upstream_git_mapped_unverified` |
|
||||
|
||||
## Écarts observed/materialized
|
||||
|
||||
Les écarts `observed_count > materialized_count` sont expliqués par des transactions failed ou par une politique decoded-only. La requête `09b` documente notamment :
|
||||
|
||||
| Entrée | Observed | Materialized | Explication |
|
||||
|---|---:|---:|---|
|
||||
| `get_fees` | `5` | `0` | decoded-only volontaire |
|
||||
| `claim_social_fee_pda_v2` | `25` | `21` | `4` failed decoded |
|
||||
| `create_fee_sharing_config` | `36` | `33` | `3` failed decoded |
|
||||
| `initialize_fee_config` | `5` | `2` | `3` failed decoded |
|
||||
| `social_fee_pda_claimed` | `17` | `15` | `2` failed decoded |
|
||||
| `crank_donation_fee_pda` | `14` | `12` | `2` failed decoded |
|
||||
| `update_fee_shares_v2` | `19` | `17` | `2` failed decoded |
|
||||
| `revoke_fee_sharing_authority` | `6` | `5` | `1` failed decoded |
|
||||
|
||||
La requête `06` confirme qu'il n'existe aucun successful non-materialized sans skip/policy explicite.
|
||||
|
||||
## Checks de fermeture
|
||||
|
||||
SQL dédié : `validation_sql/SQL_VALIDATION_PUMP_FEES_0_7_55.sql`.
|
||||
|
||||
Résultats de fermeture rapportés :
|
||||
|
||||
- fallback `upstream_git` `pump_fees` : vide ;
|
||||
- `instruction_name` `pump_fees` vide : vide ;
|
||||
- `event_family = unknown` ou vide pour instruction/event : vide ;
|
||||
- decoded `pump_fees` sans coverage : vide ;
|
||||
- fallback résiduel pour entrées couvertes localement : vide ;
|
||||
- successful non-materialized sans skip/policy : vide ;
|
||||
- failed transaction avec business materialization : vide ;
|
||||
- multi-target materialization : vide ;
|
||||
- anti-trade/candle direct `pump_fees` : vide ;
|
||||
- watchlist globale : plus aucun `pump_fees`, reste seulement `jupiter_swap.route_v2` comme backlog ponctuel.
|
||||
|
||||
## Statut final
|
||||
|
||||
`0.7.55 pump_fees` est clôturé techniquement. Ne pas rouvrir `pump_fees`, `pump_fun`, `pump_swap` ou Raydium sans bug prouvé par SQL/code ou apparition d'un nouveau discriminant/corpus externe exploitable.
|
||||
@@ -0,0 +1,127 @@
|
||||
<!-- file: docs/reports/PUMP_FUN_EVENT_COVERAGE_REPORT.md -->
|
||||
|
||||
# Pump.fun event coverage report — clôture `0.7.54`
|
||||
|
||||
## Statut du rapport
|
||||
|
||||
Ce rapport clôture la tranche `0.7.54 pump_fun` côté coverage, décodage local, matérialisation métier prudente et validation SQL.
|
||||
|
||||
Program id canonique :
|
||||
|
||||
```text
|
||||
6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P
|
||||
```
|
||||
|
||||
Source IDL locale prioritaire :
|
||||
|
||||
```text
|
||||
idls/pump_fun.6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P.json
|
||||
```
|
||||
|
||||
## Sources utilisées
|
||||
|
||||
- `kb_lib/src/dex/pump_fun.rs` ;
|
||||
- `kb_lib/src/dex_decode.rs` ;
|
||||
- `kb_lib/src/trade_aggregation.rs` ;
|
||||
- `kb_lib/src/trade_amount_resolution.rs` ;
|
||||
- `kb_lib/src/dex_detection_route.rs` ;
|
||||
- `kb_lib/src/dex_event_coverage.rs` ;
|
||||
- `kb_lib/src/upstream_registry_generated.rs` ;
|
||||
- `idls/pump_fun.6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P.json` ;
|
||||
- `validation_sql/SQL_VALIDATION_PUMP_FUN_0_7_54.sql` ;
|
||||
- `validation_sql/SQL_VALIDATION_PUMP_FUN_MATERIALIZATION_0_7_54.sql` ;
|
||||
- corpus SQLite bâti par backfills Demo3/signatures/pools et replay forcé.
|
||||
|
||||
## Couverture finale
|
||||
|
||||
L'IDL locale Pump.fun contient `40` instructions et `23` events Anchor. La tranche a ajouté la couverture locale des instructions/events connues, y compris les instructions IDL-only absentes du registre upstream initial :
|
||||
|
||||
- `add_quote_mint` ;
|
||||
- `buy_exact_quote_in_v2` ;
|
||||
- `buy_v2` ;
|
||||
- `claim_cashback_v2` ;
|
||||
- `collect_creator_fee_v2` ;
|
||||
- `distribute_creator_fees_v2` ;
|
||||
- `migrate_v2` ;
|
||||
- `remove_quote_mint` ;
|
||||
- `sell_v2` ;
|
||||
- `set_virtual_quote_reserves` ;
|
||||
- `update_buyback_config`.
|
||||
|
||||
Les events Anchor sont reconnus depuis `Program data:` et depuis le transport Anchor self-CPI/log `e445a52e51cb9a1d` quand présent.
|
||||
|
||||
## Règles de matérialisation finales
|
||||
|
||||
### Trades
|
||||
|
||||
| Source locale | Matérialisation | Règle |
|
||||
|---|---|---|
|
||||
| `pump_fun.buy` | `k_sol_trade_events` | directe si montants fiables |
|
||||
| `pump_fun.sell` | `k_sol_trade_events` | directe si montants fiables |
|
||||
| `pump_fun.buy_exact_sol_in` | `k_sol_trade_events` | directe ; les logs `Program data` tronqués sont exploités quand les montants exacts sont extractibles |
|
||||
| `pump_fun.buy_v2` | non directe | instruction audit/coverage/routing uniquement |
|
||||
| `pump_fun.sell_v2` | non directe | instruction audit/coverage/routing uniquement |
|
||||
| `pump_fun.buy_exact_quote_in_v2` | non directe | instruction audit/coverage/routing uniquement |
|
||||
| `pump_fun.trade_event` | `k_sol_trade_events` | source canonique des montants exécutés v2/exact quand corrélée sans ambiguïté |
|
||||
|
||||
Les `trade_event` déjà couverts par une instruction directe reçoivent un skip explicite afin d'éviter tout double-count.
|
||||
|
||||
### Non-trades
|
||||
|
||||
Les événements non-trade sont matérialisés uniquement vers leur table métier ciblée quand les comptes, acteurs et montants sont fiables :
|
||||
|
||||
- `k_sol_launch_events` pour create/migrate/graduate ;
|
||||
- `k_sol_fee_events` pour creator fees, fee distribution et minimum fee ;
|
||||
- `k_sol_reward_events` pour cashback, incentives et volume accumulators exploitables ;
|
||||
- `k_sol_pool_admin_events` pour admin/config/creator/global authority ;
|
||||
- `k_sol_pool_lifecycle_events` pour initialization/lifecycle.
|
||||
|
||||
Sinon, ils restent decoded-only/audit-only avec `skip*Reason` explicite. Les transactions failed ne produisent aucune matérialisation métier.
|
||||
|
||||
## Replay final rapporté
|
||||
|
||||
```text
|
||||
1679 replayed
|
||||
0 decode skipped
|
||||
1679 ledger upserts
|
||||
145 unsafe ledger rows
|
||||
89 trades
|
||||
0 liquidity
|
||||
10 lifecycle
|
||||
0 tokenAccount
|
||||
348 candle upserts
|
||||
instructionObservations = 13905
|
||||
resetDeleted = 1112
|
||||
catalog = 52 tokens / 50 pools / 50 pairs
|
||||
```
|
||||
|
||||
## Matérialisation finale Pump.fun observée
|
||||
|
||||
```text
|
||||
pump_fun.buy 17 trades
|
||||
pump_fun.sell 25 trades
|
||||
pump_fun.buy_exact_sol_in 15 trades
|
||||
pump_fun.trade_event 25 trades
|
||||
```
|
||||
|
||||
Les variantes v2/exact restent à `0` dans `k_sol_trade_events` par `decoded_event_id` d'instruction, ce qui est attendu : leur matérialisation canonique se fait via `pump_fun.trade_event`.
|
||||
|
||||
## Checks de fermeture SQL
|
||||
|
||||
Résultats finaux rapportés :
|
||||
|
||||
- `Q00` upstream fallback Pump.fun : vide ;
|
||||
- `Q04` decoded Pump.fun sans coverage : vide ;
|
||||
- `Q05` fallback upstream couvert localement : vide ;
|
||||
- `Q06` successful non-materialized sans skip reason : vide ;
|
||||
- `Q07` failed transaction materialization safety : vide ;
|
||||
- `Q08` multi-target materialization safety : vide ;
|
||||
- `Q11` trade candidates sans trade ni skip : vide ;
|
||||
- `Q12` watchlist globale : plus de `pump_fun` ; restent `pump_fees`, `jupiter_swap` et `dflow_aggregator_v4`.
|
||||
|
||||
## Décisions de clôture
|
||||
|
||||
- `pump_fun` est clos côté decoder maximal local et validation corpus.
|
||||
- Les prochaines interventions Pump.fun doivent être des corrections de bugs ou des adaptations à un changement externe prouvé.
|
||||
- La suite logique est `0.7.55 pump_fees` sur nouvelle base SQLite.
|
||||
- La politique reste : tout ce qui peut être décodé doit l'être ; tout ce qui peut être matérialisé de manière fiable doit l'être ; aucun trade/candle artificiel ne doit être créé.
|
||||
@@ -0,0 +1,168 @@
|
||||
<!-- file: docs/reports/PUMP_SWAP_EVENT_COVERAGE_REPORT.md -->
|
||||
|
||||
# PumpSwap event coverage report — `0.7.53`
|
||||
|
||||
## Scope
|
||||
|
||||
- Version cible : `0.7.53`.
|
||||
- Surface unique : `pump_swap`.
|
||||
- Program id unique : `pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA`.
|
||||
- Phasage : une version = un `program_id`.
|
||||
- `raydium_pool_v4.json` reste repoussé vers la fin du phasage et ne bloque pas cette tranche.
|
||||
|
||||
## Sources vérifiées / à vérifier pendant la fermeture
|
||||
|
||||
- `kb_lib/src/constants.rs`, notamment `PUMP_SWAP_PROGRAM_ID` et `SOLSCAN_ACCOUNT_SOURCES`.
|
||||
- Registre upstream local généré : `kb_lib/src/upstream_registry_generated.rs`.
|
||||
- Sources Git/IDL externes disponibles : Pump public docs / IDL, Carbon, fnzero, Pinax, HODL Warden si présents dans le registre.
|
||||
- IDL locale : `idls/pump_swap.pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA.json`, téléchargée depuis Solscan et versionnée dans le workspace.
|
||||
- Solscan IDL du program id PumpSwap si disponible.
|
||||
- Corpus local Demo3 + backfills signature/pool.
|
||||
- `k_sol_dex_event_coverage_entries` après replay forcé.
|
||||
|
||||
Les sources Git/IDL/Solscan sont des indices. La fermeture métier exige corpus local, replay et SQL.
|
||||
|
||||
## Couverture locale ajoutée
|
||||
|
||||
Le decoder local `kb_lib/src/dex/pump_swap.rs` ne se limite plus à `buy`/`sell`. Il reconnaît maintenant les discriminants d’instruction suivants et produit un event spécialisé `pump_swap.<entry_name>`.
|
||||
|
||||
| Entry | Kind | Discriminator | Target attendu | Matérialisation |
|
||||
|---|---|---:|---|---|
|
||||
| `admin_set_coin_creator` | instruction | `f228759149606968` | admin/config | decoded specialized non-trade |
|
||||
| `admin_update_token_incentives` | instruction | `d10b7357d5177ccc` | reward/admin | decoded specialized non-trade |
|
||||
| `buy` | instruction | `66063d1201daebea` | trade | trade/candle seulement depuis montants exacts |
|
||||
| `buy_exact_quote_in` | instruction | `c62e1552b4d9e870` | trade conditionnel | matérialisé seulement si un `BuyEvent` Anchor exact est présent (`amountSource=pump_swap_anchor_buy_event`) ; sinon decoded-only `instruction_bounds_only` avec `skipTradeReason` |
|
||||
| `claim_cashback` | instruction | `253a237ebe35e4c5` | reward | decoded specialized non-trade |
|
||||
| `claim_token_incentives` | instruction | `1004471ccc01281b` | reward | decoded specialized non-trade |
|
||||
| `close_user_volume_accumulator` | instruction | `f945a4da9667548a` | reward | decoded specialized non-trade |
|
||||
| `collect_coin_creator_fee` | instruction | `a039592ab58b2b42` | fee | decoded specialized non-trade |
|
||||
| `create_config` | instruction | `c9cff3724b6f2fbd` | admin/config | decoded specialized non-trade |
|
||||
| `create_pool` | instruction | `e992d18ecf6840bc` | pool lifecycle | decoded specialized non-trade |
|
||||
| `deposit` | instruction | `f223c68952e1f2b6` | liquidity add | decoded specialized non-trade |
|
||||
| `disable` | instruction | `b9adbb5ad80feee9` | admin/config | decoded specialized non-trade |
|
||||
| `extend_account` | instruction | `ea66c2cb96483ee5` | admin/config | decoded specialized non-trade |
|
||||
| `init_user_volume_accumulator` | instruction | `5e06ca73ff60e8b7` | reward | decoded specialized non-trade |
|
||||
| `migrate_pool_coin_creator` | instruction | `d0089f044aaf103a` | admin/migration | decoded specialized non-trade |
|
||||
| `sell` | instruction | `33e685a4017f83ad` | trade | trade/candle seulement depuis montants exacts |
|
||||
| `set_coin_creator` | instruction | `d295802dbc3a4eaf` | admin/config | decoded specialized non-trade |
|
||||
| `set_reserved_fee_recipients` | instruction | `6faca2e87259d58e` | admin/config | decoded specialized non-trade |
|
||||
| `set_reserved_fee_recipient` | instruction | `cfbdb247a77a44b4` | admin/config | local log proof only: `Instruction: SetReservedFeeRecipient` ; absent from checked Solscan IDL raw ; decoded specialized non-trade |
|
||||
| `sync_user_volume_accumulator` | instruction | `561fc057a3574fee` | reward | decoded specialized non-trade |
|
||||
| `toggle_cashback_enabled` | instruction | `7367e0ffbd5956c3` | admin/config | decoded specialized non-trade |
|
||||
| `toggle_mayhem_mode` | instruction | `01096fd0641fffa3` | admin/config | decoded specialized non-trade |
|
||||
| `transfer_creator_fees_to_pump` | instruction | `8b348655e4e56cf1` | fee | decoded specialized non-trade |
|
||||
| `transfer_creator_fees_to_pump_v2` | instruction | `01214eb921432c5c` | fee | Solscan IDL proof + local log proof: `transfer_creator_fees_to_pump_v2` / `Instruction: TransferCreatorFeesToPumpV2` ; decoded specialized non-trade |
|
||||
| `update_admin` | instruction | `a1b028d53cb8b3e4` | admin/config | decoded specialized non-trade |
|
||||
| `update_buyback_config` | instruction | `fbe0ab92a01a71e9` | admin/config | Solscan IDL proof + local log proof: `update_buyback_config` / `Instruction: UpdateBuybackConfig` ; decoded specialized non-trade |
|
||||
| `update_fee_config` | instruction | `68b867f258976b14` | admin/config | decoded specialized non-trade |
|
||||
| `withdraw` | instruction | `b712469c946da122` | liquidity remove | decoded specialized non-trade |
|
||||
|
||||
## Upstream Program-data events à statut explicite
|
||||
|
||||
Ces events sont listés dans le registre upstream. Ils doivent apparaître avec un statut explicite dans la coverage DB après sync/replay. Ils ne doivent pas créer de doublons trade/candle tant que l’instruction locale spécialisée couvre déjà le DEX effectif.
|
||||
|
||||
| Event | Discriminator | Statut `0.7.53` |
|
||||
|---|---:|---|
|
||||
| `admin_set_coin_creator_event` | `2ddc5d181961ac68` | upstream listed ; decoded-only/status explicite après replay |
|
||||
| `admin_update_token_incentives_event` | `93fa6c78f71d43de` | upstream listed ; decoded-only/status explicite après replay |
|
||||
| `buy_event` | `67f4521f2cf57777` | upstream listed ; audit/decoded-only to avoid duplicate trade |
|
||||
| `claim_cashback_event` | `e2d6f62107f293e5` | upstream listed ; decoded-only/status explicite après replay |
|
||||
| `claim_token_incentives_event` | `4facf631cd5bcee8` | upstream listed ; decoded-only/status explicite après replay |
|
||||
| `close_user_volume_accumulator_event` | `929fbdac925838f4` | upstream listed ; decoded-only/status explicite après replay |
|
||||
| `collect_coin_creator_fee_event` | `e8f5c2eeeada3a59` | upstream listed ; decoded-only/status explicite après replay |
|
||||
| `create_config_event` | `6b34598137e25116` | upstream listed ; decoded-only/status explicite après replay |
|
||||
| `create_pool_event` | `b1310cd2a076a774` | upstream listed ; decoded-only/status explicite après replay |
|
||||
| `deposit_event` | `78f83d531f8e6b90` | upstream listed ; decoded-only/status explicite après replay |
|
||||
| `disable_event` | `6bfdc14ce4ca1b68` | upstream listed ; decoded-only/status explicite après replay |
|
||||
| `extend_account_event` | `6161d7905d92167c` | upstream listed ; decoded-only/status explicite après replay |
|
||||
| `init_user_volume_accumulator_event` | `86240d48e86582d8` | upstream listed ; decoded-only/status explicite après replay |
|
||||
| `migrate_pool_coin_creator_event` | `aadd52c793a5f72e` | upstream listed ; decoded-only/status explicite après replay |
|
||||
| `reserved_fee_recipients_event` | `2bbcfa12dd4bbb5f` | upstream listed ; decoded-only/status explicite après replay |
|
||||
| `sell_event` | `3e2f370aa503dc2a` | upstream listed ; audit/decoded-only to avoid duplicate trade |
|
||||
| `set_bonding_curve_coin_creator_event` | `f2e7eb664163bdd3` | upstream listed ; decoded-only/status explicite après replay |
|
||||
| `set_metaplex_coin_creator_event` | `966bc77b7ccf66e4` | upstream listed ; decoded-only/status explicite après replay |
|
||||
| `sync_user_volume_accumulator_event` | `c57aa77c74515bff` | upstream listed ; decoded-only/status explicite après replay |
|
||||
| `update_admin_event` | `e198ab57f63f42ea` | upstream listed ; decoded-only/status explicite après replay |
|
||||
| `update_fee_config_event` | `5a1741233ef4bcd0` | upstream listed ; decoded-only/status explicite après replay |
|
||||
| `withdraw_event` | `1609851aa02c47c0` | upstream listed ; decoded-only/status explicite après replay |
|
||||
|
||||
## Matérialisation
|
||||
|
||||
- `pump_swap.buy`, `pump_swap.sell` et `pump_swap.buy_exact_quote_in` peuvent alimenter `k_sol_trade_events`, mais seulement depuis des montants exacts.
|
||||
- `pump_swap.buy_exact_quote_in` est matérialisé quand le log Anchor `BuyEvent` fournit `baseAmountOutRaw` et `userQuoteAmountInRaw` pour `ixName=buy_exact_quote_in`. Les rows `instruction_bounds_only` restent decoded-only avec `skipTradeReason` explicite.
|
||||
- Les bornes d’instruction (`maxQuoteAmountIn`, `spendableQuoteAmountIn`, `minQuoteAmountOut`, `minBaseAmountOut`) ne sont pas considérées comme des montants exacts suffisants pour créer un trade/candle.
|
||||
- La matérialisation doit passer par les résolutions exactes existantes : token transfer deltas, vault/account balance deltas ou autre source d’amount explicitement prouvée.
|
||||
- Les transactions failed restent decoded-only via l’actionability `failed_transaction`.
|
||||
- Les non-trades restent hors `k_sol_trade_events` et hors `k_sol_pair_candles`.
|
||||
|
||||
## SQL de fermeture
|
||||
|
||||
Le fichier dédié est :
|
||||
|
||||
```text
|
||||
validation_sql/SQL_VALIDATION_PUMP_SWAP_0_7_53.sql
|
||||
```
|
||||
|
||||
Les requêtes d’anomalies attendues vides couvrent :
|
||||
|
||||
- fallback upstream résiduel sur instruction couverte localement ;
|
||||
- failed tx avec trade ;
|
||||
- non-swap avec trade ;
|
||||
- decoded without coverage ;
|
||||
- successful non-materialized inexpliqué ;
|
||||
- multi-target materialization ;
|
||||
- successful swap exploitable sans trade et sans raison explicite.
|
||||
|
||||
## Delta post-replay `0.7.53-pump_swap-delta-1`
|
||||
|
||||
Le replay local a révélé trois écarts corrigés par ce delta :
|
||||
|
||||
- `pump_swap.toggle_cashback_enabled` était classé à la fois `reward` et `admin`; il devient admin-only pour respecter l’invariant single-target.
|
||||
- `pump_swap.buy_exact_quote_in` réussi non matérialisé reçoit maintenant un `skipTradeReason` explicite et reste decoded-only tant que les montants exacts ne sont pas prouvés.
|
||||
- `k_sol_instruction_observations.instruction_name` reçoit un mapping PumpSwap par discriminant pour que la requête de coverage locale ne sorte plus des noms vides. Le discriminant `e445a52e51cb9a1d` reste marqué comme transport technique Anchor self-CPI. Les trois discriminants initialement inconnus ne doivent plus sortir en `observed_unknown_*` : deux sont confirmés par le raw Solscan IDL et un reste conservé comme local-log-only.
|
||||
|
||||
`pump_swap.migrate_pool_coin_creator` est également forcé en admin/config, pas lifecycle, car il modifie l’attribution coin creator et ne représente pas une migration de pool échangeable.
|
||||
|
||||
## Delta post-replay `0.7.53-pump_swap-delta-2`
|
||||
|
||||
- Les trois discriminants initialement inconnus (`01214eb921432c5c`, `fbe0ab92a01a71e9`, `cfbdb247a77a44b4`) ont été provisoirement couverts decoded-only pour supprimer les gaps locaux sans inventer de métier.
|
||||
- `toggle_cashback_enabled` est corrigé aussi dans la famille coverage (`admin_config`) afin de refléter la matérialisation admin-only.
|
||||
|
||||
## Delta post-replay `0.7.53-pump_swap-delta-4`
|
||||
|
||||
- Le corpus local donne maintenant le nom métier via logs Anchor : `TransferCreatorFeesToPumpV2`, `UpdateBuybackConfig`, `SetReservedFeeRecipient`.
|
||||
- Ces trois discriminants deviennent des instructions locales spécialisées : `pump_swap.transfer_creator_fees_to_pump_v2`, `pump_swap.update_buyback_config`, `pump_swap.set_reserved_fee_recipient`.
|
||||
- Recomparaison raw Solscan IDL : `transfer_creator_fees_to_pump_v2` et `update_buyback_config` sont présents dans l’IDL. `set_reserved_fee_recipient` n’est pas listé dans ce raw ; il est gardé sur preuve log locale, possiblement instruction historique/supprimée ou non exposée par cette version IDL.
|
||||
- `transfer_creator_fees_to_pump_v2` est fee/non-trade ; `update_buyback_config` et `set_reserved_fee_recipient` sont admin/config non-trade.
|
||||
|
||||
|
||||
|
||||
## Clôture finale `0.7.53`
|
||||
|
||||
La tranche est clôturée après les deltas de consolidation :
|
||||
|
||||
- `buy_exact_quote_in` route désormais vers la matérialisation pool/pair/trade quand `amountSource=pump_swap_anchor_buy_event`;
|
||||
- les montants du `BuyEvent` sont normalisés par rapport à l’ordre local de la paire pour éviter les inversions base/quote ;
|
||||
- les events Anchor PumpSwap sont décodés comme events autonomes audit-only ;
|
||||
- `claim_token_incentives_event` possède un test synthétique de matérialisabilité reward si un corpus réussi apparaît ;
|
||||
- `sync_user_volume_accumulator_event` reste implémenté mais non observé malgré un backfill élargi sur l’instruction ;
|
||||
- les tests synthétiques couvrent les instructions/events IDL non observés localement ;
|
||||
- `cargo test -p kb_lib` a été validé à `421 passed / 0 failed` et clippy est OK côté utilisateur.
|
||||
|
||||
Résultats de validation rapportés après corpus élargi :
|
||||
|
||||
```text
|
||||
pump_swap decoded without coverage = vide
|
||||
pump_swap upstream fallback couvert localement = vide
|
||||
successful trade candidates sans trade = vide
|
||||
failed tx avec business trade = vide
|
||||
non-swap matérialisé en trade = vide
|
||||
multi-target materialization = vide
|
||||
buy_exact_quote_in / pump_swap_anchor_buy_event = 168 decoded / 167 trades / 1 failed tx
|
||||
```
|
||||
|
||||
Les fichiers de surveillance à conserver sont :
|
||||
|
||||
- `validation_sql/SQL_VALIDATION_PUMP_SWAP_0_7_53.sql` ;
|
||||
- `validation_sql/SQL_VALIDATION_DEX_COVERAGE_GLOBAL_0_7_53.sql` ;
|
||||
- `docs/reports/DEX_COVERAGE_GLOBAL_WATCHLIST_0_7_53.md`.
|
||||
@@ -0,0 +1,141 @@
|
||||
<!-- file: docs/reports/RAYDIUM_AMM_V4_EVENT_COVERAGE_REPORT.md -->
|
||||
|
||||
# Raydium AMM v4 Event Coverage Report — `0.7.51-final`
|
||||
|
||||
## Scope
|
||||
|
||||
Tranche : `0.7.51 raydium_amm_v4`.
|
||||
|
||||
Program id canonique local :
|
||||
|
||||
```text
|
||||
675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8
|
||||
```
|
||||
|
||||
Code local canonique :
|
||||
|
||||
```text
|
||||
raydium_amm_v4
|
||||
```
|
||||
|
||||
Cette tranche reprend AMM v4 legacy après `0.7.50 raydium_launchpad` et les rechecks CPMM/CLMM. Les sources Git/IDL/Solscan restent des indices ; les statuts observé/matérialisé proviennent du corpus local et du replay forcé.
|
||||
|
||||
## Sources inventoriées
|
||||
|
||||
Sources utilisées comme indices de coverage :
|
||||
|
||||
- Carbon : `decoders/raydium-amm-v4-decoder` ;
|
||||
- Pinax : `src/raydium/amm` ;
|
||||
- fnzero `sol-parser-sdk` : `idl/raydium_amm_v4.json` et `idls/raydium_amm_v4.json` ;
|
||||
- fnzero `sol-parser-sdk` : `idl/raydium_pool_v4.json` et `idls/raydium_pool_v4.json`, audit comparatif uniquement ;
|
||||
- Solscan Program IDL et recherche `instruction=<discriminator>` pour `675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8`.
|
||||
|
||||
## Validation Rust et replay final
|
||||
|
||||
Validation locale rapportée :
|
||||
|
||||
```text
|
||||
cargo test -p kb_lib -> 405 passed / 0 failed
|
||||
cargo clippy -p kb_lib --all-targets -- -D warnings -> OK
|
||||
```
|
||||
|
||||
Replay local final :
|
||||
|
||||
```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
|
||||
```
|
||||
|
||||
## Coverage finale par discriminant
|
||||
|
||||
| Discriminant | Entrée | Famille | Local event kind | Cible DB | Observed | Materialized | Trade |
|
||||
|---|---|---|---|---|---:|---:|---:|
|
||||
| `00` | `initialize` | `pool_create` | `raydium_amm_v4.initialize` | `k_sol_pool_lifecycle_events` | 4 | 4 | 0 |
|
||||
| `01` | `initialize2` | `pool_create` | `raydium_amm_v4.initialize2_pool` | `k_sol_pool_lifecycle_events` | 8 | 8 | 0 |
|
||||
| `02` | `monitor_step` | `order_place` | `raydium_amm_v4.monitor_step` | `k_sol_orderbook_events` | 20 | 20 | 0 |
|
||||
| `03` | `deposit` | `liquidity_add` | `raydium_amm_v4.deposit` | `k_sol_liquidity_events` | 10 | 5 | 0 |
|
||||
| `04` | `withdraw` | `liquidity_remove` | `raydium_amm_v4.withdraw` | `k_sol_liquidity_events` | 3 | 2 | 0 |
|
||||
| `05` | `migrate_to_open_book` | `order_place` | `raydium_amm_v4.migrate_to_open_book` | `k_sol_orderbook_events` | 6 | 6 | 0 |
|
||||
| `06` | `set_params` | `admin_config` | `raydium_amm_v4.set_params` | `k_sol_pool_admin_events` | 1 | 1 | 0 |
|
||||
| `07` | `withdraw_pnl` | `fee` | `raydium_amm_v4.withdraw_pnl` | `k_sol_fee_events` | 1 | 1 | 0 |
|
||||
| `08` | `withdraw_srm` | `fee` | `raydium_amm_v4.withdraw_srm` | `k_sol_fee_events` | 2 | 1 | 0 |
|
||||
| `09` | `swap_base_in` | `swap` | `raydium_amm_v4.swap_base_in` | `k_sol_trade_events` | 76 | 66 | 66 |
|
||||
| `0a` | `pre_initialize` | `pool_create` | `raydium_amm_v4.pre_initialize` | `k_sol_pool_lifecycle_events` | 8 | 7 | 0 |
|
||||
| `0b` | `swap_base_out` | `swap` | `raydium_amm_v4.swap_base_out` | `k_sol_trade_events` | 3 | 1 | 1 |
|
||||
| `0c` | `simulate_info` | `cpi_transport` | `raydium_amm_v4.simulate_info` | `k_sol_dex_decoded_events_only` | 6 | 0 | 0 |
|
||||
| `0d` | `admin_cancel_orders` | `order_cancel` | `raydium_amm_v4.admin_cancel_orders` | `k_sol_orderbook_events` | 22 | 22 | 0 |
|
||||
| `0e` | `create_config_account` | `admin_config` | `raydium_amm_v4.create_config_account` | `k_sol_pool_admin_events` | 50 | 50 | 0 |
|
||||
| `0f` | `update_config_account` | `admin_config` | `raydium_amm_v4.update_config_account` | `k_sol_pool_admin_events` | 6 | 6 | 0 |
|
||||
| `10` | `swap_base_in_v2` | `swap` | `raydium_amm_v4.swap_base_in_v2` | `k_sol_trade_events` | 35 | 35 | 35 |
|
||||
| `11` | `swap_base_out_v2` | `swap` | `raydium_amm_v4.swap_base_out_v2` | `k_sol_trade_events` | 7 | 7 | 7 |
|
||||
|
||||
Toutes les entrées ont `proof_status=upstream_git_local_corpus_materialized`, sauf `simulate_info`, qui reste volontairement `upstream_git_local_corpus_observed` / decoded-only.
|
||||
|
||||
## Matérialisation métier finale
|
||||
|
||||
| Event kind | Decoded | Trade | Liquidity | Lifecycle | Fee | Admin | Orderbook |
|
||||
|---|---:|---:|---:|---:|---:|---:|---:|
|
||||
| `raydium_amm_v4.admin_cancel_orders` | 22 | 0 | 0 | 0 | 0 | 0 | 22 |
|
||||
| `raydium_amm_v4.create_config_account` | 50 | 0 | 0 | 0 | 0 | 50 | 0 |
|
||||
| `raydium_amm_v4.deposit` | 10 | 0 | 5 | 0 | 0 | 0 | 0 |
|
||||
| `raydium_amm_v4.initialize2_pool` | 8 | 0 | 0 | 8 | 0 | 0 | 0 |
|
||||
| `raydium_amm_v4.migrate_to_open_book` | 6 | 0 | 0 | 0 | 0 | 0 | 6 |
|
||||
| `raydium_amm_v4.monitor_step` | 20 | 0 | 0 | 0 | 0 | 0 | 20 |
|
||||
| `raydium_amm_v4.pre_initialize` | 8 | 0 | 0 | 7 | 0 | 0 | 0 |
|
||||
| `raydium_amm_v4.set_params` | 1 | 0 | 0 | 0 | 0 | 1 | 0 |
|
||||
| `raydium_amm_v4.simulate_info` | 6 | 0 | 0 | 0 | 0 | 0 | 0 |
|
||||
| `raydium_amm_v4.swap_base_in` | 76 | 66 | 0 | 0 | 0 | 0 | 0 |
|
||||
| `raydium_amm_v4.swap_base_in_v2` | 35 | 35 | 0 | 0 | 0 | 0 | 0 |
|
||||
| `raydium_amm_v4.swap_base_out` | 3 | 1 | 0 | 0 | 0 | 0 | 0 |
|
||||
| `raydium_amm_v4.swap_base_out_v2` | 7 | 7 | 0 | 0 | 0 | 0 | 0 |
|
||||
| `raydium_amm_v4.update_config_account` | 6 | 0 | 0 | 0 | 0 | 6 | 0 |
|
||||
| `raydium_amm_v4.withdraw` | 3 | 0 | 2 | 0 | 0 | 0 | 0 |
|
||||
| `raydium_amm_v4.withdraw_pnl` | 1 | 0 | 0 | 0 | 1 | 0 | 0 |
|
||||
| `raydium_amm_v4.withdraw_srm` | 2 | 0 | 0 | 0 | 1 | 0 | 0 |
|
||||
|
||||
## Invariants validés
|
||||
|
||||
Les requêtes finales donnent `vide` pour :
|
||||
|
||||
- `raydium_amm_v4.swap` legacy ;
|
||||
- decoded AMM v4 sans coverage entry ;
|
||||
- observations AMM v4 dont `length(discriminator_hex) > 2` ;
|
||||
- non-swap AMM v4 avec trade ;
|
||||
- transaction failed AMM v4 avec trade ;
|
||||
- event successful non matérialisé sans raison explicite ;
|
||||
- event AMM v4 matérialisé vers plus d'une table métier principale.
|
||||
|
||||
## Gaps expliqués
|
||||
|
||||
Les écarts `observed_count > materialized_count` sont acceptés uniquement s'ils sont expliqués :
|
||||
|
||||
- `swap_base_in` / `swap_base_out` : decoded-only lorsque les deltas vault ou montants exploitables sont absents ;
|
||||
- `deposit` / `withdraw` : non matérialisés lorsque le pool/pair catalogue ou les deltas nécessaires sont absents ;
|
||||
- `withdraw_srm` : non matérialisé si le contexte fee exploitable est absent ;
|
||||
- `pre_initialize` : 1 transaction failed ; les 7 transactions successful sont matérialisées en lifecycle audit minimal ;
|
||||
- `simulate_info` : decoded-only assumé.
|
||||
|
||||
Pour `deposit`, le corpus final montre 5 événements matérialisés sur le pool catalogué `2dRNngAm729NzLbb1pzgHtfHvPqR4XHFmFyYK78EfEeX` / pair `FIDA/RAY`, et 5 événements decoded-only sur des pools absents du catalogue local.
|
||||
|
||||
## Décisions spécifiques
|
||||
|
||||
- `raydium_amm_v4.swap` est définitivement interdit : les swaps doivent rester spécialisés.
|
||||
- `pre_initialize` est conservé pour les scans historiques, matérialisé comme lifecycle audit deprecated/partial, sans pair exploitable.
|
||||
- `migrate_to_open_book`, `monitor_step` et `admin_cancel_orders` sont des side effects orderbook AMM v4, pas des trades OpenBook autonomes.
|
||||
- `simulate_info` reste `k_sol_dex_decoded_events_only`.
|
||||
- Les side effects SPL Token / Token-2022 restent transversaux.
|
||||
- `raydium_pool_v4` n'est pas promu en decoder autonome dans `0.7.51`.
|
||||
|
||||
## Clôture
|
||||
|
||||
`0.7.51 raydium_amm_v4` est clôturable côté `kb_lib` sous réserve de conserver les rechecks CPMM/CLMM/Launchpad dans la validation globale de workspace lorsque la base utilisée les contient.
|
||||
@@ -0,0 +1,140 @@
|
||||
<!-- file: docs/reports/RAYDIUM_CLMM_EVENT_COVERAGE_REPORT.md -->
|
||||
|
||||
# Rapport `0.7.49` — Raydium CLMM event coverage
|
||||
|
||||
## Résumé
|
||||
|
||||
La tranche `0.7.49` clôture la couverture fonctionnelle `raydium_clmm` sur le corpus local validé. Elle reprend CLMM après `0.7.48 raydium_cpmm` et applique la même méthode : inventaire upstream, corpus local, replay forcé, materialization contrôlée, suppression des fallbacks remplacés, validation SQL.
|
||||
|
||||
Validation locale observée après le dernier replay :
|
||||
|
||||
```text
|
||||
local replay: 2197 replayed, 0 decode skipped, 2197 ledger upserts, 1461 unsafe ledger rows, 1217 trades, 111 liquidity, 25 lifecycle, 4868 candle upserts, instructionObservations=19798
|
||||
catalog: 41 tokens, 63 pools, 63 pairs
|
||||
```
|
||||
|
||||
Synthèse coverage :
|
||||
|
||||
```text
|
||||
listed_entry_count = 45
|
||||
decoded_entry_count = 33
|
||||
observed_entry_count = 33
|
||||
materialized_entry_count = 25
|
||||
total_observed_count = 2560
|
||||
total_materialized_count = 1367
|
||||
trade_count = 1186
|
||||
```
|
||||
|
||||
## Entrées couvertes
|
||||
|
||||
La tranche couvre `33` instructions locales CLMM observées et décodées, dont :
|
||||
|
||||
```text
|
||||
swap
|
||||
swap_v2
|
||||
swap_router_base_in
|
||||
open_position
|
||||
open_position_v2
|
||||
open_position_with_token22_nft
|
||||
close_position
|
||||
close_protocol_position
|
||||
increase_liquidity
|
||||
increase_liquidity_v2
|
||||
decrease_liquidity
|
||||
decrease_liquidity_v2
|
||||
create_pool
|
||||
create_customizable_pool
|
||||
create_amm_config
|
||||
create_dynamic_fee_config
|
||||
update_amm_config
|
||||
update_pool_status
|
||||
create_operation_account
|
||||
update_operation_account
|
||||
create_support_mint_associated
|
||||
collect_fund_fee
|
||||
collect_protocol_fee
|
||||
collect_remaining_rewards
|
||||
initialize_reward
|
||||
set_reward_params
|
||||
transfer_reward_owner
|
||||
update_reward_infos
|
||||
open_limit_order
|
||||
increase_limit_order
|
||||
decrease_limit_order
|
||||
close_limit_order
|
||||
settle_limit_order
|
||||
```
|
||||
|
||||
## Matérialisations validées
|
||||
|
||||
Les matérialisations sont limitées aux transactions réussies et aux familles déjà supportées par le modèle DB :
|
||||
|
||||
| Famille | Table | Règle |
|
||||
|---|---|---|
|
||||
| Swaps | `k_sol_trade_events` + candles | Uniquement `raydium_clmm.swap` / `raydium_clmm.swap_v2` quand les montants sont exploitables. |
|
||||
| Liquidity / positions | `k_sol_liquidity_events` | Positions/liquidity prouvées par corpus, sans trade/candle. |
|
||||
| Fees | `k_sol_fee_events` | Fees prouvées par corpus, sans trade/candle. |
|
||||
| Rewards | `k_sol_reward_events` | Rewards prouvées par corpus, sans trade/candle. |
|
||||
| Admin/config | `k_sol_pool_admin_events` | Config/admin prouvés par corpus, sans trade/candle. |
|
||||
| Lifecycle | `k_sol_pool_lifecycle_events` | Pool creation prouvée par corpus, sans trade/candle. |
|
||||
| Limit orders | `k_sol_orderbook_events` | Open/increase/decrease/close/settle matérialisés comme orderbook, jamais trade/candle. |
|
||||
|
||||
## Invariants validés
|
||||
|
||||
Les requêtes SQL finales valident :
|
||||
|
||||
```text
|
||||
raydium_clmm.instruction_audit résiduel = 0
|
||||
upstream_git.instruction_match localement couvert = 0
|
||||
non-swap CLMM avec trade_count > 0 = 0
|
||||
failed tx matérialisées = 0
|
||||
```
|
||||
|
||||
Les fallbacks `upstream_git.instruction_match` localement couverts sont supprimés automatiquement, y compris quand `k_sol_instruction_observations.decoded_event_id` pointait encore vers une ligne fallback.
|
||||
|
||||
## Anchor / Program-data events non observés
|
||||
|
||||
Les `11` Anchor / `Program data` events CLMM ci-dessous restent listés en `upstream_git_unverified`, car aucun corpus local ne les observe encore comme event direct :
|
||||
|
||||
```text
|
||||
collect_personal_fee_event a6ae69c051a15369
|
||||
collect_protocol_fee_event ce57114f2d29d53d
|
||||
config_change_event f7bd07776a705f97
|
||||
create_personal_position_event 641e57f9c4df9ace
|
||||
decrease_liquidity_event 3ade563a44325538
|
||||
increase_liquidity_event 314f69d420221e54
|
||||
liquidity_calculate_event ed7094e63954b4a2
|
||||
liquidity_change_event 7ef0afce9e58996b
|
||||
pool_created_event 195e4b2f7063353f
|
||||
swap_event 40c6cde8260871e2
|
||||
update_reward_infos_event 6d7fba4e724125ec
|
||||
```
|
||||
|
||||
Le code est préparé pour les accueillir comme audit-only lorsqu’ils seront observés dans un corpus local. Ils ne produisent pas de trade/candle par défaut.
|
||||
|
||||
## Sources utilisées
|
||||
|
||||
Les entrées ont été comparées aux sources Raydium CLMM suivantes :
|
||||
|
||||
```text
|
||||
Solscan Program IDL CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK
|
||||
sevenlabs-hq/carbon raydium-clmm-decoder
|
||||
pinax-network/substreams-solana-idls raydium/clmm
|
||||
0xfnzero/sol-parser-sdk idl
|
||||
```
|
||||
|
||||
Les sources upstream restent des indices. La promotion locale dépend du corpus local, du replay et des validations SQL.
|
||||
|
||||
## SQL final
|
||||
|
||||
La validation finale est dans :
|
||||
|
||||
```text
|
||||
validation_sql/SQL_VALIDATION_RAYDIUM_CLMM_0_7_49.sql
|
||||
```
|
||||
|
||||
## Addendum `0.7.50-pre-r2` — source parity CLMM
|
||||
|
||||
La re-vérification CLMM ajoute `cpi_event` (`e445a52e51cb9a1d`) et `update_dynamic_fee_config` (`0707500802c784f0`) depuis Carbon. Les Program-data events CLMM reçoivent maintenant un `local_event_kind` et une famille explicite quand ils sont observables localement : `swap_event`, `pool_created_event`, `liquidity_change_event`, `create_personal_position_event`, `decrease_liquidity_event`, `increase_liquidity_event`, `collect_protocol_fee_event`, `config_change_event` et `update_reward_infos_event`.
|
||||
|
||||
`create_support_mint_associated` est matérialisable dans la nouvelle table `k_sol_token_account_events`. `liquidity_calculate_event` reste decoded-only car il représente un calcul/diagnostic et non une mutation de liquidité fiable. `swap_event` et `swap_router_base_in` restent également decoded-only : les trades matérialisés proviennent des instructions `swap` et `swap_v2`, ce qui évite les doublons de Program-data events et les routes sans pool direct.
|
||||
@@ -0,0 +1,130 @@
|
||||
<!-- file: docs/reports/RAYDIUM_CLMM_UPSTREAM_COVERAGE_REVIEW_PRE19.md -->
|
||||
|
||||
# Raydium CLMM upstream coverage review — `0.7.49-pre.19`
|
||||
|
||||
## Scope
|
||||
|
||||
Decoder under review:
|
||||
|
||||
```text
|
||||
raydium_clmm
|
||||
program_id = CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK
|
||||
```
|
||||
|
||||
External sources checked for the local coverage registry:
|
||||
|
||||
```text
|
||||
https://solscan.io/account/CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK#programIdl
|
||||
https://github.com/sevenlabs-hq/carbon/tree/main/decoders/raydium-clmm-decoder
|
||||
https://github.com/pinax-network/substreams-solana-idls/tree/main/src/raydium/clmm
|
||||
https://github.com/0xfnzero/sol-parser-sdk/tree/main/idl
|
||||
```
|
||||
|
||||
Notes:
|
||||
|
||||
- Solscan is used as discovery / IDL cross-check, not as final business proof.
|
||||
- `sol-parser-sdk/idl/raydium_clmm.json` maps to `raydium/amm_v3_with_swapv2.json` and exposes the CLMM program address.
|
||||
- `pinax-network/substreams-solana-idls` exposes Raydium CLMM under `src/raydium/clmm/v3`.
|
||||
- `sevenlabs-hq/carbon` exposes a dedicated `raydium-clmm-decoder` crate.
|
||||
|
||||
## Local registry status
|
||||
|
||||
The local registry now lists:
|
||||
|
||||
```text
|
||||
45 entries total:
|
||||
- 33 instructions
|
||||
- 11 Anchor/program-data events
|
||||
- 1 program row
|
||||
```
|
||||
|
||||
All 33 instruction entries have a `local_event_kind` mapping in `dex_event_coverage.rs`, `instruction_observation_index.rs`, `dex_decode.rs`, and `upstream_registry_generated.rs`.
|
||||
|
||||
The 11 event entries are listed as upstream facts and stay `upstream_git_unverified` until local corpus provides program-data/Anchor event proof.
|
||||
|
||||
## Instruction coverage matrix
|
||||
|
||||
| Entry | Discriminator | Family | Local event kind | Expected target | Status |
|
||||
|---|---|---|---|---|---|
|
||||
| close_limit_order | `4c7c800fd55725fa` | order_cancel | `raydium_clmm.close_limit_order` | `k_sol_orderbook_events` | decoded/materializable |
|
||||
| open_limit_order | `9d20dab7471d1293` | order_place | `raydium_clmm.open_limit_order` | `k_sol_orderbook_events` | decoded/materializable |
|
||||
| increase_limit_order | `b19059ecfaba7d63` | order_place | `raydium_clmm.increase_limit_order` | `k_sol_orderbook_events` | decoded/materializable |
|
||||
| decrease_limit_order | `759d3c674231a300` | order_cancel | `raydium_clmm.decrease_limit_order` | `k_sol_orderbook_events` | decoded/materializable |
|
||||
| close_position | `7b86510031446262` | position_close | `raydium_clmm.close_position` | `k_sol_liquidity_events` | decoded/materializable |
|
||||
| close_protocol_position | `c975989055556cb2` | position_close | `raydium_clmm.close_protocol_position` | `k_sol_liquidity_events` | decoded/materializable |
|
||||
| collect_fund_fee | `a78a4e95dfc2067e` | fee | `raydium_clmm.collect_fund_fee` | `k_sol_fee_events` | decoded/materializable |
|
||||
| collect_protocol_fee | `8888fcddc2427e59` | fee | `raydium_clmm.collect_protocol_fee` | `k_sol_fee_events` | decoded/materializable |
|
||||
| collect_remaining_rewards | `12eda6c52210d590` | reward | `raydium_clmm.collect_remaining_rewards` | `k_sol_reward_events` | decoded/materializable |
|
||||
| create_amm_config | `8934edd4d7756c68` | admin_config | `raydium_clmm.create_amm_config` | `k_sol_pool_admin_events` | decoded/materializable |
|
||||
| create_customizable_pool | `2b44d4a7592fa401` | pool_create | `raydium_clmm.create_customizable_pool` | `k_sol_pool_lifecycle_events` | decoded/materializable |
|
||||
| create_dynamic_fee_config | `bd0eb5785576e33e` | admin_config | `raydium_clmm.create_dynamic_fee_config` | `k_sol_pool_admin_events` | decoded/materializable |
|
||||
| create_operation_account | `3f5794216d230868` | unknown | `raydium_clmm.create_operation_account` | `k_sol_dex_decoded_events_only` | decoded/audit-only unless admin evidence is required |
|
||||
| create_pool | `e992d18ecf6840bc` | pool_create | `raydium_clmm.create_pool` | `k_sol_pool_lifecycle_events` | decoded/materializable |
|
||||
| create_support_mint_associated | `11fb415c88f20ea9` | account_create | `raydium_clmm.create_support_mint_associated` | `k_sol_token_account_events` | decoded; token-account materialization remains a later cross-DEX topic |
|
||||
| decrease_liquidity | `a026d06f685b2c01` | liquidity_remove | `raydium_clmm.decrease_liquidity` | `k_sol_liquidity_events` | decoded/materializable |
|
||||
| decrease_liquidity_v2 | `3a7fbc3e4f52c460` | liquidity_remove | `raydium_clmm.decrease_liquidity_v2` | `k_sol_liquidity_events` | decoded/materializable |
|
||||
| increase_liquidity | `2e9cf3760dcdfbb2` | liquidity_add | `raydium_clmm.increase_liquidity` | `k_sol_liquidity_events` | decoded/materializable |
|
||||
| increase_liquidity_v2 | `851d59df45eeb00a` | liquidity_add | `raydium_clmm.increase_liquidity_v2` | `k_sol_liquidity_events` | decoded/materializable |
|
||||
| initialize_reward | `5f87c0c4f281e644` | reward | `raydium_clmm.initialize_reward` | `k_sol_reward_events` | decoded/materializable |
|
||||
| open_position | `87802f4d0f98f031` | position_open | `raydium_clmm.open_position` | `k_sol_liquidity_events` | decoded/materializable |
|
||||
| open_position_v2 | `4db84ad67056f1c7` | position_open | `raydium_clmm.open_position_v2` | `k_sol_liquidity_events` | decoded/materializable |
|
||||
| open_position_with_token22_nft | `4dffae527d1dc92e` | position_open | `raydium_clmm.open_position_with_token22_nft` | `k_sol_liquidity_events` | decoded/materializable |
|
||||
| set_reward_params | `7034a74b20c9d389` | reward | `raydium_clmm.set_reward_params` | `k_sol_reward_events` | decoded/materializable |
|
||||
| settle_limit_order | `cd4e74215c691a60` | settle_funds | `raydium_clmm.settle_limit_order` | `k_sol_orderbook_events` | decoded/materializable |
|
||||
| swap | `f8c69e91e17587c8` | swap | `raydium_clmm.swap` | `k_sol_trade_events` | decoded/materializable as trade |
|
||||
| swap_router_base_in | `457d73daf5baf2c4` | swap | `raydium_clmm.swap_router_base_in` | `k_sol_trade_events` | decoded; observed but not promoted to trade without corpus proof |
|
||||
| swap_v2 | `2b04ed0b1ac91e62` | swap | `raydium_clmm.swap_v2` | `k_sol_trade_events` | decoded/materializable as trade |
|
||||
| transfer_reward_owner | `07160c53f22b3079` | reward | `raydium_clmm.transfer_reward_owner` | `k_sol_reward_events` | decoded/materializable |
|
||||
| update_amm_config | `313cae889a1c74c8` | admin_config | `raydium_clmm.update_amm_config` | `k_sol_pool_admin_events` | decoded/materializable |
|
||||
| update_operation_account | `7f467728bce33d07` | unknown | `raydium_clmm.update_operation_account` | `k_sol_dex_decoded_events_only` | decoded/audit-only unless admin evidence is required |
|
||||
| update_pool_status | `82576c062ee0757b` | admin_config | `raydium_clmm.update_pool_status` | `k_sol_pool_admin_events` | decoded/materializable |
|
||||
| update_reward_infos | `a3ace0340b9a6adf` | reward | `raydium_clmm.update_reward_infos` | `k_sol_reward_events` | decoded/materializable |
|
||||
|
||||
## Anchor/program-data event entries
|
||||
|
||||
These entries remain listed, but no local corpus row has observed them as direct CLMM decoded events in the current replay corpus:
|
||||
|
||||
| Event entry | Discriminator | Family | Expected target | Status |
|
||||
|---|---|---|---|---|
|
||||
| collect_personal_fee_event | `a6ae69c051a15369` | fee | `k_sol_fee_events` | upstream listed, local corpus unobserved |
|
||||
| collect_protocol_fee_event | `ce57114f2d29d53d` | fee | `k_sol_fee_events` | upstream listed, local corpus unobserved |
|
||||
| config_change_event | `f7bd07776a705f97` | admin_config | `k_sol_pool_admin_events` | upstream listed, local corpus unobserved |
|
||||
| create_personal_position_event | `641e57f9c4df9ace` | unknown | `k_sol_dex_decoded_events_only` | upstream listed, local corpus unobserved |
|
||||
| decrease_liquidity_event | `3ade563a44325538` | liquidity_remove | `k_sol_liquidity_events` | upstream listed, local corpus unobserved |
|
||||
| increase_liquidity_event | `314f69d420221e54` | liquidity_add | `k_sol_liquidity_events` | upstream listed, local corpus unobserved |
|
||||
| liquidity_calculate_event | `ed7094e63954b4a2` | unknown | `k_sol_dex_decoded_events_only` | upstream listed, local corpus unobserved |
|
||||
| liquidity_change_event | `7ef0afce9e58996b` | unknown | `k_sol_dex_decoded_events_only` | upstream listed, local corpus unobserved |
|
||||
| pool_created_event | `195e4b2f7063353f` | unknown | `k_sol_dex_decoded_events_only` | upstream listed, local corpus unobserved |
|
||||
| swap_event | `40c6cde8260871e2` | swap | `k_sol_trade_events` | upstream listed, local corpus unobserved |
|
||||
| update_reward_infos_event | `6d7fba4e724125ec` | reward | `k_sol_reward_events` | upstream listed, local corpus unobserved |
|
||||
|
||||
## Patch `pre.19`
|
||||
|
||||
Patch goal:
|
||||
|
||||
```text
|
||||
Stop replay/backfill from leaving `upstream_git.instruction_match` rows when a local specialized decoder already covers the same upstream decoder + entry + discriminator.
|
||||
```
|
||||
|
||||
New DB query:
|
||||
|
||||
```text
|
||||
query_dex_decoded_events_delete_locally_covered_upstream_instruction_matches(database, upstream_decoder_code)
|
||||
```
|
||||
|
||||
Called from:
|
||||
|
||||
```text
|
||||
local_pipeline_replay.rs::refresh_event_coverage_best_effort
|
||||
token_backfill.rs::refresh_event_coverage_best_effort
|
||||
```
|
||||
|
||||
Expected validation after replay:
|
||||
|
||||
```text
|
||||
raydium_clmm.instruction_audit residual query -> empty
|
||||
upstream_git.instruction_match where upstreamDecoderCode = raydium_clmm -> empty
|
||||
non-swap CLMM trade_count -> empty
|
||||
failed CLMM materialization query -> empty
|
||||
coverage summary remains populated around 45 listed / 33 decoded / 33 observed
|
||||
```
|
||||
@@ -0,0 +1,84 @@
|
||||
<!-- file: docs/reports/RAYDIUM_CPMM_CLMM_RECHECK_REPORT_0_7_50_PRE_R2.md -->
|
||||
|
||||
# Raydium CPMM/CLMM re-check report — `0.7.50-pre-r2`
|
||||
|
||||
## Scope
|
||||
|
||||
This report closes the post-Launchpad re-check for `raydium_cpmm` and `raydium_clmm` using the same discipline applied to `raydium_launchpad`:
|
||||
|
||||
- every observed discriminator must have a named local event kind or an explicit decoded-only decision;
|
||||
- `event_family='unknown'` is not acceptable outside synthetic `program` rows;
|
||||
- materializable events must target the matching business table;
|
||||
- duplicate, transport-only or context-incomplete events remain `k_sol_dex_decoded_events_only` by design;
|
||||
- failed transactions must not produce business materialization.
|
||||
|
||||
## Sources
|
||||
|
||||
The source comparison for this tranche is based on:
|
||||
|
||||
- Carbon `raydium-cpmm-decoder`;
|
||||
- Carbon `raydium-clmm-decoder`;
|
||||
- Pinax `substreams-solana-idls` Raydium CPMM/CLMM trees;
|
||||
- Solscan Program IDL pages for CPMM and CLMM;
|
||||
- `0xfnzero/sol-parser-sdk` Raydium IDL snapshots;
|
||||
- local corpus replay results from the dedicated CPMM and CLMM databases.
|
||||
|
||||
## CPMM decision
|
||||
|
||||
`40f4bc78a7e9690a` is now coded as:
|
||||
|
||||
```text
|
||||
local_event_kind = raydium_cpmm.anchor_idl_instruction
|
||||
event_family = idl_management
|
||||
expected_db_target = k_sol_dex_decoded_events_only
|
||||
```
|
||||
|
||||
Manual inspection of the three local signatures showed Anchor IDL management logs:
|
||||
|
||||
- `IdlCreateAccount` on `Hi6MkRTkcgwBi1WpiiudGPHKLuaKXKamNgVsy6YqoQeMRnrkpGjNx75ymrY59tJ3NN1GCn6nrndz9thMmwALLcY`;
|
||||
- `IdlCloseAccount` on `Kch9bYneKzyPg13txxpu151QHX4EgQhFqXUHxqYLXE3BbSrMt56bNMx9JbMAZzs4fbuCLLibHAtrRHdrn7u2VUD`;
|
||||
- `IdlCreateAccount` on `fsKqwEAiRCQyXvCBjBX4XGzkZXyz4DeNL1Kdw9BeyGYYAcTKPEP9sP4WXVNB2FRkvBXc3YjuGhUcihLZm3Y7Znu`.
|
||||
|
||||
This is not a CPMM business instruction. It must not produce trade, candle, liquidity, fee, admin or lifecycle rows.
|
||||
|
||||
## CPMM expected post-replay invariants
|
||||
|
||||
After replay on the CPMM database:
|
||||
|
||||
- observed discriminator coverage gap should be empty;
|
||||
- residual `raydium_cpmm.instruction_audit` should be empty;
|
||||
- decoded event kinds without coverage should be empty;
|
||||
- materialization shortfall should be empty after excluding `k_sol_dex_decoded_events_only` and failed transactions;
|
||||
- `swap_event` remains decoded-only because canonical trades come from `swap_base_input` / `swap_base_output`.
|
||||
|
||||
## CLMM decision
|
||||
|
||||
CLMM has no remaining unknown family in the coverage matrix. The re-check keeps the following entries decoded-only by design:
|
||||
|
||||
- `raydium_clmm.swap_event`: Program-data corroboration of swaps; canonical trade materialization remains on `swap` / `swap_v2`.
|
||||
- `raydium_clmm.swap_router_base_in`: router instruction; no single direct pool surface should be inferred without hop-level resolution.
|
||||
- `raydium_clmm.liquidity_calculate_event`: calculation/diagnostic event.
|
||||
- `raydium_clmm.close_position` and `raydium_clmm.close_protocol_position`: decoded, but not materialized unless a reliable pool/pair context is available.
|
||||
- `raydium_clmm.cpi_event`: Anchor transport only.
|
||||
|
||||
Materialization was strengthened for CLMM liquidity events by accepting snake_case amount keys (`amount0_raw`, `amount1_raw`, `liquidity_raw`) and by resolving pool/pair context from sibling decoded events in the same transaction when the current decoded event carries useful amounts but lacks direct pair context.
|
||||
|
||||
## CLMM expected post-replay invariants
|
||||
|
||||
After replay on the CLMM database:
|
||||
|
||||
- observed discriminator coverage gap should be empty;
|
||||
- residual `raydium_clmm.instruction_audit` should be empty;
|
||||
- decoded event kinds without coverage should be empty;
|
||||
- failed transactions should not produce business rows;
|
||||
- the validation SQL must count `k_sol_token_account_events`, otherwise `create_support_mint_associated` is falsely reported as a materialization gap.
|
||||
|
||||
## Validation files
|
||||
|
||||
Use:
|
||||
|
||||
```text
|
||||
validation_sql/SQL_VALIDATION_RAYDIUM_CPMM_0_7_50_PRE_R2.sql
|
||||
validation_sql/SQL_VALIDATION_RAYDIUM_CLMM_0_7_50_PRE_R2.sql
|
||||
validation_sql/SQL_TRACE_RAYDIUM_CPMM_AUDIT_40F_0_7_50_PRE_R2.sql
|
||||
```
|
||||
@@ -0,0 +1,214 @@
|
||||
<!-- file: docs/reports/RAYDIUM_CPMM_EVENT_COVERAGE_REPORT.md -->
|
||||
|
||||
# Rapport `0.7.48` — Raydium CPMM event coverage
|
||||
|
||||
## Scope
|
||||
|
||||
Tranche : `0.7.48`.
|
||||
Decoder local : `raydium_cpmm`.
|
||||
Programme : `CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C`.
|
||||
|
||||
Objectif : couvrir Raydium CPMM au-delà des swaps, avec preuve locale par backfill/replay SQL, sans modifier les règles trade/candle existantes et sans promouvoir de table métier transversale non nécessaire.
|
||||
|
||||
## Sources utilisées
|
||||
|
||||
Sources principales :
|
||||
|
||||
- Carbon `carbon-raydium-cpmm-decoder` ;
|
||||
- fnzero `solana-streamer` / `sol-parser-sdk` IDL `raydium_cpmm.json` ;
|
||||
- Raydium CP-Swap officiel ;
|
||||
- Solscan page programme / Program IDL comme accélérateur de recherche de signatures, notamment via `instruction=<discriminator>`.
|
||||
|
||||
Règle retenue : Git/IDL/Solscan sont des indices de recherche. La preuve métier reste le corpus local backfillé puis rejoué.
|
||||
|
||||
## Entrées CPMM inventoriées
|
||||
|
||||
| Kind | Entrée | Discriminant | État final `0.7.48` |
|
||||
|---|---|---|---|
|
||||
| instruction | `close_permission_pda` | `9c5420764587467b` | connu upstream, non observé localement |
|
||||
| instruction | `collect_creator_fee` | `1416567bc61cdb84` | décodé + matérialisé fee |
|
||||
| instruction | `collect_fund_fee` | `a78a4e95dfc2067e` | décodé + matérialisé fee |
|
||||
| instruction | `collect_protocol_fee` | `8888fcddc2427e59` | décodé + matérialisé fee |
|
||||
| instruction | `create_amm_config` | `8934edd4d7756c68` | décodé + matérialisé admin/config |
|
||||
| instruction | `create_permission_pda` | `878802d889a9b5ca` | décodé + matérialisé admin/config |
|
||||
| instruction | `deposit` | `f223c68952e1f2b6` | décodé + matérialisé liquidity add |
|
||||
| instruction | `initialize` | `afaf6d1f0d989bed` | décodé + matérialisé lifecycle |
|
||||
| instruction | `initialize_with_permission` | `3f37fe4131b25979` | décodé + matérialisé lifecycle only |
|
||||
| event | `lp_change_event` | `79a3cdc939da753c` | décodé + matérialisé liquidity bidirectionnelle |
|
||||
| instruction | `swap_base_input` | `8fbe5adac41e33de` | décodé + trade matérialisé quand transaction OK |
|
||||
| instruction | `swap_base_output` | `37d96256a34ab4ad` | décodé + trade matérialisé quand transaction OK |
|
||||
| event | `swap_event` | `40c6cde8260871e2` | décodé audit-only, pas trade/candle |
|
||||
| instruction | `update_amm_config` | `313cae889a1c74c8` | décodé + matérialisé admin/config |
|
||||
| instruction | `update_pool_status` | `82576c062ee0757b` | connu upstream, non observé localement |
|
||||
| instruction | `withdraw` | `b712469c946da122` | décodé + matérialisé liquidity remove |
|
||||
|
||||
## Décodage ajouté ou stabilisé
|
||||
|
||||
Le decoder spécialisé `raydium_cpmm` couvre maintenant :
|
||||
|
||||
- les swaps instruction-scoped `swap_base_input` / `swap_base_output` ;
|
||||
- les events `Program data:` / Anchor CPI `swap_event` et `lp_change_event` ;
|
||||
- les instructions lifecycle `initialize` / `initialize_with_permission` ;
|
||||
- les instructions liquidity `deposit` / `withdraw` ;
|
||||
- les fees `collect_creator_fee`, `collect_fund_fee`, `collect_protocol_fee` ;
|
||||
- les instructions admin/config `create_amm_config`, `create_permission_pda`, `update_amm_config` ;
|
||||
- les instructions connues mais non observées `close_permission_pda`, `update_pool_status` restent listées sans promotion métier.
|
||||
|
||||
Le fallback `upstream_git.instruction_match` ne doit plus apparaître pour les instructions CPMM couvertes localement.
|
||||
|
||||
## Matérialisation finale validée
|
||||
|
||||
Rejeu local validé après backfills ciblés Solscan + Demo Pipeline 2 :
|
||||
|
||||
| Event kind | Decoded | Table métier | Materialized | Trade count | Statut |
|
||||
|---|---:|---|---:|---:|---|
|
||||
| `raydium_cpmm.collect_creator_fee` | 4 | `k_sol_fee_events` | 4 | 0 | fee materialized |
|
||||
| `raydium_cpmm.collect_fund_fee` | 7 | `k_sol_fee_events` | 7 | 0 | fee materialized |
|
||||
| `raydium_cpmm.collect_protocol_fee` | 15 | `k_sol_fee_events` | 15 | 0 | fee materialized |
|
||||
| `raydium_cpmm.create_amm_config` | 6 | `k_sol_pool_admin_events` | 6 | 0 | admin materialized |
|
||||
| `raydium_cpmm.create_permission_pda` | 4 | `k_sol_pool_admin_events` | 4 | 0 | admin materialized |
|
||||
| `raydium_cpmm.deposit` | 11 | `k_sol_liquidity_events` | 11 | 0 | liquidity add materialized |
|
||||
| `raydium_cpmm.initialize` | 5 | `k_sol_pool_lifecycle_events` | 5 | 0 | lifecycle materialized |
|
||||
| `raydium_cpmm.initialize_with_permission` | 4 | `k_sol_pool_lifecycle_events` | 4 | 0 | lifecycle only |
|
||||
| `raydium_cpmm.lp_change_event` | 25 | `k_sol_liquidity_events` | 25 | 0 | liquidity materialized, `changeType` bidirectionnel |
|
||||
| `raydium_cpmm.swap_base_input` | 750 | `k_sol_trade_events` | 482 | 482 | trade materialized for OK/actionable tx |
|
||||
| `raydium_cpmm.swap_base_output` | 25 | `k_sol_trade_events` | 17 | 17 | trade materialized for OK/actionable tx |
|
||||
| `raydium_cpmm.swap_event` | 529 | `k_sol_dex_decoded_events_only` | 0 | 0 | audit-only, no duplicate trade |
|
||||
| `raydium_cpmm.update_amm_config` | 13 | `k_sol_pool_admin_events` | 13 | 0 | admin materialized |
|
||||
| `raydium_cpmm.withdraw` | 14 | `k_sol_liquidity_events` | 14 | 0 | liquidity remove materialized |
|
||||
| `raydium_cpmm.instruction_audit` | 3 | `k_sol_dex_decoded_events_only` | 0 | 0 | unknown audit-only |
|
||||
|
||||
Replay final observé :
|
||||
|
||||
```text
|
||||
1124 replayed
|
||||
561 trades
|
||||
50 liquidity
|
||||
9 lifecycle
|
||||
2224 candle upserts
|
||||
```
|
||||
|
||||
Le total liquidity correspond à :
|
||||
|
||||
```text
|
||||
deposit 11
|
||||
withdraw 14
|
||||
lp_change_event 25
|
||||
-------------------
|
||||
total 50
|
||||
```
|
||||
|
||||
## `lp_change_event`
|
||||
|
||||
`lp_change_event` est un event bidirectionnel :
|
||||
|
||||
- `changeType = 0` : add/deposit liquidity ;
|
||||
- `changeType = 1` : remove/withdraw liquidity.
|
||||
|
||||
La coverage statique utilise donc `event_family = liquidity`, pas `liquidity_add`. La matérialisation résout le sens au niveau payload. Les events qui ne contiennent pas directement les mints sont enrichis via le contexte pool/pair local ou via le sibling `deposit` / `withdraw` déjà matérialisé dans la même transaction/replay.
|
||||
|
||||
Validation finale :
|
||||
|
||||
```text
|
||||
changeType 0 -> 11 decoded / 11 liquidity / 0 trade
|
||||
changeType 1 -> 14 decoded / 14 liquidity / 0 trade
|
||||
```
|
||||
|
||||
## `initialize_with_permission`
|
||||
|
||||
`initialize_with_permission` est traité comme pool lifecycle only.
|
||||
|
||||
Validation finale :
|
||||
|
||||
```text
|
||||
raydium_cpmm.initialize 5 decoded / 5 lifecycle / 0 admin / 0 trade
|
||||
raydium_cpmm.initialize_with_permission 4 decoded / 4 lifecycle / 0 admin / 0 trade
|
||||
```
|
||||
|
||||
Le cleanup de matérialisation supprime les anciennes lignes admin dérivées si elles existent déjà dans la base.
|
||||
|
||||
## Entrées non observées
|
||||
|
||||
Solscan avec filtre `instruction=` n'a pas retourné de transaction locale utile pour :
|
||||
|
||||
- `close_permission_pda` / `9c5420764587467b` ;
|
||||
- `update_pool_status` / `82576c062ee0757b`.
|
||||
|
||||
Ces entrées restent donc :
|
||||
|
||||
```text
|
||||
upstream_git_mapped_unverified
|
||||
```
|
||||
|
||||
Absence Solscan ne signifie pas absence on-chain absolue, surtout si l'index UI ne couvre pas tout l'historique. Cela suffit cependant pour ne pas les promouvoir sans corpus local.
|
||||
|
||||
## Instruction audit inconnue
|
||||
|
||||
Le discriminator suivant a été observé localement :
|
||||
|
||||
```text
|
||||
40f4bc78a7e9690a
|
||||
```
|
||||
|
||||
Il produit actuellement `raydium_cpmm.instruction_audit` avec `tradeCandidate=false` / `candleCandidate=false`. Il n'est pas nommé dans la tranche `0.7.48`, faute de preuve upstream/corpus suffisante.
|
||||
|
||||
## Recherche Solscan retenue
|
||||
|
||||
La page programme Solscan et l'onglet Program IDL sont utiles pour accélérer la recherche :
|
||||
|
||||
```text
|
||||
https://solscan.io/account/CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C#programIdl
|
||||
```
|
||||
|
||||
Le filtre `instruction=<discriminator>` est documenté comme méthode pratique de découverte de signatures à backfiller localement, par exemple :
|
||||
|
||||
```text
|
||||
https://solscan.io/account/CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C?instruction=f223c68952e1f2b6&instruction=b712469c946da122&hide_spam=true&hide_failed=true&show_related=false&sort=desc
|
||||
```
|
||||
|
||||
Solscan reste une aide de recherche, pas une source de vérité métier.
|
||||
|
||||
## Table technique ajoutée
|
||||
|
||||
`k_sol_instruction_observations` est ajoutée comme table technique d'index local. Elle permet de retrouver les signatures observées par `decoder_code`, `instruction_name` et `discriminator_hex`, sans créer de nouvelle table métier.
|
||||
|
||||
Exemple :
|
||||
|
||||
```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_cpmm'
|
||||
GROUP BY instruction_name, discriminator_hex
|
||||
ORDER BY observed_count DESC;
|
||||
```
|
||||
|
||||
## Invariants validés
|
||||
|
||||
- `swap_event` ne produit aucun trade/candle.
|
||||
- `deposit`, `withdraw`, `lp_change_event`, fees, admin/config et lifecycle gardent `trade_count=0`.
|
||||
- Les transactions failed restent non matérialisées en trade/candle.
|
||||
- Les side effects SPL Token / Token-2022 (`burn`, `transfer`, `transferChecked`, `closeAccount`) restent hors decoder métier CPMM direct et devront passer par une future table transversale si plusieurs DEX le justifient.
|
||||
- Aucun program id n'est promu sans corpus local.
|
||||
|
||||
## État de clôture
|
||||
|
||||
`0.7.48 raydium_cpmm` est clôturable avec deux entrées connues mais non observées :
|
||||
|
||||
```text
|
||||
close_permission_pda
|
||||
update_pool_status
|
||||
```
|
||||
|
||||
La prochaine tranche fonctionnelle est `0.7.49 raydium_clmm`.
|
||||
|
||||
## Addendum `0.7.50-pre-r2` — cpi_event et audit `40f4bc78a7e9690a`
|
||||
|
||||
La re-vérification CPMM ajoute explicitement `cpi_event` à la matrice coverage locale avec le discriminant Carbon `e445a52e51cb9a1d`. Cette entrée est un transport Anchor/CPI et reste `k_sol_dex_decoded_events_only`.
|
||||
|
||||
Le discriminant observé localement `40f4bc78a7e9690a` est classé comme `raydium_cpmm.anchor_idl_instruction`, avec `event_family=idl_management` et `expected_db_target=k_sol_dex_decoded_events_only`. Les signatures inspectées montrent `Program log: Instruction: IdlCreateAccount` et `Program log: Instruction: IdlCloseAccount` sur le compte `anchor:idl`; il ne correspond donc pas au `cpi_event` Carbon et ne doit pas être matérialisé dans les tables métier.
|
||||
|
||||
Trace SQL ajouté : `validation_sql/SQL_TRACE_RAYDIUM_CPMM_AUDIT_40F_0_7_50_PRE_R2.sql` liste les signatures, slots, index d'instruction, comptes et données associées à `40f4bc78a7e9690a`.
|
||||
@@ -0,0 +1,74 @@
|
||||
<!-- file: docs/reports/RAYDIUM_CPMM_UPSTREAM_COVERAGE_REVIEW_PRE22.md -->
|
||||
|
||||
# Raydium CPMM upstream coverage review — 0.7.49-pre.22
|
||||
|
||||
## Scope
|
||||
|
||||
Compared local `raydium_cpmm` coverage against the currently referenced upstream surfaces:
|
||||
|
||||
- Solscan program IDL for `CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C`.
|
||||
- `sevenlabs-hq/carbon` `raydium-cpmm-decoder`.
|
||||
- `0xfnzero/sol-parser-sdk` `idl/raydium_cpmm.json`.
|
||||
- `pinax-network/substreams-solana-idls` `src/raydium/cpmm`.
|
||||
- Raydium official `raydium-cp-swap` source.
|
||||
|
||||
## Local CPMM coverage entries
|
||||
|
||||
Local registry currently lists 16 `raydium_cpmm` entries:
|
||||
|
||||
### Instructions
|
||||
|
||||
- `close_permission_pda` — `9c5420764587467b`
|
||||
- `collect_creator_fee` — `1416567bc61cdb84`
|
||||
- `collect_fund_fee` — `a78a4e95dfc2067e`
|
||||
- `collect_protocol_fee` — `8888fcddc2427e59`
|
||||
- `create_amm_config` — `8934edd4d7756c68`
|
||||
- `create_permission_pda` — `878802d889a9b5ca`
|
||||
- `deposit` — `f223c68952e1f2b6`
|
||||
- `initialize` — `afaf6d1f0d989bed`
|
||||
- `initialize_with_permission` — `3f37fe4131b25979`
|
||||
- `swap_base_input` — `8fbe5adac41e33de`
|
||||
- `swap_base_output` — `37d96256a34ab4ad`
|
||||
- `update_amm_config` — `313cae889a1c74c8`
|
||||
- `update_pool_status` — `82576c062ee0757b`
|
||||
- `withdraw` — `b712469c946da122`
|
||||
|
||||
### Anchor / Program-data events
|
||||
|
||||
- `lp_change_event` — `79a3cdc939da753c`
|
||||
- `swap_event` — `40c6cde8260871e2`
|
||||
|
||||
## Upstream comparison
|
||||
|
||||
Carbon `raydium-cpmm-decoder` exposes the same 14 instruction modules and the two event-like discriminator entries, `lp_change_event` and `swap_event`.
|
||||
|
||||
`sol-parser-sdk` `idl/raydium_cpmm.json` exposes the core CPMM instruction set (`createAmmConfig`, `updateAmmConfig`, `updatePoolStatus`, `collectProtocolFee`, `collectFundFee`, `initialize`, `deposit`, `withdraw`, `swapBaseInput`, `swapBaseOutput`) and IDL events `LpChangeEvent` and `SwapEvent`. The local registry also includes the permission and creator-fee entries present in Carbon / Raydium source.
|
||||
|
||||
The official Raydium `raydium-cp-swap` source lists the CPMM program ID and the main program instructions including admin/config, fee collection, permission PDA, initialize, initialize with permission, deposit, withdraw, swap base input, and swap base output.
|
||||
|
||||
## Finding
|
||||
|
||||
No missing CPMM instruction/event discriminator was identified relative to the reviewed Carbon / Raydium / fnzero / Pinax surfaces available during this check.
|
||||
|
||||
## Current local caveat
|
||||
|
||||
CPMM remains covered by the earlier 0.7.48 tranche. The useful final validation remains DB-side:
|
||||
|
||||
```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_cpmm'
|
||||
ORDER BY entry_kind, entry_name, discriminator_hex;
|
||||
```
|
||||
|
||||
Any future upstream addition should appear as a new entry in Carbon/Solscan/IDL and should be added to `upstream_registry_generated.rs`, `known_local_event_kind` only after local decoder support exists, and then validated with local corpus evidence.
|
||||
@@ -0,0 +1,233 @@
|
||||
<!-- file: docs/reports/RAYDIUM_LAUNCHPAD_EVENT_COVERAGE_REPORT.md -->
|
||||
|
||||
# Raydium Launchpad event coverage report — `0.7.50`
|
||||
|
||||
## Scope
|
||||
|
||||
`0.7.50` opens the `raydium_launchpad` tranche after the functional closure of `0.7.49 raydium_clmm`.
|
||||
|
||||
Local canonical decoder/surface code:
|
||||
|
||||
```text
|
||||
raydium_launchpad
|
||||
```
|
||||
|
||||
Canonical program id:
|
||||
|
||||
```text
|
||||
LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj
|
||||
```
|
||||
|
||||
The legacy local name `raydium_launchlab` is not kept in the public Rust API. Coverage rows, upstream registry rows, launch origin entries, and support matrix rows use `raydium_launchpad`.
|
||||
|
||||
## Sources used
|
||||
|
||||
Primary source hints for this tranche:
|
||||
|
||||
- Carbon decoder registry/source: `sevenlabs-hq/carbon/decoders/raydium-launchpad-decoder`.
|
||||
- Solscan Program IDL/account page: `https://solscan.io/account/LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj#programIdl`.
|
||||
- fnzero IDL sources: `sol-parser-sdk` / `solana-program-idls` listings, including `raydium_launchpad.json` and separate `raydium_pool_v4.json` as an audit-only source.
|
||||
- Raydium SDK Launchpad examples for account-shape hints only.
|
||||
|
||||
These sources are not treated as final business proof. Promotion still requires local corpus observation and SQL validation.
|
||||
|
||||
## Bootstrap implementation delta
|
||||
|
||||
Implemented in this delta:
|
||||
|
||||
- `RAYDIUM_LAUNCHPAD_PROGRAM_ID` added as the canonical public constant.
|
||||
- Upstream generated registry rows normalized from `raydium_launchlab` to `raydium_launchpad`.
|
||||
- Built-in launch surface code normalized to `raydium_launchpad`.
|
||||
- DEX support/catalog entries normalized to `raydium_launchpad`.
|
||||
- Raydium instruction audit fallback now recognizes Launchpad program id.
|
||||
- Launchpad mapped instruction fallback added for locally listed Launchpad discriminators.
|
||||
- Coverage target override keeps Launchpad rows `decoded_events_only` until corpus promotion.
|
||||
- SQL validation file added for the `0.7.50` tranche.
|
||||
|
||||
## Listed Launchpad entries
|
||||
|
||||
The local upstream registry now lists one program entry plus the following 26 discriminator entries.
|
||||
|
||||
| Entry kind | Entry name | Discriminator | Initial family | Initial DB target |
|
||||
|---|---:|---:|---|---|
|
||||
| instruction | `buy_exact_in` | `faea0d7bd59c13ec` | swap | decoded_events_only |
|
||||
| instruction | `buy_exact_out` | `18d3742869039938` | swap | decoded_events_only |
|
||||
| instruction | `claim_creator_fee` | `1a618acb84ab8dfc` | fee | decoded_events_only |
|
||||
| instruction | `claim_platform_fee` | `9c27d0874ced3d48` | fee | decoded_events_only |
|
||||
| instruction | `claim_platform_fee_from_vault` | `75f1c6a8f8da501d` | fee | decoded_events_only |
|
||||
| event | `claim_vested_event` | `15c2725778d3e220` | fee/vesting audit | decoded_events_only |
|
||||
| instruction | `claim_vested_token` | `3121681ebd9d4f23` | fee/vesting audit | decoded_events_only |
|
||||
| instruction | `collect_fee` | `3cadf767045d8230` | fee | decoded_events_only |
|
||||
| instruction | `collect_migrate_fee` | `ffba96dfeb76c9ba` | fee/migration audit | decoded_events_only |
|
||||
| instruction | `create_config` | `c9cff3724b6f2fbd` | admin_config | decoded_events_only |
|
||||
| instruction | `create_platform_config` | `b05ac4affd71dc14` | admin_config | decoded_events_only |
|
||||
| instruction | `create_vesting_account` | `81b2020dd9ace6da` | account_create/vesting audit | decoded_events_only |
|
||||
| event | `create_vesting_event` | `96980bb334d2bf7d` | account_create/vesting audit | decoded_events_only |
|
||||
| instruction | `initialize` | `afaf6d1f0d989bed` | pool_create/launch | decoded_events_only |
|
||||
| instruction | `initialize_v2` | `4399af27da102620` | pool_create/launch | decoded_events_only |
|
||||
| instruction | `initialize_with_token_2022` | `25be7ede2c9aab11` | pool_create/launch | decoded_events_only |
|
||||
| instruction | `migrate_to_amm` | `cf52c091fecf91df` | migration | decoded_events_only |
|
||||
| instruction | `migrate_to_cpswap` | `885cc8671cda908c` | migration | decoded_events_only |
|
||||
| event | `pool_create_event` | `97d7e20976a173ae` | pool_create | decoded_events_only |
|
||||
| instruction | `remove_platform_curve_param` | `1b1e3ea95de01891` | admin_config | decoded_events_only |
|
||||
| instruction | `sell_exact_in` | `9527de9bd37c981a` | swap | decoded_events_only |
|
||||
| instruction | `sell_exact_out` | `5fc8472208090ba6` | swap | decoded_events_only |
|
||||
| event | `trade_event` | `bddb7fd34ee661ee` | swap | decoded_events_only |
|
||||
| instruction | `update_config` | `1d9efcbf0a53db63` | admin_config | decoded_events_only |
|
||||
| instruction | `update_platform_config` | `c33c4c81922d438f` | admin_config | decoded_events_only |
|
||||
| instruction | `update_platform_curve_param` | `8a908afadc800439` | admin_config | decoded_events_only |
|
||||
|
||||
Notes:
|
||||
|
||||
- The buy/sell instruction account hints currently use account index `4` as candidate pool account and indexes `9`/`10` as candidate token mints, based on Carbon/Raydium Launchpad account shape hints. This is an audit helper, not a materialization proof.
|
||||
- Fee/admin/migration/vesting entries intentionally do not infer pool/token accounts until corpus confirms the account semantics.
|
||||
- Program-data transport is represented by `cpi_event`; embedded events are decoded by their own discriminators and materialized only when their event family has a validated target.
|
||||
|
||||
## Family audit matrix
|
||||
|
||||
| Family | Launchpad status in `0.7.50` final | Decision |
|
||||
|---|---|---|
|
||||
| swap | `trade_event` materialized as trades/candles; buy/sell instructions materialized as launch breadcrumbs. | No duplicate trades from instruction breadcrumbs. |
|
||||
| pool_create | `initialize`, `initialize_v2`, `initialize_with_token_2022`, `pool_create_event`. | Pool lifecycle/catalogue materialized when transaction succeeded. |
|
||||
| add_liquidity | No direct Launchpad entry confirmed. | Non-applicable unless local corpus proves direct Launchpad liquidity instruction. |
|
||||
| remove_liquidity | No direct Launchpad liquidity remove entry confirmed. | Non-applicable unless local corpus proves direct Launchpad liquidity instruction. |
|
||||
| position_open | No direct Launchpad position instruction confirmed. | Non-applicable. |
|
||||
| position_close | No direct Launchpad position instruction confirmed. | Non-applicable. |
|
||||
| fee | claim/collect fee entries listed. | Fee table materialization enabled for observed successful transactions. |
|
||||
| reward | No direct reward instruction confirmed. | Non-applicable unless local corpus proves otherwise. |
|
||||
| admin/config | create/update config and platform curve/config entries listed. | Pool admin materialization enabled for observed successful transactions. |
|
||||
| mint | Token minting may appear as SPL Token/Token-2022 side effect. | Not `raydium_launchpad.*` without direct program proof. |
|
||||
| burn | Token burn may appear as SPL Token/Token-2022 side effect. | Not `raydium_launchpad.*` without direct program proof. |
|
||||
| transfer | Transfers are expected as SPL Token/Token-2022 side effects. | Not `raydium_launchpad.*` without direct program proof. |
|
||||
| account_create / vesting | `create_vesting_account`, `create_platform_vesting_account`, vesting events. | Launch event materialization enabled for observed successful transactions; unobserved events remain mapped. |
|
||||
| account_close | No direct Launchpad account close confirmed. | Non-applicable. |
|
||||
| wrap_sol | No direct Launchpad wrap SOL confirmed. | Side effect only unless corpus proves direct instruction. |
|
||||
| unwrap_sol | No direct Launchpad unwrap SOL confirmed. | Side effect only unless corpus proves direct instruction. |
|
||||
| order_place | No orderbook surface confirmed. | Non-applicable. |
|
||||
| order_cancel | No orderbook surface confirmed. | Non-applicable. |
|
||||
| order_fill | No orderbook surface confirmed. | Non-applicable. |
|
||||
| consume_events | No orderbook surface confirmed. | Non-applicable. |
|
||||
| settle_funds | No orderbook surface confirmed. | Non-applicable. |
|
||||
| vault_deposit | No direct vault deposit confirmed. | Non-applicable. |
|
||||
| vault_withdraw | No direct vault withdraw confirmed. | Non-applicable. |
|
||||
| lock | No direct lock confirmed. | Non-applicable. |
|
||||
| unlock | No direct unlock confirmed. | Non-applicable. |
|
||||
| launch | initialize/pool_create path listed. | Decode/audit only. |
|
||||
| migration | `migrate_to_amm`, `migrate_to_cpswap`, `collect_migrate_fee` listed. | Decode/audit only. Destination DEX materialization must be proven locally. |
|
||||
| stake | No direct stake confirmed. | Non-applicable. |
|
||||
| unstake | No direct unstake confirmed. | Non-applicable. |
|
||||
| unknown/unmapped audit | `raydium_launchpad.instruction_audit` retained for unmatched program instructions. | Must trend toward zero for locally covered discriminators after backfill/replay. |
|
||||
|
||||
## SQL validation expectations
|
||||
|
||||
After targeted backfill and replay:
|
||||
|
||||
1. `k_sol_dex_event_coverage_entries` should contain the Launchpad program entry and discriminator entries.
|
||||
2. Mapped entries should have `local_event_kind = raydium_launchpad.<entry_name>` and initial `proof_status = upstream_git_mapped_unverified` until observed.
|
||||
3. Locally observed instructions should increment `k_sol_instruction_observations` for `decoder_code = raydium_launchpad`.
|
||||
4. `upstream_git.instruction_match` fallback rows for `upstreamDecoderCode = raydium_launchpad` should be zero for locally covered instruction discriminators.
|
||||
5. `raydium_launchpad.*` rows must not produce trades/candles unless a later corpus-backed patch explicitly promotes a specific event.
|
||||
6. Failed transactions may be decoded/audited, but must not be materialized in trade/candle tables.
|
||||
|
||||
Validation file:
|
||||
|
||||
```text
|
||||
validation_sql/SQL_VALIDATION_RAYDIUM_LAUNCHPAD_0_7_50.sql
|
||||
```
|
||||
|
||||
## Suggested targeted Solscan discovery loop
|
||||
|
||||
For each discriminator:
|
||||
|
||||
```text
|
||||
https://solscan.io/account/LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj?instruction=<DISCRIMINATOR>&hide_spam=true&hide_failed=true&show_related=false&sort=desc
|
||||
```
|
||||
|
||||
Then:
|
||||
|
||||
1. copy a small batch of recent non-failed signatures;
|
||||
2. backfill through Demo2 textarea batch;
|
||||
3. replay with `forceDexDecode=yes` and `deferInstructionObservations=yes`;
|
||||
4. run the validation SQL;
|
||||
5. promote only entries whose local payload and account semantics are proven.
|
||||
|
||||
## `raydium_pool_v4.json` audit status
|
||||
|
||||
The current workspace archive does not contain a local `raydium_pool_v4.json` copy. External fnzero IDL listings expose a separate `raydium_pool_v4.json` beside `raydium_launchpad.json`, but this delta does not confirm its program id or business role.
|
||||
|
||||
Decision for `0.7.50`:
|
||||
|
||||
- do not promote `raydium_pool_v4` as a DEX/surface;
|
||||
- keep `0.7.53 raydium_pool_v4 audit / program-id decision` conditional;
|
||||
- require program id confirmation and local corpus before any roadmap promotion.
|
||||
|
||||
## Current limitations
|
||||
|
||||
This delta was prepared from the provided archive only. No live RPC backfill, fresh SQLite replay, `cargo fmt`, `cargo test`, or `cargo clippy` could be executed in the current environment because the Rust toolchain is unavailable here. The SQL and code paths are prepared for local validation in the normal project environment.
|
||||
|
||||
## Local corpus snapshot from first 0.7.50 backfill
|
||||
|
||||
Observed after targeted Demo2 backfills and pool backfill on a fresh 0.7.50 DB:
|
||||
|
||||
- coverage listed entries: `27`;
|
||||
- decoded/local mapped entries: `26`;
|
||||
- observed entries: `21`;
|
||||
- materialized entries: `0`;
|
||||
- total observed coverage count: `672`;
|
||||
- total materialized count: `0`;
|
||||
- trade count: `0`;
|
||||
- residual `upstream_git.instruction_match` for `raydium_launchpad`: `0`;
|
||||
- residual `raydium_launchpad.instruction_audit`: `287`;
|
||||
- residual audit discriminators: `e445a52e51cb9a1d` (`276`), `9247ad4562130f6a` (`10`), `a25b92c75d85eaed` (`1`).
|
||||
|
||||
The `e445a52e51cb9a1d` selector is handled as Anchor self-CPI event transport. It is not promoted as a Raydium Launchpad business instruction. The two low-count residual discriminators remain local-corpus audit-only until an IDL/upstream mapping is confirmed.
|
||||
|
||||
|
||||
## pre3 correction — Demo3 preset and Launchpad pool catalog
|
||||
|
||||
The first replay after pre2 confirmed that Anchor self-CPI selector `e445a52e51cb9a1d` carries Launchpad `trade_event` (`bddb7fd34ee661ee`) and `pool_create_event` (`97d7e20976a173ae`). pre3 therefore decodes those two self-CPI event rows as direct `raydium_launchpad.*` events instead of leaving them under `raydium_launchpad.instruction_audit`. `trade_event` remains audit/decoded-only and is still not promoted to `k_sol_trade_events` or candles.
|
||||
|
||||
pre3 also fixes the Launchpad `initialize`, `initialize_v2` and `initialize_with_token_2022` account mapping using the Carbon account shape: `pool_state` index 5, `base_mint` index 6 and `quote_mint` index 7. These initialize rows are now routed to business-level pool detection as `raydium_launchpad` bonding-curve pools with pending status, which should allow pool `6HLQPoLrzX6LqePRiXQ1GGs2Dd9K3dp9VhTSHBugYzzZ` to appear in the local catalog after a forced replay when its initialize transaction is present locally.
|
||||
|
||||
Demo3 now exposes a `Raydium Launchpad` preset with program id `LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj`.
|
||||
|
||||
|
||||
## Final `0.7.50` closure snapshot
|
||||
|
||||
Validated closure state reported by local replay:
|
||||
|
||||
- `cargo test -p kb_lib`: 404 passed, 0 failed.
|
||||
- Local replay: 437 replayed, 437 ledger upserts, 30 unsafe ledger rows, 256 trades, 115 lifecycle rows, 1024 candle upserts, 6205 instruction observations.
|
||||
- Launchpad catalogue: 58 tokens, 58 pools, 58 pairs after replay.
|
||||
- Coverage normalization: no ambiguous `unknown` family remains; only the synthetic `program` row may have an empty family.
|
||||
- `trade_event`: 260 decoded, 250 successful materialized trades; 10 failed transactions intentionally not materialized.
|
||||
- `buy_exact_*` / `sell_exact_*`: materialized as `k_sol_launch_events` swap-instruction breadcrumbs, not as trades.
|
||||
- `cpi_event`: kept as `cpi_transport` / decoded-only; embedded events are decoded by direct event discriminator.
|
||||
- Successful `trade_event` rows without materialized `k_sol_trade_events`: zero.
|
||||
|
||||
Post-closure recheck assets added:
|
||||
|
||||
- `validation_sql/SQL_VALIDATION_RAYDIUM_CPMM_0_7_50_PRE_R2.sql`
|
||||
- `validation_sql/SQL_VALIDATION_RAYDIUM_CLMM_0_7_50_PRE_R2.sql`
|
||||
- `docs/SOLSCAN_ACCOUNT_SOURCE_MATRIX.md`
|
||||
- `kb_lib::SOLSCAN_ACCOUNT_SOURCES`
|
||||
|
||||
## Final cleanup note — CPMM residual audit after 0.7.50 recheck
|
||||
|
||||
During the 0.7.50 post-Launchpad recheck, the CPMM residual audit query still showed three `raydium_cpmm.instruction_audit` rows for discriminator `40f4bc78a7e9690a` even though the same discriminator is now locally mapped as `raydium_cpmm.anchor_idl_instruction`.
|
||||
|
||||
The final cleanup patch makes the deletion FK-safe by unlinking `k_sol_instruction_observations.decoded_event_id` before deleting the legacy audit rows. It also repeats the CPMM cleanup after coverage refresh and refreshes coverage again if rows were removed.
|
||||
|
||||
Expected final state after replay:
|
||||
|
||||
```text
|
||||
raydium_cpmm.instruction_audit / 40f4bc78a7e9690a = 0
|
||||
raydium_cpmm decoded events without coverage row = 0
|
||||
raydium_cpmm.anchor_idl_instruction remains decoded-only / idl_management
|
||||
```
|
||||
|
||||
Validation SQL:
|
||||
|
||||
```text
|
||||
validation_sql/SQL_VALIDATION_RAYDIUM_CPMM_AUDIT_CLEANUP_0_7_50_FINAL.sql
|
||||
```
|
||||
@@ -0,0 +1,56 @@
|
||||
<!-- file: docs/reports/RAYDIUM_POOL_V4_DECISION_NOTE.md -->
|
||||
|
||||
# Raydium Pool v4 Decision Note — `0.7.51`
|
||||
|
||||
## Décision courte
|
||||
|
||||
`raydium_pool_v4` ne doit pas être ouvert comme decoder autonome dans `0.7.51`.
|
||||
|
||||
Statut retenu :
|
||||
|
||||
```text
|
||||
Option C — IDL ambiguë / strategy-pool wrapper sans corpus local suffisant.
|
||||
```
|
||||
|
||||
Conséquence : `raydium_pool_v4` reste une source d'audit/comparaison pour `raydium_amm_v4`. Toute promotion en tranche dédiée exige un program id prouvé localement, des observations dans `k_sol_instruction_observations`, des decoded events locaux et une absence de fallback upstream inexpliqué.
|
||||
|
||||
## Comparaison synthétique
|
||||
|
||||
| Source | Nom / rôle constaté | Indices structurants | Décision locale |
|
||||
|---|---|---|---|
|
||||
| `idl/raydium_amm_v4.json` | `raydium_amm` | Instructions AMM v4 legacy : `initialize`, `initialize2`, `deposit`, `withdraw`, `swapBaseIn`, `swapBaseOut`, `monitorStep`, `setParams`. | Source principale pour `raydium_amm_v4`. |
|
||||
| `idls/raydium_amm_v4.json` | `raydium_amm` | Variante parallèle à comparer ligne à ligne avec `idl/`. | Source principale complémentaire. |
|
||||
| `idl/raydium_pool_v4.json` | `Raydium Liquidity Pool V4` | Entrées orientées stratégie/pool wrapper : `initializeStrategy`, comptes `strategyState`, `strategyAuthority`, `lendingProgramId`; contient aussi des noms comme `swapBaseIn`. | Audit uniquement. Ne pas promouvoir. |
|
||||
| `idls/raydium_pool_v4.json` | `Raydium Liquidity Pool V4` | Même famille de signaux que `idl/raydium_pool_v4.json` à vérifier localement. | Audit uniquement. |
|
||||
|
||||
## Raisons de non-promotion
|
||||
|
||||
1. `raydium_pool_v4` ne prouve pas encore un program id local autonome dans le workspace.
|
||||
2. La présence de noms communs (`swapBaseIn`, comptes OpenBook) ne suffit pas à conclure que la surface est le program id AMM v4 canonique `675kPX...`.
|
||||
3. Les entrées `initializeStrategy`, `strategyState`, `strategyAuthority` et `lendingProgramId` indiquent un rôle potentiellement distinct : strategy, wrapper, pool manager, lending ou ancienne ABI composite.
|
||||
4. Aucune ligne locale `k_sol_instruction_observations` / `k_sol_dex_decoded_events` / `k_sol_dex_event_coverage_entries.local_event_kind` ne justifie une tranche autonome au moment de l'ouverture `0.7.51`.
|
||||
|
||||
## Règle de décision future
|
||||
|
||||
- Si `raydium_pool_v4` correspond finalement au même program id AMM v4 ou à un layout alternatif compatible, intégrer les discriminants/layouts validés dans `raydium_amm_v4`.
|
||||
- Si `raydium_pool_v4` correspond à un autre program id / wrapper / strategy / lending surface, créer une tranche dédiée seulement après corpus local.
|
||||
- Si l'IDL reste ambiguë, conserver l'entrée en roadmap comme audit conditionnel sans decoder runtime.
|
||||
|
||||
## SQL local attendu avant toute promotion
|
||||
|
||||
Une future promotion doit au minimum montrer :
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
decoder_code,
|
||||
instruction_name,
|
||||
discriminator_hex,
|
||||
COUNT(*) AS observed_count,
|
||||
COUNT(DISTINCT signature) AS tx_count
|
||||
FROM k_sol_instruction_observations
|
||||
WHERE decoder_code IN ('raydium_amm_v4', 'raydium_pool_v4')
|
||||
GROUP BY decoder_code, instruction_name, discriminator_hex
|
||||
ORDER BY decoder_code, observed_count DESC;
|
||||
```
|
||||
|
||||
Puis une preuve de decoded events locaux, de coverage entries mappées et d'absence de fallback upstream résiduel.
|
||||
@@ -0,0 +1,164 @@
|
||||
<!-- file: docs/reports/RAYDIUM_STABLE_SWAP_EVENT_COVERAGE_REPORT.md -->
|
||||
|
||||
# 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.
|
||||
@@ -0,0 +1,219 @@
|
||||
# SQLite DB Transaction Merger — 0.7.58
|
||||
|
||||
## Statut
|
||||
|
||||
`0.7.58` introduit un outil CLI de fusion de corpus SQLite transactionnels pour construire une base consolidée de non-régression (`final.db` ou `final.next.db`) à partir de bases dédiées par DEX/surface.
|
||||
|
||||
Le merger ne lance pas de RPC, ne backfille pas, ne redécode pas et ne matérialise pas pendant la fusion. Il copie seulement le corpus brut nécessaire au replay local.
|
||||
|
||||
## Emplacement
|
||||
|
||||
```text
|
||||
kb_tools/
|
||||
Cargo.toml
|
||||
src/bin/kb_db_merge.rs
|
||||
```
|
||||
|
||||
Le package `kb_tools` est membre du workspace principal.
|
||||
|
||||
## Commandes types
|
||||
|
||||
Dry-run sur un output cible :
|
||||
|
||||
```bash
|
||||
cargo run -p kb_tools --bin kb_db_merge -- \
|
||||
--output ./final.next.db \
|
||||
--input ./final.db \
|
||||
--input ./corpus/pump_swap.db \
|
||||
--input ./corpus/pump_fees.db \
|
||||
--mode raw-corpus \
|
||||
--dry-run
|
||||
```
|
||||
|
||||
Merge réel dans une nouvelle base :
|
||||
|
||||
```bash
|
||||
cargo run -p kb_tools --bin kb_db_merge -- \
|
||||
--output ./final.next.db \
|
||||
--input ./final.db \
|
||||
--input ./corpus/new_dex.db \
|
||||
--mode raw-corpus \
|
||||
--replace-output
|
||||
```
|
||||
|
||||
Merge dans une copie explicite de `final.db` :
|
||||
|
||||
```bash
|
||||
cargo run -p kb_tools --bin kb_db_merge -- \
|
||||
--merge-into-copy-of ./final.db \
|
||||
--output ./final.next.db \
|
||||
--input ./corpus/new_dex.db \
|
||||
--mode raw-corpus \
|
||||
--replace-output
|
||||
```
|
||||
|
||||
## Modes
|
||||
|
||||
### `raw-corpus`
|
||||
|
||||
Mode par défaut.
|
||||
|
||||
Copie uniquement :
|
||||
|
||||
```text
|
||||
k_sol_chain_transactions
|
||||
k_sol_chain_instructions
|
||||
```
|
||||
|
||||
Les tables décodées ou matérialisées ne sont pas copiées, car leur contenu dépend de la version active des decoders/materializers et doit être reconstruit par replay local.
|
||||
|
||||
### `signatures-only`
|
||||
|
||||
Alimente `k_sol_db_merge_signature_staging` avec `source_id`, `signature`, `slot` et `source_transaction_id`.
|
||||
|
||||
Ce mode sert à auditer ou préparer des backfills contrôlés sans copier les transactions complètes.
|
||||
|
||||
### `full-copy-safe`
|
||||
|
||||
Le mode est exposé dans le CLI mais reste explicitement refusé dans `0.7.58`. Il ne doit devenir utilisable que si les versions de schéma, les versions logiques des decoders et les remappages de foreign keys sont prouvés compatibles.
|
||||
|
||||
## Tables de provenance
|
||||
|
||||
Le schéma `kb_lib` ajoute :
|
||||
|
||||
```text
|
||||
k_sol_db_merge_sources
|
||||
k_sol_db_merge_transactions
|
||||
k_sol_db_merge_conflicts
|
||||
k_sol_db_merge_signature_staging
|
||||
```
|
||||
|
||||
Ces tables permettent de relier chaque ligne copiée ou ignorée à sa source et de journaliser les conflits au lieu d’écraser silencieusement.
|
||||
|
||||
## Déduplication
|
||||
|
||||
L’identité canonique est :
|
||||
|
||||
```text
|
||||
signature
|
||||
```
|
||||
|
||||
Règles :
|
||||
|
||||
- signature absente de l’output : copie transaction + instructions enfants ;
|
||||
- signature déjà présente et identique : provenance `duplicate_skipped` ;
|
||||
- signature déjà présente mais différente : insertion dans `k_sol_db_merge_conflicts` ;
|
||||
- `--conflict-policy fail` : arrêt au premier conflit journalisé ;
|
||||
- `--conflict-policy prefer-complete` : remplacement uniquement si le corpus entrant obtient un score de complétude supérieur ;
|
||||
- `--conflict-policy record` : journalisation sans remplacement.
|
||||
|
||||
## Inspection de schéma
|
||||
|
||||
Chaque source est inspectée avant traitement :
|
||||
|
||||
```sql
|
||||
SELECT name, sql FROM sqlite_master WHERE type = 'table';
|
||||
PRAGMA table_info(k_sol_chain_transactions);
|
||||
PRAGMA table_info(k_sol_chain_instructions);
|
||||
```
|
||||
|
||||
Pour `raw-corpus`, une source est refusée si elle ne contient pas les tables et colonnes minimales nécessaires au replay local.
|
||||
|
||||
Les erreurs mentionnent :
|
||||
|
||||
```text
|
||||
source DB
|
||||
missing table ou missing column
|
||||
mode demandé
|
||||
```
|
||||
|
||||
## Replay attendu après merge
|
||||
|
||||
Après merge réel de `final.next.db`, rejouer localement avec :
|
||||
|
||||
```text
|
||||
metadata=no
|
||||
skipDexDecode=no
|
||||
forceDexDecode=yes
|
||||
deferInstructionObservations=yes
|
||||
```
|
||||
|
||||
Objectif : reconstruire toutes les tables dérivées avec les decoders/materializers courants et détecter les régressions cross-surface.
|
||||
|
||||
## SQL de validation
|
||||
|
||||
Fichiers ajoutés :
|
||||
|
||||
```text
|
||||
validation_sql/SQL_VALIDATION_DB_MERGE_0_7_58.sql
|
||||
validation_sql/SQL_VALIDATION_CROSS_DEX_REGRESSION_0_7_58.sql
|
||||
```
|
||||
|
||||
Gates minimaux merge :
|
||||
|
||||
- aucune signature dupliquée ;
|
||||
- aucune instruction orpheline ;
|
||||
- aucune relation parent/child orpheline ;
|
||||
- conflits listés et classifiés ;
|
||||
- provenance source lisible.
|
||||
|
||||
Gates minimaux anti-régression après replay :
|
||||
|
||||
- surfaces closes Pump/Raydium/Meteora présentes dans le rollup ;
|
||||
- failed transactions sans matérialisation actionable ;
|
||||
- non-swap sans trade ;
|
||||
- résidus decoded-without-target explicitement classés ;
|
||||
- sentinelle PumpSwap/PumpFees pour les transactions cross-surface.
|
||||
|
||||
## Workflow futur
|
||||
|
||||
Pour chaque nouveau DEX ou surface :
|
||||
|
||||
1. créer une base vide dédiée ;
|
||||
2. backfiller les signatures/pools nécessaires ;
|
||||
3. développer decoder/materializer sur cette base ;
|
||||
4. clore avec les SQL propres du DEX ;
|
||||
5. fusionner dans `final.next.db` ;
|
||||
6. rejouer `final.next.db` avec `forceDexDecode=yes` ;
|
||||
7. lancer les validations globales ;
|
||||
8. promouvoir seulement si les gates sont propres.
|
||||
|
||||
## Surfaces à vérifier en non-régression
|
||||
|
||||
Minimum actif pour `0.7.58` :
|
||||
|
||||
```text
|
||||
pump_swap
|
||||
pump_fun
|
||||
pump_fees
|
||||
raydium_cpmm
|
||||
raydium_clmm
|
||||
raydium_amm_v4
|
||||
raydium_stable_swap
|
||||
raydium_launchpad
|
||||
meteora_dbc
|
||||
meteora_dlmm
|
||||
```
|
||||
|
||||
Règle decoder associée : un payload tronqué ou incompatible sur une surface secondaire ne doit pas aborter la transaction entière si l’entrée peut être ignorée proprement. Préférer `Ok(None)` + observation/debug contrôlé pour les payloads tronqués connus ; conserver `Err` pour corruption critique ou incohérence interne.
|
||||
|
||||
## Clôture attendue
|
||||
|
||||
La tranche peut être clôturée seulement après :
|
||||
|
||||
```text
|
||||
cargo test -p kb_lib
|
||||
cargo test -p kb_tools
|
||||
cargo clippy -p kb_lib -- -D warnings
|
||||
cargo clippy -p kb_tools -- -D warnings
|
||||
```
|
||||
|
||||
Puis :
|
||||
|
||||
- dry-run merge lisible ;
|
||||
- merge réel multi-source OK ;
|
||||
- pas de duplicate signatures ;
|
||||
- pas d’instructions orphelines ;
|
||||
- conflits journalisés ;
|
||||
- replay local de `final.next.db` OK ;
|
||||
- validation anti-régression Pump/Raydium/Meteora exécutée et documentée.
|
||||
Reference in New Issue
Block a user