1use std::fmt::Debug;
2
3use serde_json::{self, Value};
4
5use crate::api::v1::structs::{ABIResponse, EncodingError, GetBlockResponse, ServerError};
6use crate::{
7 api::{
8 client::Provider,
9 v1::structs::{
10 AccountObject, ClientError, ErrorResponse, GetInfoResponse, GetTableRowsParams,
11 GetTableRowsResponse, SendTransactionResponse, SendTransactionResponseError,
12 TableIndexType,
13 },
14 },
15 chain::{
16 name::Name,
17 transaction::{CompressionType, PackedTransaction, SignedTransaction},
18 Decoder, Packer,
19 },
20 name,
21 serializer::formatter::{JSONObject, ValueTo},
22 util::hex_to_bytes,
23};
24
25#[derive(Debug, Default, Clone)]
26pub struct ChainAPI<T: Provider> {
27 provider: T,
28}
29
30impl<T: Provider> ChainAPI<T> {
31 pub fn new(provider: T) -> Self {
32 ChainAPI { provider }
33 }
34
35 pub async fn get_account(
38 &self,
39 account_name: String,
40 ) -> Result<AccountObject, ClientError<ErrorResponse>> {
41 let payload = serde_json::json!({ "account_name": account_name });
42
43 let result = self
44 .provider
45 .post(
46 String::from("/v1/chain/get_account"),
47 Some(payload.to_string()),
48 )
49 .await;
50
51 match result {
52 Ok(response) => {
53 match serde_json::from_str::<AccountObject>(&response) {
54 Ok(account_object) => Ok(account_object),
55 Err(_) => {
56 match serde_json::from_str::<ErrorResponse>(&response) {
58 Ok(error_response) => Err(ClientError::SERVER(ServerError {
59 error: error_response,
60 })),
61 Err(_) => Err(ClientError::ENCODING(EncodingError {
62 message: "Failed to parse JSON".into(),
63 })),
64 }
65 }
66 }
67 }
68 Err(msg) => Err(ClientError::NETWORK(msg)),
69 }
70 }
71
72 pub async fn get_abi(
73 &self,
74 account_name: String,
75 ) -> Result<ABIResponse, ClientError<ErrorResponse>> {
76 let payload = serde_json::json!({
77 "account_name": account_name,
78 });
79
80 let result = self
81 .provider
82 .post(String::from("/v1/chain/get_abi"), Some(payload.to_string()))
83 .await;
84
85 match result {
86 Ok(response) => {
87 match serde_json::from_str::<ABIResponse>(&response) {
88 Ok(abi_response) => Ok(abi_response),
89 Err(_) => {
90 match serde_json::from_str::<ErrorResponse>(&response) {
92 Ok(error_response) => Err(ClientError::SERVER(ServerError {
93 error: error_response,
94 })),
95 Err(_) => Err(ClientError::ENCODING(EncodingError {
96 message: "Failed to parse JSON".into(),
97 })),
98 }
99 }
100 }
101 }
102 Err(msg) => Err(ClientError::NETWORK(msg)),
103 }
104 }
105
106 pub async fn get_block(
107 &self,
108 block_num_or_id: String,
109 ) -> Result<GetBlockResponse, ClientError<ErrorResponse>> {
110 let payload = serde_json::json!({
111 "block_num_or_id": block_num_or_id,
112 });
113
114 let result = self
115 .provider
116 .post(
117 String::from("/v1/chain/get_block"),
118 Some(payload.to_string()),
119 )
120 .await;
121
122 match result {
123 Ok(response) => {
124 match serde_json::from_str::<GetBlockResponse>(&response) {
125 Ok(block_response) => Ok(block_response),
126 Err(_) => {
127 match serde_json::from_str::<ErrorResponse>(&response) {
129 Ok(error_response) => Err(ClientError::SERVER(ServerError {
130 error: error_response,
131 })),
132 Err(_) => Err(ClientError::ENCODING(EncodingError {
133 message: "Failed to parse JSON".into(),
134 })),
135 }
136 }
137 }
138 }
139 Err(msg) => Err(ClientError::NETWORK(msg)),
140 }
141 }
142
143 pub async fn get_info(&self) -> Result<GetInfoResponse, ClientError<()>> {
144 let result = self.provider.get(String::from("/v1/chain/get_info")).await;
145
146 match result {
147 Ok(response) => serde_json::from_str::<GetInfoResponse>(&response).map_err(|e| {
148 let message = format!("Failed to parse JSON: {}", e);
149 ClientError::encoding(message)
150 }),
151 Err(_) => Err(ClientError::encoding("Request failed".into())),
152 }
153 }
154
155 pub async fn send_transaction(
156 &self,
157 trx: SignedTransaction,
158 ) -> Result<SendTransactionResponse, ClientError<SendTransactionResponseError>> {
159 let packed = PackedTransaction::from_signed(trx, CompressionType::ZLIB)
160 .map_err(|_| ClientError::encoding("Failed to pack transaction".into()))?;
161
162 let trx_json = packed.to_json();
163 let result = self
164 .provider
165 .post(String::from("/v1/chain/send_transaction"), Some(trx_json))
166 .await
167 .map_err(|_| ClientError::NETWORK("Failed to send transaction".into()))?;
168
169 match serde_json::from_str::<SendTransactionResponse>(&result) {
171 Ok(response) => Ok(response),
172 Err(_) => {
173 match serde_json::from_str::<ErrorResponse>(&result) {
175 Ok(error_response) => {
176 Err(ClientError::SERVER(ServerError {
178 error: error_response.error,
179 }))
180 }
181 Err(e) => {
182 Err(ClientError::ENCODING(EncodingError {
184 message: format!("Failed to parse response: {}", e),
185 }))
186 }
187 }
188 }
189 }
190 }
191
192 pub async fn get_table_rows<P: Packer + Default>(
193 &self,
194 params: GetTableRowsParams,
195 ) -> Result<GetTableRowsResponse<P>, ClientError<()>> {
196 let result = self.provider.post(
197 String::from("/v1/chain/get_table_rows"),
198 Some(params.to_json()),
199 );
200
201 let json: Value = serde_json::from_str(result.await.unwrap().as_str()).unwrap();
202 let response_obj = JSONObject::new(json);
203 let more = response_obj.get_bool("more")?;
204 let next_key_str = response_obj.get_string("next_key")?;
205 let rows_value = response_obj.get_vec("rows")?;
206 let mut rows: Vec<P> = Vec::with_capacity(rows_value.len());
207 for encoded_row in rows_value {
208 let row_bytes_hex = &ValueTo::string(Some(encoded_row))?;
209 let row_bytes = hex_to_bytes(row_bytes_hex);
210 let mut decoder = Decoder::new(&row_bytes);
211 let mut row = P::default();
212 decoder.unpack(&mut row);
213 rows.push(row);
214 }
215
216 let next_key = TableIndexType::NAME(name!(next_key_str.as_str()));
217
218 Ok(GetTableRowsResponse {
219 rows,
220 more,
221 ram_payers: None,
222 next_key: Some(next_key),
223 })
224 }
225}