<!-- file: docs/prompts/PROMPT_0_7_57_METEORA_DLMM_FULL_DECODE_MATERIALIZATION.md -->

# Prompt de reprise — khadhroony-bobobot `0.7.57` — `meteora_dlmm` full decode / full materialization

Tu reprends le workspace Rust/Tauri `khadhroony-bobobot` après clôture de `0.7.56 meteora_dbc`.

## 1. Archive et fichiers à fournir

Utiliser l'archive la plus récente après application des docs `0.7.56 final`.

Fichiers à lire en priorité :

- `README.md` ;
- `ROADMAP.md` ;
- `CHANGELOG.md` ;
- `docs/DEX_DECODER_MATRIX.md` ;
- `docs/DEX_EVENT_COVERAGE_MATRIX.md` ;
- `docs/reports/METEORA_DBC_EVENT_COVERAGE_REPORT.md` ;
- `docs/reports/FEE_EVENT_AMOUNTS_MODEL_NOTE_0_7_56.md` ;
- `docs/VALIDATION_STATUS_0_7_56_FINAL.md` ;
- `validation_sql/SQL_VALIDATION_METEORA_DBC_0_7_56.sql` ;
- `validation_sql/SQL_VALIDATION_METEORA_DLMM_0_7_57.sql` ;
- `idls/**`, en particulier `idls/meteora_dlmm.LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo.json` ;
- `kb_lib/src/dex/meteora_dlmm.rs` ;
- `kb_lib/src/non_trade_event_materialization.rs` ;
- `kb_lib/src/db/queries/fee_event_amount.rs`.

Ne pas supposer que l'ancien support `0.7.45 meteora_dlmm` est suffisant : il était partiel. `0.7.57` doit viser la parité IDL/corpus complète.

## 2. État validé avant cette version

`0.7.56 meteora_dbc` est clos.

Build final :

```text
cargo test -p kb_lib -> 446 passed / 0 failed
cargo clippy -p kb_lib --all-targets -- -D warnings -> OK
```

Replay final DBC :

```text
480 replayed
0 decode skipped
480 ledger upserts
454 unsafe ledger rows
264 trades
1 liquidity
122 lifecycle
1056 candle upserts
instructionObservations = 7167
catalog = 86 tokens / 60 pools / 60 pairs
```

Socle fee final :

```text
k_sol_fee_events meteora_dbc        = 89 parents
k_sol_fee_event_amounts meteora_dbc = 96 legs
parent scalar without leg           = empty
orphan fee amount legs              = empty
```

Règles fee à préserver :

- parent fee scalaire -> leg `k_sol_fee_event_amounts` automatique ;
- fee multi-leg/multi-mint -> parent sans agrégation artificielle, legs explicites ;
- pas de montant depuis `maxAmount`, `u64::MAX`, bornes ou limites de claim ;
- recovery CPI SPL générique uniquement si policy/allowlist explicite ;
- aucun futur decoder ne doit hériter de `allowlisted_inner_spl_transfer` par défaut.

## 3. Objectif de `0.7.57 meteora_dlmm`

Program id cible :

```text
LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo
```

IDL locale prioritaire :

```text
idls/meteora_dlmm.LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo.json
```

Nom IDL : `lb_clmm`.

Surface IDL :

```text
76 instructions
30 events Anchor
12 accounts
```

Objectif : **full decode + full materialization**.

Règle forte :

> Tout ce qui peut être décodé doit être décodé. Tout ce qui peut être matérialisé de façon fiable doit être matérialisé. Ce qui ne peut pas être matérialisé doit rester decoded-only/audit-only avec `skip*Reason` explicite. les instructions/events/anchors/discriminator non observés aprés backfill sur une base de donnée vierge devront avoir des tests syntetiques.

## 4. Méthode obligatoire

Créer une nouvelle DB dédiée à `0.7.57 meteora_dlmm`.

Après chaque backfill ou patch decoder :

```text
skipDexDecode=no
forceDexDecode=yes
deferInstructionObservations=yes
```

Puis : refresh catalog, replay local, SQL validation, note des compteurs.

Ne pas rouvrir `meteora_dbc`, Pump ou Raydium sauf bug prouvé par SQL.

## 5. Sources à comparer

Comparer au minimum :

- IDL locale `idls/meteora_dlmm.LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo.json` ;
- Carbon Meteora DLMM decoder ;
- Pinax/Substreams Solana IDLs ;
- Solana Streamer / sol-parser-sdk si DLMM y apparaît ;
- code local historique `kb_lib/src/dex/meteora_dlmm.rs` ;
- coverage existante `k_sol_dex_event_coverage_entries` ;
- corpus SQLite neuf ;
- anciens rapports `0.7.45` et matrices pour comprendre ce qui était déjà validé.

