// 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::{Context, Result}; use rayon::iter::{IntoParallelIterator, ParallelIterator}; use rocket::{get, http::Status, response::status::Custom, serde::json::Json, State}; use rusqlite::{params, Connection}; use serde_json::{json, Value}; use crate::{db::DBPool, timeutil::time_now}; /// Fetch TVL for all tokens pub fn get_all_token_tvl( connection: &Connection, max_timestamp: usize, ) -> Result> { let mut statement = connection.prepare( "SELECT uf.token_id, SUM(uf.token_amount) AS total_unspent_token_amount, SUM(uf.sats) AS total_unspent_sats FROM utxo_funding uf LEFT JOIN utxo_spending us ON uf.new_utxo_hash = us.spent_utxo_hash JOIN tx ON uf.txid = tx.txid WHERE us.spent_utxo_hash IS NULL AND (tx.mtp_timestamp <= ? OR tx.first_seen_timestamp <= ?) GROUP BY uf.token_id ", )?; let tvl: Vec<(String, u64, u64)> = statement .query_and_then([max_timestamp, max_timestamp], |row| { let token_id: String = row.get(0)?; let token_amount: u64 = row.get(1)?; let sats: u64 = row.get(2)?; Ok((token_id, token_amount, sats)) }) .unwrap() .map(|row: Result<(String, u64, u64)>| row.unwrap()) .collect(); Ok(tvl) } /// Get TVL for a single token pub fn get_token_tvl( connection: &Connection, max_timestamp: usize, token_id: &str, ) -> Result<(u64, u64)> { let mut statement = connection.prepare( "SELECT uf.token_amount, uf.sats FROM utxo_funding uf LEFT JOIN utxo_spending us ON uf.new_utxo_hash = us.spent_utxo_hash JOIN tx ON uf.txid = tx.txid WHERE us.spent_utxo_hash IS NULL AND (tx.mtp_timestamp <= ? OR tx.first_seen_timestamp <= ?) AND uf.token_id = ? ", )?; // Execute the query with the specified parameters let mut query = statement.query(params![max_timestamp, max_timestamp, token_id])?; // Initialize accumulators let mut sum_tokens: u64 = 0; let mut sum_sats: u64 = 0; // Iterate over the query result while let Some(row) = query.next()? { let tokens: u64 = row.get(0)?; let sats: u64 = row.get(1)?; sum_tokens = sum_tokens.checked_add(tokens).context("token overflow")?; sum_sats = sum_sats.checked_add(sats).context("sats overflow")?; } Ok((sum_sats, sum_tokens)) } // Deprecated; use valuelocked with optional parameters #[get("/tvl/