<!-- file: docs/DB_EVENT_MODEL_REVIEW.md -->

# Database Event Model Review — `khadhroony-bobobot` `0.7.47-1FE5`


## Note `0.7.56` — modèle fee parent + amount legs

`0.7.56` ajoute `k_sol_fee_event_amounts` comme table enfant de `k_sol_fee_events`. Cette table est obligatoire dès qu'un event fee porte plusieurs montants, plusieurs mints ou plusieurs destinations. Le parent `k_sol_fee_events` reste l'ancre logique liée au `decoded_event_id`; les legs portent `leg_index`, `token_mint`, `amount_raw`, comptes source/destination et `amount_source`.

Invariants :

- tout parent fee avec `fee_token_mint + fee_amount_raw` doit avoir un leg scalaire automatique ;
- un fee multi-leg/multi-mint ne doit pas agréger artificiellement le parent ;
- les replays doivent supprimer/remplacer les legs avec le parent ;
- les transactions failed restent audit-only ;
- la recovery `allowlisted_inner_spl_transfer` est strictement allowlistée et ne s'applique pas par défaut aux futurs decoders.

Le contrôle standard `parent scalar without leg` doit être vide sur toute base de validation. Voir `docs/reports/FEE_EVENT_AMOUNTS_MODEL_NOTE_0_7_56.md`.

## Conclusion courte

La base actuelle est **suffisante pour continuer le décodage exhaustif en audit-only**, parce que `k_sol_dex_decoded_events` garde les events décodés avec `payload_json`.

La base actuelle est **partiellement insuffisante pour exploiter tous les events en requêtes métier**, parce que certaines familles importantes n’ont pas encore de tables dédiées ou de modèle normalisé :

- transfers SPL / Token-2022 ;
- token account create/close ;
- wrap/unwrap SOL ;
- orderbook orders/fills/settlements ;
- vault deposit/withdraw ;
- launch/migration ;
- lock/unlock LP ;
- staking/unstaking ;
- coverage matrix persistée par discriminator/event.

## Ce qui existe déjà

D’après le README, le modèle contient déjà notamment :

- `k_sol_chain_transactions`;
- `k_sol_chain_instructions`;
- `k_sol_dex_decoded_events`;
- `k_sol_trade_events`;
- `k_sol_liquidity_events`;
- `k_sol_pool_lifecycle_events`;
- `k_sol_fee_events`;
- `k_sol_reward_events`;
- `k_sol_pool_admin_events`;
- `k_sol_token_mint_events`;
- `k_sol_token_burn_events`;
- `k_sol_transaction_classifications`;
- `k_sol_protocol_candidates`;
- `k_sol_dex_decode_replay_ledger`.

Ces tables couvrent déjà les besoins principaux :

| Besoin | Couverture actuelle |
|---|---|
| Stockage brut/audit de tout event décodé | Oui, via `k_sol_dex_decoded_events.payload_json`. |
| Trades/candles | Oui. |
| Liquidity/lifecycle/fee/reward/admin | Oui, au moins structurellement. |
| Mint/burn | Oui, structurellement. |
| Replay/skip sûr | Oui, via ledger. |
| Event coverage attendu vs observé | Non ou seulement implicite. |
| Transfers/token account lifecycle | Non spécialisé. |
| Orderbook events | Non spécialisé. |
| Vault events | Non spécialisé. |
| Launch/migration | Non spécialisé ou dispersé. |

## Ne pas modifier la DB trop vite

Il ne faut pas créer une table pour chaque DEX ou chaque event upstream.

La bonne stratégie :

1. Décoder tout ce qu’on peut en `k_sol_dex_decoded_events`.
2. Ajouter `eventFamily`, `eventSemanticKind`, `eventActionability`, `proofStatus`, `sourceRepo`, `sourcePath`.
3. Matérialiser seulement les familles prouvées et utiles.
4. Ajouter des tables transversales uniquement quand plusieurs DEX en ont besoin.

## Ajouts DB recommandés

### 1. `k_sol_dex_event_coverage_entries`

But : stocker ce qui est **attendu/listé** depuis les sources upstream, même si non observé.

Colonnes conceptuelles :

```text
id
decoder_code
program_id
program_family
surface_kind
source_repo
source_path
entry_kind               -- instruction/event/account/log/program_data
entry_name
discriminator_hex
discriminator_len
event_family             -- swap/burn/mint/admin/etc.
expected_db_target
proof_status
local_event_kind
observed_count
materialized_count
trade_count
first_signature
last_signature
notes
created_at
updated_at
```

Rôle : rendre la couverture objectivable. Exemple : “Carbon liste 42 instructions Raydium CPMM, notre code en décode 18, 4 sont matérialisées”.

### 2. `k_sol_token_transfer_events`

But : matérialiser les transfers significatifs hors trade.

Colonnes conceptuelles :

```text
id
transaction_id
instruction_id
decoded_event_id
signature
slot
program_id
token_program_id
mint
source_token_account
destination_token_account
source_owner
destination_owner
amount_raw
amount_ui
transfer_kind            -- transfer, transfer_checked, routed_transfer, vault_transfer
reason                   -- audit_only, vault_movement, migration, settlement, unknown
payload_json
```

Important : ne pas créer de trade depuis cette table. Elle sert au risque/analyse.

### 3. `k_sol_token_account_events`

But : suivre create/close/init ATA/token accounts.

```text
id
transaction_id
instruction_id
decoded_event_id
signature
slot
event_kind               -- create_ata, init_account, close_account, wrap_sol, unwrap_sol
account_address
mint
owner
token_program_id
lamports_delta
payload_json
```

Cela aide à comprendre WSOL wrap/unwrap, close accounts, cleanup bots, préparation de trades.

### 4. `k_sol_orderbook_events`

But : stocker OpenBook/Phoenix et autres CLOB sans les confondre avec swaps AMM.

```text
id
transaction_id
instruction_id
decoded_event_id
signature
slot
protocol_name
market_account
event_kind               -- order_place, order_cancel, order_fill, settle_funds, consume_events, open_orders_create, open_orders_close
side
price_lots
base_lots
quote_lots
maker
taker
client_order_id
raw_event_name
interpretation_status
payload_json
```

Les fills ne deviennent `trade_events` que quand maker/taker, base/quote, lots/decimals et sens économique sont validés.

### 5. `k_sol_vault_events`

But : suivre vault deposit/withdraw, Meteora Vault, Kamino/Vault-like programs.

```text
id
transaction_id
instruction_id
decoded_event_id
signature
slot
protocol_name
vault_account
event_kind               -- deposit, withdraw, claim, rebalance, update_config
mint_a
mint_b
amount_a_raw
amount_b_raw
owner
payload_json
```

### 6. `k_sol_launch_events`

But : séparer launch/bonding/migration du DEX effectif.

```text
id
transaction_id
instruction_id
decoded_event_id
signature
slot
launch_protocol
event_kind               -- create, buy, sell, migrate, graduate, initialize_curve, close_curve
token_mint
curve_account
migration_target_program
migration_pool
quote_mint
amount_token_raw
amount_quote_raw
payload_json
```

### 7. `k_sol_liquidity_lock_events`

But : traiter LP lock/unlock explicitement.

```text
id
transaction_id
instruction_id
decoded_event_id
signature
slot
protocol_name
pool_id
pair_id
lock_account
owner
event_kind               -- create_lock, lock, unlock, extend_lock, close_lock
lp_mint
lp_amount_raw
unlock_time
payload_json
```

## Alternative minimaliste

Si on veut éviter trop de migrations immédiates, le minimum à ajouter d’abord est :

1. `k_sol_dex_event_coverage_entries`;
2. `k_sol_token_transfer_events`;
3. `k_sol_orderbook_events`.

Les autres tables peuvent attendre.

## Impact sur le plan des versions

Chaque version DEX doit répondre à deux questions :

### Couverture decoder

- A-t-on listé tous les events upstream ?
- A-t-on un decoder audit pour chaque discriminator connu ?
- Les events non observés sont-ils marqués `upstream_git_mapped_unverified` ?

