trident_explorer/
account.rs

1use crate::output::pretty_lamports_to_sol;
2use console::style;
3use serde::Serialize;
4use solana_sdk::{account::Account, pubkey::Pubkey};
5use std::fmt;
6
7#[derive(Serialize)]
8pub struct KeyedAccount {
9    pub pubkey: Pubkey,
10    pub account: Account,
11}
12
13pub struct AccountFieldVisibility {
14    lamports: bool,
15    data: bool,
16    owner: bool,
17    executable: bool,
18    rent_epoch: bool,
19}
20
21impl AccountFieldVisibility {
22    pub fn new_all_enabled() -> Self {
23        Self {
24            lamports: true,
25            data: true,
26            owner: true,
27            executable: true,
28            rent_epoch: true,
29        }
30    }
31
32    pub fn new_all_disabled() -> Self {
33        Self {
34            lamports: false,
35            data: false,
36            owner: false,
37            executable: false,
38            rent_epoch: false,
39        }
40    }
41
42    pub fn lamports(&self) -> bool {
43        self.lamports
44    }
45
46    pub fn enable_lamports(&mut self) -> &mut Self {
47        self.lamports = true;
48        self
49    }
50
51    pub fn disable_lamports(&mut self) -> &mut Self {
52        self.lamports = false;
53        self
54    }
55
56    pub fn data(&self) -> bool {
57        self.data
58    }
59
60    pub fn enable_data(&mut self) -> &mut Self {
61        self.data = true;
62        self
63    }
64
65    pub fn disable_data(&mut self) -> &mut Self {
66        self.data = false;
67        self
68    }
69
70    pub fn owner(&self) -> bool {
71        self.owner
72    }
73
74    pub fn enable_owner(&mut self) -> &mut Self {
75        self.owner = true;
76        self
77    }
78
79    pub fn disable_owner(&mut self) -> &mut Self {
80        self.owner = false;
81        self
82    }
83
84    pub fn executable(&self) -> bool {
85        self.executable
86    }
87
88    pub fn enable_executable(&mut self) -> &mut Self {
89        self.executable = true;
90        self
91    }
92
93    pub fn disable_executable(&mut self) -> &mut Self {
94        self.executable = false;
95        self
96    }
97
98    pub fn rent_epoch(&self) -> bool {
99        self.rent_epoch
100    }
101
102    pub fn enable_rent_epoch(&mut self) -> &mut Self {
103        self.rent_epoch = true;
104        self
105    }
106
107    pub fn disable_rent_epoch(&mut self) -> &mut Self {
108        self.rent_epoch = false;
109        self
110    }
111}
112
113#[derive(Serialize)]
114pub struct DisplayAccount {
115    #[serde(skip_serializing_if = "Option::is_none")]
116    pub lamports: Option<u64>,
117    #[serde(skip_serializing_if = "Option::is_none")]
118    pub data: Option<String>,
119    #[serde(skip_serializing_if = "Option::is_none")]
120    pub owner: Option<String>,
121    #[serde(skip_serializing_if = "Option::is_none")]
122    pub executable: Option<bool>,
123    #[serde(skip_serializing_if = "Option::is_none")]
124    pub rent_epoch: Option<u64>,
125}
126
127#[derive(Serialize)]
128pub struct DisplayKeyedAccount {
129    pub pubkey: String,
130    pub account: DisplayAccount,
131}
132
133impl DisplayKeyedAccount {
134    pub fn from_keyed_account(
135        keyed_account: &KeyedAccount,
136        visibility: &AccountFieldVisibility,
137    ) -> Self {
138        Self {
139            pubkey: keyed_account.pubkey.to_string(),
140            account: DisplayAccount {
141                lamports: if visibility.lamports {
142                    Some(keyed_account.account.lamports)
143                } else {
144                    None
145                },
146                data: if visibility.data {
147                    Some(base64::encode(&keyed_account.account.data))
148                } else {
149                    None
150                },
151                owner: if visibility.owner {
152                    Some(keyed_account.account.owner.to_string())
153                } else {
154                    None
155                },
156                executable: if visibility.executable {
157                    Some(keyed_account.account.executable)
158                } else {
159                    None
160                },
161                rent_epoch: if visibility.rent_epoch {
162                    Some(keyed_account.account.rent_epoch)
163                } else {
164                    None
165                },
166            },
167        }
168    }
169}
170
171impl fmt::Display for DisplayKeyedAccount {
172    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
173        writeln!(
174            f,
175            "========================================================"
176        )?;
177        writeln!(f, "{} {}", style("Public Key:").bold(), self.pubkey)?;
178        writeln!(
179            f,
180            "========================================================"
181        )?;
182
183        if let Some(lamports) = self.account.lamports {
184            writeln!(f)?;
185            write!(
186                f,
187                "{} {} (◎ {})",
188                style("Lamports:").bold(),
189                lamports,
190                pretty_lamports_to_sol(lamports)
191            )?;
192        }
193        if let Some(data) = &self.account.data {
194            writeln!(f)?;
195            if data.is_empty() {
196                write!(f, "{} [Empty]", style("Data:").bold())?;
197            } else {
198                write!(f, "{} [Hexdump below]", style("Data:").bold())?;
199            }
200        }
201        if let Some(owner) = &self.account.owner {
202            writeln!(f)?;
203            write!(f, "{} {}", style("Owner").bold(), owner)?;
204        }
205        if let Some(executable) = self.account.executable {
206            writeln!(f)?;
207            write!(f, "{} {}", style("Executable:").bold(), executable)?;
208        }
209        if let Some(rent_epoch) = self.account.rent_epoch {
210            writeln!(f)?;
211            write!(f, "{} {}", style("Rent Epoch:").bold(), rent_epoch)?;
212        }
213
214        Ok(())
215    }
216}