gadget_sdk/clients/tangle/
runtime.rsuse std::sync::Arc;
use std::time::Duration;
use crate::clients::Client;
use crate::error::Error;
use crate::mutex_ext::TokioMutexExt;
use subxt::blocks::{Block, BlockRef};
use subxt::events::Events;
use subxt::utils::AccountId32;
use subxt::{self, PolkadotConfig};
pub type TangleConfig = PolkadotConfig;
pub type TangleClient = subxt::OnlineClient<TangleConfig>;
type TangleBlock = Block<TangleConfig, TangleClient>;
type TangleBlockStream = subxt::backend::StreamOfResults<TangleBlock>;
#[derive(Clone, Debug)]
pub struct TangleEvent {
pub number: u64,
pub hash: [u8; 32],
pub events: Events<TangleConfig>,
}
#[derive(Clone, Debug)]
pub struct TangleRuntimeClient {
client: TangleClient,
finality_notification_stream: Arc<tokio::sync::Mutex<Option<TangleBlockStream>>>,
latest_finality_notification: Arc<tokio::sync::Mutex<Option<TangleEvent>>>,
account_id: AccountId32,
}
impl TangleRuntimeClient {
pub async fn from_url<U: AsRef<str>>(url: U, account_id: AccountId32) -> Result<Self, Error> {
let client = TangleClient::from_url(url).await?;
Ok(Self::new(client, account_id))
}
pub fn new(client: TangleClient, account_id: AccountId32) -> Self {
Self {
client,
finality_notification_stream: Arc::new(tokio::sync::Mutex::new(None)),
latest_finality_notification: Arc::new(tokio::sync::Mutex::new(None)),
account_id,
}
}
pub fn client(&self) -> TangleClient {
self.client.clone()
}
async fn initialize(&self) -> Result<(), Error> {
let finality_notification_stream = self.client.blocks().subscribe_finalized().await?;
*self.finality_notification_stream.lock().await = Some(finality_notification_stream);
Ok(())
}
pub fn runtime_api(
&self,
at: [u8; 32],
) -> subxt::runtime_api::RuntimeApi<TangleConfig, TangleClient> {
let block_ref = BlockRef::from_hash(sp_core::hash::H256::from_slice(&at));
self.client.runtime_api().at(block_ref)
}
pub fn account_id(&self) -> &AccountId32 {
&self.account_id
}
}
#[async_trait::async_trait]
impl Client<TangleEvent> for TangleRuntimeClient {
async fn next_event(&self) -> Option<TangleEvent> {
let mut lock = self
.finality_notification_stream
.try_lock_timeout(Duration::from_millis(500))
.await
.ok()?;
match lock.as_mut() {
Some(stream) => {
let block = stream.next().await?.ok()?;
let events = block.events().await.ok()?;
let notification = TangleEvent {
number: block.number().into(),
hash: block.hash().into(),
events,
};
let mut lock2 = self
.latest_finality_notification
.lock_timeout(Duration::from_millis(500))
.await;
*lock2 = Some(notification.clone());
Some(notification)
}
None => {
drop(lock);
self.initialize().await.ok()?;
self.next_event().await
}
}
}
async fn latest_event(&self) -> Option<TangleEvent> {
let lock = self
.latest_finality_notification
.try_lock_timeout(Duration::from_millis(500))
.await
.ok()?;
match &*lock {
Some(notification) => Some(notification.clone()),
None => {
drop(lock);
self.next_event().await
}
}
}
}