use crate::error::Error;
use crate::types::{AccountId, ChainId};
#[derive(Debug, Clone, Copy)]
pub struct KnownToken {
pub name: &'static str,
pub mainnet: &'static str,
pub testnet: Option<&'static str>,
}
impl KnownToken {
pub fn resolve(&self, chain_id: &ChainId) -> Result<AccountId, Error> {
let address = match chain_id.as_str() {
"mainnet" => self.mainnet,
"testnet" => self.testnet.ok_or_else(|| Error::TokenNotAvailable {
token: self.name.to_string(),
chain_id: chain_id.to_string(),
})?,
_ => {
return Err(Error::TokenNotAvailable {
token: self.name.to_string(),
chain_id: chain_id.to_string(),
});
}
};
address.parse().map_err(Into::into)
}
}
pub trait IntoContractId {
fn into_contract_id(self, chain_id: &ChainId) -> Result<AccountId, Error>;
}
impl IntoContractId for &str {
fn into_contract_id(self, _chain_id: &ChainId) -> Result<AccountId, Error> {
self.parse().map_err(Into::into)
}
}
impl IntoContractId for String {
fn into_contract_id(self, _chain_id: &ChainId) -> Result<AccountId, Error> {
self.parse().map_err(Into::into)
}
}
impl IntoContractId for AccountId {
fn into_contract_id(self, _chain_id: &ChainId) -> Result<AccountId, Error> {
Ok(self)
}
}
impl IntoContractId for &AccountId {
fn into_contract_id(self, _chain_id: &ChainId) -> Result<AccountId, Error> {
Ok(self.clone())
}
}
impl IntoContractId for KnownToken {
fn into_contract_id(self, chain_id: &ChainId) -> Result<AccountId, Error> {
self.resolve(chain_id)
}
}
pub const USDC: KnownToken = KnownToken {
name: "USDC",
mainnet: "17208628f84f5d6ad33f0da3bbbeb27ffcb398eac501a31bd6ad2011e36133a1",
testnet: Some("3e2210e1184b45b64c8a434c0a7e7b23cc04ea7eb7a6c3c32520d03d4afcb8af"),
};
pub const USDT: KnownToken = KnownToken {
name: "USDT",
mainnet: "usdt.tether-token.near",
testnet: None,
};
pub const W_NEAR: KnownToken = KnownToken {
name: "wNEAR",
mainnet: "wrap.near",
testnet: Some("wrap.testnet"),
};
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_usdc_mainnet() {
let account = USDC.resolve(&ChainId::mainnet()).unwrap();
assert_eq!(
account.as_str(),
"17208628f84f5d6ad33f0da3bbbeb27ffcb398eac501a31bd6ad2011e36133a1"
);
}
#[test]
fn test_usdc_testnet() {
let account = USDC.resolve(&ChainId::testnet()).unwrap();
assert_eq!(
account.as_str(),
"3e2210e1184b45b64c8a434c0a7e7b23cc04ea7eb7a6c3c32520d03d4afcb8af"
);
}
#[test]
fn test_usdt_mainnet() {
let account = USDT.resolve(&ChainId::mainnet()).unwrap();
assert_eq!(account.as_str(), "usdt.tether-token.near");
}
#[test]
fn test_usdt_testnet_not_available() {
let result = USDT.resolve(&ChainId::testnet());
assert!(result.is_err());
}
#[test]
fn test_wnear_mainnet() {
let account = W_NEAR.resolve(&ChainId::mainnet()).unwrap();
assert_eq!(account.as_str(), "wrap.near");
}
#[test]
fn test_wnear_testnet() {
let account = W_NEAR.resolve(&ChainId::testnet()).unwrap();
assert_eq!(account.as_str(), "wrap.testnet");
}
#[test]
fn test_sandbox_not_available() {
let result = USDC.resolve(&ChainId::new("test-chain-abc12"));
assert!(result.is_err());
}
#[test]
fn test_custom_not_available() {
let result = USDC.resolve(&ChainId::new("custom"));
assert!(result.is_err());
}
}