use crate::errors::ExecutionError;
use crate::transaction::confirm;
use crate::transaction::{ResolveCondition, Transaction, TransactionBuilder};
use web3::types::{TransactionReceipt, H256, U64};
use web3::Transport;
impl<T: Transport> TransactionBuilder<T> {
pub async fn send(mut self) -> Result<TransactionResult, ExecutionError> {
let web3 = self.web3.clone();
let resolve = self.resolve.take().unwrap_or_default();
let tx = self.build().await?;
let tx_hash = match tx {
Transaction::Request(tx) => web3.eth().send_transaction(tx).await?,
Transaction::Raw { bytes, hash } => {
let node_hash = web3.eth().send_raw_transaction(bytes).await?;
if node_hash != hash {
return Err(ExecutionError::UnexpectedTransactionHash);
}
hash
}
};
let tx_receipt = match resolve {
ResolveCondition::Pending => return Ok(TransactionResult::Hash(tx_hash)),
ResolveCondition::Confirmed(params) => {
confirm::wait_for_confirmation(&web3, tx_hash, params).await
}
}?;
match tx_receipt.status {
Some(U64([1])) => Ok(TransactionResult::Receipt(tx_receipt)),
_ => Err(ExecutionError::Failure(Box::new(tx_receipt))),
}
}
}
#[derive(Clone, Debug)]
#[allow(clippy::large_enum_variant)]
pub enum TransactionResult {
Hash(H256),
Receipt(TransactionReceipt),
}
impl TransactionResult {
pub fn is_hash(&self) -> bool {
matches!(self, TransactionResult::Hash(_))
}
pub fn hash(&self) -> H256 {
match self {
TransactionResult::Hash(hash) => *hash,
TransactionResult::Receipt(tx) => tx.transaction_hash,
}
}
pub fn is_receipt(&self) -> bool {
self.as_receipt().is_some()
}
pub fn as_receipt(&self) -> Option<&TransactionReceipt> {
match self {
TransactionResult::Receipt(ref tx) => Some(tx),
_ => None,
}
}
}