helius_rust_client/models/
enriched_transaction.rs

1use serde::{Deserialize};
2use solana_client::client_error::{ClientError, ClientErrorKind, Result as ClientResult};
3use solana_program::{clock::UnixTimestamp, pubkey::Pubkey, slot_history::Slot};
4use solana_sdk::{
5    commitment_config::CommitmentLevel, signature::Signature,
6};
7
8use super::{
9    enums::{TransactionSource, TransactionType},
10    nft::{CompressedNftEvent, NftEvent},
11};
12
13#[derive(Debug, Default)]
14pub struct RequestConfig {
15    pub address: Pubkey,
16    pub before: Option<Signature>,
17    pub until: Option<Signature>,
18    pub limit: Option<usize>,
19    pub source: Option<TransactionSource>,
20    pub transaction_type: Option<TransactionType>,
21    pub commitment: Option<CommitmentLevel>,
22}
23impl RequestConfig {
24    pub fn generate_query_parameters(
25        &self,
26        api_key: String,
27    ) -> ClientResult<Vec<(String, String)>> {
28        let mut query_params = vec![
29            ("address".to_string(), self.address.to_string()),
30            ("api-key".to_string(), api_key),
31        ];
32        if self.before.is_some() {
33            query_params.push(("before".to_string(), self.before.unwrap().to_string()));
34        }
35        if self.until.is_some() {
36            query_params.push(("until".to_string(), self.until.unwrap().to_string()));
37        }
38        if self.limit.is_some() {
39            query_params.push(("limit".to_string(), self.limit.unwrap().to_string()));
40        }
41        if self.source.is_some() {
42            query_params.push(("source".to_string(), self.source.unwrap().to_string()));
43        }
44        if self.transaction_type.is_some() {
45            query_params.push((
46                "type".to_string(),
47                self.transaction_type.unwrap().to_string(),
48            ));
49        }
50
51        match self.commitment {
52            Some(CommitmentLevel::Confirmed) => {
53                query_params.push(("commitment".to_string(), "confirmed".to_string()));
54            }
55            Some(CommitmentLevel::Finalized) => {
56                query_params.push(("commitment".to_string(), "finalized".to_string()));
57            }
58            None => {}
59            _ => {
60                return Err(ClientError::from(ClientErrorKind::Custom(
61                    "Only Confirmed and Finalized commitments are supported by this API"
62                        .to_string(),
63                )));
64            }
65        }
66        Ok(query_params)
67    }
68}
69
70#[derive(Clone, Debug, PartialEq, Deserialize)]
71#[serde(rename_all = "camelCase")]
72pub struct EnrichedTransaction {
73    pub description: Option<String>,
74    #[serde(rename = "type")]
75    pub transaction_type: TransactionType,
76    pub source: TransactionSource,
77    pub fee: u64,
78    pub fee_payer: String,
79    pub signature: String,
80    pub slot: Slot,
81    pub timestamp: Option<UnixTimestamp>,
82    pub native_transfers: Vec<NativeTransfer>,
83    pub token_transfers: Vec<TokenTransfer>,
84    pub account_data: Vec<EnrichedAccountData>,
85    pub transaction_error: Option<EnrichedError>,
86    pub instructions: Vec<EnrichedInstruction>,
87    pub events: EnrichedEvents,
88}
89
90#[derive(Clone, Debug, PartialEq, Deserialize)]
91#[serde(rename_all = "camelCase")]
92pub struct EnrichedEvents {
93    pub nft: Option<NftEvent>,
94    pub swap: Option<SwapEvent>,
95    pub compressed: Option<CompressedNftEvent>,
96}
97
98#[derive(Clone, Debug, PartialEq, Deserialize)]
99#[serde(rename_all = "camelCase")]
100pub struct NativeTransfer {
101    pub from_user_account: String,
102    pub to_user_account: String,
103    pub amount: u64,
104}
105
106#[derive(Clone, Debug, PartialEq, Deserialize)]
107#[serde(rename_all = "camelCase")]
108pub struct TokenTransfer {
109    pub from_user_account: String,
110    pub to_user_account: String,
111    pub from_token_account: String,
112    pub to_token_account: String,
113    pub token_amount: u64,
114    pub mint: String,
115}
116
117#[derive(Clone, Debug, PartialEq, Deserialize)]
118#[serde(rename_all = "camelCase")]
119pub struct EnrichedAccountData {
120    pub account: String,
121    pub native_balance_change: i128,
122    pub token_balance_changes: Vec<EnrichedTokenBalanceChange>,
123}
124
125#[derive(Clone, Debug, PartialEq, Deserialize)]
126#[serde(rename_all = "camelCase")]
127pub struct EnrichedInstruction {
128    pub accounts: Vec<String>,
129    pub data: String,
130    pub program_id: String,
131    pub inner_instructions: Vec<EnrichedInnerInstruction>,
132}
133
134#[derive(Clone, Debug, PartialEq, Deserialize)]
135#[serde(rename_all = "camelCase")]
136pub struct EnrichedInnerInstruction {
137    pub accounts: Vec<String>,
138    pub data: String,
139    pub program_id: String,
140}
141
142#[derive(Clone, Debug, PartialEq, Deserialize)]
143#[serde(rename_all = "camelCase")]
144pub struct EnrichedTokenBalanceChange {
145    pub user_account: String,
146    pub token_account: String,
147    pub mint: String,
148    pub raw_token_amount: RawTokenAmount,
149}
150
151#[derive(Clone, Debug, PartialEq, Deserialize)]
152#[serde(rename_all = "camelCase")]
153pub struct RawTokenAmount {
154    pub token_amount: String,
155    pub decimals: u8,
156}
157
158#[derive(Clone, Debug, PartialEq, Deserialize)]
159#[serde(rename_all = "camelCase")]
160pub struct EnrichedError {
161    pub error: String,
162}
163
164#[derive(Clone, Debug, PartialEq, Deserialize)]
165#[serde(rename_all = "camelCase")]
166pub struct SwapEvent {
167    pub error: String,
168}