Merge branch 'idoIndexer' into 'master'
Draft: What we need to keep track of idos. See merge request riftenlabs/riftenlabs-indexer!79
This commit is contained in:
commit
00588e2021
7 changed files with 1262 additions and 0 deletions
1132
src/db/cauldron/ido.rs
Normal file
1132
src/db/cauldron/ido.rs
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -15,6 +15,7 @@ use crate::db::cauldron::tokenlist::db_utils::{
|
|||
|
||||
pub mod config;
|
||||
pub mod header;
|
||||
pub mod ido;
|
||||
pub mod mempool;
|
||||
pub mod ohlcv;
|
||||
pub mod pool;
|
||||
|
|
@ -45,6 +46,7 @@ pub async fn prepare_tables(pool: &SqlitePool) {
|
|||
.unwrap();
|
||||
|
||||
pool::create_table(pool).await;
|
||||
ido::create_tables(pool).await;
|
||||
|
||||
sqlx::query(
|
||||
"CREATE INDEX idx_utxo_funding_join ON utxo_funding(new_utxo_hash, sats, token_id);",
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ use std::time::Duration;
|
|||
use super::DB;
|
||||
use crate::db::bcmr::prepare_tables as bcmr_prepare_tables;
|
||||
use crate::db::cauldron::config::check_db_version;
|
||||
use crate::db::cauldron::ido;
|
||||
use crate::db::cauldron::prepare_tables as cauldron_prepare_tables;
|
||||
use crate::db::crc20::prepare_tables as crc20_prepare_tables;
|
||||
use crate::db::oracle::prepare_tables as oracle_prepare_tables;
|
||||
|
|
@ -100,6 +101,9 @@ pub async fn initialize_databases(network: &str, read_slots: ReadSlots) -> Resul
|
|||
cauldron_prepare_tables(&cauldron_db_write).await;
|
||||
} else {
|
||||
check_db_version(&cauldron_db_read).await?;
|
||||
// Run IDO table migration/creation separately so that schema additions
|
||||
// take effect on existing databases without requiring a full DB wipe.
|
||||
ido::create_tables(&cauldron_db_write).await;
|
||||
}
|
||||
|
||||
// Initialize BCMR database
|
||||
|
|
|
|||
|
|
@ -356,6 +356,9 @@ pub async fn index_blocks(
|
|||
// last successful block indexed was. It must commit atomically with block data.
|
||||
config_set(&mut *db_tx, KEY_LAST_INDEXED, &blockhash.to_hex()).await;
|
||||
|
||||
// ido
|
||||
db::cauldron::ido::index_ido(&mut *db_tx, &sorted_txs, mtp as i64).await?;
|
||||
|
||||
// crc20
|
||||
index_crc20(&db.crc20_w, &sorted_txs).await?;
|
||||
|
||||
|
|
|
|||
|
|
@ -588,6 +588,9 @@ async fn launch() -> _ {
|
|||
rpc::pool::list_active_pools,
|
||||
rpc::pool::pool_history,
|
||||
rpc::pool::pool_id_from_utxo,
|
||||
rpc::ido::list_idos,
|
||||
rpc::ido::get_ido,
|
||||
rpc::ido::get_ido_entries,
|
||||
rpc::apy::aggregate_apy,
|
||||
rpc::contract::contract_count_token,
|
||||
rpc::contract::contract_count_all,
|
||||
|
|
|
|||
117
src/rpc/ido.rs
Normal file
117
src/rpc/ido.rs
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
// Copyright (C) 2024-2026 Whiterun LLC
|
||||
//
|
||||
// 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 crate::{
|
||||
db::{cauldron::ido::{self, deserialize_ido_params}, DB},
|
||||
rpc::{
|
||||
err::{bad_request, db_error, not_found, ApiErrorCode, CachedApiResult},
|
||||
response::{cached_ok, CACHE_NONE},
|
||||
},
|
||||
};
|
||||
use bitcoin_hashes::hex::FromHex;
|
||||
use bitcoincash::{TokenID, Txid};
|
||||
use rocket::{get, State};
|
||||
use serde_json::{json, Value};
|
||||
|
||||
fn format_ido(
|
||||
creation_txid: String,
|
||||
offered_token_category: String,
|
||||
offering_category: Option<String>,
|
||||
params_raw: Vec<u8>,
|
||||
mtp: i64,
|
||||
phase: String,
|
||||
) -> Value {
|
||||
let params = deserialize_ido_params(¶ms_raw);
|
||||
json!({
|
||||
"creation_txid": creation_txid,
|
||||
"offered_token_category": offered_token_category,
|
||||
"offering_category": offering_category,
|
||||
"params_raw": hex::encode(¶ms_raw),
|
||||
"params": params,
|
||||
"discovered_at_mtp": mtp,
|
||||
"phase": phase,
|
||||
})
|
||||
}
|
||||
|
||||
/// List all discovered IDOs with parsed parameters.
|
||||
#[get("/ido")]
|
||||
pub async fn list_idos(conn: &State<DB>) -> CachedApiResult<Value> {
|
||||
let idos = ido::list_idos(&conn.cauldron_r).await.map_err(db_error)?;
|
||||
|
||||
let idos_json: Vec<Value> = idos
|
||||
.into_iter()
|
||||
.map(|(txid, offered_cat, offering_cat, params_raw, mtp, phase)| {
|
||||
format_ido(txid, offered_cat, offering_cat, params_raw, mtp, phase)
|
||||
})
|
||||
.collect();
|
||||
|
||||
Ok(cached_ok(json!({ "idos": idos_json }), CACHE_NONE))
|
||||
}
|
||||
|
||||
/// Get all IDOs for a token category (offered_token_category) with parsed parameters.
|
||||
///
|
||||
/// Returns a list — multiple IDOs per token are allowed.
|
||||
#[get("/ido/<category>")]
|
||||
pub async fn get_ido(category: &str, conn: &State<DB>) -> CachedApiResult<Value> {
|
||||
let category = TokenID::from_hex(category).map_err(|e| {
|
||||
bad_request(
|
||||
ApiErrorCode::InvalidTokenId,
|
||||
&format!("Invalid category: {e}"),
|
||||
)
|
||||
})?;
|
||||
|
||||
let results = ido::get_idos_by_category(&conn.cauldron_r, &category)
|
||||
.await
|
||||
.map_err(db_error)?;
|
||||
|
||||
if results.is_empty() {
|
||||
return Err(not_found(
|
||||
ApiErrorCode::PoolNotFound,
|
||||
&format!("No IDO found for category: {category}"),
|
||||
));
|
||||
}
|
||||
|
||||
let idos_json: Vec<Value> = results
|
||||
.into_iter()
|
||||
.map(|(txid, offered_cat, offering_cat, params_raw, mtp, phase)| {
|
||||
format_ido(txid, offered_cat, offering_cat, params_raw, mtp, phase)
|
||||
})
|
||||
.collect();
|
||||
|
||||
Ok(cached_ok(json!({ "idos": idos_json }), CACHE_NONE))
|
||||
}
|
||||
|
||||
/// Get active (unspent) entry NFT UTXOs for a specific IDO.
|
||||
///
|
||||
/// `creation_txid` is the txid of the IDO announcement transaction.
|
||||
/// Used by the distribution robot to find which entries still need to be processed.
|
||||
#[get("/ido/<creation_txid>/entries")]
|
||||
pub async fn get_ido_entries(creation_txid: &str, conn: &State<DB>) -> CachedApiResult<Value> {
|
||||
let creation_txid = Txid::from_hex(creation_txid).map_err(|e| {
|
||||
bad_request(
|
||||
ApiErrorCode::InvalidTokenId,
|
||||
&format!("Invalid creation_txid: {e}"),
|
||||
)
|
||||
})?;
|
||||
|
||||
let entries = ido::get_ido_entries(&conn.cauldron_r, &creation_txid)
|
||||
.await
|
||||
.map_err(db_error)?;
|
||||
|
||||
let entries_json: Vec<Value> = entries
|
||||
.into_iter()
|
||||
.map(|(txid, n, sats, token_amount, commitment)| {
|
||||
json!({
|
||||
"txid": txid,
|
||||
"n": n,
|
||||
"sats": sats,
|
||||
"token_amount": token_amount,
|
||||
"commitment": commitment,
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
|
||||
Ok(cached_ok(json!({ "entries": entries_json }), CACHE_NONE))
|
||||
}
|
||||
|
|
@ -17,6 +17,7 @@ pub mod candlesticks;
|
|||
pub mod contract;
|
||||
pub mod err;
|
||||
pub mod health;
|
||||
pub mod ido;
|
||||
pub mod oracle;
|
||||
pub mod pool;
|
||||
pub mod price;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue