use crate::fuel_core_graphql_api::database::ReadView;
use fuel_core_storage::{
Error as StorageError,
Result as StorageResult,
StorageAsRef,
iter::IterDirection,
not_found,
tables::Coins,
};
use fuel_core_types::{
entities::coins::coin::Coin,
fuel_tx::UtxoId,
fuel_types::Address,
};
use futures::{
Stream,
StreamExt,
TryStreamExt,
};
impl ReadView {
pub fn coin(&self, utxo_id: UtxoId) -> StorageResult<Coin> {
let coin = self
.on_chain
.as_ref()
.storage::<Coins>()
.get(&utxo_id)?
.ok_or(not_found!(Coins))?
.into_owned();
Ok(coin.uncompress(utxo_id))
}
pub async fn coins(
&self,
utxo_ids: Vec<UtxoId>,
) -> impl Iterator<Item = StorageResult<Coin>> + '_ {
let coins = utxo_ids.into_iter().map(|id| self.coin(id));
tokio::task::yield_now().await;
coins
}
pub fn owned_coins(
&self,
owner: &Address,
start_coin: Option<UtxoId>,
direction: IterDirection,
) -> impl Stream<Item = StorageResult<Coin>> + '_ + use<'_> {
self.owned_coins_ids(owner, start_coin, direction)
.chunks(self.batch_size)
.map(|chunk| {
use itertools::Itertools;
let chunk = chunk.into_iter().try_collect::<_, Vec<_>, _>()?;
Ok::<_, StorageError>(chunk)
})
.try_filter_map(move |chunk| async move {
let chunk = self.coins(chunk).await;
Ok(Some(futures::stream::iter(chunk)))
})
.try_flatten()
}
}