Merge branch 'tt-list' into 'master'

tokentoken: add GET /tokentoken/pools (list all active pools)

See merge request riftenlabs/riftenlabs-indexer!90
This commit is contained in:
Dagur Valberg Johannsson 2026-06-17 13:24:08 +00:00
commit 81374e7881
3 changed files with 68 additions and 1 deletions

View file

@ -439,6 +439,60 @@ pub async fn db_active_pools_for_pair(
Ok(out)
}
/// Every active pool (`withdrawn_in_txid IS NULL`) at its latest state, with no
/// pair filter. Drives the frontend pooled-pair selector, which needs the full
/// set of pools to show which token pairs have liquidity (without probing each
/// candidate pair individually).
pub async fn db_all_active_pools(pool: &SqlitePool) -> Result<Vec<ActiveTokenTokenPool>> {
let rows = sqlx::query(
"SELECT p.creation_utxo, p.nft_owner, p.token_a_id, p.token_b_id, p.fee_rate, p.min_fee,
phe.reserve_a, phe.reserve_b, phe.main_sats, phe.storage_sats,
phe.txid, phe.tx_pos, phe.storage_tx_pos
FROM tokentoken_pool p
JOIN tokentoken_pool_history_entry phe ON phe.pool = p.creation_utxo
AND phe.sequence = (
SELECT MAX(sequence) FROM tokentoken_pool_history_entry WHERE pool = p.creation_utxo
)
WHERE p.withdrawn_in_txid IS NULL",
)
.fetch_all(pool)
.await?;
let mut out = Vec::with_capacity(rows.len());
for row in rows {
let pool_blob: Vec<u8> = row.get(0);
let nft_owner_blob: Vec<u8> = row.get(1);
let token_a_blob: Vec<u8> = row.get(2);
let token_b_blob: Vec<u8> = row.get(3);
let fee_rate: i64 = row.get(4);
let min_fee: i64 = row.get(5);
let reserve_a: i64 = row.get(6);
let reserve_b: i64 = row.get(7);
let main_sats: i64 = row.get(8);
let storage_sats: i64 = row.get(9);
let txid_blob: Vec<u8> = row.get(10);
let tx_pos: i64 = row.get(11);
let storage_tx_pos: i64 = row.get(12);
out.push(ActiveTokenTokenPool {
pool_id: blob_to_display_hex::<OutPointHash>(&pool_blob)?,
nft_owner: hex::encode(&nft_owner_blob),
token_a_id: blob_to_display_hex::<TokenID>(&token_a_blob)?,
token_b_id: blob_to_display_hex::<TokenID>(&token_b_blob)?,
reserve_a: reserve_a as u64,
reserve_b: reserve_b as u64,
fee_rate: fee_rate as u32,
min_fee: min_fee as u64,
main_sats: main_sats as u64,
storage_sats: storage_sats as u64,
txid: blob_to_display_hex::<bitcoincash::Txid>(&txid_blob)?,
main_vout: tx_pos as u32,
storage_vout: storage_tx_pos as u32,
});
}
Ok(out)
}
/// Distinct token ids that appear in at least one active TokenToken pool.
pub async fn db_pair_tokens(pool: &SqlitePool) -> Result<Vec<String>> {
let rows = sqlx::query(

View file

@ -630,6 +630,7 @@ async fn launch() -> _ {
"/tokentoken",
routes![
rpc::tokentoken::list_active_pools,
rpc::tokentoken::list_all_pools,
rpc::tokentoken::list_tokens,
],
)

View file

@ -7,7 +7,7 @@
use crate::{
db::{
cauldron::tokentoken::{db_active_pools_for_pair, db_pair_tokens},
cauldron::tokentoken::{db_active_pools_for_pair, db_all_active_pools, db_pair_tokens},
DB,
},
rpc::err::{bad_request, db_error, ApiErrorCode, CachedApiResult},
@ -67,3 +67,15 @@ pub async fn list_tokens(conn: &State<DB>) -> CachedApiResult<Value> {
let tokens = db_pair_tokens(&conn.cauldron_r).await.map_err(db_error)?;
Ok(cached_ok(json!({ "tokens": tokens }), CACHE_AGGREGATE))
}
/// List ALL active TokenToken pools, regardless of pair — every pool at its
/// latest state. Drives the frontend pooled-pair selector, so it can present the
/// token pairs that have liquidity (with which token is A/main vs B/storage)
/// without probing each candidate pair individually.
#[get("/pools")]
pub async fn list_all_pools(conn: &State<DB>) -> CachedApiResult<Value> {
let active = db_all_active_pools(&conn.cauldron_r)
.await
.map_err(db_error)?;
Ok(cached_ok(json!({ "active": active }), CACHE_NONE))
}