v0.1.0-pre.064-065
This commit is contained in:
208
olddocs/archivekbot2/CHANGELOG.md
Normal file
208
olddocs/archivekbot2/CHANGELOG.md
Normal file
@@ -0,0 +1,208 @@
|
||||
<!-- file: CHANGELOG.md -->
|
||||
<!-- version: 26 -->
|
||||
|
||||
# Changelog
|
||||
|
||||
Ce fichier est réservé aux versions validées. Les changements non validés restent décrits dans `ROADMAP.md` ou `RULES.md`.
|
||||
|
||||
## 0.0.1 — projet vide
|
||||
|
||||
Initialisation du dépôt comme point de départ vide. Cette version sert uniquement de repère historique avant la création du squelette modulaire.
|
||||
|
||||
## 0.0.2 — squelette stabilisé
|
||||
|
||||
Validation du squelette initial de `khadhroony-bot2` : workspace Rust modulaire, règles de développement, nomenclature des surfaces, registres de programmes, configuration multi-profils, couche d'exécution réservée, décodeurs/exécuteurs/matérialisateurs réservés, documentation de cadrage, prompts de session et application Tauri de démonstration en squelette. Cette version devient la base propre avant le développement `0.1.x` consacré à `kb_logging` et `kb_config`.
|
||||
|
||||
## 0.1.0 — `kb_logging` réel
|
||||
|
||||
Validation du jalon `kb_logging` : API publique minimale, initialisation `tracing_subscriber`, routes console, fichier humain, fichier JSON et fichier erreurs, filtrage par target et niveau, nettoyage ANSI des fichiers pour les messages issus de WebView Tauri, support des globs `crate.*` et `crate::*`, et couverture unitaire renforcée. Validation locale effectuée : `cargo test -p kb_logging` avec 14 tests passés et `cargo clippy -p kb_logging --all-targets` sans erreur. `cargo fmt` n'est pas retenu comme validation obligatoire du jalon, car la configuration `rustfmt.toml` contient des options nightly non applicables sur stable et le formatage courant est géré depuis Eclipse.
|
||||
|
||||
## 0.1.1 — `kb_config` typé et validé
|
||||
|
||||
Validation du jalon `kb_config` : configuration JSON multi-profils avec un seul profil actif, schéma `config/schema.config.json` validé via `jsonschema`, désérialisation typée, validation métier des profils, endpoints HTTP JSON-RPC et WebSocket Solana standard, listeners standards, sorties de logging configurables, stores PostgreSQL/SQLite, wallet, exécution et sections de démonstration. Les placeholders de clés restent directement dans les URLs et les champs runtime hors périmètre avant `v1.x` sont refusés par le schéma. Les exports TS-rs suivent la convention `../frontend/ts/bindings/kb_config/settings/<Type>.ts`. Validation locale effectuée : `cargo test --tests -p kb_config` avec 35 tests passés, dont les tests générateurs TS-rs `export_bindings_*`, et `cargo clippy` annoncé sans erreur pour le jalon.
|
||||
|
||||
## 0.1.2 — liaison `kb_logging`, `kb_config` et démo Tauri
|
||||
|
||||
Validation du jalon d’intégration Tauri : `kb_app_demo` charge le profil actif via `kb_config`, initialise `kb_logging` depuis cette configuration, conserve un `AppState` global, garde `demo_config` comme fenêtre de démonstration isolée et réémet les logs frontend vers `tracing` avec des targets statiques. La fenêtre principale rend le README workspace en HTML via `markdown-it`, expose un dropdown de démos, et la fenêtre configuration affiche le profil actif, la configuration complète et le schéma JSON avec un viewer JSON interactif. Le verrou mono-instance est appliqué uniquement dans `kb_app_demo/src/main.rs` afin de préserver l’entrée mobile par `kb_app_demo_lib::run()`. Le provider Rustls par défaut est initialisé dans la librairie pour desktop et mobile. Le splashscreen est aligné sur le modèle de `khadhroony-bobobot/kb_demo_app`, avec fade-in/fade-out, durée minimale extensible et attente initiale avant fade-in pour éviter l’apparition instantanée. `kb_core` expose maintenant l’erreur et le résultat communs sous `kb_core::Error` et `kb_core::Result`. Validation locale effectuée : `cargo test -p kb_core` avec 2 tests passés, `cargo test -p kb_config` avec 35 tests passés, `cargo test -p kb_logging` avec 14 tests passés, `cargo test -p kb_app_demo` avec 12 tests passés, `cargo clippy --all-targets` sans erreur et validation visuelle via `cargo tauri dev -c kb_app_demo/tauri.conf.json`.
|
||||
|
||||
## 0.1.3 — clients HTTP/WS Solana standard, rôles et pools
|
||||
|
||||
Validation du jalon RPC initial : `kb_rpc` expose les contrats JSON-RPC 2.0 partagés, le routage par rôle et `request_kind`, les clients HTTP JSON-RPC et WebSocket Solana standard, ainsi que les pools HTTP/WS par rôle. `kb_app_demo` ajoute les fenêtres dédiées `demo_http` et `demo_ws`, les listes contrôlées de rôles et méthodes, le refresh explicite des pools, le profil `mainnet` Helius, la connexion WebSocket persistante conservée dans `AppState`, les subscriptions multiples sur une même socket, l’unsubscribe individuel, la déconnexion globale à l’arrêt de l’application et le throttling des notifications WebSocket vers la WebView pour éviter les freezes sur les programmes très bavards. Les transports gRPC, Helius enhanced WebSocket, Helius gRPC et LaserStream restent hors périmètre avant les versions ultérieures. Validation locale effectuée : `cargo test -p kb_rpc` avec 39 tests passés, `cargo test -p kb_app_demo` avec 28 tests passés, `cargo clippy --all-targets` sans erreur, et validation visuelle des démos HTTP/WS via `cargo tauri dev -c kb_app_demo/tauri.conf.json`.
|
||||
|
||||
## 0.2.0 — conventions PostgreSQL et contrats DB
|
||||
|
||||
Validation du jalon de cadrage stockage : conventions PostgreSQL définies autour du schéma courant/default du profil, généralement `public`, sans espaces applicatifs séparés, et convention de tables Solana `kb_sol_<domain>_<name>` avec les domaines `raw`, `core`, `obs`, `decode`, `mat`, `catalog`, `agg`, `ops` et `wallet` intégrés au nom de table. Les règles SQL de base sont documentées pour `id`, `created_at`, `updated_at`, `slot`, `signature`, `program_id`, `raw_json` et `payload_json`, avec index minimaux et contraintes strictes mais réversibles. Les responsabilités de `kb_store_core` et `kb_store_pg` sont clarifiées, avec séparation `entities/`, `dtos/`, `queries/` et `repositories/`, et interdiction de placer des structures métier ou DB dans les requêtes. Les migrations historiques de brouillon sont neutralisées afin de ne pas créer d'espace PostgreSQL applicatif ni de table qualifiée par espace logique. Validation locale effectuée : `cargo test -p kb_config` avec 35 tests passés, `cargo test -p kb_app_demo` avec 28 tests passés et `cargo clippy --all-targets` sans erreur. `kb_store_core` et `kb_store_pg` ne disposent pas encore de tests à ce stade documentaire.
|
||||
|
||||
## 0.2.1 — contrats `kb_store_core` et replay instruction-level
|
||||
|
||||
Validation du jalon de contrats storage : `kb_store_core` expose les types communs backend-agnostiques pour pagination, healthcheck, migrations, erreurs de stockage, DTOs applicatifs, entities proches SQL et traits repositories sans implémentation PostgreSQL. Les contrats couvrent le raw RPC et WebSocket, le cycle de vie raw `Full` / `Compacted` / `Archived` / `Purged`, les états de traitement raw, la signature optionnelle des notifications WebSocket, la déduplication par `notification_key`, le lien futur optionnel notification vers transaction canonique, ainsi que le replay par instruction. Le replay est défini comme un scheduling au niveau instruction, mais le décodage reçoit un contexte extrait complet via `CoreInstructionReplayInput` : instruction ciblée, account keys, logs, balance changes et contexte transactionnel minimal. Les repositories restent abstraits et ne créent encore ni pool PostgreSQL, ni migration SQL réelle. Validation locale effectuée : `cargo test -p kb_store_core` avec 28 tests passés et `cargo clippy --all-targets` sans avertissement. Les validations précédentes du jalon ont également confirmé `kb_store_pg` sans test actif, `kb_config` avec 35 tests passés et `kb_app_demo` avec 28 tests passés.
|
||||
|
||||
## 0.2.2 — infrastructure PostgreSQL minimale
|
||||
|
||||
Validation du jalon d'infrastructure PostgreSQL : `kb_store_pg` expose maintenant une première implémentation réelle avec options de connexion, pool `sqlx::PgPool`, construction depuis la configuration active, masquage du DSN pour les diagnostics, healthcheck `SELECT 1`, lecture du schema courant, lecture de la version PostgreSQL et snapshot de migrations non destructif. La stratégie de migrations reste volontairement cadrée sans créer les tables Solana lourdes, qui sont reportées à `0.2.3` pour le raw store minimal. Les validateurs de noms de tables imposent la convention `kb_sol_<domain>_<name>` et refusent les schemas explicites. Validation locale effectuée : `cargo test -p kb_store_pg` avec 11 tests passés, test PostgreSQL réel optionnel `optional_postgres_healthcheck_from_env` validé avec `KB_POSTGRES_TEST_URL=postgres://solana:solana@localhost:5432/solana`, `cargo test -p kb_store_core` avec 28 tests passés, `cargo test -p kb_config` avec 35 tests passés, `cargo test -p kb_app_demo` avec 28 tests passés et `cargo clippy --all-targets` sans avertissement après remplacement local de l'exception `allow` par `expect` sur l'incompatibilité connue `async_trait` / `clippy::implicit_return`.
|
||||
|
||||
## 0.2.3 — raw store Solana minimal
|
||||
|
||||
Validation du jalon raw store minimal : `kb_store_pg` crée et initialise les deux premières tables Solana réelles, `kb_sol_raw_rpc_transactions` et `kb_sol_raw_ws_notifications`, sans créer de schema PostgreSQL applicatif explicite. Le raw RPC est inséré de façon idempotente par signature, les notifications WebSocket sont dédupliquées par `notification_key`, la signature des notifications reste optionnelle et le lien vers la transaction RPC canonique est préparé pour les étapes suivantes. Les tables conservent les champs de cycle de vie `retention_state`, `processing_state`, `processed_at` et `processing_reason`, avec `raw_json` nullable côté SQL afin de permettre les futures politiques `compacted`, `archived` et `purged` sans migration cassante. Les requêtes et l'implémentation PostgreSQL de `RawTransactionStore` couvrent les insertions, lookup de signature, lookup de notification et marquage lifecycle. Validation locale effectuée : `cargo test -p kb_store_pg` avec 21 tests passés, incluant le test PostgreSQL réel optionnel `optional_postgres_raw_store_roundtrip_from_env` avec `KB_POSTGRES_TEST_URL=postgres://solana:solana@localhost:5432/solana`, `cargo test -p kb_store_core` avec 28 tests passés, `cargo test -p kb_config` avec 35 tests passés, `cargo test -p kb_app_demo` avec 28 tests passés et `cargo clippy --all-targets` sans avertissement. Une correction locale du test raw PostgreSQL a été intégrée pour appeler directement `test_signature()` depuis le module de test.
|
||||
|
||||
## 0.2.4 — core Solana normalisé minimal
|
||||
|
||||
Validation du jalon core store minimal : `kb_store_pg` crée et initialise maintenant les tables core `kb_sol_core_transactions`, `kb_sol_core_account_keys`, `kb_sol_core_instructions`, `kb_sol_core_inner_instructions`, `kb_sol_core_logs` et `kb_sol_core_balance_changes`, en complément du raw store `0.2.3`, sans schema PostgreSQL applicatif explicite. Les migrations et l'initializer utilisent des noms SQL préfixés et explicites pour les contraintes et index : `pk_`, `fk_`, `ck_`, `ux_` et `ix_`. L'initialisation raw/core est sérialisée par un verrou PostgreSQL `pg_advisory_xact_lock` afin d'éviter les courses concurrentes pendant les tests ou les démarrages parallèles. `CoreTransactionStore` dispose de l'implémentation PostgreSQL minimale pour insérer les transactions core, account keys, instructions, inner instructions, logs et deltas de balances, puis reconstruire `CoreInstructionReplayInput` pour les futurs décodeurs. Le script de maintenance `kb_store_pg/maintenance/drop_raw_core_store.sql` permet de réinitialiser explicitement les tables raw/core locales dans l'ordre inverse des dépendances. Validation locale effectuée : `KB_POSTGRES_TEST_URL=postgres://solana:solana@localhost:5432/solana cargo test -p kb_store_pg -- --nocapture` avec 30 tests passés, création vérifiée des 8 tables dans PostgreSQL, réinitialisation validée via le script de maintenance, puis `cargo clippy --all-targets` sans avertissement. Le worker d'extraction raw RPC vers core, les observations et le ledger ops sont conservés pour les jalons suivants.
|
||||
|
||||
## 0.2.5 — diagnostics SQL PostgreSQL dans `kb_app_demo`
|
||||
|
||||
Validation du jalon diagnostics SQL : `kb_app_demo` ajoute les fenêtres `demo_sql_diag`, `demo_sql_pg_raw` et `demo_sql_pg_core` pour inspecter en lecture seule l’état PostgreSQL courant. Le démarrage Tauri tente l’initialisation raw/core lorsque `database.postgres.auto_initialize_schema` est actif, journalise les tables créées ou déjà présentes via le splashscreen et `tracing`, puis les fenêtres exposent le profil actif, le backend, le DSN masqué, le schema courant, le healthcheck, l’état migrations et les statistiques de tables raw/core. Les payloads JSON des trois fenêtres utilisent le viewer interactif déjà utilisé par `demo_config`, sans ajouter de nouvelle dépendance npm. Le jalon ne lance ni extracteur raw RPC vers core, ni décodage, ni matérialisation ; ces traitements restent reportés à `0.3.x`. Validation locale effectuée : `cargo test -p kb_store_pg` avec 30 tests passés, `cargo test -p kb_config` avec 35 tests passés, `cargo test -p kb_app_demo` avec 32 tests passés, `cargo clippy --all-targets` sans avertissement, et validation visuelle des trois fenêtres via `cargo tauri dev -c kb_app_demo/tauri.conf.json`.
|
||||
|
||||
## 0.3.0 — cadrage Agave local et sources temps réel
|
||||
|
||||
Validation du jalon de cadrage `0.3.x` : la phase ingestion/backfill/extraction raw vers core est reportée à `0.4.x`, tandis que `0.3.x` devient une phase d’expérimentation Agave local non votant et de stratégie live source. Le jalon documente le profil manuel `agave_local_research`, la commande de départ `agave-validator`, les probes RPC/WS attendus, les mesures ledger/accounts/CPU/RAM/réseau/lag, les règles de fallback vers les providers externes et les critères de décision avant `0.4.x`. Le profil Agave reste désactivé par défaut afin de préserver `mainnet_research` comme base stable, et aucune ingestion de production, aucun backfill historique, aucun décodage DEX, aucune matérialisation et aucune opération de trading ne sont introduits dans ce jalon. Validation locale du delta `0.3.0-pre.001` confirmée par l’utilisateur avant mise à jour du changelog.
|
||||
|
||||
## 0.3.1 — transaction canonique et observations d’acquisition
|
||||
|
||||
Validation du jalon de stockage canonique : `kb_sol_raw_transactions` conserve désormais une transaction source-indépendante par signature avec `canonical_json`, `canonical_json_hash` et `canonical_format_version`, tandis que `kb_sol_obs_transaction_observations` conserve uniquement les informations de provenance, méthode, session, timestamps, taille, statut et erreur sans dupliquer le payload complet. La lignée core utilise `raw_transaction_id`; les DTOs, entities, repositories, requêtes et diagnostics Tauri ont été alignés. La migration réelle depuis le schéma `0.2.x` a été contrôlée sur PostgreSQL 17.10 : les anciennes tables `kb_sol_raw_rpc_transactions` et `kb_sol_raw_ws_notifications` sont absentes, les tables canoniques sont présentes et les colonnes actives portent les nouveaux noms. Après cette validation, les fichiers SQL ont été consolidés en une baseline propre ne contenant que `0001_canonical_transaction_store.sql` et `0002_core_store.sql`; les fichiers SQL actifs n’embarquent plus les anciennes définitions de tables. Validation locale effectuée : `cargo test -p kb_app_demo` avec 32 tests passés, `cargo test -p kb_store_core` avec 30 tests passés, `KB_POSTGRES_TEST_URL=postgres://solana:solana@localhost:5432/solana cargo test -p kb_store_pg -- --nocapture` avec 32 tests passés, `cargo clippy --all-targets` sans avertissement, démarrage Tauri validé et diagnostics des huit tables raw/obs/core confirmés. Les fixtures PostgreSQL de test ont été nettoyées manuellement après validation.
|
||||
|
||||
## 0.3.2 — contrat canonique et adaptateur HTTP
|
||||
|
||||
Validation du jalon transactionnel canonique : `kb_model` expose désormais un modèle source-indépendant couvrant les transactions legacy et version 0, le message, les comptes statiques et chargés par Address Lookup Tables, les instructions externes et internes, les logs, le statut et les erreurs, les frais, compute units et cost units, les balances SOL et SPL/Token-2022, les rewards, les return data et le block time lorsqu’ils sont disponibles. Les signatures et clés publiques restent en base58, les données d’instruction sont normalisées en base64, les montants SPL bruts sont canonicalisés sans perte et la sérialisation déterministe trie récursivement les objets JSON avant calcul du hash SHA-256. `kb_rpc` fournit l’adaptateur `getTransaction` JSON-RPC et l’interface commune préparant les futurs adaptateurs Helius WebSocket et Yellowstone gRPC dans la crate existante, tandis que `kb_store_core::RawTransactionInsert::from_canonical` relie le modèle au store canonique. Les fixtures offline couvrent legacy/v0, succès/échec, ALT, CPI, SPL Token et Token-2022, et les formes fournisseur équivalentes produisent le même hash. Validation locale effectuée : `cargo test -p kb_model` avec 23 tests passés, `cargo test -p kb_rpc` avec 48 tests passés, `cargo test -p kb_store_core` avec 31 tests passés, `KB_POSTGRES_TEST_URL=postgres://solana:solana@localhost:5432/solana cargo test -p kb_store_pg -- --nocapture` avec 32 tests passés, puis `cargo clippy --all-targets` sans avertissement après ajout des retours explicites imposés par `clippy::implicit_return`. Les fixtures PostgreSQL du roundtrip ont été nettoyées manuellement après validation.
|
||||
|
||||
## 0.3.3 — backfill HTTP gratuit et `demo_backfill`
|
||||
|
||||
Validation du jalon de backfill HTTP : `kb_rpc` expose désormais `getSignaturesForAddress` avec pagination `before` / `until`, tandis que `getTransaction` alimente le modèle canonique sans conserver durablement le payload fournisseur. `kb_pipeline` orchestre les campagnes de signatures explicites et les recherches avant ou après une signature pour un programme, un token ou un pool, avec déduplication, limites de pages, reprise exportable, concurrence, temporisation, retries bornés, arrêt coopératif et journalisation détaillée. Le parcours `after` utilise la borne RPC `until`, des pages pouvant atteindre 1 000 signatures et une sélection bornée en mémoire afin de ne conserver que les `X` signatures directement postérieures à l’ancre dans l’historique de l’adresse. `kb_app_demo` ajoute la fenêtre `demo_backfill`, organisée en accordéons Bootstrap 5, avec paramètres communs, textarea de signatures, formulaires programme/token/pool, journal, résumé et commande d’arrêt. Chaque transaction complète est insérée une seule fois dans `kb_sol_raw_transactions`; chaque tentative d’acquisition produit une observation légère dans `kb_sol_obs_transaction_observations`, tandis que les résultats `missing` et `failed` ne créent aucun faux payload canonique.
|
||||
|
||||
La correction finale de l’arrêt coopératif remplace la création globale des futures par une file bornée à la concurrence effective, distingue les candidats sélectionnés, démarrés, terminés, annulés et non démarrés, et calcule `resume_before_signature` depuis le dernier préfixe contigu réellement terminé. Une campagne réelle de 500 candidats a validé l’arrêt avec 7 candidats démarrés, 3 terminés, 4 annulés et 493 non démarrés, sans journalisation artificielle des candidats restants. Validation locale effectuée : `cargo test -p kb_rpc` avec 54 tests passés, `cargo test -p kb_pipeline` avec 10 tests passés, `cargo test -p kb_store_core` avec 31 tests passés, `cargo test -p kb_store_pg` avec 32 tests passés, `cargo test -p kb_app_demo` avec 38 tests passés et `cargo clippy --all-targets` sans avertissement. Les campagnes Tauri réelles ont validé les signatures explicites, programme avant/après, token avant/après et pool avant/après ; le cas `program_after` a parcouru 5 516 signatures indexées avant de sélectionner les 5 signatures les plus proches de l’ancre. Les diagnostics PostgreSQL ont confirmé 62 transactions canoniques et 62 observations, sans alimentation prématurée des tables core, dont l’extraction reste prévue pour `0.3.4`.
|
||||
|
||||
## 0.3.4 — extraction canonique vers core et clôture de la fondation `0.3.x`
|
||||
|
||||
Validation du jalon d’extraction structurelle : `kb_pipeline` transforme les transactions canoniques en graphes core atomiques comprenant transactions, account keys statiques et ALT, instructions outer et inner à chemins stables, logs reliés prudemment et deltas SOL/SPL Token/Token-2022. `kb_store_core` et `kb_store_pg` exposent et implémentent les contrats de persistance, le ledger versionné `kb_sol_ops_processing_ledger`, le skip par version/hash, le force replay et le rollback complet. `kb_app_demo` ajoute `demo_core_extraction` et le navigateur read-only `demo_sql_replay_candidates` avec filtres, sélection, copie et exports CSV sous `data/exports_csv/`; `kb_program_ids` fournit un registre énumérable de 182 programmes. Les transactions Solana échouées restent extractibles et seront décodables comme observations d’intention ou d’échec, sans être matérialisées automatiquement comme mutations réussies. Validation réelle effectuée sur PostgreSQL 17.10 : 70 transactions extraites sans erreur, sept contrôles d’intégrité sans anomalie, replay normal de 14 signatures entièrement ignoré, force replay des mêmes 14 signatures sans duplication, second replay entièrement ignoré, cardinalité finale de 70 transactions core et ledger final de 70 succès pour 84 tentatives. Validation locale finale : `cargo test -p kb_pipeline` avec 24 tests passés, `KB_POSTGRES_TEST_URL=... cargo test -p kb_store_pg -- --nocapture` avec 39 tests passés dont le rollback/replay corrigé, `cargo test -p kb_app_demo` avec 60 tests passés, `cargo test -p kb_program_ids` avec 2 tests passés et `cargo clippy --all-targets` sans avertissement. L’ancien jalon `0.3.5` est absorbé dans cette version ; la suite active devient `0.4.0` pour l’infrastructure commune de décodage et de matérialisation.
|
||||
|
||||
## 0.4.0 — infrastructure commune de décodage et de matérialisation
|
||||
|
||||
Validation du socle commun de replay contextualisé : `kb_decoder_api` et `kb_materializer_api` travaillent sur les inputs core complets, `kb_pipeline` sélectionne uniquement les programmes compatibles avec les processors activés, effectue un dispatch déterministe par programme et chemin d’instruction, persiste atomiquement couverture, ledger, événements décodés et sorties matérialisées, et applique le skip par processor/version/hash. Le force replay est autorisé uniquement avec des signatures explicites ou avec l’autorisation opérateur « toutes les signatures » bornée par les filtres et la limite. La matérialisation est refusée lorsqu’aucun matérialiseur n’est enregistré. Le classifieur `solana_native_classifier` déclare les 18 surfaces natives/runtime/loaders/précompiles connues sans produire de faux décodage.
|
||||
|
||||
`kb_app_demo` ajoute `demo_decode_replay`, ses diagnostics decode/ledger/couverture et les contrôles de replay normal, force replay ciblé, replay global explicitement autorisé, concurrence bornée et arrêt coopératif. Chaque campagne possède un `campaign_id` propagé par spans jusqu’au pipeline, au store PostgreSQL et au décodeur. Les migrations raw/core/decode sont appliquées une seule fois au démarrage Tauri ; les commandes de démo réutilisent ensuite le schéma initialisé. Les validations frontend du backfill bloquent localement les requêtes incomplètes sans produire de faux événements backend `ERROR`.
|
||||
|
||||
Validation locale finale : `cargo test -p kb_config` avec 36 tests passés, `cargo test -p kb_pipeline` avec 41 tests passés, `KB_POSTGRES_TEST_URL=postgres://solana:solana@localhost:5432/solana_test cargo test -p kb_store_pg -- --nocapture` avec 44 tests passés, `cargo test -p kb_app_demo` avec 75 tests passés et `cargo clippy --all-targets` sans avertissement. Les campagnes Tauri réelles ont validé neuf skips version/hash, neuf force replays ciblés, un second skip cohérent, un replay global strictement limité à cinq inputs, l’annulation puis le redémarrage d’une campagne, et la corrélation complète des traces. Le correctif final d’annulation garantit `started + not_started = selected` et `completed = started`; une campagne réelle a terminé avec 382 inputs sélectionnés, 45 démarrés/terminés, 337 non démarrés, 45 dispatchs `unsupported`, aucun unmatched, aucun échec et aucun événement dans `errors.jsonl`. La couverture PostgreSQL confirme 18 déclarations natives, 382 observations Compute Budget reconnues sans erreur et 94 observations System reconnues sans erreur. `0.4.1` devient le jalon actif pour le décodage maximal des programmes Solana natifs, loaders et précompiles.
|
||||
|
||||
## 0.4.1 — programmes Solana natifs, loaders, précompiles et matérialisations natives
|
||||
|
||||
Validation du jalon `0.4.1` : `kb_decoder_solana_core` couvre désormais les programmes Solana natifs/runtime, historiques, loaders, précompiles et surfaces ZK explicitement incluses dans le périmètre. Le registre exécutable natif contient 18 surfaces après reclassification de `StakeConfig11111111111111111111111111111111` comme compte historique non exécutable et ajout du stateless Slashing Program `S1ashing11111111111111111111111111111111111` observé dans Agave `v4.1.1` derrière feature gate. Les surfaces décodées incluent System, Vote, Stake, Config, Compute Budget, Address Lookup Table, Feature, ZK ElGamal Proof, l’ancien ZK Token Proof historique/no-op, les loaders Native/BPF v1/v2/Upgradeable/v4, Ed25519, secp256k1, secp256r1 et Slashing. SPL Memo, SPL Token, Token-2022, Stake Pool, Single Pool, Account Compression, Noop et SPL Name Service restent réservés aux jalons suivants.
|
||||
|
||||
Le jalon a étendu le contrat de replay instructionnel avec les instructions outer ordonnées afin de résoudre les références inter-instructions des précompiles et du profil Compute Budget. Les décodeurs bornent les offsets, tailles, compteurs, références d’instructions, comptes requis et payloads suffixes sans recalcul cryptographique pour les signatures ou preuves ZK. L’ancien `solana-zk-token-sdk` déprécié a été retiré ; le miroir ZK Token historique repose maintenant sur une table wire locale auditée, sans dépendance directe à `bincode`.
|
||||
|
||||
Les matérialisations natives sont clôturées au niveau instructionnel stable. `kb_materializer_lifecycle` projette Address Lookup Table, lifecycle des loaders, révocation Feature, durable nonce, comptes System create/allocate, contextes ZK ElGamal et rapports Slashing. `kb_materializer_admin` projette assignations System, écritures Config opaques et changements d’autorité Loader. `kb_materializer_compliance_audit` projette écritures/copies de bytecode Loader et profils Compute Budget transactionnels agrégés. `kb_materializer_staking` projette les intentions commitées Stake/Vote : comptes, autorités, lockup, délégation, désactivation, split, merge, retraits, move stake/lamports, identité Vote, commission, vote state et dépôt de rewards. Les sorties ne prétendent pas reconstruire les snapshots finaux de comptes, les sysvars historiques, les crédits Vote cumulés, l’activation Stake par epoch, les unités compute consommées ou les frais finaux runtime.
|
||||
|
||||
`kb_app_demo` enregistre les matérialiseurs natifs `solana_native_lifecycle`, `solana_native_admin`, `solana_native_compliance_audit` et `solana_native_staking`. Les profils de logging montent à 53 routes avec fichiers dédiés pour les crates opérationnelles ajoutées. `demo_backfill` accepte maintenant les modes `program_latest`, `token_latest` et `pool_latest` : une recherche « avant, plus anciennes » sans ancre commence sur les signatures les plus récentes, tandis que la direction « après, plus récentes » conserve une ancre obligatoire.
|
||||
|
||||
Les validations utilisateur finales confirment : `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 et `cargo clippy --all-targets` sans avertissement. Le correctif de sérialisation test-only des tests PostgreSQL réels élimine l’interblocage intermittent observé lors des tests optionnels concurrents.
|
||||
|
||||
Les campagnes mainnet ciblées validées couvrent notamment : System 817 inputs décodés avec 258 sorties et 52 refus attendus sur transactions échouées ; Config 96/96 avec 96 sorties admin ; Stake 448/448 avec 447 sorties et un refus attendu ; Vote 600/600 avec 600 sorties ; Compute Budget 2 746/2 746 avec 1 603 profils transactionnels matérialisés ; ZK ElGamal 151/151 avec 139 sorties de contexte ; ALT 104/104 avec 104 sorties lifecycle ; Slashing sans corpus observable, validé par sources officielles et fixtures synthétiques. Tous ces replays se terminent avec `unmatched = 0`, `failedInputs = 0`, `unsupported = 0` et journaux `error.jsonl` vides dans les archives fournies.
|
||||
|
||||
La suite active devient `0.4.2` : infrastructure d’exécution et `kb_executor_solana_core`, avec séparation stricte entre plan, simulation, signature, envoi et validation post-exécution. Les exécuteurs SPL suivront ensuite la politique décodeur maximal → matérialisateurs → exécuteur limité par opération.
|
||||
|
||||
## 0.4.2 — infrastructure d’exécution native et RPC Solana standard
|
||||
|
||||
Validation du jalon d’exécution native. `kb_execution_api`, `kb_execution_safety`, `kb_execution_solana`, `kb_wallet`, `kb_executor_solana_core`, `kb_rpc` et `kb_pipeline` séparent explicitement intent, plan, politique, lecture stateful, simulation, signature, envoi, confirmation et validation post-exécution. Le wallet temporaire de laboratoire reste confiné à Localnet/Devnet ; dry-run et simulation sont obligatoires par défaut, les plafonds de dépense/frais sont vérifiés et Mainnet reste désactivé sans politique et confirmation explicites.
|
||||
|
||||
`kb_executor_solana_core` couvre 18 surfaces natives avec 109 opérations appelables : System, Compute Budget, Address Lookup Table, précompiles Ed25519/secp256k1/secp256r1, Config, Feature, Slashing, ZK ElGamal, Stake, Vote, Loader v3 et Loader v4. BPF Loader v1/v2, Native Loader et l’ancien ZK Token Proof sont classés sans builder client ; Stake `Redelegate` reste historique `decode-only`. Chaque builder est comparé à un encodeur officiel ou à un layout wire audité. La matrice `docs/NATIVE_SOLANA_EXECUTION_MATRIX.json` est vérifiée par un test Rust contre les 109 codes compilés. `kb_decoder_solana_core` conserve l’égalité exacte avec les 18 Program IDs natifs et 121 déclarations de couverture.
|
||||
|
||||
Le préflight stateful de `kb_pipeline` inspecte ALT, Config, Feature, Slashing et les contextes ZK ElGamal sur Localnet/Devnet et retourne `NotRequired`, `Ready` ou `Blocked`. Les opérations administratives non validées réellement par un scénario cluster restent derrière ce garde-fou, hors de l’UI et sans activation Mainnet. Le parcours Devnet représentatif System transfer a été validé avec un wallet persistant préfinancé et 1 000 000 lamports : simulation exacte, signature, envoi, confirmation, `getTransaction`, insertion canonique, extraction core et decode replay ciblé ont réussi.
|
||||
|
||||
`kb_rpc` expose des contrats propres et configurables pour les 52 méthodes HTTP standard et les neuf paires WebSocket standard. Les options sont composables sans exposer les DTO Agave. `WsSession` gère multiplexage, unsubscribe, timeout, reconnexion bornée et réabonnement. `blockSubscribe`, `slotsUpdatesSubscribe` et `voteSubscribe` sont activables par endpoint ; un rejet serveur indiquant une méthode absente ou non activée désactive automatiquement la capacité pour la session. `kb_app_demo` ne contient plus la boucle de transport WebSocket.
|
||||
|
||||
La frontière Tauri/TS-rs a été corrigée pour ne plus transmettre de `bigint` dans les payloads JSON actifs. Les identifiants WebSocket sont contrôlés contre `Number.isSafeInteger` et les limites du navigateur SQL sont validées avant l’invocation backend. Les logs réels confirment les souscriptions/désabonnements WebSocket et le garde-fou de changement d’endpoint avec session active.
|
||||
|
||||
Validation finale fournie par l’utilisateur : `kb_program_ids` 5 tests, `kb_decoder_solana_core` 116, `kb_executor_solana_core` 88, `kb_execution_api` 22, `kb_execution_safety` 15, `kb_execution_solana` 12, `kb_rpc` 113, `kb_pipeline` 56, `kb_config` 41, `kb_app_demo` 88 et `kb_store_pg` 45 avec PostgreSQL réel. Le test Devnet opt-in et le replay post-exécution sont réussis, `cargo clippy --all-targets` est propre et `cargo tauri dev` démarre avec Vite et initialise correctement PostgreSQL. Aucun jalon suivant n’est ouvert par cette clôture.
|
||||
|
||||
## 0.4.3 — SPL Memo v1, v3 et v4
|
||||
|
||||
Validation complète de la surface SPL Memo. `kb_decoder_spl_memo` reconnaît exactement les Program IDs v1, v3 et v4, décode le payload UTF-8 brut, sa longueur et son SHA-256, conserve les comptes ordonnés et leurs flags, distingue les règles historiques de signataires, les chemins outer/inner, les transactions réussies ou échouées et les tentatives invalides sans produire de faux état commité. La matrice machine-readable `docs/SPL_MEMO_MATRIX.json` relie les contrats officiels, les fixtures synthétiques et le corpus Mainnet réel des trois générations.
|
||||
|
||||
`kb_materializer_transaction_annotations` projette uniquement les Memo réussis et commités dans la famille `transaction_annotation`, avec texte borné, génération, Program ID, signataires vérifiés, provenance et clé d’idempotence. Les comptes complets et diagnostics d’audit restent dans le decode. La persistance réutilise `kb_sol_mat_events` et le ledger commun sans nouvelle table ; `demo_decode_replay` expose un journal typé et borné filtrable par signature.
|
||||
|
||||
`kb_executor_spl_memo` fournit les intents typés v1/v3/v4 et construit les trois générations avec `spl-memo-interface 2.1.0`, payload exact et signataires readonly ordonnés. La bibliothèque reste universelle sur les clusters ; simulation obligatoire, dry-run par défaut, plafond de frais, autorisation opérateur et politiques Mainnet appartiennent à l’infrastructure commune. Le parcours Memo v4 Devnet réutilise wallet, RPC, safety, transaction Solana, confirmation, hydratation canonique, extraction core et decode replay. Trois transactions réelles ont chacune produit une annotation et un second replay idempotent `skipped`.
|
||||
|
||||
La clôture utilisateur confirme : `kb_program_ids` 5 tests, `kb_decoder_spl_memo` 9, `kb_materializer_transaction_annotations` 7, `kb_executor_spl_memo` 15, `kb_execution_api` 22, `kb_execution_safety` 15, `kb_execution_solana` 12, `kb_pipeline` 61, `kb_rpc` 113, `kb_app_demo` 96 et `kb_store_pg` 46 avec PostgreSQL réel. Le test opt-in Devnet avec envoi est réussi et `cargo clippy --all-targets` est propre. La suite active devient `0.4.4 — SPL Token` selon `prompts/023_v0_4_4_spl_token.md`; l’acquisition historique différée reste hors ROADMAP actif.
|
||||
|
||||
## 0.4.4 — SPL Token classique
|
||||
|
||||
Validation complète du programme SPL Token classique `Tokenkeg...`. `kb_decoder_spl_token`
|
||||
reconnaît exactement les 28 tags publiés par `spl-token-interface 3.0.0`, conserve le wire borné,
|
||||
les comptes ordonnés, outer/inner paths, autorités simples ou multisig, montants bruts, decimals,
|
||||
transactions échouées non commitées et diagnostics sans inventer mint ni état final. `Batch`
|
||||
conserve son parent et ses enfants déterministes sans accepter les batchs imbriqués. La matrice
|
||||
`docs/SPL_TOKEN_MATRIX.json` relie interface, processor, builders, corpus et preuves cluster.
|
||||
|
||||
Les projections stables produisent des événements instructionnels `token_account`, `admin` et
|
||||
`risk`, sans fee classique fictive, sans OHLC et sans snapshot final reconstruit. Le replay Mainnet
|
||||
de 370 instructions a produit 371 sorties, huit refus correspondant exactement à huit transactions
|
||||
échouées, puis un second replay idempotent sans nouvelle sortie. Le journal Tauri expose des filtres
|
||||
bornés par signature, mint, compte, famille et opération, avec montants JSON sans perte.
|
||||
|
||||
`kb_executor_spl_token` expose 24 opérations typées courantes ou récentes et laisse les quatre
|
||||
initialisations Rent obsolètes en decode-only. Le préflight stateful Localnet/Devnet valide layouts,
|
||||
relations mint/comptes, soldes, native reserve, délégations, autorités, multisig et rent hors du
|
||||
décodeur et de l'exécuteur. Le parcours Devnet `TransferChecked` a réussi simulation, envoi,
|
||||
confirmation, hydratation, extraction, replay, matérialisation et second replay idempotent. Un
|
||||
lifecycle contrôlé sans ATA a ensuite initialisé mint et comptes, minté, transféré, approuvé,
|
||||
révoqué, brûlé puis fermé les comptes avec récupération sûre après interruption RPC.
|
||||
|
||||
Les tags récents `Batch` et `UnwrapLamports` ont été simulés avec succès sur le programme classique
|
||||
Devnet, sans signature ni envoi, respectivement en 270 et 140 compute units. La clôture Tauri charge
|
||||
77 routes de logs, réussit le préflight et la simulation `TransferChecked`, bloque l'envoi sans
|
||||
confirmation, affiche la matérialisation commitée exacte et simule Memo v4 sans erreur runtime.
|
||||
|
||||
La régression finale communiquée confirme notamment : `kb_program_ids` 5 tests,
|
||||
`kb_decoder_spl_token` 8, `kb_executor_spl_token` 15, `kb_decoder_spl_memo` 9,
|
||||
`kb_materializer_transaction_annotations` 7, `kb_execution_api` 22, `kb_execution_safety` 15,
|
||||
`kb_execution_solana` 12, `kb_pipeline` 81, `kb_rpc` 113, `kb_config` 41, `kb_app_demo` 102 et
|
||||
`kb_store_pg` 46 avec PostgreSQL réel. `cargo clippy --all-targets` est propre. La suite active
|
||||
devient `0.4.5 — SPL Associated Token Account` selon
|
||||
`prompts/024_v0_4_5_spl_associated_token_account.md`.
|
||||
|
||||
## 0.4.5 — SPL Associated Token Account
|
||||
|
||||
Validation complète du programme SPL Associated Token Account
|
||||
`ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL`. Le décodeur consomme
|
||||
`spl-associated-token-account-interface 2.0.0`, reconnaît exactement `Create`,
|
||||
`CreateIdempotent`, `RecoverNested` et la forme historique vide de `Create`, puis conserve comptes
|
||||
ordonnés, flags, doublons, chemins outer/inner, transactions échouées et diagnostics bornés. Les
|
||||
adresses observées sont comparées aux PDA canoniques dérivés depuis wallet, Token Program ID et
|
||||
mint ; une incohérence reste décodable et n'est jamais corrigée silencieusement.
|
||||
|
||||
`kb_materializer_token_accounts` possède exclusivement le lifecycle de l'adresse associée : créée,
|
||||
créée ou réutilisée idempotemment, ou récupérée depuis une imbrication. `kb_materializer_risk`
|
||||
possède le constat distinct d'anti-pattern nested récupéré, sans score arbitraire. Les CPI SPL Token
|
||||
restent propriétaires des initialisations, transferts et fermetures, et les matérialiseurs lifecycle
|
||||
général, admin et fees ne produisent aucun doublon. Les transactions non commitées ou invalides sont
|
||||
refusées comme mutations.
|
||||
|
||||
`kb_executor_spl_associated_token_account` expose les trois variantes actuelles pour SPL Token
|
||||
classique et Token-2022 avec les builders officiels, metas dans l'ordre exact, signataires uniques,
|
||||
simulation obligatoire, dry-run par défaut et coûts rent/frais plafonnés. Le pipeline stateful
|
||||
contrôle mints, owners, Program IDs, dérivations, comptes existants, rent, signataires et
|
||||
postconditions avant et après l'exécution. La fenêtre Tauri Solana existante ajoute création ATA,
|
||||
dérivation readonly et journal lifecycle borné ; `RecoverNested` reste volontairement hors UI.
|
||||
|
||||
Les scénarios Devnet contrôlés du 16 juillet 2026 ont validé la création et la réutilisation
|
||||
idempotente d'ATA classiques et Token-2022, puis un `RecoverNested` classique transférant
|
||||
1 000 000 000 unités brutes vers l'ATA wallet et fermant le nested ATA. Chaque envoi a suivi
|
||||
simulation, confirmation, hydratation canonique, extraction, decode, matérialisation et second
|
||||
replay idempotent. L'ATA Token-2022 observé mesure 170 octets et expose `ImmutableOwner`, sans que le
|
||||
jalon ne commence le décodage général de ses extensions.
|
||||
|
||||
La clôture confirme 5 tests Program IDs, 8 tests décodeur Token classique, 15 tests exécuteur Token,
|
||||
9 tests Memo, 7 tests annotations, 9 tests matérialiseur token accounts, 6 tests risk, 17 tests
|
||||
lifecycle, 9 tests admin, 3 tests fees, 10 tests décodeur ATA, 10 tests exécuteur ATA, 22 tests API
|
||||
d'exécution, 15 tests safety, 12 tests transaction Solana, 90 tests pipeline, 113 tests RPC, 41 tests
|
||||
configuration, 111 tests démo et 46 tests PostgreSQL réels. `cargo clippy --all-targets` est propre
|
||||
et `cargo tauri dev -c kb_app_demo/tauri.conf.json` a démarré Vite, Tauri et PostgreSQL. La suite
|
||||
active devient `0.4.6 — Token-2022, extensions et registre ElGamal` selon
|
||||
`prompts/025_v0_4_6_spl_token_2022.md`.
|
||||
|
||||
## 0.4.6 — Token-2022, extensions et registre ElGamal
|
||||
|
||||
Validation du jalon Token-2022 et ElGamal Registry avec frontières techniques séparées. Token-2022 couvre les instructions de base, les familles d’extensions identifiables, les états Mint/Account/Multisig et TLV, les metadata/group incorporés, les parcours confidentiels, les matérialisations propriétaires et les exécuteurs simulation-first avec préflights stateful et preuves inline/context-state. Huit opérations publiques Token-2022 ont été confirmées sur Devnet, hydratées, extraites, décodées, matérialisées et rejouées idempotemment. Le corpus Mainnet contient 55 instructions Token-2022 décodées sans échec.
|
||||
Le registre ElGamal dispose de son décodeur, de sa matrice, de son parser d’état de 64 octets, de sa matérialisation administrative, de ses builders `CreateRegistry`/`UpdateRegistry`, de son PDA, de ses préflights et de son orchestration de preuves. La validation réseau publique reste indisponible sur Devnet/Mainnet au 20 juillet 2026 ; la validation synthétique/offline est conservée sans inventer de preuve cluster.
|
||||
La validation Mainnet a corrigé le wire `Write` du loader immuable : longueur `u32` et données à l’offset 12, supprimant 68 diagnostics `loader_vector_length_mismatch`. Les 76 rejets restants sont tous issus de transactions Solana échouées et restent explicitement fail-closed ; quatre tags Loader v4 inconnus sont classés `Unsupported`. Un timeout ponctuel du pool PostgreSQL a été réparé par replay ciblé.
|
||||
Le replay de `kb_app_demo` ajoute `incomplete_signatures`, qui sélectionne seulement les signatures contenant une instruction `pending`, `failed`, `replay_requested` ou `unsupported`, limite d’abord les signatures puis étend leurs instructions compatibles sans force replay global. Deux campagnes PostgreSQL réelles ont produit le même résultat : 81 entrées, 1 décodée, 4 unsupported, 76 failed, aucun unmatched et aucun doublon decode/mat. Validation finale : `kb_store_core` 41/41, `kb_store_pg` 46/46 avec PostgreSQL réel, `kb_pipeline` 124/124, `kb_app_demo` 118/118 et `cargo clippy --all-targets` propre. La suite active devient `0.4.7 — Metaplex Token Metadata` selon `prompts/026_v0_4_7_metaplex_token_metadata.md`. Anchor n’étant pas requis par les programmes SPL de `0.4.x`, son infrastructure commune est planifiée en `0.4.18`, immédiatement avant Meteora.
|
||||
|
||||
293
olddocs/archivekbot2/README.md
Normal file
293
olddocs/archivekbot2/README.md
Normal file
@@ -0,0 +1,293 @@
|
||||
<!-- file: README.md -->
|
||||
<!-- version: 81 -->
|
||||
|
||||
# Khadhroony Bot2
|
||||
|
||||
Khadhroony Bot2 est un workspace Rust modulaire pour observer, décoder, matérialiser, exécuter et analyser des transactions Solana.
|
||||
|
||||
Le projet poursuit deux objectifs complémentaires. À court terme, il doit fournir un trading assisté contrôlable depuis des démos live Tauri. À long terme, il doit devenir une bibliothèque d'indexation et d'analyse Solana capable de classifier un grand nombre de programmes et de surfaces.
|
||||
|
||||
Le socle technique doit permettre de :
|
||||
|
||||
- ingérer des transactions Solana depuis RPC HTTP, WebSocket ou futures sources spécialisées ;
|
||||
- normaliser chaque source vers une transaction canonique source-indépendante ;
|
||||
- conserver la transaction canonique comme source d’audit et de replay ;
|
||||
- conserver séparément les observations légères de provenance et de timing ;
|
||||
- extraire les instructions, inner instructions, logs, comptes résolus et deltas de balances ;
|
||||
- détecter les programmes impliqués dans chaque transaction ;
|
||||
- décoder les programmes Solana de base, les programmes SPL, les surfaces DEX, les orderbooks, les routers et les protocoles annexes ;
|
||||
- matérialiser les événements décodés en tables métier exploitables ;
|
||||
- rejouer uniquement les modules nécessaires grâce à un ledger de traitement par module et version ;
|
||||
- alimenter des agrégations, diagnostics, signaux de risque et futures règles de stratégie ;
|
||||
- construire des plans d'exécution séparés des décodeurs ;
|
||||
- tester les fonctionnalités live via `kb_app_demo` avant automatisation.
|
||||
|
||||
## Architecture générale
|
||||
|
||||
Le workspace suit une chaîne de traitement en couches :
|
||||
|
||||
```text
|
||||
canonical transaction -> source observations -> Solana extraction -> decoding -> materialization -> aggregation -> strategy
|
||||
```
|
||||
|
||||
Chaque couche doit être indépendante autant que possible. Les décodeurs ne dépendent pas du stockage, du RPC, de Tauri, du wallet ou des matérialisateurs. Les matérialisateurs travaillent sur les événements décodés et produisent des événements métier normalisés.
|
||||
|
||||
## Rôle des dossiers principaux
|
||||
|
||||
- `kb_core` contient les primitives partagées minimales.
|
||||
- `kb_model` contient les types communs du modèle interne.
|
||||
- `kb_config` définit le contrat JSON multi-profils, le schéma runtime, les validations typées et les exports TS-rs destinés aux applications Tauri.
|
||||
- `kb_rpc` contient les protocoles et clients RPC Solana HTTP, WebSocket et futurs flux Helius/Yellowstone.
|
||||
- `kb_execution_solana` assemble les plans communs en transactions Solana, lie la simulation au message exact et résout les signataires via l’interface Solana `Signer`; `kb_wallet` fournit actuellement le backend temporaire.
|
||||
- Le projet différé d’acquisition historique gratuite est décrit dans `docs/HISTORICAL_DATA_ACQUISITION_PLAN.md`. Il reste hors du ROADMAP actif tant que les décodeurs, matérialisateurs et exécuteurs prioritaires ne sont pas suffisamment avancés.
|
||||
- `kb_store_core` définit les traits de stockage.
|
||||
- `kb_store_pg` fournit le backend PostgreSQL cible.
|
||||
- `kb_store_sqlite` reste limité aux tests et imports locaux.
|
||||
- `kb_decoder_api` définit le contrat des décodeurs.
|
||||
- `kb_materializer_api` définit le contrat des matérialisateurs.
|
||||
- `kb_materializer_*` contient les projections métier par famille : trades, liquidité, NFT, oracle, lending, routing, compliance audit, etc.
|
||||
- `kb_pipeline` orchestre backfill, extraction canonique vers core, décodage, matérialisation, agrégation et validation.
|
||||
- `kb_app_demo` sert de démonstrateur Tauri, sans logique métier lourde. Il charge le profil actif, initialise `kb_logging`, rend le README en HTML et expose une fenêtre dédiée à la configuration.
|
||||
- Chaque crate opérationnelle doit émettre ses propres événements `tracing` avec une cible canonique égale à son nom Cargo ; `kb_app_demo` reste limité aux frontières UI/Tauri et aux résumés.
|
||||
- Chaque profil écrit des fichiers globaux `debug.log`, `info.log`, `error.jsonl` et `app.log`, ainsi que `debug.log`, `info.log` et `error.jsonl` dans un répertoire par crate utilisant `tracing`.
|
||||
- Les interfaces officielles Solana/SPL étroites sont privilégiées ; `wincode` puis Borsh sont préférés, et un parser local borné reste autorisé lorsque l’interface officielle n’expose que `bincode`.
|
||||
|
||||
|
||||
## État `0.4.1` validé
|
||||
|
||||
`0.4.1` clôt le décodage et les matérialisations instructionnelles stables des programmes Solana natifs, historiques, loaders, précompiles et surfaces ZK du périmètre core.
|
||||
|
||||
`kb_decoder_solana_core` couvre maintenant 18 surfaces exécutables natives : System, Vote, Stake, Config, Compute Budget, Address Lookup Table, Feature, ZK ElGamal Proof, l’ancien ZK Token Proof historique/no-op, Native Loader, BPF Loader v1/v2/Upgradeable/v4, Ed25519, secp256k1, secp256r1 et Slashing. `StakeConfig11111111111111111111111111111111` est classé comme compte historique non exécutable, sans dispatch ni plan d’exécution.
|
||||
|
||||
Les matérialisations natives actives sont réparties par famille :
|
||||
|
||||
- `kb_materializer_lifecycle` : Address Lookup Table, lifecycle loaders, Feature revoke, durable nonce, comptes System create/allocate, contextes ZK ElGamal et rapports Slashing ;
|
||||
- `kb_materializer_admin` : assignations System, écritures Config opaques, changements d’autorité Loader ;
|
||||
- `kb_materializer_compliance_audit` : écritures/copies de bytecode Loader et profil transactionnel Compute Budget ;
|
||||
- `kb_materializer_staking` : projections instructionnelles Stake/Vote commitées, sans prétendre reconstruire les snapshots finaux.
|
||||
|
||||
Les précompiles de signature, les preuves ZK sans compte de contexte et l’ancien ZK Token Proof restent en decode/audit, sans duplication dans `kb_sol_mat_events` tant qu’aucun consommateur dédié ne l’exige. Les transactions échouées restent décodées comme intentions ou échecs, mais les matérialiseurs mutables appliquent `SuccessfulCommittedOnly`.
|
||||
|
||||
Les validations finales de `0.4.1` couvrent les tests unitaires, PostgreSQL réel, Clippy et des replays mainnet ciblés : System, Config, Stake, Vote, Compute Budget, ALT, ZK ElGamal et Slashing synthétique. Les replays terminent sans `unmatched`, `failedInputs` ou `unsupported`; les archives de logs fournies ont des `error.jsonl` vides.
|
||||
|
||||
## Couche d'exécution
|
||||
|
||||
Le workspace développe une couche d'exécution séparée du décodage. Les crates `kb_executor_*` sont des bibliothèques universelles : elles construisent des plans pour les applications de trading, les CLI, les workers, les outils d'administration et de futurs exécutables indépendants.
|
||||
|
||||
Les opérations dangereuses ne sont pas supprimées des bibliothèques. Elles doivent être encodées, testées et protégées par des politiques renforcées, tandis que `kb_app_demo` peut volontairement ne pas les exposer. Les exécuteurs ne dépendent ni du wallet, ni du RPC, ni des décodeurs ; l'orchestration assemble ensuite plan, sécurité, simulation, signature, envoi et validation post-exécution.
|
||||
|
||||
## Démos live
|
||||
|
||||
`kb_app_demo` reste le shell Tauri unique pour valider les capacités du workspace : configuration, logs, DB, RPC, wallet, listeners, décodage, matérialisation, exécution et validation post-transaction.
|
||||
|
||||
## Documentation
|
||||
|
||||
- `RUST_RULES.md` contient les règles Rust générales réutilisables ; `RULES.md` contient les règles spécifiques et normatives du workspace.
|
||||
- `ROADMAP.md` contient les étapes futures et changements prévus.
|
||||
- `CHANGELOG.md` ne reçoit une entrée qu'après validation d'une version.
|
||||
- `docs/` contient les notes d'architecture et de conception, notamment `TRACING_CONTRACT.md`, `SOLANA_INTERFACE_DEPENDENCIES.md`, `NATIVE_SOLANA_CLOSURE_AUDIT.md`, `NATIVE_SOLANA_MATERIALIZATION_AUDIT.md` et `DEVNET_EXECUTION.md`.
|
||||
- `validation_sql/` contient les contrôles SQL de validation.
|
||||
|
||||
## Jalon validé `0.4.2`
|
||||
|
||||
`0.4.2` valide l’infrastructure d’exécution et `kb_executor_solana_core`. L’exécuteur expose **109 opérations déterministes** : dix-sept System, quatre Compute Budget, cinq Address Lookup Table, six formes de précompile, deux Config, deux Feature, deux Slashing, trois ZK ElGamal, vingt-quatre Stake, vingt-quatre Vote, onze Loader v3 et neuf Loader v4. La surface Vote couvre les vingt variantes wire actuelles de `solana-vote-interface 6.0.3` ainsi que quatre plans composés de création legacy/V2, avec ou sans seed. Loader v3 consomme `solana-loader-v3-interface 8.x` et son schéma `wincode`; Loader v4 reproduit explicitement son wire officiel sans activer les helpers conditionnés par `bincode`. BPF Loader v1/v2 restent historiques `decode-only`, Native Loader ne possède pas de builder client et l’ancien ZK Token Proof reste historique. Les opérations nécessitant un état courant restent protégées par un préflight séparé et ne sont pas activées sur Mainnet par ce jalon.
|
||||
|
||||
`kb_pipeline` fournit le préflight stateful Localnet/Devnet pour ALT, Config, Feature, Slashing et les contextes ZK ElGamal. Le rapport `Ready`/`Blocked`/`NotRequired` expose les contrôles et faits mesurés avant simulation. `docs/NATIVE_SOLANA_EXECUTION_MATRIX.json` inventorie les dix-huit surfaces et les 109 opérations appelables, avec égalité imposée par un test Rust. La matrice décodeur couvre les mêmes dix-huit surfaces et 121 déclarations de couverture.
|
||||
|
||||
`kb_rpc` possède des contrats propres et configurables pour les 52 méthodes HTTP standard et les neuf paires WebSocket standard. Les options restent composables champ par champ et aucun DTO Agave n’est exposé par l’API publique. La session WebSocket persistante gère multiplexage, unsubscribe, timeout, reconnexion et réabonnement. `blockSubscribe`, `slotsUpdatesSubscribe` et `voteSubscribe` sont activables par endpoint ; lorsqu’un nœud les rejette comme indisponibles, la capacité concernée est désactivée automatiquement pour la session et les appels suivants sont refusés localement.
|
||||
|
||||
`kb_wallet` fournit un wallet temporaire en mémoire ou persistant sous `wallets/temporary/`, avec fichiers non écrasés, permissions privées et secrets confinés côté Rust. `kb_execution_solana` assemble les transactions, lie la simulation au hash exact du message et signe seulement après autorisation de `kb_execution_safety`. `kb_pipeline` orchestre le parcours backend Devnet complet : contrôle du destinataire et du minimum rent-exempt, financement plafonné, System transfer, simulation exacte, signature, envoi, confirmation, hydratation canonique, extraction core et decode replay ciblé. Ce parcours a été validé réellement sur Devnet avec un transfert de 1 000 000 lamports et PostgreSQL réel.
|
||||
|
||||
La frontière Tauri/TS-rs n’émet plus de `bigint` dans les payloads JSON actifs. Les identifiants WebSocket sont contrôlés contre `Number.isSafeInteger`, et les limites du navigateur SQL sont validées côté frontend avant l’appel backend. `cargo tauri dev` avec Vite constitue la validation frontend retenue ; aucun `npm run build` séparé n’est exigé pour cette clôture.
|
||||
|
||||
## Jalon validé `0.4.3`
|
||||
|
||||
Le prompt `prompts/022_v0_4_3_spl_memo.md` reste l’historique de travail du jalon. Le décodeur contextualisé distingue v1, v3 et v4 avec payload UTF‑8 ou tentative invalide, comptes ordonnés, signataires, outer/inner, hash et intentions non commitées. La projection dédiée `kb_materializer_transaction_annotations` transforme uniquement les Memo réussis et commités en annotations consultables et idempotentes ; les faits d’audit détaillés restent dans le decode. `demo_decode_replay` expose ces sorties comme un journal borné filtrable par signature, avec slot, instruction path, génération, texte, hash et signataires vérifiés.
|
||||
|
||||
`kb_executor_spl_memo` expose maintenant un intent typé `AddMemo` et appelle le builder officiel `spl-memo-interface 2.1.0` avec l’ID explicite v1/v3/v4. Le wire reste le texte UTF‑8 brut et chaque signer est readonly, ordonné et visible avant signature. La bibliothèque construit les trois générations sur tout cluster ; la disponibilité effective du programme est vérifiée par la simulation obligatoire, et Mainnet reste régi par les garde-fous communs plutôt que désactivé dans l’exécuteur. La démo opérateur reste volontairement limitée à Memo v4 Devnet et réutilise la fenêtre Solana existante. Elle montre la simulation, l’envoi explicitement confirmé, l’hydratation, l’extraction, le replay, l’annotation et l’idempotence avec des DTO Tauri JSON sans `bigint` actif.
|
||||
|
||||
Le parcours a été validé le 15 juillet 2026 avec une simulation seule puis trois transactions v4 Devnet confirmées. Chaque signature a produit une insertion canonique, une extraction core, un événement Memo, une annotation `transaction_annotation` et un second replay `skipped` sans nouvelle sortie. Le corpus Mainnet réel couvre séparément v1, v3 et v4 ; aucun envoi historique v1/v3 sur Devnet n’est revendiqué ni requis.
|
||||
|
||||
La matrice `docs/SPL_MEMO_MATRIX.json` conserve les différences historiques, le corpus Mainnet réel, les preuves Devnet v4 et les limitations explicitement non revendiquées pour v1/v3. Le worker d’acquisition historique reste un projet différé indépendant, sans numéro de version attribué.
|
||||
|
||||
La validation finale confirme 5 tests `kb_program_ids`, 9 tests décodeur Memo, 7 tests matérialiseur d’annotations, 15 tests exécuteur Memo, 22 tests API d’exécution, 15 tests safety, 12 tests Solana, 61 tests pipeline, 113 tests RPC, 96 tests démo et 46 tests PostgreSQL réels. Le test opt-in Devnet avec envoi et `cargo clippy --all-targets` sont propres. La version active devient `0.4.4 — SPL Token` selon `prompts/023_v0_4_4_spl_token.md`.
|
||||
|
||||
## Jalon validé `0.4.4`
|
||||
|
||||
Les premières tranches SPL Token établissent la matrice machine-readable des 28 tags publiés par
|
||||
`spl-token-interface 3.0.0` et remplacent le scaffold du décodeur classique. Le wire local borné
|
||||
conserve montants bruts, decimals explicites, autorités, comptes ordonnés, chemins outer/inner,
|
||||
transactions échouées non commitées, suffixes et diagnostics. `Batch` produit un parent d'audit et
|
||||
des enfants à identités dérivées stables sans accepter de batch imbriqué.
|
||||
|
||||
Les matérialiseurs actifs produisent un journal instructionnel `token_account`, des faits admin et
|
||||
des constats de risque sans score ; aucune fee classique n'est inventée. Le replay Mainnet validé de
|
||||
370 instructions a produit 371 sorties, huit refus expliqués par huit transactions échouées et un
|
||||
second replay idempotent sans nouvelle sélection.
|
||||
|
||||
`kb_executor_spl_token` expose 24 opérations typées courantes ou récentes avec montants JSON en
|
||||
chaînes, autorités simples/multisig et builders officiels. Quatre initialisations Rent obsolètes
|
||||
restent decode-only. `UnwrapLamports` et `Batch` sont constructibles selon l'interface publiée ; leur
|
||||
déploiement sur le programme classique Devnet a été observé le 16 juillet 2026 par deux simulations
|
||||
réussies sans signature ni envoi. Localnet, Testnet et Mainnet restent non testés pour ces deux tags.
|
||||
|
||||
`0.4.4-pre.005` ajoute le préflight stateful Localnet/Devnet dans `kb_pipeline`. Les lectures RPC
|
||||
restent hors du décodeur et de l’exécuteur ; elles valident les layouts Mint/Account/Multisig,
|
||||
l’état, les relations de mint, les soldes, les réserves wrapped SOL, les délégations, les autorités,
|
||||
les seuils multisig et le rent avant simulation. Les tests standards sont offline et un test Devnet
|
||||
read-only reste opt-in. La démo Token réutilise la fenêtre d’exécution Solana existante : son panneau
|
||||
`TransferChecked` expose préflight, simulation, confirmation et validation post-exécution, tandis
|
||||
qu’un journal matérialisé borné accepte des filtres typés par signature, mint, compte, famille et
|
||||
opération sans créer une WebView par opération.
|
||||
|
||||
Le correctif fonctionnel de `pre.005` ajoute l’orchestration Devnet générique : simulation autonome
|
||||
après préflight, puis envoi explicitement confirmé lorsque le wallet du profil résout tous les
|
||||
signataires. Une transaction envoyée est confirmée, hydratée, extraite, décodée et matérialisée,
|
||||
avant un second replay idempotent. Cette couche ne restreint pas les builders universels aux seuls
|
||||
clusters ou signataires disponibles dans la démo.
|
||||
|
||||
Le parcours `TransferChecked` a été validé réellement sur Devnet le 15 juillet 2026 avec deux
|
||||
comptes Token auxiliaires du même mint et un wallet isolé correspondant exactement à l’autorité.
|
||||
Le test opt-in impose désormais la présence de la soumission et de la confirmation, l’absence
|
||||
d’échec ou de refus au premier replay, au moins une matérialisation Token et un second replay sans
|
||||
nouvelle sortie ; il imprime aussi la signature afin qu’elle puisse rejoindre le corpus audité.
|
||||
|
||||
`0.4.4-pre.006` ajoute un lifecycle destructif explicitement autorisé pour trois comptes classiques
|
||||
sans ATA. Son correctif crée d'abord les comptes bruts via trois instructions System officielles,
|
||||
avec keypairs éphémères, rent et tailles 82/165/165 vérifiés, puis onze transactions initialisent le mint et deux comptes Token, mintent et
|
||||
transfèrent un montant contrôlé, créent puis révoquent une délégation, brûlent exactement les deux
|
||||
soldes et ferment les comptes Token. Chaque étape est simulée, confirmée, hydratée, décodée,
|
||||
matérialisée et rejouée une seconde fois avant que l'étape suivante ne soit admise.
|
||||
|
||||
Le correctif de reprise du lifecycle traite explicitement les confirmations RPC interrompues : une
|
||||
signature prédécesseur confirmée est hydratée, extraite, décodée, rapprochée de l'opération attendue
|
||||
et rejouée idempotemment avant de reprendre à l'index demandé. Un délai borné sépare ensuite les
|
||||
étapes afin de réduire la pression sur les endpoints Devnet publics, sans masquer leurs erreurs.
|
||||
|
||||
Le lifecycle Devnet réel a été validé le 15 juillet 2026 après une interruption du RPC public : la
|
||||
reprise a récupéré l'initialisation déjà confirmée, puis achevé mint, transfer, approve/revoke, deux
|
||||
burn et deux close. Chaque étape récupérée ou envoyée a produit exactement une matérialisation et un
|
||||
second replay idempotent. La fenêtre opérateur `pre.007` permet désormais de rejouer le parcours
|
||||
représentatif `TransferChecked` et de consulter ces faits `token_account`, `admin` et `risk` comme
|
||||
événements chronologiques, sans inventer un état final de compte.
|
||||
|
||||
L'audit `pre.008` reporte dans `docs/SPL_TOKEN_MATRIX.json` les preuves par instruction. Le corpus
|
||||
Mainnet réel couvre `Transfer`, `Approve`, `CloseAccount`, `TransferChecked`, `BurnChecked` et
|
||||
`SyncNative`; ses trois initialisations restent volontairement référencées sous leur nom matérialisé
|
||||
normalisé sans inventer une variante wire. Le lifecycle Devnet prouve `InitializeAccount3`,
|
||||
`MintToChecked`, `TransferChecked`, `ApproveChecked`, `Revoke`, `BurnChecked` et `CloseAccount`.
|
||||
Localnet n'a pas été exécuté, et la publication p-token des tags `45`/`255` n'est pas assimilée à
|
||||
leur déploiement sur un cluster public.
|
||||
|
||||
La validation Tauri de `pre.007` a démarré Vite et l'application, réussi le préflight et la
|
||||
simulation `TransferChecked`, puis refusé correctement l'envoi sans confirmation opérateur. Avec
|
||||
confirmation, un second refus a identifié que le wallet du profil et l'autorité Token étaient deux
|
||||
clés distinctes. La démo ne tente jamais de signer à la place d'une autorité externe ; pour envoyer,
|
||||
les comptes Token doivent appartenir au wallet persistant sélectionné, comme dans le scénario
|
||||
backend Devnet déjà confirmé et matérialisé.
|
||||
|
||||
La clôture du 16 juillet 2026 confirme les régressions ciblées, PostgreSQL réel, Clippy et Tauri.
|
||||
Les validations finales couvrent notamment 5 tests Program IDs, 8 tests décodeur Token, 15 tests
|
||||
exécuteur Token, 9 tests décodeur Memo, 7 tests annotations, 22 tests API d'exécution, 15 tests
|
||||
safety, 12 tests transaction Solana, 81 tests pipeline, 113 tests RPC, 41 tests configuration,
|
||||
102 tests démo et 46 tests PostgreSQL réels. Tauri charge 77 routes de logs, simule
|
||||
`TransferChecked`, bloque l'envoi non confirmé, restitue sa matérialisation commitée exacte et
|
||||
simule Memo v4 sans erreur runtime.
|
||||
|
||||
## Jalon validé `0.4.5`
|
||||
|
||||
`0.4.5` clôt la surface SPL Associated Token Account avec
|
||||
`spl-associated-token-account-interface 2.0.0`. Le décodeur reconnaît exactement `Create`,
|
||||
`CreateIdempotent`, `RecoverNested` et la forme historique vide de `Create`; il conserve comptes
|
||||
ordonnés, flags, doublons, outer/inner paths, transactions échouées non commitées et diagnostics
|
||||
bornés. Les PDA sont dérivés et validés explicitement avec les seeds
|
||||
`[wallet, Token Program ID, mint]`, ce qui distingue les ATA classiques des ATA Token-2022 sans
|
||||
prétendre décoder les extensions de ce dernier.
|
||||
|
||||
Le lifecycle ATA est possédé par `kb_materializer_token_accounts` : création normale, création ou
|
||||
réutilisation idempotente non distinguable depuis le parent seul, et récupération nested.
|
||||
`kb_materializer_risk` possède séparément le constat factuel d'anti-pattern nested récupéré. Les
|
||||
matérialiseurs lifecycle général, admin et fees déclarent explicitement leur absence de projection,
|
||||
et les CPI SPL Token conservent seules leurs initialisations, transferts et fermetures. Les
|
||||
transactions échouées ou structurellement invalides ne produisent aucune mutation.
|
||||
|
||||
`kb_executor_spl_associated_token_account` construit les trois variantes actuelles avec les
|
||||
builders officiels, pour SPL Token classique ou Token-2022. Simulation et dry-run sont obligatoires
|
||||
par défaut. Le préflight Localnet/Devnet contrôle cluster, mints, Program IDs, dérivations, comptes
|
||||
existants, signataires, rent et plafonds ; la post-validation vérifie création/réutilisation ou les
|
||||
conditions de fermeture/transfert de `RecoverNested`.
|
||||
|
||||
Les preuves Devnet du 16 juillet 2026 couvrent deux parcours complets `CreateIdempotent` classiques,
|
||||
la création puis la réutilisation d'un ATA Token-2022 avec `ImmutableOwner`, et un
|
||||
`RecoverNested` classique transférant 1 000 000 000 unités brutes avant fermeture du nested ATA.
|
||||
Chaque soumission a été simulée, confirmée, hydratée, extraite, décodée et matérialisée, puis rejouée
|
||||
sans doublon. La fenêtre Tauri unique expose création ATA et journal lifecycle borné ;
|
||||
`RecoverNested` reste couvert hors UI par un test opt-in contrôlé.
|
||||
|
||||
La validation finale confirme les régressions Token/Memo, 10 tests décodeur ATA, 10 tests exécuteur
|
||||
ATA, 90 tests pipeline, 113 tests RPC, 41 tests configuration, 111 tests démo, 46 tests PostgreSQL
|
||||
réels et `cargo clippy --all-targets` propre. Les versions Rust, npm et Tauri sont synchronisées en
|
||||
`0.4.5`.
|
||||
|
||||
## Jalon validé `0.4.6`
|
||||
|
||||
`0.4.6` clôt Token-2022 et le registre ElGamal comme surfaces séparées. Token-2022 couvre les instructions de base, les extensions identifiables, les états Mint/Account/Multisig et TLV, les matérialisations propriétaires et les exécuteurs simulation-first. Le registre ElGamal conserve son propre Program ID, sa matrice, son état de 64 octets, son PDA et ses opérations administratives ; il n’est pas fusionné avec Token-2022 ni avec le programme natif ZK ElGamal Proof.
|
||||
|
||||
La validation publique Token-2022 comprend huit opérations Devnet confirmées et 55 instructions Mainnet décodées sans échec. La validation réseau ElGamal Registry reste indisponible sur les clusters publics au 20 juillet 2026, mais ses builders, parsers, préflights, preuves et scénarios stateful sont validés synthétiquement/offline. Le bilan détaillé est publié dans `docs/V0_4_6_VALIDATION.md`.
|
||||
|
||||
Le replay contextualisé dispose désormais du mode `incomplete_signatures`. Il sélectionne uniquement les signatures contenant au moins une instruction `pending`, `failed`, `replay_requested` ou `unsupported`, applique la limite aux signatures avant expansion et réévalue leurs instructions compatibles sans activer le force replay global. Deux campagnes PostgreSQL réelles ont sélectionné 81 entrées chacune : 1 décodée, 4 unsupported et 76 rejets fail-closed appartenant tous à des transactions Solana échouées.
|
||||
|
||||
La régression finale confirme `kb_store_core` 41/41, `kb_store_pg` 46/46 avec PostgreSQL réel, `kb_pipeline` 124/124, `kb_app_demo` 118/118 et `cargo clippy --all-targets` propre.
|
||||
|
||||
## Jalon actif `0.4.7`
|
||||
|
||||
La suite active est Metaplex Token Metadata selon `prompts/026_v0_4_7_metaplex_token_metadata.md`. La préversion `0.4.7-pre.001` ouvre l’audit avec les crates `kb_decoder_metadata_metaplex_token_metadata` et `kb_executor_metadata_metaplex_token_metadata`, ainsi que `docs/METAPLEX_TOKEN_METADATA_MATRIX.json`, sans activation runtime tant que le wire complet n’est pas prouvé. L’exécuteur existe comme frontière audit-only parce que le SDK officiel fournit des builders, mais il n’expose encore aucune construction de transaction. Ce programme indépendant complète les metadata externes des mints SPL Token classique et Token-2022 sans être absorbé par leurs décodeurs. La priorité porte sur la frontière exacte du Program ID, les PDA et layouts versionnés, les NFT/collections/programmable assets, la provenance des metadata et le replay PostgreSQL idempotent.
|
||||
|
||||
Anchor n’est pas requis par les programmes SPL planifiés dans `0.4.x`. Son infrastructure commune est reportée à `0.4.18`, immédiatement avant Meteora, afin d’être conçue à partir des besoins réels des protocoles Anchor sans retarder Metaplex et les autres surfaces Core/SPL.
|
||||
|
||||
## Backend de données
|
||||
|
||||
PostgreSQL est le backend principal prévu. SQLite reste présent uniquement pour les tests, les imports ponctuels ou les petits corpus locaux.
|
||||
|
||||
Les tables Solana PostgreSQL utilisent le schéma courant du profil, généralement `public`. Le projet ne crée pas de schémas applicatifs explicites comme `raw`, `core`, `obs`, `decode`, `mat`, `catalog`, `agg`, `ops` ou `wallet`. La séparation logique se fait dans le nom physique de table au format `kb_sol_<domain>_<name>`, par exemple `kb_sol_raw_transactions`.
|
||||
|
||||
## Replay des signatures incomplètes
|
||||
|
||||
La fenêtre de replay contextualisé de `kb_app_demo` expose un mode `signatures_incomplete`. Il sélectionne uniquement les signatures contenant au moins une instruction `pending`, `failed`, `replay_requested` ou un résultat `unsupported`, puis réévalue les instructions compatibles de ces signatures sans activer le force replay global. La limite porte sur le nombre de signatures incomplètes avant expansion. La matérialisation reste optionnelle et idempotente.
|
||||
|
||||
Ce mode est destiné aux backfills croissants : une correction de décodeur peut reprendre seulement les signatures incomplètes au lieu de rejouer toutes les signatures déjà réussies.
|
||||
|
||||
## Livraison par delta
|
||||
|
||||
Après le squelette initial, les modifications doivent être livrées sous forme de zip delta contenant uniquement les fichiers ajoutés ou modifiés. Un delta multi-module ou racine utilise `khadhroony-bot2_vX.Y.Z-pre.abc-delta.zip`. Un delta limité à un module Rust utilise `kb_modulename_vX.Y.Z-pre.abc-delta.zip`. Un correctif conserve le même numéro `pre.abc` et ajoute `-delta-fix-001.zip`, puis `-fix-002.zip`, au lieu d’incrémenter la préversion. Chaque archive contient un `delta.md` non versionné listant les fichiers ajoutés, modifiés, à supprimer manuellement, ainsi que les validations exécutées ou non exécutées.
|
||||
|
||||
## Surfaces réservées
|
||||
|
||||
Le workspace réserve dès le squelette les crates de décodage pour les DEX, launchpads, orderbooks, routers, perps et surfaces candidates recensés dans `idls/` et dans la documentation de conception. Ces crates restent des points d'ancrage tant que les discriminants, corpus et règles de matérialisation ne sont pas validés.
|
||||
|
||||
|
||||
## Registres de programmes
|
||||
|
||||
Le workspace distingue deux registres :
|
||||
|
||||
- `registry/program_registry_seed.toml` pour les surfaces applicatives et protocolaires ;
|
||||
- `registry/core_program_id_seed.toml` pour les programmes primitifs, loaders, sysvars et comptes natifs Solana/SPL.
|
||||
|
||||
Les comptes non exécutables observés pendant la recherche restent documentés dans `docs/ACCOUNT_ONLY_CANDIDATES.md`. Bags dispose maintenant aussi d'une note dédiée dans `docs/BAGS_FM.md` pour les programmes Fee Share V1/V2 confirmés.
|
||||
|
||||
## Classification des surfaces
|
||||
|
||||
La classification des IDL locales est suivie dans `docs/IDL_SURFACE_CLASSIFICATION.md`. Le registre machine principal reste `registry/program_registry_seed.toml`.
|
||||
|
||||
## Configuration, endpoints et listeners
|
||||
|
||||
Le workspace utilise `kb_config` pour charger plusieurs profils de configuration, avec un seul profil actif. Le fichier JSON est d'abord validé par `config/schema.config.json`, puis désérialisé et validé par les règles métier Rust.
|
||||
|
||||
Le pipeline normalise toutes les sources vers une transaction canonique commune. HTTP JSON-RPC est utilisé d’abord pour les backfills gratuits. Helius `transactionSubscribe` et Yellowstone gRPC seront ajoutés plus tard dans `kb_rpc`, après les décodeurs prioritaires, sans créer de crate provider séparée. La fenêtre `demo_backfill` permet de lancer des campagnes bornées par liste de signatures, programme, token ou pool. En direction « avant, plus anciennes », une ancre vide commence sur la page la plus récente ; la direction « après, plus récentes » exige toujours une signature d’ancrage.
|
||||
|
||||
Les listeners WebSocket doivent permettre la détection temps réel des créations de token, créations de pool, migrations, swaps, changements de liquidité et changements sur les tokens ou pools surveillés. Les exports TS-rs de `kb_config` servent uniquement à partager les types Rust/TypeScript avec les applications Tauri comme `kb_app_demo`, puis les futures applications wallet ou finales. Les payloads Tauri partagés, comme la page de configuration, doivent aussi être exportés par TS-rs depuis leur crate applicative.
|
||||
|
||||
### Metaplex Token Metadata `0.4.7-pre.016`
|
||||
|
||||
L’inventaire officiel complet des modules d’instruction a été réaudité avant le passage aux comptes on-chain. `FreezeDelegatedAccount` et `ThawDelegatedAccount` historiques sont désormais décodés avec leurs contrats exacts ; les autres surfaces encore absentes restent planifiées avant toute déclaration de couverture exhaustive.
|
||||
|
||||
1439
olddocs/archivekbot2/ROADMAP.md
Normal file
1439
olddocs/archivekbot2/ROADMAP.md
Normal file
File diff suppressed because it is too large
Load Diff
231
olddocs/archivekbot2/RULES.md
Normal file
231
olddocs/archivekbot2/RULES.md
Normal file
@@ -0,0 +1,231 @@
|
||||
<!-- file: RULES.md -->
|
||||
<!-- version: 16 -->
|
||||
|
||||
# Règles spécifiques à `khadhroony-bot2`
|
||||
|
||||
Ce fichier contient uniquement les règles propres au projet et au workspace `khadhroony-bot2`.
|
||||
|
||||
Les règles Rust générales et réutilisables dans tous les projets sont définies dans [`RUST_RULES.md`](RUST_RULES.md). Les deux fichiers sont normatifs et cumulatifs. En cas de conflit, la règle la plus stricte s'applique ; une règle spécifique au workspace ne peut jamais assouplir une règle générale sans exception explicitement documentée.
|
||||
|
||||
Toute livraison doit exécuter l'audit `python3 scripts/audit_rust_workspace_rules.py`. Tant que l'audit global n'est pas propre, les écarts existants doivent être résorbés par lots de correctifs avant toute nouvelle prérelease.
|
||||
|
||||
## Règles de nommage
|
||||
|
||||
- Tous les noms de fichiers et de répertoires doivent être écrits en anglais.
|
||||
- Les noms de fichiers et de répertoires ne doivent contenir aucun accent, espace ou caractère spécial inutile.
|
||||
- Les noms internes doivent utiliser le format `snake_case` lorsque c'est applicable.
|
||||
- Les crates Rust utilisent le préfixe `kb_`.
|
||||
- Les crates de décodeur utilisent le format `kb_decoder_<protocol>_<surface>`.
|
||||
- Les crates de matérialisation utilisent le format `kb_materializer_<family>`.
|
||||
- Le crate de journalisation s'appelle `kb_logging`.
|
||||
|
||||
## Règles Tauri et TypeScript
|
||||
|
||||
- Toute structure ou énumération Rust exposée au frontend TypeScript doit importer le trait `TS` avec `use ts_rs::TS;` puis dériver `TS`.
|
||||
- Les types Rust exportés vers TypeScript doivent utiliser des noms stables et explicites.
|
||||
- Les bindings générés doivent être produits dans un dossier dédié, généralement `../frontend/ts/bindings` ou `#[ts(export, export_to = "../frontend/ts/bindings/MyStruct.ts")]`.
|
||||
- Les types purement internes au backend ne doivent pas être exportés vers TypeScript par défaut.
|
||||
- Un payload de commande ou d’événement Tauri traverse une frontière JSON et ne doit jamais exiger un `bigint` JavaScript. Pour un entier Rust borné et représentable par l’UI, utiliser un override TS-rs `number`; si l’exactitude au-delà de `Number.MAX_SAFE_INTEGER` est nécessaire, sérialiser explicitement une chaîne décimale côté Rust et exporter `string`. Ne jamais construire un `BigInt` dans un objet passé à `invoke` ou `emit`.
|
||||
- Corriger le type Rust/TS-rs source puis régénérer les bindings ; ne pas considérer une modification manuelle isolée d’un fichier généré comme un correctif durable.
|
||||
|
||||
## Règles d'architecture
|
||||
|
||||
- Les décodeurs ne dépendent pas de PostgreSQL, SQLite, RPC, Tauri, wallet, stratégie ou matérialisateurs.
|
||||
- Les matérialisateurs ne dépendent pas du RPC, du wallet, de Tauri ou des décodeurs spécifiques.
|
||||
- Pour chaque programme Solana, quelle que soit sa famille, un décodeur doit couvrir maximalement tout wire officiellement identifiable de sa surface, qu'il soit historique, courant, récent, expérimental ou publié avant son déploiement généralisé. Ces statuts doivent rester explicites et ne constituent pas un motif pour supprimer le décodage.
|
||||
- Une observation lisible issue d'une transaction échouée peut conserver une intention non commitée ; elle ne doit jamais être présentée comme une mutation réussie.
|
||||
- Pour chaque programme Solana, les matérialisateurs doivent projeter maximalement tous les faits métier stables et prouvés par le décodage, y compris les états historiques, obsolètes, dépréciés ou seulement rencontrables pendant un backfill. Le statut historique interdit l'exécution, mais ne constitue jamais à lui seul un motif de non-matérialisation.
|
||||
- Toute projection historique doit conserver explicitement son lifecycle, sa version de layout, sa provenance, son slot ou ordre d'observation lorsqu'ils sont connus, et ne doit jamais écraser silencieusement un état actif plus récent.
|
||||
- Une même réalité métier doit avoir une seule projection canonique. Les snapshots de comptes sont la source autoritative de l'état final lorsqu'ils sont disponibles ; les instructions et événements corrélés restent des observations de mutation et ne doivent pas produire un doublon concurrent du même état.
|
||||
- Les matérialisateurs doivent refuser les transactions non commitées pour les mutations d'état, tout en pouvant conserver séparément une intention non commitée lorsque le modèle métier le prévoit explicitement.
|
||||
- Toute absence volontaire de projection doit être documentée avec une justification technique précise. Un matérialisateur ne doit inventer ni état final, ni montant, ni autorité, ni frais, ni agrégation que l'observation ne prouve pas.
|
||||
- Pour chaque programme Solana, les exécuteurs doivent couvrir maximalement les opérations officiellement appelables et les opérations expérimentales publiées lorsque leurs contrats exacts et garde-fous sont prouvés. Les opérations historiques, dépréciées ou obsolètes doivent rester décodables et matérialisables, mais ne doivent jamais être exposées à l'exécution ; cette exclusion doit être explicite dans la matrice et le README.
|
||||
- Les stores exposent leurs comportements via les traits de `kb_store_core`.
|
||||
- `kb_store_pg` est le store de production.
|
||||
- `kb_store_sqlite` sert aux tests, imports et corpus locaux.
|
||||
- `kb_wallet` reste isolé du reste du système.
|
||||
- Les transactions raw sont immuables et restent la source d'audit.
|
||||
- Les replays doivent être ciblés par module, version, programme, surface, discriminator, slot ou signatures.
|
||||
- La documentation du projet ne doit pas référencer le nom de l'ancien workspace.
|
||||
|
||||
## Règles de documentation projet
|
||||
|
||||
- `README.md` décrit le projet, son rôle, ses objectifs et son organisation.
|
||||
- `ROADMAP.md` contient les futures étapes, versions et changements prévus.
|
||||
- `ROADMAP.md` conserve une structure documentaire normale par phases, cases cochées et journal de préversions ; les étiquettes conversationnelles de priorité ne doivent pas y être ajoutées.
|
||||
- Les réponses de livraison doivent reprendre la liste exhaustive des tâches avec les rubriques conversationnelles **Validé**, **En cours**, **Next** et **Planifié**, sans réduire le suivi à un résumé ambigu.
|
||||
- `CHANGELOG.md` n'est modifié qu'après validation d'une version, avec un paragraphe ajouté à la fin décrivant ce qui a été fait ou ajouté.
|
||||
- Chaque crate Rust doit avoir un `README.md` ou `001.README.md` expliquant son rôle dans l'écosystème.
|
||||
- Le README d'une crate opérationnelle doit inventorier ses types, traits, constantes et fonctions publics utiles, expliquer leurs paramètres, résultats, effets et frontières, puis fournir au moins un exemple d'utilisation lorsque l'API est destinée à être appelée directement.
|
||||
- Une API publique ajoutée ou modifiée n'est pas considérée comme documentée tant que le README de sa crate n'a pas été synchronisé ; les bindings générés seuls ne remplacent pas cette documentation.
|
||||
|
||||
## Nomenclature métier
|
||||
|
||||
- `protocol_code` désigne la famille : `pump`, `raydium`, `meteora`, `orca`, `jupiter`, etc.
|
||||
- `surface_code` désigne la surface concrète : `pump_swap`, `raydium_amm_v4`, `meteora_dlmm`, etc.
|
||||
- `event_code` suit le format `<surface_code>.<event_name>`.
|
||||
- Les familles d'événements principales sont : `trade`, `liquidity`, `lifecycle`, `fee`, `admin`, `reward`, `orderbook`, `token_account`, `pool_state`, `routing`, `risk`, `audit`, `unknown`.
|
||||
|
||||
## Base de données
|
||||
|
||||
- Les schémas PostgreSQL cibles sont : `raw`, `core`, `obs`, `decode`, `mat`, `catalog`, `agg`, `ops`, `wallet`.
|
||||
- Les colonnes JSONB doivent se terminer par `_jsonb`.
|
||||
- Les montants bruts on-chain doivent se terminer par `_raw`.
|
||||
- La transaction canonique raw reste la source rejouable et ne doit pas être supprimée après traitement sans politique de rétention explicite.
|
||||
|
||||
## Nommage canonique des surfaces
|
||||
|
||||
Les nouvelles surfaces de programmes doivent utiliser un nom canonique basé sur la fonction réelle du programme :
|
||||
|
||||
```text
|
||||
<function_code>_<family_code>_<identifier_code>[_vN]
|
||||
```
|
||||
|
||||
Les crates de décodage doivent utiliser :
|
||||
|
||||
```text
|
||||
kb_decoder_<function_code>_<family_code>_<identifier_code>[_vN]
|
||||
```
|
||||
|
||||
Exemples :
|
||||
|
||||
- `kb_decoder_amm_raydium_cpmm` ;
|
||||
- `kb_decoder_clmm_raydium` ;
|
||||
- `kb_decoder_dlmm_meteora` ;
|
||||
- `kb_decoder_router_jupiter_aggregator_v6` ;
|
||||
- `kb_decoder_orderbook_openbook_v2` ;
|
||||
- `kb_decoder_metadata_metaplex_token_metadata` ;
|
||||
- `kb_decoder_nft_metaplex_bubblegum`.
|
||||
|
||||
Les noms historiques ou issus d'IDL doivent être conservés dans le registre, mais ne doivent pas créer de nouvelles crates si une crate canonique existe déjà.
|
||||
|
||||
Aucun renommage massif de crates n'est autorisé sans étape de contrôle dédiée et sans `cargo build` validé.
|
||||
|
||||
## Règles de nommage des surfaces Solana
|
||||
|
||||
- Le nom canonique d'une surface doit commencer par une fonction réelle : `amm`, `clmm`, `dlmm`, `router`, `orderbook`, `launchpad`, `lending`, `vault`, `staking`, `bridge`, `perpetuals`, `oracle`, `nft`, `metadata`, `admin`, etc.
|
||||
- Le préfixe `program_` est interdit pour les nouveaux noms canoniques.
|
||||
- Les surfaces non classifiées doivent utiliser `unknown_*` et ne doivent pas avoir de crate cible tant que leur fonction n'est pas validée.
|
||||
- Les programmes Solana/SPL primitifs doivent rester séparés des surfaces DEX/router dans la documentation de contrôle.
|
||||
- `damm` ne doit pas être utilisé comme préfixe fonctionnel ; utiliser `amm_meteora_damm_v1` ou `amm_meteora_damm_v2`.
|
||||
|
||||
## Registre des identifiants core
|
||||
|
||||
- Les identifiants Solana/SPL primitifs doivent être tenus à jour dans `registry/core_program_id_seed.toml`.
|
||||
- Les sysvars et comptes natifs connus ne doivent pas être classés comme surfaces DEX/router.
|
||||
- `spl_token`, `spl_token_2022` et `associated_token_account` restent dans leurs crates spécialisées.
|
||||
- `stake_pool` doit être réservé à un futur crate spécialisé plutôt que mélangé avec le programme `stake`.
|
||||
|
||||
## Index court de programme
|
||||
|
||||
- Les noms de crates ne doivent pas commencer par un index hexadécimal.
|
||||
- Un champ `registry_code` optionnel peut être ajouté au registre pour l'UI, PostgreSQL ou les matrices.
|
||||
- Le nom canonique reste la source principale : fonction + famille + identifiant + version.
|
||||
|
||||
## Comptes non exécutables
|
||||
|
||||
- Une adresse de compte, de pool, de PDA ou de vault ne doit pas générer une crate de décodeur.
|
||||
- Le vrai `program_id` propriétaire doit être prouvé avant création d'une surface canonique.
|
||||
|
||||
## Constantes Rust
|
||||
|
||||
- Les fichiers `program_ids.rs` sont interdits dans les nouveaux crates. Utiliser `constants.rs`.
|
||||
- Les `program_id` publics doivent être réexportés depuis `lib.rs`.
|
||||
- Dans une crate, les modules internes doivent appeler les constantes réexportées via `crate::CONSTANT_NAME`.
|
||||
- Les discriminants, sélecteurs, longueurs Borsh et constantes internes futures doivent être placés dans `constants.rs` et rester `pub(crate)` sauf besoin d'API publique explicite.
|
||||
|
||||
## Règles de tracing
|
||||
|
||||
- Une crate est opérationnelle lorsqu’elle effectue des I/O, orchestre un pipeline, décode, matérialise, exécute, applique une politique runtime ou prend une décision mutable observable.
|
||||
- Toute crate opérationnelle ajoutée ou modifiée doit dépendre de `tracing` depuis le workspace et déclarer exactement un `pub(crate) const TRACING_TARGET` dans `src/constants.rs`.
|
||||
- La valeur canonique de `TRACING_TARGET` est le nom exact du package Cargo. Les targets historiques `khbot.*`, les suffixes de module et les targets de fenêtre sont interdits dans les nouvelles modifications.
|
||||
- Les macros `tracing` doivent utiliser `target: crate::TRACING_TARGET` et des champs structurés stables. La granularité interne passe par `action`, `stage`, `window`, `campaign_id`, `signature`, `instruction_path`, `program_id`, `processor_name`, `processor_version`, `status` et `error_code`.
|
||||
- Les crates passives de types, contrats, DTO, API sans exécution, registres ou constantes restent sans dépendance `tracing`. `kb_config` reste une exception de bootstrap tant que sa validation précède l’installation du subscriber.
|
||||
- Il est interdit d’ajouter `tracing` sans événement réel ou de conserver un faux target uniquement consommé par `let _target`.
|
||||
- Une décision interne doit être journalisée par la crate responsable ; `kb_app_demo` ne journalise que les frontières Tauri/UI, les actions utilisateur et les résumés d’orchestration.
|
||||
- Tout input sélectionné sans décodeur compatible, tout résultat de décodage `failed` ou `unsupported`, tout résultat de matérialisation `failed`, toute validation de résultat invalide et toute erreur de persistance doivent émettre un événement `error` avant le retour ou la persistance terminale.
|
||||
- Une transaction Solana échouée mais correctement décodée n’est pas une erreur du logiciel. Une décision `ignored`, un refus de matérialisation conforme à la politique ou une annulation coopérative ne doivent pas être promus artificiellement au niveau `error`.
|
||||
- Les erreurs de décodage et de matérialisation doivent conserver au minimum, lorsque disponibles : `campaign_id`, `signature`, `slot`, `instruction_path`, `program_id`, processor ou materializer avec version, `input_key`, `input_hash` ou hash du payload, statut, code et diagnostic borné.
|
||||
- Les payloads complets, DSN non masqués, secrets, clés privées et données non bornées sont interdits dans les logs.
|
||||
- Chaque profil doit router les événements vers les sorties globales `debug.log`, `info.log`, `error.jsonl` et `app.log`, puis vers `debug.log`, `info.log` et `error.jsonl` dans un répertoire propre à chaque crate utilisant `tracing`.
|
||||
- L’ajout ou la suppression de `tracing.workspace = true` dans une crate impose la mise à jour simultanée de la matrice de routes, de ses tests et de `docs/TRACING_CONTRACT.md`.
|
||||
- Le contrat détaillé est défini dans `docs/TRACING_CONTRACT.md`.
|
||||
- L’audit mécanique spécifique au projet est exécuté par `python3 scripts/audit_khadhroony_workspace_rules.py`. Il couvre notamment `TRACING_TARGET` et l’usage obligatoire de `solana_pubkey::Pubkey` à la place de `solana_address::Address`.
|
||||
|
||||
## Règles de réutilisation des interfaces Solana et SPL
|
||||
|
||||
- Les dépendances déclarées dans `[workspace.dependencies]` forment un catalogue de versions et de features autorisées ; elles ne doivent être ajoutées à une crate consommatrice que lorsqu’un type, un encodeur, un décodeur ou un identifiant officiel est réellement utilisé.
|
||||
|
||||
- Dans un `Cargo.toml`, placer dans `[dependencies]` toute crate référencée par le code de bibliothèque compilé en production. Réserver `[dev-dependencies]` aux références contenues exclusivement dans `#[cfg(test)]`, les tests d’intégration, benches ou exemples. Une dépendance de test vers un décodeur ou matérialiseur concret est légitime lorsqu’elle sert uniquement à éprouver une orchestration générique fondée sur les traits API ; elle ne prouve pas qu’une capacité de production manque. Toute promotion de `dev-dependencies` vers `dependencies` doit être motivée par un appel runtime réel, et toute dépendance runtime inutilisée doit être supprimée.
|
||||
- Les registres de composition runtime des applications doivent énumérer explicitement chaque décodeur et matérialiseur concret activé. Toute nouvelle surface instructionnelle dotée d’un `EventMaterializer` doit être ajoutée au registre applicatif et couverte par un test d’inventaire ordonné ; une crate présente dans le workspace ou dans `kb_pipeline` n’est pas activée automatiquement. Les matérialiseurs exclusivement stateful qui n’implémentent pas `EventMaterializer` restent routés par leurs APIs de snapshots dédiées.
|
||||
- Les corrélations instruction/état doivent produire une issue explicite (`confirmed`, `contradicted` ou `not_applicable`) et ne doivent jamais transformer automatiquement une configuration observée en violation, score ou conclusion métier.
|
||||
- Une interface officielle Solana ou SPL étroite doit être préférée à `solana-sdk` lorsque son contrat suffit.
|
||||
- L’ordre de préférence des formats est : schéma officiel `wincode`, schéma officiel Borsh, puis parseur local borné reproduisant exactement le runtime lorsque l’interface officielle n’expose que `bincode`.
|
||||
- Aucun nouveau code ne doit dépendre directement de `bincode`. Une interface officielle uniquement disponible derrière une feature `bincode` ne justifie pas l’activation de cette feature ; le layout doit alors être prouvé depuis les sources officielles et implémenté localement avec des bornes et des tests.
|
||||
- Les exécuteurs doivent utiliser les builders officiels disponibles, préserver l’ordre exact des metas, borner toute liste de comptes variable avant l’appel au builder et refuser les doublons lorsque leur répétition n’a pas de sémantique publiée.
|
||||
- Les features des interfaces doivent rester minimales et explicites. Une feature `serde`, `wincode`, `borsh`, `std`, `alloc` ou équivalente n’est activée que si la crate consommatrice l’utilise réellement.
|
||||
- Les crates applicatives ne doivent pas dépendre d’interfaces RPC ou transactionnelles uniquement pour relayer des types ; ces dépendances appartiennent à `kb_rpc`, aux modèles communs justifiés ou à la crate opérationnelle propriétaire.
|
||||
- Toute exception et toute implémentation locale doivent être documentées dans `docs/SOLANA_INTERFACE_DEPENDENCIES.md` avec la raison, la source officielle et la stratégie de test.
|
||||
|
||||
## Règles des exécuteurs
|
||||
|
||||
- Les crates d'exécution utilisent le préfixe `kb_executor_`.
|
||||
- Une surface classifiée peut avoir un décodeur `kb_decoder_<surface>` et un exécuteur `kb_executor_<surface>`.
|
||||
- Les exécuteurs ne doivent pas dépendre des décodeurs.
|
||||
- Les exécuteurs doivent passer par `kb_execution_api` pour leur contrat public.
|
||||
- Les garde-fous communs doivent être placés dans `kb_execution_safety`.
|
||||
- Aucun exécuteur ne doit envoyer de transaction sans simulation et validation explicite.
|
||||
- Les surfaces non classifiées ne doivent pas avoir de crate exécuteur.
|
||||
- Pour chaque programme Solana et contrairement aux décodeurs, les exécuteurs ne construisent pas les opérations obsolètes ou purement historiques. Ils couvrent uniquement les opérations courantes et expérimentales officiellement constructibles, avec un statut exact `Supported` ou `Unsupported(reason)`.
|
||||
- Le statut expérimental, récent ou non encore déployé partout n'interdit pas un builder universel lorsqu'un wire officiel exact existe. Le déploiement, la simulation et l'autorisation d'envoi restent trois décisions séparées ; la bibliothèque ne doit pas imposer artificiellement un cluster.
|
||||
|
||||
|
||||
- Les champs JSON exposés à TypeScript ne doivent pas utiliser directement `serde_json::Value` avec `TS-rs`; utiliser une chaîne JSON sérialisée (`std::string::String`) ou un type Rust typé exportable.
|
||||
- Les APIs qui gardent des payloads dynamiques doivent fournir des helpers explicites basés sur `serde_json::to_string` et `serde_json::to_string_pretty`.
|
||||
|
||||
## Règles de configuration
|
||||
|
||||
- La configuration applicative commune doit passer par `kb_config`.
|
||||
- Les fichiers JSON de configuration ne doivent pas contenir de commentaires.
|
||||
- Les secrets ne doivent pas être écrits en clair dans le dépôt.
|
||||
- Les valeurs sensibles doivent utiliser des variables d'environnement ou un stockage chiffré dédié.
|
||||
- Les structures de configuration exposées à Tauri doivent dériver `TS`.
|
||||
|
||||
## Ordre de développement cible
|
||||
|
||||
- `kb_logging` doit être stabilisé avant les logs avancés des autres crates.
|
||||
- `kb_config` doit être stabilisé avant les stores, RPC, wallet, applications et workers.
|
||||
- Les contrats SQL et de matérialisation doivent être définis avant les gros décodeurs DEX.
|
||||
- Les implémentations détaillées des matérialisateurs doivent suivre les sorties réelles des décodeurs correspondants.
|
||||
- `kb_app_demo` doit fournir des validations live après chaque capacité majeure, sans créer une application Tauri séparée par crate.
|
||||
|
||||
## Règles de livraison ChatGPT
|
||||
|
||||
- Après le squelette initial, ChatGPT doit fournir uniquement des zips delta sauf demande explicite de zip complet.
|
||||
- Un delta qui modifie la racine du workspace ou plusieurs modules doit être nommé `khadhroony-bot2_vX.Y.Z-pre.abc-delta.zip`.
|
||||
- Un delta qui ne modifie qu'un seul module Rust doit être nommé `kb_modulename_vX.Y.Z-pre.abc-delta.zip`.
|
||||
- Lorsqu'un delta `pre.abc` a déjà été livré et qu'un correctif est nécessaire, le numéro `abc` ne doit pas être incrémenté. Le correctif doit être nommé `khadhroony-bot2_vX.Y.Z-pre.abc-delta-fix-001.zip`, puis `-fix-002.zip`, etc. Pour un seul module, utiliser la même règle avec le préfixe `kb_modulename`.
|
||||
- Un correctif doit indiquer dans `delta.md` le delta de base et les correctifs antérieurs à appliquer. Il ne doit pas réutiliser silencieusement le nom ou l'empreinte d'une archive déjà livrée.
|
||||
- Le numéro `pre.abc` suivant est réservé à une nouvelle tranche fonctionnelle, pas à la réparation d'une archive existante.
|
||||
- Chaque zip delta ou correctif doit contenir un fichier `delta.md` non versionné à la racine du zip.
|
||||
- `delta.md` doit lister les fichiers ajoutés, les fichiers modifiés, les fichiers à supprimer manuellement, les validations exécutées et les validations non exécutées.
|
||||
- Le zip delta ne doit pas contenir de fichiers inchangés.
|
||||
- Le zip delta ne doit pas modifier `CHANGELOG.md` sauf validation explicite d'une version.
|
||||
- Les suppressions de fichiers ou dossiers doivent être indiquées dans `delta.md`, car l'extraction d'un zip ne supprime pas automatiquement les anciens fichiers.
|
||||
- Les prompts de session doivent rappeler ce format de livraison et la règle `delta-fix-NNN`.
|
||||
|
||||
## Constantes des décodeurs
|
||||
|
||||
- Chaque crate `kb_decoder_*` classifié avec un `program_id` doit avoir un fichier `src/constants.rs`.
|
||||
- `src/constants.rs` contient les `PROGRAM_ID`, puis les discriminators, sélecteurs, opcodes, constantes Borsh et constantes de décodage quand elles seront connues.
|
||||
- `src/lib.rs` doit réexporter les constantes nécessaires avec `pub use crate::constants::...`.
|
||||
- `src/decoder.rs` doit utiliser les constantes réexportées par la crate, par exemple `crate::AMM_PUMP_SWAP_PROGRAM_ID`, et non `crate::constants::AMM_PUMP_SWAP_PROGRAM_ID`.
|
||||
- Les literals de `program_id` ne doivent pas rester dans `program_ids()`, sauf dans un fichier `constants.rs`.
|
||||
|
||||
## Identifiants de programmes
|
||||
|
||||
Les `program_id` connus doivent être définis une seule fois dans `kb_program_ids`. Les crates de décodeur, d’exécuteur, de store, d’application ou d’outil doivent référencer directement `kb_program_ids::XXX_PROGRAM_ID`. Les fichiers `constants.rs` locaux ne doivent pas redéfinir ces chaînes ; ils restent réservés aux constantes internes du module, par exemple discriminators, opcodes, seeds, index de comptes ou layouts.
|
||||
|
||||
## Validation frontend Tauri
|
||||
|
||||
- Pour `kb_app_demo`, ne pas lancer `npm --prefix kb_app_demo run build` séparément : la validation frontend de développement est réalisée par `cargo tauri dev -c kb_app_demo/tauri.conf.json`, qui démarre et pilote le serveur Vite.
|
||||
134
olddocs/archivekbot2/RUST_RULES.md
Normal file
134
olddocs/archivekbot2/RUST_RULES.md
Normal file
@@ -0,0 +1,134 @@
|
||||
<!-- file: RUST_RULES.md -->
|
||||
<!-- version: 3 -->
|
||||
|
||||
# Règles Rust générales
|
||||
|
||||
Ce fichier contient les règles normatives applicables à tous les projets Rust. Elles sont indépendantes de `khadhroony-bot2` et doivent pouvoir être réutilisées telles quelles dans un autre workspace.
|
||||
|
||||
## En-têtes et versions de fichiers
|
||||
|
||||
- Tout fichier texte qui supporte des commentaires commence par une ligne indiquant son chemin relatif dans le projet, puis une ligne `version` entière.
|
||||
- La version d'un fichier est incrémentée à chaque modification après validation de sa version précédente.
|
||||
- Les fichiers Rust utilisent `// file: ...` et `// version: N`.
|
||||
- Les fichiers Markdown utilisent `<!-- file: ... -->` et `<!-- version: N -->`.
|
||||
- Tous les fichiers texte se terminent par exactement une fin de ligne.
|
||||
|
||||
## Langue et documentation
|
||||
|
||||
- Les commentaires et rustdocs du code sont rédigés en anglais.
|
||||
- Les documents Markdown du projet sont rédigés dans la langue documentaire choisie par le projet.
|
||||
- Tout élément `pub` ou `pub(crate)` possède une rustdoc utile au point de déclaration.
|
||||
- Toute réexportation `pub use` ou `pub(crate) use` dans `lib.rs` ou `main.rs` possède également sa propre rustdoc copiée ou reformulée de manière équivalente. La documentation du point d'entrée doit permettre de comprendre l'API sans ouvrir le module interne.
|
||||
|
||||
## Édition et lints obligatoires
|
||||
|
||||
- L'édition Rust cible est Rust 2024, sauf contrainte explicitement documentée.
|
||||
- Chaque `lib.rs` et `main.rs` contient :
|
||||
- `#![warn(missing_docs)]` ;
|
||||
- `#![deny(unreachable_pub)]` ;
|
||||
- `#![forbid(unsafe_code)]`.
|
||||
- Les lints Clippy obligatoires sont déclarés au niveau workspace et hérités par toutes les crates.
|
||||
- Les règles minimales sont : interdiction de `unwrap`, `expect`, `?`, retours implicites, code `unsafe`, APIs publiques inaccessibles et imports globaux non justifiés.
|
||||
- Les tests peuvent disposer d'exceptions limitées pour `unwrap` et `expect` uniquement lorsqu'elles sont explicitement autorisées par la configuration Clippy.
|
||||
|
||||
La configuration workspace doit au minimum déclarer :
|
||||
|
||||
```toml
|
||||
[workspace.lints.rust]
|
||||
missing_docs = "warn"
|
||||
unreachable_pub = "deny"
|
||||
unsafe_code = "forbid"
|
||||
|
||||
[workspace.lints.clippy]
|
||||
unwrap_used = "deny"
|
||||
expect_used = "deny"
|
||||
implicit_return = "deny"
|
||||
needless_return = "allow"
|
||||
useless_vec = "deny"
|
||||
question_mark = "deny"
|
||||
question_mark_used = "deny"
|
||||
needless_match = "allow"
|
||||
manual_ok_err = "allow"
|
||||
manual_unwrap_or = "allow"
|
||||
manual_map = "allow"
|
||||
match_like_matches_macro = "allow"
|
||||
single_match = "allow"
|
||||
manual_unwrap_or_default = "allow"
|
||||
manual_find = "allow"
|
||||
explicit_counter_loop = "allow"
|
||||
get_first = "allow"
|
||||
implicit_saturating_sub = "allow"
|
||||
```
|
||||
|
||||
## Formatage
|
||||
|
||||
- `cargo fmt --all` est exécuté après application de chaque delta ou correctif et avant les tests.
|
||||
- Les fichiers Rust ne contiennent pas de lignes vides à l'intérieur d'une fonction, d'une structure, d'une énumération ou d'une implémentation courte.
|
||||
- Les lignes vides séparent uniquement les fonctions, blocs `impl`, types et sections logiques.
|
||||
- Les exports de `lib.rs` ou `main.rs` ne contiennent aucune ligne vide à l'intérieur d'une série homogène de `pub use` ou `pub(crate) use`.
|
||||
- Les séries `pub use` et `pub(crate) use` forment deux groupes séparés lorsqu'elles coexistent.
|
||||
|
||||
## Imports et chemins
|
||||
|
||||
- `use` est interdit pour les constantes, fonctions, structures, énumérations, unions, alias de types, modules et macros.
|
||||
- `use` est autorisé uniquement pour un trait lorsque la résolution de méthode, une macro de dérivation ou une contrainte de langage l'exige réellement.
|
||||
- Un import de trait doit rester étroit et ne doit jamais importer simultanément des éléments non-traits par accolades.
|
||||
- Les imports globaux, glob imports et imports groupés par accolades sont interdits.
|
||||
- Pour un élément fourni par une crate externe au workspace, utiliser directement le chemin public le plus court exposé par cette crate. Exemple : utiliser `external_crate::Struct`, jamais `external_crate::module::Struct` si `external_crate::Struct` existe, et jamais `use external_crate::Struct`.
|
||||
- Pour un élément `pub` déclaré dans le workspace :
|
||||
- il est réexporté depuis le `lib.rs` ou `main.rs` de sa crate propriétaire ;
|
||||
- depuis une autre crate, il est appelé via `owner_crate::Item` ;
|
||||
- depuis sa propre crate, il est appelé via `crate::Item`, même depuis son module de déclaration.
|
||||
- Pour un élément `pub(crate)` :
|
||||
- il est réexporté depuis le `lib.rs` ou `main.rs` via `pub(crate) use` ;
|
||||
- il est appelé via `crate::Item`, même depuis son module de déclaration.
|
||||
- Un élément strictement privé à un module n'est pas réexporté et est appelé par son nom local uniquement. Il est interdit d'utiliser un chemin long comme `crate::module::helper` ou `owner_crate::module::helper` pour un helper privé du module courant.
|
||||
- Dans un sous-module de tests, un élément privé du module parent est appelé via `super::Item`. Un élément `pub` ou `pub(crate)` continue d’être appelé via le point d’entrée de crate le plus court, par exemple `crate::Item`.
|
||||
- Les exports ne sont jamais groupés avec des accolades. Un type, une fonction, une constante ou un alias correspond à une ligne de réexport distincte.
|
||||
|
||||
## Visibilité et API de crate
|
||||
|
||||
- Aucun `pub mod` n'est autorisé. Les modules restent privés et l'API est constituée par des réexports explicites.
|
||||
- Un élément `pub` inaccessible depuis le point d'entrée de sa crate est une erreur de conception, pas un simple avertissement.
|
||||
- Un élément `pub(crate)` utilisé hors de son module est réexporté au niveau du point d'entrée de la crate.
|
||||
- Les chemins internes de modules ne font pas partie de l'API stable.
|
||||
- Les méthodes inhérentes publiques restent appelées via le type réexporté ; les fonctions libres publiques sont appelées via le point d'entrée de crate.
|
||||
|
||||
## Helpers et réutilisation
|
||||
|
||||
- Un helper répété dans plusieurs modules d'une même crate est déplacé dans un module commun explicite, généralement `helper.rs` ou un module spécialisé plus précis.
|
||||
- Le nom `helpers.rs` ou `helper.rs` n'est utilisé que si aucune responsabilité métier plus précise ne convient.
|
||||
- Un helper général réutilisable par plusieurs crates est déplacé dans une crate commune appropriée et exposé publiquement.
|
||||
- Les types d'erreur généraux, identifiants de programme, primitives de validation et fonctions de sérialisation communes ne doivent pas être dupliqués entre crates.
|
||||
- La mutualisation ne doit pas créer de dépendance cyclique ni déplacer un comportement métier spécifique dans une crate générique.
|
||||
|
||||
## Gestion des erreurs et contrôle de flux
|
||||
|
||||
- `unwrap`, `expect` et `panic` sont interdits dans le code de production.
|
||||
- L'opérateur `?` est interdit dans les chemins de production ; utiliser des `match` explicites avec erreurs contextualisées.
|
||||
- `anyhow` et `thiserror` ne sont pas utilisés par défaut.
|
||||
- Les erreurs publiques sont typées lorsque leur contrat est stable ; les diagnostics dynamiques restent bornés.
|
||||
- Les retours sont explicites conformément au lint `clippy::implicit_return`.
|
||||
|
||||
## Sécurité et dépendances
|
||||
|
||||
- Le code `unsafe` est interdit.
|
||||
- Une dépendance n'est ajoutée que si elle est réellement utilisée dans le chemin de compilation concerné.
|
||||
- Une dépendance utilisée uniquement dans les tests reste dans `[dev-dependencies]`.
|
||||
- Les features sont minimales et explicites.
|
||||
|
||||
## Contrôle avant livraison
|
||||
|
||||
Chaque livraison Rust exécute au minimum, dans cet ordre :
|
||||
|
||||
```bash
|
||||
cargo fmt --all
|
||||
python3 scripts/audit_rust_general_rules.py
|
||||
python3 scripts/audit_khadhroony_workspace_rules.py
|
||||
cargo test --workspace
|
||||
cargo clippy --workspace --all-targets
|
||||
```
|
||||
|
||||
Un projet peut utiliser une sélection de tests plus étroite pendant le développement, mais la fermeture d'une version exige le contrôle global.
|
||||
|
||||
Le wrapper `python3 scripts/audit_rust_workspace_rules.py` exécute les deux audits sans fusionner leurs responsabilités.
|
||||
62
olddocs/archivekbot2/config/README.md
Normal file
62
olddocs/archivekbot2/config/README.md
Normal file
@@ -0,0 +1,62 @@
|
||||
<!-- file: config/README.md -->
|
||||
<!-- version: 13 -->
|
||||
|
||||
# Configuration locale
|
||||
|
||||
Ce dossier contient les exemples et le schéma de configuration JSON.
|
||||
|
||||
## Règles
|
||||
|
||||
- Le fichier versionné doit rester sans secret.
|
||||
- Les placeholders de clés restent directement dans les URLs.
|
||||
- Le champ `active_profile` sélectionne un seul profil actif.
|
||||
- Un profil actif doit être présent et unique.
|
||||
- Les profils non actifs peuvent rester dans le fichier pour les tests devnet, mainnet lecture seule, backfill ou future production.
|
||||
- Le contrat courant couvre HTTP JSON-RPC Solana et WebSocket JSON-RPC générique.
|
||||
- Helius `transactionSubscribe` et Yellowstone gRPC seront ajoutés plus tard dans `kb_rpc`, avec évolution explicite du schéma quand les transports seront réellement utilisés.
|
||||
- Les IDLs restent des artefacts de développement et ne font pas partie de la configuration runtime.
|
||||
|
||||
## Fichiers
|
||||
|
||||
- `example.config.json` : exemple complet avec profils `local_devnet`, `mainnet_research` et `mainnet`.
|
||||
- `schema.config.json` : JSON Schema de validation du fichier de configuration.
|
||||
|
||||
## Phase `0.3.x`
|
||||
|
||||
`0.3.x` utilise les endpoints HTTP des profils de recherche existants pour :
|
||||
|
||||
```text
|
||||
getSignaturesForAddress
|
||||
getTransaction
|
||||
getSignatureStatuses
|
||||
```
|
||||
|
||||
Aucun profil Helius payant ou Yellowstone n’est activé à ce stade.
|
||||
|
||||
Les sources futures devront déclarer séparément :
|
||||
|
||||
- provider ;
|
||||
- protocole ;
|
||||
- rôle ;
|
||||
- limites de streams et filtres ;
|
||||
- authentification ;
|
||||
- région éventuelle.
|
||||
|
||||
## Évolution du schéma
|
||||
|
||||
`schema.config.json` est le contrat de validation runtime. Il évolue seulement lorsqu’un champ est réellement utilisé par l’exécution.
|
||||
|
||||
## Logging de développement
|
||||
|
||||
L’exemple configure, pour chacun des trois profils, quatre fichiers globaux puis trois fichiers dédiés par crate opérationnelle utilisant `tracing` : `debug.log`, `info.log` et `error.jsonl`.
|
||||
|
||||
`pre.020` rend `kb_materializer_admin` et `kb_materializer_compliance_audit` opérationnelles. `pre.021` active ensuite `kb_materializer_staking`. Elles rejoignent donc la console et disposent de leurs routes propres sous :
|
||||
|
||||
```text
|
||||
logs/<profil>/kb_materializer_admin/
|
||||
logs/<profil>/kb_materializer_compliance_audit/
|
||||
logs/<profil>/kb_materializer_staking/
|
||||
```
|
||||
|
||||
Le test de configuration découvre dynamiquement toutes les crates déclarant `tracing.workspace = true` et vérifie leurs trois routes dans chaque profil. Les logs ne doivent contenir ni secret, ni DSN non masqué, ni payload Config ou bytecode complet.
|
||||
|
||||
5211
olddocs/archivekbot2/config/example.config.json
Normal file
5211
olddocs/archivekbot2/config/example.config.json
Normal file
File diff suppressed because it is too large
Load Diff
774
olddocs/archivekbot2/config/schema.config.json
Normal file
774
olddocs/archivekbot2/config/schema.config.json
Normal file
@@ -0,0 +1,774 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://khadhroony.local/schema/config.schema.json",
|
||||
"title": "Khadhroony Bot2 configuration",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"active_profile",
|
||||
"profiles"
|
||||
],
|
||||
"properties": {
|
||||
"active_profile": {
|
||||
"$ref": "#/$defs/non_empty_string"
|
||||
},
|
||||
"profiles": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": {
|
||||
"$ref": "#/$defs/profile"
|
||||
}
|
||||
}
|
||||
},
|
||||
"$defs": {
|
||||
"non_empty_string": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"log_level": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"trace",
|
||||
"debug",
|
||||
"info",
|
||||
"warn",
|
||||
"error",
|
||||
"off"
|
||||
]
|
||||
},
|
||||
"profile": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"name",
|
||||
"app",
|
||||
"logging",
|
||||
"database",
|
||||
"data",
|
||||
"solana",
|
||||
"wallet",
|
||||
"execution",
|
||||
"demo"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"$ref": "#/$defs/non_empty_string"
|
||||
},
|
||||
"app": {
|
||||
"$ref": "#/$defs/app_section"
|
||||
},
|
||||
"logging": {
|
||||
"$ref": "#/$defs/logging"
|
||||
},
|
||||
"database": {
|
||||
"$ref": "#/$defs/database"
|
||||
},
|
||||
"data": {
|
||||
"$ref": "#/$defs/data"
|
||||
},
|
||||
"solana": {
|
||||
"$ref": "#/$defs/solana"
|
||||
},
|
||||
"wallet": {
|
||||
"$ref": "#/$defs/wallet"
|
||||
},
|
||||
"execution": {
|
||||
"$ref": "#/$defs/execution"
|
||||
},
|
||||
"demo": {
|
||||
"$ref": "#/$defs/demo"
|
||||
}
|
||||
}
|
||||
},
|
||||
"app_section": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"name",
|
||||
"environment",
|
||||
"auto_reconnect_default"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"$ref": "#/$defs/non_empty_string"
|
||||
},
|
||||
"environment": {
|
||||
"$ref": "#/$defs/non_empty_string"
|
||||
},
|
||||
"auto_reconnect_default": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
"logging": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"default_level",
|
||||
"targets",
|
||||
"target_filters"
|
||||
],
|
||||
"properties": {
|
||||
"default_level": {
|
||||
"$ref": "#/$defs/log_level"
|
||||
},
|
||||
"targets": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": {
|
||||
"$ref": "#/$defs/log_target"
|
||||
}
|
||||
},
|
||||
"target_filters": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/$defs/log_target_filter"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"log_target": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"name",
|
||||
"enabled",
|
||||
"sink",
|
||||
"level",
|
||||
"path",
|
||||
"rotation",
|
||||
"format",
|
||||
"ansi",
|
||||
"targets"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"$ref": "#/$defs/non_empty_string"
|
||||
},
|
||||
"enabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"sink": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"console",
|
||||
"file"
|
||||
]
|
||||
},
|
||||
"level": {
|
||||
"$ref": "#/$defs/log_level"
|
||||
},
|
||||
"path": {
|
||||
"type": "string"
|
||||
},
|
||||
"rotation": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"none",
|
||||
"never",
|
||||
"daily",
|
||||
"hourly"
|
||||
]
|
||||
},
|
||||
"format": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"human",
|
||||
"compact",
|
||||
"pretty",
|
||||
"json"
|
||||
]
|
||||
},
|
||||
"ansi": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"targets": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/$defs/non_empty_string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"log_target_filter": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"target",
|
||||
"level"
|
||||
],
|
||||
"properties": {
|
||||
"target": {
|
||||
"$ref": "#/$defs/non_empty_string"
|
||||
},
|
||||
"level": {
|
||||
"$ref": "#/$defs/log_level"
|
||||
}
|
||||
}
|
||||
},
|
||||
"database": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"enabled",
|
||||
"backend",
|
||||
"postgres",
|
||||
"sqlite"
|
||||
],
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"backend": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"postgres",
|
||||
"sqlite"
|
||||
]
|
||||
},
|
||||
"postgres": {
|
||||
"$ref": "#/$defs/postgres"
|
||||
},
|
||||
"sqlite": {
|
||||
"$ref": "#/$defs/sqlite"
|
||||
}
|
||||
}
|
||||
},
|
||||
"postgres": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"url",
|
||||
"max_connections",
|
||||
"connect_timeout_ms",
|
||||
"auto_initialize_schema"
|
||||
],
|
||||
"properties": {
|
||||
"url": {
|
||||
"$ref": "#/$defs/non_empty_string"
|
||||
},
|
||||
"max_connections": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
},
|
||||
"connect_timeout_ms": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
},
|
||||
"auto_initialize_schema": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
"sqlite": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"path",
|
||||
"create_if_missing",
|
||||
"busy_timeout_ms",
|
||||
"max_connections",
|
||||
"auto_initialize_schema",
|
||||
"use_wal"
|
||||
],
|
||||
"properties": {
|
||||
"path": {
|
||||
"$ref": "#/$defs/non_empty_string"
|
||||
},
|
||||
"create_if_missing": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"busy_timeout_ms": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
},
|
||||
"max_connections": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
},
|
||||
"auto_initialize_schema": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"use_wal": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
"data": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"wallets_directory",
|
||||
"logs_directory"
|
||||
],
|
||||
"properties": {
|
||||
"wallets_directory": {
|
||||
"$ref": "#/$defs/non_empty_string"
|
||||
},
|
||||
"logs_directory": {
|
||||
"$ref": "#/$defs/non_empty_string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"solana": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"http_endpoints",
|
||||
"ws_endpoints",
|
||||
"listeners"
|
||||
],
|
||||
"properties": {
|
||||
"http_endpoints": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": {
|
||||
"$ref": "#/$defs/http_endpoint"
|
||||
}
|
||||
},
|
||||
"ws_endpoints": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": {
|
||||
"$ref": "#/$defs/ws_endpoint"
|
||||
}
|
||||
},
|
||||
"listeners": {
|
||||
"$ref": "#/$defs/listeners"
|
||||
}
|
||||
}
|
||||
},
|
||||
"http_endpoint": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"name",
|
||||
"enabled",
|
||||
"provider",
|
||||
"cluster",
|
||||
"url",
|
||||
"connect_timeout_ms",
|
||||
"request_timeout_ms",
|
||||
"max_idle_connections_per_host",
|
||||
"roles"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"$ref": "#/$defs/non_empty_string"
|
||||
},
|
||||
"enabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"provider": {
|
||||
"$ref": "#/$defs/non_empty_string"
|
||||
},
|
||||
"cluster": {
|
||||
"$ref": "#/$defs/non_empty_string"
|
||||
},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"pattern": "^https?://"
|
||||
},
|
||||
"connect_timeout_ms": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
},
|
||||
"request_timeout_ms": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
},
|
||||
"max_idle_connections_per_host": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
},
|
||||
"roles": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": {
|
||||
"$ref": "#/$defs/endpoint_role"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"ws_endpoint": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"name",
|
||||
"enabled",
|
||||
"provider",
|
||||
"cluster",
|
||||
"url",
|
||||
"connect_timeout_ms",
|
||||
"request_timeout_ms",
|
||||
"unsubscribe_timeout_ms",
|
||||
"write_channel_capacity",
|
||||
"event_channel_capacity",
|
||||
"auto_reconnect",
|
||||
"roles"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"$ref": "#/$defs/non_empty_string"
|
||||
},
|
||||
"enabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"provider": {
|
||||
"$ref": "#/$defs/non_empty_string"
|
||||
},
|
||||
"cluster": {
|
||||
"$ref": "#/$defs/non_empty_string"
|
||||
},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"pattern": "^wss?://"
|
||||
},
|
||||
"connect_timeout_ms": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
},
|
||||
"request_timeout_ms": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
},
|
||||
"unsubscribe_timeout_ms": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
},
|
||||
"write_channel_capacity": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
},
|
||||
"event_channel_capacity": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
},
|
||||
"auto_reconnect": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"roles": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": {
|
||||
"$ref": "#/$defs/endpoint_role"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"endpoint_role": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"role",
|
||||
"enabled",
|
||||
"request_kinds",
|
||||
"priority",
|
||||
"requests_per_second",
|
||||
"burst_capacity",
|
||||
"max_concurrent_requests",
|
||||
"max_subscriptions",
|
||||
"pause_after_rate_limit_ms"
|
||||
],
|
||||
"properties": {
|
||||
"role": {
|
||||
"$ref": "#/$defs/non_empty_string"
|
||||
},
|
||||
"enabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"request_kinds": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": {
|
||||
"$ref": "#/$defs/non_empty_string"
|
||||
}
|
||||
},
|
||||
"priority": {
|
||||
"type": "integer"
|
||||
},
|
||||
"requests_per_second": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
},
|
||||
"burst_capacity": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
},
|
||||
"max_concurrent_requests": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
},
|
||||
"max_subscriptions": {
|
||||
"type": "integer"
|
||||
},
|
||||
"pause_after_rate_limit_ms": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"listeners": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"enabled",
|
||||
"default_commitment",
|
||||
"log_listeners",
|
||||
"program_listeners",
|
||||
"account_listeners"
|
||||
],
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"default_commitment": {
|
||||
"$ref": "#/$defs/non_empty_string"
|
||||
},
|
||||
"log_listeners": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/$defs/log_listener"
|
||||
}
|
||||
},
|
||||
"program_listeners": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/$defs/program_listener"
|
||||
}
|
||||
},
|
||||
"account_listeners": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/$defs/account_listener"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"log_listener": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"name",
|
||||
"enabled",
|
||||
"endpoint_role",
|
||||
"program_id",
|
||||
"purpose"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"$ref": "#/$defs/non_empty_string"
|
||||
},
|
||||
"enabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"endpoint_role": {
|
||||
"$ref": "#/$defs/non_empty_string"
|
||||
},
|
||||
"program_id": {
|
||||
"$ref": "#/$defs/non_empty_string"
|
||||
},
|
||||
"purpose": {
|
||||
"$ref": "#/$defs/non_empty_string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"program_listener": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"name",
|
||||
"enabled",
|
||||
"endpoint_role",
|
||||
"program_id",
|
||||
"purpose"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"$ref": "#/$defs/non_empty_string"
|
||||
},
|
||||
"enabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"endpoint_role": {
|
||||
"$ref": "#/$defs/non_empty_string"
|
||||
},
|
||||
"program_id": {
|
||||
"$ref": "#/$defs/non_empty_string"
|
||||
},
|
||||
"purpose": {
|
||||
"$ref": "#/$defs/non_empty_string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"account_listener": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"name",
|
||||
"enabled",
|
||||
"endpoint_role",
|
||||
"account_pubkey",
|
||||
"purpose"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"$ref": "#/$defs/non_empty_string"
|
||||
},
|
||||
"enabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"endpoint_role": {
|
||||
"$ref": "#/$defs/non_empty_string"
|
||||
},
|
||||
"account_pubkey": {
|
||||
"$ref": "#/$defs/non_empty_string"
|
||||
},
|
||||
"purpose": {
|
||||
"$ref": "#/$defs/non_empty_string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"wallet": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"wallet_dir",
|
||||
"cluster",
|
||||
"temporary_wallet_enabled",
|
||||
"temporary_wallet_alias",
|
||||
"temporary_wallet_persist",
|
||||
"localnet_send_enabled",
|
||||
"devnet_send_enabled",
|
||||
"testnet_send_enabled",
|
||||
"mainnet_send_enabled"
|
||||
],
|
||||
"properties": {
|
||||
"wallet_dir": {
|
||||
"$ref": "#/$defs/non_empty_string"
|
||||
},
|
||||
"cluster": {
|
||||
"$ref": "#/$defs/non_empty_string"
|
||||
},
|
||||
"temporary_wallet_enabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"temporary_wallet_alias": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"maxLength": 64,
|
||||
"pattern": "^[A-Za-z0-9][A-Za-z0-9_-]*$"
|
||||
},
|
||||
"temporary_wallet_persist": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"localnet_send_enabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"devnet_send_enabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"testnet_send_enabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"mainnet_send_enabled": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
"execution": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"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"
|
||||
],
|
||||
"properties": {
|
||||
"dry_run_default": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"require_simulation": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"require_operator_confirmation": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"localnet_max_spend_lamports": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"devnet_max_spend_lamports": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"testnet_max_spend_lamports": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"mainnet_max_spend_lamports": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"max_fee_lamports": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
},
|
||||
"max_compute_unit_price_micro_lamports": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"recent_blockhash_max_age_slots": {
|
||||
"type": "integer",
|
||||
"minimum": 1
|
||||
},
|
||||
"send_max_retries": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 4294967295
|
||||
},
|
||||
"confirmation_poll_interval_ms": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"maximum": 60000
|
||||
},
|
||||
"confirmation_max_attempts": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"maximum": 10000
|
||||
},
|
||||
"devnet_airdrop_max_lamports": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
"demo": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"live_demo_enabled",
|
||||
"trading_demo_enabled"
|
||||
],
|
||||
"properties": {
|
||||
"live_demo_enabled": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"trading_demo_enabled": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
25
olddocs/archivekbot2/docs/ACCOUNT_ONLY_CANDIDATES.md
Normal file
25
olddocs/archivekbot2/docs/ACCOUNT_ONLY_CANDIDATES.md
Normal file
@@ -0,0 +1,25 @@
|
||||
<!-- 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.
|
||||
210
olddocs/archivekbot2/docs/AGAVE_LOCAL_NODE.md
Normal file
210
olddocs/archivekbot2/docs/AGAVE_LOCAL_NODE.md
Normal file
@@ -0,0 +1,210 @@
|
||||
<!-- 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
|
||||
```
|
||||
|
||||
28
olddocs/archivekbot2/docs/APPLICATION_CRATES.md
Normal file
28
olddocs/archivekbot2/docs/APPLICATION_CRATES.md
Normal file
@@ -0,0 +1,28 @@
|
||||
<!-- 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`.
|
||||
108
olddocs/archivekbot2/docs/ARCHITECTURE.md
Normal file
108
olddocs/archivekbot2/docs/ARCHITECTURE.md
Normal file
@@ -0,0 +1,108 @@
|
||||
<!-- 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_rpc
|
||||
-> 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_rpc
|
||||
```
|
||||
|
||||
## Responsabilités
|
||||
|
||||
- `kb_rpc` 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_rpc` ou `kb_external_sources` avec l’hydratation canonique par `kb_rpc`.
|
||||
- `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_rpc` 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 l’indexation locale et décrit explicitement une frontière de fournisseurs externes plutôt qu’une 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_rpc` 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 d’acquisition.
|
||||
- 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 qu’orchestrer 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.
|
||||
145
olddocs/archivekbot2/docs/BACKFILL_HTTP.md
Normal file
145
olddocs/archivekbot2/docs/BACKFILL_HTTP.md
Normal file
@@ -0,0 +1,145 @@
|
||||
<!-- 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 d’un `program_id` ;
|
||||
- historique d’un mint de token ;
|
||||
- historique d’une 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 d’arrêt.
|
||||
|
||||
### Après une signature
|
||||
|
||||
Le moteur transmet directement la signature d’ancrage 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 l’ancre. Le moteur ne conserve que les `X` candidates les plus proches de l’ancre, en plus de l’ensemble 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 d’augmenter `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 l’opé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 l’appel `getTransaction`.
|
||||
|
||||
Chaque tentative d’hydratation 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 n’est jamais dupliqué dans la table d’observations.
|
||||
|
||||
## 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 d’annulation 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`, l’annulation ne se limite plus aux frontières entre appels : les futures RPC `getSignaturesForAddress` et `getTransaction` sont mises en concurrence avec un observateur d’arrêt, l’attente du pacer est annulable et une pause de retry, y compris après un 429, est interrompue par sondage borné. L’abandon de la future HTTP empêche une campagne arrêtée d’attendre un timeout réseau complet.
|
||||
|
||||
Le moteur maintient une file bornée par la concurrence effective et cesse d’admettre de nouveaux candidats dès que l’arrê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 d’exé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 d’arrê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 n’a terminé, le curseur reste la signature d’ancrage initiale. Cette règle interdit de sauter les candidats non traités lors d’une reprise.
|
||||
|
||||
Le calcul de cette frontière est couvert par les tests unitaires. Une campagne réelle de 500 candidats a déjà validé l’arrê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_rpc : 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 d’une 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 d’arrê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 d’arrêt avant le premier candidat terminé, une campagne `*_latest` reprend depuis la page la plus récente et ne fabrique aucun curseur.
|
||||
26
olddocs/archivekbot2/docs/BAGS_FM.md
Normal file
26
olddocs/archivekbot2/docs/BAGS_FM.md
Normal file
@@ -0,0 +1,26 @@
|
||||
<!-- 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.
|
||||
41
olddocs/archivekbot2/docs/CODE_REUSE.md
Normal file
41
olddocs/archivekbot2/docs/CODE_REUSE.md
Normal file
@@ -0,0 +1,41 @@
|
||||
<!-- 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_rpc` | Réutiliser les idées : retry, backoff, limites, traces, idempotence. Réécrire l'API selon les nouveaux modèles. |
|
||||
| Pool RPC HTTP | `kb_rpc` | 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_rpc` | Reprendre la gestion ping/pong, subscribe/unsubscribe, shutdown explicite et reconnexion contrôlée. |
|
||||
| Pool WebSocket | `kb_rpc` | 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_rpc` 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 l’ancien code. Les enums, types, IDs et encodeurs publiés dans les interfaces officielles Solana/SPL doivent être utilisés lorsqu’ils exposent un contrat compatible avec les règles du workspace. La matrice, les exceptions `bincode` et l’ordre `wincode`/Borsh/parser borné sont maintenus dans `docs/SOLANA_INTERFACE_DEPENDENCIES.md`.
|
||||
114
olddocs/archivekbot2/docs/CONFIGURATION.md
Normal file
114
olddocs/archivekbot2/docs/CONFIGURATION.md
Normal file
@@ -0,0 +1,114 @@
|
||||
<!-- 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 ;
|
||||
- l’intervalle et le nombre de polls de confirmation sont strictement bornés ;
|
||||
- le plafond d’airdrop 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.
|
||||
148
olddocs/archivekbot2/docs/CORE_EXTRACTION_CONTRACTS.md
Normal file
148
olddocs/archivekbot2/docs/CORE_EXTRACTION_CONTRACTS.md
Normal file
@@ -0,0 +1,148 @@
|
||||
<!-- file: docs/CORE_EXTRACTION_CONTRACTS.md -->
|
||||
<!-- version: 5 -->
|
||||
|
||||
# Contrats d’extraction 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 à l’origine dans une réponse RPC n’est jamais relu depuis les observations. La seule source fonctionnelle de l’extracteur 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 ;
|
||||
- l’identité 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 d’unicité après insertion de la transaction et d’une première account key, puis vérifie l’absence totale de graphe partiel, de changement raw et de succès ledger.
|
||||
|
||||
## Validation de l’entrée
|
||||
|
||||
L’extraction refuse explicitement :
|
||||
|
||||
- un `canonical_json` absent ;
|
||||
- un `canonical_json_hash` absent ;
|
||||
- une version différente de `CANONICAL_TRANSACTION_FORMAT_VERSION` ;
|
||||
- un JSON non désérialisable en `CanonicalTransaction` ;
|
||||
- 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 l’espace résolu.
|
||||
|
||||
L’identité 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
|
||||
|
||||
L’espace d’indices 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 n’est 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 l’ordre 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 d’inventer 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 d’un 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 l’erreur 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 d’intention, 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` n’effectue aucun décodage Solana Core/SPL, aucun décodage DEX, aucune matérialisation métier et aucune compaction du JSON canonique.
|
||||
@@ -0,0 +1,456 @@
|
||||
<!-- file: docs/CORE_EXTRACTION_SELECTION_AND_REPLAY.md -->
|
||||
<!-- version: 4 -->
|
||||
|
||||
# Sélection et replay de l’extraction 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 d’une 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 n’est effectué par cette étape. Aucun décodeur Solana Core, SPL, DEX ou autre protocole n’est exécuté. Aucune ligne métier n’est matérialisée.
|
||||
|
||||
## Cycle complet d’une 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 l’entré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 s’applique aussi au mode signatures explicites. L’ordre des lignes collées dans la zone de texte n’est donc pas l’ordre d’exécution garanti.
|
||||
|
||||
### Concurrence
|
||||
|
||||
`max_concurrent_extractions` borne le nombre d’extractions 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 l’appel au pipeline, l’interface :
|
||||
|
||||
- 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 n’est pas téléchargée automatiquement. Elle n’apparaî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` n’est 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 l’idempotence sur un échantillon connu ;
|
||||
- forcer la reconstruction de quelques signatures ;
|
||||
- retenter explicitement des transactions raw en échec ;
|
||||
- comparer deux versions de l’extracteur ;
|
||||
- préparer plus tard un corpus ciblé pour un décodeur.
|
||||
|
||||
### Point d’attention
|
||||
|
||||
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 d’une campagne pending suivante.
|
||||
|
||||
### Transition après échec
|
||||
|
||||
Après un échec d’extraction 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 l’extraction 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 qu’aucune nouvelle transaction raw `received` n’a été acquise.
|
||||
|
||||
## Mode plage de slots
|
||||
|
||||
### Filtre réel
|
||||
|
||||
Le mode sélectionne toutes les transactions raw dont le slot se trouve dans l’intervalle inclusif :
|
||||
|
||||
```text
|
||||
min_slot <= slot <= max_slot
|
||||
```
|
||||
|
||||
Aucun filtre de `processing_state` n’est 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 l’extracteur.
|
||||
|
||||
## 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 n’est pas sélectionnée par ce mode dans son état actuel.
|
||||
|
||||
### Usages principaux
|
||||
|
||||
- reconstruire les transactions d’un 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 d’un 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 d’extraction actuel peut rester strictement basé sur les instructions top-level, à condition que cette limite demeure visible dans l’interface.
|
||||
|
||||
## Interprétation des compteurs
|
||||
|
||||
| Compteur | Signification |
|
||||
|-----------------------|-------------------------------------------------------------|
|
||||
| `selected` | Candidats retournés par PostgreSQL après filtres et limite. |
|
||||
| `started` | Candidats admis dans la file d’exé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 d’arrê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 d’une 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 d’une erreur entre les insertions du graphe et le commit.
|
||||
|
||||
La méthode recommandée est un test d’intégration sur `solana_test`, et non une corruption volontaire de la base principale.
|
||||
|
||||
## Sélecteur de corpus dans l’application
|
||||
|
||||
La fenêtre read-only dédiée est :
|
||||
|
||||
```text
|
||||
demo_sql_replay_candidates
|
||||
```
|
||||
|
||||
Elle est accessible depuis le menu principal et depuis l’en-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 d’instructions 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 n’est 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 d’instructions outer ;
|
||||
- le nombre d’instructions inner ;
|
||||
- le nombre de logs reliés ;
|
||||
- le slot minimum et maximum.
|
||||
|
||||
La sélection d’un 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 d’occurrences 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 l’export. Un bouton de copie individuel évite les espaces parasites liés à une sélection manuelle.
|
||||
|
||||
La règle d’export est la suivante :
|
||||
|
||||
1. lorsqu’une 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 d’exé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 l’onglet 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. L’action renseigne le program ID exact, choisit la portée `any`, ouvre l’onglet 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 à l’audit et à la conservation d’un 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 qu’un 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 l’idempotence
|
||||
|
||||
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 d’intégrité n’ont 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 l’erreur, 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.
|
||||
63
olddocs/archivekbot2/docs/CORE_PROGRAM_IDS.md
Normal file
63
olddocs/archivekbot2/docs/CORE_PROGRAM_IDS.md
Normal file
@@ -0,0 +1,63 @@
|
||||
<!-- file: docs/CORE_PROGRAM_IDS.md -->
|
||||
<!-- version: 5 -->
|
||||
|
||||
# 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_token_2022_v2022` | `TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb` | `token_2022` | `program` | `kb_decoder_spl_token_2022` | `core_handled` |
|
||||
| `core_spl_token_2022_elgamal_registry_v1` | `regVYJW7tcT8zipN5YiBvHsvR5jXW1uLFxaHSbugABg` | `spl_token_2022_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` |
|
||||
73
olddocs/archivekbot2/docs/CORE_STORE.md
Normal file
73
olddocs/archivekbot2/docs/CORE_STORE.md
Normal file
@@ -0,0 +1,73 @@
|
||||
<!-- 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 d’invocation 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 d’un 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. L’enregistrement terminal d’un échec utilise une transaction dédiée et marque la ligne raw `failed` avec un diagnostic rejouable.
|
||||
|
||||
## Clés d’idempotence
|
||||
|
||||
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 l’ajouter à 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 n’a 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 d’insertion unitaire restent disponibles, mais le worker `0.3.4` utilise exclusivement l’écriture atomique du bundle.
|
||||
155
olddocs/archivekbot2/docs/DATABASE.md
Normal file
155
olddocs/archivekbot2/docs/DATABASE.md
Normal file
@@ -0,0 +1,155 @@
|
||||
<!-- 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 d’acquisition 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_rpc` convertissent JSON-RPC, Helius WebSocket ou Yellowstone Protobuf vers le même contrat `kb_model`. Le payload canonique reste la source rejouable pour l’extraction `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 s’appliquent à 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 l’idempotence par processor. Pour l’extraction 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.
|
||||
179
olddocs/archivekbot2/docs/DECODER_MATERIALIZATION_CONTRACTS.md
Normal file
179
olddocs/archivekbot2/docs/DECODER_MATERIALIZATION_CONTRACTS.md
Normal file
@@ -0,0 +1,179 @@
|
||||
<!-- file: docs/DECODER_MATERIALIZATION_CONTRACTS.md -->
|
||||
<!-- version: 17 -->
|
||||
|
||||
# Contrats communs de décodage et de matérialisation
|
||||
|
||||
## Objet
|
||||
|
||||
La version `0.4.0` introduit l’infrastructure 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é
|
||||
|
||||
`CoreInstructionReplayInput` reste l’unique contrat d’entrée commun. Son contrat passe à la version `2` dans `0.4.1-pre.014`. Il contient la signature, le slot, le statut et l’erreur on-chain, le chemin stable de l’instruction, 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`. L’instruction 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é d’entré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
|
||||
|
||||
`InstructionDecoder` 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 d’entrée et identité stable. Il ne dépend ni du nom de la crate ni de l’ordre d’enregistrement implicite.
|
||||
|
||||
Avant la lecture du store, le pipeline calcule le périmètre effectif des programmes à partir de l’union des `program_id` déclarés par les décodeurs activés. Lorsque l’opé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 d’un 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 l’input ; il ne modifie pas globalement le lifecycle de l’instruction 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 lorsqu’un 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 l’erreur, 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. `EventMaterializer` applique une politique explicite par famille. Les familles `trade`, `liquidity` et `lifecycle` sont refusées avant l’appel au matérialiseur lorsque la source est échouée ou non commitée. Une seconde barrière valide ensuite les familles de sortie et n’autorise, dans ce contexte, que les matérialisations d’audit 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 n’est 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 l’instruction 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é d’entrée. Le force replay contourne uniquement le skip version/hash ; il ne supprime jamais les sorties d’un autre processor, d’une autre version ou d’une autre clé. Les versions antérieures restent disponibles pour l’audit.
|
||||
|
||||
Lorsqu’un 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 l’opé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 jusqu’aux 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, l’instruction path, le program ID et la clé d’input ;
|
||||
- le processor et sa version ;
|
||||
- le hash déterministe pertinent ;
|
||||
- la décision de dispatch, y compris lorsque `recognize` n’est pas appelé à cause d’un 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 d’instruction 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 l’initialisation/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 l’initialisation d’un 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 d’autorité 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 n’est jamais proposée au matérialiseur.
|
||||
|
||||
Le retrait d’un nonce account conserve une sémantique conditionnelle. Le runtime détruit le compte lorsque la totalité du solde est retirée ; l’instruction seule ne suffit pas à reconstruire de manière certaine l’état final transactionnel du compte. La projection décrit donc l’opération commitée, conserve le montant demandé et indique explicitement que l’état final n’est pas capturé. Les deltas SOL ne sont pas dupliqués.
|
||||
|
||||
La création d’un 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 l’autorité, puis décrit le reset vers le System Program. L’ancien ZK Token Proof Program n’est jamais matérialisé : son runtime actuel est un stub sans effet et sa sémantique historique n’est pas attribuable à une transaction sans preuve de version.
|
||||
|
||||
Le hash d’entrée matérialiseur reste dérivé de l’observation 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é d’input 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 d’autorité 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 d’un décodeur n’implique pas une matérialisation systématique. Une projection n’est ajoutée que lorsqu’elle possède une identité stable, un état cible explicite, une politique d’idempotence 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 d’autorité 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 n’ont 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`.
|
||||
49
olddocs/archivekbot2/docs/DECODER_SURFACE_AUDIT.md
Normal file
49
olddocs/archivekbot2/docs/DECODER_SURFACE_AUDIT.md
Normal file
@@ -0,0 +1,49 @@
|
||||
<!-- 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.
|
||||
58
olddocs/archivekbot2/docs/DELTA_WORKFLOW.md
Normal file
58
olddocs/archivekbot2/docs/DELTA_WORKFLOW.md
Normal file
@@ -0,0 +1,58 @@
|
||||
<!-- file: docs/DELTA_WORKFLOW.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Workflow delta
|
||||
|
||||
Après le squelette initial, les livraisons doivent être faites sous forme de zip delta.
|
||||
|
||||
## Nommage des zips
|
||||
|
||||
Un delta qui touche la racine du workspace ou plusieurs modules doit utiliser :
|
||||
|
||||
```text
|
||||
khadhroony-bot2_vX.Y.Z-pre.abc.zip
|
||||
```
|
||||
|
||||
Un delta qui ne touche qu'un seul module Rust doit utiliser :
|
||||
|
||||
```text
|
||||
kb_modulename_vX.Y.Z-pre.abc.zip
|
||||
```
|
||||
|
||||
Exemples :
|
||||
|
||||
```text
|
||||
khadhroony-bot2_v0.1.0-pre.001.zip
|
||||
kb_logging_v0.1.0-pre.002.zip
|
||||
```
|
||||
|
||||
## Fichier `delta.md`
|
||||
|
||||
Chaque zip delta doit contenir un fichier `delta.md` non versionné à la racine du zip.
|
||||
|
||||
`delta.md` doit indiquer :
|
||||
|
||||
- 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 de compatibilité ou d'application du delta.
|
||||
|
||||
## Contenu d'un delta
|
||||
|
||||
Un delta contient uniquement :
|
||||
|
||||
- les fichiers ajoutés ;
|
||||
- les fichiers modifiés ;
|
||||
- `delta.md`.
|
||||
|
||||
Il ne doit pas contenir de fichiers inchangés.
|
||||
|
||||
## Règles
|
||||
|
||||
- Ne pas renvoyer un zip complet sauf demande explicite.
|
||||
- Ne pas modifier `CHANGELOG.md` avant validation d'une version.
|
||||
- Placer les évolutions prévues dans `ROADMAP.md`.
|
||||
- Garder `README.md` descriptif.
|
||||
- Documenter les suppressions dans `delta.md`, car un zip ne supprime pas les anciens fichiers à l'extraction.
|
||||
91
olddocs/archivekbot2/docs/DEVELOPMENT_ORDER.md
Normal file
91
olddocs/archivekbot2/docs/DEVELOPMENT_ORDER.md
Normal file
@@ -0,0 +1,91 @@
|
||||
<!-- 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 l’ordre : 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 d’acquisition.
|
||||
- Intégrer Helius et Yellowstone dans `kb_rpc`, 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`
|
||||
|
||||
L’ordre 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, l’inté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.
|
||||
|
||||
L’ancien 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`.
|
||||
119
olddocs/archivekbot2/docs/DEVNET_EXECUTION.md
Normal file
119
olddocs/archivekbot2/docs/DEVNET_EXECUTION.md
Normal file
@@ -0,0 +1,119 @@
|
||||
<!-- file: docs/DEVNET_EXECUTION.md -->
|
||||
<!-- version: 3 -->
|
||||
|
||||
# Validation d’exécution Devnet
|
||||
|
||||
Ce document décrit le premier parcours réseau réel de la couche d’exécution native et sa fenêtre Tauri Devnet. Le test backend reste opt-in et aucune activation Mainnet n’est 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 d’exé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 n’est 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 d’airdrop 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 lorsqu’il est inférieur au minimum retourné. Lorsqu’une simulation échoue malgré ces contrôles, l’erreur remontée conserve l’erreur 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.
|
||||
|
||||
L’airdrop peut être absent lorsque le wallet possède déjà un solde suffisant. Le destinataire reste éphémère et sa clé privée n’est 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 d’airdrop nulle.
|
||||
|
||||
## Limites
|
||||
|
||||
- le faucet Devnet peut appliquer des limites temporaires ;
|
||||
- `getTransaction` peut devenir disponible après la confirmation de statut, d’où 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 n’est 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 n’a été demandé et le parcours a confirmé la chaîne complète jusqu’au 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 l’autorisation à toutes les opérations administratives stateful. Elle prouve le parcours d’orchestration commun ; ALT, Config, Feature, Slashing, ZK, Stake, Vote et loaders restent soumis à leurs contrôles spécifiques avant toute future activation mutable.
|
||||
|
||||
387
olddocs/archivekbot2/docs/EXECUTION_MODEL.md
Normal file
387
olddocs/archivekbot2/docs/EXECUTION_MODEL.md
Normal file
@@ -0,0 +1,387 @@
|
||||
<!-- 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_execution_solana` 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_rpc` 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_rpc` 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 l’alias historique `mainnet-beta`. Un hash inconnu reste explicite et n’est pas automatiquement assimilé à Devnet ou Mainnet. Le blockhash et sa dernière block height valide sont conservés séparément. L’estimation 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_rpc` 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 `ExecutionSimulationResult`. 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_execution_solana`, frontière commune entre les exécuteurs et les adaptateurs RPC. La crate convertit les `PlannedInstruction` 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 d’un autre message ou d’une autre valeur nonce, réévalue `kb_execution_safety`, exige la décision `Allow`, puis résout tous les signataires via l’interface Solana `Signer`. Les signataires manquants, supplémentaires ou dupliqués sont refusés. La transaction signée reste en mémoire/backend et n’est 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` n’est ajouté.
|
||||
|
||||
### Chemin durable nonce réel — `pre.013`
|
||||
|
||||
Le lifecycle d’un compte nonce et la consommation d’un 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 l’autorité nonce aux signataires requis du plan métier. `kb_execution_solana` refuse les états legacy ou non initialisés, conserve le plan source immuable, expose un plan effectif avec l’avance injectée et exige que le SDK reconnaisse la transaction comme durable nonce. La lecture RPC, l’assemblage, 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 l’interface Address Lookup Table : création, extension, gel, désactivation et fermeture. Le builder stateless garantit le program ID, le payload, l’ordre 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 l’autorité et un slot récent. L’extension conserve l’ordre des adresses, exige une liste non vide et borne l’input à 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 n’est autorisée qu’après désactivation et expiration du cooldown lié aux slots. `requested_spend_lamports` reste nul dans le plan ALT parce qu’aucun montant de rent n’est encodé directement dans l’instruction ; l’orchestrateur doit calculer le top-up à partir du compte réel et du minimum rent-exempt, le comparer au plafond de dépense, puis confirmer l’instruction 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 l’instruction correspondante et appliquer lui-même son contrat d’autorisation.
|
||||
|
||||
```text
|
||||
message + signature + clé/adresse
|
||||
-> builder inline ou table d’offsets officielle
|
||||
-> instruction précompile sans comptes
|
||||
-> positionnement transactionnel exact
|
||||
-> programme consommateur qui inspecte le sysvar d’instructions
|
||||
-> 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 d’instruction `u8` sans sentinelle ; la forme inline et les références locales du builder exigent donc que l’instruction secp256k1 soit à l’index 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 d’entré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 l’adresse Ethereum déjà dérivée ; il ne manipule aucune clé privée et n’active aucun helper `bincode`. Le runtime secp256k1 ne garantit pas la canonicalité low-S : lorsqu’elle 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 l’orchestrateur
|
||||
-> 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 l’interface. Feature reproduit les séquences officielles d’activation 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 l’orchestrateur stateful.
|
||||
|
||||
ZK ElGamal accepte une preuve inline ou une preuve dans un compte, avec création optionnelle d’un contexte déjà préalloué. La fermeture exige l’autorité comme signataire. Le builder vérifie discriminant, taille et comptes, mais ne crée pas le contexte et ne recalcule pas la preuve cryptographique. L’ancien 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 l’ordre 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 l’enum 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, l’orchestrateur 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 d’activation/désactivation, la compatibilité merge/split/move, la version Vote, les collecteurs et l’admissibilité runtime de la tour. `Redelegate` reste historique `decode-only`, car l’interface 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 qu’aucun schéma `wincode` n’est exposé.
|
||||
|
||||
Les plans de création conservent l’ordre atomique System puis Loader. Les écritures sont bornées, les offsets contrôlés contre les dépassements, les comptes/signataires reproduisent l’interface 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, l’orchestrateur 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 d’extension. 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 n’expose pas d’instruction 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 l’admissibilité 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 d’un 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 n’envoie 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 s’applique à 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 qu’avec 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 d’exé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 d’idempotence. Cette restriction de signataire appartient à l’orchestrateur actuel, pas à l’exé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 d’envoi 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 l’audit.
|
||||
|
||||
`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 l’inventaire 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 qu’une 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 l’intent 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, l’absence 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 n’envoie rien. L’orchestration de soumission,
|
||||
confirmation et replay reste une tranche séparée afin qu’un 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 l’instruction 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 d’exécution ATA reste indépendante du cluster et du wallet. L’orchestrateur Devnet
|
||||
fourni ne peut signer qu’avec 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…` lorsqu’il était
|
||||
fourni à la place d’un 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é l’ATA `6WfC…C9Y`, compte de 170 octets
|
||||
initialisé pour `DwuA…g8B2` avec l’extension `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 l’instruction 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é l’owner 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 l’expiration
|
||||
-> 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 d’airdrop Devnet appartient à la configuration et sera appliqué par l’orchestrateur 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 d’un 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, n’envoie pas et ne fabrique pas de signature vide. Le parcours soumis exige simultanément l’autorisation `submit`, la confirmation opérateur lorsque le profil l’impose, l’activation 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. L’airdrop 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 l’adresse existe déjà. Lorsqu’elle est absente, `getMinimumBalanceForRentExemption(0)` fournit le minimum nécessaire à la création implicite d’un compte System sans données ; un transfert inférieur est refusé avant simulation. Les échecs de simulation conservent désormais l’erreur 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 à l’insertion 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 l’envoi a été confirmé.
|
||||
|
||||
Une erreur avant signature reste un `Err`. Dès qu’une signature locale existe, l’orchestrateur conserve cette signature et transforme les erreurs d’envoi, de confirmation ou de replay en diagnostics dans le résumé. Cette règle évite qu’un appelant perde la référence d’une transaction potentiellement diffusée.
|
||||
|
||||
L’orchestrateur 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 l’interface.
|
||||
|
||||
## É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 d’activation, pas une instruction manquante.
|
||||
130
olddocs/archivekbot2/docs/EXECUTOR_SURFACE_MATRIX.md
Normal file
130
olddocs/archivekbot2/docs/EXECUTOR_SURFACE_MATRIX.md
Normal file
@@ -0,0 +1,130 @@
|
||||
<!-- 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 l’exé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 l’ancien 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 d’activation 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 d’instructions. Elle ne confond pas réservation d’une crate, disponibilité d’un builder, autorisation d’envoi et exposition dans une interface.
|
||||
|
||||
## Socle d’exé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_execution_solana` | Compilation Solana, blockhash/nonce, preuve de simulation et signature. |
|
||||
| `kb_rpc` | 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.
|
||||
|
||||
L’audit 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 l’implé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é à l’exé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 l’API 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 lorsqu’elle 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 l’exé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 d’exposition 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.
|
||||
78
olddocs/archivekbot2/docs/FOUNDATION_CLOSURE.md
Normal file
78
olddocs/archivekbot2/docs/FOUNDATION_CLOSURE.md
Normal file
@@ -0,0 +1,78 @@
|
||||
<!-- file: docs/FOUNDATION_CLOSURE.md -->
|
||||
<!-- version: 2 -->
|
||||
|
||||
# Clôture de la fondation `0.3.x`
|
||||
|
||||
## Décision de version
|
||||
|
||||
Le jalon `0.3.5` n’est plus conservé comme version autonome. Ses outils d’inté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 d’unicité après le début de la persistance. Il vérifie :
|
||||
|
||||
- absence de transaction core partielle ;
|
||||
- absence d’account 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 l’abandon coopératif d’une 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 l’indépendance de l’extracteur 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 d’un backfill `before` depuis `resume_before_signature` reste recommandé lors d’une prochaine campagne longue. La logique de frontière contiguë, les compteurs d’arrêt et une campagne réelle interrompue sont déjà validés.
|
||||
355
olddocs/archivekbot2/docs/HISTORICAL_DATA_ACQUISITION_PLAN.md
Normal file
355
olddocs/archivekbot2/docs/HISTORICAL_DATA_ACQUISITION_PLAN.md
Normal file
@@ -0,0 +1,355 @@
|
||||
<!-- 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_rpc`, 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_rpc` 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_rpc`, mais sa politique de campagne, son coût, sa provenance et ses fallbacks restent hors de `kb_rpc`.
|
||||
- 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_rpc
|
||||
|
||||
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_rpc` 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_rpc`, `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.
|
||||
107
olddocs/archivekbot2/docs/IDL_SURFACE_CLASSIFICATION.md
Normal file
107
olddocs/archivekbot2/docs/IDL_SURFACE_CLASSIFICATION.md
Normal file
@@ -0,0 +1,107 @@
|
||||
<!-- 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` d’une 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 d’adaptation 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` |
|
||||
112
olddocs/archivekbot2/docs/INSTRUCTION_REPLAY_CONTRACTS.md
Normal file
112
olddocs/archivekbot2/docs/INSTRUCTION_REPLAY_CONTRACTS.md
Normal file
@@ -0,0 +1,112 @@
|
||||
<!-- 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.
|
||||
|
||||
`CoreInstructionReplayInput` 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 `CoreInstructionReplayInput`. 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`.
|
||||
104
olddocs/archivekbot2/docs/LIVE_SOURCE_STRATEGY.md
Normal file
104
olddocs/archivekbot2/docs/LIVE_SOURCE_STRATEGY.md
Normal file
@@ -0,0 +1,104 @@
|
||||
<!-- 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 l’axe 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_rpc`, sans créer de crate séparée, puis convertie vers le modèle canonique commun.
|
||||
|
||||
### Yellowstone gRPC
|
||||
|
||||
Yellowstone fournit l’équivalent fonctionnel d’un flux de transactions complètes filtrées. Les endpoints Triton, Chainstack, Shyft ou compatibles doivent être supportés par configuration dans `kb_rpc`.
|
||||
|
||||
### 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 qu’après hydratation de la transaction ou enregistrement d’une 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 d’acquisition.
|
||||
|
||||
## 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`.
|
||||
|
||||
106
olddocs/archivekbot2/docs/LOGGING.md
Normal file
106
olddocs/archivekbot2/docs/LOGGING.md
Normal file
@@ -0,0 +1,106 @@
|
||||
<!-- file: docs/LOGGING.md -->
|
||||
<!-- version: 8 -->
|
||||
|
||||
# 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 d’une crate sans dépendre de son découpage interne en modules.
|
||||
|
||||
## Arborescence d’un 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 exactement le nom de la crate et provient de `src/constants.rs` :
|
||||
|
||||
```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_materializer_admin
|
||||
kb_materializer_compliance_audit
|
||||
kb_materializer_lifecycle
|
||||
kb_materializer_staking
|
||||
kb_pipeline
|
||||
kb_rpc
|
||||
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 l’agrégation. Le RPC journalise le transport et l’endpoint sélectionné sans exposer l’URL 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 d’erreurs
|
||||
|
||||
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 d’un même défaut.
|
||||
|
||||
Une transaction on-chain échouée mais correctement décodée n’est 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 d’erreurs.
|
||||
|
||||
## 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 d’un retry RPC, d’un parsing binaire ou d’un commit SQL. Il journalise l’invocation, 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`.
|
||||
68
olddocs/archivekbot2/docs/MATERIALIZATIONS.md
Normal file
68
olddocs/archivekbot2/docs/MATERIALIZATIONS.md
Normal file
@@ -0,0 +1,68 @@
|
||||
<!-- file: docs/MATERIALIZATIONS.md -->
|
||||
<!-- version: 6 -->
|
||||
|
||||
# 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 actives dans `0.4.1`
|
||||
|
||||
`kb_materializer_lifecycle` 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_materializer_admin` produit des sorties `Admin` pour les assignations System, les écritures Config opaques et les changements d’autorité Loader. `kb_materializer_compliance_audit` produit des sorties `ComplianceAudit` pour les écritures/copies de bytecode Loader. `kb_materializer_staking` 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.
|
||||
|
||||
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é.
|
||||
|
||||
## Matérialisations spécialisées à prévoir
|
||||
|
||||
- `nft` : NFT classiques, programmables et compressés.
|
||||
- `metadata` : metadata Metaplex, creators, collection, update authority, URI et symbol.
|
||||
- `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.
|
||||
1612
olddocs/archivekbot2/docs/METAPLEX_TOKEN_METADATA_MATRIX.json
Normal file
1612
olddocs/archivekbot2/docs/METAPLEX_TOKEN_METADATA_MATRIX.json
Normal file
File diff suppressed because it is too large
Load Diff
113
olddocs/archivekbot2/docs/NATIVE_SOLANA_CLOSURE_AUDIT.md
Normal file
113
olddocs/archivekbot2/docs/NATIVE_SOLANA_CLOSURE_AUDIT.md
Normal file
@@ -0,0 +1,113 @@
|
||||
<!-- 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.
|
||||
|
||||
L’absence de transaction mainnet n’autorise ni à supprimer une surface officielle, ni à prétendre qu’elle 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 n’a é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 n’utilise 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 d’erreurs opérationnelles dans les journaux fournis.
|
||||
|
||||
## Backfills
|
||||
|
||||
Aucun backfill supplémentaire n’est requis pour clôturer `0.4.1`.
|
||||
|
||||
Le mode `program_latest` ajouté dans `pre.019` reste disponible pour de futures recherches sans signature d’ancrage. 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 n’est 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 l’initialisation 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 l’infrastructure d’exécution et `kb_executor_solana_core`.
|
||||
155
olddocs/archivekbot2/docs/NATIVE_SOLANA_DECODER_MATRIX.json
Normal file
155
olddocs/archivekbot2/docs/NATIVE_SOLANA_DECODER_MATRIX.json
Normal file
@@ -0,0 +1,155 @@
|
||||
{
|
||||
"file": "docs/NATIVE_SOLANA_DECODER_MATRIX.json",
|
||||
"version": 1,
|
||||
"release": "0.4.2-pre.023",
|
||||
"surface_count": 18,
|
||||
"coverage_entry_count": 121,
|
||||
"registry_contract": "Exact equality with kb_program_ids::native_program_ids and SolanaCoreDecoder::surfaces",
|
||||
"completeness_contract": "Each surface has exact declared coverage count plus a dedicated official-enum or audited-wire completeness test",
|
||||
"surfaces": [
|
||||
{
|
||||
"surface_code": "solana_native_address_lookup_table",
|
||||
"program_id": "AddressLookupTab1e1111111111111111111111111",
|
||||
"runtime_status": "current",
|
||||
"expected_coverage_entries": 5,
|
||||
"source_contract": "solana-address-lookup-table-interface@3.1.x official instruction enum",
|
||||
"completeness_test": "address_lookup_table::tests::coverage_uses_official_encoder_discriminants"
|
||||
},
|
||||
{
|
||||
"surface_code": "solana_native_bpf_loader_deprecated",
|
||||
"program_id": "BPFLoader1111111111111111111111111111111111",
|
||||
"runtime_status": "historical",
|
||||
"expected_coverage_entries": 2,
|
||||
"source_contract": "solana-loader-v2-interface@3.0.0 immutable write/finalize layout",
|
||||
"completeness_test": "loaders::tests::coverage_declares_every_loader_entry"
|
||||
},
|
||||
{
|
||||
"surface_code": "solana_native_bpf_loader",
|
||||
"program_id": "BPFLoader2111111111111111111111111111111111",
|
||||
"runtime_status": "historical",
|
||||
"expected_coverage_entries": 2,
|
||||
"source_contract": "solana-loader-v2-interface@3.0.0 immutable write/finalize layout",
|
||||
"completeness_test": "loaders::tests::coverage_declares_every_loader_entry"
|
||||
},
|
||||
{
|
||||
"surface_code": "solana_native_bpf_loader_upgradeable",
|
||||
"program_id": "BPFLoaderUpgradeab1e11111111111111111111111",
|
||||
"runtime_status": "current_with_historical_variants",
|
||||
"expected_coverage_entries": 8,
|
||||
"source_contract": "solana-loader-v3-interface@8.0.1 with wincode exact wire layout",
|
||||
"completeness_test": "loaders::tests::coverage_declares_every_loader_entry"
|
||||
},
|
||||
{
|
||||
"surface_code": "solana_native_compute_budget",
|
||||
"program_id": "ComputeBudget111111111111111111111111111111",
|
||||
"runtime_status": "current_with_historical_variants",
|
||||
"expected_coverage_entries": 6,
|
||||
"source_contract": "solana-compute-budget-interface@3.0.0 plus historical RequestUnitsDeprecated",
|
||||
"completeness_test": "compute_budget::tests::coverage_declares_current_and_historical_entries"
|
||||
},
|
||||
{
|
||||
"surface_code": "solana_native_config",
|
||||
"program_id": "Config1111111111111111111111111111111111111",
|
||||
"runtime_status": "current",
|
||||
"expected_coverage_entries": 1,
|
||||
"source_contract": "solana-config-interface@2.0.0 generic bounded store contract",
|
||||
"completeness_test": "config::tests::coverage_declares_one_generic_store_surface"
|
||||
},
|
||||
{
|
||||
"surface_code": "solana_native_ed25519",
|
||||
"program_id": "Ed25519SigVerify111111111111111111111111111",
|
||||
"runtime_status": "current",
|
||||
"expected_coverage_entries": 1,
|
||||
"source_contract": "Agave Ed25519 precompile exact offset-table layout",
|
||||
"completeness_test": "precompiles::tests::coverage_declares_exactly_three_signature_precompile_surfaces"
|
||||
},
|
||||
{
|
||||
"surface_code": "solana_native_feature",
|
||||
"program_id": "Feature111111111111111111111111111111111111",
|
||||
"runtime_status": "current",
|
||||
"expected_coverage_entries": 1,
|
||||
"source_contract": "solana-feature-gate-interface revoke-pending-activation instruction contract",
|
||||
"completeness_test": "feature::tests::coverage_declares_the_single_official_instruction"
|
||||
},
|
||||
{
|
||||
"surface_code": "solana_native_loader_v4",
|
||||
"program_id": "LoaderV411111111111111111111111111111111111",
|
||||
"runtime_status": "current",
|
||||
"expected_coverage_entries": 7,
|
||||
"source_contract": "solana-loader-v4-interface@3.1.0 official instruction enum",
|
||||
"completeness_test": "loaders::tests::coverage_declares_every_loader_entry"
|
||||
},
|
||||
{
|
||||
"surface_code": "solana_native_loader",
|
||||
"program_id": "NativeLoader1111111111111111111111111111111",
|
||||
"runtime_status": "runtime_dispatch",
|
||||
"expected_coverage_entries": 1,
|
||||
"source_contract": "Agave native-loader runtime direct-invocation behavior",
|
||||
"completeness_test": "loaders::tests::coverage_declares_every_loader_entry"
|
||||
},
|
||||
{
|
||||
"surface_code": "solana_native_secp256k1",
|
||||
"program_id": "KeccakSecp256k11111111111111111111111111111",
|
||||
"runtime_status": "current",
|
||||
"expected_coverage_entries": 1,
|
||||
"source_contract": "Agave secp256k1 precompile exact offset-table layout",
|
||||
"completeness_test": "precompiles::tests::coverage_declares_exactly_three_signature_precompile_surfaces"
|
||||
},
|
||||
{
|
||||
"surface_code": "solana_native_secp256r1",
|
||||
"program_id": "Secp256r1SigVerify1111111111111111111111111",
|
||||
"runtime_status": "current",
|
||||
"expected_coverage_entries": 1,
|
||||
"source_contract": "Agave secp256r1 precompile exact offset-table layout",
|
||||
"completeness_test": "precompiles::tests::coverage_declares_exactly_three_signature_precompile_surfaces"
|
||||
},
|
||||
{
|
||||
"surface_code": "solana_native_slashing",
|
||||
"program_id": "S1ashing11111111111111111111111111111111111",
|
||||
"runtime_status": "current",
|
||||
"expected_coverage_entries": 2,
|
||||
"source_contract": "SIMD-0204 and Agave Slashing builtin instruction contract",
|
||||
"completeness_test": "slashing::tests::coverage_declares_exactly_two_official_instructions"
|
||||
},
|
||||
{
|
||||
"surface_code": "solana_native_stake",
|
||||
"program_id": "Stake11111111111111111111111111111111111111",
|
||||
"runtime_status": "current",
|
||||
"expected_coverage_entries": 18,
|
||||
"source_contract": "solana-stake-interface@4.3.x official StakeInstruction variants",
|
||||
"completeness_test": "stake::tests::coverage_declares_every_official_stake_instruction"
|
||||
},
|
||||
{
|
||||
"surface_code": "solana_native_system",
|
||||
"program_id": "11111111111111111111111111111111",
|
||||
"runtime_status": "current",
|
||||
"expected_coverage_entries": 14,
|
||||
"source_contract": "solana-system-interface@3.2.x official SystemInstruction variants",
|
||||
"completeness_test": "system::tests::coverage_declares_all_current_system_variants"
|
||||
},
|
||||
{
|
||||
"surface_code": "solana_native_vote",
|
||||
"program_id": "Vote111111111111111111111111111111111111111",
|
||||
"runtime_status": "current",
|
||||
"expected_coverage_entries": 20,
|
||||
"source_contract": "solana-vote-interface@6.0.x official VoteInstruction variants",
|
||||
"completeness_test": "vote::tests::coverage_declares_every_official_vote_instruction"
|
||||
},
|
||||
{
|
||||
"surface_code": "solana_native_zk_elgamal_proof",
|
||||
"program_id": "ZkE1Gama1Proof11111111111111111111111111111",
|
||||
"runtime_status": "current",
|
||||
"expected_coverage_entries": 13,
|
||||
"source_contract": "solana-zk-elgamal-proof-interface official ProofInstruction variants",
|
||||
"completeness_test": "zk_elgamal::tests::coverage_declares_all_thirteen_official_instructions"
|
||||
},
|
||||
{
|
||||
"surface_code": "solana_native_zk_token_proof",
|
||||
"program_id": "ZkTokenProof1111111111111111111111111111111",
|
||||
"runtime_status": "historical_with_current_noop",
|
||||
"expected_coverage_entries": 18,
|
||||
"source_contract": "audited historical ZK Token Proof wire table plus current runtime no-op behavior",
|
||||
"completeness_test": "zk_token_proof::tests::coverage_declares_seventeen_historical_entries_and_current_noop_fallback"
|
||||
}
|
||||
]
|
||||
}
|
||||
1279
olddocs/archivekbot2/docs/NATIVE_SOLANA_EXECUTION_MATRIX.json
Normal file
1279
olddocs/archivekbot2/docs/NATIVE_SOLANA_EXECUTION_MATRIX.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,85 @@
|
||||
<!-- file: docs/NATIVE_SOLANA_MATERIALIZATION_AUDIT.md -->
|
||||
<!-- version: 5 -->
|
||||
|
||||
# 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 d’un 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 |
|
||||
|------------------------------------|----------------------|---------------------------------------------------------------------------------------------------------------------|
|
||||
| `kb_materializer_lifecycle` | Address Lookup Table | lifecycle create/freeze/extend/deactivate/close |
|
||||
| `kb_materializer_lifecycle` | Feature | révocation de feature gate |
|
||||
| `kb_materializer_lifecycle` | Loaders | déploiement, finalisation et transitions lifecycle stables |
|
||||
| `kb_materializer_lifecycle` | System | durable nonce, create account et allocate |
|
||||
| `kb_materializer_lifecycle` | ZK ElGamal | création ou fermeture d’un compte de contexte |
|
||||
| `kb_materializer_lifecycle` | Slashing | initialisation ou fermeture d’un rapport de violation |
|
||||
| `kb_materializer_admin` | System | assign et assign with seed |
|
||||
| `kb_materializer_admin` | Config | écriture opaque bornée avec clés, taille, SHA-256 et préfixe |
|
||||
| `kb_materializer_admin` | Loaders | changements d’autorité |
|
||||
| `kb_materializer_compliance_audit` | Loaders | écritures/copies de bytecode bornées par offsets, tailles, SHA-256 et préfixes |
|
||||
| `kb_materializer_compliance_audit` | Compute Budget | profil transactionnel agrégé, last-write-wins, une seule sortie par transaction |
|
||||
| `kb_materializer_staking` | Stake | compte, délégation, désactivation, split, merge, withdraw, move stake/lamports, autorités et lockup instructionnels |
|
||||
| `kb_materializer_staking` | 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 d’audit 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 d’un compte Stake ou Vote ;
|
||||
- activation/désactivation Stake par epoch ;
|
||||
- crédits Vote cumulés ;
|
||||
- rewards recalculées par epoch ;
|
||||
- état final d’un compte System après lamport drain conditionnel ;
|
||||
- bytecode final complet d’un 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 n’est identifiée comme manquante dans le périmètre `0.4.1`.
|
||||
|
||||
La suite `0.4.2` peut se concentrer sur l’exécution : plans, simulation, signature, envoi et validation post-exécution, sans rouvrir le jalon de décodage/matérialisation natif.
|
||||
233
olddocs/archivekbot2/docs/NATIVE_SOLANA_PROGRAMS.md
Normal file
233
olddocs/archivekbot2/docs/NATIVE_SOLANA_PROGRAMS.md
Normal file
@@ -0,0 +1,233 @@
|
||||
<!-- 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 l’identité `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 qu’avec 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 d’interface 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 n’utilise 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 n’est 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 d’extension incomplète et les octets suffixes. La création conserve `expectedSigner = null` pour l’autorité, car l’encodeur officiel actuel ne la marque plus signer tandis que les runtimes historiques antérieurs à v1.12 l’exigeaient.
|
||||
|
||||
La projection `solana_native_lifecycle` produit une sortie `address_lookup_table:<operation>:0` uniquement si l’observation 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 d’autorité 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 à l’offset `u64` de l’instruction. Le replay transactionnel ne possède pas le contenu historique de ce compte. Le décodeur conserve l’offset, le slot, les clés, racines et signatures intégrées à l’instruction, résume l’instruction Ed25519 précédente et ne prétend ni relire le compte ni recalculer les signatures.
|
||||
|
||||
Une transaction réussie prouve seulement l’acceptation runtime, l’assignation/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 n’est recopié, aucune signature n’est recalculée et aucune sortie métier n’est 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 l’interface 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 d’une preuve stockée dans le premier compte lorsque l’instruction 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 d’une transaction donnée.
|
||||
|
||||
Aucune signature mainnet n’a é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 l’offset et la taille attendue. Aucune preuve n’est recalculée et aucune sortie n’est 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 d’une transaction échouée et reste non commitée.
|
||||
|
||||
L’enum officielle de `solana-stake-interface ^4.3` conserve le contrat Serde/Bincode historique, mais n’implémente pas directement `SchemaRead`/`SchemaWrite`. Pour respecter l’interdiction workspace de dépendre de `bincode`, le décodeur utilise un miroir wire privé, ordonné exactement comme l’enum 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 l’interface.
|
||||
|
||||
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 n’est ajoutée dans ce delta.
|
||||
|
||||
### Compte Stake Config historique
|
||||
|
||||
`StakeConfig11111111111111111111111111111111` n’est pas un programme exécutable. L’interface 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 l’exécuteur.
|
||||
|
||||
### Config Program
|
||||
|
||||
Le Config Program ne possède pas un enum d’instructions discriminé comparable à System ou Stake. Chaque invocation stocke un préfixe `ConfigKeys` sérialisé avec `solana_short_vec`, suivi d’un payload spécifique au type de configuration. Le décodeur valide la longueur compacte, les clés, les booléens signataires et l’ordre 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 d’instruction 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 l’interface. 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 n’est 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 l’enum `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 l’instruction a été acceptée par le runtime. Pour une transaction échouée, aucune validité n’est affirmée et l’observation 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 à l’instant d’exécution. L’événement conserve donc le compte source, l’offset, 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 l’autorité 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 n’est éligible que lorsque `contextStateRequested = true`, que la transaction a réussi et que l’observation est commitée. La sortie conserve le compte, l’autorité 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 l’owner 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 qu’une 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. L’observation 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 d’opé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 d’un corpus réel.
|
||||
|
||||
Le backfill Vote de 500 signatures a inséré 500 transactions et l’extraction 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. L’unique `failed` de la campagne provient d’un `set_compute_unit_limit` de 12 octets : le runtime l’accepte 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é.
|
||||
106
olddocs/archivekbot2/docs/NOMENCLATURE.md
Normal file
106
olddocs/archivekbot2/docs/NOMENCLATURE.md
Normal file
@@ -0,0 +1,106 @@
|
||||
<!-- 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.
|
||||
91
olddocs/archivekbot2/docs/POSTGRES_STORE.md
Normal file
91
olddocs/archivekbot2/docs/POSTGRES_STORE.md
Normal file
@@ -0,0 +1,91 @@
|
||||
<!-- 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` n’est pas requis pour démarrer l’application.
|
||||
|
||||
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 l’ordre, 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 l’initialisation d’un 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 d’un 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 l’index unique après le début de la transaction ;
|
||||
4. vérifie qu’aucune transaction core, account key ou entrée ledger n’a é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é d’un 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.
|
||||
42
olddocs/archivekbot2/docs/PROGRAM_CODE_INDEX.md
Normal file
42
olddocs/archivekbot2/docs/PROGRAM_CODE_INDEX.md
Normal file
@@ -0,0 +1,42 @@
|
||||
<!-- 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.
|
||||
15
olddocs/archivekbot2/docs/PROGRAM_IDS.md
Normal file
15
olddocs/archivekbot2/docs/PROGRAM_IDS.md
Normal file
@@ -0,0 +1,15 @@
|
||||
<!-- 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.
|
||||
|
||||
18
olddocs/archivekbot2/docs/PROGRAM_ID_CONSTANTS_AUDIT.md
Normal file
18
olddocs/archivekbot2/docs/PROGRAM_ID_CONSTANTS_AUDIT.md
Normal file
@@ -0,0 +1,18 @@
|
||||
<!-- 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 l’utiliser 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 d’instruction 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`.
|
||||
|
||||
152
olddocs/archivekbot2/docs/PROGRAM_NAMING.md
Normal file
152
olddocs/archivekbot2/docs/PROGRAM_NAMING.md
Normal file
@@ -0,0 +1,152 @@
|
||||
<!-- file: docs/PROGRAM_NAMING.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# 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, d’un IDL ou d’une 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 crates techniques déjà lisibles :
|
||||
|
||||
- `kb_decoder_solana_core` ;
|
||||
- `kb_decoder_spl_token` ;
|
||||
- `kb_decoder_spl_token_2022` ;
|
||||
- `kb_decoder_spl_associated_token_account`.
|
||||
|
||||
Ces crates ne sont pas renommées en `kb_decoder_core_*` ou `kb_decoder_token_*`, car elles 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 une seule crate ;
|
||||
3. mettre à jour `Cargo.toml` ;
|
||||
4. mettre à jour le registre ;
|
||||
5. exécuter `cargo build` ;
|
||||
6. supprimer l’ancien 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.
|
||||
328
olddocs/archivekbot2/docs/PROGRAM_REGISTRY_CONTROL.md
Normal file
328
olddocs/archivekbot2/docs/PROGRAM_REGISTRY_CONTROL.md
Normal file
@@ -0,0 +1,328 @@
|
||||
<!-- file: docs/PROGRAM_REGISTRY_CONTROL.md -->
|
||||
<!-- version: 4 -->
|
||||
|
||||
# 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_token_2022_v2022` | `TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb` | `token_2022` | `program` | `kb_decoder_spl_token_2022` | `core_handled` |
|
||||
| `core_spl_token_2022_elgamal_registry_v1` | `regVYJW7tcT8zipN5YiBvHsvR5jXW1uLFxaHSbugABg` | `spl_token_2022_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_decoder_metadata_metaplex_token_metadata` | `reserved_missing` |
|
||||
| `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` |
|
||||
20
olddocs/archivekbot2/docs/PROJECT_OBJECTIVES.md
Normal file
20
olddocs/archivekbot2/docs/PROJECT_OBJECTIVES.md
Normal file
@@ -0,0 +1,20 @@
|
||||
<!-- 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.
|
||||
115
olddocs/archivekbot2/docs/RAW_STORAGE_LIFECYCLE.md
Normal file
115
olddocs/archivekbot2/docs/RAW_STORAGE_LIFECYCLE.md
Normal file
@@ -0,0 +1,115 @@
|
||||
<!-- 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 d’origine 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 d’information 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 d’acquisition
|
||||
|
||||
`kb_sol_obs_transaction_observations` conserve les preuves techniques d’acquisition :
|
||||
|
||||
- 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 n’existe 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’à l’hydratation 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 l’audit minimal, mais le payload canonique complet n’est plus dans la ligne chaude.
|
||||
|
||||
### `archived`
|
||||
|
||||
Le payload a été déplacé vers un stockage d’archive durable.
|
||||
|
||||
### `purged`
|
||||
|
||||
Le payload n’est 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 :
|
||||
|
||||
- l’extraction 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.
|
||||
|
||||
147
olddocs/archivekbot2/docs/RAW_STORE.md
Normal file
147
olddocs/archivekbot2/docs/RAW_STORE.md
Normal file
@@ -0,0 +1,147 @@
|
||||
<!-- 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 d’extraction 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 d’une signature sans recopier le payload complet.
|
||||
|
||||
Colonnes principales visées :
|
||||
|
||||
| Colonne | Rôle |
|
||||
|-----------------------|-------------------------------------------------------|
|
||||
| `id` | clé primaire technique |
|
||||
| `observation_key` | clé idempotente de l’observation |
|
||||
| `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 d’ingestion |
|
||||
| `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` n’est 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 d’hydratation.
|
||||
|
||||
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é d’unicité 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 l’observation 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`.
|
||||
80
olddocs/archivekbot2/docs/REPLAY_PIPELINE.md
Normal file
80
olddocs/archivekbot2/docs/REPLAY_PIPELINE.md
Normal file
@@ -0,0 +1,80 @@
|
||||
<!-- 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é d’inputs.
|
||||
|
||||
## É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 l’union 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 qu’un classifieur natif sélectionne des instructions SPL, Jupiter, Pump ou d’autres programmes non compatibles. Elle empêche également la resélection infinie d’un 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 l’un de ces deux scopes est refusée.
|
||||
|
||||
Lorsqu’une 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 l’input 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 qu’aucun décodeur compatible n’a accepté l’input après le filtre exact de programme. L’instruction n’est 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.
|
||||
77
olddocs/archivekbot2/docs/RPC_ENDPOINT_ROLES.md
Normal file
77
olddocs/archivekbot2/docs/RPC_ENDPOINT_ROLES.md
Normal file
@@ -0,0 +1,77 @@
|
||||
<!-- file: docs/RPC_ENDPOINT_ROLES.md -->
|
||||
<!-- version: 4 -->
|
||||
|
||||
# Rôles des endpoints RPC et streams
|
||||
|
||||
Les rôles servent à sélectionner un endpoint selon l’opé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_rpc`. 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_rpc`.
|
||||
|
||||
236
olddocs/archivekbot2/docs/RUST_WORKSPACE_RULE_AUDIT.md
Normal file
236
olddocs/archivekbot2/docs/RUST_WORKSPACE_RULE_AUDIT.md
Normal file
@@ -0,0 +1,236 @@
|
||||
<!-- file: docs/RUST_WORKSPACE_RULE_AUDIT.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# Audit des règles Rust du workspace
|
||||
|
||||
Violations détectées : **616**.
|
||||
|
||||
## Synthèse
|
||||
|
||||
| Code | Nombre |
|
||||
|------------|-------:|
|
||||
| `RUST010` | 156 |
|
||||
| `RUST011` | 16 |
|
||||
| `RUST013` | 19 |
|
||||
| `RUST021` | 1 |
|
||||
| `TRACE002` | 32 |
|
||||
| `TRACE003` | 202 |
|
||||
| `TRACE004` | 190 |
|
||||
|
||||
## Premiers écarts
|
||||
|
||||
- `RUST010` `kb_app_demo/src/demo_backfill.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_app_demo/src/demo_backfill.rs:7` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_app_demo/src/demo_backfill.rs:8` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_app_demo/src/demo_config.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_app_demo/src/demo_config.rs:7` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_app_demo/src/demo_core_extraction.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_app_demo/src/demo_core_extraction.rs:7` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_app_demo/src/demo_core_extraction.rs:8` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_app_demo/src/demo_decode_replay.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_app_demo/src/demo_decode_replay.rs:7` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_app_demo/src/demo_decode_replay.rs:8` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_app_demo/src/demo_execution_solana_core.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_app_demo/src/demo_execution_solana_core.rs:7` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_app_demo/src/demo_execution_solana_core.rs:8` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_app_demo/src/demo_execution_spl.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_app_demo/src/demo_http.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_app_demo/src/demo_http.rs:7` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_app_demo/src/demo_spl_ata.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_app_demo/src/demo_spl_token.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_app_demo/src/demo_spl_token_2022.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_app_demo/src/demo_sql_common.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_app_demo/src/demo_sql_common.rs:7` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_app_demo/src/demo_sql_diag.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_app_demo/src/demo_sql_pg_core.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_app_demo/src/demo_sql_pg_raw.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_app_demo/src/demo_sql_replay_candidates.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_app_demo/src/demo_ws.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_app_demo/src/demo_ws.rs:7` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_app_demo/src/demo_ws.rs:8` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_app_demo/src/demo_ws.rs:993` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_app_demo/src/frontend_log.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_app_demo/src/lib.rs:13` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_app_demo/src/lib.rs:14` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_app_demo/src/main.rs:12` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_app_demo/src/splash.rs:9` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_app_demo/src/splash.rs:10` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_config/src/settings.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_config/src/settings.rs:1223` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_decoder_api/src/contracts.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_decoder_metadata_metaplex_token_metadata/src/canonical.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_decoder_metadata_metaplex_token_metadata/src/decoder.rs:144` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_decoder_metadata_metaplex_token_metadata/src/instruction.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_decoder_metadata_metaplex_token_metadata/src/instruction.rs:7` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_decoder_solana_core/src/address_lookup_table.rs:326` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_decoder_solana_core/src/compute_budget.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_decoder_solana_core/src/compute_budget.rs:673` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_decoder_solana_core/src/config.rs:322` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_decoder_solana_core/src/feature.rs:167` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_decoder_solana_core/src/loaders.rs:992` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_decoder_solana_core/src/payload.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_decoder_solana_core/src/payload.rs:7` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_decoder_solana_core/src/slashing.rs:461` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_decoder_solana_core/src/stake.rs:805` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_decoder_solana_core/src/system.rs:438` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_decoder_solana_core/src/vote.rs:707` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_decoder_solana_core/src/zk_elgamal.rs:522` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_decoder_solana_core/src/zk_token_proof.rs:693` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_decoder_spl_associated_token_account/src/decoder.rs:335` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_decoder_spl_associated_token_account/src/instruction.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_decoder_spl_associated_token_account/src/instruction.rs:7` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_decoder_spl_elgamal_registry/src/decoder.rs:95` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_decoder_spl_elgamal_registry/src/decoder.rs:162` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_decoder_spl_elgamal_registry/src/registry.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_decoder_spl_elgamal_registry/src/registry.rs:7` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_decoder_spl_elgamal_registry/src/state.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_decoder_spl_elgamal_registry/src/state.rs:49` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_decoder_spl_memo/src/decoder.rs:160` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_decoder_spl_memo/src/memo.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_decoder_spl_memo/src/memo.rs:7` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_decoder_spl_token/src/decoder.rs:144` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_decoder_spl_token/src/token.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_decoder_spl_token/src/token.rs:7` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_decoder_spl_token_2022/src/decoder.rs:144` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_decoder_spl_token_2022/src/state.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_decoder_spl_token_2022/src/state.rs:916` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_decoder_spl_token_2022/src/token.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_decoder_spl_token_2022/src/token.rs:7` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_execution_api/src/execution.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_execution_api/src/executor.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_execution_safety/src/safety.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_execution_solana/src/nonce.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_execution_solana/src/transaction.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_execution_solana/src/transaction.rs:7` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_execution_solana/src/transaction.rs:654` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_execution_solana/src/transaction.rs:655` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_executor_solana_core/src/address_lookup_table.rs:321` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_executor_solana_core/src/builder.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_executor_solana_core/src/builder.rs:1374` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_executor_solana_core/src/intent.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_executor_solana_core/src/native_admin.rs:381` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_executor_solana_core/src/precompiles.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_executor_solana_core/src/slashing.rs:346` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_executor_solana_core/src/stake.rs:1497` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_executor_solana_core/src/validation.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_executor_solana_core/src/validation.rs:108` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_executor_solana_core/src/vote.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_executor_solana_core/src/vote.rs:1846` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_executor_spl_associated_token_account/src/intent.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_executor_spl_elgamal_registry/src/builder.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_executor_spl_elgamal_registry/src/builder.rs:7` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_executor_spl_elgamal_registry/src/intent.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_executor_spl_memo/src/builder.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_executor_spl_memo/src/builder.rs:194` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_executor_spl_memo/src/intent.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_executor_spl_token/src/builder.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_executor_spl_token/src/intent.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_executor_spl_token_2022/src/builder.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_executor_spl_token_2022/src/confidential.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_executor_spl_token_2022/src/confidential.rs:425` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_executor_spl_token_2022/src/intent.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_logging/src/tracing_runtime.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_logging/src/tracing_runtime.rs:7` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_logging/src/tracing_runtime.rs:8` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_logging/src/tracing_runtime.rs:676` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_logging/src/tracing_runtime.rs:677` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_model/src/canonical_transaction.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_model/src/canonical_transaction.rs:7` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_model/src/decoded.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_model/src/materialized.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_model/src/nomenclature.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_model/src/observation.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_model/src/solana.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_pipeline/src/backfill.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_pipeline/src/backfill.rs:7` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_pipeline/src/backfill.rs:8` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_pipeline/src/core_extraction.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_pipeline/src/core_extraction.rs:7` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_pipeline/src/core_extraction.rs:8` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_pipeline/src/decode_replay.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_pipeline/src/decode_replay.rs:7` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_pipeline/src/solana_elgamal_registry_stateful.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_pipeline/src/solana_elgamal_registry_stateful.rs:227` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_pipeline/src/solana_stateful.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_pipeline/src/solana_token_stateful.rs:392` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_pipeline/src/solana_token_stateful.rs:470` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_rpc/src/execution_rpc.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_rpc/src/execution_rpc.rs:2251` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_rpc/src/get_transaction.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_rpc/src/standard_http.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_rpc/src/ws_client.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_rpc/src/ws_client.rs:7` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_rpc/src/ws_session.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_rpc/src/ws_session.rs:7` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_rpc/src/ws_session.rs:1219` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_rpc/src/ws_session.rs:1220` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_store_pg/src/queries/core_extraction_queries.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_store_pg/src/queries/core_queries.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_store_pg/src/queries/decode_pipeline_queries.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_store_pg/src/queries/table_diagnostics_queries.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_wallet/src/wallet.rs:6` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_wallet/src/wallet.rs:7` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_wallet/src/wallet.rs:261` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_wallet/src/wallet.rs:294` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_wallet/src/wallet.rs:299` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_wallet/src/wallet.rs:411` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST010` `kb_wallet/src/wallet.rs:524` — ordinary `use` requires a trait-import justification marker
|
||||
- `RUST011` `kb_executor_solana_core/src/lib.rs:129` — grouped re-export is forbidden
|
||||
- `RUST011` `kb_executor_solana_core/src/lib.rs:137` — grouped re-export is forbidden
|
||||
- `RUST011` `kb_executor_solana_core/src/lib.rs:145` — grouped re-export is forbidden
|
||||
- `RUST011` `kb_executor_solana_core/src/lib.rs:159` — grouped re-export is forbidden
|
||||
- `RUST011` `kb_executor_spl_token/src/lib.rs:29` — grouped re-export is forbidden
|
||||
- `RUST011` `kb_executor_spl_token_2022/src/lib.rs:16` — grouped re-export is forbidden
|
||||
- `RUST011` `kb_executor_spl_token_2022/src/lib.rs:47` — grouped re-export is forbidden
|
||||
- `RUST011` `kb_rpc/src/lib.rs:167` — grouped re-export is forbidden
|
||||
- `RUST011` `kb_rpc/src/lib.rs:175` — grouped re-export is forbidden
|
||||
- `RUST011` `kb_rpc/src/lib.rs:180` — grouped re-export is forbidden
|
||||
- `RUST011` `kb_rpc/src/lib.rs:188` — grouped re-export is forbidden
|
||||
- `RUST011` `kb_rpc/src/lib.rs:198` — grouped re-export is forbidden
|
||||
- `RUST011` `kb_rpc/src/lib.rs:204` — grouped re-export is forbidden
|
||||
- `RUST011` `kb_rpc/src/lib.rs:209` — grouped re-export is forbidden
|
||||
- `RUST011` `kb_rpc/src/lib.rs:232` — grouped re-export is forbidden
|
||||
- `RUST011` `kb_rpc/src/lib.rs:257` — grouped re-export is forbidden
|
||||
- `RUST013` `kb_decoder_metadata_metaplex_token_metadata/src/canonical.rs:6` — grouped imports are forbidden
|
||||
- `RUST013` `kb_decoder_spl_token_2022/src/state.rs:916` — grouped imports are forbidden
|
||||
- `RUST013` `kb_executor_solana_core/src/lib.rs:129` — grouped imports are forbidden
|
||||
- `RUST013` `kb_executor_solana_core/src/lib.rs:137` — grouped imports are forbidden
|
||||
- `RUST013` `kb_executor_solana_core/src/lib.rs:145` — grouped imports are forbidden
|
||||
- `RUST013` `kb_executor_solana_core/src/lib.rs:159` — grouped imports are forbidden
|
||||
- `RUST013` `kb_executor_spl_token/src/lib.rs:29` — grouped imports are forbidden
|
||||
- `RUST013` `kb_executor_spl_token_2022/src/confidential.rs:425` — grouped imports are forbidden
|
||||
- `RUST013` `kb_executor_spl_token_2022/src/lib.rs:16` — grouped imports are forbidden
|
||||
- `RUST013` `kb_executor_spl_token_2022/src/lib.rs:47` — grouped imports are forbidden
|
||||
- `RUST013` `kb_rpc/src/lib.rs:167` — grouped imports are forbidden
|
||||
- `RUST013` `kb_rpc/src/lib.rs:175` — grouped imports are forbidden
|
||||
- `RUST013` `kb_rpc/src/lib.rs:180` — grouped imports are forbidden
|
||||
- `RUST013` `kb_rpc/src/lib.rs:188` — grouped imports are forbidden
|
||||
- `RUST013` `kb_rpc/src/lib.rs:198` — grouped imports are forbidden
|
||||
- `RUST013` `kb_rpc/src/lib.rs:204` — grouped imports are forbidden
|
||||
- `RUST013` `kb_rpc/src/lib.rs:209` — grouped imports are forbidden
|
||||
- `RUST013` `kb_rpc/src/lib.rs:232` — grouped imports are forbidden
|
||||
- `RUST013` `kb_rpc/src/lib.rs:257` — grouped imports are forbidden
|
||||
- `RUST021` `kb_app_demo/src/lib.rs:42` — crate-root re-export requires adjacent rustdoc
|
||||
- `TRACE002` `kb_app_demo/src/lib.rs:1` — TRACING_TARGET must be re-exported with `pub(crate) use`
|
||||
- `TRACE002` `kb_decoder_metadata_metaplex_token_metadata/src/lib.rs:1` — TRACING_TARGET must be re-exported with `pub(crate) use`
|
||||
- `TRACE002` `kb_decoder_solana_core/src/lib.rs:1` — TRACING_TARGET must be re-exported with `pub(crate) use`
|
||||
- `TRACE002` `kb_decoder_spl_associated_token_account/src/lib.rs:1` — TRACING_TARGET must be re-exported with `pub(crate) use`
|
||||
- `TRACE002` `kb_decoder_spl_elgamal_registry/src/lib.rs:1` — TRACING_TARGET must be re-exported with `pub(crate) use`
|
||||
- `TRACE002` `kb_decoder_spl_memo/src/lib.rs:1` — TRACING_TARGET must be re-exported with `pub(crate) use`
|
||||
- `TRACE002` `kb_decoder_spl_token/src/lib.rs:1` — TRACING_TARGET must be re-exported with `pub(crate) use`
|
||||
- `TRACE002` `kb_decoder_spl_token_2022/src/lib.rs:1` — TRACING_TARGET must be re-exported with `pub(crate) use`
|
||||
|
||||
Le rapport est tronqué aux 200 premiers écarts sur 616.
|
||||
|
||||
## Stratégie de correction
|
||||
|
||||
La mise en conformité est découpée avant toute nouvelle prérelease :
|
||||
|
||||
1. `pre.035-delta-fix-002` : séparation des règles et audit automatisé reproductible ;
|
||||
2. correctifs suivants : points d'entrée de crates, réexports `pub`/`pub(crate)`, rustdocs et chemins `crate::...` ;
|
||||
3. correctifs suivants : imports de traits et suppression des imports ordinaires/groupés ;
|
||||
4. correctifs suivants : `TRACING_TARGET`, dépendances `tracing`, macros et matrice de routes ;
|
||||
5. correctifs suivants : helpers dupliqués et mutualisation inter-crates ;
|
||||
6. fermeture : `cargo fmt --all`, audit strict, tests workspace et Clippy global.
|
||||
|
||||
Aucune nouvelle prérelease ne doit être créée tant que cette séquence n'est pas terminée et validée localement.
|
||||
272
olddocs/archivekbot2/docs/SOLANA_INTERFACE_DEPENDENCIES.md
Normal file
272
olddocs/archivekbot2/docs/SOLANA_INTERFACE_DEPENDENCIES.md
Normal file
@@ -0,0 +1,272 @@
|
||||
<!-- file: docs/SOLANA_INTERFACE_DEPENDENCIES.md -->
|
||||
<!-- version: 28 -->
|
||||
|
||||
# Dépendances d’interfaces 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 lorsqu’elle utilise réellement au moins un de ses éléments :
|
||||
|
||||
- enum d’instruction 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` lorsqu’il est officiellement exposé par l’interface ;
|
||||
2. Borsh lorsqu’il correspond au contrat officiel ou au comportement du runtime ;
|
||||
3. parseur local borné lorsque l’interface officielle ne fournit son helper qu’avec `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 l’orphan rule interdit de les réimplémenter localement pour ces types externes.
|
||||
|
||||
La migration vers `wincode 0.6` doit attendre que l’ensemble des crates Solana consommées migre de façon cohérente. Une double dépendance aliasée n’est 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 d’origine. Avant toute migration, vérifier avec `cargo tree -d` et `cargo tree -i wincode@<version>`.
|
||||
|
||||
|
||||
Le workspace n’ajoute pas de dépendance directe à `bincode`. Une feature officielle `bincode` seule n’est 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 d’offsets, 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 n’exé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` n’est ajoutée.
|
||||
|
||||
## Transaction client dans `kb_execution_solana`
|
||||
|
||||
`kb_execution_solana` n’importe plus l’agré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 l’interface 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 l’exé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 `Pubkey` canoniques. `solana-instructions-sysvar` ne doit être ajouté que lorsqu’une crate appelle réellement ses fonctions d’introspection d’instructions, 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` n’est 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 l’enum officielle de façon exacte tout en conservant la compatibilité du booléen optionnel historique des dernières variantes. L’exécuteur appelle les helpers officiels pour onze plans : création de buffer, écriture, déploiement, upgrade, changements d’autorité, fermetures et extension.
|
||||
|
||||
`solana-loader-v4-interface ^3.1` publie l’enum et les comptes officiels, mais ses helpers de construction sont conditionnés par la feature `bincode` et l’enum ne fournit pas de schéma `wincode`. Pour respecter l’interdiction 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 n’ajoute donc pas une dépendance inutilisée à l’interface 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 ; l’instruction actuelle reste un tag d’un octet vérifié depuis le builder/processor |
|
||||
| `solana-feature-set-interface ^4.0` | classification/diagnostics natifs | ajouter seulement lorsqu’un 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 qu’aucun schéma `wincode` n’est publié |
|
||||
| interfaces SPL | crates `kb_decoder_spl_*` et `kb_executor_spl_*` correspondantes | ne pas les rattacher au décodeur natif ni à l’application |
|
||||
| types RPC/account/transaction status | `kb_rpc` | ne pas les ajouter à `kb_app_demo` ; l’application 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.
|
||||
|
||||
L’exé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 l’autorisation d’envoi et Mainnet. La démo du jalon retient séparément v4 sur Devnet. La taille packet finale reste contrôlée par `kb_execution_solana` 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 l’UTF‑8. 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 l’UTF‑8. Ces règles restent séparées dans `docs/SPL_MEMO_MATRIX.json` et les tests comparent les trois IDs locaux aux constantes de l’interface officielle.
|
||||
|
||||
L’archive 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 `0.4.5`. Les crates
|
||||
`kb_decoder_spl_associated_token_account` et `kb_executor_spl_associated_token_account` consomment
|
||||
réellement l'enum, les builders, le Program ID et le helper officiel de dérivation ; le pipeline et
|
||||
la démo consomment ensuite leurs contrats typés sans recopier l'interface.
|
||||
|
||||
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. L'exécuteur
|
||||
utilise les mêmes builders pour les trois variantes, impose simulation et dry-run par défaut, puis
|
||||
laisse au pipeline stateful les contrôles de mint, owner, compte existant, rent, signataires et
|
||||
postconditions.
|
||||
|
||||
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`, consommées par
|
||||
`kb_decoder_spl_token_2022` pour poursuivre l'audit. 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.
|
||||
|
||||
### ZK ElGamal Proof
|
||||
|
||||
`kb_decoder_solana_core` consomme directement `solana-zk-elgamal-proof-interface ^0.1`. L’enum `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 l’acceptation des octets suffixes de `CloseContextState`.
|
||||
|
||||
Aucune dépendance à `bytemuck` n’est ajoutée directement : le décodeur ne convertit pas les octets en preuve cryptographique et n’appelle aucun vérificateur. Il utilise uniquement `size_of` sur les types officiels, puis conserve longueur, SHA-256 et préfixe borné. Le contenu d’un compte de preuve externe n’est 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 à l’offset `u32 LE`, auditée contre la version historique `3.1.14`; aucun code de preuve ni sérialiseur historique n’est 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 n’ayant été observé, les tests sont synthétiques et n’exigent 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 à l’enum d’instruction. Le décodeur et l’exécuteur consomment donc l’ID et les types sémantiques officiels, avec un miroir wire privé commun dans son ordre de variantes et de champs. Aucun helper `bincode` n’est activé.
|
||||
|
||||
L’exé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 à l’orchestration localnet/devnet.
|
||||
|
||||
### Config Program
|
||||
|
||||
`solana-config-interface 2.x` expose son module d’instruction derrière sa feature `bincode`. Le décodeur et l’exé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 l’initialisation `ConfigKeys vide + T::default()` à partir d’octets déjà sérialisés ; il n’active aucun helper `bincode`.
|
||||
|
||||
### BPF Loader v2
|
||||
|
||||
`solana-loader-v2-interface 3.x` publie ses helpers d’instruction derrière `bincode`. Le décodeur conserve le layout local vérifié tant qu’aucun schéma officiel `wincode` n’est disponible.
|
||||
|
||||
### Feature Gate
|
||||
|
||||
`solana-feature-gate-interface 4.x` publie la séquence d’activation `transfer -> allocate -> assign` et `RevokePendingActivation`, mais les helpers restent derrière sa feature `bincode`. L’exé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 l’ordre 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 n’est nécessaire. L’exé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 l’exé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 d’instruction 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 n’est 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 l’exé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 d’activer `bincode` uniquement pour appeler les helpers de l’interface.
|
||||
|
||||
## `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 l’agré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 l’encodeur officiel lorsque disponible ;
|
||||
6. tester les payloads tronqués, inconnus, suffixés et les comptes invalides ;
|
||||
7. documenter toute divergence entre l’interface et le runtime.
|
||||
|
||||
### Metaplex Token Metadata — audit et premier décodage `0.4.7-pre.002`
|
||||
|
||||
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 l’IDL Metaplex, sans introduire Anchor. La crate officielle utilise Borsh `< 1.0`; le décodeur référence donc explicitement `borsh 0.10` sous l’alias workspace `borsh_0_10`, distinct de Borsh 1.x utilisé par d’autres interfaces du workspace.
|
||||
|
||||
Le dépôt officiel `metaplex-foundation/mpl-token-metadata` confirme le Program ID `metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s`. L’IDL officiel audité porte la version `1.14.0` et le blob `5df4a24f62c2743125be096cc174680790c92c18`; l’inventaire Rust généré des instructions porte le blob `3c42eec629f82e44ba690a7c4bd2177cc78f1d49`.
|
||||
|
||||
`kb_decoder_metadata_metaplex_token_metadata` implémente désormais `InstructionDecoder` pour `CreateMetadataAccountV3` et `UpdateMetadataAccountV2`. Les arguments sont lus avec les types Borsh officiels et projetés avec la feature `serde`; les payloads, chaînes, créateurs, frais, comptes et suffixes sont bornés. L’enregistrement dans le registre runtime reste différé jusqu’à validation de ce premier groupe. Les metadata Token-2022 incorporées, Metaplex Core, Bubblegum et le JSON externe restent des provenances ou composants distincts.
|
||||
|
||||
106
olddocs/archivekbot2/docs/SOLANA_NATIVE_RPC_CLOSURE_AUDIT.md
Normal file
106
olddocs/archivekbot2/docs/SOLANA_NATIVE_RPC_CLOSURE_AUDIT.md
Normal file
@@ -0,0 +1,106 @@
|
||||
<!-- 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é. L’audit 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_rpc` ;
|
||||
4. l’orchestration de sécurité, de simulation, d’envoi et de replay post-exécution.
|
||||
|
||||
Une méthode transportable via JSON brut n’est pas considérée comme un adaptateur typé. Un builder stateless n’autorise pas à lui seul une opération dépendant d’un compte, d’une autorité, du rent, d’un slot ou d’un epoch. Une opération dangereuse peut être complète dans la bibliothèque tout en restant absente de l’UI 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 d’opé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 l’ancien ZK Token Proof Program. Stake `Redelegate` reste historique `decode-only`. Cette classification évite d’inventer des instructions qui ne sont plus ou n’ont 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 l’activation mutable exige encore une preuve stateful par scénario sur Localnet/Devnet. Aucune de ces opérations n’est 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 d’instruction ni plan d’exé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_rpc`. 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 l’API publique. La voie JSON brute reste une primitive interne ou d’extension 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_rpc`. `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 lorsqu’un 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, d’authentification 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 d’identifiants sont contrôlées avec `Number.isSafeInteger` avant invocation. Les types génériques hors frontière Tauri conservent leurs contrats exacts lorsqu’ils ne sont pas sérialisés par `JSON.stringify`.
|
||||
|
||||
Le navigateur SQL applique maintenant la limite maximale reçue du backend avant l’appel Tauri. Une valeur supérieure à 5 000 produit un diagnostic frontend et n’atteint 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_execution_solana` | 12 tests |
|
||||
| `kb_rpc` | 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.
|
||||
|
||||
L’archive de logs Mainnet/Tauri confirme des unsubscribe réels pour `slot`, `root` et `program`. Le refus de sélectionner un autre endpoint tant qu’une session est active est un garde-fou volontaire. L’ancien échec `JSON.stringify cannot serialize BigInt` n’est 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 à l’exécution.
|
||||
|
||||
La clôture de `0.4.2` n’ouvre aucune version suivante et ne fixe aucun plan de sources historiques externes.
|
||||
430
olddocs/archivekbot2/docs/SOLANA_STANDARD_RPC_MATRIX.json
Normal file
430
olddocs/archivekbot2/docs/SOLANA_STANDARD_RPC_MATRIX.json
Normal file
@@ -0,0 +1,430 @@
|
||||
{
|
||||
"file": "docs/SOLANA_STANDARD_RPC_MATRIX.json",
|
||||
"version": 3,
|
||||
"release": "0.4.2-pre.025",
|
||||
"canonical_reference": "https://solana.com/docs/rpc",
|
||||
"http_method_count": 52,
|
||||
"http_typed_adapter_count": 52,
|
||||
"http_raw_json_count": 0,
|
||||
"ws_subscription_pair_count": 9,
|
||||
"ws_method_count": 18,
|
||||
"ws_unstable_subscription_count": 3,
|
||||
"http_methods": [
|
||||
{
|
||||
"method": "getAccountInfo",
|
||||
"category": "accounts",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "dedicated execution/acquisition adapter plus HttpClient/HttpEndpointPool"
|
||||
},
|
||||
{
|
||||
"method": "getBalance",
|
||||
"category": "accounts",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "dedicated execution/acquisition adapter plus HttpClient/HttpEndpointPool"
|
||||
},
|
||||
{
|
||||
"method": "getLargestAccounts",
|
||||
"category": "accounts",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "configurable kb_rpc request/result contract plus typed HttpClient/HttpEndpointPool transport"
|
||||
},
|
||||
{
|
||||
"method": "getMinimumBalanceForRentExemption",
|
||||
"category": "accounts",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "dedicated execution/acquisition adapter plus HttpClient/HttpEndpointPool"
|
||||
},
|
||||
{
|
||||
"method": "getMultipleAccounts",
|
||||
"category": "accounts",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "configurable kb_rpc request/result contract plus typed HttpClient/HttpEndpointPool transport"
|
||||
},
|
||||
{
|
||||
"method": "getProgramAccounts",
|
||||
"category": "accounts",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "configurable kb_rpc request/result contract plus typed HttpClient/HttpEndpointPool transport"
|
||||
},
|
||||
{
|
||||
"method": "getTokenAccountBalance",
|
||||
"category": "tokens",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "configurable kb_rpc request/result contract plus typed HttpClient/HttpEndpointPool transport"
|
||||
},
|
||||
{
|
||||
"method": "getTokenAccountsByDelegate",
|
||||
"category": "tokens",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "configurable kb_rpc request/result contract plus typed HttpClient/HttpEndpointPool transport"
|
||||
},
|
||||
{
|
||||
"method": "getTokenAccountsByOwner",
|
||||
"category": "tokens",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "configurable kb_rpc request/result contract plus typed HttpClient/HttpEndpointPool transport"
|
||||
},
|
||||
{
|
||||
"method": "getTokenLargestAccounts",
|
||||
"category": "tokens",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "configurable kb_rpc request/result contract plus typed HttpClient/HttpEndpointPool transport"
|
||||
},
|
||||
{
|
||||
"method": "getTokenSupply",
|
||||
"category": "tokens",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "configurable kb_rpc request/result contract plus typed HttpClient/HttpEndpointPool transport"
|
||||
},
|
||||
{
|
||||
"method": "getFeeForMessage",
|
||||
"category": "transactions",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "dedicated execution/acquisition adapter plus HttpClient/HttpEndpointPool"
|
||||
},
|
||||
{
|
||||
"method": "getLatestBlockhash",
|
||||
"category": "transactions",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "dedicated execution/acquisition adapter plus HttpClient/HttpEndpointPool"
|
||||
},
|
||||
{
|
||||
"method": "getRecentPrioritizationFees",
|
||||
"category": "transactions",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "configurable kb_rpc request/result contract plus typed HttpClient/HttpEndpointPool transport"
|
||||
},
|
||||
{
|
||||
"method": "getSignaturesForAddress",
|
||||
"category": "transactions",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "dedicated execution/acquisition adapter plus HttpClient/HttpEndpointPool"
|
||||
},
|
||||
{
|
||||
"method": "getSignatureStatuses",
|
||||
"category": "transactions",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "dedicated execution/acquisition adapter plus HttpClient/HttpEndpointPool"
|
||||
},
|
||||
{
|
||||
"method": "getTransaction",
|
||||
"category": "transactions",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "dedicated execution/acquisition adapter plus HttpClient/HttpEndpointPool"
|
||||
},
|
||||
{
|
||||
"method": "getTransactionCount",
|
||||
"category": "transactions",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "configurable kb_rpc request/result contract plus typed HttpClient/HttpEndpointPool transport"
|
||||
},
|
||||
{
|
||||
"method": "isBlockhashValid",
|
||||
"category": "transactions",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "configurable kb_rpc request/result contract plus typed HttpClient/HttpEndpointPool transport"
|
||||
},
|
||||
{
|
||||
"method": "requestAirdrop",
|
||||
"category": "transactions",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "dedicated execution/acquisition adapter plus HttpClient/HttpEndpointPool"
|
||||
},
|
||||
{
|
||||
"method": "sendTransaction",
|
||||
"category": "transactions",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "dedicated execution/acquisition adapter plus HttpClient/HttpEndpointPool"
|
||||
},
|
||||
{
|
||||
"method": "simulateTransaction",
|
||||
"category": "transactions",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "dedicated execution/acquisition adapter plus HttpClient/HttpEndpointPool"
|
||||
},
|
||||
{
|
||||
"method": "getBlock",
|
||||
"category": "blocks",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "configurable kb_rpc request/result contract plus typed HttpClient/HttpEndpointPool transport"
|
||||
},
|
||||
{
|
||||
"method": "getBlockCommitment",
|
||||
"category": "blocks",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "configurable kb_rpc request/result contract plus typed HttpClient/HttpEndpointPool transport"
|
||||
},
|
||||
{
|
||||
"method": "getBlockHeight",
|
||||
"category": "blocks",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "dedicated execution/acquisition adapter plus HttpClient/HttpEndpointPool"
|
||||
},
|
||||
{
|
||||
"method": "getBlockProduction",
|
||||
"category": "blocks",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "configurable kb_rpc request/result contract plus typed HttpClient/HttpEndpointPool transport"
|
||||
},
|
||||
{
|
||||
"method": "getBlocks",
|
||||
"category": "blocks",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "configurable kb_rpc request/result contract plus typed HttpClient/HttpEndpointPool transport"
|
||||
},
|
||||
{
|
||||
"method": "getBlocksWithLimit",
|
||||
"category": "blocks",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "configurable kb_rpc request/result contract plus typed HttpClient/HttpEndpointPool transport"
|
||||
},
|
||||
{
|
||||
"method": "getBlockTime",
|
||||
"category": "blocks",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "configurable kb_rpc request/result contract plus typed HttpClient/HttpEndpointPool transport"
|
||||
},
|
||||
{
|
||||
"method": "getFirstAvailableBlock",
|
||||
"category": "blocks",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "configurable kb_rpc request/result contract plus typed HttpClient/HttpEndpointPool transport"
|
||||
},
|
||||
{
|
||||
"method": "getRecentPerformanceSamples",
|
||||
"category": "blocks",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "configurable kb_rpc request/result contract plus typed HttpClient/HttpEndpointPool transport"
|
||||
},
|
||||
{
|
||||
"method": "minimumLedgerSlot",
|
||||
"category": "blocks",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "configurable kb_rpc request/result contract plus typed HttpClient/HttpEndpointPool transport"
|
||||
},
|
||||
{
|
||||
"method": "getClusterNodes",
|
||||
"category": "cluster",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "configurable kb_rpc request/result contract plus typed HttpClient/HttpEndpointPool transport"
|
||||
},
|
||||
{
|
||||
"method": "getEpochInfo",
|
||||
"category": "cluster",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "dedicated execution/acquisition adapter plus HttpClient/HttpEndpointPool"
|
||||
},
|
||||
{
|
||||
"method": "getEpochSchedule",
|
||||
"category": "cluster",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "configurable kb_rpc request/result contract plus typed HttpClient/HttpEndpointPool transport"
|
||||
},
|
||||
{
|
||||
"method": "getGenesisHash",
|
||||
"category": "cluster",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "dedicated execution/acquisition adapter plus HttpClient/HttpEndpointPool"
|
||||
},
|
||||
{
|
||||
"method": "getHealth",
|
||||
"category": "cluster",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "configurable kb_rpc request/result contract plus typed HttpClient/HttpEndpointPool transport"
|
||||
},
|
||||
{
|
||||
"method": "getHighestSnapshotSlot",
|
||||
"category": "cluster",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "configurable kb_rpc request/result contract plus typed HttpClient/HttpEndpointPool transport"
|
||||
},
|
||||
{
|
||||
"method": "getIdentity",
|
||||
"category": "cluster",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "configurable kb_rpc request/result contract plus typed HttpClient/HttpEndpointPool transport"
|
||||
},
|
||||
{
|
||||
"method": "getLeaderSchedule",
|
||||
"category": "cluster",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "configurable kb_rpc request/result contract plus typed HttpClient/HttpEndpointPool transport"
|
||||
},
|
||||
{
|
||||
"method": "getMaxRetransmitSlot",
|
||||
"category": "cluster",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "configurable kb_rpc request/result contract plus typed HttpClient/HttpEndpointPool transport"
|
||||
},
|
||||
{
|
||||
"method": "getMaxShredInsertSlot",
|
||||
"category": "cluster",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "configurable kb_rpc request/result contract plus typed HttpClient/HttpEndpointPool transport"
|
||||
},
|
||||
{
|
||||
"method": "getSlot",
|
||||
"category": "cluster",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "configurable kb_rpc request/result contract plus typed HttpClient/HttpEndpointPool transport"
|
||||
},
|
||||
{
|
||||
"method": "getSlotLeader",
|
||||
"category": "cluster",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "configurable kb_rpc request/result contract plus typed HttpClient/HttpEndpointPool transport"
|
||||
},
|
||||
{
|
||||
"method": "getSlotLeaders",
|
||||
"category": "cluster",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "configurable kb_rpc request/result contract plus typed HttpClient/HttpEndpointPool transport"
|
||||
},
|
||||
{
|
||||
"method": "getVersion",
|
||||
"category": "cluster",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "configurable kb_rpc request/result contract plus typed HttpClient/HttpEndpointPool transport"
|
||||
},
|
||||
{
|
||||
"method": "getVoteAccounts",
|
||||
"category": "cluster",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "configurable kb_rpc request/result contract plus typed HttpClient/HttpEndpointPool transport"
|
||||
},
|
||||
{
|
||||
"method": "getInflationGovernor",
|
||||
"category": "economics",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "configurable kb_rpc request/result contract plus typed HttpClient/HttpEndpointPool transport"
|
||||
},
|
||||
{
|
||||
"method": "getInflationRate",
|
||||
"category": "economics",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "configurable kb_rpc request/result contract plus typed HttpClient/HttpEndpointPool transport"
|
||||
},
|
||||
{
|
||||
"method": "getInflationReward",
|
||||
"category": "economics",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "configurable kb_rpc request/result contract plus typed HttpClient/HttpEndpointPool transport"
|
||||
},
|
||||
{
|
||||
"method": "getStakeMinimumDelegation",
|
||||
"category": "economics",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "configurable kb_rpc request/result contract plus typed HttpClient/HttpEndpointPool transport"
|
||||
},
|
||||
{
|
||||
"method": "getSupply",
|
||||
"category": "economics",
|
||||
"contract": "typed_adapter",
|
||||
"implementation": "configurable kb_rpc request/result contract plus typed HttpClient/HttpEndpointPool transport"
|
||||
}
|
||||
],
|
||||
"ws_subscriptions": [
|
||||
{
|
||||
"subscribe_method": "accountSubscribe",
|
||||
"unsubscribe_method": "accountUnsubscribe",
|
||||
"notification_method": "accountNotification",
|
||||
"stability": "stable",
|
||||
"request_contract": "typed_adapter",
|
||||
"persistent_runtime": true,
|
||||
"library_runtime": "kb_rpc::WsSession multiplexing, explicit unsubscribe, bounded reconnect and resubscription",
|
||||
"notification_contract": "typed_adapter",
|
||||
"explicit_capability_required": false
|
||||
},
|
||||
{
|
||||
"subscribe_method": "blockSubscribe",
|
||||
"unsubscribe_method": "blockUnsubscribe",
|
||||
"notification_method": "blockNotification",
|
||||
"stability": "unstable",
|
||||
"request_contract": "typed_adapter",
|
||||
"persistent_runtime": true,
|
||||
"library_runtime": "kb_rpc::WsSession multiplexing, explicit unsubscribe, bounded reconnect and resubscription",
|
||||
"notification_contract": "typed_adapter",
|
||||
"explicit_capability_required": true
|
||||
},
|
||||
{
|
||||
"subscribe_method": "logsSubscribe",
|
||||
"unsubscribe_method": "logsUnsubscribe",
|
||||
"notification_method": "logsNotification",
|
||||
"stability": "stable",
|
||||
"request_contract": "typed_adapter",
|
||||
"persistent_runtime": true,
|
||||
"library_runtime": "kb_rpc::WsSession multiplexing, explicit unsubscribe, bounded reconnect and resubscription",
|
||||
"notification_contract": "typed_adapter",
|
||||
"explicit_capability_required": false
|
||||
},
|
||||
{
|
||||
"subscribe_method": "programSubscribe",
|
||||
"unsubscribe_method": "programUnsubscribe",
|
||||
"notification_method": "programNotification",
|
||||
"stability": "stable",
|
||||
"request_contract": "typed_adapter",
|
||||
"persistent_runtime": true,
|
||||
"library_runtime": "kb_rpc::WsSession multiplexing, explicit unsubscribe, bounded reconnect and resubscription",
|
||||
"notification_contract": "typed_adapter",
|
||||
"explicit_capability_required": false
|
||||
},
|
||||
{
|
||||
"subscribe_method": "rootSubscribe",
|
||||
"unsubscribe_method": "rootUnsubscribe",
|
||||
"notification_method": "rootNotification",
|
||||
"stability": "stable",
|
||||
"request_contract": "typed_adapter",
|
||||
"persistent_runtime": true,
|
||||
"library_runtime": "kb_rpc::WsSession multiplexing, explicit unsubscribe, bounded reconnect and resubscription",
|
||||
"notification_contract": "typed_adapter",
|
||||
"explicit_capability_required": false
|
||||
},
|
||||
{
|
||||
"subscribe_method": "signatureSubscribe",
|
||||
"unsubscribe_method": "signatureUnsubscribe",
|
||||
"notification_method": "signatureNotification",
|
||||
"stability": "stable",
|
||||
"request_contract": "typed_adapter",
|
||||
"persistent_runtime": true,
|
||||
"library_runtime": "kb_rpc::WsSession multiplexing, explicit unsubscribe, bounded reconnect and resubscription",
|
||||
"notification_contract": "typed_adapter",
|
||||
"explicit_capability_required": false
|
||||
},
|
||||
{
|
||||
"subscribe_method": "slotSubscribe",
|
||||
"unsubscribe_method": "slotUnsubscribe",
|
||||
"notification_method": "slotNotification",
|
||||
"stability": "stable",
|
||||
"request_contract": "typed_adapter",
|
||||
"persistent_runtime": true,
|
||||
"library_runtime": "kb_rpc::WsSession multiplexing, explicit unsubscribe, bounded reconnect and resubscription",
|
||||
"notification_contract": "typed_adapter",
|
||||
"explicit_capability_required": false
|
||||
},
|
||||
{
|
||||
"subscribe_method": "slotsUpdatesSubscribe",
|
||||
"unsubscribe_method": "slotsUpdatesUnsubscribe",
|
||||
"notification_method": "slotsUpdatesNotification",
|
||||
"stability": "unstable",
|
||||
"request_contract": "typed_adapter",
|
||||
"persistent_runtime": true,
|
||||
"library_runtime": "kb_rpc::WsSession multiplexing, explicit unsubscribe, bounded reconnect and resubscription",
|
||||
"notification_contract": "typed_adapter",
|
||||
"explicit_capability_required": true
|
||||
},
|
||||
{
|
||||
"subscribe_method": "voteSubscribe",
|
||||
"unsubscribe_method": "voteUnsubscribe",
|
||||
"notification_method": "voteNotification",
|
||||
"stability": "unstable",
|
||||
"request_contract": "typed_adapter",
|
||||
"persistent_runtime": true,
|
||||
"library_runtime": "kb_rpc::WsSession multiplexing, explicit unsubscribe, bounded reconnect and resubscription",
|
||||
"notification_contract": "typed_adapter",
|
||||
"explicit_capability_required": true
|
||||
}
|
||||
],
|
||||
"ws_typed_request_count": 9,
|
||||
"ws_typed_notification_count": 9,
|
||||
"ws_persistent_runtime_count": 9
|
||||
}
|
||||
@@ -0,0 +1,199 @@
|
||||
{
|
||||
"file": "docs/SPL_ASSOCIATED_TOKEN_ACCOUNT_MATRIX.json",
|
||||
"version": 9,
|
||||
"schemaVersion": 1,
|
||||
"programId": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL",
|
||||
"systemProgramId": "11111111111111111111111111111111",
|
||||
"supportedTokenPrograms": [
|
||||
{"code": "spl_token", "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", "scope": "classic_token_account_lifecycle_only"},
|
||||
{"code": "spl_token_2022", "programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb", "scope": "ata_lifecycle_only_without_general_token_2022_instruction_or_extension_decode"}
|
||||
],
|
||||
"interface": {
|
||||
"workspaceConstraint": "^2.0",
|
||||
"resolvedVersion": "2.0.0",
|
||||
"resolutionEvidence": "docs_rs_latest_published_version_and_official_interface_tag",
|
||||
"workspaceCargoResolutionStatus": "confirmed_by_operator_cargo_tree_2026-07-16",
|
||||
"features": ["borsh"],
|
||||
"bincodeEnabled": false,
|
||||
"officialTag": "interface@v2.0.0",
|
||||
"releaseCommit": "250da0e21a9853a7afddba85658ed8a9119c71c9",
|
||||
"releaseDate": "2025-08-08",
|
||||
"instructionSource": "https://github.com/solana-program/associated-token-account/blob/interface@v2.0.0/interface/src/instruction.rs",
|
||||
"addressSource": "https://github.com/solana-program/associated-token-account/blob/interface@v2.0.0/interface/src/address.rs",
|
||||
"publishedDocumentation": "https://docs.rs/spl-associated-token-account-interface/2.0.0/spl_associated_token_account_interface/"
|
||||
},
|
||||
"processor": {
|
||||
"auditedRelease": "program@v8.0.0",
|
||||
"releaseCommit": "0b867b5",
|
||||
"releaseDate": "2025-10-29",
|
||||
"source": "https://github.com/solana-program/associated-token-account/blob/program@v8.0.0/program/src/processor.rs",
|
||||
"deploymentBinaryEquality": {"localnet": "not_tested", "devnet": "not_proven", "mainnet": "not_proven"},
|
||||
"note": "Interface publication, processor source, cluster deployment and successful execution are tracked independently."
|
||||
},
|
||||
"wire": {
|
||||
"format": "Borsh enum with unit variants encoded as one u8 ordinal",
|
||||
"strictSuffixPolicy": "reject",
|
||||
"legacyEmptyCreate": {"decodeSupport": true, "builderEmits": false, "encodingHex": "", "status": "historical_runtime_and_transaction_parser_compatibility_to_be_reconfirmed_by_cluster_corpus"},
|
||||
"unknownOrTruncatedPolicy": "bounded diagnostic without lifecycle projection"
|
||||
},
|
||||
"pdaDerivation": {
|
||||
"programId": "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL",
|
||||
"seedOrder": ["wallet_address_bytes[32]", "token_program_id_bytes[32]", "mint_address_bytes[32]"],
|
||||
"algorithm": "Pubkey::find_program_address",
|
||||
"validationPolicy": "preserve observed address and report exact match or mismatch; never replace an observed account silently",
|
||||
"differentialVectors": [
|
||||
{"wallet": "11111111111111111111111111111111", "mint": "So11111111111111111111111111111111111111112", "tokenProgramId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", "expectedAta": "aqxoAhCwpy3oB1BpNw9hL1HdLYLgPpbPjzxDrrQj3Fs", "expectedBump": 254, "evidence": "PublicKey.findProgramAddressSync with the canonical official seed order"},
|
||||
{"wallet": "11111111111111111111111111111111", "mint": "So11111111111111111111111111111111111111112", "tokenProgramId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb", "expectedAta": "2sZUUBGq1i6aE47ZoxCaCW89jmYm2EXLPPmNMgMDXHMS", "expectedBump": 250, "evidence": "PublicKey.findProgramAddressSync with the canonical official seed order"}
|
||||
]
|
||||
},
|
||||
"limits": {"exactVariantCount": 3, "createRequiredAccountCount": 6, "recoverNestedRequiredAccountCount": 7, "maximumDiagnosticBytes": 256, "extraAccounts": "preserved_and_reported; never assigned an invented role"},
|
||||
"executionPreflight": {
|
||||
"clusters": ["localnet", "devnet"],
|
||||
"programIds": ["associated_token_program", "selected_token_program", "system_program_for_creation"],
|
||||
"stateChecks": ["mint_exists_initialized_and_owned_by_selected_token_program", "canonical_pda_derivation", "strict_create_absence", "idempotent_absence_or_existing_account_compatibility", "recover_nested_three_account_relationships", "required_signers_available", "payer_balance_covers_rent_plus_fee_ceiling"],
|
||||
"token2022Boundary": "base Mint and Token Account prefixes are validated while suffix extensions remain opaque; simulation determines extension-dependent runtime acceptance and exact account size",
|
||||
"simulation": "required_before_signing_or_sending",
|
||||
"defaultMode": "dry_run"
|
||||
},
|
||||
"surfaceEquality": {"matrixVariantCount": 3, "officialInterfaceVariantCount": 3, "compiledDecoderCoverageStatus": "three_exact_compiled_instruction_declarations_operator_validated", "compiledExecutorCapabilityStatus": "three_exact_current_capabilities_operator_validated", "requiredFinalInvariant": "matrix == official interface enum == decoder coverage == executor capability declarations"},
|
||||
"instructions": [
|
||||
{
|
||||
"name": "create",
|
||||
"discriminant": 0,
|
||||
"canonicalEncodingHex": "00",
|
||||
"acceptedDecodeEncodingsHex": ["", "00"],
|
||||
"status": "current_with_legacy_empty_wire_compatibility",
|
||||
"accounts": [
|
||||
{"position": 0, "role": "funding_account", "signer": true, "writable": true, "expectedProgram": "system_account"},
|
||||
{"position": 1, "role": "associated_token_account", "signer": false, "writable": true, "expectedProgram": "derived_pda_before_creation_or_supported_token_program_after_creation"},
|
||||
{"position": 2, "role": "wallet_owner", "signer": false, "writable": false, "expectedProgram": "unconstrained_wallet_address"},
|
||||
{"position": 3, "role": "mint", "signer": false, "writable": false, "expectedProgram": "account_owned_by_token_program_at_runtime"},
|
||||
{"position": 4, "role": "system_program", "signer": false, "writable": false, "expectedAddress": "11111111111111111111111111111111"},
|
||||
{"position": 5, "role": "token_program", "signer": false, "writable": false, "allowedAddresses": ["TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb"]}
|
||||
],
|
||||
"addressRules": ["associated_token_account = PDA(wallet_owner, token_program, mint)", "observed associated_token_account is retained on mismatch"],
|
||||
"tokenProgramDifferences": {"classic": "create and initialize a classic token account", "token2022": "size is obtained from the Token-2022 mint and immutable-owner initialization is performed before account initialization; extensions themselves remain out of decoder scope"},
|
||||
"runtimeRules": ["fails if the associated account already exists", "funding account pays rent and creation cost", "mint and created account must be coherent with the selected token program"],
|
||||
"event": "spl_associated_token_account.create",
|
||||
"authorizedProjections": ["token_accounts:ata_created"],
|
||||
"forbiddenProjections": ["token_balance_snapshot", "duplicate_spl_token_initialize_account_cpi", "token_2022_extension_fact"],
|
||||
"officialBuilder": {"available": true, "function": "create_associated_token_account", "canonicalWireOnly": true},
|
||||
"executorSupport": {"status": "supported", "operationCode": "spl_associated_token_account.create", "builder": "create_associated_token_account", "simulation": "required", "defaultMode": "dry_run"},
|
||||
"proofs": {"synthetic": ["canonical_00", "legacy_empty", "classic_token_program", "token_2022_program", "wrong_ata", "missing_account", "extra_account", "duplicate_account", "wrong_flags", "unknown_suffix", "outer", "inner_cpi", "committed", "failed_intent"], "localnet": "not_tested", "devnet": "not_tested", "mainnetSignatures": []}
|
||||
},
|
||||
{
|
||||
"name": "create_idempotent",
|
||||
"discriminant": 1,
|
||||
"canonicalEncodingHex": "01",
|
||||
"acceptedDecodeEncodingsHex": ["01"],
|
||||
"status": "current",
|
||||
"accounts": [
|
||||
{"position": 0, "role": "funding_account", "signer": true, "writable": true, "expectedProgram": "system_account"},
|
||||
{"position": 1, "role": "associated_token_account", "signer": false, "writable": true, "expectedProgram": "derived_pda_or_supported_token_program"},
|
||||
{"position": 2, "role": "wallet_owner", "signer": false, "writable": false},
|
||||
{"position": 3, "role": "mint", "signer": false, "writable": false},
|
||||
{"position": 4, "role": "system_program", "signer": false, "writable": false, "expectedAddress": "11111111111111111111111111111111"},
|
||||
{"position": 5, "role": "token_program", "signer": false, "writable": false, "allowedAddresses": ["TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb"]}
|
||||
],
|
||||
"addressRules": ["associated_token_account = PDA(wallet_owner, token_program, mint)", "existing account must retain the selected token program, wallet owner and mint"],
|
||||
"tokenProgramDifferences": {"classic": "existing classic account is accepted only when owner and mint match", "token2022": "existing Token-2022 account is accepted only when owner and mint match; no extension semantics are inferred"},
|
||||
"runtimeRules": ["creates when absent", "succeeds without recreating when an initialized compatible ATA already exists", "fails when an existing account has a different wallet owner, mint or account owner program"],
|
||||
"event": "spl_associated_token_account.create_idempotent",
|
||||
"authorizedProjections": ["token_accounts:ata_created_or_reused_idempotently"],
|
||||
"forbiddenProjections": ["token_balance_snapshot", "duplicate_spl_token_initialize_account_cpi", "token_2022_extension_fact"],
|
||||
"officialBuilder": {"available": true, "function": "create_associated_token_account_idempotent", "canonicalWireOnly": true},
|
||||
"executorSupport": {"status": "supported", "operationCode": "spl_associated_token_account.create_idempotent", "builder": "create_associated_token_account_idempotent", "simulation": "required", "defaultMode": "dry_run"},
|
||||
"proofs": {"synthetic": ["canonical_01", "absent_account", "compatible_existing_account", "conflicting_existing_owner", "conflicting_existing_mint", "conflicting_existing_program", "classic_token_program", "token_2022_program", "wrong_ata", "wrong_flags", "unexpected_suffix", "outer", "inner_cpi", "committed", "failed_intent"], "localnet": "not_tested", "devnet": ["5Vw4QFpMa8oJ8MsLrvDg4RFzxqUh27mTFRFzzwJFoA4uAry8rZQc6GP92aidzWugn3CeZ5NYNxDp7tZ6bh8XyN1P", "2H9VfhDySdXMteazm2P3s2fTttJBQzMJinQtKqsLtkjDg7zbFFgiWG81UxRQF4va3bbR2pUV4QGo2qErisR8CPbP", "3wWTkx45LoDR3UaU8VUfsWxwHuLFyJyhrnDrmijCa7pXPdmJKz3rQ1LdyDvb78dvNRiKqw5ee7HuZ6Gjj1Gpfv6q", "bMMjoHcwbaTvLXerdQ4kbGXGb7wydiTyvSEwwmoKKLQcRWWBzqGUMYHZztonNnER1iWZ7yKp9p3neeMhypX4QAJ", "4RZKA3KwEbSqgU8UnemTgvd3fBgJmoSK2nmaaTNP8nJGTVh6DrFwrHVZYCBvLFvhvzUdi9p1KRFe4hHqYt7JbVSG"], "mainnetSignatures": ["2F9RvuCkevfJN7ju252hAWoCE58wagCXCWHQF9Wsdtsxvp3HcuNJQFCwU7zGqe3z3b8pv3vPp4xY5EH7KLcaHQCY"], "realCorpusStatus": "controlled classic and Token-2022 CreateIdempotent creation then compatible-existing reuse confirmed, materialized once per signature and replayed idempotently; search-discovered Token-2022 outer transaction remains additional corpus"}
|
||||
},
|
||||
{
|
||||
"name": "recover_nested",
|
||||
"discriminant": 2,
|
||||
"canonicalEncodingHex": "02",
|
||||
"acceptedDecodeEncodingsHex": ["02"],
|
||||
"status": "current_recovery_operation",
|
||||
"accounts": [
|
||||
{"position": 0, "role": "nested_associated_token_account", "signer": false, "writable": true},
|
||||
{"position": 1, "role": "nested_mint", "signer": false, "writable": false},
|
||||
{"position": 2, "role": "wallet_nested_mint_associated_token_account", "signer": false, "writable": true},
|
||||
{"position": 3, "role": "owner_associated_token_account", "signer": false, "writable": false},
|
||||
{"position": 4, "role": "owner_mint", "signer": false, "writable": false},
|
||||
{"position": 5, "role": "wallet_owner", "signer": true, "writable": true},
|
||||
{"position": 6, "role": "token_program", "signer": false, "writable": false, "allowedAddresses": ["TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb"]}
|
||||
],
|
||||
"addressRules": ["owner_associated_token_account = PDA(wallet_owner, token_program, owner_mint)", "nested_associated_token_account = PDA(owner_associated_token_account, token_program, nested_mint)", "wallet_nested_mint_associated_token_account = PDA(wallet_owner, token_program, nested_mint)"],
|
||||
"tokenProgramDifferences": {"classic": "transfer the complete nested balance and close the nested classic token account", "token2022": "same ATA address relationships through Token-2022 CPIs; extension-specific transfer or close restrictions can prevent recovery and are not decoded as ATA facts"},
|
||||
"runtimeRules": ["all three derived addresses must match their observed accounts", "owner and nested token accounts must be initialized and coherent with their respective mints", "wallet owner must sign", "complete nested token balance is moved to the wallet destination ATA", "nested account is closed and its lamports are returned to the wallet"],
|
||||
"event": "spl_associated_token_account.recover_nested",
|
||||
"authorizedProjections": ["token_accounts:nested_ata_recovered", "risk:nested_ata_anti_pattern_recovered"],
|
||||
"forbiddenProjections": ["duplicate_spl_token_transfer_cpi", "duplicate_spl_token_close_account_cpi", "token_balance_snapshot", "token_2022_extension_fact"],
|
||||
"officialBuilder": {"available": true, "function": "recover_nested", "canonicalWireOnly": true},
|
||||
"executorSupport": {"status": "supported", "operationCode": "spl_associated_token_account.recover_nested", "builder": "recover_nested", "simulation": "required", "defaultMode": "dry_run"},
|
||||
"proofs": {"synthetic": ["canonical_02", "classic_token_program", "token_2022_program", "valid_three_pda_relationships", "wrong_nested_ata", "wrong_destination_ata", "wrong_owner_ata", "owner_and_nested_mints_not_inverted", "missing_account", "extra_account", "duplicate_account", "wrong_flags", "unexpected_suffix", "outer", "inner_cpi", "committed", "failed_intent"], "localnet": "not_tested", "devnet": ["37LG6GdMRp5ECG8qf1RSYxmriJk75UtCwqwzXZWpArebkKo6BQvGhYEnbDh2A6KWiUaHK28Zy1gGGZ5zihvrHskM"], "mainnetSignatures": [], "realCorpusStatus": "controlled classic RecoverNested confirmed with positive raw balance transfer, nested ATA closure, owner and destination post-validation, two distinct ATA lifecycle and risk projections, and idempotent second replay", "controlledDevnetFixture": {"walletOwner": "DwuAapPLg6pEJ4QhmxvPg8rzkavmYdg5FW4dfEMcg8B2", "ownerMint": "So11111111111111111111111111111111111111112", "ownerAssociatedTokenAccount": "3tdXq1W7vEbbkxQmT1r2fc349uYti98zpwLKhp7FFbF5", "nestedMint": "3fd5CqP1w4Y1xeMoAe3apA7Jf5SbL3vboxv7ihyXhC9A", "nestedAssociatedTokenAccount": "AAyvGeKpq6i3kxMcScJLcN2u5iyAsspr731LhgXygti5", "walletNestedMintAssociatedTokenAccount": "69TP2QoSx2inueFAEb6npjumH5o3wGJQDSwwAJLLfyWp", "rawAmountTransferred": "1000000000", "nestedAccountClosed": true, "destinationUiBalanceAfter": "1", "materializedOutputCount": 2}}
|
||||
}
|
||||
],
|
||||
"offlineCorpus": {
|
||||
"status": "implemented_and_operator_validated_in_decoder_unit_tests",
|
||||
"wire": ["create_00", "legacy_empty_create", "create_idempotent_01", "recover_nested_02", "unknown_tag", "rejected_suffix"],
|
||||
"tokenPrograms": ["spl_token_classic", "token_2022"],
|
||||
"locations": ["outer", "inner_cpi"],
|
||||
"transactionOutcomes": ["committed", "failed_uncommitted_intent"],
|
||||
"accountShapes": ["canonical", "missing", "extra", "duplicate", "wrong_flags", "wrong_derived_address", "unsupported_token_program", "wrong_system_program"],
|
||||
"derivation": ["create_single_pda", "recover_nested_three_independent_pda_relationships", "official_helper_differential_vectors"],
|
||||
"limits": "diagnostic count and payload prefix are bounded; no arbitrary payload or account repair"
|
||||
},
|
||||
"materializationContract": {
|
||||
"committedOnly": true,
|
||||
"idempotenceIdentity": "signature + instruction_path + program_id + normalized_operation + ata",
|
||||
"projectionOwners": [
|
||||
{
|
||||
"crate": "kb_materializer_token_accounts",
|
||||
"facts": [
|
||||
"ata_created",
|
||||
"ata_created_or_reused_idempotently",
|
||||
"nested_ata_recovered"
|
||||
],
|
||||
"justification": "ATA creation and recovery are stable token-account lifecycle facts; this crate already owns instruction-level token-account mutations."
|
||||
},
|
||||
{
|
||||
"crate": "kb_materializer_risk",
|
||||
"facts": [
|
||||
"nested_ata_anti_pattern_recovered"
|
||||
],
|
||||
"justification": "A committed RecoverNested proves the distinct stable risk fact that a nested ATA anti-pattern existed and was recovered; no score or speculative severity is added."
|
||||
}
|
||||
],
|
||||
"explicitNoProjection": [
|
||||
{
|
||||
"crate": "kb_materializer_lifecycle",
|
||||
"reason": "Native program lifecycle remains owned here; duplicating ATA lifecycle would overlap kb_materializer_token_accounts."
|
||||
},
|
||||
{
|
||||
"crate": "kb_materializer_admin",
|
||||
"reason": "ATA instructions do not change a mint authority, freeze authority, close authority or multisig configuration."
|
||||
},
|
||||
{
|
||||
"crate": "kb_materializer_fees",
|
||||
"reason": "ATA wire does not prove an exact rent or network-fee amount; core balance changes and execution validation retain those facts."
|
||||
}
|
||||
],
|
||||
"implementationStatus": "pre_004 executor and stateful preflight operator validated; pre_005 classic and Token-2022 CreateIdempotent Devnet orchestration plus Tauri validated; pre_006 classic RecoverNested Devnet orchestration validated",
|
||||
"idempotentOutcomeLimit": "CreateIdempotent parent proves successful ensure semantics but cannot distinguish created from reused without sibling CPI correlation; the projection preserves created_or_reused and invents neither boolean.",
|
||||
"parentChildOwnership": "ATA parent owns only associated-address lifecycle and the distinct nested-ATA risk fact; SPL Token or Token-2022 CPI observations own token initialize, transfer and close mutations.",
|
||||
"noSnapshotClaim": true,
|
||||
"databaseMigrationStatus": "not_justified"
|
||||
},
|
||||
"executionContract": {"simulationRequired": true, "dryRunDefault": true, "clusterPolicyOwnedByCommonLayers": true, "rentAndFeeCeilingRequired": true, "signerDeduplicationDoesNotChangeMetaOrder": true, "confirmedStateReadRetryBound": 20, "canonicalHydrationRpcRetryBoundPerAttempt": 2, "postValidation": {"create": "ATA exists, is owned by selected token program, and contains expected wallet owner and mint", "createIdempotent": "same invariant whether the ATA was created or reused", "recoverNested": "owner ATA and destination remain coherent, nested ATA is absent, and no balance value is invented by ATA projection"}},
|
||||
"deploymentAudit": {
|
||||
"localnet": {"status": "not_tested", "evidence": []},
|
||||
"devnet": {"status": "classic and Token-2022 CreateIdempotent creation and compatible-existing reuse confirmed; classic RecoverNested positive-balance recovery confirmed", "evidence": ["5Vw4QFpMa8oJ8MsLrvDg4RFzxqUh27mTFRFzzwJFoA4uAry8rZQc6GP92aidzWugn3CeZ5NYNxDp7tZ6bh8XyN1P", "2H9VfhDySdXMteazm2P3s2fTttJBQzMJinQtKqsLtkjDg7zbFFgiWG81UxRQF4va3bbR2pUV4QGo2qErisR8CPbP", "3wWTkx45LoDR3UaU8VUfsWxwHuLFyJyhrnDrmijCa7pXPdmJKz3rQ1LdyDvb78dvNRiKqw5ee7HuZ6Gjj1Gpfv6q", "bMMjoHcwbaTvLXerdQ4kbGXGb7wydiTyvSEwwmoKKLQcRWWBzqGUMYHZztonNnER1iWZ7yKp9p3neeMhypX4QAJ", "4RZKA3KwEbSqgU8UnemTgvd3fBgJmoSK2nmaaTNP8nJGTVh6DrFwrHVZYCBvLFvhvzUdi9p1KRFe4hHqYt7JbVSG", "37LG6GdMRp5ECG8qf1RSYxmriJk75UtCwqwzXZWpArebkKo6BQvGhYEnbDh2A6KWiUaHK28Zy1gGGZ5zihvrHskM"], "controlledToken2022Fixture": {"mint": "3DxKAUfCZkR9oRfMXeRNpiVL464eKbTieymBrVhsoKTE", "mintOwner": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb", "mintBaseLength": 82, "walletOwner": "DwuAapPLg6pEJ4QhmxvPg8rzkavmYdg5FW4dfEMcg8B2", "associatedTokenAccount": "6WfCJPt7GZQyMJAUS1AMHJrD7Vid8e9xUEQVgi5Q9C9Y", "accountLength": 170, "accountExtension": "immutable_owner", "creationSlot": 476702448, "existingReuseSlot": 476703343}},
|
||||
"mainnet": {"status": "search_discovered_token_2022_create_idempotent_not_yet_replayed", "evidence": ["2F9RvuCkevfJN7ju252hAWoCE58wagCXCWHQF9Wsdtsxvp3HcuNJQFCwU7zGqe3z3b8pv3vPp4xY5EH7KLcaHQCY"]},
|
||||
"rateLimitRecovery": "preserve confirmed signatures and resume bounded hydration; never recreate accounts blindly after HTTP 429"
|
||||
},
|
||||
"nonClaims": [
|
||||
"No general Token-2022 instruction or extension decoding is implemented in 0.4.5.",
|
||||
"No Token balance or final account snapshot is reconstructed from ATA instructions.",
|
||||
"No cluster binary equality is inferred from interface publication.",
|
||||
"The controlled Token-2022 proof covers ATA lifecycle only and does not claim general Token-2022 instruction or extension decoding.",
|
||||
"No dedicated SQL table is justified by this audit tranche."
|
||||
]
|
||||
}
|
||||
121
olddocs/archivekbot2/docs/SPL_ELGAMAL_REGISTRY_MATRIX.json
Normal file
121
olddocs/archivekbot2/docs/SPL_ELGAMAL_REGISTRY_MATRIX.json
Normal file
@@ -0,0 +1,121 @@
|
||||
{
|
||||
"file": "docs/SPL_ELGAMAL_REGISTRY_MATRIX.json",
|
||||
"version": 1,
|
||||
"programId": "regVYJW7tcT8zipN5YiBvHsvR5jXW1uLFxaHSbugABg",
|
||||
"interface": {
|
||||
"crate": "spl-elgamal-registry-interface",
|
||||
"resolvedVersion": "0.2.1",
|
||||
"auditedCommitPrefix": "e18f9c6"
|
||||
},
|
||||
"technicalBoundaries": {
|
||||
"token2022ProgramId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb",
|
||||
"zkElgamalProofProgramId": "ZkE1Gama1Proof11111111111111111111111111111",
|
||||
"registryDecodesProofInstructions": false,
|
||||
"token2022DecoderOwnsRegistryInstructions": false
|
||||
},
|
||||
"pda": {
|
||||
"seedUtf8": "elgamal-registry",
|
||||
"ownerAddressIsSeed": true,
|
||||
"programIdIsDerivationProgram": true
|
||||
},
|
||||
"instructions": [
|
||||
{
|
||||
"name": "create_registry",
|
||||
"tag": 0,
|
||||
"wire": {
|
||||
"exactLengthBytes": 2,
|
||||
"fields": [
|
||||
{
|
||||
"name": "tag",
|
||||
"type": "u8",
|
||||
"value": 0
|
||||
},
|
||||
{
|
||||
"name": "proofInstructionOffset",
|
||||
"type": "i8"
|
||||
}
|
||||
]
|
||||
},
|
||||
"accounts": [
|
||||
{
|
||||
"position": 0,
|
||||
"role": "registry_account",
|
||||
"writable": true,
|
||||
"signer": false
|
||||
},
|
||||
{
|
||||
"position": 1,
|
||||
"role": "wallet_owner",
|
||||
"writable": false,
|
||||
"signer": true
|
||||
},
|
||||
{
|
||||
"position": 2,
|
||||
"role": "system_program",
|
||||
"writable": false,
|
||||
"signer": false
|
||||
},
|
||||
{
|
||||
"position": 3,
|
||||
"role": "instructions_sysvar_or_proof_context",
|
||||
"writable": false,
|
||||
"signer": false
|
||||
}
|
||||
],
|
||||
"builder": "create_registry",
|
||||
"status": "current"
|
||||
},
|
||||
{
|
||||
"name": "update_registry",
|
||||
"tag": 1,
|
||||
"wire": {
|
||||
"exactLengthBytes": 2,
|
||||
"fields": [
|
||||
{
|
||||
"name": "tag",
|
||||
"type": "u8",
|
||||
"value": 1
|
||||
},
|
||||
{
|
||||
"name": "proofInstructionOffset",
|
||||
"type": "i8"
|
||||
}
|
||||
]
|
||||
},
|
||||
"accounts": [
|
||||
{
|
||||
"position": 0,
|
||||
"role": "registry_account",
|
||||
"writable": true,
|
||||
"signer": false
|
||||
},
|
||||
{
|
||||
"position": 1,
|
||||
"role": "instructions_sysvar_or_proof_context",
|
||||
"writable": false,
|
||||
"signer": false
|
||||
},
|
||||
{
|
||||
"position": 2,
|
||||
"role": "registry_owner",
|
||||
"writable": false,
|
||||
"signer": true
|
||||
}
|
||||
],
|
||||
"builder": "update_registry",
|
||||
"status": "current"
|
||||
}
|
||||
],
|
||||
"proofLocationSemantics": {
|
||||
"offsetZero": "context_state_account",
|
||||
"offsetNonZero": "relative_zk_proof_instruction",
|
||||
"publishedInlineBuilderOffset": 1
|
||||
},
|
||||
"decoder": {
|
||||
"crate": "kb_decoder_spl_elgamal_registry",
|
||||
"coverageEqualityRequired": true,
|
||||
"unknownTagPolicy": "failed",
|
||||
"trailingBytesPolicy": "failed",
|
||||
"failedTransactionCommitted": false
|
||||
}
|
||||
}
|
||||
266
olddocs/archivekbot2/docs/SPL_MEMO_MATRIX.json
Normal file
266
olddocs/archivekbot2/docs/SPL_MEMO_MATRIX.json
Normal file
@@ -0,0 +1,266 @@
|
||||
{
|
||||
"file": "docs/SPL_MEMO_MATRIX.json",
|
||||
"version": 8,
|
||||
"matrixVersion": 4,
|
||||
"scope": "SPL Memo v1, v3 et v4",
|
||||
"interface": {
|
||||
"crate": "spl-memo-interface",
|
||||
"requestedVersion": "^2.1",
|
||||
"auditedPublishedVersion": "2.1.0",
|
||||
"lockfilePresentInInputArchive": false,
|
||||
"builder": "spl_memo_interface::instruction::build_memo",
|
||||
"builderAcceptsExplicitProgramId": true,
|
||||
"wire": "octets exacts du message, sans préfixe ni discriminator",
|
||||
"accountMetas": "ordre fourni, readonly, signer=true"
|
||||
},
|
||||
"generations": [
|
||||
{
|
||||
"generation": "v1",
|
||||
"programId": "Memo1UhkJRfHyvLMcVucJwxXeuD728EqVDDwQDxFMNo",
|
||||
"surfaceCode": "spl_memo_v1",
|
||||
"status": "historique immuable",
|
||||
"instructionData": "octets UTF-8 bruts",
|
||||
"emptyPayload": "accepte",
|
||||
"accounts": "acceptes mais ignores par le runtime v1",
|
||||
"signerRequirement": "aucune",
|
||||
"accountOrder": "sans effet runtime mais conserve par le decodeur",
|
||||
"duplicateAccounts": "sans effet runtime mais conserves par le decodeur",
|
||||
"runtimeLogs": [],
|
||||
"utf8Failure": "InvalidInstructionData",
|
||||
"builderOfficial": "builder generique 2.1.0 avec program ID v1 explicite",
|
||||
"currentInvocation": {
|
||||
"mainnet": "transactions reelles observees et rejouees; aucun envoi execute dans cette tranche",
|
||||
"devnet": "non verifie",
|
||||
"localnet": "binaire historique non embarque"
|
||||
},
|
||||
"realCorpusSignatures": [
|
||||
"imGSCgR83S3tFPTcZPqWLWRcL1piFX1vkYMRVsRdJeBM4p7viDb4V6Hq2x51ovTmbMgGBMdn8kyeNiAg9Ph6MfE",
|
||||
"65J2cmiZAB5h7B3kyzhponNZQzMCbbxVn1A8cydvKKq1FYxYLEarG7ydjuuxFatXCG7Foju21XMUdRkT96jYBS3C"
|
||||
]
|
||||
},
|
||||
{
|
||||
"generation": "v3",
|
||||
"programId": "MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr",
|
||||
"surfaceCode": "spl_memo_v3",
|
||||
"status": "historique encore largement observe",
|
||||
"instructionData": "octets UTF-8 bruts",
|
||||
"emptyPayload": "accepte",
|
||||
"accounts": "zero ou plusieurs; chaque compte fourni doit etre signer",
|
||||
"signerRequirement": "tous les comptes fournis",
|
||||
"accountOrder": "ordre de parcours et de logs conserve",
|
||||
"duplicateAccounts": "parcourus et journalises dans leur ordre; aucun rejet dedie",
|
||||
"runtimeLogs": [
|
||||
"Signed by <pubkey> pour chaque compte signer",
|
||||
"Invalid UTF-8, from byte <offset> en cas d'erreur",
|
||||
"Memo (len <octets>): <texte> en cas de succes"
|
||||
],
|
||||
"utf8Failure": "InvalidInstructionData",
|
||||
"missingSignerFailure": "MissingRequiredSignature avant validation UTF-8",
|
||||
"builderOfficial": "builder generique 2.1.0 avec program ID v3 explicite",
|
||||
"currentInvocation": {
|
||||
"mainnet": "transactions reelles observees et rejouees; aucun envoi execute dans cette tranche",
|
||||
"devnet": "non verifie",
|
||||
"localnet": "possible avec binaire officiel, non execute"
|
||||
},
|
||||
"realCorpusSignatures": [
|
||||
"2DkiJJVAyJ1aJHn2ff8JhKA5C8wbakw76LZvgxmcQ1qtHNDprGvA6TntXXK5FSAeRMZyrDt8ujAkGMgBVcEhjsmT",
|
||||
"3G18ZUSP29Aw12NwnAYRYgix87fa559nMzaBa3LSkCQZjJ5AYEjSDnQHLbgU3QZax2efmeJHdxu1LamSCxCJzg37"
|
||||
]
|
||||
},
|
||||
{
|
||||
"generation": "v4",
|
||||
"programId": "Memo4c2pN8afCj432Lb7RMVKi9PbQnnW7ewFFaV3oAH",
|
||||
"surfaceCode": "spl_memo_v4",
|
||||
"status": "generation courante publiee avec implementation Pinocchio",
|
||||
"instructionData": "octets UTF-8 bruts",
|
||||
"emptyPayload": "accepte",
|
||||
"accounts": "zero ou plusieurs; chaque compte fourni doit etre signer",
|
||||
"signerRequirement": "tous les comptes fournis",
|
||||
"accountOrder": "ordre de parcours et de logs conserve",
|
||||
"duplicateAccounts": "aucun rejet dedie prouve; ordre et doublons conserves",
|
||||
"runtimeLogs": [
|
||||
"signataires puis diagnostic UTF-8 ou memo selon l'implementation officielle"
|
||||
],
|
||||
"utf8Failure": "InvalidInstructionData",
|
||||
"missingSignerFailure": "MissingRequiredSignature avant validation UTF-8",
|
||||
"builderOfficial": "builder generique 2.1.0 avec program ID v4 explicite",
|
||||
"currentInvocation": {
|
||||
"mainnet": "transactions reelles observees et rejouees; aucun envoi execute dans cette tranche",
|
||||
"devnet": "simulation et trois executions v4 confirmees avec post-validation complete le 2026-07-15",
|
||||
"localnet": "binaire officiel disponible, non execute"
|
||||
},
|
||||
"realCorpusSignatures": [
|
||||
"2vgR56q2NR6ehu1uNnpt3te3RqhX2sXryXi4SpBHKUyVaeERr1HLYSLvDFRzd3eDeNejjLX9hVZJZ5GvtsTtBr1c",
|
||||
"53aHhj6rt77hCkadHedpWS7GstdER5XqQrHDutZ7gAQrDvAxcDcktrUtwxZcCbTV2FnLzELqfwoJgvabjdLPWkQ5",
|
||||
"3NxmPdF9W3GBiD8qF2VzvUhEDrTM48EEkaosTtzVceRhQc4sGEojDFppBsXYgqK9GCrCUo4wzAWciprsqZEmRyee",
|
||||
"2njzDJUBar6TTPPcuwEDdkiW8kVLUsZXfdvUQNP7TC6La44E4kZtLFfdJ1Q8nPNJbKa9Vuby4TtiuLX2rQQTa65C"
|
||||
]
|
||||
}
|
||||
],
|
||||
"decoderContract": {
|
||||
"maximumRetainedPayloadBytes": 4096,
|
||||
"diagnosticHexPrefixBytes": 32,
|
||||
"completeTextRetainedWhenUtf8Valid": true,
|
||||
"failedTransactionRuntimeValidation": "not_proven_transaction_failed",
|
||||
"failedTransactionCommitted": false,
|
||||
"unknownProgramProducesObservation": false
|
||||
},
|
||||
"materializationContract": {
|
||||
"crate": "kb_materializer_transaction_annotations",
|
||||
"processorName": "transaction_annotations",
|
||||
"materializedFamily": "transaction_annotation",
|
||||
"acceptedEntries": ["add_memo", "memo_intent", "invalid_memo_attempt"],
|
||||
"projectedEntry": "add_memo",
|
||||
"transactionPolicy": "SuccessfulCommittedOnly",
|
||||
"failedOrUncommittedOutput": false,
|
||||
"store": "kb_sol_mat_events",
|
||||
"newMigrationRequired": false,
|
||||
"idempotence": "ledger processor/version/input hash plus deterministic output key",
|
||||
"readModel": {
|
||||
"contract": "DecodePipelineStore.list_materialized_events",
|
||||
"demo": "demo_decode_replay transaction annotation journal",
|
||||
"boundedMaximumRows": 500,
|
||||
"filters": ["processor exact", "family exact", "partial signature"],
|
||||
"visualization": "table journal, not OHLC"
|
||||
},
|
||||
"decodedOnlyFields": [
|
||||
"complete accounts and writable flags",
|
||||
"payload hex diagnostic prefix",
|
||||
"UTF-8 error offset",
|
||||
"transaction error",
|
||||
"decoder proof"
|
||||
]
|
||||
},
|
||||
"executorContract": {
|
||||
"crate": "kb_executor_spl_memo",
|
||||
"operationCode": "spl_memo.add_memo",
|
||||
"typedIntent": "SplMemoExecutionIntent",
|
||||
"officialBuilder": "spl_memo_interface::instruction::build_memo",
|
||||
"supportedGenerations": ["v4"],
|
||||
"decodeOnlyGenerations": ["v1", "v3"],
|
||||
"maximumMessageBytes": 566,
|
||||
"maximumSignerOccurrences": 32,
|
||||
"preserveSignerOrderAndDuplicates": true,
|
||||
"inventWritableAccounts": false,
|
||||
"requestedSpendLamports": 0,
|
||||
"simulationRequired": true,
|
||||
"dryRunDefault": true,
|
||||
"allClustersConstructible": true,
|
||||
"historicalGenerationSendEnabled": false,
|
||||
"mainnetSendGovernedByCommonPolicy": true,
|
||||
"clusterAvailabilityProvenBySimulation": true,
|
||||
"demoCluster": "devnet",
|
||||
"demoGeneration": "v4",
|
||||
"postExecutionValidation": [
|
||||
"canonical_insert",
|
||||
"core_extraction",
|
||||
"memo_decode_replay",
|
||||
"transaction_annotation_materialization"
|
||||
]
|
||||
},
|
||||
"requiredCorpusCases": [
|
||||
"empty_payload",
|
||||
"ascii",
|
||||
"unicode_multibyte",
|
||||
"near_practical_transaction_limit",
|
||||
"invalid_utf8",
|
||||
"zero_signer",
|
||||
"one_signer",
|
||||
"multiple_signers",
|
||||
"non_signer_account",
|
||||
"duplicate_accounts",
|
||||
"additional_writable_account",
|
||||
"outer_instruction",
|
||||
"inner_instruction",
|
||||
"successful_transaction",
|
||||
"failed_transaction",
|
||||
"malformed_base64",
|
||||
"payload_over_decoder_limit"
|
||||
],
|
||||
"mainnetReplayValidation": {
|
||||
"date": "2026-07-14",
|
||||
"acquisition": {
|
||||
"programCampaigns": 3,
|
||||
"canonicalTransactionsInserted": 300,
|
||||
"missingTransactions": 0
|
||||
},
|
||||
"coreExtraction": {
|
||||
"selected": 300,
|
||||
"extracted": 300,
|
||||
"failed": 0
|
||||
},
|
||||
"generations": [
|
||||
{
|
||||
"generation": "v1",
|
||||
"decodedInstructions": 102,
|
||||
"materializedAnnotations": 69,
|
||||
"refusedUncommittedIntents": 33
|
||||
},
|
||||
{
|
||||
"generation": "v3",
|
||||
"decodedInstructions": 439,
|
||||
"materializedAnnotations": 422,
|
||||
"refusedUncommittedIntents": 17,
|
||||
"secondNonForcedReplaySelected": 0
|
||||
},
|
||||
{
|
||||
"generation": "v4",
|
||||
"decodedInstructions": 100,
|
||||
"materializedAnnotations": 100,
|
||||
"refusedUncommittedIntents": 0
|
||||
}
|
||||
],
|
||||
"decodeFailures": 0,
|
||||
"unmatchedInstructions": 0,
|
||||
"operationalErrorLogEntries": 0
|
||||
},
|
||||
"devnetExecutionValidation": {
|
||||
"date": "2026-07-15",
|
||||
"generation": "v4",
|
||||
"programId": "Memo4c2pN8afCj432Lb7RMVKi9PbQnnW7ewFFaV3oAH",
|
||||
"simulationOnlyValidated": true,
|
||||
"submittedTransactions": 3,
|
||||
"confirmedTransactions": 3,
|
||||
"canonicalTransactionsInserted": 3,
|
||||
"coreTransactionsExtracted": 3,
|
||||
"decodedInstructions": 3,
|
||||
"materializedAnnotations": 3,
|
||||
"annotationPayloadLengthBytes": 34,
|
||||
"secondReplaySkipped": 3,
|
||||
"secondReplayNewMaterializedOutputs": 0,
|
||||
"decodeFailures": 0,
|
||||
"materializationRefusals": 0,
|
||||
"signatures": [
|
||||
"53aHhj6rt77hCkadHedpWS7GstdER5XqQrHDutZ7gAQrDvAxcDcktrUtwxZcCbTV2FnLzELqfwoJgvabjdLPWkQ5",
|
||||
"3NxmPdF9W3GBiD8qF2VzvUhEDrTM48EEkaosTtzVceRhQc4sGEojDFppBsXYgqK9GCrCUo4wzAWciprsqZEmRyee",
|
||||
"2njzDJUBar6TTPPcuwEDdkiW8kVLUsZXfdvUQNP7TC6La44E4kZtLFfdJ1Q8nPNJbKa9Vuby4TtiuLX2rQQTa65C"
|
||||
]
|
||||
},
|
||||
"sources": [
|
||||
{
|
||||
"kind": "official_interface_source",
|
||||
"url": "https://docs.rs/spl-memo-interface/2.1.0/src/spl_memo_interface/instruction.rs.html"
|
||||
},
|
||||
{
|
||||
"kind": "official_interface_ids",
|
||||
"url": "https://docs.rs/spl-memo-interface/2.1.0/src/spl_memo_interface/lib.rs.html"
|
||||
},
|
||||
{
|
||||
"kind": "official_v1_historical_source",
|
||||
"url": "https://github.com/solana-program/memo/commit/479839141a99b7d0c3a35bc648c0fa1e4704ea3e"
|
||||
},
|
||||
{
|
||||
"kind": "official_v3_published_source",
|
||||
"url": "https://docs.rs/spl-memo/3.0.0/src/spl_memo/processor.rs.html"
|
||||
},
|
||||
{
|
||||
"kind": "official_current_source",
|
||||
"url": "https://github.com/solana-program/memo/blob/main/program/src/processor.rs"
|
||||
}
|
||||
],
|
||||
"documentedLimitations": [
|
||||
"v1 et v3 restent decodees depuis un corpus Mainnet reel et leur wire officiel reste audite, mais l'executeur les classe decode-only et ne construit que v4",
|
||||
"l'invocabilite Localnet depend du deploiement explicite du binaire de generation demande",
|
||||
"les differences de cout v3/v4 ne sont pas transformees en garantie statique; chaque plan reste soumis a la simulation et au plafond de frais"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
<!-- file: docs/SPL_TOKEN_2022_CONFIDENTIAL_EXECUTION_AUDIT.md -->
|
||||
<!-- version: 6 -->
|
||||
|
||||
# Audit d’exé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 d’une preuve déjà vérifiée ; le wire Token-2022 encode alors l’offset `0`.
|
||||
|
||||
Un offset inline égal à zéro est invalide dans le contrat de l’exécuteur, car il rendrait le mode ambigu.
|
||||
|
||||
## Inventaire audité
|
||||
|
||||
| Opération | Preuves ordonnées | Classe d’exé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 l’instruction 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 l’ordre officiel : `CiphertextCommitmentEquality`, puis `BatchedRangeProofU64`. Les modes inline et context-state peuvent être combinés. L’exé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 n’ajoute 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`.
|
||||
|
||||
L’ordre des comptes est source writable, mint readonly, destination writable, Instructions Sysvar si au moins une preuve est inline, comptes context-state dans l’ordre des cinq preuves, autorité, puis signataires multisig. Aucun type opaque Token-2022 supplémentaire n’est 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 l’ordre 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 l’Instructions Sysvar n’est présent qu’une fois lorsqu’au 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 l’ordre 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`, l’offset 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 d’un 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 l’alternative 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.
|
||||
2698
olddocs/archivekbot2/docs/SPL_TOKEN_2022_MATRIX.json
Normal file
2698
olddocs/archivekbot2/docs/SPL_TOKEN_2022_MATRIX.json
Normal file
File diff suppressed because it is too large
Load Diff
251
olddocs/archivekbot2/docs/SPL_TOKEN_2022_SOURCE_AUDIT.md
Normal file
251
olddocs/archivekbot2/docs/SPL_TOKEN_2022_SOURCE_AUDIT.md
Normal file
@@ -0,0 +1,251 @@
|
||||
<!-- file: docs/SPL_TOKEN_2022_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.
|
||||
146
olddocs/archivekbot2/docs/SPL_TOKEN_2022_VALIDATION_MATRIX.json
Normal file
146
olddocs/archivekbot2/docs/SPL_TOKEN_2022_VALIDATION_MATRIX.json
Normal file
@@ -0,0 +1,146 @@
|
||||
{
|
||||
"matrixVersion": 2,
|
||||
"milestone": "0.4.6",
|
||||
"status": "partially_confirmed",
|
||||
"statusVocabulary": [
|
||||
"not_run",
|
||||
"simulated",
|
||||
"submitted",
|
||||
"confirmed",
|
||||
"unavailable",
|
||||
"failed"
|
||||
],
|
||||
"scenarios": [
|
||||
{
|
||||
"id": "offline_full_regression",
|
||||
"environment": "offline",
|
||||
"status": "confirmed",
|
||||
"requiredEvidence": [
|
||||
"test_suite",
|
||||
"clippy"
|
||||
],
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "test_suite",
|
||||
"value": "kb_pipeline 120/120"
|
||||
},
|
||||
{
|
||||
"kind": "test_suite",
|
||||
"value": "kb_executor_spl_token_2022 44/44"
|
||||
},
|
||||
{
|
||||
"kind": "test_suite",
|
||||
"value": "kb_executor_spl_elgamal_registry 6/6"
|
||||
},
|
||||
{
|
||||
"kind": "clippy",
|
||||
"value": "cargo clippy --all-targets clean"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "token_2022_public_devnet",
|
||||
"environment": "devnet",
|
||||
"status": "not_run",
|
||||
"requiredEvidence": [
|
||||
"simulation",
|
||||
"signature",
|
||||
"canonical_hydration",
|
||||
"core_extraction",
|
||||
"decode_replay",
|
||||
"materialization",
|
||||
"second_replay"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "elgamal_registry_devnet",
|
||||
"environment": "devnet",
|
||||
"status": "not_run",
|
||||
"requiredEvidence": [
|
||||
"simulation",
|
||||
"signature",
|
||||
"canonical_hydration",
|
||||
"core_extraction",
|
||||
"decode_replay",
|
||||
"materialization",
|
||||
"second_replay"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "confidential_transfer_localnet_or_devnet",
|
||||
"environment": "localnet_or_devnet",
|
||||
"status": "not_run",
|
||||
"requiredEvidence": [
|
||||
"simulation",
|
||||
"proof_mode",
|
||||
"signature",
|
||||
"canonical_hydration",
|
||||
"core_extraction",
|
||||
"decode_replay",
|
||||
"materialization",
|
||||
"second_replay"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "confidential_mint_burn_localnet_or_devnet",
|
||||
"environment": "localnet_or_devnet",
|
||||
"status": "not_run",
|
||||
"requiredEvidence": [
|
||||
"simulation",
|
||||
"proof_mode",
|
||||
"signature",
|
||||
"canonical_hydration",
|
||||
"core_extraction",
|
||||
"decode_replay",
|
||||
"materialization",
|
||||
"second_replay"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "permissioned_confidential_burn_localnet_or_devnet",
|
||||
"environment": "localnet_or_devnet",
|
||||
"status": "not_run",
|
||||
"requiredEvidence": [
|
||||
"simulation",
|
||||
"proof_mode",
|
||||
"signature",
|
||||
"canonical_hydration",
|
||||
"core_extraction",
|
||||
"decode_replay",
|
||||
"materialization",
|
||||
"second_replay"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "mainnet_observation_corpus",
|
||||
"environment": "mainnet_observation",
|
||||
"status": "not_run",
|
||||
"requiredEvidence": [
|
||||
"signatures",
|
||||
"outer_cpi",
|
||||
"success_failure"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "postgres_double_replay",
|
||||
"environment": "postgres",
|
||||
"status": "not_run",
|
||||
"requiredEvidence": [
|
||||
"postgres_tests",
|
||||
"first_replay",
|
||||
"second_replay",
|
||||
"no_duplicates"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "tauri_smoke",
|
||||
"environment": "tauri",
|
||||
"status": "not_run",
|
||||
"requiredEvidence": [
|
||||
"startup",
|
||||
"routes",
|
||||
"journal"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
1440
olddocs/archivekbot2/docs/SPL_TOKEN_MATRIX.json
Normal file
1440
olddocs/archivekbot2/docs/SPL_TOKEN_MATRIX.json
Normal file
File diff suppressed because it is too large
Load Diff
109
olddocs/archivekbot2/docs/SQL_DEMOS.md
Normal file
109
olddocs/archivekbot2/docs/SQL_DEMOS.md
Normal file
@@ -0,0 +1,109 @@
|
||||
<!-- 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 d’acquisition. |
|
||||
| `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 d’ouvrir 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 l’exploration 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 n’est 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` lorsqu’il existe, le nombre de transactions distinctes, d’instructions outer, d’instructions 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 ». Lorsqu’aucune ligne n’est cochée, l’action 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 l’extension 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 l’export 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`. L’export 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` n’est donc pas un échec de l’extracteur. Le tri DataTables utilise un rang numérique distinct pour ces trois états.
|
||||
|
||||
### Pools et paires
|
||||
|
||||
Aucun onglet pool/pair n’est 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 ; l’onglet 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 l’absence de lignes filles orphelines ;
|
||||
- vérifier l’unicité 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 à l’emploi sont dans `sql/validation/000_core_integrity.sql`.
|
||||
272
olddocs/archivekbot2/docs/SURFACE_CRATE_MATRIX.md
Normal file
272
olddocs/archivekbot2/docs/SURFACE_CRATE_MATRIX.md
Normal file
@@ -0,0 +1,272 @@
|
||||
<!-- file: docs/SURFACE_CRATE_MATRIX.md -->
|
||||
<!-- version: 4 -->
|
||||
|
||||
# Matrice des crates 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 l’exé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_token_2022` | `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
|
||||
|
||||
| Crate |
|
||||
|---------------------------------------|
|
||||
| `kb_materializer_admin` |
|
||||
| `kb_materializer_bridge` |
|
||||
| `kb_materializer_compliance_audit` |
|
||||
| `kb_materializer_fees` |
|
||||
| `kb_materializer_governance` |
|
||||
| `kb_materializer_lending` |
|
||||
| `kb_materializer_lifecycle` |
|
||||
| `kb_materializer_liquidity` |
|
||||
| `kb_materializer_metadata` |
|
||||
| `kb_materializer_nft` |
|
||||
| `kb_materializer_oracle` |
|
||||
| `kb_materializer_orderbook` |
|
||||
| `kb_materializer_perpetuals` |
|
||||
| `kb_materializer_pool_state` |
|
||||
| `kb_materializer_rewards` |
|
||||
| `kb_materializer_risk` |
|
||||
| `kb_materializer_routing` |
|
||||
| `kb_materializer_staking` |
|
||||
| `kb_materializer_token_accounts` |
|
||||
| `kb_materializer_token_metadata_risk` |
|
||||
| `kb_materializer_trades` |
|
||||
| `kb_materializer_vault` |
|
||||
168
olddocs/archivekbot2/docs/TRACING_CONTRACT.md
Normal file
168
olddocs/archivekbot2/docs/TRACING_CONTRACT.md
Normal file
@@ -0,0 +1,168 @@
|
||||
<!-- file: docs/TRACING_CONTRACT.md -->
|
||||
<!-- version: 12 -->
|
||||
|
||||
# Contrat de tracing par crate
|
||||
|
||||
## 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 d’orchestration ; il ne recopie pas les décisions internes du RPC, du pipeline, du store, d’un décodeur, d’un matérialiseur ou d’un exécuteur.
|
||||
|
||||
## Classification des crates
|
||||
|
||||
Une crate est opérationnelle lorsqu’elle 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 d’un plan d’exé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 l’installation du subscriber.
|
||||
|
||||
## Cible canonique
|
||||
|
||||
Toute crate 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 ;
|
||||
- appeler les macros avec `target: crate::constants::TRACING_TARGET` ;
|
||||
- déplacer la granularité interne dans des champs structurés.
|
||||
|
||||
Exemple :
|
||||
|
||||
```rust
|
||||
tracing::error!(
|
||||
target: crate::constants::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.*`, les targets suffixés par module et les targets de fenêtre ne sont plus utilisés par les crates opérationnelles migrées. Les identifiants frontend historiques restent acceptés comme valeurs du champ `frontend_target`, mais l’événement Rust est émis sous `kb_app_demo`.
|
||||
|
||||
## Crates actuellement routées
|
||||
|
||||
La configuration couvre toutes les crates qui déclarent actuellement `tracing.workspace = true` :
|
||||
|
||||
```text
|
||||
kb_app_demo
|
||||
kb_decoder_solana_core
|
||||
kb_decoder_spl_associated_token_account
|
||||
kb_decoder_spl_memo
|
||||
kb_decoder_spl_token
|
||||
kb_decoder_spl_token_2022
|
||||
kb_executor_metadata_spl_name_service
|
||||
kb_execution_solana
|
||||
kb_executor_solana_core
|
||||
kb_executor_spl_account_compression
|
||||
kb_executor_spl_associated_token_account
|
||||
kb_executor_spl_memo
|
||||
kb_executor_spl_noop
|
||||
kb_executor_spl_single_pool
|
||||
kb_logging
|
||||
kb_materializer_admin
|
||||
kb_materializer_compliance_audit
|
||||
kb_materializer_lifecycle
|
||||
kb_materializer_staking
|
||||
kb_materializer_transaction_annotations
|
||||
kb_pipeline
|
||||
kb_rpc
|
||||
kb_store_pg
|
||||
kb_wallet
|
||||
```
|
||||
|
||||
Le test `every_tracing_crate_has_one_canonical_target_constant` détecte automatiquement toute crate avec `tracing.workspace = true` et vérifie la présence d’une unique constante canonique. Le test de `kb_config` vérifie parallèlement la matrice de routes de chaque profil.
|
||||
|
||||
Les routes sont filtrées au niveau de leur writer plutôt que par un `Filtered` layer distinct. Un seul filtre d’admission 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 l’action 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 d’input 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 l’input et la cause. Il conserve, lorsque disponibles, la campagne, la signature, le slot, le chemin d’instruction, le program ID, l’identité et la version du processor, la clé/hash d’input, 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 l’opérateur.
|
||||
|
||||
Ils sont journalisés en `debug`, `info` ou `warn` selon leur impact.
|
||||
|
||||
## Responsabilité
|
||||
|
||||
- `kb_rpc` : sélection d’endpoint, requêtes, réponses bornées, retry, rate limit et transport.
|
||||
- `kb_execution_solana` : assemblage du message, contrôle du contrat de signataires, liaison de simulation et signature transactionnelle.
|
||||
- `kb_store_pg` : 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 l’audit du payload est nécessaire.
|
||||
|
||||
## Évolution
|
||||
|
||||
L’ajout 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.
|
||||
137
olddocs/archivekbot2/docs/TRANSACTION_ACQUISITION_MODEL.md
Normal file
137
olddocs/archivekbot2/docs/TRANSACTION_ACQUISITION_MODEL.md
Normal file
@@ -0,0 +1,137 @@
|
||||
<!-- file: docs/TRANSACTION_ACQUISITION_MODEL.md -->
|
||||
<!-- version: 5 -->
|
||||
|
||||
# Modèle d’acquisition 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_rpc
|
||||
|
|
||||
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 d’instruction 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 d’un hash SHA-256 sur le document compact. Les tableaux conservent l’ordre Solana d’origine. Les détails de source, timestamps locaux et identifiants de subscription sont exclus du document hashé.
|
||||
|
||||
L’adaptateur HTTP standard demande `encoding = json`, puis convertit explicitement les payloads d’instruction 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 l’observation |
|
||||
| `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` n’est plus une cible durable.
|
||||
|
||||
Une notification `logsSubscribe` peut être conservée temporairement en mémoire jusqu’à l’hydratation 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 l’hydratation ;
|
||||
- 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 l’observation 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 d’un 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_rpc` 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 d’acquisition.
|
||||
|
||||
66
olddocs/archivekbot2/docs/V0_4_6_VALIDATION.md
Normal file
66
olddocs/archivekbot2/docs/V0_4_6_VALIDATION.md
Normal file
@@ -0,0 +1,66 @@
|
||||
<!-- 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 d’identité.
|
||||
|
||||
## 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 n’est 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 à l’offset 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
|
||||
```
|
||||
|
||||
L’instruction 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.
|
||||
30
olddocs/archivekbot2/docs/VERSION_HEADER_AUDIT.md
Normal file
30
olddocs/archivekbot2/docs/VERSION_HEADER_AUDIT.md
Normal file
@@ -0,0 +1,30 @@
|
||||
<!-- 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
|
||||
```
|
||||
69
olddocs/archivekbot2/docs/WS_LISTENERS.md
Normal file
69
olddocs/archivekbot2/docs/WS_LISTENERS.md
Normal file
@@ -0,0 +1,69 @@
|
||||
<!-- 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
|
||||
```
|
||||
|
||||
L’audit confirme encore l’absence 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 lorsqu’une transaction canonique existe.
|
||||
|
||||
## Cas d’usage
|
||||
|
||||
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.
|
||||
|
||||
8
olddocs/archivekbot2/idls/001.README.md
Normal file
8
olddocs/archivekbot2/idls/001.README.md
Normal file
@@ -0,0 +1,8 @@
|
||||
<!-- file: idls/001.README.md -->
|
||||
<!-- version: 1 -->
|
||||
|
||||
# IDL locales
|
||||
|
||||
Ce répertoire contient les IDL locales utilisées comme sources de connaissance pour les décodeurs.
|
||||
|
||||
Les fichiers JSON ne doivent pas être modifiés pour ajouter des commentaires, car le format JSON standard ne les supporte pas.
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user