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(
|
conn.execute(
|
||||||
"CREATE TABLE utxo_funding (
|
"CREATE TABLE utxo_funding (
|
||||||
new_utxo_hash TEXT PRIMARY KEY,
|
new_utxo_hash TEXT PRIMARY KEY,
|
||||||
|
spent_utxo_hash TEXT,
|
||||||
timestamp BIGINT,
|
timestamp BIGINT,
|
||||||
new_utxo_txid TEXT,
|
new_utxo_txid TEXT,
|
||||||
new_utxo_n INT,
|
new_utxo_n INT,
|
||||||
|
|
@ -48,6 +49,14 @@ pub fn prepare_tables(conn: &Connection) {
|
||||||
[],
|
[],
|
||||||
)
|
)
|
||||||
.unwrap();
|
.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) {
|
pub fn config_set(conn: &Connection, key: &str, value: i64) {
|
||||||
|
|
@ -70,7 +79,7 @@ pub fn insert_utxo_funding(
|
||||||
cauldrons: &Vec<ParsedContract>,
|
cauldrons: &Vec<ParsedContract>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let mut statement = con
|
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 {
|
for c in cauldrons {
|
||||||
if c.new_utxo_hash.is_none() {
|
if c.new_utxo_hash.is_none() {
|
||||||
|
|
@ -78,6 +87,7 @@ pub fn insert_utxo_funding(
|
||||||
}
|
}
|
||||||
statement.execute(params![
|
statement.execute(params![
|
||||||
c.new_utxo_hash.unwrap().to_hex(),
|
c.new_utxo_hash.unwrap().to_hex(),
|
||||||
|
c.spent_utxo_hash.to_hex(),
|
||||||
timestamp,
|
timestamp,
|
||||||
c.new_utxo_txid.unwrap().to_hex(),
|
c.new_utxo_txid.unwrap().to_hex(),
|
||||||
c.new_utxo_n.unwrap(),
|
c.new_utxo_n.unwrap(),
|
||||||
|
|
@ -143,49 +153,87 @@ pub fn list_tokens_by_volume(
|
||||||
connection: &Connection,
|
connection: &Connection,
|
||||||
seconds: usize,
|
seconds: usize,
|
||||||
limit: 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
|
// List token ID's by volume last n seconds
|
||||||
let mut statement = connection
|
let mut statement = connection
|
||||||
.prepare(
|
.prepare(
|
||||||
"
|
"
|
||||||
WITH FundingVolume AS (
|
WITH TradeData AS (
|
||||||
SELECT token_id, SUM(sats) as total_volume
|
SELECT
|
||||||
FROM utxo_funding
|
uf1.token_id,
|
||||||
WHERE timestamp >= (strftime('%s', 'now') - ?)
|
ABS(uf1.sats - COALESCE(uf2.sats, 0)) as trade_volume
|
||||||
GROUP BY token_id
|
FROM utxo_funding uf1
|
||||||
),
|
LEFT JOIN utxo_funding uf2 ON uf1.spent_utxo_hash = uf2.new_utxo_hash
|
||||||
Liquidity AS (
|
WHERE uf1.timestamp >= (strftime('%s', 'now') - ?)
|
||||||
SELECT f.token_id, SUM(f.sats) as total_funded_sats,
|
),
|
||||||
COALESCE((SELECT SUM(sp.sats)
|
TVLData AS (
|
||||||
FROM utxo_funding sp
|
SELECT
|
||||||
INNER JOIN utxo_spending s ON sp.new_utxo_hash = s.spent_utxo_hash
|
token_id,
|
||||||
WHERE sp.token_id = f.token_id), 0) as spent_sats
|
SUM(sats) as tvl_sats,
|
||||||
FROM utxo_funding f
|
SUM(token_amount) as tvl_tokens
|
||||||
GROUP BY f.token_id
|
FROM utxo_funding
|
||||||
)
|
WHERE new_utxo_hash NOT IN (SELECT spent_utxo_hash FROM utxo_spending)
|
||||||
SELECT
|
GROUP BY token_id
|
||||||
fv.token_id,
|
),
|
||||||
fv.total_volume,
|
HighestUnspentUTXO AS (
|
||||||
(SELECT SUM(l.total_funded_sats - l.spent_sats)
|
SELECT
|
||||||
FROM Liquidity l
|
token_id,
|
||||||
WHERE l.token_id = fv.token_id) as TVL
|
MAX(sats) as highest_sats,
|
||||||
FROM FundingVolume fv
|
token_amount
|
||||||
JOIN Liquidity l ON fv.token_id = l.token_id
|
FROM utxo_funding
|
||||||
ORDER BY fv.total_volume DESC, (l.total_funded_sats - l.spent_sats) DESC
|
WHERE new_utxo_hash NOT IN (SELECT spent_utxo_hash FROM utxo_spending)
|
||||||
LIMIT ?;
|
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();
|
.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| {
|
.query_and_then([seconds, limit], |row| {
|
||||||
let token_id: String = row.get(0)?;
|
let token_id: String = row.get(0)?;
|
||||||
let token_volume: u64 = row.get(1)?;
|
let trade_volume: u64 = row.get(1)?;
|
||||||
let token_tv: u64 = row.get(2)?;
|
let trade_count: u64 = row.get(2)?;
|
||||||
Ok((token_id, token_volume, token_tv))
|
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()
|
.unwrap()
|
||||||
.map(|row: Result<(String, u64, u64)>| row.unwrap())
|
.map(|row: Result<(String, u64, u64, u64, u64, u64, u64)>| row.unwrap())
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
Ok(tokens)
|
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 = limit.unwrap_or(50);
|
||||||
let limit = std::cmp::max(limit, 1000);
|
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)
|
list_tokens_by_volume(&conn.lock().unwrap(), duration, limit)
|
||||||
.map_err(|e| Custom(Status::InternalServerError, format!("Error: {}", e)))?;
|
.map_err(|e| Custom(Status::InternalServerError, format!("Error: {}", e)))?;
|
||||||
|
|
||||||
let result: Vec<Value> = list
|
let result: Vec<Value> = list
|
||||||
.into_par_iter()
|
.into_par_iter()
|
||||||
.map(|(token, volume, sats)| {
|
.map(
|
||||||
json!({
|
|(
|
||||||
"token_id": token,
|
token_id,
|
||||||
"volume": volume,
|
trade_volume,
|
||||||
"tvl": sats
|
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();
|
.collect();
|
||||||
|
|
||||||
Ok(Json(result))
|
Ok(Json(result))
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue