1use serde::{Deserialize, Serialize};
7use std::collections::HashMap;
8
9const RAW_BASE: &str = "https://raw.githubusercontent.com/cosmos/chain-registry/master";
10
11#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
13pub struct Chain {
14 #[serde(rename = "$schema")]
15 pub dollar_schema: String,
16
17 #[serde(rename = "chain_name")]
18 pub chain_name: String,
19
20 #[serde(rename = "chain_type")]
21 pub chain_type: String,
22
23 #[serde(rename = "status")]
24 pub status: String,
25}
26
27#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
29pub struct AssetList {
30 #[serde(rename = "$schema")]
31 pub dollar_schema: String,
32 #[serde(rename = "chain_name")]
33 pub chain_name: String,
34 pub assets: Vec<Asset>,
35}
36
37#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
38pub struct Asset {
39 pub denom_units: Vec<DenomUnit>,
40 pub type_asset: String,
41 pub base: String,
42 pub display: String,
43 pub name: String,
44 pub symbol: String,
45 #[serde(rename = "logo_URIs")]
46 pub logo_uris: Option<LogoUris>,
47}
48
49#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
50pub struct DenomUnit {
51 pub denom: String,
52 pub exponent: Option<u32>,
53 pub aliases: Option<Vec<String>>,
54}
55
56#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
57pub struct LogoUris {
58 pub png: Option<String>,
59 pub svg: Option<String>,
60}
61
62#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
64pub struct MemoKeys {
65 #[serde(rename = "$schema")]
66 pub dollar_schema: String,
67 #[serde(rename = "memo_keys")]
68 pub memo_keys: Vec<MemoKey>,
69}
70
71#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
72pub struct MemoKey {
73 pub key: String,
74 pub description: String,
75 #[serde(rename = "git_repo")]
76 pub git_repo: String,
77 pub memo: HashMap<String, serde_json::Value>,
78}
79
80#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
82pub struct IbcData {
83 #[serde(rename = "$schema")]
84 pub dollar_schema: String,
85 #[serde(rename = "chain_1")]
86 pub chain_1: ChainInfo,
87 #[serde(rename = "chain_2")]
88 pub chain_2: ChainInfo,
89 pub channels: Vec<Channel>,
90 pub operators: Option<Vec<Operator>>,
91}
92
93#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
94pub struct ChainInfo {
95 #[serde(rename = "chain_name")]
96 pub chain_name: String,
97 #[serde(rename = "chain_id")]
98 pub chain_id: String,
99 #[serde(rename = "client_id")]
100 pub client_id: String,
101 #[serde(rename = "connection_id")]
102 pub connection_id: String,
103}
104
105#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
106pub struct Channel {
107 #[serde(rename = "chain_1")]
108 pub chain_1: ChannelInfo,
109 #[serde(rename = "chain_2")]
110 pub chain_2: ChannelInfo,
111 pub ordering: String,
112 pub version: String,
113 pub fee_version: Option<String>,
114 pub tags: Option<ChannelTags>,
115}
116
117#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
118pub struct ChannelInfo {
119 pub channel_id: String,
120 pub port_id: String,
121 pub client_id: Option<String>,
122 pub connection_id: Option<String>,
123}
124
125#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
126pub struct ChannelTags {
127 pub preferred: Option<bool>,
128 pub status: Option<String>,
129}
130
131#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
132pub struct Operator {
133 #[serde(rename = "chain_1")]
134 pub chain_1: OperatorInfo,
135 #[serde(rename = "chain_2")]
136 pub chain_2: OperatorInfo,
137 pub memo: String,
138 pub name: String,
139 pub discord_handle: Option<String>,
140}
141
142#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
143pub struct OperatorInfo {
144 pub address: Option<String>,
145}
146
147fn chain_url(name: &str) -> String {
148 format!("{}/{}/chain.json", RAW_BASE, name)
149}
150
151fn assetlist_url(name: &str) -> String {
152 format!("{}/{}/assetlist.json", RAW_BASE, name)
153}
154
155fn memo_keys_url() -> String {
156 format!("{}/_memo_keys/ICS20_memo_keys.json", RAW_BASE)
157}
158
159
160pub fn ibc_connection_url(a: &str, b: &str) -> String {
161 let (x, y) = if a <= b { (a, b) } else { (b, a) };
162 format!("{}/_IBC/{}-{}.json", RAW_BASE, x, y)
163}
164
165fn versions_url(name: &str) -> String {
166 format!("{}/{}/versions.json", RAW_BASE, name)
167}
168
169pub async fn fetch_ibc_connection(chain_a: &str, chain_b: &str) -> Result<IbcData, reqwest::Error> {
171 if chain_a.is_empty() || chain_b.is_empty() {
172 }
175 let url = ibc_connection_url(chain_a, chain_b);
176 let resp = reqwest::Client::new()
177 .get(url)
178 .header("Accept", "application/json")
179 .header("User-Agent", "chain-registry-interface-rust/0.0")
180 .send()
181 .await?;
182 let d = resp.json::<IbcData>().await?;
183 Ok(d)
184}
185
186pub async fn fetch_chain(chain_name: &str) -> Result<Chain, reqwest::Error> {
189 let url = chain_url(chain_name);
190 let resp = reqwest::Client::new()
191 .get(url)
192 .header("Accept", "application/json")
193 .header("User-Agent", "chain-registry-interface-rust/0.0")
194 .send()
195 .await?;
196 let chain = resp.json::<Chain>().await?;
197 Ok(chain)
198}
199
200pub async fn fetch_asset_list(chain_name: &str) -> Result<AssetList, reqwest::Error> {
202 let url = assetlist_url(chain_name);
203 let resp = reqwest::Client::new()
204 .get(url)
205 .header("Accept", "application/json")
206 .header("User-Agent", "chain-registry-interface-rust/0.0")
207 .send()
208 .await?;
209 let al = resp.json::<AssetList>().await?;
210 Ok(al)
211}
212
213pub async fn fetch_memo_keys(_chain_name: &str) -> Result<MemoKeys, reqwest::Error> {
215 let url = memo_keys_url();
216 let resp = reqwest::Client::new()
217 .get(url)
218 .header("Accept", "application/json")
219 .header("User-Agent", "chain-registry-interface-rust/0.0")
220 .send()
221 .await?;
222 let mk = resp.json::<MemoKeys>().await?;
223 Ok(mk)
224}
225
226
227pub async fn fetch_versions(chain_name: &str) -> Result<Versions, reqwest::Error> {
229 let url = versions_url(chain_name);
230 let resp = reqwest::Client::new()
231 .get(url)
232 .header("Accept", "application/json")
233 .header("User-Agent", "chain-registry-interface-rust/0.0")
234 .send()
235 .await?;
236 let v = resp.json::<Versions>().await?;
237 Ok(v)
238}
239
240
241#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
243pub struct Versions {
244 #[serde(rename = "$schema")]
245 pub dollar_schema: String,
246 #[serde(rename = "chain_name")]
247 pub chain_name: String,
248 pub versions: Vec<ChainVersion>,
249}
250
251#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
252pub struct ChainVersion {
253 pub name: String,
254 pub tag: Option<String>,
255 pub height: Option<f64>,
256 pub proposal: Option<f64>,
257 #[serde(rename = "previous_version_name")]
258 pub previous_version_name: Option<String>,
259 #[serde(rename = "next_version_name")]
260 pub next_version_name: Option<String>,
261 #[serde(rename = "recommended_version")]
262 pub recommended_version: Option<String>,
263 #[serde(rename = "compatible_versions")]
264 pub compatible_versions: Option<Vec<String>>,
265 pub sdk: Option<SdkInfo>,
266 pub consensus: Option<ConsensusInfo>,
267 pub cosmwasm: Option<CosmwasmInfo>,
268 pub ibc: Option<IbcInfo>,
269 pub language: Option<LanguageInfo>,
270 pub binaries: Option<Binaries>,
271}
272
273#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
274pub struct SdkInfo {
275 #[serde(rename = "type")]
276 pub r#type: String,
277 pub version: Option<String>,
278 pub repo: Option<String>,
279 pub tag: Option<String>,
280}
281
282#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
283pub struct ConsensusInfo {
284 #[serde(rename = "type")]
285 pub r#type: String,
286 pub version: Option<String>,
287 pub repo: Option<String>,
288 pub tag: Option<String>,
289}
290
291#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
292pub struct CosmwasmInfo {
293 pub version: Option<String>,
294 pub repo: Option<String>,
295 pub tag: Option<String>,
296 pub enabled: Option<bool>,
297 pub path: Option<String>,
298}
299
300#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
301pub struct IbcInfo {
302 #[serde(rename = "type")]
303 pub r#type: String,
304 pub version: Option<String>,
305 pub repo: Option<String>,
306 pub tag: Option<String>,
307 #[serde(rename = "ics_enabled")]
308 pub ics_enabled: Option<Vec<String>>,
309}
310
311#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
312pub struct LanguageInfo {
313 #[serde(rename = "type")]
314 pub r#type: String,
315 pub version: Option<String>,
316 pub repo: Option<String>,
317 pub tag: Option<String>,
318}
319
320#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
321pub struct Binaries {
322 #[serde(rename = "linux/amd64")]
323 pub linux_amd64: Option<String>,
324 #[serde(rename = "linux/arm64")]
325 pub linux_arm64: Option<String>,
326 #[serde(rename = "darwin/amd64")]
327 pub darwin_amd64: Option<String>,
328 #[serde(rename = "darwin/arm64")]
329 pub darwin_arm64: Option<String>,
330 #[serde(rename = "windows/amd64")]
331 pub windows_amd64: Option<String>,
332 #[serde(rename = "windows/arm64")]
333 pub windows_arm64: Option<String>,
334}