df_hyperliquid_core/client/evm/precompiles/
assets.rs1use crate::client::evm::abi::AbiError;
5use crate::client::evm::precompiles::fields::{Fields, tokens};
6use crate::client::evm::precompiles::read::{Arg, Read, read};
7use crate::utils::Address;
8
9#[derive(Debug, Clone, PartialEq, Eq)]
10pub struct PerpAssetInfo {
11 pub coin: String,
12 pub margin_table_id: u32,
13 pub sz_decimals: u8,
14 pub max_leverage: u8,
15 pub only_isolated: bool,
16}
17
18#[must_use]
20pub fn perp_asset_info(perp: u32) -> Read<PerpAssetInfo> {
21 read(0x80a, &[Arg::Uint(u64::from(perp))], |answer| {
22 let tokens = tokens(0x80a, answer)?;
23 let mut fields = Fields::of("perpAssetInfo", &tokens)?;
24 Ok(PerpAssetInfo {
25 coin: fields.string()?,
26 margin_table_id: fields.u32()?,
27 sz_decimals: fields.u8()?,
28 max_leverage: fields.u8()?,
29 only_isolated: fields.bool()?,
30 })
31 })
32}
33
34#[derive(Debug, Clone, PartialEq, Eq)]
35pub struct SpotInfo {
36 pub name: String,
37 pub tokens: [u64; 2],
39}
40
41#[must_use]
43pub fn spot_info(spot: u32) -> Read<SpotInfo> {
44 read(0x80b, &[Arg::Uint(u64::from(spot))], |answer| {
45 let tokens = tokens(0x80b, answer)?;
46 let mut fields = Fields::of("spotInfo", &tokens)?;
47 let name = fields.string()?;
48 let pair: [u64; 2] =
49 fields.u64s()?.try_into().map_err(|_| AbiError::Type("spotInfo: not two tokens".to_owned()))?;
50 Ok(SpotInfo { name, tokens: pair })
51 })
52}
53
54#[derive(Debug, Clone, PartialEq, Eq)]
55pub struct TokenInfo {
56 pub name: String,
57 pub spots: Vec<u64>,
59 pub deployer_trading_fee_share: u64,
60 pub deployer: Address,
61 pub evm_contract: Address,
63 pub sz_decimals: u8,
64 pub wei_decimals: u8,
65 pub evm_extra_wei_decimals: i8,
67}
68
69#[must_use]
71pub fn token_info(token: u32) -> Read<TokenInfo> {
72 read(0x80c, &[Arg::Uint(u64::from(token))], |answer| {
73 let tokens = tokens(0x80c, answer)?;
74 let mut fields = Fields::of("tokenInfo", &tokens)?;
75 Ok(TokenInfo {
76 name: fields.string()?,
77 spots: fields.u64s()?,
78 deployer_trading_fee_share: fields.u64()?,
79 deployer: fields.address()?,
80 evm_contract: fields.address()?,
81 sz_decimals: fields.u8()?,
82 wei_decimals: fields.u8()?,
83 evm_extra_wei_decimals: fields.i8()?,
84 })
85 })
86}
87
88#[derive(Debug, Clone, Copy, PartialEq, Eq)]
90pub struct UserBalance {
91 pub user: Address,
92 pub balance: u64,
93}
94
95#[derive(Debug, Clone, PartialEq, Eq)]
96pub struct TokenSupply {
97 pub max_supply: u64,
98 pub total_supply: u64,
99 pub circulating_supply: u64,
100 pub future_emissions: u64,
101 pub non_circulating_user_balances: Vec<UserBalance>,
102}
103
104#[must_use]
106pub fn token_supply(token: u32) -> Read<TokenSupply> {
107 read(0x80d, &[Arg::Uint(u64::from(token))], |answer| {
108 let tokens = tokens(0x80d, answer)?;
109 let mut fields = Fields::of("tokenSupply", &tokens)?;
110 let (max_supply, total_supply, circulating_supply, future_emissions) =
111 (fields.u64()?, fields.u64()?, fields.u64()?, fields.u64()?);
112 let holders = fields
113 .items()?
114 .iter()
115 .map(|item| {
116 let mut holder = Fields::of("tokenSupply", std::slice::from_ref(item))?;
117 Ok(UserBalance { user: holder.address()?, balance: holder.u64()? })
118 })
119 .collect::<Result<_, AbiError>>()?;
120 Ok(TokenSupply {
121 max_supply,
122 total_supply,
123 circulating_supply,
124 future_emissions,
125 non_circulating_user_balances: holders,
126 })
127 })
128}
129
130#[cfg(test)]
131#[path = "tests/assets.rs"]
132mod tests;