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}