├── .gitignore ├── src ├── stream_api │ ├── mod.rs │ ├── sse.rs │ └── ws.rs ├── rest_api │ ├── mod.rs │ ├── query_params.rs │ ├── error.rs │ ├── base.rs │ ├── models.rs │ └── v2.rs └── lib.rs ├── examples ├── rest_api.rs ├── sse_api.rs └── ws_api.rs ├── Cargo.toml ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | Cargo.lock 3 | -------------------------------------------------------------------------------- /src/stream_api/mod.rs: -------------------------------------------------------------------------------- 1 | mod sse; 2 | mod ws; 3 | 4 | pub use sse::SseApi; 5 | pub use ws::{WsApi, AccountOperations}; -------------------------------------------------------------------------------- /src/rest_api/mod.rs: -------------------------------------------------------------------------------- 1 | mod base; 2 | mod error; 3 | pub mod models; 4 | mod v2; 5 | mod query_params; 6 | 7 | pub use v2::RestApiClientV2; 8 | pub use error::TonApiError; 9 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | mod stream_api; 2 | mod rest_api; 3 | 4 | pub use stream_api::*; 5 | pub use rest_api::*; 6 | 7 | pub enum Network { 8 | Mainnet, 9 | Testnet, 10 | } 11 | -------------------------------------------------------------------------------- /examples/rest_api.rs: -------------------------------------------------------------------------------- 1 | use tonapi::{Network, RestApiClientV2}; 2 | 3 | #[tokio::main] 4 | async fn main() -> Result<(), Box> { 5 | let client = RestApiClientV2::new(Network::Mainnet, None); 6 | 7 | let result = client.get_account("0QCbOix87iy37AwRCWaYhJHzc2gXE_WnAG5vVEAySNT7zClz").await.unwrap(); 8 | println!("Account balance: {}", result.balance); 9 | 10 | Ok(()) 11 | } -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "tonapi" 3 | version = "0.3.2" 4 | edition = "2021" 5 | license = "MIT" 6 | description = "SDK for integrating TonAPI into Rust apps" 7 | repository = "https://github.com/liketurbo/tonapi-rs" 8 | readme = "README.md" 9 | categories = ["cryptography::cryptocurrencies", "web-programming::http-client"] 10 | keywords = ["blockchain", "ton", "tonapi"] 11 | 12 | [dependencies] 13 | serde = { version = "^1.0", features = ["derive"] } 14 | serde_json = "^1.0" 15 | reqwest = { version = "^0.11", features = ["json", "multipart"] } 16 | reqwest-eventsource = "^0.5" 17 | futures = "^0.3" 18 | async-recursion = "^1.0" 19 | tokio = "^1.34" 20 | tokio-tungstenite = { version = "^0.20", features = ["native-tls"] } 21 | futures-util = "^0.3" 22 | log = "^0.4" 23 | url = "^2.5" 24 | anyhow = "^1.0" 25 | 26 | [dev-dependencies] 27 | tokio = { version = "^1.34", features = ["full"] } 28 | simple_logger = "^4.3" -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Rami Chasygov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /examples/sse_api.rs: -------------------------------------------------------------------------------- 1 | use simple_logger::SimpleLogger; 2 | use tonapi::{Network, SseApi}; 3 | 4 | async fn subscribe_to_transactions(sse: &SseApi) -> Result<(), Box> { 5 | let mut stream = sse.transactions_stream( 6 | Some(vec![ 7 | "-1:5555555555555555555555555555555555555555555555555555555555555555".to_string(), 8 | ]), 9 | None, 10 | ); 11 | 12 | while let Ok(evt) = stream.next().await { 13 | if let Some(evt) = evt { 14 | println!("Event: {}", evt.tx_hash); 15 | } else { 16 | // Stream ended 17 | break; 18 | } 19 | } 20 | 21 | Ok(()) 22 | } 23 | 24 | async fn subscribe_to_traces(sse: &SseApi) -> Result<(), Box> { 25 | let mut stream = sse.traces_stream(Some(vec![ 26 | "-1:5555555555555555555555555555555555555555555555555555555555555555".to_string(), 27 | ])); 28 | 29 | while let Ok(evt) = stream.next().await { 30 | if let Some(evt) = evt { 31 | println!("Event: {}", evt.hash); 32 | } else { 33 | // Stream ended 34 | break; 35 | } 36 | } 37 | 38 | Ok(()) 39 | } 40 | 41 | async fn subscribe_to_mempool(sse: &SseApi) -> Result<(), Box> { 42 | let mut stream = sse.mempool_stream(Some(vec![ 43 | "-1:5555555555555555555555555555555555555555555555555555555555555555".to_string(), 44 | ])); 45 | 46 | while let Ok(evt) = stream.next().await { 47 | if let Some(evt) = evt { 48 | println!("Boc: {}", evt.boc); 49 | } else { 50 | // Stream ended 51 | break; 52 | } 53 | } 54 | 55 | Ok(()) 56 | } 57 | 58 | #[tokio::main] 59 | async fn main() -> Result<(), Box> { 60 | SimpleLogger::new().init().expect("logging init"); 61 | 62 | let sse_api = SseApi::new(Network::Mainnet, None); 63 | 64 | let _ = subscribe_to_transactions(&sse_api).await; 65 | let _ = subscribe_to_traces(&sse_api).await; 66 | let _ = subscribe_to_mempool(&sse_api).await; 67 | 68 | Ok(()) 69 | } 70 | -------------------------------------------------------------------------------- /examples/ws_api.rs: -------------------------------------------------------------------------------- 1 | use simple_logger::SimpleLogger; 2 | use tonapi::{AccountOperations, Network, WsApi}; 3 | 4 | async fn subscribe_to_transactions(ws: &WsApi) -> Result<(), Box> { 5 | let mut stream = ws.transactions_stream(Some(vec![AccountOperations { 6 | account: "-1:5555555555555555555555555555555555555555555555555555555555555555".to_string(), 7 | operations: None 8 | }])); 9 | 10 | while let Ok(evt) = stream.next().await { 11 | if let Some(evt) = evt { 12 | println!("Event: {}", evt.params.tx_hash); 13 | } else { 14 | // Stream ended 15 | break; 16 | } 17 | } 18 | 19 | Ok(()) 20 | } 21 | 22 | async fn subscribe_to_traces(ws: &WsApi) -> Result<(), Box> { 23 | let mut stream = ws.traces_stream(Some(vec![ 24 | "-1:5555555555555555555555555555555555555555555555555555555555555555".to_string(), 25 | ])); 26 | 27 | while let Ok(evt) = stream.next().await { 28 | if let Some(evt) = evt { 29 | println!("Event: {}", evt.params.hash); 30 | } else { 31 | // Stream ended 32 | break; 33 | } 34 | } 35 | 36 | Ok(()) 37 | } 38 | 39 | async fn subscribe_to_mempool(ws: &WsApi) -> Result<(), Box> { 40 | let mut stream = ws.mempool_stream(Some(vec![ 41 | "-1:5555555555555555555555555555555555555555555555555555555555555555".to_string(), 42 | ])); 43 | 44 | while let Ok(evt) = stream.next().await { 45 | if let Some(evt) = evt { 46 | println!("Boc: {}", evt.params.boc); 47 | } else { 48 | // Stream ended 49 | break; 50 | } 51 | } 52 | 53 | Ok(()) 54 | } 55 | 56 | #[tokio::main] 57 | async fn main() -> Result<(), Box> { 58 | SimpleLogger::new().init().expect("logging init"); 59 | 60 | let ws_api = WsApi::new(Network::Mainnet, None); 61 | 62 | let _ = subscribe_to_transactions(&ws_api).await; 63 | let _ = subscribe_to_traces(&ws_api).await; 64 | let _ = subscribe_to_mempool(&ws_api).await; 65 | 66 | Ok(()) 67 | } 68 | -------------------------------------------------------------------------------- /src/rest_api/query_params.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | 3 | #[derive(Default)] 4 | pub struct QueryParams(HashMap); 5 | 6 | impl QueryParams { 7 | pub fn new() -> Self { 8 | Self(HashMap::new()) 9 | } 10 | 11 | pub fn from_pairs(pairs: I) -> Self 12 | where 13 | I: IntoIterator, 14 | K: Into, 15 | V: ToQueryParamValue, 16 | { 17 | let mut map = HashMap::new(); 18 | pairs.into_iter().for_each(|(key, value)| { 19 | map.insert(key.into(), value.to_query_param_value()); 20 | }); 21 | Self(map) 22 | } 23 | 24 | pub fn insert(&mut self, key: K, value: V) 25 | where 26 | K: Into, 27 | V: ToQueryParamValue, 28 | { 29 | self.0.insert(key.into(), value.to_query_param_value()); 30 | } 31 | } 32 | 33 | impl IntoIterator for QueryParams { 34 | type Item = (String, String); 35 | type IntoIter = std::collections::hash_map::IntoIter; 36 | 37 | fn into_iter(self) -> Self::IntoIter { 38 | self.0.into_iter() 39 | } 40 | } 41 | 42 | pub(crate) trait ToQueryParamValue { 43 | fn to_query_param_value(self) -> String; 44 | } 45 | 46 | impl ToQueryParamValue for String { 47 | fn to_query_param_value(self) -> String { 48 | self 49 | } 50 | } 51 | 52 | impl<'a> ToQueryParamValue for &'a str { 53 | fn to_query_param_value(self) -> String { 54 | self.to_string() 55 | } 56 | } 57 | 58 | impl ToQueryParamValue for u64 { 59 | fn to_query_param_value(self) -> String { 60 | self.to_string() 61 | } 62 | } 63 | 64 | impl ToQueryParamValue for i64 { 65 | fn to_query_param_value(self) -> String { 66 | self.to_string() 67 | } 68 | } 69 | 70 | impl ToQueryParamValue for i32 { 71 | fn to_query_param_value(self) -> String { 72 | self.to_string() 73 | } 74 | } 75 | 76 | impl ToQueryParamValue for &[&str] { 77 | fn to_query_param_value(self) -> String { 78 | self.join(",") 79 | } 80 | } 81 | 82 | impl ToQueryParamValue for bool { 83 | fn to_query_param_value(self) -> String { 84 | self.to_string() 85 | } 86 | } -------------------------------------------------------------------------------- /src/rest_api/error.rs: -------------------------------------------------------------------------------- 1 | use reqwest::{header::InvalidHeaderValue, Error as ReqwestError}; 2 | use serde_json::Error as SerdeError; 3 | use std::fmt::{self, Display, Formatter}; 4 | use url::ParseError as UrlParseError; 5 | 6 | #[derive(Debug)] 7 | pub enum TonApiError { 8 | InvalidInput(InvalidInput), 9 | ProcessingError(ProcessingError), 10 | RateLimitExceeded, 11 | ApiError { code: u16, message: String }, 12 | } 13 | 14 | #[derive(Debug)] 15 | pub enum InvalidInput { 16 | HeaderValue(InvalidHeaderValue), 17 | UrlParse(UrlParseError), 18 | } 19 | 20 | #[derive(Debug)] 21 | pub enum ProcessingError { 22 | Network(ReqwestError), 23 | Deserialization(SerdeError), 24 | } 25 | 26 | impl fmt::Display for TonApiError { 27 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 28 | match self { 29 | Self::InvalidInput(err) => write!(f, "Invalid input: {}", err), 30 | Self::ProcessingError(err) => write!(f, "Processing error: {}", err), 31 | Self::RateLimitExceeded => write!(f, "Rate limit exceeded"), 32 | Self::ApiError { code, message } => { 33 | write!(f, "Api error (code: {}): {}", code, message) 34 | } 35 | } 36 | } 37 | } 38 | 39 | impl Display for InvalidInput { 40 | fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { 41 | match self { 42 | InvalidInput::HeaderValue(err) => write!(f, "Invalid header value: {}", err), 43 | InvalidInput::UrlParse(err) => write!(f, "URL parse error: {}", err), 44 | } 45 | } 46 | } 47 | 48 | impl fmt::Display for ProcessingError { 49 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 50 | match self { 51 | Self::Network(err) => write!(f, "Network error: {}", err), 52 | Self::Deserialization(err) => write!(f, "Deserialization error: {}", err), 53 | } 54 | } 55 | } 56 | 57 | impl From for TonApiError { 58 | fn from(err: InvalidHeaderValue) -> Self { 59 | Self::InvalidInput(InvalidInput::HeaderValue(err)) 60 | } 61 | } 62 | 63 | impl From for TonApiError { 64 | fn from(err: UrlParseError) -> Self { 65 | Self::InvalidInput(InvalidInput::UrlParse(err)) 66 | } 67 | } 68 | 69 | impl From for TonApiError { 70 | fn from(err: ReqwestError) -> Self { 71 | Self::ProcessingError(ProcessingError::Network(err)) 72 | } 73 | } 74 | 75 | impl From for TonApiError { 76 | fn from(err: SerdeError) -> Self { 77 | Self::ProcessingError(ProcessingError::Deserialization(err)) 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tonapi-rs 2 | 3 | [![Latest version](https://img.shields.io/crates/v/tonapi.svg)](https://crates.io/crates/tonapi) 4 | 5 | This is a SDK, that provides comprehensive support for interacting with the [TonAPI](https://tonapi.io). 6 | 7 | ## Features 8 | 9 | * **Authorization Support**: You can obtain token from [tonconsole.com](https://tonconsole.com). 10 | * **REST API Integration**: Interact with TonAPI RESTful endpoints. 11 | * **Streaming API (SSE, WebSocket)**: Utilize Server-Sent Events (SSE) and WebSocket protocols for real-time data streaming. 12 | * **Comparability with [tonlib-rs](https://github.com/ston-fi/tonlib-rs) Types**: TonAddress 13 | 14 | ## Usage 15 | 16 | ### REST 17 | 18 | ```rust 19 | #[tokio::main] 20 | async fn main() -> Result<(), Box> { 21 | let client = RestApiClientV2::new(Network::Mainnet, None); 22 | 23 | let result = client.get_account(ACCOUNT_ID).await.unwrap(); 24 | println!("Account balance: {}", result.balance); 25 | 26 | Ok(()) 27 | } 28 | ``` 29 | 30 | ## SSE 31 | 32 | ```rust 33 | #[tokio::main] 34 | async fn main() -> Result<(), Box> { 35 | let sse_api = SseApi::new(Network::Mainnet, None); 36 | 37 | let mut stream = sse_api.transactions_stream( 38 | Some(vec![ 39 | "-1:5555555555555555555555555555555555555555555555555555555555555555".to_string(), 40 | ]), 41 | None, 42 | ); 43 | 44 | while let Ok(evt) = stream.next().await { 45 | if let Some(evt) = evt { 46 | println!("Event: {}", evt.tx_hash); 47 | } else { 48 | // Stream ended 49 | break; 50 | } 51 | } 52 | 53 | Ok(()) 54 | } 55 | ``` 56 | 57 | ## WebSocket 58 | 59 | ```rust 60 | #[tokio::main] 61 | async fn main() -> Result<(), Box> { 62 | let ws_api = WsApi::new(Network::Mainnet, None); 63 | 64 | let mut stream = ws.transactions_stream(Some(vec![AccountOperations { 65 | account: "-1:5555555555555555555555555555555555555555555555555555555555555555".to_string(), 66 | operations: None 67 | }])); 68 | 69 | while let Ok(evt) = stream.next().await { 70 | if let Some(evt) = evt { 71 | println!("Event: {}", evt.params.tx_hash); 72 | } else { 73 | // Stream ended 74 | break; 75 | } 76 | } 77 | 78 | Ok(()) 79 | } 80 | 81 | ``` 82 | 83 | ## Contributing 84 | 85 | Contributions to this library is welcomed! If you'd like to contribute, please feel free to open a pull request on GitHub. Your input is highly appreciated and helps improve the SDK for the entire TON community. 86 | -------------------------------------------------------------------------------- /src/rest_api/base.rs: -------------------------------------------------------------------------------- 1 | use log::debug; 2 | use reqwest::{header::HeaderMap, Client, Method, RequestBuilder, StatusCode}; 3 | use serde::{de::DeserializeOwned, Serialize}; 4 | 5 | use super::{error::TonApiError, models::ApiResponse, query_params::QueryParams}; 6 | 7 | pub struct BaseRestApiClient { 8 | client: Client, 9 | base_url: String, 10 | api_key: Option, 11 | } 12 | 13 | impl BaseRestApiClient { 14 | pub fn new(client: Client, base_url: String, api_key: Option) -> Self { 15 | Self { 16 | client, 17 | base_url, 18 | api_key, 19 | } 20 | } 21 | 22 | pub async fn get( 23 | &self, 24 | endpoint: String, 25 | params: Option, 26 | headers: Option, 27 | ) -> Result { 28 | let request_builder = self.build_request(Method::GET, endpoint, params, headers)?; 29 | self.send_request(request_builder).await 30 | } 31 | 32 | pub async fn post_json( 33 | &self, 34 | endpoint: String, 35 | params: Option, 36 | body: Option, 37 | headers: Option, 38 | ) -> Result { 39 | let request_builder = self.build_request(Method::POST, endpoint, params, headers)?; 40 | let request_builder = if let Some(body) = body { 41 | request_builder.json(&body) 42 | } else { 43 | request_builder 44 | }; 45 | self.send_request(request_builder).await 46 | } 47 | 48 | pub async fn put_bytes( 49 | &self, 50 | endpoint: String, 51 | params: Option, 52 | body: Option>, 53 | headers: Option, 54 | ) -> Result { 55 | let request_builder = self.build_request(Method::PUT, endpoint, params, headers)?; 56 | let request_builder = if let Some(body) = body { 57 | request_builder.json(&body) 58 | } else { 59 | request_builder 60 | }; 61 | self.send_request(request_builder).await 62 | } 63 | 64 | fn build_request( 65 | &self, 66 | method: Method, 67 | endpoint: String, 68 | params: Option, 69 | headers: Option, 70 | ) -> Result { 71 | let headers = headers.unwrap_or_default(); 72 | let query_params = params.unwrap_or_default(); 73 | 74 | let url = format!("{}{}", self.base_url, endpoint); 75 | let url_with_params = reqwest::Url::parse_with_params(&url, query_params)?; 76 | let mut request_builder = match method { 77 | Method::GET => self.client.get(url_with_params).headers(headers), 78 | Method::POST => self.client.post(url_with_params).headers(headers), 79 | Method::PUT => self.client.put(url_with_params).headers(headers), 80 | _ => unimplemented!(), 81 | }; 82 | debug!("Request after processing: {:?}", request_builder); 83 | 84 | if let Some(ref api_key) = self.api_key { 85 | request_builder = request_builder.bearer_auth(api_key); 86 | } 87 | 88 | Ok(request_builder) 89 | } 90 | 91 | async fn send_request( 92 | &self, 93 | request_builder: RequestBuilder, 94 | ) -> Result { 95 | let response = request_builder.send().await?; 96 | debug!("Received response: {:?}", response); 97 | 98 | let status = response.status(); 99 | 100 | if let Some(length) = response.content_length() { 101 | if status.is_success() && length == 0 { 102 | return Ok(serde_json::from_value(serde_json::Value::Null) 103 | .expect("Can't serialize null value")); 104 | } 105 | } 106 | 107 | let response_text = response.text().await?; 108 | debug!("Response text: {}", response_text); 109 | 110 | let response_body: ApiResponse = serde_json::from_str(&response_text)?; 111 | debug!("Response body: {:?}", response_body); 112 | 113 | match response_body { 114 | ApiResponse::Success { result } => Ok(result), 115 | ApiResponse::Error { error } => match status { 116 | StatusCode::TOO_MANY_REQUESTS => Err(TonApiError::RateLimitExceeded), 117 | _ => Err(TonApiError::ApiError { 118 | code: status.as_u16(), 119 | message: error, 120 | }), 121 | }, 122 | } 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/stream_api/sse.rs: -------------------------------------------------------------------------------- 1 | use async_recursion::async_recursion; 2 | use futures::stream::StreamExt; 3 | use log::debug; 4 | use reqwest::RequestBuilder; 5 | use reqwest_eventsource::{Event, EventSource}; 6 | use serde::Deserialize; 7 | 8 | use crate::Network; 9 | 10 | mod constants { 11 | include!(concat!(env!("OUT_DIR"), "/constants.rs")); 12 | } 13 | 14 | pub struct SseApi { 15 | connect_request: reqwest::Request, 16 | } 17 | 18 | impl SseApi { 19 | pub fn new(network: Network, api_key: Option) -> Self { 20 | let client = reqwest::Client::builder() 21 | .user_agent(constants::USER_AGENT) 22 | .build() 23 | .expect("build client"); 24 | 25 | let base_url = match network { 26 | Network::Mainnet => "https://tonapi.io/v2/sse/", 27 | Network::Testnet => "https://testnet.tonapi.io/v2/sse/", 28 | }; 29 | 30 | let mut builder = client.get(reqwest::Url::parse(base_url).expect("docs url")); 31 | 32 | if let Some(api_key) = api_key { 33 | builder = builder.bearer_auth(api_key); 34 | } 35 | 36 | let connect_request = builder.build().expect("build request"); 37 | 38 | SseApi { connect_request } 39 | } 40 | 41 | pub fn transactions_stream(&self, accounts: Option>, operations: Option>) -> TransactionsStream { 42 | let mut connect_request = self.connect_request.try_clone().expect("clone request"); 43 | let url = connect_request.url_mut(); 44 | 45 | *url = url 46 | .join("accounts/transactions") 47 | .expect("accounts/transactions join with base"); 48 | 49 | let accounts = accounts.and_then(|a| { 50 | if a.is_empty() { 51 | return None; 52 | } 53 | Some(a) 54 | }); 55 | let operations = operations.and_then(|o| { 56 | if o.is_empty() { 57 | return None; 58 | } 59 | Some(o) 60 | }); 61 | 62 | match (accounts, operations) { 63 | (Some(acs), Some(ops)) => { 64 | url.query_pairs_mut() 65 | .append_pair("accounts", &acs.join(",")) 66 | .append_pair("operations", &ops.join(",")); 67 | } 68 | (Some(acs), None) => { 69 | url.query_pairs_mut() 70 | .append_pair("accounts", &acs.join(",")); 71 | } 72 | (None, Some(ops)) => { 73 | url.query_pairs_mut() 74 | .append_pair("accounts", "ALL") 75 | .append_pair("operations", &ops.join(",")); 76 | } 77 | (None, None) => { 78 | url.query_pairs_mut().append_pair("accounts", "ALL"); 79 | } 80 | } 81 | 82 | debug!("generated sse url: {}", url); 83 | 84 | TransactionsStream::new(reqwest::RequestBuilder::from_parts( 85 | reqwest::Client::new(), 86 | connect_request, 87 | )) 88 | } 89 | 90 | pub fn traces_stream(&self, accounts: Option>) -> TracesStream { 91 | let mut connect_request = self.connect_request.try_clone().expect("clone request"); 92 | let url = connect_request.url_mut(); 93 | 94 | *url = url 95 | .join("accounts/traces") 96 | .expect("accounts/traces join with base"); 97 | 98 | let accounts = accounts.and_then(|a| { 99 | if a.is_empty() { 100 | return None; 101 | } 102 | Some(a) 103 | }); 104 | 105 | match accounts { 106 | Some(acs) => { 107 | url.query_pairs_mut() 108 | .append_pair("accounts", &acs.join(",")); 109 | } 110 | None => { 111 | url.query_pairs_mut().append_pair("accounts", "ALL"); 112 | } 113 | } 114 | 115 | debug!("generated sse url: {}", url); 116 | 117 | TracesStream::new(reqwest::RequestBuilder::from_parts( 118 | reqwest::Client::new(), 119 | connect_request, 120 | )) 121 | } 122 | 123 | pub fn mempool_stream(&self, accounts: Option>) -> MempoolStream { 124 | let mut connect_request = self.connect_request.try_clone().expect("clone request"); 125 | let url = connect_request.url_mut(); 126 | 127 | *url = url.join("mempool").expect("mempool join with base"); 128 | 129 | let accounts = accounts.and_then(|a| { 130 | if a.is_empty() { 131 | return None; 132 | } 133 | Some(a) 134 | }); 135 | 136 | if let Some(acs) = accounts { 137 | url.query_pairs_mut() 138 | .append_pair("accounts", &acs.join(",")); 139 | } 140 | 141 | debug!("generated sse url: {}", url); 142 | 143 | MempoolStream::new(reqwest::RequestBuilder::from_parts( 144 | reqwest::Client::new(), 145 | connect_request, 146 | )) 147 | } 148 | } 149 | 150 | pub struct TransactionsStream { 151 | es: EventSource, 152 | } 153 | 154 | impl TransactionsStream { 155 | pub(crate) fn new(builder: RequestBuilder) -> Self { 156 | Self { 157 | es: EventSource::new(builder).expect("build es"), 158 | } 159 | } 160 | 161 | #[async_recursion] 162 | pub async fn next(&mut self) -> anyhow::Result> { 163 | let evt = match self.es.next().await { 164 | Some(e) => e, 165 | None => return Ok(None), 166 | }; 167 | let evt = evt?; 168 | 169 | match evt { 170 | Event::Open => self.next().await, 171 | Event::Message(e) => { 172 | let t: TransactionEventData = serde_json::from_str(&e.data)?; 173 | Ok(Some(t)) 174 | } 175 | } 176 | } 177 | } 178 | 179 | #[derive(Deserialize, Debug)] 180 | pub struct TransactionEventData { 181 | pub account_id: String, 182 | pub lt: u64, 183 | pub tx_hash: String, 184 | } 185 | 186 | pub struct TracesStream { 187 | es: EventSource, 188 | } 189 | 190 | impl TracesStream { 191 | pub(crate) fn new(builder: RequestBuilder) -> Self { 192 | Self { 193 | es: EventSource::new(builder).expect("build es"), 194 | } 195 | } 196 | 197 | #[async_recursion] 198 | pub async fn next(&mut self) -> anyhow::Result> { 199 | let evt = match self.es.next().await { 200 | Some(e) => e, 201 | None => return Ok(None), 202 | }; 203 | let evt = evt?; 204 | 205 | match evt { 206 | Event::Open => self.next().await, 207 | Event::Message(e) => { 208 | let t: TraceEventData = serde_json::from_str(&e.data)?; 209 | Ok(Some(t)) 210 | } 211 | } 212 | } 213 | } 214 | 215 | #[derive(Deserialize, Debug)] 216 | pub struct TraceEventData { 217 | pub account: Vec, 218 | pub hash: String, 219 | } 220 | 221 | pub struct MempoolStream { 222 | es: EventSource, 223 | } 224 | 225 | impl MempoolStream { 226 | pub(crate) fn new(builder: RequestBuilder) -> Self { 227 | Self { 228 | es: EventSource::new(builder).expect("build es"), 229 | } 230 | } 231 | 232 | #[async_recursion] 233 | pub async fn next(&mut self) -> anyhow::Result> { 234 | let evt = match self.es.next().await { 235 | Some(e) => e, 236 | None => return Ok(None), 237 | }; 238 | let evt = evt?; 239 | 240 | match evt { 241 | Event::Open => self.next().await, 242 | Event::Message(e) => { 243 | let t: MempoolEventData = serde_json::from_str(&e.data)?; 244 | Ok(Some(t)) 245 | } 246 | } 247 | } 248 | } 249 | 250 | #[derive(Deserialize, Debug)] 251 | pub struct MempoolEventData { 252 | pub boc: String, 253 | pub involved_accounts: Vec, 254 | } 255 | -------------------------------------------------------------------------------- /src/stream_api/ws.rs: -------------------------------------------------------------------------------- 1 | use anyhow::Context; 2 | use async_recursion::async_recursion; 3 | use futures_util::{SinkExt, StreamExt}; 4 | use log::{debug, error, info, warn}; 5 | use reqwest::header::HeaderValue; 6 | use serde::{Deserialize, Serialize}; 7 | use tokio_tungstenite::tungstenite::client::IntoClientRequest; 8 | use tokio_tungstenite::tungstenite::http; 9 | use tokio_tungstenite::tungstenite::Message; 10 | use tokio_tungstenite::{connect_async, WebSocketStream}; 11 | 12 | use crate::Network; 13 | 14 | mod constants { 15 | include!(concat!(env!("OUT_DIR"), "/constants.rs")); 16 | } 17 | 18 | pub struct WsApi { 19 | connect_params: http::request::Parts, 20 | } 21 | 22 | pub struct AccountOperations { 23 | pub account: String, 24 | pub operations: Option>, 25 | } 26 | 27 | impl WsApi { 28 | pub fn new(network: Network, api_key: Option) -> Self { 29 | let base_url = match network { 30 | Network::Mainnet => "wss://tonapi.io/v2/websocket", 31 | Network::Testnet => "wss://testnet.tonapi.io/v2/websocket", 32 | }; 33 | 34 | let mut request = base_url 35 | .into_client_request() 36 | .expect("docs url"); 37 | 38 | request.headers_mut().insert( 39 | "User-Agent", 40 | HeaderValue::from_static(constants::USER_AGENT), 41 | ); 42 | 43 | if let Some(api_key) = api_key { 44 | let bearer_token = format!("Bearer {}", api_key); 45 | request.headers_mut().insert( 46 | "Authorization", 47 | HeaderValue::from_str(&bearer_token) 48 | .expect("hope users won't use some crazy auth tokens"), 49 | ); 50 | } 51 | 52 | Self { 53 | connect_params: request.into_parts().0, 54 | } 55 | } 56 | 57 | pub fn transactions_stream( 58 | &self, 59 | account_operations: Option>, 60 | ) -> TransactionsStream { 61 | TransactionsStream::new(&self.connect_params, account_operations) 62 | } 63 | 64 | pub fn traces_stream(&self, accounts: Option>) -> TracesStream { 65 | TracesStream::new(&self.connect_params, accounts.map(|accounts| StreamParams { entries: accounts })) 66 | } 67 | 68 | pub fn mempool_stream(&self, accounts: Option>) -> MempoolStream { 69 | MempoolStream::new(&self.connect_params, accounts.map(|accounts| StreamParams { entries: accounts })) 70 | } 71 | } 72 | 73 | #[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] 74 | #[serde(rename_all = "snake_case")] 75 | enum WsMethod { 76 | SubscribeAccount, 77 | SubscribeTrace, 78 | SubscribeMempool, 79 | } 80 | 81 | pub(crate) struct StreamParams { 82 | pub entries: Vec, 83 | } 84 | 85 | struct WsStream { 86 | connect_request: Option>, 87 | subscribe_message: SubscribeMessage, 88 | raw_ws_stream: 89 | Option>>, 90 | } 91 | 92 | impl WsStream { 93 | pub fn new( 94 | connect_params: &http::request::Parts, 95 | subscribe_method: WsMethod, 96 | subscribe_params: Option, 97 | ) -> Self { 98 | let subscribe_message = SubscribeMessage { 99 | // I wonder, what's purpose of id ... 100 | id: 1, 101 | jsonrpc: "2.0".to_string(), 102 | method: subscribe_method, 103 | params: subscribe_params.map(|e| e.entries), 104 | }; 105 | 106 | let mut new_req = http::Request::new(()); 107 | *new_req.method_mut() = connect_params.method.clone(); 108 | new_req.headers_mut().extend(connect_params.headers.clone()); 109 | *new_req.uri_mut() = connect_params.uri.clone(); 110 | 111 | Self { 112 | connect_request: Some(new_req), 113 | subscribe_message, 114 | raw_ws_stream: None, 115 | } 116 | } 117 | 118 | #[async_recursion] 119 | pub async fn next(&mut self) -> anyhow::Result>> { 120 | if let Some(ws_stream) = self.raw_ws_stream.as_mut() { 121 | let evt = match ws_stream.next().await { 122 | Some(e) => e, 123 | None => return Ok(None), 124 | }; 125 | let msg = evt.context("get next ws event")?; 126 | 127 | match msg { 128 | Message::Close(message) => { 129 | let msg = message 130 | .map(|fr| format!("{} {}", fr.code, fr.reason)) 131 | .unwrap_or("no message".to_string()); 132 | info!("server closed connection with {}", msg); 133 | return Ok(None); 134 | } 135 | Message::Ping(payload) => { 136 | debug!("ping from server with {:#?}", payload); 137 | return self.next().await; 138 | } 139 | Message::Pong(payload) => { 140 | debug!("ping from server with {:#?}", payload); 141 | unreachable!() 142 | } 143 | Message::Binary(payload) => { 144 | debug!("binary from server with {:#?}", payload); 145 | return Err(anyhow::anyhow!("unexpected binary instead of text")); 146 | } 147 | Message::Text(text) => { 148 | debug!("text from server with {:#?}", text); 149 | let parsed_msg: SubscribeEvent = 150 | serde_json::from_str(&text).expect("json parsing subscribed event"); 151 | return Ok(Some(parsed_msg)); 152 | } 153 | Message::Frame(_) => { 154 | debug!("raw frame from server"); 155 | unreachable!() 156 | } 157 | } 158 | } else { 159 | self.connect().await?; 160 | self.next().await 161 | } 162 | } 163 | 164 | pub async fn connect(&mut self) -> anyhow::Result<()> { 165 | if let Some(con_req) = self.connect_request.take() { 166 | let (ws_stream, _) = connect_async(con_req).await?; 167 | 168 | self.raw_ws_stream = Some(ws_stream); 169 | self.raw_ws_stream 170 | .as_mut() 171 | .expect("self.ws_stream set above") 172 | .send(Message::Text( 173 | serde_json::to_string(&self.subscribe_message) 174 | .expect("stringify subscribe request"), 175 | )) 176 | .await?; 177 | 178 | self.wait_connect().await 179 | } else { 180 | Err(anyhow::anyhow!("already called connect")) 181 | } 182 | } 183 | 184 | #[async_recursion] 185 | pub async fn wait_connect(&mut self) -> anyhow::Result<()> { 186 | let msg = self 187 | .raw_ws_stream 188 | .as_mut() 189 | .expect("ws_stream set in connect(...)") 190 | .next() 191 | .await 192 | .context("fetch initial connect response")? 193 | .context("get initial connect message")?; 194 | 195 | match msg { 196 | Message::Close(message) => { 197 | let msg = message 198 | .map(|fr| format!("{} {}", fr.code, fr.reason)) 199 | .unwrap_or("no message".to_string()); 200 | error!("server closed connection with {}", msg); 201 | return Err(anyhow::anyhow!("closed connection before init")); 202 | } 203 | Message::Ping(payload) => { 204 | debug!("ping from server with {:#?}", payload); 205 | return self.wait_connect().await; 206 | } 207 | Message::Pong(payload) => { 208 | debug!("ping from server with {:#?}", payload); 209 | unreachable!() 210 | } 211 | Message::Binary(payload) => { 212 | debug!("binary from server with {:#?}", payload); 213 | return Err(anyhow::anyhow!("unexpected binary instead of text")); 214 | } 215 | 216 | Message::Text(text) => { 217 | debug!("text from server with {:#?}", text); 218 | let parsed_msg: SubscribeResponse = 219 | serde_json::from_str(&text).expect("json parsing subscribed event"); 220 | if parsed_msg.id != self.subscribe_message.id 221 | || parsed_msg.jsonrpc != self.subscribe_message.jsonrpc 222 | || parsed_msg.method != self.subscribe_message.method 223 | { 224 | debug!("request: {:#?}", self.subscribe_message); 225 | debug!("response: {:#?}", parsed_msg); 226 | warn!("ws request didn't match with response"); 227 | } 228 | debug!("init connection response: {}", parsed_msg.result); 229 | return Ok(()); 230 | } 231 | Message::Frame(fr) => { 232 | debug!("raw frame from server with {:#?}", fr.payload()); 233 | unreachable!() 234 | } 235 | } 236 | } 237 | } 238 | 239 | #[derive(Serialize, Debug)] 240 | struct SubscribeMessage { 241 | id: u64, 242 | // 2.0 243 | jsonrpc: String, 244 | // subscribe_account | subscribe_trace | subscribe_mempool 245 | method: WsMethod, 246 | // (account_id | account_id;operations)[] 247 | params: Option>, 248 | } 249 | 250 | #[derive(Deserialize, Debug)] 251 | pub struct SubscribeEvent

