soroban_cli/config/
alias.rs1use std::{collections::HashMap, convert::Infallible, str::FromStr};
2
3use serde::{Deserialize, Serialize};
4use stellar_strkey::Contract;
5
6use super::locator;
7use crate::config::token::UnresolvedToken;
8use crate::tx::builder;
9
10#[derive(Serialize, Deserialize, Default)]
11pub struct Data {
12 pub ids: HashMap<String, String>,
13}
14
15pub const NATIVE: &str = "native";
19
20#[must_use]
23pub fn is_reserved(alias: &str) -> bool {
24 alias == NATIVE
25}
26
27#[must_use]
32pub fn resolve_reserved(
33 alias: &str,
34 locator: &locator::Args,
35 network_passphrase: &str,
36) -> Option<Contract> {
37 if !is_reserved(alias) {
38 return None;
39 }
40
41 let resolved = UnresolvedToken::Asset(builder::Asset::Native)
47 .resolve(locator, network_passphrase)
48 .expect("the reserved native alias always resolves to its SAC");
49 Some(resolved.contract_id)
50}
51
52pub fn validate_reserved_aliases(alias: &str) -> Result<(), locator::Error> {
56 if is_reserved(alias) {
57 return Err(locator::Error::ContractAliasReserved(alias.to_owned()));
58 }
59 Ok(())
60}
61
62#[derive(Clone, Debug)]
64pub enum UnresolvedContract {
65 Resolved(stellar_strkey::Contract),
66 Alias(String),
67}
68
69impl Default for UnresolvedContract {
70 fn default() -> Self {
71 UnresolvedContract::Alias(String::default())
72 }
73}
74
75impl FromStr for UnresolvedContract {
76 type Err = Infallible;
77
78 fn from_str(value: &str) -> Result<Self, Self::Err> {
79 Ok(stellar_strkey::Contract::from_str(value).map_or_else(
80 |_| UnresolvedContract::Alias(value.to_string()),
81 UnresolvedContract::Resolved,
82 ))
83 }
84}
85
86impl UnresolvedContract {
87 pub fn resolve_contract_id(
88 &self,
89 locator: &locator::Args,
90 network_passphrase: &str,
91 ) -> Result<stellar_strkey::Contract, locator::Error> {
92 match self {
93 UnresolvedContract::Resolved(contract) => Ok(*contract),
94 UnresolvedContract::Alias(alias) => {
95 Self::resolve_alias(alias, locator, network_passphrase)
96 }
97 }
98 }
99
100 pub fn resolve_alias(
101 alias: &str,
102 locator: &locator::Args,
103 network_passphrase: &str,
104 ) -> Result<stellar_strkey::Contract, locator::Error> {
105 locator
106 .get_contract_id(alias, network_passphrase)?
107 .ok_or_else(|| locator::Error::ContractNotFound(alias.to_owned()))
108 }
109}
110
111#[cfg(test)]
112mod tests {
113 use super::*;
114
115 #[test]
116 fn native_is_reserved() {
117 assert!(is_reserved("native"));
118 assert!(validate_reserved_aliases("native").is_err());
119 }
120
121 #[test]
122 fn regular_aliases_are_not_reserved() {
123 assert!(!is_reserved("my-token"));
124 assert!(validate_reserved_aliases("my-token").is_ok());
125 }
126}