df_hyperliquid_core/transfer/
link.rs1use crate::client::evm::chain::NATIVE_DECIMALS;
6use crate::client::evm::tx::Call;
7use crate::client::evm::u256::{BadAmount, U256};
8use crate::transfer::erc20;
9use crate::utils::{Address, Dec};
10
11pub use crate::transfer::system::{HYPE_SYSTEM, is_system_address, system_address};
13pub use crate::transfer::system_token;
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq)]
18pub struct Linked {
19 pub index: u64,
20 pub contract: Option<Address>,
22 pub wei_decimals: u32,
24 pub evm_extra_wei_decimals: i32,
26}
27
28impl Linked {
29 #[must_use]
31 pub const fn hype(wei_decimals: u32) -> Linked {
32 Linked { index: 0, contract: None, wei_decimals, evm_extra_wei_decimals: 0 }
33 }
34
35 #[must_use]
37 pub const fn erc20(index: u64, contract: Address, wei_decimals: u32, evm_extra_wei_decimals: i32) -> Linked {
38 Linked { index, contract: Some(contract), wei_decimals, evm_extra_wei_decimals }
39 }
40
41 #[must_use]
44 pub fn system(&self) -> Address {
45 match self.contract {
46 None => HYPE_SYSTEM,
47 Some(_) => system_address(self.index),
48 }
49 }
50
51 #[must_use]
53 pub fn evm_decimals(&self) -> Option<u32> {
54 match self.contract {
55 None => Some(NATIVE_DECIMALS),
56 Some(_) => u32::try_from(i64::from(self.wei_decimals) + i64::from(self.evm_extra_wei_decimals)).ok(),
57 }
58 }
59
60 #[must_use]
63 pub fn core_places(&self) -> Option<u32> {
64 self.evm_decimals().map(|evm| evm.min(self.wei_decimals))
65 }
66
67 pub fn to_core(&self, amount: Dec) -> Result<Call, BadAmount> {
71 let places = self.core_places().ok_or(BadAmount::TooLarge)?;
72 let decimals = self.evm_decimals().ok_or(BadAmount::TooLarge)?;
73 if !amount.is_positive() {
74 return Err(BadAmount::NotPositive(amount));
75 }
76 if amount.places() > places {
77 return Err(BadAmount::TooFine { value: amount, decimals: places });
78 }
79 let units = U256::from_dec(amount, decimals)?;
80 Ok(match self.contract {
81 None => Call { to: Some(HYPE_SYSTEM), value: units, data: Vec::new() },
82 Some(contract) => {
83 Call { to: Some(contract), value: U256::ZERO, data: erc20::transfer(self.system(), units) }
84 }
85 })
86 }
87}
88
89#[cfg(test)]
90#[path = "tests/link.rs"]
91mod tests;