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
use anchor_client::ClientError;
use solana_account_decoder::UiAccountEncoding;
use solana_client::{pubsub_client::PubsubClient, rpc_config::RpcAccountInfoConfig};
use solana_client_helpers::Client;
use solana_sdk::{
account::Account,
clock::{Clock, Epoch, Slot, UnixTimestamp},
commitment_config::CommitmentConfig,
pubkey::Pubkey,
};
use std::{
str::FromStr,
sync::{
mpsc::{self, Receiver},
Arc,
},
thread,
};
pub fn get_time(client: &Arc<Client>) -> Result<i64, ClientError> {
let clock = fetch(client).unwrap();
Ok(clock.unix_timestamp)
}
pub fn monitor_time(url: String) -> Receiver<i64> {
let (blocktime_sender, blocktime_receiver) = mpsc::channel::<i64>();
thread::spawn(move || {
let mut latest_blocktime: i64 = 0;
let (_ws_client, clock_receiver) = PubsubClient::account_subscribe(
url.as_str(),
&address(),
Some(RpcAccountInfoConfig {
encoding: Some(UiAccountEncoding::Base64),
commitment: Some(CommitmentConfig::processed()),
data_slice: None,
}),
)
.unwrap();
for ui_account_response in clock_receiver {
let ui_account = ui_account_response.value;
let account = ui_account.decode::<Account>().unwrap();
let clock = deserialize(account.data);
let blocktime = clock.unix_timestamp;
if blocktime > latest_blocktime {
latest_blocktime = blocktime;
blocktime_sender.send(blocktime).unwrap()
}
}
});
return blocktime_receiver;
}
fn address() -> Pubkey {
Pubkey::from_str("SysvarC1ock11111111111111111111111111111111").unwrap()
}
fn fetch(client: &Arc<Client>) -> Result<Clock, ClientError> {
let data = client.get_account_data(&address())?;
Ok(deserialize(data))
}
fn deserialize(data: Vec<u8>) -> Clock {
Clock {
slot: Slot::from_le_bytes(data.as_slice()[0..8].try_into().unwrap()),
epoch_start_timestamp: UnixTimestamp::from_le_bytes(
data.as_slice()[8..16].try_into().unwrap(),
),
epoch: Epoch::from_le_bytes(data.as_slice()[16..24].try_into().unwrap()),
leader_schedule_epoch: Epoch::from_le_bytes(data.as_slice()[24..32].try_into().unwrap()),
unix_timestamp: UnixTimestamp::from_le_bytes(data.as_slice()[32..40].try_into().unwrap()),
}
}