1use crate::error::Error;
25use crate::types::{AccountId, Network};
26
27#[derive(Debug, Clone, Copy)]
32pub struct KnownToken {
33 pub name: &'static str,
35 pub mainnet: &'static str,
37 pub testnet: Option<&'static str>,
39}
40
41impl KnownToken {
42 pub fn resolve(&self, network: Network) -> Result<AccountId, Error> {
49 let address = match network {
50 Network::Mainnet => self.mainnet,
51 Network::Testnet => self.testnet.ok_or_else(|| Error::TokenNotAvailable {
52 token: self.name.to_string(),
53 network: network.to_string(),
54 })?,
55 Network::Sandbox | Network::Custom => {
56 return Err(Error::TokenNotAvailable {
57 token: self.name.to_string(),
58 network: network.to_string(),
59 });
60 }
61 };
62 address.parse().map_err(Into::into)
63 }
64}
65
66pub trait IntoContractId {
71 fn into_contract_id(self, network: Network) -> Result<AccountId, Error>;
73}
74
75impl IntoContractId for &str {
76 fn into_contract_id(self, _network: Network) -> Result<AccountId, Error> {
77 self.parse().map_err(Into::into)
78 }
79}
80
81impl IntoContractId for String {
82 fn into_contract_id(self, _network: Network) -> Result<AccountId, Error> {
83 self.parse().map_err(Into::into)
84 }
85}
86
87impl IntoContractId for AccountId {
88 fn into_contract_id(self, _network: Network) -> Result<AccountId, Error> {
89 Ok(self)
90 }
91}
92
93impl IntoContractId for &AccountId {
94 fn into_contract_id(self, _network: Network) -> Result<AccountId, Error> {
95 Ok(self.clone())
96 }
97}
98
99impl IntoContractId for KnownToken {
100 fn into_contract_id(self, network: Network) -> Result<AccountId, Error> {
101 self.resolve(network)
102 }
103}
104
105pub const USDC: KnownToken = KnownToken {
114 name: "USDC",
115 mainnet: "17208628f84f5d6ad33f0da3bbbeb27ffcb398eac501a31bd6ad2011e36133a1",
116 testnet: Some("3e2210e1184b45b64c8a434c0a7e7b23cc04ea7eb7a6c3c32520d03d4afcb8af"),
117};
118
119pub const USDT: KnownToken = KnownToken {
124 name: "USDT",
125 mainnet: "usdt.tether-token.near",
126 testnet: None,
127};
128
129pub const W_NEAR: KnownToken = KnownToken {
138 name: "wNEAR",
139 mainnet: "wrap.near",
140 testnet: Some("wrap.testnet"),
141};
142
143#[cfg(test)]
144mod tests {
145 use super::*;
146
147 #[test]
148 fn test_usdc_mainnet() {
149 let account = USDC.resolve(Network::Mainnet).unwrap();
150 assert_eq!(
151 account.as_str(),
152 "17208628f84f5d6ad33f0da3bbbeb27ffcb398eac501a31bd6ad2011e36133a1"
153 );
154 }
155
156 #[test]
157 fn test_usdc_testnet() {
158 let account = USDC.resolve(Network::Testnet).unwrap();
159 assert_eq!(
160 account.as_str(),
161 "3e2210e1184b45b64c8a434c0a7e7b23cc04ea7eb7a6c3c32520d03d4afcb8af"
162 );
163 }
164
165 #[test]
166 fn test_usdt_mainnet() {
167 let account = USDT.resolve(Network::Mainnet).unwrap();
168 assert_eq!(account.as_str(), "usdt.tether-token.near");
169 }
170
171 #[test]
172 fn test_usdt_testnet_not_available() {
173 let result = USDT.resolve(Network::Testnet);
174 assert!(result.is_err());
175 }
176
177 #[test]
178 fn test_wnear_mainnet() {
179 let account = W_NEAR.resolve(Network::Mainnet).unwrap();
180 assert_eq!(account.as_str(), "wrap.near");
181 }
182
183 #[test]
184 fn test_wnear_testnet() {
185 let account = W_NEAR.resolve(Network::Testnet).unwrap();
186 assert_eq!(account.as_str(), "wrap.testnet");
187 }
188
189 #[test]
190 fn test_sandbox_not_available() {
191 let result = USDC.resolve(Network::Sandbox);
192 assert!(result.is_err());
193 }
194
195 #[test]
196 fn test_custom_not_available() {
197 let result = USDC.resolve(Network::Custom);
198 assert!(result.is_err());
199 }
200}