use subxt::{
client::OnlineClientT,
error::TransactionError,
tx::{TxInBlock, TxStatus},
};
use crate::debug;
#[async_trait::async_trait]
pub trait TxProgressExt<T: subxt::Config, C> {
async fn wait_for_in_block(mut self) -> Result<TxInBlock<T, C>, subxt::Error>;
async fn wait_for_in_block_success(
self,
) -> Result<subxt::blocks::ExtrinsicEvents<T>, subxt::Error>;
}
#[async_trait::async_trait]
impl<T: subxt::Config, C: OnlineClientT<T>> TxProgressExt<T, C> for subxt::tx::TxProgress<T, C> {
async fn wait_for_in_block(mut self) -> Result<TxInBlock<T, C>, subxt::Error> {
while let Some(status) = self.next().await {
match status? {
TxStatus::InBestBlock(s) => return Ok(s),
TxStatus::Error { message } => return Err(TransactionError::Error(message).into()),
TxStatus::Invalid { message } => {
return Err(TransactionError::Invalid(message).into())
}
TxStatus::Dropped { message } => {
return Err(TransactionError::Dropped(message).into())
}
_ => continue,
}
}
Err(subxt::error::RpcError::SubscriptionDropped.into())
}
async fn wait_for_in_block_success(
self,
) -> Result<subxt::blocks::ExtrinsicEvents<T>, subxt::Error> {
let evs = self.wait_for_in_block().await?.wait_for_success().await?;
Ok(evs)
}
}
#[tracing::instrument(skip_all)]
pub async fn send<T, S, X>(
client: &subxt::OnlineClient<T>,
signer: &S,
xt: &X,
) -> Result<subxt::blocks::ExtrinsicEvents<T>, subxt::Error>
where
T: subxt::Config,
S: subxt::tx::Signer<T>,
X: subxt::tx::Payload,
<T::ExtrinsicParams as subxt::config::ExtrinsicParams<T>>::Params: Default,
{
if let Some(details) = xt.validation_details() {
debug!("Calling {}.{}", details.pallet_name, details.call_name);
}
debug!("Waiting for the transaction to be included in a finalized block");
let progress = client
.tx()
.sign_and_submit_then_watch_default(xt, signer)
.await?;
#[cfg(not(test))]
{
debug!("Waiting for finalized success ...");
let result = progress.wait_for_finalized_success().await?;
debug!(
"Transaction with hash: {:?} has been finalized",
result.extrinsic_hash()
);
Ok(result)
}
#[cfg(test)]
{
debug!("Waiting for in block success ...");
let result = progress.wait_for_in_block_success().await?;
debug!(
"Transaction with hash: {:?} has been included in a block",
result.extrinsic_hash()
);
Ok(result)
}
}