rpc: list_tokens update
Improve volume calculation; add additional fields
This commit is contained in:
parent
2387888017
commit
b4305a07de
2 changed files with 102 additions and 40 deletions
112
src/db.rs
112
src/db.rs
|
|
@ -7,6 +7,7 @@ pub fn prepare_tables(conn: &Connection) {
|
|||
conn.execute(
|
||||
"CREATE TABLE utxo_funding (
|
||||
new_utxo_hash TEXT PRIMARY KEY,
|
||||
spent_utxo_hash TEXT,
|
||||
timestamp BIGINT,
|
||||
new_utxo_txid TEXT,
|
||||
new_utxo_n INT,
|
||||
|
|
@ -48,6 +49,14 @@ pub fn prepare_tables(conn: &Connection) {
|
|||
[],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// Indexes for list_by_volume
|
||||
conn.execute(
|
||||
"CREATE INDEX idx_utxo_funding_join ON utxo_funding(new_utxo_hash, sats, token_id);",
|
||||
[],
|
||||
)
|
||||
.unwrap();
|
||||
conn.execute("CREATE INDEX idx_utxo_funding_tvl_highest ON utxo_funding(token_id, new_utxo_hash, sats, token_amount);", []).unwrap();
|
||||
}
|
||||
|
||||
pub fn config_set(conn: &Connection, key: &str, value: i64) {
|
||||
|
|
@ -70,7 +79,7 @@ pub fn insert_utxo_funding(
|
|||
cauldrons: &Vec<ParsedContract>,
|
||||
) -> Result<()> {
|
||||
let mut statement = con
|
||||
.prepare("INSERT OR IGNORE INTO utxo_funding (new_utxo_hash, timestamp, new_utxo_txid, new_utxo_n, sats, token_amount, token_id) VALUES (?, ?, ?, ?, ?, ?, ?)")?;
|
||||
.prepare("INSERT OR IGNORE INTO utxo_funding (new_utxo_hash, spent_utxo_hash, timestamp, new_utxo_txid, new_utxo_n, sats, token_amount, token_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?)")?;
|
||||
|
||||
for c in cauldrons {
|
||||
if c.new_utxo_hash.is_none() {
|
||||
|
|
@ -78,6 +87,7 @@ pub fn insert_utxo_funding(
|
|||
}
|
||||
statement.execute(params![
|
||||
c.new_utxo_hash.unwrap().to_hex(),
|
||||
c.spent_utxo_hash.to_hex(),
|
||||
timestamp,
|
||||
c.new_utxo_txid.unwrap().to_hex(),
|
||||
c.new_utxo_n.unwrap(),
|
||||
|
|
@ -143,49 +153,87 @@ pub fn list_tokens_by_volume(
|
|||
connection: &Connection,
|
||||
seconds: usize,
|
||||
limit: usize,
|
||||
) -> Result<Vec<(String, u64, u64)>> {
|
||||
) -> Result<Vec<(String, u64, u64, u64, u64, u64, u64)>> {
|
||||
// List token ID's by volume last n seconds
|
||||
let mut statement = connection
|
||||
.prepare(
|
||||
"
|
||||
WITH FundingVolume AS (
|
||||
SELECT token_id, SUM(sats) as total_volume
|
||||
FROM utxo_funding
|
||||
WHERE timestamp >= (strftime('%s', 'now') - ?)
|
||||
GROUP BY token_id
|
||||
),
|
||||
Liquidity AS (
|
||||
SELECT f.token_id, SUM(f.sats) as total_funded_sats,
|
||||
COALESCE((SELECT SUM(sp.sats)
|
||||
FROM utxo_funding sp
|
||||
INNER JOIN utxo_spending s ON sp.new_utxo_hash = s.spent_utxo_hash
|
||||
WHERE sp.token_id = f.token_id), 0) as spent_sats
|
||||
FROM utxo_funding f
|
||||
GROUP BY f.token_id
|
||||
)
|
||||
SELECT
|
||||
fv.token_id,
|
||||
fv.total_volume,
|
||||
(SELECT SUM(l.total_funded_sats - l.spent_sats)
|
||||
FROM Liquidity l
|
||||
WHERE l.token_id = fv.token_id) as TVL
|
||||
FROM FundingVolume fv
|
||||
JOIN Liquidity l ON fv.token_id = l.token_id
|
||||
ORDER BY fv.total_volume DESC, (l.total_funded_sats - l.spent_sats) DESC
|
||||
LIMIT ?;
|
||||
WITH TradeData AS (
|
||||
SELECT
|
||||
uf1.token_id,
|
||||
ABS(uf1.sats - COALESCE(uf2.sats, 0)) as trade_volume
|
||||
FROM utxo_funding uf1
|
||||
LEFT JOIN utxo_funding uf2 ON uf1.spent_utxo_hash = uf2.new_utxo_hash
|
||||
WHERE uf1.timestamp >= (strftime('%s', 'now') - ?)
|
||||
),
|
||||
TVLData AS (
|
||||
SELECT
|
||||
token_id,
|
||||
SUM(sats) as tvl_sats,
|
||||
SUM(token_amount) as tvl_tokens
|
||||
FROM utxo_funding
|
||||
WHERE new_utxo_hash NOT IN (SELECT spent_utxo_hash FROM utxo_spending)
|
||||
GROUP BY token_id
|
||||
),
|
||||
HighestUnspentUTXO AS (
|
||||
SELECT
|
||||
token_id,
|
||||
MAX(sats) as highest_sats,
|
||||
token_amount
|
||||
FROM utxo_funding
|
||||
WHERE new_utxo_hash NOT IN (SELECT spent_utxo_hash FROM utxo_spending)
|
||||
GROUP BY token_id
|
||||
),
|
||||
AggregateTradeData AS (
|
||||
SELECT
|
||||
td.token_id,
|
||||
SUM(td.trade_volume) as total_trade_volume,
|
||||
COUNT(*) as number_of_trades,
|
||||
tvl.tvl_sats,
|
||||
tvl.tvl_tokens,
|
||||
hu.highest_sats,
|
||||
hu.token_amount
|
||||
FROM TradeData td
|
||||
LEFT JOIN TVLData tvl ON td.token_id = tvl.token_id
|
||||
LEFT JOIN HighestUnspentUTXO hu ON td.token_id = hu.token_id
|
||||
GROUP BY td.token_id
|
||||
)
|
||||
SELECT
|
||||
token_id,
|
||||
total_trade_volume,
|
||||
number_of_trades,
|
||||
tvl_sats,
|
||||
tvl_tokens,
|
||||
highest_sats,
|
||||
token_amount
|
||||
FROM AggregateTradeData
|
||||
ORDER BY total_trade_volume DESC, number_of_trades DESC
|
||||
LIMIT ?
|
||||
",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let tokens: Vec<(String, u64, u64)> = statement
|
||||
let tokens: Vec<(String, u64, u64, u64, u64, u64, u64)> = statement
|
||||
.query_and_then([seconds, limit], |row| {
|
||||
let token_id: String = row.get(0)?;
|
||||
let token_volume: u64 = row.get(1)?;
|
||||
let token_tv: u64 = row.get(2)?;
|
||||
Ok((token_id, token_volume, token_tv))
|
||||
let trade_volume: u64 = row.get(1)?;
|
||||
let trade_count: u64 = row.get(2)?;
|
||||
let tvl_sats: u64 = row.get(3)?;
|
||||
let tvl_token: u64 = row.get(4)?;
|
||||
let best_contract_sats: u64 = row.get(5)?;
|
||||
let best_contracts_token: u64 = row.get(6)?;
|
||||
Ok((
|
||||
token_id,
|
||||
trade_volume,
|
||||
trade_count,
|
||||
tvl_sats,
|
||||
tvl_token,
|
||||
best_contract_sats,
|
||||
best_contracts_token,
|
||||
))
|
||||
})
|
||||
.unwrap()
|
||||
.map(|row: Result<(String, u64, u64)>| row.unwrap())
|
||||
.map(|row: Result<(String, u64, u64, u64, u64, u64, u64)>| row.unwrap())
|
||||
.collect();
|
||||
|
||||
Ok(tokens)
|
||||
|
|
|
|||
30
src/main.rs
30
src/main.rs
|
|
@ -174,19 +174,33 @@ fn list_by_volume(
|
|||
let limit = limit.unwrap_or(50);
|
||||
let limit = std::cmp::max(limit, 1000);
|
||||
|
||||
let list: Vec<(String, u64, u64)> =
|
||||
let list: Vec<(String, u64, u64, u64, u64, u64, u64)> =
|
||||
list_tokens_by_volume(&conn.lock().unwrap(), duration, limit)
|
||||
.map_err(|e| Custom(Status::InternalServerError, format!("Error: {}", e)))?;
|
||||
|
||||
let result: Vec<Value> = list
|
||||
.into_par_iter()
|
||||
.map(|(token, volume, sats)| {
|
||||
json!({
|
||||
"token_id": token,
|
||||
"volume": volume,
|
||||
"tvl": sats
|
||||
})
|
||||
})
|
||||
.map(
|
||||
|(
|
||||
token_id,
|
||||
trade_volume,
|
||||
trade_count,
|
||||
tvl_sats,
|
||||
tvl_token,
|
||||
best_contract_sats,
|
||||
best_contract_tokens,
|
||||
)| {
|
||||
json!({
|
||||
"token_id": token_id,
|
||||
"trade_volume": trade_volume,
|
||||
"trade_count": trade_count,
|
||||
"tvl_sats": tvl_sats,
|
||||
"tvl_tokens": tvl_token,
|
||||
"best_contract_sats": best_contract_sats,
|
||||
"best_contract_tokens": best_contract_tokens
|
||||
})
|
||||
},
|
||||
)
|
||||
.collect();
|
||||
|
||||
Ok(Json(result))
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue