v0.1.0-pre.061

This commit is contained in:
2026-07-28 18:41:30 +02:00
parent c7bad46f50
commit f40fb78817
527 changed files with 4598 additions and 4114 deletions

View File

@@ -1,25 +0,0 @@
<!-- file: docs/ACCOUNT_ONLY_CANDIDATES.md -->
<!-- version: 1 -->
# Candidats qui ne sont pas encore des program_id
Certains identifiants vus dans les explorateurs peuvent être des comptes de configuration, de pool, d'autorité, de registre, de vault ou de PDA. Ils ne doivent pas devenir des crates de décodeur tant que leur owner executable n'est pas prouvé.
## Bags
| Identifiant | Source supposée | Statut | Décision |
|------------------------------------------------|-----------------|-----------------------|-----------------------------------------------------------------------------------------------------------|
| `BAGSB9TpGrZxQbEsrEznv5jXXdwyP6AXerN8aVRiAmcv` | Bags | `account_not_program` | Ne pas créer `kb_decoder_bags` comme surface canonique tant que le vrai `program_id` n'est pas identifié. |
## Règle
Avant de créer une crate de décodeur :
1. vérifier que l'adresse est bien un programme exécutable ;
2. vérifier l'owner et les transactions qui l'invoquent ;
3. rattacher les comptes non exécutables à leur `program_id` propriétaire ;
4. documenter les comptes importants dans une matrice séparée du registre des programmes.
## Bags Fee Share
Les programmes Fee Share V1/V2 sont maintenant documentés dans `docs/BAGS_FM.md`. Le compte `BAGSB9TpGrZxQbEsrEznv5jXXdwyP6AXerN8aVRiAmcv` reste un compte observé, pas une surface exécutable canonique.

View File

@@ -1,210 +0,0 @@
<!-- file: docs/AGAVE_LOCAL_NODE.md -->
<!-- version: 3 -->
# Nœud Agave local expérimental
Ce document cadre le jalon `0.3.x`. L'objectif est de mesurer si un nœud Agave local non votant peut devenir une source temps réel utile avant de construire l'ingestion, le backfill et l'extracteur raw vers core en `0.4.x`.
## Positionnement
`khadhroony-bot2` ne doit pas embarquer un validateur. Le validateur reste un process externe démarré manuellement ou par script de développement.
```text
agave-validator local non votant
-> HTTP RPC local
-> WebSocket RPC local
-> demo_ws ou future démo Agave
-> mesures de capacité et de retard
-> décision pour l'ingestion 0.4.x
```
Le jalon `0.3.x` est une phase de recherche. Il ne doit pas écrire de raw de production, ne doit pas extraire vers core et ne doit pas déclencher d'achat/revente.
## Hypothèse à tester
Un nœud local Agave non votant avec ledger pruné pourrait permettre :
- `blockSubscribe` local avec transactions complètes ;
- moins de `getTransaction` temps réel ;
- moins de listeners par programme ;
- filtrage local par program id, logs, instructions, balances et discriminators ;
- usage des providers externes surtout pour backfill historique, réparation et `sendTransaction`.
Cette hypothèse doit être mesurée. Elle ne doit pas devenir une décision d'architecture sans chiffres locaux.
## Commande de départ
La commande exacte dépend de la version Agave installée, du snapshot disponible, des ports libres et des ressources locales. La commande de départ à documenter et ajuster est :
```bash
agave-validator \
--no-voting \
--full-rpc-api \
--enable-rpc-transaction-history \
--rpc-pubsub-enable-block-subscription \
--limit-ledger-size <N_SHREDS> \
--ledger ./data/agave-ledger \
--accounts ./data/agave-accounts \
--rpc-port 8899 \
--dynamic-port-range 8000-8020
```
`<N_SHREDS>` est une limite de shreds, pas une durée exacte ni un nombre exact de blocks. La fenêtre réellement conservée dépend du débit réseau, de la purge, des snapshots, de la vitesse disque et de l'état local du nœud.
## Préparation locale
Créer les dossiers explicitement pour éviter de mélanger le ledger expérimental avec d'autres données :
```bash
mkdir -p ./data/agave-ledger ./data/agave-accounts ./logs/agave_local_research
```
Avant chaque essai, noter :
```text
version agave-validator
commande exacte
valeur N_SHREDS
heure de lancement
état initial du dossier ledger
état initial du dossier accounts
profil de configuration utilisé
endpoint externe de référence
```
Ne pas supprimer automatiquement `./data/agave-ledger` ou `./data/agave-accounts` dans le projet. Toute purge doit rester une action manuelle et documentée dans le compte rendu d'essai.
## Profil de configuration
`config/example.config.json` contient le profil `agave_local_research`, non actif par défaut.
```text
HTTP local: http://127.0.0.1:8899
WS local: ws://127.0.0.1:8900
```
Pour l'utiliser, changer `active_profile` dans un fichier local non versionné ou lancer l'application avec `KB_CONFIG_PATH` pointant vers une copie locale.
Le profil expose les rôles suivants :
| Rôle | Usage |
|----------------------|-----------------------------------------------------------|
| `local_node_status` | santé, version et retard du nœud local |
| `http_queries` | lectures RPC légères locales |
| `http_heavy` | `getBlock`, `getTransaction`, `getProgramAccounts` locaux |
| `block_stream` | probe `blockSubscribe` local |
| `slot_notifications` | `slotSubscribe`, `slotsUpdatesSubscribe`, `rootSubscribe` |
| `logs_subscribe` | `logsSubscribe` par mention de programme |
| `program_subscribe` | `programSubscribe` par programme |
| `account_subscribe` | `accountSubscribe` par compte précis |
Le fallback externe est volontairement séparé. Il ne doit pas masquer un échec local pendant les mesures.
## Probes minimaux
Les probes `0.3.2` devront couvrir au minimum :
| Famille | Méthode | Résultat attendu |
|---------|-------------------------------------------------|--------------------------------------------------|
| HTTP | `getVersion` | version du nœud ou erreur explicite |
| HTTP | `getHealth` | état du nœud ou erreur explicite |
| HTTP | `getSlot` | slot local |
| HTTP | `getBlockHeight` | block height local |
| HTTP | `getMaxShredInsertSlot` | slot maximal de shred inséré |
| WS | `blockSubscribe` avec `transactionDetails=none` | `supported`, `unsupported`, `timeout` ou `error` |
| WS | `slotSubscribe` | subscription id puis notifications |
| WS | `slotsUpdatesSubscribe` | subscription id puis notifications |
| WS | `rootSubscribe` | subscription id puis notifications |
| WS | `logsSubscribe` `mentions` | subscription id ou refus provider |
| WS | `programSubscribe` | subscription id ou refus provider |
| WS | `accountSubscribe` | subscription id ou refus provider |
Le probe minimal `blockSubscribe` ne doit pas laisser un flux ouvert :
```text
1. ouvrir la WebSocket ;
2. envoyer blockSubscribe avec transactionDetails=none ;
3. attendre un subscription id ou une erreur ;
4. désabonner immédiatement ;
5. classer supported / unsupported / timeout / error ;
6. journaliser la réponse brute tronquée si nécessaire.
```
Paramètres de départ à tester dans `demo_ws` :
```text
role: block_stream
method: blockSubscribe
filterJson: "all"
configJson: {"commitment":"confirmed","encoding":"json","transactionDetails":"none","showRewards":false}
```
Si `"all"` est refusé par la version RPC testée, documenter l'erreur et tester ensuite un filtre plus ciblé par programme dans `0.3.4`.
## Mesures à collecter
| Mesure | Commande ou source indicative | Rôle |
|-----------------------------|----------------------------------------------|-----------------------------------|
| taille ledger | `du -sh ./data/agave-ledger` | calibrer `--limit-ledger-size` |
| taille accounts | `du -sh ./data/agave-accounts` | vérifier le coût disque |
| CPU | `pidstat`, `top`, `htop` | mesurer le coût du nœud local |
| RAM | `pidstat`, `free`, `ps` | vérifier la faisabilité locale |
| réseau RX/TX | `nload`, `iftop`, `/proc/net/dev` | mesurer le coût mainnet |
| slot local | `getSlot` local | vérifier l'avancement |
| slot externe | `getSlot` provider de référence | calculer le retard |
| lag slots | slot externe moins slot local | détecter un décrochage |
| lag secondes | lag slots multiplié par estimation slot time | estimer l'impact trading |
| débit WebSocket | compte notifications par seconde | comparer les modes live |
| taille moyenne notification | taille texte JSON ou bytes WS | dimensionner raw_ws_notifications |
| reconnects | logs `kb_app_demo.demo_ws` et nœud | détecter l'instabilité |
| erreurs provider ou Agave | logs et réponses JSON-RPC | classer les limites |
La mesure de lag secondes reste approximative tant que le slot time local n'est pas calculé sur fenêtre glissante. Le chiffre utile pour la décision reste le couple `lag slots` plus `lag secondes estimées`.
## Erreurs à documenter sans les masquer
| Catégorie | Exemples à noter |
|------------|---------------------------------------------------------------------------------------------|
| snapshot | téléchargement lent, snapshot incompatible, absence de snapshot |
| ledger | corruption, purge trop agressive, croissance disque excessive |
| accounts | croissance inattendue, I/O saturée, chemin invalide |
| ports | `8899` occupé, port WS indisponible, `dynamic-port-range` trop étroit |
| ressources | CPU saturé, RAM insuffisante, disque saturé, réseau insuffisant |
| retard | slot local qui n'avance plus, lag croissant, root très en retard |
| RPC | méthode non supportée, timeouts, erreurs JSON-RPC |
| WebSocket | connexion refusée, fermeture serveur, subscription refusée, notifications trop volumineuses |
Un essai qui échoue est exploitable s'il indique précisément la commande, le contexte, l'erreur et la ressource bloquante.
## Table de résultats à remplir
| Date | Agave | N_SHREDS | durée | ledger | accounts | CPU moy/max | RAM moy/max | RX/TX | slot local | slot réf. | lag slots | lag sec. | blockSubscribe none | remarques |
|-----------|-----------|-----------|-----------|-----------|-----------|-------------|-------------|-----------|------------|-----------|-----------|-----------|---------------------|-----------|
| À remplir | À remplir | À remplir | À remplir | À remplir | À remplir | À remplir | À remplir | À remplir | À remplir | À remplir | À remplir | À remplir | À remplir | À remplir |
## Critères de décision pour `0.4.x`
Le nœud local peut être retenu comme source live principale uniquement si les conditions suivantes sont mesurées :
- le slot local suit l'endpoint externe avec un retard stable et acceptable ;
- le ledger et les accounts restent soutenables sur le disque local ;
- `blockSubscribe` est supporté et stable avec au moins `transactionDetails=none` ;
- le mode `full` ou `signatures` ne bloque pas la WebView ni le process Rust lorsqu'il sera testé ;
- les reconnects et timeouts restent rares ou récupérables ;
- un fallback externe reste disponible pour backfill, réparation et envoi de transaction.
Si une de ces conditions échoue, `0.4.x` doit privilégier `slotSubscribe + getBlock`, les listeners ciblés ou une stratégie hybride, sans dépendance obligatoire à Agave local.
## Sortie attendue de `0.3.x`
La fin de `0.3.x` doit produire une décision documentée :
```text
source temps réel principale retenue
fallback temps réel retenu
politique raw_ws_notifications
faisabilité du nœud local
limites ressources observées
prochain design de l'ingestion 0.4.x
```

View File

@@ -1,28 +0,0 @@
<!-- file: docs/APPLICATION_CRATES.md -->
<!-- version: 1 -->
# Crates applicatifs
Les crates applicatifs sont les points d'entrée exécutables ou Tauri du workspace. Ils orchestrent les crates internes mais ne portent pas la logique métier profonde.
## Nomenclature
- Les applications ponctuelles ou interactives utilisent le préfixe `kb_app_`.
- `kb_app_cli` contient les commandes de contrôle, import, replay et diagnostic.
- `kb_app_demo` contient la démonstration Tauri.
- `kb_worker` est l'exception autorisée, car il représente un processus de travail long-running.
## Responsabilités autorisées
- Lire la configuration.
- Initialiser `kb_logging`.
- Appeler les APIs publiques de `kb_pipeline`.
- Afficher ou exposer les résultats.
- Retourner des codes de sortie ou événements UI.
## Responsabilités interdites
- Décoder directement une instruction DEX.
- Écrire directement dans PostgreSQL sans passer par les traits de stockage.
- Réimplémenter les règles de matérialisation.
- Charger ou manipuler des secrets wallet hors `kb_wallet`.

View File

@@ -1,108 +0,0 @@
<!-- file: docs/ARCHITECTURE.md -->
<!-- version: 7 -->
# Architecture
L'architecture cible est organisée en couches strictes afin d'éviter de recréer un monolithe. Les noms `raw`, `core`, `obs`, `decode`, `mat`, `agg` et `ops` désignent des couches logiques, pas des schémas PostgreSQL applicatifs.
## Chaîne principale
```text
sources RPC HTTP / WebSocket / gRPC
-> kb_onchain_transport
-> kb_model transaction canonique
-> raw
-> core
-> obs
-> decode
-> mat
-> agg
-> strategy
-> execution
sources historiques déjà indexées
-> kb_external_sources
-> candidats de signatures
-> kb_pipeline
-> hydratation canonique via kb_onchain_transport
```
## Responsabilités
- `kb_onchain_transport` gère les méthodes et flux RPC Solana : JSON-RPC HTTP, WebSocket, Helius/LaserStream et Yellowstone gRPC lorsque ces surfaces seront activées.
- `kb_external_sources` est une crate future réservée aux APIs REST, exports et imports historiques externes, par exemple Solscan Pro ou un CSV officiel. Elle ne produit jamais directement une transaction canonique et ne doit pas être confondue avec un futur index interne PostgreSQL.
- `kb_pipeline` combine la découverte de signatures par `kb_onchain_transport` ou `kb_external_sources` avec lhydratation canonique par `kb_onchain_transport`.
- `kb_model` définit la transaction Solana canonique indépendante du fournisseur.
- `raw` conserve une transaction canonique unique et rejouable par signature.
- `obs` conserve les observations techniques de source, programme, instruction et discriminator.
- `core` expose les structures Solana normalisées pour les décodeurs.
- `decode` contient les événements protocolairement compris.
- `mat` contient les projections métier.
- `agg` contient les agrégations temporelles ou analytiques.
- `ops` trace les modules, versions et traitements.
## Acquisition multi-source
```text
getTransaction JSON-RPC
transactionSubscribe Helius
Yellowstone gRPC
logsSubscribe + hydration
|
v
transaction canonique identique
```
Les détails de fournisseur restent dans `kb_sol_obs_transaction_observations`. Ils ne contaminent pas les décodeurs ni les tables core.
`kb_onchain_transport` ne doit pas être renommée en `kb_com` ou `kb_transport` pour accueillir des sources historiques externes. Ces noms seraient trop génériques et mélangeraient RPC Solana, APIs REST indexées, imports CSV et orchestration métier. Le nom `kb_external_sources` évite la confusion avec lindexation locale et décrit explicitement une frontière de fournisseurs externes plutôt quune simple action de récupération. Si des primitives HTTP réellement communes apparaissent plus tard, elles pourront être extraites dans une crate technique dédiée sans modifier la frontière fonctionnelle entre `kb_onchain_transport` et `kb_external_sources`.
## Convention DB associée
Quand une couche logique devient une table Solana PostgreSQL, elle est encodée dans le nom de table :
```text
kb_sol_<domain>_<name>
```
Exemples :
```text
kb_sol_raw_transactions
kb_sol_obs_transaction_observations
kb_sol_core_transactions
kb_sol_obs_program_observations
kb_sol_decode_decoded_events
kb_sol_mat_trade_events
kb_sol_ops_processing_ledger
```
Les formes qualifiées héritées, écrites ici avec `DOT` (`raw DOT sol_transactions`, `core DOT sol_instructions`, `obs DOT program_observations`), sont interdites.
## Frontières interdites
- Un décodeur ne dépend pas du store concret.
- Un décodeur ne dépend pas du fournisseur ou du transport dacquisition.
- Un matérialisateur ne dépend pas du RPC.
- Le wallet ne dépend pas des décodeurs.
- L'application de démonstration ne doit pas contourner les APIs de pipeline.
- Une observation de source ne doit pas dupliquer le payload canonique complet.
## Frontière extraction canonique vers core
Depuis `0.3.4`, `kb_pipeline` contient un extracteur pur qui dépend de `kb_model` et des contrats `kb_store_core`, mais pas de PostgreSQL ni de Tauri. `kb_store_pg` implémente la transaction atomique et `kb_app_demo` ne fait quorchestrer la requête opérateur.
```text
kb_model::CanonicalTransaction
|
v
kb_pipeline::core_extraction
| CoreExtractionBundle
v
kb_store_core::CoreExtractionStore
|
v
kb_store_pg::PostgresStore
```
Les futurs décodeurs consommeront les inputs core contextualisés ; ils ne reliront pas directement le JSON canonique pour reconstruire les comptes, CPI, logs ou balances.

View File

@@ -1,145 +0,0 @@
<!-- file: docs/BACKFILL_HTTP.md -->
<!-- version: 6 -->
# Backfill HTTP transactionnel
## Objectif
Le jalon `0.3.3` fournit un moteur de backfill réutilisable qui transforme les réponses HTTP Solana standard en transactions canoniques indépendantes du fournisseur.
```text
signatures explicites
ou getSignaturesForAddress
-> getTransaction
-> kb_model::CanonicalTransaction
-> kb_sol_raw_transactions
-> kb_sol_obs_transaction_observations
```
Aucun décodeur DEX, aucune extraction core et aucune source temps réel payante ne sont exécutés dans ce jalon.
## Sources de signatures
Le moteur accepte quatre catégories :
- liste explicite de signatures, une signature par ligne ;
- historique dun `program_id` ;
- historique dun mint de token ;
- historique dune adresse de pool.
Les trois modes par adresse utilisent la même méthode standard `getSignaturesForAddress`. La catégorie est conservée dans le `filter_code` des observations afin de distinguer `program_before`, `program_after`, `program_latest`, et les équivalents token/pool.
## Sens de pagination
### Avant une signature
Avec une ancre, le paramètre RPC `before` sélectionne les transactions plus anciennes que cette signature. Sans ancre, le mode `Before` omet `before` et commence sur la page la plus récente retournée par le RPC. Le moteur poursuit la pagination jusquà atteindre la limite demandée, une page incomplète, la limite de pages ou une demande darrêt.
### Après une signature
Le moteur transmet directement la signature dancrage dans le paramètre RPC `until`. Les pages suivantes combinent le même `until` avec un curseur `before` correspondant à la dernière signature de la page précédente.
Le mode `after` utilise des pages RPC de 1 000 signatures afin que la limite par défaut de 20 pages puisse couvrir jusquà 20 000 signatures plus récentes que lancre. Le moteur ne conserve que les `X` candidates les plus proches de lancre, en plus de lensemble de déduplication borné par `max_pages × 1 000`.
Une page incomplète signifie que la borne `until` a été atteinte. Si toutes les pages autorisées sont pleines, la campagne échoue avec le nombre de signatures inspectées et demande daugmenter `max_pages`. Une erreur RPC de borne inconnue est propagée sans être transformée en résultat vide.
## Limites et retries
Le moteur combine :
- les limites saisies par lopérateur ;
- `requests_per_second` du rôle sélectionné ;
- `max_concurrent_requests` du rôle sélectionné ;
- `pause_after_rate_limit_ms` après une erreur 429 ;
- un backoff borné pour les autres erreurs temporaires.
Le rôle HTTP doit supporter à la fois :
```text
get_signatures_for_address
get_transaction
```
Le rôle recommandé reste `history_backfill`.
## Persistance
Une signature déjà présente dans `kb_sol_raw_transactions` est ignorée avant lappel `getTransaction`.
Chaque tentative dhydratation produit une observation légère :
- provider et endpoint ;
- protocole `solana_http_json_rpc` ;
- méthode `getTransaction` ;
- origine `backfill` ;
- commitment, session et filtre ;
- timestamps ;
- taille et hash du payload source lorsque disponibles ;
- statut `persisted`, `missing` ou `failed` ;
- erreur normalisée lorsque nécessaire.
Le payload source complet nest jamais dupliqué dans la table dobservations.
## Démo Tauri et arrêt coopératif
La fenêtre `demo_backfill` regroupe dans des accordéons Bootstrap 5 :
1. paramètres communs ;
2. signatures explicites ;
3. programme ;
4. token ;
5. pool ;
6. journal et résumé JSON.
Une seule campagne peut fonctionner à la fois. Le bouton `Arrêter` pose un drapeau dannulation coopérative lu entre les pages, les candidats, le pacer et les retries.
Depuis la préversion de clôture `0.3.4-pre.011`, lannulation ne se limite plus aux frontières entre appels : les futures RPC `getSignaturesForAddress` et `getTransaction` sont mises en concurrence avec un observateur darrêt, lattente du pacer est annulable et une pause de retry, y compris après un 429, est interrompue par sondage borné. Labandon de la future HTTP empêche une campagne arrêtée dattendre un timeout réseau complet.
Le moteur maintient une file bornée par la concurrence effective et cesse dadmettre de nouveaux candidats dès que larrêt est demandé. Les candidats non démarrés ne sont ni journalisés comme traités, ni inclus dans `candidates_completed`.
Le résumé distingue :
- `candidates_selected` : candidats découverts ;
- `candidates_started` : candidats admis dans la file dexécution ;
- `candidates_completed` : candidats arrivés à un résultat terminal ;
- `candidates_cancelled` : candidats démarrés puis interrompus avant un résultat terminal ;
- `candidates_not_started` : candidats jamais admis après la demande darrêt.
Les invariants attendus sont :
```text
candidates_selected = candidates_started + candidates_not_started
candidates_started = candidates_completed + candidates_cancelled
```
Pour une campagne `before`, `resume_before_signature` correspond à la dernière signature terminée dans un préfixe contigu de la liste ordonnée. Une transaction terminée hors ordre ne fait pas avancer seule ce curseur. Si aucun candidat na terminé, le curseur reste la signature dancrage initiale. Cette règle interdit de sauter les candidats non traités lors dune reprise.
Le calcul de cette frontière est couvert par les tests unitaires. Une campagne réelle de 500 candidats a déjà validé larrêt et la séparation entre terminés, annulés et non démarrés. Le rejeu manuel depuis `resume_before_signature` reste un contrôle opératoire recommandé, mais il ne constitue plus un jalon séparé ni un blocage pour `0.4.0`.
## Validation finale `0.3.3`
Validations locales :
```text
cargo test -p kb_onchain_transport : 54 tests passés
cargo test -p kb_pipeline : 10 tests passés
cargo test -p kb_store_core: 31 tests passés
cargo test -p kb_store_pg : 32 tests passés
cargo test -p kb_app_demo : 38 tests passés
cargo clippy --all-targets : validé
```
Les campagnes Tauri ont validé :
- signatures explicites ;
- programme avant/après ;
- token avant/après ;
- pool avant/après ;
- parcours profond `program_after` avec 5 516 signatures indexées parcourues pour 5 transactions hydratées ;
- arrêt dune campagne de 500 candidats avec 7 démarrés, 3 terminés, 4 annulés et 493 non démarrés.
Les diagnostics PostgreSQL ont confirmé 62 transactions canoniques et 62 observations avant les derniers tests darrêt. Les tables core restent volontairement vides jusquà `0.3.4`.
## Recherche latest sans ancre
Pour programme, token et pool, une direction `before` avec ancre absente produit un filtre `*_latest`. La première page est demandée sans `before`, puis les pages suivantes utilisent normalement la dernière signature reçue comme curseur. Une direction `after` sans ancre est refusée, car la borne `until` ne peut pas être déterminée. En cas darrêt avant le premier candidat terminé, une campagne `*_latest` reprend depuis la page la plus récente et ne fabrique aucun curseur.

View File

@@ -1,26 +0,0 @@
<!-- file: docs/BAGS_FM.md -->
<!-- version: 1 -->
# Bags.fm
## Décision de classification
`BAGSB9TpGrZxQbEsrEznv5jXXdwyP6AXerN8aVRiAmcv` reste classé comme compte observé et non comme `program_id` exécutable prouvé.
En revanche, la documentation publique Bags liste deux programmes Fee Share :
| Surface canonique | Program id | Statut |
|--------------------------|------------------------------------------------|---------|
| `fees_bags_fee_share_v1` | `FEEhPbKVKnco9EXnaY3i4R5rQVUx91wgVfu8qokixywi` | legacy |
| `fees_bags_fee_share_v2` | `FEE2tBhCKAt7shrod19QttSVREUYPiyMzoku1mL1gqVK` | current |
## Crates réservés
- `kb_decoder_fees_bags_fee_share_v1`
- `kb_executor_fees_bags_fee_share_v1`
- `kb_decoder_fees_bags_fee_share_v2`
- `kb_executor_fees_bags_fee_share_v2`
## Rôle dans le trading assisté
Ces surfaces ne sont pas des DEX directs. Elles peuvent cependant être utiles pour détecter des configurations de frais, claims, partenaires, vaults de frais ou comportements liés à des tokens lancés via Bags.

View File

@@ -1,41 +0,0 @@
<!-- file: docs/CODE_REUSE.md -->
<!-- version: 2 -->
# Réutilisation de code
Ce document liste les composants de l'ancien workspace qui peuvent servir de référence pour le nouveau workspace. Le code ne doit pas être copié mécaniquement : chaque portion reprise doit être adaptée aux nouvelles frontières de crates, aux règles de nommage, aux règles `crate::` et au backend PostgreSQL.
## Composants candidats
| Composant | Cible dans le nouveau workspace | Décision provisoire |
|--------------------------------------------|-------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------|
| Client RPC HTTP | `kb_onchain_transport` | Réutiliser les idées : retry, backoff, limites, traces, idempotence. Réécrire l'API selon les nouveaux modèles. |
| Pool RPC HTTP | `kb_onchain_transport` | Reprendre le principe de sélection d'endpoint et de contrôle de débit. Isoler les métriques et les erreurs dans `kb_core`. |
| Client WebSocket | `kb_onchain_transport` | Reprendre la gestion ping/pong, subscribe/unsubscribe, shutdown explicite et reconnexion contrôlée. |
| Pool WebSocket | `kb_onchain_transport` | Garder l'idée de pool, mais éviter toute dépendance vers les décodeurs ou le stockage concret. |
| Ledger de replay | `kb_pipeline` et `kb_store_core` | Réécrire en versionné par module, version, scope et input hash. |
| Validation SQL | `validation_sql/` | Porter seulement les contrôles encore utiles : doublons de signatures, events failed, non-swap vers trade, coverage résiduelle. |
| Découvertes de discriminators | `docs/DECODER_SURFACE_AUDIT.md`, `idls/`, futurs catalogues | Conserver comme corpus de décision, pas comme support automatique. |
| Matérialisations trade/liquidity/lifecycle | `kb_materializer_*` | Reprendre les règles validées, mais séparer strictement decode et materialize. |
## Interdictions
- Ne pas importer directement l'ancien schéma SQLite dans les nouveaux décodeurs.
- Ne pas faire dépendre `kb_onchain_transport` de `kb_store_pg`.
- Ne pas faire dépendre un décodeur de `kb_pipeline`.
- Ne pas conserver une fonction monolithique de replay global.
## Critère d'acceptation
Une portion reprise est acceptée seulement si elle respecte les règles suivantes :
- responsabilité limitée à un crate cible ;
- documentation de code en anglais ;
- absence de `use` hors traits nécessaires ;
- erreurs typées via `kb_core` ;
- tracing target stable ;
- tests unitaires ou validation de build.
## Interfaces officielles actuelles
La réutilisation prioritaire ne concerne pas uniquement lancien code. Les enums, types, IDs et encodeurs publiés dans les interfaces officielles Solana/SPL doivent être utilisés lorsquils exposent un contrat compatible avec les règles du workspace. La matrice, les exceptions `bincode` et lordre `wincode`/Borsh/parser borné sont maintenus dans `docs/SOLANA_INTERFACE_DEPENDENCIES.md`.

View File

@@ -1,114 +0,0 @@
<!-- file: docs/CONFIGURATION.md -->
<!-- version: 3 -->
# Configuration
La configuration sert de contrat commun entre les applications Tauri, les workers, les tests locaux, les stores, le RPC, le wallet et les exécuteurs.
## Fichier principal
```text
config/example.config.json
```
Ce fichier ne contient pas de commentaires, car JSON ne le permet pas.
## Profils
La configuration racine contient plusieurs profils et un seul profil actif :
```json
{
"active_profile": "local_devnet",
"profiles": []
}
```
Les profils fournis sont `local_devnet`, `mainnet_research` et `mainnet`.
## Logging
Chaque sortie définit son nom, activation, sink, niveau, chemin, rotation, format, ANSI et liste de targets. Toute crate opérationnelle disposant d'un target `tracing` canonique doit recevoir ses fichiers `debug.log`, `info.log` et `error.jsonl` dédiés dans chaque profil.
`kb_wallet` devient une crate opérationnelle en `0.4.2-pre.003`; ses logs ne contiennent jamais de secret ou d'octets de keypair.
## Endpoints HTTP et WS
Le modèle principal conserve les endpoints HTTP JSON-RPC et WebSocket Solana standards. Les rôles permettent de sélectionner un endpoint selon le type de requête et d'appliquer débit, burst, concurrence, subscriptions et pause 429.
Les transports gRPC, Helius enrichi et LaserStream restent planifiés dans leurs jalons dédiés.
## URL et clés API
Une clé API doit rester sous forme de placeholder dans l'URL :
```text
https://mainnet.helius-rpc.com/?api-key=${HELIUS_API_KEY}
```
Aucune clé réelle ne doit être committée.
## Wallet
Le bloc `wallet` contient :
```text
wallet_dir
temporary_wallet_enabled
temporary_wallet_alias
temporary_wallet_persist
cluster
localnet_send_enabled
devnet_send_enabled
testnet_send_enabled
mainnet_send_enabled
```
Le profil local devnet persiste le wallet sous :
```text
wallets/temporary/local_devnet/local-devnet-operator.json
```
Cette persistance est nécessaire pour conserver la même adresse entre plusieurs sessions, recevoir un airdrop et signer une séquence de tests. Le fichier contient un keypair Solana standard non chiffré : il est exclu du dépôt, protégé par permissions privées sur Unix et réservé au laboratoire local/devnet.
La validation refuse :
- un alias vide, trop long ou contenant un séparateur de chemin ;
- `temporary_wallet_persist = true` lorsque le wallet temporaire est désactivé ;
- un wallet temporaire actif sur `mainnet-beta`.
## Exécution
Le bloc `execution` contient :
```text
dry_run_default
require_simulation
require_operator_confirmation
localnet_max_spend_lamports
devnet_max_spend_lamports
testnet_max_spend_lamports
mainnet_max_spend_lamports
max_fee_lamports
max_compute_unit_price_micro_lamports
recent_blockhash_max_age_slots
send_max_retries
confirmation_poll_interval_ms
confirmation_max_attempts
devnet_airdrop_max_lamports
```
Règles :
- toute dépense configurée exige la simulation ;
- tout envoi activé exige un plafond de dépense positif pour le cluster correspondant ;
- mainnet exige la confirmation opérateur ;
- le plafond de frais et l'âge maximal du blockhash doivent être strictement positifs ;
- lintervalle et le nombre de polls de confirmation sont strictement bornés ;
- le plafond dairdrop Devnet doit rester nul dans les profils non Devnet ;
- `dry_run_default` reste actif dans tous les profils fournis.
## Règle de sécurité
Aucun secret ne doit être écrit dans le dépôt, les logs, PostgreSQL ou un payload Tauri. Les futurs backends chiffrés ou hardware wallet resteront confinés dans `kb_wallet` et exposeront uniquement une interface de signature.

View File

@@ -1,148 +0,0 @@
<!-- file: docs/CORE_EXTRACTION_CONTRACTS.md -->
<!-- version: 6 -->
# Contrats dextraction core Solana
## État de clôture `0.3.4-pre.011`
Le jalon transforme une transaction canonique déjà persistée en graphe core normalisé et rejouable :
```text
kb_sol_raw_transactions.canonical_json
-> kb_model::CanonicalTransaction
-> validation version/signature/slot/hash
-> kb_pipeline::extract_raw_transaction_to_core
-> CoreExtractionBundle
-> transaction PostgreSQL atomique
```
Le payload fournisseur contenu à lorigine dans une réponse RPC nest jamais relu depuis les observations. La seule source fonctionnelle de lextracteur est le document canonique de `kb_sol_raw_transactions`.
## Unité atomique
Une signature produit un `CoreExtractionBundle` contenant :
- une transaction core liée par `raw_transaction_id` ;
- les account keys statiques et chargées par ALT ;
- les instructions top-level ;
- les inner instructions ;
- les logs ordonnés ;
- les changements de balances natifs et token ;
- lidentité du processor dans le ledger.
Le repository PostgreSQL supprime puis recrée le graphe de la signature dans une transaction unique. Un échec avant le commit laisse intact létat précédemment validé. Le test PostgreSQL de clôture provoque volontairement une violation dunicité après insertion de la transaction et dune première account key, puis vérifie labsence totale de graphe partiel, de changement raw et de succès ledger.
## Validation de lentrée
Lextraction refuse explicitement :
- un `canonical_json` absent ;
- un `canonical_json_hash` absent ;
- une version différente de `MD_CANONICAL_TRANSACTION_FORMAT_VERSION` ;
- un JSON non désérialisable en `MdCanonicalTransaction` ;
- une signature ou un slot différent de la ligne raw ;
- un hash recalculé différent du hash stocké ;
- un indice de programme ou de compte hors de lespace résolu.
Lidentité du ledger est :
```text
stage = core_extraction
processor_name = canonical_to_core
processor_version = 1
input_key = signature
input_hash = canonical_json_hash
```
## Account keys
Lespace dindices est construit strictement dans cet ordre :
```text
static account keys
loaded writable addresses
loaded readonly addresses
```
Pour les comptes statiques, les flags `signer` et `writable` sont dérivés du header Solana. Les loaded writable sont non-signers et writable. Les loaded readonly sont non-signers et readonly. `executable` reste `NULL`, car cette information nest pas contenue de manière fiable dans le contrat canonique actuel.
## Instructions
Les chemins sont déterministes :
```text
0
1
2
0/0
0/1
2/0
```
`accounts_json` conserve, dans lordre original, chaque indice et la clé publique résolue. `payload_json` conserve `programIdIndex`, `dataBase64` et `stackHeight`. Un SHA-256 stable du payload JSON est persisté dans `payload_json_hash`.
## Logs
Chaque log conserve :
- son `log_index` global ;
- son texte original ;
- un SHA-256 du texte ;
- un `program_id` et un `instruction_path` uniquement lorsque la pile `invoke/success/failed` permet un rattachement déterministe.
Lorsque la reconstruction est ambiguë, le lien reste `NULL` plutôt que dinventer une relation.
## Balances
Les changements natifs utilisent les valeurs entières en lamports et stockent pre, post et delta comme chaînes décimales dans JSONB afin déviter toute perte de précision.
Les changements SPL et Token-2022 utilisent exclusivement `amount` et `decimals`. Les valeurs UI du fournisseur ne sont pas utilisées comme source de calcul. Pour un compte créé ou fermé pendant la transaction, le côté absent est représenté explicitement par un montant brut nul avec les mêmes décimales.
Le `balance_change_index` est déterministe : balances natives par index de compte, puis balances token triées par `(account_index, mint, program_id)`.
## Modes de sélection
La campagne peut sélectionner des transactions raw par signatures explicites, état `received`, plage de slots ou programme déjà présent dans les instructions top-level core. Les filtres, limites et scénarios de validation sont détaillés dans `docs/CORE_EXTRACTION_SELECTION_AND_REPLAY.md`.
Le mode par programme ne découvre pas un programme nouveau : il dépend des lignes déjà présentes dans `kb_sol_core_instructions` et ne couvre pas actuellement les occurrences exclusivement inner.
## Idempotence et replay
En mode normal, une entrée ledger `succeeded` ayant la même version et le même hash provoque un skip.
Un changement de version ou de hash entraîne une nouvelle extraction. Le mode `force_replay` ignore le skip et remplace atomiquement le graphe existant de la signature.
## Orchestration
`kb_pipeline::execute_core_extraction` fournit :
- sélection par signatures ;
- lot raw en état `received` ;
- plage de slots ;
- replay par program id déjà présent dans core ;
- limite et concurrence bornées ;
- arrêt coopératif avant admission de nouveaux candidats ;
- résumé `selected`, `started`, `completed`, `skipped`, `extracted`, `failed`, `cancelled_candidates` et `not_started`.
La logique de transformation ne dépend ni de Tauri ni dun décodeur protocolaire.
## Transactions échouées
Une transaction Solana ayant `failed = true` reste extraite intégralement lorsque ses métadonnées sont disponibles. Les instructions, inner instructions et logs exécutés avant lerreur constituent des observations utiles pour les futurs décodeurs.
Le futur pipeline doit distinguer :
```text
observation décodée dans une transaction échouée
mutation détat confirmée dans une transaction réussie
```
Une transaction échouée peut produire des observations dintention, de cause déchec, de compute budget ou de surface appelée. Elle ne doit pas produire automatiquement un trade, une modification de liquidité ou une candle présentés comme réussis.
## Validation réelle
Le skip et le force replay ont été validés sur 14 signatures : `14 skipped`, puis `14 extracted` avec force replay, puis `14 skipped`. Les tables core restent à 70 transactions et le ledger totalise 84 tentatives. Les requêtes `sql/validation/000_core_integrity.sql` ne retournent aucune anomalie.
## Hors périmètre
`0.3.4` neffectue aucun décodage Solana Core/SPL, aucun décodage DEX, aucune matérialisation métier et aucune compaction du JSON canonique.

View File

@@ -1,456 +0,0 @@
<!-- file: docs/CORE_EXTRACTION_SELECTION_AND_REPLAY.md -->
<!-- version: 4 -->
# Sélection et replay de lextraction core
## Objet
Ce document décrit les modes disponibles dans `demo_core_extraction`, leur effet réel sur PostgreSQL et la différence entre :
- acquisition dune transaction depuis le réseau ;
- extraction du document canonique vers les tables core ;
- futur décodage protocolaire ;
- future matérialisation métier.
Dans `0.3.4`, le mot « replay » désigne uniquement le rejeu de létape suivante :
```text
kb_sol_raw_transactions.canonical_json
-> kb_model::CanonicalTransaction
-> CoreExtractionBundle
-> kb_sol_core_transactions
-> kb_sol_core_account_keys
-> kb_sol_core_instructions
-> kb_sol_core_inner_instructions
-> kb_sol_core_logs
-> kb_sol_core_balance_changes
-> kb_sol_ops_processing_ledger
```
Aucun appel RPC nest effectué par cette étape. Aucun décodeur Solana Core, SPL, DEX ou autre protocole nest exécuté. Aucune ligne métier nest matérialisée.
## Cycle complet dune transaction
Le cycle prévu est séparé en étapes rejouables :
```text
réseau RPC
-> acquisition HTTP ou WebSocket
-> transaction canonique raw
-> extraction structurelle core
-> observation et classification
-> décodage protocolaire
-> matérialisation métier
-> agrégations et stratégies
```
`0.3.4` couvre uniquement la transition `raw canonique -> core structurel`.
Les lignes de `kb_sol_core_instructions` sont créées avec `processing_state = pending`. Elles constituent lentrée des futurs décodeurs prévus à partir de `0.4.x`.
## Paramètres communs
### Transactions maximales
`limit` borne le nombre de transactions sélectionnées par PostgreSQL avant démarrage de la campagne.
La sélection est ordonnée par :
```text
slot ASC, signature ASC
```
Cette règle sapplique aussi au mode signatures explicites. Lordre des lignes collées dans la zone de texte nest donc pas lordre dexécution garanti.
### Concurrence
`max_concurrent_extractions` borne le nombre dextractions admises simultanément.
Chaque signature reste une unité transactionnelle indépendante. Une transaction Solana produit son graphe core dans une transaction PostgreSQL atomique.
### Force replay
Sans `force_replay`, une signature est ignorée lorsque le ledger contient déjà un succès ayant exactement :
```text
stage = core_extraction
processor_name = canonical_to_core
processor_version = version courante
input_key = signature
input_hash = canonical_json_hash courant
status = succeeded
```
Avec `force_replay`, ce skip est désactivé. Le graphe core existant de la signature est supprimé puis recréé dans la même transaction PostgreSQL. Les autres signatures ne sont pas touchées.
Le force replay ne relance pas `getTransaction` et ne remplace pas le document canonique raw. Il reconstruit uniquement le core depuis le raw déjà présent.
## Mode signatures explicites
### Entrée
La zone de texte accepte une signature par ligne.
Avant lappel au pipeline, linterface :
- supprime les espaces autour de chaque ligne ;
- ignore les lignes vides ;
- supprime les doublons en conservant la première occurrence ;
- valide chaque valeur comme signature Solana.
### Sélection PostgreSQL
Le mode sélectionne uniquement les signatures déjà présentes dans `kb_sol_raw_transactions`.
Une signature absente de la table raw nest pas téléchargée automatiquement. Elle napparaît simplement pas dans les candidats sélectionnés. Le compteur `selected` peut donc être inférieur au nombre de signatures saisies.
Aucun filtre de `processing_state` nest appliqué. Ce mode peut sélectionner une transaction raw :
- `received` ;
- `core_extracted` ;
- `failed`.
Le ledger décide ensuite entre skip, extraction ou retry.
### Usages principaux
- vérifier lidempotence sur un échantillon connu ;
- forcer la reconstruction de quelques signatures ;
- retenter explicitement des transactions raw en échec ;
- comparer deux versions de lextracteur ;
- préparer plus tard un corpus ciblé pour un décodeur.
### Point dattention
Si le nombre de signatures existantes dépasse `limit`, seules les premières selon `slot ASC, signature ASC` sont retenues.
## Mode transactions en attente
### Filtre réel
Le mode pending sélectionne :
```text
kb_sol_raw_transactions.processing_state = received
```
Il ne sélectionne ni les lignes déjà `core_extracted`, ni les lignes `failed`.
### Transition après succès
Après commit du graphe core :
```text
received -> core_extracted
```
La même ligne ne sera donc plus sélectionnée lors dune campagne pending suivante.
### Transition après échec
Après un échec dextraction persistable :
```text
received -> failed
```
La raison est stockée dans `lifecycle_reason` et le ledger reçoit un statut `failed`.
Une ligne `failed` doit être retentée par signature explicite ou par un futur mode dédié aux erreurs. Une nouvelle campagne pending ne la reprend pas.
### Usages principaux
- vider progressivement la file des transactions canoniques nouvellement acquises ;
- exécuter lextraction courante après un backfill HTTP ;
- traiter un lot borné sans sélectionner manuellement les signatures.
### Conséquence sur le corpus actuel
Après la campagne réelle de 70 transactions :
```text
selected = 70
extracted = 70
failed = 0
```
les 70 lignes raw sont normalement passées à `core_extracted`. Une nouvelle campagne pending doit donc sélectionner zéro transaction tant quaucune nouvelle transaction raw `received` na été acquise.
## Mode plage de slots
### Filtre réel
Le mode sélectionne toutes les transactions raw dont le slot se trouve dans lintervalle inclusif :
```text
min_slot <= slot <= max_slot
```
Aucun filtre de `processing_state` nest appliqué.
### Comportement normal
Les transactions déjà à jour sont sélectionnées puis comptées comme `skipped` par le ledger. Les transactions reçues, en échec, ou dont la version/hash a changé peuvent être extraites.
### Comportement avec force replay
Toutes les transactions sélectionnées sont reconstruites dans la limite configurée.
### Usages principaux
- rejouer un intervalle temporel connu ;
- vérifier une régression sur un bloc ou une période ;
- reconstruire un corpus après changement de version de lextracteur.
## Mode programme déjà indexé dans core
### Filtre réel actuel
Le mode sélectionne les signatures raw pour lesquelles il existe déjà une ligne correspondante dans :
```text
kb_sol_core_instructions
```
avec un `program_id` exactement égal à la valeur demandée.
La requête actuelle ne recherche pas dans :
- `kb_sol_core_inner_instructions` ;
- `kb_sol_core_logs` ;
- `kb_sol_core_account_keys` ;
- le document canonique raw.
### Conséquences
Ce mode ne peut pas découvrir un programme pour la première fois. Il fonctionne uniquement après une première extraction core ayant déjà résolu au moins une instruction top-level de ce programme.
Une transaction où le programme apparaît exclusivement en inner instruction nest pas sélectionnée par ce mode dans son état actuel.
### Usages principaux
- reconstruire les transactions dun programme déjà indexé après changement de version ;
- vérifier une correction de résolution des comptes ou instructions ;
- préparer un sous-corpus structurel avant le futur replay dun décodeur.
### Évolution recommandée
Le futur sélecteur de corpus devrait distinguer explicitement :
- programme top-level ;
- programme inner ;
- programme observé dans les logs ;
- union de toutes les occurrences core fiables.
Le mode dextraction actuel peut rester strictement basé sur les instructions top-level, à condition que cette limite demeure visible dans linterface.
## Interprétation des compteurs
| Compteur | Signification |
|-----------------------|-------------------------------------------------------------|
| `selected` | Candidats retournés par PostgreSQL après filtres et limite. |
| `started` | Candidats admis dans la file dexécution bornée. |
| `completed` | Candidats arrivés à un résultat terminal. |
| `skipped` | Ledger déjà à jour pour la même version et le même hash. |
| `extracted` | Graphe core écrit et commit réussi. |
| `failed` | Extraction ou persistance terminée en erreur. |
| `cancelledCandidates` | Candidats admis mais annulés avant résultat terminal. |
| `notStarted` | Candidats sélectionnés mais jamais admis après arrêt. |
| `cancelled` | Une demande darrêt coopératif a été observée. |
Pour une campagne terminée normalement :
```text
completed = skipped + extracted + failed
selected = completed + cancelledCandidates + notStarted
```
## Scénarios de validation recommandés
### Vérifier le skip
1. Extraire 5 à 10 signatures déjà présentes dans core depuis un outil de sélection.
2. Les coller dans le mode signatures explicites.
3. Laisser `force_replay` désactivé.
Résultat attendu :
```text
selected = N
skipped = N
extracted = 0
failed = 0
```
### Vérifier le force replay
1. Réutiliser exactement les mêmes signatures.
2. Activer `force_replay`.
Résultat attendu :
```text
selected = N
skipped = 0
extracted = N
failed = 0
```
Les cardinalités globales des tables core doivent rester stables pour ces signatures. Le `attempt_count` du ledger doit augmenter.
### Vérifier un changement de version ou de hash
Un changement réel de `processor_version` ou de `canonical_json_hash` doit provoquer une nouvelle extraction même sans `force_replay`.
Cette vérification doit être effectuée dans une base de test dédiée. Le hash canonique dune ligne de production ne doit pas être modifié manuellement.
### Vérifier le rollback
Le rollback atomique doit être validé par un test PostgreSQL avec injection dune erreur entre les insertions du graphe et le commit.
La méthode recommandée est un test dintégration sur `solana_test`, et non une corruption volontaire de la base principale.
## Sélecteur de corpus dans lapplication
La fenêtre read-only dédiée est :
```text
demo_sql_replay_candidates
```
Elle est accessible depuis le menu principal et depuis len-tête de `demo_core_extraction`. `demo_sql_diag` reste limité à la connexion, au profil actif, aux migrations et aux cardinalités.
Le sélecteur ne déclenche aucune acquisition RPC, extraction core, opération de décodage ou matérialisation. Il lit uniquement les tables PostgreSQL déjà alimentées.
## Tableau des transactions et signatures
Les filtres PostgreSQL disponibles sont :
- fragment de signature ;
- slot minimum et maximum inclusifs ;
- état raw `received`, `core_extracted`, `decoded`, `materialized` ou `failed` ;
- statut ledger `not_started`, `running`, `succeeded` ou `failed` ;
- program ID exact ;
- portée du programme : `any`, `outer`, `inner` ou `logs` ;
- entité exacte : `mint`, `owner` ou `account_key` ;
- limite ;
- ordre par slot croissant ou décroissant.
Chaque résultat affiche :
- signature et slot ;
- état raw et rétention ;
- présence de la transaction core et éventuel échec Solana ;
- dernier statut du ledger `core_extraction` ;
- version et nombre de tentatives ;
- nombres dinstructions et de programmes outer/inner ;
- date de dernière mise à jour raw.
Le filtre de programme inspecte les instructions outer, les inner instructions et les logs auxquels un `program_id` a pu être rattaché de manière prudente. Une occurrence dans les logs nest donc visible que lorsque le rattachement core a produit un `program_id` non nul.
## Tableau des programmes
Le tableau agrège :
```text
kb_sol_core_instructions.program_id
kb_sol_core_inner_instructions.program_id
kb_sol_core_logs.program_id
```
Pour chaque programme, il expose :
- le `program_id` ;
- le nombre de transactions distinctes ;
- le nombre dinstructions outer ;
- le nombre dinstructions inner ;
- le nombre de logs reliés ;
- le slot minimum et maximum.
La sélection dun programme peut alimenter le filtre programme du tableau des transactions, puis charger les signatures correspondantes.
## Tableau des entités
Le tableau agrège trois familles :
- `mint` depuis `kb_sol_core_balance_changes.mint` ;
- `owner` depuis `kb_sol_core_balance_changes.owner` ;
- `account_key` depuis `kb_sol_core_account_keys.account_key`.
Chaque ligne indique le nombre de transactions distinctes, le nombre doccurrences et la plage de slots. Une entité sélectionnée peut alimenter le filtre du tableau des transactions.
Les account keys ne sont pas présentées comme wallet, pool, mint ou token account sans classification supplémentaire.
## DataTables, copie et exports
La fenêtre utilise cinq tableaux DataTables avec intégration Bootstrap 5 et extension Select :
1. transactions et signatures ;
2. programmes ;
3. mints ;
4. owners ;
5. account keys.
Chaque tableau affiche 10 lignes par défaut. Une checkbox par ligne et une checkbox de header permettent de sélectionner le jeu filtré. Les filtres possèdent un bouton de reset qui restaure les valeurs par défaut, efface la recherche locale, désélectionne les lignes et recharge PostgreSQL.
Les signatures, program IDs, mints, owners et account keys sont tronqués visuellement sous la forme `préfixe…suffixe`. La valeur complète reste utilisée par le tri, la recherche, les tooltips, la copie et lexport. Un bouton de copie individuel évite les espaces parasites liés à une sélection manuelle.
La règle dexport est la suivante :
1. lorsquune ou plusieurs lignes sont sélectionnées, seules ces lignes sont exportées ;
2. sans sélection, toutes les lignes correspondant au filtre local DataTables sont exportées ;
3. la limite PostgreSQL reste la borne supérieure du corpus chargé.
Le frontend construit un CSV UTF-8 avec BOM, séparateur `;` et fins de ligne CRLF. Une commande Rust lécrit dans :
```text
data/exports_csv/
```
Le backend ajoute un suffixe numérique lorsque le nom existe déjà. Ce chemin a été validé sous Tauri/Linux et ne dépend pas du téléchargement HTML du WebView.
La copie multiligne des signatures est directement compatible avec la zone `Signatures explicites` de `demo_core_extraction`.
## Garanties et limites
- commandes Tauri read-only ;
- requêtes SQL statiques et paramétrées ;
- aucune zone permettant dexécuter du SQL libre ;
- limite obligatoire comprise entre `1` et `5 000` ;
- filtres exacts pour programme et entité afin déviter une sélection ambiguë ;
- recherche locale DataTables appliquée après le chargement serveur ;
- aucune découverte de transaction absente du raw ;
- aucun décodage de protocole ;
- aucun changement détat raw, core ou ledger.
Les futurs écrans de `0.4.x` pourront réutiliser le même principe pour les replays de décodeurs et de matérialiseurs.
## Utilisation du sélecteur SQL
`demo_sql_replay_candidates` aide à constituer des corpus sans requête manuelle dans pgAdmin ou DBeaver. Il reste séparé du worker : il lit les tables raw/core/ledger, puis produit des signatures ou des filtres réutilisables.
Dans longlet programmes, « Utiliser comme filtre transactions » prend exactement un programme coché. À défaut de sélection, une unique ligne restant après le filtre local est acceptée. Laction renseigne le program ID exact, choisit la portée `any`, ouvre longlet transactions et recharge la liste.
Le sélecteur des programmes connus est alimenté par `kb_program_ids`, mais la saisie libre reste disponible pour les programmes observés qui ne sont pas encore enregistrés.
Les exports CSV sont écrits dans `data/exports_csv/` par le backend Rust. Ils servent à laudit et à la conservation dun corpus ; pour rejouer immédiatement des signatures, la copie multiligne reste le chemin le plus direct.
Les notions de pool et de paire ne sont pas encore disponibles à ce stade structurel. Une account key core ne suffit pas à prouver quun compte représente un pool ou une paire. Cette navigation sera ajoutée après matérialisation de catalogues sémantiques par les décodeurs.
## Validation réelle de lidempotence
Un échantillon de 14 signatures a produit les résultats suivants :
```text
mode normal : extracted=0, skipped=14
force replay: extracted=14, skipped=0
mode normal : extracted=0, skipped=14
```
Le nombre de transactions core est resté à 70. Le ledger contient 70 lignes `succeeded` et 84 tentatives, soit les 70 tentatives initiales plus les 14 remplacements forcés. Les requêtes dintégrité nont détecté aucune anomalie.
## Politique future pour les transactions échouées
Les transactions on-chain échouées restent candidates au décodage. Elles conservent des informations sur les programmes appelés, les instructions exécutées avant lerreur, les logs, le compute consommé et la cause déchec.
Les décodeurs devront produire des observations marquées par le statut de la transaction. Les matérialiseurs ne devront pas convertir ces observations en mutations détat réussies, trades confirmés, changements de liquidité ou candles normales.

View File

@@ -1,63 +0,0 @@
<!-- file: docs/CORE_PROGRAM_IDS.md -->
<!-- version: 6 -->
# Identifiants core Solana et SPL
Ce fichier sépare les identifiants primitifs Solana/SPL du registre des surfaces applicatives. Cette séparation évite de traiter `system`, `token`, `memo`, `sysvar` ou les loaders comme des DEX/routers.
## Règle de classification
- Les programmes runtime natifs, loaders et précompiles relèvent de `kb_decoder_solana_core`.
- Chaque programme SPL vérifié conserve une frontière spécialisée : Token, Token-2022, ATA, Memo, Stake Pool, Single Pool, Account Compression, Noop ou Name Service.
- Les sysvars sont des comptes connus à reconnaître pendant l'extraction, pas des surfaces DEX à décoder comme des programmes applicatifs.
- `stake_pool` et `single_pool` sont distincts du Stake Program natif et possèdent leurs propres crates.
## Table de contrôle
| Canonique | Program ID | Source | Type | Crate cible | Statut |
|--------------------------------------------|------------------------------------------------|----------------------------------|----------------------|-------------------------------------------|-------------------------------------|
| `core_solana_address_lookup_table_v1` | `AddressLookupTab1e1111111111111111111111111` | `address_lookup_table` | `program` | `kb_decoder_solana_core` | `core_handled` |
| `core_solana_bpf_loader_deprecated_v1` | `BPFLoader1111111111111111111111111111111111` | `bpf_loader_deprecated` | `loader_program` | `kb_decoder_solana_core` | `core_handled` |
| `core_solana_bpf_loader_v2` | `BPFLoader2111111111111111111111111111111111` | `bpf_loader` | `loader_program` | `kb_decoder_solana_core` | `core_handled` |
| `core_solana_bpf_loader_upgradeable_v1` | `BPFLoaderUpgradeab1e11111111111111111111111` | `bpf_loader_upgradeable` | `loader_program` | `kb_decoder_solana_core` | `core_handled` |
| `core_solana_compute_budget_v1` | `ComputeBudget111111111111111111111111111111` | `compute_budget` | `program` | `kb_decoder_solana_core` | `core_handled` |
| `core_solana_config_v1` | `Config1111111111111111111111111111111111111` | `config` | `program` | `kb_decoder_solana_core` | `core_handled` |
| `core_solana_ed25519_v1` | `Ed25519SigVerify111111111111111111111111111` | `ed25519` | `program` | `kb_decoder_solana_core` | `core_handled` |
| `core_solana_feature_v1` | `Feature111111111111111111111111111111111111` | `feature` | `program` | `kb_decoder_solana_core` | `core_handled` |
| `core_solana_incinerator_v1` | `1nc1nerator11111111111111111111111111111111` | `incinerator` | `well_known_account` | `kb_decoder_solana_core` | `core_recognized_account` |
| `core_solana_loader_v4` | `LoaderV411111111111111111111111111111111111` | `loader_v4` | `loader_program` | `kb_decoder_solana_core` | `core_handled` |
| `core_solana_native_loader_v1` | `NativeLoader1111111111111111111111111111111` | `native_loader` | `loader_program` | `kb_decoder_solana_core` | `core_handled` |
| `core_solana_secp256k1_v1` | `KeccakSecp256k11111111111111111111111111111` | `secp256k1` | `program` | `kb_decoder_solana_core` | `core_handled` |
| `core_solana_secp256r1_v1` | `Secp256r1SigVerify1111111111111111111111111` | `secp256r1` | `program` | `kb_decoder_solana_core` | `core_handled` |
| `core_solana_slashing_v1` | `S1ashing11111111111111111111111111111111111` | `slashing` | `stateless_program` | `kb_decoder_solana_core` | `core_handled` |
| `core_solana_stake_config_v1` | `StakeConfig11111111111111111111111111111111` | `stake_config` | `well_known_account` | `kb_decoder_solana_core` | `core_recognized_account` |
| `core_solana_stake_v1` | `Stake11111111111111111111111111111111111111` | `stake` | `program` | `kb_decoder_solana_core` | `core_handled` |
| `core_solana_system_v1` | `11111111111111111111111111111111` | `system` | `program` | `kb_decoder_solana_core` | `core_handled` |
| `core_solana_sysvar_clock_v1` | `SysvarC1ock11111111111111111111111111111111` | `sysvar_clock` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` |
| `core_solana_sysvar_epoch_rewards_v1` | `SysvarEpochRewards1111111111111111111111111` | `sysvar_epoch_rewards` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` |
| `core_solana_sysvar_epoch_schedule_v1` | `SysvarEpochSchedu1e111111111111111111111111` | `sysvar_epoch_schedule` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` |
| `core_solana_sysvar_fees_v1` | `SysvarFees111111111111111111111111111111111` | `sysvar_fees` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` |
| `core_solana_sysvar_instructions_v1` | `Sysvar1nstructions1111111111111111111111111` | `sysvar_instructions` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` |
| `core_solana_sysvar_last_restart_slot_v1` | `SysvarLastRestartS1ot1111111111111111111111` | `sysvar_last_restart_slot` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` |
| `core_solana_sysvar_recent_blockhashes_v1` | `SysvarRecentB1ockHashes11111111111111111111` | `sysvar_recent_blockhashes` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` |
| `core_solana_sysvar_rent_v1` | `SysvarRent111111111111111111111111111111111` | `sysvar_rent` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` |
| `core_solana_sysvar_rewards_v1` | `SysvarRewards111111111111111111111111111111` | `sysvar_rewards` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` |
| `core_solana_sysvar_slot_hashes_v1` | `SysvarS1otHashes111111111111111111111111111` | `sysvar_slot_hashes` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` |
| `core_solana_sysvar_slot_history_v1` | `SysvarS1otHistory11111111111111111111111111` | `sysvar_slot_history` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` |
| `core_solana_sysvar_stake_history_v1` | `SysvarStakeHistory1111111111111111111111111` | `sysvar_stake_history` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` |
| `core_solana_sysvar_v1` | `Sysvar1111111111111111111111111111111111111` | `sysvar` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` |
| `core_solana_vote_v1` | `Vote111111111111111111111111111111111111111` | `vote` | `program` | `kb_decoder_solana_core` | `core_handled` |
| `core_solana_zk_elgamal_proof_v1` | `ZkE1Gama1Proof11111111111111111111111111111` | `zk_elgamal_proof` | `program` | `kb_decoder_solana_core` | `core_handled` |
| `core_solana_zk_token_proof_v1` | `ZkTokenProof1111111111111111111111111111111` | `zk_token_proof` | `program` | `kb_decoder_solana_core` | `core_handled` |
| `core_spl_associated_token_account_v1` | `ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL` | `associated_token_account` | `program` | `kb_decoder_spl_associated_token_account` | `core_handled` |
| `core_spl_account_compression_v1` | `cmtDvXumGCrqC1Age74AVPhSRVXJMd8PJS91L8KbNCK` | `spl_account_compression` | `program` | `kb_decoder_spl_account_compression` | `core_specialized_reserved_current` |
| `core_spl_memo_v1` | `Memo1UhkJRfHyvLMcVucJwxXeuD728EqVDDwQDxFMNo` | `spl_memo_v1` | `program` | `kb_decoder_spl_memo` | `core_specialized_reserved_current` |
| `core_spl_memo_v3` | `MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr` | `spl_memo_v3` | `program` | `kb_decoder_spl_memo` | `core_specialized_reserved_current` |
| `core_spl_memo_v4` | `Memo4c2pN8afCj432Lb7RMVKi9PbQnnW7ewFFaV3oAH` | `spl_memo_v4` | `program` | `kb_decoder_spl_memo` | `core_specialized_reserved_current` |
| `core_spl_noop_v1` | `noopb9bkMVfRPU8AsbpTUg8AQkHtKwMYZiFUjNRtMmV` | `spl_noop` | `program` | `kb_decoder_spl_noop` | `core_specialized_reserved_current` |
| `core_spl_single_pool_v1` | `SVSPxpvHdN29nkVg9rPapPNDddN5DipNLRUFhyjFThE` | `spl_single_pool` | `program` | `kb_decoder_spl_single_pool` | `core_specialized_reserved_current` |
| `core_spl_name_service_v1` | `namesLPneVptA9Z5rqUDD9tMTWEJwofgaYwp8cawRkX` | `spl_name_service` | `program` | `kb_decoder_metadata_spl_name_service` | `core_specialized_reserved_current` |
| `core_spl_stake_pool_v1` | `SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy` | `stake_pool` | `program` | `kb_decoder_spl_stake_pool` | `core_specialized_reserved_current` |
| `core_spl_token2022_v2022` | `TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb` | `token2022` | `program` | `kb_decoder_spl_token_2022` | `core_handled` |
| `core_spl_token2022_elgamal_registry_v1` | `regVYJW7tcT8zipN5YiBvHsvR5jXW1uLFxaHSbugABg` | `spl_token2022_elgamal_registry` | `program` | `kb_decoder_spl_token_2022` | `core_specialized_reserved_current` |
| `core_spl_token_v1` | `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA` | `token` | `program` | `kb_decoder_spl_token` | `core_handled` |

View File

@@ -1,73 +0,0 @@
<!-- file: docs/CORE_STORE.md -->
<!-- version: 3 -->
# Store core Solana
## Évolution `0.3.4`
Le store core historique devient alimenté par un extracteur transactionnel à partir de `kb_sol_raw_transactions.canonical_json`.
| Table | Rôle |
|----------------------------------|------------------------------------------------------------|
| `kb_sol_core_transactions` | Transaction normalisée, statut et lien vers la ligne raw. |
| `kb_sol_core_account_keys` | Espace résolu statique + ALT avec flags Solana. |
| `kb_sol_core_instructions` | Instructions top-level et payload canonique hashé. |
| `kb_sol_core_inner_instructions` | Inner instructions rattachées à un chemin parent. |
| `kb_sol_core_logs` | Logs ordonnés, texte hashé et lien dinvocation optionnel. |
| `kb_sol_core_balance_changes` | Deltas natifs, SPL Token et Token-2022. |
| `kb_sol_ops_processing_ledger` | Version, hash, statut et tentatives du processor. |
## Écriture atomique
Une extraction réussie exécute dans la même transaction PostgreSQL :
1. validation du bundle ;
2. recherche dun graphe core existant ;
3. suppression en cascade de ce graphe pour la signature ;
4. insertion de la transaction et de toutes ses lignes filles ;
5. passage de la ligne raw à `core_extracted` ;
6. upsert du ledger en `succeeded` ;
7. commit.
Une erreur déclenche le rollback implicite de la transaction. Lenregistrement terminal dun échec utilise une transaction dédiée et marque la ligne raw `failed` avec un diagnostic rejouable.
## Clés didempotence
Les contraintes actives restent :
```text
core transaction : signature
account key : signature + account_index
instruction top-level : signature + instruction_path
inner instruction : signature + instruction_path
log : signature + log_index
balance change : signature + balance_change_index
ledger : stage + processor_name + processor_version + input_key
```
Le ledger ajoute `input_hash` à la décision de skip sans lajouter à la clé unique. Un nouvel hash met à jour la même identité de processor et augmente `attempt_count`.
## Sélection raw
Le contrat `CoreExtractionSelectionFilter` permet :
- une liste de signatures ;
- une plage inclusive de slots ;
- un état raw ;
- un program id déjà indexé dans les instructions core ;
- une limite stricte.
Le filtre par program id est un mode de replay. Il ne peut pas découvrir un programme dans une transaction qui na jamais encore été extraite.
## Repositories
`CoreExtractionStore` isole le pipeline du backend :
```text
list_raw_transactions_for_core_extraction
is_core_extraction_current
persist_core_extraction
mark_core_extraction_failed
```
Les repositories historiques dinsertion unitaire restent disponibles, mais le worker `0.3.4` utilise exclusivement lécriture atomique du bundle.

View File

@@ -1,155 +0,0 @@
<!-- file: docs/DATABASE.md -->
<!-- version: 11 -->
# Base de données
PostgreSQL est le backend principal prévu pour `khadhroony-bot2`. `0.2.0` fixe uniquement les conventions de stockage : les migrations complètes, repositories SQL et diagnostics applicatifs sont reportés aux jalons suivants.
## Décision PostgreSQL
Le projet ne crée pas de schémas PostgreSQL applicatifs explicites.
Le store utilise le schéma courant du profil PostgreSQL, généralement `public`. Le choix du schéma reste donc une responsabilité de configuration ou d'administration PostgreSQL, pas une responsabilité des migrations applicatives.
Interdits, écrits avec `DOT` pour que les audits textuels simples ne confondent pas documentation et usage réel :
```text
raw DOT kb_sol_rpc_transactions
core DOT kb_sol_transactions
obs DOT kb_sol_program_observations
decode DOT kb_sol_decoded_events
mat DOT kb_sol_trade_events
catalog DOT kb_sol_tokens
ops DOT kb_sol_processing_ledger
```
Autorisés :
```text
kb_sol_raw_transactions
kb_sol_core_transactions
kb_sol_obs_program_observations
kb_sol_decode_decoded_events
kb_sol_mat_trade_events
kb_sol_catalog_tokens
kb_sol_ops_processing_ledger
```
## Format canonique des tables Solana
Toutes les tables Solana applicatives suivent ce format :
```text
kb_sol_<domain>_<name>
```
Domaines autorisés au départ :
| Domaine | Rôle logique | Exemple de table |
|-----------|-------------------------------------------------------------------------------------|---------------------------------------|
| `raw` | transactions Solana canoniques, source-indépendantes et rejouables | `kb_sol_raw_transactions` |
| `core` | extraction Solana générique normalisée | `kb_sol_core_instructions` |
| `obs` | observations techniques de source, programmes, instructions, logs et discriminators | `kb_sol_obs_transaction_observations` |
| `decode` | événements décodés par les décodeurs | `kb_sol_decode_decoded_events` |
| `mat` | projections métier matérialisées | `kb_sol_mat_trade_events` |
| `catalog` | tokens, pools, paires et références stables | `kb_sol_catalog_pairs` |
| `agg` | agrégations temporelles ou analytiques | `kb_sol_agg_pair_candles` |
| `ops` | ledger de traitement, migrations applicatives et diagnostics | `kb_sol_ops_processing_ledger` |
| `wallet` | métadonnées wallet non sensibles | `kb_sol_wallet_accounts` |
Le domaine reste un préfixe de nom de table, jamais un schéma PostgreSQL.
## Décision de phasage à partir de `0.3.x`
`0.3.x` corrige le modèle dacquisition avant les décodeurs : transaction canonique source-indépendante, observations de source légères, backfill HTTP sur comptes gratuits et extraction vers `core`.
Les flux payants Helius `transactionSubscribe` et Yellowstone gRPC sont reportés à `0.10.x`, après les décodeurs Core, Pump, Meteora, Raydium, Orca et Jupiter. Ils devront alimenter exactement le même contrat canonique que `getTransaction`.
## Tables candidates initiales
Ces tables sont candidates, pas toutes implémentées en `0.2.0`.
| Table | Jalons pressentis | Rôle |
|---------------------------------------|--------------------|--------------------------------------------------------------------------------------------------------------------------|
| `kb_sol_raw_rpc_transactions` | `0.2.3` historique | Ancienne table validée puis remplacée pendant `0.3.1`; absente de la baseline SQL active. |
| `kb_sol_raw_transactions` | `0.3.1` | Stocker une transaction Solana canonique unique par signature, indépendante de la source. |
| `kb_sol_raw_ws_notifications` | `0.2.3` historique | Ancienne table supprimée pendant `0.3.1` après conversion des métadonnées utiles; absente de la baseline active. |
| `kb_sol_obs_transaction_observations` | `0.3.1` | Stocker source, protocole, méthode, timestamps, taille, latences et statuts sans dupliquer le payload transactionnel. |
| `kb_sol_core_transactions` | `0.2.4` | Ligne transaction normalisée liée à une signature. |
| `kb_sol_core_account_keys` | `0.2.4` | Comptes résolus, y compris loaded addresses. |
| `kb_sol_core_instructions` | `0.2.4` | Instructions top-level normalisées. |
| `kb_sol_core_inner_instructions` | `0.2.4` | Instructions internes normalisées. |
| `kb_sol_core_logs` | `0.2.4` | Logs de transaction et ordre d'apparition. |
| `kb_sol_core_balance_changes` | `0.2.4` | Deltas SOL/SPL dérivés du metadata RPC. |
| `kb_sol_obs_program_observations` | `0.3.4+` | Observations par programme invoqué, après stabilisation de l'ingestion et de l'extraction. |
| `kb_sol_obs_instruction_observations` | `0.3.4+` | Observations par instruction, discriminator et surface candidate, après stabilisation de l'ingestion et de l'extraction. |
| `kb_sol_decode_decoded_events` | `0.4.x+` | Événements décodés par surface et version de décodeur. |
| `kb_sol_mat_trade_events` | `0.5.x+` | Trades matérialisés. |
| `kb_sol_catalog_tokens` | `0.5.x+` | Catalogue de tokens observés. |
| `kb_sol_catalog_pools` | `0.5.x+` | Catalogue de pools observés. |
| `kb_sol_catalog_pairs` | `0.5.x+` | Catalogue de paires tradables. |
| `kb_sol_ops_processing_ledger` | `0.3.4+` | Ledger de traitements par module, version, input et statut, après stabilisation de l'ingestion. |
## Règles SQL générales
- `id` est la clé primaire technique, sauf exception explicitement documentée.
- `created_at` est le timestamp d'insertion.
- `updated_at` existe seulement si la table est mutable.
- `slot` est un `BIGINT` côté SQL ; les conversions Rust doivent être explicites.
- `signature` est un texte non vide quand applicable.
- `program_id` est un texte non vide quand applicable.
- `canonical_json` est un `JSONB` réservé à la représentation canonique source-indépendante de la transaction.
- `payload_json` est un `JSONB` réservé au payload décodé, enrichi ou matérialisé.
- Les index minimaux sont ajoutés selon l'usage : `signature`, `slot`, `program_id`, `created_at`.
- Les noms d'index utilisent un préfixe fonctionnel : `ux_` pour les index uniques et `ix_` pour les index non uniques, par exemple `ux_kb_sol_raw_transactions_signature` ou `ix_kb_sol_obs_transaction_observations_signature`.
- Les contraintes de clés nommées utilisent un préfixe fonctionnel : `pk_` pour les clés primaires et `fk_` pour les clés étrangères. Les contraintes de validation peuvent utiliser `ck_`.
- Les contraintes métier doivent rester strictes mais réversibles tant que les corpus ne sont pas stabilisés.
## Principe raw et cycle de vie
La couche `raw` conserve une seule représentation canonique de chaque transaction Solana. Elle ne conserve pas une copie complète par transport ou fournisseur.
Les adaptateurs `kb_onchain_transport` convertissent JSON-RPC, Helius WebSocket ou Yellowstone Protobuf vers le même contrat `kb_model`. Le payload canonique reste la source rejouable pour lextraction `core`, les décodeurs et les matérialisateurs.
La couche `obs` conserve les acquisitions successives : fournisseur, endpoint, protocole, méthode, commitment, timestamps, taille et statut. `kb_sol_obs_transaction_observations` ne contient pas de `raw_json` complet.
Les états de rétention sappliquent à la transaction canonique. Les observations techniques ont une politique de conservation séparée, car elles sont petites et utiles aux mesures de couverture et de latence.
Le contrat détaillé est décrit dans `docs/TRANSACTION_ACQUISITION_MODEL.md`. Le cycle de vie est décrit dans `docs/RAW_STORAGE_LIFECYCLE.md`. Le découpage core destiné aux décodeurs est décrit dans `docs/CORE_EXTRACTION_CONTRACTS.md`.
## Replay partiel
Le replay ne doit pas être limité à la transaction complète. Après extraction `core`, l'unité de scheduling principale devient l'instruction normalisée. Cela permet de traiter uniquement les instructions `Pending`, `Failed` ou `ReplayRequested`, sans rejouer toute une transaction déjà extraite.
Le décodage ne doit cependant pas être limité au payload de l'instruction. Les décodeurs doivent recevoir une entrée contextualisée : instruction ciblée, comptes résolus, inner instructions, logs, deltas de balance et statut de transaction.
Les contrats de replay par instruction sont décrits dans `docs/INSTRUCTION_REPLAY_CONTRACTS.md`. Les contrats d'extraction core sont décrits dans `docs/CORE_EXTRACTION_CONTRACTS.md`.
Chaque table dérivée doit pouvoir être reconstruite par au moins un des axes suivants quand l'information existe :
- module et version ;
- signature ;
- plage de slots ;
- `program_id` ;
- surface candidate ;
- discriminator ;
- état dans `kb_sol_ops_processing_ledger`.
## Frontière Rust store
`kb_store_core` définit les contrats indépendants du backend : DTOs, entities, health, pagination, erreurs et traits repository.
`kb_store_pg` implémente PostgreSQL : pool, migrations, requêtes SQL, repositories concrets et diagnostics du schéma courant.
Les structures Rust ne doivent pas être placées dans `queries/`. Les requêtes SQL, les binds et l'exécution SQL restent dans `queries/`; les types proches des lignes SQL restent dans `entities/`; les contrats applicatifs restent dans `dtos/`; les APIs de stockage restent dans `repositories/`.
## Statut `0.2.0`
`0.2.0` est un jalon de cadrage. Il ne doit pas introduire un grand schéma SQL. Les migrations présentes avant cette convention doivent être neutralisées ou remplacées avant d'être exécutées sur une base réelle.
## Ajout `0.3.4` — ledger de traitement
La table `kb_sol_ops_processing_ledger` devient la source de vérité de lidempotence par processor. Pour lextraction core, elle mémorise la signature, le hash canonique, la version, le statut, le nombre de tentatives et le dernier diagnostic.
Lécriture du succès ledger, le passage raw à `core_extracted` et le graphe core sont commités ensemble. Un statut `failed` reste rejouable et ne doit jamais être interprété comme une transaction canonique invalide de façon définitive.

View File

@@ -1,179 +0,0 @@
<!-- file: docs/DECODER_MATERIALIZATION_CONTRACTS.md -->
<!-- version: 17 -->
# Contrats communs de décodage et de matérialisation
## Objet
La version `0.4.0` introduit linfrastructure backend-agnostique utilisée par les futurs décodeurs Solana Core, SPL et protocolaires. Elle ne cherche pas encore à décoder maximalement un protocole précis.
Le flux commun est :
```text
core instruction contextualisée
-> dispatch déterministe
-> observation décodée versionnée
-> persistance atomique decode + couverture + ledger
-> matérialisation optionnelle explicitement autorisée
-> persistance atomique mat + ledger
```
## Input contextualisé
`MdCoreInstructionReplayInput` reste lunique contrat dentrée commun. Son contrat passe à la version `2` dans `0.4.1-pre.014`. Il contient la signature, le slot, le statut et lerreur on-chain, le chemin stable de linstruction, le program ID, les comptes résolus dans leur ordre original, le payload brut déterministe et son hash, toutes les instructions outer ordonnées par index numérique, les inner instructions descendantes, les logs reliés prudemment, les changements de balances et la version du contrat core.
`outer_instructions_json` est un tableau stable dont chaque entrée contient `instructionIndex`, `instructionPath`, `programId`, `payloadJson` et `payloadHash`. Linstruction cible est incluse. Cette projection provient des tables core existantes et ne nécessite aucune migration SQL.
Le hash de replay est calculé à partir de la sérialisation JSON canonique de cet input. Le skip exige la même étape, le même processor, la même version, la même clé dentrée, le même hash et un statut ledger réussi.
Le passage au contrat `2` modifie légitimement les hashes existants, car les payloads outer participent désormais à la sérialisation. Le pipeline reste en version `1` : la version du contrat core et le nouveau contexte suffisent à invalider les anciens skips. Un force replay est requis après mise à niveau.
## Contrat de décodeur
`DcApiInstructionDecoder` expose :
- une identité stable `name/version` ;
- les programmes et surfaces supportés ;
- une matrice de couverture déclarée ;
- une reconnaissance déterministe ;
- un résultat terminal `decoded`, `ignored`, `unsupported` ou `failed` ;
- zéro ou plusieurs observations typées uniquement pour `decoded` ;
- une preuve, une confiance et des diagnostics structurés.
Le dispatch est ordonné par compatibilité exacte, priorité déclarée, surface, code dentrée et identité stable. Il ne dépend ni du nom de la crate ni de lordre denregistrement implicite.
Avant la lecture du store, le pipeline calcule le périmètre effectif des programmes à partir de lunion des `program_id` déclarés par les décodeurs activés. Lorsque lopérateur fournit un filtre explicite, ce filtre doit être un sous-ensemble exact de ces programmes ; une valeur incompatible est refusée avant toute sélection SQL. Cette règle empêche un décodeur natif de consommer par défaut des instructions SPL ou protocolaires et évite de rejouer indéfiniment le même lot `unmatched` sans rapport avec les processors choisis.
Une instruction inconnue dun programme reconnu doit être classée sans produire de faux événement. Un `unmatched` reste possible lorsque le program ID est supporté mais que la reconnaissance contextuelle refuse linput ; il ne modifie pas globalement le lifecycle de linstruction pour ne pas empêcher un autre décodeur futur de la traiter.
## Transactions on-chain échouées
Une transaction échouée reste décodable lorsquun input structurel existe. Toute observation conserve :
```text
transaction_failed
transaction_error
observation_committed
```
`observation_committed` doit être faux lorsque la transaction a été annulée. Ces observations peuvent décrire une instruction tentée, un événement loggé avant lerreur, une classification déchec, une consommation de compute ou une surface appelée.
Elles ne peuvent pas produire automatiquement un trade réussi, une modification de liquidité réussie, un changement confirmé de catalogue ou une candle normale. `MtApiEventMaterializer` applique une politique explicite par famille. Les familles `trade`, `liquidity` et `lifecycle` sont refusées avant lappel au matérialiseur lorsque la source est échouée ou non commitée. Une seconde barrière valide ensuite les familles de sortie et nautorise, dans ce contexte, que les matérialisations daudit ou de risque.
## Persistance
Les tables actives sont :
- `kb_sol_decode_events` ;
- `kb_sol_decode_coverage_declarations` ;
- `kb_sol_decode_coverage_observations` ;
- `kb_sol_mat_events` ;
- `kb_sol_ops_processing_ledger`.
Aucun schéma PostgreSQL applicatif explicite nest créé. Les payloads et preuves JSONB utilisent des colonnes suffixées par `_jsonb`.
Le décodage persiste dans une transaction unique les observations, la couverture, létat lifecycle de linstruction et le ledger. La matérialisation persiste également ses sorties et son ledger dans une transaction unique. Un rollback à la dernière étape doit donc supprimer toutes les écritures précédentes de la même tentative.
Toute exécution non skippée remplace atomiquement les sorties du même processor, de la même version et de la même clé dentrée. Le force replay contourne uniquement le skip version/hash ; il ne supprime jamais les sorties dun autre processor, dune autre version ou dune autre clé. Les versions antérieures restent disponibles pour laudit.
Lorsquun force replay contient une liste explicite de signatures, le pipeline retire le filtre de lifecycle pour cette sélection bornée. Le même contournement est autorisé sans signatures uniquement lorsque lopérateur active explicitement le mode « toutes les signatures » ; la sélection reste alors limitée par les programmes compatibles, les instruction paths, les slots éventuels et la limite. Sans signatures ni cette autorisation explicite, la requête est refusée.
Les déclarations de couverture sont synchronisées comme un snapshot du couple processor/version. Le résultat de persistance distingue les lignes réellement insérées, modifiées, supprimées du snapshot ou strictement inchangées ; une déclaration identique est comptée comme `skipped`, pas comme une nouvelle insertion.
## Couverture
La couverture compare les entrées déclarées et observées, puis agrège :
- reconnaissance ;
- décodage ;
- matérialisation ;
- erreurs ;
- inconnues ;
- transactions réussies ;
- transactions échouées.
Une surface ne peut pas être considérée comme clôturée tant que toutes les instructions, événements et discriminants connus, y compris historiques et non liés au trading, ne sont pas classifiés.
## Traçabilité structurée
Chaque campagne reçoit un `campaign_id` process-local stable, propagé de la démo jusquaux décisions de dispatch, de ledger, de décodage, de matérialisation et de persistance. Des spans imbriqués de campagne, input et processor transmettent aussi ce contexte aux événements émis par les décodeurs et les stores sans modifier leurs contrats. Elle doit permettre de reconstruire précisément les décisions prises sans requête SQL libre. Les événements `debug` utilisent un champ `action` stable et conservent au minimum, selon létape :
- le nombre de signatures, un échantillon borné et la sélection normalisée ;
- les filtres demandés puis les `program_id` et états effectivement appliqués ;
- la signature, le slot, linstruction path, le program ID et la clé dinput ;
- le processor et sa version ;
- le hash déterministe pertinent ;
- la décision de dispatch, y compris lorsque `recognize` nest pas appelé à cause dun program ID incompatible ;
- le résultat de reconnaissance et de décodage ;
- le contrôle du ledger, le motif exact du skip ou son contournement par force replay ;
- le début et la validation de la persistance PostgreSQL ;
- le statut terminal et les compteurs par processor.
Les targets stables sont :
```text
kb_app_demo.demo_decode_replay
kb_app_demo.frontend.demo_decode_replay
kb_pipeline.decode_replay
kb_store_pg.decode_pipeline
kb_decoder_solana_core
```
Les signatures, slots, paths et program IDs sont des identifiants publics on-chain. Les listes complètes de signatures ne sont pas répétées à chaque couche : les événements de campagne conservent un compteur et un petit échantillon, tandis que les événements par input conservent la signature exacte. Les traces ne doivent pas enregistrer de DSN, secret, clé privée ni payload brut complet. Le payload dinstruction est représenté par son hash déterministe.
## Orchestration
`kb_pipeline::execute_decode_replay` fournit :
- sélection bornée par signatures, états, slots, program IDs et instruction paths ;
- zéro, un ou plusieurs décodeurs compatibles selon la politique choisie ;
- concurrence bornée ;
- arrêt coopératif ;
- skip version/hash ;
- force replay ;
- résumé par processor et statut ;
- matérialisation optionnelle après succès de la persistance decode.
La fenêtre Tauri `demo_decode_replay` ne contient aucune logique SQL libre. Elle construit une requête typée, appelle le pipeline et affiche les diagnostics read-only.
## Projections natives actives
`kb_materializer_lifecycle::LifecycleMaterializer` est enregistré dans `demo_decode_replay` à partir de `0.4.1-pre.003`. Son applicabilité est filtrée par surface, entrée et paramètres avant toute consultation du ledger ou application de politique. `pre.017` étend ses familles acceptées à `Lifecycle`, `Admin` et `Audit`, mais uniquement pour des observations exactes qui produisent réellement une mutation lifecycle. `pre.018` ajoute linitialisation/la fermeture des rapports Slashing sous `slashing_violation_report`, sans transformer le rapport en pénalité de stake. Il applique toujours `SuccessfulCommittedOnly`.
Les sorties stables actives sont :
- `address_lookup_table:<operation>:0` pour les cinq mutations ALT ;
- `program_loader:<surface>:<operation>:0` pour les mutations loader stables ;
- `feature_gate:revoke_pending_activation:0` pour la révocation Feature Gate ;
- `durable_nonce_account:<operation>:0` pour initialize, advance, authorize, upgrade et withdraw du System Program ;
- `zk_proof_context:<operation>:0` pour linitialisation dun contexte ZK ElGamal demandée par une vérification réussie et pour sa fermeture.
`authorize_nonce_account` reste décodé en famille `Admin`, mais sa mutation dautorité durable est promue en sortie `Lifecycle`. Les vérifications ZK ElGamal restent des événements `Audit`; elles ne sont acceptées par le matérialiseur que lorsque `contextStateRequested = true`. Une preuve sans contexte nest jamais proposée au matérialiseur.
Le retrait dun nonce account conserve une sémantique conditionnelle. Le runtime détruit le compte lorsque la totalité du solde est retirée ; linstruction seule ne suffit pas à reconstruire de manière certaine létat final transactionnel du compte. La projection décrit donc lopération commitée, conserve le montant demandé et indique explicitement que létat final nest pas capturé. Les deltas SOL ne sont pas dupliqués.
La création dun contexte ZK conserve le compte cible, son autorité et le type de preuve, sans matérialiser les octets de preuve. La fermeture conserve le compte, la destination des lamports et lautorité, puis décrit le reset vers le System Program. Lancien ZK Token Proof Program nest jamais matérialisé : son runtime actuel est un stub sans effet et sa sémantique historique nest pas attribuable à une transaction sans preuve de version.
Le hash dentrée matérialiseur reste dérivé de lobservation décodée complète. Le ledger conserve séparément les processors `solana_native_lifecycle`, `solana_native_admin` et `solana_native_compliance_audit`, leur version, la clé dinput et le hash. Une transaction échouée ou une observation non commitée est refusée avant toute sortie mutable.
`pre.020` répartit les responsabilités : create/allocate System restent dans lifecycle ; assignations System, Config `store` et changements dautorité Loader appartiennent à `kb_materializer_admin` ; writes/copies de bytecode Loader appartiennent à `kb_materializer_compliance_audit`. Les transferts SOL ne sont pas rematérialisés, car les balance changes core en sont la source canonique.
## Projections natives restantes
La couverture maximale dun décodeur nimplique pas une matérialisation systématique. Une projection nest ajoutée que lorsquelle possède une identité stable, un état cible explicite, une politique didempotence et suffisamment de contexte pour ne pas reconstruire une mutation fictive.
Les prochaines projections sont réparties par propriétaire :
- `kb_materializer_lifecycle` : créations et allocations System, sans dupliquer les deltas SOL ;
- `kb_materializer_admin` : assignations System, écritures Config opaques commitées et changements dautorité Loader ;
- `kb_materializer_compliance_audit` : écritures et copies de bytecode Loader, avec hash et préfixe borné sans payload complet ;
- `kb_materializer_staking` : intentions/transitions Stake et Vote commitées. `pre.021` active des projections instructionnelles pour comptes Stake/Vote, autorités, lockup, vote state, retraits et rewards ; un snapshot final exige toujours létat antérieur/suivant du compte, les crédits cumulés et les sysvars ;
- un matérialiseur transactionnel Compute Budget : profil fusionnant toutes les instructions Compute Budget du message.
Les surfaces suivantes restent volontairement en decode/audit :
- précompiles de signature, qui décrivent une vérification runtime sans état métier durable ;
- preuves ZK sans compte de contexte, qui nont pas de mutation persistante à projeter ;
- ancien ZK Token Proof Program, dont le runtime Agave `v4.1.1` est un stub sans effet.
Chaque ajout futur doit indiquer le matérialiseur propriétaire, la source détat et la politique de transaction, au lieu détendre automatiquement `solana_native_lifecycle`.

View File

@@ -1,49 +0,0 @@
<!-- file: docs/DECODER_SURFACE_AUDIT.md -->
<!-- version: 1 -->
# Audit des surfaces de décodage
Ce document suit les noms de crates de décodeurs réservés, les aliases probables et les surfaces à consolider. Il s'appuie sur les IDL locales du dossier `idls/` et sur les matrices de conception historiques importées dans l'archive de travail.
## Règle de décision
Un nom de décodeur devient canonique seulement si au moins un des critères suivants est vérifié :
- une IDL locale existe avec un `program_id` explicite ;
- le `program_id` est prouvé par corpus local ;
- le rôle de la surface est stable : DEX effectif, router, orderbook, launchpad, vault, lending, staking, etc. ;
- le nom respecte la nomenclature `<protocol>_<surface>` sans alias marketing ambigu.
Un nom historique sans `program_id` local reste en statut `alias_candidate` ou `watchlist`. Il ne doit pas recevoir de logique métier avant consolidation.
## Aliases et doublons à traiter
| Groupe | Canonique recommandé | Crates ou noms concurrents | Statut | Décision provisoire |
|------------------------|-----------------------------------------------------|-------------------------------------------------------|-------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| OKX Labs | `kb_decoder_okx_lab_v1` | `kb_decoder_okx_v1`, `kb_decoder_onchain_labs_dex_v1` | `alias_candidate` | L'IDL locale existe pour `okx_lab_v1` avec le programme `6m2CDdhRgxpH4WjvdzxAYbGxwdGUz5MziiL5jek2kBma`. Les noms `okx_v1` et `onchain_labs_dex_v1` ne doivent pas être implémentés séparément sans preuve contraire. |
| OKX Router | `kb_decoder_okx_dex_router` | `kb_decoder_okx_v2`, `kb_decoder_onchain_labs_dex_v2` | `alias_candidate` | L'IDL locale existe pour `okx_dex_router` avec le programme `proVF4pMXVaYqmy4NjniPh4pqKNfMmsihgd4wdkCX3u`. Les noms `okx_v2` et `onchain_labs_dex_v2` restent des noms historiques à vérifier. |
| GooseFX | `kb_decoder_goosefx_v2`, `kb_decoder_goosefx_gamma` | `kb_decoder_goosefx_v1` | `watchlist` | `goosefx_v2` et `goosefx_gamma` ont des IDL locales et des programmes distincts. `goosefx_v1` reste une entrée historique sans IDL locale dans l'archive courante. |
| Fusion AMM | `kb_decoder_fusion_amm` | `kb_decoder_fusionamm` | `alias_candidate` | L'IDL locale se nomme `fusion_amm`, mais son metadata interne peut utiliser `fusionamm`. Le crate canonique doit rester lisible : `fusion_amm`. |
| PancakeSwap | `kb_decoder_pancakeswap` | `kb_decoder_pancake_swap` | `alias_candidate` | L'IDL locale se nomme `pancakeswap`. Le crate avec underscore supplémentaire doit rester non canonique. |
| Orca Wavebreak | `kb_decoder_orca_wavebreak` | `kb_decoder_wavebreak` | `alias_candidate` | L'IDL locale se nomme `orca_wavebreak`. Le nom sans protocole est trop ambigu. |
| Jupiter Limit Order v2 | `kb_decoder_jupiter_limit_order_v2` | `kb_decoder_jupiter_limit_order_2` | `alias_candidate` | L'IDL locale utilise `jupiter_limit_order_v2`. Le suffixe `_2` ne doit pas être utilisé. |
| dFlow | `kb_decoder_dflow_v4` | `kb_decoder_dflow_aggregator_v4` | `alias_candidate` | L'IDL locale se nomme `dflow_v4`. Le nom `dflow_aggregator_v4` peut rester comme alias historique mais ne doit pas porter une implémentation distincte sans `program_id` différent. |
| Meteora DAMM v1 | `kb_decoder_meteora_damm_v1` | `kb_decoder_meteora_pools_amm` | `alias_candidate` | Les matrices historiques indiquent que `meteora_pools` peut être un alias de DAMM v1. La consolidation doit être décidée par `program_id`, corpus et naming final. |
| Raydium LaunchLab | `kb_decoder_raydium_launchlab` | `kb_decoder_raydium_launchpad` | `naming_mismatch` | L'IDL locale se nomme `raydium_launchlab`. L'ancien nom `launchpad` décrit la famille métier, mais pas forcément la surface canonique. |
| Raydium Lock | `kb_decoder_raydium_lock` | `kb_decoder_raydium_liquidity_locking` | `naming_mismatch` | L'IDL locale se nomme `raydium_lock`. Le nom `liquidity_locking` est descriptif. La surface canonique doit être confirmée avant implémentation. |
| Raydium Pool v4 | `kb_decoder_raydium_amm_v4` | `kb_decoder_raydium_pool_v4` | `audit_only` | La note historique indique que `raydium_pool_v4` ne doit pas être promu comme décodeur autonome sans `program_id` distinct et corpus local. |
## Actions recommandées
- Ne pas supprimer immédiatement les crates aliases tant que le squelette sert de matrice de réservation.
- Ne pas implémenter deux décodeurs pour le même `program_id`.
- Ajouter dans chaque décodeur un mapping explicite `surface_code`, `program_code` et `program_id` dès que le corpus commence.
- Déplacer les aliases historiques vers une table de catalogue ou un document de watchlist quand le support réel commence.
- Supprimer ou fusionner les crates aliases seulement dans un delta dédié, avec validation `cargo build` et manifeste de suppression.
## Surfaces à ajouter ou renommer plus tard
- Ajouter `kb_decoder_raydium_launchlab` si la décision est de refléter strictement le nom de l'IDL locale.
- Vérifier si `kb_decoder_raydium_launchpad` doit devenir un alias documentaire ou rester une surface métier.
- Vérifier si `kb_decoder_meteora_pools_amm` doit être fusionné dans `kb_decoder_meteora_damm_v1`.
- Vérifier si les crates `okx_v1`, `okx_v2`, `onchain_labs_dex_v1` et `onchain_labs_dex_v2` doivent être supprimés après confirmation des deux programmes OKX canoniques.

View File

@@ -1,74 +0,0 @@
<!-- file: docs/DELTA_WORKFLOW.md -->
<!-- version: 3 -->
# Workflow de livraison delta
Les règles normatives de livraison sont définies dans [`../RULES_GENERAL.md`](../RULES_GENERAL.md). Ce document décrit leur application pratique.
## Nommage
Delta multi-module ou racine :
```text
khadhroony-bot3_vX.Y.Z-pre.abc-delta.zip
```
Delta limité à un package :
```text
kb-modulename_vX.Y.Z-pre.abc-delta.zip
```
Correctif dune prerelease déjà livrée :
```text
khadhroony-bot3_vX.Y.Z-pre.abc-delta-fix-001.zip
```
La numérotation des correctifs recommence à `fix-001` pour chaque nouvelle prerelease.
## Contenu
Chaque archive contient uniquement :
- les fichiers ajoutés ;
- les fichiers modifiés ;
- un `delta.md` non versionné à la racine.
Elle exclut :
- les fichiers inchangés ;
- `Cargo.lock` ;
- `package-lock.json` ;
- `node_modules/`, `target/`, `dist/` et les autres sorties de build ;
- `gen/`, les bindings TS-RS générés et tout autre code régénérable ;
- les logs, caches, PID, bases et données locales ;
- les fichiers `.env` réels et toute configuration contenant des secrets ;
- les fichiers dIDE ou propres à la machine ;
- les empreintes SHA256 ;
- les fichiers supprimés, qui doivent être indiqués comme suppressions manuelles.
`.env.example`, `.gitignore` et les autres fichiers source explicitement maintenus peuvent être livrés. `delta.md` est généré spécialement pour le ZIP et reste obligatoire même si les documents `delta*.md` sont ignorés dans le dépôt.
## Contrat de `delta.md`
`delta.md` indique obligatoirement :
- la base requise ;
- les correctifs antérieurs requis ;
- les fichiers ajoutés ;
- les fichiers modifiés ;
- les fichiers à supprimer manuellement ;
- les validations exécutées ;
- les validations non exécutées ;
- les remarques dapplication et de compatibilité.
## Application
1. Partir de la base indiquée.
2. Appliquer les deltas et correctifs antérieurs dans lordre indiqué.
3. Extraire larchive à la racine du workspace.
4. Effectuer les suppressions manuelles listées dans `delta.md`.
5. Lancer les validations demandées.
Une archive déjà livrée ne doit jamais être remplacée silencieusement sous le même nom.

View File

@@ -1,91 +0,0 @@
<!-- file: docs/DEVELOPMENT_ORDER.md -->
<!-- version: 9 -->
# Ordre de développement
## Principe
La priorité est de rendre chaque transaction exploitable avant de payer un flux temps réel enrichi. Le développement suit donc lordre : acquisition gratuite, transaction canonique, extraction core, décodeurs, matérialisations, puis sources live payantes.
## Ordre cible après `0.2.x`
- [x] `0.1.x` : logging, configuration, clients HTTP/WS standard, rôles et démos RPC.
- [x] `0.2.0` à `0.2.5` : conventions PostgreSQL, stores raw/core historiques et diagnostics SQL.
- [x] `0.3.0` : cadrage Agave local historique, ensuite abandonné comme axe actif après mesures réelles.
- [x] `0.3.1` : transaction canonique, observations légères, validation PostgreSQL réelle et consolidation de la baseline SQL.
- [x] `0.3.2` : modèle canonique et adaptateur HTTP `getTransaction`.
- [x] `0.3.3` : backfill gratuit par signatures, programme, token et pool, avec parcours avant/après et arrêt coopératif borné.
- [~] `0.3.4` : extraction core, navigateur de candidats, intégrité et replay validés ; derniers tests automatisés de rollback/annulation à exécuter.
- [ ] `0.4.0` : infrastructure commune de décodage et de matérialisation.
- [ ] `0.4.1+` : décodeurs et matérialisations Solana Core/SPL.
- [ ] `0.5.x` : Pump.
- [ ] `0.6.x` : Meteora.
- [ ] `0.7.x` : Raydium.
- [ ] `0.8.x` : Orca.
- [ ] `0.9.x` : Jupiter, routeurs et surfaces complémentaires.
- [ ] `0.10.x` : Helius `transactionSubscribe`, Yellowstone gRPC, fallback standard et comparaison fournisseur.
- [ ] `0.11.x` : wallet, sécurité et démos devnet.
- [ ] `0.12.x` : listeners métier et trading assisté.
## Ordre technique de stockage
1. Maintenir une baseline SQL courante ne contenant que les tables actives.
2. Normaliser chaque source vers un contrat canonique dans `kb_model`.
3. Écrire une transaction unique dans `kb_sol_raw_transactions`.
4. Écrire une observation légère dans `kb_sol_obs_transaction_observations`.
5. Extraire les tables `kb_sol_core_*` depuis la transaction canonique.
6. Ajouter les observations programme/instruction nécessaires aux décodeurs.
7. Ajouter les tables `kb_sol_decode_*` et `kb_sol_mat_*` par surface.
8. Ajouter les sources live payantes seulement lorsque les décodeurs peuvent exploiter immédiatement le flux.
## Séquence par surface
```text
program ids
-> corpus de signatures
-> backfill gratuit
-> decodeur maximal
-> événements stables
-> matérialisation complète
-> replay et anti-régression
-> listener live
```
## Démos
`kb_app_demo` reste le shell unique pour :
- diagnostics DB ;
- backfills ;
- inspection canonique/core ;
- couverture des décodeurs ;
- comparaison future des sources live ;
- wallet et sécurité.
## Contraintes permanentes
- Ne pas créer de schémas PostgreSQL applicatifs explicites.
- Utiliser le format `kb_sol_<domain>_<name>`.
- Ne pas placer de structures Rust dans `queries/`.
- Ne pas faire dépendre les décodeurs du store concret.
- Ne pas faire dépendre les décodeurs du fournisseur dacquisition.
- Intégrer Helius et Yellowstone dans `kb_onchain_transport`, sans crate provider séparée.
- Ne pas modifier `CHANGELOG.md` avant validation locale du jalon.
## État de clôture `0.3.4-pre.011`
Lordre technique est concrétisé jusquà lécriture core et aux outils de replay :
```text
backfill HTTP
-> transaction canonique
-> sélection raw bornée
-> extraction core pure
-> commit PostgreSQL atomique
-> ledger version/hash
-> sélection et export de corpus
```
Les validations réelles couvrent 70 transactions core, lintégrité SQL, lécriture CSV, le skip et le force replay sur 14 signatures. `pre.011` automatise le dernier contrôle de rollback PostgreSQL et rend les attentes réseau/retry annulables.
Lancien jalon `0.3.5` est supprimé. Après validation de `pre.011` et mise à jour du changelog, la prochaine version active est directement `0.4.0`.

View File

@@ -1,119 +0,0 @@
<!-- file: docs/DEVNET_EXECUTION.md -->
<!-- version: 3 -->
# Validation dexécution Devnet
Ce document décrit le premier parcours réseau réel de la couche dexécution native et sa fenêtre Tauri Devnet. Le test backend reste opt-in et aucune activation Mainnet nest autorisée.
## Périmètre
Le parcours exécute une instruction System transfer depuis le wallet temporaire persistant du profil `local_devnet` vers un destinataire éphémère créé uniquement pour le test.
```text
wallet persistant
-> vérification du genesis hash Devnet
-> contrôle du destinataire et du minimum rent-exempt
-> lecture du solde
-> airdrop plafonné si nécessaire
-> plan System transfer
-> blockhash et estimation des frais
-> simulation exacte
-> signature locale
-> envoi avec preflight
-> confirmation bornée
-> getTransaction
-> insertion canonique
-> extraction core
-> decode replay System
```
Les clés privées restent dans `kb_wallet`. Elles ne sont ni sérialisées dans les résumés, ni envoyées à une WebView, ni écrites dans PostgreSQL ou les logs.
## Préconditions
- le profil `local_devnet` doit rester configuré sur le genesis hash Devnet officiel ;
- `temporary_wallet_enabled`, `temporary_wallet_persist` et `devnet_send_enabled` doivent être actifs ;
- la simulation et la confirmation opérateur doivent rester obligatoires ;
- PostgreSQL doit être disponible pour la validation canonique/core/decode ;
- le rôle `http_queries` doit accepter `getTransaction` et les lectures dexécution ;
- le rôle `http_transactions` doit accepter simulation, envoi et lecture des statuts.
Le wallet persistant par défaut est créé sous :
```text
wallets/temporary/local_devnet/local-devnet-operator.json
```
Ce fichier nest pas chiffré. Il est exclusivement destiné à Localnet/Devnet et ne doit jamais recevoir de fonds réels.
## Exécution du test réel
Depuis la racine du workspace :
```bash
KB_DEVNET_EXECUTION_TEST=1 \
KB_POSTGRES_TEST_URL='postgres://solana:solana@localhost:5432/solana_test' \
KB_DEVNET_WALLET_DIR='./wallets/temporary/local_devnet' \
KB_DEVNET_AIRDROP_LAMPORTS=0 \
KB_DEVNET_TRANSFER_LAMPORTS=1000000 \
cargo test -p kb_pipeline optional_devnet_system_transfer_from_env -- --nocapture
```
Variables :
- `KB_DEVNET_EXECUTION_TEST=1` autorise explicitement le test réseau ;
- `KB_POSTGRES_TEST_URL` sélectionne la base de validation ;
- `KB_DEVNET_WALLET_DIR` peut isoler le wallet utilisé par le test ;
- `KB_DEVNET_AIRDROP_LAMPORTS` fixe le montant maximal demandé au faucet lorsque le solde est insuffisant ;
- `KB_DEVNET_TRANSFER_LAMPORTS` fixe le transfert System réel.
Les valeurs restent soumises aux plafonds de `ExecutionConfig`. Une valeur dairdrop supérieure à `devnet_airdrop_max_lamports` ou un transfert supérieur à `devnet_max_spend_lamports` est refusé avant tout appel mutable.
## Résultat attendu
Pour un destinataire inexistant, le pipeline appelle `getAccountInfo`, puis `getMinimumBalanceForRentExemption` avec une longueur de données nulle. Le transfert est refusé avant simulation lorsquil est inférieur au minimum retourné. Lorsquune simulation échoue malgré ces contrôles, lerreur remontée conserve lerreur runtime structurée et les vingt premières lignes de logs.
Le test doit confirmer :
- cluster classifié `Devnet` ;
- simulation exacte réussie ;
- signature locale vérifiée ;
- signature RPC identique à la signature calculée ;
- statut `confirmed` ou `finalized` ;
- transaction canonique présente ou déjà existante ;
- extraction core terminée ou déjà courante ;
- decode replay System terminé sans input unmatched ou failed.
Lairdrop peut être absent lorsque le wallet possède déjà un solde suffisant. Le destinataire reste éphémère et sa clé privée nest pas persistée. Après signature, tout échec ultérieur conserve la signature dans le résumé avec un diagnostic de létape concernée.
## Fenêtre Tauri
`demo_execution_solana_core` est accessible depuis la fenêtre principale. Elle expose uniquement les profils Devnet utilisant un wallet temporaire persistant. Elle permet de générer une adresse destinataire jetable, de simuler exactement le message ou de signer/envoyer après confirmation opérateur. Le plan, les comptes, les signataires, la simulation, la confirmation et les résultats canonical/core/decode sont affichés en lecture seule. La clé privée du wallet source reste exclusivement dans le backend Rust.
Un airdrop demandé par la fenêtre reste soumis au plafond du profil et peut échouer lorsque le faucet public est limité. Un wallet déjà financé peut être utilisé avec une valeur dairdrop nulle.
## Limites
- le faucet Devnet peut appliquer des limites temporaires ;
- `getTransaction` peut devenir disponible après la confirmation de statut, doù les retries bornés ;
- le parcours utilise actuellement une transaction legacy avec recent blockhash ;
- durable nonce, ALT et transactions v0 seront validés dans des tranches dédiées ;
- aucune opération Mainnet nest autorisée par ce test.
## Validation de clôture `0.4.2`
Le 13 juillet 2026, la commande complète a été exécutée avec :
```bash
KB_DEVNET_EXECUTION_TEST=1 \
KB_POSTGRES_TEST_URL='postgres://solana:solana@localhost:5432/solana_test' \
KB_DEVNET_WALLET_DIR='./wallets/temporary/local_devnet' \
KB_DEVNET_AIRDROP_LAMPORTS=0 \
KB_DEVNET_TRANSFER_LAMPORTS=1000000 \
cargo test -p kb_pipeline -- --nocapture
```
Les 56 tests de `kb_pipeline` ont réussi, y compris `optional_devnet_system_transfer_from_env`. Le wallet était déjà financé, aucun airdrop na été demandé et le parcours a confirmé la chaîne complète jusquau replay post-exécution. Les 45 tests de `kb_store_pg` ont également réussi avec PostgreSQL réel.
Cette validation ne généralise pas lautorisation à toutes les opérations administratives stateful. Elle prouve le parcours dorchestration commun ; ALT, Config, Feature, Slashing, ZK, Stake, Vote et loaders restent soumis à leurs contrôles spécifiques avant toute future activation mutable.

View File

@@ -0,0 +1,110 @@
<!-- file: docs/DEVNET_EXECUTION_GUIDE.md -->
<!-- version: 3 -->
# Guide dexécution Devnet
## 1. Objet
Ce guide est créé avant la campagne Devnet puis corrigé pendant les essais réels. Il décrit uniquement les scénarios exposés par `kb-app-demo-desktop` et `kb-pipeline-demo-scenarios`.
## 2. Préparation du profil
1. Copier `.env.example` vers `.env` et renseigner au minimum `KB_POSTGRES_DEVNET_URL`.
2. Vérifier que `KB_POSTGRES_DEVNET_URL`, `KB_POSTGRES_MAINNET_URL` et `KB_POSTGRES_TEST_URL` désignent trois bases distinctes.
3. Sélectionner le profil `local_devnet` ou le profil Devnet explicitement autorisé dans `example.config.json`.
4. Vérifier que lenvoi mainnet reste désactivé.
5. Vérifier les plafonds de frais, de dépense et les politiques `simulation-first`.
6. Démarrer lapplication avec la configuration de développement attendue.
7. Contrôler dans la fenêtre Configuration que `local_devnet` utilise bien la base Devnet et non la base Mainnet.
## 3. Wallet de démonstration
Créer un wallet dédié avec les outils Solana installés localement, conserver le fichier hors du dépôt et vérifier ses permissions privées. Relever la pubkey sans copier la clé privée dans linterface ou les logs.
Champs à consigner pendant les tests :
- alias du wallet ;
- pubkey ;
- cluster ;
- solde initial ;
- source de financement Devnet ;
- date du test.
## 4. Financement Devnet
Le financement doit être réalisé avec un faucet Web Devnet. La commande `solana airdrop` nest pas considérée comme une procédure valide dans lenvironnement de validation. Fournir uniquement la pubkey au faucet, ne jamais transmettre le fichier du wallet ni sa clé privée, puis vérifier le solde via la fenêtre HTTP ou une lecture RPC non mutable.
## 5. Ordre des tests existants
### 5.1 Solana Core
- génération dun destinataire ;
- transfert System en simulation ;
- envoi après confirmation opérateur ;
- confirmation réseau ;
- extraction Core ciblée ;
- Decode replay ciblé ;
- vérification des projections.
### 5.2 SPL Memo v4
- saisir un texte borné ;
- vérifier le plan et les signers ;
- simuler ;
- envoyer ;
- confirmer ;
- vérifier lannotation de transaction et lidempotence du replay.
### 5.3 SPL Token classique
- préparer mint et comptes contrôlés ;
- exécuter les scénarios non destructifs avant le lifecycle complet ;
- documenter chaque signature et chaque solde brut avant/après ;
- vérifier replay et matérialisation.
### 5.4 ATA
- dériver lATA classique et Token-2022 ;
- simuler la création idempotente ;
- envoyer uniquement après contrôle du payer et du plafond de rent ;
- vérifier la projection lifecycle.
### 5.5 Token-2022 et registre ElGamal
- utiliser uniquement les scénarios explicitement disponibles dans linterface ;
- conserver les preuves de préflight, comptes, extensions et signers ;
- distinguer registre ElGamal et programme Token-2022 ;
- vérifier les projections admin, token, fee, metadata et risk attendues.
## 6. Future fenêtre Metadata
La fenêtre `demo_execution_metadata` sera ajoutée avec le pipeline metadata général. Lordre prévu est :
1. SPL Token Metadata incorporé à Token-2022 ;
2. programme Metaplex Token Metadata ;
3. éventuel enrichissement off-chain via `kb-offchain-transport`, sans couplage au replay canonique.
## 7. Preuves à conserver par scénario
- profil et cluster ;
- paramètres saisis ;
- plan exact ;
- signers requis ;
- estimation des frais ;
- résultat de simulation ;
- signature denvoi ;
- confirmation ;
- résumé dextraction/replay ;
- projections matérialisées ;
- diagnostics et écarts observés.
## 8. Critères de validation
Un scénario nest validé que si :
- la simulation réussit ;
- lenvoi est explicitement confirmé ;
- la confirmation réseau correspond à la signature ;
- le replay post-exécution ne produit ni échec fonctionnel ni erreur de traitement ;
- les projections attendues sont présentes et idempotentes ;
- le guide est corrigé lorsque le comportement réel diffère des étapes écrites.

View File

@@ -1,387 +0,0 @@
<!-- file: docs/EXECUTION_MODEL.md -->
<!-- version: 29 -->
# Modèle d'exécution
Ce document décrit la couche d'exécution universelle du workspace.
## Séparation des responsabilités
Un décodeur lit une transaction existante. Un exécuteur prépare une opération future. Les deux couches peuvent partager une surface canonique, mais elles ne doivent pas dépendre l'une de l'autre.
```text
kb_decoder_amm_pump_swap -> observation, décodage, audit
kb_executor_amm_pump_swap -> construction future d'instructions d'achat/vente
```
## Bibliothèques universelles
Le trading est le premier consommateur du workspace, pas la limite de ses crates. Les exécuteurs doivent pouvoir être réutilisés par une CLI, un worker, un outil d'administration, une application de jeu, une application Tauri ou un service autonome.
Cette universalité implique :
- un intent typé indépendant de l'interface utilisateur ;
- un plan déterministe sans I/O ;
- des builders couvrant les opérations officiellement appelables, y compris administratives ou dangereuses ;
- des politiques de sécurité séparées du builder ;
- une exposition UI volontairement plus étroite que la capacité de la bibliothèque ;
- aucune dépendance vers les décodeurs pour construire ou signer une transaction.
Une opération dangereuse ne doit pas être supprimée de l'exécuteur. Elle doit être implémentée, testée, classifiée et soumise à une politique renforcée. `kb_app_demo` peut ne jamais l'exposer.
## Couches
- `kb_execution_api` définit les contrats communs des exécuteurs.
- `kb_execution_safety` regroupe les validations avant simulation, signature ou envoi.
- `kb-lib::executor::solana::transaction` assemble les plans en messages/transactions Solana et orchestre la signature sans RPC.
- `kb_executor_solana_core` construit les instructions des programmes natifs.
- `kb_wallet` isole les secrets et fournit des signataires.
- `kb_onchain_transport` fournit simulation, envoi et confirmation.
- `kb_pipeline` peut orchestrer la validation post-exécution par réingestion et replay.
- `kb_app_demo` ne fait qu'orchestrer une sélection sûre de ces capacités.
## Pipeline obligatoire
```text
intent
-> execution plan
-> policy checks
-> transaction build
-> simulation / dry-run
-> signature
-> send
-> confirmation
-> post-execution decode replay validation
```
Construction, signature, envoi et validation ne doivent jamais être fusionnés dans une fonction opaque.
## Politique de couverture
`Supported` signifie que le builder et son contrat de comptes/signataires sont implémentés. `Unsupported(reason)` reste acceptable uniquement lorsqu'une surface n'est pas appelable par transaction, a été retirée du runtime, ne dispose pas encore d'une source officielle suffisante ou constitue une dette temporaire explicitement planifiée.
L'objectif de clôture de `kb_executor_solana_core` est de ne laisser aucune instruction native officiellement appelable oubliée. Les variantes historiques uniquement décodables ne doivent pas être artificiellement réémises.
## Adaptateurs RPC de simulation
`0.4.2-pre.004` ajoute dans `kb_onchain_transport` les premières lectures nécessaires avant signature :
```text
getGenesisHash
getLatestBlockhash
getFeeForMessage
simulateTransaction
```
Le genesis hash sert à classifier les clusters publics connus. Le réseau de production est nommé Mainnet dans le contrat public du workspace ; le hash est inchangé et certains endpoints/CLI conservent encore lalias historique `mainnet-beta`. Un hash inconnu reste explicite et nest pas automatiquement assimilé à Devnet ou Mainnet. Le blockhash et sa dernière block height valide sont conservés séparément. Lestimation des frais accepte une valeur nulle lorsque le message référence un blockhash expiré.
La simulation accepte une transaction base64 non signée lorsque `sigVerify = false`; `replaceRecentBlockhash = true` permet au nœud de remplacer le blockhash avant simulation. Les erreurs runtime restent un résultat de simulation typé et ne sont pas confondues avec une erreur HTTP ou JSON-RPC.
`kb_onchain_transport` ne fabrique pas le contexte de sécurité : cluster attendu, âge du blockhash, nonce account et nonce authority sont fournis explicitement lors de la conversion vers `ExApiExecutionSimulationResult`. Depuis `pre.013`, `getAccountInfo` possède aussi un mode données complètes borné : le mode metadata-only conserve `dataSlice.length = 0`, tandis que `confirmed_with_data(max_data_bytes)` exige un tuple base64 complet dont la longueur décodée égale `space`.
## Assemblage et signature Solana
`0.4.2-pre.005` introduit `kb-lib::executor::solana::transaction`, frontière commune entre les exécuteurs et les adaptateurs RPC. La crate convertit les `ExApiPlannedInstruction` en instructions SDK, compile le message avec son fee payer et sa source de blockhash, puis vérifie que les signataires réellement compilés correspondent exactement au contrat du plan.
La transaction non signée fournit deux sorties distinctes :
```text
message base64 -> getFeeForMessage
transaction non signée -> simulateTransaction(sigVerify=false, replaceRecentBlockhash=false)
```
Le résultat de simulation est lié au hash exact du message et à la valeur de blockhash ou nonce compilée. Une simulation avec remplacement de blockhash reste utile au diagnostic, mais ne peut pas autoriser la signature du message original. La signature refuse un résultat provenant dun autre message ou dune autre valeur nonce, réévalue `kb_execution_safety`, exige la décision `Allow`, puis résout tous les signataires via linterface Solana `Signer`. Les signataires manquants, supplémentaires ou dupliqués sont refusés. La transaction signée reste en mémoire/backend et nest ni envoyée ni exposée automatiquement à Tauri.
La sérialisation transactionnelle utilise le schéma officiel `wincode` fourni par les types Solana et applique la limite réseau de 1 232 octets. Aucun appel direct à `bincode` nest ajouté.
### Chemin durable nonce réel — `pre.013`
Le lifecycle dun compte nonce et la consommation dun durable nonce sont deux contrats distincts. Les opérations `initialize`, `advance`, `authorize`, `withdraw` et `upgrade` administrent le compte avec une politique `Latest`. Une transaction métier utilisant un nonce durable suit le chemin stateful suivant :
```text
getAccountInfo complet et borné à la taille nonce officielle
-> validation owner System Program / non-executable / space exact
-> décodage wincode Versions::Current(State::Initialized)
-> concordance compte et autorité avec ExecutionBlockhashPolicy
-> Message::new_with_nonce
-> AdvanceNonceAccount en instruction 0
-> valeur nonce comme recent_blockhash du message
-> simulation exacte sans remplacement
-> signature du même hash de message et de la même valeur nonce
```
`kb_executor_solana_core` ajoute lautorité nonce aux signataires requis du plan métier. `kb-lib::executor::solana::transaction` refuse les états legacy ou non initialisés, conserve le plan source immuable, expose un plan effectif avec lavance injectée et exige que le SDK reconnaisse la transaction comme durable nonce. La lecture RPC, lassemblage, la simulation et la signature restent des étapes séparées.
### Builders Address Lookup Table — `pre.015`
`kb_executor_solana_core` couvre les cinq opérations client de linterface Address Lookup Table : création, extension, gel, désactivation et fermeture. Le builder stateless garantit le program ID, le payload, lordre des comptes et les signataires exacts, mais ne prétend pas connaître létat courant du compte ni le coût de rent calculé par le runtime.
```text
intent ALT typé
-> builder officiel exact
-> plan avec autorité/payer explicites
-> lecture RPC stateful du compte et du slot
-> contrôle owner / autorité / état / capacité / cooldown
-> calcul du top-up rent-exempt et simulation exacte
-> politique de dépense
-> signature et envoi
```
La création dérive la table depuis lautorité et un slot récent. Lextension conserve lordre des adresses, exige une liste non vide et borne linput à la capacité maximale officielle ; la capacité restante et le top-up effectif doivent être contrôlés sur le compte réel. Le gel est irréversible. La fermeture nest autorisée quaprès désactivation et expiration du cooldown lié aux slots. `requested_spend_lamports` reste nul dans le plan ALT parce quaucun montant de rent nest encodé directement dans linstruction ; lorchestrateur doit calculer le top-up à partir du compte réel et du minimum rent-exempt, le comparer au plafond de dépense, puis confirmer linstruction par simulation.
### Précompiles de signature — `pre.016`
Les précompiles Ed25519, secp256k1 et secp256r1 sont des vérifications natives, pas des signatures de transaction. Leur plan ne déclare aucun compte applicatif ni signataire propre ; le fee payer signe uniquement la transaction. Le programme métier qui consomme la preuve doit inspecter linstruction correspondante et appliquer lui-même son contrat dautorisation.
```text
message + signature + clé/adresse
-> builder inline ou table doffsets officielle
-> instruction précompile sans comptes
-> positionnement transactionnel exact
-> programme consommateur qui inspecte le sysvar dinstructions
-> simulation exacte
-> signature Solana du fee payer et des signataires métier distincts
```
Les formes inline Ed25519 et secp256r1 utilisent `u16::MAX` comme référence à leurs propres données. secp256k1 encode des index dinstruction `u8` sans sentinelle ; la forme inline et les références locales du builder exigent donc que linstruction secp256k1 soit à lindex transactionnel `0`. Un futur assembleur multi-plans doit refuser ou réécrire explicitement toute combinaison qui violerait cette position.
Les tables avancées acceptent des références externes et un buffer local ajouté après les offsets. Le builder borne le nombre dentrées à 255, la taille totale à 65 535 octets et les plages locales connues. Il ne lit pas les données des autres instructions : leur cohérence cryptographique est vérifiée par le runtime et leur signification métier par le programme consommateur.
La signature secp256r1 est fournie au format compact `r || s`; le builder exige des composants non nuls et la forme low-S imposée par le runtime. Le builder secp256k1 reçoit la signature compacte, le recovery ID et ladresse Ethereum déjà dérivée ; il ne manipule aucune clé privée et nactive aucun helper `bincode`. Le runtime secp256k1 ne garantit pas la canonicalité low-S : lorsquelle est requise, cette politique appartient au programme consommateur ou à une validation métier explicite.
### Config, Feature, Slashing et ZK ElGamal — `pre.017`
Les opérations administratives natives restent des plans déterministes sans accès RPC implicite.
```text
état/rent fourni par lorchestrateur
-> builder exact
-> plan et signataires
-> lecture stateful de confirmation
-> simulation exacte
```
Config encode manuellement le contrat `ConfigKeys + données sérialisées` afin de ne pas activer le helper `bincode` de linterface. Feature reproduit les séquences officielles dactivation et de révocation. Les montants de rent sont des entrées explicites comptabilisées dans le plafond de dépense.
La preuve de bloc dupliqué Slashing est indivisible : transfert de préfinancement, instruction Ed25519 et instruction Slashing doivent conserver leurs positions. Le plan refuse donc durable nonce et exige un recent blockhash normal. Le compte de preuve, la fenêtre temporelle, le montant rent-exempt et la rétention avant fermeture relèvent de lorchestrateur stateful.
ZK ElGamal accepte une preuve inline ou une preuve dans un compte, avec création optionnelle dun contexte déjà préalloué. La fermeture exige lautorité comme signataire. Le builder vérifie discriminant, taille et comptes, mais ne crée pas le contexte et ne recalcule pas la preuve cryptographique. Lancien ZK Token Proof est historique et reste `decode-only`.
## Stake et Vote dans la bibliothèque
`pre.018` ajoute les vingt-quatre helpers clients actuels de `solana-stake-interface 4.3.1` sous forme de plans déterministes. Les formes composées conservent lordre officiel : création System puis initialisation Stake, délégation ajoutée en dernier, allocation/assignation avant split. Les rôles staker/withdrawer sont typés par `StakeAuthorizationKind`.
`pre.019` ajoute les vingt variantes wire Vote actuelles et quatre créations composées legacy/V2. Les autorités Ed25519/BLS, commissions, collecteurs, votes, switch proofs, compact updates et TowerSync sont encodés avec lenum officielle `VoteInstruction` et `wincode`. Les créations, retraits et dépôts de récompenses déclarent leurs lamports dans le plafond de dépense.
La construction reste stateless. Avant simulation puis envoi, lorchestrateur doit charger et valider létat des comptes Stake/Vote, les autorités, le lockup, le rent, le minimum de délégation, les epochs dactivation/désactivation, la compatibilité merge/split/move, la version Vote, les collecteurs et ladmissibilité runtime de la tour. `Redelegate` reste historique `decode-only`, car linterface officielle le déclare déprécié et non activable.
## Loaders dans la bibliothèque
`pre.020` ajoute onze plans Loader v3 et neuf plans Loader v4. Loader v3 utilise les helpers de `solana-loader-v3-interface 8.x` et leur schéma `wincode` pour créer des buffers, écrire, déployer, upgrader, modifier les autorités, fermer et étendre. Loader v4 conserve le contrat officiel des sept discriminants, mais son wire est construit localement et explicitement parce que les helpers publiés sont conditionnés par `bincode` et quaucun schéma `wincode` nest exposé.
Les plans de création conservent lordre atomique System puis Loader. Les écritures sont bornées, les offsets contrôlés contre les dépassements, les comptes/signataires reproduisent linterface officielle et les lamports explicitement transférés sont inclus dans `requested_spend_lamports`. Les loyers calculés dynamiquement par le runtime ne sont pas inventés par le builder.
Avant simulation, lorchestrateur stateful doit vérifier owner, état courant, autorité, taille/capacité, rent, existence des comptes Program/ProgramData/buffer, relations dérivées et admissibilité de fermeture ou dextension. Les opérations Loader restent hors de la démo opérateur. BPF Loader v1/v2 sont historiques `decode-only`; Native Loader correspond au déploiement du logiciel validator et nexpose pas dinstruction client autonome.
## Préflight stateful natif — `pre.022`
Les builders restent déterministes et sans I/O. `kb_pipeline::inspect_solana_core_stateful_readiness` ajoute une étape séparée avant la simulation pour les opérations dont ladmissibilité dépend de comptes ou de lépoque courante.
```text
SolanaCoreOperation
-> plan stateless
-> préflight stateful Localnet/Devnet
-> rapport Ready / Blocked / NotRequired
-> simulation exacte
```
Le préflight vérifie le genesis hash attendu et utilise uniquement des RPC typés. Il couvre :
- ALT : PDA de création, slot récent, owner, autorité, capacité, rent top-up, état actif/désactivé et cooldown de fermeture ;
- Config : absence/réutilisation contrôlée, allocation calculée, owner et espace disponible ;
- Feature : compte absent ou System réutilisable, rent mesuré et état pending avant révocation ;
- Slashing : compte de preuve complet et borné, deux shreds length-prefixed, fenêtre dun epoch, rent du rapport, destination retenue et délai de fermeture ;
- ZK ElGamal : plage de preuve, owner/space/rent du contexte préalloué, état zéro avant écriture, puis autorité et discriminant avant fermeture.
Le rapport contient des codes de contrôle stables, des faits mesurés et le plus haut slot de contexte observé. Il ne signe, ne simule et nenvoie aucune transaction. Testnet et Mainnet sont refusés dans cette couche tant que les parcours Localnet/Devnet ne sont pas validés.
## Préflight stateful SPL Token classique — `0.4.4-pre.005`
Le même découpage sapplique à SPL Token : `kb_executor_spl_token` construit un plan universel sans I/O, puis `kb_pipeline::inspect_spl_token_stateful_readiness` vérifie létat Localnet ou Devnet avant simulation. Le décodeur ne réalise aucune lecture RPC.
Le préflight lit des données complètes bornées et reproduit les layouts classiques Mint, Account et Multisig. Il contrôle notamment owner programme, initialisation, mint/decimals, état frozen, solde et réserve native, delegate/allowance, autorités spécialisées, seuil multisig et rent des comptes préparés. Les montants restent des entiers bruts exacts. Une précondition métier invalide produit `Blocked`; une erreur de transport ou de forme reste une erreur `kb_core`.
La preuve réseau est séparée en deux niveaux. Le test opt-in de `pre.005` vérifie en lecture seule un `TransferChecked` sur des comptes Devnet fournis explicitement. Le scénario opérateur complet doit ensuite créer des comptes classiques sans ATA, simuler par défaut, et ne signer/envoyer quavec une autorisation distincte ; après confirmation, il doit réutiliser hydratation canonique, extraction core, replay, projections et second replay idempotent.
`pre.005-delta-fix-001` relie ce préflight au chemin dexécution commun. La simulation constitue une API autonome sans store et conserve le plan, le rapport stateful, le blockhash, les frais et le résultat runtime. La soumission est une seconde API : elle refuse tout signataire absent du wallet de profil, puis applique confirmation, hydratation, extraction, decode replay, requête matérialisée bornée et preuve didempotence. Cette restriction de signataire appartient à lorchestrateur actuel, pas à lexécuteur universel ni au wire multisig.
Le 15 juillet 2026, ce parcours a réussi en simulation puis avec un envoi `TransferChecked` réel sur Devnet, entre deux comptes auxiliaires classiques créés sans dépendance ATA. `pre.005-delta-fix-002` durcit la preuve opt-in : résultat denvoi présent, confirmation `confirmed` ou `finalized`, premier replay sans échec ni refus, matérialisation Token présente, second replay sans échec, refus ou nouvelle sortie, et signature imprimée pour laudit.
`0.4.4-pre.006` compose ce contrat sans le contourner. La préparation interne génère trois keypairs éphémères, mesure le rent exact puis construit trois `SystemCreateAccount` officiels avec le propriétaire Token classique et les tailles 82/165/165. Chaque création est simulée, signée par le payeur et le nouveau compte, confirmée, puis relue pour vérifier owner, rent, taille, absence d'executable et données entièrement nulles. Les clés de création peuvent ensuite disparaître : les initialisations Token n'en ont pas besoin. Le lifecycle n'utilise pas ATA. Après autorisation destructive explicite, il exécute onze transactions séparées : initialisation du mint, initialisation des deux comptes, mint checked, transfer checked, approve checked, revoke, burn checked des deux soldes puis fermeture des deux comptes. Une étape incomplète arrête la séquence ; la suivante n'est construite qu'après confirmation, hydratation, extraction, décodage, matérialisation et second replay idempotent de la précédente.
Une confirmation RPC interrompue ne rend pas la séquence aveuglément rejouable : les initialisations Token ne sont pas idempotentes. La reprise exige donc l'index de la prochaine étape et la signature confirmée de son prédécesseur. Le pipeline hydrate cette signature, extrait le core, impose le decode Token commité, vérifie l'opération matérialisée attendue et un second replay sans sortie avant de construire l'étape suivante. Un délai borné entre étapes réduit les rafales vers le RPC public ; il ne transforme pas un statut inconnu en succès.
Cette reprise a été exercée sur Devnet le 15 juillet 2026 après un throttling `429` puis une confirmation momentanément incomplète. L'initialisation du compte destination déjà finalisée a été récupérée depuis sa signature canonique ; les étapes 3 à 10 ont ensuite achevé `MintToChecked`, `TransferChecked`, `ApproveChecked`, `Revoke`, deux `BurnChecked` et deux `CloseAccount`. Les neuf étapes récupérées ou envoyées ont chacune validé une matérialisation et un second replay idempotent.
`0.4.4-pre.007` n'ajoute aucune nouvelle couche d'exécution. La fenêtre Tauri existante construit un intent `TransferChecked` mince, puis appelle le même `execute_devnet_spl_token`. Le journal opérateur interroge au maximum 500 lignes via `MaterializedEventFilter`; les filtres exacts mint, compte et opération sont appliqués au payload typé en mémoire. La frontière UI conserve slots et montants bruts sous forme de chaînes et ne revendique aucun snapshot final ni agrégat OHLC.
`docs/NATIVE_SOLANA_EXECUTION_MATRIX.json` constitue linventaire machine-readable de clôture. Un test Rust de `kb_executor_solana_core` charge cette matrice et impose dix-huit surfaces, 109 opérations appelables exactement égales à `SOLANA_CORE_OPERATION_CODES`, ainsi quune justification non vide pour chaque surface sans builder client. Le validateur Python provisoire a été supprimé.
## Préflight stateful ATA — `0.4.5-pre.004`
`kb_executor_spl_associated_token_account` construit exactement un builder officiel parmi
`Create`, `CreateIdempotent` et `RecoverNested`. Le Token Program classique ou Token-2022 fait
partie de lintent et de la dérivation ; la bibliothèque ne lie toujours pas un plan à un endpoint
ou à un wallet concret.
`kb_pipeline::inspect_spl_associated_token_account_stateful_readiness` est la frontière I/O
Localnet/Devnet. Elle vérifie le genesis, le Program ID ATA, la simulation obligatoire, les mints,
les PDA, labsence stricte pour `Create`, la compatibilité absence/compte existant pour
`CreateIdempotent`, les trois comptes Token de `RecoverNested`, tous les signataires et le solde du
payer couvrant le plafond rent-plus-frais.
Les comptes Token-2022 peuvent dépasser 165 octets. Le préflight valide leur préfixe Token Account
commun et laisse les extensions opaques ; il ne commence donc pas `0.4.6`. Le rent minimal du
compte de base et le plafond sont contrôlés avant simulation. La taille et le rent exacts imposés
par des extensions restent vérifiés par le runtime pendant la simulation obligatoire.
Le rapport `Ready`/`Blocked` ne signe, ne simule et nenvoie rien. Lorchestration de soumission,
confirmation et replay reste une tranche séparée afin quun statut RPC inconnu ne provoque jamais
une recréation ATA aveugle.
## Orchestration ATA Devnet — `0.4.5-pre.005`
`execute_devnet_spl_associated_token_account` réutilise les frontières communes validées : wallet
persistant de profil, plan typé, préflight stateful, message exact, frais, simulation liée au hash,
signature après autorisation, envoi et confirmation. Après confirmation, la signature déjà connue
est hydratée par tentatives bornées ; chaque tentative RPC autorise deux reprises internes pour les
réponses transitoires telles que `429`, sans reconstruire ni renvoyer linstruction ATA.
Le replay sélectionne toujours le Program ID ATA. Pour une cible SPL Token classique, il sélectionne
aussi le Program ID Token afin de décoder les CPI internes, tout en laissant chaque matérialiseur
posséder uniquement ses faits. Pour Token-2022, il ne prétend pas décoder les instructions ou
extensions CPI générales réservées à `0.4.6`. La seconde passe inclut létat matérialisé et doit ne
produire aucune nouvelle sortie.
La bibliothèque dexécution ATA reste indépendante du cluster et du wallet. Lorchestrateur Devnet
fourni ne peut signer quavec le wallet persistant du profil ; un `RecoverNested` exigeant une autre
clé est donc refusé comme signataire indisponible. La fenêtre Tauri existante expose seulement les
modes représentatifs `Create` et `CreateIdempotent`, la dérivation readonly et un journal ATA borné.
Le 16 juillet 2026, le parcours classique `CreateIdempotent` a été confirmé deux fois sur le même
ATA Devnet. La première signature `2H9V…CPbP` et la seconde `3wWT…fv6q` ont chacune réussi
simulation, confirmation, hydratation canonique, extraction, décodage, projection lifecycle unique
et second replay sans nouvelle sortie. La seconde exécution prouve le chemin compte existant
compatible ; elle reste un fait transactionnel distinct et non un doublon de replay.
Le garde-fou Token-2022 a également refusé correctement le Program ID `TokenzQd…` lorsquil était
fourni à la place dun compte mint : owner, layout Mint et état initialisé ne correspondaient pas.
La preuve positive utilise ensuite le mint contrôlé `3DxK…KTE`, initialisé sur 82 octets et possédé
par Token-2022. `CreateIdempotent` a créé puis réutilisé lATA `6WfC…C9Y`, compte de 170 octets
initialisé pour `DwuA…g8B2` avec lextension `ImmutableOwner`. Les signatures `bMMj…QAJ` au slot
476702448 et `4RZK…VSG` au slot 476703343 ont chacune été simulées, confirmées, hydratées, décodées
et matérialisées une fois, puis ignorées au second replay. Létat préalable observé établit la
réutilisation de la seconde transaction, tandis que la projection parent conserve correctement
`created_or_reused` car linstruction seule ne distingue pas ces branches.
`RecoverNested` reste volontairement hors UI. Son parcours contrôlé opt-in reçoit deux mints et une
fixture nested déjà préparée, puis réutilise le même orchestrateur afin de vérifier simulation,
confirmation, fermeture du nested ATA, destination cohérente, deux projections ATA/risk et second
replay idempotent sans introduire de décodeur Token-2022 général.
La preuve Devnet classique du 16 juillet 2026 utilise `3tdX…FbF5`, ATA wrapped SOL du wallet,
comme owner du nested ATA `AAyv…gti5`. Celui-ci contenait exactement 1 token, soit
1 000 000 000 unités brutes du mint `3fd5…hC9A`, et la destination `69TP…fyWp` était vide. La
signature `37LG…HskM` a transféré le montant complet, fermé le nested ATA, conservé lowner ATA et
la destination initialisés, produit exactement les deux sorties parent `nested_ata_recovered` et
`nested_ata_anti_pattern_recovered`, puis réussi le second replay sans doublon. Les mutations CPI
Token de transfert et fermeture ne sont pas recopiées dans les projections parent ATA.
## Soumission et confirmation RPC
`0.4.2-pre.008` complète la frontière réseau sans fusionner les étapes :
```text
SignedSolanaTransaction
-> sendTransaction avec preflight obligatoire
-> contrôle de la signature primaire retournée
-> getSignatureStatuses borné
-> getBlockHeight pour détecter lexpiration
-> confirmed / finalized / failed / expired / timed_out
```
`sendTransaction` signifie uniquement que le nœud a accepté la transaction signée pour relay. La confirmation reste une opération séparée. La politique borne le nombre de polls et leur intervalle, conserve le dernier slot et la dernière block height observée, puis termine explicitement sur succès, erreur runtime, expiration du recent blockhash ou timeout.
`requestAirdrop` et `getBalance` sont ajoutés comme primitives génériques de laboratoire. Le plafond dairdrop Devnet appartient à la configuration et sera appliqué par lorchestrateur du parcours réel ; la méthode RPC reste indépendante de Tauri et du wallet concret.
## Wallet temporaire persistant
`0.4.2-pre.003` introduit un signer de laboratoire dans `kb_wallet` :
```text
wallets/temporary/<profile>/<alias>.json
```
Il peut être généré en mémoire ou persisté afin de conserver la même adresse entre plusieurs démarrages, recevoir un airdrop devnet, créer des comptes et signer les transactions de validation. Le fichier utilise le format JSON Solana standard, reste exclu du dépôt et reçoit des permissions privées sur Unix.
Ce backend n'est pas un wallet de production : il n'est pas chiffré et les profils fournis l'interdisent sur mainnet. Les futurs backends chiffrés, coffre système et hardware wallet devront conserver la même frontière de signature afin que les exécuteurs ne changent pas.
## Garde-fous obligatoires
- dry-run activé par défaut ;
- simulation RPC obligatoire avant envoi ;
- cluster réel comparé au cluster attendu ;
- contrôle du wallet source et des signataires requis ;
- plafond de dépense, de frais et de compute-unit price ;
- fraîcheur du blockhash ou état nonce durable complet, courant, initialisé et concordant ;
- confirmation explicite pour tout envoi mainnet ;
- journalisation séparée des plans et résultats ;
- validation post-exécution par transaction canonique, extraction core, décodage et matérialisation.
## Exposition dans `kb_app_demo`
La démo exposera uniquement un sous-ensemble opérationnel sûr : transfert, création/allocate/assign contrôlés, Compute Budget et durable nonce après ajout dun orchestrateur stateful validé sur cluster. Stake, Vote, loaders, changement d'autorité, Feature, Slashing et opérations ZK peuvent être disponibles dans les crates sans apparaître dans la fenêtre Tauri.
## Orchestration Devnet et validation post-exécution
`0.4.2-pre.009` ajoute dans `kb_pipeline` une orchestration backend bornée pour le premier parcours System transfer sur Devnet. La fonction publique ne remplace aucune couche : elle appelle successivement les contrats existants et conserve leurs résultats séparés.
```text
classification du genesis hash
-> wallet temporaire persistant
-> solde / airdrop plafonné
-> PreparedExecutionPlan System transfer
-> getLatestBlockhash
-> getFeeForMessage
-> simulateTransaction exact
-> signature locale
-> sendTransaction
-> getSignatureStatuses + getBlockHeight
-> getTransaction
-> transaction canonique
-> extraction core
-> decode replay ciblé
```
Le mode par défaut reste une simulation seule. Il ne signe pas, nenvoie pas et ne fabrique pas de signature vide. Le parcours soumis exige simultanément lautorisation `submit`, la confirmation opérateur lorsque le profil limpose, lactivation Devnet du wallet, un plafond de dépense et une simulation exacte réussie.
Le financement par faucet est une étape distincte, uniquement disponible sur Devnet et bornée par `devnet_airdrop_max_lamports`. Il est déclenché seulement lorsque le solde du wallet persistant ne couvre pas le transfert plus le plafond de frais. Lairdrop est lui-même confirmé avant de poursuivre.
`0.4.2-pre.010` ajoute une précondition liée au destinataire. Le mode metadata-only de `getAccountInfo` détermine si ladresse existe déjà. Lorsquelle est absente, `getMinimumBalanceForRentExemption(0)` fournit le minimum nécessaire à la création implicite dun compte System sans données ; un transfert inférieur est refusé avant simulation. Les échecs de simulation conservent désormais lerreur runtime et un extrait borné des logs. La fenêtre `demo_execution_solana_core` ne réimplémente aucune de ces règles : elle sélectionne un profil Devnet, construit la requête et relaie les événements du pipeline.
Après une confirmation terminale, le pipeline hydrate exclusivement la signature envoyée. Une transaction on-chain échouée reste éligible à linsertion canonique et au décodage comme intention échouée. Une expiration ou un timeout arrête la validation post-exécution sans prétendre que lenvoi a été confirmé.
Une erreur avant signature reste un `Err`. Dès quune signature locale existe, lorchestrateur conserve cette signature et transforme les erreurs denvoi, de confirmation ou de replay en diagnostics dans le résumé. Cette règle évite quun appelant perde la référence dune transaction potentiellement diffusée.
Lorchestrateur est une API de bibliothèque et ne dépend pas de Tauri. La fenêtre `demo_execution_solana_core` expose uniquement une sélection Devnet réduite de ce backend ; les opérations administratives natives restent disponibles à terme dans les bibliothèques sans être nécessairement proposées dans linterface.
## État de clôture `0.4.2`
Le parcours représentatif Devnet a validé la chaîne plan → simulation exacte → signature → envoi → confirmation → hydratation canonique → extraction core → decode replay. Les builders administratifs supplémentaires restent disponibles dans la bibliothèque, mais ne reçoivent aucune autorisation Mainnet implicite.
La règle de clôture est donc la suivante : complétude du wire et des plans offline, politique de sécurité et préflight stateful présents, puis preuve cluster obligatoire avant toute exposition mutable supplémentaire. Un statut `future` dans la matrice désigne cette preuve dactivation, pas une instruction manquante.

View File

@@ -1,130 +0,0 @@
<!-- file: docs/EXECUTOR_SURFACE_MATRIX.md -->
<!-- version: 10 -->
# Matrice des exécuteurs
## Matrice canonique machine-readable — `pre.022`
Le fichier `docs/NATIVE_SOLANA_EXECUTION_MATRIX.json` est désormais la source vérifiable pour la clôture de lexécuteur natif. Il contient exactement :
- 18 surfaces natives ;
- 14 surfaces `callable` ;
- 4 surfaces `non_invocable` ou historiques ;
- 109 opérations callable, chacune munie de sa source de construction, politique, préflight stateful, contrat de test, décision cluster et exposition UI.
Les quatre classifications sans builder client sont BPF Loader v1, BPF Loader v2, Native Loader et lancien ZK Token Proof historique. Un test Rust charge la matrice et la compare à `SOLANA_CORE_OPERATION_CODES`; toute omission, duplication ou opération inconnue fait échouer `cargo test -p kb_executor_solana_core`. Le validateur Python provisoire a été supprimé.
Le préflight stateful est actif pour Address Lookup Table, Config, Feature, Slashing et ZK ElGamal. Stake, Vote et Loaders restent marqués `future` dans la matrice pour leur preuve dactivation stateful approfondie ; cela ne retire aucun builder de la surface appelable, mais interdit toute exposition mutable sans validation cluster dédiée.
Cette matrice suit la symétrie entre surfaces de décodage et surfaces de construction dinstructions. Elle ne confond pas réservation dune crate, disponibilité dun builder, autorisation denvoi et exposition dans une interface.
## Socle dexécution
| Crate | Rôle |
|-----------------------------------------|------------------------------------------------------------------------------|
| `kb_execution_api` | Contrats provider-neutral des capacités, politiques, plans et résultats. |
| `kb_execution_safety` | Garde-fous stateless avant simulation, signature ou envoi. |
| `kb-lib::executor::solana::transaction` | Compilation Solana, blockhash/nonce, preuve de simulation et signature. |
| `kb_onchain_transport` | Acquisition, simulation, envoi et confirmation JSON-RPC ; aucune clé privée. |
| `kb_wallet` | Résolution des signataires derrière un backend explicite. |
## Règle mécanique
Pour chaque décodeur de programme ou de protocole classifié :
```text
kb_decoder_<surface> -> kb_executor_<surface>
```
Deux crates de décodage ne suivent volontairement pas cette règle :
- `kb_decoder_api` est le contrat commun des décodeurs, pas un programme appelable ;
- `kb_decoder_anchor` est un helper technique partagé, pas une surface on-chain autonome.
Laudit du workspace `0.4.2-pre.014` trouve :
```text
104 crates kb_decoder_*
102 crates kb_executor_*
102 paires mécaniques exactes
2 exceptions techniques documentées
0 exécuteur orphelin
```
## Répartition des 102 surfaces appariées
| Famille | Paires |
|---------------------------------------------------------------------------------------------------------------|----------:|
| AMM | 26 |
| Launchpad | 9 |
| SPL | 8 |
| Lending | 7 |
| CLMM | 6 |
| Router | 6 |
| Vault | 6 |
| Bridge | 4 |
| Stable | 4 |
| Orderbook | 3 |
| Perpetuals | 3 |
| Staking | 3 |
| Admin | 2 |
| Fees | 2 |
| Adapter, CPMM, DLMM, Governance, Lock, Metadata, NFT, RWA, Solana Core, Treasury, Vesting, Wallet et Weighted | 1 chacune |
## Niveaux de maturité
Une paire doit utiliser un statut explicite :
| Statut | Signification |
|------------------|--------------------------------------------------------------------------------------------------|
| `reserved` | Crate et identité réservées ; aucun builder utilisable. |
| `implementing` | Contrat officiel et politiques en cours de validation. |
| `complete` | Toutes les opérations client officiellement appelables du périmètre sont construites et testées. |
| `not_applicable` | Surface non invocable, retirée ou purement technique, avec justification officielle. |
`Unsupported(reason)` est acceptable pendant limplémentation ou pour une impossibilité officielle précise. Il ne doit pas masquer une opération callable oubliée.
## Politique de jalon
Chaque version qui active un décodeur doit également :
1. identifier la crate `kb_executor_<surface>` correspondante ;
2. attribuer un statut de maturité à lexécuteur ;
3. lister les opérations client appelables et les opérations historiques decode-only ;
4. définir autorités, signataires, coûts, slippage ou autres garde-fous ;
5. comparer les payloads et comptes à un builder, une IDL ou un layout officiel ;
6. ajouter les tests offline puis localnet/devnet nécessaires ;
7. documenter lAPI publique de la crate dans son README ;
8. décider séparément quelles opérations sont visibles dans `kb_app_demo` ou activables par une stratégie.
Une opération dangereuse peut rester hors UI, mais elle reste dans le périmètre de la bibliothèque lorsquelle est officiellement appelable.
## Programme Solana Core
`kb_executor_solana_core` est la première surface passée de `reserved` à une implémentation opérationnelle. Après `pre.021`, elle expose toujours 109 opérations : 17 System, 4 Compute Budget, 5 Address Lookup Table, 6 précompiles de signature, 2 Config, 2 Feature, 2 Slashing, 3 ZK ElGamal, 24 Stake, 24 Vote, 11 Loader v3 et 9 Loader v4.
| Surface native | Statut à la clôture `0.4.2` | Décision |
|-------------------------------|-----------------------------------------------------|-------------------------------------------------------------------------------------------------|
| System, Compute Budget | `complete` pour les builders client actuels | orchestration durable nonce séparée ; exposition mutable toujours soumise aux politiques |
| Address Lookup Table | `complete` stateless | autorité, rent, capacité et cooldown contrôlés par le préflight stateful |
| Ed25519, secp256k1, secp256r1 | `complete` | formes inline et offsets ; aucune autorisation métier implicite |
| Config | `complete` builder | wire local vérifié sans helper `bincode`; rent/état contrôlés avant envoi |
| Feature | `complete` builder | activation et révocation ; état/rent contrôlés avant envoi |
| Slashing | `complete` builder | close et plan atomique duplicate-block ; compte de preuve et fenêtres epoch stateful |
| ZK ElGamal Proof | `complete` builder | douze preuves inline/account et fermeture de contexte |
| ZK Token Proof historique | `not_applicable` | programme retiré/stub runtime, conservé uniquement pour décodage historique |
| Stake | `complete` pour les 24 helpers clients actuels | validations compte/rent/epoch exigées avant exposition ; Redelegate historique `decode-only` |
| Vote | `complete` pour les 20 variantes wire + 4 créations | validations account/rent/autorités/BLS/tour exigées avant exposition |
| Loader v3 upgradeable | `complete` pour 11 opérations client | interface officielle `wincode`; état, rent, owner et capacité restent stateful |
| Loader v4 | `complete` pour 9 plans client | wire officiel reproduit sans activer les helpers `bincode`; état/autorité/rent restent stateful |
| BPF Loader v1/v2 | `historical_decode_only` | builders dépréciés historiques non promus dans lexécuteur moderne |
| Native Loader direct | `non_invocable_by_client_instruction` | déploiement lié au logiciel validator, aucun builder transactionnel inventé |
`pre.021` ne change aucune capacité : elle centralise les validations communes `pub(crate)` et élimine les implémentations identiques détectées dans les modules System, ALT, Config/Feature, Slashing, ZK, Stake, Vote et Loader.
La clôture `0.4.2` confirme la matrice machine-readable des dix-huit surfaces natives, avec pour chaque opération : builder/layout officiel, politique, tests offline, statut de validation cluster et décision dexposition UI.
## Versions futures
Le `ROADMAP.md` associe désormais explicitement les exécuteurs aux séries Pump, Meteora, Raydium, Orca, Jupiter/routeurs et à chaque jalon ultérieur de décodeur. La symétrie de crates ne vaut pas activation : les listeners et stratégies ne peuvent demander que des capacités explicitement validées et autorisées.

View File

@@ -1,78 +0,0 @@
<!-- file: docs/FOUNDATION_CLOSURE.md -->
<!-- version: 2 -->
# Clôture de la fondation `0.3.x`
## Décision de version
Le jalon `0.3.5` nest plus conservé comme version autonome. Ses outils dintégrité, de sélection de corpus et de replay ont été réalisés pendant `0.3.4`.
La séquence retenue est :
```text
0.3.4 -> clôture raw/canonical/core/replay
0.4.0 -> infrastructure de décodage et matérialisation
```
## Validations réelles acquises
| Contrôle | Résultat |
|-------------------------|--------------------------------------------------|
| Extraction pending | 70 extraites, 0 échec |
| Intégrité SQL | 7 contrôles sans ligne anormale |
| Ledger initial | 70 succès, 70 tentatives |
| Skip sur échantillon | 14 skips, 0 extraction |
| Force replay | 14 extractions, 0 skip |
| Skip après replay | 14 skips, 0 extraction |
| Cardinalité finale | 70 transactions core |
| Ledger final | 70 succès, 84 tentatives |
| CSV natif | écrit dans `data/exports_csv/` sous Tauri/Linux |
| Tests application | `kb_app_demo` 60 tests, `kb_program_ids` 2 tests |
| Tests pipeline finaux | `kb_pipeline` 24 tests |
| Tests PostgreSQL finaux | `kb_store_pg` 39 tests, rollback inclus |
| Clippy final | `cargo clippy --all-targets` sans avertissement |
Ces résultats confirment que le force-replay remplace le graphe ciblé sans créer de transaction supplémentaire et que le ledger comptabilise la tentative additionnelle.
## Contrôles automatisés finaux validés
### Rollback PostgreSQL
Le test `optional_postgres_core_extraction_rolls_back_partial_graph_from_env` injecte une violation dunicité après le début de la persistance. Il vérifie :
- absence de transaction core partielle ;
- absence daccount key partielle ;
- raw toujours `received` ;
- aucune entrée ledger réussie ;
- replay corrigé possible ;
- nettoyage des fixtures.
### Annulation backfill
Les appels réseau et attentes suivantes sont maintenant annulables :
- `getSignaturesForAddress` en vol ;
- `getTransaction` en vol ;
- attente du pacer ;
- pause de retry standard ;
- pause configurée après 429.
Les tests offline couvrent une attente déjà annulée et labandon coopératif dune future longue.
## Clôture acquise
Les commandes finales ont été exécutées avec succès le 7 juillet 2026 :
```text
kb_pipeline: 24 passed, 0 failed
kb_store_pg avec PostgreSQL réel: 39 passed, 0 failed
cargo clippy --all-targets: aucun avertissement
```
`0.3.4` est inscrite dans `CHANGELOG.md`, le jalon `0.3.x` est clôturé et `0.4.0` devient le jalon actif. La session suivante doit démarrer avec `prompts/019_v0_4_0_decoder_infrastructure.md`.
## Éléments reportés sans blocage
Les corpus exhaustifs de protocoles ne sont pas nécessaires pour prouver lindépendance de lextracteur core. Ils sont constitués dans leurs versions respectives : Pump `0.5.x`, Meteora `0.6.x`, Raydium `0.7.x` et Orca `0.8.x`.
Le rejeu manuel dun backfill `before` depuis `resume_before_signature` reste recommandé lors dune prochaine campagne longue. La logique de frontière contiguë, les compteurs darrêt et une campagne réelle interrompue sont déjà validés.

View File

@@ -1,355 +0,0 @@
<!-- file: docs/HISTORICAL_DATA_ACQUISITION_PLAN.md -->
<!-- version: 1 -->
# Plan différé — acquisition historique gratuite et worker de campagnes
## Statut
Ce document conserve un projet futur volontairement retiré du `ROADMAP.md` actif.
Aucune version n'est attribuée à ce chantier. Il ne doit pas retarder les décodeurs, matérialisateurs et exécuteurs Solana Core, SPL, AMM, launchpads, orderbooks, routers ou autres surfaces prioritaires.
Le nom **W2** est provisoire. Il désigne ici un worker manuel d'acquisition historique, distinct du worker temps réel destiné au trading. Le nom final des crates et binaires sera décidé au moment de l'activation du chantier.
## 1. Motivation
Le projet aura besoin de deux voies d'acquisition complémentaires :
```text
W1 — temps réel
-> fournisseurs fiables ou payants
-> faible latence
-> détection de créations de tokens, pools et pairs
-> changements de prix/liquidité
-> déclencheurs d'achat, vente et gestion du risque
W2 — historique manuel
-> sources gratuites ou très économiques
-> campagnes lentes et reprenables
-> corpus vieux d'un an, deux ans ou davantage
-> données destinées à l'analyse, aux tests et à la détection de patterns
-> aucune consommation implicite du budget réservé au trading
```
W2 ne remplace ni `kb_onchain_transport`, ni le pipeline canonique, ni les fournisseurs temps réel. Il sert à alimenter progressivement PostgreSQL avec des données historiques dont la latence n'est pas critique.
## 2. Principes non négociables
- `kb_onchain_transport` reste la frontière des protocoles Solana : JSON-RPC HTTP/WS standard, extensions fournisseur officiellement prises en charge, Yellowstone/gRPC et transports similaires.
- Une source historique parlant JSON-RPC standard peut réutiliser `kb_onchain_transport`, mais sa politique de campagne, son coût, sa provenance et ses fallbacks restent hors de `kb_onchain_transport`.
- Les APIs REST indexées, exports, datasets analytiques, archives CAR ou outils externes appartiennent à des crates de sources historiques séparées.
- W2 fonctionne en `free_only` par défaut. Aucun fournisseur payant ne doit être interrogé sans autorisation explicite de la campagne.
- Les endpoints et crédits de W1 ne doivent jamais être utilisés comme fallback silencieux de W2.
- Toute donnée destinée au pipeline doit finir par être normalisée dans le contrat canonique existant.
- Une source externe peut découvrir une signature, un slot ou un candidat ; elle ne devient pas pour autant la source canonique de la transaction.
- Les campagnes doivent être bornées, annulables, reprenables, dédupliquées et auditées.
- Une page vide ou une réponse `null` provenant d'une source best-effort ne prouve pas nécessairement l'absence historique de la donnée.
## 3. Séparation découverte / hydratation
W2 doit séparer deux responsabilités.
### 3.1 Découverte
Trouver des candidats à partir de :
- adresses ou Program IDs ;
- signatures explicites ;
- plages de slots ou périodes ;
- pools, vaults ou token accounts ;
- programmes DEX/launchpads ;
- datasets indexés capables de filtrer par comptes, instructions ou timestamps.
### 3.2 Hydratation
Récupérer la transaction ou le bloc brut correspondant, puis suivre le pipeline existant :
```text
candidate
-> transaction ou bloc brut
-> insertion raw canonique
-> core extraction
-> decode replay
-> materialization
-> agrégations et corpus d'analyse
```
La source de découverte et la source d'hydratation peuvent être différentes.
Exemple :
```text
BigQuery découvre les signatures d'une période
-> Old Faithful hydrate les anciennes transactions
-> un RPC public hydrate les transactions encore disponibles
-> PostgreSQL ignore les signatures déjà présentes
-> aucun crédit Helius n'est consommé
```
## 4. Architecture candidate
Les noms ci-dessous sont provisoires et ne constituent pas encore des réservations de crates :
```text
kb_historical_api
-> capacités, campagnes, candidats, provenance, coût et complétude
kb_historical_source_rpc
-> profils RPC publics/best-effort utilisant les contrats de kb_onchain_transport
kb_historical_source_old_faithful
-> intégration avec un processus faithful-cli externe ou une archive locale
kb_historical_source_bigquery
-> découverte indexée par requêtes analytiques bornées
kb_historical_source_solscan
-> API officielle optionnelle, avec clé et budget explicites
kb_worker_historical
-> orchestration manuelle, reprise, quotas, déduplication et import canonique
```
Une alternative consiste à garder les contrats et l'orchestration dans des modules internes d'une crate plus compacte. Ce choix devra être tranché après les prototypes et mesures, pas avant.
## 5. Sources candidates
### 5.1 RPC utilisé par l'Explorer Solana
L'Explorer officiel repose sur des appels JSON-RPC Solana standards. Une source `rpc_best_effort` peut donc utiliser des endpoints publics ou communautaires pour :
- `getSignaturesForAddress` ;
- `getTransaction` ;
- `getBlocks` ;
- `getBlock` ;
- réparations ciblées par signature ou slot.
Cette source convient aux campagnes étroites et lentes. Elle n'offre pas de SLA, d'index arbitraire ni de garantie de rétention complète. Le site HTML ne doit pas être scrapé.
Références de recherche :
- <https://github.com/solana-foundation/explorer>
- <https://solana.com/docs/rpc/http/getsignaturesforaddress>
- <https://solana.com/docs/rpc/http/gettransaction>
### 5.2 Old Faithful
Old Faithful est la piste prioritaire pour l'histoire profonde. L'intégration initiale doit privilégier un processus externe `faithful-cli` ou un serveur JSON-RPC local, afin d'éviter un couplage prématuré au format CAR, à l'implémentation Go et à sa licence.
Usages visés :
- hydratation de transactions anciennes ;
- scans bornés par époque ou slots ;
- constitution progressive d'un corpus local durable ;
- fallback gratuit lorsque les RPC récents ont purgé les données.
Références de recherche :
- <https://github.com/rpcpool/yellowstone-faithful>
- <https://docs.triton.one/project-yellowstone/old-faithful-historical-archive>
### 5.3 BigQuery ou dataset analytique équivalent
Un dataset indexé peut servir de moteur de découverte et réduire massivement le nombre d'appels RPC. Il doit être évalué pour :
- schéma et fraîcheur ;
- instructions outer/inner disponibles ;
- comptes et balances pré/post ;
- précision des filtres ;
- coût réel des requêtes ;
- capacité à exporter des signatures et slots de manière reprenable.
Il ne remplace pas PostgreSQL ni le pipeline canonique.
Référence de recherche :
- <https://cloud.google.com/blockchain-analytics/docs/supported-datasets>
### 5.4 Solscan
Solscan fournit un index fonctionnellement intéressant, mais l'intégration durable doit utiliser uniquement son API officielle et respecter ses quotas et conditions.
Cette source serait :
- optionnelle ;
- désactivée par défaut ;
- configurée par clé ;
- classée `free_quota` ou `paid` selon le plan ;
- interdite dans une campagne `free_only` si elle entraîne un coût.
Les endpoints privés du site, cookies, jetons internes et scraping HTML ne doivent pas être utilisés.
Références de recherche :
- <https://solscan.io/apis>
- <https://pro-api.solscan.io/pro-api-docs/v2.0>
### 5.5 Fournisseurs payants
Helius, Shyft, Chainstack, Triton ou équivalents peuvent être ajoutés ultérieurement comme fallback explicitement autorisé. Ils ne doivent pas être activés dans la politique par défaut de W2 et ne doivent jamais consommer les crédits de W1 à l'insu de l'opérateur.
## 6. Stablecoins et corpus de marché
Une campagne naïve `getSignaturesForAddress(MINT)` ne suffit pas à reconstruire toute l'activité d'un stablecoin. Les transferts classiques peuvent référencer les token accounts sans inclure systématiquement le mint dans les comptes de l'instruction.
Pour constituer des séries utiles à un analyseur de patterns, la stratégie prioritaire doit être :
```text
stablecoin
-> pools et pairs pertinents
-> vaults et token accounts des pools
-> Program IDs des AMM/CLMM/DLMM/routers
-> transactions candidates
-> décodage des swaps et changements de liquidité
-> matérialisation trades/pools
-> bougies et séries temporelles
```
Les transferts génériques du token restent un corpus séparé, beaucoup plus volumineux et moins directement utile au prix.
## 7. Contrats fonctionnels candidats
### 7.1 Capacités
```rust
pub struct HistoricalSourceCapabilities {
pub signatures_by_address: bool,
pub transactions_by_signature: bool,
pub blocks_by_slot: bool,
pub slot_ranges: bool,
pub time_ranges: bool,
pub program_filter: bool,
pub token_filter: bool,
pub instruction_filter: bool,
pub indexed_results: bool,
pub full_history: bool,
}
```
### 7.2 Budget
```rust
pub enum HistoricalSourceCost {
Free,
FreeQuota,
Paid,
}
pub enum HistoricalBudgetPolicy {
FreeOnly,
FreeThenPaid,
ExplicitSourcesOnly,
}
```
`FreeOnly` doit être la valeur de départ de toute campagne manuelle.
### 7.3 Complétude et provenance
```rust
pub enum HistoricalCompleteness {
Complete,
Partial,
Unknown,
Pruned,
}
pub struct HistoricalProvenance {
pub source_name: String,
pub source_kind: String,
pub method: String,
pub fetched_at_unix_ms: i64,
pub paid: bool,
}
```
Les types définitifs devront respecter les conventions du workspace, les bornes PostgreSQL et les règles TS-rs si une UI est ajoutée.
## 8. Campagnes et observabilité
Une campagne doit conserver au minimum :
- identifiant stable ;
- cible et filtres ;
- source de découverte et source d'hydratation ;
- politique de coût ;
- curseur et checkpoint de reprise ;
- plage temporelle ou de slots ;
- concurrence, rate limit et backoff ;
- candidats découverts ;
- signatures déjà présentes ;
- transactions hydratées, absentes, pruned ou invalides ;
- erreurs et fallbacks ;
- volume réseau et coût estimé ;
- état `running`, `paused`, `cancelled`, `completed` ou `failed`.
Les événements `tracing` doivent être émis par les crates responsables. Les secrets, clés API, payloads complets non bornés et URLs contenant des credentials sont interdits dans les logs.
## 9. Étude préalable obligatoire
Avant toute activation dans le ROADMAP, exécuter un benchmark reproductible avec :
- une transaction récente ;
- une transaction vieille d'environ un an ;
- une transaction vieille d'environ deux ans ;
- une adresse peu active ;
- un Program ID très actif ;
- un pool stablecoin ;
- une plage de slots bornée.
Mesurer pour chaque source :
- profondeur historique ;
- taux de réponse `null` ou pruned ;
- cohérence de pagination ;
- latence et débit soutenable ;
- limitations et `Retry-After` ;
- filtres disponibles ;
- complétude des transactions et métadonnées ;
- coût ;
- conditions d'utilisation ;
- capacité de reprise et stabilité du contrat.
## 10. Phases futures sans numéro de version
### Phase R0 — recherche
- valider les sources, licences, conditions d'utilisation, coûts et corpus ;
- produire une matrice comparative et un prototype jetable ;
- choisir le nom final de W2.
### Phase R1 — contrats et ledger de campagne
- définir les capacités, budgets, candidats, provenance et checkpoints ;
- ajouter les migrations PostgreSQL seulement après stabilisation du contrat.
### Phase R2 — source RPC gratuite
- réutiliser `kb_onchain_transport` pour les méthodes standards ;
- ajouter quotas, backoff, déduplication et frontières de complétude.
### Phase R3 — archive profonde
- intégrer `faithful-cli` comme processus externe ou service local ;
- valider les imports par époque/slots et la cohérence avec le canonique.
### Phase R4 — découverte indexée
- intégrer BigQuery ou une source analytique équivalente après benchmark ;
- exporter uniquement les candidats nécessaires.
### Phase R5 — sources commerciales facultatives et UI
- ajouter Solscan ou d'autres APIs officielles avec budget explicite ;
- ajouter une UI de campagne manuelle seulement lorsque les contrats backend sont stables.
## 11. Conditions avant retour dans le ROADMAP
Ce chantier ne revient dans le `ROADMAP.md` que lorsque :
- les décodeurs/matérialisateurs/exécuteurs prioritaires ont suffisamment progressé ;
- au moins deux sources gratuites ont été testées réellement ;
- une stratégie de licence et de conditions d'utilisation est validée ;
- la frontière avec `kb_onchain_transport`, `kb_pipeline` et PostgreSQL est décidée ;
- la politique `free_only` est testable et empêche réellement tout fallback payant ;
- un prompt de session dédié peut être écrit sans hypothèse majeure non vérifiée.

32
docs/IDEA_REMINDERS.md Normal file
View File

@@ -0,0 +1,32 @@
<!-- file: docs/IDEA_REMINDERS.md -->
<!-- version: 2 -->
# Rappels didées
Ce document regroupe les améliorations utiles mais non bloquantes pour la clôture de la migration et pour la reprise du développement fonctionnel.
## Application desktop
- Ajouter une autocomplétion Token lorsque des tables de référence fiables existeront.
- Ajouter une autocomplétion Pool lorsque des tables de référence fiables existeront.
- Introduire une pagination SQL/IPC côté serveur avant lexploitation de volumes massifs.
- Étudier une résolution configurable du chemin de base utilisé par `kb-store`.
## Pipeline et PostgreSQL
- Dimensionner dynamiquement la concurrence Decode replay en fonction du pool PostgreSQL disponible.
- Ajouter un retry borné et observable pour les erreurs transitoires de pool PostgreSQL.
- Conserver dans les résumés des compteurs distincts pour les échecs fonctionnels, les erreurs de traitement ou de stockage, les entrées récupérées après retry et les échecs finaux.
- Étudier une persistance dédiée des erreurs transitoires qui surviennent avant quune ligne de ledger puisse être écrite.
## Documentation et outils
- Refaire les scripts Python daudit après stabilisation définitive de la structure, des targets et de la nomenclature.
- Maintenir un inventaire des IDL actives avec leur source, leur version ou commit, leur Program ID et les surfaces qui les utilisent.
## Transport off-chain des metadata
- Évaluer une crate `kb-offchain-transport` générale après le pipeline metadata : fetch HTTP(S)/IPFS/Arweave, prix SOL/USD-EUR-CHF, APIs Jupiter et autres fournisseurs non Solana RPC.
- Décider séparément si cette crate accepte uniquement des lectures ou aussi des opérations off-chain authentifiées/mutables, avec contrats de sécurité distincts.
- Borner tailles, types MIME, redirections, délais et schémas HTTP(S)/IPFS/Arweave.
- Ne pas coupler le fetch off-chain au décodage déterministe ni au replay canonique on-chain.

View File

@@ -1,107 +0,0 @@
<!-- file: docs/IDL_SURFACE_CLASSIFICATION.md -->
<!-- version: 1 -->
# Classification des surfaces IDL
Ce fichier résume les reclassements déduits des fichiers présents dans `idls/`. Il ne remplace pas une validation on-chain ; il sert à stabiliser la nomenclature et les crates réservés.
## Décisions principales
- `program_ids.rs` est remplacé par `constants.rs` dans les crates core/SPL, afin de regrouper plus tard les discriminants, sélecteurs et constantes internes non publiques.
- Les constantes réexportées par le `lib.rs` dune crate doivent être appelées via `crate::CONSTANT_NAME` depuis les modules internes de cette même crate.
- Les surfaces IDL classifiées reçoivent un nom canonique fonctionnel : `amm_*`, `clmm_*`, `router_*`, `vault_*`, `lending_*`, etc.
- Les comptes non prouvés comme `program_id`, comme `BAGSB...`, restent hors workspace de décodage. Les vrais programmes Bags Fee Share V1/V2 sont classés séparément dans `docs/BAGS_FM.md`.
## Reclassements notables
| Canonique | Ancien nom/source | Justification IDL |
|--------------------------------------|-------------------------------|----------------------------------------------------------------------------------------|
| `vault_carrot_defi` | `carrot_defi` | IDL orientée vault : `initVault`, `issue`, `redeem`, `addAsset`, `removeStrategy`. |
| `lending_clone` | `clone` | IDL orientée lending : borrow positions, collateral, pool parameters, oracle updates. |
| `clmm_fusion` | `fusion_amm` | IDL avec positions, liquidity, fees et limit orders ; plus proche CLMM que simple AMM. |
| `stable_swap_hylo_exchange` | `hylo_exchange` | IDL stable/levercoin : mint, redeem, swap stable/lever. |
| `vault_hylo_stability_pool` | `hylo_stability_pool` | IDL de stability pool : user deposit/withdraw et rebalances. |
| `wallet_jupiter_apepro_smart_wallet` | `jupiter_apepro_smart_wallet` | IDL smart wallet avec approvals, `postSwap` et withdraw. |
| `vault_kamino_yvaults` | `kamino` | IDL `yvaults`, stratégies, collateral info et shares metadata. |
| `governance_metadao_bid_wall` | `metadao_bid_wall` | Surface MetaDAO liée à la gouvernance/futarchy plutôt quà un AMM direct. |
| `stable_swap_numeraire` | `numeraire` | IDL avec pool stable virtuel, add/remove liquidity et metadata LP. |
| `rwa_ondo_global_markets` | `ondo_global_markets` | IDL RWA/roles/attestation/burn ; pas un DEX. |
| `clmm_pancake_swap` | `pancake_swap` | IDL `amm_v3` avec positions et liquidity : classé CLMM. |
| `adapter_saber_decimal_wrapper` | `sabre_decimal_wrapper` | IDL wrapper dadaptation de décimales : initializeWrapper, deposit, withdraw. |
## Table IDL triée par canonique
| Canonique | Source | Program ID | IDL | Crate cible | Statut |
|------------------------------------------------|----------------------------------|------------------------------------------------|---------------------------------------------------------------------------------|-----------------------------------------------------------|---------------------|
| `adapter_saber_decimal_wrapper` | `sabre_decimal_wrapper` | `DecZY86MU5Gj7kppfUCEmd4LbXXuyZH1yHaP2NTqdiZB` | `saber_decimal.DecZY86MU5Gj7kppfUCEmd4LbXXuyZH1yHaP2NTqdiZB.json` | `kb_decoder_adapter_saber_decimal_wrapper` | `canonical_current` |
| `admin_jupiter_lock` | `jupiter_lock` | `LocpQgucEQHbqNABEYvBvwoxCPsSbG91A1QaQhQQqjn` | `jupiter_locker.LocpQgucEQHbqNABEYvBvwoxCPsSbG91A1QaQhQQqjn.json` | `kb_decoder_admin_jupiter_lock` | `canonical_current` |
| `admin_pump_fees` | `pump_fees` | `pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ` | `pump_fees.pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ.json` | `kb_decoder_admin_pump_fees` | `canonical_current` |
| `amm_bonk_swap` | `bonk_swap` | `BSwp6bEBihVLdqJRKGgzjcGLHkcTuzmSo1TQkHepzH8p` | `bonkswap.BSwp6bEBihVLdqJRKGgzjcGLHkcTuzmSo1TQkHepzH8p.json` | `kb_decoder_amm_bonk_swap` | `canonical_current` |
| `amm_goosefx_gamma` | `goose_fx_gamma` | `GAMMA7meSFWaBXF25oSUgmGRwaW6sCMFLmBNiMSdbHVT` | `goosefx_gamma.GAMMA7meSFWaBXF25oSUgmGRwaW6sCMFLmBNiMSdbHVT.json` | `kb_decoder_amm_goosefx_gamma` | `canonical_current` |
| `amm_goosefx_v2` | `goose_fx_v2` | `GFXsSL5sSaDfNFQUYsHekbWBW1TsFdjDYzACh62tEHxn` | `goosefx_v2.GFXsSL5sSaDfNFQUYsHekbWBW1TsFdjDYzACh62tEHxn.json` | `kb_decoder_amm_goosefx_v2` | `canonical_current` |
| `amm_guac_swap` | `guac_swap` | `Gswppe6ERWKpUTXvRPfXdzHhiCyJvLadVvXGfdpBqcE1` | `guacswap.Gswppe6ERWKpUTXvRPfXdzHhiCyJvLadVvXGfdpBqcE1.json` | `kb_decoder_amm_guac_swap` | `canonical_current` |
| `amm_lifinity_swap_v2` | `lifinity_swap_v2` | `2wT8Yq49kHgDzXuPxZSaeLaH1qbmGXtEyPy64bL7aD3c` | `lifinity_amm_v2.2wT8Yq49kHgDzXuPxZSaeLaH1qbmGXtEyPy64bL7aD3c.json` | `kb_decoder_amm_lifinity_swap_v2` | `canonical_current` |
| `amm_metadao_futarchy_amm` | `metadao_futarchy_amm` | `FUTARELBfJfQ8RDGhg1wdhddq1odMAJUePHFuBYfUxKq` | `metadao_futarchy.FUTARELBfJfQ8RDGhg1wdhddq1odMAJUePHFuBYfUxKq.json` | `kb_decoder_amm_metadao_futarchy_amm` | `canonical_current` |
| `amm_metadao_v0_5` | `metadao_amm_v0_5` | `AMMJdEiCCa8mdugg6JPF7gFirmmxisTfDJoSNSUi5zDJ` | `metadao_amm_v0.5.AMMJdEiCCa8mdugg6JPF7gFirmmxisTfDJoSNSUi5zDJ.json` | `kb_decoder_amm_metadao_v0_5` | `canonical_current` |
| `amm_meteora_damm_v1` | `meteora_damm_v1` | `Eo7WjKq67rjJQSZxS6z3YkapzY3eMj6Xy8X5EQVn5UaB` | `meteora_pools_amm.Eo7WjKq67rjJQSZxS6z3YkapzY3eMj6Xy8X5EQVn5UaB.json` | `kb_decoder_amm_meteora_damm_v1` | `canonical_current` |
| `amm_meteora_damm_v2` | `meteora_damm_v2` | `cpamdpZCGKUy5JxQXB4dcpGPiikHawvSWAd6mEn1sGG` | `meteora_damm_v2.cpamdpZCGKUy5JxQXB4dcpGPiikHawvSWAd6mEn1sGG.json` | `kb_decoder_amm_meteora_damm_v2` | `canonical_current` |
| `amm_pump_swap` | `pump_swap` | `pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA` | `pump_swap.pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA.json` | `kb_decoder_amm_pump_swap` | `canonical_current` |
| `amm_vertigo` | `vertigo` | `vrTGoBuy5rYSxAfV3jaRJWHH6nN9WK4NRExGxsk1bCJ` | `vertigo.vrTGoBuy5rYSxAfV3jaRJWHH6nN9WK4NRExGxsk1bCJ.json` | `kb_decoder_amm_vertigo` | `canonical_current` |
| `amm_virtuals` | `virtuals` | `5U3EU2ubXtK84QcRjWVmYt9RaDyA8gKxdUrPFXmZyaki` | `virtuals.5U3EU2ubXtK84QcRjWVmYt9RaDyA8gKxdUrPFXmZyaki.json` | `kb_decoder_amm_virtuals` | `canonical_current` |
| `amm_woofi` | `woofi` | `WooFif76YGRNjk1pA8wCsN67aQsD9f9iLsz4NcJ1AVb` | `woofi.WooFif76YGRNjk1pA8wCsN67aQsD9f9iLsz4NcJ1AVb.json` | `kb_decoder_amm_woofi` | `canonical_current` |
| `bridge_circle_cctp_token_messenger_minter` | `cctp_token_messenger_minter` | `CCTPiPYPc6AsJuwueEnWgSgucamXDZwBd53dQ11YiKX3` | `cctp_v1.CCTPiPYPc6AsJuwueEnWgSgucamXDZwBd53dQ11YiKX3.json` | `kb_decoder_bridge_circle_cctp_token_messenger_minter` | `canonical_current` |
| `bridge_circle_cctp_token_messenger_minter_v2` | `cctp_token_messenger_minter_v2` | `CCTPV2vPZJS2u2BBsUoscuikbYjnpFmbFsvVuJdgUMQe` | `cctp_v2.CCTPV2vPZJS2u2BBsUoscuikbYjnpFmbFsvVuJdgUMQe.json` | `kb_decoder_bridge_circle_cctp_token_messenger_minter_v2` | `canonical_current` |
| `bridge_layer_zero_endpoint` | `layer_zero_endpoint` | `76y77prsiCMvXMjuoZ5VRrhG5qYBrUMYTE5WgHqgjEn6` | `layerzero_endpoint.76y77prsiCMvXMjuoZ5VRrhG5qYBrUMYTE5WgHqgjEn6.json` | `kb_decoder_bridge_layer_zero_endpoint` | `canonical_current` |
| `bridge_layer_zero_executor` | `layer_zero_executor` | `6doghB248px58JSSwG4qejQ46kFMW4AMj7vzJnWZHNZn` | `layerzero_executor.6doghB248px58JSSwG4qejQ46kFMW4AMj7vzJnWZHNZn.json` | `kb_decoder_bridge_layer_zero_executor` | `canonical_current` |
| `clmm_byreal` | `byreal_clmm` | `REALQqNEomY6cQGZJUGwywTBD2UmDT32rZcNnfxQ5N2` | `byreal_clmm.REALQqNEomY6cQGZJUGwywTBD2UmDT32rZcNnfxQ5N2.json` | `kb_decoder_clmm_byreal` | `canonical_current` |
| `clmm_fusion` | `fusion_amm` | `fUSioN9YKKSa3CUC2YUc4tPkHJ5Y6XW1yz8y6F7qWz9` | `fusion_amm.fUSioN9YKKSa3CUC2YUc4tPkHJ5Y6XW1yz8y6F7qWz9.json` | `kb_decoder_clmm_fusion` | `canonical_current` |
| `clmm_orca_whirlpool` | `orca_whirlpool` | `whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc` | `orca_whirlpool.whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc.json` | `kb_decoder_clmm_orca_whirlpool` | `canonical_current` |
| `clmm_orca_whirlpool` | `orca_whirlpool` | `whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc` | `orca_whirlpool.whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc.json` | `kb_decoder_clmm_orca_whirlpool` | `canonical_current` |
| `clmm_pancake_swap` | `pancake_swap` | `HpNfyc2Saw7RKkQd8nEL4khUcuPhQ7WwY1B2qjx8jxFq` | `pancakeswap.HpNfyc2Saw7RKkQd8nEL4khUcuPhQ7WwY1B2qjx8jxFq.json` | `kb_decoder_clmm_pancake_swap` | `canonical_current` |
| `clmm_raydium` | `raydium_clmm` | `CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK` | `raydium_clmm.CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK.json` | `kb_decoder_clmm_raydium` | `canonical_current` |
| `clmm_stabble` | `stabble_clmm` | `6dMXqGZ3ga2dikrYS9ovDXgHGh5RUsb2RTUj6hrQXhk6` | `stabble_clmm.6dMXqGZ3ga2dikrYS9ovDXgHGh5RUsb2RTUj6hrQXhk6.json` | `kb_decoder_clmm_stabble` | `canonical_current` |
| `cpmm_raydium` | `raydium_cpmm` | `CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C` | `raydium_cpmm.CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C.json` | `kb_decoder_cpmm_raydium` | `canonical_current` |
| `dlmm_meteora` | `meteora_dlmm` | `LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo` | `meteora_dlmm.LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo.json` | `kb_decoder_dlmm_meteora` | `canonical_current` |
| `governance_metadao_bid_wall` | `metadao_bid_wall` | `WALL8ucBuUyL46QYxwYJjidaFYhdvxUFrgvBxPshERx` | `metdao_bid_wall.WALL8ucBuUyL46QYxwYJjidaFYhdvxUFrgvBxPshERx.json` | `kb_decoder_governance_metadao_bid_wall` | `canonical_current` |
| `launchpad_boop_fun` | `boop_fun` | `boop8hVGQGqehUK2iVEMEnMrL5RbjywRzHKBmBE7ry4` | `boop_fun.boop8hVGQGqehUK2iVEMEnMrL5RbjywRzHKBmBE7ry4.json` | `kb_decoder_launchpad_boop_fun` | `canonical_current` |
| `launchpad_metadao_ico` | `metadao_ico` | `moontUzsdepotRGe5xsfip7vLPTJnVuafqdUWexVnPM` | `metadao_launchpad.moontUzsdepotRGe5xsfip7vLPTJnVuafqdUWexVnPM.json` | `kb_decoder_launchpad_metadao_ico` | `canonical_current` |
| `launchpad_meteora_dbc` | `meteora_dbc` | `dbcij3LWUppWqq96dh6gJWwBifmcGfLSB5D4DuSMaqN` | `meteora_dbc.dbcij3LWUppWqq96dh6gJWwBifmcGfLSB5D4DuSMaqN.json` | `kb_decoder_launchpad_meteora_dbc` | `canonical_current` |
| `launchpad_moonit` | `moonit` | `MoonCVVNZFSYkqNXP6bxHLPL6QQJiMagDL3qcqUQTrG` | `moonit.MoonCVVNZFSYkqNXP6bxHLPL6QQJiMagDL3qcqUQTrG.json` | `kb_decoder_launchpad_moonit` | `canonical_current` |
| `launchpad_orca_wavebreak` | `orca_wavebreak` | `waveQX2yP3H1pVU8djGvEHmYg8uamQ84AuyGtpsrXTF` | `orca_wavebreak.waveQX2yP3H1pVU8djGvEHmYg8uamQ84AuyGtpsrXTF.json` | `kb_decoder_launchpad_orca_wavebreak` | `canonical_current` |
| `launchpad_printr` | `printr` | `T8HsGYv7sMk3kTnyaRqZrbRPuntYzdh12evXBkprint` | `printr.T8HsGYv7sMk3kTnyaRqZrbRPuntYzdh12evXBkprint.json` | `kb_decoder_launchpad_printr` | `canonical_current` |
| `launchpad_pump_fun` | `pump_fun` | `6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P` | `pump_fun.6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P.json` | `kb_decoder_launchpad_pump_fun` | `canonical_current` |
| `launchpad_pump_pumpup_ai` | `pumpup_ai` | `PdMDrKEMaX8q7CCJb7NvUCxerBCcsFUa4LjBEynTtEd` | `pumpup.PdMDrKEMaX8q7CCJb7NvUCxerBCcsFUa4LjBEynTtEd.json` | `kb_decoder_launchpad_pump_pumpup_ai` | `canonical_current` |
| `launchpad_raydium_launchlab` | `raydium_launchlab` | `LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj` | `raydium_launchlab.LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj.json` | `kb_decoder_launchpad_raydium_launchlab` | `canonical_current` |
| `lending_clone` | `clone` | `C1onEW2kPetmHmwe74YC1ESx3LnFEpVau6g2pg4fHycr` | `clone.C1onEW2kPetmHmwe74YC1ESx3LnFEpVau6g2pg4fHycr.json` | `kb_decoder_lending_clone` | `canonical_current` |
| `lending_kamino` | `kamino_lending` | `KLend2g3cP87fffoy8q1mQqGKjrxjC8boSyAYavgmjD` | `kamino_lending.KLend2g3cP87fffoy8q1mQqGKjrxjC8boSyAYavgmjD.json` | `kb_decoder_lending_kamino` | `canonical_current` |
| `lending_marginfi_v2` | `marginfi_v2` | `MFv2hWf31Z9kbCa1snEPYctwafyhdvnV7FZnsebVacA` | `marginfi_v2.MFv2hWf31Z9kbCa1snEPYctwafyhdvnV7FZnsebVacA.json` | `kb_decoder_lending_marginfi_v2` | `canonical_current` |
| `lock_raydium_lp` | `raydium_lock_lp` | `LockrWmn6K5twhz3y9w1dQERbmgSaRkfnTeTKbpofwE` | `raydium_lock.LockrWmn6K5twhz3y9w1dQERbmgSaRkfnTeTKbpofwE.json` | `kb_decoder_lock_raydium_lp` | `canonical_current` |
| `nft_metaplex_bubblegum` | `bubblegum` | `BGUMAp9Gq7iTEuizy4pqaxsTyUCBK68MDfK752saRPUY` | `bubblegum.BGUMAp9Gq7iTEuizy4pqaxsTyUCBK68MDfK752saRPUY.json` | `kb_decoder_nft_metaplex_bubblegum` | `canonical_current` |
| `orderbook_jupiter_limit_order` | `jupiter_limit_order` | `jupoNjAxXgZ4rjzxzPMP4oxduvQsQtZzyknqvzYNrNu` | `jupiter_limit_order.jupoNjAxXgZ4rjzxzPMP4oxduvQsQtZzyknqvzYNrNu.json` | `kb_decoder_orderbook_jupiter_limit_order` | `canonical_current` |
| `orderbook_jupiter_limit_order_v2` | `jupiter_limit_order_v2` | `j1o2qRpjcyUwEvwtcfhEQefh773ZgjxcVRry7LDqg5X` | `jupiter_limit_order_v2.j1o2qRpjcyUwEvwtcfhEQefh773ZgjxcVRry7LDqg5X.json` | `kb_decoder_orderbook_jupiter_limit_order_v2` | `canonical_current` |
| `orderbook_openbook_v2` | `openbook_v2` | `opnb2LAfJYbRMAHHvqjCwQxanZn7ReEHp1k81EohpZb` | `openbook_v2.opnb2LAfJYbRMAHHvqjCwQxanZn7ReEHp1k81EohpZb.json` | `kb_decoder_orderbook_openbook_v2` | `canonical_current` |
| `perpetuals_drift_v2` | `drift_v2` | `dRiftyHA39MWEi3m9aunc5MzRF1JYuBsbn6VPcn33UH` | `drift_v2.dRiftyHA39MWEi3m9aunc5MzRF1JYuBsbn6VPcn33UH.json` | `kb_decoder_perpetuals_drift_v2` | `canonical_current` |
| `perpetuals_jupiter` | `jupiter_perpetuals` | `PERPHjGBqRHArX4DySjwM6UJHiR3sWAatqfdBS2qQJu` | `jupiter_perpetuals.PERPHjGBqRHArX4DySjwM6UJHiR3sWAatqfdBS2qQJu.json` | `kb_decoder_perpetuals_jupiter` | `canonical_current` |
| `perpetuals_zeta` | `zeta` | `ZETAxsqBRek56DhiGXrn75yj2NHU3aYUnxvHXpkf3aD` | `zeta.ZETAxsqBRek56DhiGXrn75yj2NHU3aYUnxvHXpkf3aD.json` | `kb_decoder_perpetuals_zeta` | `canonical_current` |
| `router_jupiter_aggregator_v4` | `jupiter_agregator_v4` | `JUP4Fb2cqiRUcaTHdrPC8h2gNsA2ETXiPDD33WcGuJB` | `jupiter_v4.JUP4Fb2cqiRUcaTHdrPC8h2gNsA2ETXiPDD33WcGuJB.json` | `kb_decoder_router_jupiter_aggregator_v4` | `canonical_current` |
| `router_jupiter_aggregator_v6` | `jupiter_agregator_v6` | `JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4` | `jupiter_v6.JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4.json` | `kb_decoder_router_jupiter_aggregator_v6` | `canonical_current` |
| `router_jupiter_dca` | `jupiter_dca` | `DCA265Vj8a9CEuX1eb1LWRnDT7uK6q1xMipnNyatn23M` | `jupiter_dca.DCA265Vj8a9CEuX1eb1LWRnDT7uK6q1xMipnNyatn23M.json` | `kb_decoder_router_jupiter_dca` | `canonical_current` |
| `router_okx_labs_v1` | `okx_labs_v1` | `6m2CDdhRgxpH4WjvdzxAYbGxwdGUz5MziiL5jek2kBma` | `okx_lab_v1.6m2CDdhRgxpH4WjvdzxAYbGxwdGUz5MziiL5jek2kBma.json` | `kb_decoder_router_okx_labs_v1` | `canonical_current` |
| `router_okx_labs_v2` | `okx_labs_v2` | `proVF4pMXVaYqmy4NjniPh4pqKNfMmsihgd4wdkCX3u` | `okx_dex_router.proVF4pMXVaYqmy4NjniPh4pqKNfMmsihgd4wdkCX3u.json` | `kb_decoder_router_okx_labs_v2` | `canonical_current` |
| `rwa_ondo_global_markets` | `ondo_global_markets` | `XzTT4XB8m7sLD2xi6snefSasaswsKCxx5Tifjondogm` | `ondo_gm.XzTT4XB8m7sLD2xi6snefSasaswsKCxx5Tifjondogm.json` | `kb_decoder_rwa_ondo_global_markets` | `canonical_current` |
| `stable_swap_hylo_exchange` | `hylo_exchange` | `HYEXCHtHkBagdStcJCp3xbbb9B7sdMdWXFNj6mdsG4hn` | `hylo_exchange.HYEXCHtHkBagdStcJCp3xbbb9B7sdMdWXFNj6mdsG4hn.json` | `kb_decoder_stable_swap_hylo_exchange` | `canonical_current` |
| `stable_swap_jupiter_stable` | `jupiter_stable` | `JUPUSDecMzAVgztLe6eGhwUBj1Pn3j9WAXwmtHmfbRr` | `jupiter_stable.JUPUSDecMzAVgztLe6eGhwUBj1Pn3j9WAXwmtHmfbRr.json` | `kb_decoder_stable_swap_jupiter_stable` | `canonical_current` |
| `stable_swap_numeraire` | `numeraire` | `NUMERUNsFCP3kuNmWZuXtm1AaQCPj9uw6Guv2Ekoi5P` | `numeraire.NUMERUNsFCP3kuNmWZuXtm1AaQCPj9uw6Guv2Ekoi5P.json` | `kb_decoder_stable_swap_numeraire` | `canonical_current` |
| `stable_swap_stabble` | `stabble_stable_swap` | `swapNyd8XiQwJ6ianp9snpu4brUqFxadzvHebnAXjJZ` | `stabble_stable_swap.swapNyd8XiQwJ6ianp9snpu4brUqFxadzvHebnAXjJZ.json` | `kb_decoder_stable_swap_stabble` | `canonical_current` |
| `staking_kamino_farm` | `kamino_farm` | `FarmsPZpWu9i7Kky8tPN37rs2TpmMrAZrC7S7vJa91Hr` | `kamino_farms.FarmsPZpWu9i7Kky8tPN37rs2TpmMrAZrC7S7vJa91Hr.json` | `kb_decoder_staking_kamino_farm` | `canonical_current` |
| `staking_marinade_finance` | `marinade_finance` | `MarBmsSgKXdrN1egZf5sqe1TMai9K1rChYNDJgjq7aD` | `marinade_finance.MarBmsSgKXdrN1egZf5sqe1TMai9K1rChYNDJgjq7aD.json` | `kb_decoder_staking_marinade_finance` | `canonical_current` |
| `treasury_helium_treasury_management` | `helium_treasury_management` | `treaf4wWBBty3fHdyBpo35Mz84M8k3heKXmjmi9vFt5` | `helium_treasury_management.treaf4wWBBty3fHdyBpo35Mz84M8k3heKXmjmi9vFt5.json` | `kb_decoder_treasury_helium_treasury_management` | `canonical_current` |
| `vault_carrot_defi` | `carrot_defi` | `CarrotwivhMpDnm27EHmRLeQ683Z1PufuqEmBZvD282s` | `carrot.CarrotwivhMpDnm27EHmRLeQ683Z1PufuqEmBZvD282s.json` | `kb_decoder_vault_carrot_defi` | `canonical_current` |
| `vault_hylo_stability_pool` | `hylo_stability_pool` | `HysTabVUfmQBFcmzu1ctRd1Y1fxd66RBpboy1bmtDSQQ` | `hylo_stability_pool.HysTabVUfmQBFcmzu1ctRd1Y1fxd66RBpboy1bmtDSQQ.json` | `kb_decoder_vault_hylo_stability_pool` | `canonical_current` |
| `vault_kamino` | `kamino_vault` | `kvauTFR8qm1dhniz6pYuBZkuene3Hfrs1VQhVRgCNrr` | `kamino_vault.kvauTFR8qm1dhniz6pYuBZkuene3Hfrs1VQhVRgCNrr.json` | `kb_decoder_vault_kamino` | `canonical_current` |
| `vault_kamino_v2` | `kamino_vault_v2` | `KvauGMspG5k6rtzrqqn7WNn3oZdyKqLKwK2XWQ8FLjd` | `kamino_vault_v2.KvauGMspG5k6rtzrqqn7WNn3oZdyKqLKwK2XWQ8FLjd.json` | `kb_decoder_vault_kamino_v2` | `canonical_current` |
| `vault_kamino_yvaults` | `kamino` | `6LtLpnUFNByNXLyCoK9wA2MykKAmQNZKBdY8s47dehDc` | `kamino.6LtLpnUFNByNXLyCoK9wA2MykKAmQNZKBdY8s47dehDc.json` | `kb_decoder_vault_kamino_yvaults` | `canonical_current` |
| `vault_meteora` | `meteora_vault` | `24Uqj9JCLxUeoC3hGfh5W3s9FM9uCHDS2SG3LYwBpyTi` | `meteora_vault.24Uqj9JCLxUeoC3hGfh5W3s9FM9uCHDS2SG3LYwBpyTi.json` | `kb_decoder_vault_meteora` | `canonical_current` |
| `vesting_streamflow` | `streamflow` | `strmRqUCoQUgGUan5YhzUZa6KqdzwX5L6FpUxfmKg5m` | `streamflow.strmRqUCoQUgGUan5YhzUZa6KqdzwX5L6FpUxfmKg5m.json` | `kb_decoder_vesting_streamflow` | `canonical_current` |
| `wallet_jupiter_apepro_smart_wallet` | `jupiter_apepro_smart_wallet` | `JSW99DKmxNyREQM14SQLDykeBvEUG63TeohrvmofEiw` | `jupiter_aprepro_smart_wallet.JSW99DKmxNyREQM14SQLDykeBvEUG63TeohrvmofEiw.json` | `kb_decoder_wallet_jupiter_apepro_smart_wallet` | `canonical_current` |
| `weighted_swap_stabble` | `stabble_weighted_swap` | `swapFpHZwjELNnjvThjajtiVmkz3yPQEHjLtka2fwHW` | `stabble_weighted_swap.swapFpHZwjELNnjvThjajtiVmkz3yPQEHjLtka2fwHW.json` | `kb_decoder_weighted_swap_stabble` | `canonical_current` |

View File

@@ -1,112 +0,0 @@
<!-- file: docs/INSTRUCTION_REPLAY_CONTRACTS.md -->
<!-- version: 4 -->
# Contrats de replay par instruction
Ce document complète le cadrage `0.2.1`. Il ne crée pas encore le schéma SQL complet, mais il verrouille l'idée suivante : le scheduling de replay doit cibler les instructions normalisées, tandis que le décodage doit recevoir une instruction avec son contexte Solana extrait.
## Motivation
Une transaction Solana peut contenir plusieurs instructions top-level et plusieurs inner instructions. Certaines instructions peuvent être déjà décodées, d'autres non. Rejouer toute la transaction à chaque correction de décodeur serait plus coûteux et moins précis.
Le pipeline doit donc pouvoir faire :
```text
raw transaction
→ extraction core transaction
→ extraction account keys, instructions, inner instructions, logs, balances
→ sélection des instructions non traitées
→ reconstruction d'un replay input contextualisé
→ decode/materialize uniquement sur ces inputs
```
## Scheduling instruction-level
L'état `CoreInstructionProcessingState` prépare cette granularité.
| État | Sens |
|-------------------|---------------------------------------------------------------|
| `Pending` | Instruction disponible pour premier traitement. |
| `Decoded` | Instruction décodée par au moins un décodeur. |
| `Materialized` | Instruction ayant produit une projection métier. |
| `Ignored` | Instruction ignorée volontairement par la politique courante. |
| `Failed` | Instruction en échec, à diagnostiquer. |
| `ReplayRequested` | Instruction à rejouer même si un traitement précédent existe. |
Les états ne remplacent pas le ledger par module/version. Ils servent de vue rapide et de filtre de scheduling.
## Décodage contextualisé
Le décodeur ne doit pas être limité à `CoreInstructionRow.payload_json`.
Certains protocoles Solana exigent de lire :
- les inner instructions ;
- les logs Anchor ou non Anchor ;
- les balances avant/après ;
- les comptes résolus ;
- les loaded addresses ;
- les erreurs de transaction ;
- des séquences de logs liées à un CPI ;
- des instructions voisines de la même transaction.
`MdCoreInstructionReplayInput` représente ce contrat de lecture : une instruction ciblée plus un contexte extrait depuis les tables `core`. Depuis le contrat `2`, ce contexte inclut également toutes les instructions outer de la signature, ordonnées numériquement et munies de leur payload retenu et de son hash.
## Sélection de replay
`CoreInstructionReplayFilter` permet de sélectionner les instructions par :
- état de traitement ;
- `program_id` ;
- plage de slots.
L'usage standard pour un worker de decode sera :
```text
processing_state = Pending ou ReplayRequested
program_id = programme ciblé par le décodeur
plage de slots = optionnelle
```
Le repository charge les logs, balances, account keys et instructions outer nécessaires pour retourner `MdCoreInstructionReplayInput`. La liste outer inclut la cible et utilise les champs stables `instructionIndex`, `instructionPath`, `programId`, `payloadJson` et `payloadHash`. Cette extension lit les tables existantes et ne demande aucune migration.
## Marquage de cycle de vie
`CoreInstructionLifecycleMark` permet à un module de changer l'état d'une instruction après traitement.
Exemples :
- un décodeur reconnu marque l'instruction `Decoded` ;
- un materializer complet marque l'instruction `Materialized` ;
- un décodeur non concerné peut marquer `Ignored` dans un contexte contrôlé ;
- une erreur de parsing marque `Failed` ;
- une correction de décodeur peut remettre `ReplayRequested`.
## Relation avec `kb_sol_ops_processing_ledger`
Le processing ledger garde le détail par module, version et input. L'état sur l'instruction reste le dernier état opérationnel visible.
Pour éviter les doublons, l'input key du ledger devra être stable, par exemple :
```text
signature:instruction_path:program_id:processor_name:processor_version
```
La forme exacte n'est pas figée en `0.2.1`, mais elle doit rester déterministe.
## Rétention du payload d'instruction et des logs
Le payload JSON d'une instruction et le texte des logs sont utiles au début. Plus tard, après décodage et matérialisation fiables, ils pourront être compactés ou purgés avec conservation d'un hash.
Les entities `CoreInstructionRow` et `CoreLogRow` préparent ce cas en autorisant :
- payload ou texte présent ;
- payload ou texte absent ;
- hash conservé ;
- état de traitement consultable pour replay.
La purge effective ne doit pas être implémentée avant que les diagnostics de replay soient fiables.
## Décision pour `0.2.1`
`0.2.1` ajoute les contrats Rust nécessaires, mais ne crée pas encore les tables SQL. Les migrations réelles restent prévues pour `0.2.3` et `0.2.4`.

View File

@@ -1,31 +0,0 @@
# Audit de migration de `kb-lib`
## État après `0.1.0-pre.021`
Linventaire des anciennes crates métier de `khadhroony-bot2` a été comparé à larborescence consolidée de `khadhroony-bot3/kb-lib`.
### Implémentations fonctionnelles migrées
- modèles et contrats publics de décodage, matérialisation et exécution ;
- décodeur Solana Core ;
- décodeurs SPL Memo, Token classique, ATA, Token-2022 et ElGamal Registry ;
- décodeur Metaplex Token Metadata dans létat intermédiaire atteint par bot2 `0.4.7` ;
- matérialisateurs transaction annotations, token accounts, admin, risk, fees, lifecycle, metadata, staking et compliance audit ;
- exécuteurs Solana Core, SPL Memo v4, SPL Token classique, ATA, Token-2022 et ElGamal Registry ;
- politique de sécurité commune des exécuteurs.
### Éléments encore à migrer dans `kb-lib`
Il reste une ancienne crate fonctionnelle :
- `kb-lib::executor::solana::transaction` : assemblage de transactions legacy, durable nonce, validation des comptes nonce, signature, preuves de simulation et contrôle de taille de paquet.
Cette couche nest pas un exécuteur de programme. Elle doit être portée sous la famille `executor/solana` avant la migration du transport on-chain.
### Éléments volontairement réservés
Les autres modules de décodeurs, matérialisateurs et exécuteurs présents dans bot3 correspondent aux placeholders réservés de bot2. Ils ne contiennent pas dimplémentation fonctionnelle perdue à migrer.
### Étape suivante
La couche `kb-lib::executor::solana::transaction` est migrée. Après validation utilisateur de cette tranche, la parité fonctionnelle de `kb-lib` avec bot2 est close avant la future crate de transport on-chain.

View File

@@ -1,104 +0,0 @@
<!-- file: docs/LIVE_SOURCE_STRATEGY.md -->
<!-- version: 3 -->
# Stratégie des sources de transactions
## Décision actuelle
Les sources temps réel payantes ne sont plus laxe actif de `0.3.x`.
La priorité est :
```text
backfills HTTP sur comptes gratuits
-> transaction canonique
-> extraction core
-> décodeurs Core/Pump/Meteora/Raydium/Orca/Jupiter
```
Helius Developer, Triton, Chainstack, Shyft ou un autre provider seront testés seulement lorsque le pipeline pourra décoder et matérialiser immédiatement les transactions reçues.
## Sources futures
### HTTP JSON-RPC
Usage :
- backfill historique ;
- hydratation de signatures ;
- réparation ;
- validation ponctuelle.
Méthodes principales :
```text
getSignaturesForAddress
getTransaction
getSignatureStatuses
getSlot
```
### Helius WebSocket enrichi
`transactionSubscribe` est une extension Helius, pas une méthode Solana standard.
Elle sera implémentée dans des modules internes de `kb_onchain_transport`, sans créer de crate séparée, puis convertie vers le modèle canonique commun.
### Yellowstone gRPC
Yellowstone fournit léquivalent fonctionnel dun flux de transactions complètes filtrées. Les endpoints Triton, Chainstack, Shyft ou compatibles doivent être supportés par configuration dans `kb_onchain_transport`.
### Solana WebSocket standard
`logsSubscribe` par mention ou avec filtre `"all"` reste une solution de probe, de fallback ou de comparaison. Une notification de logs ne devient durable quaprès hydratation de la transaction ou enregistrement dune observation technique légère.
## Stockage commun
Toutes les sources convergent vers :
```text
kb_sol_raw_transactions
kb_sol_obs_transaction_observations
```
Les décodeurs ne connaissent ni le fournisseur, ni le protocole, ni la méthode dacquisition.
## Ordre de mise en œuvre
```text
0.3.x transaction canonique, observations, backfill gratuit, extraction core
0.4.x décodeurs Core/SPL
0.5.x Pump
0.6.x Meteora
0.7.x Raydium
0.8.x Orca
0.9.x Jupiter et routeurs
0.10.x Helius transactionSubscribe, Yellowstone gRPC et comparaison
```
## Sécurité de reprise
Pendant toute perte du flux principal :
```text
trading = disabled
```
Le replay ou le backfill après reconnexion sert à remettre la base en cohérence. Un événement `replayed`, `backfilled` ou `repaired` ne doit pas déclencher rétroactivement un ordre.
## Critères de choix futur
La décision provider devra comparer :
- couverture par programme et CPI ;
- latence par signature ;
- coût par Go, crédit ou forfait ;
- nombre de filtres et streams ;
- régions ;
- reconnexion et fenêtre de replay ;
- pertes et backpressure ;
- portabilité du protocole ;
- qualité du support.
Les timings seront mesurés dans `kb_sol_obs_transaction_observations`.

View File

@@ -1,106 +0,0 @@
<!-- file: docs/LOGGING.md -->
<!-- version: 9 -->
# Logging
La journalisation est centralisée dans `kb_logging` et repose sur des événements `tracing` structurés.
## Objectifs
- séparer console, fichiers globaux et fichiers par crate ;
- conserver un fichier JSONL dédié aux erreurs ;
- retrouver immédiatement un échec de décodage ou de matérialisation ;
- corréler RPC, pipeline, store et processor sans dupliquer les décisions dans Tauri ;
- activer le debug dune crate sans dépendre de son découpage interne en modules.
## Arborescence dun profil
Pour un profil stocké sous `logs/<profile>/`, la configuration crée :
```text
logs/<profile>/debug.log
logs/<profile>/info.log
logs/<profile>/error.jsonl
logs/<profile>/app.log
logs/<profile>/<crate>/debug.log
logs/<profile>/<crate>/info.log
logs/<profile>/<crate>/error.jsonl
```
Les routes sont en rotation quotidienne. `tracing-appender` insère la date dans le nom physique produit à partir du préfixe et du suffixe configurés.
Les niveaux sont cumulatifs :
- `debug.log` reçoit `debug`, `info`, `warn` et `error` ;
- `info.log` reçoit `info`, `warn` et `error` ;
- `error.jsonl` reçoit uniquement `error` ;
- `app.log` reçoit les événements `kb_app_demo` à partir de `debug`.
`error.jsonl` utilise le format JSON pour permettre la recherche par champ. Les autres fichiers utilisent le format humain sans ANSI.
## Targets canoniques
Le target est le nom exact de la crate hors `kb-lib`. Dans `kb-lib`, il suit la hiérarchie du composant :
```text
kb_app_demo
kb_decoder_solana_core
kb_executor_metadata_spl_name_service
kb_executor_solana_core
kb_executor_spl_account_compression
kb_executor_spl_memo
kb_executor_spl_noop
kb_executor_spl_single_pool
kb_logging
kb-lib.materializer.admin
kb-lib.materializer.compliance
kb-lib.materializer.lifecycle
kb-lib.materializer.staking
kb_pipeline
kb_onchain_transport
kb_store_pg
```
La granularité passe par les champs `action`, `stage`, `window`, `campaign_id`, `signature`, `instruction_path`, `program_id`, `processor_name`, `status` et `error_code`.
## Corrélation de campagne
Les campagnes de backfill, extraction core et replay decode utilisent des identifiants stables :
```text
capture_session_id
campaign_id
signature
slot
instruction_path
program_id
input_key
input_hash
processor_name
processor_version
```
Le pipeline journalise la sélection et lagrégation. Le RPC journalise le transport et lendpoint sélectionné sans exposer lURL secrète. Le store journalise la persistance et les rollbacks. Le décodeur et chacun des matérialiseurs lifecycle, admin et compliance audit journalisent leur décision propre.
## Fichier derreurs
Les erreurs de décodage et de matérialisation sont émises au niveau `error` par la crate responsable, puis éventuellement par la frontière qui constate léchec terminal. Elles apparaissent donc dans :
- `logs/<profile>/error.jsonl` ;
- `logs/<profile>/<crate>/error.jsonl`.
Cette duplication volontaire fournit une vue globale et une vue isolée par composant. Les champs de corrélation permettent de regrouper les événements dun même défaut.
Une transaction on-chain échouée mais correctement décodée nest pas écrite dans `error.jsonl` uniquement à cause de `meta.err`. En revanche, un payload déclaré compatible mais `failed` ou `unsupported` indique une lacune du code ou une évolution du protocole et doit être visible dans le fichier derreurs.
## Frontend et Tauri
Le frontend peut continuer à transmettre un identifiant logique tel que `kb_app_demo.frontend.demo_decode_replay`. Le backend le valide et le conserve dans le champ `frontend_target`, mais lévénement est émis avec le target canonique `kb_app_demo`.
`kb_app_demo` ne doit pas recopier les détails internes dun retry RPC, dun parsing binaire ou dun commit SQL. Il journalise linvocation, la progression visible et le résumé reçu de la crate opérationnelle.
## Sécurité
Les logs ne contiennent jamais de clé privée, seed phrase, DSN non masqué, URL fournisseur secrète ou payload complet non borné. Pour un payload problématique, conserver la taille, un préfixe borné et un SHA-256.
Le contrat normatif complet se trouve dans `docs/TRACING_CONTRACT.md`.

View File

@@ -1,80 +0,0 @@
<!-- file: docs/MATERIALIZATIONS.md -->
<!-- version: 8 -->
# Catalogue des matérialisations
Les matérialisations transforment des événements décodés en événements métier exploitables par la base de données, les validations, les agrégations et les futurs signaux de stratégie.
## Matérialisations prioritaires
- `trade` : swaps, buys, sells, fills et conversions entre actifs.
- `liquidity` : dépôts, retraits, ajout ou retrait de liquidité, bootstrap de pool.
- `lifecycle` : création, initialisation, migration, fermeture ou changement d'état d'un pool, marché, compte ou vault.
- `fee` : collecte, claim, sweep, buyback, mise à jour de configuration de frais.
- `admin` : changement d'autorité, update de config, pause, unpause, transfert de rôle.
- `token_account` : création ATA, transfert, mint, burn, close account, approve, revoke.
- `pool_state` : snapshots de réserves, ticks, bins, prix, liquidité active ou virtual reserves.
- `orderbook` : place order, cancel order, fill, settle funds, consume events.
- `reward` : émission, claim, distribution, farming, incentives.
- `risk` : signaux dérivés à partir des événements admin, liquidité, metadata, authority ou anomalies.
## Projections natives portées dans `kb-lib`
`kb_lib::LifecycleMaterializer` produit des événements lifecycle idempotents à partir d'observations exactes, réussies et commitées :
| Domaine | Sortie stable | Entrées couvertes |
|----------------------|--------------------------------------------|--------------------------------------------------------------------------------------------------------------|
| Address Lookup Table | `address_lookup_table:<operation>:0` | create, freeze, extend, deactivate, close |
| Program loaders | `program_loader:<surface>:<operation>:0` | finalize immuable, initialize/deploy/upgrade/close/extend upgradeable, set length/deploy/retract/finalize v4 |
| Feature Gate | `feature_gate:revoke_pending_activation:0` | revoke pending activation |
| Comptes System | `system_account:<operation>:0` | create, create with seed, create allow prefund, allocate, allocate with seed |
| Durable nonce System | `durable_nonce_account:<operation>:0` | initialize, advance, authorize, upgrade, withdraw |
| Contexte ZK ElGamal | `zk_proof_context:<operation>:0` | initialisation demandée après vérification réussie, fermeture |
| Rapport Slashing | `slashing_violation_report:<operation>:0` | initialisation après preuve duplicate block acceptée, fermeture après rétention |
La famille décodée n'impose pas à elle seule la famille matérialisée. `authorize_nonce_account` est un événement `Admin`, tandis qu'une vérification ZK ElGamal est un événement `Audit`; ces observations ne produisent une sortie `Lifecycle` que lorsque leur mutation durable exacte est reconnue. Une transaction échouée ou non commitée est toujours refusée.
`kb_lib::AdminMaterializer` produit des sorties `Admin` pour les assignations System, les écritures Config opaques et les changements dautorité Loader. `kb_lib::ComplianceAuditMaterializer` produit des sorties `ComplianceAudit` pour les écritures/copies de bytecode Loader. `kb_lib::StakingMaterializer` produit les projections instructionnelles Stake/Vote commitées : comptes stake/vote, autorités, lockup, délégation, vote state, retraits et dépôt de rewards. Les données complètes ne sont jamais recopiées : seules les clés, autorités, offsets, tailles, hashes, préfixes et paramètres bornés disponibles sont conservés.
Les implémentations résident dans des modules privés et sont réexportées uniquement à la racine de `kb-lib`. Les identités de processor historiques restent stables pour les replays ; les targets de tracing utilisent la hiérarchie consolidée `kb-lib.materializer.*`.
Le retrait d'un nonce account conserve une sémantique conditionnelle : le runtime ferme le compte uniquement lorsque la totalité du solde est retirée. La projection décrit l'opération commitée et ne prétend pas reconstruire l'état final transactionnel du compte. Les deltas SOL restent la responsabilité du graphe core.
Une preuve ZK n'est jamais matérialisée. Seul le lifecycle du compte de contexte est projeté lorsqu'il existe. Un rapport Slashing conserve le signal de violation et son lifecycle, mais pas le contenu du compte de preuve externe ; `penaltyAppliedByProgram` reste faux car le programme ne retire pas lui-même du stake. L'ancien ZK Token Proof Program reste en decode/audit, car le runtime actuel est sans effet et aucun historique mainnet fiable n'a été observé.
## Projections SPL et Metaplex portées
- `MtTransactionAnnotationMaterializer` accepte uniquement les observations Memo exactes, réussies et commitées, puis produit une annotation idempotente bornée avec texte, hash, génération et signataires vérifiés.
- `MtTokenAccountsMaterializer` projette les mutations SPL Token classique et Token2022, possède le lifecycle ATA et peut produire un snapshot borné Mint/Account/Multisig Token2022 à partir de létat parsé.
- `MtFeesMaterializer` projette les instructions et snapshots de frais Token2022 publics ou confidentiels. Les blobs confidentiels restent opaques et `confidentialValuesDecrypted` demeure faux.
- `MtRiskMaterializer` produit uniquement des faits structurels SPL Token/ATA : délégation, freeze/thaw, autorités révoquées, multisig faible et récupération dATA imbriquée. Aucun score arbitraire nest inventé.
- `MtMetadataMaterializer` projette les metadata incorporées Token2022 et les comptes Metaplex canoniques, avec provenance et lifecycle explicites. `externalUriFetched` reste faux.
Le registre ElGamal ne possède pas un matérialiseur autonome : ses snapshots administratifs sont la responsabilité de `MtAdminMaterializer`. Le fetch HTTP/IPFS/Arweave des URI est off-chain et reste réservé à une future crate dédiée.
## Matérialisations spécialisées à prévoir
- `nft` : NFT classiques, programmables et compressés.
- `metadata` avancée : fetch off-chain borné, réconciliation de provenance et historique des changements.
- `oracle` : prix, publisher, confidence, staleness et sources d'oracle.
- `lending` : borrow, repay, collateral, liquidation et health factor.
- `staking` avancé : snapshots de comptes Stake/Vote avant/après, activation par epoch, crédits Vote cumulés et réconciliation avec sysvars.
- `governance` : proposal, vote, execute et update de realm/config.
- `bridge` : lock, mint wrapped asset, burn, redeem et message verification.
- `perpetuals` : position, funding, liquidation, collateral et PnL.
- `vault` : share mint/burn, deposit, withdraw, rebalance et fee collection.
- `routing` : route, route leg, quote, slippage, aggregator hop.
- `compliance_audit` : événements d'audit non directement matérialisables en trading.
- `token_metadata_risk` : signaux de risque issus des métadonnées de tokens, par exemple autorité mutable, creators suspects, symbol/URI incohérents ou changements de metadata.
## Projections natives encore à terminer avant clôture
Toutes les sémantiques matérialisables ne sont pas encore projetées. Les lots restants sont explicites :
- Compute Budget : profil transactionnel agrégé regroupant toutes les instructions Compute Budget du message.
Les précompiles de signature et les preuves ZK sans contexte restent des observations d'audit déjà suffisantes. Une projection supplémentaire n'est justifiée que si un consommateur `compliance_audit` exige une table dédiée. L'ancien ZK Token Proof no-op reste sans matérialisation.
## Règle de conception
Une matérialisation spécialisée ne doit être ajoutée que si la table générique ne suffit pas pour représenter correctement la sémantique du protocole. Le modèle commun reste prioritaire, puis les tables spécialisées complètent ce modèle. Chaque projection doit posséder une identité stable, un état cible explicite, une politique d'idempotence et une règle documentée pour les transactions échouées.

View File

@@ -1,113 +0,0 @@
<!-- file: docs/NATIVE_SOLANA_CLOSURE_AUDIT.md -->
<!-- version: 5 -->
# Audit de clôture Solana natif `0.4.1`
## Objet
Ce document fixe létat final du jalon `0.4.1` : couverture native, preuves synthétiques, corpus mainnet observés et limites assumées.
Labsence de transaction mainnet nautorise ni à supprimer une surface officielle, ni à prétendre quelle a été observée. Elle impose une validation synthétique documentée et une tentative de découverte bornée lorsque la surface est officiellement déclarée.
## Surfaces couvertes
`kb_decoder_solana_core` couvre 18 surfaces exécutables natives ou assimilées :
1. System Program ;
2. Vote Program ;
3. Stake Program ;
4. Config Program ;
5. Compute Budget Program ;
6. Address Lookup Table Program ;
7. ZK ElGamal Proof Program ;
8. Feature Program ;
9. ancien ZK Token Proof Program ;
10. Native Loader ;
11. BPF Loader v1 ;
12. BPF Loader v2 ;
13. BPF Loader Upgradeable ;
14. Loader v4 ;
15. Ed25519 precompile ;
16. secp256k1 precompile ;
17. secp256r1 precompile ;
18. Slashing Program.
`StakeConfig11111111111111111111111111111111` est volontairement classé comme compte natif historique non exécutable.
## Divergence Slashing corrigée
Agave `v4.1.1` déclare le programme stateless Slashing sous :
```text
S1ashing11111111111111111111111111111111111
```
La surface a été ajoutée dans `pre.018` : deux instructions exactes, dispatch sans fallback, couverture déclarée et projection de rapport. Aucun corpus public observable na été trouvé ; la validation repose donc sur les sources officielles et les fixtures synthétiques.
## Invariants automatiques
Les tests garantissent que :
- chaque entrée de `kb_program_ids::native_program_ids()` possède exactement une surface de décodeur ;
- chaque surface possède au moins une déclaration de couverture ;
- aucune déclaration nutilise le fallback `unclassified_native_instruction` ;
- chaque déclaration référence une surface réellement déclarée ;
- les identités programme/surface/entrée sont uniques ;
- le Slashing Program est dispatché vers son parseur exact ;
- ZK Token Proof historique passe par le fallback actuel no-op sans prétendre vérifier une preuve.
## Corpus et replays validés
| Programme | Résultat de clôture |
|---------------------------|------------------------------------------------------------------------------|
| System | 817 inputs décodés, 258 sorties, 52 refus attendus sur transactions échouées |
| Config | 96 inputs décodés, 96 sorties admin |
| Stake | 448 inputs décodés, 447 sorties, 1 refus attendu |
| Vote | 600 inputs décodés, 600 sorties |
| Compute Budget | 2 746 inputs décodés, 1 603 profils transactionnels |
| Address Lookup Table | 104 inputs décodés, 104 sorties lifecycle |
| ZK ElGamal | 151 inputs décodés, 139 sorties de contexte |
| Slashing | zéro corpus public observable, validation synthétique |
| Feature | zéro corpus observable dans les campagnes adressées, validation synthétique |
| Loaders rares | zéro corpus observable pour certaines générations, validation synthétique |
| ZK Token Proof historique | zéro corpus public observable, runtime actuel no-op, validation synthétique |
Les campagnes de clôture rapportées ont `unmatched = 0`, `failedInputs = 0`, `unsupported = 0` et ne produisent pas derreurs opérationnelles dans les journaux fournis.
## Backfills
Aucun backfill supplémentaire nest requis pour clôturer `0.4.1`.
Le mode `program_latest` ajouté dans `pre.019` reste disponible pour de futures recherches sans signature dancrage. Il ne doit pas être utilisé pour inventer un corpus absent sur des surfaces feature-gated ou historiquement rares.
## Matérialisations
La clôture instructionnelle est documentée dans `docs/NATIVE_SOLANA_MATERIALIZATION_AUDIT.md`.
Aucune projection native stable immédiatement dérivable du graphe core actuel nest identifiée comme manquante. Les snapshots finaux de comptes et métriques runtime restent différés.
## Validations finales
Validations utilisateur finales rapportées pour la clôture :
```text
kb_program_ids 5 tests
kb_decoder_solana_core 114 tests
kb_materializer_lifecycle 16 tests
kb_materializer_admin 7 tests
kb_materializer_compliance_audit 7 tests
kb_materializer_staking 8 tests
kb_config 36 tests
kb_pipeline 45 tests
kb_store_pg 45 tests avec PostgreSQL réel
kb_app_demo 78 tests
cargo clippy --all-targets propre
```
Le démarrage Tauri validé après `pre.021-fix.001` confirme les 53 routes de logging et linitialisation PostgreSQL. `pre.022` ne modifie pas la configuration Tauri.
## Décision
`0.4.1` est clôturée.
La prochaine session doit utiliser `prompts/022_v0_4_2_executor_solana_core.md` et démarrer `0.4.2` sur linfrastructure dexécution et `kb_executor_solana_core`.

View File

@@ -1,85 +0,0 @@
<!-- file: docs/NATIVE_SOLANA_MATERIALIZATION_AUDIT.md -->
<!-- version: 6 -->
# Audit des matérialisations Solana natives
## Conclusion
`0.4.1` clôt les matérialisations natives instructionnelles stables. Les projections actives couvrent les mutations ou profils qui peuvent être déduits de façon déterministe depuis le graphe core transactionnel et les événements décodés.
Les sorties ne sont pas des snapshots finaux de comptes ou de runtime. Les états finaux qui exigent létat précédent/suivant dun compte, les sysvars historiques ou des métriques runtime restent différés jusquà enrichissement explicite du contrat core.
## Projections actives par matérialiseur
| Matérialiseur | Surfaces | Projection |
|---------------------------------|----------------------|---------------------------------------------------------------------------------------------------------------------|
| `MtLifecycleMaterializer` | Address Lookup Table | lifecycle create/freeze/extend/deactivate/close |
| `MtLifecycleMaterializer` | Feature | révocation de feature gate |
| `MtLifecycleMaterializer` | Loaders | déploiement, finalisation et transitions lifecycle stables |
| `MtLifecycleMaterializer` | System | durable nonce, create account et allocate |
| `MtLifecycleMaterializer` | ZK ElGamal | création ou fermeture dun compte de contexte |
| `MtLifecycleMaterializer` | Slashing | initialisation ou fermeture dun rapport de violation |
| `MtAdminMaterializer` | System | assign et assign with seed |
| `MtAdminMaterializer` | Config | écriture opaque bornée avec clés, taille, SHA-256 et préfixe |
| `MtAdminMaterializer` | Loaders | changements dautorité |
| `MtComplianceAuditMaterializer` | Loaders | écritures/copies de bytecode bornées par offsets, tailles, SHA-256 et préfixes |
| `MtComplianceAuditMaterializer` | Compute Budget | profil transactionnel agrégé, last-write-wins, une seule sortie par transaction |
| `MtStakingMaterializer` | Stake | compte, délégation, désactivation, split, merge, withdraw, move stake/lamports, autorités et lockup instructionnels |
| `MtStakingMaterializer` | Vote | compte, autorités, identité, commission, vote state, retraits et dépôt de rewards instructionnels |
## Politique des transactions échouées
Les transactions on-chain échouées restent décodables comme intentions ou diagnostics. Les matérialiseurs mutables utilisent la politique `SuccessfulCommittedOnly` et refusent les observations non commitées au lieu de produire une mutation réussie fictive.
Le profil Compute Budget est une sortie `ComplianceAudit`, pas une mutation détat ; il peut donc être matérialisé même lorsque la transaction échoue. Il décrit le budget demandé par les instructions, pas les unités réellement consommées.
## Absences volontaires
Les surfaces suivantes ne produisent pas de projection dédiée dans `kb_sol_mat_events` à la clôture de `0.4.1` :
- Ed25519 ;
- secp256k1 ;
- secp256r1 ;
- preuves ZK sans compte de contexte ;
- ancien ZK Token Proof historique/no-op.
Leur décodage est déjà un événement daudit borné. Une matérialisation supplémentaire serait une duplication sans consommateur métier dédié.
## États finaux différés
Les éléments suivants ne doivent pas être présentés comme disponibles dans `0.4.1` :
- état final exact dun compte Stake ou Vote ;
- activation/désactivation Stake par epoch ;
- crédits Vote cumulés ;
- rewards recalculées par epoch ;
- état final dun compte System après lamport drain conditionnel ;
- bytecode final complet dun loader ;
- unités compute réellement consommées ;
- frais finaux réellement facturés ;
- résultat cryptographique recalculé pour signature ou preuve ZK.
Ces états exigent une extension du contexte core ou un audit de comptes/snapshots dédié.
## Validations finales `0.4.1`
Les validations utilisateur finales couvrent :
| Surface | Corpus / preuve | Résultat |
|----------------------|--------------------------------|----------------------------------------------------------------|
| System | replay ciblé | 817 inputs décodés, 258 sorties, 52 refus attendus |
| Config | replay ciblé | 96 inputs décodés, 96 sorties admin |
| Stake | replay ciblé | 448 inputs décodés, 447 sorties, 1 refus attendu |
| Vote | replay ciblé | 600 inputs décodés, 600 sorties |
| Compute Budget | replay ciblé | 2 746 inputs décodés, 1 603 profils |
| ZK ElGamal | replay ciblé | 151 inputs décodés, 139 sorties de contexte |
| Address Lookup Table | inventaire/replay ciblé | 104 inputs décodés, 104 sorties lifecycle |
| Slashing | sources officielles + fixtures | aucun corpus public observable, validation synthétique assumée |
Toutes les campagnes de clôture rapportées se terminent avec `unmatched = 0`, `failedInputs = 0`, `unsupported = 0` et des journaux `error.jsonl` vides.
## Décision de clôture
Aucune projection native instructionnelle stable nest identifiée comme manquante dans le périmètre `0.4.1`.
La suite `0.4.2` peut se concentrer sur lexécution : plans, simulation, signature, envoi et validation post-exécution, sans rouvrir le jalon de décodage/matérialisation natif.

View File

@@ -1,233 +0,0 @@
<!-- file: docs/NATIVE_SOLANA_PROGRAMS.md -->
<!-- version: 18 -->
# Inventaire et couverture des programmes Solana natifs
## Périmètre
Le registre `kb_program_ids::native_program_ids()` contient dix-huit surfaces exécutables : programmes runtime natifs, loaders, précompiles et programmes historiques encore observables. Les sysvars et comptes natifs non exécutables restent suivis séparément dans `registry/core_program_id_seed.toml`.
Memo ne fait pas partie de ce périmètre. Les IDs officiels v1 `Memo1U...`, v3 `MemoSq...` et v4 `Memo4c...` sont réservés dans `kb_decoder_spl_memo`.
## État du phasage
| Phase | Contenu | État |
|-------|---------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------|
| A | modèle dévénement, lecture bornée, validation des comptes et diagnostics | implémenté dans `0.4.1-pre.001` |
| B | System Program et Compute Budget | implémenté, replay mainnet validé dans `pre.005` |
| C | Address Lookup Table et loaders | implémenté dans `pre.003` puis `pre.006` |
| D | Vote, Stake, Config et programmes historiques | implémenté : Config/Feature `pre.008`, Vote `pre.010` validé dans `pre.011`, Stake `pre.013` validé mainnet |
| E | précompiles et preuves ZK | précompiles signature `pre.014`, ZK ElGamal Proof `pre.015`, ancien ZK Token Proof `pre.016` |
| F | matérialisations justifiées, diagnostics globaux et clôture | nonce System/contextes ZK `pre.017`; Slashing et invariants de couverture `pre.018`; corpus final à valider |
Le processor conserve lidentité `solana_native_classifier@0.4.1` pendant les deltas préparatoires. Les nouveaux décodeurs nécessitent donc un force replay ciblé ou global ; la version ne sera relevée quavec un changement explicite du contrat de processor.
## Sources normatives couvertes
| Surface | Source officielle | Sérialisation retenue | Couverture |
|---------------------------|---------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------|-----------------------------------------|
| System Program | `solana-system-interface 3.2.0`, enum `SystemInstruction` | schéma `wincode` officiel compatible avec le format bincode historique, lecture exacte sans octets suffixes | 14 variantes |
| Compute Budget actuel | `solana-compute-budget-interface 3.0.0` + runtime `solana-compute-budget-instruction 4.1.1` | tag `u8` puis entier little-endian/Borsh ; désérialisation runtime unchecked, suffixe accepté et audité | 5 entrées, dont le tag réservé `Unused` |
| Compute Budget historique | ancien `solana-sdk`, `RequestUnitsDeprecated` | tag `0`, `u32 units`, `u32 additional_fee` | 1 variante historique |
| Address Lookup Table | `solana-address-lookup-table-interface 3.1.0`, enum `ProgramInstruction` | schéma `wincode` officiel, lecture exacte | 5 variantes |
| BPF Loader immuable | `solana-loader-v2-interface 3.0.0`, enum `LoaderInstruction` | tag `u32 LE`, offset `u32`, longueur de vector `u64`, lecture exacte | write, finalize sur deux générations |
| BPF Loader upgradeable | `solana-loader-v3-interface 8.0.1`, enum `UpgradeableLoaderInstruction` | wire format historique compatible bincode, champs booléens suffixes avec valeurs historiques documentées | 8 variantes |
| Loader v4 | `solana-loader-v4-interface 3.1.0`, enum `LoaderV4Instruction` | tag et entiers little-endian, tailles exactes | 7 variantes |
| Config Program | `solana-config-interface 2.0.0` et processor `solana-config-program 2.2.20` | `ConfigKeys` en `solana_short_vec`, clés `(Pubkey, bool)`, puis payload typé opaque pour le décodeur générique | 1 écriture générique `store` |
| Feature Gate | `solana-feature-gate-interface 4.0.0`, `FeatureGateInstruction` | tag `u8` exact `0`, sans suffixe | 1 variante |
| Vote Program | `solana-vote-interface ^6.0`, enum `VoteInstruction` | schéma officiel `wincode`, discriminant historique `u32 LE`, lecture exacte sans octets suffixes | 20 variantes |
| Stake Program | `solana-stake-interface ^4.3`, enum `StakeInstruction` | miroir wire privé `wincode` exact du layout historique ; types sémantiques officiels consommés | 18 variantes |
| ZK ElGamal Proof | `solana-zk-elgamal-proof-interface ^0.1`, `ProofInstruction`, types `Pod`, runtime Agave | tag `u8`; preuve inline de taille officielle ou référence compte `u32 LE` sur instruction exacte de 5 octets | 13 variantes |
| ZK Token Proof historique | miroir wire local audité contre `solana-zk-token-sdk 3.1.14`, Agave `v2.0.0`/`v4.1.1` | tag `u8`; layout historique inline ou offset compte sur 5 octets ; fallback runtime actuel sans effet | 17 variantes + fallback no-op |
| Slashing stateless | Agave `v4.1.1` + `solana-program/slashing@fe8da3a` | tag `u8`; fermeture sur 1 octet ou preuve duplicate block sur 305 octets exacts | 2 variantes |
Les versions de crates sont utilisées comme références reproductibles. Un futur changement dinterface doit entraîner un changement de version du décodeur et un replay ledger/version/hash.
## System Program
Program ID : `11111111111111111111111111111111`.
| Tag historique compatible bincode/wincode `u32 LE` | Entry code | Paramètres structurés | Comptes principaux | État |
|---------------------------------------------------:|--------------------------------|------------------------------------|----------------------------------------|--------|
| 0 | `create_account` | lamports, space, owner | funding, new account | décodé |
| 1 | `assign` | owner | assigned account | décodé |
| 2 | `transfer` | lamports | funding, recipient | décodé |
| 3 | `create_account_with_seed` | base, seed, lamports, space, owner | funding, new account, base optionnelle | décodé |
| 4 | `advance_nonce_account` | aucun | nonce, recent blockhashes, authority | décodé |
| 5 | `withdraw_nonce_account` | lamports | nonce, recipient, sysvars, authority | décodé |
| 6 | `initialize_nonce_account` | authority | nonce, recent blockhashes, rent | décodé |
| 7 | `authorize_nonce_account` | authority | nonce, authority | décodé |
| 8 | `allocate` | space | allocated account | décodé |
| 9 | `allocate_with_seed` | base, seed, space, owner | derived account, base | décodé |
| 10 | `assign_with_seed` | base, seed, owner | derived account, base | décodé |
| 11 | `transfer_with_seed` | lamports, from seed, from owner | funding, base, recipient | décodé |
| 12 | `upgrade_nonce_account` | aucun | nonce account | décodé |
| 13 | `create_account_allow_prefund` | lamports, space, owner | new account, funding conditionnel | décodé |
Le décodeur utilise le schéma `wincode` dérivé directement par `solana-system-interface 3.2.0`. `wincode::deserialize_exact` conserve la compatibilité octet pour octet avec le format historique de cette enum et refuse les octets suffixes. Le crate nutilise aucune dépendance directe à `bincode`.
`pre.017` matérialise les cinq opérations durable nonce sous `durable_nonce_account:<operation>:0`. Initialize, advance, authorize et upgrade conservent leur transition explicite. Withdraw conserve le montant demandé et la règle officielle de fermeture conditionnelle : le compte nest détruit que lorsque la totalité de son solde est retirée. La projection ne prétend pas reconstruire létat final transactionnel du compte et ne duplique pas les deltas SOL du graphe core.
Les flags signer/writable sont conservés sous deux formes : privilèges attendus par le contrat officiel et privilèges réellement résolus depuis core. Ils ne sont pas confondus, car une CPI signée par PDA ne se reflète pas nécessairement comme signer statique de la transaction.
## Compute Budget
Program ID : `ComputeBudget111111111111111111111111111111`.
| Tag `u8` | Entry code | Taille décodée minimale | Paramètres | Statut |
|---------:|---------------------------------------|------------------------:|--------------------------|-----------------------|
| 0 | `unused_reserved` | 1 | aucun | `ignored` |
| 0 | `request_units_deprecated` | 9 | units, additional fee | `decoded`, historique |
| 1 | `request_heap_frame` | 5 | bytes `u32` | `decoded` |
| 2 | `set_compute_unit_limit` | 5 | compute unit limit `u32` | `decoded` |
| 3 | `set_compute_unit_price` | 9 | micro-lamports `u64` | `decoded` |
| 4 | `set_loaded_accounts_data_size_limit` | 5 | bytes `u32` | `decoded` |
Le runtime Agave traite les variantes modernes avec `solana_borsh::v1::try_from_slice_unchecked`. Les octets suffixes sont donc acceptés après les 5 ou 9 octets utiles. Le décodeur reproduit cette règle et conserve `trailingDataByteLength`, `trailingDataSha256`, `trailingDataPrefixHex` et `trailingDataSemantics = ignored_by_runtime_borsh_unchecked`. Les payloads trop courts restent `failed`. Le tag `0` demeure dispatché par taille afin de distinguer le tag réservé actuel de la variante historique à neuf octets ; toute autre taille pour ce tag reste `failed`. Un tag inconnu est `unsupported` avec diagnostic borné et hash du payload disponible pour un replay futur.
## Address Lookup Table
Program ID : `AddressLookupTab1e1111111111111111111111111`.
| Tag `u32 LE` | Entry code | Paramètres | Comptes | État |
|-------------:|---------------------------|------------------------------------------------------------------|--------------------------------------------------|--------|
| 0 | `create_lookup_table` | recent slot, bump seed, politique historique du signer authority | table, authority, payer, System Program | décodé |
| 1 | `freeze_lookup_table` | aucun | table, authority | décodé |
| 2 | `extend_lookup_table` | adresses ajoutées, count, présence du financement | table, authority, paire optionnelle payer/System | décodé |
| 3 | `deactivate_lookup_table` | aucun | table, authority | décodé |
| 4 | `close_lookup_table` | aucun | table, authority, recipient | décodé |
Le décodeur refuse une paire optionnelle dextension incomplète et les octets suffixes. La création conserve `expectedSigner = null` pour lautorité, car lencodeur officiel actuel ne la marque plus signer tandis que les runtimes historiques antérieurs à v1.12 lexigeaient.
La projection `solana_native_lifecycle` produit une sortie `address_lookup_table:<operation>:0` uniquement si lobservation est exacte, réussie et commitée. Les intentions issues de transactions échouées restent dans decode et sont refusées avant matérialisation.
## Programmes runtime natifs principaux
| Code canonique | Program ID | État au début de `pre.018` |
|--------------------|-----------------------------------------------|--------------------------------------------------------------------------------|
| `vote` | `Vote111111111111111111111111111111111111111` | 20 variantes décodées ; 500 `tower_sync` validés mainnet |
| `stake` | `Stake11111111111111111111111111111111111111` | 18 variantes décodées ; 339 instructions mainnet sur neuf entry codes observés |
| `config` | `Config1111111111111111111111111111111111111` | écriture générique `store` décodée ; corpus ciblé à inventorier |
| `zk_elgamal_proof` | `ZkE1Gama1Proof11111111111111111111111111111` | 13 variantes ; 151 instructions mainnet et 139 contextes matérialisés |
## Loaders
| Surface | Program ID | Variantes | Statut `pre.006` |
|------------------------|-----------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------|---------------------------------------------|
| Native Loader | `NativeLoader1111111111111111111111111111111` | invocation directe opaque | `ignored`, historique, aucun faux événement |
| BPF Loader deprecated | `BPFLoader1111111111111111111111111111111111` | write, finalize | décodé |
| BPF Loader v2 | `BPFLoader2111111111111111111111111111111111` | write, finalize | décodé |
| BPF Loader upgradeable | `BPFLoaderUpgradeab1e11111111111111111111111` | initialize buffer, write, deploy with max data length, upgrade, set authority, close, extend program, set authority checked | décodé |
| Loader v4 | `LoaderV411111111111111111111111111111111111` | write, copy, set program length, deploy, retract, transfer authority, finalize | décodé |
Les payloads `write` ne recopient pas le bytecode dans lévénement : ils conservent offset, longueur et SHA-256. Les tailles de vectors, booléens, octets suffixes et paires de comptes optionnelles sont validés avant toute lecture. Les anciennes formes upgradeable sans le booléen suffixe sont acceptées avec la valeur par défaut officielle et marquées comme telles.
La projection lifecycle produit `program_loader:<surface>:<operation>:0` pour les mutations réussies et commitées : finalize immuable, initialize/deploy/upgrade/close/extend upgradeable, puis set length/deploy/retract/finalize v4. Les écritures, copies et changements dautorité restent des événements decode de familles Audit ou Admin.
## Slashing Program stateless
Program ID : `S1ashing11111111111111111111111111111111111`.
Agave `v4.1.1` le déclare comme stateless builtin derrière `enshrine_slashing_program`, avec un hash de build vérifié correspondant à la release officielle `solana-program/slashing@fe8da3a`.
| Tag `u8` | Entry code | Taille exacte | Effet runtime observé |
|---------:|--------------------------|--------------:|------------------------------------------------------------------------|
| 0 | `close_violation_report` | 1 | ferme le rapport après au moins trois epochs et transfère ses lamports |
| 1 | `duplicate_block_proof` | 305 | vérifie une preuve externe puis stocke un rapport de violation |
La preuve duplicate block est lue depuis un compte externe à loffset `u64` de linstruction. Le replay transactionnel ne possède pas le contenu historique de ce compte. Le décodeur conserve loffset, le slot, les clés, racines et signatures intégrées à linstruction, résume linstruction Ed25519 précédente et ne prétend ni relire le compte ni recalculer les signatures.
Une transaction réussie prouve seulement lacceptation runtime, lassignation/allocation du PDA préfinancé et lécriture du rapport. Le programme ne brûle ni ne retire lui-même du stake : la projection `slashing_violation_report` conserve donc `penaltyAppliedByProgram = false` et décrit un signal destiné à une application de pénalité externe au programme.
## Précompiles de signature `pre.014`
| Code canonique | Program ID | Format | État `pre.014` |
|----------------|-----------------------------------------------|---------------------------------------------------------------------------|-----------------------------------------------------------------------------|
| `ed25519` | `Ed25519SigVerify111111111111111111111111111` | header 2 octets, offsets 14 octets, clé 32, signature 64 | décodé, zéro signature accepté seulement sur 2 octets |
| `secp256k1` | `KeccakSecp256k11111111111111111111111111111` | header 1 octet, offsets 11 octets, adresse 20, signature 64 + recovery ID | décodé, index `u8` explicites, zéro signature accepté seulement sur 1 octet |
| `secp256r1` | `Secp256r1SigVerify1111111111111111111111111` | header 2 octets, offsets 14 octets, clé compressée 33, signature 64 | décodé, zéro signature refusé, maximum 8 |
Le contrat core `2` fournit les payloads de toutes les instructions outer. Ed25519 et secp256r1 interprètent `u16::MAX` comme la cible ; secp256k1 résout toujours un index explicite. Les références aux inner instructions ne sont pas autorisées. Les offsets et longueurs utilisent des additions vérifiées avant chaque slice.
Chaque observation conserve les index bruts et résolus, la provenance, les longueurs, SHA-256 et préfixes bornés des composants, ainsi que `runtimeVerification`. Aucun message complet nest recopié, aucune signature nest recalculée et aucune sortie métier nest matérialisée. Une transaction échouée reste `decoded` si le layout est valide, mais porte `not_asserted_transaction_failed` et reste non commitée.
## Surfaces historiques ou complémentaires
| Code canonique | Program ID | État après `pre.008` |
|------------------|-----------------------------------------------|-----------------------------------------------------------------------------------------------------|
| `feature` | `Feature111111111111111111111111111111111111` | `revoke_pending_activation` décodé et lifecycle matérialisable |
| `zk_token_proof` | `ZkTokenProof1111111111111111111111111111111` | 17 layouts historiques décodés + fallback `current_runtime_noop_invocation`; validation synthétique |
### Ancien ZK Token Proof Program
`pre.016` couvre les discriminants `0..16` de linterface historique : fermeture du contexte, zero balance, withdraw, égalités de ciphertext/commitment, transfer, transfer with fee, validité de pubkey, range proofs simples et batchés, validité de grouped ciphertext à deux ou trois handles et fee sigma. Les tailles de preuve et de contexte sont maintenant conservées dans une table locale auditée contre les types `Pod` de `solana-zk-token-sdk 3.1.14`, sans dépendre de cette crate dépréciée.
Le runtime historique Agave `v2.0.0` distinguait une preuve inline dune preuve stockée dans le premier compte lorsque linstruction faisait exactement cinq octets. Il imposait des arités distinctes pour le contexte, refusait les vérifications comme inner instructions et plaçait certains chemins derrière `enable_zk_proof_from_account` ou `enable_zk_transfer_with_fee`. Le runtime Agave `v4.1.1` est au contraire un stub qui retourne succès sans mutation. Le décodeur conserve ces deux références sans prétendre connaître la version runtime dune transaction donnée.
Aucune signature mainnet na été trouvée pour ce program ID lors du jalon. La surface est donc validée par fixtures synthétiques et sources officielles, sans critère de backfill. Les preuves inline sont seulement mesurées, hashées et préfixées de façon bornée ; les preuves externes conservent loffset et la taille attendue. Aucune preuve nest recalculée et aucune sortie nest matérialisée.
### Stake Program
`pre.013` couvre les dix-huit variantes de `StakeInstruction`, tags `u32 LE` `0..17` : initialize, authorize, delegate, split, withdraw, deactivate, set lockup, merge, autorisations avec seed, variantes checked, minimum delegation, deactivate delinquent, `redelegate`, move stake et move lamports. `Redelegate` reste déclaré historique : le processor actuel renvoie `InvalidInstructionData` avant tout traitement de comptes ; une occurrence réelle doit donc provenir dune transaction échouée et reste non commitée.
Lenum officielle de `solana-stake-interface ^4.3` conserve le contrat Serde/Bincode historique, mais nimplémente pas directement `SchemaRead`/`SchemaWrite`. Pour respecter linterdiction workspace de dépendre de `bincode`, le décodeur utilise un miroir wire privé, ordonné exactement comme lenum officielle, décodé par `wincode::deserialize_exact`. Les tests vérifient manuellement les tags, pubkeys, entiers, enums imbriquées et longueurs de chaînes du layout historique. Les types sémantiques et le program ID officiels restent consommés depuis linterface.
Le processor BPF actuel supporte deux familles de comptes. Les layouts historiques sont détectés par la première sysvar héritée, généralement Clock ou Rent ; les layouts modernes retirent ces sysvars et placent directement les autorités aux positions attendues. `Split`, `SetLockup` et `SetLockupChecked` conservent volontairement les contraintes historiques plus souples du runtime. Le décodeur expose `accountLayout`, conserve les comptes additionnels et les privilèges attendus/observés, mais ne prétend pas rejouer les vérifications dépendant de létat du stake account, du lockup, de la délégation ou des sysvars courantes. Aucune matérialisation Stake nest ajoutée dans ce delta.
### Compte Stake Config historique
`StakeConfig11111111111111111111111111111111` nest pas un programme exécutable. Linterface Stake officielle le déclare comme identifiant déprécié du compte de configuration historique du Stake Program. Il reste dans `kb_program_ids` comme `STAKE_CONFIG_ACCOUNT_ID` et dans le registre core avec `identifier_kind = well_known_account`, mais il est exclu des surfaces du décodeur et de lexécuteur.
### Config Program
Le Config Program ne possède pas un enum dinstructions discriminé comparable à System ou Stake. Chaque invocation stocke un préfixe `ConfigKeys` sérialisé avec `solana_short_vec`, suivi dun payload spécifique au type de configuration. Le décodeur valide la longueur compacte, les clés, les booléens signataires et lordre des comptes signataires, puis conserve le reste par taille, préfixe borné et SHA-256 avec la sémantique explicite `opaque_program_specific`.
### Vote Program
`pre.010` utilise `solana-vote-interface ^6.0` avec les features `serde` et `wincode`. Le discriminant wire historique reste un `u32` little-endian compris entre `0` et `19`, et `wincode::deserialize_exact` rejette les octets résiduels. `VoteInitV2` contient les autorités, la clé BLS, sa preuve de possession et les deux commissions en points de base ; les collecteurs Inflation Rewards et Block Revenue sont les comptes dinstruction 2 et 3.
La couverture comprend : initialisations V1/V2, autorisations simples/checked/seed, vote et vote switch, mises à jour détat normales/compactes, tower sync, retrait, identité, commissions historiques et en points de base, collecteurs différenciés et dépôt de récompenses délégateurs. Les tableaux BLS V2 sont conservés en hexadécimal exact. Les sysvars Rent, Clock et Slot Hashes sont vérifiées aux positions imposées par linterface. Les privilèges attendus et observés restent distincts afin de ne pas confondre les signataires statiques et les signatures PDA de CPI.
Aucune projection matérialisée spécifique à Vote nest ajoutée dans ce delta : la mutation réelle dépend de létat du vote account et du runtime. Une transaction échouée produit uniquement une observation non commitée.
## ZK ElGamal Proof `pre.015`
Program ID : `ZkE1Gama1Proof11111111111111111111111111111`.
Le décodeur consomme `solana-zk-elgamal-proof-interface ^0.1` pour lenum `ProofInstruction` et les tailles exactes des types `Pod`. Il couvre `CloseContextState` et les douze preuves : zero ciphertext, égalités ciphertext/ciphertext et ciphertext/commitment, validité de clé publique, percentage with cap, range proofs 64/128/256 bits et validités grouped/batched à deux ou trois handles.
Deux modes de transport sont distingués conformément au runtime :
- instruction de cinq octets : tag puis offset `u32 LE` vers un compte contenant la preuve ;
- autre taille exacte : preuve inline immédiatement après le tag, avec taille égale au type `ProofData` officiel.
Pour une preuve inline, les blocs contexte et preuve sont séparés par leurs tailles `Pod`, puis conservés uniquement sous forme de longueur, SHA-256 et préfixe hexadécimal borné. Le décodeur ne recalcule aucune preuve cryptographique. Pour une transaction réussie, il indique seulement que linstruction a été acceptée par le runtime. Pour une transaction échouée, aucune validité nest affirmée et lobservation reste non commitée.
Le mode référencé par compte a une limite historique structurelle : le graphe core de transaction ne contient pas le contenu du compte à linstant dexécution. Lévénement conserve donc le compte source, loffset, le type et la taille attendue, mais marque les octets de preuve comme indisponibles. Il ne tente ni lecture RPC actuelle, qui pourrait être divergente, ni reconstruction.
Les comptes optionnels de contexte sont résolus selon le mode : positions 0/1 pour une preuve inline et 1/2 après le compte de preuve pour une preuve externe. La fermeture du contexte conserve le contexte, la destination des lamports et lautorité signataire, accepte les octets suffixes comme le runtime et refuse que contexte et destination désignent le même compte.
`pre.017` matérialise le lifecycle du compte de contexte sous `zk_proof_context:<operation>:0`. Une vérification nest éligible que lorsque `contextStateRequested = true`, que la transaction a réussi et que lobservation est commitée. La sortie conserve le compte, lautorité et le type de preuve, mais jamais la preuve elle-même. La fermeture réussie décrit la récupération des lamports, la remise à zéro des données et le retour de lowner au System Program. Les preuves sans contexte restent en decode/audit.
## Statuts et politique déchec
- `decoded` signifie que le format complet a été validé et quune observation structurée a été produite.
- `ignored` est réservé à une entrée comprise mais sans événement utile, comme le tag Compute Budget `Unused`.
- `unsupported` conserve une variante inconnue ou une surface non encore implémentée sans faux événement.
- `failed` indique un payload absent, invalide, tronqué, non canonique ou des comptes incohérents.
- `unmatched` reste un défaut de dispatch et ne doit pas apparaître pour une sélection bornée aux surfaces déclarées.
Une transaction on-chain échouée reste décodable comme intention. Lobservation porte `transactionSucceeded = false` et `observation_committed = false`. Le matérialiseur `solana_native_lifecycle` est actif pour ALT, les mutations loader listées, Feature Gate, les durable nonce accounts System et les comptes de contexte ZK ElGamal. Il accepte les familles `Lifecycle`, `Admin` et `Audit` uniquement au niveau exact surface/entrée/paramètres, puis applique `SuccessfulCommittedOnly`. Une observation non commitée est refusée et une preuve ZK sans contexte est exclue avant ledger et politique.
## Validation mainnet `pre.005`
Les correctifs de `pre.005` ont été validés par les tests ciblés, `cargo clippy --all-targets` et deux campagnes Tauri. Le force replay ciblé a décodé 3/3 inputs sans échec. Le replay global a sélectionné, démarré et terminé 476 inputs : 476 décodés, zéro `failed`, `unsupported`, `unmatched` et zéro faux `materializationRefused`. Aucun output nétait attendu, car le corpus ne contenait pas dopération ALT éligible.
## Validation `pre.006`, `pre.008`, Vote mainnet et anomalie Compute Budget
Les tests `pre.006`, Clippy et le replay Tauri global ont été validés : 476 inputs sélectionnés, 476 décodés, aucun échec, `unsupported`, `unmatched` ou refus de matérialisation. Les validations utilisateur de `pre.008` couvrent 256 tests ciblés, PostgreSQL réel, Clippy et un démarrage/replay Tauri propre. Le corpus initial ne contenait que System et Compute Budget : loaders, Config et Feature restent en attente dun corpus réel.
Le backfill Vote de 500 signatures a inséré 500 transactions et lextraction core a terminé 500/500 sans échec. Le replay global suivant contient 500 instructions Vote réelles, toutes reconnues et décodées comme `tower_sync`, sans échec Vote. Lunique `failed` de la campagne provient dun `set_compute_unit_limit` de 12 octets : le runtime laccepte grâce à la désérialisation Borsh unchecked, alors que le décodeur strict exigeait encore 5 octets exacts. `pre.011` corrige cet écart. Le processor reste `solana_native_classifier@0.4.1` : un force replay est requis pour remplacer le résultat `failed` déjà enregistré.

View File

@@ -1,106 +0,0 @@
<!-- file: docs/NOMENCLATURE.md -->
<!-- version: 4 -->
# Nomenclature
Ce document fixe les noms internes utilisés dans le workspace.
## Programmes
- `program_id` : adresse Solana réelle.
- `program_code` : nom interne stable du programme.
- `protocol_code` : famille protocolaire.
- `surface_code` : surface concrète.
## Événements
Le format canonique est :
```text
<surface_code>.<event_name>
```
Exemples :
```text
pump_swap.buy
raydium_amm_v4.swap_base_in
meteora_dlmm.swap
jupiter_v6.route
```
## Tables Solana PostgreSQL
Les tables Solana PostgreSQL utilisent le schéma courant du profil PostgreSQL, généralement `public`. Le projet ne crée pas de schémas applicatifs `raw`, `core`, `obs`, `decode`, `mat`, `catalog`, `agg`, `ops` ou `wallet`.
Le format canonique est :
```text
kb_sol_<domain>_<name>
```
Domaines autorisés au départ :
```text
raw
core
obs
decode
mat
catalog
agg
ops
wallet
```
Exemples valides :
```text
kb_sol_raw_transactions
kb_sol_core_transactions
kb_sol_obs_transaction_observations
kb_sol_obs_program_observations
kb_sol_decode_decoded_events
kb_sol_mat_trade_events
kb_sol_catalog_tokens
kb_sol_ops_processing_ledger
```
Exemples interdits, écrits avec `DOT` pour que les audits textuels simples ne confondent pas documentation et usage réel :
```text
raw DOT kb_sol_rpc_transactions
core DOT kb_sol_transactions
obs DOT kb_sol_program_observations
decode DOT kb_sol_decoded_events
mat DOT kb_sol_trade_events
catalog DOT kb_sol_tokens
ops DOT kb_sol_processing_ledger
```
## Surfaces de programmes
Le nom canonique d'une surface de programme doit suivre le format :
```text
<function_code>_<family_code>_<identifier_code>[_vN]
```
Le nom de crate correspondant doit suivre le format :
```text
kb_decoder_<function_code>_<family_code>_<identifier_code>[_vN]
```
Les anciens noms issus des IDL, des explorateurs ou des anciennes matrices doivent être conservés dans le registre sous `source_code` ou `normalized_code`, mais ne doivent pas être utilisés comme nouvelle référence stable si un nom canonique existe.
Voir aussi :
- `docs/DATABASE.md` ;
- `docs/PROGRAM_NAMING.md` ;
- `docs/PROGRAM_REGISTRY_CONTROL.md` ;
- `registry/program_registry_seed.toml`.
Le préfixe `program_` est interdit pour les surfaces canoniques. Les entrées dont la fonction est inconnue doivent rester en `unknown_*` avec un statut de classification, sans création de crate cible.
Les programmes core Solana/SPL sont documentés séparément des DEX et routers, même s'ils restent dans le registre machine.

View File

@@ -1,91 +0,0 @@
<!-- file: docs/POSTGRES_STORE.md -->
<!-- version: 10 -->
# Store PostgreSQL canonique
## Baseline active
PostgreSQL reste le backend principal. Le store utilise le schéma courant du profil, généralement `public`, et ne qualifie pas les tables par un schéma applicatif explicite.
La baseline active contient :
```text
kb_sol_raw_transactions
kb_sol_obs_transaction_observations
kb_sol_core_transactions
kb_sol_core_account_keys
kb_sol_core_instructions
kb_sol_core_inner_instructions
kb_sol_core_logs
kb_sol_core_balance_changes
kb_sol_ops_processing_ledger
kb_sol_decode_events
kb_sol_decode_coverage_declarations
kb_sol_decode_coverage_observations
kb_sol_mat_events
```
## Initialisation
Le projet utilise encore des DDL idempotents gérés par `kb_store_pg`. `_sqlx_migrations` nest pas requis pour démarrer lapplication.
Les fichiers SQL actifs sont conservés comme représentation lisible de la baseline :
```text
0001_canonical_transaction_store.sql
0002_core_store.sql
0003_processing_ledger.sql
0004_decode_materialization_store.sql
```
Au démarrage Tauri, `initialize_store_schema()` applique une seule fois, dans lordre, les DDL raw, core puis decode/mat. Les connexions ouvertes ensuite par les commandes de démo désactivent `auto_initialize_schema` et ne relancent plus les migrations. Les méthodes spécialisées restent disponibles pour les tests et outils qui demandent explicitement linitialisation dun sous-ensemble dépendant.
## Extraction canonique vers core
`CoreExtractionStore` sélectionne les lignes raw, vérifie le ledger puis persiste un `CoreExtractionBundle` dans une transaction PostgreSQL unique.
Le mode normal skippe la combinaison déjà réussie :
```text
processor version + signature + canonical hash
```
Le replay forcé remplace uniquement le graphe de la signature ciblée. Les autres signatures ne sont pas modifiées.
## Tests PostgreSQL
Les tests qui utilisent `KB_POSTGRES_TEST_URL` doivent être lancés sur une base dédiée ou suivis dun nettoyage explicite.
Depuis `0.4.1-pre.021`, les tests optionnels qui partagent une base PostgreSQL réelle acquièrent un verrou process-local test-only. Ce verrou évite les interblocages intermittents entre campagnes de tests parallèles sans changer le code runtime ni le schéma SQL.
Les tests optionnels couvrent notamment le rollback atomique core/decode, la persistance réelle du ledger et la sémantique exacte des déclarations de couverture. `optional_postgres_core_extraction_rolls_back_partial_graph_from_env` :
1. insère une ligne raw isolée ;
2. tente de persister un bundle contenant deux account keys avec le même index ;
3. attend une violation de lindex unique après le début de la transaction ;
4. vérifie quaucune transaction core, account key ou entrée ledger na été conservée et que le raw reste `received` ;
5. rejoue un bundle corrigé ;
6. vérifie le passage à `core_extracted` et le ledger `succeeded` ;
7. nettoie ses lignes de test.
Commande de clôture :
```bash
KB_POSTGRES_TEST_URL='postgres://solana:solana@localhost:5432/solana_test' \
cargo test -p kb_store_pg -- --nocapture
```
Les contrôles réels déjà effectués sur la base principale ont confirmé :
- 70 transactions raw et core ;
- 70 entrées ledger `succeeded` ;
- 84 tentatives après un force replay de 14 signatures ;
- aucune duplication ni ligne fille orpheline ;
- cardinalité core inchangée après remplacement forcé.
## Couverture et skip decode
`persist_decode_coverage_declarations()` synchronise le snapshot déclaré dun processor/version et retourne des compteurs exacts : insertion réelle, modification/suppression du snapshot ou déclaration inchangée.
Le test PostgreSQL `optional_postgres_same_version_and_hash_is_current_from_env` persiste un résultat `unsupported` puis vérifie que le même stage, processor, version, input key et input hash est reconnu comme courant par le ledger.

View File

@@ -1,42 +0,0 @@
<!-- file: docs/PROGRAM_CODE_INDEX.md -->
<!-- version: 1 -->
# Index court des programmes
L'idée d'un préfixe hexadécimal `00` à `ff` peut être utile comme identifiant court interne, mais elle ne doit pas remplacer le nom canonique lisible.
## Décision
Le nom de crate reste descriptif :
```text
kb_decoder_amm_pump_swap
kb_decoder_router_jupiter_aggregator_v6
kb_decoder_clmm_orca_whirlpool
```
Un code court optionnel peut être ajouté dans le registre :
```toml
registry_code = "00"
canonical_surface_code = "amm_pump_swap"
target_crate = "kb_decoder_amm_pump_swap"
```
## Pourquoi ne pas mettre `00_` dans les crates
- Le code `00` ne décrit pas la fonction du programme.
- L'ordre peut changer quand de nouvelles surfaces sont ajoutées.
- Deux cent cinquante-six valeurs peuvent devenir insuffisantes si toutes les surfaces, sysvars, routers, vaults, perps, bridges et variantes historiques sont incluses.
- Les renommages de crates deviendraient fréquents et inutiles.
## Usage acceptable
Le code court est acceptable pour :
- affichage UI compact ;
- clé stable optionnelle dans PostgreSQL ;
- tri manuel dans les matrices ;
- identifiant de configuration humain court.
Le code court ne doit pas servir de préfixe principal de nommage Rust.

View File

@@ -1,15 +0,0 @@
<!-- file: docs/PROGRAM_IDS.md -->
<!-- version: 1 -->
# Identifiants de programmes
`kb_program_ids` est la source unique des `program_id` connus du workspace.
Les décodeurs et exécuteurs ne doivent pas redéfinir les mêmes chaînes dans leurs propres fichiers `constants.rs`. Ils doivent utiliser directement `kb_program_ids::XXX_PROGRAM_ID`.
Les fichiers `constants.rs` locaux restent utiles pour les constantes propres à une surface : discriminators, opcodes, seeds, index de comptes, tailles de payload ou constantes Borsh.
## Audit de génération
Le crate central a été alimenté à partir des constantes existantes des décodeurs/exécuteurs et des fichiers registry.

View File

@@ -1,18 +0,0 @@
<!-- file: docs/PROGRAM_ID_CONSTANTS_AUDIT.md -->
<!-- version: 1 -->
# Audit des constantes `PROGRAM_ID` des décodeurs
Ce document décrit la correction appliquée aux crates de décodeurs classifiés. Chaque décodeur associé à un `program_id` dans `registry/program_registry_seed.toml` doit exposer ce `program_id` via `src/constants.rs`, le réexporter depuis `src/lib.rs`, puis lutiliser dans `program_ids()` via `crate::XXX_PROGRAM_ID`.
## Règle retenue
- `src/constants.rs` contient les identifiants stables du programme, puis plus tard les discriminants, sélecteurs, discriminators Anchor, codes dinstruction et constantes de décodage.
- `src/lib.rs` réexporte les constantes publiques nécessaires.
- `src/decoder.rs` ne doit pas contenir de literal de `program_id` dans `program_ids()`.
- Les décodeurs génériques comme `kb_decoder_anchor` ne doivent pas inventer de `program_id`.
## Portée
La correction couvre les décodeurs classifiés présents dans le workspace et associés à un `program_id` non vide dans le registre. Les crates core Solana/SPL disposaient déjà de `constants.rs`.

View File

@@ -1,152 +0,0 @@
<!-- file: docs/PROGRAM_NAMING.md -->
<!-- version: 2 -->
# Nommage canonique des programmes et surfaces
Le nommage doit permettre de distinguer la fonction réelle du programme, sa famille protocolaire et sa version.
## Format recommandé
```text
<function_code>_<family_code>_<identifier_code>[_vN]
```
Le nom de crate correspondant est :
```text
kb_decoder_<function_code>_<family_code>_<identifier_code>[_vN]
```
## Préfixes fonctionnels autorisés
Le préfixe doit décrire la fonction principale du programme, pas seulement le fait qu'il s'agit d'un programme Solana.
Exemples de préfixes acceptés :
```text
core
token
amm
cpmm
clmm
dlmm
stable_swap
weighted_swap
orderbook
router
launchpad
lending
vault
staking
bridge
perpetuals
oracle
nft
metadata
admin
fees
governance
treasury
lock
vesting
unknown
```
Le préfixe `program` est interdit pour les nouveaux noms canoniques. Une entrée non classifiée doit utiliser `unknown_*` et ne doit pas déclencher la création d'une crate cible avant classification.
## Cas Meteora DAMM
`damm` est conservé comme identifiant de surface Meteora, mais pas comme préfixe fonctionnel. La forme attendue est donc `amm_meteora_damm_v1` ou `amm_meteora_damm_v2`. En revanche `cpmm`, `clmm`, `dlmm`, `stable_swap` et `weighted_swap` sont des mécanismes et peuvent être utilisés comme préfixes fonctionnels.
## Colonnes à conserver
Le registre ne doit pas perdre les anciens noms. Chaque programme doit conserver :
- `program_id` : adresse Solana réelle ;
- `source_code` : nom brut issu de la liste, dun IDL ou dune ancienne documentation ;
- `normalized_code` : nom nettoyé sans faute évidente ;
- `canonical_surface_code` : nom cible stable ;
- `current_crate` : crate existant si la surface est déjà réservée ;
- `target_crate` : nom de crate à atteindre après migration contrôlée ;
- `registry_status` : statut de contrôle.
## Exemples de normalisation
| Nom source | Fonction | Famille | Nom canonique |
|---------------------------|-------------|------------|------------------------------------|
| `raydium_lp_v4` | `amm` | `raydium` | `amm_raydium_lp_v4` |
| `raydium_cpmm` | `cpmm` | `raydium` | `cpmm_raydium` |
| `raydium_clmm` | `clmm` | `raydium` | `clmm_raydium` |
| `meteora_dlmm` | `dlmm` | `meteora` | `dlmm_meteora` |
| `meteora_damm_v2` | `amm` | `meteora` | `amm_meteora_damm_v2` |
| `jupiter_agregator_v6` | `router` | `jupiter` | `router_jupiter_aggregator_v6` |
| `okx_labs_v2` | `router` | `okx` | `router_okx_labs_v2` |
| `openbook_v2` | `orderbook` | `openbook` | `orderbook_openbook_v2` |
| `phoenix` | `orderbook` | `phoenix` | `orderbook_phoenix_v1` |
| `pump_swap` | `amm` | `pump` | `amm_pump_swap` |
| `pump_fun` | `launchpad` | `pump` | `launchpad_pump_fun` |
| `pump_fees` | `admin` | `pump` | `admin_pump_fees` |
| `orca_whirlpool` | `clmm` | `orca` | `clmm_orca_whirlpool` |
| `metaplex_token_metadata` | `metadata` | `metaplex` | `metadata_metaplex_token_metadata` |
| `bubblegum` | `nft` | `metaplex` | `nft_metaplex_bubblegum` |
## Exceptions conservées
Les programmes Solana/SPL de base restent groupés dans des modules techniques privés et des types publics explicites :
- `DcSolanaCoreDecoder` ;
- `DcSplTokenDecoder` ;
- `DcSplToken2022Decoder` ;
- `DcSplAssociatedTokenAccountDecoder`.
Ces types restent dans la façade `kb_lib`, car ils servent de couche primitive avant les surfaces DEX/router.
## Politique de migration
La migration physique des dossiers ne doit pas être faite en masse. Pour chaque rename :
1. prouver que le `program_id` correspond à la surface ;
2. créer ou renommer un seul module privé ;
3. mettre à jour la façade `kb-lib/src/lib.rs` ;
4. mettre à jour le registre ;
5. exécuter `cargo build` ;
6. supprimer lancien alias seulement après validation.
## Préfixe hexadécimal
Les préfixes `00` à `ff` sont interdits comme préfixes principaux de crate. Ils peuvent exister uniquement comme champ de registre optionnel `registry_code`. Le nom canonique doit rester lisible et fonctionnel.
Exemple accepté :
```toml
registry_code = "01"
canonical_surface_code = "amm_pump_swap"
target_crate = "kb_decoder_amm_pump_swap"
```
Exemple refusé :
```text
kb_decoder_01_pump_swap
```
## Fichiers `constants.rs`
Les crates peuvent avoir un fichier `src/constants.rs` pour regrouper les `program_id`, discriminants, sélecteurs, longueurs Borsh et autres constantes techniques. Les `program_id` publics sont réexportés dans `lib.rs`. Les constantes internes futures, par exemple des discriminants ou tailles de payload, doivent rester `pub(crate)` sauf besoin explicite d'API publique.
Depuis un module interne de la même crate, une constante réexportée par `lib.rs` doit être appelée via `crate::CONSTANT_NAME`. Le chemin `crate::constants::CONSTANT_NAME` reste réservé aux constantes non réexportées.
## Préfixes ajoutés après inspection IDL
- `adapter` : wrapper technique ou adaptation de format, par exemple `adapter_saber_decimal_wrapper`.
- `rwa` : programme d'actifs réels tokenisés ou marchés globaux, par exemple `rwa_ondo_global_markets`.
- `vesting` : programme de vesting, streaming ou timelock.
- `wallet` : smart wallet applicatif ou surface d'approbation/exécution.
## Préfixe `fees`
Le préfixe `fees` est autorisé pour les programmes dont le rôle principal est la configuration, distribution ou réclamation de frais. Il doit être préféré à `admin` lorsque la surface est explicitement centrée sur le partage de frais.

View File

@@ -1,328 +0,0 @@
<!-- file: docs/PROGRAM_REGISTRY_CONTROL.md -->
<!-- version: 7 -->
# Contrôle du registre des programmes
Ce document transforme la liste de programmes fournie en registre contrôlable. Il ne valide pas encore chaque `program_id` sur chaîne ; il sert de base interne pour détecter les doublons, les aliases, les surfaces mal nommées et les crates manquantes.
## Résumé
- Entrées du registre : 150.
- `program_id` distincts : 149.
- Doublons exacts de `program_id` : 1.
- Registre machine : `registry/program_registry_seed.toml`.
- La colonne `Canonique` est la référence de tri et de migration.
## Correction de principe
La table de contrôle est maintenant triée par `Canonique`, avec `Canonique` en première colonne. C'est le nom qui doit piloter les futures crates, les noms de surfaces et les tables de couverture.
Les programmes Solana/SPL de base ne sont plus mélangés avec les DEX, routers et protocoles applicatifs. Ils sont listés dans un tableau séparé parce qu'ils relèvent de la couche core : `kb_decoder_solana_core`, `kb_decoder_spl_token`, `kb_decoder_spl_token_2022` et futurs décodeurs primitifs.
## Pourquoi `amm` et pas `damm` en préfixe ?
Le préfixe doit représenter la fonction générique du programme. `amm` signifie Automated Market Maker. `damm` est un nom de surface Meteora, généralement interprété comme Dynamic AMM. Donc `damm` ne doit pas être utilisé comme préfixe fonctionnel général.
La forme recommandée est :
```text
amm_meteora_damm_v1
amm_meteora_damm_v2
```
et non :
```text
damm_meteora_v1
damm_meteora_v2
```
À l'inverse, `dlmm`, `clmm`, `cpmm`, `stable_swap` et `weighted_swap` sont des types de mécanismes et peuvent être utilisés comme préfixes fonctionnels quand ils décrivent mieux la surface.
## Pourquoi supprimer `program_` ?
Le préfixe `program_` était un fallback technique. Il n'indique aucune fonction : ni AMM, ni router, ni lending, ni bridge, ni NFT. Il est donc insuffisant pour une nomenclature stable.
Nouvelle règle :
- aucune nouvelle surface canonique ne doit commencer par `program_` ;
- une surface non classifiée utilise temporairement `unknown_*` ;
- une surface `unknown_*` ne doit pas devenir une crate cible tant que sa fonction réelle n'est pas décidée ;
- le statut attendu est `needs_classification` ou `current_alias_needs_classification`.
## Programmes core Solana/SPL
Ces identifiants sont détaillés dans `docs/CORE_PROGRAM_IDS.md`. Ils sont couverts par les décodeurs core/primitifs ou par des crates spécialisées SPL futures, pas par une crate DEX dédiée.
| Canonique | Program ID | Source | Type | Crate cible | Statut |
|--------------------------------------------|------------------------------------------------|----------------------------------|----------------------|-------------------------------------------|-------------------------------------|
| `core_solana_address_lookup_table_v1` | `AddressLookupTab1e1111111111111111111111111` | `address_lookup_table` | `program` | `kb_decoder_solana_core` | `core_handled` |
| `core_solana_bpf_loader_deprecated_v1` | `BPFLoader1111111111111111111111111111111111` | `bpf_loader_deprecated` | `loader_program` | `kb_decoder_solana_core` | `core_handled` |
| `core_solana_bpf_loader_v2` | `BPFLoader2111111111111111111111111111111111` | `bpf_loader` | `loader_program` | `kb_decoder_solana_core` | `core_handled` |
| `core_solana_bpf_loader_upgradeable_v1` | `BPFLoaderUpgradeab1e11111111111111111111111` | `bpf_loader_upgradeable` | `loader_program` | `kb_decoder_solana_core` | `core_handled` |
| `core_solana_compute_budget_v1` | `ComputeBudget111111111111111111111111111111` | `compute_budget` | `program` | `kb_decoder_solana_core` | `core_handled` |
| `core_solana_config_v1` | `Config1111111111111111111111111111111111111` | `config` | `program` | `kb_decoder_solana_core` | `core_handled` |
| `core_solana_ed25519_v1` | `Ed25519SigVerify111111111111111111111111111` | `ed25519` | `program` | `kb_decoder_solana_core` | `core_handled` |
| `core_solana_feature_v1` | `Feature111111111111111111111111111111111111` | `feature` | `program` | `kb_decoder_solana_core` | `core_handled` |
| `core_solana_incinerator_v1` | `1nc1nerator11111111111111111111111111111111` | `incinerator` | `well_known_account` | `kb_decoder_solana_core` | `core_recognized_account` |
| `core_solana_loader_v4` | `LoaderV411111111111111111111111111111111111` | `loader_v4` | `loader_program` | `kb_decoder_solana_core` | `core_handled` |
| `core_solana_native_loader_v1` | `NativeLoader1111111111111111111111111111111` | `native_loader` | `loader_program` | `kb_decoder_solana_core` | `core_handled` |
| `core_solana_secp256k1_v1` | `KeccakSecp256k11111111111111111111111111111` | `secp256k1` | `program` | `kb_decoder_solana_core` | `core_handled` |
| `core_solana_secp256r1_v1` | `Secp256r1SigVerify1111111111111111111111111` | `secp256r1` | `program` | `kb_decoder_solana_core` | `core_handled` |
| `core_solana_stake_config_v1` | `StakeConfig11111111111111111111111111111111` | `stake_config` | `well_known_account` | `kb_decoder_solana_core` | `core_recognized_account` |
| `core_solana_stake_v1` | `Stake11111111111111111111111111111111111111` | `stake` | `program` | `kb_decoder_solana_core` | `core_handled` |
| `core_solana_system_v1` | `11111111111111111111111111111111` | `system` | `program` | `kb_decoder_solana_core` | `core_handled` |
| `core_solana_sysvar_clock_v1` | `SysvarC1ock11111111111111111111111111111111` | `sysvar_clock` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` |
| `core_solana_sysvar_epoch_rewards_v1` | `SysvarEpochRewards1111111111111111111111111` | `sysvar_epoch_rewards` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` |
| `core_solana_sysvar_epoch_schedule_v1` | `SysvarEpochSchedu1e111111111111111111111111` | `sysvar_epoch_schedule` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` |
| `core_solana_sysvar_fees_v1` | `SysvarFees111111111111111111111111111111111` | `sysvar_fees` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` |
| `core_solana_sysvar_instructions_v1` | `Sysvar1nstructions1111111111111111111111111` | `sysvar_instructions` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` |
| `core_solana_sysvar_last_restart_slot_v1` | `SysvarLastRestartS1ot1111111111111111111111` | `sysvar_last_restart_slot` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` |
| `core_solana_sysvar_recent_blockhashes_v1` | `SysvarRecentB1ockHashes11111111111111111111` | `sysvar_recent_blockhashes` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` |
| `core_solana_sysvar_rent_v1` | `SysvarRent111111111111111111111111111111111` | `sysvar_rent` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` |
| `core_solana_sysvar_rewards_v1` | `SysvarRewards111111111111111111111111111111` | `sysvar_rewards` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` |
| `core_solana_sysvar_slot_hashes_v1` | `SysvarS1otHashes111111111111111111111111111` | `sysvar_slot_hashes` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` |
| `core_solana_sysvar_slot_history_v1` | `SysvarS1otHistory11111111111111111111111111` | `sysvar_slot_history` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` |
| `core_solana_sysvar_stake_history_v1` | `SysvarStakeHistory1111111111111111111111111` | `sysvar_stake_history` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` |
| `core_solana_sysvar_v1` | `Sysvar1111111111111111111111111111111111111` | `sysvar` | `sysvar_account` | `kb_decoder_solana_core` | `core_recognized_account` |
| `core_solana_vote_v1` | `Vote111111111111111111111111111111111111111` | `vote` | `program` | `kb_decoder_solana_core` | `core_handled` |
| `core_solana_zk_elgamal_proof_v1` | `ZkE1Gama1Proof11111111111111111111111111111` | `zk_elgamal_proof` | `program` | `kb_decoder_solana_core` | `core_handled` |
| `core_solana_zk_token_proof_v1` | `ZkTokenProof1111111111111111111111111111111` | `zk_token_proof` | `program` | `kb_decoder_solana_core` | `core_handled` |
| `core_spl_associated_token_account_v1` | `ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL` | `associated_token_account` | `program` | `kb_decoder_spl_associated_token_account` | `core_handled` |
| `core_spl_account_compression_v1` | `cmtDvXumGCrqC1Age74AVPhSRVXJMd8PJS91L8KbNCK` | `spl_account_compression` | `program` | `kb_decoder_spl_account_compression` | `core_specialized_reserved_current` |
| `core_spl_memo_v1` | `Memo1UhkJRfHyvLMcVucJwxXeuD728EqVDDwQDxFMNo` | `spl_memo_v1` | `program` | `kb_decoder_spl_memo` | `core_specialized_reserved_current` |
| `core_spl_memo_v3` | `MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr` | `spl_memo_v3` | `program` | `kb_decoder_spl_memo` | `core_specialized_reserved_current` |
| `core_spl_memo_v4` | `Memo4c2pN8afCj432Lb7RMVKi9PbQnnW7ewFFaV3oAH` | `spl_memo_v4` | `program` | `kb_decoder_spl_memo` | `core_specialized_reserved_current` |
| `core_spl_noop_v1` | `noopb9bkMVfRPU8AsbpTUg8AQkHtKwMYZiFUjNRtMmV` | `spl_noop` | `program` | `kb_decoder_spl_noop` | `core_specialized_reserved_current` |
| `core_spl_single_pool_v1` | `SVSPxpvHdN29nkVg9rPapPNDddN5DipNLRUFhyjFThE` | `spl_single_pool` | `program` | `kb_decoder_spl_single_pool` | `core_specialized_reserved_current` |
| `core_spl_name_service_v1` | `namesLPneVptA9Z5rqUDD9tMTWEJwofgaYwp8cawRkX` | `spl_name_service` | `program` | `kb_decoder_metadata_spl_name_service` | `core_specialized_reserved_current` |
| `core_spl_stake_pool_v1` | `SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy` | `stake_pool` | `program` | `kb_decoder_spl_stake_pool` | `core_specialized_reserved_current` |
| `core_spl_token2022_v2022` | `TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb` | `token2022` | `program` | `kb_decoder_spl_token_2022` | `core_handled` |
| `core_spl_token2022_elgamal_registry_v1` | `regVYJW7tcT8zipN5YiBvHsvR5jXW1uLFxaHSbugABg` | `spl_token2022_elgamal_registry` | `program` | `kb_decoder_spl_token_2022` | `core_specialized_reserved_current` |
| `core_spl_token_v1` | `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA` | `token` | `program` | `kb_decoder_spl_token` | `core_handled` |
## DEX, AMM, CPMM, CLMM, DLMM, stable swap, weighted swap et orderbooks
| Canonique | Program ID | Source | Normalisé | Crate actuelle | Crate cible | Statut |
|------------------------------------|------------------------------------------------|--------------------------|--------------------------|-------------------------------------|-----------------------------------------------|------------------------|
| `amm_aldrin_v1` | `AMM55ShdkoGRB5jVYPjWziwk8m5MpwyDgsMWHaMSQWH6` | `aldrin_amm_v1` | `aldrin_amm_v1` | `-` | `kb_decoder_amm_aldrin_v1` | `reserved_missing` |
| `amm_aldrin_v2` | `CURVGoZn8zycx6FXwwevgBTB2gVvdbGTEpvMJDbgs2t4` | `aldrin_amm_v2` | `aldrin_amm_v2` | `-` | `kb_decoder_amm_aldrin_v2` | `reserved_missing` |
| `amm_alphaq` | `ALPHAQmeA7bjrVuccPsYPiCvsi428SNwte66Srvs4pHA` | `alphaq` | `alphaq` | `kb_decoder_alphaq` | `kb_decoder_amm_alphaq` | `current_alias` |
| `amm_believe` | `5qWya6UjwWnGVhdSBL3hyZ7B45jbk6Byt1hwd7ohEGXE` | `believe` | `believe` | `kb_decoder_believe` | `kb_decoder_amm_believe` | `current_alias` |
| `amm_bonk_swap` | `BSwp6bEBihVLdqJRKGgzjcGLHkcTuzmSo1TQkHepzH8p` | `bonk_swap` | `bonk_swap` | `kb_decoder_bonkswap` | `kb_decoder_amm_bonk_swap` | `current_alias` |
| `amm_cropper_finance` | `CTMAxxk34HjKWxQ3QLZK1HpaLXmBveao3ESePXbiyfzh` | `cropper_finance` | `cropper_finance` | `-` | `kb_decoder_amm_cropper_finance` | `reserved_missing` |
| `amm_dexlab_swap` | `DSwpgjMvXhtGn6BsbqmacdBZyfLj6jSWf3HJpdJtmg6N` | `dexlab_swap` | `dexlab_swap` | `-` | `kb_decoder_amm_dexlab_swap` | `reserved_missing` |
| `amm_fluxbeam` | `FLUXubRmkEi2q6K3Y9kBPg9248ggaZVsoSFhtJHSrm1X` | `fluxbeam` | `fluxbeam` | `kb_decoder_fluxbeam` | `kb_decoder_amm_fluxbeam` | `current_alias` |
| `amm_fusion` | `fUSioN9YKKSa3CUC2YUc4tPkHJ5Y6XW1yz8y6F7qWz9` | `fusion_amm` | `fusion_amm` | `kb_decoder_fusion_amm` | `kb_decoder_amm_fusion` | `current_alias` |
| `amm_goon_fi` | `goonERTdGsjnkZqWuVjs73BZ3Pb9qoCUdBUL17BnS5j` | `goon_fi` | `goon_fi` | `kb_decoder_goonfi` | `kb_decoder_amm_goon_fi` | `current_alias` |
| `amm_goon_fi_v2` | `goonuddtQRrWqqn5nFyczVKaie28f3kDkHWkHtURSLE` | `goon_fi_v2` | `goon_fi_v2` | `-` | `kb_decoder_amm_goon_fi_v2` | `reserved_missing` |
| `amm_goosefx_gamma` | `GAMMA7meSFWaBXF25oSUgmGRwaW6sCMFLmBNiMSdbHVT` | `goose_fx_gamma` | `goosefx_gamma` | `kb_decoder_goosefx_gamma` | `kb_decoder_amm_goosefx_gamma` | `current_alias` |
| `amm_goosefx_v2` | `GFXsSL5sSaDfNFQUYsHekbWBW1TsFdjDYzACh62tEHxn` | `goose_fx_v2` | `goosefx_v2` | `kb_decoder_goosefx_v2` | `kb_decoder_amm_goosefx_v2` | `current_alias` |
| `amm_guac_swap` | `Gswppe6ERWKpUTXvRPfXdzHhiCyJvLadVvXGfdpBqcE1` | `guac_swap` | `guac_swap` | `kb_decoder_guacswap` | `kb_decoder_amm_guac_swap` | `current_alias` |
| `amm_heaven_dex` | `HEAVENoP2qxoeuF8Dj2oT1GHEnu49U5mJYkdeC8BAX2o` | `heaven_dex` | `heaven_dex` | `-` | `kb_decoder_amm_heaven_dex` | `reserved_missing` |
| `amm_hylo_exchange` | `HYEXCHtHkBagdStcJCp3xbbb9B7sdMdWXFNj6mdsG4hn` | `hylo_exchange` | `hylo_exchange` | `kb_decoder_hylo_exchange` | `kb_decoder_amm_hylo_exchange` | `current_alias` |
| `amm_invariant_swap` | `HyaB3W9q6XdA5xwpU4XnSZV94htfmbmqJXZcEbRaJutt` | `invariant_swap` | `invariant_swap` | `-` | `kb_decoder_amm_invariant_swap` | `reserved_missing` |
| `amm_lifinity_swap` | `EewxydAPCCVuNEyrVN68PuSYdQ7wKn27V9Gjeoi8dy3S` | `lifinity_swap` | `lifinity_swap` | `-` | `kb_decoder_amm_lifinity_swap` | `reserved_missing` |
| `amm_lifinity_swap_v2` | `2wT8Yq49kHgDzXuPxZSaeLaH1qbmGXtEyPy64bL7aD3c` | `lifinity_swap_v2` | `lifinity_swap_v2` | `-` | `kb_decoder_amm_lifinity_swap_v2` | `reserved_missing` |
| `amm_marcopolo_swap` | `9tKE7Mbmj4mxDjWatikzGAtkoWosiiZX9y6J4Hfm2R8H` | `marcopolo_swap` | `marcopolo_swap` | `-` | `kb_decoder_amm_marcopolo_swap` | `reserved_missing` |
| `amm_metadao_futarchy_amm` | `FUTARELBfJfQ8RDGhg1wdhddq1odMAJUePHFuBYfUxKq` | `metadao_futarchy_amm` | `metadao_futarchy_amm` | `-` | `kb_decoder_amm_metadao_futarchy_amm` | `reserved_missing` |
| `amm_metadao_v0_5` | `AMMJdEiCCa8mdugg6JPF7gFirmmxisTfDJoSNSUi5zDJ` | `metadao_amm_v0_5` | `metadao_amm_v0_5` | `kb_decoder_metadao_amm_v0_5` | `kb_decoder_amm_metadao_v0_5` | `current_alias` |
| `amm_meteora_damm_v1` | `Eo7WjKq67rjJQSZxS6z3YkapzY3eMj6Xy8X5EQVn5UaB` | `meteora_damm_v1` | `meteora_damm_v1` | `kb_decoder_meteora_damm_v1` | `kb_decoder_amm_meteora_damm_v1` | `current_alias` |
| `amm_meteora_damm_v2` | `cpamdpZCGKUy5JxQXB4dcpGPiikHawvSWAd6mEn1sGG` | `meteora_damm_v2` | `meteora_damm_v2` | `kb_decoder_meteora_damm_v2` | `kb_decoder_amm_meteora_damm_v2` | `current_alias` |
| `amm_obric_v2` | `obriQD1zbpyLz95G5n7nJe6a4DPjpFwa5XYPoNm113y` | `obric_v2` | `obric_v2` | `kb_decoder_obric_v2` | `kb_decoder_amm_obric_v2` | `current_alias` |
| `amm_one_dex` | `DEXYosS6oEGvk8uCDayvwEZz4qEyDJRf9nFgYCaqPMTm` | `one_dex` | `one_dex` | `kb_decoder_one_dex` | `kb_decoder_amm_one_dex` | `current_alias` |
| `amm_orca_token_swap` | `DjVE6JNiYqPL2QXyCUUh8rNjHrbz9hXHNYt99MQ59qw1` | `orca_token_swap` | `orca_token_swap` | `-` | `kb_decoder_amm_orca_token_swap` | `reserved_missing` |
| `amm_orca_token_swap_v2` | `9W959DqEETiGZocYWCQPaJ6sBmUzgfxXfqGeTEdp3aQP` | `orca_token_swap_v2` | `orca_token_swap_v2` | `-` | `kb_decoder_amm_orca_token_swap_v2` | `reserved_missing` |
| `amm_pancake_swap` | `HpNfyc2Saw7RKkQd8nEL4khUcuPhQ7WwY1B2qjx8jxFq` | `pancake_swap` | `pancake_swap` | `kb_decoder_pancake_swap` | `kb_decoder_amm_pancake_swap` | `current_alias` |
| `amm_pump_swap` | `pAMMBay6oceH9fJKBRHGP5D4bD4sWpmSwMn52FMfXEA` | `pump_swap` | `pump_swap` | `kb_decoder_pump_swap` | `kb_decoder_amm_pump_swap` | `current_alias` |
| `amm_raydium_lp_amm` | `5quBtoiQqxF9Jv6KYKctB59NT3gtJD2Y65kdnB1Uev3h` | `raydium_lp_amm` | `raydium_lp_amm` | `-` | `kb_decoder_amm_raydium_lp_amm` | `reserved_missing` |
| `amm_raydium_lp_v2` | `RVKd61ztZW9GUwhRbbLoYVRE5Xf1B2tVscKqwZqXgEr` | `raydium_lp_v2` | `raydium_lp_v2` | `-` | `kb_decoder_amm_raydium_lp_v2` | `reserved_missing` |
| `amm_raydium_lp_v3` | `27haf8L6oxUeXrHrgEgsexjSY5hbVUWEmvv9Nyxg8vQv` | `raydium_lp_v3` | `raydium_lp_v3` | `-` | `kb_decoder_amm_raydium_lp_v3` | `reserved_missing` |
| `amm_raydium_lp_v4` | `675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8` | `raydium_lp_v4` | `raydium_lp_v4` | `-` | `kb_decoder_amm_raydium_lp_v4` | `reserved_missing` |
| `amm_saros` | `SSwapUtytfBdBn1b9NUGG6foMVPtcWgpRU32HToDUZr` | `saros_amm` | `saros_amm` | `-` | `kb_decoder_amm_saros` | `reserved_missing` |
| `amm_solfi` | `SoLFiHG9TfgtdUXUjWAxi3LtvYuFyDLVhBWxdMZxyCe` | `solfi` | `solfi` | `kb_decoder_solfi` | `kb_decoder_amm_solfi` | `current_alias` |
| `amm_solfi_v2` | `SV2EYYJyRz2YhfXwXnhNAevDEui5Q6yrfyo13WtupPF` | `solfi_v2` | `solfi_v2` | `kb_decoder_solfi_v2` | `kb_decoder_amm_solfi_v2` | `current_alias` |
| `amm_step_finance_swap` | `SSwpMgqNDsyV7mAgN9ady4bDVu5ySjmmXejXvy2vLt1` | `step_finance_swap` | `step_finance_swap` | `-` | `kb_decoder_amm_step_finance_swap` | `reserved_missing` |
| `amm_stepn_dooar_swap` | `Dooar9JkhdZ7J3LHN3A7YCuoGRUggXhQaG4kijfLGU2j` | `stepn_dooar_swap` | `stepn_dooar_swap` | `-` | `kb_decoder_amm_stepn_dooar_swap` | `reserved_missing` |
| `amm_swap_v1` | `SwaPpA9LAaLfeLi3a68M4DjnLqgtticKg6CnyNwgAC8` | `swap` | `swap` | `-` | `kb_decoder_amm_swap_v1` | `reserved_missing` |
| `amm_vertigo` | `vrTGoBuy5rYSxAfV3jaRJWHH6nN9WK4NRExGxsk1bCJ` | `vertigo` | `vertigo` | `kb_decoder_vertigo` | `kb_decoder_amm_vertigo` | `current_alias` |
| `amm_virtuals` | `5U3EU2ubXtK84QcRjWVmYt9RaDyA8gKxdUrPFXmZyaki` | `virtuals` | `virtuals` | `kb_decoder_virtuals` | `kb_decoder_amm_virtuals` | `current_alias` |
| `amm_woofi` | `WooFif76YGRNjk1pA8wCsN67aQsD9f9iLsz4NcJ1AVb` | `woofi` | `woofi` | `kb_decoder_woofi` | `kb_decoder_amm_woofi` | `current_alias` |
| `amm_zero_fi` | `ZERor4xhbUycZ6gb9ntrhqscUcZmAbQDjEAtCf4hbZY` | `zero_fi` | `zero_fi` | `kb_decoder_zerofi` | `kb_decoder_amm_zero_fi` | `current_alias` |
| `amm_zora` | `zoRabwLGd5zXaV7Gxacppw8tcceXEiTrSKyNLSaSTUc` | `zora` | `zora` | `kb_decoder_zora` | `kb_decoder_amm_zora` | `current_alias` |
| `clmm_byreal` | `REALQqNEomY6cQGZJUGwywTBD2UmDT32rZcNnfxQ5N2` | `byreal_clmm` | `byreal_clmm` | `kb_decoder_byreal_clmm` | `kb_decoder_clmm_byreal` | `current_alias` |
| `clmm_crema_finance` | `CLMM9tUoggJu2wagPkkqs9eFG4BWhVBZWkP1qv3Sp7tR` | `crema_finance` | `crema_finance` | `-` | `kb_decoder_clmm_crema_finance` | `reserved_missing` |
| `clmm_cropper_whirlpool` | `H8W3ctz92svYg6mkn1UtGfu2aQr2fnUFHM1RhScEtQDt` | `cropper_whirlpool` | `cropper_whirlpool` | `-` | `kb_decoder_clmm_cropper_whirlpool` | `reserved_missing` |
| `clmm_orca_whirlpool` | `whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc` | `orca_whirlpool` | `orca_whirlpool` | `kb_decoder_orca_whirlpool` | `kb_decoder_clmm_orca_whirlpool` | `duplicate_program_id` |
| `clmm_orca_whirlpool` | `whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc` | `orca_whirlpool` | `orca_whirlpool` | `kb_decoder_orca_whirlpool` | `kb_decoder_clmm_orca_whirlpool` | `duplicate_program_id` |
| `clmm_raydium` | `CAMMCzo5YL8w4VFF8KVHrK22GGUsp5VTaW7grrKgrWqK` | `raydium_clmm` | `raydium_clmm` | `kb_decoder_raydium_clmm` | `kb_decoder_clmm_raydium` | `current_alias` |
| `clmm_stabble` | `6dMXqGZ3ga2dikrYS9ovDXgHGh5RUsb2RTUj6hrQXhk6` | `stabble_clmm` | `stabble_clmm` | `kb_decoder_stabble_clmm` | `kb_decoder_clmm_stabble` | `current_alias` |
| `cpmm_raydium` | `CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C` | `raydium_cpmm` | `raydium_cpmm` | `kb_decoder_raydium_cpmm` | `kb_decoder_cpmm_raydium` | `current_alias` |
| `dlmm_meteora` | `LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo` | `meteora_dlmm` | `meteora_dlmm` | `kb_decoder_meteora_dlmm` | `kb_decoder_dlmm_meteora` | `current_alias` |
| `orderbook_jupiter_limit_order` | `jupoNjAxXgZ4rjzxzPMP4oxduvQsQtZzyknqvzYNrNu` | `jupiter_limit_order` | `jupiter_limit_order` | `kb_decoder_jupiter_limit_order` | `kb_decoder_orderbook_jupiter_limit_order` | `current_alias` |
| `orderbook_jupiter_limit_order_v2` | `j1o2qRpjcyUwEvwtcfhEQefh773ZgjxcVRry7LDqg5X` | `jupiter_limit_order_v2` | `jupiter_limit_order_v2` | `kb_decoder_jupiter_limit_order_v2` | `kb_decoder_orderbook_jupiter_limit_order_v2` | `current_alias` |
| `orderbook_manifest_v1` | `MNFSTqtC93rEfYHB6hF82sKdZpUDFWkViLByLd1k1Ms` | `manifest` | `manifest` | `-` | `kb_decoder_orderbook_manifest_v1` | `reserved_missing` |
| `orderbook_openbook_v2` | `opnb2LAfJYbRMAHHvqjCwQxanZn7ReEHp1k81EohpZb` | `openbook_v2` | `openbook_v2` | `kb_decoder_openbook_v2` | `kb_decoder_orderbook_openbook_v2` | `current_alias` |
| `orderbook_phoenix_v1` | `PhoeNiXZ8ByJGLkxNfZRnkUfjvmuYqLR89jjFHGqdXY` | `phoenix` | `phoenix` | `-` | `kb_decoder_orderbook_phoenix_v1` | `reserved_missing` |
| `stable_swap_jupiter_stable` | `JUPUSDecMzAVgztLe6eGhwUBj1Pn3j9WAXwmtHmfbRr` | `jupiter_stable` | `jupiter_stable` | `kb_decoder_jupiter_stable` | `kb_decoder_stable_swap_jupiter_stable` | `current_alias` |
| `stable_swap_mercurial` | `MERLuDFBMmsHnsBPZw2sDQZHvXFMwp8EdjudcU2HKky` | `mercurial_stable_swap` | `mercurial_stable_swap` | `-` | `kb_decoder_stable_swap_mercurial` | `reserved_missing` |
| `stable_swap_saber` | `SSwpkEEcbUqx4vtoEByFjSkhKdCT862DNVb52nZg1UZ` | `sabre_statble_swap` | `sabre_stable_swap` | `-` | `kb_decoder_stable_swap_saber` | `reserved_missing` |
| `stable_swap_stabble` | `swapNyd8XiQwJ6ianp9snpu4brUqFxadzvHebnAXjJZ` | `stabble_stable_swap` | `stabble_stable_swap` | `kb_decoder_stabble_stable_swap` | `kb_decoder_stable_swap_stabble` | `current_alias` |
| `weighted_swap_stabble` | `swapFpHZwjELNnjvThjajtiVmkz3yPQEHjLtka2fwHW` | `stabble_weighted_swap` | `stabble_weighted_swap` | `kb_decoder_stabble_weighted_swap` | `kb_decoder_weighted_swap_stabble` | `current_alias` |
## Routers et surfaces de routing
| Canonique | Program ID | Source | Normalisé | Crate actuelle | Crate cible | Statut |
|--------------------------------|------------------------------------------------|-------------------------|-------------------------|----------------------------------|-------------------------------------------|--------------------|
| `router_dflow_aggregator_v4` | `DF1ow4tspfHX9WJsAb9epbkA8hmpSEAtxXy1V27QBH` | `dflow_agregator_v4` | `dflow_aggregator_v4` | `kb_decoder_dflow_aggregator_v4` | `kb_decoder_router_dflow_aggregator_v4` | `current_alias` |
| `router_jupiter_aggregator_v4` | `JUP4Fb2cqiRUcaTHdrPC8h2gNsA2ETXiPDD33WcGuJB` | `jupiter_agregator_v4` | `jupiter_aggregator_v4` | `-` | `kb_decoder_router_jupiter_aggregator_v4` | `reserved_missing` |
| `router_jupiter_aggregator_v6` | `JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4` | `jupiter_agregator_v6` | `jupiter_aggregator_v6` | `-` | `kb_decoder_router_jupiter_aggregator_v6` | `reserved_missing` |
| `router_jupiter_dca` | `DCA265Vj8a9CEuX1eb1LWRnDT7uK6q1xMipnNyatn23M` | `jupiter_dca` | `jupiter_dca` | `kb_decoder_jupiter_dca` | `kb_decoder_router_jupiter_dca` | `current_alias` |
| `router_okx_labs_v1` | `6m2CDdhRgxpH4WjvdzxAYbGxwdGUz5MziiL5jek2kBma` | `okx_labs_v1` | `okx_labs_v1` | `kb_decoder_okx_lab_v1` | `kb_decoder_router_okx_labs_v1` | `current_alias` |
| `router_okx_labs_v2` | `proVF4pMXVaYqmy4NjniPh4pqKNfMmsihgd4wdkCX3u` | `okx_labs_v2` | `okx_labs_v2` | `-` | `kb_decoder_router_okx_labs_v2` | `reserved_missing` |
| `router_raydium_amm_routing` | `routeUGWgWzqBWFcrCfv8tritsqukccJPu3q5GPP3xS` | `raydium_amm_routing` | `raydium_amm_routing` | `-` | `kb_decoder_router_raydium_amm_routing` | `reserved_missing` |
| `router_sanctum` | `stkitrT1Uoy18Dk1fTrgPw8W6MVzoCfYoAFT4MLsmhq` | `sanctum_router` | `sanctum_router` | `-` | `kb_decoder_router_sanctum` | `reserved_missing` |
| `router_tessera_v` | `TessVdML9pBGgG9yGks7o4HewRaXVAMuoVj4x83GLQH` | `tessera_v` | `tessera_v` | `-` | `kb_decoder_router_tessera_v` | `reserved_missing` |
| `router_titan_exchange_router` | `T1TANpTeScyeqVzzgNViGDNrkQ6qHz9KrSBS4aNXvGT` | `titan_exchange_router` | `titan_exchange_router` | `-` | `kb_decoder_router_titan_exchange_router` | `reserved_missing` |
## Launchpads et bonding curves
| Canonique | Program ID | Source | Normalisé | Crate actuelle | Crate cible | Statut |
|--------------------------------------|------------------------------------------------|----------------------------|----------------------------|-----------------------------|-------------------------------------------------|--------------------|
| `launchpad_boop_fun` | `boop8hVGQGqehUK2iVEMEnMrL5RbjywRzHKBmBE7ry4` | `boop_fun` | `boop_fun` | `kb_decoder_boop_fun` | `kb_decoder_launchpad_boop_fun` | `current_alias` |
| `launchpad_letsbonk_fun` | `FfYek5vEz23cMkWsdJwG2oa6EphsvXSHrGpdALN4g6W1` | `letsbonk_fun` | `letsbonk_fun` | `-` | `kb_decoder_launchpad_letsbonk_fun` | `reserved_missing` |
| `launchpad_metadao_ico` | `moontUzsdepotRGe5xsfip7vLPTJnVuafqdUWexVnPM` | `metadao_ico` | `metadao_ico` | `-` | `kb_decoder_launchpad_metadao_ico` | `reserved_missing` |
| `launchpad_meteora_dbc` | `dbcij3LWUppWqq96dh6gJWwBifmcGfLSB5D4DuSMaqN` | `meteora_dbc` | `meteora_dbc` | `kb_decoder_meteora_dbc` | `kb_decoder_launchpad_meteora_dbc` | `current_alias` |
| `launchpad_moonit` | `MoonCVVNZFSYkqNXP6bxHLPL6QQJiMagDL3qcqUQTrG` | `moonit` | `moonit` | `kb_decoder_moonit` | `kb_decoder_launchpad_moonit` | `current_alias` |
| `launchpad_moonshot_token_authority` | `7rtiKSUDLBm59b1SBmD9oajcP8xE64vAGSMbAN5CXy1q` | `moonshot_token_authority` | `moonshot_token_authority` | `-` | `kb_decoder_launchpad_moonshot_token_authority` | `reserved_missing` |
| `launchpad_orca_wavebreak` | `waveQX2yP3H1pVU8djGvEHmYg8uamQ84AuyGtpsrXTF` | `orca_wavebreak` | `orca_wavebreak` | `kb_decoder_orca_wavebreak` | `kb_decoder_launchpad_orca_wavebreak` | `current_alias` |
| `launchpad_printr` | `T8HsGYv7sMk3kTnyaRqZrbRPuntYzdh12evXBkprint` | `printr` | `printr` | `kb_decoder_printr` | `kb_decoder_launchpad_printr` | `current_alias` |
| `launchpad_pump_fun` | `6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P` | `pump_fun` | `pump_fun` | `kb_decoder_pump_fun` | `kb_decoder_launchpad_pump_fun` | `current_alias` |
| `launchpad_pump_pumpup_ai` | `PdMDrKEMaX8q7CCJb7NvUCxerBCcsFUa4LjBEynTtEd` | `pumpup_ai` | `pumpup_ai` | `-` | `kb_decoder_launchpad_pump_pumpup_ai` | `reserved_missing` |
| `launchpad_raydium_launchlab` | `LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj` | `raydium_launchlab` | `raydium_launchlab` | `-` | `kb_decoder_launchpad_raydium_launchlab` | `reserved_missing` |
## Lending, vault, staking, bridge, perps, oracle et treasury
| Canonique | Program ID | Source | Normalisé | Crate actuelle | Crate cible | Statut |
|---------------------------------------------------|------------------------------------------------|-------------------------------------------|-------------------------------------------|---------------------------------|--------------------------------------------------------------|--------------------|
| `bridge_circle_cctp_token_messenger_minter` | `CCTPiPYPc6AsJuwueEnWgSgucamXDZwBd53dQ11YiKX3` | `cctp_token_messenger_minter` | `cctp_token_messenger_minter` | `-` | `kb_decoder_bridge_circle_cctp_token_messenger_minter` | `reserved_missing` |
| `bridge_circle_cctp_token_messenger_minter_v2` | `CCTPV2vPZJS2u2BBsUoscuikbYjnpFmbFsvVuJdgUMQe` | `cctp_token_messenger_minter_v2` | `cctp_token_messenger_minter_v2` | `-` | `kb_decoder_bridge_circle_cctp_token_messenger_minter_v2` | `reserved_missing` |
| `bridge_de_bridge_destination` | `dst5MGcFPoBeREFAA5E3tU5ij8m5uVYwkzkSAbsLbNo` | `de_bridge_destination` | `de_bridge_destination` | `-` | `kb_decoder_bridge_de_bridge_destination` | `reserved_missing` |
| `bridge_de_bridge_source` | `src5qyZHqTqecJV4aY6Cb6zDZLMDzrDKKezs22MPHr4` | `de_bridge_source` | `de_bridge_source` | `-` | `kb_decoder_bridge_de_bridge_source` | `reserved_missing` |
| `bridge_layer_zero_endpoint` | `76y77prsiCMvXMjuoZ5VRrhG5qYBrUMYTE5WgHqgjEn6` | `layer_zero_endpoint` | `layer_zero_endpoint` | `-` | `kb_decoder_bridge_layer_zero_endpoint` | `reserved_missing` |
| `bridge_layer_zero_executor` | `6doghB248px58JSSwG4qejQ46kFMW4AMj7vzJnWZHNZn` | `layer_zero_executor` | `layer_zero_executor` | `-` | `kb_decoder_bridge_layer_zero_executor` | `reserved_missing` |
| `bridge_wormhole` | `wormDTUJ6AWPNvk59vGQbDvGJmqbDTdgWgAqcLBCgUb` | `whormhole_bridge` | `wormhole_bridge` | `-` | `kb_decoder_bridge_wormhole` | `reserved_missing` |
| `lending_jupiter_lend_borrow` | `jupr81YtYssSyPt8jbnGuiWon5f6x9TcDEFxYe3Bdzi` | `jupiter_lend_borrow` | `jupiter_lend_borrow` | `-` | `kb_decoder_lending_jupiter_lend_borrow` | `reserved_missing` |
| `lending_jupiter_lend_earn` | `jup3YeL8QhtSx1e253b2FDvsMNC87fDrgQZivbrndc9` | `jupiter_lend_earn` | `jupiter_lend_earn` | `-` | `kb_decoder_lending_jupiter_lend_earn` | `reserved_missing` |
| `lending_jupiter_lend_flash_loan` | `jupgfSgfuAXv4B6R2Uxu85Z1qdzgju79s6MfZekN6XS` | `jupiter_lend_flash_loan` | `jupiter_lend_flash_loan` | `-` | `kb_decoder_lending_jupiter_lend_flash_loan` | `reserved_missing` |
| `lending_jupiter_lend_liquidity` | `jupeiUmn818Jg1ekPURTpr4mFo29p46vygyykFJ3wZC` | `jupiter_lend_liquidity` | `jupiter_lend_liquidity` | `-` | `kb_decoder_lending_jupiter_lend_liquidity` | `reserved_missing` |
| `lending_kamino` | `KLend2g3cP87fffoy8q1mQqGKjrxjC8boSyAYavgmjD` | `kamino_lending` | `kamino_lending` | `-` | `kb_decoder_lending_kamino` | `reserved_missing` |
| `lending_marginfi` | `MFLQPPPPjNinkdKoy2odNFBhvpY43XtCDZjBwG2fwn5` | `marginfi` | `marginfi` | `-` | `kb_decoder_lending_marginfi` | `reserved_missing` |
| `lending_marginfi_v2` | `MFv2hWf31Z9kbCa1snEPYctwafyhdvnV7FZnsebVacA` | `marginfi_v2` | `marginfi_v2` | `-` | `kb_decoder_lending_marginfi_v2` | `reserved_missing` |
| `lending_sharky_fi` | `SHARKobtfF1bHhxD2eqftjHBdVSCbKo9JtgK71FhELP` | `sharky_fi` | `sharky_fi` | `-` | `kb_decoder_lending_sharky_fi` | `reserved_missing` |
| `lending_solend_protocol` | `So1endDq2YkqhipRh3WViPa8hdiSpxWy6z3Z6tMCpAo` | `solend_protocol` | `solend_protocol` | `-` | `kb_decoder_lending_solend_protocol` | `reserved_missing` |
| `oracle_jupiter_prediction_market` | `3ZZuTbwC6aJbvteyVxXUS7gtFYdf7AuXeitx6VyvjvUp` | `jupiter_prediction_market` | `jupiter_prediction_market` | `-` | `kb_decoder_oracle_jupiter_prediction_market` | `reserved_missing` |
| `perpetuals_drift_v2` | `dRiftyHA39MWEi3m9aunc5MzRF1JYuBsbn6VPcn33UH` | `drift_v2` | `drift_v2` | `kb_decoder_drift_v2` | `kb_decoder_perpetuals_drift_v2` | `current_alias` |
| `perpetuals_jupiter` | `PERPHjGBqRHArX4DySjwM6UJHiR3sWAatqfdBS2qQJu` | `jupiter_perpetuals` | `jupiter_perpetuals` | `kb_decoder_jupiter_perpetuals` | `kb_decoder_perpetuals_jupiter` | `current_alias` |
| `perpetuals_zeta` | `ZETAxsqBRek56DhiGXrn75yj2NHU3aYUnxvHXpkf3aD` | `zeta` | `zeta` | `kb_decoder_zeta` | `kb_decoder_perpetuals_zeta` | `current_alias` |
| `perpetuals_zeta_matching_engine` | `zDEXqXEG7gAyxb1Kg9mK5fPnUdENCGKzWrM21RMdWRq` | `zeta_matching_engine` | `zeta_matching_engine` | `-` | `kb_decoder_perpetuals_zeta_matching_engine` | `reserved_missing` |
| `staking_jito_tip_distribution` | `4R3gSG8BpU4t19KYj8CfnbtRpnT8gtk4dvTHxVRwc2r7` | `jito_tip_distribution` | `jito_tip_distribution` | `-` | `kb_decoder_staking_jito_tip_distribution` | `reserved_missing` |
| `staking_kamino_farm` | `FarmsPZpWu9i7Kky8tPN37rs2TpmMrAZrC7S7vJa91Hr` | `kamino_farm` | `kamino_farm` | `-` | `kb_decoder_staking_kamino_farm` | `reserved_missing` |
| `staking_marinade_finance` | `MarBmsSgKXdrN1egZf5sqe1TMai9K1rChYNDJgjq7aD` | `marinade_finance` | `marinade_finance` | `-` | `kb_decoder_staking_marinade_finance` | `reserved_missing` |
| `staking_sanctum_multi_validator_spl_stake_pool` | `SPMBzsVUuoHA4Jm6KunbsotaahvVikZs1JyTW6iJvbn` | `sanctum_multi_validator_spl_stake_pool` | `sanctum_multi_validator_spl_stake_pool` | `-` | `kb_decoder_staking_sanctum_multi_validator_spl_stake_pool` | `reserved_missing` |
| `staking_sanctum_single_validator_spl_stake_pool` | `SP12tWFxD9oJsVWNavTTBZvMbA6gkAmxtVgxdqvyvhY` | `sanctum_single_validator_spl_stake_pool` | `sanctum_single_validator_spl_stake_pool` | `-` | `kb_decoder_staking_sanctum_single_validator_spl_stake_pool` | `reserved_missing` |
| `staking_solayer` | `sSo1iU21jBrU9VaJ8PJib1MtorefUV4fzC9GURa2KNn` | `solayer` | `solayer` | `kb_decoder_solayer` | `kb_decoder_staking_solayer` | `current_alias` |
| `treasury_helium_treasury_management` | `treaf4wWBBty3fHdyBpo35Mz84M8k3heKXmjmi9vFt5` | `helium_treasury_management` | `helium_treasury_management` | `-` | `kb_decoder_treasury_helium_treasury_management` | `reserved_missing` |
| `vault_kamino` | `kvauTFR8qm1dhniz6pYuBZkuene3Hfrs1VQhVRgCNrr` | `kamino_vault` | `kamino_vault` | `-` | `kb_decoder_vault_kamino` | `reserved_missing` |
| `vault_kamino_v2` | `KvauGMspG5k6rtzrqqn7WNn3oZdyKqLKwK2XWQ8FLjd` | `kamino_vault_v2` | `kamino_vault_v2` | `-` | `kb_decoder_vault_kamino_v2` | `reserved_missing` |
| `vault_meteora` | `24Uqj9JCLxUeoC3hGfh5W3s9FM9uCHDS2SG3LYwBpyTi` | `meteora_vault` | `meteora_vault` | `kb_decoder_meteora_vault` | `kb_decoder_vault_meteora` | `current_alias` |
| `vesting_streamflow` | `strmRqUCoQUgGUan5YhzUZa6KqdzwX5L6FpUxfmKg5m` | `streamflow` | `streamflow` | `-` | `kb_decoder_vesting_streamflow` | `reserved_missing` |
## NFT, metadata, admin, governance et locks
| Canonique | Program ID | Source | Normalisé | Crate actuelle | Crate cible | Statut |
|------------------------------------|------------------------------------------------|---------------------------|---------------------------|------------------------|--------------------------------------------------|--------------------|
| `lock_raydium_lp` | `LockrWmn6K5twhz3y9w1dQERbmgSaRkfnTeTKbpofwE` | `raydium_lock_lp` | `raydium_lock_lp` | `-` | `kb_decoder_lock_raydium_lp` | `reserved_missing` |
| `admin_jupiter_lock` | `LocpQgucEQHbqNABEYvBvwoxCPsSbG91A1QaQhQQqjn` | `jupiter_lock` | `jupiter_lock` | `-` | `kb_decoder_admin_jupiter_lock` | `reserved_missing` |
| `admin_pump_fees` | `pfeeUxB6jkeY1Hxd7CsFCAjcbHA9rWtchMGdZ6VojVZ` | `pump_fees` | `pump_fees` | `kb_decoder_pump_fees` | `kb_decoder_admin_pump_fees` | `current_alias` |
| `metadata_metaplex_token_metadata` | `metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s` | `metaplex_token_metadata` | `metaplex_token_metadata` | `-` | `kb_lib::DcMetadataMetaplexTokenMetadataDecoder` | `current_migrated` |
| `metadata_name_service` | `namesLPneVptA9Z5rqUDD9tMTWEJwofgaYwp8cawRkX` | `name_service` | `name_service` | `-` | `kb_decoder_metadata_spl_name_service` | `reserved_missing` |
| `nft_metaplex_bubblegum` | `BGUMAp9Gq7iTEuizy4pqaxsTyUCBK68MDfK752saRPUY` | `bubblegum` | `bubblegum` | `-` | `kb_decoder_nft_metaplex_bubblegum` | `reserved_missing` |
| `nft_metaplex_mpl_core` | `CoREENxT6tW1HoK8ypY1SxRMZTcVPm7R94rH4PZNhX7d` | `mpl_core` | `mpl_core` | `-` | `kb_decoder_nft_metaplex_mpl_core` | `reserved_missing` |
## Surfaces à classifier
Ces entrées ont un `program_id`, mais leur fonction réelle n'est pas encore assez claire pour créer une crate canonique. Elles doivent être étudiées avant renommage.
| Canonique | Program ID | Source | Normalisé | Crate actuelle | Crate cible | Statut |
|---------------------------------------|------------------------------------------------|-------------------------------|-------------------------------|----------------------------------|-------------|--------------------------------------|
| `unknown_aquifer` | `AQU1FRd7papthgdrwPTTq5JacJh8YtwEXaBfKU3bTz45` | `aquifer` | `aquifer` | `-` | `-` | `needs_classification` |
| `unknown_axiom_trade` | `FLASHX8DrLbgeR8FcfNV1F5krxYcYMUdBkrP1EPBtxB9` | `axiom_trade` | `axiom_trade` | `-` | `-` | `needs_classification` |
| `unknown_bison_fi` | `BiSoNHVpsVZW2F7rx2eQ59yQwKxzU5NvBcmKshCSUypi` | `bison_fi` | `bison_fi` | `kb_decoder_bisonfi` | `-` | `current_alias_needs_classification` |
| `unknown_carrot_defi` | `CarrotwivhMpDnm27EHmRLeQ683Z1PufuqEmBZvD282s` | `carrot_defi` | `carrot_defi` | `-` | `-` | `needs_classification` |
| `unknown_clone` | `C1onEW2kPetmHmwe74YC1ESx3LnFEpVau6g2pg4fHycr` | `clone` | `clone` | `kb_decoder_clone` | `-` | `current_alias_needs_classification` |
| `unknown_gavel` | `srAMMzfVHVAtgSJc8iH6CfKzuWuUTzLHVCE81QU1rgi` | `gavel` | `gavel` | `kb_decoder_gavel` | `-` | `current_alias_needs_classification` |
| `unknown_hawk_fi` | `FqGg2Y1FNxMiGd51Q6UETixQWkF5fB92MysbYogRJb3P` | `hawk_fi` | `hawk_fi` | `-` | `-` | `needs_classification` |
| `unknown_humidi_fi` | `9H6tua7jkLhdm3w8BvgpTn5LZNU7g4ZynDmCiNN3q6Rp` | `humidi_fi` | `humidi_fi` | `-` | `-` | `needs_classification` |
| `unknown_hylo_stability_pool` | `HysTabVUfmQBFcmzu1ctRd1Y1fxd66RBpboy1bmtDSQQ` | `hylo_stability_pool` | `hylo_stability_pool` | `kb_decoder_hylo_stability_pool` | `-` | `current_alias_needs_classification` |
| `unknown_jup_studio_authority` | `8rE9CtCjwhSmbwL5fbJBtRFsS3ohfMcDFeTTC7t4ciUA` | `jup_studio_authority` | `jup_studio_authority` | `-` | `-` | `needs_classification` |
| `unknown_jupiter_apepro_smart_wallet` | `JSW99DKmxNyREQM14SQLDykeBvEUG63TeohrvmofEiw` | `jupiter_apepro_smart_wallet` | `jupiter_apepro_smart_wallet` | `-` | `-` | `needs_classification` |
| `unknown_kamino` | `6LtLpnUFNByNXLyCoK9wA2MykKAmQNZKBdY8s47dehDc` | `kamino` | `kamino` | `-` | `-` | `needs_classification` |
| `unknown_metadao_bid_wall` | `WALL8ucBuUyL46QYxwYJjidaFYhdvxUFrgvBxPshERx` | `metadao_bid_wall` | `metadao_bid_wall` | `-` | `-` | `needs_classification` |
| `unknown_numeraire` | `NUMERUNsFCP3kuNmWZuXtm1AaQCPj9uw6Guv2Ekoi5P` | `numeraire` | `numeraire` | `kb_decoder_numeraire` | `-` | `current_alias_needs_classification` |
| `unknown_ondo_global_markets` | `XzTT4XB8m7sLD2xi6snefSasaswsKCxx5Tifjondogm` | `ondo_global_markets` | `ondo_global_markets` | `-` | `-` | `needs_classification` |
| `unknown_ore_v3` | `oreV3EG1i9BEgiAJ8b177Z2S2rMarzak4NMv1kULvWv` | `ore_v3` | `ore_v3` | `-` | `-` | `needs_classification` |
| `unknown_penguin_finance` | `PSwapMdSai8tjrEXcxFeQth87xC4rRsa4VA5mhGhXkP` | `pinguin_finance` | `penguin_finance` | `-` | `-` | `needs_classification` |
| `unknown_sabre_decimal_wrapper` | `DecZY86MU5Gj7kppfUCEmd4LbXXuyZH1yHaP2NTqdiZB` | `sabre_decimal_wrapper` | `sabre_decimal_wrapper` | `-` | `-` | `needs_classification` |
| `unknown_sanctum_s_controller` | `5ocnV1qiCgaQR8Jb8xWnVbApfaygJ8tNoZfgPwsgx9kx` | `sanctum_s_controller` | `sanctum_s_controller` | `-` | `-` | `needs_classification` |
| `unknown_scorch` | `SCoRcH8c2dpjvcJD6FiPbCSQyQgu3PcUAWj2Xxx3mqn` | `scorch` | `scorch` | `kb_decoder_scorch` | `-` | `current_alias_needs_classification` |
| `unknown_swig` | `swigypWHEksbC64pWKwah1WTeh9JXwx8H1rJHLdbQMB` | `swig` | `swig` | `-` | `-` | `needs_classification` |
## Autres surfaces
| Canonique | Program ID | Source | Normalisé | Crate actuelle | Crate cible | Statut |
|-----------|------------|--------|-----------|----------------|-------------|--------|
## Doublons et aliases à surveiller
- Les noms `okx_v1`, `okx_v2`, `onchain_labs_dex_v1`, `onchain_labs_dex_v2` ne doivent pas être retenus comme noms canoniques tant que les `program_id` prouvés sont `okx_labs_v1` et `okx_labs_v2`.
- `goosefx_gamma` et `goosefx_v2` ne doivent pas être fusionnés tant que les `program_id` restent distincts.
- `raydium_pool_v4` doit être traité comme alias de documentation de `amm_raydium_lp_v4` si le `program_id` est `675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8`.
- `meteora_pools_amm` est un alias documentaire probable de `amm_meteora_damm_v1` si le `program_id` est `Eo7WjKq67rjJQSZxS6z3YkapzY3eMj6Xy8X5EQVn5UaB`.
## Règle de migration
Aucun renommage physique massif ne doit être fait dans un delta général. Pour chaque surface :
1. confirmer le `program_id` ;
2. confirmer la fonction réelle ;
3. choisir le `canonical_surface_code` ;
4. créer ou renommer une seule crate ;
5. mettre à jour `Cargo.toml` ;
6. exécuter `cargo build` ;
7. mettre à jour le registre ;
8. supprimer l'ancien alias seulement après validation.
## Comptes qui ne sont pas des programmes
Les comptes qui ne sont pas prouvés comme programmes exécutables doivent rester hors du registre de surfaces. Le cas `BAGSB9TpGrZxQbEsrEznv5jXXdwyP6AXerN8aVRiAmcv` est documenté dans `docs/ACCOUNT_ONLY_CANDIDATES.md`.
## Index hexadécimal optionnel
Un préfixe `00` à `ff` ne doit pas remplacer le nom canonique. Il peut être ajouté comme champ `registry_code` dans le registre, mais les crates doivent rester descriptives. Voir `docs/PROGRAM_CODE_INDEX.md`.
## Bags Fee Share
| Canonique | Program id | Source | Fonction | Crate cible | Statut |
|--------------------------|------------------------------------------------|-------------------|----------|-------------------------------------|---------------------|
| `fees_bags_fee_share_v1` | `FEEhPbKVKnco9EXnaY3i4R5rQVUx91wgVfu8qokixywi` | Bags Fee Share V1 | `fees` | `kb_decoder_fees_bags_fee_share_v1` | `canonical_current` |
| `fees_bags_fee_share_v2` | `FEE2tBhCKAt7shrod19QttSVREUYPiyMzoku1mL1gqVK` | Bags Fee Share V2 | `fees` | `kb_decoder_fees_bags_fee_share_v2` | `canonical_current` |

View File

@@ -1,20 +0,0 @@
<!-- file: docs/PROJECT_OBJECTIVES.md -->
<!-- version: 1 -->
# Objectifs du projet
## Objectif court terme
L'objectif court terme est de construire un système de trading assisté sur Solana. Le programme doit aider l'opérateur à observer les créations de tokens, créations de pools, migrations, changements de liquidité, swaps, claims de frais et opérations administratives qui peuvent influencer une décision d'achat ou de revente.
Le système ne doit pas commencer par une stratégie autonome. Il doit d'abord fournir une observation fiable, des démos live, des garde-fous d'exécution et une validation post-transaction.
## Objectif long terme
L'objectif long terme est de construire une bibliothèque d'analyse Solana capable de rivaliser progressivement avec des outils d'exploration et d'analyse comme les indexeurs publics : parser la blockchain, classifier les programmes, décoder les instructions, matérialiser les événements métier, agréger les états et rendre les surfaces inconnues auditables.
Ce second objectif impose de conserver une architecture large : raw immuable, registres de programmes, décodeurs par surface, matérialisateurs transversaux, exécuteurs séparés, tests anti-régression et documentation de classification.
## Conséquence sur le squelette
Le squelette doit rester plus large que le besoin immédiat de trading. En revanche, le développement actif doit rester priorisé : logging, configuration, stockage, RPC, wallet, démos live, puis surfaces prioritaires pour les listeners et l'exécution contrôlée.

View File

@@ -1,115 +0,0 @@
<!-- file: docs/RAW_STORAGE_LIFECYCLE.md -->
<!-- version: 4 -->
# Cycle de vie du stockage transactionnel Solana
## Principe général
Le stockage rejouable repose désormais sur une transaction Solana canonique unique par signature. Les formats dorigine JSON-RPC, WebSocket Helius ou Yellowstone Protobuf sont des formats de transport, pas des modèles de stockage métier.
Le cycle est :
```text
acquisition
-> normalisation canonique
-> persistance raw canonique
-> extraction core
-> décodage
-> matérialisation
-> compaction / archivage / purge éventuelle
```
## Transaction canonique
`kb_sol_raw_transactions` conserve suffisamment dinformation pour :
- auditer une transaction ;
- reconstruire les tables `core` ;
- rejouer de nouvelles versions de décodeurs ;
- rejouer de nouvelles versions de matérialiseurs ;
- comparer plusieurs sources sans dépendre de leur format.
La ligne est unique par signature. `canonical_format_version` permet de faire évoluer le contrat sans ambiguïté.
## Observations dacquisition
`kb_sol_obs_transaction_observations` conserve les preuves techniques dacquisition :
- fournisseur et endpoint ;
- protocole et méthode ;
- origine live/backfill/replay/réparation ;
- commitment ;
- session et filtre ;
- timestamps de détection, réception, normalisation et persistance ;
- taille du message ;
- statut et erreur éventuelle.
Cette table ne conserve pas le payload complet. Elle peut contenir plusieurs lignes pour une même signature.
## Ancienne table WebSocket
`kb_sol_raw_ws_notifications` est une table historique de `0.2.3`, supprimée pendant la transition validée `0.3.1`. Elle nexiste plus dans la baseline SQL active.
Les nouvelles notifications WebSocket ne doivent pas être stockées intégralement par défaut. Une notification de logs peut rester temporairement dans une queue mémoire jusquà lhydratation de la transaction.
## États de rétention
Les états de rétention de `kb_sol_raw_transactions` sont :
```text
full
compacted
archived
purged
```
### `full`
Le document canonique complet est présent dans PostgreSQL.
### `compacted`
Une représentation réduite ou un stockage externe permet encore laudit minimal, mais le payload canonique complet nest plus dans la ligne chaude.
### `archived`
Le payload a été déplacé vers un stockage darchive durable.
### `purged`
Le payload nest plus disponible. Le hash canonique, la signature, le slot et les données dérivées doivent rester suffisants pour les diagnostics autorisés.
## États de traitement
```text
received
core_extracted
decoded
materialized
failed
```
Létat décrit la progression de la transaction canonique, pas celle de chaque observation de source.
## Conditions avant compaction ou purge
Aucune purge destructive ne doit être activée avant validation de :
- lextraction core idempotente ;
- la couverture des décodeurs prioritaires ;
- la reconstruction depuis archive ;
- la stabilité du hash canonique ;
- la conservation du ledger de traitement ;
- la stratégie de sauvegarde PostgreSQL.
## Payloads fournisseur de diagnostic
Les payloads complets spécifiques à un fournisseur peuvent être exportés temporairement pour une session de test. Ils ne doivent pas devenir une dépendance du replay métier.
Un export de diagnostic doit être :
- opt-in ;
- borné en durée et en taille ;
- associé à une session ;
- supprimable indépendamment de PostgreSQL.

View File

@@ -1,147 +0,0 @@
<!-- file: docs/RAW_STORE.md -->
<!-- version: 6 -->
# Store transactionnel Solana canonique
## Historique
`0.2.3` a créé deux tables minimales :
```text
kb_sol_raw_rpc_transactions
kb_sol_raw_ws_notifications
```
Ces tables restent un jalon historique validé dans `CHANGELOG.md`. La transition a été appliquée et contrôlée sur PostgreSQL réel pendant `0.3.1`.
Le modèle actif est :
```text
kb_sol_raw_transactions
kb_sol_obs_transaction_observations
```
## Objectif cible
Le store principal conserve une transaction Solana source-indépendante par signature. Les sources HTTP, WebSocket Helius et Yellowstone gRPC ne doivent pas produire plusieurs copies complètes du même contenu.
```text
source provider
-> normalisation canonique
-> transaction unique
-> observations multiples
```
## Table `kb_sol_raw_transactions`
Rôle : stocker la représentation canonique rejouable de la transaction et de ses metadata.
Colonnes principales visées :
| Colonne | Rôle |
|----------------------------|-----------------------------------------|
| `id` | clé primaire technique |
| `signature` | signature Solana unique |
| `slot` | slot de la transaction |
| `canonical_format_version` | version du contrat canonique |
| `canonical_json` | transaction et metadata normalisées |
| `canonical_json_hash` | hash déterministe du document canonique |
| `retention_state` | état de rétention |
| `processing_state` | état dextraction et de traitement |
| `lifecycle_reason` | raison technique optionnelle |
| `created_at` | première insertion |
| `updated_at` | dernière évolution autorisée |
Le contenu canonique ne contient pas de nom de fournisseur, endpoint, subscription id ou format de transport.
`kb_model::CanonicalTransaction` fournit la sérialisation déterministe et le hash SHA-256. `kb_store_core::RawTransactionInsert::from_canonical` construit le DTO de persistance avec la signature primaire, le slot, `canonical_format_version`, `canonical_json` et `canonical_json_hash`. Le transport RPC ne dépend donc pas du backend PostgreSQL.
## Table `kb_sol_obs_transaction_observations`
Rôle : enregistrer chaque détection ou acquisition dune signature sans recopier le payload complet.
Colonnes principales visées :
| Colonne | Rôle |
|-----------------------|-------------------------------------------------------|
| `id` | clé primaire technique |
| `observation_key` | clé idempotente de lobservation |
| `raw_transaction_id` | lien optionnel vers `kb_sol_raw_transactions` |
| `signature` | signature détectée ou reçue |
| `slot` | slot quand connu |
| `provider` | fournisseur |
| `endpoint_code` | endpoint de configuration |
| `protocol` | protocole de transport |
| `acquisition_method` | méthode ou type de stream |
| `origin` | `live`, `backfill`, `replay`, `repair` ou `migration` |
| `commitment` | commitment demandé ou reçu |
| `capture_session_id` | session de mesure ou dingestion |
| `filter_code` | filtre logique utilisé |
| `detected_at` | premier signal reçu |
| `received_at` | transaction complète reçue |
| `normalized_at` | fin de normalisation |
| `persisted_at` | fin de persistance |
| `payload_size_bytes` | taille du message source |
| `source_payload_hash` | hash optionnel du message source |
| `status` | résultat technique |
| `error_code` | erreur normalisée optionnelle |
| `error_message` | message de diagnostic optionnel |
Cette table ne possède pas de `raw_json`, de `canonical_json` ni de payload Protobuf complet.
## Notifications WebSocket
`kb_sol_raw_ws_notifications` nest plus conservée comme cible durable.
Pour `logsSubscribe` :
1. recevoir la signature et le slot ;
2. mémoriser temporairement le timestamp de détection ;
3. hydrater par `getTransaction` si nécessaire ;
4. écrire la transaction canonique ;
5. écrire une observation avec `detected_at`, `received_at` et le statut dhydratation.
Les payloads complets de notifications peuvent être exportés temporairement pour un benchmark borné, mais ils ne doivent pas être dupliqués en PostgreSQL.
## Fusion par signature
La signature est la clé dunicité de la transaction canonique.
- hash identique : conserver la ligne et ajouter une observation ;
- metadata plus complètes : appliquer un enrichissement déterministe ;
- différence incompatible : enregistrer un conflit et ne pas écraser silencieusement ;
- transaction absente ou erreur provider : écrire uniquement lobservation technique.
## Cycle de vie
Les états de rétention de la transaction canonique restent :
```text
full
compacted
archived
purged
```
Les états de traitement restent :
```text
received
core_extracted
decoded
materialized
failed
```
Les observations sont append-only et suivent une rétention technique distincte.
## Baseline SQL active
Après validation de la transition historique, le dossier `kb_store_pg/migrations/` a été consolidé :
```text
0001_canonical_transaction_store.sql
0002_core_store.sql
```
La baseline ne contient que les tables et colonnes actives. Les anciens noms RPC/WS ne sont plus recréés. Le DDL runtime conserve temporairement un chemin de compatibilité idempotent pour les workspaces encore issus de `pre.001`.

View File

@@ -1,80 +0,0 @@
<!-- file: docs/REPLAY_PIPELINE.md -->
<!-- version: 3 -->
# Pipeline de replay
Le replay ne doit pas être global par défaut. Chaque campagne reçoit un `campaign_id` et cible un ensemble explicite de processors, une version et un périmètre borné dinputs.
## Étapes
```text
ingest -> extract -> observe -> decode -> materialize -> aggregate -> validate
```
Chaque étape doit être rejouable séparément avec son propre ledger versionné.
## Sélection de décodage
La sélection opérateur peut utiliser :
- des signatures ;
- une plage de slots ;
- des `program_id` ;
- des instruction paths ;
- des états lifecycle ;
- une limite stricte.
Le pipeline calcule ensuite `effective_program_ids` comme lunion des programmes déclarés par les décodeurs activés. Sans filtre program ID explicite, cette union est appliquée automatiquement au store. Avec un filtre explicite, chaque valeur doit être supportée par au moins un décodeur activé, sinon la campagne est refusée avant la requête SQL.
Cette règle évite quun classifieur natif sélectionne des instructions SPL, Jupiter, Pump ou dautres programmes non compatibles. Elle empêche également la resélection infinie dun lot entièrement `unmatched` uniquement parce que les processors choisis ne couvrent pas ses programmes.
## Force replay
Le force replay contourne le skip processor/version/input/hash, mais reste borné par une liste de signatures explicites ou par une autorisation opérateur « toutes les signatures » combinée aux autres filtres et à la limite. Une requête sans lun de ces deux scopes est refusée.
Lorsquune campagne contient des signatures explicites, `force_replay=true` retire le filtre lifecycle pour ces signatures. Les inputs déjà terminaux peuvent alors être réellement rejoués. Le mode explicite « toutes les signatures » retire également ce filtre, mais conserve obligatoirement le scope des programmes compatibles, les slots et instruction paths éventuels ainsi que la limite. Sans signatures ni autorisation « toutes les signatures », la requête est refusée.
Le remplacement ne touche que les sorties du processor, de la version et de linput ciblés. Les autres processors et les autres versions restent intacts.
## Skip
Sans force replay, un input est skippé uniquement lorsque le ledger contient un succès ayant exactement :
```text
stage
processor_name
processor_version
input_key
input_hash
```
Une campagne de validation doit pouvoir montrer successivement :
```text
premier passage -> decoded/ignored/unsupported
second passage -> skipped
force replay -> exécution sans skip
passage suivant -> skipped
```
## Unmatched
`unmatched` signifie quaucun décodeur compatible na accepté linput après le filtre exact de programme. Linstruction nest pas marquée globalement comme définitivement ignorée, car un futur processor peut la supporter. Les décodeurs doivent classer comme `unsupported` les instructions inconnues de leurs propres programmes afin de produire une couverture exploitable.
## Traçabilité
Les logs de campagne conservent :
```text
campaign_id
signature_count
signature_sample
decoder_names
requested_program_ids
effective_program_ids
requested_processing_states
effective_processing_states
force_replay
```
Les logs par input conservent ensuite la signature exacte, le path, le programme, le processor, le hash et la décision terminale.

View File

@@ -1,77 +0,0 @@
<!-- file: docs/RPC_ENDPOINT_ROLES.md -->
<!-- version: 4 -->
# Rôles des endpoints RPC et streams
Les rôles servent à sélectionner un endpoint selon lopération, le provider, le protocole et les limites locales.
## Rôles HTTP actifs
| Rôle | Usage |
|---------------------|-----------------------------------------------------------------|
| `http_queries` | lectures courantes |
| `history_backfill` | `getSignaturesForAddress`, `getTransaction` et backfills ciblés |
| `http_transactions` | simulation, envoi et confirmation |
| `http_fallback` | endpoint de secours |
| `http_heavy` | appels lourds |
`0.3.x` utilise principalement `history_backfill` avec les comptes gratuits.
## Rôles WebSocket standard existants
| Rôle | Usage |
|-------------------------|-------------------------------|
| `slot_notifications` | progression et santé du flux |
| `logs_subscribe` | logs ciblés |
| `program_subscribe` | comptes détenus par programme |
| `account_subscribe` | comptes précis |
| `program_logs` | compatibilité historique |
| `account_notifications` | compatibilité historique |
## Rôles futurs `0.10.x`
| Rôle | Usage |
|----------------------------------|-----------------------------------------------|
| `helius_transaction_stream` | extension Helius `transactionSubscribe` |
| `yellowstone_transaction_stream` | filtre transactions Yellowstone gRPC |
| `logs_all_probe` | comparaison temporaire `logsSubscribe("all")` |
| `realtime_transaction_hydration` | hydratation HTTP et réparation |
Les transports Helius et Yellowstone restent implémentés dans `kb_onchain_transport`. Les rôles ne créent pas de dépendance provider dans les décodeurs.
## Request kinds actifs pour le backfill
```text
get_signatures_for_address
get_transaction
get_signature_statuses
get_slot
get_version
```
## Request kinds futurs
```text
transaction_subscribe
transaction_unsubscribe
yellowstone_transaction_subscribe
logs_subscribe_all
logs_unsubscribe
```
## Limites par rôle
```text
requests_per_second
burst_capacity
max_concurrent_requests
max_subscriptions
pause_after_rate_limit_ms
```
Pour les streams gRPC, la configuration future ajoutera les limites de streams, filtres, adresses et taille de queue sans casser les rôles HTTP/WS existants.
## Preuve runtime
Un rôle ou un plan configuré ne garantit pas la capacité distante. La réponse du provider reste la preuve runtime. Les refus de plan, filtres invalides et limitations doivent être normalisés comme erreurs de `kb_onchain_transport`.

View File

@@ -1,85 +0,0 @@
<!-- file: docs/RUST_WORKSPACE_RULE_AUDIT.md -->
<!-- version: 2 -->
# Audit des règles Rust du workspace
Lentrée unique est :
```bash
python3 scripts/audit_rust_workspace_rules.py
```
Elle exécute trois contrôles obligatoires :
1. `audit_rust_general_rules.py` pour les règles Rust réutilisables ;
2. `audit_rust_export_completeness.py` pour la fermeture des façades ;
3. `audit_khadhroony_workspace_rules.py` pour les contrats propres au projet.
## Façades et réexports
Tous les modules sont privés avec `mod`. Une API de crate est formée uniquement par des
réexports explicites depuis `lib.rs` ou `main.rs`.
Les réexports dun module interne utilisent `self::`, ne sont jamais groupés, ne changent
jamais le nom du symbole avec `as` et possèdent une rustdoc adjacente. Un bloc homogène de
`pub use` ou `pub(crate) use` ne contient aucune ligne vide.
Laudit de complétude suit les réexports transitifs à travers les façades privées. Il vérifie
donc quun type déclaré dans un sous-module atteint réellement la racine de sa crate sans
exiger un faux accès public au module qui le contient. Les constantes de suivi des scaffolds
de migration restent internes à leur inventaire et ne font pas partie de lAPI publique.
## Nomenclature de `kb-lib`
| Famille | Constante | Type ou trait | Fonction libre |
|---------------|-----------|---------------|-----------------|
| Décodeur | `DC_` | `Dc` | `decoder_` |
| Matérialiseur | `MT_` | `Mt` | `materializer_` |
| Exécuteur | `EX_` | `Ex` | `executor_` |
| Modèle | `MD_` | `Md` | `model_` |
Les méthodes inhérentes et les helpers strictement privés ne sont pas soumis à un préfixe
global. Les symboles `pub` et `pub(crate)` le sont, car ils peuvent entrer en collision après
la fusion des anciennes crates dans `kb-lib`.
Les 98 frontières de décodeurs encore en attente utilisent des constantes uniques
`DC_<FAMILLE>_<SURFACE>_LEGACY_CRATE` et
`DC_<FAMILLE>_<SURFACE>_MIGRATION_STATUS`. Elles sont référencées par un inventaire interne
pour que `cargo check` ne produise pas davertissements de code mort.
## Tracing
Une crate opérationnelle autonome garde un unique `TRACING_TARGET` dans `constants.rs` et le
réexporte avec :
```rust
pub(crate) use self::constants::TRACING_TARGET;
```
Un composant opérationnel de `kb-lib` utilise un nom préfixé, par exemple
`TRACING_TARGET_DECODER_SPL_TOKEN2022` ou `TRACING_TARGET_MATERIALIZER_TOKEN_ACCOUNTS`, réexporté
transitivement jusquà `kb-lib/src/lib.rs`. Sa valeur suit exactement le chemin hiérarchique
du composant, par exemple `kb-lib.decoder.spl.token2022`.
## Validation
Laudit strict exige le `Cargo.lock` versionné de lapplication et vérifie exclusivement :
```text
wincode 0.5.5
solana-wincode-varint 1.0.0
```
Une livraison sans `Cargo.lock` peut contrôler le reste avec `--report-only`, mais elle ne
doit pas annoncer laudit strict comme propre tant que le lock réel na pas été utilisé.
La fermeture dune tranche demande ensuite :
```bash
cargo fmt --all
python3 scripts/audit_rust_workspace_rules.py
cargo check --workspace
cargo test --workspace
cargo clippy --workspace --all-targets
```

View File

@@ -1,303 +0,0 @@
<!-- file: docs/SOLANA_INTERFACE_DEPENDENCIES.md -->
<!-- version: 32 -->
# Dépendances dinterfaces Solana et SPL
## Objectif
Le workspace privilégie les interfaces officielles étroites afin déviter de recopier des enums, layouts, IDs ou builders déjà publiés par Solana ou SPL. Les dépendances de `[workspace.dependencies]` constituent un catalogue de versions cohérentes ; elles ne sont pas automatiquement ajoutées à toutes les crates.
## Règle de consommation
Une crate ajoute une interface uniquement lorsquelle utilise réellement au moins un de ses éléments :
- enum dinstruction ou détat ;
- encodeur/décodeur officiel ;
- type de compte ou paramètre ;
- program ID ou sysvar ID ;
- modèle RPC appartenant à sa responsabilité.
Une déclaration à la racine ne justifie pas une dépendance inutilisée dans une crate feuille. Les features restent minimales et explicites.
## Ordre des formats
1. `wincode` lorsquil est officiellement exposé par linterface ;
2. Borsh lorsquil correspond au contrat officiel ou au comportement du runtime ;
3. parseur local borné lorsque linterface officielle ne fournit son helper quavec `bincode`.
### Compatibilité de version `wincode`
Le workspace reste épinglé sur `wincode ^0.5`. Les crates Solana modulaires actuellement utilisées avec la feature `wincode` publient leurs implémentations `SchemaRead`/`SchemaWrite` contre `wincode 0.5.x`. Ces traits sont nominalement distincts de ceux de `wincode 0.6.x` : une dépendance directe migrée seule vers `0.6` ne peut donc ni désérialiser `solana_nonce::versions::Versions`, ni sérialiser `solana_transaction::Transaction`. Cargo peut charger les deux versions simultanément, mais les implémentations de traits ne sont pas interchangeables et lorphan rule interdit de les réimplémenter localement pour ces types externes.
Le catalogue `[workspace.dependencies]` ne gouverne que les dépendances réellement consommées par
les crates membres ; il ne peut pas contraindre à lui seul une branche transitive compatible avec
plusieurs versions. Ajouter `solana-wincode-varint` comme dépendance inutilisée de `kb-lib` serait
contraire aux règles du workspace. Comme bot3 est un workspace applicatif, son `Cargo.lock`
versionné constitue le verrou reproductible de cette branche : il doit résoudre exactement
`solana-wincode-varint 1.0.0` et `wincode 0.5.5`. Laudit
`scripts/audit_khadhroony_workspace_rules.py` vérifie le manifeste et ces deux versions avant les
contrôles Cargo.
La migration vers `wincode 0.6` doit attendre que lensemble des crates Solana consommées migre de façon cohérente. Une double dépendance aliasée nest acceptable que pour des types propres au workspace ; tous les appels portant sur des types Solana doivent utiliser la même version `0.5.x` que celle employée par leurs crates dorigine. Avant toute migration, vérifier avec `cargo tree -d` et `cargo tree -i wincode@<version>`.
Le workspace najoute pas de dépendance directe à `bincode`. Une feature officielle `bincode` seule nest pas activée pour contourner cette règle.
## Interfaces utilisées dans `kb_decoder_solana_core`
| Surface | Interface | Features utiles | Stratégie actuelle |
|---------------------------|---------------------------------------------------|----------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------|
| Address Lookup Table | `solana-address-lookup-table-interface ^3.1` | `serde`, `wincode` | enum officielle et `wincode` exact |
| Compute Budget | `solana-compute-budget-interface ^3.0` | `borsh`, `serde` | enum officielle pour les fixtures ; parser borné aligné sur le Borsh unchecked du runtime |
| System Program | `solana-system-interface ^3.2` | `alloc`, `serde`, `std`, `solana-instruction`, `wincode` | enum officielle et `wincode` |
| Vote Program | `solana-vote-interface ^6.0` | `serde`, `wincode` | enum officielle et `wincode::deserialize_exact` |
| Stake Program | `solana-stake-interface ^4.3` | `borsh`, `serde`, `wincode` | types/ID officiels + miroir wire privé `wincode` exact, compatible avec le layout historique |
| Précompiles signature | sources runtime Agave et crates programme `3.0.0` | aucune nouvelle dépendance consommée | parseurs locaux bornés des tables doffsets, résolution outer via contrat core `2`, sans cryptographie ni `bincode` |
| ZK ElGamal Proof | `solana-zk-elgamal-proof-interface ^0.1` | aucune feature additionnelle | enum `ProofInstruction` et tailles `Pod` officielles ; comportement des comptes vérifié contre le runtime Agave |
| ZK Token Proof historique | aucune dépendance runtime dédiée | miroir wire local borné | tags et tailles historiques audités contre `solana-zk-token-sdk 3.1.14`; comparaison Agave `v2.0.0`/`v4.1.1` |
| Slashing Program | Agave `v4.1.1`, `solana-program/slashing@fe8da3a` | aucune dépendance ajoutée | parseur local borné du contrat release vérifié ; compte de preuve externe non relu et aucune cryptographie locale |
## Décision pour les précompiles de signature
Les crates officielles Ed25519, secp256k1 et secp256r1 exposent les IDs, constantes et structures de layout, mais `kb_program_ids` centralise déjà les IDs et le delta nexécute aucune vérification cryptographique. Ajouter ces dépendances uniquement pour recopier des tailles ou des structures `Pod` constituerait une dépendance sans consommation fonctionnelle.
`kb_decoder_solana_core` reproduit les layouts exacts depuis les sources runtime Agave : table Ed25519/secp256r1 de 14 octets, table secp256k1 de 11 octets, sentinelle `u16::MAX` uniquement pour Ed25519/secp256r1, index `u8` toujours explicite pour secp256k1, règles zéro signature et limite secp256r1. Les fixtures manuelles rendent chaque offset visible et les tests couvrent les références inter-instructions et les bornes. Aucune dépendance `bincode` nest ajoutée.
## Transaction client dans `kb-lib::executor::solana::transaction`
`kb-lib::executor::solana::transaction` nimporte plus lagrégat `solana-sdk`. Sa frontière transactionnelle utilise les crates modulaires réellement consommées : `solana-instruction`, `solana-message`, `solana-transaction`, `solana-hash`, `solana-pubkey`, `solana-keypair`, `solana-signer`, `solana-nonce` et `solana-system-interface`. Les exécuteurs spécifiques conservent la même politique et ajoutent uniquement linterface de programme nécessaire.
Le message à signer provient de `solana_transaction::Transaction::message_data()`. La transaction complète utilise `wincode::serialize`, supporté officiellement par les types modulaires `Message` et `Transaction`. Cette stratégie remplace tout appel direct à `bincode` et reproduit le wire attendu par `getFeeForMessage`, `simulateTransaction` et `sendTransaction`. La taille sérialisée est refusée au-delà de 1 232 octets.
## Identifiants natifs, Vote et loaders dans lexécuteur
`solana-sdk-ids` est conservé intentionnellement comme registre officiel modulaire des adresses natives et sysvars. Les chemins `solana_sdk_ids::sysvar::{clock,rent,slot_hashes,instructions}` ne constituent pas un retour au SDK monolithique : ils fournissent uniquement des `MdPubkey` canoniques. `solana-instructions-sysvar` ne doit être ajouté que lorsquune crate appelle réellement ses fonctions dintrospection dinstructions, pas pour remplacer un simple ID officiel.
`kb_executor_solana_core` consomme `solana-vote-interface ^6.0` avec `serde` et `wincode` pour construire les vingt variantes wire Vote actuelles. Il utilise `solana-instruction` pour `Instruction`/`AccountMeta`, `solana-pubkey::Pubkey` pour les adresses publiques, `solana-hash::Hash` pour les hashes et `solana-sdk-ids` pour Rent, Clock et SlotHashes. Les quatre créations composées utilisent `solana-system-interface`; aucune dépendance `solana-sdk` ni feature `bincode` nest ajoutée à la crate.
`kb_decoder_solana_core` et `kb_executor_solana_core` consomment désormais `solana-loader-v3-interface ^8.0` avec `wincode`. Le décodeur désérialise lenum officielle de façon exacte tout en conservant la compatibilité du booléen optionnel historique des dernières variantes. Lexécuteur appelle les helpers officiels pour onze plans : création de buffer, écriture, déploiement, upgrade, changements dautorité, fermetures et extension.
`solana-loader-v4-interface ^3.1` publie lenum et les comptes officiels, mais ses helpers de construction sont conditionnés par la feature `bincode` et lenum ne fournit pas de schéma `wincode`. Pour respecter linterdiction de `bincode`, `kb_executor_solana_core` reproduit localement le wire borné des sept discriminants (`u32 LE`, champs numériques et vecteur borné) et les métadonnées de comptes exactes pour neuf plans. La crate feuille najoute donc pas une dépendance inutilisée à linterface v4; le catalogue workspace la conserve comme source normative/versionnée.
## Interfaces officielles non encore consommées
| Interface | Propriétaire futur | Décision |
|--------------------------------------|------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------|
| `solana-feature-gate-interface ^4.0` | `kb_decoder_solana_core` | peut fournir les types officiels ; linstruction actuelle reste un tag dun octet vérifié depuis le builder/processor |
| `solana-feature-set-interface ^4.0` | classification/diagnostics natifs | ajouter seulement lorsquun type est consommé |
| `solana-loader-v4-interface ^3.1` | source normative Loader v4 | helpers officiels conditionnés par `bincode`; conserver le miroir wire local borné tant quaucun schéma `wincode` nest publié |
| interfaces SPL | crates `kb_decoder_spl_*` et `kb_executor_spl_*` correspondantes | ne pas les rattacher au décodeur natif ni à lapplication |
| types RPC/account/transaction status | `kb_onchain_transport` | ne pas les ajouter à `kb_app_demo` ; lapplication consomme les DTO du workspace |
## Exceptions locales actuelles
### SPL Memo v1, v3 et v4
`kb_decoder_spl_memo` et `kb_executor_spl_memo` consomment `spl-memo-interface ^2.1` sans feature additionnelle. La version effectivement résolue pendant les validations est 2.1.0. Elle publie les trois IDs exacts et un builder générique recevant explicitement le Program ID. Ce builder place les octets exacts du message dans `Instruction::data` et transforme chaque pubkey fournie en compte readonly signer, sans sérialisation intermédiaire.
Lexécuteur appelle ce builder pour les trois générations et compare chaque plan au résultat officiel. Les différences runtime restent explicites : v1 ignore les comptes, v3/v4 les vérifient. La bibliothèque ne lie toutefois aucune génération à un cluster ou au dry-run : la simulation obligatoire établit la disponibilité effective du Program ID ciblé, puis les politiques communes gouvernent lautorisation denvoi et Mainnet. La démo du jalon retient séparément v4 sur Devnet. La taille packet finale reste contrôlée par `kb-lib::executor::solana::transaction` après compilation du message.
Le décodeur ne dépend pas du builder pour lire le wire : il analyse directement les octets base64 retenus par le core, avec une borne de 4 096 octets, puis valide lUTF8. La source historique v1 prouve que les comptes sont ignorés ; les processors v3/v4 exigent au contraire que chaque compte fourni soit signer avant de valider lUTF8. Ces règles restent séparées dans `docs/SPL_MEMO_MATRIX.json` et les tests comparent les trois IDs locaux aux constantes de linterface officielle.
Larchive source `0.4.2` ne contenait pas de `Cargo.lock`. Les compilations et validations `0.4.3` ont résolu `spl-memo-interface 2.1.0`, sans mise à jour automatique de la contrainte workspace. Cette version exacte a construit les trois générations et le parcours v4 Devnet réel.
### SPL Token classique
Le catalogue workspace déclare `spl-token-interface ^3.0` sans feature. Le tag officiel
`interface@v3.0.0` publie la version `3.0.0`, sans feature optionnelle ni dépendance à `bincode`.
`kb_decoder_spl_token` consomme l'ID officiel et utilise `TokenInstruction::unpack` dans les tests
différentiels. Le wire de production reste un parseur local borné afin de conserver les tailles
consommées, les suffixes acceptés par les processors, les diagnostics UTF-8 et la structure interne
de `Batch`, que l'enum officielle représente seulement par son tag parent.
La surface compte 28 tags : `0..24`, `38` (`WithdrawExcessLamports`), `45`
(`UnwrapLamports`) et `255` (`Batch`). L'interface `3.0.0` fournit un builder pour chacun. La source
historique `program/src/processor.rs` ne suffit toutefois pas à prouver les deux nouveaux tags : le
processor p-token `1.0.0` sous le même Program ID implémente explicitement `UnwrapLamports` et
`Batch`. La publication de l'interface, la constructibilité, le binaire déployé par cluster et le
résultat de simulation restent quatre preuves séparées dans `docs/SPL_TOKEN_MATRIX.json`.
Le processor p-token lit les champs numériques avec des contrôles de longueur minimale et peut
donc ignorer des octets suffixes selon l'opération. Le décodeur les conserve et les signale au lieu
de les accepter silencieusement. `Batch` est découpé selon les paires `account_count/data_len`,
interdit les données enfant vides et appelle uniquement le processor interne, ce qui rend un batch
imbriqué invalide. Le décodeur ajoute des bornes défensives de 64 enfants, 512 comptes cumulés et
16 384 octets par instruction.
La résolution `3.0.0` et les tests différentiels du décodeur ont été confirmés dans le workspace le
15 juillet 2026. `kb_executor_spl_token` consomme les builders officiels de cette même interface.
Les variantes `InitializeMint`, `InitializeAccount`, `InitializeMultisig` et `InitializeAccount2`
restent decode-only dans la politique d'exécution ; les opérations anciennes toujours publiées et
utilisables, comme `Transfer` ou `SetAuthority`, ne sont pas confondues avec des opérations
obsolètes.
Les signatures officielles de `unwrap_lamports` et `batch` ont été auditées au commit `46eaacd`.
Leur constructibilité est donc prouvée. Leur déploiement sur le programme classique Devnet a été
observé le 16 juillet 2026 par deux simulations sans signature ni envoi : `Batch` avec un enfant
`TransferChecked` de montant nul a réussi en 270 compute units, puis `UnwrapLamports` d'un lamport
depuis un compte wrapped SOL auxiliaire classique a réussi en 140 compute units. Localnet, Testnet
et Mainnet restent des preuves séparées. L'exécuteur ne bloque aucun cluster et laisse
l'autorisation d'envoi aux politiques communes.
Sur Devnet, le programme classique a également confirmé un `TransferChecked` complet et un
lifecycle sans ATA couvrant `InitializeAccount3`, `MintToChecked`, `TransferChecked`,
`ApproveChecked`, `Revoke`, `BurnChecked` et `CloseAccount`. Sur Mainnet, un corpus canonique de 370
instructions a été décodé et matérialisé sans entrée unsupported, failed ou unmatched. Localnet n'a
pas été exercé. La matrice conserve donc indépendamment la version d'interface, le processor de
référence, le builder, les observations réelles et le résultat de simulation/soumission par
instruction.
### SPL Associated Token Account
Le catalogue workspace déclare `spl-associated-token-account-interface ^2.0` avec la feature
`borsh`. Cargo a résolu la version `2.0.0` pendant le jalon bot2 `0.4.5`. Depuis bot3
`0.1.0-pre.007`, `kb-lib::decoder::spl::associated_token_account` consomme réellement le Program
ID et le helper officiel de dérivation en production, puis l'enum et les builders dans ses tests
différentiels. L'ancien exécuteur n'est pas encore porté ; le pipeline et la démo restent donc hors
de cette tranche.
L'interface publie exactement trois variantes Borsh actuelles : `Create` (`0`),
`CreateIdempotent` (`1`) et `RecoverNested` (`2`). Le processor accepte aussi historiquement une
donnée vide comme `Create`; cette forme reste décodable mais n'est pas produite par le builder
actuel. La dérivation canonique utilise les seeds `[wallet, Token Program ID, mint]` sous le Program
ID ATA. Le Token Program fait donc partie de l'adresse et distingue nécessairement les ATA
classiques des ATA Token-2022 d'un même wallet et mint.
Le décodeur conserve les comptes, flags, doublons, chemins outer/inner, transactions échouées,
adresses observées et dérivées, ainsi que les rôles distincts de `RecoverNested`. Les tests
différentiels comparent les trois builders et les vecteurs PDA au helper officiel. Dans bot2,
l'exécuteur validé utilisait les mêmes builders pour les trois variantes, imposait simulation et
dry-run par défaut, puis laissait au pipeline stateful les contrôles de mint, owner, compte
existant, rent, signataires et postconditions. Cette capacité reste une preuve de référence tant
que les modules exécuteur et pipeline correspondants ne sont pas portés dans bot3.
Les preuves Devnet du 16 juillet 2026 couvrent `CreateIdempotent` pour SPL Token classique et
Token-2022, y compris création, réutilisation, replay post-exécution idempotent et ATA Token-2022
avec extension `ImmutableOwner`. Elles couvrent aussi un `RecoverNested` classique contrôlé : le
solde brut a été transféré vers l'ATA wallet, le compte nested a été fermé et les deux faits
lifecycle/risk ont été matérialisés sans dupliquer les CPI SPL Token. Le décodage général des
instructions et extensions Token-2022 reste réservé à `0.4.6`.
### Token-2022 — audit initial `0.4.6-pre.001`
Le catalogue workspace déclare `spl-token-2022-interface ^3.1` avec `serde` et
`spl-elgamal-registry-interface ^0.2` sans feature additionnelle. La résolution opérateur confirme
respectivement `3.1.1` avec `default + serde` et `0.2.1` avec `default`. Dans bot3, `kb-lib`
les consomme comme dépendances de développement pour les tests différentiels ; le code de
production utilise les parseurs locaux bornés déjà prouvés contre ces interfaces. La matrice
inventorie 48 tags de premier niveau et 29 types TLV de production, dont le récent
`PermissionedBurnExtension` `46` et son TLV
`PermissionedBurn` `28`.
Les sous-discriminants, comptes, layouts, tailles, builders et processors restent explicitement
`pending`. L'interface ElGamal `0.2.1` confirme le Program ID
`regVYJW7tcT8zipN5YiBvHsvR5jXW1uLFxaHSbugABg` et la seed PDA `elgamal-registry`. Le registre
garde toutefois une matrice, un dispatch et une politique d'exécution séparés du programme natif
ZK ElGamal Proof. Les TLV Token Metadata/Token Group et les pointeurs Transfer Hook ne donnent
aucun Program ID universel aux programmes externes qui implémentent ces interfaces.
L'interface Token-2022 `3.1.1` publie le commit exact
`e18f9c6f9bf6044b934f48e3090e8e59e4820f02` (`interface@v3.1.1`). Au même commit, le processor
porte la version `11.0.0` et son lock source résout Token Group `0.7.2`, Token Metadata `1.0.0` et
le registre ElGamal `0.2.1`. Son dispatch tente d'abord les 48 tags Token-2022, puis les cinq
discriminants Token Metadata et les quatre discriminants Token Group. Cette incorporation ne donne
pas de Program ID universel aux interfaces : elle décrit seulement leur exécution directe par
Token-2022. L'égalité avec les binaires cluster reste à prouver séparément.
Le `Cargo.lock` opérateur confirme le graphe réellement consommé par l'interface `3.1.1` : ZK
ElGamal Proof `0.1.3`, extraction de preuve confidentielle `0.6.1`, Token Group `0.7.2`, Token
Metadata `1.0.1` et TLV `0.9.1`. Token Metadata apparaît directement sous
`spl-token-2022-interface` dans `cargo tree -p ... -e features`. Le processor source `11.0.0`
audité figeait encore Token Metadata `1.0.0`. La publication officielle `1.0.1` ne change ni wire,
ni discriminant, ni builder : elle ajoute seulement, avant Borsh, une validation bornée des
longueurs de chaînes de `Initialize`, `UpdateField` et `RemoveKey`. Cette garde plus sûre devient
normative pour le décodeur ; `UpdateAuthority` et `Emit` restent sans chaîne.
La migration `0.1.0-pre.008` conserve ces contrats dans le type public
`kb_lib::DcSplToken2022Decoder` et isole le registre dans
`kb_lib::DcSplElgamalRegistryDecoder`. Les targets de tracing, matrices et Program IDs restent
distincts ; aucun pointeur TLV nest interprété comme une preuve de létat du programme externe
pointé.
### ZK ElGamal Proof
`kb_decoder_solana_core` consomme directement `solana-zk-elgamal-proof-interface ^0.1`. Lenum `ProofInstruction` fournit les treize discriminants et les types de `proof_data` fournissent les tailles `Pod` exactes pour séparer le contexte du corps de preuve inline. Le runtime Agave reste la source normative pour la sélection entre preuve inline et preuve stockée dans un compte, les positions de comptes optionnels et lacceptation des octets suffixes de `CloseContextState`.
Aucune dépendance à `bytemuck` nest ajoutée directement : le décodeur ne convertit pas les octets en preuve cryptographique et nappelle aucun vérificateur. Il utilise uniquement `size_of` sur les types officiels, puis conserve longueur, SHA-256 et préfixe borné. Le contenu dun compte de preuve externe nest pas récupéré par RPC pendant un replay historique.
### ZK Token Proof historique
`kb_decoder_solana_core` ne dépend plus de `solana-zk-token-sdk`. Cette crate historique est dépréciée et entraînait `bincode` transitivement. Le workspace conserve une table wire locale limitée aux tags `0..16`, aux tailles exactes de contexte/preuve et à loffset `u32 LE`, auditée contre la version historique `3.1.14`; aucun code de preuve ni sérialiseur historique nest recopié.
Le comportement est documenté depuis deux références runtime distinctes : Agave `v2.0.0` pour le vérificateur historique et Agave `v4.1.1` pour le stub actuel sans effet. Aucun corpus mainnet nayant été observé, les tests sont synthétiques et nexigent pas de backfill.
### Stake Program
`solana-stake-interface 4.3.1` publie `StakeInstruction` avec Serde et conserve ses builders derrière la feature `bincode`. La feature `wincode` fournit les schémas nécessaires aux types détat, mais pas directement à lenum dinstruction. Le décodeur et lexécuteur consomment donc lID et les types sémantiques officiels, avec un miroir wire privé commun dans son ordre de variantes et de champs. Aucun helper `bincode` nest activé.
Lexécuteur reproduit les vingt-quatre helpers clients actuels : initialize/create, checked/seed, split/merge, create-and-delegate, quatre authorize, delegate, withdraw, deactivate, lockup, minimum delegation, delinquent deactivation et move. Les helpers `redelegate` et `redelegate_with_seed` sont explicitement exclus parce que la source officielle les marque dépréciés et « will not be enabled » ; ils restent uniquement dans le miroir historique du décodeur.
Le contrat des comptes est aligné sur les builders officiels. Les contrôles stateful du processor BPF — état de compte, rent, epochs, compatibilité et autorités courantes — restent à lorchestration localnet/devnet.
### Config Program
`solana-config-interface 2.x` expose son module dinstruction derrière sa feature `bincode`. Le décodeur et lexécuteur conservent donc un wire local borné pour `ConfigKeys` : compact-u16 canonique, booléens stricts, ordre exact des signataires, rejet des doublons et payload métier opaque. Le builder de création reproduit la taille `max_config_space + serialized_size(ConfigKeys)` et linitialisation `ConfigKeys vide + T::default()` à partir doctets déjà sérialisés ; il nactive aucun helper `bincode`.
### BPF Loader v2
`solana-loader-v2-interface 3.x` publie ses helpers dinstruction derrière `bincode`. Le décodeur conserve le layout local vérifié tant quaucun schéma officiel `wincode` nest disponible.
### Feature Gate
`solana-feature-gate-interface 4.x` publie la séquence dactivation `transfer -> allocate -> assign` et `RevokePendingActivation`, mais les helpers restent derrière sa feature `bincode`. Lexécuteur utilise `Feature::size_of()` et reproduit ces instructions à partir des interfaces System étroites ; la révocation reste exactement `vec![0]` avec feature, incinerator et System Program dans lordre officiel.
### Slashing Program
La source normative est SIMD-0204 et le contrat du programme Slashing publié : deux instructions, un payload DuplicateBlockProof de 305 octets, un report PDA dérivé de `node_pubkey + slot LE + type`, et une instruction Ed25519 précédente dont les offsets pointent vers le payload Slashing. Aucune crate de sérialisation générale nest nécessaire. Lexécuteur construit le plan atomique et laisse au pipeline stateful le compte de preuve, le rent et les fenêtres epoch.
### ZK ElGamal Proof dans lexécuteur
`kb_executor_solana_core` dépend directement de `solana-zk-elgamal-proof-interface ^0.1` pour les types POD et leurs tailles. Les layouts dinstruction sont simples et officiels : discriminant + preuve inline, ou discriminant + offset `u32 LE`; les comptes de contexte suivent `ContextStateInfo`. La fermeture reproduit le builder officiel. Aucune vérification cryptographique nest recalculée côté client.
### Loaders v3 et v4
La migration Loader v3 est terminée dans `pre.020` : le décodeur utilise `wincode::deserialize_exact<UpgradeableLoaderInstruction>` et lexécuteur utilise les helpers officiels de `solana-loader-v3-interface 8.x`. Les payloads tronqués, suffixés, les longueurs et les contrats de comptes restent bornés par les tests.
Loader v4 conserve un parser et un constructeur locaux limités aux sept discriminants publiés. Le layout est suffisamment petit pour être audité explicitement : tag `u32 LE`, `Write { offset, Vec<u8> }`, `Copy { destination_offset, source_offset, length }`, `SetProgramLength { new_size }` et quatre variantes unitaires. Cette exception évite dactiver `bincode` uniquement pour appeler les helpers de linterface.
## `solana-sdk`
`solana-sdk` avec la feature `full` peut rester disponible au niveau workspace pour les applications ou outils qui ont réellement besoin de lagrégat complet. Les crates feuille doivent préférer les interfaces étroites afin de réduire les features transitives, les temps de compilation et les risques de dépendances inutilisées.
## Vérification avant ajout
Pour chaque nouvelle interface :
1. lire ses features et ses modules réellement compilés ;
2. identifier le format officiel de sérialisation ;
3. confirmer la version compatible avec Agave ciblée ;
4. ajouter la dépendance uniquement à la crate propriétaire ;
5. créer une fixture depuis lencodeur officiel lorsque disponible ;
6. tester les payloads tronqués, inconnus, suffixés et les comptes invalides ;
7. documenter toute divergence entre linterface et le runtime.
### Metaplex Token Metadata — port maximal `0.1.0-pre.009`
Le catalogue workspace déclare `mpl-token-metadata ^5.1` avec la seule feature `serde`. La publication officielle résolue reste `5.1.1`; elle fournit les modules générés `accounts`, `instructions`, `types` et `errors` issus de lIDL Metaplex, sans introduire Anchor. La crate officielle utilise Borsh `< 1.0`; le décodeur référence donc explicitement `borsh 0.10` sous lalias workspace `borsh_0_10`, distinct de Borsh 1.x utilisé par dautres interfaces du workspace.
Le dépôt officiel `metaplex-foundation/mpl-token-metadata` confirme le Program ID `metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s`. LIDL officiel audité porte la version `1.14.0` et le blob `5df4a24f62c2743125be096cc174680790c92c18`; linventaire Rust généré des instructions porte le blob `3c42eec629f82e44ba690a7c4bd2177cc78f1d49`.
`kb_lib::DcMetadataMetaplexTokenMetadataDecoder` implémente désormais la couverture exhaustive des
58 discriminateurs `0..=57`. Les arguments sont lus avec les types Borsh officiels lorsque le SDK
les expose, ou avec un miroir local borné du wire publié pour les variantes historiques. Les
payloads, chaînes, créateurs, frais, comptes et suffixes sont bornés.
Le même composant inventorie les 15 variantes `Key 0..=14` et décode les quatorze layouts
représentant un compte réel. Les parseurs utilisent `solana-pubkey ^4.2` pour vérifier owner,
PDA et bump, puis les comptes historiques reçoivent une politique de matérialisation historique
distincte de leur interdiction dexécution. `Uninitialized` reste une sentinelle explicitement
refusée et toute variante future absente de linventaire fait échouer les tests.
Les metadata Token2022 incorporées, Metaplex Core, Bubblegum et le JSON externe restent des
provenances ou composants distincts. Aucun fetch HTTP, IPFS ou Arweave nappartient au replay
canonique de cette tranche.

View File

@@ -1,106 +0,0 @@
<!-- file: docs/SOLANA_NATIVE_RPC_CLOSURE_AUDIT.md -->
<!-- version: 4 -->
# Audit de clôture native, exécution et RPC — `0.4.2`
## Décision
Le jalon `0.4.2` est clôturé. Laudit distingue quatre contrats indépendants :
1. les opérations futures constructibles par `kb_executor_solana_core` ;
2. les instructions passées décodables par `kb_decoder_solana_core` ;
3. les méthodes standard HTTP/WebSocket exposées par `kb_onchain_transport` ;
4. lorchestration de sécurité, de simulation, denvoi et de replay post-exécution.
Une méthode transportable via JSON brut nest pas considérée comme un adaptateur typé. Un builder stateless nautorise pas à lui seul une opération dépendant dun compte, dune autorité, du rent, dun slot ou dun epoch. Une opération dangereuse peut être complète dans la bibliothèque tout en restant absente de lUI et désactivée sur Mainnet.
## Résultat synthétique
| Domaine | Inventaire canonique | Contrat final `0.4.2` |
|-------------------------|-------------------------------------------------------------------------:|------------------------------------------------------------------------------------------------|
| Exécuteur natif | 18 surfaces, 14 appelables, 4 non invocables/historiques, 109 opérations | égalité imposée par test Rust ; builders comparés aux interfaces ou layouts officiels |
| Décodeur natif | 18 surfaces, 121 déclarations | égalité imposée avec `kb_program_ids::native_program_ids()` et `SolanaCoreDecoder::coverage()` |
| HTTP JSON-RPC | 52 méthodes | 52 contrats typés configurables, 0 méthode standard limitée au JSON brut |
| WebSocket JSON-RPC | 9 paires / 18 méthodes | 9 requêtes, 9 notifications et 9 runtimes persistants typés |
| Préflight stateful | ALT, Config, Feature, Slashing, ZK ElGamal | rapports `NotRequired` / `Ready` / `Blocked`, Localnet/Devnet uniquement |
| Parcours mutable validé | System transfer Devnet | simulation, signature, envoi, confirmation, canonical, core et decode replay réussis |
## Exécuteur Solana Core
`docs/NATIVE_SOLANA_EXECUTION_MATRIX.json` et `SOLANA_CORE_OPERATION_CODES` imposent :
- exactement 18 surfaces ;
- exactement 14 surfaces appelables et 4 surfaces sans instruction client ;
- exactement 109 codes dopération uniques ;
- Program IDs présents dans `kb_program_ids` ;
- contrat de construction, politique, tests, validation cluster et décision UI pour chaque opération ;
- distribution des préflights `27 none / 14 required / 68 future`.
Les surfaces sans builder client sont BPF Loader v1, BPF Loader v2, Native Loader et lancien ZK Token Proof Program. Stake `Redelegate` reste historique `decode-only`. Cette classification évite dinventer des instructions qui ne sont plus ou nont jamais été appelables par un client moderne.
Les entrées `future` ne signifient pas « non implémenté ». Elles signifient que le wire et le plan sont couverts offline, mais que lactivation mutable exige encore une preuve stateful par scénario sur Localnet/Devnet. Aucune de ces opérations nest activée sur Mainnet par `0.4.2`.
## Décodeur Solana Core
`docs/NATIVE_SOLANA_DECODER_MATRIX.json` couvre exactement les 18 surfaces du registre natif et 121 déclarations. Les tests de complétude parcourent les enums officielles ou les tables wire auditées pour System, Compute Budget, ALT, Stake, Vote, loaders, précompiles, Slashing et preuves ZK.
Stake Config reste un compte bien connu non exécutable. Il ne possède ni dispatch dinstruction ni plan dexécution.
## HTTP JSON-RPC standard
`docs/SOLANA_STANDARD_RPC_MATRIX.json` et `STANDARD_HTTP_METHODS` enregistrent 52 méthodes. Chacune possède un contrat de requête/résultat propre à `kb_onchain_transport`. Les options facultatives restent indépendantes : commitment, `minContextSlot`, encodage, `dataSlice`, filtres, contexte, tri, niveau de détail, rewards et version maximale de transaction.
Les DTO Agave ne font pas partie de lAPI publique. La voie JSON brute reste une primitive interne ou dextension fournisseur, pas un substitut à une méthode standard absente.
## WebSocket JSON-RPC standard
Les neuf paires standard possèdent paramètres, notifications et runtime persistant dans `kb_onchain_transport`. `WsSession` fournit :
- une socket multiplexée ;
- des identifiants locaux stables et distants remappables ;
- unsubscribe explicite ;
- timeouts bornés ;
- ping/pong et fermeture ;
- reconnexion exponentielle bornée ;
- réabonnement ;
- suppression terminale de `signatureSubscribe`.
`blockSubscribe`, `slotsUpdatesSubscribe` et `voteSubscribe` sont désactivées par défaut, mais activables lorsquun endpoint les annonce explicitement. La première souscription réelle sert de probe paresseux. Une réponse `Method not found`, `not enabled`, `unavailable` ou `unsupported` désactive uniquement la capacité concernée pour la session ; les erreurs de paramètres, dauthentification ou de rate limit ne la désactivent pas.
## Frontière Tauri et TS-rs
Les payloads actifs de `kb_app_demo` et `kb_config` transmis par JSON utilisent des `number`, pas des `bigint`. Les valeurs didentifiants sont contrôlées avec `Number.isSafeInteger` avant invocation. Les types génériques hors frontière Tauri conservent leurs contrats exacts lorsquils ne sont pas sérialisés par `JSON.stringify`.
Le navigateur SQL applique maintenant la limite maximale reçue du backend avant lappel Tauri. Une valeur supérieure à 5 000 produit un diagnostic frontend et natteint plus PostgreSQL.
## Preuves de validation
Validations fournies le 13 juillet 2026 :
| Crate / contrôle | Résultat |
|-----------------------------------------|----------:|
| `kb_program_ids` | 5 tests |
| `kb_decoder_solana_core` | 116 tests |
| `kb_executor_solana_core` | 88 tests |
| `kb_execution_api` | 22 tests |
| `kb_execution_safety` | 15 tests |
| `kb-lib::executor::solana::transaction` | 12 tests |
| `kb_onchain_transport` | 113 tests |
| `kb_pipeline` | 56 tests |
| `kb_config` | 41 tests |
| `kb_app_demo` | 88 tests |
| `kb_store_pg` avec PostgreSQL réel | 45 tests |
| `cargo clippy --all-targets` | propre |
Le test Devnet opt-in a exécuté un transfert de 1 000 000 lamports avec airdrop nul depuis un wallet préfinancé. Il a confirmé simulation, signature, envoi, confirmation, hydratation canonique, extraction core et decode replay. `cargo tauri dev` a démarré Vite, initialisé les treize tables attendues et exercé les sessions WebSocket.
Larchive de logs Mainnet/Tauri confirme des unsubscribe réels pour `slot`, `root` et `program`. Le refus de sélectionner un autre endpoint tant quune session est active est un garde-fou volontaire. Lancien échec `JSON.stringify cannot serialize BigInt` nest plus présent.
## Limites conservées après clôture
- Mainnet reste désactivé par défaut et exige une politique explicite.
- Les opérations stateful administratives non exercées sur cluster restent hors UI et bloquées avant toute future activation mutable.
- Le parcours validé utilise une transaction legacy avec recent blockhash ; durable nonce et transactions v0 sont couverts par les bibliothèques mais nécessitent leurs propres parcours opérateur avant exposition.
- Les méthodes WebSocket instables dépendent du nœud et peuvent être désactivées automatiquement à lexécution.
La clôture de `0.4.2` nouvre aucune version suivante et ne fixe aucun plan de sources historiques externes.

View File

@@ -1,110 +0,0 @@
<!-- file: docs/SPL_TOKEN2022_CONFIDENTIAL_EXECUTION_AUDIT.md -->
<!-- version: 6 -->
# Audit dexécution Confidential Transfer Token-2022
## Frontières de programme
Les instructions Confidential Transfer restent des instructions du programme Token-2022. Les preuves associées sont des instructions distinctes du programme natif ZK ElGamal Proof ou des comptes de contexte déjà vérifiés. Le registre ElGamal reste une troisième surface avec son propre Program ID.
Aucun builder Token-2022 ne doit incorporer silencieusement une preuve, déchiffrer un solde ou générer une clé privée.
## Modes de preuve
Chaque preuve est fournie selon un seul mode explicite :
- `instruction_offset` : offset relatif signé non nul vers une instruction ZK distincte de la même transaction ;
- `context_state_account` : compte readonly contenant le contexte public dune preuve déjà vérifiée ; le wire Token-2022 encode alors loffset `0`.
Un offset inline égal à zéro est invalide dans le contrat de lexécuteur, car il rendrait le mode ambigu.
## Inventaire audité
| Opération | Preuves ordonnées | Classe dexécution |
|-------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------|
| InitializeMint | aucune | builder public |
| UpdateMint | aucune | builder public |
| ConfigureAccount | PubkeyValidity | entrées cryptographiques appelant |
| ApproveAccount | aucune | builder public |
| EmptyAccount | ZeroCiphertext | entrées cryptographiques appelant |
| Deposit | aucune | builder public |
| Withdraw | CiphertextCommitmentEquality, BatchedRangeProofU64 | entrées cryptographiques appelant |
| Transfer | CiphertextCommitmentEquality, BatchedGroupedCiphertext3HandlesValidity, BatchedRangeProofU128 | entrées cryptographiques appelant |
| ApplyPendingBalance | aucune | builder public |
| EnableConfidentialCredits | aucune | builder public |
| DisableConfidentialCredits | aucune | builder public |
| EnableNonConfidentialCredits | aucune | builder public |
| DisableNonConfidentialCredits | aucune | builder public |
| TransferWithFee | CiphertextCommitmentEquality, BatchedGroupedCiphertext3HandlesValidity, PercentageWithFee, BatchedGroupedCiphertext2HandlesValidity, BatchedRangeProofU256 | entrées cryptographiques appelant |
| ConfigureAccountWithRegistry | PubkeyValidity | entrées cryptographiques appelant |
La classe « builder public » signifie seulement que linstruction Token-2022 ne nécessite pas de ciphertext ou preuve nouvellement généré. Elle ne dispense ni du préflight, ni de la simulation, ni des autorités et postconditions.
## Plan de livraison
- `pre.048` : types, modes de preuve, ordre des preuves et classification de support ;
- `pre.049` : builders publics Initialize/Update/Approve/Deposit/Apply/credit toggles ;
- `pre.050` : clés ElGamal et balances déchiffrables opaques, Initialize/Update Mint et Apply Pending Balance ;
- `pre.051` : Configure Account et Configure Account With Registry ;
- `pre.052` : Empty Account avec preuve ZeroCiphertext inline ou context-state ;
- `pre.053` : Withdraw avec Equality et Range U64 ;
- `pre.054` : Transfer avec Equality, Grouped Ciphertext Validity à trois handles et Range U128 ;
- `pre.055` : audit exact de Transfer With Fee, cinq preuves, comptes et payload ;
- `pre.056` : builder Transfer With Fee ;
- tranches ultérieures : Confidential Transfer Fee, Confidential Mint/Burn et Permissioned Confidential Burn.
## `pre.053` — Withdraw
`Withdraw` exige deux références de preuve dans lordre officiel : `CiphertextCommitmentEquality`, puis `BatchedRangeProofU64`. Les modes inline et context-state peuvent être combinés. Lexécuteur transporte la nouvelle balance déchiffrable opaque sans produire ni vérifier localement les secrets ou preuves.
## `pre.054` — Transfer
`Transfer` transporte une nouvelle balance source déchiffrable de 36 octets et deux ciphertexts auditeur ElGamal de 64 octets. Il exige exactement trois références de preuve dans l'ordre officiel : `CiphertextCommitmentEquality`, `BatchedGroupedCiphertext3HandlesValidity`, puis `BatchedRangeProofU128`. Chaque preuve peut être inline ou context-state ; l'Instructions Sysvar n'est ajouté qu'une fois lorsqu'au moins un offset est utilisé. Aucune donnée cryptographique n'est générée par l'exécuteur.
## `pre.055` — audit Transfer With Fee
`TransferWithFee` conserve le même payload cryptographique Token-2022 que `Transfer` : une balance source déchiffrable de 36 octets et deux ciphertexts auditeur ElGamal de 64 octets. Il najoute pas de ciphertext withheld ou de montant de frais au payload Token-2022. Les informations de frais et le ciphertext de frais appartiennent aux contextes publics des preuves `PercentageWithFee` et `BatchedGroupedCiphertext2HandlesValidity`.
Le wire exact contient le tag externe `27`, le sous-tag `13`, puis 169 octets de payload : `36 + 64 + 64 + 5 offsets i8`. La donnée complète mesure donc 171 octets.
Les cinq preuves restent ordonnées :
1. `CiphertextCommitmentEquality` ;
2. `BatchedGroupedCiphertext3HandlesValidity` pour le montant transféré ;
3. `PercentageWithFee` ;
4. `BatchedGroupedCiphertext2HandlesValidity` pour le ciphertext de frais ;
5. `BatchedRangeProofU256`.
Lordre des comptes est source writable, mint readonly, destination writable, Instructions Sysvar si au moins une preuve est inline, comptes context-state dans lordre des cinq preuves, autorité, puis signataires multisig. Aucun type opaque Token-2022 supplémentaire nest nécessaire avant le builder de `pre.056`.
## Builder Transfer With Fee — pre.056
Le builder `inner_transfer_with_fee` est activé avec les cinq preuves dans lordre officiel. Le payload reste limité à la nouvelle balance déchiffrable, aux deux ciphertexts auditeur et aux cinq offsets. Les comptes context-state suivent le même ordre que les preuves et lInstructions Sysvar nest présent quune fois lorsquau moins un offset inline est utilisé.
## Confidential Transfer Fee public builder tranche (`pre.057`)
The proof-free builder surface is restricted to subdiscriminants 0, 3, 4 and 5
of the Token-2022 `ConfidentialTransferFeeExtension` envelope (external tag 37).
Initialization accepts one writable mint, an optional configuration authority
and one exact 32-byte ElGamal public key. Enable/disable harvest preserve simple
or multisig authority metas. Permissionless harvest preserves an ordered,
non-empty, duplicate-free source list bounded to 255 accounts. Withdrawals remain
separate because they require ciphertext-equality proof context.
## Confidential Transfer Fee — retrait depuis plusieurs comptes (`pre.059`)
Le builder `inner_withdraw_withheld_tokens_from_accounts` conserve lordre officiel suivant : Mint readonly, destination writable, Instructions Sysvar ou compte context-state, autorité withdraw-withheld, signataires multisig, puis sources writable. Le payload encode `num_token_accounts: u8`, loffset de preuve et la nouvelle balance déchiffrable destination.
La preuve requise est `CiphertextCiphertextEquality`. La liste des sources est non vide, unique, ordonnée et limitée à 255 comptes. Cette opération est explicitement sensible au front-running : une mutation dun withheld ciphertext source après génération de la preuve fait échouer la transaction. Le parcours harvest-vers-Mint puis retrait-depuis-Mint reste lalternative recommandée lorsque la stabilité des comptes sources ne peut pas être garantie.
## `pre.060` — audit Confidential Mint/Burn
L'interface publie six sous-instructions contiguës : `InitializeMint = 0`, `RotateSupplyElGamalPubkey = 1`, `UpdateDecryptableSupply = 2`, `Mint = 3`, `Burn = 4` et `ApplyPendingBurn = 5`. Cette famille reste dans l'enveloppe Token-2022 Confidential Mint/Burn et ne doit pas être confondue avec Permissioned Burn.
`InitializeMint` transporte une clé publique ElGamal de supply et une supply déchiffrable initiale. `RotateSupplyElGamalPubkey` transporte la nouvelle clé et exige `CiphertextCiphertextEquality`. `UpdateDecryptableSupply` et `ApplyPendingBurn` n'exigent aucune preuve, mais restent soumis aux autorités et préconditions d'état.
`Mint` et `Burn` exigent exactement trois preuves dans l'ordre : `CiphertextCommitmentEquality`, `BatchedGroupedCiphertext3HandlesValidity`, puis `BatchedRangeProofU128`. Les deux opérations transportent deux ciphertexts auditeur ; `Mint` transporte la nouvelle supply déchiffrable, tandis que `Burn` transporte la nouvelle balance disponible déchiffrable du compte source. Aucun secret, ciphertext ou preuve n'est généré par l'exécuteur.
Le découpage prévu est : builders publics et rotation dans `pre.061`, puis Mint/Burn prouvés dans `pre.062`. Permissioned Confidential Burn reste une tranche indépendante.

View File

@@ -1,251 +0,0 @@
<!-- file: docs/SPL_TOKEN2022_SOURCE_AUDIT.md -->
<!-- version: 6 -->
# Audit des sources Token-2022 résolues
## Ancrage reproductible
L'interface Cargo résolue `spl-token-2022-interface 3.1.1` publie le commit
`e18f9c6f9bf6044b934f48e3090e8e59e4820f02`, tagué `interface@v3.1.1` le 26 juin 2026.
L'audit est effectué sur ce commit détaché, jamais sur la branche `main` mouvante.
Le `Cargo.lock` du workspace opérateur, SHA-256
`248c02af8c78d3bb6ad747460fee0011f8141feef83364cf697e35e44bd4ceb9`, confirme que
`kb_decoder_spl_token_2022 0.4.5` consomme directement les interfaces Token-2022 et registre
ElGamal. Pour `spl-token-2022-interface 3.1.1`, il résout exactement :
- `solana-zk-elgamal-proof-interface 0.1.3` ;
- `spl-token-confidential-transfer-proof-extraction 0.6.1` ;
- `spl-token-group-interface 0.7.2` ;
- `spl-token-metadata-interface 1.0.1` ;
- `spl-type-length-value 0.9.1`.
La sortie `cargo tree -p spl-token-2022-interface -e features` prouve en particulier le chemin de
consommation direct de Token Metadata `1.0.1`. Cette version diffère du `1.0.0` figé dans le
`Cargo.lock` du processor source audité : les discriminants, layouts et builders devront donc être
comparés différentiellement avant le décodeur, sans supposer leur égalité.
La comparaison officielle clôt cette dérive : `interface@v1.0.1`, publiée le 29 juin 2026 au
commit court `7038969`, contient le correctif fusionné `fc97c60` de la pull request `87`. Le diff
de production ajoute 78 lignes dans `interface/src/instruction.rs` sans suppression. Les
discriminants, structures de payload et builders existants ne changent pas ; `unpack()` valide
désormais les longueurs Borsh `u32 LE` avant `try_from_slice` pour :
- `Initialize` : `name`, `symbol`, `uri` ;
- `UpdateField` : la chaîne de `Field::Key` lorsque le tag vaut `3`, puis `value` ;
- `RemoveKey` : `key`, après l'octet booléen `idempotent`.
`UpdateAuthority` et `Emit` ne transportent pas de chaîne et restent inchangés. Le décodeur devra
appliquer la garde `1.0.1` avant toute allocation, même si le processor source figé résolvait
encore `1.0.0`.
Au même commit :
- `program/Cargo.toml` déclare le processor `spl-token-2022 11.0.0` ;
- sa dépendance path demande l'interface `3.1.0`, satisfaite par le package workspace `3.1.1` ;
- le `Cargo.lock` source résout `spl-token-group-interface 0.7.2`,
`spl-token-metadata-interface 1.0.0` et `spl-elgamal-registry-interface 0.2.1` ;
- l'égalité du binaire déployé avec cette source reste non prouvée sur Localnet, Devnet et Mainnet.
## Dispatch réellement implémenté
`Processor::_process_inner` applique cet ordre :
1. `PodTokenInstruction`, discriminant `u8` ;
2. si ce décodage échoue, `TokenMetadataInstruction`, discriminant SPL de huit octets ;
3. si ce décodage échoue, `TokenGroupInstruction`, discriminant SPL de huit octets ;
4. sinon `InvalidInstruction`.
La surface routable contient donc :
| Famille | Enveloppes ou formes |
|------------------------------------------------------|---------------------:|
| Tags Token-2022 `u8` | 48 |
| Familles d'extensions parmi ces tags | 15 |
| Sous-instructions de ces familles | 58 |
| Formes Token-2022 hors enveloppes | 33 |
| Instructions Token Metadata exécutées par Token-2022 | 5 |
| Instructions Token Group exécutées par Token-2022 | 4 |
| Formes feuilles routables par le processor | 100 |
Les 48 tags ne constituent donc pas, seuls, une déclaration de couverture maximale. Les quinze
tags d'extension sont des enveloppes et doivent être remplacés par leurs 58 sous-instructions dans
le comptage des formes feuilles.
## Interfaces incorporées au processor
Les neuf discriminants ci-dessous sont exécutés par Token-2022 lorsqu'ils ciblent le Program ID
`TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb` :
| Interface | Instruction | Discriminant hexadécimal |
|------------------------|--------------------------|--------------------------|
| Token Metadata `1.0.0` | `initialize` | `d2e11ea258b84d8d` |
| Token Metadata `1.0.0` | `update_field` | `dde9312db5cadcc8` |
| Token Metadata `1.0.0` | `remove_key` | `ea122038598d25b5` |
| Token Metadata `1.0.0` | `update_authority` | `d7e4a6e45464567b` |
| Token Metadata `1.0.0` | `emit` | `faa6b4fa0d0cb846` |
| Token Group `0.7.2` | `initialize_group` | `79716c2736330004` |
| Token Group `0.7.2` | `update_group_max_size` | `6c25ab8ff81e126e` |
| Token Group `0.7.2` | `update_group_authority` | `a1695801edddd8cb` |
| Token Group `0.7.2` | `initialize_member` | `9820deb0dfed7486` |
Le propriétaire du décodage dépend toujours du Program ID exécutable : une CPI vers un programme
tiers implémentant la même interface appartient au décodeur de ce programme tiers. Un TLV pointeur
reste un lien et ne transfère pas la propriété du fait métier.
## Wire public des instructions hors enveloppes
Les 33 tags qui ne sont pas des enveloppes d'extension ont maintenant une ligne machine-readable
dans `baseInstructionWireAudit`. Les tailles incluent toujours le tag `u8`. L'interface `3.1.1`
encode les options d'instruction de manière compacte, distincte du `COption` à quatre octets des
états de compte : `0` tient sur un octet ; `1` est suivi de 32 octets pour une clé publique ou de
huit octets pour un `u64`.
Ce point donne notamment les tailles exactes suivantes :
- `InitializeMint` et `InitializeMint2` : 35 octets sans freeze authority, 67 avec ;
- `SetAuthority` : 3 octets sans nouvelle autorité, 35 avec ;
- `InitializeMintCloseAuthority` : 2 octets sans autorité, 34 avec ;
- `UnwrapLamports` : 2 octets sans montant, 10 avec.
`GetAccountDataSize` et `Reallocate` consomment tout le suffixe par éléments `ExtensionType u16 LE` ;
un suffixe impair ou un type inconnu est rejeté par l'unpacker d'interface. `UiAmountToAmount`
consomme tout le suffixe comme UTF-8, y compris une chaîne vide au seul niveau de l'interface.
`Batch` conserve tout le suffixe comme wire de records, dont les bornes et la validation processor
restent à auditer.
La distinction critique est conservée dans la matrice : `TokenInstruction::unpack()` appelle
`unpack_with_rest()` puis ignore le reste retourné. Pour les formes à préfixe fixe ou sans payload,
un succès de cet unpacker public ne prouve donc pas la consommation de tout le buffer, ni
l'acceptation du suffixe par le runtime. Le futur décodeur devra préserver et diagnostiquer tout
suffixe borné jusqu'à ce que le chemin exact du processor figé en établisse la règle variante par
variante.
## Règles de suffixe du processor figé
La comparaison a ensuite été menée sur les trois fichiers exacts du commit, avec leurs empreintes
SHA-256 enregistrées dans la matrice :
- `interface/src/instruction.rs` : `672b3890…b3a287` ;
- `program/src/pod_instruction.rs` : `7b546580…49c7e5` ;
- `program/src/processor.rs` : `9d11b834…3032d`.
Les 33 formes hors enveloppes forment une partition complète et sans doublon :
| Règle processor | Tags | Nombre |
|------------------------------------------------|----------------------------------------|-------:|
| longueur totale Pod exacte | `2,3,4,7,8,12,13,14,15,16,18,19,23,35` | 14 |
| préfixe Pod + option compacte, suffixe accepté | `0,6,20,25,45` | 5 |
| tag seul, suffixe non inspecté et accepté | `1,5,9,10,11,17,22,31,32,38` | 10 |
| reste entier interprété comme payload | `21,24,29` | 3 |
| flux de records `Batch` | `255` | 1 |
`decode_instruction_data<T>()` exige exactement `1 + size_of::<T>()` octets. À l'inverse, les
helpers privés des options compactes lisent la structure Pod, puis `0`, ou `1` suivi de la valeur,
sans vérifier l'épuisement du buffer. Pour les dix branches sans données, le processor n'appelle
aucun décodeur après la lecture du premier octet. Ces quinze formes acceptent donc réellement un
suffixe, même si celui-ci ne porte aucune sémantique publiée. Le décodeur devra le préserver sous
forme bornée et le diagnostiquer explicitement, sans créer de champ métier.
Pour `GetAccountDataSize` et `Reallocate`, chaque morceau de deux octets doit former un
`ExtensionType` connu ; un dernier morceau incomplet ou un type inconnu échoue. Pour
`UiAmountToAmount`, tout le reste doit être UTF-8, la chaîne vide restant admise à ce niveau.
`Batch` ne peut pas être vide : le plus petit wire total contient le tag externe, un header de deux
octets et au moins un discriminant interne, soit quatre octets. Chaque record encode en `u8` son
nombre de comptes et la longueur totale de son instruction interne. Un header ou payload tronqué
échoue ; une longueur interne nulle échoue au dispatch ; un `Batch` interne est rejeté par
`_process_inner`. Les fallbacks Token Metadata et Token Group restent en revanche joignables dans
un record lorsque leur wire tient dans les 255 octets. Le processor n'impose pas de nombre maximal
explicite de records au-delà des limites de transaction et de calcul : le décodeur devra donc poser
sa propre borne.
## Comptes publiés par les builders de base
La matrice contient désormais une ligne ordonnée pour chacune des 33 formes hors enveloppes. Elle
enregistre les metas exactes des 32 helpers Rust publiés : rôle, `writable`, `signer`, compte
optionnel et queue multisig. `Batch` reste la seule forme sans helper Rust dédié pour construire
ses metas ; `TokenInstruction::pack()` ne produit que ses données.
Les autorités simples et multisig partagent le contrat classique des builders : l'autorité est
signataire lorsque la liste `signer_pubkeys` est vide ; sinon elle ne signe pas et chaque élément
de la queue est ajouté en lecture seule avec le flag signataire. Le builder ne borne pas la taille
de cette queue pour les opérations d'autorité et conserve ordre et doublons. Le runtime ne peut
toutefois satisfaire qu'un multisig stockant de un à onze positions.
`InitializeMultisig` et `InitializeMultisig2` ont un contrat différent : les clés de configuration
ne signent pas. Le builder exige `m` et `n` dans `1..=11` ainsi que `m <= n`. Le processor consomme
tous les comptes restants comme clés de configuration, valide séparément `m` et `n`, mais ne
répète pas le contrôle `m <= n`. Une instruction manuelle `m > n` peut donc initialiser un état que
le builder refuse. Le décodeur doit conserver ce fait et le diagnostiquer sans le normaliser.
`SyncNative` publie deux helpers : le premier fournit seulement le compte natif modifiable ; le
second ajoute Rent en lecture seule. Le processor traite effectivement le deuxième compte comme
optionnel, mais ignore ceux qui suivraient. `Batch` découpe les comptes selon le compteur `u8` de
chaque record ; les comptes externes restant après le dernier record ne sont pas rejetés. Ils
devront rester visibles comme comptes non assignés.
Le contrat builder de `Reallocate` est fixé — compte à agrandir modifiable, payer modifiable et
signataire, System Program, propriétaire conditionnel puis queue multisig — mais la consommation
runtime détaillée reste ouverte jusqu'à reconfirmation du module séparé
`program/src/extension/reallocate.rs` au même commit. Cette limite empêche de déclarer l'audit
processor des comptes entièrement clos.
## Sources auditées
- dépôt `solana-program/token-2022`, commit figé ci-dessus ;
- `interface/src/instruction.rs` et `interface/src/extension/**/instruction.rs` ;
- `interface/src/extension/mod.rs` et les états d'extension ;
- `program/src/processor.rs` et `program/src/extension/**/processor.rs` ;
- dépôt `solana-program/token-metadata`, commit
`552935e00710478541e3394a8b2624c9ba7f503f`, tag `interface@v1.0.0` ;
- dépôt `solana-program/token-group`, commit
`2645064953937118572735993ed0ac1d07db5f14`, tag `interface@v0.7.2`.
## Limites restantes
Cette tranche confirme le wire public, les règles runtime de suffixe et les metas officielles des
builders des 33 formes hors enveloppes. Elle ne clôt pas encore l'audit par variante : consommation
processor complète des comptes, données de preuve, builders des extensions, statuts de
construction et compatibilité cluster doivent encore être renseignés avant le décodeur.
## Première tranche verticale d'extensions
Le décodeur structure désormais exactement douze feuilles issues de quatre enveloppes : les six
instructions Transfer Fee, les deux Default Account State, les deux Memo Transfer et les deux CPI
Guard. Les discriminants, champs numériques, options compactes et règles de longueur proviennent
des interfaces figées au commit audité. Les onze autres enveloppes restent opaques et ne sont pas
comptées comme décodées sémantiquement.
Cette tranche ne déclare encore aucune capacité exécuteur d'extension. Conformément à l'ordre du
jalon, les projections propriétaires et leurs tests de non-duplication doivent être validés avant
d'activer les builders officiels correspondants.
## Dispatch incorporé Token Metadata et Token Group
Le dispatch de production ne peut pas se limiter au premier octet de `TokenInstruction`. Après
échec du décodage Token-2022 principal, le processor `11.0.0` audité tente successivement les
interfaces Token Metadata puis Token Group. Les neuf discriminants déjà inventoriés dans la
matrice sont donc désormais reconnus par le décodeur Token-2022 lorsque le Program ID réellement
exécuté est `Tokenz...` : cinq feuilles Metadata et quatre feuilles Group.
Les chaînes Borsh Metadata sont bornées avant allocation et décodage. Les layouts Pod Group sont
traités avec une longueur exacte. Cette intégration ne décode pas un programme tiers implémentant
les mêmes interfaces : une CPI vers un autre Program ID reste la propriété du décodeur de ce
programme.
L'égalité de surface à maintenir est désormais explicitement compilée et documentée :
```text
33 feuilles hors enveloppes + 58 feuilles d'extensions + 5 Metadata + 4 Group = 100
```
## Audit ElGamal restant
La présence de `spl-elgamal-registry-interface 0.2.1`, de son Program ID `regVY...` et de la seed
`elgamal-registry` ne suffit pas à revendiquer sa couverture. La tranche dédiée doit encore fixer
les discriminants et le wire exacts, la dérivation PDA, la relation wallet/owner, les clés ElGamal,
les références de preuve, le lifecycle create/update, les autorités et signataires, les builders
actuels ou expérimentaux et les preuves de déploiement cluster. Toute référence au registre depuis
une instruction confidentielle Token-2022 reste un lien inter-programme et non une instruction du
registre.

View File

@@ -1,109 +0,0 @@
<!-- file: docs/SQL_DEMOS.md -->
<!-- version: 12 -->
# Démos SQL
## Fenêtres disponibles
| Fenêtre | Rôle |
|------------------------------|------------------------------------------------------------------------------------------------------|
| `demo_sql_diag` | Profil, backend, DSN masqué, santé PostgreSQL et tables attendues. |
| `demo_sql_pg_raw` | Transactions canoniques et observations dacquisition. |
| `demo_sql_pg_core` | Transactions, comptes, instructions, inner instructions, logs, balances et ledger. |
| `demo_sql_replay_candidates` | Exploration read-only, filtrage et export des signatures, programmes, mints, owners et account keys. |
Depuis `0.3.4`, le diagnostic core inclut :
```text
kb_sol_ops_processing_ledger
```
La fenêtre `demo_core_extraction` exécute le worker puis permet douvrir les diagnostics raw/core et le sélecteur de candidats. Les fenêtres SQL restent read-only et ne modifient aucune donnée.
## Sélecteur de candidats replay
`demo_sql_replay_candidates` sépare lexploration en cinq tableaux DataTables avec intégration Bootstrap 5 :
1. transactions et signatures ;
2. programmes observés dans les instructions outer, inner et dans les logs reliés ;
3. mints ;
4. owners ;
5. account keys.
Les requêtes PostgreSQL sont statiques, paramétrées et limitées à `5 000` lignes au maximum par chargement. Aucun éditeur SQL libre nest exposé.
### Transactions et signatures
Filtres serveur disponibles :
- fragment de signature ;
- plage inclusive de slots ;
- état raw ;
- statut du ledger `core_extraction` ;
- program ID exact avec portée `any`, `outer`, `inner` ou `logs` ;
- mint, owner ou account key exact ;
- limite et ordre des slots.
Le tableau affiche aussi la présence du graphe core, le statut du ledger, sa version et son nombre de tentatives, ainsi que les cardinalités outer/inner.
### Programmes
Le tableau agrège les occurrences issues de :
```text
kb_sol_core_instructions
kb_sol_core_inner_instructions
kb_sol_core_logs
```
Chaque ligne expose le code connu de `kb_program_ids` lorsquil existe, le nombre de transactions distinctes, dinstructions outer, dinstructions inner, de logs reliés et la plage de slots observée. Le filtre propose une liste des programmes enregistrés tout en conservant une saisie libre pour les identifiants inconnus ou partiels.
Pour appliquer un programme au tableau des transactions, il faut cocher exactement une ligne puis utiliser « Utiliser comme filtre transactions ». Lorsquaucune ligne nest cochée, laction accepte aussi une seule ligne restant après le filtre local DataTables.
### Mints, owners et comptes
Les trois familles disposent de tableaux et filtres indépendants. Les mints et owners proviennent de `kb_sol_core_balance_changes`; les account keys proviennent de `kb_sol_core_account_keys` et ne sont pas classifiées automatiquement comme wallet, pool, mint ou token account.
Chaque tableau affiche transactions distinctes, occurrences, occurrences par transaction, slots minimum/maximum et étendue. Une valeur sélectionnée peut être appliquée directement au filtre du tableau des transactions.
### Sélection et export
Dans chaque tableau :
- la première colonne contient une case à cocher gérée par lextension DataTables Select ;
- la case du header sélectionne ou désélectionne toutes les lignes correspondant au filtre local ;
- une sélection explicite est prioritaire ;
- sans sélection, la copie et lexport utilisent toutes les lignes correspondant au filtre local DataTables ;
- les identifiants peuvent être copiés dans le presse-papiers sous forme multiligne ;
- le frontend construit un CSV diagnostique avec BOM UTF-8, séparateur `;` et CRLF ;
- une commande Rust bornée écrit le fichier dans `data/exports_csv/` et ajoute un suffixe lorsque le nom existe déjà ;
- les valeurs longues sont tronquées visuellement, exposées intégralement par tooltip et copiables cellule par cellule ;
- tous les tableaux affichent 10 lignes par défaut et possèdent un reset complet des filtres.
La copie multiligne des signatures peut être collée telle quelle dans le mode `Signatures explicites` de `demo_core_extraction`. Lexport ne dépend plus du téléchargement HTML du WebView.
### Lecture des colonnes transactions
Les cardinalités sont séparées en quatre colonnes : `Outer inst.`, `Inner inst.`, `Outer pr.` et `Inner pr.`. Les deux premières comptent les instructions ; les deux dernières comptent les program IDs distincts.
La colonne `Core` décrit le graphe structurel :
- `absent` : aucune ligne `kb_sol_core_transactions` ;
- `présent` : graphe core présent et transaction Solana réussie ;
- `échec on-chain` : graphe core présent, mais la transaction Solana elle-même a retourné une erreur.
`échec on-chain` nest donc pas un échec de lextracteur. Le tri DataTables utilise un rang numérique distinct pour ces trois états.
### Pools et paires
Aucun onglet pool/pair nest ajouté dans `0.3.4`. Le core connaît des account keys mais ne peut pas déterminer de façon fiable leur rôle sémantique. Les futurs décodeurs et matérialiseurs alimenteront les tables catalogues de pools et de paires ; longlet pourra alors reposer sur des identifiants explicites plutôt que sur une heuristique.
## Contrôles recommandés après extraction
- comparer le nombre de transactions raw `core_extracted` et de transactions core ;
- vérifier labsence de lignes filles orphelines ;
- vérifier lunicité des chemins et indices ;
- comparer les statuts ledger avec les graphes core présents ;
- examiner les lignes raw `failed` et leur `lifecycle_reason`.
Les requêtes prêtes à lemploi sont dans `sql/validation/000_core_integrity.sql`.

View File

@@ -1,273 +0,0 @@
<!-- file: docs/SURFACE_CRATE_MATRIX.md -->
<!-- version: 6 -->
# Matrice des modules réservés
Ce document liste les crates actuellement présents dans le workspace. Un crate réservé ne signifie pas que le décodage, la matérialisation ou lexécution est validé.
## Principes
- Les surfaces non classifiées ne doivent pas avoir de crate.
- Les décodeurs et exécuteurs sont réservés par surface canonique lorsque la surface est classifiée.
- Les détails de validation restent dans `registry/program_registry_seed.toml` et les docs spécialisées.
## Solana
| Surface | Décodeur | Exécuteur |
|---------------|--------------------------|---------------------------|
| `solana_core` | `kb_decoder_solana_core` | `kb_executor_solana_core` |
## Spl
| Surface | Décodeur | Exécuteur |
|--------------------------------|-------------------------------------------|--------------------------------------------|
| `spl_account_compression` | `kb_decoder_spl_account_compression` | `kb_executor_spl_account_compression` |
| `spl_associated_token_account` | `kb_decoder_spl_associated_token_account` | `kb_executor_spl_associated_token_account` |
| `spl_memo` | `kb_decoder_spl_memo` | `kb_executor_spl_memo` |
| `spl_name_service` | `kb_decoder_metadata_spl_name_service` | `kb_executor_metadata_spl_name_service` |
| `spl_noop` | `kb_decoder_spl_noop` | `kb_executor_spl_noop` |
| `spl_single_pool` | `kb_decoder_spl_single_pool` | `kb_executor_spl_single_pool` |
| `spl_stake_pool` | `kb_decoder_spl_stake_pool` | `kb_executor_spl_stake_pool` |
| `spl_token` | `kb_decoder_spl_token` | `kb_executor_spl_token` |
| `spl_token2022` | `kb_decoder_spl_token_2022` | `kb_executor_spl_token_2022` |
## Amm
| Surface | Décodeur | Exécuteur |
|----------------------------|---------------------------------------|----------------------------------------|
| `amm_aldrin_v1` | `kb_decoder_amm_aldrin_v1` | `kb_executor_amm_aldrin_v1` |
| `amm_aldrin_v2` | `kb_decoder_amm_aldrin_v2` | `kb_executor_amm_aldrin_v2` |
| `amm_alphaq` | `kb_decoder_amm_alphaq` | `kb_executor_amm_alphaq` |
| `amm_believe` | `kb_decoder_amm_believe` | `kb_executor_amm_believe` |
| `amm_bonk_swap` | `kb_decoder_amm_bonk_swap` | `kb_executor_amm_bonk_swap` |
| `amm_fluxbeam` | `kb_decoder_amm_fluxbeam` | `kb_executor_amm_fluxbeam` |
| `amm_goon_fi` | `kb_decoder_amm_goon_fi` | `kb_executor_amm_goon_fi` |
| `amm_goosefx_gamma` | `kb_decoder_amm_goosefx_gamma` | `kb_executor_amm_goosefx_gamma` |
| `amm_goosefx_v2` | `kb_decoder_amm_goosefx_v2` | `kb_executor_amm_goosefx_v2` |
| `amm_guac_swap` | `kb_decoder_amm_guac_swap` | `kb_executor_amm_guac_swap` |
| `amm_lifinity_swap_v2` | `kb_decoder_amm_lifinity_swap_v2` | `kb_executor_amm_lifinity_swap_v2` |
| `amm_metadao_futarchy_amm` | `kb_decoder_amm_metadao_futarchy_amm` | `kb_executor_amm_metadao_futarchy_amm` |
| `amm_metadao_v0_5` | `kb_decoder_amm_metadao_v0_5` | `kb_executor_amm_metadao_v0_5` |
| `amm_meteora_damm_v1` | `kb_decoder_amm_meteora_damm_v1` | `kb_executor_amm_meteora_damm_v1` |
| `amm_meteora_damm_v2` | `kb_decoder_amm_meteora_damm_v2` | `kb_executor_amm_meteora_damm_v2` |
| `amm_obric_v2` | `kb_decoder_amm_obric_v2` | `kb_executor_amm_obric_v2` |
| `amm_one_dex` | `kb_decoder_amm_one_dex` | `kb_executor_amm_one_dex` |
| `amm_pump_swap` | `kb_decoder_amm_pump_swap` | `kb_executor_amm_pump_swap` |
| `amm_raydium_lp_v4` | `kb_decoder_amm_raydium_lp_v4` | `kb_executor_amm_raydium_lp_v4` |
| `amm_solfi` | `kb_decoder_amm_solfi` | `kb_executor_amm_solfi` |
| `amm_solfi_v2` | `kb_decoder_amm_solfi_v2` | `kb_executor_amm_solfi_v2` |
| `amm_vertigo` | `kb_decoder_amm_vertigo` | `kb_executor_amm_vertigo` |
| `amm_virtuals` | `kb_decoder_amm_virtuals` | `kb_executor_amm_virtuals` |
| `amm_woofi` | `kb_decoder_amm_woofi` | `kb_executor_amm_woofi` |
| `amm_zero_fi` | `kb_decoder_amm_zero_fi` | `kb_executor_amm_zero_fi` |
| `amm_zora` | `kb_decoder_amm_zora` | `kb_executor_amm_zora` |
## Cpmm
| Surface | Décodeur | Exécuteur |
|----------------|---------------------------|----------------------------|
| `cpmm_raydium` | `kb_decoder_cpmm_raydium` | `kb_executor_cpmm_raydium` |
## Clmm
| Surface | Décodeur | Exécuteur |
|-----------------------|----------------------------------|-----------------------------------|
| `clmm_byreal` | `kb_decoder_clmm_byreal` | `kb_executor_clmm_byreal` |
| `clmm_fusion` | `kb_decoder_clmm_fusion` | `kb_executor_clmm_fusion` |
| `clmm_orca_whirlpool` | `kb_decoder_clmm_orca_whirlpool` | `kb_executor_clmm_orca_whirlpool` |
| `clmm_pancake_swap` | `kb_decoder_clmm_pancake_swap` | `kb_executor_clmm_pancake_swap` |
| `clmm_raydium` | `kb_decoder_clmm_raydium` | `kb_executor_clmm_raydium` |
| `clmm_stabble` | `kb_decoder_clmm_stabble` | `kb_executor_clmm_stabble` |
## Dlmm
| Surface | Décodeur | Exécuteur |
|----------------|---------------------------|----------------------------|
| `dlmm_meteora` | `kb_decoder_dlmm_meteora` | `kb_executor_dlmm_meteora` |
## Stable Swap
| Surface | Décodeur | Exécuteur |
|------------------------------|-----------------------------------------|------------------------------------------|
| `stable_swap_hylo_exchange` | `kb_decoder_stable_swap_hylo_exchange` | `kb_executor_stable_swap_hylo_exchange` |
| `stable_swap_jupiter_stable` | `kb_decoder_stable_swap_jupiter_stable` | `kb_executor_stable_swap_jupiter_stable` |
| `stable_swap_numeraire` | `kb_decoder_stable_swap_numeraire` | `kb_executor_stable_swap_numeraire` |
| `stable_swap_stabble` | `kb_decoder_stable_swap_stabble` | `kb_executor_stable_swap_stabble` |
## Weighted Swap
| Surface | Décodeur | Exécuteur |
|-------------------------|------------------------------------|-------------------------------------|
| `weighted_swap_stabble` | `kb_decoder_weighted_swap_stabble` | `kb_executor_weighted_swap_stabble` |
## Launchpad
| Surface | Décodeur | Exécuteur |
|-------------------------------|------------------------------------------|-------------------------------------------|
| `launchpad_boop_fun` | `kb_decoder_launchpad_boop_fun` | `kb_executor_launchpad_boop_fun` |
| `launchpad_metadao_ico` | `kb_decoder_launchpad_metadao_ico` | `kb_executor_launchpad_metadao_ico` |
| `launchpad_meteora_dbc` | `kb_decoder_launchpad_meteora_dbc` | `kb_executor_launchpad_meteora_dbc` |
| `launchpad_moonit` | `kb_decoder_launchpad_moonit` | `kb_executor_launchpad_moonit` |
| `launchpad_orca_wavebreak` | `kb_decoder_launchpad_orca_wavebreak` | `kb_executor_launchpad_orca_wavebreak` |
| `launchpad_printr` | `kb_decoder_launchpad_printr` | `kb_executor_launchpad_printr` |
| `launchpad_pump_fun` | `kb_decoder_launchpad_pump_fun` | `kb_executor_launchpad_pump_fun` |
| `launchpad_pump_pumpup_ai` | `kb_decoder_launchpad_pump_pumpup_ai` | `kb_executor_launchpad_pump_pumpup_ai` |
| `launchpad_raydium_launchlab` | `kb_decoder_launchpad_raydium_launchlab` | `kb_executor_launchpad_raydium_launchlab` |
## Router
| Surface | Décodeur | Exécuteur |
|--------------------------------|-------------------------------------------|--------------------------------------------|
| `router_dflow_aggregator_v4` | `kb_decoder_router_dflow_aggregator_v4` | `kb_executor_router_dflow_aggregator_v4` |
| `router_jupiter_aggregator_v4` | `kb_decoder_router_jupiter_aggregator_v4` | `kb_executor_router_jupiter_aggregator_v4` |
| `router_jupiter_aggregator_v6` | `kb_decoder_router_jupiter_aggregator_v6` | `kb_executor_router_jupiter_aggregator_v6` |
| `router_jupiter_dca` | `kb_decoder_router_jupiter_dca` | `kb_executor_router_jupiter_dca` |
| `router_okx_labs_v1` | `kb_decoder_router_okx_labs_v1` | `kb_executor_router_okx_labs_v1` |
| `router_okx_labs_v2` | `kb_decoder_router_okx_labs_v2` | `kb_executor_router_okx_labs_v2` |
## Orderbook
| Surface | Décodeur | Exécuteur |
|------------------------------------|-----------------------------------------------|------------------------------------------------|
| `orderbook_jupiter_limit_order` | `kb_decoder_orderbook_jupiter_limit_order` | `kb_executor_orderbook_jupiter_limit_order` |
| `orderbook_jupiter_limit_order_v2` | `kb_decoder_orderbook_jupiter_limit_order_v2` | `kb_executor_orderbook_jupiter_limit_order_v2` |
| `orderbook_openbook_v2` | `kb_decoder_orderbook_openbook_v2` | `kb_executor_orderbook_openbook_v2` |
## Admin
| Surface | Décodeur | Exécuteur |
|----------------------|---------------------------------|----------------------------------|
| `admin_jupiter_lock` | `kb_decoder_admin_jupiter_lock` | `kb_executor_admin_jupiter_lock` |
| `admin_pump_fees` | `kb_decoder_admin_pump_fees` | `kb_executor_admin_pump_fees` |
## Fees
| Surface | Décodeur | Exécuteur |
|--------------------------|-------------------------------------|--------------------------------------|
| `fees_bags_fee_share_v1` | `kb_decoder_fees_bags_fee_share_v1` | `kb_executor_fees_bags_fee_share_v1` |
| `fees_bags_fee_share_v2` | `kb_decoder_fees_bags_fee_share_v2` | `kb_executor_fees_bags_fee_share_v2` |
## Lock
| Surface | Décodeur | Exécuteur |
|-------------------|------------------------------|-------------------------------|
| `lock_raydium_lp` | `kb_decoder_lock_raydium_lp` | `kb_executor_lock_raydium_lp` |
## Adapter
| Surface | Décodeur | Exécuteur |
|---------------------------------|--------------------------------------------|---------------------------------------------|
| `adapter_saber_decimal_wrapper` | `kb_decoder_adapter_saber_decimal_wrapper` | `kb_executor_adapter_saber_decimal_wrapper` |
## Governance
| Surface | Décodeur | Exécuteur |
|-------------------------------|------------------------------------------|-------------------------------------------|
| `governance_metadao_bid_wall` | `kb_decoder_governance_metadao_bid_wall` | `kb_executor_governance_metadao_bid_wall` |
## Bridge
| Surface | Décodeur | Exécuteur |
|------------------------------------------------|-----------------------------------------------------------|------------------------------------------------------------|
| `bridge_circle_cctp_token_messenger_minter` | `kb_decoder_bridge_circle_cctp_token_messenger_minter` | `kb_executor_bridge_circle_cctp_token_messenger_minter` |
| `bridge_circle_cctp_token_messenger_minter_v2` | `kb_decoder_bridge_circle_cctp_token_messenger_minter_v2` | `kb_executor_bridge_circle_cctp_token_messenger_minter_v2` |
| `bridge_layer_zero_endpoint` | `kb_decoder_bridge_layer_zero_endpoint` | `kb_executor_bridge_layer_zero_endpoint` |
| `bridge_layer_zero_executor` | `kb_decoder_bridge_layer_zero_executor` | `kb_executor_bridge_layer_zero_executor` |
## Rwa
| Surface | Décodeur | Exécuteur |
|---------------------------|--------------------------------------|---------------------------------------|
| `rwa_ondo_global_markets` | `kb_decoder_rwa_ondo_global_markets` | `kb_executor_rwa_ondo_global_markets` |
## Lending
| Surface | Décodeur | Exécuteur |
|-----------------------------------|----------------------------------------------|-----------------------------------------------|
| `lending_clone` | `kb_decoder_lending_clone` | `kb_executor_lending_clone` |
| `lending_jupiter_lend_borrow` | `kb_decoder_lending_jupiter_lend_borrow` | `kb_executor_lending_jupiter_lend_borrow` |
| `lending_jupiter_lend_earn` | `kb_decoder_lending_jupiter_lend_earn` | `kb_executor_lending_jupiter_lend_earn` |
| `lending_jupiter_lend_flash_loan` | `kb_decoder_lending_jupiter_lend_flash_loan` | `kb_executor_lending_jupiter_lend_flash_loan` |
| `lending_jupiter_lend_liquidity` | `kb_decoder_lending_jupiter_lend_liquidity` | `kb_executor_lending_jupiter_lend_liquidity` |
| `lending_kamino` | `kb_decoder_lending_kamino` | `kb_executor_lending_kamino` |
| `lending_marginfi_v2` | `kb_decoder_lending_marginfi_v2` | `kb_executor_lending_marginfi_v2` |
## Staking
| Surface | Décodeur | Exécuteur |
|----------------------------|---------------------------------------|----------------------------------------|
| `staking_kamino_farm` | `kb_decoder_staking_kamino_farm` | `kb_executor_staking_kamino_farm` |
| `staking_marinade_finance` | `kb_decoder_staking_marinade_finance` | `kb_executor_staking_marinade_finance` |
| `staking_solayer` | `kb_decoder_staking_solayer` | `kb_executor_staking_solayer` |
## Vault
| Surface | Décodeur | Exécuteur |
|-----------------------------|----------------------------------------|-----------------------------------------|
| `vault_carrot_defi` | `kb_decoder_vault_carrot_defi` | `kb_executor_vault_carrot_defi` |
| `vault_hylo_stability_pool` | `kb_decoder_vault_hylo_stability_pool` | `kb_executor_vault_hylo_stability_pool` |
| `vault_kamino` | `kb_decoder_vault_kamino` | `kb_executor_vault_kamino` |
| `vault_kamino_v2` | `kb_decoder_vault_kamino_v2` | `kb_executor_vault_kamino_v2` |
| `vault_kamino_yvaults` | `kb_decoder_vault_kamino_yvaults` | `kb_executor_vault_kamino_yvaults` |
| `vault_meteora` | `kb_decoder_vault_meteora` | `kb_executor_vault_meteora` |
## Vesting
| Surface | Décodeur | Exécuteur |
|----------------------|---------------------------------|----------------------------------|
| `vesting_streamflow` | `kb_decoder_vesting_streamflow` | `kb_executor_vesting_streamflow` |
## Nft
| Surface | Décodeur | Exécuteur |
|--------------------------|-------------------------------------|--------------------------------------|
| `nft_metaplex_bubblegum` | `kb_decoder_nft_metaplex_bubblegum` | `kb_executor_nft_metaplex_bubblegum` |
## Treasury
| Surface | Décodeur | Exécuteur |
|---------------------------------------|--------------------------------------------------|---------------------------------------------------|
| `treasury_helium_treasury_management` | `kb_decoder_treasury_helium_treasury_management` | `kb_executor_treasury_helium_treasury_management` |
## Wallet
| Surface | Décodeur | Exécuteur |
|--------------------------------------|-------------------------------------------------|--------------------------------------------------|
| `wallet_jupiter_apepro_smart_wallet` | `kb_decoder_wallet_jupiter_apepro_smart_wallet` | `kb_executor_wallet_jupiter_apepro_smart_wallet` |
## Perpetuals
| Surface | Décodeur | Exécuteur |
|-----------------------|----------------------------------|-----------------------------------|
| `perpetuals_drift_v2` | `kb_decoder_perpetuals_drift_v2` | `kb_executor_perpetuals_drift_v2` |
| `perpetuals_jupiter` | `kb_decoder_perpetuals_jupiter` | `kb_executor_perpetuals_jupiter` |
| `perpetuals_zeta` | `kb_decoder_perpetuals_zeta` | `kb_executor_perpetuals_zeta` |
## Matérialisateurs
| Module `kb-lib` |
|-----------------------------------------------|
| `materializer::admin::core` |
| `materializer::bridge::core` |
| `materializer::compliance::audit` |
| `materializer::fees::core` |
| `materializer::governance::core` |
| `materializer::lending::core` |
| `materializer::lifecycle::core` |
| `materializer::liquidity::core` |
| `materializer::metadata::core` |
| `materializer::nft::core` |
| `materializer::oracle::core` |
| `materializer::orderbook::core` |
| `materializer::perpetuals::core` |
| `materializer::pool::state` |
| `materializer::rewards::core` |
| `materializer::risk::core` |
| `materializer::routing::core` |
| `materializer::staking::core` |
| `materializer::token::accounts` |
| `materializer::token::metadata_risk` |
| `materializer::trades::core` |
| `materializer::transaction::annotations` |
| `materializer::vault::core` |

View File

@@ -1,39 +0,0 @@
# Classification des fixtures de test
## Objet
Ce document inventorie les données structurées actuellement stockées sous `docs/` alors qu'elles sont consommées par le code ou les tests. Le répertoire `docs/` reste réservé à la documentation destinée à une lecture humaine.
## Destination retenue
Les matrices partagées doivent être déplacées sous :
```text
test-fixtures/contract-matrices/
```
Le déplacement sera effectué dans une tranche fonctionnelle atomique avec la mise à jour de tous les chemins `include_str!`, des références documentaires et des tests concernés.
## Inventaire
| Fichier actuel | Consommateurs Rust détectés | Classification cible |
|---|---:|---|
| `docs/METAPLEX_TOKEN_METADATA_MATRIX.json` | 2 | fixture contractuelle partagée |
| `docs/NATIVE_SOLANA_DECODER_MATRIX.json` | 1 | fixture contractuelle partagée |
| `docs/NATIVE_SOLANA_EXECUTION_MATRIX.json` | 1 | fixture contractuelle partagée |
| `docs/SOLANA_STANDARD_RPC_MATRIX.json` | 1 | fixture contractuelle partagée |
| `docs/SPL_ASSOCIATED_TOKEN_ACCOUNT_MATRIX.json` | 4 | fixture contractuelle partagée |
| `docs/SPL_ELGAMAL_REGISTRY_MATRIX.json` | 0 | usage à confirmer avant déplacement |
| `docs/SPL_MEMO_MATRIX.json` | 3 | fixture contractuelle partagée |
| `docs/SPL_TOKEN2022_MATRIX.json` | 2 | fixture contractuelle partagée |
| `docs/SPL_TOKEN2022_VALIDATION_MATRIX.json` | 1 | fixture contractuelle partagée |
| `docs/SPL_TOKEN_MATRIX.json` | 2 | fixture contractuelle partagée |
## Contraintes de migration
- Ne pas déplacer un fichier sans mettre à jour tous ses consommateurs dans le même delta.
- Ne pas laisser une copie durable sous `docs/`.
- Conserver les noms actuels sauf justification explicite.
- Ajouter les suppressions sous forme de commandes `rm -- ...` dans `delta.md`.
- Exécuter les tests de chaque crate consommatrice après le déplacement.
- Les helpers d'audit restent en lecture seule et signalent uniquement les emplacements suspects.

View File

@@ -1,164 +0,0 @@
<!-- file: docs/TRACING_CONTRACT.md -->
<!-- version: 21 -->
# Contrat de tracing par crate et composant
## Objectif
Chaque événement est émis par la crate qui prend réellement la décision. `kb_app_demo` journalise les frontières Tauri, les actions utilisateur, létat des fenêtres et les résumés dorchestration ; il ne recopie pas les décisions internes du RPC, du pipeline, du store, dun décodeur, dun matérialiseur ou dun exécuteur.
## Classification des crates
Une crate est opérationnelle lorsquelle réalise au moins une des actions suivantes :
- I/O réseau ou base de données ;
- orchestration concurrente, retry, pacing ou annulation ;
- décodage ou matérialisation ;
- construction ou simulation dun plan dexécution ;
- décision runtime mutable ayant un effet observable.
Une crate passive contient uniquement des types, contrats, DTO, traits sans implémentation, registres ou constantes. Elle ne dépend pas de `tracing`. `kb_config` reste une exception de bootstrap : son chargement et sa validation précèdent linstallation du subscriber.
## Cible canonique
Toute crate opérationnelle hors `kb-lib` qui déclare `tracing.workspace = true` doit :
- posséder `src/constants.rs` ;
- définir exactement une constante `pub(crate) const TRACING_TARGET` ;
- utiliser comme valeur le nom exact du package Cargo ;
- réexporter la constante depuis sa façade puis appeler les macros avec `target: crate::TRACING_TARGET` ;
- déplacer la granularité interne dans des champs structurés.
`kb-lib` constitue une exception architecturale volontaire : chaque décodeur, matérialiseur ou exécuteur opérationnel possède son propre `constants.rs` et un target hiérarchique `kb-lib.<famille>.<surface>`. Le target reçoit son nom préfixé canonique dans son module propriétaire, puis la façade de `kb-lib` le réexporte sans alias afin que plusieurs composants puissent coexister sans collision.
Exemple :
```rust
tracing::error!(
target: crate::SOLANA_CORE_TRACING_TARGET,
action = "decoder_outcome_failure",
campaign_id = %campaign_id,
signature = %input.signature,
instruction_path = %input.instruction_path,
program_id = %input.program_id,
processor_name = %identity.name,
processor_version = %identity.version,
status = ?result.status,
diagnostics = ?result.diagnostics,
"contextual instruction was not decoded successfully"
);
```
Les targets `khbot.*` et les targets de fenêtre ne sont plus utilisés par les composants opérationnels migrés. Les identifiants frontend historiques restent acceptés comme valeurs du champ `frontend_target`, mais lévénement Rust est émis sous le target canonique de lapplication.
## Crates actuellement routées
Les targets déjà migrés vers les noms canoniques bot3 sont :
```text
kb-lib.decoder.solana.core
kb-lib.decoder.metadata.metaplex_token_metadata
kb-lib.decoder.spl.associated_token_account
kb-lib.decoder.spl.elgamal_registry
kb-lib.decoder.spl.memo
kb-lib.decoder.spl.token
kb-lib.decoder.spl.token2022
kb-lib.materializer.admin
kb-lib.materializer.compliance
kb-lib.materializer.lifecycle
kb-lib.materializer.risk
kb-lib.materializer.staking
kb-lib.materializer.token
kb-lib.materializer.transaction
kb-logging
kb-store
```
Laudit `audit_khadhroony_workspace_rules.py` vérifie les targets de crates et les targets hiérarchiques de `kb-lib`. Il interdit également les faux usages `let _target` et impose que chaque macro de `kb-lib` utilise le nom préfixé réexporté sans transformation par la façade.
Les routes sont filtrées au niveau de leur writer plutôt que par un `Filtered` layer distinct. Un seul filtre dadmission agrégé empêche en amont le formatage des événements refusés par toutes les routes. Cette architecture préserve toutes les sorties globales et par crate au-delà de la limite interne de 64 identifiants de filtres de `tracing-subscriber`. Le test `more_than_64_routes_compose_without_filtered_layer_ids` protège explicitement ce contrat.
## Granularité et corrélation
Le target identifie la crate. Les champs décrivent laction et le contexte :
```text
action
stage
window
campaign_id
capture_session_id
signature
slot
instruction_path
program_id
processor_name
processor_version
materializer_name
materializer_version
input_key
input_hash
status
decision
error_code
```
Les spans de campagne et dinput utilisent eux aussi le target canonique `kb_pipeline`. Les événements des autres crates conservent leur propre target et reprennent les identifiants de corrélation utiles dans leurs champs.
## Politique des erreurs de décodage et de matérialisation
Un événement `error` est obligatoire pour :
- un input sélectionné sans décodeur compatible ;
- un résultat de décodeur `failed` ;
- un résultat de décodeur `unsupported` après dispatch vers une surface déclarée compatible ;
- un résultat de décodeur invalide au regard du contrat API ;
- un résultat de matérialiseur `failed` ;
- une erreur de persistance decode, couverture, ledger ou matérialisation ;
- une campagne qui termine avec `unmatched > 0` ou `failed_inputs > 0`.
Lévénement doit permettre de retrouver rapidement linput et la cause. Il conserve, lorsque disponibles, la campagne, la signature, le slot, le chemin dinstruction, le program ID, lidentité et la version du processor, la clé/hash dinput, le statut et les diagnostics structurés.
Les cas suivants ne sont pas des erreurs logicielles :
- transaction Solana échouée mais payload correctement décodé ;
- observation non commitée conformément au statut on-chain ;
- matérialisation `refused` par la politique de transaction ;
- entrée volontairement `ignored` avec justification ;
- annulation coopérative demandée par lopérateur.
Ils sont journalisés en `debug`, `info` ou `warn` selon leur impact.
## Responsabilité
- `kb-onchain-transport` : sélection dendpoint, requêtes, réponses bornées, retry, rate limit et transport.
- composants `kb-lib.executor` : assemblage du message, contrôle du contrat de signataires, liaison de simulation et signature transactionnelle.
- `kb-store` : transactions SQL, commit/rollback, compteurs et erreurs de persistance.
- `kb-pipeline` : sélection, dispatch, concurrence, annulation, backfill et agrégation.
- décodeur : reconnaissance, validation du format, décision et diagnostic borné.
- matérialiseur : applicabilité exacte, politique de transaction et sorties produites.
- exécuteur : support, construction, simulation et garde-fous.
- application : invocation Tauri, fenêtre, progression utilisateur et résumé final.
## Données interdites
Ne jamais journaliser :
- clé privée, seed phrase ou transaction à signer ;
- DSN ou URL contenant un secret non masqué ;
- payload brut complet ou réponse RPC volumineuse ;
- donnée dynamique non bornée.
Conserver à la place la taille, un préfixe borné et un SHA-256 lorsque laudit du payload est nécessaire.
## Évolution
Lajout ou la suppression de `tracing.workspace = true` impose dans le même delta :
1. la constante canonique ou sa suppression ;
2. les événements réels de la crate ;
3. la mise à jour de `config/example.config.json` ;
4. la mise à jour des tests de contrat ;
5. la mise à jour de la liste ci-dessus.
Pour un composant de `kb-lib`, les mêmes obligations sappliquent au target hiérarchique, à son nom préfixé de façade et à ses routes dédiées.

View File

@@ -1,137 +0,0 @@
<!-- file: docs/TRANSACTION_ACQUISITION_MODEL.md -->
<!-- version: 5 -->
# Modèle dacquisition des transactions Solana
## Décision
Le pipeline ne conserve pas un payload complet différent pour chaque fournisseur. Toutes les sources doivent produire une représentation canonique commune avant lécriture principale.
```text
getTransaction JSON-RPC
Helius transactionSubscribe JSON
Yellowstone gRPC Protobuf
logsSubscribe + getTransaction
backfill ou réparation
|
v
adaptateur de source dans kb_onchain_transport
|
v
transaction Solana canonique
|
+--> kb_sol_raw_transactions
|
+--> kb_sol_obs_transaction_observations
```
## Transaction canonique
`kb_sol_raw_transactions` contient une seule ligne par signature. Le contenu est indépendant du fournisseur et ne doit contenir aucun champ propre à Helius, Triton, Chainstack, Shyft ou un endpoint particulier.
Le document canonique doit inclure, quand la source les fournit :
- signature ;
- slot ;
- version de transaction ;
- message header ;
- static account keys ;
- Address Lookup Tables ;
- loaded writable et readonly addresses ;
- recent blockhash ;
- outer instructions ;
- inner instructions ;
- logs ;
- statut et erreur ;
- fee et compute units ;
- balances SOL avant/après ;
- balances SPL avant/après ;
- rewards ;
- return data ;
- block time.
Les public keys et signatures restent en base58, avec validation stricte de leur taille décodée : 32 octets pour les clés et blockhashes, 64 octets pour les signatures. Les données binaires dinstruction restent en base64. Les montants SPL conservent le montant entier brut normalisé sans zéros non significatifs, les décimales et une représentation décimale fixe recalculée localement, sans dépendre de `uiAmount` ou `uiAmountString` du fournisseur.
Depuis `0.3.2`, ce contrat est matérialisé par `kb_model::CanonicalTransaction` avec `canonical_format_version = 1`. La sérialisation trie récursivement les clés des objets JSON avant calcul dun hash SHA-256 sur le document compact. Les tableaux conservent lordre Solana dorigine. Les détails de source, timestamps locaux et identifiants de subscription sont exclus du document hashé.
Ladaptateur HTTP standard demande `encoding = json`, puis convertit explicitement les payloads dinstruction reçus en base58 vers la représentation base64 canonique. Les champs optionnels absents et `null` sont normalisés vers le même état interne afin de stabiliser le hash entre réponses compatibles.
## Observations de source
`kb_sol_obs_transaction_observations` décrit comment et quand une transaction a été détectée ou reçue. Elle ne duplique pas la transaction complète.
Champs minimaux visés :
| Champ | Rôle |
|-----------------------|----------------------------------------------------------------------------------------------|
| `observation_key` | clé idempotente de lobservation |
| `raw_transaction_id` | lien optionnel vers la transaction canonique |
| `signature` | signature observée |
| `slot` | slot observé quand connu |
| `provider` | fournisseur, par exemple `helius`, `triton`, `chainstack`, `shyft` |
| `endpoint_code` | endpoint de configuration utilisé |
| `protocol` | `solana_http_json_rpc`, `solana_ws_json_rpc`, `helius_ws` ou `yellowstone_grpc` |
| `acquisition_method` | `getTransaction`, `transactionSubscribe`, `yellowstone_transactions`, `logs_hydration`, etc. |
| `origin` | `live`, `backfill`, `replay`, `repair` ou `migration` |
| `commitment` | commitment demandé ou observé |
| `capture_session_id` | session ou campagne de capture |
| `filter_code` | profil de filtre utilisé |
| `detected_at` | réception du premier signal, par exemple le log |
| `received_at` | réception de la transaction complète |
| `normalized_at` | fin de normalisation canonique |
| `persisted_at` | fin décriture durable |
| `payload_size_bytes` | taille du message source reçu |
| `source_payload_hash` | hash optionnel du message source sans le conserver |
| `status` | `detected`, `received`, `normalized`, `persisted`, `failed` ou `missing` |
| `error_code` | code technique normalisé optionnel |
| `error_message` | message de diagnostic optionnel |
Les observations permettent de comparer les sources par signature, sans multiplier le volume de stockage transactionnel.
## Notifications WebSocket
`kb_sol_raw_ws_notifications` nest plus une cible durable.
Une notification `logsSubscribe` peut être conservée temporairement en mémoire jusquà lhydratation de la transaction. La base conserve ensuite seulement :
- les timestamps utiles ;
- la signature et le slot ;
- la source et la méthode ;
- la taille ;
- le statut de lhydratation ;
- le lien éventuel vers la transaction canonique.
Les notifications non transactionnelles comme `slotSubscribe`, `accountSubscribe` ou `programSubscribe` pourront avoir des tables métier dédiées seulement si un besoin durable apparaît. Elles ne doivent pas être entassées dans une table générique de payloads WebSocket.
## Fusion multi-source
Pour une signature déjà présente :
1. normaliser le nouveau message ;
2. calculer le hash canonique ;
3. ajouter lobservation de source ;
4. si le hash est identique, ne pas dupliquer la transaction ;
5. si la nouvelle source apporte uniquement des champs auparavant absents, appliquer un enrichissement déterministe ;
6. si des champs incompatibles diffèrent, ne pas écraser silencieusement et enregistrer un conflit technique.
Les différences liées au commitment ou à la disponibilité progressive des metadata doivent être distinguées dun conflit réel.
## Raw provider facultatif
Un payload fournisseur complet peut être exporté de façon bornée pour une campagne de diagnostic, par exemple en NDJSON ou Protobuf, mais il ne fait pas partie du stockage PostgreSQL transactionnel normal.
Ces exports doivent être :
- explicitement activés ;
- limités en durée et en volume ;
- associés à une session de capture ;
- supprimables sans affecter les replays métier.
## Frontières des crates
- `kb_onchain_transport` contient les transports et adaptateurs HTTP, WebSocket Helius et Yellowstone gRPC.
- `kb_model` contient le contrat canonique source-indépendant.
- `kb_store_core` contient les DTOs et repositories de transactions et observations.
- `kb_store_pg` contient la migration, les queries et les repositories PostgreSQL.
- les décodeurs ne dépendent jamais de la source dacquisition.

View File

@@ -1,66 +0,0 @@
<!-- file: docs/V0_4_6_VALIDATION.md -->
<!-- version: 1 -->
# Validation finale `0.4.6`
## Périmètre
Le jalon couvre Token-2022 et le registre ElGamal comme programmes distincts, ainsi que la régression des décodeurs Solana Core/SPL livrés auparavant. Il ne transforme pas Anchor, Metaplex ou les futurs DEX en surfaces implicitement couvertes.
## Résultats de tests
| Suite | Résultat |
|------------------------------------|---------:|
| `kb_store_core` | 41/41 |
| `kb_store_pg` avec PostgreSQL réel | 46/46 |
| `kb_pipeline` | 124/124 |
| `kb_app_demo` | 118/118 |
| `cargo clippy --all-targets` | propre |
Les contrôles SQL sur `kb_sol_decode_events` et `kb_sol_mat_events` ne révèlent aucun doublon didentité.
## Token-2022 et ElGamal Registry
- 55 instructions Token-2022 Mainnet ont été décodées sans échec persistant.
- Huit opérations publiques Token-2022 ont été confirmées sur Devnet : `MintToChecked`, `TransferChecked`, `ApproveChecked`, `Revoke`, `BurnChecked`, `FreezeAccount`, `ThawAccount` et `CloseAccount`.
- Chaque parcours Devnet a été simulé, confirmé, hydraté, extrait, décodé, matérialisé puis rejoué idempotemment.
- ElGamal Registry est validé synthétiquement/offline pour le wire, le PDA, létat, les lectures RPC, les préflights et les preuves.
- La validation publique ElGamal Registry reste indisponible sur Devnet/Mainnet au 20 juillet 2026 ; aucune preuve réseau nest revendiquée.
## Loader immuable et Loader v4
Le parser `Write` du loader immuable lit désormais la longueur vectorielle en `u32` et les données à loffset 12. Le replay Mainnet a supprimé 68 diagnostics `loader_vector_length_mismatch`.
Les rejets persistants restants sont tous issus de transactions Solana échouées :
| Diagnostic | Nombre |
|----------------------------------|-------:|
| `immutable_loader_tag_truncated` | 31 |
| `loader_v4_tag_truncated` | 44 |
| `loader_accounts_invalid` | 1 |
Quatre variantes Loader v4 inconnues sont persistées comme traitement réussi avec résultat métier `Unsupported`. Elles ne sont pas assimilées à des décodages complets.
## Replay des signatures incomplètes
Le mode `incomplete_signatures` sélectionne les signatures contenant au moins une instruction `pending`, `failed`, `replay_requested` ou `unsupported`. La limite est appliquée au nombre de signatures avant expansion vers les instructions compatibles. Ce mode ne nécessite pas de force replay global.
Deux campagnes PostgreSQL réelles successives ont produit exactement :
```text
selected=81
started=81
completed=81
unmatched=0
notStarted=0
failedInputs=76
decoded=1
unsupported=4
failed=76
```
Linstruction décodée appartient à une signature incomplète contenant également une instruction valide. La répétition identique du second passage confirme la sélection stable ; les événements et matérialisations restent idempotents.
## Conclusion
Tous les décodeurs livrés jusquà `0.4.6` respectent leur contrat sur les tests synthétiques, les scénarios stateful et les données réseau observées. Les payloads malformés sont rejetés fail-closed et les variantes inconnues sont classées explicitement `Unsupported`. Cette conclusion ne prétend pas que chaque variante rare possible a été observée sur un cluster public.

View File

@@ -1,30 +0,0 @@
<!-- file: docs/VERSION_HEADER_AUDIT.md -->
<!-- version: 1 -->
# Audit des en-têtes de version
Ce document regroupe les commandes utiles pour vérifier les en-têtes `file:` et `version:`.
## Lignes `version` différentes de 1
La commande suivante utilise deux passes pour éviter les problèmes de lookahead et d'expansion d'historique Bash :
```bash
rg -n -P '^\s*(//|#|<!--|--|/\*)\s*version\s*:\s*[0-9]+' -g '!target/**' -g '!node_modules/**' -g '!dist/**' -g '!idls/**/*.json' . | rg -v -P 'version\s*:\s*1\s*(-->|\*/)?\s*$'
```
## Fichiers concernés uniquement
```bash
rg -n -P '^\s*(//|#|<!--|--|/\*)\s*version\s*:\s*[0-9]+' -g '!target/**' -g '!node_modules/**' -g '!dist/**' -g '!idls/**/*.json' . | rg -v -P 'version\s*:\s*1\s*(-->|\*/)?\s*$' | cut -d: -f1 | sort -u
```
## Fichiers commentables sans ligne `version`
```bash
find . -path './target' -prune -o -path './node_modules' -prune -o -path './dist' -prune -o -path './idls' -prune -o -type f \( -name '*.rs' -o -name '*.toml' -o -name '*.sql' -o -name '*.md' -o -name '*.ts' -o -name '*.js' -o -name '*.html' -o -name '*.scss' -o -name '*.sass' \) -print | while read -r f; do
if ! head -n 5 "$f" | rg -q 'version\s*:'; then
echo "$f"
fi
done
```

View File

@@ -1,69 +0,0 @@
<!-- file: docs/WS_LISTENERS.md -->
<!-- version: 4 -->
# Listeners WebSocket
## Statut
Les listeners temps réel ne dirigent plus `0.3.x`. Ils seront repris après les décodeurs Core, Pump, Meteora, Raydium, Orca et Jupiter.
## Méthodes déjà présentes dans `demo_ws`
```text
slotSubscribe
slotsUpdatesSubscribe
rootSubscribe
logsSubscribe
accountSubscribe
programSubscribe
signatureSubscribe
blockSubscribe
voteSubscribe
```
Laudit confirme encore labsence de :
```text
transactionSubscribe
transactionUnsubscribe
request kind transaction_subscribe
classification logs_subscribe_all
```
Ces ajouts sont reportés à `0.10.x`.
## Modèle futur
```text
Helius transactionSubscribe
Yellowstone gRPC transactions
logsSubscribe + hydration
|
v
transaction canonique commune
|
+--> kb_sol_raw_transactions
+--> kb_sol_obs_transaction_observations
```
Le payload complet de la notification WebSocket ne doit pas être stocké durablement lorsquune transaction canonique existe.
## Cas dusage
Les flux devront détecter rapidement :
- création de token ou pool ;
- premiers swaps ;
- migration ;
- changement de liquidité ;
- activité administrative dangereuse ;
- frais et buybacks ;
- changements sur les comptes critiques.
## Sécurité
- Aucun ordre direct depuis la couche transport.
- Toute perte du flux principal désactive le trading.
- Les événements rejoués ou backfillés mettent à jour létat sans déclencher rétroactivement un ordre.
- Les queues, tailles, retries et exports de diagnostic restent bornés.