## 6. Checklist d'instructions IDL à inventorier

| Instruction | Discriminator hex |
|---|---|
| `add_liquidity` | `b59d59438fb63448` |
| `add_liquidity2` | `e4a24e1c46db7473` |
| `add_liquidity_by_strategy` | `0703967f94283dc8` |
| `add_liquidity_by_strategy2` | `03dd95da6f8d76d5` |
| `add_liquidity_by_strategy_one_side` | `2905eeaf64e106cd` |
| `add_liquidity_by_weight` | `1c8cee63e7a21595` |
| `add_liquidity_by_weight2` | `d13b3f5b6fc899e4` |
| `add_liquidity_one_side` | `5e9b6797465fdca5` |
| `add_liquidity_one_side_precise` | `a1c26754ab47fa9a` |
| `add_liquidity_one_side_precise2` | `2133a3c975627de7` |
| `cancel_limit_order` | `849c841f4328e861` |
| `claim_fee` | `a9204f8988e84689` |
| `claim_fee2` | `70bf65ab1c907fbb` |
| `claim_reward` | `955fb5f25e5a9ea2` |
| `claim_reward2` | `be037f77b2579db7` |
| `close_bin_array` | `44ae5850b5cc13e0` |
| `close_claim_fee_operator_account` | `b8d5581fb3658224` |
| `close_limit_order_if_empty` | `397c249b7ef95dab` |
| `close_operator_account` | `ab09d54a7817031d` |
| `close_position` | `7b86510031446262` |
| `close_position2` | `ae5a2373ba2893e2` |
| `close_position_if_empty` | `3b7cd4765b986e9d` |
| `close_preset_parameter` | `04949164861ab53d` |
| `close_preset_parameter2` | `27195f6b7411731c` |
| `close_token_badge` | `6c92566eb3fe0a68` |
| `create_operator_account` | `dd40f695f099e5a3` |
| `decrease_position_length` | `c2db882019606925` |
| `for_idl_type_generation_do_not_call` | `b46945505f32496c` |
| `fund_reward` | `bc32f9a55d97263f` |
| `go_to_a_bin` | `9248aee028fd54ae` |
| `increase_oracle_length` | `be3d7d57674f9ead` |
| `increase_position_length` | `505375d3420d2195` |
| `increase_position_length2` | `ffd2cc477389e171` |
| `initialize_bin_array` | `235613b94ed44bd3` |
| `initialize_bin_array_bitmap_extension` | `2f9de2b40cf02147` |
| `initialize_customizable_permissionless_lb_pair` | `2e2729876fb7c840` |
| `initialize_customizable_permissionless_lb_pair2` | `f349817e3313f16b` |
| `initialize_lb_pair` | `2d9aedd2dd0fa65c` |
| `initialize_lb_pair2` | `493b2478ed536cc6` |
| `initialize_permission_lb_pair` | `6c66d555fb033515` |
| `initialize_position` | `dbc0ea47bebf6650` |
| `initialize_position2` | `8f13f291d50f6873` |
| `initialize_position_by_operator` | `fbbdbef475fe2394` |
| `initialize_position_pda` | `2e527d92558de499` |
| `initialize_preset_parameter` | `42bc47d3626d0eba` |
| `initialize_reward` | `5f87c0c4f281e644` |
| `initialize_token_badge` | `fd4dcd5f1be059df` |
| `place_limit_order` | `6cb021ba92e501c5` |
| `rebalance_liquidity` | `5c04b0c177b95309` |
| `remove_all_liquidity` | `0a333d2370691855` |
| `remove_liquidity` | `5055d14818ceb16c` |
| `remove_liquidity2` | `e6d7527ff165e392` |
| `remove_liquidity_by_range` | `1a526698f04a691a` |
| `remove_liquidity_by_range2` | `cc02c391359191cd` |
| `set_activation_point` | `5bf90fa51a81fe7d` |
| `set_pair_status` | `43f8e7899a95d9ae` |
| `set_pair_status_permissionless` | `4e3b98d346b72ed0` |
| `set_permissionless_operation_bits` | `543acb8ba351beba` |
| `set_pre_activation_duration` | `a53dc9f4829f1664` |
| `set_pre_activation_swap_address` | `398b2f7bd850df0a` |
| `swap` | `f8c69e91e17587c8` |
| `swap2` | `414b3f4ceb5b5b88` |
| `swap_exact_out` | `fa49652126cf4bb8` |
| `swap_exact_out2` | `2bd7f784893cf351` |
| `swap_with_price_impact` | `38ade6d0ade49ccd` |
| `swap_with_price_impact2` | `4a62c0d6b1334b33` |
| `update_base_fee_parameters` | `4ba8dfa110c3032f` |
| `update_dynamic_fee_parameters` | `5ca12ef6ffbd1616` |
| `update_fees_and_reward2` | `208eb89a6741b858` |
| `update_fees_and_rewards` | `9ae6fa0decd14bdf` |
| `update_position_operator` | `cab8678fb4bf74d9` |
| `update_reward_duration` | `8aaec4a9d5ebfe6b` |
| `update_reward_funder` | `d31c3020d7a02317` |
| `withdraw_ineligible_reward` | `94ce2ac3f7316708` |
| `withdraw_protocol_fee` | `9ec99ebd215da267` |
| `zap_protocol_fee` | `d59bbb2238b65bf0` |

