jam_tooling/
node_ext.rs

1use crate::{CodeInfo, Error};
2use codec::{Compact, Decode};
3use futures::StreamExt;
4use jam_program_blob_common::{ConventionalMetadata as Metadata, CrateInfo};
5use jam_std_common::{Node, NodeError, NodeExt as _, Service, SyncStatus};
6use jam_types::{HeaderHash, ServiceId};
7use std::future::Future;
8
9pub trait NodeExt: Node {
10	fn query_service(
11		&self,
12		head: HeaderHash,
13		id: ServiceId,
14	) -> impl Future<Output = Result<(Service, CodeInfo<CrateInfo>), anyhow::Error>> + Send {
15		async move {
16			use CodeInfo::*;
17			let info = self.service_data(head, id).await?.ok_or(Error::ServiceNotFound)?;
18			let maybe_code = self.service_preimage(head, id, info.code_hash.0).await?;
19			let meta = match maybe_code {
20				None => CodeNotProvided(info.code_hash.0),
21				Some(code) =>
22					match <(Compact<u32>, Metadata)>::decode(&mut &code[..]).ok().map(|x| x.1) {
23						None => Undefined(info.code_hash.0),
24						Some(Metadata::Info(crate_info)) => Known(crate_info),
25					},
26			};
27			Ok((info, meta))
28		}
29	}
30
31	fn wait_for_sync(&self) -> impl Future<Output = Result<(), anyhow::Error>> + Send {
32		async move {
33			let mut sync_state = self.subscribe_sync_status().await?;
34			loop {
35				let status = sync_state.next().await;
36				match status {
37					Some(Ok(SyncStatus::Completed)) => break,
38					Some(Ok(_)) => continue,
39					Some(Err(e)) => return Err(e.into()),
40					None => break,
41				}
42			}
43			// Wait for any non-genesis block to be finalized
44			let mut final_block = self.subscribe_finalized_block().await?;
45			loop {
46				let status = final_block.next().await;
47				match status {
48					Some(Ok(block)) if block.slot > 0 => {
49						match self.parent(block.header_hash).await {
50							Ok(parent) => {
51								if parent.slot > 0 {
52									// Break only if the parent of the finalized block is
53									// non-genesis.
54									break;
55								}
56								eprintln!("Waiting for two non-genesis blocks to be finalized...");
57							},
58							Err(NodeError::BlockUnavailable(_)) => {
59								// Just wait for another block
60								eprintln!("Waiting for two non-genesis blocks to be finalized and available...");
61							},
62							Err(err) => return Err(err.into()),
63						}
64					},
65					Some(Ok(_)) => {
66						eprintln!("Waiting for two non-genesis blocks to be finalized...");
67					},
68					Some(Err(e)) => return Err(e.into()),
69					None => break,
70				}
71			}
72			Ok(())
73		}
74	}
75}
76
77impl<T: Node + ?Sized> NodeExt for T {}