This commit is contained in:
2026-05-19 11:48:32 +02:00
parent 3da01156a0
commit fad7ec5107
19 changed files with 218 additions and 64 deletions

View File

@@ -69,4 +69,4 @@
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.
0.7.38 - Priorisation des metadata manquantes : ajout du profil `0.7.38_token_metadata_gap_prioritization`, samples `tokenMetadataGapSamples`, priorités tradable/quote/catalog, raccordement UI Demo Pipeline 2 et maintien du caractère non bloquant des metadata incomplètes.
0.7.39 - Tranche sûre launch surfaces : ensemencement contrôlé des origins LaunchLab/Launchpad/LetsBonk/Bonk.fun/Bags/Moonshot/Moonit/Boop.fun/Believe, Heaven préparé mais désactivé, mappings génériques vérifiés, samples diagnostics `launchOriginSamples` / `poolOriginSamples`, profil `0.7.39_launch_surface_origin_baseline`, raccordement Demo Pipeline 2 et maintien de linvariant sans faux trade/candle ni program id fictif.
0.7.39 - Réorientation DEX-first : ajout du rôle stratégique `surfaceRole` dans la matrice DEX (`dex_effective`, `aggregator_router`, `launch_surface`, `to_verify`), profil `0.7.39_dex_first_effective_swap_surfaces`, ajout de `metaDAO` et `Printr` comme entrées `to_verify` sans `program_id`, maintien des launch surfaces en état différé et des invariants sans faux trade/candle ni program id fictif.

View File

@@ -114,7 +114,7 @@ La distinction de travail à partir de `0.7.39` est la suivante :
### 4.1. Matrice de travail
Depuis `0.7.29`, la matrice de support DEX est portée par `kb_lib/src/dex_support_matrix.rs`. Elle centralise le code interne, la famille, la version, le type de surface, les program ids vérifiés localement, le statut de support, les capacités actuelles et les raisons de skip.
Depuis `0.7.29`, la matrice de support DEX est portée par `kb_lib/src/dex_support_matrix.rs`. Elle centralise le code interne, la famille, la version, le type technique de surface, le rôle stratégique de surface (`dex_effective`, `aggregator_router`, `launch_surface`, `to_verify`), les program ids vérifiés localement, le statut de support, les capacités actuelles et les raisons de skip.
Depuis `0.7.30`, les événements décodés reçoivent aussi une classification plus fine : `eventLifecycleKind`, `eventActionability` et `nonTradeUseful`. Cette classification sert aux diagnostics et prépare la matérialisation future des événements non-trade sans alimenter directement les trades/candles.

View File

@@ -787,7 +787,7 @@ Contraintes :
Réalisé :
- ajouter `kb_lib/src/dex_support_matrix.rs` comme source commune de metadata DEX/surfaces ;
- exposer pour chaque entrée : code interne, famille, version, type de surface, program id connu ou à vérifier, support actuel, statut, confiance, raisons de skip et activation catalogue ;
- exposer pour chaque entrée : code interne, famille, version, type technique de surface, rôle stratégique de surface, program id connu ou à vérifier, support actuel, statut, confiance, raisons de skip et activation catalogue ;
- raccorder `dex_catalog`, `transaction_classification` et `protocol_candidate_recording` à cette matrice ;
- ajouter le profil `0.7.29_multi_dex_matrix_baseline` ;
- exposer la matrice dans le rapport de validation local ;
@@ -947,9 +947,9 @@ Décision : `0.7.38` est clos. La clôture `0.7.38-B` conserve la logique de sta
### 6.071. Version `0.7.39` — Réorientation DEX-first et inventaire des DEX effectifs
Objectif : remplacer la priorité précédemment donnée aux launch surfaces par une consolidation des vrais DEX sur lesquels les swaps et événements de marché sont exécutés.
À faire :
Réalisé :
- modifier la matrice DEX pour distinguer explicitement : `dex_effective`, `aggregator/router`, `launch_surface`, `to_verify` ;
- modifier la matrice DEX pour distinguer explicitement les rôles `dex_effective`, `aggregator_router`, `launch_surface`, `to_verify` ;
- vérifier les DEX de swap principaux déjà connus : `pump_swap`, `raydium_cpmm`, `raydium_clmm`, `raydium_amm_v4`, `raydium_stable_swap`, `meteora_dlmm`, `meteora_damm_v1`, `meteora_damm_v2`, `meteora_dbc`, `orca_whirlpools`, `fluxbeam`, `dexlab` ;
- ajouter `metaDAO` et `Printr` comme entrées `to_verify` dans la matrice, sans `program_id` tant quils ne sont pas prouvés ;
- rechercher ou confirmer les `program_id` inconnus depuis les corpus locaux, les protocol candidates, DEX Screener, les explorateurs et les transactions résolues ;

