use crate::{CodeInfo, Error};
use codec::{Compact, Decode};
use futures::StreamExt;
use jam_program_blob_common::{ConventionalMetadata as Metadata, CrateInfo};
use jam_std_common::{Node, NodeError, NodeExt as _, Service, SyncStatus};
use jam_types::{HeaderHash, ServiceId};
use std::future::Future;
pub trait NodeExt: Node {
fn query_service(
&self,
head: HeaderHash,
id: ServiceId,
) -> impl Future<Output = Result<(Service, CodeInfo<CrateInfo>), anyhow::Error>> + Send {
async move {
use CodeInfo::*;
let info = self.service_data(head, id).await?.ok_or(Error::ServiceNotFound)?;
let maybe_code = self.service_preimage(head, id, info.code_hash.0).await?;
let meta = match maybe_code {
None => CodeNotProvided(info.code_hash.0),
Some(code) =>
match <(Compact<u32>, Metadata)>::decode(&mut &code[..]).ok().map(|x| x.1) {
None => Undefined(info.code_hash.0),
Some(Metadata::Info(crate_info)) => Known(crate_info),
},
};
Ok((info, meta))
}
}
fn wait_for_sync(&self) -> impl Future<Output = Result<(), anyhow::Error>> + Send {
async move {
let mut sync_state = self.subscribe_sync_status().await?;
loop {
let status = sync_state.next().await;
match status {
Some(Ok(SyncStatus::Completed)) => break,
Some(Ok(_)) => continue,
Some(Err(e)) => return Err(e.into()),
None => break,
}
}
let mut final_block = self.subscribe_finalized_block().await?;
loop {
let status = final_block.next().await;
match status {
Some(Ok(block)) if block.slot > 0 => {
match self.parent(block.header_hash).await {
Ok(parent) => {
if parent.slot > 0 {
break;
}
eprintln!("Waiting for two non-genesis blocks to be finalized...");
},
Err(NodeError::BlockUnavailable(_)) => {
eprintln!("Waiting for two non-genesis blocks to be finalized and available...");
},
Err(err) => return Err(err.into()),
}
},
Some(Ok(_)) => {
eprintln!("Waiting for two non-genesis blocks to be finalized...");
},
Some(Err(e)) => return Err(e.into()),
None => break,
}
}
Ok(())
}
}
}
impl<T: Node + ?Sized> NodeExt for T {}