mirror of
https://github.com/serai-dex/serai.git
synced 2024-12-23 12:09:37 +00:00
Support extracting timestamps from blocks
This commit is contained in:
parent
92ad689c7e
commit
fa2cf03e61
2 changed files with 69 additions and 4 deletions
|
@ -1,6 +1,6 @@
|
|||
use thiserror::Error;
|
||||
|
||||
use scale::{Encode, Decode};
|
||||
use scale::{Encode, Decode, Compact};
|
||||
mod scale_value;
|
||||
pub(crate) use scale_value::{Value, Composite, scale_value, scale_composite};
|
||||
|
||||
|
@ -59,6 +59,14 @@ impl SubxtConfig for SeraiConfig {
|
|||
#[derive(Debug)]
|
||||
pub struct Block(ChainBlock<SeraiConfig>);
|
||||
impl Block {
|
||||
fn new(block: ChainBlock<SeraiConfig>) -> Result<Block, SeraiError> {
|
||||
for extrinsic in &block.extrinsics {
|
||||
if extrinsic.0.len() < 3 {
|
||||
Err(SeraiError::InvalidNode)?;
|
||||
}
|
||||
}
|
||||
Ok(Block(block))
|
||||
}
|
||||
pub fn hash(&self) -> [u8; 32] {
|
||||
self.0.header.hash().into()
|
||||
}
|
||||
|
@ -66,6 +74,32 @@ impl Block {
|
|||
self.0.header.number
|
||||
}
|
||||
|
||||
/// Returns the time of this block, set by its producer, as a unix timestamp.
|
||||
pub fn time(&self) -> Result<u64, SeraiError> {
|
||||
for extrinsic in &self.0.extrinsics {
|
||||
// Inherent/unsigned
|
||||
let inherent = (extrinsic.0[0] >> 7) == 0;
|
||||
|
||||
// To timestamp pallet
|
||||
use serai_runtime::Timestamp;
|
||||
let timestamp =
|
||||
extrinsic.0[1] == u8::try_from(PalletInfo::index::<Timestamp>().unwrap()).unwrap();
|
||||
|
||||
// set call
|
||||
let set = extrinsic.0[2] == 0;
|
||||
|
||||
if inherent && timestamp && set {
|
||||
if extrinsic.0.len() < 4 {
|
||||
Err(SeraiError::InvalidNode)?;
|
||||
}
|
||||
return Ok(
|
||||
Compact::<u64>::decode(&mut &extrinsic.0[3 ..]).map_err(|_| SeraiError::InvalidNode)?.0,
|
||||
);
|
||||
}
|
||||
}
|
||||
Err(SeraiError::InvalidNode)
|
||||
}
|
||||
|
||||
pub fn header(&self) -> &Header {
|
||||
&self.0.header
|
||||
}
|
||||
|
@ -146,7 +180,7 @@ impl Serai {
|
|||
}
|
||||
|
||||
pub async fn get_latest_block(&self) -> Result<Block, SeraiError> {
|
||||
Ok(Block(
|
||||
Block::new(
|
||||
self
|
||||
.0
|
||||
.rpc()
|
||||
|
@ -155,7 +189,7 @@ impl Serai {
|
|||
.map_err(SeraiError::RpcError)?
|
||||
.ok_or(SeraiError::InvalidNode)?
|
||||
.block,
|
||||
))
|
||||
)
|
||||
}
|
||||
|
||||
// There is no provided method for this
|
||||
|
@ -207,7 +241,7 @@ impl Serai {
|
|||
return Ok(None);
|
||||
}
|
||||
|
||||
Ok(Some(Block(res.block)))
|
||||
Ok(Some(Block::new(res.block)?))
|
||||
}
|
||||
|
||||
// Ideally, this would be get_block_hash, not get_block_by_number
|
||||
|
|
31
substrate/client/tests/time.rs
Normal file
31
substrate/client/tests/time.rs
Normal file
|
@ -0,0 +1,31 @@
|
|||
use std::time::{Duration, SystemTime};
|
||||
|
||||
use tokio::time::sleep;
|
||||
|
||||
use serai_client::Serai;
|
||||
|
||||
mod common;
|
||||
use common::serai;
|
||||
|
||||
serai_test!(
|
||||
async fn time() {
|
||||
let serai = serai().await;
|
||||
|
||||
let mut number = serai.get_latest_block().await.unwrap().number();
|
||||
let mut done = 0;
|
||||
while done < 3 {
|
||||
// Wait for the next block
|
||||
let block = serai.get_latest_block().await.unwrap();
|
||||
if block.number() == number {
|
||||
sleep(Duration::from_secs(1)).await;
|
||||
continue;
|
||||
}
|
||||
number = block.number();
|
||||
|
||||
// Make sure the time we extract from the block is within 5 seconds of now
|
||||
let now = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_secs();
|
||||
assert!(now.saturating_sub(block.time().unwrap()) < 5);
|
||||
done += 1;
|
||||
}
|
||||
}
|
||||
);
|
Loading…
Reference in a new issue