bscscan 0.5.1

BSC (Binance Smart Chain) non-async API in Rust
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
use crate::prelude::*;
use crate::deserialize::{de_string_to_numeric,
                         de_string_to_U256,
                         de_string_to_bool,
                         de_constructor_arguments_string_to_vec_string};

/// Type of bscscan.com's API request
pub enum BSCApiResponseType {
    NormalTransaction,
    InternalTransaction
}

/// Structure that holds information from API response from bscscan.com
/// of normal transaction
#[derive(Debug, Clone, serde::Deserialize)]
#[serde(rename_all = "camelCase")]  // source JSON response is in camelCase except
                                    // 'txreceipt_status' which we explicitly `rename` it.
pub struct BSCNormalTransactionResponseSuccessVariantResult {
    #[serde(deserialize_with = "de_string_to_numeric")]
    pub block_number: u64,

    #[serde(deserialize_with = "de_string_to_numeric")]
    #[serde(rename = "timeStamp")]
    pub timestamp: u64,

    pub hash: String,

    #[serde(deserialize_with = "de_string_to_numeric")]
    pub nonce: u32,

    #[serde(deserialize_with = "de_string_to_numeric")]
    pub transaction_index: u64,

    pub from: String,

    pub to: String,

    #[serde(deserialize_with = "de_string_to_U256")]
    pub value: U256,

    #[serde(deserialize_with = "de_string_to_numeric")]
    pub gas: u64,

    #[serde(deserialize_with = "de_string_to_numeric")]
    pub gas_price: u64,

    #[serde(deserialize_with = "de_string_to_bool")]
    pub is_error: bool,

    #[serde(rename = "txreceipt_status")]
    pub txreceipt_status: String,

    pub input: String,

    pub contract_address: String,

    #[serde(deserialize_with = "de_string_to_numeric")]
    pub cumulative_gas_used: u64,

    #[serde(deserialize_with = "de_string_to_numeric")]
    pub gas_used: u64,

    #[serde(deserialize_with = "de_string_to_numeric")]
    pub confirmations: u32,
}

/// Structure that holds information from API response from bscscan.com
/// of internal transaction
#[derive(Debug, Clone, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct BSCInternalTransactionResponseSuccessVariantResult {
    #[serde(deserialize_with = "de_string_to_numeric")]
    pub block_number: u64,

    #[serde(deserialize_with = "de_string_to_numeric")]
    #[serde(rename = "timeStamp")]
    pub timestamp: u64,

    pub hash: String,

    pub from: String,

    pub to: String,

    #[serde(deserialize_with = "de_string_to_U256")]
    pub value: U256,

    pub contract_address: String,

    pub input: String,

    // this is how to escape reserved keyword to use as identifier
    pub r#type: Option<String>,

    #[serde(deserialize_with = "de_string_to_numeric")]
    pub gas: u64,

    #[serde(deserialize_with = "de_string_to_numeric")]
    pub gas_used: u64,

    pub trace_id: Option<String>,

    #[serde(deserialize_with = "de_string_to_bool")]
    pub is_error: bool,

    pub err_code: Option<String>
}

/// Structure that holds account balance
#[derive(Debug, serde::Deserialize)]
pub struct BSCBnbBalanceResponse {
    pub status: String,
    pub message: String,
    pub result: GenericBSCBnbBalanceResponseResult,
}

/// Generic result for `result` field of `BSCBnbBalanceResponse`.
#[derive(Debug, serde::Deserialize)]
#[serde(untagged)]
pub enum GenericBSCBnbBalanceResponseResult {
    #[serde(deserialize_with = "de_string_to_U256")]
    Success(U256),
    Failed(String),
}

/// Structure that holds balance for multiple addresses query via API
#[derive(Debug, serde::Deserialize)]
pub struct BSCBnbBalanceMultiResponse {
    pub status: String,
    pub message: String,
    pub result: GenericBSCBnbBalanceMultiResponseResult,
}

/// Generic result for `result` field of `BSCBnbBalanceMultiResponse`.
#[derive(Debug, serde::Deserialize)]
#[serde(untagged)]
pub enum GenericBSCBnbBalanceMultiResponseResult {
    Success(Vec<BSCBnbBalanceMulti>),
    Failed(String),
}

/// Structure which hold individual record of Getting BNB balance for multiple
/// addresses API.
#[derive(Debug, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct BSCBnbBalanceMulti {
    /// Account address
    pub account: String,

    /// Balance in Wei
    #[serde(deserialize_with = "de_string_to_U256")]
    pub balance: U256,
}

