fyuz-sdk 0.1.1

Async Rust client for the Fyuz public REST API — bonding-curve token market data on BNB Smart Chain.
Documentation
//! Tokens, holders and the discovery feed.

use serde::Deserialize;

use super::trade::Trade;

/// Public profile stub attached to tokens, trades and holders.
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CreatorInfo {
    /// Wallet address.
    pub address: String,
    /// Chosen display name. `None` when the wallet never set one.
    #[serde(default)]
    pub username: Option<String>,
    /// Avatar URL. `None` when the wallet never set one.
    #[serde(default)]
    pub avatar: Option<String>,
}

/// Full token record.
///
/// Monetary and token amounts ([`marketcap`](Self::marketcap),
/// [`price`](Self::price), [`virtual_eth_amount`](Self::virtual_eth_amount), …)
/// are **decimal strings**, not floats: they carry 18-decimal values that lose
/// precision in `f64`. Keep them as strings, or parse them with a decimal type
/// of your choosing.
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Token {
    /// Internal row id. Pass the highest one you have seen as `latest_token_id`
    /// to [`RecentTradesParams`](crate::RecentTradesParams) to poll incrementally.
    pub id: i64,
    /// Contract address of the token.
    pub token_address: String,
    /// Token name.
    pub token_name: String,
    /// Token ticker.
    pub token_symbol: String,
    /// Creator-supplied description.
    #[serde(default)]
    pub token_description: Option<String>,
    /// Generated-image style tag, when the image was generated by Fyuz.
    #[serde(default)]
    pub image_style: Option<String>,
    /// Token image URL.
    #[serde(default)]
    pub token_image: Option<String>,
    /// Token banner URL.
    #[serde(default)]
    pub token_banner: Option<String>,
    /// Wallet that launched the token.
    pub creator_address: String,
    /// Creator's public profile stub.
    pub user: CreatorInfo,
    /// Chain slug, currently always `"bsc"`.
    pub network: String,
    /// USD market cap. Decimal string.
    pub marketcap: String,
    /// Token price in USD. Decimal string.
    pub price: String,
    /// BNB price in USD at last update. Decimal string.
    pub eth_price: String,
    /// Traded volume. Decimal string.
    pub volume: String,
    /// Internal ranking score. Decimal string.
    pub score: String,
    /// Bonding-curve virtual BNB reserve. Decimal string.
    pub virtual_eth_amount: String,
    /// Bonding-curve virtual token reserve. Decimal string.
    pub virtual_token_amount: String,
    /// PancakeSwap pair address. `None` while the token is still on the bonding
    /// curve — there is no DEX pool to read in that state, this API is the only
    /// price source.
    #[serde(default)]
    pub pair_address: Option<String>,
    /// `1` = PancakeSwap V2, `2` = V3, `3` = V4 / direct launch.
    pub pool_type: i64,
    /// Category tag assigned at launch.
    pub category: String,
    /// Number of comments on the token page.
    pub replies: i64,
    /// Project website.
    #[serde(default)]
    pub web_link: Option<String>,
    /// Telegram link.
    #[serde(default)]
    pub telegram_link: Option<String>,
    /// X/Twitter link.
    #[serde(default)]
    pub twitter_link: Option<String>,
    /// Graduation timestamp, RFC-3339. `None` means the token has not graduated.
    #[serde(default)]
    pub launched_at: Option<String>,
    /// Row creation timestamp, RFC-3339.
    pub created_at: String,
    /// Row update timestamp, RFC-3339.
    pub updated_at: String,
    /// On-chain creation timestamp, RFC-3339.
    pub creation_time: String,
    /// Pool liquidity. Decimal string. `None` before graduation.
    #[serde(default)]
    pub liquidity: Option<String>,
    /// Graduation progress toward the $30,000 target, 0-100.
    #[serde(default)]
    pub progress: Option<f64>,
    /// Price change over the reporting window, percent.
    #[serde(default)]
    pub price_change: Option<f64>,
    /// Price 15 minutes ago. Omitted by the server when unavailable.
    #[serde(default)]
    pub price_15m: Option<f64>,
    /// Price change over the last 15 minutes, percent. Omitted by the server
    /// when unavailable.
    #[serde(default)]
    pub price_change_15m: Option<f64>,
}

