From 635d57d5599f649c0afd4ebce64c025d0a75624f Mon Sep 17 00:00:00 2001 From: hal3e Date: Tue, 14 Jan 2025 12:39:53 +0100 Subject: [PATCH 1/2] feat: use pagination for requests --- packages/fuels-accounts/src/provider.rs | 138 ++++++++++++++---------- 1 file changed, 80 insertions(+), 58 deletions(-) diff --git a/packages/fuels-accounts/src/provider.rs b/packages/fuels-accounts/src/provider.rs index 707a0f795..eacf01334 100644 --- a/packages/fuels-accounts/src/provider.rs +++ b/packages/fuels-accounts/src/provider.rs @@ -56,6 +56,8 @@ use tokio::sync::Mutex; use crate::coin_cache::CoinsCache; use crate::provider::retryable_client::RetryableClient; +const NUM_RESULTS_PER_REQUEST: i32 = 100; + #[derive(Debug, Clone, PartialEq)] // ANCHOR: transaction_cost pub struct TransactionCost { @@ -414,28 +416,28 @@ impl Provider { /// Gets all unspent coins owned by address `from`, with asset ID `asset_id`. pub async fn get_coins(&self, from: &Bech32Address, asset_id: AssetId) -> Result> { let mut coins: Vec = vec![]; - let mut cursor = None; loop { - let res = self + let response = self .uncached_client() .coins( &from.into(), Some(&asset_id), PaginationRequest { cursor: cursor.clone(), - results: 100, + results: NUM_RESULTS_PER_REQUEST, direction: PageDirection::Forward, }, ) .await?; - if res.results.is_empty() { + if response.results.is_empty() { break; } - coins.extend(res.results.into_iter().map(Into::into)); - cursor = res.cursor; + + coins.extend(response.results.into_iter().map(Into::into)); + cursor = response.cursor; } Ok(coins) @@ -550,28 +552,39 @@ impl Provider { /// getting the coins because we are only returning the numbers (the sum of UTXOs coins amount /// for each asset id) and not the UTXOs coins themselves pub async fn get_balances(&self, address: &Bech32Address) -> Result> { - // We don't paginate results because there are likely at most ~100 different assets in one - // wallet - let pagination = PaginationRequest { - cursor: None, - results: 9999, - direction: PageDirection::Forward, - }; - let balances_vec = self + let mut balances = HashMap::new(); + // let mut cursor = None; + let cursor = None; + + // loop { //TODO: BLOCKED: pagination is not supported in rocks_db + // do not merge PR until the pagination is enabled + let response = self .uncached_client() - .balances(&address.into(), pagination) - .await? - .results; - let balances = balances_vec - .into_iter() - .map( - |Balance { - owner: _, - amount, - asset_id, - }| (asset_id.to_string(), amount), + .balances( + &address.into(), + PaginationRequest { + cursor: cursor.clone(), + // results: NUM_RESULTS_PER_REQUEST, + results: 9999, + direction: PageDirection::Forward, + }, ) - .collect(); + .await?; + + // if response.results.is_empty() { + // break; + // } + + balances.extend(response.results.into_iter().map( + |Balance { + owner: _, + amount, + asset_id, + }| (asset_id.to_string(), amount), + )); + // cursor = response.cursor; + // } + Ok(balances) } @@ -580,39 +593,37 @@ impl Provider { &self, contract_id: &Bech32ContractId, ) -> Result> { - let mut pagination = PaginationRequest { - cursor: None, - results: 512, - direction: PageDirection::Forward, - }; + let mut contract_balances = HashMap::new(); + let mut cursor = None; - let mut balances_vec = vec![]; loop { - let mut paginated_result = self + let response = self .uncached_client() - .contract_balances(&contract_id.into(), pagination.clone()) + .contract_balances( + &contract_id.into(), + PaginationRequest { + cursor: cursor.clone(), + results: NUM_RESULTS_PER_REQUEST, + direction: PageDirection::Forward, + }, + ) .await?; - pagination.cursor = paginated_result.cursor; - balances_vec.append(&mut paginated_result.results); - - if !paginated_result.has_next_page { + if response.results.is_empty() { break; } - } - let balances = balances_vec - .into_iter() - .map( + contract_balances.extend(response.results.into_iter().map( |ContractBalance { contract: _, amount, asset_id, }| (asset_id, amount), - ) - .collect(); + )); + cursor = response.cursor; + } - Ok(balances) + Ok(contract_balances) } pub async fn get_transaction_by_id(&self, tx_id: &TxId) -> Result> { @@ -766,20 +777,31 @@ impl Provider { } pub async fn get_messages(&self, from: &Bech32Address) -> Result> { - let pagination = PaginationRequest { - cursor: None, - results: 100, - direction: PageDirection::Forward, - }; + let mut messages = Vec::new(); + let mut cursor = None; - Ok(self - .uncached_client() - .messages(Some(&from.into()), pagination) - .await? - .results - .into_iter() - .map(Into::into) - .collect()) + loop { + let response = self + .uncached_client() + .messages( + Some(&from.into()), + PaginationRequest { + cursor: cursor.clone(), + results: NUM_RESULTS_PER_REQUEST, + direction: PageDirection::Forward, + }, + ) + .await?; + + if response.results.is_empty() { + break; + } + + messages.extend(response.results.into_iter().map(Into::into)); + cursor = response.cursor; + } + + Ok(messages) } pub async fn get_message_proof( From 1c9abf936fe426cb9478247541b0d0df63ce68cb Mon Sep 17 00:00:00 2001 From: hal3e Date: Tue, 14 Jan 2025 13:11:02 +0100 Subject: [PATCH 2/2] enable pagination --- packages/fuels-accounts/src/provider.rs | 56 ++++++++++++------------- 1 file changed, 27 insertions(+), 29 deletions(-) diff --git a/packages/fuels-accounts/src/provider.rs b/packages/fuels-accounts/src/provider.rs index eacf01334..38add9b11 100644 --- a/packages/fuels-accounts/src/provider.rs +++ b/packages/fuels-accounts/src/provider.rs @@ -553,37 +553,35 @@ impl Provider { /// for each asset id) and not the UTXOs coins themselves pub async fn get_balances(&self, address: &Bech32Address) -> Result> { let mut balances = HashMap::new(); - // let mut cursor = None; - let cursor = None; + let mut cursor = None; - // loop { //TODO: BLOCKED: pagination is not supported in rocks_db - // do not merge PR until the pagination is enabled - let response = self - .uncached_client() - .balances( - &address.into(), - PaginationRequest { - cursor: cursor.clone(), - // results: NUM_RESULTS_PER_REQUEST, - results: 9999, - direction: PageDirection::Forward, - }, - ) - .await?; + loop { + let response = self + .uncached_client() + .balances( + &address.into(), + PaginationRequest { + cursor: cursor.clone(), + // results: NUM_RESULTS_PER_REQUEST, + results: 9999, + direction: PageDirection::Forward, + }, + ) + .await?; + + if response.results.is_empty() { + break; + } - // if response.results.is_empty() { - // break; - // } - - balances.extend(response.results.into_iter().map( - |Balance { - owner: _, - amount, - asset_id, - }| (asset_id.to_string(), amount), - )); - // cursor = response.cursor; - // } + balances.extend(response.results.into_iter().map( + |Balance { + owner: _, + amount, + asset_id, + }| (asset_id.to_string(), amount), + )); + cursor = response.cursor; + } Ok(balances) }