Skip to main content

krusty_kms_common/
token.rs

1//! Token metadata and presets for known Starknet tokens.
2
3use crate::address::Address;
4use crate::chain::ChainId;
5
6/// ERC-20 token metadata.
7#[derive(Debug, Clone)]
8pub struct Token {
9    pub address: Address,
10    pub name: String,
11    pub symbol: String,
12    pub decimals: u8,
13}
14
15impl Token {
16    /// Create a new token with all fields.
17    pub fn new(
18        address: Address,
19        name: impl Into<String>,
20        symbol: impl Into<String>,
21        decimals: u8,
22    ) -> Self {
23        Self {
24            address,
25            name: name.into(),
26            symbol: symbol.into(),
27            decimals,
28        }
29    }
30}
31
32/// Well-known token presets.
33pub mod presets {
34    use super::*;
35
36    // ---- Mainnet addresses ----
37
38    const MAINNET_ETH: &str = "0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7";
39    const MAINNET_STRK: &str = "0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d";
40    const MAINNET_USDC: &str = "0x053c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8";
41    const MAINNET_USDT: &str = "0x068f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8";
42    const MAINNET_DAI: &str = "0x00da114221cb83fa859dbdb4c44beeaa0bb37c7537ad5ae66fe5e0efd20e6eb3";
43    const MAINNET_WBTC: &str = "0x03fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac";
44    const MAINNET_WSTETH: &str =
45        "0x042b8f0484674ca266ac5d08e4ac6a3fe65bd3129795def2dca5c34ecc5f96d2";
46    const MAINNET_RETH: &str = "0x0319111a5037cbec2b3e638cc34a3474e2d2608299f3e62866e9cc683208c610";
47    const MAINNET_UNI: &str = "0x049210ffc442172463f3177147c1aebc0c9677d34a20d2de4b51f9f14e99eead";
48    const MAINNET_NSTR: &str = "0x04b3a82103374b4006c7a15dae5cdd76a4e1cfd1096f25e5ec0aba1f4dc63387";
49    const MAINNET_LORDS: &str =
50        "0x0124aeb495b947201f5fac96fd1138e326ad86195b98df6dec9009158a533b49";
51    const MAINNET_EKUBO: &str =
52        "0x075afe6402ad5a5c20dd25e10ec3b3986acaa647b77e4ae24b0cbc9a54a27a87";
53    const MAINNET_SSTRK: &str =
54        "0x0356f304b154d29d2a8fe22f1cb9107a9b564a733cf6b4cc47fd121ac1b1f95f";
55    const MAINNET_NSTSTRK: &str =
56        "0x04619e9ce4109590219c5263787050726be63382148538f3f936c22aa87d2fc2";
57    const MAINNET_XSTRK: &str =
58        "0x028d709c875c0ceac3dce7065bec5328186dc89fe254527084d1689910954b0a";
59
60    // ---- Sepolia addresses ----
61
62    const SEPOLIA_ETH: &str = "0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7";
63    const SEPOLIA_STRK: &str = "0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d";
64    const SEPOLIA_USDC: &str = "0x053b40a647cedfca6ca84f542a0fe36736031905a9639a7f19a3c1e66bfd5080";
65    const SEPOLIA_USDT: &str = "0x0386c7e15e0cf0ada26620ef4d8ea065bbb1138d656089fdfce391e9fc8e7c21";
66
67    fn t(hex: &str, name: &str, symbol: &str, decimals: u8) -> Token {
68        Token::new(Address::from_hex(hex).unwrap(), name, symbol, decimals)
69    }
70
71    /// All well-known mainnet tokens.
72    pub fn mainnet_tokens() -> Vec<Token> {
73        vec![
74            t(MAINNET_ETH, "Ether", "ETH", 18),
75            t(MAINNET_STRK, "Starknet Token", "STRK", 18),
76            t(MAINNET_USDC, "USD Coin", "USDC", 6),
77            t(MAINNET_USDT, "Tether USD", "USDT", 6),
78            t(MAINNET_DAI, "Dai Stablecoin", "DAI", 18),
79            t(MAINNET_WBTC, "Wrapped BTC", "WBTC", 8),
80            t(MAINNET_WSTETH, "Wrapped stETH", "wstETH", 18),
81            t(MAINNET_RETH, "Rocket Pool ETH", "rETH", 18),
82            t(MAINNET_UNI, "Uniswap", "UNI", 18),
83            t(MAINNET_NSTR, "Nostra", "NSTR", 18),
84            t(MAINNET_LORDS, "Lords", "LORDS", 18),
85            t(MAINNET_EKUBO, "Ekubo Protocol", "EKUBO", 18),
86            t(MAINNET_SSTRK, "Staked STRK (Nostra)", "sSTRK", 18),
87            t(MAINNET_NSTSTRK, "Nostra Staked STRK", "nstSTRK", 18),
88            t(MAINNET_XSTRK, "xSTRK (Endur)", "xSTRK", 18),
89        ]
90    }
91
92    /// All well-known Sepolia testnet tokens.
93    pub fn sepolia_tokens() -> Vec<Token> {
94        vec![
95            t(SEPOLIA_ETH, "Ether", "ETH", 18),
96            t(SEPOLIA_STRK, "Starknet Token", "STRK", 18),
97            t(SEPOLIA_USDC, "USD Coin", "USDC", 6),
98            t(SEPOLIA_USDT, "Tether USD", "USDT", 6),
99        ]
100    }
101
102    /// Get the STRK token for a given chain.
103    pub fn strk(chain_id: ChainId) -> Token {
104        match chain_id {
105            ChainId::Mainnet => t(MAINNET_STRK, "Starknet Token", "STRK", 18),
106            ChainId::Sepolia => t(SEPOLIA_STRK, "Starknet Token", "STRK", 18),
107        }
108    }
109
110    /// Get the ETH token for a given chain.
111    pub fn eth(chain_id: ChainId) -> Token {
112        match chain_id {
113            ChainId::Mainnet => t(MAINNET_ETH, "Ether", "ETH", 18),
114            ChainId::Sepolia => t(SEPOLIA_ETH, "Ether", "ETH", 18),
115        }
116    }
117}
118
119#[cfg(test)]
120mod tests {
121    use super::*;
122
123    #[test]
124    fn test_mainnet_tokens_not_empty() {
125        let tokens = presets::mainnet_tokens();
126        assert!(tokens.len() >= 10);
127    }
128
129    #[test]
130    fn test_sepolia_tokens_not_empty() {
131        let tokens = presets::sepolia_tokens();
132        assert!(tokens.len() >= 2);
133    }
134
135    #[test]
136    fn test_strk_preset() {
137        let strk = presets::strk(ChainId::Mainnet);
138        assert_eq!(strk.symbol, "STRK");
139        assert_eq!(strk.decimals, 18);
140    }
141
142    #[test]
143    fn test_eth_preset() {
144        let eth = presets::eth(ChainId::Sepolia);
145        assert_eq!(eth.symbol, "ETH");
146        assert_eq!(eth.decimals, 18);
147    }
148}