scope_cli/cli/tui/
vocab.rs1use scope::config::Config;
9use scope::domain::address_book::AddressBook;
10use scope::market::{MarketVenue, VenueRegistry};
11use scope::tokens::TokenAliases;
12
13#[derive(Debug, Clone, Default)]
15pub struct Vocab {
16 pub labels: Vec<String>,
18 pub aliases: Vec<String>,
20 pub venues: Vec<String>,
22 pub chains: Vec<String>,
24}
25
26impl Vocab {
27 pub fn load(config: &Config) -> Self {
29 let mut labels: Vec<String> = AddressBook::load(&config.data_dir())
30 .map(|b| b.addresses.into_iter().filter_map(|a| a.label).collect())
31 .unwrap_or_default();
32 labels.sort();
33 labels.dedup();
34 let mut aliases: Vec<String> = TokenAliases::load()
35 .list()
36 .into_iter()
37 .map(|t| t.symbol.clone())
38 .collect();
39 aliases.sort();
40 aliases.dedup();
41 let venues = VenueRegistry::load()
42 .map(|r| MarketVenue::ids(&r))
43 .unwrap_or_default();
44 Self {
45 labels,
46 aliases,
47 venues,
48 chains: scope::chains::registry::client_chain_ids()
49 .iter()
50 .map(|c| c.to_string())
51 .collect(),
52 }
53 }
54}
55
56#[cfg(test)]
57mod tests {
58 use super::*;
59
60 #[test]
61 fn test_load_with_missing_stores_still_has_chains() {
62 let dir = tempfile::tempdir().unwrap();
65 let mut config = Config::default();
66 config.address_book.data_dir = Some(dir.path().join("nothing-here"));
67 let v = Vocab::load(&config);
68 assert!(v.labels.is_empty());
69 assert!(v.chains.iter().any(|c| c == "ethereum"));
70 }
71
72 #[test]
73 fn test_load_with_corrupt_address_book_gives_empty_labels() {
74 let dir = tempfile::tempdir().unwrap();
75 std::fs::write(dir.path().join("address_book.yaml"), "addresses: [unclosed").unwrap();
76 let mut config = Config::default();
77 config.address_book.data_dir = Some(dir.path().to_path_buf());
78 let v = Vocab::load(&config);
79 assert!(v.labels.is_empty());
80 }
81
82 #[test]
83 fn test_labels_come_from_the_address_book() {
84 let dir = tempfile::tempdir().unwrap();
85 std::fs::write(
86 dir.path().join("address_book.yaml"),
87 "addresses:\n - address: '0x1'\n label: cold\n chain: ethereum\n tags: []\n added_at: 0\n",
88 )
89 .unwrap();
90 let mut config = Config::default();
91 config.address_book.data_dir = Some(dir.path().to_path_buf());
92 assert_eq!(Vocab::load(&config).labels, vec!["cold"]);
93 }
94}