## 7. Checklist d'events Anchor IDL à inventorier

| Event | Discriminator hex |
|---|---|
| `AddLiquidity` | `1f5e7d5ae3343dba` |
| `CancelLimitOrderEvt` | `83eac285090ebdd1` |
| `ClaimFee` | `4b7a9a308c4a7ba3` |
| `ClaimFee2` | `e8abf2613a4d232d` |
| `ClaimReward` | `947486cc16ab555f` |
| `ClaimReward2` | `1b8ff421502b6e92` |
| `CloseLimitOrderEvt` | `8e87084c5c3f7653` |
| `CompositionFee` | `80977b6a1166718e` |
| `DecreasePositionLength` | `3476eb55aca90f80` |
| `DynamicFeeParameterUpdate` | `5858b287c2925bf3` |
| `FeeParameterUpdate` | `304cf17590d7f22c` |
| `FundReward` | `f6e43a8291aa4fcc` |
| `GoToABin` | `3b8a4c448a83b043` |
| `IncreaseObservation` | `63f91179a69ccfd7` |
| `IncreasePositionLength` | `9def2acc1e38df2e` |
| `InitializeReward` | `d399583e953cb146` |
| `LbPairCreate` | `b94afc7d1bd7bc6f` |
| `PlaceLimitOrderEvt` | `2b4f1ba9f41ce13f` |
| `PositionClose` | `ffc4106b1cca3580` |
| `PositionCreate` | `908efc549d352579` |
| `Rebalancing` | `006d75b33d5bc7c8` |
| `RemoveLiquidity` | `74f461e8671f983a` |
| `SetPositionPermissionlessOperationBitsEvt` | `c3e593f51d7d30a8` |
| `Swap` | `516ce3becdd00ac4` |
| `Swap2Evt` | `2e7452d7941b544d` |
| `UpdatePositionLockReleasePoint` | `85d642e0400c07bf` |
| `UpdatePositionOperator` | `277330ccf62f4239` |
| `UpdateRewardDuration` | `dff5e099311da3ac` |
| `UpdateRewardFunder` | `e0b2ae4afca555b4` |
| `WithdrawIneligibleReward` | `e7bd419566d79af4` |

## 8. Matérialisation attendue

### Swaps

Cibles :

```text
swap
swap2
swap_exact_out
swap_exact_out2
swap_with_price_impact
swap_with_price_impact2
Swap
Swap2Evt
```

Décision :

- `k_sol_trade_events` + candles uniquement si montants exécutés, sens, pool, token X/Y et mints sont fiables ;
- les events Anchor swap ne doivent pas double-compter une instruction swap déjà matérialisée ;
- exact-out et price-impact ne doivent pas utiliser des bornes comme montants exécutés ;
- si le contexte n'est pas fiable : `skipTradeReason` + `skipCandleReason`.

### Liquidity / bins / positions

Cibles :

```text
add_liquidity*
remove_liquidity*
remove_all_liquidity
rebalance_liquidity
initialize_position*
close_position*
position create/close/update events
initialize_bin_array*
close_bin_array
```

Décision :

- `k_sol_liquidity_events` quand les montants token X/Y, pool, position et acteur sont fiables ;
- lifecycle pour création/fermeture position/bin/pair ;
- skip reason explicite pour position/bin sans montants exploitables.

### Pools / catalog

Cibles :

```text
initialize_lb_pair
initialize_lb_pair2
initialize_permission_lb_pair
initialize_customizable_permissionless_lb_pair
initialize_customizable_permissionless_lb_pair2
LbPairCreate
```

Décision : lifecycle/catalog/pool/pair si mints X/Y, pool, config/preset et comptes vault sont fiables.

### Fees

Cibles :