{ 252 | pub jsonrpc: String, 253 | pub method: String, 254 | pub params: P, 255 | } 256 | 257 | #[derive(Deserialize, Debug)] 258 | #[serde(untagged)] 259 | enum SubscribeEventData { 260 | AccountData(TransactionEventData), 261 | TraceData(TraceEventData), 262 | MempoolData(MempoolEventData), 263 | } 264 | 265 | #[derive(Deserialize, Debug)] 266 | struct SubscribeResponse { 267 | pub id: u64, 268 | pub jsonrpc: String, 269 | pub method: WsMethod, 270 | pub result: String, 271 | } 272 | 273 | pub struct TransactionsStream { 274 | ws_stream: WsStream, 275 | } 276 | 277 | impl TransactionsStream { 278 | pub(crate) fn new( 279 | connect_params: &http::request::Parts, 280 | subscribe_params: Option>, 281 | ) -> Self { 282 | let subscribe_params = subscribe_params.map(|acs_ops| { 283 | let entries = acs_ops 284 | .into_iter() 285 | .map(|ac_op| { 286 | let ops = ac_op.operations.unwrap_or_default(); 287 | if ops.is_empty() { 288 | ac_op.account 289 | } else { 290 | format!("{};operations={}", ac_op.account, ops.join(",")) 291 | } 292 | }) 293 | .collect(); 294 | StreamParams { entries } 295 | }); 296 | Self { 297 | ws_stream: WsStream::new(connect_params, WsMethod::SubscribeAccount, subscribe_params), 298 | } 299 | } 300 | 301 | #[async_recursion] 302 | pub async fn next(&mut self) -> anyhow::Result>> { 303 | let evt = self.ws_stream.next().await?; 304 | let evt = match evt { 305 | Some(e) => e, 306 | None => return Ok(None), 307 | }; 308 | match evt.params { 309 | SubscribeEventData::AccountData(t_data) => Ok(Some(SubscribeEvent { 310 | jsonrpc: evt.jsonrpc, 311 | method: evt.method, 312 | params: TransactionEventData { 313 | account_id: t_data.account_id, 314 | lt: t_data.lt, 315 | tx_hash: t_data.tx_hash, 316 | }, 317 | })), 318 | _ => { 319 | error!("invalid event.params {:#?}", evt.params); 320 | Err(anyhow::anyhow!("received wrong data in params")) 321 | } 322 | } 323 | } 324 | } 325 | 326 | #[derive(Deserialize, Debug)] 327 | pub struct TransactionEventData { 328 | pub account_id: String, 329 | pub lt: u64, 330 | pub tx_hash: String, 331 | } 332 | 333 | pub struct TracesStream { 334 | ws_stream: WsStream, 335 | } 336 | 337 | impl TracesStream { 338 | pub(crate) fn new( 339 | connect_params: &http::request::Parts, 340 | subscribe_params: Option, 341 | ) -> Self { 342 | Self { 343 | ws_stream: WsStream::new( 344 | connect_params, 345 | WsMethod::SubscribeTrace, 346 | subscribe_params, 347 | ), 348 | } 349 | } 350 | 351 | #[async_recursion] 352 | pub async fn next(&mut self) -> anyhow::Result>> { 353 | let evt = self.ws_stream.next().await?; 354 | let evt = match evt { 355 | Some(e) => e, 356 | None => return Ok(None), 357 | }; 358 | match evt.params { 359 | SubscribeEventData::TraceData(t_data) => Ok(Some(SubscribeEvent { 360 | jsonrpc: evt.jsonrpc, 361 | method: evt.method, 362 | params: TraceEventData { 363 | accounts: t_data.accounts, 364 | hash: t_data.hash, 365 | }, 366 | })), 367 | _ => { 368 | error!("invalid event.params {:#?}", evt.params); 369 | Err(anyhow::anyhow!("received wrong data in params")) 370 | } 371 | } 372 | } 373 | } 374 | 375 | #[derive(Deserialize, Debug)] 376 | pub struct TraceEventData { 377 | pub accounts: Vec, 378 | pub hash: String, 379 | } 380 | 381 | pub struct MempoolStream { 382 | ws_stream: WsStream, 383 | } 384 | 385 | impl MempoolStream { 386 | pub(crate) fn new( 387 | connect_params: &http::request::Parts, 388 | subscribe_params: Option, 389 | ) -> Self { 390 | Self { 391 | ws_stream: WsStream::new( 392 | connect_params, 393 | WsMethod::SubscribeMempool, 394 | subscribe_params, 395 | ), 396 | } 397 | } 398 | 399 | #[async_recursion] 400 | pub async fn next(&mut self) -> anyhow::Result>> { 401 | let evt = self.ws_stream.next().await?; 402 | let evt = match evt { 403 | Some(e) => e, 404 | None => return Ok(None), 405 | }; 406 | match evt.params { 407 | SubscribeEventData::MempoolData(m_data) => Ok(Some(SubscribeEvent { 408 | jsonrpc: evt.jsonrpc, 409 | method: evt.method, 410 | params: MempoolEventData { 411 | boc: m_data.boc, 412 | involved_accounts: m_data.involved_accounts, 413 | }, 414 | })), 415 | _ => { 416 | error!("invalid event.params {:#?}", evt.params); 417 | Err(anyhow::anyhow!("received wrong data in params")) 418 | } 419 | } 420 | } 421 | } 422 | 423 | #[derive(Deserialize, Debug)] 424 | pub struct MempoolEventData { 425 | pub boc: String, 426 | pub involved_accounts: Option>, 427 | } 428 | -------------------------------------------------------------------------------- /src/rest_api/models.rs: -------------------------------------------------------------------------------- 1 | use serde::Deserialize; 2 | use std::collections::HashMap; 3 | 4 | #[derive(Debug, Deserialize)] 5 | #[serde(untagged)] 6 | pub enum ApiResponse { 7 | Success { 8 | #[serde(flatten)] 9 | result: T, 10 | }, 11 | Error { 12 | error: String, 13 | }, 14 | } 15 | 16 | #[derive(Debug, Deserialize)] 17 | pub struct Accounts { 18 | pub accounts: Vec, 19 | } 20 | 21 | #[derive(Debug, Deserialize)] 22 | pub struct Account { 23 | pub address: String, 24 | pub balance: i64, 25 | pub currencies_balance: Option>, 26 | pub last_activity: i64, 27 | pub status: AccountStatus, 28 | pub interfaces: Option>, 29 | pub name: Option, 30 | pub is_scam: Option, 31 | pub icon: Option, 32 | pub memo_required: Option, 33 | pub get_methods: Vec, 34 | pub is_suspended: Option, 35 | pub is_wallet: bool, 36 | } 37 | 38 | #[derive(Debug, Deserialize)] 39 | #[serde(rename_all = "lowercase")] 40 | pub enum AccountStatus { 41 | Nonexist, 42 | Uninit, 43 | Active, 44 | Frozen, 45 | } 46 | 47 | #[derive(Debug, Deserialize)] 48 | pub struct DomainNames { 49 | pub domains: Vec, 50 | } 51 | 52 | #[derive(Debug, Deserialize)] 53 | pub struct JettonBalances { 54 | pub balances: Vec, 55 | } 56 | 57 | #[derive(Debug, Deserialize)] 58 | pub struct JettonBalance { 59 | pub balance: String, 60 | pub price: Option, 61 | pub wallet_address: AccountAddress, 62 | pub jetton: JettonPreview, 63 | pub extensions: Option>, 64 | pub lock: Option, 65 | } 66 | 67 | #[derive(Debug, Deserialize)] 68 | pub struct TokenRates { 69 | pub prices: Option>, 70 | pub diff_24h: Option>, 71 | pub diff_7d: Option>, 72 | pub diff_30d: Option>, 73 | } 74 | 75 | #[derive(Debug, Deserialize)] 76 | pub struct AccountAddress { 77 | pub address: String, 78 | pub name: Option, 79 | pub is_scam: bool, 80 | pub icon: Option, 81 | pub is_wallet: bool, 82 | } 83 | 84 | #[derive(Debug, Deserialize)] 85 | pub struct JettonPreview { 86 | pub address: String, 87 | pub name: String, 88 | pub symbol: String, 89 | pub decimals: u32, 90 | pub image: String, 91 | pub verification: JettonVerificationType, 92 | } 93 | 94 | #[derive(Debug, Deserialize)] 95 | #[serde(rename_all = "lowercase")] 96 | pub enum JettonVerificationType { 97 | Whitelist, 98 | GrayList, 99 | Blacklist, 100 | None, 101 | } 102 | 103 | #[derive(Debug, Deserialize)] 104 | pub struct Lock { 105 | pub amount: String, 106 | pub till: i64, // Unix timestamp 107 | } 108 | 109 | #[derive(Debug, Deserialize)] 110 | pub struct AccountEvents { 111 | pub events: Vec, 112 | pub next_from: i64, 113 | } 114 | 115 | #[derive(Debug, Deserialize)] 116 | pub struct AccountEvent { 117 | pub event_id: String, 118 | pub timestamp: i64, 119 | pub actions: Vec, 120 | pub account: AccountAddress, 121 | pub is_scam: bool, 122 | pub lt: i64, 123 | pub in_progress: bool, 124 | pub extra: i64, 125 | } 126 | 127 | #[derive(Debug, Deserialize)] 128 | pub struct Action { 129 | pub r#type: ActionType, 130 | pub status: ActionStatus, 131 | pub simple_preview: ActionSimplePreview, 132 | pub base_transactions: Vec, 133 | pub ton_transfer: Option, 134 | pub contract_deploy: Option, 135 | pub jetton_transfer: Option, 136 | pub jetton_burn: Option, 137 | pub jetton_mint: Option, 138 | pub nft_item_transfer: Option, 139 | pub subscribe: Option, 140 | pub unsubscribe: Option, 141 | pub auction_bid: Option, 142 | pub nft_purchase: Option, 143 | pub deposit_stake: Option, 144 | pub withdraw_stake: Option, 145 | pub withdraw_stake_request: Option, 146 | pub elections_deposit_stake: Option, 147 | pub elections_recover_stake: Option, 148 | pub jetton_swap: Option, 149 | pub smart_contract_exec: Option, 150 | pub domain_renew: Option, 151 | pub inscription_transfer: Option, 152 | pub inscription_mint: Option, 153 | } 154 | 155 | #[derive(Debug, Deserialize)] 156 | pub enum ActionType { 157 | TonTransfer, 158 | JettonTransfer, 159 | JettonBurn, 160 | JettonMint, 161 | NftItemTransfer, 162 | ContractDeploy, 163 | Subscribe, 164 | UnSubscribe, 165 | AuctionBid, 166 | NftPurchase, 167 | DepositStake, 168 | WithdrawStake, 169 | WithdrawStakeRequest, 170 | JettonSwap, 171 | SmartContractExec, 172 | ElectionsRecoverStake, 173 | ElectionsDepositStake, 174 | DomainRenew, 175 | InscriptionTransfer, 176 | InscriptionMint, 177 | Unknown, 178 | } 179 | 180 | #[derive(Debug, Deserialize)] 181 | #[serde(rename_all = "lowercase")] 182 | pub enum ActionStatus { 183 | Ok, 184 | Failed, 185 | } 186 | 187 | #[derive(Debug, Deserialize)] 188 | pub struct ActionSimplePreview { 189 | pub name: String, 190 | pub description: String, 191 | pub action_image: Option, 192 | pub value: Option, 193 | pub value_image: Option, 194 | pub accounts: Vec, 195 | } 196 | 197 | #[derive(Debug, Deserialize)] 198 | pub struct TonTransferAction { 199 | pub sender: AccountAddress, 200 | pub recipient: AccountAddress, 201 | pub amount: i64, 202 | pub comment: Option, 203 | pub encrypted_comment: Option, 204 | pub refund: Option, 205 | } 206 | 207 | #[derive(Debug, Deserialize)] 208 | pub struct EncryptedComment { 209 | pub encryption_type: String, 210 | pub cipher_text: String, 211 | } 212 | 213 | #[derive(Debug, Deserialize)] 214 | pub struct Refund { 215 | pub r#type: RefundType, 216 | pub origin: String, 217 | } 218 | 219 | #[derive(Debug, Deserialize)] 220 | pub enum RefundType { 221 | #[serde(rename = "DNS.ton")] 222 | DnsTon, 223 | #[serde(rename = "DNS.tg")] 224 | DnsTg, 225 | #[serde(rename = "GetGems")] 226 | GetGems, 227 | } 228 | 229 | #[derive(Debug, Deserialize)] 230 | pub struct ContractDeployAction { 231 | pub address: String, 232 | pub interfaces: Vec, 233 | } 234 | 235 | #[derive(Debug, Deserialize)] 236 | pub struct JettonTransferAction { 237 | pub sender: AccountAddress, 238 | pub recipient: AccountAddress, 239 | pub senders_wallet: String, 240 | pub recipients_wallet: String, 241 | pub amount: String, 242 | pub comment: Option, 243 | pub encrypted_comment: Option, 244 | pub refund: Option, 245 | pub jetton: JettonPreview, 246 | } 247 | 248 | #[derive(Debug, Deserialize)] 249 | pub struct JettonBurnAction { 250 | pub sender: AccountAddress, 251 | pub senders_wallet: String, 252 | pub amount: String, 253 | pub jetton: JettonPreview, 254 | } 255 | 256 | #[derive(Debug, Deserialize)] 257 | pub struct JettonMintAction { 258 | pub recipient: AccountAddress, 259 | pub recipients_wallet: String, 260 | pub amount: String, 261 | pub jetton: JettonPreview, 262 | } 263 | 264 | #[derive(Debug, Deserialize)] 265 | pub struct NftItemTransferAction { 266 | pub sender: Option, 267 | pub recipient: Option, 268 | pub nft: String, 269 | pub comment: Option, 270 | pub encrypted_comment: Option, 271 | pub payload: Option, 272 | pub refund: Option, 273 | } 274 | 275 | #[derive(Debug, Deserialize)] 276 | pub struct SubscriptionAction { 277 | pub subscriber: AccountAddress, 278 | pub subscription: String, 279 | pub beneficiary: AccountAddress, 280 | pub amount: i64, 281 | pub initial: bool, 282 | } 283 | 284 | #[derive(Debug, Deserialize)] 285 | pub struct UnSubscriptionAction { 286 | pub subscriber: AccountAddress, 287 | pub subscription: String, 288 | pub beneficiary: AccountAddress, 289 | } 290 | 291 | #[derive(Debug, Deserialize)] 292 | pub struct AuctionBidAction { 293 | pub auction_type: AuctionType, 294 | pub amount: Price, 295 | pub nft: NftItem, 296 | pub bidder: AccountAddress, 297 | pub auction: AccountAddress, 298 | } 299 | 300 | #[derive(Debug, Deserialize)] 301 | pub enum AuctionType { 302 | #[serde(rename = "DNS.ton")] 303 | DnsTon, 304 | #[serde(rename = "DNS.tg")] 305 | DnsTg, 306 | #[serde(rename = "NUMBER.tg")] 307 | NumberTg, 308 | #[serde(rename = "getgems")] 309 | Getgems, 310 | } 311 | 312 | #[derive(Debug, Deserialize)] 313 | pub struct Price { 314 | pub value: String, 315 | pub token_name: String, 316 | } 317 | 318 | #[derive(Debug, Deserialize)] 319 | pub struct NftItem { 320 | pub address: String, 321 | pub index: i64, 322 | pub owner: Option, 323 | pub collection: Option, 324 | pub verified: bool, 325 | pub metadata: HashMap, 326 | pub sale: Option, 327 | pub previews: Option>, 328 | pub dns: Option, 329 | pub approved_by: Option, 330 | pub include_cnft: Option, 331 | pub trust: Option, 332 | } 333 | 334 | #[derive(Debug, Deserialize)] 335 | pub struct Collection { 336 | pub address: String, 337 | pub name: String, 338 | pub description: String, 339 | } 340 | 341 | #[derive(Debug, Deserialize)] 342 | pub struct Sale { 343 | pub address: String, 344 | pub market: AccountAddress, 345 | pub owner: Option, 346 | pub price: Price, 347 | } 348 | 349 | #[derive(Debug, Deserialize)] 350 | pub struct ImagePreview { 351 | pub resolution: String, 352 | pub url: String, 353 | } 354 | 355 | #[derive(Debug, Deserialize)] 356 | pub enum NftApprovalSource { 357 | #[serde(rename = "getgems")] 358 | Getgems, 359 | #[serde(rename = "tonkeeper")] 360 | Tonkeeper, 361 | #[serde(rename = "ton.diamonds")] 362 | TonDiamonds, 363 | } 364 | 365 | #[derive(Debug, Deserialize)] 366 | pub struct NftApprovedBy(pub Vec); 367 | 368 | #[derive(Debug, Deserialize)] 369 | #[serde(rename_all = "lowercase")] 370 | pub enum TrustType { 371 | Whitelist, 372 | Graylist, 373 | Blacklist, 374 | None, 375 | } 376 | 377 | #[derive(Debug, Deserialize)] 378 | pub struct NftPurchaseAction { 379 | pub auction_type: AuctionType, 380 | pub amount: Price, 381 | pub nft: NftItem, 382 | pub seller: AccountAddress, 383 | pub buyer: AccountAddress, 384 | } 385 | 386 | #[derive(Debug, Deserialize)] 387 | pub struct DepositStakeAction { 388 | pub amount: i64, 389 | pub staker: AccountAddress, 390 | pub pool: AccountAddress, 391 | pub implementation: PoolImplementationType, 392 | } 393 | 394 | #[derive(Debug, Deserialize)] 395 | pub enum PoolImplementationType { 396 | #[serde(rename = "whales")] 397 | Whales, 398 | #[serde(rename = "tf")] 399 | Tf, 400 | #[serde(rename = "liquidTF")] 401 | LiquidTF, 402 | } 403 | 404 | #[derive(Debug, Deserialize)] 405 | pub struct WithdrawStakeAction { 406 | pub amount: i64, 407 | pub staker: AccountAddress, 408 | pub pool: AccountAddress, 409 | pub implementation: PoolImplementationType, 410 | } 411 | 412 | #[derive(Debug, Deserialize)] 413 | pub struct WithdrawStakeRequestAction { 414 | pub amount: Option, 415 | pub staker: AccountAddress, 416 | pub pool: AccountAddress, 417 | pub implementation: PoolImplementationType, 418 | } 419 | 420 | #[derive(Debug, Deserialize)] 421 | pub struct ElectionsDepositStakeAction { 422 | pub amount: i64, 423 | pub staker: AccountAddress, 424 | } 425 | 426 | #[derive(Debug, Deserialize)] 427 | pub struct ElectionsRecoverStakeAction { 428 | pub amount: i64, 429 | pub staker: AccountAddress, 430 | } 431 | 432 | #[derive(Debug, Deserialize)] 433 | pub struct JettonSwapAction { 434 | pub dex: DexType, 435 | pub amount_in: String, 436 | pub amount_out: String, 437 | pub ton_in: Option, 438 | pub ton_out: Option, 439 | pub user_wallet: AccountAddress, 440 | pub router: AccountAddress, 441 | pub jetton_master_in: Option, 442 | pub jetton_master_out: Option, 443 | } 444 | 445 | #[derive(Debug, Deserialize)] 446 | #[serde(rename_all = "lowercase")] 447 | pub enum DexType { 448 | Stonfi, 449 | Dedust, 450 | Megatonfi, 451 | } 452 | 453 | #[derive(Debug, Deserialize)] 454 | pub struct SmartContractAction { 455 | pub executor: AccountAddress, 456 | pub contract: AccountAddress, 457 | pub ton_attached: i64, // Amount in nanotons 458 | pub operation: String, 459 | pub payload: Option, 460 | pub refund: Option, 461 | } 462 | 463 | #[derive(Debug, Deserialize)] 464 | pub struct DomainRenewAction { 465 | pub domain: String, 466 | pub contract_address: String, // Address in string format 467 | pub renewer: AccountAddress, 468 | } 469 | 470 | #[derive(Debug, Deserialize)] 471 | pub struct InscriptionTransferAction { 472 | pub sender: AccountAddress, 473 | pub recipient: AccountAddress, 474 | pub amount: String, // Amount is in string format as per the example 475 | pub comment: Option, 476 | #[serde(rename = "type")] 477 | pub transfer_type: String, // The type field is renamed to transfer_type to avoid keyword conflict 478 | pub ticker: String, 479 | pub decimals: i32, 480 | } 481 | 482 | #[derive(Debug, Deserialize)] 483 | pub struct InscriptionMintAction { 484 | #[serde(rename = "type")] 485 | pub mint_type: String, // The type field is renamed to mint_type to avoid keyword conflict 486 | pub ticker: String, 487 | pub recipient: AccountAddress, 488 | pub amount: String, // Amount is in string format as per the example 489 | pub decimals: i32, 490 | } 491 | 492 | #[derive(Debug, Deserialize)] 493 | pub struct NftItems { 494 | pub nft_items: Vec, 495 | } 496 | 497 | #[derive(Debug, Deserialize)] 498 | pub struct TraceIds { 499 | pub traces: Vec, 500 | } 501 | 502 | #[derive(Debug, Deserialize)] 503 | pub struct TraceId { 504 | pub id: String, 505 | pub utime: i64, 506 | } 507 | 508 | #[derive(Debug, Deserialize)] 509 | pub struct Subscriptions { 510 | pub subscriptions: Vec, 511 | } 512 | 513 | #[derive(Debug, Deserialize)] 514 | pub struct Subscription { 515 | pub address: String, 516 | pub wallet_address: String, 517 | pub beneficiary_address: String, 518 | pub amount: i64, 519 | pub period: i64, 520 | pub start_time: i64, 521 | pub timeout: i64, 522 | pub last_payment_time: i64, 523 | pub last_request_time: i64, 524 | pub subscription_id: i64, 525 | pub failed_attempts: i32, 526 | } 527 | 528 | #[derive(Debug, Deserialize)] 529 | pub struct FoundAccounts { 530 | pub addresses: Vec, 531 | } 532 | 533 | #[derive(Debug, Deserialize)] 534 | pub struct FoundAccountAddress { 535 | pub address: String, 536 | pub name: String, 537 | pub preview: String, 538 | } 539 | 540 | #[derive(Debug, Deserialize)] 541 | pub struct DnsExpiring { 542 | pub items: Vec, 543 | } 544 | 545 | #[derive(Debug, Deserialize)] 546 | pub struct DnsExpiringItem { 547 | pub expiring_at: i64, 548 | pub name: String, 549 | pub dns_item: NftItem, 550 | } 551 | 552 | #[derive(Debug, Deserialize)] 553 | pub struct PublicKey { 554 | pub public_key: String, 555 | } 556 | 557 | #[derive(Debug, Deserialize)] 558 | pub struct Multisigs { 559 | pub multisigs: Vec, 560 | } 561 | 562 | #[derive(Debug, Deserialize)] 563 | pub struct Multisig { 564 | pub address: String, 565 | pub seqno: i64, 566 | pub threshold: i32, 567 | pub signers: Vec, 568 | pub proposers: Vec, 569 | pub orders: Vec, 570 | } 571 | 572 | #[derive(Debug, Deserialize)] 573 | pub struct MultisigOrder { 574 | pub address: String, 575 | pub order_seqno: i64, 576 | pub threshold: i32, 577 | pub sent_for_execution: bool, 578 | pub signers: Vec, 579 | pub approvals_num: i32, 580 | pub expiration_date: i64, 581 | pub risk: Risk, 582 | } 583 | 584 | #[derive(Debug, Deserialize)] 585 | pub struct Risk { 586 | pub transfer_all_remaining_balance: bool, 587 | pub ton: i64, 588 | pub jettons: Vec, 589 | pub nfts: Vec, 590 | } 591 | 592 | #[derive(Debug, Deserialize)] 593 | pub struct JettonQuantity { 594 | pub quantity: String, 595 | pub wallet_address: AccountAddress, 596 | pub jetton: JettonPreview, 597 | } 598 | 599 | #[derive(Debug, Deserialize)] 600 | pub struct BalanceChange { 601 | pub balance_change: i64, 602 | } 603 | 604 | #[derive(Debug, Deserialize)] 605 | pub struct NftCollections { 606 | pub nft_collections: Vec, 607 | } 608 | 609 | #[derive(Debug, Deserialize)] 610 | pub struct NftCollection { 611 | pub address: String, 612 | pub next_item_index: i64, 613 | pub owner: Option, 614 | pub raw_collection_content: String, 615 | pub metadata: Option>, 616 | pub previews: Option>, 617 | pub approved_by: NftApprovedBy, 618 | } 619 | 620 | #[derive(Debug, Deserialize)] 621 | pub struct Jettons { 622 | pub jettons: Vec, 623 | } 624 | 625 | #[derive(Debug, Deserialize)] 626 | pub struct JettonInfo { 627 | pub mintable: bool, 628 | pub total_supply: String, 629 | pub admin: Option, 630 | pub metadata: JettonMetadata, 631 | pub verification: JettonVerificationType, 632 | pub holders_count: i32, 633 | } 634 | 635 | #[derive(Debug, Deserialize)] 636 | pub struct JettonMetadata { 637 | pub address: String, 638 | pub name: String, 639 | pub symbol: String, 640 | pub decimals: String, 641 | pub image: Option, 642 | pub description: Option, 643 | pub social: Option>, 644 | pub websites: Option>, 645 | pub catalogs: Option>, 646 | } 647 | 648 | #[derive(Debug, Deserialize)] 649 | pub struct JettonHolders { 650 | pub addresses: Vec, 651 | pub total: i64, 652 | } 653 | 654 | #[derive(Debug, Deserialize)] 655 | pub struct JettonHolderAddress { 656 | pub address: String, 657 | pub owner: AccountAddress, 658 | pub balance: String, 659 | } 660 | 661 | #[derive(Debug, Deserialize)] 662 | pub struct JettonTransferPayload { 663 | pub custom_payload: Option, 664 | pub state_init: Option, 665 | } 666 | 667 | #[derive(Debug, Deserialize)] 668 | pub struct Event { 669 | pub event_id: String, 670 | pub timestamp: i64, 671 | pub actions: Vec, 672 | pub value_flow: Vec, 673 | pub is_scam: bool, 674 | pub lt: i64, 675 | pub in_progress: bool, 676 | } 677 | 678 | #[derive(Debug, Deserialize)] 679 | pub struct ValueFlow { 680 | pub account: AccountAddress, 681 | pub ton: i64, 682 | pub fees: i64, 683 | pub jettons: Option>, 684 | } 685 | 686 | #[derive(Debug, Deserialize)] 687 | pub struct JettonFlow { 688 | pub account: AccountAddress, 689 | pub jetton: JettonPreview, 690 | pub quantity: i64, 691 | } 692 | 693 | #[derive(Debug, Deserialize)] 694 | pub struct DomainInfo { 695 | pub name: String, 696 | pub expiring_at: Option, 697 | pub item: Option, 698 | } 699 | 700 | #[derive(Debug, Deserialize)] 701 | pub struct DnsRecord { 702 | pub wallet: Option, 703 | pub next_resolver: Option, 704 | pub sites: Vec, 705 | pub storage: Option, 706 | } 707 | 708 | #[derive(Debug, Deserialize)] 709 | pub struct WalletDns { 710 | pub address: String, 711 | pub account: AccountAddress, 712 | pub is_wallet: bool, 713 | pub has_method_pubkey: bool, 714 | pub has_method_seqno: bool, 715 | pub names: Vec, 716 | } 717 | 718 | #[derive(Debug, Deserialize)] 719 | pub struct DomainBids { 720 | pub data: Vec, 721 | } 722 | 723 | #[derive(Debug, Deserialize)] 724 | pub struct DomainBid { 725 | pub success: bool, 726 | pub value: i64, 727 | #[serde(rename = "txTime")] 728 | pub tx_time: i64, 729 | #[serde(rename = "txHash")] 730 | pub tx_hash: String, 731 | pub bidder: AccountAddress, 732 | } 733 | 734 | #[derive(Debug, Deserialize)] 735 | pub struct Auctions { 736 | pub data: Vec, 737 | pub total: i64, 738 | } 739 | 740 | #[derive(Debug, Deserialize)] 741 | pub struct Auction { 742 | pub domain: String, 743 | pub owner: String, 744 | pub price: i64, 745 | pub bids: i64, 746 | pub date: i64, 747 | } 748 | 749 | #[derive(Debug, Deserialize)] 750 | pub struct Dump { 751 | pub dump: String, 752 | } 753 | 754 | #[derive(Debug, Deserialize)] 755 | pub struct AuthToken { 756 | pub token: String, 757 | } 758 | 759 | #[derive(Debug, Deserialize)] 760 | pub struct AccountSeqno { 761 | pub seqno: i64, 762 | } 763 | 764 | #[derive(Debug, Deserialize)] 765 | pub struct MessageConsequences { 766 | pub trace: Trace, 767 | pub risk: Risk, 768 | pub event: AccountEvent, 769 | } 770 | 771 | #[derive(Debug, Deserialize)] 772 | pub struct Trace { 773 | pub transaction: Transaction, 774 | pub interfaces: Vec, 775 | pub children: Option>, 776 | pub emulated: Option, 777 | } 778 | 779 | #[derive(Debug, Deserialize)] 780 | pub struct Transaction { 781 | pub hash: String, 782 | pub lt: i64, 783 | pub account: AccountAddress, 784 | pub success: bool, 785 | pub utime: i64, 786 | pub orig_status: AccountStatus, 787 | pub end_status: AccountStatus, 788 | pub total_fees: i64, 789 | pub end_balance: i64, 790 | pub transaction_type: TransactionType, 791 | pub state_update_old: String, 792 | pub state_update_new: String, 793 | pub in_msg: Option, 794 | pub out_msgs: Vec, 795 | pub block: String, 796 | pub prev_trans_hash: Option, 797 | pub prev_trans_lt: Option, 798 | pub compute_phase: Option, 799 | pub storage_phase: Option, 800 | pub credit_phase: Option, 801 | pub action_phase: Option, 802 | pub bounce_phase: Option, 803 | pub aborted: bool, 804 | pub destroyed: bool, 805 | pub raw: String, 806 | } 807 | 808 | #[derive(Debug, Deserialize)] 809 | pub enum TransactionType { 810 | TransOrd, 811 | TransTickTock, 812 | TransSplitPrepare, 813 | TransSplitInstall, 814 | TransMergePrepare, 815 | TransMergeInstall, 816 | TransStorage, 817 | } 818 | 819 | #[derive(Debug, Deserialize)] 820 | pub struct Message { 821 | pub msg_type: MsgType, 822 | pub created_lt: i64, 823 | pub ihr_disabled: bool, 824 | pub bounce: bool, 825 | pub bounced: bool, 826 | pub value: i64, 827 | pub fwd_fee: i64, 828 | pub ihr_fee: i64, 829 | pub destination: Option, 830 | pub source: Option, 831 | pub import_fee: i64, 832 | pub created_at: i64, 833 | pub op_code: Option, 834 | pub init: Option, 835 | pub hash: String, 836 | pub raw_body: Option, 837 | pub decoded_op_name: Option, 838 | pub decoded_body: Option, 839 | } 840 | 841 | #[derive(Debug, Deserialize)] 842 | #[serde(rename_all = "snake_case")] 843 | pub enum MsgType { 844 | IntMsg, 845 | ExtInMsg, 846 | ExtOutMsg, 847 | } 848 | 849 | #[derive(Debug, Deserialize)] 850 | pub struct StateInit { 851 | pub boc: String, 852 | pub interfaces: Vec, 853 | } 854 | 855 | #[derive(Debug, Deserialize)] 856 | pub struct ComputePhase { 857 | pub skipped: bool, 858 | pub skip_reason: Option, 859 | pub success: Option, 860 | pub gas_fees: Option, 861 | pub gas_used: Option, 862 | pub vm_steps: Option, 863 | pub exit_code: Option, 864 | pub exit_code_description: Option, 865 | } 866 | 867 | #[derive(Debug, Deserialize)] 868 | #[serde(rename_all = "snake_case")] 869 | pub enum ComputeSkipReason { 870 | CskipNoState, 871 | CskipBadState, 872 | CskipNoGas, 873 | } 874 | 875 | #[derive(Debug, Deserialize)] 876 | pub struct StoragePhase { 877 | pub fees_collected: i64, 878 | pub fees_due: Option, 879 | pub status_change: AccStatusChange, 880 | } 881 | 882 | #[derive(Debug, Deserialize)] 883 | #[serde(rename_all = "snake_case")] 884 | pub enum AccStatusChange { 885 | AcstUnchanged, 886 | AcstFrozen, 887 | AcstDeleted, 888 | } 889 | 890 | #[derive(Debug, Deserialize)] 891 | pub struct CreditPhase { 892 | pub fees_collected: i64, 893 | pub credit: i64, 894 | } 895 | 896 | #[derive(Debug, Deserialize)] 897 | pub struct ActionPhase { 898 | pub success: bool, 899 | pub result_code: i32, 900 | pub total_actions: i32, 901 | pub skipped_actions: i32, 902 | pub fwd_fees: i64, 903 | pub total_fees: i64, 904 | pub result_code_description: Option, 905 | } 906 | 907 | #[derive(Debug, Deserialize)] 908 | pub enum BouncePhaseType { 909 | #[serde(rename = "TrPhaseBounceNegfunds")] 910 | TrPhaseBounceNegFunds, 911 | #[serde(rename = "TrPhaseBounceNofunds")] 912 | TrPhaseBounceNoFunds, 913 | TrPhaseBounceOk, 914 | } 915 | 916 | #[derive(Debug, Deserialize)] 917 | pub struct Rates { 918 | pub rates: TokenRates, 919 | } 920 | 921 | #[derive(Debug, Deserialize)] 922 | pub struct RateChart { 923 | pub points: Vec, 924 | } 925 | 926 | #[derive(Debug, Deserialize)] 927 | pub struct Point( 928 | pub u64, // timestamp 929 | pub f64, // value 930 | ); 931 | 932 | #[derive(Debug, Deserialize)] 933 | pub struct MarketRates { 934 | pub markets: Vec, 935 | } 936 | 937 | #[derive(Debug, Deserialize)] 938 | pub struct MarketTonRates { 939 | pub market: String, 940 | pub usd_price: f64, 941 | pub last_date_update: i64, 942 | } 943 | 944 | #[derive(Debug, Deserialize)] 945 | pub struct AccountStaking { 946 | pub pools: Vec, 947 | } 948 | 949 | #[derive(Debug, Deserialize)] 950 | pub struct AccountStakingInfo { 951 | pub pool: String, 952 | pub amount: i64, 953 | pub pending_deposit: i64, 954 | pub pending_withdraw: i64, 955 | pub ready_withdraw: i64, 956 | } 957 | 958 | #[derive(Debug, Deserialize)] 959 | pub struct StakingPoolInfo { 960 | pub implementation: PoolImplementation, 961 | pub pool: PoolInfo, 962 | } 963 | 964 | #[derive(Debug, Deserialize)] 965 | pub struct PoolImplementation { 966 | pub name: String, 967 | pub description: String, 968 | pub url: String, 969 | pub socials: Vec, 970 | } 971 | 972 | #[derive(Debug, Deserialize)] 973 | pub struct PoolInfo { 974 | pub address: String, 975 | pub name: String, 976 | pub total_amount: i64, 977 | pub implementation: PoolImplementationType, 978 | pub apy: f64, 979 | pub min_stake: i64, 980 | pub cycle_start: i64, 981 | pub cycle_end: i64, 982 | pub verified: bool, 983 | pub current_nominators: i32, 984 | pub max_nominators: i32, 985 | pub liquid_jetton_master: Option, 986 | pub nominators_stake: i64, 987 | pub validator_stake: i64, 988 | pub cycle_length: Option, 989 | } 990 | 991 | #[derive(Debug, Deserialize)] 992 | pub struct StakingPoolHistory { 993 | pub apy: ApyHistory, 994 | } 995 | 996 | #[derive(Debug, Deserialize)] 997 | pub struct ApyHistory { 998 | pub apy: f64, 999 | pub time: i64, 1000 | } 1001 | 1002 | #[derive(Debug, Deserialize)] 1003 | pub struct StakingPools { 1004 | pub implementations: HashMap, 1005 | pub pools: Vec, 1006 | } 1007 | 1008 | #[derive(Debug, Deserialize)] 1009 | pub struct StorageProviders { 1010 | pub providers: Vec, 1011 | } 1012 | 1013 | #[derive(Debug, Deserialize)] 1014 | pub struct StorageProvider { 1015 | pub address: String, 1016 | pub accept_new_contracts: bool, 1017 | pub rate_per_mb_day: i64, 1018 | pub max_span: i64, 1019 | pub minimal_file_size: i64, 1020 | pub maximal_file_size: i64, 1021 | } 1022 | 1023 | #[derive(Debug, Deserialize)] 1024 | pub struct TonConnectPayload { 1025 | pub payload: String, 1026 | } 1027 | 1028 | #[derive(Debug, Deserialize)] 1029 | pub struct AccountInfo { 1030 | pub public_key: String, 1031 | pub address: String, 1032 | } 1033 | 1034 | #[derive(Debug, Deserialize)] 1035 | pub struct GaslessConfig { 1036 | pub relay_address: String, 1037 | pub gas_jettons: Vec, 1038 | } 1039 | 1040 | #[derive(Debug, Deserialize)] 1041 | pub struct GasJetton { 1042 | pub master_id: String, 1043 | } 1044 | 1045 | #[derive(Debug, Deserialize)] 1046 | pub struct SignRawParams { 1047 | pub relay_address: String, 1048 | pub commission: String, 1049 | pub from: String, 1050 | pub valid_until: i64, 1051 | pub messages: Vec, 1052 | } 1053 | 1054 | #[derive(Debug, Deserialize)] 1055 | pub struct SignRawMessage { 1056 | pub address: String, 1057 | pub amount: String, 1058 | pub payload: Option, 1059 | pub state_init: Option, 1060 | } 1061 | 1062 | #[derive(Debug, Deserialize)] 1063 | pub struct ReducedBlocks { 1064 | pub blocks: Vec, 1065 | } 1066 | 1067 | #[derive(Debug, Deserialize)] 1068 | pub struct ReducedBlock { 1069 | pub workchain_id: i32, 1070 | pub shard: String, 1071 | pub seqno: i32, 1072 | pub master_ref: Option, 1073 | pub tx_quantity: i32, 1074 | pub utime: i64, 1075 | pub shards_blocks: Vec, 1076 | pub parent: Vec, 1077 | } 1078 | 1079 | #[derive(Debug, Deserialize)] 1080 | pub struct BlockchainBlock { 1081 | pub workchain_id: i32, 1082 | pub shard: String, 1083 | pub seqno: i32, 1084 | pub root_hash: String, 1085 | pub file_hash: String, 1086 | pub global_id: i32, 1087 | pub value_flow: BlockValueFlow, 1088 | pub version: i32, 1089 | pub after_merge: bool, 1090 | pub before_split: bool, 1091 | pub after_split: bool, 1092 | pub want_split: bool, 1093 | pub want_merge: bool, 1094 | pub key_block: bool, 1095 | pub gen_utime: i64, 1096 | pub start_lt: i64, 1097 | pub end_lt: i64, 1098 | pub vert_seqno: i32, 1099 | pub gen_catchain_seqno: i32, 1100 | pub min_ref_mc_seqno: i32, 1101 | pub prev_key_block_seqno: i32, 1102 | pub gen_software_version: Option, 1103 | pub gen_software_capabilities: Option, 1104 | pub master_ref: Option, 1105 | pub prev_refs: Option>, 1106 | pub in_msg_descr_length: i64, 1107 | pub out_msg_descr_length: i64, 1108 | pub rand_seed: String, 1109 | pub created_by: String, 1110 | pub tx_quantity: i32, 1111 | } 1112 | 1113 | #[derive(Debug, Deserialize)] 1114 | pub struct BlockValueFlow { 1115 | pub from_prev_blk: BlockCurrencyCollection, 1116 | pub to_next_blk: BlockCurrencyCollection, 1117 | pub imported: BlockCurrencyCollection, 1118 | pub exported: BlockCurrencyCollection, 1119 | pub fees_collected: BlockCurrencyCollection, 1120 | pub burned: Option, 1121 | pub fees_imported: BlockCurrencyCollection, 1122 | pub recovered: BlockCurrencyCollection, 1123 | pub created: BlockCurrencyCollection, 1124 | pub minted: BlockCurrencyCollection, 1125 | } 1126 | 1127 | #[derive(Debug, Deserialize)] 1128 | pub struct BlockCurrencyCollection { 1129 | pub grams: i64, 1130 | pub other: Vec, 1131 | } 1132 | 1133 | #[derive(Debug, Deserialize)] 1134 | pub struct OtherCurrency { 1135 | pub id: i64, 1136 | pub value: String, 1137 | } 1138 | 1139 | #[derive(Debug, Deserialize)] 1140 | pub struct BlockchainBlockShards { 1141 | pub shards: Vec, 1142 | } 1143 | 1144 | #[derive(Debug, Deserialize)] 1145 | pub struct Shard { 1146 | pub last_known_block_id: String, 1147 | pub last_known_block: BlockchainBlock, 1148 | } 1149 | 1150 | #[derive(Debug, Deserialize)] 1151 | pub struct BlockchainBlocks { 1152 | pub blocks: Vec, 1153 | } 1154 | 1155 | #[derive(Debug, Deserialize)] 1156 | pub struct Transactions { 1157 | pub transactions: Vec, 1158 | } 1159 | 1160 | #[derive(Debug, Deserialize)] 1161 | pub struct BlockchainConfig { 1162 | pub raw: String, 1163 | #[serde(rename = "0")] 1164 | pub config_address: String, 1165 | #[serde(rename = "1")] 1166 | pub elector_address: String, 1167 | #[serde(rename = "2")] 1168 | pub minter_address: String, 1169 | #[serde(rename = "3")] 1170 | pub fee_collector_address: Option, 1171 | #[serde(rename = "4")] 1172 | pub dns_root_address: String, 1173 | #[serde(rename = "5")] 1174 | pub fee_burn_config: Option, 1175 | #[serde(rename = "6")] 1176 | pub minting_fees: Option, 1177 | #[serde(rename = "7")] 1178 | pub currency_volumes: Option, 1179 | #[serde(rename = "8")] 1180 | pub network_version: Option, 1181 | #[serde(rename = "9")] 1182 | pub mandatory_params: Option, 1183 | #[serde(rename = "10")] 1184 | pub critical_params: Option, 1185 | #[serde(rename = "11")] 1186 | pub proposal_setup: Option, 1187 | #[serde(rename = "12")] 1188 | pub workchains: Option, 1189 | #[serde(rename = "13")] 1190 | pub complaint_fees: Option, 1191 | #[serde(rename = "14")] 1192 | pub block_creation_rewards: Option, 1193 | #[serde(rename = "15")] 1194 | pub validator_election: Option, 1195 | #[serde(rename = "16")] 1196 | pub validator_limits: Option, 1197 | #[serde(rename = "17")] 1198 | pub stake_params: Option, 1199 | #[serde(rename = "18")] 1200 | pub storage_prices: Option, 1201 | #[serde(rename = "20")] 1202 | pub gas_limits_masterchain: Option, 1203 | #[serde(rename = "21")] 1204 | pub gas_limits_basechain: Option, 1205 | #[serde(rename = "22")] 1206 | pub block_limits_masterchain: Option, 1207 | #[serde(rename = "23")] 1208 | pub block_limits_basechain: Option, 1209 | #[serde(rename = "24")] 1210 | pub msg_forward_prices_masterchain: Option, 1211 | #[serde(rename = "25")] 1212 | pub msg_forward_prices_basechain: Option, 1213 | #[serde(rename = "28")] 1214 | pub catchain_config: Option, 1215 | #[serde(rename = "29")] 1216 | pub consensus_config: Option, 1217 | #[serde(rename = "31")] 1218 | pub fundamental_smc_addr: Option, 1219 | #[serde(rename = "32")] 1220 | pub validators_set_32: Option, 1221 | #[serde(rename = "33")] 1222 | pub validators_set_33: Option, 1223 | #[serde(rename = "34")] 1224 | pub validators_set_34: Option, 1225 | #[serde(rename = "35")] 1226 | pub validators_set_35: Option, 1227 | #[serde(rename = "36")] 1228 | pub validators_set_36: Option, 1229 | #[serde(rename = "37")] 1230 | pub validators_set_37: Option, 1231 | #[serde(rename = "40")] 1232 | pub misbehaviour_punishment: Option, 1233 | #[serde(rename = "43")] 1234 | pub size_limits_config: Option, 1235 | #[serde(rename = "44")] 1236 | pub suspended_accounts: SuspendedAccounts, 1237 | #[serde(rename = "71")] 1238 | pub oracle_bridge_params_71: Option, 1239 | #[serde(rename = "72")] 1240 | pub oracle_bridge_params_72: Option, 1241 | #[serde(rename = "73")] 1242 | pub oracle_bridge_params_73: Option, 1243 | #[serde(rename = "79")] 1244 | pub jetton_bridge_params_79: Option, 1245 | #[serde(rename = "81")] 1246 | pub jetton_bridge_params_81: Option, 1247 | #[serde(rename = "82")] 1248 | pub jetton_bridge_params_82: Option, 1249 | } 1250 | 1251 | #[derive(Debug, Deserialize)] 1252 | pub struct FeeBurnConfig { 1253 | pub blackhole_addr: Option, 1254 | pub fee_burn_nom: i64, 1255 | pub fee_burn_denom: i64, 1256 | } 1257 | 1258 | #[derive(Debug, Deserialize)] 1259 | pub struct MintingFees { 1260 | pub mint_new_price: i64, 1261 | pub mint_add_price: i64, 1262 | } 1263 | 1264 | #[derive(Debug, Deserialize)] 1265 | pub struct CurrencyVolumes { 1266 | pub currencies: Vec, 1267 | } 1268 | 1269 | #[derive(Debug, Deserialize)] 1270 | pub struct Currency { 1271 | pub currency_id: i64, 1272 | pub amount: String, 1273 | } 1274 | 1275 | #[derive(Debug, Deserialize)] 1276 | pub struct NetworkVersion { 1277 | pub version: i64, 1278 | pub capabilities: i64, 1279 | } 1280 | 1281 | #[derive(Debug, Deserialize)] 1282 | pub struct MandatoryParams { 1283 | pub mandatory_params: Vec, 1284 | } 1285 | 1286 | #[derive(Debug, Deserialize)] 1287 | pub struct CriticalParams { 1288 | pub critical_params: Vec, 1289 | } 1290 | 1291 | #[derive(Debug, Deserialize)] 1292 | pub struct ConfigProposal { 1293 | pub normal_params: ConfigProposalSetup, 1294 | pub critical_params: ConfigProposalSetup, 1295 | } 1296 | 1297 | #[derive(Debug, Deserialize)] 1298 | pub struct ConfigProposalSetup { 1299 | pub min_tot_rounds: i32, 1300 | pub max_tot_rounds: i32, 1301 | pub min_wins: i32, 1302 | pub max_losses: i32, 1303 | pub min_store_sec: i64, 1304 | pub max_store_sec: i64, 1305 | pub bit_price: i64, 1306 | pub cell_price: i64, 1307 | } 1308 | 1309 | #[derive(Debug, Deserialize)] 1310 | pub struct WorkchainsWrapper { 1311 | pub workchains: Vec, 1312 | } 1313 | 1314 | #[derive(Debug, Deserialize)] 1315 | pub struct WorkchainDescr { 1316 | pub workchain: i32, 1317 | pub enabled_since: i64, 1318 | pub actual_min_split: i32, 1319 | pub min_split: i32, 1320 | pub max_split: i32, 1321 | pub basic: i32, 1322 | pub active: bool, 1323 | pub accept_msgs: bool, 1324 | pub flags: i32, 1325 | pub zerostate_root_hash: String, 1326 | pub zerostate_file_hash: String, 1327 | pub version: i64, 1328 | } 1329 | 1330 | #[derive(Debug, Deserialize)] 1331 | pub struct ComplaintFees { 1332 | pub deposit: i64, 1333 | pub bit_price: i64, 1334 | pub cell_price: i64, 1335 | } 1336 | 1337 | #[derive(Debug, Deserialize)] 1338 | pub struct BlockCreationRewards { 1339 | pub masterchain_block_fee: i64, 1340 | pub basechain_block_fee: i64, 1341 | } 1342 | 1343 | #[derive(Debug, Deserialize)] 1344 | pub struct ValidatorElection { 1345 | pub validators_elected_for: i64, 1346 | pub elections_start_before: i64, 1347 | pub elections_end_before: i64, 1348 | pub stake_held_for: i64, 1349 | } 1350 | 1351 | #[derive(Debug, Deserialize)] 1352 | pub struct ValidatorLimits { 1353 | pub max_validators: i32, 1354 | pub max_main_validators: i32, 1355 | pub min_validators: i32, 1356 | } 1357 | 1358 | #[derive(Debug, Deserialize)] 1359 | pub struct StakeParams { 1360 | pub min_stake: String, 1361 | pub max_stake: String, 1362 | pub min_total_stake: String, 1363 | pub max_stake_factor: i64, 1364 | } 1365 | 1366 | #[derive(Debug, Deserialize)] 1367 | pub struct StoragePrices { 1368 | pub storage_prices: Vec, 1369 | } 1370 | 1371 | #[derive(Debug, Deserialize)] 1372 | pub struct StoragePrice { 1373 | pub utime_since: i64, 1374 | pub bit_price_ps: i64, 1375 | pub cell_price_ps: i64, 1376 | pub mc_bit_price_ps: i64, 1377 | pub mc_cell_price_ps: i64, 1378 | } 1379 | 1380 | #[derive(Debug, Deserialize)] 1381 | pub struct GasLimitPricesWrapper { 1382 | pub gas_limits_prices: GasLimitPrices, 1383 | } 1384 | 1385 | #[derive(Debug, Deserialize)] 1386 | pub struct GasLimitPrices { 1387 | pub gas_price: i64, 1388 | pub gas_limit: i64, 1389 | pub gas_credit: i64, 1390 | pub block_gas_limit: i64, 1391 | pub freeze_due_limit: i64, 1392 | pub delete_due_limit: i64, 1393 | pub special_gas_limit: Option, 1394 | pub flat_gas_limit: Option, 1395 | pub flat_gas_price: Option, 1396 | } 1397 | 1398 | #[derive(Debug, Deserialize)] 1399 | pub struct BlockParamLimits { 1400 | pub underload: i64, 1401 | pub soft_limit: i64, 1402 | pub hard_limit: i64, 1403 | } 1404 | 1405 | #[derive(Debug, Deserialize)] 1406 | pub struct BlockLimitsWrapper { 1407 | pub block_limits: BlockLimits, 1408 | } 1409 | 1410 | #[derive(Debug, Deserialize)] 1411 | pub struct BlockLimits { 1412 | pub bytes: BlockParamLimits, 1413 | pub gas: BlockParamLimits, 1414 | pub lt_delta: BlockParamLimits, 1415 | } 1416 | 1417 | #[derive(Debug, Deserialize)] 1418 | pub struct MsgForwardPricesWrapper { 1419 | pub msg_forward_prices: MsgForwardPrices, 1420 | } 1421 | 1422 | #[derive(Debug, Deserialize)] 1423 | pub struct MsgForwardPrices { 1424 | pub lump_price: i64, 1425 | pub bit_price: i64, 1426 | pub cell_price: i64, 1427 | pub ihr_price_factor: i64, 1428 | pub first_frac: i64, 1429 | pub next_frac: i64, 1430 | } 1431 | 1432 | #[derive(Debug, Deserialize)] 1433 | pub struct CatchainConfig { 1434 | pub mc_catchain_lifetime: i64, 1435 | pub shard_catchain_lifetime: i64, 1436 | pub shard_validators_lifetime: i64, 1437 | pub shard_validators_num: i64, 1438 | pub flags: Option, 1439 | pub shuffle_mc_validators: Option, 1440 | } 1441 | 1442 | #[derive(Debug, Deserialize)] 1443 | pub struct ConsensusConfig { 1444 | pub round_candidates: i64, 1445 | pub next_candidate_delay_ms: i64, 1446 | pub consensus_timeout_ms: i64, 1447 | pub fast_attempts: i64, 1448 | pub attempt_duration: i64, 1449 | pub catchain_max_deps: i64, 1450 | pub max_block_bytes: i64, 1451 | pub max_collated_bytes: i64, 1452 | pub proto_version: i64, 1453 | pub catchain_max_blocks_coeff: i64, 1454 | pub flags: Option, 1455 | pub new_catchain_ids: Option, 1456 | } 1457 | 1458 | #[derive(Debug, Deserialize)] 1459 | pub struct FundamentalSmcAddr { 1460 | pub fundamental_smc_addr: Vec, 1461 | } 1462 | 1463 | #[derive(Debug, Deserialize)] 1464 | pub struct ValidatorsSet { 1465 | pub utime_since: i64, 1466 | pub utime_until: i64, 1467 | pub total: i32, 1468 | pub main: i32, 1469 | pub total_weight: String, 1470 | pub list: Vec, 1471 | } 1472 | 1473 | #[derive(Debug, Deserialize)] 1474 | pub struct ValidatorInfo { 1475 | pub public_key: String, 1476 | pub weight: i64, 1477 | pub adnl_addr: Option, 1478 | } 1479 | 1480 | #[derive(Debug, Deserialize)] 1481 | pub struct MisbehaviourPunishmentConfig { 1482 | pub default_flat_fine: i64, 1483 | pub default_proportional_fine: i64, 1484 | pub severity_flat_mult: i64, 1485 | pub severity_proportional_mult: i64, 1486 | pub unpunishable_interval: i64, 1487 | pub long_interval: i64, 1488 | pub long_flat_mult: i64, 1489 | pub long_proportional_mult: i64, 1490 | pub medium_interval: i64, 1491 | pub medium_flat_mult: i64, 1492 | pub medium_proportional_mult: i64, 1493 | } 1494 | 1495 | #[derive(Debug, Deserialize)] 1496 | pub struct SizeLimitsConfig { 1497 | pub max_msg_bits: i64, 1498 | pub max_msg_cells: i64, 1499 | pub max_library_cells: i64, 1500 | pub max_vm_data_depth: i32, 1501 | pub max_ext_msg_size: i64, 1502 | pub max_ext_msg_depth: i32, 1503 | pub max_acc_state_cells: Option, 1504 | pub max_acc_state_bits: Option, 1505 | } 1506 | 1507 | #[derive(Debug, Deserialize)] 1508 | pub struct SuspendedAccounts { 1509 | pub accounts: Vec, 1510 | pub suspended_until: i64, 1511 | } 1512 | 1513 | #[derive(Debug, Deserialize)] 1514 | pub struct OracleBridgeParamsWrapper { 1515 | pub oracle_bridge_params: OracleBridgeParams, 1516 | } 1517 | 1518 | #[derive(Debug, Deserialize)] 1519 | pub struct OracleBridgeParams { 1520 | pub bridge_addr: String, 1521 | pub oracle_multisig_address: String, 1522 | pub external_chain_address: String, 1523 | pub oracles: Vec, 1524 | } 1525 | 1526 | #[derive(Debug, Deserialize)] 1527 | pub struct Oracle { 1528 | pub address: String, 1529 | pub secp_pubkey: String, 1530 | } 1531 | 1532 | #[derive(Debug, Deserialize)] 1533 | pub struct JettonBridgeParamsWrapper { 1534 | pub jetton_bridge_params: JettonBridgeParams, 1535 | } 1536 | 1537 | #[derive(Debug, Deserialize)] 1538 | pub struct JettonBridgeParams { 1539 | pub bridge_address: String, 1540 | pub oracles_address: String, 1541 | pub state_flags: i64, 1542 | pub burn_bridge_fee: Option, 1543 | pub oracles: Vec, 1544 | pub external_chain_address: Option, 1545 | pub prices: Option, 1546 | } 1547 | 1548 | #[derive(Debug, Deserialize)] 1549 | pub struct JettonBridgePrices { 1550 | pub bridge_burn_fee: i64, 1551 | pub bridge_mint_fee: i64, 1552 | pub wallet_min_tons_for_storage: i64, 1553 | pub wallet_gas_consumption: i64, 1554 | pub minter_min_tons_for_storage: i64, 1555 | pub discover_gas_consumption: i64, 1556 | } 1557 | 1558 | #[derive(Debug, Deserialize)] 1559 | pub struct RawBlockchainConfig { 1560 | pub config: HashMap, 1561 | } 1562 | 1563 | #[derive(Debug, Deserialize)] 1564 | pub struct Validators { 1565 | pub elect_at: i64, 1566 | pub elect_close: i64, 1567 | pub min_stake: i64, 1568 | pub total_stake: i64, 1569 | pub validators: Vec, 1570 | } 1571 | 1572 | #[derive(Debug, Deserialize)] 1573 | pub struct Validator { 1574 | pub address: String, 1575 | pub adnl_address: String, 1576 | pub stake: i64, 1577 | pub max_factor: i64, 1578 | } 1579 | 1580 | #[derive(Debug, Deserialize)] 1581 | pub struct BlockchainRawAccount { 1582 | pub address: String, 1583 | pub balance: i64, 1584 | pub extra_balance: Option>, 1585 | pub code: Option, 1586 | pub data: Option, 1587 | pub last_transaction_lt: i64, 1588 | pub last_transaction_hash: Option, 1589 | pub frozen_hash: Option, 1590 | pub status: AccountStatus, 1591 | pub storage: AccountStorageInfo, 1592 | pub libraries: Option>, 1593 | } 1594 | 1595 | #[derive(Debug, Deserialize)] 1596 | pub struct AccountStorageInfo { 1597 | pub used_cells: i64, 1598 | pub used_bits: i64, 1599 | pub used_public_cells: i64, 1600 | pub last_paid: i64, 1601 | pub due_payment: i64, 1602 | } 1603 | 1604 | #[derive(Debug, Deserialize)] 1605 | pub struct AccountLibrary { 1606 | pub public: bool, 1607 | pub root: String, 1608 | } 1609 | 1610 | #[derive(Debug, Deserialize)] 1611 | pub struct MethodExecutionResult { 1612 | pub success: bool, 1613 | pub exit_code: i32, 1614 | pub stack: Vec, 1615 | pub decoded: Option, 1616 | } 1617 | 1618 | #[derive(Debug, Deserialize)] 1619 | #[serde(tag = "type")] 1620 | pub enum TvmStackRecord { 1621 | #[serde(rename = "cell")] 1622 | Cell { 1623 | #[serde(skip_serializing_if = "Option::is_none")] 1624 | cell: Option, 1625 | }, 1626 | #[serde(rename = "slice")] 1627 | Slice { 1628 | #[serde(skip_serializing_if = "Option::is_none")] 1629 | slice: Option, 1630 | }, 1631 | #[serde(rename = "num")] 1632 | Num { 1633 | #[serde(skip_serializing_if = "Option::is_none")] 1634 | num: Option, 1635 | }, 1636 | #[serde(rename = "tuple")] 1637 | Tuple { 1638 | #[serde(skip_serializing_if = "Option::is_none")] 1639 | tuple: Option>, 1640 | }, 1641 | #[serde(rename = "nan")] 1642 | Nan, 1643 | #[serde(rename = "null")] 1644 | Null, 1645 | } 1646 | 1647 | #[derive(Debug, Deserialize)] 1648 | pub struct BlockchainAccountInspect { 1649 | pub code: String, 1650 | pub code_hash: String, 1651 | pub methods: Vec, 1652 | pub compiler: Option, 1653 | } 1654 | 1655 | #[derive(Debug, Deserialize)] 1656 | pub struct Method { 1657 | pub id: i64, 1658 | pub method: String, 1659 | } 1660 | 1661 | #[derive(Debug, Deserialize)] 1662 | pub struct RawMasterchainInfo { 1663 | pub last: BlockRaw, 1664 | pub state_root_hash: String, 1665 | pub init: InitStateRaw, 1666 | } 1667 | 1668 | #[derive(Debug, Deserialize)] 1669 | pub struct BlockRaw { 1670 | pub workchain: i32, 1671 | pub shard: String, 1672 | pub seqno: i32, 1673 | pub root_hash: String, 1674 | pub file_hash: String, 1675 | } 1676 | 1677 | #[derive(Debug, Deserialize)] 1678 | pub struct InitStateRaw { 1679 | pub workchain: i32, 1680 | pub root_hash: String, 1681 | pub file_hash: String, 1682 | } 1683 | 1684 | #[derive(Deserialize, Debug)] 1685 | pub struct RawMasterchainInfoExt { 1686 | pub mode: i32, 1687 | pub version: i32, 1688 | pub capabilities: i64, 1689 | pub last: BlockRaw, 1690 | pub last_utime: i32, 1691 | pub now: i32, 1692 | pub state_root_hash: String, 1693 | pub init: InitStateRaw, 1694 | } 1695 | 1696 | #[derive(Deserialize, Debug)] 1697 | pub struct RawTime { 1698 | pub time: i32, 1699 | } 1700 | 1701 | #[derive(Deserialize, Debug)] 1702 | pub struct RawBlockchainBlock { 1703 | pub id: BlockRaw, 1704 | pub data: String, 1705 | } 1706 | 1707 | #[derive(Deserialize, Debug)] 1708 | pub struct RawBlockchainBlockState { 1709 | pub id: BlockRaw, 1710 | pub root_hash: String, 1711 | pub file_hash: String, 1712 | pub data: String, 1713 | } 1714 | 1715 | #[derive(Deserialize, Debug)] 1716 | pub struct RawBlockchainBlockHeader { 1717 | pub id: BlockRaw, 1718 | pub mode: i32, 1719 | pub header_proof: String, 1720 | } 1721 | 1722 | #[derive(Deserialize, Debug)] 1723 | pub struct SendMessageResponse { 1724 | pub code: i32, 1725 | } 1726 | 1727 | #[derive(Deserialize, Debug)] 1728 | pub struct RawAccountState { 1729 | pub id: BlockRaw, 1730 | pub shardblk: BlockRaw, 1731 | pub shard_proof: String, 1732 | pub proof: String, 1733 | pub state: String, 1734 | } 1735 | 1736 | #[derive(Deserialize, Debug)] 1737 | pub struct RawShardInfo { 1738 | pub id: BlockRaw, 1739 | pub shardblk: BlockRaw, 1740 | pub shard_proof: String, 1741 | pub shard_descr: String, 1742 | } 1743 | 1744 | #[derive(Deserialize, Debug)] 1745 | pub struct AllRawShardsInfo { 1746 | pub id: BlockRaw, 1747 | pub proof: String, 1748 | pub data: String, 1749 | } 1750 | 1751 | #[derive(Deserialize, Debug)] 1752 | pub struct RawTransactions { 1753 | pub ids: Vec, 1754 | pub transactions: String, 1755 | } 1756 | 1757 | #[derive(Deserialize, Debug)] 1758 | pub struct RawListBlockTransactions { 1759 | pub id: BlockRaw, 1760 | pub req_count: i32, 1761 | pub incomplete: bool, 1762 | pub ids: Vec, 1763 | pub proof: String, 1764 | } 1765 | 1766 | #[derive(Deserialize, Debug)] 1767 | pub struct TransactionId { 1768 | pub mode: i32, 1769 | pub account: Option, 1770 | pub lt: Option, 1771 | pub hash: Option, 1772 | } 1773 | 1774 | #[derive(Deserialize, Debug)] 1775 | pub struct RawBlockProof { 1776 | pub complete: bool, 1777 | pub from: BlockRaw, 1778 | pub to: BlockRaw, 1779 | pub steps: Vec, 1780 | } 1781 | 1782 | #[derive(Deserialize, Debug)] 1783 | pub struct BlockProofStep { 1784 | pub lite_server_block_link_back: LiteServerBlockLinkBack, 1785 | pub lite_server_block_link_forward: LiteServerBlockLinkForward, 1786 | } 1787 | 1788 | #[derive(Deserialize, Debug)] 1789 | pub struct LiteServerBlockLinkBack { 1790 | pub to_key_block: bool, 1791 | pub from: BlockRaw, 1792 | pub to: BlockRaw, 1793 | pub dest_proof: String, 1794 | pub proof: String, 1795 | pub state_proof: String, 1796 | } 1797 | 1798 | #[derive(Deserialize, Debug)] 1799 | pub struct LiteServerBlockLinkForward { 1800 | pub to_key_block: bool, 1801 | pub from: BlockRaw, 1802 | pub to: BlockRaw, 1803 | pub dest_proof: String, 1804 | pub config_proof: String, 1805 | pub signatures: Signatures, 1806 | } 1807 | 1808 | #[derive(Deserialize, Debug)] 1809 | pub struct Signatures { 1810 | pub validator_set_hash: i64, 1811 | pub catchain_seqno: i32, 1812 | pub signatures: Vec, 1813 | } 1814 | 1815 | #[derive(Deserialize, Debug)] 1816 | pub struct Signature { 1817 | pub node_id_short: String, 1818 | pub signature: String, 1819 | } 1820 | 1821 | #[derive(Deserialize, Debug)] 1822 | pub struct RawConfig { 1823 | pub mode: i32, 1824 | pub id: BlockRaw, 1825 | pub state_proof: String, 1826 | pub config_proof: String, 1827 | } 1828 | 1829 | #[derive(Deserialize, Debug)] 1830 | pub struct RawShardBlockProof { 1831 | pub masterchain_id: BlockRaw, 1832 | pub links: Vec, 1833 | } 1834 | 1835 | #[derive(Deserialize, Debug)] 1836 | pub struct ShardBlockProofLink { 1837 | pub id: BlockRaw, 1838 | pub proof: String, 1839 | } 1840 | 1841 | #[derive(Deserialize, Debug)] 1842 | pub struct OutMsgQueueSizes { 1843 | pub ext_msg_queue_size_limit: u32, 1844 | pub shards: Vec, 1845 | } 1846 | 1847 | #[derive(Deserialize, Debug)] 1848 | pub struct ShardQueueSize { 1849 | pub id: BlockRaw, 1850 | pub size: u32, 1851 | } 1852 | 1853 | #[derive(Debug, Deserialize)] 1854 | pub struct DecodedMessage { 1855 | pub destination: AccountAddress, 1856 | pub destination_wallet_version: String, 1857 | pub ext_in_msg_decoded: Option, 1858 | } 1859 | 1860 | #[derive(Debug, Deserialize)] 1861 | pub struct ExtInMsgDecoded { 1862 | pub wallet_v3: Option, 1863 | pub wallet_v4: Option, 1864 | pub wallet_highload_v2: Option, 1865 | } 1866 | 1867 | #[derive(Debug, Deserialize)] 1868 | pub struct WalletV3Message { 1869 | pub subwallet_id: i64, 1870 | pub valid_until: i64, 1871 | pub seqno: i64, 1872 | pub raw_messages: Vec, 1873 | } 1874 | 1875 | #[derive(Debug, Deserialize)] 1876 | pub struct WalletV4Message { 1877 | pub subwallet_id: i64, 1878 | pub valid_until: i64, 1879 | pub seqno: i64, 1880 | pub op: i32, 1881 | pub raw_messages: Vec, 1882 | } 1883 | 1884 | #[derive(Debug, Deserialize)] 1885 | pub struct WalletHighloadV2Message { 1886 | pub subwallet_id: i64, 1887 | pub bounded_query_id: String, 1888 | pub raw_messages: Vec, 1889 | } 1890 | 1891 | #[derive(Debug, Deserialize)] 1892 | pub struct DecodedRawMessage { 1893 | pub message: DecodedMessageDetails, 1894 | pub mode: i32, 1895 | } 1896 | 1897 | #[derive(Debug, Deserialize)] 1898 | pub struct DecodedMessageDetails { 1899 | pub boc: String, 1900 | pub decoded_op_name: Option, 1901 | pub op_code: Option, 1902 | pub decoded_body: Option, 1903 | } 1904 | 1905 | #[derive(Debug, Deserialize)] 1906 | pub struct InscriptionBalances { 1907 | pub inscriptions: Vec, 1908 | } 1909 | 1910 | #[derive(Debug, Deserialize)] 1911 | pub struct InscriptionBalance { 1912 | #[serde(rename = "type")] 1913 | pub inscription_type: String, 1914 | pub ticker: String, 1915 | pub balance: String, 1916 | pub decimals: i32, 1917 | } 1918 | 1919 | #[derive(Deserialize, Debug)] 1920 | pub struct InscriptionOpTemplate { 1921 | pub comment: String, 1922 | pub destination: String, 1923 | } 1924 | 1925 | #[derive(Deserialize, Debug)] 1926 | pub struct ServiceStatus { 1927 | pub rest_online: bool, 1928 | pub indexing_latency: i64, 1929 | pub last_known_masterchain_seqno: i32, 1930 | } 1931 | 1932 | #[derive(Deserialize, Debug)] 1933 | pub struct ParsedAddress { 1934 | pub raw_form: String, 1935 | pub bounceable: AddressFormat, 1936 | pub non_bounceable: AddressFormat, 1937 | pub given_type: String, 1938 | pub test_only: bool, 1939 | } 1940 | 1941 | #[derive(Deserialize, Debug)] 1942 | pub struct AddressFormat { 1943 | pub b64: String, 1944 | pub b64url: String, 1945 | } 1946 | -------------------------------------------------------------------------------- /src/rest_api/v2.rs: -------------------------------------------------------------------------------- 1 | use super::{ 2 | base::BaseRestApiClient, 3 | error::TonApiError, 4 | models::{ 5 | Account, AccountEvent, AccountEvents, AccountInfo, AccountSeqno, AccountStaking, Accounts, 6 | AllRawShardsInfo, Auctions, AuthToken, BalanceChange, BlockchainAccountInspect, 7 | BlockchainBlock, BlockchainBlockShards, BlockchainBlocks, BlockchainConfig, 8 | BlockchainRawAccount, DecodedMessage, DnsExpiring, DnsRecord, DomainBids, DomainInfo, 9 | DomainNames, Dump, Event, FoundAccounts, GaslessConfig, InscriptionBalances, 10 | InscriptionOpTemplate, JettonBalance, JettonBalances, JettonHolders, JettonInfo, 11 | JettonTransferPayload, Jettons, MarketRates, MessageConsequences, MethodExecutionResult, 12 | Multisig, Multisigs, NftCollection, NftCollections, NftItem, NftItems, OutMsgQueueSizes, 13 | ParsedAddress, PublicKey, RateChart, Rates, RawAccountState, RawBlockProof, 14 | RawBlockchainBlock, RawBlockchainBlockHeader, RawBlockchainBlockState, RawBlockchainConfig, 15 | RawConfig, RawListBlockTransactions, RawMasterchainInfo, RawMasterchainInfoExt, 16 | RawShardBlockProof, RawShardInfo, RawTime, RawTransactions, ReducedBlocks, 17 | SendMessageResponse, ServiceStatus, SignRawParams, StakingPoolHistory, StakingPoolInfo, 18 | StakingPools, StorageProviders, Subscriptions, TonConnectPayload, Trace, TraceIds, 19 | Transaction, Transactions, Validators, 20 | }, 21 | query_params::QueryParams, 22 | }; 23 | use crate::Network; 24 | use reqwest::{ 25 | header::{HeaderMap, HeaderValue, ACCEPT_LANGUAGE}, 26 | Client, 27 | }; 28 | 29 | pub struct RestApiClientV2 { 30 | base_client: BaseRestApiClient, 31 | } 32 | 33 | impl RestApiClientV2 { 34 | pub fn new(network: Network, api_key: Option) -> Self { 35 | let client = Client::new(); 36 | let base_url = match network { 37 | Network::Mainnet => "https://tonapi.io/v2/".to_string(), 38 | Network::Testnet => "https://testnet.tonapi.io/v2/".to_string(), 39 | }; 40 | Self { 41 | base_client: BaseRestApiClient::new(client, base_url, api_key), 42 | } 43 | } 44 | 45 | /// Get human-friendly information about several accounts without low-level details. 46 | /// 47 | /// # Parameters 48 | /// 49 | /// - `account_ids` - a list of account ids 50 | /// - `currency` 51 | /// 52 | /// # Returns 53 | /// 54 | /// a list of account ids 55 | pub async fn get_accounts( 56 | &self, 57 | account_ids: &[&str], 58 | currency: Option<&str>, 59 | ) -> Result { 60 | let mut params = QueryParams::new(); 61 | 62 | if let Some(currency) = currency { 63 | params.insert("currency", currency); 64 | } 65 | 66 | let body = serde_json::json!({ 67 | "account_ids": account_ids 68 | }); 69 | 70 | self.base_client 71 | .post_json( 72 | "accounts/_bulk".to_string(), 73 | Some(params), 74 | Some(&body), 75 | None, 76 | ) 77 | .await 78 | } 79 | 80 | /// Get human-friendly information about an account without low-level details. 81 | /// 82 | /// # Parameters 83 | /// 84 | /// - `account_id` - account ID 85 | /// 86 | /// # Returns 87 | /// 88 | /// account 89 | pub async fn get_account(&self, account_id: &str) -> Result { 90 | self.base_client 91 | .get(format!("accounts/{account_id}"), None, None) 92 | .await 93 | } 94 | 95 | /// Get account's domains. 96 | /// 97 | /// # Parameters 98 | /// 99 | /// - `account_id` - account ID 100 | /// 101 | /// # Returns 102 | /// 103 | /// account's domains 104 | pub async fn account_dns_back_resolve( 105 | &self, 106 | account_id: &str, 107 | ) -> Result { 108 | self.base_client 109 | .get(format!("accounts/{account_id}/dns/backresolve"), None, None) 110 | .await 111 | } 112 | 113 | /// Get all Jettons balances by owner address. 114 | /// 115 | /// # Parameters 116 | /// 117 | /// - `account_id` - account ID 118 | /// - `currencies` - accept ton and all possible fiat currencies 119 | /// - `supported_extensions` - list of supported extensions 120 | /// 121 | /// # Returns 122 | /// 123 | /// account jettons balances 124 | pub async fn get_account_jettons_balances( 125 | &self, 126 | account_id: &str, 127 | currencies: Option<&[&str]>, 128 | supported_extensions: Option<&[&str]>, 129 | ) -> Result { 130 | let mut params = QueryParams::new(); 131 | 132 | if let Some(currencies) = currencies { 133 | params.insert("currencies", currencies); 134 | } 135 | 136 | if let Some(supported_extensions) = supported_extensions { 137 | params.insert("supported_extensions", supported_extensions); 138 | } 139 | 140 | self.base_client 141 | .get(format!("accounts/{account_id}/jettons"), Some(params), None) 142 | .await 143 | } 144 | 145 | /// Get Jetton balance by owner address. 146 | /// 147 | /// # Parameters 148 | /// 149 | /// - `account_id` - account ID 150 | /// - `jetton_id` - jetton ID 151 | /// - `currencies` - accept ton and all possible fiat currencies 152 | /// 153 | /// # Returns 154 | /// 155 | /// account jetton balance 156 | pub async fn get_account_jetton_balance( 157 | &self, 158 | account_id: &str, 159 | jetton_id: &str, 160 | currencies: Option<&[&str]>, 161 | ) -> Result { 162 | let mut params = QueryParams::new(); 163 | 164 | if let Some(currencies) = currencies { 165 | params.insert("currencies", currencies); 166 | } 167 | 168 | self.base_client 169 | .get( 170 | format!("accounts/{account_id}/jettons/{jetton_id}"), 171 | Some(params), 172 | None, 173 | ) 174 | .await 175 | } 176 | 177 | /// Get the transfer jettons history for account. 178 | /// 179 | /// # Parameters 180 | /// 181 | /// - `account_id` - account ID 182 | /// - `accept_language` - *Default value*: en 183 | /// - `before_lt` - omit this parameter to get last events 184 | /// - `limit` 185 | /// - `start_date` 186 | /// - `end_date` 187 | /// 188 | /// # Returns 189 | /// 190 | /// account jettons history 191 | pub async fn get_account_jettons_history( 192 | &self, 193 | account_id: &str, 194 | accept_language: Option<&str>, 195 | before_lt: Option, 196 | limit: u64, 197 | start_date: Option, 198 | end_date: Option, 199 | ) -> Result { 200 | let mut params = QueryParams::from_pairs([("limit", limit)]); 201 | 202 | if let Some(before_lt) = before_lt { 203 | params.insert("before_lt", before_lt); 204 | } 205 | 206 | if let Some(start_date) = start_date { 207 | params.insert("start_date", start_date); 208 | } 209 | 210 | if let Some(end_date) = end_date { 211 | params.insert("end_date", end_date); 212 | } 213 | 214 | let mut headers = HeaderMap::new(); 215 | 216 | if let Some(language) = accept_language { 217 | headers.insert(ACCEPT_LANGUAGE, HeaderValue::from_str(language)?); 218 | } 219 | 220 | self.base_client 221 | .get( 222 | format!("accounts/{account_id}/jettons/history"), 223 | Some(params), 224 | Some(headers), 225 | ) 226 | .await 227 | } 228 | 229 | /// Get the transfer jetton history for account and jetton. 230 | /// 231 | /// # Parameters 232 | /// 233 | /// - `account_id` - account ID 234 | /// - `jetton_id` - jetton ID 235 | /// - `accept_language` - *Default value*: en 236 | /// - `before_lt` - omit this parameter to get last events 237 | /// - `limit` 238 | /// - `start_date` 239 | /// - `end_date` 240 | /// 241 | /// # Returns 242 | /// 243 | /// account jetton history 244 | pub async fn get_account_jetton_history_by_id( 245 | &self, 246 | account_id: &str, 247 | jetton_id: &str, 248 | accept_language: Option<&str>, 249 | before_lt: Option, 250 | limit: u64, 251 | start_date: Option, 252 | end_date: Option, 253 | ) -> Result { 254 | let mut params = QueryParams::from_pairs([("limit", limit)]); 255 | 256 | if let Some(before_lt) = before_lt { 257 | params.insert("before_lt", before_lt); 258 | } 259 | 260 | if let Some(start_date) = start_date { 261 | params.insert("start_date", start_date); 262 | } 263 | 264 | if let Some(end_date) = end_date { 265 | params.insert("end_date", end_date); 266 | } 267 | 268 | let mut headers = HeaderMap::new(); 269 | 270 | if let Some(language) = accept_language { 271 | headers.insert(ACCEPT_LANGUAGE, HeaderValue::from_str(language)?); 272 | } 273 | 274 | self.base_client 275 | .get( 276 | format!("accounts/{account_id}/jettons/{jetton_id}/history"), 277 | Some(params), 278 | Some(headers), 279 | ) 280 | .await 281 | } 282 | 283 | /// Get all NFT items by owner address. 284 | /// 285 | /// # Parameters 286 | /// 287 | /// - `account_id` - account ID 288 | /// - `collection` - nft collection 289 | /// - `limit` 290 | /// - `offset` 291 | /// - `indirect_ownership` - Selling nft items in ton implemented usually via transfer items to special selling account. This option enables including items which owned not directly. 292 | /// 293 | /// # Returns 294 | /// 295 | /// account nft items 296 | pub async fn get_account_nft_items( 297 | &self, 298 | account_id: &str, 299 | collection: Option<&str>, 300 | limit: Option, 301 | offset: Option, 302 | indirect_ownership: Option, 303 | ) -> Result { 304 | let mut params = QueryParams::new(); 305 | 306 | if let Some(collection) = collection { 307 | params.insert("collection", collection); 308 | } 309 | 310 | if let Some(limit) = limit { 311 | params.insert("limit", limit); 312 | } 313 | 314 | if let Some(offset) = offset { 315 | params.insert("offset", offset); 316 | } 317 | 318 | if let Some(indirect_ownership) = indirect_ownership { 319 | params.insert("indirect_ownership", indirect_ownership); 320 | } 321 | 322 | self.base_client 323 | .get(format!("accounts/{account_id}/nfts"), Some(params), None) 324 | .await 325 | } 326 | 327 | /// Get events for an account. Each event is built on top of a trace which is a series of transactions caused by one inbound message. TonAPI looks for known patterns inside the trace and splits the trace into actions, where a single action represents a meaningful high-level operation like a Jetton Transfer or an NFT Purchase. Actions are expected to be shown to users. It is advised not to build any logic on top of actions because actions can be changed at any time. 328 | /// 329 | /// # Parameters 330 | /// 331 | /// - `account_id` - account ID 332 | /// - `accept_language` - *Default value*: en 333 | /// - `initiator` - Show only events that are initiated by this account 334 | /// - `subject_only` - filter actions where requested account is not real subject (for example sender or receiver jettons) 335 | /// - `before_lt` - omit this parameter to get last events 336 | /// - `limit` 337 | /// - `start_date` 338 | /// - `end_date` 339 | /// 340 | /// # Returns 341 | /// 342 | /// account's events 343 | pub async fn get_account_events( 344 | &self, 345 | account_id: &str, 346 | accept_language: Option<&str>, 347 | initiator: Option, 348 | subject_only: Option, 349 | before_lt: Option, 350 | limit: u64, 351 | start_date: Option, 352 | end_date: Option, 353 | ) -> Result { 354 | let mut params = QueryParams::from_pairs([("limit", limit)]); 355 | 356 | if let Some(initiator) = initiator { 357 | params.insert("initiator", initiator); 358 | } 359 | 360 | if let Some(subject_only) = subject_only { 361 | params.insert("subject_only", subject_only); 362 | } 363 | 364 | if let Some(before_lt) = before_lt { 365 | params.insert("before_lt", before_lt); 366 | } 367 | 368 | if let Some(start_date) = start_date { 369 | params.insert("start_date", start_date); 370 | } 371 | 372 | if let Some(end_date) = end_date { 373 | params.insert("end_date", end_date); 374 | } 375 | 376 | let mut headers = HeaderMap::new(); 377 | 378 | if let Some(language) = accept_language { 379 | headers.insert(ACCEPT_LANGUAGE, HeaderValue::from_str(language)?); 380 | } 381 | 382 | self.base_client 383 | .get(format!("accounts/{account_id}/events"), Some(params), None) 384 | .await 385 | } 386 | 387 | /// Get event for an account by event_id. 388 | /// 389 | /// # Parameters 390 | /// 391 | /// - `account_id` - account ID 392 | /// - `event_id` - event ID or transaction hash in hex (without 0x) or base64url format 393 | /// - `accept_language` - *Default value*: en 394 | /// - `subject_only` - filter actions where requested account is not real subject (for example sender or receiver jettons) 395 | /// 396 | /// # Returns 397 | /// 398 | /// account's event 399 | pub async fn get_account_event( 400 | &self, 401 | account_id: &str, 402 | event_id: &str, 403 | accept_language: Option<&str>, 404 | subject_only: Option, 405 | ) -> Result { 406 | let mut params = QueryParams::new(); 407 | 408 | if let Some(subject_only) = subject_only { 409 | params.insert("subject_only", subject_only); 410 | } 411 | 412 | let mut headers = HeaderMap::new(); 413 | 414 | if let Some(language) = accept_language { 415 | headers.insert(ACCEPT_LANGUAGE, HeaderValue::from_str(language)?); 416 | } 417 | 418 | self.base_client 419 | .get( 420 | format!("accounts/{account_id}/events/{event_id}"), 421 | Some(params), 422 | None, 423 | ) 424 | .await 425 | } 426 | 427 | /// Get traces for account. 428 | /// 429 | /// # Parameters 430 | /// 431 | /// - `account_id` - account ID 432 | /// - `before_lt` - omit this parameter to get last events 433 | /// - `limit` - *Default value*: 100 434 | /// 435 | /// # Returns 436 | /// 437 | /// account's traces 438 | pub async fn get_account_traces( 439 | &self, 440 | account_id: &str, 441 | before_lt: Option, 442 | limit: Option, 443 | ) -> Result { 444 | let mut params = QueryParams::new(); 445 | 446 | if let Some(before_lt) = before_lt { 447 | params.insert("before_lt", before_lt); 448 | } 449 | 450 | if let Some(limit) = limit { 451 | params.insert("limit", limit); 452 | } 453 | 454 | self.base_client 455 | .get(format!("accounts/{account_id}/traces"), Some(params), None) 456 | .await 457 | } 458 | 459 | /// Get all subscriptions by wallet address. 460 | /// 461 | /// # Parameters 462 | /// 463 | /// - `account_id` - account ID 464 | /// 465 | /// # Returns 466 | /// 467 | /// account's subscriptions 468 | pub async fn get_account_subscriptions( 469 | &self, 470 | account_id: &str, 471 | ) -> Result { 472 | self.base_client 473 | .get(format!("accounts/{account_id}/subscriptions"), None, None) 474 | .await 475 | } 476 | 477 | /// Update internal cache for a particular account. 478 | /// 479 | /// # Parameters 480 | /// 481 | /// - `account_id` - account ID 482 | pub async fn reindex_account(&self, account_id: &str) -> Result<(), TonApiError> { 483 | self.base_client 484 | .post_json( 485 | format!("accounts/{account_id}/reindex"), 486 | None, 487 | None::, 488 | None, 489 | ) 490 | .await 491 | } 492 | 493 | /// Search by account domain name. 494 | /// 495 | /// # Parameters 496 | /// 497 | /// - `name` 498 | /// 499 | /// # Returns 500 | /// 501 | /// found accounts 502 | pub async fn search_accounts(&self, name: &str) -> Result { 503 | let params = QueryParams::from_pairs([("name", name)]); 504 | 505 | self.base_client 506 | .get(format!("accounts/search"), Some(params), None) 507 | .await 508 | } 509 | 510 | /// Get expiring account .ton dns. 511 | /// 512 | /// # Parameters 513 | /// 514 | /// - `account_id` - account ID 515 | /// - `period` - number of days before expiration 516 | /// 517 | /// # Returns 518 | /// 519 | /// found accounts 520 | pub async fn get_account_dns_expiring( 521 | &self, 522 | account_id: &str, 523 | period: Option, 524 | ) -> Result { 525 | let mut params = QueryParams::new(); 526 | 527 | if let Some(period) = period { 528 | params.insert("period", period); 529 | } 530 | 531 | self.base_client 532 | .get( 533 | format!("accounts/{account_id}/dns/expiring"), 534 | Some(params), 535 | None, 536 | ) 537 | .await 538 | } 539 | 540 | /// Get public key by account id. 541 | /// 542 | /// # Parameters 543 | /// 544 | /// - `account_id` - account ID 545 | /// 546 | /// # Returns 547 | /// 548 | /// account's public key 549 | pub async fn get_account_public_key(&self, account_id: &str) -> Result { 550 | self.base_client 551 | .get(format!("accounts/{account_id}/publickey"), None, None) 552 | .await 553 | } 554 | 555 | /// Get account's multisigs. 556 | /// 557 | /// # Parameters 558 | /// 559 | /// - `account_id` - account ID 560 | /// 561 | /// # Returns 562 | /// 563 | /// account's multisigs 564 | pub async fn get_account_multisigs(&self, account_id: &str) -> Result { 565 | self.base_client 566 | .get(format!("accounts/{account_id}/multisigs"), None, None) 567 | .await 568 | } 569 | 570 | /// Get account's balance change. 571 | /// 572 | /// # Parameters 573 | /// 574 | /// - `account_id` - account ID 575 | /// - `start_date` 576 | /// - `end_date` 577 | /// 578 | /// # Returns 579 | /// 580 | /// account's balance change 581 | pub async fn get_account_diff( 582 | &self, 583 | account_id: &str, 584 | start_date: i64, 585 | end_date: i64, 586 | ) -> Result { 587 | let params = QueryParams::from_pairs([("start_date", start_date), ("end_date", end_date)]); 588 | 589 | self.base_client 590 | .get(format!("accounts/{account_id}/diff"), Some(params), None) 591 | .await 592 | } 593 | 594 | /// Emulate sending message to blockchain. 595 | /// 596 | /// # Parameters 597 | /// 598 | /// - `accept_language` - *Default value*: en 599 | /// - `account_id` - account ID 600 | /// - `ignore_signature_check` 601 | /// 602 | /// # Returns 603 | /// 604 | /// emulated message to account 605 | pub async fn emulate_message_to_account_event( 606 | &self, 607 | boc: &str, 608 | accept_language: Option<&str>, 609 | account_id: &str, 610 | ignore_signature_check: Option, 611 | ) -> Result { 612 | let mut params = QueryParams::new(); 613 | 614 | if let Some(ignore_signature_check) = ignore_signature_check { 615 | params.insert("ignore_signature_check", ignore_signature_check); 616 | } 617 | 618 | let body = serde_json::json!({ 619 | "boc": boc, 620 | }); 621 | 622 | let mut headers = HeaderMap::new(); 623 | 624 | if let Some(language) = accept_language { 625 | headers.insert(ACCEPT_LANGUAGE, HeaderValue::from_str(language)?); 626 | } 627 | 628 | self.base_client 629 | .post_json( 630 | format!("accounts/{account_id}/events/emulate"), 631 | Some(params), 632 | Some(body), 633 | Some(headers), 634 | ) 635 | .await 636 | } 637 | 638 | /// Get the transfer nft history. 639 | /// 640 | /// # Parameters 641 | /// 642 | /// - `account_id` - account ID 643 | /// - `accept_language` - *Default value*: en 644 | /// - `before_lt` - omit this parameter to get last events 645 | /// - `limit` 646 | /// - `start_date` 647 | /// - `end_date` 648 | /// 649 | /// # Returns 650 | /// 651 | /// emulated message to account 652 | pub async fn get_account_nft_history( 653 | &self, 654 | account_id: &str, 655 | accept_language: Option<&str>, 656 | before_lt: Option, 657 | limit: u64, 658 | start_date: Option, 659 | end_date: Option, 660 | ) -> Result { 661 | let mut params = QueryParams::from_pairs([("limit", limit)]); 662 | 663 | if let Some(before_lt) = before_lt { 664 | params.insert("before_lt", before_lt); 665 | } 666 | 667 | if let Some(start_date) = start_date { 668 | params.insert("start_date", start_date); 669 | } 670 | 671 | if let Some(end_date) = end_date { 672 | params.insert("end_date", end_date); 673 | } 674 | 675 | let mut headers = HeaderMap::new(); 676 | 677 | if let Some(language) = accept_language { 678 | headers.insert(ACCEPT_LANGUAGE, HeaderValue::from_str(language)?); 679 | } 680 | 681 | self.base_client 682 | .get( 683 | format!("accounts/{account_id}/nfts/history"), 684 | Some(params), 685 | Some(headers), 686 | ) 687 | .await 688 | } 689 | 690 | /// Get NFT collections. 691 | /// 692 | /// # Parameters 693 | /// 694 | /// - `limit` - *Default value*: 100 695 | /// - `offset` - *Default value*: 0 696 | /// 697 | /// # Returns 698 | /// 699 | /// nft collections 700 | pub async fn get_nft_collections( 701 | &self, 702 | limit: Option, 703 | offset: Option, 704 | ) -> Result { 705 | let mut params = QueryParams::new(); 706 | 707 | if let Some(limit) = limit { 708 | params.insert("limit", limit); 709 | } 710 | 711 | if let Some(offset) = offset { 712 | params.insert("offset", offset); 713 | } 714 | 715 | self.base_client 716 | .get("nfts/collections".to_string(), Some(params), None) 717 | .await 718 | } 719 | 720 | /// Get NFT collection by collection address. 721 | /// 722 | /// # Parameters 723 | /// 724 | /// - `account_id` - account ID 725 | /// 726 | /// # Returns 727 | /// 728 | /// nft collection 729 | pub async fn get_nft_collection(&self, account_id: &str) -> Result { 730 | self.base_client 731 | .get(format!("nfts/collections/{account_id}"), None, None) 732 | .await 733 | } 734 | 735 | /// Get NFT items from collection by collection address. 736 | /// 737 | /// # Parameters 738 | /// 739 | /// - `account_id` - account ID 740 | /// - `limit` - *Default*: 1000 741 | /// - `offset` - *Default*: 0 742 | /// 743 | /// # Returns 744 | /// 745 | /// nft items 746 | pub async fn get_items_from_collection( 747 | &self, 748 | account_id: &str, 749 | limit: Option, 750 | offset: Option, 751 | ) -> Result { 752 | let mut params = QueryParams::new(); 753 | 754 | if let Some(limit) = limit { 755 | params.insert("limit", limit); 756 | } 757 | 758 | if let Some(offset) = offset { 759 | params.insert("offset", offset); 760 | } 761 | 762 | self.base_client 763 | .get( 764 | format!("nfts/collections/{account_id}/items"), 765 | Some(params), 766 | None, 767 | ) 768 | .await 769 | } 770 | 771 | /// Get NFT items by their addresses. 772 | /// 773 | /// # Parameters 774 | /// 775 | /// - `account_ids` - a list of account ids 776 | /// 777 | /// # Returns 778 | /// 779 | /// nft items 780 | pub async fn get_nft_items_by_addresses( 781 | &self, 782 | account_ids: &[&str], 783 | ) -> Result { 784 | let body = serde_json::json!({ 785 | "account_ids": account_ids 786 | }); 787 | 788 | self.base_client 789 | .post_json("nfts/_bulk".to_string(), None, Some(body), None) 790 | .await 791 | } 792 | 793 | /// Get NFT item by its address. 794 | /// 795 | /// # Parameters 796 | /// 797 | /// - `account_id` - account ID 798 | /// 799 | /// # Returns 800 | /// 801 | /// nft item 802 | pub async fn get_nft_item_by_address(&self, account_id: &str) -> Result { 803 | self.base_client 804 | .get(format!("nfts/{account_id}"), None, None) 805 | .await 806 | } 807 | 808 | /// Get the transfer nfts history for account. 809 | /// 810 | /// # Parameters 811 | /// 812 | /// - `account_id` - account ID 813 | /// - `accept_language` - *Default value*: en 814 | /// - `before_lt` - omit this parameter to get last events 815 | /// - `limit` 816 | /// - `start_date` 817 | /// - `end_date` 818 | /// 819 | /// # Returns 820 | /// 821 | /// nft history 822 | pub async fn get_nft_history_by_id( 823 | &self, 824 | account_id: &str, 825 | accept_language: Option<&str>, 826 | before_lt: Option, 827 | limit: u64, 828 | start_date: Option, 829 | end_date: Option, 830 | ) -> Result { 831 | let mut params = QueryParams::from_pairs([("limit", limit)]); 832 | 833 | if let Some(before_lt) = before_lt { 834 | params.insert("before_lt", before_lt); 835 | } 836 | 837 | if let Some(start_date) = start_date { 838 | params.insert("start_date", start_date); 839 | } 840 | 841 | if let Some(end_date) = end_date { 842 | params.insert("end_date", end_date); 843 | } 844 | 845 | let mut headers = HeaderMap::new(); 846 | 847 | if let Some(language) = accept_language { 848 | headers.insert(ACCEPT_LANGUAGE, HeaderValue::from_str(language)?); 849 | } 850 | 851 | self.base_client 852 | .get( 853 | format!("nfts/{account_id}/history"), 854 | Some(params), 855 | Some(headers), 856 | ) 857 | .await 858 | } 859 | 860 | /// Get a list of all indexed jetton masters in the blockchain. 861 | /// 862 | /// # Parameters 863 | /// 864 | /// - `account_id` - account ID 865 | /// - `limit` - *Default*: 1000 866 | /// - `offset` - *Default*: 0 867 | /// 868 | /// # Returns 869 | /// 870 | /// a list of jettons 871 | pub async fn get_jettons( 872 | &self, 873 | limit: Option, 874 | offset: Option, 875 | ) -> Result { 876 | let mut params = QueryParams::new(); 877 | 878 | if let Some(limit) = limit { 879 | params.insert("limit", limit); 880 | } 881 | 882 | if let Some(offset) = offset { 883 | params.insert("offset", offset); 884 | } 885 | 886 | self.base_client 887 | .get("jettons".to_string(), Some(params), None) 888 | .await 889 | } 890 | 891 | /// Get jetton metadata by jetton master address. 892 | /// 893 | /// # Parameters 894 | /// 895 | /// - `account_id` - account ID 896 | /// 897 | /// # Returns 898 | /// 899 | /// jetton info 900 | pub async fn get_jetton_info(&self, account_id: &str) -> Result { 901 | self.base_client 902 | .get(format!("jettons/{account_id}"), None, None) 903 | .await 904 | } 905 | 906 | /// Get jetton's holders. 907 | /// 908 | /// # Parameters 909 | /// 910 | /// - `account_id` - account ID 911 | /// - `limit` - *Default*: 1000 912 | /// - `offset` - *Default*: 0 913 | /// 914 | /// # Returns 915 | /// 916 | /// jetton's holders 917 | pub async fn get_jetton_holders( 918 | &self, 919 | account_id: &str, 920 | limit: Option, 921 | offset: Option, 922 | ) -> Result { 923 | let mut params = QueryParams::new(); 924 | 925 | if let Some(limit) = limit { 926 | params.insert("limit", limit); 927 | } 928 | 929 | if let Some(offset) = offset { 930 | params.insert("offset", offset); 931 | } 932 | 933 | self.base_client 934 | .get(format!("jettons/{account_id}/holders"), Some(params), None) 935 | .await 936 | } 937 | 938 | /// Get jetton's custom payload and state init required for transfer. 939 | /// 940 | /// # Parameters 941 | /// 942 | /// - `account_id` - account ID 943 | /// - `jetton_id` - jetton ID 944 | /// 945 | /// # Returns 946 | /// 947 | /// jetton's custom payload 948 | pub async fn get_jetton_transfer_payload( 949 | &self, 950 | account_id: &str, 951 | jetton_id: &str, 952 | ) -> Result { 953 | self.base_client 954 | .get( 955 | format!("jettons/{jetton_id}/transfer/{account_id}/payload"), 956 | None, 957 | None, 958 | ) 959 | .await 960 | } 961 | 962 | /// Get only jetton transfers in the event. 963 | /// 964 | /// # Parameters 965 | /// 966 | /// - `event_id` - event ID or transaction hash in hex (without 0x) or base64url format 967 | /// - `accept_language` - *Default value*: en 968 | /// 969 | /// # Returns 970 | /// 971 | /// events 972 | pub async fn get_jettons_events( 973 | &self, 974 | event_id: &str, 975 | accept_language: Option<&str>, 976 | ) -> Result { 977 | let mut headers = HeaderMap::new(); 978 | 979 | if let Some(language) = accept_language { 980 | headers.insert(ACCEPT_LANGUAGE, HeaderValue::from_str(language)?); 981 | } 982 | 983 | self.base_client 984 | .get(format!("events/{event_id}/jettons"), None, Some(headers)) 985 | .await 986 | } 987 | 988 | /// Get full information about domain name. 989 | /// 990 | /// # Parameters 991 | /// 992 | /// - `domain_name` - domain name with .ton or .t.me 993 | /// 994 | /// # Returns 995 | /// 996 | /// domain info 997 | pub async fn get_dns_info(&self, domain_name: &str) -> Result { 998 | self.base_client 999 | .get(format!("dns/{domain_name}"), None, None) 1000 | .await 1001 | } 1002 | 1003 | /// DNS resolve for domain name. 1004 | /// 1005 | /// # Parameters 1006 | /// 1007 | /// - `domain_name` - domain name with .ton or .t.me 1008 | /// 1009 | /// # Returns 1010 | /// 1011 | /// dns record 1012 | pub async fn dns_resolve(&self, domain_name: &str) -> Result { 1013 | self.base_client 1014 | .get(format!("dns/{domain_name}/resolve"), None, None) 1015 | .await 1016 | } 1017 | 1018 | /// Get domain bids. 1019 | /// 1020 | /// # Parameters 1021 | /// 1022 | /// - `domain_name` - domain name with .ton or .t.me 1023 | /// 1024 | /// # Returns 1025 | /// 1026 | /// domain bids 1027 | pub async fn get_domain_bids(&self, domain_name: &str) -> Result { 1028 | self.base_client 1029 | .get(format!("dns/{domain_name}/bids"), None, None) 1030 | .await 1031 | } 1032 | 1033 | /// Get all auctions. 1034 | /// 1035 | /// # Parameters 1036 | /// 1037 | /// - `tld` - domain filter for current auctions "ton" or "t.me" 1038 | /// 1039 | /// # Returns 1040 | /// 1041 | /// auctions 1042 | pub async fn get_all_auctions(&self, tld: &str) -> Result { 1043 | let params = QueryParams::from_pairs([("tld", tld)]); 1044 | 1045 | self.base_client 1046 | .get("dns/auctions".to_string(), Some(params), None) 1047 | .await 1048 | } 1049 | 1050 | /// Get backup info. 1051 | /// 1052 | /// # Parameters 1053 | /// 1054 | /// - `x_ton_connect_auth` 1055 | /// 1056 | /// # Returns 1057 | /// 1058 | /// get wallet dump 1059 | pub async fn get_wallet_backup(&self, x_ton_connect_auth: &str) -> Result { 1060 | let mut headers = HeaderMap::new(); 1061 | 1062 | headers.insert( 1063 | "X-TonConnect-Auth", 1064 | HeaderValue::from_str(x_ton_connect_auth)?, 1065 | ); 1066 | 1067 | self.base_client 1068 | .get("wallet/backup".to_string(), None, Some(headers)) 1069 | .await 1070 | } 1071 | 1072 | /// Set backup info. 1073 | /// 1074 | /// # Parameters 1075 | /// 1076 | /// - `backup` 1077 | /// - `x_ton_connect_auth` 1078 | pub async fn set_wallet_backup( 1079 | &self, 1080 | backup: Vec, 1081 | x_ton_connect_auth: &str, 1082 | ) -> Result<(), TonApiError> { 1083 | let mut headers = HeaderMap::new(); 1084 | 1085 | headers.insert( 1086 | "X-TonConnect-Auth", 1087 | HeaderValue::from_str(x_ton_connect_auth)?, 1088 | ); 1089 | 1090 | self.base_client 1091 | .put_bytes( 1092 | "wallet/backup".to_string(), 1093 | None, 1094 | Some(backup), 1095 | Some(headers), 1096 | ) 1097 | .await 1098 | } 1099 | 1100 | /// Account verification and token issuance. 1101 | /// 1102 | /// # Parameters 1103 | /// 1104 | /// - `ton_connect` - Data that is expected from TON Connect 1105 | /// 1106 | /// # Returns 1107 | /// 1108 | /// auth token 1109 | pub async fn ton_connect_proof( 1110 | &self, 1111 | ton_connect: serde_json::Value, 1112 | ) -> Result { 1113 | self.base_client 1114 | .post_json( 1115 | "wallet/auth/proof".to_string(), 1116 | None, 1117 | Some(ton_connect), 1118 | None, 1119 | ) 1120 | .await 1121 | } 1122 | 1123 | /// Get account seqno. 1124 | /// 1125 | /// # Parameters 1126 | /// 1127 | /// - `account_id` - account ID 1128 | /// 1129 | /// # Returns 1130 | /// 1131 | /// account seqno 1132 | pub async fn get_account_seqno(&self, account_id: &str) -> Result { 1133 | self.base_client 1134 | .get(format!("wallet/{account_id}/seqno"), None, None) 1135 | .await 1136 | } 1137 | 1138 | /// Get wallets by public key. 1139 | /// 1140 | /// # Parameters 1141 | /// 1142 | /// - `public_key` 1143 | /// 1144 | /// # Returns 1145 | /// 1146 | /// a list of wallets 1147 | pub async fn get_wallets_by_public_key( 1148 | &self, 1149 | public_key: &str, 1150 | ) -> Result { 1151 | self.base_client 1152 | .get(format!("pubkeys/{public_key}/wallets"), None, None) 1153 | .await 1154 | } 1155 | 1156 | /// Emulate sending message to blockchain. 1157 | /// 1158 | /// # Parameters 1159 | /// 1160 | /// - `input` - bag-of-cells serialized to base64/hex and additional parameters to configure emulation 1161 | /// - `accept_language` - *Default value*: en 1162 | /// 1163 | /// # Returns 1164 | /// 1165 | /// a list of wallets 1166 | pub async fn emulate_message_to_wallet( 1167 | &self, 1168 | input: serde_json::Value, 1169 | accept_language: Option<&str>, 1170 | ) -> Result { 1171 | let mut headers = HeaderMap::new(); 1172 | 1173 | if let Some(language) = accept_language { 1174 | headers.insert(ACCEPT_LANGUAGE, HeaderValue::from_str(language)?); 1175 | } 1176 | 1177 | self.base_client 1178 | .post_json( 1179 | "wallet/emulate".to_string(), 1180 | None, 1181 | Some(input), 1182 | Some(headers), 1183 | ) 1184 | .await 1185 | } 1186 | 1187 | /// Get the token price in the chosen currency for display only. Don’t use this for financial transactions. 1188 | /// 1189 | /// # Parameters 1190 | /// 1191 | /// - `tokens` - accept ton and jetton master addresses 1192 | /// - `currencies` - accept ton and all possible fiat currencies 1193 | /// 1194 | /// # Returns 1195 | /// 1196 | /// tokens rates 1197 | pub async fn get_rates( 1198 | &self, 1199 | tokens: &[&str], 1200 | currencies: &[&str], 1201 | ) -> Result { 1202 | let params = QueryParams::from_pairs([("tokens", tokens), ("currencies", currencies)]); 1203 | 1204 | self.base_client 1205 | .get("rates".to_string(), Some(params), None) 1206 | .await 1207 | } 1208 | 1209 | /// Get chart by token. 1210 | /// 1211 | /// # Parameters 1212 | /// 1213 | /// - `token` - accept jetton master address 1214 | /// - `currency` 1215 | /// - `start_date` 1216 | /// - `end_date` 1217 | /// - `points_count` 1218 | /// 1219 | /// # Returns 1220 | /// 1221 | /// token chart 1222 | pub async fn get_chart_rates( 1223 | &self, 1224 | token: &str, 1225 | currency: Option<&str>, 1226 | start_date: Option, 1227 | end_date: Option, 1228 | points_count: Option, 1229 | ) -> Result { 1230 | let mut params = QueryParams::from_pairs([("token", token)]); 1231 | 1232 | if let Some(currency) = currency { 1233 | params.insert("currency", currency); 1234 | } 1235 | 1236 | if let Some(start_date) = start_date { 1237 | params.insert("start_date", start_date); 1238 | } 1239 | 1240 | if let Some(end_date) = end_date { 1241 | params.insert("end_date", end_date); 1242 | } 1243 | 1244 | if let Some(points_count) = points_count { 1245 | params.insert("points_count", points_count); 1246 | } 1247 | 1248 | self.base_client 1249 | .get("rates/chart".to_string(), Some(params), None) 1250 | .await 1251 | } 1252 | 1253 | /// Get the TON price from markets. 1254 | /// 1255 | /// # Returns 1256 | /// 1257 | /// markets rates 1258 | pub async fn get_markets_rates(&self) -> Result { 1259 | self.base_client 1260 | .get("rates/markets".to_string(), None, None) 1261 | .await 1262 | } 1263 | 1264 | /// All pools where account participates. 1265 | /// 1266 | /// # Parameters 1267 | /// 1268 | /// - `account_id` - account ID 1269 | /// 1270 | /// # Returns 1271 | /// 1272 | /// account's pools 1273 | pub async fn get_account_nominators_pools( 1274 | &self, 1275 | account_id: &str, 1276 | ) -> Result { 1277 | self.base_client 1278 | .get(format!("staking/nominator/{account_id}/pools"), None, None) 1279 | .await 1280 | } 1281 | 1282 | /// Staking pool info. 1283 | /// 1284 | /// # Parameters 1285 | /// 1286 | /// - `account_id` - account ID 1287 | /// - `accept_language` - *Default value*: en 1288 | /// 1289 | /// # Returns 1290 | /// 1291 | /// staking pool info 1292 | pub async fn get_staking_pool_info( 1293 | &self, 1294 | account_id: &str, 1295 | accept_language: Option<&str>, 1296 | ) -> Result { 1297 | let mut headers = HeaderMap::new(); 1298 | 1299 | if let Some(language) = accept_language { 1300 | headers.insert(ACCEPT_LANGUAGE, HeaderValue::from_str(language)?); 1301 | } 1302 | 1303 | self.base_client 1304 | .get(format!("staking/pool/{account_id}"), None, Some(headers)) 1305 | .await 1306 | } 1307 | 1308 | /// Pool history. 1309 | /// 1310 | /// # Parameters 1311 | /// 1312 | /// - `account_id` - account ID 1313 | /// 1314 | /// # Returns 1315 | /// 1316 | /// pool history 1317 | pub async fn get_staking_pool_history( 1318 | &self, 1319 | account_id: &str, 1320 | ) -> Result { 1321 | self.base_client 1322 | .get(format!("staking/pool/{account_id}/history"), None, None) 1323 | .await 1324 | } 1325 | 1326 | /// All pools available in the network. 1327 | /// 1328 | /// # Parameters 1329 | /// 1330 | /// - `available_for` - account ID 1331 | /// - `include_unverified` - return also pools not from white list - just compatible by interfaces (maybe dangerous!) 1332 | /// - `accept_language` - *Default value*: en 1333 | /// 1334 | /// # Returns 1335 | /// 1336 | /// a list of pools 1337 | pub async fn get_staking_pools( 1338 | &self, 1339 | available_for: Option<&str>, 1340 | include_unverified: Option, 1341 | accept_language: Option<&str>, 1342 | ) -> Result { 1343 | let mut params = QueryParams::new(); 1344 | 1345 | if let Some(account_id) = available_for { 1346 | params.insert("available_for", account_id); 1347 | } 1348 | 1349 | if let Some(include) = include_unverified { 1350 | params.insert("include_unverified", include); 1351 | } 1352 | 1353 | let mut headers = HeaderMap::new(); 1354 | 1355 | if let Some(language) = accept_language { 1356 | headers.insert(ACCEPT_LANGUAGE, HeaderValue::from_str(language)?); 1357 | } 1358 | 1359 | self.base_client 1360 | .get("staking/pools".to_string(), Some(params), Some(headers)) 1361 | .await 1362 | } 1363 | 1364 | /// Get the trace by trace ID or hash of any transaction in the trace. 1365 | /// 1366 | /// # Parameters 1367 | /// 1368 | /// - `trace_id` - trace ID or transaction hash in hex (without 0x) or base64url format 1369 | /// 1370 | /// # Returns 1371 | /// 1372 | /// trace 1373 | pub async fn get_trace(&self, trace_id: &str) -> Result { 1374 | self.base_client 1375 | .get(format!("traces/{}", trace_id), None, None) 1376 | .await 1377 | } 1378 | 1379 | /// Emulate sending message to blockchain. 1380 | /// 1381 | /// # Parameters 1382 | /// 1383 | /// - `boc` - bag-of-cells serialized to hex 1384 | /// - `ignore_signature_check` 1385 | /// 1386 | /// # Returns 1387 | /// 1388 | /// emulated trace 1389 | pub async fn emulate_message_to_trace( 1390 | &self, 1391 | boc: &str, 1392 | ignore_signature_check: Option, 1393 | ) -> Result { 1394 | let mut params = QueryParams::new(); 1395 | 1396 | if let Some(ignore_check) = ignore_signature_check { 1397 | params.insert("ignore_signature_check", ignore_check); 1398 | } 1399 | 1400 | let body = serde_json::json!({ 1401 | "boc": boc 1402 | }); 1403 | 1404 | self.base_client 1405 | .post_json("traces/emulate".to_string(), Some(params), Some(body), None) 1406 | .await 1407 | } 1408 | 1409 | /// Get an event by event ID or a hash of any transaction in a trace. 1410 | /// 1411 | /// An event is built on top of a trace, which is a series of transactions caused by one inbound message. 1412 | /// The event represents meaningful high-level operations like a Jetton Transfer or an NFT Purchase. 1413 | /// 1414 | /// # Parameters 1415 | /// 1416 | /// - `event_id` - event ID or transaction hash in hex (without 0x) or base64url format 1417 | /// - `accept_language` - *Default value*: en 1418 | /// 1419 | /// # Returns 1420 | /// 1421 | /// event 1422 | pub async fn get_event( 1423 | &self, 1424 | event_id: &str, 1425 | accept_language: Option<&str>, 1426 | ) -> Result { 1427 | let mut headers = HeaderMap::new(); 1428 | 1429 | if let Some(language) = accept_language { 1430 | headers.insert(ACCEPT_LANGUAGE, HeaderValue::from_str(language)?); 1431 | } 1432 | 1433 | self.base_client 1434 | .get(format!("events/{}", event_id), None, Some(headers)) 1435 | .await 1436 | } 1437 | 1438 | /// Emulate sending message to blockchain. 1439 | /// 1440 | /// # Parameters 1441 | /// 1442 | /// - `boc` - bag-of-cells serialized to hex 1443 | /// - `accept_language` - *Default value*: en 1444 | /// - `ignore_signature_check` 1445 | /// 1446 | /// # Returns 1447 | /// 1448 | /// emulated event 1449 | pub async fn emulate_message_to_event( 1450 | &self, 1451 | boc: &str, 1452 | ignore_signature_check: Option, 1453 | accept_language: Option<&str>, 1454 | ) -> Result { 1455 | let mut params = QueryParams::new(); 1456 | 1457 | if let Some(ignore_check) = ignore_signature_check { 1458 | params.insert("ignore_signature_check", ignore_check); 1459 | } 1460 | 1461 | let body = serde_json::json!({ 1462 | "boc": boc 1463 | }); 1464 | 1465 | let mut headers = HeaderMap::new(); 1466 | 1467 | if let Some(language) = accept_language { 1468 | headers.insert(ACCEPT_LANGUAGE, HeaderValue::from_str(language)?); 1469 | } 1470 | 1471 | self.base_client 1472 | .post_json( 1473 | "events/emulate".to_string(), 1474 | Some(params), 1475 | Some(body), 1476 | Some(headers), 1477 | ) 1478 | .await 1479 | } 1480 | 1481 | /// Get TON storage providers deployed to the blockchain. 1482 | /// 1483 | /// # Returns 1484 | /// 1485 | /// A list of storage providers 1486 | pub async fn get_storage_providers(&self) -> Result { 1487 | self.base_client 1488 | .get("storage/providers".to_string(), None, None) 1489 | .await 1490 | } 1491 | 1492 | /// Get a payload for further token receipt. 1493 | /// 1494 | /// # Returns 1495 | /// 1496 | /// payload 1497 | pub async fn get_ton_connect_payload(&self) -> Result { 1498 | self.base_client 1499 | .get("tonconnect/payload".to_string(), None, None) 1500 | .await 1501 | } 1502 | 1503 | /// Get account info by state init. 1504 | /// 1505 | /// # Parameters 1506 | /// 1507 | /// - `state_init` - Data that is expected, base64 1508 | /// 1509 | /// # Returns 1510 | /// 1511 | /// account info 1512 | pub async fn get_account_info_by_state_init( 1513 | &self, 1514 | state_init: &str, 1515 | ) -> Result { 1516 | let body = serde_json::json!({ 1517 | "state_init": state_init 1518 | }); 1519 | 1520 | self.base_client 1521 | .post_json("tonconnect/stateinit".to_string(), None, Some(body), None) 1522 | .await 1523 | } 1524 | 1525 | /// Returns configuration of gasless transfers. 1526 | /// 1527 | /// # Returns 1528 | /// 1529 | /// gasless config 1530 | pub async fn get_gasless_config(&self) -> Result { 1531 | self.base_client 1532 | .get("gasless/config".to_string(), None, None) 1533 | .await 1534 | } 1535 | 1536 | /// Estimates the cost of the given messages and returns a payload to sign. 1537 | /// 1538 | /// # Parameters 1539 | /// 1540 | /// - `master_id` - The jetton address to pay commission 1541 | /// - `wallet_address` 1542 | /// - `wallet_public_key` 1543 | /// - `messages` 1544 | /// 1545 | /// # Returns 1546 | /// 1547 | /// A `SignRawParams` object containing the payload to sign 1548 | pub async fn gasless_estimate( 1549 | &self, 1550 | master_id: &str, 1551 | wallet_address: &str, 1552 | wallet_public_key: &str, 1553 | messages: &[&str], 1554 | ) -> Result { 1555 | let body = serde_json::json!({ 1556 | "wallet_address": wallet_address, 1557 | "wallet_public_key": wallet_public_key, 1558 | "messages": messages 1559 | }); 1560 | 1561 | self.base_client 1562 | .post_json( 1563 | format!("gasless/estimate/{master_id}"), 1564 | None, 1565 | Some(body), 1566 | None, 1567 | ) 1568 | .await 1569 | } 1570 | 1571 | /// Submits the signed gasless transaction message to the network. 1572 | /// 1573 | /// # Parameters 1574 | /// 1575 | /// - `wallet_public_key` 1576 | /// - `boc` 1577 | /// 1578 | /// # Returns 1579 | /// 1580 | /// the message has been sent 1581 | pub async fn gasless_send( 1582 | &self, 1583 | wallet_public_key: &str, 1584 | boc: &str, 1585 | ) -> Result<(), TonApiError> { 1586 | let body = serde_json::json!({ 1587 | "wallet_public_key": wallet_public_key, 1588 | "boc": boc 1589 | }); 1590 | 1591 | self.base_client 1592 | .post_json("gasless/send".to_string(), None, Some(body), None) 1593 | .await 1594 | } 1595 | 1596 | /// Get multisig account info. 1597 | /// 1598 | /// # Parameters 1599 | /// 1600 | /// - `account_id` - account ID 1601 | /// 1602 | /// # Returns 1603 | /// 1604 | /// multisig account 1605 | pub async fn get_multisig_account(&self, account_id: &str) -> Result { 1606 | self.base_client 1607 | .get(format!("multisig/{account_id}"), None, None) 1608 | .await 1609 | } 1610 | 1611 | /// Get reduced blockchain blocks data. 1612 | /// 1613 | /// # Parameters 1614 | /// 1615 | /// - `from` 1616 | /// - `to` 1617 | /// 1618 | /// # Returns 1619 | /// 1620 | /// blockchain reduced blocks 1621 | pub async fn get_reduced_blockchain_blocks( 1622 | &self, 1623 | from: i64, 1624 | to: i64, 1625 | ) -> Result { 1626 | let params = QueryParams::from_pairs([("from", from), ("to", to)]); 1627 | 1628 | self.base_client 1629 | .get("blockchain/reduced/blocks".to_string(), Some(params), None) 1630 | .await 1631 | } 1632 | 1633 | /// Get blockchain block data. 1634 | /// 1635 | /// # Parameters 1636 | /// 1637 | /// - `block_id` - block ID 1638 | /// 1639 | /// # Returns 1640 | /// 1641 | /// blockchain block 1642 | pub async fn get_blockchain_block( 1643 | &self, 1644 | block_id: &str, 1645 | ) -> Result { 1646 | self.base_client 1647 | .get(format!("blockchain/blocks/{block_id}"), None, None) 1648 | .await 1649 | } 1650 | 1651 | /// Get blockchain block shards. 1652 | /// 1653 | /// # Parameters 1654 | /// 1655 | /// - `masterchain_seqno` - masterchain block seqno 1656 | /// 1657 | /// # Returns 1658 | /// 1659 | /// blockchain block shards 1660 | pub async fn get_blockchain_masterchain_shards( 1661 | &self, 1662 | masterchain_seqno: i32, 1663 | ) -> Result { 1664 | self.base_client 1665 | .get( 1666 | format!("blockchain/masterchain/{masterchain_seqno}/shards"), 1667 | None, 1668 | None, 1669 | ) 1670 | .await 1671 | } 1672 | 1673 | /// Get all blocks in all shards and workchains between target and previous masterchain block according to shards last blocks snapshot in masterchain. We don't recommend to build your app around this method because it has problem with scalability and will work very slow in the future. 1674 | /// 1675 | /// # Parameters 1676 | /// 1677 | /// - `masterchain_seqno` - masterchain block seqno 1678 | /// 1679 | /// # Returns 1680 | /// 1681 | /// blockchain blocks 1682 | pub async fn get_blockchain_masterchain_blocks( 1683 | &self, 1684 | masterchain_seqno: i32, 1685 | ) -> Result { 1686 | self.base_client 1687 | .get( 1688 | format!("blockchain/masterchain/{masterchain_seqno}/blocks"), 1689 | None, 1690 | None, 1691 | ) 1692 | .await 1693 | } 1694 | 1695 | /// Get all transactions in all shards and workchains between target and previous masterchain block according to shards last blocks snapshot in masterchain. We don't recommend to build your app around this method because it has problem with scalability and will work very slow in the future. 1696 | /// 1697 | /// # Parameters 1698 | /// 1699 | /// - `masterchain_seqno` - masterchain block seqno 1700 | /// 1701 | /// # Returns 1702 | /// 1703 | /// blockchain transactions 1704 | pub async fn get_blockchain_masterchain_transactions( 1705 | &self, 1706 | masterchain_seqno: i32, 1707 | ) -> Result { 1708 | self.base_client 1709 | .get( 1710 | format!("blockchain/masterchain/{masterchain_seqno}/transactions"), 1711 | None, 1712 | None, 1713 | ) 1714 | .await 1715 | } 1716 | 1717 | /// Get blockchain config from a specific block, if present. 1718 | /// 1719 | /// # Parameters 1720 | /// 1721 | /// - `masterchain_seqno` - masterchain block seqno 1722 | /// 1723 | /// # Returns 1724 | /// 1725 | /// blockchain config 1726 | pub async fn get_blockchain_config_from_block( 1727 | &self, 1728 | masterchain_seqno: i32, 1729 | ) -> Result { 1730 | self.base_client 1731 | .get( 1732 | format!("blockchain/masterchain/{masterchain_seqno}/config"), 1733 | None, 1734 | None, 1735 | ) 1736 | .await 1737 | } 1738 | 1739 | /// Get raw blockchain config from a specific block, if present. 1740 | /// 1741 | /// # Parameters 1742 | /// 1743 | /// - `masterchain_seqno` - masterchain block seqno 1744 | /// 1745 | /// # Returns 1746 | /// 1747 | /// blockchain config 1748 | pub async fn get_raw_blockchain_config_from_block( 1749 | &self, 1750 | masterchain_seqno: i32, 1751 | ) -> Result { 1752 | self.base_client 1753 | .get( 1754 | format!("blockchain/masterchain/{masterchain_seqno}/config/raw"), 1755 | None, 1756 | None, 1757 | ) 1758 | .await 1759 | } 1760 | 1761 | /// Get transactions from block. 1762 | /// 1763 | /// # Parameters 1764 | /// 1765 | /// - `block_id` - block ID 1766 | /// 1767 | /// # Returns 1768 | /// 1769 | /// blockchain block transactions 1770 | pub async fn get_blockchain_block_transactions( 1771 | &self, 1772 | block_id: &str, 1773 | ) -> Result { 1774 | self.base_client 1775 | .get( 1776 | format!("blockchain/blocks/{block_id}/transactions"), 1777 | None, 1778 | None, 1779 | ) 1780 | .await 1781 | } 1782 | 1783 | /// Get transaction data. 1784 | /// 1785 | /// # Parameters 1786 | /// 1787 | /// - `transaction_id` - transaction ID 1788 | /// 1789 | /// # Returns 1790 | /// 1791 | /// blockchain transaction 1792 | pub async fn get_blockchain_transaction( 1793 | &self, 1794 | transaction_id: &str, 1795 | ) -> Result { 1796 | self.base_client 1797 | .get( 1798 | format!("blockchain/transactions/{transaction_id}"), 1799 | None, 1800 | None, 1801 | ) 1802 | .await 1803 | } 1804 | 1805 | /// Get transaction data by message hash. 1806 | /// 1807 | /// # Parameters 1808 | /// 1809 | /// - `msg_id` - message ID 1810 | /// 1811 | /// # Returns 1812 | /// 1813 | /// transaction by message hash 1814 | pub async fn get_blockchain_transaction_by_message_hash( 1815 | &self, 1816 | msg_id: &str, 1817 | ) -> Result { 1818 | self.base_client 1819 | .get( 1820 | format!("blockchain/messages/{msg_id}/transaction"), 1821 | None, 1822 | None, 1823 | ) 1824 | .await 1825 | } 1826 | 1827 | /// Get blockchain validators. 1828 | /// 1829 | /// # Returns 1830 | /// 1831 | /// blockchain validators 1832 | pub async fn get_blockchain_validators(&self) -> Result { 1833 | self.base_client 1834 | .get("blockchain/validators".to_string(), None, None) 1835 | .await 1836 | } 1837 | 1838 | /// Get the last known masterchain block. 1839 | /// 1840 | /// # Returns 1841 | /// 1842 | /// blockchain masterchain head 1843 | pub async fn get_blockchain_masterchain_head(&self) -> Result { 1844 | self.base_client 1845 | .get("blockchain/masterchain-head".to_string(), None, None) 1846 | .await 1847 | } 1848 | 1849 | /// Get low-level information about an account taken directly from the blockchain. 1850 | /// 1851 | /// # Parameters 1852 | /// 1853 | /// - `account_id` - account ID 1854 | /// 1855 | /// # Returns 1856 | /// 1857 | /// raw account 1858 | pub async fn get_blockchain_raw_account( 1859 | &self, 1860 | account_id: &str, 1861 | ) -> Result { 1862 | self.base_client 1863 | .get(format!("blockchain/accounts/{account_id}"), None, None) 1864 | .await 1865 | } 1866 | 1867 | /// Get account transactions. 1868 | /// 1869 | /// # Parameters 1870 | /// 1871 | /// - `account_id` - account ID 1872 | /// - `after_lt` - omit this parameter to get last transactions 1873 | /// - `before_lt` - omit this parameter to get last transactions 1874 | /// - `limit` - *Default value*: 100 1875 | /// - `sort_order` - *Available values*: desc, asc *Default value*: desc 1876 | /// 1877 | /// # Returns 1878 | /// 1879 | /// blockchain account transactions 1880 | pub async fn get_blockchain_account_transactions( 1881 | &self, 1882 | account_id: &str, 1883 | after_lt: Option, 1884 | before_lt: Option, 1885 | limit: Option, 1886 | sort_order: Option<&str>, 1887 | ) -> Result { 1888 | let mut params = QueryParams::new(); 1889 | 1890 | if let Some(after_lt) = after_lt { 1891 | params.insert("after_lt", after_lt); 1892 | } 1893 | 1894 | if let Some(before_lt) = before_lt { 1895 | params.insert("before_lt", before_lt); 1896 | } 1897 | 1898 | if let Some(limit) = limit { 1899 | params.insert("limit", limit); 1900 | } 1901 | 1902 | if let Some(sort_order) = sort_order { 1903 | params.insert("sort_order", sort_order); 1904 | } 1905 | 1906 | self.base_client 1907 | .get( 1908 | format!("blockchain/accounts/{account_id}/transactions"), 1909 | Some(params), 1910 | None, 1911 | ) 1912 | .await 1913 | } 1914 | 1915 | /// Execute get method for account. 1916 | /// 1917 | /// # Parameters 1918 | /// 1919 | /// - `account_id` - account ID 1920 | /// - `method_name` - contract get method name 1921 | /// - `args` 1922 | /// 1923 | /// # Returns 1924 | /// 1925 | /// method execution result 1926 | pub async fn exec_get_method_for_blockchain_account( 1927 | &self, 1928 | account_id: &str, 1929 | method_name: &str, 1930 | args: Option<&[&str]>, 1931 | ) -> Result { 1932 | let mut params = QueryParams::new(); 1933 | 1934 | if let Some(args) = args { 1935 | params.insert("args", args); 1936 | } 1937 | 1938 | self.base_client 1939 | .get( 1940 | format!("blockchain/accounts/{account_id}/methods/{method_name}"), 1941 | Some(params), 1942 | None, 1943 | ) 1944 | .await 1945 | } 1946 | 1947 | /// Send a message to blockchain. 1948 | /// 1949 | /// # Parameters 1950 | /// 1951 | /// - `boc` - both a single boc and a batch of boc serialized in base64/hex are accepted 1952 | /// - `batch` - both a single boc and a batch of boc serialized in base64/hex are accepted 1953 | pub async fn send_blockchain_message( 1954 | &self, 1955 | boc: &str, 1956 | batch: &[&str], 1957 | ) -> Result<(), TonApiError> { 1958 | let body = serde_json::json!({ 1959 | "boc": boc, 1960 | "batch": batch 1961 | }); 1962 | 1963 | self.base_client 1964 | .post_json("blockchain/message".to_string(), None, Some(body), None) 1965 | .await 1966 | } 1967 | 1968 | /// Get the blockchain configuration. 1969 | /// 1970 | /// # Returns 1971 | /// 1972 | /// blockchain config 1973 | pub async fn get_blockchain_config(&self) -> Result { 1974 | self.base_client 1975 | .get("blockchain/config".to_string(), None, None) 1976 | .await 1977 | } 1978 | 1979 | /// Get the raw blockchain configuration. 1980 | /// 1981 | /// # Returns 1982 | /// 1983 | /// blockchain config 1984 | pub async fn get_raw_blockchain_config(&self) -> Result { 1985 | self.base_client 1986 | .get("blockchain/config/raw".to_string(), None, None) 1987 | .await 1988 | } 1989 | 1990 | /// Blockchain account inspect. 1991 | /// 1992 | /// # Parameters 1993 | /// 1994 | /// - `account_id` - account ID 1995 | /// 1996 | /// # Returns 1997 | /// 1998 | /// blockchain account inspect 1999 | pub async fn blockchain_account_inspect( 2000 | &self, 2001 | account_id: &str, 2002 | ) -> Result { 2003 | self.base_client 2004 | .get( 2005 | format!("blockchain/accounts/{account_id}/inspect"), 2006 | None, 2007 | None, 2008 | ) 2009 | .await 2010 | } 2011 | 2012 | /// Get raw masterchain info. 2013 | /// 2014 | /// # Returns 2015 | /// 2016 | /// raw masterchain info 2017 | pub async fn get_raw_masterchain_info(&self) -> Result { 2018 | self.base_client 2019 | .get("liteserver/get_masterchain_info".to_string(), None, None) 2020 | .await 2021 | } 2022 | 2023 | /// Get raw masterchain info ext. 2024 | /// 2025 | /// # Parameters 2026 | /// 2027 | /// - `mode` - mode 2028 | /// 2029 | /// # Returns 2030 | /// 2031 | /// raw masterchain info ext 2032 | pub async fn get_raw_masterchain_info_ext( 2033 | &self, 2034 | mode: i32, 2035 | ) -> Result { 2036 | let params = QueryParams::from_pairs([("mode", mode)]); 2037 | 2038 | self.base_client 2039 | .get( 2040 | "liteserver/get_masterchain_info_ext".to_string(), 2041 | Some(params), 2042 | None, 2043 | ) 2044 | .await 2045 | } 2046 | 2047 | /// Get raw time. 2048 | /// 2049 | /// # Returns 2050 | /// 2051 | /// raw time 2052 | pub async fn get_raw_time(&self) -> Result { 2053 | self.base_client 2054 | .get("liteserver/get_time".to_string(), None, None) 2055 | .await 2056 | } 2057 | 2058 | /// Get raw blockchain block. 2059 | /// 2060 | /// # Parameters 2061 | /// 2062 | /// - `block_id` - block ID: (workchain,shard,seqno,root_hash,file_hash) 2063 | /// 2064 | /// # Returns 2065 | /// 2066 | /// raw blockchain block 2067 | pub async fn get_raw_blockchain_block( 2068 | &self, 2069 | block_id: &str, 2070 | ) -> Result { 2071 | self.base_client 2072 | .get(format!("liteserver/get_block/{block_id}"), None, None) 2073 | .await 2074 | } 2075 | 2076 | /// Get raw blockchain block state. 2077 | /// 2078 | /// # Parameters 2079 | /// 2080 | /// - `block_id` - block ID: (workchain,shard,seqno,root_hash,file_hash) 2081 | /// 2082 | /// # Returns 2083 | /// 2084 | /// raw blockchain block state 2085 | pub async fn get_raw_blockchain_block_state( 2086 | &self, 2087 | block_id: &str, 2088 | ) -> Result { 2089 | self.base_client 2090 | .get(format!("liteserver/get_state/{block_id}"), None, None) 2091 | .await 2092 | } 2093 | 2094 | /// Get raw blockchain block header. 2095 | /// 2096 | /// # Parameters 2097 | /// 2098 | /// - `block_id` - block ID: (workchain,shard,seqno,root_hash,file_hash) 2099 | /// - `mode` - mode 2100 | /// 2101 | /// # Returns 2102 | /// 2103 | /// raw blockchain block header 2104 | pub async fn get_raw_blockchain_block_header( 2105 | &self, 2106 | block_id: &str, 2107 | mode: i32, 2108 | ) -> Result { 2109 | let params = QueryParams::from_pairs([("mode", mode)]); 2110 | 2111 | self.base_client 2112 | .get( 2113 | format!("liteserver/get_block_header/{block_id}"), 2114 | Some(params), 2115 | None, 2116 | ) 2117 | .await 2118 | } 2119 | 2120 | /// Send raw message to blockchain. 2121 | /// 2122 | /// # Parameters 2123 | /// 2124 | /// - `body` - Data that is expected 2125 | /// 2126 | /// # Returns 2127 | /// 2128 | /// code 2129 | pub async fn send_raw_message(&self, body: &str) -> Result { 2130 | let body = serde_json::json!({ 2131 | "body": body, 2132 | }); 2133 | 2134 | self.base_client 2135 | .post_json( 2136 | "liteserver/send_message".to_string(), 2137 | None, 2138 | Some(body), 2139 | None, 2140 | ) 2141 | .await 2142 | } 2143 | 2144 | /// Get raw account state. 2145 | /// 2146 | /// # Parameters 2147 | /// 2148 | /// - `account_id` - account ID 2149 | /// - `target_block_id` - target block: (workchain,shard,seqno,root_hash,file_hash) 2150 | /// 2151 | /// # Returns 2152 | /// 2153 | /// raw account state 2154 | pub async fn get_raw_account_state( 2155 | &self, 2156 | account_id: &str, 2157 | target_block_id: Option<&str>, 2158 | ) -> Result { 2159 | let mut params = QueryParams::new(); 2160 | 2161 | if let Some(target_block_id) = target_block_id { 2162 | params.insert("target_block_id", target_block_id); 2163 | } 2164 | 2165 | self.base_client 2166 | .get( 2167 | format!("liteserver/get_account_state/{account_id}"), 2168 | Some(params), 2169 | None, 2170 | ) 2171 | .await 2172 | } 2173 | 2174 | /// Get raw shard info. 2175 | /// 2176 | /// # Parameters 2177 | /// 2178 | /// - `block_id` - block ID: (workchain,shard,seqno,root_hash,file_hash) 2179 | /// - `workchain` - workchain 2180 | /// - `shard` - shard 2181 | /// - `exact` - exact 2182 | /// 2183 | /// # Returns 2184 | /// 2185 | /// raw shard info 2186 | pub async fn get_raw_shard_info( 2187 | &self, 2188 | block_id: &str, 2189 | workchain: Option, 2190 | shard: Option<&str>, 2191 | exact: Option, 2192 | ) -> Result { 2193 | let mut params = QueryParams::new(); 2194 | 2195 | if let Some(workchain) = workchain { 2196 | params.insert("workchain", workchain); 2197 | } 2198 | 2199 | if let Some(shard) = shard { 2200 | params.insert("shard", shard); 2201 | } 2202 | 2203 | if let Some(exact) = exact { 2204 | params.insert("exact", exact); 2205 | } 2206 | 2207 | self.base_client 2208 | .get( 2209 | format!("liteserver/get_shard_info/{block_id}"), 2210 | Some(params), 2211 | None, 2212 | ) 2213 | .await 2214 | } 2215 | 2216 | /// Get all raw shards info. 2217 | /// 2218 | /// # Parameters 2219 | /// 2220 | /// - `block_id` - block ID: (workchain,shard,seqno,root_hash,file_hash) 2221 | /// 2222 | /// # Returns 2223 | /// 2224 | /// all raw shards info 2225 | pub async fn get_all_raw_shards_info( 2226 | &self, 2227 | block_id: &str, 2228 | ) -> Result { 2229 | self.base_client 2230 | .get( 2231 | format!("liteserver/get_all_shards_info/{block_id}"), 2232 | None, 2233 | None, 2234 | ) 2235 | .await 2236 | } 2237 | 2238 | /// Get raw transactions. 2239 | /// 2240 | /// # Parameters 2241 | /// 2242 | /// - `account_id` - account ID 2243 | /// - `count` - count 2244 | /// - `lt` - lt 2245 | /// - `hash` - hash 2246 | /// 2247 | /// # Returns 2248 | /// 2249 | /// raw transactions 2250 | pub async fn get_raw_transactions( 2251 | &self, 2252 | account_id: &str, 2253 | count: i32, 2254 | lt: i64, 2255 | hash: &str, 2256 | ) -> Result { 2257 | let params = QueryParams::from_pairs([ 2258 | ("count", count.to_string().as_str()), 2259 | ("lt", lt.to_string().as_str()), 2260 | ("hash", hash), 2261 | ]); 2262 | 2263 | self.base_client 2264 | .get( 2265 | format!("liteserver/get_transactions/{account_id}"), 2266 | Some(params), 2267 | None, 2268 | ) 2269 | .await 2270 | } 2271 | 2272 | /// Get raw list block transactions. 2273 | /// 2274 | /// # Parameters 2275 | /// 2276 | /// - `block_id` - block ID: (workchain,shard,seqno,root_hash,file_hash) 2277 | /// - `mode` - mode 2278 | /// - `count` - count 2279 | /// - `account_id` - account ID 2280 | /// - `lt` - lt 2281 | /// 2282 | /// # Returns 2283 | /// 2284 | /// a list of raw block transactions 2285 | pub async fn get_raw_list_block_transactions( 2286 | &self, 2287 | block_id: &str, 2288 | mode: i32, 2289 | count: i32, 2290 | account_id: Option<&str>, 2291 | lt: Option, 2292 | ) -> Result { 2293 | let mut params = QueryParams::from_pairs([("mode", mode), ("count", count)]); 2294 | 2295 | if let Some(account_id) = account_id { 2296 | params.insert("account_id", account_id); 2297 | } 2298 | 2299 | if let Some(lt) = lt { 2300 | params.insert("lt", lt); 2301 | } 2302 | 2303 | self.base_client 2304 | .get( 2305 | format!("liteserver/list_block_transactions/{block_id}"), 2306 | Some(params), 2307 | None, 2308 | ) 2309 | .await 2310 | } 2311 | 2312 | /// Get raw block proof. 2313 | /// 2314 | /// # Parameters 2315 | /// 2316 | /// - `known_block_id` - known block: (workchain,shard,seqno,root_hash,file_hash) 2317 | /// - `target_block_id` - target block: (workchain,shard,seqno,root_hash,file_hash) 2318 | /// - `mode` - mode 2319 | /// 2320 | /// # Returns 2321 | /// 2322 | /// raw block proof 2323 | pub async fn get_raw_block_proof( 2324 | &self, 2325 | known_block_id: &str, 2326 | target_block_id: Option<&str>, 2327 | mode: i32, 2328 | ) -> Result { 2329 | let mut params = QueryParams::from_pairs([ 2330 | ("known_block_id", known_block_id), 2331 | ("mode", mode.to_string().as_str()), 2332 | ]); 2333 | 2334 | if let Some(target_block_id) = target_block_id { 2335 | params.insert("target_block_id", target_block_id); 2336 | } 2337 | 2338 | self.base_client 2339 | .get("liteserver/get_block_proof".to_string(), Some(params), None) 2340 | .await 2341 | } 2342 | 2343 | /// Get raw config. 2344 | /// 2345 | /// # Parameters 2346 | /// 2347 | /// - `block_id` - block ID: (workchain,shard,seqno,root_hash,file_hash) 2348 | /// - `mode` - mode 2349 | /// 2350 | /// # Returns 2351 | /// 2352 | /// A `RawConfig` object containing the raw config data 2353 | pub async fn get_raw_config( 2354 | &self, 2355 | block_id: &str, 2356 | mode: i32, 2357 | ) -> Result { 2358 | let params = QueryParams::from_pairs([("mode", mode)]); 2359 | 2360 | self.base_client 2361 | .get( 2362 | format!("liteserver/get_config_all/{block_id}"), 2363 | Some(params), 2364 | None, 2365 | ) 2366 | .await 2367 | } 2368 | 2369 | /// Get raw shard block proof. 2370 | /// 2371 | /// # Parameters 2372 | /// 2373 | /// - `block_id` - block ID: (workchain,shard,seqno,root_hash,file_hash) 2374 | /// 2375 | /// # Returns 2376 | /// 2377 | /// raw shard block proof 2378 | pub async fn get_raw_shard_block_proof( 2379 | &self, 2380 | block_id: &str, 2381 | ) -> Result { 2382 | self.base_client 2383 | .get( 2384 | format!("liteserver/get_shard_block_proof/{block_id}"), 2385 | None, 2386 | None, 2387 | ) 2388 | .await 2389 | } 2390 | 2391 | /// Get out msg queue sizes. 2392 | /// 2393 | /// # Returns 2394 | /// 2395 | /// out msg queue sizes 2396 | pub async fn get_out_msg_queue_sizes(&self) -> Result { 2397 | self.base_client 2398 | .get("liteserver/get_out_msg_queue_sizes".to_string(), None, None) 2399 | .await 2400 | } 2401 | 2402 | /// Decode a given message. Only external incoming messages can be decoded currently. 2403 | /// 2404 | /// # Parameters 2405 | /// 2406 | /// - `boc` - bag-of-cells serialized to hex 2407 | /// 2408 | /// # Returns 2409 | /// 2410 | /// decoded message 2411 | pub async fn decode_message(&self, boc: &str) -> Result { 2412 | self.base_client 2413 | .post_json("message/decode".to_string(), None, Some(boc), None) 2414 | .await 2415 | } 2416 | 2417 | /// Get all inscriptions by owner address. It's experimental API and can be dropped in the future. 2418 | /// 2419 | /// # Parameters 2420 | /// 2421 | /// - `account_id` - account ID 2422 | /// - `limit` - Default value : 1000 2423 | /// - `offset` - Default value : 0 2424 | /// 2425 | /// # Returns 2426 | /// 2427 | /// account inscriptions 2428 | pub async fn get_account_inscriptions( 2429 | &self, 2430 | account_id: &str, 2431 | limit: Option, 2432 | offset: Option, 2433 | ) -> Result { 2434 | let mut params = QueryParams::new(); 2435 | 2436 | if let Some(limit) = limit { 2437 | params.insert("limit", limit); 2438 | } 2439 | 2440 | if let Some(offset) = offset { 2441 | params.insert("offset", offset); 2442 | } 2443 | 2444 | self.base_client 2445 | .get( 2446 | format!("experimental/accounts/{}/inscriptions", account_id), 2447 | Some(params), 2448 | None, 2449 | ) 2450 | .await 2451 | } 2452 | 2453 | /// Get the transfer inscriptions history for account. It's experimental API and can be dropped in the future. 2454 | /// 2455 | /// # Parameters 2456 | /// 2457 | /// - `account_id` - account ID 2458 | /// - `accept_language` - *Default value*: en 2459 | /// - `before_lt` - omit this parameter to get last events 2460 | /// - `limit` - *Default value*: 100 2461 | /// 2462 | /// # Returns 2463 | /// 2464 | /// account inscriptions history 2465 | pub async fn get_account_inscriptions_history( 2466 | &self, 2467 | account_id: &str, 2468 | accept_language: Option<&str>, 2469 | before_lt: Option, 2470 | limit: Option, 2471 | ) -> Result { 2472 | let mut params = QueryParams::new(); 2473 | 2474 | if let Some(before_lt) = before_lt { 2475 | params.insert("before_lt", before_lt); 2476 | } 2477 | 2478 | if let Some(limit) = limit { 2479 | params.insert("limit", limit); 2480 | } 2481 | 2482 | let mut headers = HeaderMap::new(); 2483 | 2484 | if let Some(language) = accept_language { 2485 | headers.insert(ACCEPT_LANGUAGE, HeaderValue::from_str(language)?); 2486 | } 2487 | 2488 | self.base_client 2489 | .get( 2490 | format!("experimental/accounts/{}/inscriptions/history", account_id), 2491 | Some(params), 2492 | Some(headers), 2493 | ) 2494 | .await 2495 | } 2496 | 2497 | /// Get the transfer inscriptions history for account. It's experimental API and can be dropped in the future. 2498 | /// 2499 | /// # Parameters 2500 | /// 2501 | /// - `account_id` - account ID 2502 | /// - `ticker` 2503 | /// - `before_lt` - omit this parameter to get last events 2504 | /// - `limit` - *Default value*: 100 2505 | /// - `accept_language` - The language to use for the response (optional) 2506 | /// 2507 | /// # Returns 2508 | /// 2509 | /// account inscriptions history 2510 | pub async fn get_account_inscriptions_history_by_ticker( 2511 | &self, 2512 | account_id: &str, 2513 | ticker: &str, 2514 | before_lt: Option, 2515 | limit: Option, 2516 | accept_language: Option<&str>, 2517 | ) -> Result { 2518 | let mut params = QueryParams::new(); 2519 | 2520 | if let Some(before_lt) = before_lt { 2521 | params.insert("before_lt", before_lt); 2522 | } 2523 | 2524 | if let Some(limit) = limit { 2525 | params.insert("limit", limit); 2526 | } 2527 | 2528 | let mut headers = HeaderMap::new(); 2529 | 2530 | if let Some(language) = accept_language { 2531 | headers.insert(ACCEPT_LANGUAGE, HeaderValue::from_str(language)?); 2532 | } 2533 | 2534 | self.base_client 2535 | .get( 2536 | format!( 2537 | "experimental/accounts/{}/inscriptions/{}/history", 2538 | account_id, ticker 2539 | ), 2540 | Some(params), 2541 | Some(headers), 2542 | ) 2543 | .await 2544 | } 2545 | 2546 | /// Return comment for making operation with inscription. please don't use it if you don't know what you are doing. 2547 | /// 2548 | /// # Parameters 2549 | /// 2550 | /// - `type` - Available values : ton20, gram20 2551 | /// - `destination` 2552 | /// - `comment` 2553 | /// - `operation` - Available values : transfer 2554 | /// - `amount` 2555 | /// - `ticker` 2556 | /// - `who` 2557 | /// 2558 | /// # Returns 2559 | /// 2560 | /// inscription op template 2561 | pub async fn get_inscription_op_template( 2562 | &self, 2563 | type_: &str, 2564 | destination: Option<&str>, 2565 | comment: Option<&str>, 2566 | operation: &str, 2567 | amount: &str, 2568 | ticker: &str, 2569 | who: &str, 2570 | ) -> Result { 2571 | let mut params = QueryParams::from_pairs([ 2572 | ("type", type_), 2573 | ("operation", operation), 2574 | ("amount", amount), 2575 | ("ticker", ticker), 2576 | ("who", who), 2577 | ]); 2578 | 2579 | if let Some(destination) = destination { 2580 | params.insert("destination", destination); 2581 | } 2582 | 2583 | if let Some(comment) = comment { 2584 | params.insert("comment", comment); 2585 | } 2586 | 2587 | self.base_client 2588 | .get( 2589 | "experimental/inscriptions/op-template".to_string(), 2590 | Some(params), 2591 | None, 2592 | ) 2593 | .await 2594 | } 2595 | 2596 | /// Status. 2597 | /// 2598 | /// # Returns 2599 | /// 2600 | /// status 2601 | pub async fn get_status(&self) -> Result { 2602 | self.base_client.get("status".to_string(), None, None).await 2603 | } 2604 | 2605 | /// Parse address and display in all formats. 2606 | /// 2607 | /// # Parameters 2608 | /// 2609 | /// - `account_id` - account ID 2610 | /// 2611 | /// # Returns 2612 | /// 2613 | /// all forms and info 2614 | pub async fn parse_address(&self, account_id: &str) -> Result { 2615 | self.base_client 2616 | .get(format!("address/{}/parse", account_id), None, None) 2617 | .await 2618 | } 2619 | } 2620 | 2621 | #[cfg(test)] 2622 | mod tests { 2623 | use super::*; 2624 | 2625 | const API_KEY: Option = None; 2626 | const ACCOUNT_ID: &str = "0QCbOix87iy37AwRCWaYhJHzc2gXE_WnAG5vVEAySNT7zClz"; 2627 | const ACCOUNT_ID_MAINNET: &str = "EQCD39VS5jcptHL8vMjEXrzGaRcCVYto7HUn4bpAOg8xqB2N"; 2628 | const JETTON_ID: &str = "kQDZADmMBA5A10sLWNssTjH-2FS8aix2UixT48Xt3j_g0NZY"; 2629 | const JETTON_ID_MAINNET: &str = "EQBCFwW8uFUh-amdRmNY9NyeDEaeDYXd9ggJGsicpqVcHq7B"; 2630 | const EVENT_ID: &str = "df5d00116aebaab3a60c4d4551663deb3e5ae334d229e541913cd9cac6811981"; 2631 | const EVENT_ID_MAINNET: &str = 2632 | "68656e74d18b10309e41e057191abcfc42f973c82bc84326985cdbf7bf89b126"; 2633 | const DOMAIN_NAME_1: &str = "fragment.ton"; 2634 | const DOMAIN_NAME_2: &str = "foundation.ton"; 2635 | const NFT_COLLECTION_ID: &str = "EQDD6a-rK5jMrrhoZUhPOkByWRIHmCdf1f0-PI-1Cdl3NRBV"; 2636 | const NFT_ID: &str = "EQDhmGLnSk463FC1G6RVgfQs0JJ6OIlBKoQ6fRVb9-JIPQ2R"; 2637 | const NFT_ID_MAINNET: &str = "EQBSZKEvqoiuPUCFz-CHtpVxAwg1F8PyjZhWAJL2yeujn0_H"; 2638 | const TRACE_ID_HEX: &str = "97264395BD65A255A429B11326C84128B7D70FFED7949ABAE3036D506BA38621"; 2639 | const EVENT_ID_HEX: &str = "53388440417dc044d00e99d89b591acc28f100332a004f180e4f14b876620c13"; 2640 | const MASTERCHAIN_SEQNO: i32 = 123456; 2641 | const BLOCK_ID: &str = "(-1,8000000000000000,4234234)"; 2642 | const TRANSACTION_ID: &str = "97264395BD65A255A429B11326C84128B7D70FFED7949ABAE3036D506BA38621"; 2643 | const MESSAGE_ID: &str = "EAC465A0DC51E844B12BBD0040308801FA19B8D1BD49208AA929E2CAAEE9D401"; 2644 | 2645 | #[tokio::test] 2646 | #[ignore] 2647 | async fn test_get_accounts_does_not_fail() { 2648 | let client = RestApiClientV2::new(Network::Testnet, API_KEY); 2649 | let result = client.get_accounts(&[ACCOUNT_ID], None).await; 2650 | assert!(result.is_ok()); 2651 | } 2652 | 2653 | #[tokio::test] 2654 | #[ignore] 2655 | async fn test_get_account_does_not_fail() { 2656 | let client = RestApiClientV2::new(Network::Testnet, API_KEY); 2657 | let result = client.get_account(ACCOUNT_ID).await; 2658 | assert!(result.is_ok()); 2659 | } 2660 | 2661 | #[tokio::test] 2662 | #[ignore] 2663 | async fn test_account_dns_back_resolve_does_not_fail() { 2664 | let client = RestApiClientV2::new(Network::Testnet, API_KEY); 2665 | let result = client.account_dns_back_resolve(ACCOUNT_ID).await; 2666 | assert!(result.is_ok()); 2667 | } 2668 | 2669 | #[tokio::test] 2670 | #[ignore] 2671 | async fn test_get_account_jettons_balances_does_not_fail() { 2672 | let client = RestApiClientV2::new(Network::Testnet, API_KEY); 2673 | let result = client 2674 | .get_account_jettons_balances(ACCOUNT_ID, None, None) 2675 | .await; 2676 | assert!(result.is_ok()); 2677 | } 2678 | 2679 | #[tokio::test] 2680 | #[ignore] 2681 | async fn test_get_account_jetton_balance_does_not_fail() { 2682 | let client = RestApiClientV2::new(Network::Testnet, API_KEY); 2683 | let result = client 2684 | .get_account_jetton_balance(ACCOUNT_ID, JETTON_ID, None) 2685 | .await; 2686 | assert!(result.is_ok()); 2687 | } 2688 | 2689 | #[tokio::test] 2690 | #[ignore] 2691 | async fn test_get_account_jettons_history_does_not_fail() { 2692 | let client = RestApiClientV2::new(Network::Testnet, API_KEY); 2693 | let result = client 2694 | .get_account_jettons_history(ACCOUNT_ID, None, None, 10, None, None) 2695 | .await; 2696 | assert!(result.is_ok()); 2697 | } 2698 | 2699 | #[tokio::test] 2700 | #[ignore] 2701 | async fn test_get_account_jetton_history_by_id_does_not_fail() { 2702 | let client = RestApiClientV2::new(Network::Testnet, API_KEY); 2703 | let result = client 2704 | .get_account_jetton_history_by_id(ACCOUNT_ID, JETTON_ID, None, None, 10, None, None) 2705 | .await; 2706 | assert!(result.is_ok()); 2707 | } 2708 | 2709 | #[tokio::test] 2710 | #[ignore] 2711 | async fn test_get_account_nft_items_does_not_fail() { 2712 | let client = RestApiClientV2::new(Network::Testnet, API_KEY); 2713 | let result = client 2714 | .get_account_nft_items(ACCOUNT_ID, None, None, None, None) 2715 | .await; 2716 | assert!(result.is_ok()); 2717 | } 2718 | 2719 | #[tokio::test] 2720 | #[ignore] 2721 | async fn test_get_account_events_does_not_fail() { 2722 | let client = RestApiClientV2::new(Network::Testnet, API_KEY); 2723 | let result = client 2724 | .get_account_events(ACCOUNT_ID, None, None, None, None, 10, None, None) 2725 | .await; 2726 | assert!(result.is_ok()); 2727 | } 2728 | 2729 | #[tokio::test] 2730 | #[ignore] 2731 | async fn test_get_account_event_does_not_fail() { 2732 | let client = RestApiClientV2::new(Network::Testnet, API_KEY); 2733 | let result = client 2734 | .get_account_event(ACCOUNT_ID, EVENT_ID, None, None) 2735 | .await; 2736 | assert!(result.is_ok()); 2737 | } 2738 | 2739 | #[tokio::test] 2740 | #[ignore] 2741 | async fn test_get_account_traces_does_not_fail() { 2742 | let client = RestApiClientV2::new(Network::Testnet, API_KEY); 2743 | let result = client.get_account_traces(ACCOUNT_ID, None, None).await; 2744 | assert!(result.is_ok()); 2745 | } 2746 | 2747 | #[tokio::test] 2748 | #[ignore] 2749 | async fn test_get_account_subscriptions_does_not_fail() { 2750 | let client = RestApiClientV2::new(Network::Testnet, API_KEY); 2751 | let result = client.get_account_subscriptions(ACCOUNT_ID).await; 2752 | assert!(result.is_ok()); 2753 | } 2754 | 2755 | #[tokio::test] 2756 | #[ignore] 2757 | async fn test_reindex_account_does_not_fail() { 2758 | let client = RestApiClientV2::new(Network::Testnet, API_KEY); 2759 | let result = client.reindex_account(ACCOUNT_ID).await; 2760 | assert!(result.is_ok()); 2761 | } 2762 | 2763 | #[tokio::test] 2764 | #[ignore] 2765 | async fn test_search_accounts_does_not_fail() { 2766 | let client = RestApiClientV2::new(Network::Testnet, API_KEY); 2767 | let result = client.search_accounts(DOMAIN_NAME_1).await; 2768 | assert!(result.is_ok()); 2769 | } 2770 | 2771 | #[tokio::test] 2772 | #[ignore] 2773 | async fn test_get_account_dns_expiring_does_not_fail() { 2774 | let client = RestApiClientV2::new(Network::Testnet, API_KEY); 2775 | let result = client.get_account_dns_expiring(ACCOUNT_ID, None).await; 2776 | assert!(result.is_ok()); 2777 | } 2778 | 2779 | #[tokio::test] 2780 | #[ignore] 2781 | async fn test_get_account_public_key_does_not_fail() { 2782 | let client = RestApiClientV2::new(Network::Testnet, API_KEY); 2783 | let result = client.get_account_public_key(ACCOUNT_ID).await; 2784 | assert!(result.is_ok()); 2785 | } 2786 | 2787 | #[tokio::test] 2788 | #[ignore] 2789 | async fn test_get_account_multisigs_does_not_fail() { 2790 | let client = RestApiClientV2::new(Network::Testnet, API_KEY); 2791 | let result = client.get_account_multisigs(ACCOUNT_ID).await; 2792 | assert!(result.is_ok()); 2793 | } 2794 | 2795 | #[tokio::test] 2796 | #[ignore] 2797 | async fn test_get_account_diff_does_not_fail() { 2798 | let client = RestApiClientV2::new(Network::Testnet, API_KEY); 2799 | let result = client 2800 | .get_account_diff(ACCOUNT_ID, 1514746800, 1672513200) 2801 | .await; 2802 | assert!(result.is_ok()); 2803 | } 2804 | 2805 | #[tokio::test] 2806 | #[ignore] 2807 | async fn test_get_account_nft_history_does_not_fail() { 2808 | let client = RestApiClientV2::new(Network::Testnet, API_KEY); 2809 | let result = client 2810 | .get_account_nft_history(ACCOUNT_ID, None, None, 10, None, None) 2811 | .await; 2812 | assert!(result.is_ok()); 2813 | } 2814 | 2815 | #[tokio::test] 2816 | #[ignore] 2817 | async fn test_get_nft_collections_does_not_fail() { 2818 | let client = RestApiClientV2::new(Network::Testnet, API_KEY); 2819 | let result = client.get_nft_collections(None, None).await; 2820 | assert!(result.is_ok()); 2821 | } 2822 | 2823 | #[tokio::test] 2824 | #[ignore] 2825 | async fn test_get_nft_collection_does_not_fail() { 2826 | let client = RestApiClientV2::new(Network::Testnet, API_KEY); 2827 | let result = client.get_nft_collection(NFT_COLLECTION_ID).await; 2828 | assert!(result.is_ok()); 2829 | } 2830 | 2831 | #[tokio::test] 2832 | #[ignore] 2833 | async fn test_get_items_from_collection_does_not_fail() { 2834 | let client = RestApiClientV2::new(Network::Testnet, API_KEY); 2835 | let result = client 2836 | .get_items_from_collection(NFT_COLLECTION_ID, None, None) 2837 | .await; 2838 | assert!(result.is_ok()); 2839 | } 2840 | 2841 | #[tokio::test] 2842 | #[ignore] 2843 | async fn test_get_nft_items_by_addresses_does_not_fail() { 2844 | let client = RestApiClientV2::new(Network::Testnet, API_KEY); 2845 | let result = client.get_nft_items_by_addresses(&[NFT_ID]).await; 2846 | assert!(result.is_ok()); 2847 | } 2848 | 2849 | #[tokio::test] 2850 | #[ignore] 2851 | async fn test_get_nft_item_by_address_does_not_fail() { 2852 | let client = RestApiClientV2::new(Network::Mainnet, API_KEY); 2853 | let result = client.get_nft_item_by_address(NFT_ID_MAINNET).await; 2854 | assert!(result.is_ok()); 2855 | } 2856 | 2857 | #[tokio::test] 2858 | #[ignore] 2859 | async fn test_get_nft_history_by_id_does_not_fail() { 2860 | let client = RestApiClientV2::new(Network::Testnet, API_KEY); 2861 | let result = client 2862 | .get_nft_history_by_id(ACCOUNT_ID, None, None, 10, None, None) 2863 | .await; 2864 | assert!(result.is_ok()); 2865 | } 2866 | 2867 | #[tokio::test] 2868 | #[ignore] 2869 | async fn test_get_jettons_does_not_fail() { 2870 | let client = RestApiClientV2::new(Network::Testnet, API_KEY); 2871 | let result = client.get_jettons(None, None).await; 2872 | assert!(result.is_ok()); 2873 | } 2874 | 2875 | #[tokio::test] 2876 | #[ignore] 2877 | async fn test_get_jetton_info_does_not_fail() { 2878 | let client = RestApiClientV2::new(Network::Mainnet, API_KEY); 2879 | let result = client.get_jetton_info(JETTON_ID_MAINNET).await; 2880 | assert!(result.is_ok()); 2881 | } 2882 | 2883 | #[tokio::test] 2884 | #[ignore] 2885 | async fn test_get_jetton_holders_does_not_fail() { 2886 | let client = RestApiClientV2::new(Network::Mainnet, API_KEY); 2887 | let result = client 2888 | .get_jetton_holders(JETTON_ID_MAINNET, None, None) 2889 | .await; 2890 | assert!(result.is_ok()); 2891 | } 2892 | 2893 | #[tokio::test] 2894 | #[ignore] 2895 | async fn test_get_jetton_transfer_payload_does_not_fail() { 2896 | let client = RestApiClientV2::new(Network::Mainnet, API_KEY); 2897 | let result = client 2898 | .get_jetton_transfer_payload(ACCOUNT_ID_MAINNET, JETTON_ID_MAINNET) 2899 | .await; 2900 | assert!(result.is_ok()); 2901 | } 2902 | 2903 | #[tokio::test] 2904 | #[ignore] 2905 | async fn test_get_jettons_events_does_not_fail() { 2906 | let client = RestApiClientV2::new(Network::Mainnet, API_KEY); 2907 | let result = client.get_jettons_events(EVENT_ID_MAINNET, None).await; 2908 | assert!(result.is_ok()); 2909 | } 2910 | 2911 | #[tokio::test] 2912 | #[ignore] 2913 | async fn test_get_dns_info_does_not_fail() { 2914 | let client = RestApiClientV2::new(Network::Mainnet, API_KEY); 2915 | let result = client.get_dns_info(DOMAIN_NAME_1).await; 2916 | assert!(result.is_ok()); 2917 | } 2918 | 2919 | #[tokio::test] 2920 | #[ignore] 2921 | async fn test_dns_resolve_does_not_fail() { 2922 | let client = RestApiClientV2::new(Network::Testnet, API_KEY); 2923 | let result = client.dns_resolve(DOMAIN_NAME_1).await; 2924 | assert!(result.is_ok()); 2925 | } 2926 | 2927 | #[tokio::test] 2928 | #[ignore] 2929 | async fn test_get_domain_bids_does_not_fail() { 2930 | let client = RestApiClientV2::new(Network::Mainnet, API_KEY); 2931 | let result = client.get_domain_bids(DOMAIN_NAME_2).await; 2932 | assert!(result.is_ok()); 2933 | } 2934 | 2935 | #[tokio::test] 2936 | #[ignore] 2937 | async fn test_get_all_auctions_does_not_fail() { 2938 | let client = RestApiClientV2::new(Network::Mainnet, API_KEY); 2939 | let result = client.get_all_auctions(DOMAIN_NAME_2).await; 2940 | assert!(result.is_ok()); 2941 | } 2942 | 2943 | #[tokio::test] 2944 | #[ignore] 2945 | async fn test_get_account_seqno_does_not_fail() { 2946 | let client = RestApiClientV2::new(Network::Testnet, API_KEY); 2947 | let result = client.get_account_seqno(ACCOUNT_ID).await; 2948 | assert!(result.is_ok()); 2949 | } 2950 | 2951 | #[tokio::test] 2952 | #[ignore] 2953 | async fn test_get_rates_does_not_fail() { 2954 | let client = RestApiClientV2::new(Network::Mainnet, API_KEY); 2955 | let result = client.get_rates(&["ton"], &["ton", "usd", "rub"]).await; 2956 | assert!(result.is_ok()); 2957 | } 2958 | 2959 | #[tokio::test] 2960 | #[ignore] 2961 | async fn test_get_chart_rates_does_not_fail() { 2962 | let client = RestApiClientV2::new(Network::Mainnet, API_KEY); 2963 | let result = client.get_chart_rates("ton", None, None, None, None).await; 2964 | assert!(result.is_ok()); 2965 | } 2966 | 2967 | #[tokio::test] 2968 | #[ignore] 2969 | async fn test_get_markets_rates_does_not_fail() { 2970 | let client = RestApiClientV2::new(Network::Mainnet, API_KEY); 2971 | let result = client.get_markets_rates().await; 2972 | assert!(result.is_ok()); 2973 | } 2974 | 2975 | #[tokio::test] 2976 | #[ignore] 2977 | async fn test_get_account_nominators_pools_does_not_fail() { 2978 | let client = RestApiClientV2::new(Network::Mainnet, API_KEY); 2979 | let result = client 2980 | .get_account_nominators_pools(ACCOUNT_ID_MAINNET) 2981 | .await; 2982 | assert!(result.is_ok()); 2983 | } 2984 | 2985 | #[tokio::test] 2986 | #[ignore] 2987 | async fn test_get_staking_pools_does_not_fail() { 2988 | let client = RestApiClientV2::new(Network::Mainnet, API_KEY); 2989 | let result = client.get_staking_pools(None, None, None).await; 2990 | assert!(result.is_ok()); 2991 | } 2992 | 2993 | #[tokio::test] 2994 | #[ignore] 2995 | async fn test_get_trace_does_not_fail() { 2996 | let client = RestApiClientV2::new(Network::Mainnet, API_KEY); 2997 | let result = client.get_trace(TRACE_ID_HEX).await; 2998 | assert!(result.is_ok()); 2999 | } 3000 | 3001 | #[tokio::test] 3002 | #[ignore] 3003 | async fn test_get_event_does_not_fail() { 3004 | let client = RestApiClientV2::new(Network::Mainnet, API_KEY); 3005 | let result = client.get_event(EVENT_ID_HEX, None).await; 3006 | assert!(result.is_ok()); 3007 | } 3008 | 3009 | #[tokio::test] 3010 | #[ignore] 3011 | async fn test_get_storage_providers_does_not_fail() { 3012 | let client = RestApiClientV2::new(Network::Mainnet, API_KEY); 3013 | let result = client.get_storage_providers().await; 3014 | assert!(result.is_ok()); 3015 | } 3016 | 3017 | #[tokio::test] 3018 | #[ignore] 3019 | async fn test_get_ton_connect_payload_does_not_fail() { 3020 | let client = RestApiClientV2::new(Network::Mainnet, API_KEY); 3021 | let result = client.get_ton_connect_payload().await; 3022 | assert!(result.is_ok()); 3023 | } 3024 | 3025 | #[tokio::test] 3026 | #[ignore] 3027 | async fn test_get_gasless_config_does_not_fail() { 3028 | let client = RestApiClientV2::new(Network::Mainnet, API_KEY); 3029 | let result = client.get_gasless_config().await; 3030 | assert!(result.is_ok()); 3031 | } 3032 | 3033 | #[tokio::test] 3034 | #[ignore] 3035 | async fn test_get_reduced_blockchain_blocks_does_not_fail() { 3036 | let client = RestApiClientV2::new(Network::Mainnet, API_KEY); 3037 | let result = client.get_reduced_blockchain_blocks(1000, 1001).await; 3038 | assert!(result.is_ok()); 3039 | } 3040 | 3041 | #[tokio::test] 3042 | #[ignore] 3043 | async fn test_get_blockchain_block_does_not_fail() { 3044 | let client = RestApiClientV2::new(Network::Mainnet, API_KEY); 3045 | 3046 | let result = client.get_blockchain_block(BLOCK_ID).await; 3047 | assert!(result.is_ok()); 3048 | } 3049 | 3050 | #[tokio::test] 3051 | #[ignore] 3052 | async fn test_get_blockchain_masterchain_shards_does_not_fail() { 3053 | let client = RestApiClientV2::new(Network::Mainnet, API_KEY); 3054 | 3055 | let result = client 3056 | .get_blockchain_masterchain_shards(MASTERCHAIN_SEQNO) 3057 | .await; 3058 | assert!(result.is_ok()); 3059 | } 3060 | 3061 | #[tokio::test] 3062 | #[ignore] 3063 | async fn test_get_blockchain_masterchain_blocks_does_not_fail() { 3064 | let client = RestApiClientV2::new(Network::Mainnet, API_KEY); 3065 | 3066 | let result = client 3067 | .get_blockchain_masterchain_blocks(MASTERCHAIN_SEQNO) 3068 | .await; 3069 | assert!(result.is_ok()); 3070 | } 3071 | 3072 | #[tokio::test] 3073 | #[ignore] 3074 | async fn test_get_blockchain_masterchain_transactions_does_not_fail() { 3075 | let client = RestApiClientV2::new(Network::Mainnet, API_KEY); 3076 | let result = client 3077 | .get_blockchain_masterchain_transactions(MASTERCHAIN_SEQNO) 3078 | .await; 3079 | assert!(result.is_ok()); 3080 | } 3081 | 3082 | #[tokio::test] 3083 | #[ignore] 3084 | async fn test_get_blockchain_block_transactions_does_not_fail() { 3085 | let client = RestApiClientV2::new(Network::Mainnet, API_KEY); 3086 | let result = client.get_blockchain_block_transactions(BLOCK_ID).await; 3087 | assert!(result.is_ok()); 3088 | } 3089 | 3090 | #[tokio::test] 3091 | #[ignore] 3092 | async fn test_get_blockchain_transaction_does_not_fail() { 3093 | let client = RestApiClientV2::new(Network::Mainnet, API_KEY); 3094 | let result = client.get_blockchain_transaction(TRANSACTION_ID).await; 3095 | assert!(result.is_ok()); 3096 | } 3097 | 3098 | #[tokio::test] 3099 | #[ignore] 3100 | async fn test_get_blockchain_transaction_by_message_hash_does_not_fail() { 3101 | let client = RestApiClientV2::new(Network::Mainnet, API_KEY); 3102 | let result = client 3103 | .get_blockchain_transaction_by_message_hash(MESSAGE_ID) 3104 | .await; 3105 | assert!(result.is_ok()); 3106 | } 3107 | 3108 | #[tokio::test] 3109 | #[ignore] 3110 | async fn test_get_blockchain_validators_does_not_fail() { 3111 | let client = RestApiClientV2::new(Network::Mainnet, API_KEY); 3112 | let result = client.get_blockchain_validators().await; 3113 | assert!(result.is_ok()); 3114 | } 3115 | 3116 | #[tokio::test] 3117 | #[ignore] 3118 | async fn test_get_blockchain_masterchain_head_does_not_fail() { 3119 | let client = RestApiClientV2::new(Network::Mainnet, API_KEY); 3120 | let result = client.get_blockchain_masterchain_head().await; 3121 | assert!(result.is_ok()); 3122 | } 3123 | 3124 | #[tokio::test] 3125 | #[ignore] 3126 | async fn test_get_blockchain_raw_account_does_not_fail() { 3127 | let client = RestApiClientV2::new(Network::Mainnet, API_KEY); 3128 | let result = client.get_blockchain_raw_account(ACCOUNT_ID_MAINNET).await; 3129 | assert!(result.is_ok()); 3130 | } 3131 | 3132 | #[tokio::test] 3133 | #[ignore] 3134 | async fn test_get_blockchain_account_transactions_does_not_fail() { 3135 | let client = RestApiClientV2::new(Network::Mainnet, API_KEY); 3136 | let result = client 3137 | .get_blockchain_account_transactions( 3138 | ACCOUNT_ID, 3139 | Some(39787624000003), 3140 | None, 3141 | Some(100), 3142 | Some("desc"), 3143 | ) 3144 | .await; 3145 | assert!(result.is_ok()); 3146 | } 3147 | 3148 | #[tokio::test] 3149 | #[ignore] 3150 | async fn test_exec_get_method_for_blockchain_account_does_not_fail() { 3151 | let client = RestApiClientV2::new(Network::Mainnet, API_KEY); 3152 | let result = client 3153 | .exec_get_method_for_blockchain_account(ACCOUNT_ID_MAINNET, "get_wallet_address", None) 3154 | .await; 3155 | assert!(result.is_ok()); 3156 | } 3157 | 3158 | #[tokio::test] 3159 | #[ignore] 3160 | async fn test_get_blockchain_config_does_not_fail() { 3161 | let client = RestApiClientV2::new(Network::Mainnet, API_KEY); 3162 | let result = client.get_blockchain_config().await; 3163 | assert!(result.is_ok()); 3164 | } 3165 | 3166 | #[tokio::test] 3167 | #[ignore] 3168 | async fn test_get_raw_blockchain_config_does_not_fail() { 3169 | let client = RestApiClientV2::new(Network::Mainnet, API_KEY); 3170 | let result = client.get_raw_blockchain_config().await; 3171 | assert!(result.is_ok()); 3172 | } 3173 | 3174 | #[tokio::test] 3175 | #[ignore] 3176 | async fn test_get_raw_masterchain_info_does_not_fail() { 3177 | let client = RestApiClientV2::new(Network::Mainnet, API_KEY); 3178 | let result = client.get_raw_masterchain_info().await; 3179 | assert!(result.is_ok()); 3180 | } 3181 | 3182 | #[tokio::test] 3183 | #[ignore] 3184 | async fn test_get_raw_masterchain_info_ext_does_not_fail() { 3185 | let client = RestApiClientV2::new(Network::Mainnet, API_KEY); 3186 | let result = client.get_raw_masterchain_info_ext(0).await; 3187 | assert!(result.is_ok()); 3188 | } 3189 | 3190 | #[tokio::test] 3191 | #[ignore] 3192 | async fn test_get_raw_time_does_not_fail() { 3193 | let client = RestApiClientV2::new(Network::Testnet, API_KEY); 3194 | let result = client.get_raw_time().await; 3195 | assert!(result.is_ok()); 3196 | } 3197 | 3198 | #[tokio::test] 3199 | #[ignore] 3200 | async fn test_get_out_msg_queue_sizes_does_not_fail() { 3201 | let client = RestApiClientV2::new(Network::Mainnet, API_KEY); 3202 | let result = client.get_out_msg_queue_sizes().await; 3203 | assert!(result.is_ok()); 3204 | } 3205 | 3206 | #[tokio::test] 3207 | #[ignore] 3208 | async fn test_get_account_inscriptions_does_not_fail() { 3209 | let client = RestApiClientV2::new(Network::Mainnet, API_KEY); 3210 | let result = client 3211 | .get_account_inscriptions(ACCOUNT_ID_MAINNET, Some(10), Some(0)) 3212 | .await; 3213 | assert!(result.is_ok()); 3214 | } 3215 | 3216 | #[tokio::test] 3217 | #[ignore] 3218 | async fn test_get_status_does_not_fail() { 3219 | let client = RestApiClientV2::new(Network::Mainnet, API_KEY); 3220 | let result = client.get_status().await; 3221 | assert!(result.is_ok()); 3222 | } 3223 | 3224 | #[tokio::test] 3225 | #[ignore] 3226 | async fn test_parse_address_does_not_fail() { 3227 | let client = RestApiClientV2::new(Network::Testnet, API_KEY); 3228 | 3229 | let result = client.parse_address(ACCOUNT_ID).await; 3230 | assert!(result.is_ok()); 3231 | } 3232 | } 3233 | --------------------------------------------------------------------------------