Skip to main content

fyuz/models/
token.rs

1//! Tokens, holders and the discovery feed.
2
3use serde::Deserialize;
4
5use super::trade::Trade;
6
7/// Public profile stub attached to tokens, trades and holders.
8#[derive(Debug, Clone, Deserialize)]
9#[serde(rename_all = "camelCase")]
10pub struct CreatorInfo {
11    /// Wallet address.
12    pub address: String,
13    /// Chosen display name. `None` when the wallet never set one.
14    #[serde(default)]
15    pub username: Option<String>,
16    /// Avatar URL. `None` when the wallet never set one.
17    #[serde(default)]
18    pub avatar: Option<String>,
19}
20
21/// Full token record.
22///
23/// Monetary and token amounts ([`marketcap`](Self::marketcap),
24/// [`price`](Self::price), [`virtual_eth_amount`](Self::virtual_eth_amount), …)
25/// are **decimal strings**, not floats: they carry 18-decimal values that lose
26/// precision in `f64`. Keep them as strings, or parse them with a decimal type
27/// of your choosing.
28#[derive(Debug, Clone, Deserialize)]
29#[serde(rename_all = "camelCase")]
30pub struct Token {
31    /// Internal row id. Pass the highest one you have seen as `latest_token_id`
32    /// to [`RecentTradesParams`](crate::RecentTradesParams) to poll incrementally.
33    pub id: i64,
34    /// Contract address of the token.
35    pub token_address: String,
36    /// Token name.
37    pub token_name: String,
38    /// Token ticker.
39    pub token_symbol: String,
40    /// Creator-supplied description.
41    #[serde(default)]
42    pub token_description: Option<String>,
43    /// Generated-image style tag, when the image was generated by Fyuz.
44    #[serde(default)]
45    pub image_style: Option<String>,
46    /// Token image URL.
47    #[serde(default)]
48    pub token_image: Option<String>,
49    /// Token banner URL.
50    #[serde(default)]
51    pub token_banner: Option<String>,
52    /// Wallet that launched the token.
53    pub creator_address: String,
54    /// Creator's public profile stub.
55    pub user: CreatorInfo,
56    /// Chain slug, currently always `"bsc"`.
57    pub network: String,
58    /// USD market cap. Decimal string.
59    pub marketcap: String,
60    /// Token price in USD. Decimal string.
61    pub price: String,
62    /// BNB price in USD at last update. Decimal string.
63    pub eth_price: String,
64    /// Traded volume. Decimal string.
65    pub volume: String,
66    /// Internal ranking score. Decimal string.
67    pub score: String,
68    /// Bonding-curve virtual BNB reserve. Decimal string.
69    pub virtual_eth_amount: String,
70    /// Bonding-curve virtual token reserve. Decimal string.
71    pub virtual_token_amount: String,
72    /// PancakeSwap pair address. `None` while the token is still on the bonding
73    /// curve — there is no DEX pool to read in that state, this API is the only
74    /// price source.
75    #[serde(default)]
76    pub pair_address: Option<String>,
77    /// `1` = PancakeSwap V2, `2` = V3, `3` = V4 / direct launch.
78    pub pool_type: i64,
79    /// Category tag assigned at launch.
80    pub category: String,
81    /// Number of comments on the token page.
82    pub replies: i64,
83    /// Project website.
84    #[serde(default)]
85    pub web_link: Option<String>,
86    /// Telegram link.
87    #[serde(default)]
88    pub telegram_link: Option<String>,
89    /// X/Twitter link.
90    #[serde(default)]
91    pub twitter_link: Option<String>,
92    /// Graduation timestamp, RFC-3339. `None` means the token has not graduated.
93    #[serde(default)]
94    pub launched_at: Option<String>,
95    /// Row creation timestamp, RFC-3339.
96    pub created_at: String,
97    /// Row update timestamp, RFC-3339.
98    pub updated_at: String,
99    /// On-chain creation timestamp, RFC-3339.
100    pub creation_time: String,
101    /// Pool liquidity. Decimal string. `None` before graduation.
102    #[serde(default)]
103    pub liquidity: Option<String>,
104    /// Graduation progress toward the $30,000 target, 0-100.
105    #[serde(default)]
106    pub progress: Option<f64>,
107    /// Price change over the reporting window, percent.
108    #[serde(default)]
109    pub price_change: Option<f64>,
110    /// Price 15 minutes ago. Omitted by the server when unavailable.
111    #[serde(default)]
112    pub price_15m: Option<f64>,
113    /// Price change over the last 15 minutes, percent. Omitted by the server
114    /// when unavailable.
115    #[serde(default)]
116    pub price_change_15m: Option<f64>,
117}
118
119/// One wallet's position in a token, as served on the token detail page.
120#[derive(Debug, Clone, Deserialize)]
121#[serde(rename_all = "camelCase")]
122pub struct Holder {
123    /// Internal row id.
124    pub id: i64,
125    /// Token contract address.
126    pub token_address: String,
127    /// Holder wallet address.
128    pub holder_address: String,
129    /// Balance in whole tokens. Decimal string — do not parse as `f64`.
130    pub token_amount: String,
131    /// Token name.
132    pub token_name: String,
133    /// Token ticker.
134    pub token_symbol: String,
135    /// Token image URL.
136    #[serde(default)]
137    pub token_image: Option<String>,
138    /// USD market cap of the token. Decimal string.
139    pub marketcap: String,
140    /// Chain slug.
141    pub network: String,
142    /// Wallet that launched the token.
143    pub creator_address: String,
144    /// Holder's public profile stub.
145    pub user: CreatorInfo,
146}
147
148/// Response of `GET /tokens/{network}/{tokenAddress}`.
149#[derive(Debug, Clone, Deserialize)]
150#[serde(rename_all = "camelCase")]
151pub struct TokenDetail {
152    /// The token record itself.
153    pub token_details: Token,
154    /// Page of recent trades, newest first.
155    pub trades: Vec<Trade>,
156    /// Total trades for this token, for paginating [`trades`](Self::trades).
157    pub trades_count: i64,
158    /// Page of holders, largest first.
159    pub holders_details: Vec<Holder>,
160    /// Price 15 minutes ago. Decimal string.
161    #[serde(default)]
162    pub fifteen_min_price: Option<String>,
163    /// Liquidity over the last day. Decimal string.
164    #[serde(default)]
165    pub one_day_liquidity: Option<String>,
166    /// Bonding curve's own balance in whole tokens, as a decimal string.
167    ///
168    /// `None` means **unknown** (the chain read failed) — it does not mean zero
169    /// and must never be rendered as `0`.
170    #[serde(default)]
171    pub curve_holding: Option<String>,
172}
173
174/// One row of the discovery feed.
175///
176/// Unlike [`Token`], this endpoint pre-aggregates everything into `f64`s: these
177/// are display numbers, not balances.
178#[derive(Debug, Clone, Deserialize)]
179#[serde(rename_all = "camelCase")]
180pub struct DiscoverToken {
181    /// Token contract address.
182    pub token_address: String,
183    /// Token name.
184    pub name: String,
185    /// Token ticker.
186    pub symbol: String,
187    /// Token image URL.
188    #[serde(default)]
189    pub image: Option<String>,
190    /// Chain slug.
191    pub network: String,
192    /// Wallet that launched the token.
193    #[serde(default)]
194    pub creator_address: Option<String>,
195    /// USD market cap.
196    pub marketcap: f64,
197    /// Token price in USD.
198    pub price_usd: f64,
199    /// Creation time, UNIX **seconds**.
200    pub created_at: i64,
201    /// `true` once graduated to a DEX pair.
202    pub launched: bool,
203    /// USD volume over the last 24 hours.
204    pub volume24h: f64,
205    /// Buy count over the last 24 hours.
206    pub buys24h: i64,
207    /// Sell count over the last 24 hours.
208    pub sells24h: i64,
209    /// Holder count.
210    pub holders: i64,
211    /// Price change over the last 24 hours, percent.
212    pub price_change24h: f64,
213    /// Progress toward the $30,000 graduation target, 0-100.
214    pub graduation_pct: f64,
215}
216
217/// Response of `GET /tokens/king`.
218///
219/// The API wraps the token in a `king` envelope rather than returning it bare,
220/// and sends `{"king": null}` whenever no token qualifies — everything on the
221/// hill has graduated. [`FyuzClient::get_king`](crate::FyuzClient::get_king)
222/// unwraps this for you.
223#[derive(Debug, Clone, Deserialize)]
224#[serde(rename_all = "camelCase")]
225pub struct KingResponse {
226    /// The leading token still on the bonding curve, or `None` when the hill is
227    /// empty.
228    pub king: Option<Token>,
229}
230
231/// One page of `GET /tokens`.
232#[derive(Debug, Clone, Deserialize)]
233#[serde(rename_all = "camelCase")]
234pub struct TokenPage {
235    /// Tokens on this page.
236    pub token_list: Vec<Token>,
237    /// Total matching rows across all pages.
238    pub token_count: i64,
239}