soroban_cli/config/
sc_address.rs

1use std::str::FromStr;
2
3use crate::xdr;
4
5use super::{key, locator, UnresolvedContract};
6
7/// `ScAddress` can be either a resolved `xdr::ScAddress` or an alias of a `Contract` or `MuxedAccount`.
8#[allow(clippy::module_name_repetitions)]
9#[derive(Clone, Debug)]
10pub enum UnresolvedScAddress {
11    Resolved(xdr::ScAddress),
12    Alias(String),
13}
14
15impl Default for UnresolvedScAddress {
16    fn default() -> Self {
17        UnresolvedScAddress::Alias(String::default())
18    }
19}
20
21#[derive(thiserror::Error, Debug)]
22pub enum Error {
23    #[error(transparent)]
24    Locator(#[from] locator::Error),
25    #[error(transparent)]
26    Key(#[from] key::Error),
27    #[error("Account alias \"{0}\" not Found")]
28    AccountAliasNotFound(String),
29}
30
31impl FromStr for UnresolvedScAddress {
32    type Err = Error;
33
34    fn from_str(value: &str) -> Result<Self, Self::Err> {
35        Ok(xdr::ScAddress::from_str(value).map_or_else(
36            |_| UnresolvedScAddress::Alias(value.to_string()),
37            UnresolvedScAddress::Resolved,
38        ))
39    }
40}
41
42impl UnresolvedScAddress {
43    pub fn resolve(
44        self,
45        locator: &locator::Args,
46        network_passphrase: &str,
47    ) -> Result<xdr::ScAddress, Error> {
48        let alias = match self {
49            UnresolvedScAddress::Resolved(addr) => return Ok(addr),
50            UnresolvedScAddress::Alias(alias) => alias,
51        };
52        let contract = UnresolvedContract::resolve_alias(&alias, locator, network_passphrase);
53        let key = locator.read_key(&alias);
54        match (contract, key) {
55            (Ok(contract), Ok(_)) => {
56                eprintln!(
57                    "Warning: ScAddress alias {alias} is ambiguous, assuming it is a contract"
58                );
59                Ok(xdr::ScAddress::Contract(stellar_xdr::curr::ContractId(
60                    xdr::Hash(contract.0),
61                )))
62            }
63            (Ok(contract), _) => Ok(xdr::ScAddress::Contract(stellar_xdr::curr::ContractId(
64                xdr::Hash(contract.0),
65            ))),
66            (_, Ok(key)) => Ok(xdr::ScAddress::Account(
67                key.muxed_account(None)?.account_id(),
68            )),
69            _ => Err(Error::AccountAliasNotFound(alias)),
70        }
71    }
72}