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
#![allow(dead_code)]
#![allow(unused_imports)]
use bitcoind_request::command::{
get_best_block_hash::GetBestBlockHashCommand,
get_block::{
GetBlockCommand, GetBlockCommandResponse, GetBlockCommandTransactionResponse,
GetBlockCommandVerbosity,
},
get_block_count::{self, GetBlockCountCommand},
get_block_hash::GetBlockHashCommand,
get_block_header::GetBlockHeaderCommand,
get_block_stats::{
GetBlockStatsCommand, GetBlockStatsCommandResponse,
GetBlockStatsCommandWithAllStatsResponse, GetBlockStatsCommandWithSelectiveStatsResponse,
StatsArgumentChoices, TargetBlockArgument,
},
get_blockchain_info::GetBlockchainInfoCommand,
get_chain_tips::GetChainTipsCommand,
get_chain_tx_stats::GetChainTxStatsCommand,
get_difficulty::GetDifficultyCommand,
get_mining_info::GetMiningInfoCommand,
get_network_hash_ps::GetNetworkHashPsCommand,
get_raw_transaction::{GetRawTransactionCommand, GetRawTransactionCommandResponse, Vin},
get_tx_out::GetTxOutCommand,
get_tx_out_set_info::GetTxOutSetInfoCommand,
CallableCommand,
};
use bitcoind_request::{Blockhash, BlockhashHexEncoded};
use chrono::{DateTime, Duration, TimeZone, Utc};
use jsonrpc::simple_http::{self, SimpleHttpTransport};
use jsonrpc::Client;
use std::{env, time::SystemTimeError};
pub struct Seconds(pub i64);
pub fn get_block_height(client: &Client) -> u64 {
let block_count = GetBlockCountCommand::new().call(client);
return block_count.0;
}
pub fn get_time_since_last_block_in_seconds(client: &Client) -> i64 {
let block_count = GetBlockCountCommand::new().call(client);
let arg = TargetBlockArgument::Height(block_count.0);
let block_stats_response = GetBlockStatsCommand::new(arg).call(client);
let time_of_last_block = match block_stats_response {
GetBlockStatsCommandResponse::AllStats(response) => response.time,
GetBlockStatsCommandResponse::SelectiveStats(response) => response.time.unwrap(),
};
let current_datetime = chrono::offset::Utc::now();
let datetime_of_last_block = Utc.timestamp(time_of_last_block as i64, 0);
let difference = current_datetime.signed_duration_since(datetime_of_last_block);
difference.num_seconds()
}
pub fn get_average_block_time(client: &Client) -> u64 {
let blocks_to_calculate = 2016;
let chain_tx_stats = GetChainTxStatsCommand::new()
.set_n_blocks(2016)
.call(client);
let average_seconds_per_block = chain_tx_stats.window_interval / blocks_to_calculate;
average_seconds_per_block
}
pub fn get_total_money_supply(client: &Client) -> u64 {
let tx_out_set_info = GetTxOutSetInfoCommand::new().call(client);
tx_out_set_info.total_amount
}
pub fn get_chain_size(client: &Client) -> u64 {
let blockchain_info = GetBlockchainInfoCommand::new().call(client);
blockchain_info.size_on_disk
}
pub fn get_utxo_set_size(client: &Client) -> u64 {
let tx_out_set_info = GetTxOutSetInfoCommand::new().call(client);
tx_out_set_info.txouts
}
pub fn get_total_transactions_count(client: &Client) -> u64 {
let chain_tx_stats = GetChainTxStatsCommand::new().call(client);
chain_tx_stats.txcount
}
pub fn get_tps_for_last_30_days(client: &Client) -> f64 {
let chain_tx_stats = GetChainTxStatsCommand::new().call(client);
let seconds_in_interval = chain_tx_stats.window_interval;
let transactions_count_in_window = chain_tx_stats.window_tx_count as f64;
let elapsed_seconds_in_window = seconds_in_interval as f64;
let tps = transactions_count_in_window / elapsed_seconds_in_window;
tps
}
pub fn get_transactions_count_over_last_30_days(client: &Client) -> u64 {
let chain_tx_stats = GetChainTxStatsCommand::new().call(client);
chain_tx_stats.window_tx_count
}
pub fn get_total_fee_for_block_at_height(client: &Client, height: u64) -> u64 {
let block_stats = GetBlockStatsCommand::new(TargetBlockArgument::Height(height))
.add_selective_stats(vec![StatsArgumentChoices::TotalFee])
.call(client);
let total_fee = match block_stats {
GetBlockStatsCommandResponse::AllStats(response) => response.totalfee,
GetBlockStatsCommandResponse::SelectiveStats(response) => response.totalfee.unwrap(),
};
total_fee
}
fn get_timestamp_of_block_at_height(client: &Client, height: u64) -> u64 {
let block_stats = GetBlockStatsCommand::new(TargetBlockArgument::Height(height))
.add_selective_stats(vec![StatsArgumentChoices::Time])
.call(client);
let time = match block_stats {
GetBlockStatsCommandResponse::AllStats(response) => response.time,
GetBlockStatsCommandResponse::SelectiveStats(response) => response.time.unwrap(),
};
time
}
pub fn get_total_fee_for_24_hours(client: &Client) -> u64 {
let last_block_height = get_block_height(&client);
fn timestamp_is_from_more_than_24_hours_ago(timestamp: i64) -> bool {
let hour_window_to_calculate_for = 24;
let current_datetime = chrono::offset::Utc::now();
let window_to_cacluate_duration_in_seconds =
Duration::seconds(60 * 60 * hour_window_to_calculate_for);
let datetime_24_hours_ago = current_datetime - window_to_cacluate_duration_in_seconds;
let datetime_of_block = Utc.timestamp(timestamp as i64, 0);
datetime_of_block < datetime_24_hours_ago
}
let mut total_fee = 0;
let mut current_block_height = last_block_height;
let mut next_block_timestamp = chrono::offset::Utc::now().timestamp();
while !timestamp_is_from_more_than_24_hours_ago(next_block_timestamp) {
let fee = get_total_fee_for_block_at_height(client, current_block_height);
let time = get_timestamp_of_block_at_height(client, current_block_height);
total_fee = total_fee + fee;
current_block_height = current_block_height - 1;
next_block_timestamp = time as i64;
}
total_fee
}