use std::{collections::HashMap, convert::Infallible, str::FromStr};
use serde::{Deserialize, Serialize};
use stellar_strkey::Contract;
use super::locator;
use crate::config::token::UnresolvedToken;
use crate::tx::builder;
#[derive(Serialize, Deserialize, Default)]
pub struct Data {
pub ids: HashMap<String, String>,
}
pub const NATIVE: &str = "native";
#[must_use]
pub fn is_reserved(alias: &str) -> bool {
alias == NATIVE
}
#[must_use]
pub fn resolve_reserved(
alias: &str,
locator: &locator::Args,
network_passphrase: &str,
) -> Option<Contract> {
if !is_reserved(alias) {
return None;
}
let resolved = UnresolvedToken::Asset(builder::Asset::Native)
.resolve(locator, network_passphrase)
.expect("the reserved native alias always resolves to its SAC");
Some(resolved.contract_id)
}
pub fn validate_reserved_aliases(alias: &str) -> Result<(), locator::Error> {
if is_reserved(alias) {
return Err(locator::Error::ContractAliasReserved(alias.to_owned()));
}
Ok(())
}
#[derive(Clone, Debug)]
pub enum UnresolvedContract {
Resolved(stellar_strkey::Contract),
Alias(String),
}
impl Default for UnresolvedContract {
fn default() -> Self {
UnresolvedContract::Alias(String::default())
}
}
impl FromStr for UnresolvedContract {
type Err = Infallible;
fn from_str(value: &str) -> Result<Self, Self::Err> {
Ok(stellar_strkey::Contract::from_str(value).map_or_else(
|_| UnresolvedContract::Alias(value.to_string()),
UnresolvedContract::Resolved,
))
}
}
impl UnresolvedContract {
pub fn resolve_contract_id(
&self,
locator: &locator::Args,
network_passphrase: &str,
) -> Result<stellar_strkey::Contract, locator::Error> {
match self {
UnresolvedContract::Resolved(contract) => Ok(*contract),
UnresolvedContract::Alias(alias) => {
Self::resolve_alias(alias, locator, network_passphrase)
}
}
}
pub fn resolve_alias(
alias: &str,
locator: &locator::Args,
network_passphrase: &str,
) -> Result<stellar_strkey::Contract, locator::Error> {
locator
.get_contract_id(alias, network_passphrase)?
.ok_or_else(|| locator::Error::ContractNotFound(alias.to_owned()))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn native_is_reserved() {
assert!(is_reserved("native"));
assert!(validate_reserved_aliases("native").is_err());
}
#[test]
fn regular_aliases_are_not_reserved() {
assert!(!is_reserved("my-token"));
assert!(validate_reserved_aliases("my-token").is_ok());
}
}