This commit is contained in:
2026-05-13 13:19:23 +02:00
parent 24d21818cf
commit 693a456e62
19 changed files with 631 additions and 40 deletions

View File

@@ -555,7 +555,56 @@ SELECT
WHERE te_last.pair_id = pair.id
ORDER BY te_last.id DESC
LIMIT 1
) AS last_price_quote_per_base
) AS last_price_quote_per_base,
CASE
WHEN COUNT(DISTINCT te.id) = 0 THEN 'non_trade_materialized'
WHEN quote_token.mint = 'So11111111111111111111111111111111111111112' THEN 'direct_wsol_quote'
WHEN quote_token.mint IN (
'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB',
'USD1ttGY1N17NEEHLmELoaybftRBUSErhqYiQzvEmuB',
'JuprjznTrTSp2UFa3ZBUFgwdAmtZCq4MQCwysN55USD'
) THEN 'direct_stable_quote'
WHEN base_token.mint = 'So11111111111111111111111111111111111111112' THEN 'inverse_wsol_base'
WHEN base_token.mint IN (
'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB',
'USD1ttGY1N17NEEHLmELoaybftRBUSErhqYiQzvEmuB',
'JuprjznTrTSp2UFa3ZBUFgwdAmtZCq4MQCwysN55USD'
) THEN 'inverse_stable_base'
WHEN quote_token.mint IS NULL OR quote_token.mint = '' THEN 'unknown_quote'
ELSE 'cross_quote_requires_router'
END AS pair_trading_readiness,
CASE
WHEN quote_token.mint = 'So11111111111111111111111111111111111111112' THEN 'wsol'
WHEN quote_token.mint IN (
'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB',
'USD1ttGY1N17NEEHLmELoaybftRBUSErhqYiQzvEmuB',
'JuprjznTrTSp2UFa3ZBUFgwdAmtZCq4MQCwysN55USD'
) THEN 'stable'
WHEN quote_token.mint IS NULL OR quote_token.mint = '' THEN 'unknown'
ELSE 'other'
END AS quote_asset_class,
CASE
WHEN COUNT(DISTINCT te.id) = 0 THEN 0
WHEN quote_token.mint IS NULL OR quote_token.mint = '' THEN 1
WHEN quote_token.mint = 'So11111111111111111111111111111111111111112' THEN 0
WHEN quote_token.mint IN (
'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB',
'USD1ttGY1N17NEEHLmELoaybftRBUSErhqYiQzvEmuB',
'JuprjznTrTSp2UFa3ZBUFgwdAmtZCq4MQCwysN55USD'
) THEN 0
WHEN base_token.mint = 'So11111111111111111111111111111111111111112' THEN 0
WHEN base_token.mint IN (
'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB',
'USD1ttGY1N17NEEHLmELoaybftRBUSErhqYiQzvEmuB',
'JuprjznTrTSp2UFa3ZBUFgwdAmtZCq4MQCwysN55USD'
) THEN 0
ELSE 1
END AS trading_route_required
FROM k_sol_pairs pair
JOIN k_sol_pools p ON p.id = pair.pool_id
JOIN k_sol_dexes d ON d.id = p.dex_id
@@ -605,6 +654,9 @@ ORDER BY pair.id
invalid_trade_event_count: row.invalid_trade_event_count,
pair_candle_count: row.pair_candle_count,
last_price_quote_per_base: row.last_price_quote_per_base,
pair_trading_readiness: row.pair_trading_readiness,
quote_asset_class: row.quote_asset_class,
trading_route_required: row.trading_route_required != 0,
});
}
return Ok(summaries);
@@ -716,6 +768,146 @@ ORDER BY
return Ok(summaries);
},
}
}
/// Lists local pair trading-readiness summaries.
pub async fn query_local_pair_trading_readiness_diagnostic_list_summaries(
database: &crate::Database,
) -> Result<std::vec::Vec<crate::LocalPairTradingReadinessDiagnosticSummaryDto>, crate::Error> {
match database.connection() {
crate::DatabaseConnection::Sqlite(pool) => {
let rows_result = sqlx::query_as::<
sqlx::Sqlite,
crate::db::dtos::LocalPairTradingReadinessDiagnosticSummaryRow,
>(
r#"
WITH pair_state AS (
SELECT
pair.id AS pair_id,
base_token.mint AS base_mint,
quote_token.mint AS quote_mint,
COUNT(DISTINCT dde.id) AS decoded_event_count,
COUNT(DISTINCT CASE WHEN json_extract(dde.payload_json, '$.tradeCandidate') = 1 THEN dde.id END) AS decoded_trade_candidate_count,
COUNT(DISTINCT te.id) AS trade_event_count,
COUNT(DISTINCT pc.bucket_start_unix || ':' || pc.timeframe_seconds) AS pair_candle_count
FROM k_sol_pairs pair
JOIN k_sol_pools p ON p.id = pair.pool_id
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
LEFT JOIN k_sol_dex_decoded_events dde ON dde.pool_account = p.address
LEFT JOIN k_sol_trade_events te ON te.pair_id = pair.id
LEFT JOIN k_sol_pair_candles pc ON pc.pair_id = pair.id
GROUP BY pair.id, base_token.mint, quote_token.mint
), classified AS (
SELECT
CASE
WHEN trade_event_count = 0 THEN 'non_trade_materialized'
WHEN quote_mint = 'So11111111111111111111111111111111111111112' THEN 'direct_wsol_quote'
WHEN quote_mint IN (
'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB',
'USD1ttGY1N17NEEHLmELoaybftRBUSErhqYiQzvEmuB',
'JuprjznTrTSp2UFa3ZBUFgwdAmtZCq4MQCwysN55USD'
) THEN 'direct_stable_quote'
WHEN base_mint = 'So11111111111111111111111111111111111111112' THEN 'inverse_wsol_base'
WHEN base_mint IN (
'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB',
'USD1ttGY1N17NEEHLmELoaybftRBUSErhqYiQzvEmuB',
'JuprjznTrTSp2UFa3ZBUFgwdAmtZCq4MQCwysN55USD'
) THEN 'inverse_stable_base'
WHEN quote_mint IS NULL OR quote_mint = '' THEN 'unknown_quote'
ELSE 'cross_quote_requires_router'
END AS pair_trading_readiness,
CASE
WHEN quote_mint = 'So11111111111111111111111111111111111111112' THEN 'wsol'
WHEN quote_mint IN (
'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB',
'USD1ttGY1N17NEEHLmELoaybftRBUSErhqYiQzvEmuB',
'JuprjznTrTSp2UFa3ZBUFgwdAmtZCq4MQCwysN55USD'
) THEN 'stable'
WHEN quote_mint IS NULL OR quote_mint = '' THEN 'unknown'
ELSE 'other'
END AS quote_asset_class,
CASE
WHEN trade_event_count = 0 THEN 0
WHEN quote_mint IS NULL OR quote_mint = '' THEN 1
WHEN quote_mint = 'So11111111111111111111111111111111111111112' THEN 0
WHEN quote_mint IN (
'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB',
'USD1ttGY1N17NEEHLmELoaybftRBUSErhqYiQzvEmuB',
'JuprjznTrTSp2UFa3ZBUFgwdAmtZCq4MQCwysN55USD'
) THEN 0
WHEN base_mint = 'So11111111111111111111111111111111111111112' THEN 0
WHEN base_mint IN (
'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB',
'USD1ttGY1N17NEEHLmELoaybftRBUSErhqYiQzvEmuB',
'JuprjznTrTSp2UFa3ZBUFgwdAmtZCq4MQCwysN55USD'
) THEN 0
ELSE 1
END AS trading_route_required,
pair_id,
decoded_event_count,
decoded_trade_candidate_count,
trade_event_count,
pair_candle_count
FROM pair_state
)
SELECT
pair_trading_readiness AS pair_trading_readiness,
quote_asset_class AS quote_asset_class,
trading_route_required AS trading_route_required,
COUNT(pair_id) AS pair_count,
SUM(decoded_event_count) AS decoded_event_count,
SUM(decoded_trade_candidate_count) AS decoded_trade_candidate_count,
SUM(trade_event_count) AS trade_event_count,
SUM(pair_candle_count) AS pair_candle_count
FROM classified
GROUP BY pair_trading_readiness, quote_asset_class, trading_route_required
ORDER BY
CASE pair_trading_readiness
WHEN 'direct_wsol_quote' THEN 1
WHEN 'direct_stable_quote' THEN 2
WHEN 'inverse_wsol_base' THEN 3
WHEN 'inverse_stable_base' THEN 4
WHEN 'cross_quote_requires_router' THEN 5
WHEN 'unknown_quote' THEN 6
ELSE 7
END,
pair_trading_readiness,
quote_asset_class
"#,
)
.fetch_all(pool)
.await;
let rows = match rows_result {
Ok(rows) => rows,
Err(error) => {
return Err(crate::Error::Db(format!(
"cannot list local pair trading readiness diagnostic summaries on sqlite: {}",
error
)));
},
};
let mut summaries = std::vec::Vec::new();
for row in rows {
summaries.push(crate::LocalPairTradingReadinessDiagnosticSummaryDto {
pair_trading_readiness: row.pair_trading_readiness,
quote_asset_class: row.quote_asset_class,
trading_route_required: row.trading_route_required != 0,
pair_count: row.pair_count,
decoded_event_count: row.decoded_event_count,
decoded_trade_candidate_count: row.decoded_trade_candidate_count,
trade_event_count: row.trade_event_count,
pair_candle_count: row.pair_candle_count,
});
}
return Ok(summaries);
},
}
}
/// Lists local decoded-event diagnostic summaries.