/// One wallet's position in a token, as served on the token detail page.
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Holder {
    /// Internal row id.
    pub id: i64,
    /// Token contract address.
    pub token_address: String,
    /// Holder wallet address.
    pub holder_address: String,
    /// Balance in whole tokens. Decimal string — do not parse as `f64`.
    pub token_amount: String,
    /// Token name.
    pub token_name: String,
    /// Token ticker.
    pub token_symbol: String,
    /// Token image URL.
    #[serde(default)]
    pub token_image: Option<String>,
    /// USD market cap of the token. Decimal string.
    pub marketcap: String,
    /// Chain slug.
    pub network: String,
    /// Wallet that launched the token.
    pub creator_address: String,
    /// Holder's public profile stub.
    pub user: CreatorInfo,
}

/// Response of `GET /tokens/{network}/{tokenAddress}`.
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TokenDetail {
    /// The token record itself.
    pub token_details: Token,
    /// Page of recent trades, newest first.
    pub trades: Vec<Trade>,
    /// Total trades for this token, for paginating [`trades`](Self::trades).
    pub trades_count: i64,
    /// Page of holders, largest first.
    pub holders_details: Vec<Holder>,
    /// Price 15 minutes ago. Decimal string.
    #[serde(default)]
    pub fifteen_min_price: Option<String>,
    /// Liquidity over the last day. Decimal string.
    #[serde(default)]
    pub one_day_liquidity: Option<String>,
    /// Bonding curve's own balance in whole tokens, as a decimal string.
    ///
    /// `None` means **unknown** (the chain read failed) — it does not mean zero
    /// and must never be rendered as `0`.
    #[serde(default)]
    pub curve_holding: Option<String>,
}

/// One row of the discovery feed.
///
/// Unlike [`Token`], this endpoint pre-aggregates everything into `f64`s: these
/// are display numbers, not balances.
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct DiscoverToken {
    /// Token contract address.
    pub token_address: String,
    /// Token name.
    pub name: String,
    /// Token ticker.
    pub symbol: String,
    /// Token image URL.
    #[serde(default)]
    pub image: Option<String>,
    /// Chain slug.
    pub network: String,
    /// Wallet that launched the token.
    #[serde(default)]
    pub creator_address: Option<String>,
    /// USD market cap.
    pub marketcap: f64,
    /// Token price in USD.
    pub price_usd: f64,
    /// Creation time, UNIX **seconds**.
    pub created_at: i64,
    /// `true` once graduated to a DEX pair.
    pub launched: bool,
    /// USD volume over the last 24 hours.
    pub volume24h: f64,
    /// Buy count over the last 24 hours.
    pub buys24h: i64,
    /// Sell count over the last 24 hours.
    pub sells24h: i64,
    /// Holder count.
    pub holders: i64,
    /// Price change over the last 24 hours, percent.
    pub price_change24h: f64,
    /// Progress toward the $30,000 graduation target, 0-100.
    pub graduation_pct: f64,
}

/// Response of `GET /tokens/king`.
///
/// The API wraps the token in a `king` envelope rather than returning it bare,
/// and sends `{"king": null}` whenever no token qualifies — everything on the
/// hill has graduated. [`FyuzClient::get_king`](crate::FyuzClient::get_king)
/// unwraps this for you.
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct KingResponse {
    /// The leading token still on the bonding curve, or `None` when the hill is
    /// empty.
    pub king: Option<Token>,
}

/// One page of `GET /tokens`.
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TokenPage {
    /// Tokens on this page.
    pub token_list: Vec<Token>,
    /// Total matching rows across all pages.
    pub token_count: i64,
}