/// Generic result as returned from `result` field from API response from bscscan.com
#[derive(Debug, Clone, serde::Deserialize)]
#[serde(untagged)]
pub enum GenericBSCTransactionResponseResult<T> {
    Success(Vec::<T>),
    Failed(Option<String>)
}

/// Common structure which has shared fields for API response from bscscan.com.
#[derive(Debug, serde::Deserialize)]
pub struct BSCTransactionResponse<T> {
    pub status: String,
    pub message: String,
    pub result: GenericBSCTransactionResponseResult::<T>,
}

/// Trait to satisfy implementing generic handling function for multiple API response
/// within one function.
pub trait CompatibleTransactionResponse<T> {
    fn status(&self) -> &str;
    fn message(&self) -> &str;
    fn result(&self) -> GenericBSCTransactionResponseResult::<T>;
}

/// Implementation of `CompatibleTransactionResponse` for
/// `BSCNormalTransactionResponseSuccessVariantResult`.
impl CompatibleTransactionResponse<BSCNormalTransactionResponseSuccessVariantResult> for BSCTransactionResponse<BSCNormalTransactionResponseSuccessVariantResult>
{
    fn status(&self) -> &str {
        &self.status
    }

    fn message(&self) -> &str {
        &self.message
    }

    fn result(&self) -> GenericBSCTransactionResponseResult::<BSCNormalTransactionResponseSuccessVariantResult> {
        self.result.clone()
    }
}

/// Implementation of `CompatibleTransactionResponse` for
/// `BSCInternalTransactionResponseSuccessVariantResult`.
impl CompatibleTransactionResponse<BSCInternalTransactionResponseSuccessVariantResult> for BSCTransactionResponse<BSCInternalTransactionResponseSuccessVariantResult>
{
    fn status(&self) -> &str {
        &self.status
    }

    fn message(&self) -> &str {
        &self.message
    }

    fn result(&self) -> GenericBSCTransactionResponseResult::<BSCInternalTransactionResponseSuccessVariantResult> {
        self.result.clone()
    }
}

/// Structure holding returne API response of `result` field for BEP-20 tokens
/// transfer events
#[derive(Debug, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct BSCBep20TokenTransferEventResponseSuccessVariantResult {
    #[serde(deserialize_with = "de_string_to_numeric")]
    pub block_number: u64,

    #[serde(deserialize_with = "de_string_to_numeric")]
    #[serde(rename = "timeStamp")]
    pub timestamp: u64,

    pub hash: String,

    #[serde(deserialize_with = "de_string_to_numeric")]
    pub nonce: u32,

    pub block_hash: String,

    pub from: String,

    pub contract_address: String,

    pub to: String,

    #[serde(deserialize_with = "de_string_to_U256")]
    pub value: U256,

    pub token_name: String,

    pub token_symbol: String,

    #[serde(deserialize_with = "de_string_to_numeric")]
    pub token_decimal: u8,

    #[serde(deserialize_with = "de_string_to_numeric")]
    pub transaction_index: u64,

    #[serde(deserialize_with = "de_string_to_numeric")]
    pub gas: u64,

    #[serde(deserialize_with = "de_string_to_numeric")]
    pub gas_price: u64,

    #[serde(deserialize_with = "de_string_to_numeric")]
    pub gas_used: u64,

    #[serde(deserialize_with = "de_string_to_numeric")]
    pub cumulative_gas_used: u64,

    pub input: String,

    #[serde(deserialize_with = "de_string_to_numeric")]
    pub confirmations: u32,
}

/// Structure holding information returned from API response for BEP-20 token
/// transfer event.
#[derive(Debug, serde::Deserialize)]
pub struct BSCBep20TokenTransferEventResponse {
    pub status: String,
    pub message: String,
    pub result: GenericBSCBep20TokenTransferEventResponseResult,
}

/// Structure holding variant of either success or failed returned for `result`
/// field of API response for BEP-20 token transfer event.
#[derive(Debug, serde::Deserialize)]
#[serde(untagged)]
pub enum GenericBSCBep20TokenTransferEventResponseResult {
    Success(Vec::<BSCBep20TokenTransferEventResponseSuccessVariantResult>),
    Failed(String)
}

/// Structure holding response back for Stats API's Get BNB last price
#[derive(Debug, serde::Deserialize)]
pub struct BSCBnbLastPriceResponse {
    pub status: String,
    pub message: String,
    pub result: BSCBnbLastPriceResult,
}

/// Sturcture holding variant response for field 'result' of Stats API's
/// Get BNB last price.
#[derive(Debug, serde::Deserialize)]
#[serde(untagged)]
pub enum BSCBnbLastPriceResult {
    Success(BSCBnbLastPrice),
    Failed(String)
}

/// Actual structure holding a success response for Stats API's
/// Get BNB last price.
#[derive(Debug, serde::Deserialize)]
pub struct BSCBnbLastPrice {
    #[serde(deserialize_with = "de_string_to_numeric")]
    pub ethbtc: f64,

    #[serde(deserialize_with = "de_string_to_numeric")]
    pub ethbtc_timestamp: u64,

    #[serde(deserialize_with = "de_string_to_numeric")]
    pub ethusd: f64,

    #[serde(deserialize_with = "de_string_to_numeric")]
    pub ethusd_timestamp: u64,
}

/// Contract ABI
#[derive(Debug, serde::Deserialize)]
pub struct BSCContractABIResponse {
    pub status: String,
    pub message: String,
    pub result: String,
}

/// Actual structure holding individual contract ABI.
#[derive(Debug, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct BSCContractABIItem {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub anonymous: Option<bool>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub inputs: Option<Vec<BSCContractABIItemType>>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub name: Option<String>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub outputs: Option<Vec<BSCContractABIItemType>>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub state_mutability: Option<String>,

    pub r#type: String
}

/// Type definition for each ABI item
#[derive(Debug, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub(crate) struct BSCContractABIItemType {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub indexed: Option<bool>,
    pub internal_type: String,
    pub name: String,
    pub r#type: String,
}

/// Contract source code response
#[derive(Debug, serde::Deserialize)]
pub struct BSCContractSourceCodeResponse {
    pub status: String,
    pub message: String,
    pub result: BSCContractSourceCodeResult,
}

/// Structure holding variant response fro field `reuslt` of Contracts's
/// getting contract code API.
#[derive(Debug, serde::Deserialize)]
#[serde(untagged)]
pub enum BSCContractSourceCodeResult {
    Success(Vec<BSCContractSourceCode>),

    /// This also includes the case of querying for non-verified source code.
    /// Although it is not error / failed case per-se as its `abi` field will
    /// contain exactly "Contract source code not verified". But it is included
    /// as failed case as well.
    Failed(String),
}

/// Actual structure holding contract's verified source code
/// If such contract doesn't verify source code, then most fields will be empty.
#[derive(Debug, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct BSCContractSourceCode {
    /// Actual smart contract source code
    #[serde(rename = "SourceCode")]
    pub source_code: String,

    /// Contract ABI
    #[serde(rename = "ABI")]
    pub abi: String,

    /// Contract name
    #[serde(rename = "ContractName")]
    pub contract_name: String,

    /// Compiler version
    #[serde(rename = "CompilerVersion")]
    pub compiler_version: String,

    /// Whether or not optimization has been applied
    #[serde(deserialize_with = "de_string_to_bool")]
    #[serde(rename = "OptimizationUsed")]
    pub optimization_used: bool,

    /// Number of runs as part of optimization
    #[serde(deserialize_with = "de_string_to_numeric")]
    #[serde(rename = "Runs")]
    pub runs: u32,

    /// Constructor's arguments
    #[serde(deserialize_with = "de_constructor_arguments_string_to_vec_string")]
    #[serde(rename = "ConstructorArguments")]
    pub constructor_arguments: Vec<String>,

    /// EVM version
    #[serde(rename = "EVMVersion")]
    pub evm_version: String,

    /// Library used by this constract
    /// FIXME: For now, returned as a whole as string, we need to find an example of
    /// contract which contains non-empty of this field.
    #[serde(rename = "Library")]
    pub library: String,

    /// License type
    #[serde(rename = "LicenseType")]
    pub license_type: String,

    /// Whether or not this contract is the proxy, if so then `implementation`
    /// field contains the actual implementation address.
    #[serde(deserialize_with = "de_string_to_bool")]
    #[serde(rename = "Proxy")]
    pub proxy: bool,

    /// Contract address that is the implementation for this contract as it is
    /// acting as a proxy.
    #[serde(rename = "Implementation")]
    pub implementation: String,

    /// URL to swarm source
    #[serde(rename = "SwarmSource")]
    pub swarm_source: String,
}