192 lines
7.1 KiB
Rust
192 lines
7.1 KiB
Rust
|
|
// Copyright (C) 2024 Riften Labs AS
|
||
|
|
//
|
||
|
|
// This software is licensed under the GNU Affero General Public License (AGPL), version 3.0 or later.
|
||
|
|
// A copy of the license can be found in the LICENSE file or at https://www.gnu.org/licenses/agpl-3.0.html
|
||
|
|
|
||
|
|
use anyhow::Result;
|
||
|
|
use rusqlite::Connection;
|
||
|
|
|
||
|
|
pub enum CachedSort {
|
||
|
|
ScoreDesc,
|
||
|
|
ScoreAsc,
|
||
|
|
NameAsc,
|
||
|
|
NameDesc,
|
||
|
|
SymbolAsc,
|
||
|
|
SymbolDesc,
|
||
|
|
TvlDesc,
|
||
|
|
TvlAsc,
|
||
|
|
VolumeDesc,
|
||
|
|
VolumeAsc,
|
||
|
|
Change24hDesc,
|
||
|
|
Change24hAsc,
|
||
|
|
Change7dDesc,
|
||
|
|
Change7dAsc,
|
||
|
|
PriceUsdDesc,
|
||
|
|
PriceUsdAsc,
|
||
|
|
Change24hUsdDesc,
|
||
|
|
Change24hUsdAsc,
|
||
|
|
Change7dUsdDesc,
|
||
|
|
Change7dUsdAsc,
|
||
|
|
Apy30dDesc,
|
||
|
|
Apy30dAsc,
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn order_clause(sort: CachedSort) -> &'static str {
|
||
|
|
match sort {
|
||
|
|
CachedSort::ScoreDesc => "ORDER BY score DESC, trade_volume DESC, token_id ASC",
|
||
|
|
CachedSort::ScoreAsc => "ORDER BY score ASC, trade_volume ASC, token_id ASC",
|
||
|
|
CachedSort::NameAsc => "ORDER BY display_name COLLATE NOCASE ASC, token_id ASC",
|
||
|
|
CachedSort::NameDesc => "ORDER BY display_name COLLATE NOCASE DESC, token_id ASC",
|
||
|
|
CachedSort::SymbolAsc => "ORDER BY display_symbol COLLATE NOCASE ASC, token_id ASC",
|
||
|
|
CachedSort::SymbolDesc => "ORDER BY display_symbol COLLATE NOCASE DESC, token_id ASC",
|
||
|
|
CachedSort::TvlDesc => "ORDER BY tvl_sats DESC, token_id ASC",
|
||
|
|
CachedSort::TvlAsc => "ORDER BY tvl_sats ASC, token_id ASC",
|
||
|
|
CachedSort::VolumeDesc => "ORDER BY trade_volume DESC, token_id ASC",
|
||
|
|
CachedSort::VolumeAsc => "ORDER BY trade_volume ASC, token_id ASC",
|
||
|
|
CachedSort::Change24hDesc => "ORDER BY change_24h_bp DESC, token_id ASC",
|
||
|
|
CachedSort::Change24hAsc => "ORDER BY change_24h_bp ASC, token_id ASC",
|
||
|
|
CachedSort::Change7dDesc => "ORDER BY change_7d_bp DESC, token_id ASC",
|
||
|
|
CachedSort::Change7dAsc => "ORDER BY change_7d_bp ASC, token_id ASC",
|
||
|
|
CachedSort::PriceUsdDesc => "ORDER BY price_now_usd DESC, token_id ASC",
|
||
|
|
CachedSort::PriceUsdAsc => "ORDER BY price_now_usd ASC, token_id ASC",
|
||
|
|
CachedSort::Change24hUsdDesc => "ORDER BY change_24h_usd_bp DESC, token_id ASC",
|
||
|
|
CachedSort::Change24hUsdAsc => "ORDER BY change_24h_usd_bp ASC, token_id ASC",
|
||
|
|
CachedSort::Change7dUsdDesc => "ORDER BY change_7d_usd_bp DESC, token_id ASC",
|
||
|
|
CachedSort::Change7dUsdAsc => "ORDER BY change_7d_usd_bp ASC, token_id ASC",
|
||
|
|
CachedSort::Apy30dDesc => "ORDER BY apy_30d_bp DESC, token_id ASC",
|
||
|
|
CachedSort::Apy30dAsc => "ORDER BY apy_30d_bp ASC, token_id ASC",
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn create_cached_token_metrics_indexes(conn: &Connection) -> Result<()> {
|
||
|
|
conn.execute_batch(
|
||
|
|
r#"
|
||
|
|
-- ====== cached_token_metrics: list/sort indexes ======
|
||
|
|
|
||
|
|
-- Score (matches: ORDER BY score DESC, trade_volume DESC, token_id ASC)
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_ctm_score_desc
|
||
|
|
ON cached_token_metrics(score DESC, trade_volume DESC, token_id ASC);
|
||
|
|
|
||
|
|
-- Score ASC
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_ctm_score_asc
|
||
|
|
ON cached_token_metrics(score ASC, trade_volume ASC, token_id ASC);
|
||
|
|
|
||
|
|
-- Price USD
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_ctm_price_usd_desc
|
||
|
|
ON cached_token_metrics(price_now_usd DESC, token_id ASC);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_ctm_price_usd_asc
|
||
|
|
ON cached_token_metrics(price_now_usd ASC, token_id ASC);
|
||
|
|
|
||
|
|
-- APY 30d
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_ctm_apy_desc
|
||
|
|
ON cached_token_metrics(apy_30d_bp DESC, token_id ASC);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_ctm_apy_asc
|
||
|
|
ON cached_token_metrics(apy_30d_bp ASC, token_id ASC);
|
||
|
|
|
||
|
|
-- Name/Symbol sorts (note the collation!)
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_ctm_name_asc
|
||
|
|
ON cached_token_metrics(display_name COLLATE NOCASE ASC, token_id ASC);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_ctm_name_desc
|
||
|
|
ON cached_token_metrics(display_name COLLATE NOCASE DESC, token_id ASC);
|
||
|
|
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_ctm_symbol_asc
|
||
|
|
ON cached_token_metrics(display_symbol COLLATE NOCASE ASC, token_id ASC);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_ctm_symbol_desc
|
||
|
|
ON cached_token_metrics(display_symbol COLLATE NOCASE DESC, token_id ASC);
|
||
|
|
|
||
|
|
-- TVL & Volume
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_ctm_tvl_desc
|
||
|
|
ON cached_token_metrics(tvl_sats DESC, token_id ASC);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_ctm_tvl_asc
|
||
|
|
ON cached_token_metrics(tvl_sats ASC, token_id ASC);
|
||
|
|
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_ctm_volume_desc
|
||
|
|
ON cached_token_metrics(trade_volume DESC, token_id ASC);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_ctm_volume_asc
|
||
|
|
ON cached_token_metrics(trade_volume ASC, token_id ASC);
|
||
|
|
|
||
|
|
-- % change (sats)
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_ctm_ch24_desc
|
||
|
|
ON cached_token_metrics(change_24h_bp DESC, token_id ASC);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_ctm_ch24_asc
|
||
|
|
ON cached_token_metrics(change_24h_bp ASC, token_id ASC);
|
||
|
|
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_ctm_ch7d_desc
|
||
|
|
ON cached_token_metrics(change_7d_bp DESC, token_id ASC);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_ctm_ch7d_asc
|
||
|
|
ON cached_token_metrics(change_7d_bp ASC, token_id ASC);
|
||
|
|
|
||
|
|
-- % change (USD)
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_ctm_ch24_usd_desc
|
||
|
|
ON cached_token_metrics(change_24h_usd_bp DESC, token_id ASC);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_ctm_ch24_usd_asc
|
||
|
|
ON cached_token_metrics(change_24h_usd_bp ASC, token_id ASC);
|
||
|
|
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_ctm_ch7d_usd_desc
|
||
|
|
ON cached_token_metrics(change_7d_usd_bp DESC, token_id ASC);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_ctm_ch7d_usd_asc
|
||
|
|
ON cached_token_metrics(change_7d_usd_bp ASC, token_id ASC);
|
||
|
|
|
||
|
|
-- ====== aggregation path (update job) ======
|
||
|
|
|
||
|
|
-- Speeds WHERE tx.effective_timestamp >= ? and join by txid
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_tx_effective_ts
|
||
|
|
ON tx(effective_timestamp, txid);
|
||
|
|
|
||
|
|
-- Speeds JOIN pool_history_entry(pool) → pool(creation_utxo)
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_pool_creation_utxo
|
||
|
|
ON pool(creation_utxo, token_id);
|
||
|
|
|
||
|
|
-- Speeds SUM(...) GROUP BY p.token_id over phe JOINs
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_phe_pool_txid
|
||
|
|
ON pool_history_entry(pool, txid);
|
||
|
|
|
||
|
|
-- Helpful for other token lookups
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_pool_token_id
|
||
|
|
ON pool(token_id, creation_utxo);
|
||
|
|
|
||
|
|
-- Analyze stats for the new indexes
|
||
|
|
ANALYZE;
|
||
|
|
PRAGMA optimize;
|
||
|
|
"#,
|
||
|
|
)?;
|
||
|
|
Ok(())
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn create_cached_token_metrics_table(conn: &Connection) -> Result<()> {
|
||
|
|
conn.execute_batch(
|
||
|
|
r#"
|
||
|
|
CREATE TABLE IF NOT EXISTS cached_token_metrics (
|
||
|
|
token_id TEXT PRIMARY KEY,
|
||
|
|
trade_volume INTEGER NOT NULL DEFAULT 0,
|
||
|
|
tvl_sats INTEGER NOT NULL DEFAULT 0,
|
||
|
|
tvl_tokens INTEGER NOT NULL DEFAULT 0,
|
||
|
|
score INTEGER NOT NULL DEFAULT 0,
|
||
|
|
score_rank INTEGER NOT NULL DEFAULT 0,
|
||
|
|
display_name TEXT NOT NULL DEFAULT '',
|
||
|
|
display_symbol TEXT NOT NULL DEFAULT '',
|
||
|
|
-- sats per human token (already cached)
|
||
|
|
price_now REAL NOT NULL DEFAULT 0,
|
||
|
|
price_24h REAL NOT NULL DEFAULT 0,
|
||
|
|
price_7d REAL NOT NULL DEFAULT 0,
|
||
|
|
change_24h_bp INTEGER NOT NULL DEFAULT 0,
|
||
|
|
change_7d_bp INTEGER NOT NULL DEFAULT 0,
|
||
|
|
|
||
|
|
-- NEW: USD per human token (computed with time-matched BCH/USD oracle)
|
||
|
|
price_now_usd REAL NOT NULL DEFAULT 0,
|
||
|
|
price_24h_usd REAL NOT NULL DEFAULT 0,
|
||
|
|
price_7d_usd REAL NOT NULL DEFAULT 0,
|
||
|
|
change_24h_usd_bp INTEGER NOT NULL DEFAULT 0,
|
||
|
|
change_7d_usd_bp INTEGER NOT NULL DEFAULT 0,
|
||
|
|
|
||
|
|
apy_30d_bp INTEGER NOT NULL DEFAULT 0,
|
||
|
|
|
||
|
|
last_trade_ts INTEGER,
|
||
|
|
updated_at INTEGER NOT NULL
|
||
|
|
);
|
||
|
|
|
||
|
|
"#,
|
||
|
|
)?;
|
||
|
|
Ok(())
|
||
|
|
}
|