helius_rust_client/models/
nft.rs1use serde::Deserialize;
2use serde_json::{json, Value};
3
4use solana_client::client_error::{ClientError, ClientErrorKind, Result as ClientResult};
5
6use super::{
7 enriched_transaction::{NativeTransfer, TokenTransfer},
8 enums::{CompressedNftEventType, NftEventType, SaleType, TokenStandard, TransactionSource},
9};
10
11#[derive(Deserialize, Debug, PartialEq)]
12#[serde(rename_all = "camelCase")]
13pub struct ActiveListing {
14 pub transaction_signature: String,
15 pub marketplace: String,
16 pub amount: u64,
17 pub seller: String,
18}
19
20#[derive(Deserialize, Debug, PartialEq)]
21#[serde(rename_all = "camelCase")]
22pub struct NftMetadata {
23 pub mint: String,
24 pub name: String,
25 pub burned: bool,
26 pub first_verified_creator: String,
27 pub verified_collection_address: String,
28 pub active_listings: Vec<ActiveListing>,
29}
30
31#[derive(Deserialize, Debug, PartialEq, Clone)]
32#[serde(rename_all = "camelCase")]
33pub struct CompressedNftEvent {
34 event_type: CompressedNftEventType,
35 tree_id: String,
36 asset_id: String,
37 leaf_index: u64,
38 instruction_index: u64,
39 inner_instruction_index: u64,
40}
41
42#[derive(Deserialize, Debug, PartialEq, Clone)]
43#[serde(rename_all = "camelCase")]
44pub struct NftEvent {
45 pub amount: i128, pub fee: u64,
47 pub fee_payer: String,
48 pub signature: String,
49 pub slot: u64,
50 pub timestamp: u64,
51 #[serde(rename = "type")]
52 pub event_type: NftEventType,
53 pub buyer: String,
54 pub seller: String,
55 pub staker: String,
56 pub nfts: Vec<NftToken>,
57}
58
59#[derive(Deserialize, Debug, PartialEq, Clone)]
60#[serde(rename_all = "camelCase")]
61pub struct NftEventV2 {
62 #[serde(rename = "type")]
63 pub event_type: NftEventType,
64 pub source: TransactionSource,
65 pub amount: i128, pub fee: u64,
67 pub fee_payer: String,
68 pub signature: String,
69 pub slot: u64,
70 pub timestamp: u64,
71 pub sale_type: SaleType,
72 pub buyer: String,
73 pub seller: String,
74 pub staker: String,
75 pub nfts: Value,
76 pub native_transfers: Vec<NativeTransfer>,
77 pub token_transfers: Vec<TokenTransfer>,
78 pub pagination_token: Option<String>,
79}
80
81#[derive(Deserialize, Debug, PartialEq, Clone)]
82#[serde(rename_all = "camelCase")]
83pub struct NftToken {
84 pub mint: String,
85 pub token_standard: TokenStandard,
86}
87
88#[derive(Deserialize, Debug, PartialEq)]
89#[serde(rename_all = "camelCase")]
90pub struct MintListResult {
91 pub mint: String,
92 pub name: String,
93}
94
95#[derive(Deserialize, Debug, PartialEq)]
96#[serde(rename_all = "camelCase")]
97pub struct TokenBalancesResponse {
98 pub native_balance: u64,
99 pub tokens: Vec<TokenBalance>,
100}
101
102#[derive(Deserialize, Debug, PartialEq)]
103#[serde(rename_all = "camelCase")]
104pub struct MintListResponse {
105 pub result: Vec<MintListResult>,
106 pub pagination_token: String,
107}
108
109#[derive(Deserialize, Debug, PartialEq)]
110#[serde(rename_all = "camelCase")]
111pub struct NftResponse {
112 pub number_of_pages: usize,
113 pub nfts: NftInfo,
114}
115
116#[derive(Deserialize, Debug, PartialEq)]
117#[serde(rename = "nft")]
118#[serde(rename_all = "camelCase")]
119pub struct NftInfo {
120 pub name: String,
121 pub token_address: String,
122 pub collection_address: String,
123 pub collection_name: String,
124 pub image_url: String,
125 pub traits: Vec<Trait>,
126}
127
128#[derive(Deserialize, Debug, PartialEq)]
129#[serde(rename_all = "camelCase")]
130pub struct Trait {
131 pub trait_type: String,
132 pub value: String,
133}
134
135#[derive(Deserialize, Debug, PartialEq)]
136#[serde(rename_all = "camelCase")]
137pub struct TokenBalance {
138 pub token_account: String,
139 pub mint: String,
140 pub amount: u64,
141 pub decimals: u8,
142}
143
144#[derive(Debug, Default)]
146pub struct MintListRequestConfig {
147 pub verified_collection_addresses: Option<Vec<String>>,
148 pub first_verified_creators: Option<Vec<String>>,
149 pub limit: Option<usize>,
150 pub pagination_token: Option<String>,
151}
152impl MintListRequestConfig {
153 pub fn generate_request_body(self) -> ClientResult<serde_json::Value> {
154 if self.verified_collection_addresses.is_some() && self.first_verified_creators.is_some() {
155 return single_verified_args_error();
156 }
157
158 if self.verified_collection_addresses.is_some() {
159 Ok(json!({
160 "query" : {
161 "verifiedCollectionAddresses": self.verified_collection_addresses.unwrap(),
162 },
163 "options": {
164 "limit": self.limit,
165 "paginationToken": self.pagination_token
166 }
167 }))
168 } else {
169 Ok(json!({
170 "query": {
171 "firstVerifiedCreators": self.first_verified_creators.unwrap(),
172 },
173 "options": {
174 "limit": self.limit,
175 "paginationToken": self.pagination_token
176 }
177 }))
178 }
179 }
180}
181
182#[derive(Deserialize, Debug, PartialEq)]
183#[serde(rename_all = "camelCase")]
184pub struct ActiveListingsResponse {
185 pub result: Vec<ListingResult>,
186 pub pagination_token: String,
187}
188
189#[derive(Deserialize, Debug, PartialEq)]
190#[serde(rename_all = "camelCase")]
191pub struct ListingResult {
192 pub mint: String,
193 pub name: String,
194 pub first_verified_creator: String,
195 pub verified_collection_address: String,
196 pub active_listings: Vec<ActiveListing>,
197}
198
199#[derive(Debug, Default)]
201pub struct ActiveListingsRequestConfig {
202 pub marketplaces: Vec<String>,
203 pub verified_collection_addresses: Option<Vec<String>>,
204 pub first_verified_creators: Option<Vec<String>>,
205 pub limit: Option<usize>,
206 pub pagination_token: Option<String>,
207}
208impl ActiveListingsRequestConfig {
209 pub fn generate_request_body(self) -> ClientResult<serde_json::Value> {
210 if self.verified_collection_addresses.is_some() && self.first_verified_creators.is_some() {
211 return single_verified_args_error();
212 }
213
214 if self.verified_collection_addresses.is_some() {
215 Ok(json!({
216 "query" : {
217 "marketplaces": self.marketplaces,
218 "verifiedCollectionAddresses": self.verified_collection_addresses.unwrap(),
219 },
220 "options": {
221 "limit": self.limit,
222 "paginationToken": self.pagination_token
223 }
224 }))
225 } else {
226 Ok(json!({
227 "query": {
228 "marketplaces": self.marketplaces,
229 "firstVerifiedCreators": self.first_verified_creators.unwrap(),
230 },
231 "options": {
232 "limit": self.limit,
233 "paginationToken": self.pagination_token
234 }
235 }))
236 }
237 }
238}
239
240fn single_verified_args_error<T>() -> ClientResult<T> {
241 Err(ClientError::from(ClientErrorKind::Custom(
242 "API only accepts one of first_verified_creators or verified_collection_addresses"
243 .to_string(),
244 )))
245}