### Couverture DB

- L’event peut-il rester dans `k_sol_dex_decoded_events` ?
- Doit-il être matérialisé dans une table existante ?
- Faut-il une table transversale nouvelle ?
- Une table nouvelle peut-elle servir à plusieurs DEX ?

## Décision pratique pour `0.7.48`

Avant de reprendre `raydium_cpmm`, faire une micro-tranche DB/doc :

```text
0.7.48-pre — event coverage + DB model checkpoint
```

Objectif :

- ajouter ou documenter `k_sol_dex_event_coverage_entries`;
- ne pas encore ajouter toutes les tables métier ;
- produire un rapport par DEX :
  - listed events,
  - decoded events,
  - materialized events,
  - missing DB target,
  - trade_count invariant.

## Note `0.7.48` — Raydium CPMM sans nouvelle table DB

La tranche `0.7.48` confirme que `k_sol_dex_decoded_events` suffit pour continuer la couverture exhaustive CPMM en audit-only.

Aucune nouvelle table n'est ajoutée pour CPMM :

- les swaps exploitables restent dans `k_sol_trade_events` via les chemins existants ;
- `deposit` / `withdraw` utilisent les tables non-trade existantes seulement si le corpus et le rattachement pool/pair sont fiables ;
- les fees/admin/config/permission restent non-trade et ne peuvent pas produire candles ;
- les transfers SPL, account lifecycle, wrap/unwrap SOL, vault et launch/migration restent des familles transversales futures, à promouvoir seulement si plusieurs DEX en justifient le besoin.

## Note 0.7.48 final — Instruction observations et CPMM

La tranche `raydium_cpmm` ajoute `k_sol_instruction_observations` comme table technique d’index local, non comme table métier. Elle sert à chercher les instructions observées par `decoder_code`, `instruction_name` et `discriminator_hex`, puis à relier ces observations au corpus backfillé/rejoué.

La matérialisation métier reste limitée aux tables existantes : `k_sol_trade_events`, `k_sol_liquidity_events`, `k_sol_pool_lifecycle_events`, `k_sol_fee_events` et `k_sol_pool_admin_events`. Les opérations SPL Token / Token-2022 visibles dans Solscan (`burn`, `transfer`, `transferChecked`, `closeAccount`) ne sont pas promues en tables métier dans `0.7.48`; elles justifient seulement une future table transversale si plusieurs DEX le nécessitent.

## Note 0.7.49 — Raydium CLMM sans nouvelle table transversale immédiate

La reprise `raydium_clmm` confirme que la table `k_sol_dex_event_coverage_entries` suffit pour inventorier les instructions/events CLMM avant promotion métier. Les entrées IDL-only ajoutées en `0.7.49` restent des lignes de coverage et de recherche, pas des tables métier.

Aucune nouvelle table transversale n'est ajoutée dans ce delta :

- les swaps spécialisés restent dans `k_sol_trade_events` seulement lorsque les montants et le sens économique sont validés ;
- les liquidity/positions CLMM restent à distinguer : une position NFT/tick n'est pas forcément une liquidity row simple ;
- les fees et rewards peuvent utiliser `k_sol_fee_events` / `k_sol_reward_events` seulement après preuve de corpus et typage fin ;
- les side effects SPL Token / Token-2022 (`mint`, `burn`, `transfer`, `closeAccount`, wrap/unwrap SOL) restent indirects tant qu'une preuve multi-DEX ne justifie pas une table transversale.

La table `k_sol_instruction_observations` reste technique : elle sert à trouver des signatures et discriminants observés localement, sans être une preuve métier.


## Note `0.7.50-pre-r2` — `k_sol_token_account_events`

La re-vérification Raydium CLMM introduit une table dédiée `k_sol_token_account_events` pour les événements de cycle de vie de comptes token qui ne sont ni des swaps, ni de la liquidité, ni du lifecycle pool. Le premier cas d'usage est `raydium_clmm.create_support_mint_associated`.

### Règle de matérialisation

