use super::{GearApi, Result};
use crate::Error;
use gsdk::{
config::Header,
ext::subxt::{
config::{Header as _, substrate::BlakeTwo256},
utils::H256,
},
gear::{self, Event},
};
type GearBlock = Header;
impl GearApi {
pub fn block_gas_limit(&self) -> Result<u64> {
Ok(self
.0
.api()
.constants()
.at(&gear::constants().gear_gas().block_gas_limit())?)
}
pub fn expected_block_time(&self) -> Result<u64> {
Ok(self
.0
.api()
.constants()
.at(&gear::constants().babe().expected_block_time())?)
}
async fn get_block_at(&self, block_hash: Option<H256>) -> Result<GearBlock> {
let hash = if let Some(hash) = block_hash {
hash
} else {
self.0
.api()
.backend()
.latest_finalized_block_ref()
.await?
.hash()
};
self.0
.api()
.backend()
.block_header(hash)
.await?
.ok_or(Error::BlockDataNotFound)
}
pub async fn last_block_hash(&self) -> Result<H256> {
Ok(self.get_block_at(None).await?.hash_with(BlakeTwo256))
}
pub async fn last_block_number(&self) -> Result<u32> {
Ok(self.get_block_at(None).await?.number())
}
pub async fn last_events(&self) -> Result<Vec<Event>> {
self.0.api().get_events_at(None).await.map_err(Into::into)
}
pub async fn block_number_at(&self, block_hash: H256) -> Result<u32> {
Ok(self.get_block_at(Some(block_hash)).await?.number())
}
pub async fn get_block_hash(&self, block_number: u32) -> Result<H256> {
self.0
.api()
.legacy()
.chain_get_block_hash(Some(block_number.into()))
.await
.map_err(gsdk::Error::from)?
.ok_or(Error::BlockHashNotFound)
}
pub async fn last_block_timestamp(&self) -> Result<u64> {
self.0
.api()
.block_timestamp(None)
.await
.map_err(|_| Error::TimestampNotFound)
}
pub async fn events_at(&self, block_hash: H256) -> Result<Vec<Event>> {
self.0
.api()
.get_events_at(block_hash)
.await
.map_err(Into::into)
}
pub async fn events_since(&self, block_hash: H256, max_depth: usize) -> Result<Vec<Event>> {
let mut block_hashes = Vec::with_capacity(max_depth);
let mut current = self.get_block_at(None).await?;
for _ in 0..max_depth {
let current_hash = current.hash_with(BlakeTwo256);
block_hashes.push(current_hash);
if current_hash == block_hash {
break;
}
current = self.get_block_at(Some(current.parent_hash)).await?;
}
if block_hashes.contains(&block_hash) {
let mut events = vec![];
for hash in block_hashes.into_iter() {
events.append(self.events_at(hash).await?.as_mut());
}
Ok(events)
} else {
Err(Error::MaxDepthReached)
}
}
pub async fn queue_processing_enabled(&self) -> Result<bool> {
self.0.api().execute_inherent().await.map_err(Into::into)
}
pub async fn queue_processing_stalled(&self) -> Result<bool> {
let mut listener = self.subscribe().await?;
let current = listener.next_block_hash().await?;
let gear_current = self.0.api().gear_block_number(Some(current)).await?;
let mut next = current;
while next == current {
next = listener.next_block_hash().await?;
}
let gear_next = self.0.api().gear_block_number(Some(next)).await?;
Ok(gear_next <= gear_current)
}
}