Skip to content

Commit d1a83ec

Browse files
committed
add coin cache exclude
1 parent 26d45d4 commit d1a83ec

File tree

2 files changed

+75
-1
lines changed

2 files changed

+75
-1
lines changed

packages/fuels-accounts/src/coin_cache.rs

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,15 @@ impl CoinsCache {
4141
}
4242
}
4343

44+
pub fn get_all_active(&mut self) -> Vec<CoinTypeId> {
45+
self.remove_all_expired_entries();
46+
47+
self.items
48+
.iter()
49+
.flat_map(|(_key, entry)| entry.iter().map(|cci| cci.id.clone()))
50+
.collect()
51+
}
52+
4453
pub fn get_active(&mut self, key: &CoinCacheKey) -> HashSet<CoinTypeId> {
4554
self.remove_expired_entries(key);
4655

@@ -76,6 +85,12 @@ impl CoinsCache {
7685
entry.retain(|item| item.is_valid(self.ttl));
7786
}
7887
}
88+
89+
fn remove_all_expired_entries(&mut self) {
90+
for (_key, entry) in self.items.iter_mut() {
91+
entry.retain(|item| item.is_valid(self.ttl));
92+
}
93+
}
7994
}
8095

8196
#[derive(Eq, Debug, Clone)]
@@ -175,8 +190,42 @@ mod tests {
175190
assert!(active_coins.is_empty());
176191
}
177192

193+
#[tokio::test]
194+
async fn get_all_active() {
195+
let mut cache = CoinsCache::new(Duration::from_secs(10));
196+
197+
let key = CoinCacheKey::default();
198+
let (item1, _) = get_items();
199+
let items = HashMap::from([(key.clone(), vec![item1.clone()])]);
200+
201+
cache.insert_multiple(items);
202+
203+
// Advance time by more than the cache's TTL
204+
tokio::time::pause();
205+
tokio::time::advance(Duration::from_secs(12)).await;
206+
207+
let (_, item2) = get_items();
208+
let items = HashMap::from([(key.clone(), vec![item2.clone()])]);
209+
cache.insert_multiple(items);
210+
211+
let active_coins = cache.get_all_active();
212+
213+
assert_eq!(active_coins.len(), 1);
214+
assert!(!active_coins.contains(&item1));
215+
assert!(active_coins.contains(&item2));
216+
}
217+
218+
#[test]
219+
fn get_all_active_no_items() {
220+
let mut cache = CoinsCache::new(Duration::from_secs(60));
221+
222+
let active_coins = cache.get_all_active();
223+
224+
assert!(active_coins.is_empty());
225+
}
226+
178227
#[test]
179-
fn test_remove_items() {
228+
fn remove_items() {
180229
let mut cache = CoinsCache::new(Duration::from_secs(60));
181230

182231
let key: CoinCacheKey = Default::default();

packages/fuels-accounts/src/provider.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ use fuels_core::{
4747
},
4848
};
4949
use futures::StreamExt;
50+
#[cfg(feature = "coin-cache")]
51+
use itertools::{Either, Itertools};
5052
pub use retry_util::{Backoff, RetryConfig};
5153
pub use supported_fuel_core_version::SUPPORTED_FUEL_CORE_VERSION;
5254
use tai64::Tai64;
@@ -399,6 +401,29 @@ impl Provider {
399401
estimate_predicates: bool,
400402
reserve_gas: Option<u64>,
401403
) -> Result<AssembleTransactionResult> {
404+
#[cfg(feature = "coin-cache")]
405+
let (cache_utxos, cache_nonces) = self
406+
.coins_cache
407+
.lock()
408+
.await
409+
.get_all_active()
410+
.into_iter()
411+
.partition_map(|coin_type_id| match coin_type_id {
412+
CoinTypeId::UtxoId(utxo_id) => Either::Left(utxo_id),
413+
CoinTypeId::Nonce(nonce) => Either::Right(nonce),
414+
});
415+
416+
#[cfg(feature = "coin-cache")]
417+
let exclude = match exclude {
418+
Some((mut utxos, mut nonces)) => {
419+
utxos.extend(cache_utxos);
420+
nonces.extend(cache_nonces);
421+
422+
Some((utxos, nonces))
423+
}
424+
None => Some((cache_utxos, cache_nonces)),
425+
};
426+
402427
Ok(self
403428
.uncached_client()
404429
.assemble_tx(

0 commit comments

Comments
 (0)