View File

@@ -166,7 +166,7 @@
<div class="mb-3">
<label for="demoPipeline2ValidationProfileSelect" class="form-label">Validation profile</label>
<select id="demoPipeline2ValidationProfileSelect" class="form-select">
<option value="0.7.39_launch_surface_origin_baseline" selected>0.7.39 — launch surface origin baseline</option>
<option value="0.7.39_dex_first_effective_swap_surfaces" selected>0.7.39 — DEX-first effective swap surfaces</option>
<option value="0.7.38_token_metadata_gap_prioritization">0.7.38 — token metadata gap prioritization</option>
<option value="0.7.37_token_metadata_catalog_enrichment">0.7.37 — token metadata/catalog enrichment</option>
<option value="0.7.36_meteora_family_consolidation">0.7.36 — Meteora family consolidation</option>

View File

@@ -21,9 +21,13 @@ family: string,
*/
version: string,
/**
* Surface type: launch, bonding curve, AMM, CLMM, DLMM, router, aggregator or unknown.
* Technical surface type: launch, bonding curve, AMM, CLMM, DLMM, router, aggregator or unknown.
*/
surfaceType: string,
/**
* Strategic surface role: dex_effective, aggregator_router, launch_surface or to_verify.
*/
surfaceRole: string,
/**
* Primary Solana program id, when verified in local constants or docs.
*/

View File

