use crate::fuel_core_graphql_api::ports::{ OffChainDatabase, OnChainDatabase, }; use fuel_core_storage::{ iter::{ BoxedIter, IntoBoxedIter, IterDirection, }, not_found, tables::Transactions, Result as StorageResult, StorageAsRef, }; use fuel_core_txpool::types::TxId; use fuel_core_types::{ fuel_tx::{ Receipt, Transaction, TxPointer, }, fuel_types::Address, services::txpool::TransactionStatus, }; pub trait SimpleTransactionData: Send + Sync { /// Return all receipts in the given transaction. fn receipts(&self, transaction_id: &TxId) -> StorageResult>; /// Get the transaction. fn transaction(&self, transaction_id: &TxId) -> StorageResult; } impl SimpleTransactionData for D where D: OnChainDatabase + OffChainDatabase + ?Sized, { fn transaction(&self, tx_id: &TxId) -> StorageResult { if let Some(tx) = self.storage::().get(tx_id)? { Ok(tx.into_owned()) } else if let Some(tx) = self.old_transaction(tx_id)? { Ok(tx) } else { Err(not_found!(Transactions)) } } fn receipts(&self, tx_id: &TxId) -> StorageResult> { let status = self.status(tx_id)?; let receipts = match status { TransactionStatus::Success { receipts, .. } | TransactionStatus::Failed { receipts, .. } => Some(receipts), _ => None, }; receipts.ok_or(not_found!(Transactions)) } } pub trait TransactionQueryData: Send + Sync + SimpleTransactionData { fn status(&self, tx_id: &TxId) -> StorageResult; fn owned_transactions( &self, owner: Address, start: Option, direction: IterDirection, ) -> BoxedIter>; } impl TransactionQueryData for D where D: OnChainDatabase + OffChainDatabase + ?Sized, { fn status(&self, tx_id: &TxId) -> StorageResult { self.tx_status(tx_id) } fn owned_transactions( &self, owner: Address, start: Option, direction: IterDirection, ) -> BoxedIter> { self.owned_transactions_ids(owner, start, direction) .map(|result| { result.and_then(|(tx_pointer, tx_id)| { let tx = self.transaction(&tx_id)?; Ok((tx_pointer, tx)) }) }) .into_boxed() } }