use ethers_core::abi;
use ethers_core::abi::{Detokenize, ParamType};
use std::time::Duration;
pub(crate) fn truncate_str(src: &str, side: usize) -> String {
if src.len() < side * 2 + 3 {
return src.to_string();
}
format!("{}..{}", &src[..side], &src[src.len() - side..])
}
pub(crate) fn decode_bytes<T: Detokenize>(param: ParamType, bytes: &[u8]) -> Result<T, abi::Error> {
let tokens = abi::decode(&[param], bytes)?;
T::from_tokens(tokens).map_err(|err| abi::Error::Other(err.to_string().into()))
}
#[cfg(not(target_arch = "wasm32"))]
pub(crate) fn build_reqwest(timeout: Duration) -> reqwest::Client {
reqwest::Client::builder()
.timeout(timeout)
.build()
.expect("should be a valid reqwest client")
}
#[cfg(target_arch = "wasm32")]
pub(crate) fn build_reqwest(_timeout: Duration) -> reqwest::Client {
reqwest::Client::new()
}
pub fn dns_encode(domain: &str) -> Result<Vec<u8>, String> {
let mut encoded = Vec::new();
let labels = domain.split('.');
for label in labels {
let label_len = label.len();
if label_len > 63 {
return Err(format!("Label is too long: {}", label));
}
encoded.push(label_len as u8);
encoded.extend(label.as_bytes());
}
encoded.push(0);
Ok(encoded)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_dns_encode() {
let ens_name = "vitalik.eth";
let expected_result = vec![
7, b'v', b'i', b't', b'a', b'l', b'i', b'k', 3, b'e', b't', b'h', 0,
];
let encoded_name = dns_encode(ens_name).unwrap();
assert_eq!(
encoded_name, expected_result,
"Expected dns encoded result to be {:?}, but got {:?}",
expected_result, encoded_name
);
}
#[test]
fn test_dns_encode_with_a_long_name() {
let ens_name = "superlongbutmeaningfulnameforanextraordinaryrustproject1234567890x.eth";
let mut labels = ens_name.split('.');
let encoded_name = dns_encode(ens_name);
assert_eq!(
encoded_name.unwrap_err(),
format!("Label is too long: {}", labels.next().unwrap()),
);
}
}