diff --git a/CHANGELOG.md b/CHANGELOG.md
index e13bf6b..245ca2b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -66,4 +66,5 @@
0.7.33 - Ajout de la classification diagnostique `pairTradingReadiness` pour les paires, avec `quoteAssetClass`, `tradingRouteRequired`, résumé `pairTradingReadinessSummaries`, profil de validation `0.7.33_pair_trading_readiness` et mise à jour de la sélection UI Demo Pipeline 2 sans modifier la matérialisation trade/candle.
0.7.34 - Ajout du profil `0.7.34_non_trade_liquidity_lifecycle`, matérialisation des tables non-trade liquidité/lifecycle, warning non bloquant pour DEX attendus absents du corpus local, première tranche DLMM : `add_liquidity`, `remove_liquidity`, `initialize_position`, `initialize_bin_array`, intégration de la matérialisation non-trade dans les backfills token/pool ciblés, et distinction `PositionOpen`/`PositionClose` dans `LiquidityEventKind`.
0.7.35 - Ajout du profil `0.7.35_non_trade_fee_reward_admin`, matérialisation des événements non-trade fees/rewards/admin, raccordement aux diagnostics locaux et maintien strict de l’invariant : aucun fee/reward/admin ne peut produire de trade, metric ou candle.
-0.7.36 - Consolidation de la famille Meteora : corpus mixte `meteora_damm_v1`, `meteora_damm_v2`, `meteora_dbc` et `meteora_dlmm`, correction des discriminants DAMM v2 / DBC, validation du profil `0.7.36_meteora_family_consolidation`, et reclassement explicite des swaps DAMM v2 / DBC sans payload montant/prix en `non_actionable_trade` afin d’éviter tout trade/candle artificiel.
+0.7.36 - Consolidation de la famille Meteora : corpus mixte `meteora_damm_v1`, `meteora_damm_v2`, `meteora_dbc` et `meteora_dlmm`, correction des discriminants DAMM v2 / DBC, validation du profil `0.7.36_meteora_family_consolidation`, et reclassement explicite des swaps DAMM v2 / DBC sans payload montant/prix en `non_actionable_trade` afin d’éviter tout trade/candle artificiel.
+0.7.37 - Première tranche metadata/catalog : ajout du profil `0.7.37_token_metadata_catalog_enrichment`, exposition des compteurs metadata dans diagnostics/validation et raccordement UI Demo Pipeline 2 sans rendre les metadata manquantes bloquantes.
diff --git a/Cargo.toml b/Cargo.toml
index 31c943c..dc37b69 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -8,7 +8,7 @@ members = [
]
[workspace.package]
-version = "0.7.36-D"
+version = "0.7.37"
edition = "2024"
license = "MIT"
repository = "https://git.sasedev.com/Sasedev/khadhroony-bobobot"
diff --git a/README.md b/README.md
index c44de46..9ae2a52 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@
`khadhroony-bobobot` est un workspace Rust destiné à la détection, au décodage, à l’analyse et, à terme, au trading semi-automatisé de tokens Solana.
-Le README précédent décrivait surtout l’état `0.3.1`. Ce fichier reflète l’état de reprise autour de `0.7.36` et ouvre le travail `0.7.37` : le socle transport HTTP/WS, la résolution transactionnelle, le modèle SQLite, plusieurs connecteurs DEX, les candles, les signaux analytiques, la validation locale et une matrice DEX commune existent déjà.
+Le README précédent décrivait surtout l’état `0.3.1`. Ce fichier reflète l’état de reprise autour de `0.7.37-A` : le socle transport HTTP/WS, la résolution transactionnelle, le modèle SQLite, plusieurs connecteurs DEX, les candles, les signaux analytiques, la validation locale et une matrice DEX commune existent déjà.
## 1. Objectif
@@ -31,7 +31,7 @@ Le workspace contient deux crates principales.
La logique métier doit rester dans `kb_lib`. `kb_demo_app` doit rester une façade UI/Tauri et ne doit pas récupérer de logique Solana ou DEX profonde.
-## 3. État actuel autour de `0.7.36`
+## 3. État actuel autour de `0.7.37-A`
### 3.1. Socle stabilisé à ne pas refactorer maintenant
@@ -232,7 +232,7 @@ Les tests peuvent rester plus souples lorsque cela clarifie le test.
## 8. Priorité immédiate
-La prochaine étape est `0.7.37_token_metadata_catalog_enrichment`.
+La phase actuelle est `0.7.37_token_metadata_catalog_enrichment`.
Objectif : rendre le catalogue local exploitable visuellement et analytiquement sans toucher aux invariants de décodage/trade validés en `0.7.36`.
diff --git a/ROADMAP.md b/ROADMAP.md
index 2b3949d..bc8bc9c 100644
--- a/ROADMAP.md
+++ b/ROADMAP.md
@@ -915,6 +915,13 @@ Réalisé :
### 6.069. Version `0.7.37` — Token metadata et catalogue local
Objectif : rendre le catalogue local exploitable et lisible avant d’ajouter davantage de launch surfaces.
+Réalisé en `0.7.37-A` :
+
+- ajout du profil `0.7.37_token_metadata_catalog_enrichment` ;
+- exposition des compteurs metadata/catalog dans les diagnostics et le rapport de validation ;
+- raccordement UI Demo Pipeline 2 au profil `0.7.37` ;
+- maintien volontaire du caractère non bloquant des metadata manquantes.
+
À faire :
- ajouter ou consolider un registre local des mints connus et stables : `SOL`, `WSOL`, `USDC`, `USDT`, puis autres mints seulement si vérifiés ;
@@ -1236,7 +1243,7 @@ Le projet doit maintenir au minimum :
## 12. Priorité immédiate
-La priorité immédiate est désormais `0.7.37_token_metadata_catalog_enrichment`.
+La priorité immédiate reste de terminer `0.7.37_token_metadata_catalog_enrichment` par le backfill metadata effectif et le rafraîchissement des symboles de paires.
Ordre de travail recommandé :
diff --git a/kb_demo_app/frontend/demo_pipeline2.html b/kb_demo_app/frontend/demo_pipeline2.html
index f4fc323..a245771 100644
--- a/kb_demo_app/frontend/demo_pipeline2.html
+++ b/kb_demo_app/frontend/demo_pipeline2.html
@@ -166,7 +166,8 @@
Validation profile
- 0.7.36 — Meteora family consolidation
+ 0.7.37 — token metadata/catalog enrichment
+ 0.7.36 — Meteora family consolidation
0.7.35 — non-trade fee/reward admin
0.7.34 — non-trade liquidity/lifecycle
0.7.33 — pair trading readiness
diff --git a/kb_demo_app/package.json b/kb_demo_app/package.json
index bb5e999..9c0a010 100644
--- a/kb_demo_app/package.json
+++ b/kb_demo_app/package.json
@@ -1,7 +1,7 @@
{
"name": "kb-demo-app",
"private": true,
- "version": "0.7.36",
+ "version": "0.7.37",
"type": "module",
"scripts": {
"dev": "vite",
diff --git a/kb_demo_app/src/demo_pipeline2.rs b/kb_demo_app/src/demo_pipeline2.rs
index 49430a7..9136fef 100644
--- a/kb_demo_app/src/demo_pipeline2.rs
+++ b/kb_demo_app/src/demo_pipeline2.rs
@@ -167,6 +167,39 @@ pub(crate) struct DemoPipeline2LocalPipelineValidationReport {
/// Total persisted pool lifecycle events.
#[ts(type = "number")]
pub pool_lifecycle_event_count: i64,
+ /// Total persisted fee events.
+ #[ts(type = "number")]
+ pub fee_event_count: i64,
+ /// Total persisted reward events.
+ #[ts(type = "number")]
+ pub reward_event_count: i64,
+ /// Total persisted pool administration events.
+ #[ts(type = "number")]
+ pub pool_admin_event_count: i64,
+ /// Total known tokens.
+ #[ts(type = "number")]
+ pub token_count: i64,
+ /// Total tokens missing symbol or name.
+ #[ts(type = "number")]
+ pub token_metadata_missing_count: i64,
+ /// Total tokens used by trade-materialized pairs that still miss symbol or name.
+ #[ts(type = "number")]
+ pub tradable_token_metadata_missing_count: i64,
+ /// Total quote-side tokens used by pairs that still miss symbol or name.
+ #[ts(type = "number")]
+ pub quote_token_metadata_missing_count: i64,
+ /// Total pairs whose display symbol is missing or still falls back to raw mints.
+ #[ts(type = "number")]
+ pub pair_symbol_fallback_count: i64,
+ /// Total pairs whose display symbol is present and does not include raw mints.
+ #[ts(type = "number")]
+ pub pair_symbol_resolved_count: i64,
+ /// Total pairs whose quote token is WSOL.
+ #[ts(type = "number")]
+ pub wsol_quote_pair_count: i64,
+ /// Total pairs whose quote token is a known stable quote.
+ #[ts(type = "number")]
+ pub stable_quote_pair_count: i64,
/// Number of entries currently exposed by the DEX support matrix.
#[ts(type = "number")]
pub dex_support_matrix_entry_count: i64,
@@ -283,6 +316,15 @@ pub(crate) struct DemoPipeline2LocalPipelineDiagnosticSummary {
/// Total persisted pool lifecycle events.
#[ts(type = "number")]
pub pool_lifecycle_event_count: i64,
+ /// Total persisted fee events.
+ #[ts(type = "number")]
+ pub fee_event_count: i64,
+ /// Total persisted reward events.
+ #[ts(type = "number")]
+ pub reward_event_count: i64,
+ /// Total persisted pool administration events.
+ #[ts(type = "number")]
+ pub pool_admin_event_count: i64,
/// Whether the local persisted pipeline has no blocking diagnostic issue.
pub diagnostics_clean: bool,
/// Number of blocking diagnostic issues.
@@ -333,6 +375,24 @@ pub(crate) struct DemoPipeline2LocalPipelineDiagnosticSummary {
/// Total tokens missing symbol or name.
#[ts(type = "number")]
pub token_metadata_missing_count: i64,
+ /// Total tokens used by trade-materialized pairs that still miss symbol or name.
+ #[ts(type = "number")]
+ pub tradable_token_metadata_missing_count: i64,
+ /// Total quote-side tokens used by pairs that still miss symbol or name.
+ #[ts(type = "number")]
+ pub quote_token_metadata_missing_count: i64,
+ /// Total pairs whose display symbol is missing or still falls back to raw mints.
+ #[ts(type = "number")]
+ pub pair_symbol_fallback_count: i64,
+ /// Total pairs whose display symbol is present and does not include raw mints.
+ #[ts(type = "number")]
+ pub pair_symbol_resolved_count: i64,
+ /// Total pairs whose quote token is WSOL.
+ #[ts(type = "number")]
+ pub wsol_quote_pair_count: i64,
+ /// Total pairs whose quote token is a known stable quote.
+ #[ts(type = "number")]
+ pub stable_quote_pair_count: i64,
/// Total known pools.
#[ts(type = "number")]
pub pool_count: i64,
@@ -1087,7 +1147,7 @@ pub(crate) async fn demo_pipeline2_validate_local_pipeline(
let service = kb_lib::LocalPipelineValidationService::new(database.clone());
let profile_code = match request {
Some(request) => request.profile_code,
- None => "0.7.36_meteora_family_consolidation".to_string(),
+ None => "0.7.37_token_metadata_catalog_enrichment".to_string(),
};
let run_result = match profile_code.as_str() {
"0.7.27" | "0.7.27_dexes_non_regression" => {
@@ -1120,6 +1180,9 @@ pub(crate) async fn demo_pipeline2_validate_local_pipeline(
"0.7.36" | "0.7.36_meteora_family_consolidation" => {
service.validate_v0_7_36_current_database().await
},
+ "0.7.37" | "0.7.37_token_metadata_catalog_enrichment" => {
+ service.validate_v0_7_37_current_database().await
+ },
other => Err(kb_lib::Error::InvalidState(format!(
"unsupported local pipeline validation profile: {other}"
))),
@@ -1551,6 +1614,17 @@ fn demo_pipeline2_map_local_validation_report(
decoded_unknown_event_count: report.decoded_unknown_event_count,
liquidity_event_count: report.liquidity_event_count,
pool_lifecycle_event_count: report.pool_lifecycle_event_count,
+ fee_event_count: report.fee_event_count,
+ reward_event_count: report.reward_event_count,
+ pool_admin_event_count: report.pool_admin_event_count,
+ token_count: report.token_count,
+ token_metadata_missing_count: report.token_metadata_missing_count,
+ tradable_token_metadata_missing_count: report.tradable_token_metadata_missing_count,
+ quote_token_metadata_missing_count: report.quote_token_metadata_missing_count,
+ pair_symbol_fallback_count: report.pair_symbol_fallback_count,
+ pair_symbol_resolved_count: report.pair_symbol_resolved_count,
+ wsol_quote_pair_count: report.wsol_quote_pair_count,
+ stable_quote_pair_count: report.stable_quote_pair_count,
dex_support_matrix_entry_count: report.dex_support_matrix_entry_count,
dex_support_matrix,
issues,
@@ -1679,6 +1753,9 @@ fn demo_pipeline2_map_local_diagnostics_summary(
decoded_unknown_event_count: summary.decoded_unknown_event_count,
liquidity_event_count: summary.liquidity_event_count,
pool_lifecycle_event_count: summary.pool_lifecycle_event_count,
+ fee_event_count: summary.fee_event_count,
+ reward_event_count: summary.reward_event_count,
+ pool_admin_event_count: summary.pool_admin_event_count,
diagnostics_clean: summary.diagnostics_clean,
blocking_issue_count: summary.blocking_issue_count,
missing_trade_event_count: summary.missing_trade_event_count,
@@ -1701,6 +1778,12 @@ fn demo_pipeline2_map_local_diagnostics_summary(
duplicate_candle_bucket_count: summary.duplicate_candle_bucket_count,
token_count: summary.token_count,
token_metadata_missing_count: summary.token_metadata_missing_count,
+ tradable_token_metadata_missing_count: summary.tradable_token_metadata_missing_count,
+ quote_token_metadata_missing_count: summary.quote_token_metadata_missing_count,
+ pair_symbol_fallback_count: summary.pair_symbol_fallback_count,
+ pair_symbol_resolved_count: summary.pair_symbol_resolved_count,
+ wsol_quote_pair_count: summary.wsol_quote_pair_count,
+ stable_quote_pair_count: summary.stable_quote_pair_count,
pool_count: summary.pool_count,
pair_count: summary.pair_count,
pair_gap_counter_semantics: summary.pair_gap_counter_semantics,
diff --git a/kb_demo_app/tauri.conf.json b/kb_demo_app/tauri.conf.json
index 9232519..6cbe55f 100644
--- a/kb_demo_app/tauri.conf.json
+++ b/kb_demo_app/tauri.conf.json
@@ -1,7 +1,7 @@
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "kb-demo-app",
- "version": "0.7.36",
+ "version": "0.7.37",
"identifier": "com.sasedev.kb-demo-app",
"build": {
"beforeDevCommand": "npm run dev",
diff --git a/kb_lib/src/db/dtos/local_pipeline_diagnostics.rs b/kb_lib/src/db/dtos/local_pipeline_diagnostics.rs
index 0403174..b47d38f 100644
--- a/kb_lib/src/db/dtos/local_pipeline_diagnostics.rs
+++ b/kb_lib/src/db/dtos/local_pipeline_diagnostics.rs
@@ -71,6 +71,18 @@ pub struct LocalPipelineDiagnosticSummaryDto {
pub token_count: i64,
/// Total tokens missing symbol or name.
pub token_metadata_missing_count: i64,
+ /// Total tokens used by trade-materialized pairs that still miss symbol or name.
+ pub tradable_token_metadata_missing_count: i64,
+ /// Total quote-side tokens used by pairs that still miss symbol or name.
+ pub quote_token_metadata_missing_count: i64,
+ /// Total pairs whose display symbol is missing or still falls back to raw mints.
+ pub pair_symbol_fallback_count: i64,
+ /// Total pairs whose display symbol is present and does not include raw mints.
+ pub pair_symbol_resolved_count: i64,
+ /// Total pairs whose quote token is WSOL.
+ pub wsol_quote_pair_count: i64,
+ /// Total pairs whose quote token is a known stable quote.
+ pub stable_quote_pair_count: i64,
/// Total known pools.
pub pool_count: i64,
/// Total known pairs.
@@ -413,6 +425,18 @@ pub struct LocalPipelineDiagnosticCountersDto {
pub token_count: i64,
/// Total tokens missing metadata.
pub token_metadata_missing_count: i64,
+ /// Total tokens used by trade-materialized pairs that still miss metadata.
+ pub tradable_token_metadata_missing_count: i64,
+ /// Total quote-side tokens used by pairs that still miss metadata.
+ pub quote_token_metadata_missing_count: i64,
+ /// Total pairs whose display symbol is missing or falls back to raw mints.
+ pub pair_symbol_fallback_count: i64,
+ /// Total pairs whose display symbol is resolved without raw mints.
+ pub pair_symbol_resolved_count: i64,
+ /// Total pairs whose quote token is WSOL.
+ pub wsol_quote_pair_count: i64,
+ /// Total pairs whose quote token is a known stable quote.
+ pub stable_quote_pair_count: i64,
/// Total known pools.
pub pool_count: i64,
/// Total known pairs.
@@ -473,6 +497,12 @@ pub(crate) struct LocalPipelineDiagnosticCountersRow {
pub(crate) duplicate_candle_bucket_count: i64,
pub(crate) token_count: i64,
pub(crate) token_metadata_missing_count: i64,
+ pub(crate) tradable_token_metadata_missing_count: i64,
+ pub(crate) quote_token_metadata_missing_count: i64,
+ pub(crate) pair_symbol_fallback_count: i64,
+ pub(crate) pair_symbol_resolved_count: i64,
+ pub(crate) wsol_quote_pair_count: i64,
+ pub(crate) stable_quote_pair_count: i64,
pub(crate) pool_count: i64,
pub(crate) pair_count: i64,
pub(crate) literal_pair_without_trade_count: i64,
diff --git a/kb_lib/src/db/queries/local_pipeline_diagnostics.rs b/kb_lib/src/db/queries/local_pipeline_diagnostics.rs
index 2816b78..5f69653 100644
--- a/kb_lib/src/db/queries/local_pipeline_diagnostics.rs
+++ b/kb_lib/src/db/queries/local_pipeline_diagnostics.rs
@@ -187,10 +187,75 @@ SELECT
SELECT COUNT(*)
FROM k_sol_tokens
WHERE symbol IS NULL
- OR symbol = ''
+ OR TRIM(symbol) = ''
OR name IS NULL
- OR name = ''
+ OR TRIM(name) = ''
) AS token_metadata_missing_count,
+ (
+ SELECT COUNT(DISTINCT token.id)
+ FROM k_sol_tokens token
+ JOIN (
+ SELECT pair.base_token_id AS token_id
+ FROM k_sol_pairs pair
+ JOIN k_sol_trade_events te ON te.pair_id = pair.id
+ UNION
+ SELECT pair.quote_token_id AS token_id
+ FROM k_sol_pairs pair
+ JOIN k_sol_trade_events te ON te.pair_id = pair.id
+ ) tradable_pair_token ON tradable_pair_token.token_id = token.id
+ WHERE token.symbol IS NULL
+ OR TRIM(token.symbol) = ''
+ OR token.name IS NULL
+ OR TRIM(token.name) = ''
+ ) AS tradable_token_metadata_missing_count,
+ (
+ SELECT COUNT(DISTINCT quote_token.id)
+ FROM k_sol_pairs pair
+ JOIN k_sol_tokens quote_token ON quote_token.id = pair.quote_token_id
+ WHERE quote_token.symbol IS NULL
+ OR TRIM(quote_token.symbol) = ''
+ OR quote_token.name IS NULL
+ OR TRIM(quote_token.name) = ''
+ ) AS quote_token_metadata_missing_count,
+ (
+ SELECT COUNT(*)
+ FROM k_sol_pairs pair
+ JOIN k_sol_tokens base_token ON base_token.id = pair.base_token_id
+ JOIN k_sol_tokens quote_token ON quote_token.id = pair.quote_token_id
+ WHERE pair.symbol IS NULL
+ OR TRIM(pair.symbol) = ''
+ OR pair.symbol = base_token.mint || '/' || quote_token.mint
+ OR instr(pair.symbol, base_token.mint) > 0
+ OR instr(pair.symbol, quote_token.mint) > 0
+ ) AS pair_symbol_fallback_count,
+ (
+ SELECT COUNT(*)
+ FROM k_sol_pairs pair
+ JOIN k_sol_tokens base_token ON base_token.id = pair.base_token_id
+ JOIN k_sol_tokens quote_token ON quote_token.id = pair.quote_token_id
+ WHERE pair.symbol IS NOT NULL
+ AND TRIM(pair.symbol) != ''
+ AND pair.symbol != base_token.mint || '/' || quote_token.mint
+ AND instr(pair.symbol, base_token.mint) = 0
+ AND instr(pair.symbol, quote_token.mint) = 0
+ ) AS pair_symbol_resolved_count,
+ (
+ SELECT COUNT(*)
+ FROM k_sol_pairs pair
+ JOIN k_sol_tokens quote_token ON quote_token.id = pair.quote_token_id
+ WHERE quote_token.mint = 'So11111111111111111111111111111111111111112'
+ ) AS wsol_quote_pair_count,
+ (
+ SELECT COUNT(*)
+ FROM k_sol_pairs pair
+ JOIN k_sol_tokens quote_token ON quote_token.id = pair.quote_token_id
+ WHERE quote_token.mint IN (
+ 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
+ 'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB',
+ 'USD1ttGY1N17NEEHLmELoaybftRBUSErhqYiQzvEmuB',
+ 'JuprjznTrTSp2UFa3ZBUFgwdAmtZCq4MQCwysN55USD'
+ )
+ ) AS stable_quote_pair_count,
(SELECT COUNT(*) FROM k_sol_pools) AS pool_count,
(SELECT COUNT(*) FROM k_sol_pairs) AS pair_count,
(
@@ -384,6 +449,12 @@ SELECT
duplicate_candle_bucket_count: row.duplicate_candle_bucket_count,
token_count: row.token_count,
token_metadata_missing_count: row.token_metadata_missing_count,
+ tradable_token_metadata_missing_count: row.tradable_token_metadata_missing_count,
+ quote_token_metadata_missing_count: row.quote_token_metadata_missing_count,
+ pair_symbol_fallback_count: row.pair_symbol_fallback_count,
+ pair_symbol_resolved_count: row.pair_symbol_resolved_count,
+ wsol_quote_pair_count: row.wsol_quote_pair_count,
+ stable_quote_pair_count: row.stable_quote_pair_count,
pool_count: row.pool_count,
pair_count: row.pair_count,
literal_pair_without_trade_count: row.literal_pair_without_trade_count,
diff --git a/kb_lib/src/local_pipeline_diagnostics.rs b/kb_lib/src/local_pipeline_diagnostics.rs
index b42ecbe..7f59a75 100644
--- a/kb_lib/src/local_pipeline_diagnostics.rs
+++ b/kb_lib/src/local_pipeline_diagnostics.rs
@@ -179,6 +179,12 @@ impl LocalPipelineDiagnosticsService {
duplicate_candle_bucket_count: counters.duplicate_candle_bucket_count,
token_count: counters.token_count,
token_metadata_missing_count: counters.token_metadata_missing_count,
+ tradable_token_metadata_missing_count: counters.tradable_token_metadata_missing_count,
+ quote_token_metadata_missing_count: counters.quote_token_metadata_missing_count,
+ pair_symbol_fallback_count: counters.pair_symbol_fallback_count,
+ pair_symbol_resolved_count: counters.pair_symbol_resolved_count,
+ wsol_quote_pair_count: counters.wsol_quote_pair_count,
+ stable_quote_pair_count: counters.stable_quote_pair_count,
pool_count: counters.pool_count,
pair_count: counters.pair_count,
pair_gap_counter_semantics: "blocking_actionable_pairs_only".to_string(),
diff --git a/kb_lib/src/local_pipeline_validation.rs b/kb_lib/src/local_pipeline_validation.rs
index d310df5..93a2586 100644
--- a/kb_lib/src/local_pipeline_validation.rs
+++ b/kb_lib/src/local_pipeline_validation.rs
@@ -254,6 +254,18 @@ impl LocalPipelineValidationConfig {
config.allow_unexpected_dexes = true;
return config;
}
+
+ /// Builds the `0.7.37` token metadata/catalog enrichment validation config.
+ ///
+ /// This profile keeps the `0.7.36` Meteora-family checks and exposes
+ /// token metadata and pair-symbol diagnostics. Missing metadata remains
+ /// informational in this profile; refresh/materialization invariants stay
+ /// governed by the existing trade and candle checks.
+ pub fn v0_7_37_token_metadata_catalog_enrichment() -> Self {
+ let mut config = Self::v0_7_36_meteora_family_consolidation();
+ config.profile_code = "0.7.37_token_metadata_catalog_enrichment".to_string();
+ return config;
+ }
}
/// A single local pipeline validation issue.
@@ -302,6 +314,22 @@ pub struct LocalPipelineValidationReportDto {
pub reward_event_count: i64,
/// Total persisted pool administration events.
pub pool_admin_event_count: i64,
+ /// Total known tokens.
+ pub token_count: i64,
+ /// Total tokens missing symbol or name.
+ pub token_metadata_missing_count: i64,
+ /// Total tokens used by trade-materialized pairs that still miss symbol or name.
+ pub tradable_token_metadata_missing_count: i64,
+ /// Total quote-side tokens used by pairs that still miss symbol or name.
+ pub quote_token_metadata_missing_count: i64,
+ /// Total pairs whose display symbol is missing or still falls back to raw mints.
+ pub pair_symbol_fallback_count: i64,
+ /// Total pairs whose display symbol is present and does not include raw mints.
+ pub pair_symbol_resolved_count: i64,
+ /// Total pairs whose quote token is WSOL.
+ pub wsol_quote_pair_count: i64,
+ /// Total pairs whose quote token is a known stable quote.
+ pub stable_quote_pair_count: i64,
/// Number of entries currently exposed by the DEX support matrix.
pub dex_support_matrix_entry_count: i64,
/// DEX support matrix snapshot exposed with the validation report.
@@ -448,6 +476,15 @@ impl LocalPipelineValidationService {
let config = crate::LocalPipelineValidationConfig::v0_7_36_meteora_family_consolidation();
return self.validate_current_database(&config).await;
}
+
+ /// Diagnoses the current database with the `0.7.37` metadata/catalog profile.
+ pub async fn validate_v0_7_37_current_database(
+ &self,
+ ) -> Result {
+ let config =
+ crate::LocalPipelineValidationConfig::v0_7_37_token_metadata_catalog_enrichment();
+ return self.validate_current_database(&config).await;
+ }
}
/// Validates a diagnostics summary without performing database access.
@@ -568,7 +605,8 @@ pub fn validate_local_pipeline_diagnostics_summary(
let missing_expected_dex_is_warning = config.profile_code
== "0.7.34_non_trade_liquidity_lifecycle"
|| config.profile_code == "0.7.35_non_trade_fee_reward_admin"
- || config.profile_code == "0.7.36_meteora_family_consolidation";
+ || config.profile_code == "0.7.36_meteora_family_consolidation"
+ || config.profile_code == "0.7.37_token_metadata_catalog_enrichment";
if config.require_all_expected_dexes || missing_expected_dex_is_warning {
for expected_dex_code in &expected_dex_codes {
if !observed_dex_codes.contains(expected_dex_code) {
@@ -643,6 +681,14 @@ pub fn validate_local_pipeline_diagnostics_summary(
fee_event_count: summary.fee_event_count,
reward_event_count: summary.reward_event_count,
pool_admin_event_count: summary.pool_admin_event_count,
+ token_count: summary.token_count,
+ token_metadata_missing_count: summary.token_metadata_missing_count,
+ tradable_token_metadata_missing_count: summary.tradable_token_metadata_missing_count,
+ quote_token_metadata_missing_count: summary.quote_token_metadata_missing_count,
+ pair_symbol_fallback_count: summary.pair_symbol_fallback_count,
+ pair_symbol_resolved_count: summary.pair_symbol_resolved_count,
+ wsol_quote_pair_count: summary.wsol_quote_pair_count,
+ stable_quote_pair_count: summary.stable_quote_pair_count,
dex_support_matrix_entry_count: crate::dex_support_matrix_entries().len() as i64,
dex_support_matrix: crate::dex_support_matrix_entry_dtos(),
issues,
@@ -873,6 +919,12 @@ mod tests {
duplicate_candle_bucket_count: 0,
token_count: 22,
token_metadata_missing_count: 0,
+ tradable_token_metadata_missing_count: 0,
+ quote_token_metadata_missing_count: 0,
+ pair_symbol_fallback_count: 4,
+ pair_symbol_resolved_count: 23,
+ wsol_quote_pair_count: 20,
+ stable_quote_pair_count: 3,
pool_count: 27,
pair_count: 27,
pair_gap_counter_semantics: "blocking_actionable_pairs_only".to_string(),
@@ -1221,6 +1273,33 @@ mod tests {
assert!(report.expected_dex_codes.contains(&"meteora_dlmm".to_string()));
}
+ #[test]
+ fn validation_accepts_0_7_37_metadata_catalog_summary() {
+ let mut summary = make_0_7_28_summary_with_meteora();
+ summary.token_count = 108;
+ summary.token_metadata_missing_count = 102;
+ summary.tradable_token_metadata_missing_count = 12;
+ summary.quote_token_metadata_missing_count = 4;
+ summary.pair_symbol_fallback_count = 16;
+ summary.pair_symbol_resolved_count = 5;
+ summary.wsol_quote_pair_count = 13;
+ summary.stable_quote_pair_count = 2;
+ let config =
+ crate::LocalPipelineValidationConfig::v0_7_37_token_metadata_catalog_enrichment();
+ let report = crate::validate_local_pipeline_diagnostics_summary(&summary, &config);
+ assert!(report.validation_passed);
+ assert_eq!(report.validation_profile_code, "0.7.37_token_metadata_catalog_enrichment");
+ assert_eq!(report.blocking_issue_count, 0);
+ assert_eq!(report.token_count, 108);
+ assert_eq!(report.token_metadata_missing_count, 102);
+ assert_eq!(report.tradable_token_metadata_missing_count, 12);
+ assert_eq!(report.quote_token_metadata_missing_count, 4);
+ assert_eq!(report.pair_symbol_fallback_count, 16);
+ assert_eq!(report.pair_symbol_resolved_count, 5);
+ assert_eq!(report.wsol_quote_pair_count, 13);
+ assert_eq!(report.stable_quote_pair_count, 2);
+ }
+
#[test]
fn validation_rejects_0_7_33_pair_trading_readiness_mismatch() {
let mut summary = make_0_7_28_summary_with_meteora();