- `create_support_mint_associated` cible `k_sol_token_account_events`.
- `cpi_event` reste `k_sol_dex_decoded_events_only` : c'est un transport Anchor/CPI, pas un event métier autonome.
- `liquidity_calculate_event` reste `k_sol_dex_decoded_events_only` : c'est un event de calcul/diagnostic, pas une mutation de liquidité fiable.
- `create_operation_account` et `update_operation_account` relèvent de `k_sol_pool_admin_events` quand le corpus le permet.

### Colonnes principales

`k_sol_token_account_events` conserve `transaction_id`, `decoded_event_id`, `dex_id`, `pool_id`, `pair_id`, `signature`, `instruction_index`, `slot`, `protocol_name`, `program_id`, `event_kind`, `token_account`, `token_mint`, `owner_wallet`, `account_action`, `payload_json`, `executed_at` et `created_at`.

Cette table permet de suivre les événements Token-2022/ATA significatifs sans les confondre avec les trades ou les liquidités.

## Note `0.7.51` — impact AMM v4 sur le modèle DB

Aucune nouvelle table n'est ajoutée pour `raydium_amm_v4`.

Décisions DB maintenues :

- `k_sol_instruction_observations` reste une table technique d'indexation instruction/discriminant ;
- AMM v4 utilise des discriminants d'un octet, donc l'index technique doit conserver `09`, `0b`, `10`, `11`, etc. sans les convertir en discriminants Anchor huit octets ;
- le refresh de `k_sol_instruction_observations` reconstruit les observations par transaction avant upsert, afin de supprimer les restes historiques en huit octets après changement de stratégie d'indexation ;
- les side effects SPL Token / Token-2022 restent transversaux et ne doivent pas être promus comme events directs `raydium_amm_v4.*` ;
- les side effects Serum/OpenBook de AMM v4 doivent être documentés comme contexte orderbook, pas comme trades OpenBook autonomes ;
- `raydium_pool_v4` ne justifie aucune table ni aucun decoder séparé sans corpus local.

Le modèle actuel suffit pour ouvrir la tranche : decoded events + coverage entries + instruction observations + matérialisations existantes trade/liquidity/lifecycle/fee/admin/orderbook. Une extension future orderbook/vault/token-account ne doit être ajoutée qu'après preuves multi-DEX.



### Clôture `0.7.51` — AMM v4 et modèle DB

La validation finale AMM v4 confirme qu'aucune nouvelle table n'est requise pour `raydium_amm_v4`.

Règles validées :

- chaque decoded event AMM v4 matérialisé cible au plus une table métier principale ;
- `migrate_to_open_book`, `monitor_step` et `admin_cancel_orders` alimentent `k_sol_orderbook_events` uniquement ;
- `pre_initialize` alimente `k_sol_pool_lifecycle_events` comme audit deprecated/partial, sans création de paire exploitable ;
- `simulate_info` reste dans `k_sol_dex_decoded_events` uniquement ;
- les `deposit` / `withdraw` sans pool/pair catalogue ou sans deltas exploitables restent decoded-only expliqués ;
- les side effects SPL Token / Token-2022 restent transversaux.

Contrôle final AMM v4 : le SQL `materialized_target_count > 1` doit rester vide.

## 0.7.52 — Raydium Stable Swap DB model decision

No schema migration is introduced for `raydium_stable_swap` at tranche opening.

Stable Swap maps to existing DB targets:

- `initialize` / `pre_initialize` → `k_sol_pool_lifecycle_events` when pool context is sufficient;
- `deposit` / `withdraw` → `k_sol_liquidity_events` when pool/pair context is sufficient;
- `swap_base_in` / `swap_base_out` → `k_sol_trade_events` and candles only when mints and amounts are reliable;
- `swap_event` → `k_sol_dex_decoded_events` only until a corpus-backed materialization decision exists.

Side effects from SPL Token, Token-2022, Serum/OpenBook-style accounts or router transport remain transverse evidence and are not promoted as direct `raydium_stable_swap.*` business events without an explicit later DB decision.
