riftenlabs-indexer/src/rpc/mod.rs

131 lines
3.6 KiB
Rust
Raw Normal View History

2024-03-04 16:40:50 +01:00
// 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 std::{
collections::HashMap,
sync::{Arc, Mutex},
};
2024-04-03 11:39:49 +02:00
2024-10-31 10:55:29 +00:00
use anyhow::{Context, Result};
use rusqlite::{params, Connection};
pub mod apy;
pub mod bcmr;
2025-06-17 13:22:46 +00:00
pub mod candlesticks;
2024-04-03 11:39:49 +02:00
pub mod contract;
2025-02-14 18:02:48 +01:00
pub mod err;
pub mod oracle;
2024-04-03 21:40:33 +02:00
pub mod pool;
2024-04-03 11:39:49 +02:00
pub mod price;
pub mod tokens;
2024-04-03 09:49:44 +02:00
pub mod tvl;
2024-09-25 11:56:55 +02:00
pub mod tx;
pub mod user;
2024-03-04 16:40:50 +01:00
2025-02-17 20:49:52 +01:00
pub struct ResponseCacheInner {
update_timestamp: i64,
value: Option<serde_json::Value>,
in_progress: bool,
}
pub type ResponseCache = Arc<Mutex<HashMap<String, ResponseCacheInner>>>;
2024-03-04 16:40:50 +01:00
2024-03-21 11:15:44 +01:00
fn all_time_volume(db: &Connection, end_timestamp: u64) -> Result<Vec<(String, i64)>> {
let sql = "
SELECT
uf1.token_id,
SUM(ABS(uf1.sats - COALESCE(uf2.sats, 0))) AS total_volume_sats
FROM utxo_funding uf1
INNER JOIN utxo_funding uf2 ON uf1.spent_utxo_hash = uf2.new_utxo_hash
JOIN tx ON uf1.txid = tx.txid
WHERE COALESCE(tx.first_seen_timestamp, tx.mtp_timestamp) <= ?
GROUP BY uf1.token_id";
let mut stmt = db.prepare(sql)?;
let volume_iter = stmt.query_map(params![end_timestamp], |row| {
Ok((row.get::<_, String>(0)?, row.get::<_, i64>(1)?))
})?;
let mut volumes = Vec::new();
for volume in volume_iter {
volumes.push(volume?);
}
Ok(volumes)
}
fn period_volume(
db: &Connection,
begin_timestamp: u64,
end_timestamp: u64,
) -> Result<Vec<(String, i64)>> {
let sql = "
SELECT
uf1.token_id,
SUM(ABS(uf1.sats - COALESCE(uf2.sats, 0))) AS total_volume_sats
FROM utxo_funding uf1
INNER JOIN utxo_funding uf2 ON uf1.spent_utxo_hash = uf2.new_utxo_hash
JOIN tx ON uf1.txid = tx.txid
WHERE COALESCE(tx.first_seen_timestamp, tx.mtp_timestamp) BETWEEN ? AND ?
GROUP BY uf1.token_id
";
let mut stmt = db.prepare(sql)?;
let volume_iter = stmt.query_map(params![begin_timestamp, end_timestamp], |row| {
Ok((row.get::<_, String>(0)?, row.get::<_, i64>(1)?))
})?;
let mut volumes = Vec::new();
for volume in volume_iter {
volumes.push(volume?);
}
Ok(volumes)
}
pub fn contract_volume(
db: &Connection,
end_timestamp: u64,
) -> Result<HashMap<String, (i64, i64, i64)>> {
let one_day_seconds = 86400_u64;
let thirty_days_seconds = 30 * 86400_u64;
let one_day_begin_timestamp = end_timestamp
.checked_sub(one_day_seconds)
.context("timestamp underflow")?;
let thirty_days_begin_timestamp = end_timestamp
.checked_sub(thirty_days_seconds)
.context("timestamp underflow")?;
let all_time = all_time_volume(db, end_timestamp)?;
let one_day = period_volume(db, one_day_begin_timestamp, end_timestamp)?;
let thirty_days = period_volume(db, thirty_days_begin_timestamp, end_timestamp)?;
let mut result = HashMap::new();
for (token_id, volume) in all_time.into_iter() {
result.insert(token_id, (volume, 0, 0));
}
for (token_id, day_volume) in one_day.into_iter() {
if let Some((_, _, one_day_volume)) = result.get_mut(&token_id) {
*one_day_volume = day_volume;
} else {
result.insert(token_id.clone(), (0, 0, day_volume));
}
}
for (token_id, month_volume) in thirty_days.into_iter() {
if let Some((_, thirty_day_volume, _)) = result.get_mut(&token_id) {
*thirty_day_volume = month_volume;
} else {
result.insert(token_id.clone(), (0, month_volume, 0));
}
}
Ok(result)
}