solders_account_decoder/
lib.rs1use solders_traits_core::{
2 handle_py_value_err, py_from_bytes_general_via_bincode, pybytes_general_via_bincode,
3 RichcmpEqualityOnly,
4};
5use std::fmt::Display;
6
7use derive_more::{From, Into};
8use pyo3::prelude::*;
9use pythonize::{depythonize, pythonize};
10use serde::{Deserialize, Serialize};
11use serde_json::Value;
12use solana_account_decoder::{
13 parse_account_data::ParsedAccount as ParsedAccountOriginal,
14 parse_token::UiTokenAmount as UiTokenAmountOriginal,
15 UiAccountEncoding as UiAccountEncodingOriginal, UiDataSliceConfig as UiDataSliceConfigOriginal,
16};
17use solders_macros::{common_methods, enum_original_mapping, richcmp_eq_only};
18
19#[pyclass(module = "solders.account_decoder")]
26#[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq, Eq, Hash, From, Into)]
27pub struct UiDataSliceConfig(UiDataSliceConfigOriginal);
28
29#[richcmp_eq_only]
30#[pymethods]
31impl UiDataSliceConfig {
32 #[new]
33 fn new(offset: usize, length: usize) -> Self {
34 Self(UiDataSliceConfigOriginal { offset, length })
35 }
36
37 #[getter]
38 pub fn offset(&self) -> usize {
39 self.0.offset
40 }
41
42 #[getter]
43 pub fn length(&self) -> usize {
44 self.0.length
45 }
46
47 pub fn __repr__(&self) -> String {
48 format!("{self:#?}")
49 }
50}
51
52impl RichcmpEqualityOnly for UiDataSliceConfig {}
53
54#[pyclass(module = "solders.account_decoder")]
56#[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq, Eq, Hash)]
57#[serde(rename_all = "camelCase")]
58#[enum_original_mapping(UiAccountEncodingOriginal)]
59pub enum UiAccountEncoding {
60 Binary, Base58,
62 Base64,
63 JsonParsed,
64 #[serde(rename = "base64+zstd")]
65 Base64Zstd,
66}
67
68#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, From, Into)]
69#[pyclass(module = "solders.account_decoder")]
70pub struct ParsedAccount(pub ParsedAccountOriginal);
71
72impl RichcmpEqualityOnly for ParsedAccount {}
73impl Display for ParsedAccount {
74 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
75 write!(f, "{self:?}")
76 }
77}
78pybytes_general_via_bincode!(ParsedAccount);
79py_from_bytes_general_via_bincode!(ParsedAccount);
80solders_traits_core::common_methods_default!(ParsedAccount);
81
82#[richcmp_eq_only]
83#[common_methods]
84#[pymethods]
85impl ParsedAccount {
86 #[new]
87 pub fn new(program: &str, parsed: &PyAny, space: u64) -> PyResult<Self> {
88 let value = handle_py_value_err(depythonize::<Value>(parsed))?;
89 Ok(ParsedAccountOriginal {
90 program: program.to_owned(),
91 parsed: value,
92 space,
93 }
94 .into())
95 }
96
97 #[getter]
98 pub fn program(&self) -> String {
99 self.0.program.clone()
100 }
101
102 #[getter]
103 pub fn parsed(&self, py: Python<'_>) -> PyResult<PyObject> {
104 handle_py_value_err(pythonize(py, &self.0.parsed))
105 }
106
107 #[getter]
108 pub fn space(&self) -> u64 {
109 self.0.space
110 }
111}
112
113#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, From, Into)]
114#[pyclass(module = "solders.account_decoder")]
115pub struct UiTokenAmount(UiTokenAmountOriginal);
116
117impl RichcmpEqualityOnly for UiTokenAmount {}
118impl Display for UiTokenAmount {
119 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
120 write!(f, "{self:?}")
121 }
122}
123pybytes_general_via_bincode!(UiTokenAmount);
124py_from_bytes_general_via_bincode!(UiTokenAmount);
125solders_traits_core::common_methods_default!(UiTokenAmount);
126
127#[richcmp_eq_only]
128#[common_methods]
129#[pymethods]
130impl UiTokenAmount {
131 #[pyo3(
132 signature = (ui_amount, decimals, amount, ui_amount_string)
133 )]
134 #[new]
135 pub fn new(
136 ui_amount: Option<f64>,
137 decimals: u8,
138 amount: String,
139 ui_amount_string: String,
140 ) -> PyResult<Self> {
141 Ok(UiTokenAmountOriginal {
142 ui_amount,
143 decimals,
144 amount,
145 ui_amount_string,
146 }
147 .into())
148 }
149
150 #[getter]
151 pub fn ui_amount(&self) -> Option<f64> {
152 self.0.ui_amount
153 }
154
155 #[getter]
156 pub fn decimals(&self) -> u8 {
157 self.0.decimals
158 }
159
160 #[getter]
161 pub fn amount(&self) -> String {
162 self.0.amount.clone()
163 }
164
165 #[getter]
166 pub fn ui_amount_string(&self) -> String {
167 self.0.ui_amount_string.clone()
168 }
169}
170
171pub fn create_account_decoder_mod(py: Python<'_>) -> PyResult<&PyModule> {
172 let m = PyModule::new(py, "account_decoder")?;
173 m.add_class::<UiDataSliceConfig>()?;
174 m.add_class::<UiAccountEncoding>()?;
175 m.add_class::<ParsedAccount>()?;
176 m.add_class::<UiTokenAmount>()?;
177 Ok(m)
178}