```text
claim_fee
claim_fee2
withdraw_protocol_fee
zap_protocol_fee
ClaimFee
ClaimFee2
CompositionFee
```

Décision :

- `k_sol_fee_events` + `k_sol_fee_event_amounts` obligatoires si montant/mint fiable ;
- utiliser parent scalaire + leg automatique pour mono-fee ;
- utiliser multi-leg sans agrégation parent si plusieurs mints/composants ;
- ne pas confondre composition fee inclus dans swap/liquidity avec claim fee matérialisable ;
- déclarer explicitement toute policy de recovery ; ne pas ajouter DLMM à l'allowlist générique sans preuve et tests.

### Rewards

Cibles :

```text
initialize_reward
fund_reward
claim_reward
claim_reward2
withdraw_ineligible_reward
ClaimReward
ClaimReward2
FundReward
InitializeReward
WithdrawIneligibleReward
```

Décision : `k_sol_reward_events` si montant/mint/reward index fiables ; decoded-only sinon.

### Admin/config/status/operator/token badge

Cibles :

```text
update_base_fee_parameters
update_dynamic_fee_parameters
update_fees_and_rewards
update_fees_and_reward2
set_pair_status
set_pair_status_permissionless
set_activation_point
set_pre_activation_duration
set_pre_activation_swap_address
set_permissionless_operation_bits
create_operator_account
close_operator_account
close_claim_fee_operator_account
initialize_token_badge
close_token_badge
initialize_preset_parameter
close_preset_parameter
close_preset_parameter2
```

Décision : `k_sol_pool_admin_events` si acteur/cible fiables ; decoded-only avec raison sinon.

### Limit orders / orderbook-like events

Cibles :

```text
place_limit_order
cancel_limit_order
close_limit_order_if_empty
PlaceLimitOrderEvt
CancelLimitOrderEvt
CloseLimitOrderEvt
```

Décision : `k_sol_orderbook_events` si sémantique fiable ; pas de trade/candle sans fill exact.

## 9. SQL de validation attendu

Créer/mettre à jour :

```text
validation_sql/SQL_VALIDATION_METEORA_DLMM_0_7_57.sql
```

Le fichier doit vérifier au minimum :

1. fallback upstream DLMM ;
2. instruction observations DLMM ;
3. coverage DLMM ;
4. decoded DLMM sans coverage ;
5. successful non-materialized sans skip reason ;
6. failed tx materialization ;
7. multi-target materialization ;
8. trade/candle sur non-swap ;
9. fee parent/legs ;
10. orphan fee legs ;
11. reward/fee separation ;
12. orderbook/limit-order sans double-count ;
13. watchlist globale.

## 10. Invariants de fermeture

`0.7.57 meteora_dlmm` ne peut être clôturé que si :

- les `76` instructions et `30` events Anchor IDL sont dans la coverage ou explicitement non observés avec tests synthétiques ;
- aucun fallback upstream DLMM ne reste pour les entrées couvertes localement ;
- aucun decoded DLMM local sans coverage ;
- aucune tx failed n'alimente une table métier ;
- aucun event multi-target incohérent ;
- aucune ligne successful non-materialized sans `skip*Reason` ou policy explicite ;
- aucun non-swap ne produit trade/candle ;
- aucun fee parent scalaire sans leg ;
- aucun leg fee orphelin ;
- aucun reward n'est classé fee par défaut ;
- aucun limit/order event ne produit une candle sans fill exact ;
- la watchlist globale ne contient plus de backlog dominant `meteora_dlmm`.

## 11. Contraintes de code à respecter

- Rust 2024 ;
- async-first ;
- tracing obligatoire ;
- pas de `?`, pas de `unwrap/expect` en production ;
- pas de `anyhow` / `thiserror` ;
- pas de `mod.rs` ;
- pas de `pub mod` : utiliser `mod` + `pub use` ;
- imports seulement pour les traits ;
- `#![deny(unreachable_pub)]`, `#![warn(missing_docs)]` ;
- tests offline ;
- pas de macro DB/coverage ;
- après modification DB : re-exports `kb_lib/src/db.rs` et `kb_lib/src/lib.rs` ;
- après modification decoder : vérifier `kb_lib/src/dex.rs`, `kb_lib/src/lib.rs`, coverage et tests synthétiques.

## 12. Format de livraison attendu

Livrer des deltas successifs :

```text
khadhroony-bobobot-v0.7.57-meteora_dlmm-delta-pre.xxx.zip
```

Chaque réponse doit indiquer : fichiers modifiés, raisons, tests à lancer, SQL à exécuter, résultat attendu, et risques éventuels.
