From 18a3d64aff5a8de16b11019bfb31ea0bcfb632e8 Mon Sep 17 00:00:00 2001 From: Konstantin Fastov Date: Sat, 30 Aug 2025 13:07:45 +0300 Subject: [PATCH 1/5] add missing fields for userFees response --- src/info/response_structs.rs | 12 ++++++++++-- src/info/sub_structs.rs | 27 +++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/info/response_structs.rs b/src/info/response_structs.rs index 221dbf91..b7579a79 100644 --- a/src/info/response_structs.rs +++ b/src/info/response_structs.rs @@ -4,9 +4,10 @@ use alloy::primitives::Address; use crate::{ info::{AssetPosition, Level, MarginSummary}, - DailyUserVlm, Delta, FeeSchedule, Leverage, OrderInfo, Referrer, ReferrerState, - UserTokenBalance, + ActiveStakingDiscount, DailyUserVlm, Delta, FeeSchedule, Leverage, OrderInfo, Referrer, + ReferrerState, StakingLink, UserTokenBalance, }; +use serde_json::Value; #[derive(Deserialize, Debug)] #[serde(rename_all = "camelCase")] @@ -30,6 +31,13 @@ pub struct UserFeesResponse { pub fee_schedule: FeeSchedule, pub user_add_rate: String, pub user_cross_rate: String, + pub user_spot_cross_rate: String, + pub user_spot_add_rate: String, + pub trial: Option, + pub fee_trial_reward: String, + pub next_trial_available_timestamp: Option, + pub staking_link: Option, + pub active_staking_discount: ActiveStakingDiscount, } #[derive(serde::Deserialize, Debug)] diff --git a/src/info/sub_structs.rs b/src/info/sub_structs.rs index d244a063..62c238eb 100644 --- a/src/info/sub_structs.rs +++ b/src/info/sub_structs.rs @@ -83,7 +83,10 @@ pub struct DailyUserVlm { pub struct FeeSchedule { pub add: String, pub cross: String, + pub spot_cross: String, + pub spot_add: String, pub referral_discount: String, + pub staking_discount_tiers: Vec, pub tiers: Tiers, } @@ -105,6 +108,8 @@ pub struct Mm { pub struct Vip { pub add: String, pub cross: String, + pub spot_cross: String, + pub spot_add: String, pub ntl_cutoff: String, } @@ -117,6 +122,28 @@ pub struct UserTokenBalance { pub entry_ntl: String, } +#[derive(Deserialize, Debug, Clone)] +#[serde(rename_all = "camelCase")] +pub struct StakingLink { + #[serde(rename = "type")] + pub link_type: String, + pub staking_user: String, +} + +#[derive(Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct StakingDiscountTier { + pub bps_of_max_supply: String, + pub discount: String, +} + +#[derive(Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct ActiveStakingDiscount { + pub bps_of_max_supply: String, + pub discount: String, +} + #[derive(Deserialize, Clone, Debug)] #[serde(rename_all = "camelCase")] pub struct OrderInfo { From e08335736e984e021ccf043d01bebcd2f190805e Mon Sep 17 00:00:00 2001 From: Konstantin Fastov Date: Mon, 8 Sep 2025 14:31:07 +0300 Subject: [PATCH 2/5] Refactor StakingLink struct to enum to better match real-life data --- src/info/sub_structs.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/info/sub_structs.rs b/src/info/sub_structs.rs index 62c238eb..940cccbc 100644 --- a/src/info/sub_structs.rs +++ b/src/info/sub_structs.rs @@ -123,11 +123,14 @@ pub struct UserTokenBalance { } #[derive(Deserialize, Debug, Clone)] -#[serde(rename_all = "camelCase")] -pub struct StakingLink { - #[serde(rename = "type")] - pub link_type: String, - pub staking_user: String, +#[serde(tag = "type", rename_all = "camelCase")] +pub enum StakingLink { + // {"type":"stakingUser","tradingUser":"0x..."} + StakingUser { trading_user: String }, + // {"type":"tradingUser","stakingUser":"0x..."} + TradingUser { staking_user: String }, + // {"type":"requested","stakingUser":"0x..."} + Requested { staking_user: String }, } #[derive(Deserialize, Debug)] From 7aaee6fb39e65ffa32f293c1f8ebcff25f8a845b Mon Sep 17 00:00:00 2001 From: Konstantin Fastov Date: Mon, 8 Sep 2025 17:05:42 +0300 Subject: [PATCH 3/5] refactor: fallback for standard StakingLink struct for better compatibility --- src/info/sub_structs.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/info/sub_structs.rs b/src/info/sub_structs.rs index 940cccbc..7b9fbc60 100644 --- a/src/info/sub_structs.rs +++ b/src/info/sub_structs.rs @@ -123,14 +123,14 @@ pub struct UserTokenBalance { } #[derive(Deserialize, Debug, Clone)] -#[serde(tag = "type", rename_all = "camelCase")] -pub enum StakingLink { - // {"type":"stakingUser","tradingUser":"0x..."} - StakingUser { trading_user: String }, - // {"type":"tradingUser","stakingUser":"0x..."} - TradingUser { staking_user: String }, - // {"type":"requested","stakingUser":"0x..."} - Requested { staking_user: String }, +#[serde(rename_all = "camelCase")] +pub struct StakingLink { + #[serde(rename = "type")] + pub link_type: String, + #[serde(default)] + pub staking_user: Option, + #[serde(default)] + pub trading_user: Option, } #[derive(Deserialize, Debug)] From 4063356076f46955488276c909df6669016771fc Mon Sep 17 00:00:00 2001 From: Konstantin Fastov Date: Mon, 8 Sep 2025 17:34:20 +0300 Subject: [PATCH 4/5] Remove trial field from UserFeesResponse struct due to unclear documentation and lack of observed usage. --- src/info/response_structs.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/info/response_structs.rs b/src/info/response_structs.rs index b7579a79..ce02cafd 100644 --- a/src/info/response_structs.rs +++ b/src/info/response_structs.rs @@ -7,7 +7,8 @@ use crate::{ ActiveStakingDiscount, DailyUserVlm, Delta, FeeSchedule, Leverage, OrderInfo, Referrer, ReferrerState, StakingLink, UserTokenBalance, }; -use serde_json::Value; +// NOTE: Docs mention a trial field, but its format is unclear and we have not +// observed it in practice. Omitting the field for now to avoid guessing. #[derive(Deserialize, Debug)] #[serde(rename_all = "camelCase")] @@ -33,7 +34,6 @@ pub struct UserFeesResponse { pub user_cross_rate: String, pub user_spot_cross_rate: String, pub user_spot_add_rate: String, - pub trial: Option, pub fee_trial_reward: String, pub next_trial_available_timestamp: Option, pub staking_link: Option, From fac978ec160cf5820b49bb7e1e7d8e0401371e40 Mon Sep 17 00:00:00 2001 From: Konstantin Fastov Date: Tue, 23 Sep 2025 14:05:06 +0300 Subject: [PATCH 5/5] Capture user fees trial payload --- src/info/response_structs.rs | 7 ++++--- src/info/sub_structs.rs | 4 ++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/info/response_structs.rs b/src/info/response_structs.rs index ce02cafd..e7ca6ff3 100644 --- a/src/info/response_structs.rs +++ b/src/info/response_structs.rs @@ -5,10 +5,9 @@ use alloy::primitives::Address; use crate::{ info::{AssetPosition, Level, MarginSummary}, ActiveStakingDiscount, DailyUserVlm, Delta, FeeSchedule, Leverage, OrderInfo, Referrer, - ReferrerState, StakingLink, UserTokenBalance, + ReferrerState, StakingLink, TrialInfo, UserTokenBalance, }; -// NOTE: Docs mention a trial field, but its format is unclear and we have not -// observed it in practice. Omitting the field for now to avoid guessing. +// NOTE: The `trial` field appears but the schema is undocumented; capture it as raw JSON for now. #[derive(Deserialize, Debug)] #[serde(rename_all = "camelCase")] @@ -34,6 +33,8 @@ pub struct UserFeesResponse { pub user_cross_rate: String, pub user_spot_cross_rate: String, pub user_spot_add_rate: String, + #[serde(default)] + pub trial: Option, pub fee_trial_reward: String, pub next_trial_available_timestamp: Option, pub staking_link: Option, diff --git a/src/info/sub_structs.rs b/src/info/sub_structs.rs index 7b9fbc60..09c2e283 100644 --- a/src/info/sub_structs.rs +++ b/src/info/sub_structs.rs @@ -1,5 +1,6 @@ use alloy::primitives::Address; use serde::{Deserialize, Serialize}; +use serde_json::Value; #[derive(Deserialize, Serialize, Debug, Clone)] #[serde(rename_all = "camelCase")] @@ -147,6 +148,9 @@ pub struct ActiveStakingDiscount { pub discount: String, } +/// The API exposes a `trial` object whose schema is not yet documented; capture it raw for now. +pub type TrialInfo = Value; + #[derive(Deserialize, Clone, Debug)] #[serde(rename_all = "camelCase")] pub struct OrderInfo {