1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
const EXPLORER_URL: &str = "https://explorer.solana.com";
const CK_EXPLORER_URL: &str = "https://explorer.clockwork.xyz";
#[derive(Default)]
pub struct Explorer {
cluster: String,
custom_rpc: Option<String>,
}
impl From<String> for Explorer {
fn from(json_rpc_url: String) -> Self {
match &json_rpc_url.to_lowercase() {
url if url.contains("devnet") => Explorer::devnet(),
url if url.contains("testnet") => Explorer::testnet(),
url if url.contains("mainnet") => Explorer::mainnet(),
_ => {
Explorer::custom(json_rpc_url)
}
}
}
}
impl Explorer {
pub fn mainnet() -> Self {
Self {
cluster: "mainnet-beta".into(),
..Default::default()
}
}
pub fn testnet() -> Self {
Self {
cluster: "testnet".into(),
..Default::default()
}
}
pub fn devnet() -> Self {
Self {
cluster: "devnet".into(),
..Default::default()
}
}
pub fn custom(custom_rpc: String) -> Self {
Self {
cluster: "custom".into(),
custom_rpc: Some(custom_rpc),
}
}
pub fn tx_url<T: std::fmt::Display>(&self, tx: T) -> String {
let url = format!("{}/tx/{}?cluster={}", EXPLORER_URL, tx, self.cluster);
if self.cluster == "custom" {
url + "&customUrl=" + self.custom_rpc.as_ref().unwrap()
} else {
url
}
}
pub fn thread_url<T: std::fmt::Display, U: std::fmt::Display>(&self, thread: T, program_id: U) -> String {
let url = format!("{}/address/{}?programID={}&network={}", CK_EXPLORER_URL,
thread, program_id, self
.cluster);
if self.cluster == "custom" {
url + "&customRPC=" + self.custom_rpc.as_ref().unwrap()
} else {
url
}
}
}