@@ -225,8 +225,10 @@ pub(crate) struct DemoPipeline2DexSupportMatrixEntry {
pub family: std::string::String,
/// Protocol version or `unknown` when not verified locally.
pub version: std::string::String,
/// Surface type: launch, bonding curve, AMM, CLMM, DLMM, router, aggregator or unknown.
/// Technical surface type: launch, bonding curve, AMM, CLMM, DLMM, router, aggregator or unknown.
pub surface_type: std::string::String,
/// Strategic surface role: dex_effective, aggregator_router, launch_surface or to_verify.
pub surface_role: std::string::String,
/// Primary Solana program id, when verified in local constants or docs.
pub program_id: std::option::Option<std::string::String>,
/// Optional router program id, when this entry uses a distinct router.
@@ -1263,7 +1265,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.39_launch_surface_origin_baseline".to_string(),
None => "0.7.39_dex_first_effective_swap_surfaces".to_string(),
};
let run_result = match profile_code.as_str() {
"0.7.27" | "0.7.27_dexes_non_regression" => {
@@ -1302,7 +1304,7 @@ pub(crate) async fn demo_pipeline2_validate_local_pipeline(
"0.7.38" | "0.7.38_token_metadata_gap_prioritization" => {
service.validate_v0_7_38_current_database().await
},
"0.7.39" | "0.7.39_launch_surface_origin_baseline" => {
"0.7.39" | "0.7.39_dex_first_effective_swap_surfaces" | "0.7.39_launch_surface_origin_baseline" => {
service.validate_v0_7_39_current_database().await
},
other => Err(kb_lib::Error::InvalidState(format!(
@@ -1762,6 +1764,7 @@ fn demo_pipeline2_map_dex_support_matrix_entry(
family: entry.family,
version: entry.version,
surface_type: entry.surface_type,
surface_role: entry.surface_role,
program_id: entry.program_id,
router_program_id: entry.router_program_id,
program_id_status: entry.program_id_status,

View File

@@ -186,16 +186,16 @@ mod tests {
.expect("database init must succeed");
let dex_id = crate::query_dexs_upsert(
&database,
&crate::DexDto::new("raydium".to_string(), "Raydium".to_string(), None, None, true),
&crate::DexDto::new("raydium_amm_v4".to_string(), "Raydium AMM v4".to_string(), None, None, true),
)
.await
.expect("dex upsert must succeed");
assert!(dex_id > 0);
let dex = crate::query_dexs_get_by_code(&database, "raydium")
let dex = crate::query_dexs_get_by_code(&database, "raydium_amm_v4")
.await
.expect("get dex must succeed");
assert!(dex.is_some());
assert_eq!(dex.expect("dex must exist").name, "Raydium");
assert_eq!(dex.expect("dex must exist").name, "Raydium AMM v4");
let dexes = crate::query_dexs_list(&database).await.expect("list dexes must succeed");
assert_eq!(dexes.len(), 1);
}

View File

@@ -225,7 +225,7 @@ mod tests {
.expect("database init must succeed");
let dex_id = crate::query_dexs_upsert(
&database,
&crate::DexDto::new("raydium".to_string(), "Raydium".to_string(), None, None, true),
&crate::DexDto::new("raydium_amm_v4".to_string(), "Raydium AMM v4".to_string(), None, None, true),
)
.await
.expect("dex upsert must succeed");

View File

@@ -181,7 +181,7 @@ mod tests {
.expect("database init must succeed");
let dex_id = crate::query_dexs_upsert(
&database,
&crate::DexDto::new("raydium".to_string(), "Raydium".to_string(), None, None, true),
&crate::DexDto::new("raydium_amm_v4".to_string(), "Raydium AMM v4".to_string(), None, None, true),
)
.await
.expect("dex upsert must succeed");

View File

@@ -202,7 +202,7 @@ mod tests {
.expect("database init must succeed");
let dex_id = crate::query_dexs_upsert(
&database,
&crate::DexDto::new("raydium".to_string(), "Raydium".to_string(), None, None, true),
&crate::DexDto::new("raydium_amm_v4".to_string(), "Raydium AMM v4".to_string(), None, None, true),
)
.await
.expect("dex upsert must succeed");

View File

@@ -140,7 +140,7 @@ mod tests {
.expect("database init must succeed");
let dex_id = crate::query_dexs_upsert(
&database,
&crate::DexDto::new("raydium".to_string(), "Raydium".to_string(), None, None, true),
&crate::DexDto::new("raydium_amm_v4".to_string(), "Raydium AMM v4".to_string(), None, None, true),
)
.await
.expect("dex upsert must succeed");

View File

@@ -167,7 +167,7 @@ mod tests {
.expect("database init must succeed");
let dex_id = crate::query_dexs_upsert(
&database,
&crate::DexDto::new("raydium".to_string(), "Raydium".to_string(), None, None, true),
&crate::DexDto::new("raydium_amm_v4".to_string(), "Raydium AMM v4".to_string(), None, None, true),
)
.await
.expect("dex upsert must succeed");

View File

@@ -353,8 +353,8 @@ mod tests {
let dex_id = crate::query_dexs_upsert(
service.database().as_ref(),
&crate::DexDto::new(
"raydium".to_string(),
"Raydium".to_string(),
"raydium_amm_v4".to_string(),
"Raydium AMM v4".to_string(),
Some("DexProgram111111111111111111111111111111111".to_string()),
None,
true,

View File

@@ -1009,8 +1009,8 @@ mod tests {
let dex_id = crate::query_dexs_upsert(
persistence.database().as_ref(),
&crate::DexDto::new(
"raydium".to_string(),
"Raydium".to_string(),
"raydium_amm_v4".to_string(),
"Raydium AMM v4".to_string(),
Some("DexProgram111111111111111111111111111111111".to_string()),
None,
true,

View File

@@ -92,7 +92,7 @@ mod tests {
#[test]
fn known_active_dexes_are_available_from_catalog() {
let codes = [
"raydium",
"raydium_amm_v4",
"raydium_cpmm",
"raydium_clmm",
"pump_fun",

View File

@@ -149,7 +149,7 @@ impl DexDetectService {
decoded_event: &crate::DexDecodedEventDto,
) -> Result<crate::DexPoolDetectionResult, crate::Error> {
let dex_id_result =
crate::dex_catalog::ensure_known_dex(self.database.as_ref(), "raydium").await;
crate::dex_catalog::ensure_known_dex(self.database.as_ref(), "raydium_amm_v4").await;
let dex_id = match dex_id_result {
Ok(dex_id) => dex_id,
Err(error) => return Err(error),

View File

@@ -19,8 +19,10 @@ pub struct DexSupportMatrixEntry {
pub family: &'static str,
/// Protocol version or `unknown` when not verified locally.
pub version: &'static str,
/// Surface type: `launch`, `bonding_curve`, `AMM`, `CLMM`, `DLMM`, `router`, `aggregator` or `unknown`.
/// Technical surface type: `launch`, `bonding_curve`, `AMM`, `CLMM`, `DLMM`, `router`, `aggregator` or `unknown`.
pub surface_type: &'static str,
/// Strategic surface role used by the DEX-first roadmap: `dex_effective`, `aggregator_router`, `launch_surface` or `to_verify`.
pub surface_role: &'static str,
/// Primary Solana program id, when verified in local constants or docs.
pub program_id: std::option::Option<&'static str>,
/// Optional router program id, when this entry uses a distinct router.
@@ -63,8 +65,10 @@ pub struct DexSupportMatrixEntryDto {
pub family: std::string::String,
/// Protocol version or `unknown` when not verified locally.
pub version: std::string::String,
/// Surface type: `launch`, `bonding_curve`, `AMM`, `CLMM`, `DLMM`, `router`, `aggregator` or `unknown`.
/// Technical surface type: `launch`, `bonding_curve`, `AMM`, `CLMM`, `DLMM`, `router`, `aggregator` or `unknown`.
pub surface_type: std::string::String,
/// Strategic surface role used by the DEX-first roadmap: `dex_effective`, `aggregator_router`, `launch_surface` or `to_verify`.
pub surface_role: std::string::String,
/// Primary Solana program id, when verified in local constants or docs.
pub program_id: std::option::Option<std::string::String>,
/// Optional router program id, when this entry uses a distinct router.
@@ -104,6 +108,7 @@ impl DexSupportMatrixEntryDto {
family: entry.family.to_string(),
version: entry.version.to_string(),
surface_type: entry.surface_type.to_string(),
surface_role: entry.surface_role.to_string(),
program_id: match entry.program_id {
Some(program_id) => Some(program_id.to_string()),
None => None,
@@ -138,6 +143,7 @@ const DEX_SUPPORT_MATRIX_ENTRIES: &[DexSupportMatrixEntry] = &[
family: "pump",
version: "bonding_curve",
surface_type: "launch",
surface_role: "launch_surface",
program_id: Some(crate::PUMP_FUN_PROGRAM_ID),
router_program_id: None,
program_id_status: "known",
@@ -159,6 +165,7 @@ const DEX_SUPPORT_MATRIX_ENTRIES: &[DexSupportMatrixEntry] = &[
family: "pump",
version: "amm",
surface_type: "AMM",
surface_role: "dex_effective",
program_id: Some(crate::PUMP_SWAP_PROGRAM_ID),
router_program_id: None,
program_id_status: "known",
@@ -180,6 +187,7 @@ const DEX_SUPPORT_MATRIX_ENTRIES: &[DexSupportMatrixEntry] = &[
family: "raydium",
version: "cpmm",
surface_type: "AMM",
surface_role: "dex_effective",
program_id: Some(crate::RAYDIUM_CPMM_PROGRAM_ID),
router_program_id: None,
program_id_status: "known",
@@ -201,6 +209,7 @@ const DEX_SUPPORT_MATRIX_ENTRIES: &[DexSupportMatrixEntry] = &[
family: "raydium",
version: "clmm",
surface_type: "CLMM",
surface_role: "dex_effective",
program_id: Some(crate::RAYDIUM_CLMM_PROGRAM_ID),
router_program_id: None,
program_id_status: "known",
@@ -222,6 +231,7 @@ const DEX_SUPPORT_MATRIX_ENTRIES: &[DexSupportMatrixEntry] = &[
family: "raydium",
version: "amm_v4",
surface_type: "AMM",
surface_role: "dex_effective",
program_id: Some(crate::RAYDIUM_AMM_V4_PROGRAM_ID),
router_program_id: None,
program_id_status: "known",
@@ -237,33 +247,13 @@ const DEX_SUPPORT_MATRIX_ENTRIES: &[DexSupportMatrixEntry] = &[
skip_reason: Some("not_observed_in_0_7_28_replay"),
catalog_enabled: true,
},
DexSupportMatrixEntry {
code: "raydium",
display_name: "Raydium AMM v4",
family: "raydium",
version: "amm_v4_alias",
surface_type: "AMM",
program_id: Some(crate::RAYDIUM_AMM_V4_PROGRAM_ID),
router_program_id: None,
program_id_status: "known",
observed: false,
decoded: true,
materialized: true,
trade_candidate: true,
candle_candidate: true,
pair_candidate: true,
pool_candidate: true,
status: "partial",
confidence: "medium",
skip_reason: Some("legacy_catalog_alias_for_raydium_amm_v4"),
catalog_enabled: true,
},
DexSupportMatrixEntry {
code: "raydium_launchlab",
display_name: "Raydium LaunchLab",
family: "raydium",
version: "launchlab",
surface_type: "launch",
surface_role: "launch_surface",
program_id: Some(crate::RAYDIUM_LAUNCHLAB_PROGRAM_ID),
router_program_id: None,
program_id_status: "known",
@@ -285,6 +275,7 @@ const DEX_SUPPORT_MATRIX_ENTRIES: &[DexSupportMatrixEntry] = &[
family: "raydium",
version: "unknown",
surface_type: "launch",
surface_role: "launch_surface",
program_id: None,
router_program_id: None,
program_id_status: "to_verify",
@@ -306,6 +297,7 @@ const DEX_SUPPORT_MATRIX_ENTRIES: &[DexSupportMatrixEntry] = &[
family: "raydium",
version: "router",
surface_type: "router",
surface_role: "aggregator_router",
program_id: Some(crate::RAYDIUM_AMM_ROUTING_PROGRAM_ID),
router_program_id: None,
program_id_status: "known",
@@ -327,6 +319,7 @@ const DEX_SUPPORT_MATRIX_ENTRIES: &[DexSupportMatrixEntry] = &[
family: "raydium",
version: "stable_swap",
surface_type: "AMM",
surface_role: "dex_effective",
program_id: Some(crate::RAYDIUM_STABLE_SWAP_AMM_PROGRAM_ID),
router_program_id: None,
program_id_status: "known",
@@ -348,6 +341,7 @@ const DEX_SUPPORT_MATRIX_ENTRIES: &[DexSupportMatrixEntry] = &[
family: "meteora",
version: "dlmm",
surface_type: "DLMM",
surface_role: "dex_effective",
program_id: Some(crate::METEORA_DLMM_PROGRAM_ID),
router_program_id: None,
program_id_status: "known",
@@ -369,6 +363,7 @@ const DEX_SUPPORT_MATRIX_ENTRIES: &[DexSupportMatrixEntry] = &[
family: "meteora",
version: "unknown",
surface_type: "unknown",
surface_role: "to_verify",
program_id: None,
router_program_id: None,
program_id_status: "to_verify",
@@ -390,6 +385,7 @@ const DEX_SUPPORT_MATRIX_ENTRIES: &[DexSupportMatrixEntry] = &[
family: "meteora",
version: "damm_v1",
surface_type: "AMM",
surface_role: "dex_effective",
program_id: Some(crate::METEORA_DAMM_V1_PROGRAM_ID),
router_program_id: None,
program_id_status: "known",
@@ -411,6 +407,7 @@ const DEX_SUPPORT_MATRIX_ENTRIES: &[DexSupportMatrixEntry] = &[
family: "meteora",
version: "damm_v2",
surface_type: "AMM",
surface_role: "dex_effective",
program_id: Some(crate::METEORA_DAMM_V2_PROGRAM_ID),
router_program_id: None,
program_id_status: "known",
@@ -432,6 +429,7 @@ const DEX_SUPPORT_MATRIX_ENTRIES: &[DexSupportMatrixEntry] = &[
family: "meteora",
version: "dbc",
surface_type: "bonding_curve",
surface_role: "dex_effective",
program_id: Some(crate::METEORA_DBC_PROGRAM_ID),
router_program_id: None,
program_id_status: "known",
@@ -453,6 +451,7 @@ const DEX_SUPPORT_MATRIX_ENTRIES: &[DexSupportMatrixEntry] = &[
family: "orca",
version: "whirlpools",
surface_type: "CLMM",
surface_role: "dex_effective",
program_id: Some(crate::ORCA_WHIRLPOOLS_PROGRAM_ID),
router_program_id: None,
program_id_status: "known",
@@ -474,6 +473,7 @@ const DEX_SUPPORT_MATRIX_ENTRIES: &[DexSupportMatrixEntry] = &[
family: "fluxbeam",
version: "unknown",
surface_type: "AMM",
surface_role: "dex_effective",
program_id: Some(crate::FLUXBEAM_PROGRAM_ID),
router_program_id: None,
program_id_status: "known",
@@ -495,6 +495,7 @@ const DEX_SUPPORT_MATRIX_ENTRIES: &[DexSupportMatrixEntry] = &[
family: "dexlab",
version: "unknown",
surface_type: "AMM",
surface_role: "dex_effective",
program_id: Some(crate::DEXLAB_PROGRAM_ID),
router_program_id: None,
program_id_status: "known",
@@ -516,6 +517,7 @@ const DEX_SUPPORT_MATRIX_ENTRIES: &[DexSupportMatrixEntry] = &[
family: "bags",
version: "unknown",
surface_type: "launch",
surface_role: "launch_surface",
program_id: None,
router_program_id: None,
program_id_status: "unknown",
@@ -537,6 +539,7 @@ const DEX_SUPPORT_MATRIX_ENTRIES: &[DexSupportMatrixEntry] = &[
family: "bonk",
version: "unknown",
surface_type: "launch",
surface_role: "launch_surface",
program_id: None,
router_program_id: None,
program_id_status: "unknown",
@@ -558,6 +561,7 @@ const DEX_SUPPORT_MATRIX_ENTRIES: &[DexSupportMatrixEntry] = &[
family: "bonk",
version: "unknown",
surface_type: "launch",
surface_role: "launch_surface",
program_id: None,
router_program_id: None,
program_id_status: "unknown",
@@ -579,6 +583,7 @@ const DEX_SUPPORT_MATRIX_ENTRIES: &[DexSupportMatrixEntry] = &[
family: "bonk",
version: "unknown",
surface_type: "launch",
surface_role: "launch_surface",
program_id: None,
router_program_id: None,
program_id_status: "unknown",
@@ -600,6 +605,7 @@ const DEX_SUPPORT_MATRIX_ENTRIES: &[DexSupportMatrixEntry] = &[
family: "okx",
version: "unknown",
surface_type: "aggregator",
surface_role: "aggregator_router",
program_id: None,
router_program_id: None,
program_id_status: "unknown",
@@ -621,6 +627,7 @@ const DEX_SUPPORT_MATRIX_ENTRIES: &[DexSupportMatrixEntry] = &[
family: "boop",
version: "unknown",
surface_type: "launch",
surface_role: "launch_surface",
program_id: None,
router_program_id: None,
program_id_status: "unknown",
@@ -642,6 +649,7 @@ const DEX_SUPPORT_MATRIX_ENTRIES: &[DexSupportMatrixEntry] = &[
family: "moonshot",
version: "unknown",
surface_type: "launch",
surface_role: "launch_surface",
program_id: None,
router_program_id: None,
program_id_status: "unknown",
@@ -663,6 +671,7 @@ const DEX_SUPPORT_MATRIX_ENTRIES: &[DexSupportMatrixEntry] = &[
family: "believe",
version: "unknown",
surface_type: "launch",
surface_role: "launch_surface",
program_id: None,
router_program_id: None,
program_id_status: "unknown",
@@ -678,12 +687,57 @@ const DEX_SUPPORT_MATRIX_ENTRIES: &[DexSupportMatrixEntry] = &[
skip_reason: Some("program_id_to_verify"),
catalog_enabled: false,
},
DexSupportMatrixEntry {
code: "metadao",
display_name: "metaDAO",
family: "metadao",
version: "unknown",
surface_type: "unknown",
surface_role: "to_verify",
program_id: None,
router_program_id: None,
program_id_status: "to_verify",
observed: false,
decoded: false,
materialized: false,
trade_candidate: false,
candle_candidate: false,
pair_candidate: false,
pool_candidate: false,
status: "to_verify",
confidence: "low",
skip_reason: Some("surface_and_program_id_to_verify"),
catalog_enabled: false,
},
DexSupportMatrixEntry {
code: "printr",
display_name: "Printr",
family: "printr",
version: "unknown",
surface_type: "unknown",
surface_role: "to_verify",
program_id: None,
router_program_id: None,
program_id_status: "to_verify",
observed: false,
decoded: false,
materialized: false,
trade_candidate: false,
candle_candidate: false,
pair_candidate: false,
pool_candidate: false,
status: "to_verify",
confidence: "low",
skip_reason: Some("surface_and_program_id_to_verify"),
catalog_enabled: false,
},
DexSupportMatrixEntry {
code: "zora",
display_name: "Zora",
family: "zora",
version: "unknown",
surface_type: "unknown",
surface_role: "to_verify",
program_id: None,
router_program_id: None,
program_id_status: "to_verify",
@@ -705,6 +759,7 @@ const DEX_SUPPORT_MATRIX_ENTRIES: &[DexSupportMatrixEntry] = &[
family: "moonit",
version: "unknown",
surface_type: "launch",
surface_role: "launch_surface",
program_id: None,
router_program_id: None,
program_id_status: "unknown",
@@ -726,6 +781,7 @@ const DEX_SUPPORT_MATRIX_ENTRIES: &[DexSupportMatrixEntry] = &[
family: "launchbeam",
version: "unknown",
surface_type: "launch",
surface_role: "launch_surface",
program_id: None,
router_program_id: None,
program_id_status: "unknown",
@@ -747,6 +803,7 @@ const DEX_SUPPORT_MATRIX_ENTRIES: &[DexSupportMatrixEntry] = &[
family: "heaven",
version: "unknown",
surface_type: "launch",
surface_role: "launch_surface",
program_id: None,
router_program_id: None,
program_id_status: "unknown",
@@ -812,7 +869,7 @@ pub fn dex_support_matrix_entry_by_program_id(
#[cfg(test)]
mod tests {
#[test]
fn matrix_contains_required_0_7_29_entries() {
fn matrix_contains_required_0_7_39_dex_first_entries() {
let codes = [
"pump_fun",
"pump_swap",
@@ -837,6 +894,8 @@ mod tests {
"launchbeam",
"heaven",
"dexlab",
"metadao",
"printr",
];
for code in codes {
let entry = crate::dex_support_matrix_entry_by_code(code);
@@ -860,6 +919,8 @@ mod tests {
"moonit",
"launchbeam",
"heaven",
"metadao",
"printr",
];
for code in codes {
let entry = match crate::dex_support_matrix_entry_by_code(code) {
@@ -932,7 +993,7 @@ mod tests {
}
#[test]
fn matrix_keeps_0_7_39_launch_surfaces_non_trade_materialized() {
fn matrix_keeps_0_7_39_deferred_surfaces_non_trade_materialized() {
let codes = [
"raydium_launchlab",
"raydium_launchpad",
@@ -958,6 +1019,50 @@ mod tests {
}
}
#[test]
fn matrix_marks_effective_dexes_for_dex_first_work() {
let codes = [
"pump_swap",
"raydium_cpmm",
"raydium_clmm",
"raydium_amm_v4",
"raydium_stable_swap",
"meteora_dlmm",
"meteora_damm_v1",
"meteora_damm_v2",
"meteora_dbc",
"orca_whirlpools",
"fluxbeam",
"dexlab",
];
for code in codes {
let entry = match crate::dex_support_matrix_entry_by_code(code) {
Some(entry) => entry,
None => panic!("missing matrix entry for {}", code),
};
assert_eq!(entry.surface_role, "dex_effective", "{} must be DEX-first", code);
}
}
#[test]
fn matrix_keeps_metadao_and_printr_unverified_without_program_id() {
let codes = ["metadao", "printr"];
for code in codes {
let entry = match crate::dex_support_matrix_entry_by_code(code) {
Some(entry) => entry,
None => panic!("missing matrix entry for {}", code),
};
assert_eq!(entry.surface_role, "to_verify");
assert_eq!(entry.program_id_status, "to_verify");
assert!(entry.program_id.is_none());
assert!(!entry.decoded);
assert!(!entry.materialized);
assert!(!entry.trade_candidate);
assert!(!entry.candle_candidate);
assert!(!entry.catalog_enabled);
}
}
#[test]
fn matrix_dto_preserves_core_fields() {
let entry = match crate::dex_support_matrix_entry_by_code("pump_swap") {
@@ -967,6 +1072,7 @@ mod tests {
let dto = crate::DexSupportMatrixEntryDto::from_entry(entry);
assert_eq!(dto.code, "pump_swap");
assert_eq!(dto.program_id, Some(crate::PUMP_SWAP_PROGRAM_ID.to_string()));
assert_eq!(dto.surface_role, "dex_effective");
assert!(dto.trade_candidate);
assert!(dto.candle_candidate);
}

View File

@@ -104,7 +104,7 @@ impl LaunchOriginService {
return Self { database, persistence };
}
/// Ensures that every built-in launch surface tracked by `0.7.39` exists.
/// Ensures that every deferred built-in launch surface exists.
pub async fn ensure_target_launch_surfaces(&self) -> Result<std::vec::Vec<i64>, crate::Error> {
let mut surface_ids = std::vec::Vec::new();
for spec in BUILTIN_LAUNCH_SURFACE_SPECS {

View File

@@ -278,18 +278,26 @@ impl LocalPipelineValidationConfig {
return config;
}
/// Builds the `0.7.39` launch surface origin baseline validation config.
/// Builds the `0.7.39` DEX-first effective swap surfaces validation config.
///
/// This profile keeps the `0.7.38` metadata-gap semantics and requires the
/// static DEX matrix invariants that prevent planned launch surfaces from
/// being treated as priced trade/candle producers before corpus-backed
/// decoders are available.
pub fn v0_7_39_launch_surface_origin_baseline() -> Self {
/// static DEX matrix invariants that distinguish effective swap surfaces,
/// routers/aggregators, deferred launch surfaces and unverified candidates.
pub fn v0_7_39_dex_first_effective_swap_surfaces() -> Self {
let mut config = Self::v0_7_38_token_metadata_gap_prioritization();
config.profile_code = "0.7.39_launch_surface_origin_baseline".to_string();
config.profile_code = "0.7.39_dex_first_effective_swap_surfaces".to_string();
config.require_dex_support_matrix_semantics = true;
return config;
}
/// Builds the legacy `0.7.39` launch-surface validation alias.
///
/// The implementation now delegates to the DEX-first profile so callers that
/// still pass the previous profile code do not accidentally revive the old
/// launch-surface priority.
pub fn v0_7_39_launch_surface_origin_baseline() -> Self {
return Self::v0_7_39_dex_first_effective_swap_surfaces();
}
}
/// A single local pipeline validation issue.
@@ -519,11 +527,11 @@ impl LocalPipelineValidationService {
return self.validate_current_database(&config).await;
}
/// Diagnoses the current database with the `0.7.39` launch-origin baseline profile.
/// Diagnoses the current database with the `0.7.39` DEX-first profile.
pub async fn validate_v0_7_39_current_database(
&self,
) -> Result<crate::LocalPipelineValidationRunDto, crate::Error> {
let config = crate::LocalPipelineValidationConfig::v0_7_39_launch_surface_origin_baseline();
let config = crate::LocalPipelineValidationConfig::v0_7_39_dex_first_effective_swap_surfaces();
return self.validate_current_database(&config).await;
}
}
@@ -649,6 +657,7 @@ pub fn validate_local_pipeline_diagnostics_summary(
|| config.profile_code == "0.7.36_meteora_family_consolidation"
|| config.profile_code == "0.7.37_token_metadata_catalog_enrichment"
|| config.profile_code == "0.7.38_token_metadata_gap_prioritization"
|| config.profile_code == "0.7.39_dex_first_effective_swap_surfaces"
|| config.profile_code == "0.7.39_launch_surface_origin_baseline";
if config.require_all_expected_dexes || missing_expected_dex_is_warning {
for expected_dex_code in &expected_dex_codes {
@@ -898,16 +907,48 @@ fn validate_dex_support_matrix_semantics(
});
}
if (entry.status == "planned" || entry.status == "to_verify" || entry.status == "unknown")
&& entry.surface_type == "launch"
&& (entry.surface_role == "launch_surface" || entry.surface_role == "to_verify")
&& (entry.decoded
|| entry.materialized
|| entry.trade_candidate
|| entry.candle_candidate)
{
issues.push(crate::LocalPipelineValidationIssueDto {
code: "inactive_launch_surface_matrix_entry_actionable".to_string(),
code: "inactive_deferred_surface_matrix_entry_actionable".to_string(),
message: format!(
"inactive launch surface '{}' must not be decoded, materialized, or priced as trade/candle candidate",
"inactive deferred surface '{}' must not be decoded, materialized, or priced as trade/candle candidate",
entry_code
),
subject: Some(entry_code.clone()),
blocking: true,
});
}
if entry.surface_role == "aggregator_router"
&& (entry.trade_candidate || entry.candle_candidate || entry.catalog_enabled)
{
issues.push(crate::LocalPipelineValidationIssueDto {
code: "aggregator_router_matrix_entry_direct_trade_enabled".to_string(),
message: format!(
"aggregator/router '{}' must not be enabled as a direct trade/candle surface before proof",
entry_code
),
subject: Some(entry_code.clone()),
blocking: true,
});
}
if entry.surface_role == "to_verify"
&& (entry.program_id.is_some()
|| entry.program_id_status != "to_verify"
|| entry.catalog_enabled
|| entry.decoded
|| entry.materialized
|| entry.trade_candidate
|| entry.candle_candidate)
{
issues.push(crate::LocalPipelineValidationIssueDto {
code: "to_verify_matrix_entry_promoted_without_proof".to_string(),
message: format!(
"to-verify surface '{}' must not expose program id, catalog activation, decoding or trade/candle materialization without corpus proof",
entry_code
),
subject: Some(entry_code.clone()),
@@ -1397,12 +1438,12 @@ mod tests {
}
#[test]
fn validation_accepts_0_7_39_launch_surface_origin_baseline() {
fn validation_accepts_0_7_39_dex_first_effective_swap_surfaces() {
let summary = make_0_7_28_summary_with_meteora();
let config = crate::LocalPipelineValidationConfig::v0_7_39_launch_surface_origin_baseline();
let config = crate::LocalPipelineValidationConfig::v0_7_39_dex_first_effective_swap_surfaces();
let report = crate::validate_local_pipeline_diagnostics_summary(&summary, &config);
assert!(report.validation_passed);
assert_eq!(report.validation_profile_code, "0.7.39_launch_surface_origin_baseline");
assert_eq!(report.validation_profile_code, "0.7.39_dex_first_effective_swap_surfaces");
assert_eq!(report.blocking_issue_count, 0);
}