Document improvements
Misc improves to API documentation
This commit is contained in:
parent
527b9ba91c
commit
e8371c3967
8 changed files with 201 additions and 13 deletions
|
|
@ -151,7 +151,7 @@ class FunctionSignatureParser:
|
||||||
content = f.read()
|
content = f.read()
|
||||||
|
|
||||||
# Look for the function definition
|
# Look for the function definition
|
||||||
func_pattern = rf"pub fn {function_name}\s*\([^)]*\)\s*->[^{{]*{{"
|
func_pattern = rf"pub(?:\s+async)?\s+fn {function_name}\b\s*\([^)]*\)\s*->[^{{]*{{"
|
||||||
func_match = re.search(func_pattern, content)
|
func_match = re.search(func_pattern, content)
|
||||||
|
|
||||||
if not func_match:
|
if not func_match:
|
||||||
|
|
@ -167,8 +167,8 @@ class FunctionSignatureParser:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# Find the #[get("...")] attribute before the function
|
# Find the #[get("...")] attribute before the function
|
||||||
get_attr_pattern = rf'#\[get\("([^"]+)"\)\]\s*pub fn {function_name}'
|
get_attr_pattern = rf'#\[get\("([^"]+)"\)\]\s*pub(?:\s+async)?\s+fn {function_name}\b'
|
||||||
get_match = re.search(get_attr_pattern, content)
|
get_match = re.search(get_attr_pattern, content, re.DOTALL)
|
||||||
|
|
||||||
if get_match:
|
if get_match:
|
||||||
route_path = get_match.group(1)
|
route_path = get_match.group(1)
|
||||||
|
|
@ -190,7 +190,7 @@ class FunctionSignatureParser:
|
||||||
) -> tuple[str, str, bool]:
|
) -> tuple[str, str, bool]:
|
||||||
"""Extract description, status, and deprecated flag from comments above the function"""
|
"""Extract description, status, and deprecated flag from comments above the function"""
|
||||||
# Look for the function definition - simpler pattern
|
# Look for the function definition - simpler pattern
|
||||||
func_pattern = rf"pub fn {function_name}"
|
func_pattern = rf"pub(?:\s+async)?\s+fn {function_name}\b"
|
||||||
func_match = re.search(func_pattern, content)
|
func_match = re.search(func_pattern, content)
|
||||||
|
|
||||||
if not func_match:
|
if not func_match:
|
||||||
|
|
@ -209,8 +209,8 @@ class FunctionSignatureParser:
|
||||||
line = line.strip()
|
line = line.strip()
|
||||||
if line.startswith("///"):
|
if line.startswith("///"):
|
||||||
comment_lines.insert(0, line[3:].strip()) # Remove /// and strip
|
comment_lines.insert(0, line[3:].strip()) # Remove /// and strip
|
||||||
elif line.startswith("pub fn"):
|
elif line.startswith("pub fn") or line.startswith("pub async fn"):
|
||||||
break
|
break
|
||||||
elif line and not line.startswith("///") and not line.startswith("#["):
|
elif line and not line.startswith("///") and not line.startswith("#["):
|
||||||
break
|
break
|
||||||
|
|
||||||
|
|
@ -385,7 +385,7 @@ Base URL: `{mount_display}`
|
||||||
}
|
}
|
||||||
|
|
||||||
tpl_title = f"{route.path}"
|
tpl_title = f"{route.path}"
|
||||||
tpl = f"https://indexer.cauldron.quest{mount.path}{route.path}"
|
tpl = f"https://indexer.riften.net{mount.path}{route.path}"
|
||||||
|
|
||||||
for param in route.path_params:
|
for param in route.path_params:
|
||||||
if param not in example_params:
|
if param not in example_params:
|
||||||
|
|
|
||||||
|
|
@ -279,7 +279,9 @@ pub async fn index_blocks(
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.raw_call("blockchain.block.get", vec![Param::U32(next_height as u32)])
|
.raw_call("blockchain.block.get", vec![Param::U32(next_height as u32)])
|
||||||
.unwrap_or_else(|e| panic!("Failed to fetch block at height {next_height} from electrum: {e}"));
|
.unwrap_or_else(|e| {
|
||||||
|
panic!("Failed to fetch block at height {next_height} from electrum: {e}")
|
||||||
|
});
|
||||||
|
|
||||||
let block_hex: String = serde_json::from_str(&res.to_string()).unwrap();
|
let block_hex: String = serde_json::from_str(&res.to_string()).unwrap();
|
||||||
let block: Block = deserialize(&hex::decode(&block_hex).unwrap()).unwrap();
|
let block: Block = deserialize(&hex::decode(&block_hex).unwrap()).unwrap();
|
||||||
|
|
|
||||||
|
|
@ -17,10 +17,30 @@ use serde_json::{json, Value};
|
||||||
///
|
///
|
||||||
/// Status: Stable
|
/// Status: Stable
|
||||||
///
|
///
|
||||||
/// - token_id: The 32 byte token ID
|
/// - token_id: The 32 byte token ID of the oracle contract. Known oracle contract IDs:
|
||||||
/// - timestamp: Unix timestamp
|
/// - BCH/USD: `d0d46f5cbd82188acede0d3e49c75700c19cb8331a30101f0bb6a260066ac972`
|
||||||
|
/// - timestamp: Unix timestamp (optional, defaults to now)
|
||||||
///
|
///
|
||||||
/// Returns `null` if no oracle data is found.
|
/// Returns `null` if no oracle data is found.
|
||||||
|
///
|
||||||
|
/// **Important:** `oracle_price` is returned in **cents** (not dollars). Divide by 100
|
||||||
|
/// to get the price in USD:
|
||||||
|
/// ```
|
||||||
|
/// price_usd = oracle_price / 100
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// **Response Example:**
|
||||||
|
/// ```json
|
||||||
|
/// {
|
||||||
|
/// "oracle_timestamp": 1709468902,
|
||||||
|
/// "oracle_price": 64320,
|
||||||
|
/// "oracle_sequence": 12345,
|
||||||
|
/// "token_id": "d0d46f5cbd82188acede0d3e49c75700c19cb8331a30101f0bb6a260066ac972",
|
||||||
|
/// "txid": "...",
|
||||||
|
/// "blockhash": "..."
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
/// In this example, `oracle_price` of 64320 cents = $643.20 USD.
|
||||||
#[get("/delphi/closest?<token_id>&<timestamp>")]
|
#[get("/delphi/closest?<token_id>&<timestamp>")]
|
||||||
pub async fn oracle_get_closest(
|
pub async fn oracle_get_closest(
|
||||||
token_id: Option<String>,
|
token_id: Option<String>,
|
||||||
|
|
@ -83,8 +103,22 @@ pub async fn oracle_get_range(
|
||||||
|
|
||||||
/// Get historical oracle prices for a given token.
|
/// Get historical oracle prices for a given token.
|
||||||
///
|
///
|
||||||
/// - token: The 32 byte token ID
|
/// - token: The 32 byte token ID of the oracle contract. Known oracle contract IDs:
|
||||||
|
/// - BCH/USD: `d0d46f5cbd82188acede0d3e49c75700c19cb8331a30101f0bb6a260066ac972`
|
||||||
/// - start: Unix timestamp for start of period
|
/// - start: Unix timestamp for start of period
|
||||||
|
/// - end: Unix timestamp for end of period (optional, defaults to now)
|
||||||
|
/// - stepsize: Seconds per interval (optional)
|
||||||
|
///
|
||||||
|
/// **Important:** `oracle_price` values are in **cents**. Divide by 100 to convert to USD.
|
||||||
|
///
|
||||||
|
/// **Response Example:**
|
||||||
|
/// ```json
|
||||||
|
/// [
|
||||||
|
/// { "time": 1709468902, "price": 64320, "txid": "...", "blockhash": "...", "sequence": 12345 },
|
||||||
|
/// { "time": 1709555302, "price": 65100, "txid": "...", "blockhash": "...", "sequence": 12346 }
|
||||||
|
/// ]
|
||||||
|
/// ```
|
||||||
|
/// In this example, `price` values of 64320 cents = $643.20 USD.
|
||||||
#[get("/delphi/<token>/history?<start>&<end>&<stepsize>")]
|
#[get("/delphi/<token>/history?<start>&<end>&<stepsize>")]
|
||||||
pub async fn oracle_get_history(
|
pub async fn oracle_get_history(
|
||||||
token: &str,
|
token: &str,
|
||||||
|
|
|
||||||
|
|
@ -135,6 +135,29 @@ pub async fn list_active_pools(
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get historical state changes for a specific pool.
|
||||||
|
///
|
||||||
|
/// Returns the price history (token/BCH ratio) over time. Each entry represents
|
||||||
|
/// a state change event.
|
||||||
|
///
|
||||||
|
/// - pool_id: The pool ID (can be obtained via `/pool/id_from_utxo`)
|
||||||
|
/// - start: Unix timestamp for period start (default: 30 days ago)
|
||||||
|
///
|
||||||
|
/// **Response Example:**
|
||||||
|
/// ```json
|
||||||
|
/// {
|
||||||
|
/// "history": [
|
||||||
|
/// {
|
||||||
|
/// "sats": 1000000,
|
||||||
|
/// "tokens": 500,
|
||||||
|
/// "timestamp": 1709468902,
|
||||||
|
/// "txid": "..."
|
||||||
|
/// }
|
||||||
|
/// ],
|
||||||
|
/// "token_id": "b79bfc8246b5fc4707e7c7dedcb6619ef1ab91f494a790c20b0f4c422ed95b92",
|
||||||
|
/// "owner_pkh": "36c0020dd39e7cd66c21f237dc53d384661a557f"
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
#[get("/pool/history/<pool_id>?<start>")]
|
#[get("/pool/history/<pool_id>?<start>")]
|
||||||
pub async fn pool_history(
|
pub async fn pool_history(
|
||||||
pool_id: &str,
|
pool_id: &str,
|
||||||
|
|
@ -175,10 +198,10 @@ pub async fn pool_history(
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get pool ID from a UTXO specified by transaction ID and input position.
|
/// Get pool ID from a UTXO specified by transaction ID and output position.
|
||||||
///
|
///
|
||||||
/// - txid: Transaction ID (hex string)
|
/// - txid: Transaction ID (hex string)
|
||||||
/// - input_pos: Input position (vout) in the transaction
|
/// - n: Output position (vout) in the transaction
|
||||||
///
|
///
|
||||||
/// **Response Example:**
|
/// **Response Example:**
|
||||||
/// ```json
|
/// ```json
|
||||||
|
|
|
||||||
|
|
@ -273,9 +273,24 @@ pub async fn price_at_or_before_2(
|
||||||
|
|
||||||
/// Get the price of a given token at a specific timestamp.
|
/// Get the price of a given token at a specific timestamp.
|
||||||
///
|
///
|
||||||
|
/// Status: Stable
|
||||||
|
///
|
||||||
/// - token: The 32 byte token ID
|
/// - token: The 32 byte token ID
|
||||||
/// - timestamp: Unix timestamp
|
/// - timestamp: Unix timestamp
|
||||||
///
|
///
|
||||||
|
/// **Important:** The `price` field is denominated **per the smallest unit** of the token
|
||||||
|
/// (e.g. satoshis for an 8-decimal token), not per whole token. To get the price per
|
||||||
|
/// whole token, multiply by 10^decimals:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// price_per_token = api_price * (10 ** decimals)
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// For example, if `decimals` is 8 and `api_price` is `34493809.347826086`, then:
|
||||||
|
/// ```
|
||||||
|
/// price_per_token = 34493809.347826086 * (10 ** 8) -- price in satoshis per whole token
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
/// **Response Example:**
|
/// **Response Example:**
|
||||||
/// ```json
|
/// ```json
|
||||||
/// {
|
/// {
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,28 @@ use crate::db::DB;
|
||||||
use super::err::{bad_request, db_error, not_found, ApiErrorCode, CachedApiResult};
|
use super::err::{bad_request, db_error, not_found, ApiErrorCode, CachedApiResult};
|
||||||
use super::response::{cached_ok, CACHE_AGGREGATE, CACHE_IMMUTABLE};
|
use super::response::{cached_ok, CACHE_AGGREGATE, CACHE_IMMUTABLE};
|
||||||
|
|
||||||
|
/// Search tokens by name or symbol, sorted by trade volume.
|
||||||
|
///
|
||||||
|
/// Status: Unstable
|
||||||
|
///
|
||||||
|
/// Queries BCMR and CRC20 registries for matching tokens, then joins with live
|
||||||
|
/// trade volume data.
|
||||||
|
///
|
||||||
|
/// - search_query: Token name or symbol to search for
|
||||||
|
///
|
||||||
|
/// **Response:** A direct JSON array, sorted by `trade_volume` descending.
|
||||||
|
///
|
||||||
|
/// **Response Example:**
|
||||||
|
/// ```json
|
||||||
|
/// [
|
||||||
|
/// {
|
||||||
|
/// "token_id": "b79bfc8246b5fc4707e7c7dedcb6619ef1ab91f494a790c20b0f4c422ed95b92",
|
||||||
|
/// "name": "ExampleToken",
|
||||||
|
/// "ticker": "EXT",
|
||||||
|
/// "trade_volume": 1459676788
|
||||||
|
/// }
|
||||||
|
/// ]
|
||||||
|
/// ```
|
||||||
#[get("/tokens/search_by_volume?<search_query>")]
|
#[get("/tokens/search_by_volume?<search_query>")]
|
||||||
pub async fn search_by_volume(search_query: &str, db: &State<DB>) -> CachedApiResult<Vec<Value>> {
|
pub async fn search_by_volume(search_query: &str, db: &State<DB>) -> CachedApiResult<Vec<Value>> {
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
|
|
@ -49,6 +71,27 @@ pub async fn search_by_volume(search_query: &str, db: &State<DB>) -> CachedApiRe
|
||||||
Ok(cached_ok(result, CACHE_AGGREGATE))
|
Ok(cached_ok(result, CACHE_AGGREGATE))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Search tokens with optional filtering and sorting.
|
||||||
|
///
|
||||||
|
/// - q: Search query string
|
||||||
|
/// - limit: Maximum number of results (default: 250)
|
||||||
|
/// - offset: Pagination offset (default: 0)
|
||||||
|
/// - by: Sort field (`name`, `symbol`, `tvl`, `volume`)
|
||||||
|
/// - order: Sort direction (`asc`, `desc`)
|
||||||
|
///
|
||||||
|
/// **Response:** A direct JSON array.
|
||||||
|
///
|
||||||
|
/// **Response Example:**
|
||||||
|
/// ```json
|
||||||
|
/// [
|
||||||
|
/// {
|
||||||
|
/// "token_id": "b79bfc8246b5fc4707e7c7dedcb6619ef1ab91f494a790c20b0f4c422ed95b92",
|
||||||
|
/// "name": "ExampleToken",
|
||||||
|
/// "symbol": "EXT",
|
||||||
|
/// "decimals": 8
|
||||||
|
/// }
|
||||||
|
/// ]
|
||||||
|
/// ```
|
||||||
#[get("/tokens/search_cached?<q>&<limit>&<offset>&<by>&<order>")]
|
#[get("/tokens/search_cached?<q>&<limit>&<offset>&<by>&<order>")]
|
||||||
pub async fn search_cached(
|
pub async fn search_cached(
|
||||||
db: &State<DB>,
|
db: &State<DB>,
|
||||||
|
|
@ -160,6 +203,17 @@ fn parse_cached_sort(by: Option<String>, order: Option<String>) -> CachedSort {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// List all tokens with optional pagination and sorting.
|
||||||
|
///
|
||||||
|
/// Similar to `/tokens/search_cached` but without search filtering — returns all tokens
|
||||||
|
/// sorted by the specified field.
|
||||||
|
///
|
||||||
|
/// - limit: Maximum number of results (default: 250)
|
||||||
|
/// - offset: Pagination offset (default: 0)
|
||||||
|
/// - by: Sort field (`name`, `symbol`, `tvl`, `volume`, `score`)
|
||||||
|
/// - order: Sort direction (`asc`, `desc`)
|
||||||
|
///
|
||||||
|
/// **Response:** A direct JSON array.
|
||||||
#[get("/tokens/list_cached?<limit>&<offset>&<by>&<order>")]
|
#[get("/tokens/list_cached?<limit>&<offset>&<by>&<order>")]
|
||||||
pub async fn list_cached(
|
pub async fn list_cached(
|
||||||
db: &State<DB>,
|
db: &State<DB>,
|
||||||
|
|
@ -180,6 +234,20 @@ pub async fn list_cached(
|
||||||
Ok(cached_ok(json!(items), CACHE_AGGREGATE))
|
Ok(cached_ok(json!(items), CACHE_AGGREGATE))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// List specific tokens by their IDs.
|
||||||
|
///
|
||||||
|
/// Status: Unstable
|
||||||
|
///
|
||||||
|
/// Fetch token metadata for multiple tokens in a single request.
|
||||||
|
///
|
||||||
|
/// - ids: Comma-separated list of token IDs (hex strings)
|
||||||
|
/// - by: Sort field for results (`name`, `symbol`, `tvl`, `volume`, `score`)
|
||||||
|
/// - order: Sort direction (`asc`, `desc`)
|
||||||
|
///
|
||||||
|
/// **Response:** A direct JSON array.
|
||||||
|
///
|
||||||
|
/// **Example:**
|
||||||
|
/// `/tokens/list_cached_by_ids?ids=b79bfc8246b5fc4707e7c7dedcb6619ef1ab91f494a790c20b0f4c422ed95b92,abc123...`
|
||||||
#[get("/tokens/list_cached_by_ids?<ids>&<by>&<order>")]
|
#[get("/tokens/list_cached_by_ids?<ids>&<by>&<order>")]
|
||||||
pub async fn list_cached_by_ids(
|
pub async fn list_cached_by_ids(
|
||||||
db: &State<DB>,
|
db: &State<DB>,
|
||||||
|
|
@ -206,6 +274,22 @@ pub async fn list_cached_by_ids(
|
||||||
Ok(cached_ok(json!(items), CACHE_AGGREGATE))
|
Ok(cached_ok(json!(items), CACHE_AGGREGATE))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the first pool creation event for a given token.
|
||||||
|
///
|
||||||
|
/// - token: The 32 byte token ID
|
||||||
|
///
|
||||||
|
/// Returns 404 if no pools have ever been created for the token.
|
||||||
|
///
|
||||||
|
/// **Response Example:**
|
||||||
|
/// ```json
|
||||||
|
/// {
|
||||||
|
/// "token": "b79bfc8246b5fc4707e7c7dedcb6619ef1ab91f494a790c20b0f4c422ed95b92",
|
||||||
|
/// "creation_utxo": "94a933a0fa55093a0965eb867f1b9cac2bb07488ced4825bc31f86c9371f76aa:0",
|
||||||
|
/// "txid": "94a933a0fa55093a0965eb867f1b9cac2bb07488ced4825bc31f86c9371f76aa",
|
||||||
|
/// "timestamp": 1709468902,
|
||||||
|
/// "block_height": 880000
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
#[get("/token/<token>/first_pool")]
|
#[get("/token/<token>/first_pool")]
|
||||||
pub async fn first_pool_creation(token: &str, dbp: &State<DB>) -> CachedApiResult<Value> {
|
pub async fn first_pool_creation(token: &str, dbp: &State<DB>) -> CachedApiResult<Value> {
|
||||||
let token = TokenID::from_hex(token).map_err(|e| {
|
let token = TokenID::from_hex(token).map_err(|e| {
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,27 @@ use crate::db::DB;
|
||||||
use crate::rpc::err::{bad_request, db_error, ApiErrorCode, CachedApiResult};
|
use crate::rpc::err::{bad_request, db_error, ApiErrorCode, CachedApiResult};
|
||||||
use crate::rpc::response::{cached_ok, CACHE_NONE};
|
use crate::rpc::response::{cached_ok, CACHE_NONE};
|
||||||
|
|
||||||
|
/// Get the latest Cauldron transactions, optionally filtered by token.
|
||||||
|
///
|
||||||
|
/// Status: Stable
|
||||||
|
///
|
||||||
|
/// - limit: Maximum number of results (default: 100, max: 10000)
|
||||||
|
/// - offset: Pagination offset (default: 0)
|
||||||
|
/// - token: The 32 byte token ID to filter by (optional)
|
||||||
|
///
|
||||||
|
/// Note: `blockhash` is `null` for unconfirmed transactions.
|
||||||
|
/// `timestamp_guess` is an estimate derived from block time.
|
||||||
|
///
|
||||||
|
/// **Response Example:**
|
||||||
|
/// ```json
|
||||||
|
/// [
|
||||||
|
/// {
|
||||||
|
/// "txid": "94a933a0fa55093a0965eb867f1b9cac2bb07488ced4825bc31f86c9371f76aa",
|
||||||
|
/// "blockhash": "000000000000000002b4e6c0a1f4b3d2e5c7f891a2b3c4d5e6f7a8b9c0d1e2f3",
|
||||||
|
/// "timestamp_guess": 1709468902
|
||||||
|
/// }
|
||||||
|
/// ]
|
||||||
|
/// ```
|
||||||
#[get("/tx/latest?<limit>&<offset>&<token>")]
|
#[get("/tx/latest?<limit>&<offset>&<token>")]
|
||||||
pub async fn tx_latest(
|
pub async fn tx_latest(
|
||||||
limit: Option<usize>,
|
limit: Option<usize>,
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,15 @@ use crate::db::{cauldron::user::get_unique_per_month_accumilating, DB};
|
||||||
use crate::rpc::err::{db_error, CachedApiResult};
|
use crate::rpc::err::{db_error, CachedApiResult};
|
||||||
use crate::rpc::response::{cached_ok, CACHE_AGGREGATE};
|
use crate::rpc::response::{cached_ok, CACHE_AGGREGATE};
|
||||||
|
|
||||||
|
/// Get the count of unique addresses that have ever interacted with Cauldron, grouped by month.
|
||||||
|
///
|
||||||
|
/// **Response Example:**
|
||||||
|
/// ```json
|
||||||
|
/// [
|
||||||
|
/// { "month": "2024-01", "count": 1234 },
|
||||||
|
/// { "month": "2024-02", "count": 1456 }
|
||||||
|
/// ]
|
||||||
|
/// ```
|
||||||
#[get("/user/unique_addresses")]
|
#[get("/user/unique_addresses")]
|
||||||
pub async fn unique_addresses(conn: &State<DB>) -> CachedApiResult<Value> {
|
pub async fn unique_addresses(conn: &State<DB>) -> CachedApiResult<Value> {
|
||||||
let users = get_unique_per_month_accumilating(&conn.cauldron_r)
|
let users = get_unique_per_month_accumilating(&conn.cauldron_r)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue