From c09a6e0581899e7af611a9a1d8770e9dcfeec5b3 Mon Sep 17 00:00:00 2001 From: hal3e Date: Wed, 12 Oct 2022 17:06:48 +0200 Subject: [PATCH 01/17] feat: add new provider api and tests --- examples/predicates/src/lib.rs | 6 +- examples/providers/src/lib.rs | 4 +- packages/fuels-contract/src/script.rs | 2 +- packages/fuels-signers/src/lib.rs | 2 +- packages/fuels-signers/src/provider.rs | 281 ++++++++++++++++++++- packages/fuels-signers/src/wallet.rs | 10 +- packages/fuels-test-helpers/src/signers.rs | 2 +- packages/fuels/tests/predicates/mod.rs | 44 ++-- 8 files changed, 308 insertions(+), 43 deletions(-) diff --git a/examples/predicates/src/lib.rs b/examples/predicates/src/lib.rs index 316545359c..c85ec44267 100644 --- a/examples/predicates/src/lib.rs +++ b/examples/predicates/src/lib.rs @@ -78,7 +78,7 @@ mod tests { .await?; let predicate_balance = provider - .get_asset_balance(predicate.address(), asset_id) + .get_asset_balance(predicate.address(), &asset_id) .await?; assert_eq!(predicate_balance, amount_to_predicate); // ANCHOR_END: predicate_send @@ -107,12 +107,12 @@ mod tests { .await?; let receiver_balance_after = provider - .get_asset_balance(receiver.address(), asset_id) + .get_asset_balance(receiver.address(), &asset_id) .await?; assert_eq!(amount_to_predicate, receiver_balance_after); let predicate_balance = provider - .get_asset_balance(predicate.address(), asset_id) + .get_asset_balance(predicate.address(), &asset_id) .await?; assert_eq!(predicate_balance, 0); // ANCHOR_END: predicate_spend diff --git a/examples/providers/src/lib.rs b/examples/providers/src/lib.rs index e88b882a2a..a9720fae46 100644 --- a/examples/providers/src/lib.rs +++ b/examples/providers/src/lib.rs @@ -59,13 +59,13 @@ mod tests { // ANCHOR_END: setup_test_blockchain // ANCHOR: get_coins - let coins = provider.get_coins(wallet.address(), BASE_ASSET_ID).await?; + let coins = provider.get_coins(wallet.address(), &BASE_ASSET_ID).await?; assert_eq!(coins.len(), 1); // ANCHOR_END: get_coins // ANCHOR: get_spendable_coins let spendable_coins = provider - .get_spendable_coins(wallet.address(), BASE_ASSET_ID, 1) + .get_spendable_coins(wallet.address(), &BASE_ASSET_ID, 1) .await?; assert_eq!(spendable_coins.len(), 1); // ANCHOR_END: get_spendable_coins diff --git a/packages/fuels-contract/src/script.rs b/packages/fuels-contract/src/script.rs index dbe9baf6d5..6075ae3b1e 100644 --- a/packages/fuels-contract/src/script.rs +++ b/packages/fuels-contract/src/script.rs @@ -98,7 +98,7 @@ impl Script { required_asset_amounts: &[(AssetId, u64)], ) -> Result, Error> { stream::iter(required_asset_amounts) - .map(|(asset_id, amount)| wallet.get_spendable_coins(*asset_id, *amount)) + .map(|(asset_id, amount)| wallet.get_spendable_coins(asset_id, *amount)) .buffer_unordered(10) .collect::>() .await diff --git a/packages/fuels-signers/src/lib.rs b/packages/fuels-signers/src/lib.rs index 943ec77242..cbe74ef6ce 100644 --- a/packages/fuels-signers/src/lib.rs +++ b/packages/fuels-signers/src/lib.rs @@ -191,7 +191,7 @@ mod tests { assert_eq!(res.transaction.gas_price(), gas_price); assert_eq!(res.transaction.maturity(), maturity); - let wallet_1_spendable_coins = wallet_1.get_spendable_coins(BASE_ASSET_ID, 0).await?; + let wallet_1_spendable_coins = wallet_1.get_spendable_coins(&BASE_ASSET_ID, 0).await?; let wallet_1_all_coins = wallet_1.get_coins(BASE_ASSET_ID).await?; let wallet_2_all_coins = wallet_2.get_coins(BASE_ASSET_ID).await?; diff --git a/packages/fuels-signers/src/provider.rs b/packages/fuels-signers/src/provider.rs index f6c1d720a2..0e81a75be9 100644 --- a/packages/fuels-signers/src/provider.rs +++ b/packages/fuels-signers/src/provider.rs @@ -6,14 +6,14 @@ use fuel_core::service::{Config, FuelService}; use fuel_gql_client::{ client::{ schema::{ - balance::Balance, chain::ChainInfo, coin::Coin, contract::ContractBalance, - message::Message, node_info::NodeInfo, resource::Resource, + balance::Balance, block::Block, chain::ChainInfo, coin::Coin, contract::Contract, + contract::ContractBalance, message::Message, node_info::NodeInfo, resource::Resource, }, types::{TransactionResponse, TransactionStatus}, FuelClient, PageDirection, PaginatedResult, PaginationRequest, }, - fuel_tx::{Receipt, Transaction, TransactionFee}, - fuel_types::AssetId, + fuel_tx::{Receipt, Transaction, TransactionFee, UtxoId}, + fuel_types::{AssetId, ContractId}, }; use fuels_core::constants::{DEFAULT_GAS_ESTIMATION_TOLERANCE, MAX_GAS_PER_TX}; use std::collections::HashMap; @@ -167,12 +167,17 @@ impl Provider { Ok(self.client.dry_run_opt(tx, Some(false)).await?) } + pub async fn get_coin(&self, id: &UtxoId) -> Result, ProviderError> { + let hex_id = format!("{:#x}", id); + self.client.coin(&hex_id).await.map_err(Into::into) + } + /// Gets all coins owned by address `from`, with asset ID `asset_id`, *even spent ones*. This /// returns actual coins (UTXOs). pub async fn get_coins( &self, from: &Bech32Address, - asset_id: AssetId, + asset_id: &AssetId, ) -> Result, ProviderError> { let mut coins: Vec = vec![]; @@ -208,7 +213,7 @@ impl Provider { pub async fn get_spendable_coins( &self, from: &Bech32Address, - asset_id: AssetId, + asset_id: &AssetId, amount: u64, ) -> Result, ProviderError> { let res = self @@ -238,7 +243,7 @@ impl Provider { pub async fn get_asset_balance( &self, address: &Bech32Address, - asset_id: AssetId, + asset_id: &AssetId, ) -> Result { self.client .balance(&address.hash().to_string(), Some(&*asset_id.to_string())) @@ -250,7 +255,7 @@ impl Provider { pub async fn get_contract_asset_balance( &self, contract_id: &Bech32ContractId, - asset_id: AssetId, + asset_id: &AssetId, ) -> Result { self.client .contract_balance(&contract_id.hash().to_string(), Some(&asset_id.to_string())) @@ -321,6 +326,14 @@ impl Provider { Ok(balances) } + pub async fn get_contract( + &self, + id: &Bech32ContractId, + ) -> Result, ProviderError> { + let hex_id = format!("{:#x}", ContractId::from(id)); + self.client.contract(&hex_id).await.map_err(Into::into) + } + /// Get transaction by id. pub async fn get_transaction_by_id( &self, @@ -432,4 +445,256 @@ impl Provider { .await?; Ok(res.results) } + + pub async fn get_block(&self, block_id: &str) -> Result, ProviderError> { + self.client.block(block_id).await.map_err(Into::into) + } + + pub async fn get_blocks( + &self, + request: PaginationRequest, + ) -> Result, ProviderError> { + self.client.blocks(request).await.map_err(Into::into) + } } + +#[cfg(test)] +mod tests { + #[cfg(feature = "test-helpers")] + use fuel_core::model::Coin; + + use fuel_gql_client::fuel_tx::UtxoId; + use fuels::prelude::*; + + async fn setup_provider_api_test() -> ( + WalletUnlocked, + (Vec<(UtxoId, Coin)>, Vec), + Provider, + ) { + let mut wallet = WalletUnlocked::new_random(None); + let (coins, asset_ids) = setup_multiple_assets_coins(wallet.address(), 2, 4, 8); + let (provider, _) = setup_test_provider(coins.clone(), vec![], None).await; + wallet.set_provider(provider.clone()); + + (wallet, (coins, asset_ids), provider) + } + + #[tokio::test] + async fn test_coin_api() -> Result<(), Error> { + let (_, (coins, _), provider) = setup_provider_api_test().await; + + let (coin_id, _) = &coins[0]; + let hex_coin_id = format!("{:#x}", coin_id); + + let expected_coin = provider + .get_coin(coin_id) + .await? + .expect("could not find coin with provided id"); + + assert_eq!(hex_coin_id, expected_coin.utxo_id.0.to_string()); + Ok(()) + } + + #[tokio::test] + async fn test_coins_api() -> Result<(), Error> { + use std::collections::HashSet; + + let (wallet, (coins, asset_ids), provider) = setup_provider_api_test().await; + let asset_id = &asset_ids[0]; + let utxo_ids_of_coins_with_asset_id: HashSet = coins + .iter() + .filter(|c| c.1.asset_id == *asset_id) + .map(|c| format!("{:#x}", c.0)) + .collect(); + + let expected_coins = provider.get_coins(wallet.address(), asset_id).await?; + + assert_eq!(expected_coins.len(), utxo_ids_of_coins_with_asset_id.len()); + assert!(expected_coins + .iter() + .all(|ec| utxo_ids_of_coins_with_asset_id.contains(&ec.utxo_id.0.to_string()))); + + Ok(()) + } + + #[tokio::test] + async fn test_spendable_coins_api() -> Result<(), Error> { + use std::collections::HashSet; + + let (wallet, (coins, asset_ids), provider) = setup_provider_api_test().await; + let asset_id = &asset_ids[0]; + let amount = 18; + let utxo_ids_of_coins_with_asset_id: HashSet = coins + .iter() + .filter(|c| c.1.asset_id == *asset_id) + .map(|c| format!("{:#x}", c.0)) + .collect(); + + let expected_coins = provider + .get_spendable_coins(wallet.address(), asset_id, amount) + .await?; + + assert!(expected_coins.iter().map(|ec| ec.amount.0).sum::() > amount); + assert!(expected_coins + .iter() + .all(|ec| utxo_ids_of_coins_with_asset_id.contains(&ec.utxo_id.0.to_string()))); + + Ok(()) + } + + #[tokio::test] + async fn test_balance_api() -> Result<(), Error> { + let (wallet, (coins, asset_ids), provider) = setup_provider_api_test().await; + let asset_id = &asset_ids[0]; + let hex_asset_id = format!("{:#x}", asset_id); + let wallet_balance_asset_id: u64 = coins + .iter() + .filter(|c| c.1.asset_id == *asset_id) + .map(|c| c.1.amount) + .sum(); + + let wallet_balances = provider.get_balances(wallet.address()).await?; + let expected_asset_balance = wallet_balances + .get(&hex_asset_id) + .expect("could not get balance for asset id"); + + assert_eq!(*expected_asset_balance, wallet_balance_asset_id); + + Ok(()) + } + + #[tokio::test] + async fn test_asset_balance_api() -> Result<(), Error> { + let (wallet, (coins, asset_ids), provider) = setup_provider_api_test().await; + let asset_id = &asset_ids[0]; + let balance_of_coins_with_asset_id: u64 = coins + .iter() + .filter(|c| c.1.asset_id == *asset_id) + .map(|c| c.1.amount) + .sum(); + + let expected_balance = provider + .get_asset_balance(wallet.address(), asset_id) + .await?; + + assert_eq!(balance_of_coins_with_asset_id, expected_balance); + + Ok(()) + } + + #[tokio::test] + async fn test_contract_balance_api() -> Result<(), Error> { + let (wallet, (_, asset_ids), provider) = setup_provider_api_test().await; + let asset_id = &asset_ids[0]; + let hex_asset_id = format!("{:#x}", asset_id); + + let contract_id = Contract::deploy( + "../fuels/tests/contracts/contract_test/out/debug/contract_test.bin", + &wallet, + TxParameters::default(), + StorageConfiguration::default(), + ) + .await?; + + let amount = 18; + let _receipts = wallet + .force_transfer_to_contract(&contract_id, amount, *asset_id, TxParameters::default()) + .await?; + + let contract_balances = provider.get_contract_balances(&contract_id).await?; + + let expected_asset_balance = contract_balances + .get(&hex_asset_id) + .expect("could not get balance for asset id"); + assert_eq!(*expected_asset_balance, amount); + + Ok(()) + } + + #[tokio::test] + async fn test_contract_asset_balance_api() -> Result<(), Error> { + let (wallet, (_, asset_ids), provider) = setup_provider_api_test().await; + let asset_id = &asset_ids[0]; + + let contract_id = Contract::deploy( + "../fuels/tests/contracts/contract_test/out/debug/contract_test.bin", + &wallet, + TxParameters::default(), + StorageConfiguration::default(), + ) + .await?; + + let amount = 18; + let _receipts = wallet + .force_transfer_to_contract(&contract_id, amount, *asset_id, TxParameters::default()) + .await?; + + let expected_contract_balance = provider + .get_contract_asset_balance(&contract_id, asset_id) + .await?; + + assert_eq!(expected_contract_balance, amount); + + Ok(()) + } + + #[tokio::test] + async fn test_transaction_by_id_api() -> Result<(), Error> { + let (wallet, (_, _), provider) = setup_provider_api_test().await; + + let wallet2 = WalletUnlocked::new_random(Some(provider.clone())); + + let gas_price = 1; + let gas_limit = 500_000; + let maturity = 0; + let tx_params = TxParameters { + gas_price, + gas_limit, + maturity, + }; + + let (tx_id, _receipts) = wallet + .transfer(wallet2.address(), 1, Default::default(), tx_params) + .await?; + + let expected_response = provider.get_transaction_by_id(&tx_id).await?; + + assert_eq!(expected_response.transaction.gas_limit(), gas_limit); + assert_eq!(expected_response.transaction.gas_price(), gas_price); + assert_eq!(expected_response.transaction.maturity(), maturity); + + Ok(()) + } + + #[tokio::test] + async fn test_get_contract_api() -> Result<(), Error> { + let (wallet, (_, _), provider) = setup_provider_api_test().await; + + let contract_id = Contract::deploy( + "../fuels/tests/contracts/contract_test/out/debug/contract_test.bin", + &wallet, + TxParameters::default(), + StorageConfiguration::default(), + ) + .await?; + let hex_contract_id = format!("{:#x}", ContractId::from(&contract_id)); + + let expected_contract = provider + .get_contract(&contract_id) + .await? + .expect("could not find contract with specified id"); + + assert_eq!(hex_contract_id, expected_contract.id.to_string()); + + Ok(()) + } +} + +// TODO: update get_messages +// pub async fn get_messages(&self, from: &Bech32Address) -> Result, ProviderError> { + +// TODO: make tests +// pub async fn get_transactions +// pub async fn get_transactions_by_owner +// pub async fn get_block +// pub async fn get_blocks diff --git a/packages/fuels-signers/src/wallet.rs b/packages/fuels-signers/src/wallet.rs index 6a6605ebd4..ee6934ba0f 100644 --- a/packages/fuels-signers/src/wallet.rs +++ b/packages/fuels-signers/src/wallet.rs @@ -148,7 +148,7 @@ impl Wallet { amount: u64, witness_index: u8, ) -> Result, Error> { - let spendable = self.get_spendable_coins(asset_id, amount).await?; + let spendable = self.get_spendable_coins(&asset_id, amount).await?; let mut inputs = vec![]; for coin in spendable { let input_coin = Input::coin_signed( @@ -186,7 +186,7 @@ impl Wallet { pub async fn get_coins(&self, asset_id: AssetId) -> Result, Error> { Ok(self .get_provider()? - .get_coins(&self.address, asset_id) + .get_coins(&self.address, &asset_id) .await?) } @@ -195,7 +195,7 @@ impl Wallet { /// of coins (UXTOs) is optimized to prevent dust accumulation. pub async fn get_spendable_coins( &self, - asset_id: AssetId, + asset_id: &AssetId, amount: u64, ) -> Result, Error> { self.get_provider()? @@ -209,7 +209,7 @@ impl Wallet { /// of the UTXOs. pub async fn get_asset_balance(&self, asset_id: &AssetId) -> Result { self.get_provider()? - .get_asset_balance(&self.address, *asset_id) + .get_asset_balance(&self.address, asset_id) .await .map_err(Into::into) } @@ -644,7 +644,7 @@ impl WalletUnlocked { ) -> Result, Error> { let spendable_predicate_coins = self .get_provider()? - .get_spendable_coins(predicate_address, asset_id, amount) + .get_spendable_coins(predicate_address, &asset_id, amount) .await?; // input amount is: amount < input_amount < 2*amount diff --git a/packages/fuels-test-helpers/src/signers.rs b/packages/fuels-test-helpers/src/signers.rs index 6d5e4f7865..122109eab9 100644 --- a/packages/fuels-test-helpers/src/signers.rs +++ b/packages/fuels-test-helpers/src/signers.rs @@ -179,7 +179,7 @@ mod tests { for asset in assets { for wallet in &wallets { let coins = wallet - .get_spendable_coins(asset.id, asset.num_coins * asset.coin_amount) + .get_spendable_coins(&asset.id, asset.num_coins * asset.coin_amount) .await?; assert_eq!(coins.len() as u64, asset.num_coins); diff --git a/packages/fuels/tests/predicates/mod.rs b/packages/fuels/tests/predicates/mod.rs index 1905b77002..590cd43523 100644 --- a/packages/fuels/tests/predicates/mod.rs +++ b/packages/fuels/tests/predicates/mod.rs @@ -47,7 +47,7 @@ async fn can_call_no_arg_predicate_returns_true() -> Result<(), Error> { .await?; let receiver_balance_before = provider - .get_asset_balance(receiver.address(), asset_id) + .get_asset_balance(receiver.address(), &asset_id) .await?; assert_eq!(receiver_balance_before, 16); @@ -63,7 +63,7 @@ async fn can_call_no_arg_predicate_returns_true() -> Result<(), Error> { .await?; let receiver_balance_after = provider - .get_asset_balance(receiver.address(), asset_id) + .get_asset_balance(receiver.address(), &asset_id) .await?; assert_eq!( receiver_balance_before + amount_to_predicate, @@ -71,7 +71,7 @@ async fn can_call_no_arg_predicate_returns_true() -> Result<(), Error> { ); let predicate_balance = provider - .get_asset_balance(predicate.address(), asset_id) + .get_asset_balance(predicate.address(), &asset_id) .await?; assert_eq!(predicate_balance, 0); Ok(()) @@ -98,7 +98,7 @@ async fn can_call_no_arg_predicate_returns_false() -> Result<(), Error> { .await?; let receiver_balance_before = provider - .get_asset_balance(receiver.address(), asset_id) + .get_asset_balance(receiver.address(), &asset_id) .await?; assert_eq!(receiver_balance_before, 16); @@ -115,12 +115,12 @@ async fn can_call_no_arg_predicate_returns_false() -> Result<(), Error> { .expect_err("should error"); let receiver_balance_after = provider - .get_asset_balance(receiver.address(), asset_id) + .get_asset_balance(receiver.address(), &asset_id) .await?; assert_eq!(receiver_balance_before, receiver_balance_after); let predicate_balance = provider - .get_asset_balance(predicate.address(), asset_id) + .get_asset_balance(predicate.address(), &asset_id) .await?; assert_eq!(predicate_balance, amount_to_predicate); Ok(()) @@ -147,7 +147,7 @@ async fn can_call_predicate_with_u32_data() -> Result<(), Error> { .await?; let receiver_balance_before = provider - .get_asset_balance(receiver.address(), asset_id) + .get_asset_balance(receiver.address(), &asset_id) .await?; assert_eq!(receiver_balance_before, 16); @@ -168,12 +168,12 @@ async fn can_call_predicate_with_u32_data() -> Result<(), Error> { .expect_err("should error"); let receiver_balance_after = provider - .get_asset_balance(receiver.address(), asset_id) + .get_asset_balance(receiver.address(), &asset_id) .await?; assert_eq!(receiver_balance_before, receiver_balance_after); let predicate_balance = provider - .get_asset_balance(predicate.address(), asset_id) + .get_asset_balance(predicate.address(), &asset_id) .await?; assert_eq!(predicate_balance, amount_to_predicate); @@ -193,7 +193,7 @@ async fn can_call_predicate_with_u32_data() -> Result<(), Error> { .await?; let receiver_balance_after = provider - .get_asset_balance(receiver.address(), asset_id) + .get_asset_balance(receiver.address(), &asset_id) .await?; assert_eq!( receiver_balance_before + amount_to_predicate, @@ -201,7 +201,7 @@ async fn can_call_predicate_with_u32_data() -> Result<(), Error> { ); let predicate_balance = provider - .get_asset_balance(predicate.address(), asset_id) + .get_asset_balance(predicate.address(), &asset_id) .await?; assert_eq!(predicate_balance, 0); Ok(()) @@ -228,7 +228,7 @@ async fn can_call_predicate_with_address_data() -> Result<(), Error> { .await?; let receiver_balance_before = provider - .get_asset_balance(receiver.address(), asset_id) + .get_asset_balance(receiver.address(), &asset_id) .await?; assert_eq!(receiver_balance_before, 16); @@ -248,7 +248,7 @@ async fn can_call_predicate_with_address_data() -> Result<(), Error> { .await?; let receiver_balance_after = provider - .get_asset_balance(receiver.address(), asset_id) + .get_asset_balance(receiver.address(), &asset_id) .await?; assert_eq!( receiver_balance_before + amount_to_predicate, @@ -256,7 +256,7 @@ async fn can_call_predicate_with_address_data() -> Result<(), Error> { ); let predicate_balance = provider - .get_asset_balance(predicate.address(), asset_id) + .get_asset_balance(predicate.address(), &asset_id) .await?; assert_eq!(predicate_balance, 0); Ok(()) @@ -283,7 +283,7 @@ async fn can_call_predicate_with_struct_data() -> Result<(), Error> { .await?; let receiver_balance_before = provider - .get_asset_balance(receiver.address(), asset_id) + .get_asset_balance(receiver.address(), &asset_id) .await?; assert_eq!(receiver_balance_before, 16); @@ -304,12 +304,12 @@ async fn can_call_predicate_with_struct_data() -> Result<(), Error> { .expect_err("should error"); let receiver_balance_after = provider - .get_asset_balance(receiver.address(), asset_id) + .get_asset_balance(receiver.address(), &asset_id) .await?; assert_eq!(receiver_balance_before, receiver_balance_after); let predicate_balance = provider - .get_asset_balance(predicate.address(), asset_id) + .get_asset_balance(predicate.address(), &asset_id) .await?; assert_eq!(predicate_balance, amount_to_predicate); @@ -329,7 +329,7 @@ async fn can_call_predicate_with_struct_data() -> Result<(), Error> { .await?; let receiver_balance_after = provider - .get_asset_balance(receiver.address(), asset_id) + .get_asset_balance(receiver.address(), &asset_id) .await?; assert_eq!( receiver_balance_before + amount_to_predicate, @@ -337,7 +337,7 @@ async fn can_call_predicate_with_struct_data() -> Result<(), Error> { ); let predicate_balance = provider - .get_asset_balance(predicate.address(), asset_id) + .get_asset_balance(predicate.address(), &asset_id) .await?; assert_eq!(predicate_balance, 0); Ok(()) @@ -373,7 +373,7 @@ async fn predicate_with_multiple_coins() -> Result<(), Error> { .await?; let receiver_balance_before = provider - .get_asset_balance(receiver.address(), asset_id) + .get_asset_balance(receiver.address(), &asset_id) .await?; assert_eq!(receiver_balance_before, 300); @@ -389,7 +389,7 @@ async fn predicate_with_multiple_coins() -> Result<(), Error> { .await?; let receiver_balance_after = provider - .get_asset_balance(receiver.address(), asset_id) + .get_asset_balance(receiver.address(), &asset_id) .await?; assert_eq!( receiver_balance_before + amount_to_predicate - 1, @@ -397,7 +397,7 @@ async fn predicate_with_multiple_coins() -> Result<(), Error> { ); let predicate_balance = provider - .get_asset_balance(predicate.address(), asset_id) + .get_asset_balance(predicate.address(), &asset_id) .await?; assert_eq!(predicate_balance, 10); Ok(()) From 227a937bdf4b6ba55f4438e637bfc4eeac63060b Mon Sep 17 00:00:00 2001 From: hal3e Date: Wed, 19 Oct 2022 15:31:30 +0200 Subject: [PATCH 02/17] add tests --- packages/fuels-signers/src/lib.rs | 5 +- packages/fuels-signers/src/provider.rs | 276 ++++++++++++++++++------- packages/fuels-signers/src/wallet.rs | 9 +- 3 files changed, 205 insertions(+), 85 deletions(-) diff --git a/packages/fuels-signers/src/lib.rs b/packages/fuels-signers/src/lib.rs index cbe74ef6ce..c3fc6cbcb9 100644 --- a/packages/fuels-signers/src/lib.rs +++ b/packages/fuels-signers/src/lib.rs @@ -182,10 +182,7 @@ mod tests { .await?; // Assert that the transaction was properly configured. - let res = wallet_1 - .get_provider()? - .get_transaction_by_id(&tx_id) - .await?; + let res = wallet_1.get_provider()?.get_transaction(&tx_id).await?; assert_eq!(res.transaction.gas_limit(), gas_limit); assert_eq!(res.transaction.gas_price(), gas_price); diff --git a/packages/fuels-signers/src/provider.rs b/packages/fuels-signers/src/provider.rs index 0e81a75be9..bada804f92 100644 --- a/packages/fuels-signers/src/provider.rs +++ b/packages/fuels-signers/src/provider.rs @@ -10,7 +10,7 @@ use fuel_gql_client::{ contract::ContractBalance, message::Message, node_info::NodeInfo, resource::Resource, }, types::{TransactionResponse, TransactionStatus}, - FuelClient, PageDirection, PaginatedResult, PaginationRequest, + FuelClient, PageDirection, PaginationRequest, }, fuel_tx::{Receipt, Transaction, TransactionFee, UtxoId}, fuel_types::{AssetId, ContractId}, @@ -266,6 +266,7 @@ impl Provider { /// Get all the spendable balances of all assets for address `address`. This is different from /// 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 + //TODO: check if we need to change String to AssetId pub async fn get_balances( &self, address: &Bech32Address, @@ -296,6 +297,7 @@ impl Provider { } /// Get all balances of all assets for the contract with id `contract_id`. + //TODO: check if we need to change String to AssetId pub async fn get_contract_balances( &self, contract_id: &Bech32ContractId, @@ -334,32 +336,64 @@ impl Provider { self.client.contract(&hex_id).await.map_err(Into::into) } - /// Get transaction by id. - pub async fn get_transaction_by_id( - &self, - tx_id: &str, - ) -> Result { + pub async fn get_transaction(&self, tx_id: &str) -> Result { Ok(self.client.transaction(tx_id).await.unwrap().unwrap()) } - // - Get transaction(s) - pub async fn get_transactions( - &self, - request: PaginationRequest, - ) -> Result, ProviderError> { - self.client.transactions(request).await.map_err(Into::into) + pub async fn get_transactions(&self) -> Result, ProviderError> { + let mut transaction_responses: Vec = vec![]; + + let mut cursor = None; + + loop { + let res = self + .client + .transactions(PaginationRequest { + cursor: cursor.clone(), + results: 100, + direction: PageDirection::Forward, + }) + .await?; + + if res.results.is_empty() { + break; + } + transaction_responses.extend(res.results); + cursor = res.cursor; + } + + Ok(transaction_responses) } - // Get transaction(s) by owner pub async fn get_transactions_by_owner( &self, owner: &Bech32Address, - request: PaginationRequest, - ) -> Result, ProviderError> { - self.client - .transactions_by_owner(&owner.hash().to_string(), request) - .await - .map_err(Into::into) + ) -> Result, ProviderError> { + let mut transaction_responses: Vec = vec![]; + + let mut cursor = None; + + loop { + let res = self + .client + .transactions_by_owner( + &owner.hash().to_string(), + PaginationRequest { + cursor: cursor.clone(), + results: 100, + direction: PageDirection::Forward, + }, + ) + .await?; + + if res.results.is_empty() { + break; + } + transaction_responses.extend(res.results); + cursor = res.cursor; + } + + Ok(transaction_responses) } pub async fn latest_block_height(&self) -> Result { @@ -450,11 +484,16 @@ impl Provider { self.client.block(block_id).await.map_err(Into::into) } - pub async fn get_blocks( - &self, - request: PaginationRequest, - ) -> Result, ProviderError> { - self.client.blocks(request).await.map_err(Into::into) + pub async fn get_blocks(&self) -> Result, ProviderError> { + let res = self + .client + .blocks(PaginationRequest { + cursor: None, + results: 999, + direction: PageDirection::Forward, + }) + .await?; + Ok(res.results) } } @@ -463,6 +502,7 @@ mod tests { #[cfg(feature = "test-helpers")] use fuel_core::model::Coin; + use fuel_gql_client::client::types::TransactionStatus; use fuel_gql_client::fuel_tx::UtxoId; use fuels::prelude::*; @@ -543,47 +583,74 @@ mod tests { } #[tokio::test] - async fn test_balance_api() -> Result<(), Error> { + async fn test_asset_balance_api() -> Result<(), Error> { let (wallet, (coins, asset_ids), provider) = setup_provider_api_test().await; let asset_id = &asset_ids[0]; - let hex_asset_id = format!("{:#x}", asset_id); - let wallet_balance_asset_id: u64 = coins + let balance_of_coins_with_asset_id: u64 = coins .iter() .filter(|c| c.1.asset_id == *asset_id) .map(|c| c.1.amount) .sum(); - let wallet_balances = provider.get_balances(wallet.address()).await?; - let expected_asset_balance = wallet_balances - .get(&hex_asset_id) - .expect("could not get balance for asset id"); + let expected_balance = provider + .get_asset_balance(wallet.address(), asset_id) + .await?; - assert_eq!(*expected_asset_balance, wallet_balance_asset_id); + assert_eq!(balance_of_coins_with_asset_id, expected_balance); Ok(()) } #[tokio::test] - async fn test_asset_balance_api() -> Result<(), Error> { + async fn test_contract_asset_balance_api() -> Result<(), Error> { + let (wallet, (_, asset_ids), provider) = setup_provider_api_test().await; + let asset_id = &asset_ids[0]; + + let contract_id = Contract::deploy( + "../fuels/tests/contracts/contract_test/out/debug/contract_test.bin", + &wallet, + TxParameters::default(), + StorageConfiguration::default(), + ) + .await?; + + let amount = 18; + let _receipts = wallet + .force_transfer_to_contract(&contract_id, amount, *asset_id, TxParameters::default()) + .await?; + + let expected_contract_balance = provider + .get_contract_asset_balance(&contract_id, asset_id) + .await?; + + assert_eq!(expected_contract_balance, amount); + + Ok(()) + } + + #[tokio::test] + async fn test_balances_api() -> Result<(), Error> { let (wallet, (coins, asset_ids), provider) = setup_provider_api_test().await; let asset_id = &asset_ids[0]; - let balance_of_coins_with_asset_id: u64 = coins + let hex_asset_id = format!("{:#x}", asset_id); + let wallet_balance_asset_id: u64 = coins .iter() .filter(|c| c.1.asset_id == *asset_id) .map(|c| c.1.amount) .sum(); - let expected_balance = provider - .get_asset_balance(wallet.address(), asset_id) - .await?; + let wallet_balances = provider.get_balances(wallet.address()).await?; + let expected_asset_balance = wallet_balances + .get(&hex_asset_id) + .expect("could not get balance for asset id"); - assert_eq!(balance_of_coins_with_asset_id, expected_balance); + assert_eq!(*expected_asset_balance, wallet_balance_asset_id); Ok(()) } #[tokio::test] - async fn test_contract_balance_api() -> Result<(), Error> { + async fn test_contract_balances_api() -> Result<(), Error> { let (wallet, (_, asset_ids), provider) = setup_provider_api_test().await; let asset_id = &asset_ids[0]; let hex_asset_id = format!("{:#x}", asset_id); @@ -612,9 +679,8 @@ mod tests { } #[tokio::test] - async fn test_contract_asset_balance_api() -> Result<(), Error> { - let (wallet, (_, asset_ids), provider) = setup_provider_api_test().await; - let asset_id = &asset_ids[0]; + async fn test_get_contract_api() -> Result<(), Error> { + let (wallet, (_, _), provider) = setup_provider_api_test().await; let contract_id = Contract::deploy( "../fuels/tests/contracts/contract_test/out/debug/contract_test.bin", @@ -623,23 +689,20 @@ mod tests { StorageConfiguration::default(), ) .await?; + let hex_contract_id = format!("{:#x}", ContractId::from(&contract_id)); - let amount = 18; - let _receipts = wallet - .force_transfer_to_contract(&contract_id, amount, *asset_id, TxParameters::default()) - .await?; - - let expected_contract_balance = provider - .get_contract_asset_balance(&contract_id, asset_id) - .await?; + let expected_contract = provider + .get_contract(&contract_id) + .await? + .expect("could not find contract with specified id"); - assert_eq!(expected_contract_balance, amount); + assert_eq!(hex_contract_id, expected_contract.id.to_string()); Ok(()) } #[tokio::test] - async fn test_transaction_by_id_api() -> Result<(), Error> { + async fn test_transaction_api() -> Result<(), Error> { let (wallet, (_, _), provider) = setup_provider_api_test().await; let wallet2 = WalletUnlocked::new_random(Some(provider.clone())); @@ -657,7 +720,7 @@ mod tests { .transfer(wallet2.address(), 1, Default::default(), tx_params) .await?; - let expected_response = provider.get_transaction_by_id(&tx_id).await?; + let expected_response = provider.get_transaction(&tx_id).await?; assert_eq!(expected_response.transaction.gas_limit(), gas_limit); assert_eq!(expected_response.transaction.gas_price(), gas_price); @@ -667,34 +730,97 @@ mod tests { } #[tokio::test] - async fn test_get_contract_api() -> Result<(), Error> { + async fn test_transactions_api() -> Result<(), Error> { let (wallet, (_, _), provider) = setup_provider_api_test().await; - let contract_id = Contract::deploy( - "../fuels/tests/contracts/contract_test/out/debug/contract_test.bin", - &wallet, - TxParameters::default(), - StorageConfiguration::default(), - ) - .await?; - let hex_contract_id = format!("{:#x}", ContractId::from(&contract_id)); + let wallet2 = WalletUnlocked::new_random(Some(provider.clone())); - let expected_contract = provider - .get_contract(&contract_id) - .await? - .expect("could not find contract with specified id"); + // Make two transactions + let (_tx_id1, _receipts) = wallet + .transfer(wallet2.address(), 1, Default::default(), Default::default()) + .await?; + let (_tx_id2, _receipts) = wallet + .transfer(wallet2.address(), 1, Default::default(), Default::default()) + .await?; - assert_eq!(hex_contract_id, expected_contract.id.to_string()); + let expected_response = provider.get_transactions().await?; + + assert_eq!(expected_response.len(), 2); + //TODO: check if I can test it in another way Ok(()) } -} -// TODO: update get_messages -// pub async fn get_messages(&self, from: &Bech32Address) -> Result, ProviderError> { + #[tokio::test] + async fn test_transaction_by_owner_api() -> Result<(), Error> { + let (wallet, (_, _), provider) = setup_provider_api_test().await; + + let wallet2 = WalletUnlocked::new_random(Some(provider.clone())); + + // Make two transactions + let (_tx_id1, _receipts) = wallet + .transfer(wallet2.address(), 1, Default::default(), Default::default()) + .await?; + let (_tx_id2, _receipts) = wallet + .transfer(wallet2.address(), 1, Default::default(), Default::default()) + .await?; + + let expected_response = provider.get_transactions_by_owner(wallet.address()).await?; + + assert_eq!(expected_response.len(), 2); + //TODO: check if I can test it in another way + + Ok(()) + } + + #[tokio::test] + async fn test_block_api() -> Result<(), Error> { + let (wallet, (_, _), provider) = setup_provider_api_test().await; + + let wallet2 = WalletUnlocked::new_random(Some(provider.clone())); + + let (tx_id, _receipts) = wallet + .transfer(wallet2.address(), 1, Default::default(), Default::default()) + .await?; + + if let TransactionStatus::Success { block_id, time, .. } = + provider.get_transaction(&tx_id).await?.status + { + let expected_block = provider + .get_block(&block_id) + .await? + .expect("could not find block with specified id"); + + assert_eq!(block_id, expected_block.id.to_string()); + assert_eq!(expected_block.time, time); + + return Ok(()); + } + + Err(Error::ProviderError( + "Transaction was not successfull".into(), + )) + } + + #[tokio::test] + async fn test_blocks_api() -> Result<(), Error> { + let (wallet, (_, _), provider) = setup_provider_api_test().await; + + let wallet2 = WalletUnlocked::new_random(Some(provider.clone())); + + // Make two transactions + let (_tx_id1, _receipts) = wallet + .transfer(wallet2.address(), 1, Default::default(), Default::default()) + .await?; + let (_tx_id2, _receipts) = wallet + .transfer(wallet2.address(), 1, Default::default(), Default::default()) + .await?; -// TODO: make tests -// pub async fn get_transactions -// pub async fn get_transactions_by_owner -// pub async fn get_block -// pub async fn get_blocks + let expected_blocks = provider.get_blocks().await?; + + assert_eq!(expected_blocks.len(), 2); + //TODO: check if I can test it in another way + + Ok(()) + } +} diff --git a/packages/fuels-signers/src/wallet.rs b/packages/fuels-signers/src/wallet.rs index ee6934ba0f..a376a0c38d 100644 --- a/packages/fuels-signers/src/wallet.rs +++ b/packages/fuels-signers/src/wallet.rs @@ -7,7 +7,7 @@ use fuel_crypto::{Message, PublicKey, SecretKey, Signature}; use fuel_gql_client::client::schema; use fuel_gql_client::fuel_vm::prelude::GTFArgs; use fuel_gql_client::{ - client::{schema::coin::Coin, types::TransactionResponse, PaginatedResult, PaginationRequest}, + client::{schema::coin::Coin, types::TransactionResponse}, fuel_tx::{ AssetId, Bytes32, ContractId, Input, Output, Receipt, Transaction, TransactionFee, TxPointer, UtxoId, Witness, @@ -126,12 +126,9 @@ impl Wallet { &self.address } - pub async fn get_transactions( - &self, - request: PaginationRequest, - ) -> Result, Error> { + pub async fn get_transactions(&self) -> Result, Error> { self.get_provider()? - .get_transactions_by_owner(&self.address, request) + .get_transactions_by_owner(&self.address) .await .map_err(Into::into) } From d0b57d357db66fe8e431ceb69c00ac75ad8013ef Mon Sep 17 00:00:00 2001 From: hal3e Date: Wed, 19 Oct 2022 16:47:41 +0200 Subject: [PATCH 03/17] refactor balances api --- .../wallets/checking-balances-and-coins.md | 2 +- examples/cookbook/src/lib.rs | 5 +- examples/wallets/src/lib.rs | 9 ++- packages/fuels-signers/src/lib.rs | 6 +- packages/fuels-signers/src/provider.rs | 56 ++++++++++++------- packages/fuels-signers/src/wallet.rs | 2 +- packages/fuels/tests/scripts.rs | 3 +- packages/fuels/tests/wallets.rs | 10 ++-- 8 files changed, 53 insertions(+), 40 deletions(-) diff --git a/docs/src/wallets/checking-balances-and-coins.md b/docs/src/wallets/checking-balances-and-coins.md index 5cf61273b9..dd13540d4c 100644 --- a/docs/src/wallets/checking-balances-and-coins.md +++ b/docs/src/wallets/checking-balances-and-coins.md @@ -12,7 +12,7 @@ If you want to query all the balances (i.e., get the balance for each asset ID i {{#include ../../../examples/wallets/src/lib.rs:get_balances}} ``` -The return type is a `HashMap`, where the key is the _asset ID's_ hex string, and the value is the corresponding balance. For example, we can get the base asset balance with: +The return type is a `HashMap`, where the key is an `AssetId`, and the value is the corresponding balance. For example, we can get the base asset balance with: ```rust,ignore {{#include ../../../examples/wallets/src/lib.rs:get_balance_hashmap}} diff --git a/examples/cookbook/src/lib.rs b/examples/cookbook/src/lib.rs index 69a6ef8a9b..bbf97fb879 100644 --- a/examples/cookbook/src/lib.rs +++ b/examples/cookbook/src/lib.rs @@ -117,7 +117,6 @@ mod tests { async fn transfer_multiple() -> Result<(), Error> { // ANCHOR: transfer_multiple use fuels::prelude::*; - use std::str::FromStr; // ANCHOR: transfer_multiple_setup let mut wallet_1 = WalletUnlocked::new_random(None); @@ -140,9 +139,7 @@ mod tests { let mut inputs = vec![]; let mut outputs = vec![]; - for (id_string, amount) in balances { - let id = AssetId::from_str(&id_string).unwrap(); - + for (id, amount) in balances { // leave the base asset to cover transaction fees if id == BASE_ASSET_ID { continue; diff --git a/examples/wallets/src/lib.rs b/examples/wallets/src/lib.rs index 4d6323d946..2d3925d669 100644 --- a/examples/wallets/src/lib.rs +++ b/examples/wallets/src/lib.rs @@ -200,8 +200,7 @@ mod tests { .await?; assert_eq!(contract_balances.len(), 1); - let random_asset_id_key = format!("{:#x}", random_asset_id); - let random_asset_balance = contract_balances.get(&random_asset_id_key).unwrap(); + let random_asset_balance = contract_balances.get(&random_asset_id).unwrap(); assert_eq!(*random_asset_balance, 300); // ANCHOR_END: wallet_contract_transfer @@ -318,12 +317,12 @@ mod tests { let balance: u64 = wallet.get_asset_balance(&asset_id).await?; // ANCHOR_END: get_asset_balance // ANCHOR: get_balances - let balances: HashMap = wallet.get_balances().await?; + let balances: HashMap = wallet.get_balances().await?; // ANCHOR_END: get_balances // ANCHOR: get_balance_hashmap - let asset_id_key = format!("{:#x}", asset_id); - let asset_balance = balances.get(&asset_id_key).unwrap(); + let asset_id: AssetId = BASE_ASSET_ID; + let asset_balance = balances.get(&asset_id).unwrap(); // ANCHOR_END: get_balance_hashmap assert_eq!(*asset_balance, DEFAULT_COIN_AMOUNT * DEFAULT_NUM_COINS); diff --git a/packages/fuels-signers/src/lib.rs b/packages/fuels-signers/src/lib.rs index c3fc6cbcb9..ef637f8133 100644 --- a/packages/fuels-signers/src/lib.rs +++ b/packages/fuels-signers/src/lib.rs @@ -182,7 +182,11 @@ mod tests { .await?; // Assert that the transaction was properly configured. - let res = wallet_1.get_provider()?.get_transaction(&tx_id).await?; + let res = wallet_1 + .get_provider()? + .get_transaction(&tx_id) + .await? + .expect("could not find transaction with specified id"); assert_eq!(res.transaction.gas_limit(), gas_limit); assert_eq!(res.transaction.gas_price(), gas_price); diff --git a/packages/fuels-signers/src/provider.rs b/packages/fuels-signers/src/provider.rs index bada804f92..f8e9359c93 100644 --- a/packages/fuels-signers/src/provider.rs +++ b/packages/fuels-signers/src/provider.rs @@ -16,7 +16,7 @@ use fuel_gql_client::{ fuel_types::{AssetId, ContractId}, }; use fuels_core::constants::{DEFAULT_GAS_ESTIMATION_TOLERANCE, MAX_GAS_PER_TX}; -use std::collections::HashMap; +use std::{collections::HashMap, str::FromStr}; use thiserror::Error; use fuels_types::bech32::{Bech32Address, Bech32ContractId}; @@ -266,11 +266,10 @@ impl Provider { /// Get all the spendable balances of all assets for address `address`. This is different from /// 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 - //TODO: check if we need to change String to AssetId pub async fn get_balances( &self, address: &Bech32Address, - ) -> Result, ProviderError> { + ) -> Result, ProviderError> { // We don't paginate results because there are likely at most ~100 different assets in one // wallet let pagination = PaginationRequest { @@ -290,18 +289,22 @@ impl Provider { owner: _, amount, asset_id, - }| (asset_id.to_string(), amount.try_into().unwrap()), + }| { + ( + AssetId::from_str(&asset_id.to_string()).unwrap(), + amount.try_into().unwrap(), + ) + }, ) .collect(); Ok(balances) } /// Get all balances of all assets for the contract with id `contract_id`. - //TODO: check if we need to change String to AssetId pub async fn get_contract_balances( &self, contract_id: &Bech32ContractId, - ) -> Result, ProviderError> { + ) -> Result, ProviderError> { // We don't paginate results because there are likely at most ~100 different assets in one // wallet let pagination = PaginationRequest { @@ -322,12 +325,18 @@ impl Provider { contract: _, amount, asset_id, - }| (asset_id.to_string(), amount.try_into().unwrap()), + }| { + ( + AssetId::from_str(&asset_id.to_string()).unwrap(), + amount.try_into().unwrap(), + ) + }, ) .collect(); Ok(balances) } + // Get a Contract with fields: id, bytecode (as hex string) and salt, from the client pub async fn get_contract( &self, id: &Bech32ContractId, @@ -336,8 +345,11 @@ impl Provider { self.client.contract(&hex_id).await.map_err(Into::into) } - pub async fn get_transaction(&self, tx_id: &str) -> Result { - Ok(self.client.transaction(tx_id).await.unwrap().unwrap()) + pub async fn get_transaction( + &self, + tx_id: &str, + ) -> Result, ProviderError> { + self.client.transaction(tx_id).await.map_err(Into::into) } pub async fn get_transactions(&self) -> Result, ProviderError> { @@ -632,7 +644,6 @@ mod tests { async fn test_balances_api() -> Result<(), Error> { let (wallet, (coins, asset_ids), provider) = setup_provider_api_test().await; let asset_id = &asset_ids[0]; - let hex_asset_id = format!("{:#x}", asset_id); let wallet_balance_asset_id: u64 = coins .iter() .filter(|c| c.1.asset_id == *asset_id) @@ -641,7 +652,7 @@ mod tests { let wallet_balances = provider.get_balances(wallet.address()).await?; let expected_asset_balance = wallet_balances - .get(&hex_asset_id) + .get(asset_id) .expect("could not get balance for asset id"); assert_eq!(*expected_asset_balance, wallet_balance_asset_id); @@ -653,7 +664,6 @@ mod tests { async fn test_contract_balances_api() -> Result<(), Error> { let (wallet, (_, asset_ids), provider) = setup_provider_api_test().await; let asset_id = &asset_ids[0]; - let hex_asset_id = format!("{:#x}", asset_id); let contract_id = Contract::deploy( "../fuels/tests/contracts/contract_test/out/debug/contract_test.bin", @@ -671,7 +681,7 @@ mod tests { let contract_balances = provider.get_contract_balances(&contract_id).await?; let expected_asset_balance = contract_balances - .get(&hex_asset_id) + .get(asset_id) .expect("could not get balance for asset id"); assert_eq!(*expected_asset_balance, amount); @@ -720,11 +730,14 @@ mod tests { .transfer(wallet2.address(), 1, Default::default(), tx_params) .await?; - let expected_response = provider.get_transaction(&tx_id).await?; + let expected_tresponse = provider + .get_transaction(&tx_id) + .await? + .expect("could not find transaction with specified id"); - assert_eq!(expected_response.transaction.gas_limit(), gas_limit); - assert_eq!(expected_response.transaction.gas_price(), gas_price); - assert_eq!(expected_response.transaction.maturity(), maturity); + assert_eq!(expected_tresponse.transaction.gas_limit(), gas_limit); + assert_eq!(expected_tresponse.transaction.gas_price(), gas_price); + assert_eq!(expected_tresponse.transaction.maturity(), maturity); Ok(()) } @@ -783,9 +796,12 @@ mod tests { .transfer(wallet2.address(), 1, Default::default(), Default::default()) .await?; - if let TransactionStatus::Success { block_id, time, .. } = - provider.get_transaction(&tx_id).await?.status - { + let transaction_response = provider + .get_transaction(&tx_id) + .await? + .expect("could not find transaction with specified id"); + + if let TransactionStatus::Success { block_id, time, .. } = transaction_response.status { let expected_block = provider .get_block(&block_id) .await? diff --git a/packages/fuels-signers/src/wallet.rs b/packages/fuels-signers/src/wallet.rs index a376a0c38d..e72658aa87 100644 --- a/packages/fuels-signers/src/wallet.rs +++ b/packages/fuels-signers/src/wallet.rs @@ -214,7 +214,7 @@ impl Wallet { /// Get all the spendable balances of all assets for the wallet. This is different from getting /// the coins because we are only returning the sum of UTXOs coins amount and not the UTXOs /// coins themselves. - pub async fn get_balances(&self) -> Result, Error> { + pub async fn get_balances(&self) -> Result, Error> { self.get_provider()? .get_balances(&self.address) .await diff --git a/packages/fuels/tests/scripts.rs b/packages/fuels/tests/scripts.rs index 38fbbb5407..1cfaa09676 100644 --- a/packages/fuels/tests/scripts.rs +++ b/packages/fuels/tests/scripts.rs @@ -142,8 +142,7 @@ async fn test_script_interface() -> Result<(), Error> { .await?; assert_eq!(contract_balances.len(), 1); - let asset_id_key = format!("{:#x}", BASE_ASSET_ID); - let balance = contract_balances.get(&asset_id_key).unwrap(); + let balance = contract_balances.get(&BASE_ASSET_ID).unwrap(); assert_eq!(*balance, 100); Ok(()) diff --git a/packages/fuels/tests/wallets.rs b/packages/fuels/tests/wallets.rs index 79b78bf264..f548347e05 100644 --- a/packages/fuels/tests/wallets.rs +++ b/packages/fuels/tests/wallets.rs @@ -22,10 +22,9 @@ async fn test_wallet_balance_api_multi_asset() -> Result<(), Error> { let balance = wallet.get_asset_balance(&asset_id).await; assert_eq!(balance?, coins_per_asset * amount_per_coin); - let expected_key = format!("{:#x}", asset_id); - assert!(balances.contains_key(&expected_key)); + assert!(balances.contains_key(&asset_id)); assert_eq!( - *balances.get(&expected_key).unwrap(), + *balances.get(&asset_id).unwrap(), coins_per_asset * amount_per_coin ); } @@ -53,11 +52,10 @@ async fn test_wallet_balance_api_single_asset() -> Result<(), Error> { } let balances = wallet.get_balances().await?; - let expected_key = format!("{:#x}", BASE_ASSET_ID); assert_eq!(balances.len(), 1); // only the base asset - assert!(balances.contains_key(&expected_key)); + assert!(balances.contains_key(&BASE_ASSET_ID)); assert_eq!( - *balances.get(&expected_key).unwrap(), + *balances.get(&BASE_ASSET_ID).unwrap(), number_of_coins * amount_per_coin ); From d3189be4a69f7017b102120553f0d7eb977458e3 Mon Sep 17 00:00:00 2001 From: hal3e Date: Mon, 24 Oct 2022 12:24:27 +0200 Subject: [PATCH 04/17] fix merge error --- packages/fuels-core/src/code_gen/abigen.rs | 4 ++-- packages/fuels/tests/contracts.rs | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/fuels-core/src/code_gen/abigen.rs b/packages/fuels-core/src/code_gen/abigen.rs index 6bf64130f1..6e0112de2f 100644 --- a/packages/fuels-core/src/code_gen/abigen.rs +++ b/packages/fuels-core/src/code_gen/abigen.rs @@ -111,7 +111,7 @@ impl Abigen { use fuels::core::code_gen::function_selector::resolve_fn_selector; use fuels::core::types::*; use fuels::signers::WalletUnlocked; - use fuels::tx::{ContractId, Address, Receipt}; + use fuels::tx::{ContractId, Address, Receipt, AssetId}; use fuels::types::bech32::Bech32ContractId; use fuels::types::ResolvedLog; use fuels::types::errors::Error as SDKError; @@ -147,7 +147,7 @@ impl Abigen { Ok(Self { contract_id: self.contract_id.clone(), wallet: wallet, logs_lookup: self.logs_lookup.clone() }) } - pub async fn get_balances(&self) -> Result, SDKError> { + pub async fn get_balances(&self) -> Result, SDKError> { self.wallet.get_provider()?.get_contract_balances(&self.contract_id).await.map_err(Into::into) } diff --git a/packages/fuels/tests/contracts.rs b/packages/fuels/tests/contracts.rs index 7977507b36..ebb4c756a4 100644 --- a/packages/fuels/tests/contracts.rs +++ b/packages/fuels/tests/contracts.rs @@ -612,8 +612,7 @@ async fn test_contract_instance_get_balances() -> Result<(), Error> { let contract_balances = contract_instance.get_balances().await?; assert_eq!(contract_balances.len(), 1); - let random_asset_id_key = format!("{:#x}", random_asset_id); - let random_asset_balance = contract_balances.get(&random_asset_id_key).unwrap(); + let random_asset_balance = contract_balances.get(&random_asset_id).unwrap(); assert_eq!(*random_asset_balance, amount); Ok(()) From fc3611d38829718a02efd9ebfa159109722768fb Mon Sep 17 00:00:00 2001 From: hal3e Date: Mon, 24 Oct 2022 12:39:46 +0200 Subject: [PATCH 05/17] fix clippy --- packages/fuels/tests/contracts.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/fuels/tests/contracts.rs b/packages/fuels/tests/contracts.rs index ebb4c756a4..dc519ce796 100644 --- a/packages/fuels/tests/contracts.rs +++ b/packages/fuels/tests/contracts.rs @@ -612,7 +612,7 @@ async fn test_contract_instance_get_balances() -> Result<(), Error> { let contract_balances = contract_instance.get_balances().await?; assert_eq!(contract_balances.len(), 1); - let random_asset_balance = contract_balances.get(&random_asset_id).unwrap(); + let random_asset_balance = contract_balances.get(random_asset_id).unwrap(); assert_eq!(*random_asset_balance, amount); Ok(()) From a99089a26593fa874abf66435c3dfe5ee7e01844 Mon Sep 17 00:00:00 2001 From: hal3e Date: Mon, 24 Oct 2022 21:24:03 +0200 Subject: [PATCH 06/17] POC of new provider api --- packages/fuels-signers/src/provider.rs | 168 ++++++++++++++++++++++++- 1 file changed, 166 insertions(+), 2 deletions(-) diff --git a/packages/fuels-signers/src/provider.rs b/packages/fuels-signers/src/provider.rs index f8e9359c93..f44a7621b5 100644 --- a/packages/fuels-signers/src/provider.rs +++ b/packages/fuels-signers/src/provider.rs @@ -1,4 +1,4 @@ -use std::io; +use std::{fmt::Debug, future::Future, io}; #[cfg(feature = "fuel-core")] use fuel_core::service::{Config, FuelService}; @@ -10,7 +10,7 @@ use fuel_gql_client::{ contract::ContractBalance, message::Message, node_info::NodeInfo, resource::Resource, }, types::{TransactionResponse, TransactionStatus}, - FuelClient, PageDirection, PaginationRequest, + FuelClient, PageDirection, PaginatedResult, PaginationRequest, }, fuel_tx::{Receipt, Transaction, TransactionFee, UtxoId}, fuel_types::{AssetId, ContractId}, @@ -44,6 +44,60 @@ impl From for Error { } } +type BoxFutureResult<'a, U> = Box> + 'a + Unpin>; +type BoxFnFuture<'a, T, U> = Box) -> BoxFutureResult<'a, U> + 'a>; + +pub struct ProviderPaginationCaller<'a, T, U> +where + T: Debug, +{ + /// The cursor returned from a previous query to indicate an offset + pub cursor: Option, + /// The number of results to take + pub results: usize, + /// The direction of the query (e.g. asc, desc order). + pub direction: PageDirection, + // The function to call + pub function: BoxFnFuture<'a, T, U>, +} + +impl<'a, T, U> ProviderPaginationCaller<'a, T, U> +where + T: Debug, +{ + fn new( + results: usize, + function: impl Fn(PaginationRequest) -> BoxFutureResult<'a, U> + 'a, + ) -> Self { + ProviderPaginationCaller { + cursor: None::, + results, + direction: PageDirection::Forward, + function: Box::new(function), + } + } + + pub fn with_cursor(mut self, cursor: Option) -> Self { + self.cursor = cursor; + self + } + + pub fn with_direction(mut self, direction: PageDirection) -> Self { + self.direction = direction; + self + } + + pub async fn call(self) -> Result { + let pagination = PaginationRequest { + cursor: self.cursor, + results: self.results, + direction: self.direction, + }; + + (self.function)(pagination).await + } +} + /// Encapsulates common client operations in the SDK. /// Note that you may also use `client`, which is an instance /// of `FuelClient`, directly, which provides a broader API. @@ -207,6 +261,28 @@ impl Provider { Ok(coins) } + /// Gets all coins owned by address `from`, with asset ID `asset_id`, *even spent ones*. This + /// returns actual coins (UTXOs). + pub fn get_coins_new<'a>( + &'a self, + from: &'a Bech32Address, + asset_id: &'a AssetId, + num_results: usize, + ) -> ProviderPaginationCaller> { + ProviderPaginationCaller::new(num_results, |pr: PaginationRequest| { + let hash = from.hash().to_string(); + let asset_id_string = asset_id.to_string(); + let provider_clone = self.clone(); + Box::new(Box::pin(async move { + provider_clone + .client + .coins(&hash, Some(&asset_id_string), pr) + .await + .map_err(Into::into) + })) + }) + } + /// Get some spendable coins of asset `asset_id` for address `from` that add up at least to /// amount `amount`. The returned coins (UTXOs) are actual coins that can be spent. The number /// of coins (UXTOs) is optimized to prevent dust accumulation. @@ -300,6 +376,40 @@ impl Provider { Ok(balances) } + /// Get all the spendable balances of all assets for address `address`. This is different from + /// 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 fn get_balances_new<'a>( + &'a self, + from: &'a Bech32Address, + num_results: usize, + ) -> ProviderPaginationCaller> { + ProviderPaginationCaller::new(num_results, |pr: PaginationRequest| { + let hash = from.hash().to_string(); + let provider_clone = self.clone(); + Box::new(Box::pin(async move { + let balances_vec = provider_clone.client.balances(&hash, pr).await?.results; + + let balances = balances_vec + .into_iter() + .map( + |Balance { + owner: _, + amount, + asset_id, + }| { + ( + AssetId::from_str(&asset_id.to_string()).unwrap(), + amount.try_into().unwrap(), + ) + }, + ) + .collect(); + Ok(balances) + })) + }) + } + /// Get all balances of all assets for the contract with id `contract_id`. pub async fn get_contract_balances( &self, @@ -515,6 +625,7 @@ mod tests { use fuel_core::model::Coin; use fuel_gql_client::client::types::TransactionStatus; + use fuel_gql_client::client::PageDirection; use fuel_gql_client::fuel_tx::UtxoId; use fuels::prelude::*; @@ -839,4 +950,57 @@ mod tests { Ok(()) } + + #[tokio::test] + async fn test_get_coins_new_api() -> Result<(), Error> { + let (wallet, (_, asset_ids), provider) = setup_provider_api_test().await; + let asset_id = &asset_ids[0]; + + let pagineted_result = provider + .get_coins_new(wallet.address(), asset_id, 4) + .call() + .await?; + dbg!(pagineted_result.results.len()); + + let pagineted_result = provider + .get_coins_new(wallet.address(), asset_id, 2) + .with_cursor(None) + .with_direction(PageDirection::Forward) + .call() + .await?; + dbg!(pagineted_result.results.len()); + + let pagineted_result = provider + .get_coins_new(wallet.address(), asset_id, 2) + .with_cursor(pagineted_result.cursor) + .with_direction(PageDirection::Backward) + .call() + .await?; + dbg!(pagineted_result.results.len()); + + Ok(()) + } + + #[tokio::test] + async fn test_balances_new_api() -> Result<(), Error> { + let (wallet, (coins, asset_ids), provider) = setup_provider_api_test().await; + let asset_id = &asset_ids[0]; + let wallet_balance_asset_id: u64 = coins + .iter() + .filter(|c| c.1.asset_id == *asset_id) + .map(|c| c.1.amount) + .sum(); + + let wallet_balances = provider + .get_balances_new(wallet.address(), 100) + .call() + .await?; + let asset_balance = wallet_balances + .get(asset_id) + .expect("could not get balance for asset id"); + + assert_eq!(*asset_balance, wallet_balance_asset_id); + + Ok(()) + } } From 890f9a89a931f7f68528eaf66f22b5c8691a8741 Mon Sep 17 00:00:00 2001 From: hal3e Date: Mon, 24 Oct 2022 21:55:18 +0200 Subject: [PATCH 07/17] fix typo --- packages/fuels-signers/src/provider.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/fuels-signers/src/provider.rs b/packages/fuels-signers/src/provider.rs index f44a7621b5..83f625ea05 100644 --- a/packages/fuels-signers/src/provider.rs +++ b/packages/fuels-signers/src/provider.rs @@ -44,8 +44,8 @@ impl From for Error { } } -type BoxFutureResult<'a, U> = Box> + 'a + Unpin>; type BoxFnFuture<'a, T, U> = Box) -> BoxFutureResult<'a, U> + 'a>; +type BoxFutureResult<'a, U> = Box> + 'a + Unpin>; pub struct ProviderPaginationCaller<'a, T, U> where @@ -956,27 +956,27 @@ mod tests { let (wallet, (_, asset_ids), provider) = setup_provider_api_test().await; let asset_id = &asset_ids[0]; - let pagineted_result = provider + let paginated_result = provider .get_coins_new(wallet.address(), asset_id, 4) .call() .await?; - dbg!(pagineted_result.results.len()); + dbg!(paginated_result.results.len()); - let pagineted_result = provider + let paginated_result = provider .get_coins_new(wallet.address(), asset_id, 2) .with_cursor(None) .with_direction(PageDirection::Forward) .call() .await?; - dbg!(pagineted_result.results.len()); + dbg!(paginated_result.results.len()); - let pagineted_result = provider + let paginated_result = provider .get_coins_new(wallet.address(), asset_id, 2) - .with_cursor(pagineted_result.cursor) + .with_cursor(paginated_result.cursor) .with_direction(PageDirection::Backward) .call() .await?; - dbg!(pagineted_result.results.len()); + dbg!(paginated_result.results.len()); Ok(()) } From a41e1c7a05cb952967cf78f9846f389b1ab33642 Mon Sep 17 00:00:00 2001 From: hal3e Date: Thu, 27 Oct 2022 14:27:21 +0200 Subject: [PATCH 08/17] convert all API calls --- packages/fuels-signers/Cargo.toml | 1 + packages/fuels-signers/src/provider.rs | 254 +++++++++---------------- packages/fuels-signers/src/wallet.rs | 26 ++- 3 files changed, 103 insertions(+), 178 deletions(-) diff --git a/packages/fuels-signers/Cargo.toml b/packages/fuels-signers/Cargo.toml index aa119df73e..ad155f9d5a 100644 --- a/packages/fuels-signers/Cargo.toml +++ b/packages/fuels-signers/Cargo.toml @@ -25,6 +25,7 @@ serde = { version = "1.0.124", default-features = true, features = ["derive"] } sha2 = { version = "0.9.8", default-features = false } thiserror = { version = "1.0.30", default-features = false } tokio = { version = "1.10.1", features = ["full"] } +futures = "0.3.21" [dev-dependencies] fuels = { path = "../fuels" } diff --git a/packages/fuels-signers/src/provider.rs b/packages/fuels-signers/src/provider.rs index 83f625ea05..854f2f9065 100644 --- a/packages/fuels-signers/src/provider.rs +++ b/packages/fuels-signers/src/provider.rs @@ -1,4 +1,5 @@ -use std::{fmt::Debug, future::Future, io}; +use futures::future::BoxFuture; +use std::{io, sync::Arc}; #[cfg(feature = "fuel-core")] use fuel_core::service::{Config, FuelService}; @@ -44,30 +45,40 @@ impl From for Error { } } -type BoxFnFuture<'a, T, U> = Box) -> BoxFutureResult<'a, U> + 'a>; -type BoxFutureResult<'a, U> = Box> + 'a + Unpin>; +type BoxFnFuture<'a, T, U> = Box) -> BoxFutureResult<'a, T, U> + 'a>; +type BoxFutureResult<'a, T, U> = + BoxFuture<'a, Result, ProviderError>>; -pub struct ProviderPaginationCaller<'a, T, U> -where - T: Debug, -{ - /// The cursor returned from a previous query to indicate an offset +pub struct ProviderPaginationCaller<'a, T, U> { pub cursor: Option, - /// The number of results to take pub results: usize, - /// The direction of the query (e.g. asc, desc order). pub direction: PageDirection, - // The function to call pub function: BoxFnFuture<'a, T, U>, } -impl<'a, T, U> ProviderPaginationCaller<'a, T, U> -where - T: Debug, -{ +#[derive(Debug)] +pub struct ProviderPaginatedResult { + pub cursor: Option, + pub results: U, + pub has_next_page: bool, + pub has_previous_page: bool, +} + +impl From> for ProviderPaginatedResult> { + fn from(pr: PaginatedResult) -> Self { + Self { + cursor: pr.cursor, + results: pr.results, + has_next_page: pr.has_next_page, + has_previous_page: pr.has_previous_page, + } + } +} + +impl<'a, T, U> ProviderPaginationCaller<'a, T, U> { fn new( results: usize, - function: impl Fn(PaginationRequest) -> BoxFutureResult<'a, U> + 'a, + function: impl Fn(PaginationRequest) -> BoxFutureResult<'a, T, U> + 'a, ) -> Self { ProviderPaginationCaller { cursor: None::, @@ -82,12 +93,17 @@ where self } - pub fn with_direction(mut self, direction: PageDirection) -> Self { - self.direction = direction; + pub fn forward(mut self) -> Self { + self.direction = PageDirection::Forward; self } - pub async fn call(self) -> Result { + pub fn backward(mut self) -> Self { + self.direction = PageDirection::Backward; + self + } + + pub async fn call(self) -> Result, ProviderError> { let pagination = PaginationRequest { cursor: self.cursor, results: self.results, @@ -228,58 +244,26 @@ impl Provider { /// Gets all coins owned by address `from`, with asset ID `asset_id`, *even spent ones*. This /// returns actual coins (UTXOs). - pub async fn get_coins( + pub fn get_coins( &self, from: &Bech32Address, asset_id: &AssetId, - ) -> Result, ProviderError> { - let mut coins: Vec = vec![]; - - let mut cursor = None; - - loop { - let res = self - .client - .coins( - &from.hash().to_string(), - Some(&asset_id.to_string()), - PaginationRequest { - cursor: cursor.clone(), - results: 100, - direction: PageDirection::Forward, - }, - ) - .await?; - - if res.results.is_empty() { - break; - } - coins.extend(res.results); - cursor = res.cursor; - } - - Ok(coins) - } - - /// Gets all coins owned by address `from`, with asset ID `asset_id`, *even spent ones*. This - /// returns actual coins (UTXOs). - pub fn get_coins_new<'a>( - &'a self, - from: &'a Bech32Address, - asset_id: &'a AssetId, num_results: usize, - ) -> ProviderPaginationCaller> { - ProviderPaginationCaller::new(num_results, |pr: PaginationRequest| { - let hash = from.hash().to_string(); - let asset_id_string = asset_id.to_string(); - let provider_clone = self.clone(); - Box::new(Box::pin(async move { - provider_clone + ) -> ProviderPaginationCaller> { + let hash = Arc::new(from.hash().to_string()); + let asset_id = Arc::new(asset_id.to_string()); + let provider = Arc::new(self.clone()); + ProviderPaginationCaller::new(num_results, move |pr: PaginationRequest<_>| { + let hash = Arc::clone(&hash); + let asset_id_string = Arc::clone(&asset_id); + let provider_clone = Arc::clone(&provider); + Box::pin(async move { + let response = provider_clone .client .coins(&hash, Some(&asset_id_string), pr) - .await - .map_err(Into::into) - })) + .await?; + Ok(response.into()) + }) }) } @@ -342,55 +326,21 @@ impl Provider { /// Get all the spendable balances of all assets for address `address`. This is different from /// 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( + pub fn get_balances( &self, - address: &Bech32Address, - ) -> Result, ProviderError> { - // 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 - .client - .balances(&address.hash().to_string(), pagination) - .await? - .results; - let balances = balances_vec - .into_iter() - .map( - |Balance { - owner: _, - amount, - asset_id, - }| { - ( - AssetId::from_str(&asset_id.to_string()).unwrap(), - amount.try_into().unwrap(), - ) - }, - ) - .collect(); - Ok(balances) - } - - /// Get all the spendable balances of all assets for address `address`. This is different from - /// 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 fn get_balances_new<'a>( - &'a self, - from: &'a Bech32Address, + from: &Bech32Address, num_results: usize, ) -> ProviderPaginationCaller> { - ProviderPaginationCaller::new(num_results, |pr: PaginationRequest| { - let hash = from.hash().to_string(); - let provider_clone = self.clone(); - Box::new(Box::pin(async move { - let balances_vec = provider_clone.client.balances(&hash, pr).await?.results; - - let balances = balances_vec + let hash = Arc::new(from.hash().to_string()); + let provider = Arc::new(self.clone()); + ProviderPaginationCaller::new(num_results, move |pr: PaginationRequest<_>| { + let hash = Arc::clone(&hash); + let provider_clone = Arc::clone(&provider); + Box::pin(async move { + let response = provider_clone.client.balances(&hash, pr).await?; + + let balances = response + .results .into_iter() .map( |Balance { @@ -405,8 +355,14 @@ impl Provider { }, ) .collect(); - Ok(balances) - })) + + Ok(ProviderPaginatedResult { + cursor: response.cursor, + results: balances, + has_next_page: response.has_next_page, + has_previous_page: response.has_previous_page, + }) + }) }) } @@ -625,7 +581,6 @@ mod tests { use fuel_core::model::Coin; use fuel_gql_client::client::types::TransactionStatus; - use fuel_gql_client::client::PageDirection; use fuel_gql_client::fuel_tx::UtxoId; use fuels::prelude::*; @@ -670,7 +625,11 @@ mod tests { .map(|c| format!("{:#x}", c.0)) .collect(); - let expected_coins = provider.get_coins(wallet.address(), asset_id).await?; + let expected_coins = provider + .get_coins(wallet.address(), asset_id, 12) + .call() + .await? + .results; assert_eq!(expected_coins.len(), utxo_ids_of_coins_with_asset_id.len()); assert!(expected_coins @@ -761,7 +720,11 @@ mod tests { .map(|c| c.1.amount) .sum(); - let wallet_balances = provider.get_balances(wallet.address()).await?; + let wallet_balances = provider + .get_balances(wallet.address(), 12) + .call() + .await? + .results; let expected_asset_balance = wallet_balances .get(asset_id) .expect("could not get balance for asset id"); @@ -950,57 +913,10 @@ mod tests { Ok(()) } - - #[tokio::test] - async fn test_get_coins_new_api() -> Result<(), Error> { - let (wallet, (_, asset_ids), provider) = setup_provider_api_test().await; - let asset_id = &asset_ids[0]; - - let paginated_result = provider - .get_coins_new(wallet.address(), asset_id, 4) - .call() - .await?; - dbg!(paginated_result.results.len()); - - let paginated_result = provider - .get_coins_new(wallet.address(), asset_id, 2) - .with_cursor(None) - .with_direction(PageDirection::Forward) - .call() - .await?; - dbg!(paginated_result.results.len()); - - let paginated_result = provider - .get_coins_new(wallet.address(), asset_id, 2) - .with_cursor(paginated_result.cursor) - .with_direction(PageDirection::Backward) - .call() - .await?; - dbg!(paginated_result.results.len()); - - Ok(()) - } - - #[tokio::test] - async fn test_balances_new_api() -> Result<(), Error> { - let (wallet, (coins, asset_ids), provider) = setup_provider_api_test().await; - let asset_id = &asset_ids[0]; - let wallet_balance_asset_id: u64 = coins - .iter() - .filter(|c| c.1.asset_id == *asset_id) - .map(|c| c.1.amount) - .sum(); - - let wallet_balances = provider - .get_balances_new(wallet.address(), 100) - .call() - .await?; - let asset_balance = wallet_balances - .get(asset_id) - .expect("could not get balance for asset id"); - - assert_eq!(*asset_balance, wallet_balance_asset_id); - - Ok(()) - } } + +// pub async fn get_contract_balances( +// pub async fn get_transactions(&self) -> Result, ProviderError> { +// pub async fn get_transactions_by_owner( +// pub async fn get_messages(&self, from: &Bech32Address) -> Result, ProviderError> { +// pub async fn get_blocks(&self) -> Result, ProviderError> { diff --git a/packages/fuels-signers/src/wallet.rs b/packages/fuels-signers/src/wallet.rs index e72658aa87..20903aa0de 100644 --- a/packages/fuels-signers/src/wallet.rs +++ b/packages/fuels-signers/src/wallet.rs @@ -180,11 +180,17 @@ impl Wallet { /// Gets all coins of asset `asset_id` owned by the wallet, *even spent ones* (this is useful /// for some particular cases, but in general, you should use `get_spendable_coins`). This /// returns actual coins (UTXOs). - pub async fn get_coins(&self, asset_id: AssetId) -> Result, Error> { + pub async fn get_coins( + &self, + asset_id: AssetId, + num_results: usize, + ) -> Result, Error> { Ok(self .get_provider()? - .get_coins(&self.address, &asset_id) - .await?) + .get_coins(&self.address, &asset_id, num_results) + .call() + .await? + .results) } /// Get some spendable coins of asset `asset_id` owned by the wallet that add up at least to @@ -214,11 +220,13 @@ impl Wallet { /// Get all the spendable balances of all assets for the wallet. This is different from getting /// the coins because we are only returning the sum of UTXOs coins amount and not the UTXOs /// coins themselves. - pub async fn get_balances(&self) -> Result, Error> { - self.get_provider()? - .get_balances(&self.address) - .await - .map_err(Into::into) + pub async fn get_balances(&self, num_results: usize) -> Result, Error> { + Ok(self + .get_provider()? + .get_balances(&self.address, num_results) + .call() + .await? + .results) } pub async fn get_messages(&self) -> Result, Error> { @@ -594,7 +602,7 @@ impl WalletUnlocked { /// .await /// .unwrap(); /// - /// let wallet_2_final_coins = wallet_2.get_coins(BASE_ASSET_ID).await.unwrap(); + /// let wallet_2_final_coins = wallet_2.get_coins(BASE_ASSET_ID, 4).await.unwrap(); /// /// // Check that wallet two now has two coins /// assert_eq!(wallet_2_final_coins.len(), 2); From a8a27e3393a8396adff49570f4fd0f56dc599b29 Mon Sep 17 00:00:00 2001 From: hal3e Date: Thu, 27 Oct 2022 19:09:53 +0200 Subject: [PATCH 09/17] fix merge --- packages/fuels-signers/src/lib.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/fuels-signers/src/lib.rs b/packages/fuels-signers/src/lib.rs index ef637f8133..5808be6894 100644 --- a/packages/fuels-signers/src/lib.rs +++ b/packages/fuels-signers/src/lib.rs @@ -158,8 +158,8 @@ mod tests { wallet_1.set_provider(provider.clone()); wallet_2.set_provider(provider); - let wallet_1_initial_coins = wallet_1.get_coins(BASE_ASSET_ID).await?; - let wallet_2_initial_coins = wallet_2.get_coins(BASE_ASSET_ID).await?; + let wallet_1_initial_coins = wallet_1.get_coins(BASE_ASSET_ID, 1).await?; + let wallet_2_initial_coins = wallet_2.get_coins(BASE_ASSET_ID, 1).await?; // Check initial wallet state. assert_eq!(wallet_1_initial_coins.len(), 1); @@ -193,8 +193,8 @@ mod tests { assert_eq!(res.transaction.maturity(), maturity); let wallet_1_spendable_coins = wallet_1.get_spendable_coins(&BASE_ASSET_ID, 0).await?; - let wallet_1_all_coins = wallet_1.get_coins(BASE_ASSET_ID).await?; - let wallet_2_all_coins = wallet_2.get_coins(BASE_ASSET_ID).await?; + let wallet_1_all_coins = wallet_1.get_coins(BASE_ASSET_ID, 2).await?; + let wallet_2_all_coins = wallet_2.get_coins(BASE_ASSET_ID, 2).await?; // wallet_1 has now only 1 spent coin (so 0 spendable) assert_eq!(wallet_1_spendable_coins.len(), 0); @@ -213,7 +213,7 @@ mod tests { .await; assert!(response.is_err()); - let wallet_2_coins = wallet_2.get_coins(BASE_ASSET_ID).await?; + let wallet_2_coins = wallet_2.get_coins(BASE_ASSET_ID, 2).await?; assert_eq!(wallet_2_coins.len(), 2); // Not changed Ok(()) } @@ -235,8 +235,8 @@ mod tests { wallet_1.set_provider(provider.clone()); wallet_2.set_provider(provider); - let wallet_1_initial_coins = wallet_1.get_coins(BASE_ASSET_ID).await?; - let wallet_2_initial_coins = wallet_2.get_coins(BASE_ASSET_ID).await?; + let wallet_1_initial_coins = wallet_1.get_coins(BASE_ASSET_ID, 1).await?; + let wallet_2_initial_coins = wallet_2.get_coins(BASE_ASSET_ID, 1).await?; assert_eq!(wallet_1_initial_coins.len(), 1); assert_eq!(wallet_2_initial_coins.len(), 1); @@ -251,13 +251,13 @@ mod tests { ) .await?; - let wallet_1_final_coins = wallet_1.get_coins(BASE_ASSET_ID).await?; + let wallet_1_final_coins = wallet_1.get_coins(BASE_ASSET_ID, 2).await?; // Assert that we've sent 2 from wallet 1, resulting in an amount of 3 in wallet 1. let resulting_amount = wallet_1_final_coins.first().unwrap(); assert_eq!(resulting_amount.amount.0, 3); - let wallet_2_final_coins = wallet_2.get_coins(BASE_ASSET_ID).await?; + let wallet_2_final_coins = wallet_2.get_coins(BASE_ASSET_ID, 2).await?; assert_eq!(wallet_2_final_coins.len(), 2); // Check that wallet 2's amount is 7: From 9bafb430fc4cc5be820142f92828f4cd83e6b402 Mon Sep 17 00:00:00 2001 From: hal3e Date: Fri, 28 Oct 2022 12:58:29 +0200 Subject: [PATCH 10/17] change API to new style --- examples/cookbook/src/lib.rs | 12 +- examples/wallets/src/lib.rs | 24 +- packages/fuels-core/src/code_gen/abigen.rs | 6 +- packages/fuels-signers/src/lib.rs | 18 +- packages/fuels-signers/src/provider.rs | 241 ++++++++++----------- packages/fuels-signers/src/wallet.rs | 51 +++-- packages/fuels-test-helpers/src/signers.rs | 6 +- packages/fuels/tests/contracts.rs | 4 +- packages/fuels/tests/scripts.rs | 12 +- packages/fuels/tests/wallets.rs | 8 +- 10 files changed, 210 insertions(+), 172 deletions(-) diff --git a/examples/cookbook/src/lib.rs b/examples/cookbook/src/lib.rs index 92c96aeeb7..1af532cbac 100644 --- a/examples/cookbook/src/lib.rs +++ b/examples/cookbook/src/lib.rs @@ -135,7 +135,11 @@ mod tests { // ANCHOR_END: transfer_multiple_setup // ANCHOR: transfer_multiple_inout - let balances = wallet_1.get_balances(NUM_ASSETS * NUM_COINS).await?; + let balances = wallet_1 + .get_balances(NUM_ASSETS * NUM_COINS)? + .call() + .await? + .results; let mut inputs = vec![]; let mut outputs = vec![]; @@ -158,7 +162,11 @@ mod tests { let _receipts = provider.send_transaction(&tx).await?; - let balances = wallet_2.get_balances(NUM_ASSETS * NUM_COINS).await?; + let balances = wallet_2 + .get_balances(NUM_ASSETS * NUM_COINS)? + .call() + .await? + .results; assert_eq!(balances.len(), (NUM_ASSETS - 1) as usize); for (_, balance) in balances { diff --git a/examples/wallets/src/lib.rs b/examples/wallets/src/lib.rs index 2e8c2e823d..5b9a9645e5 100644 --- a/examples/wallets/src/lib.rs +++ b/examples/wallets/src/lib.rs @@ -134,7 +134,11 @@ mod tests { .transfer(wallets[1].address(), 1, asset_id, TxParameters::default()) .await?; - let wallet_2_final_coins = wallets[1].get_coins(BASE_ASSET_ID, 2).await?; + let wallet_2_final_coins = wallets[1] + .get_coins(BASE_ASSET_ID, 2)? + .call() + .await? + .results; // Check that wallet 2 now has 2 coins assert_eq!(wallet_2_final_coins.len(), 2); @@ -182,8 +186,10 @@ mod tests { // Check the current balance of the contract with id 'contract_id' let contract_balances = wallet .get_provider()? - .get_contract_balances(&contract_id) - .await?; + .get_contract_balances(&contract_id, 1) + .call() + .await? + .results; assert!(contract_balances.is_empty()); // Transfer an amount of 300 to the contract @@ -196,8 +202,10 @@ mod tests { // Check that the contract now has 1 coin let contract_balances = wallet .get_provider()? - .get_contract_balances(&contract_id) - .await?; + .get_contract_balances(&contract_id, 1) + .call() + .await? + .results; assert_eq!(contract_balances.len(), 1); let random_asset_balance = contract_balances.get(&random_asset_id).unwrap(); @@ -317,7 +325,11 @@ mod tests { let balance: u64 = wallet.get_asset_balance(&asset_id).await?; // ANCHOR_END: get_asset_balance // ANCHOR: get_balances - let balances: HashMap = wallet.get_balances(DEFAULT_NUM_COINS).await?; + let balances: HashMap = wallet + .get_balances(DEFAULT_NUM_COINS)? + .call() + .await? + .results; // ANCHOR_END: get_balances // ANCHOR: get_balance_hashmap diff --git a/packages/fuels-core/src/code_gen/abigen.rs b/packages/fuels-core/src/code_gen/abigen.rs index 7ab4374750..99ab391761 100644 --- a/packages/fuels-core/src/code_gen/abigen.rs +++ b/packages/fuels-core/src/code_gen/abigen.rs @@ -110,7 +110,7 @@ impl Abigen { use fuels::core::abi_decoder::ABIDecoder; use fuels::core::code_gen::function_selector::resolve_fn_selector; use fuels::core::types::*; - use fuels::signers::WalletUnlocked; + use fuels::signers::{provider::Paginator, WalletUnlocked}; use fuels::tx::{ContractId, Address, Receipt, AssetId}; use fuels::types::bech32::Bech32ContractId; use fuels::types::ResolvedLog; @@ -147,8 +147,8 @@ impl Abigen { Ok(Self { contract_id: self.contract_id.clone(), wallet: wallet, logs_lookup: self.logs_lookup.clone() }) } - pub async fn get_balances(&self) -> Result, SDKError> { - self.wallet.get_provider()?.get_contract_balances(&self.contract_id).await.map_err(Into::into) + pub fn get_balances(&self, num_results: u64) -> Result>, SDKError> { + Ok(self.wallet.get_provider()?.get_contract_balances(&self.contract_id, num_results)) } pub fn logs_with_type(&self, receipts: &[Receipt]) -> Result, SDKError> { diff --git a/packages/fuels-signers/src/lib.rs b/packages/fuels-signers/src/lib.rs index 5808be6894..7dabdd27a2 100644 --- a/packages/fuels-signers/src/lib.rs +++ b/packages/fuels-signers/src/lib.rs @@ -158,8 +158,8 @@ mod tests { wallet_1.set_provider(provider.clone()); wallet_2.set_provider(provider); - let wallet_1_initial_coins = wallet_1.get_coins(BASE_ASSET_ID, 1).await?; - let wallet_2_initial_coins = wallet_2.get_coins(BASE_ASSET_ID, 1).await?; + let wallet_1_initial_coins = wallet_1.get_coins(BASE_ASSET_ID, 1)?.call().await?.results; + let wallet_2_initial_coins = wallet_2.get_coins(BASE_ASSET_ID, 1)?.call().await?.results; // Check initial wallet state. assert_eq!(wallet_1_initial_coins.len(), 1); @@ -193,8 +193,8 @@ mod tests { assert_eq!(res.transaction.maturity(), maturity); let wallet_1_spendable_coins = wallet_1.get_spendable_coins(&BASE_ASSET_ID, 0).await?; - let wallet_1_all_coins = wallet_1.get_coins(BASE_ASSET_ID, 2).await?; - let wallet_2_all_coins = wallet_2.get_coins(BASE_ASSET_ID, 2).await?; + let wallet_1_all_coins = wallet_1.get_coins(BASE_ASSET_ID, 2)?.call().await?.results; + let wallet_2_all_coins = wallet_2.get_coins(BASE_ASSET_ID, 2)?.call().await?.results; // wallet_1 has now only 1 spent coin (so 0 spendable) assert_eq!(wallet_1_spendable_coins.len(), 0); @@ -213,7 +213,7 @@ mod tests { .await; assert!(response.is_err()); - let wallet_2_coins = wallet_2.get_coins(BASE_ASSET_ID, 2).await?; + let wallet_2_coins = wallet_2.get_coins(BASE_ASSET_ID, 2)?.call().await?.results; assert_eq!(wallet_2_coins.len(), 2); // Not changed Ok(()) } @@ -235,8 +235,8 @@ mod tests { wallet_1.set_provider(provider.clone()); wallet_2.set_provider(provider); - let wallet_1_initial_coins = wallet_1.get_coins(BASE_ASSET_ID, 1).await?; - let wallet_2_initial_coins = wallet_2.get_coins(BASE_ASSET_ID, 1).await?; + let wallet_1_initial_coins = wallet_1.get_coins(BASE_ASSET_ID, 1)?.call().await?.results; + let wallet_2_initial_coins = wallet_2.get_coins(BASE_ASSET_ID, 1)?.call().await?.results; assert_eq!(wallet_1_initial_coins.len(), 1); assert_eq!(wallet_2_initial_coins.len(), 1); @@ -251,13 +251,13 @@ mod tests { ) .await?; - let wallet_1_final_coins = wallet_1.get_coins(BASE_ASSET_ID, 2).await?; + let wallet_1_final_coins = wallet_1.get_coins(BASE_ASSET_ID, 2)?.call().await?.results; // Assert that we've sent 2 from wallet 1, resulting in an amount of 3 in wallet 1. let resulting_amount = wallet_1_final_coins.first().unwrap(); assert_eq!(resulting_amount.amount.0, 3); - let wallet_2_final_coins = wallet_2.get_coins(BASE_ASSET_ID, 2).await?; + let wallet_2_final_coins = wallet_2.get_coins(BASE_ASSET_ID, 2)?.call().await?.results; assert_eq!(wallet_2_final_coins.len(), 2); // Check that wallet 2's amount is 7: diff --git a/packages/fuels-signers/src/provider.rs b/packages/fuels-signers/src/provider.rs index c441605690..7b8c61e930 100644 --- a/packages/fuels-signers/src/provider.rs +++ b/packages/fuels-signers/src/provider.rs @@ -46,10 +46,9 @@ impl From for Error { } type BoxFnFuture<'a, T, U> = Box) -> BoxFutureResult<'a, T, U> + 'a>; -type BoxFutureResult<'a, T, U> = - BoxFuture<'a, Result, ProviderError>>; +type BoxFutureResult<'a, T, U> = BoxFuture<'a, Result, ProviderError>>; -pub struct ProviderPaginationCaller<'a, T, U> { +pub struct Paginator<'a, T, U> { pub cursor: Option, pub results: usize, pub direction: PageDirection, @@ -57,14 +56,14 @@ pub struct ProviderPaginationCaller<'a, T, U> { } #[derive(Debug)] -pub struct ProviderPaginatedResult { +pub struct Page { pub cursor: Option, pub results: U, pub has_next_page: bool, pub has_previous_page: bool, } -impl From> for ProviderPaginatedResult> { +impl From> for Page> { fn from(pr: PaginatedResult) -> Self { Self { cursor: pr.cursor, @@ -75,12 +74,12 @@ impl From> for ProviderPaginatedResult> { } } -impl<'a, T, U> ProviderPaginationCaller<'a, T, U> { +impl<'a, T, U> Paginator<'a, T, U> { fn new( results: u64, function: impl Fn(PaginationRequest) -> BoxFutureResult<'a, T, U> + 'a, ) -> Self { - ProviderPaginationCaller { + Paginator { cursor: None::, results: results as usize, direction: PageDirection::Forward, @@ -103,7 +102,7 @@ impl<'a, T, U> ProviderPaginationCaller<'a, T, U> { self } - pub async fn call(self) -> Result, ProviderError> { + pub async fn call(self) -> Result, ProviderError> { let pagination = PaginationRequest { cursor: self.cursor, results: self.results, @@ -249,11 +248,11 @@ impl Provider { from: &Bech32Address, asset_id: &AssetId, num_results: u64, - ) -> ProviderPaginationCaller> { + ) -> Paginator> { let hash = Arc::new(from.hash().to_string()); let asset_id = Arc::new(asset_id.to_string()); let provider = Arc::new(self.clone()); - ProviderPaginationCaller::new(num_results, move |pr: PaginationRequest<_>| { + Paginator::new(num_results, move |pr: PaginationRequest<_>| { let hash = Arc::clone(&hash); let asset_id_string = Arc::clone(&asset_id); let provider_clone = Arc::clone(&provider); @@ -358,10 +357,10 @@ impl Provider { &self, from: &Bech32Address, num_results: u64, - ) -> ProviderPaginationCaller> { + ) -> Paginator> { let hash = Arc::new(from.hash().to_string()); let provider = Arc::new(self.clone()); - ProviderPaginationCaller::new(num_results, move |pr: PaginationRequest<_>| { + Paginator::new(num_results, move |pr: PaginationRequest<_>| { let hash = Arc::clone(&hash); let provider_clone = Arc::clone(&provider); Box::pin(async move { @@ -384,7 +383,7 @@ impl Provider { ) .collect(); - Ok(ProviderPaginatedResult { + Ok(Page { cursor: response.cursor, results: balances, has_next_page: response.has_next_page, @@ -395,39 +394,44 @@ impl Provider { } /// Get all balances of all assets for the contract with id `contract_id`. - pub async fn get_contract_balances( + pub fn get_contract_balances( &self, contract_id: &Bech32ContractId, - ) -> Result, ProviderError> { - // 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, - }; + num_results: u64, + ) -> Paginator> { + let hash = Arc::new(contract_id.hash().to_string()); + let provider = Arc::new(self.clone()); + Paginator::new(num_results, move |pr: PaginationRequest<_>| { + let hash = Arc::clone(&hash); + let provider_clone = Arc::clone(&provider); + Box::pin(async move { + let response = provider_clone.client.contract_balances(&hash, pr).await?; - let balances_vec = self - .client - .contract_balances(&contract_id.hash().to_string(), pagination) - .await? - .results; - let balances = balances_vec - .into_iter() - .map( - |ContractBalance { - contract: _, - amount, - asset_id, - }| { - ( - AssetId::from_str(&asset_id.to_string()).unwrap(), - amount.try_into().unwrap(), + let balances = response + .results + .into_iter() + .map( + |ContractBalance { + contract: _, + amount, + asset_id, + }| { + ( + AssetId::from_str(&asset_id.to_string()).unwrap(), + amount.try_into().unwrap(), + ) + }, ) - }, - ) - .collect(); - Ok(balances) + .collect(); + + Ok(Page { + cursor: response.cursor, + results: balances, + has_next_page: response.has_next_page, + has_previous_page: response.has_previous_page, + }) + }) + }) } // Get a Contract with fields: id, bytecode (as hex string) and salt, from the client @@ -446,60 +450,38 @@ impl Provider { self.client.transaction(tx_id).await.map_err(Into::into) } - pub async fn get_transactions(&self) -> Result, ProviderError> { - let mut transaction_responses: Vec = vec![]; - - let mut cursor = None; - - loop { - let res = self - .client - .transactions(PaginationRequest { - cursor: cursor.clone(), - results: 100, - direction: PageDirection::Forward, - }) - .await?; - - if res.results.is_empty() { - break; - } - transaction_responses.extend(res.results); - cursor = res.cursor; - } - - Ok(transaction_responses) + pub fn get_transactions( + &self, + num_results: u64, + ) -> Paginator> { + let provider = Arc::new(self.clone()); + Paginator::new(num_results, move |pr: PaginationRequest<_>| { + let provider_clone = Arc::clone(&provider); + Box::pin(async move { + let response = provider_clone.client.transactions(pr).await?; + Ok(response.into()) + }) + }) } - pub async fn get_transactions_by_owner( + pub fn get_transactions_by_owner( &self, owner: &Bech32Address, - ) -> Result, ProviderError> { - let mut transaction_responses: Vec = vec![]; - - let mut cursor = None; - - loop { - let res = self - .client - .transactions_by_owner( - &owner.hash().to_string(), - PaginationRequest { - cursor: cursor.clone(), - results: 100, - direction: PageDirection::Forward, - }, - ) - .await?; - - if res.results.is_empty() { - break; - } - transaction_responses.extend(res.results); - cursor = res.cursor; - } - - Ok(transaction_responses) + num_results: u64, + ) -> Paginator> { + let hash = Arc::new(owner.hash().to_string()); + let provider = Arc::new(self.clone()); + Paginator::new(num_results, move |pr: PaginationRequest<_>| { + let hash = Arc::clone(&hash); + let provider_clone = Arc::clone(&provider); + Box::pin(async move { + let response = provider_clone + .client + .transactions_by_owner(&hash, pr) + .await?; + Ok(response.into()) + }) + }) } pub async fn latest_block_height(&self) -> Result { @@ -573,33 +555,36 @@ impl Provider { .unwrap_or(0) } - pub async fn get_messages(&self, from: &Bech32Address) -> Result, ProviderError> { - let pagination = PaginationRequest { - cursor: None, - results: 100, - direction: PageDirection::Forward, - }; - let res = self - .client - .messages(Some(&from.hash().to_string()), pagination) - .await?; - Ok(res.results) + pub fn get_messages( + &self, + from: &Bech32Address, + num_results: u64, + ) -> Paginator> { + let hash = Arc::new(from.hash().to_string()); + let provider = Arc::new(self.clone()); + Paginator::new(num_results, move |pr: PaginationRequest<_>| { + let hash = Arc::clone(&hash); + let provider_clone = Arc::clone(&provider); + Box::pin(async move { + let response = provider_clone.client.messages(Some(&hash), pr).await?; + Ok(response.into()) + }) + }) } pub async fn get_block(&self, block_id: &str) -> Result, ProviderError> { self.client.block(block_id).await.map_err(Into::into) } - pub async fn get_blocks(&self) -> Result, ProviderError> { - let res = self - .client - .blocks(PaginationRequest { - cursor: None, - results: 999, - direction: PageDirection::Forward, + pub fn get_blocks(&self, num_results: u64) -> Paginator> { + let provider = Arc::new(self.clone()); + Paginator::new(num_results, move |pr: PaginationRequest<_>| { + let provider_clone = Arc::clone(&provider); + Box::pin(async move { + let response = provider_clone.client.blocks(pr).await?; + Ok(response.into()) }) - .await?; - Ok(res.results) + }) } } @@ -780,7 +765,11 @@ mod tests { .force_transfer_to_contract(&contract_id, amount, *asset_id, TxParameters::default()) .await?; - let contract_balances = provider.get_contract_balances(&contract_id).await?; + let contract_balances = provider + .get_contract_balances(&contract_id, 12) + .call() + .await? + .results; let expected_asset_balance = contract_balances .get(asset_id) @@ -858,9 +847,14 @@ mod tests { .transfer(wallet2.address(), 1, Default::default(), Default::default()) .await?; - let expected_response = provider.get_transactions().await?; + let num_transactions = 2; + let response = provider + .get_transactions(num_transactions) + .call() + .await? + .results; - assert_eq!(expected_response.len(), 2); + assert_eq!(response.len() as u64, num_transactions); //TODO: check if I can test it in another way Ok(()) @@ -880,9 +874,14 @@ mod tests { .transfer(wallet2.address(), 1, Default::default(), Default::default()) .await?; - let expected_response = provider.get_transactions_by_owner(wallet.address()).await?; + let num_transactions = 2; + let response = provider + .get_transactions_by_owner(wallet.address(), num_transactions) + .call() + .await? + .results; - assert_eq!(expected_response.len(), 2); + assert_eq!(response.len() as u64, num_transactions); //TODO: check if I can test it in another way Ok(()) @@ -934,17 +933,15 @@ mod tests { .transfer(wallet2.address(), 1, Default::default(), Default::default()) .await?; - let expected_blocks = provider.get_blocks().await?; + let num_blocks = 2; + let blocks = provider.get_blocks(num_blocks).call().await?.results; - assert_eq!(expected_blocks.len(), 2); + assert_eq!(blocks.len() as u64, num_blocks); //TODO: check if I can test it in another way Ok(()) } } -// pub async fn get_contract_balances( -// pub async fn get_transactions(&self) -> Result, ProviderError> { -// pub async fn get_transactions_by_owner( // pub async fn get_messages(&self, from: &Bech32Address) -> Result, ProviderError> { // pub async fn get_blocks(&self) -> Result, ProviderError> { diff --git a/packages/fuels-signers/src/wallet.rs b/packages/fuels-signers/src/wallet.rs index b822255712..6e0a00ce38 100644 --- a/packages/fuels-signers/src/wallet.rs +++ b/packages/fuels-signers/src/wallet.rs @@ -1,4 +1,4 @@ -use crate::provider::Provider; +use crate::provider::{Paginator, Provider}; use crate::Signer; use async_trait::async_trait; use elliptic_curve::rand_core; @@ -128,11 +128,13 @@ impl Wallet { &self.address } - pub async fn get_transactions(&self) -> Result, Error> { - self.get_provider()? - .get_transactions_by_owner(&self.address) - .await - .map_err(Into::into) + pub fn get_transactions( + &self, + num_results: u64, + ) -> Result>, Error> { + Ok(self + .get_provider()? + .get_transactions_by_owner(&self.address, num_results)) } /// Returns a proper vector of `Input::Coin`s for the given asset ID, amount, and witness index. @@ -179,16 +181,18 @@ impl Wallet { ] } + /// TODO: change description /// Gets all coins of asset `asset_id` owned by the wallet, *even spent ones* (this is useful /// for some particular cases, but in general, you should use `get_spendable_coins`). This /// returns actual coins (UTXOs). - pub async fn get_coins(&self, asset_id: AssetId, num_results: u64) -> Result, Error> { + pub fn get_coins( + &self, + asset_id: AssetId, + num_results: u64, + ) -> Result>, Error> { Ok(self .get_provider()? - .get_coins(&self.address, &asset_id, num_results) - .call() - .await? - .results) + .get_coins(&self.address, &asset_id, num_results)) } /// Get some spendable coins of asset `asset_id` owned by the wallet that add up at least to @@ -225,26 +229,33 @@ impl Wallet { .map_err(Into::into) } + /// TODO: change description /// Get all the spendable balances of all assets for the wallet. This is different from getting /// the coins because we are only returning the sum of UTXOs coins amount and not the UTXOs /// coins themselves. - pub async fn get_balances(&self, num_results: u64) -> Result, Error> { + pub fn get_balances( + &self, + num_results: u64, + ) -> Result>, Error> { Ok(self .get_provider()? - .get_balances(&self.address, num_results) - .call() - .await? - .results) + .get_balances(&self.address, num_results)) } - pub async fn get_messages(&self) -> Result, Error> { - Ok(self.get_provider()?.get_messages(&self.address).await?) + pub fn get_messages( + &self, + num_results: u64, + ) -> Result>, Error> { + Ok(self + .get_provider()? + .get_messages(&self.address, num_results)) } pub async fn get_inputs_for_messages(&self, witness_index: u8) -> Result, Error> { let to_u8_bytes = |v: &[i32]| v.iter().flat_map(|e| e.to_ne_bytes()).collect::>(); - let messages = self.get_messages().await?; + // TODO: make a loop to get all messages + let messages = self.get_messages(9999)?.call().await?.results; let inputs: Vec = messages .into_iter() @@ -610,7 +621,7 @@ impl WalletUnlocked { /// .await /// .unwrap(); /// - /// let wallet_2_final_coins = wallet_2.get_coins(BASE_ASSET_ID, 4).await.unwrap(); + /// let wallet_2_final_coins = wallet_2.get_coins(BASE_ASSET_ID, 4)?.call().await?.results; /// /// // Check that wallet two now has two coins /// assert_eq!(wallet_2_final_coins.len(), 2); diff --git a/packages/fuels-test-helpers/src/signers.rs b/packages/fuels-test-helpers/src/signers.rs index 18673a4f57..adb64d2b02 100644 --- a/packages/fuels-test-helpers/src/signers.rs +++ b/packages/fuels-test-helpers/src/signers.rs @@ -132,7 +132,11 @@ mod tests { assert_eq!(wallets.len(), num_wallets as usize); for wallet in &wallets { - let coins = wallet.get_coins(BASE_ASSET_ID, num_coins).await?; + let coins = wallet + .get_coins(BASE_ASSET_ID, num_coins)? + .call() + .await? + .results; assert_eq!(coins.len(), num_coins as usize); diff --git a/packages/fuels/tests/contracts.rs b/packages/fuels/tests/contracts.rs index dc519ce796..d8b09d9370 100644 --- a/packages/fuels/tests/contracts.rs +++ b/packages/fuels/tests/contracts.rs @@ -594,7 +594,7 @@ async fn test_contract_instance_get_balances() -> Result<(), Error> { let contract_id = contract_instance.get_contract_id(); // Check the current balance of the contract with id 'contract_id' - let contract_balances = contract_instance.get_balances().await?; + let contract_balances = contract_instance.get_balances(1)?.call().await?.results; assert!(contract_balances.is_empty()); // Transfer an amount to the contract @@ -609,7 +609,7 @@ async fn test_contract_instance_get_balances() -> Result<(), Error> { .await?; // Check that the contract now has 1 coin - let contract_balances = contract_instance.get_balances().await?; + let contract_balances = contract_instance.get_balances(1)?.call().await?.results; assert_eq!(contract_balances.len(), 1); let random_asset_balance = contract_balances.get(random_asset_id).unwrap(); diff --git a/packages/fuels/tests/scripts.rs b/packages/fuels/tests/scripts.rs index 1cfaa09676..161495b388 100644 --- a/packages/fuels/tests/scripts.rs +++ b/packages/fuels/tests/scripts.rs @@ -74,8 +74,10 @@ async fn test_script_interface() -> Result<(), Error> { let contract_coins = wallet .get_provider()? - .get_contract_balances(&contract_id) - .await?; + .get_contract_balances(&contract_id, 1) + .call() + .await? + .results; assert!(contract_coins.is_empty()); let amount = 100; @@ -138,8 +140,10 @@ async fn test_script_interface() -> Result<(), Error> { let contract_balances = wallet .get_provider()? - .get_contract_balances(&contract_id) - .await?; + .get_contract_balances(&contract_id, 1) + .call() + .await? + .results; assert_eq!(contract_balances.len(), 1); let balance = contract_balances.get(&BASE_ASSET_ID).unwrap(); diff --git a/packages/fuels/tests/wallets.rs b/packages/fuels/tests/wallets.rs index 7ce8bcade8..eac74420a8 100644 --- a/packages/fuels/tests/wallets.rs +++ b/packages/fuels/tests/wallets.rs @@ -16,8 +16,10 @@ async fn test_wallet_balance_api_multi_asset() -> Result<(), Error> { let (provider, _) = setup_test_provider(coins.clone(), vec![], None).await; wallet.set_provider(provider); let balances = wallet - .get_balances(number_of_assets * coins_per_asset) - .await?; + .get_balances(number_of_assets * coins_per_asset)? + .call() + .await? + .results; assert_eq!(balances.len() as u64, number_of_assets); for asset_id in asset_ids { @@ -53,7 +55,7 @@ async fn test_wallet_balance_api_single_asset() -> Result<(), Error> { assert_eq!(balance?, number_of_coins * amount_per_coin); } - let balances = wallet.get_balances(number_of_coins).await?; + let balances = wallet.get_balances(number_of_coins)?.call().await?.results; assert_eq!(balances.len(), 1); // only the base asset assert!(balances.contains_key(&BASE_ASSET_ID)); assert_eq!( From 1ea24db1026a69e30f9481deeb4a05c1e0ba7f92 Mon Sep 17 00:00:00 2001 From: hal3e Date: Fri, 28 Oct 2022 13:25:11 +0200 Subject: [PATCH 11/17] implement comments --- packages/fuels-signers/src/provider.rs | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/packages/fuels-signers/src/provider.rs b/packages/fuels-signers/src/provider.rs index 7b8c61e930..8c4dcc0dca 100644 --- a/packages/fuels-signers/src/provider.rs +++ b/packages/fuels-signers/src/provider.rs @@ -710,7 +710,7 @@ mod tests { .await?; let amount = 18; - let _receipts = wallet + let _ = wallet .force_transfer_to_contract(&contract_id, amount, *asset_id, TxParameters::default()) .await?; @@ -761,7 +761,7 @@ mod tests { .await?; let amount = 18; - let _receipts = wallet + let _ = wallet .force_transfer_to_contract(&contract_id, amount, *asset_id, TxParameters::default()) .await?; @@ -817,7 +817,7 @@ mod tests { maturity, }; - let (tx_id, _receipts) = wallet + let (tx_id, _) = wallet .transfer(wallet2.address(), 1, Default::default(), tx_params) .await?; @@ -840,10 +840,10 @@ mod tests { let wallet2 = WalletUnlocked::new_random(Some(provider.clone())); // Make two transactions - let (_tx_id1, _receipts) = wallet + let (_tx_id1, _) = wallet .transfer(wallet2.address(), 1, Default::default(), Default::default()) .await?; - let (_tx_id2, _receipts) = wallet + let (_tx_id2, _) = wallet .transfer(wallet2.address(), 1, Default::default(), Default::default()) .await?; @@ -867,10 +867,10 @@ mod tests { let wallet2 = WalletUnlocked::new_random(Some(provider.clone())); // Make two transactions - let (_tx_id1, _receipts) = wallet + let (_tx_id1, _) = wallet .transfer(wallet2.address(), 1, Default::default(), Default::default()) .await?; - let (_tx_id2, _receipts) = wallet + let (_tx_id2, _) = wallet .transfer(wallet2.address(), 1, Default::default(), Default::default()) .await?; @@ -893,7 +893,7 @@ mod tests { let wallet2 = WalletUnlocked::new_random(Some(provider.clone())); - let (tx_id, _receipts) = wallet + let (tx_id, _) = wallet .transfer(wallet2.address(), 1, Default::default(), Default::default()) .await?; @@ -926,10 +926,10 @@ mod tests { let wallet2 = WalletUnlocked::new_random(Some(provider.clone())); // Make two transactions - let (_tx_id1, _receipts) = wallet + let (_tx_id1, _) = wallet .transfer(wallet2.address(), 1, Default::default(), Default::default()) .await?; - let (_tx_id2, _receipts) = wallet + let (_tx_id2, _) = wallet .transfer(wallet2.address(), 1, Default::default(), Default::default()) .await?; @@ -942,6 +942,3 @@ mod tests { Ok(()) } } - -// pub async fn get_messages(&self, from: &Bech32Address) -> Result, ProviderError> { -// pub async fn get_blocks(&self) -> Result, ProviderError> { From 8631840ebae22531b3d59fe1ebb176e3dc0c0ed2 Mon Sep 17 00:00:00 2001 From: hal3e Date: Fri, 28 Oct 2022 15:27:04 +0200 Subject: [PATCH 12/17] update get messages --- packages/fuels-signers/src/wallet.rs | 9 +++------ packages/fuels/tests/contracts.rs | 19 ++++++++++++++----- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/packages/fuels-signers/src/wallet.rs b/packages/fuels-signers/src/wallet.rs index 6e0a00ce38..a7b7d80582 100644 --- a/packages/fuels-signers/src/wallet.rs +++ b/packages/fuels-signers/src/wallet.rs @@ -181,8 +181,7 @@ impl Wallet { ] } - /// TODO: change description - /// Gets all coins of asset `asset_id` owned by the wallet, *even spent ones* (this is useful + /// Gets a page of coins of asset `asset_id` owned by the wallet, *even spent ones* (this is useful /// for some particular cases, but in general, you should use `get_spendable_coins`). This /// returns actual coins (UTXOs). pub fn get_coins( @@ -229,8 +228,7 @@ impl Wallet { .map_err(Into::into) } - /// TODO: change description - /// Get all the spendable balances of all assets for the wallet. This is different from getting + /// Get a page of spendable balances of all assets for the wallet. This is different from getting /// the coins because we are only returning the sum of UTXOs coins amount and not the UTXOs /// coins themselves. pub fn get_balances( @@ -254,8 +252,7 @@ impl Wallet { pub async fn get_inputs_for_messages(&self, witness_index: u8) -> Result, Error> { let to_u8_bytes = |v: &[i32]| v.iter().flat_map(|e| e.to_ne_bytes()).collect::>(); - // TODO: make a loop to get all messages - let messages = self.get_messages(9999)?.call().await?.results; + let messages = self.get_spendable_messages().await?; let inputs: Vec = messages .into_iter() diff --git a/packages/fuels/tests/contracts.rs b/packages/fuels/tests/contracts.rs index d8b09d9370..810712016e 100644 --- a/packages/fuels/tests/contracts.rs +++ b/packages/fuels/tests/contracts.rs @@ -592,9 +592,14 @@ async fn test_contract_instance_get_balances() -> Result<(), Error> { "packages/fuels/tests/contracts/contract_test" ); let contract_id = contract_instance.get_contract_id(); + let num_coins = 1; - // Check the current balance of the contract with id 'contract_id' - let contract_balances = contract_instance.get_balances(1)?.call().await?.results; + // Try to get 1 coin from the contract balance - should be empty + let contract_balances = contract_instance + .get_balances(num_coins)? + .call() + .await? + .results; assert!(contract_balances.is_empty()); // Transfer an amount to the contract @@ -608,9 +613,13 @@ async fn test_contract_instance_get_balances() -> Result<(), Error> { ) .await?; - // Check that the contract now has 1 coin - let contract_balances = contract_instance.get_balances(1)?.call().await?.results; - assert_eq!(contract_balances.len(), 1); + // Check that the contract now has 1 coin with `random_asset_id` + let contract_balances = contract_instance + .get_balances(num_coins)? + .call() + .await? + .results; + assert_eq!(contract_balances.len() as u64, num_coins); let random_asset_balance = contract_balances.get(random_asset_id).unwrap(); assert_eq!(*random_asset_balance, amount); From a1661a923dd6c169c99446f3b9c66b485daff489 Mon Sep 17 00:00:00 2001 From: hal3e Date: Fri, 28 Oct 2022 16:50:38 +0200 Subject: [PATCH 13/17] update docs --- .../wallets/checking-balances-and-coins.md | 13 ++- examples/wallets/src/lib.rs | 34 +++++--- packages/fuels-signers/src/lib.rs | 85 ++++++++++++++----- packages/fuels-signers/src/wallet.rs | 9 +- packages/fuels/tests/scripts.rs | 13 +-- 5 files changed, 113 insertions(+), 41 deletions(-) diff --git a/docs/src/wallets/checking-balances-and-coins.md b/docs/src/wallets/checking-balances-and-coins.md index dd13540d4c..d37d63a64e 100644 --- a/docs/src/wallets/checking-balances-and-coins.md +++ b/docs/src/wallets/checking-balances-and-coins.md @@ -5,15 +5,24 @@ First, one should remember that, with UTXOs, each _coin_ is unique. Each UTXO co ```rust,ignore {{#include ../../../examples/wallets/src/lib.rs:get_asset_balance}} ``` +If you want to get all spendable coins, you can use: -If you want to query all the balances (i.e., get the balance for each asset ID in that wallet), then it is as simple as: +```rust,ignore +{{#include ../../../examples/wallets/src/lib.rs:get_spendable_coins}} +``` + +If you want to query all the balances (i.e., get the balance for each asset ID in that wallet), you can use: ```rust,ignore {{#include ../../../examples/wallets/src/lib.rs:get_balances}} ``` -The return type is a `HashMap`, where the key is an `AssetId`, and the value is the corresponding balance. For example, we can get the base asset balance with: +`get_balances(num_results: u64)` is a paginated request and the input is the number of results that you want to have per page. The `Pager` struct can be used to set the `cursor` and the pagination direction. To get the actual results, you have to use the `call()` method. The return type of `call()` is a `Page` struct. The `Page` struct includes the current `cursor`, `results` and information on whether we have the next and previous page (`has_next_page`, `has_previous_page`). + +In this case, the `results` variable is a `HashMap`, where the key is an `AssetId`, and the value is the corresponding balance. For example, we can get the base asset balance with: ```rust,ignore {{#include ../../../examples/wallets/src/lib.rs:get_balance_hashmap}} ``` + +> **Note:** That `get_coins`, `get_messages` and `get_transactions` are also paginated requests and are used in the same way as `get_balances`. diff --git a/examples/wallets/src/lib.rs b/examples/wallets/src/lib.rs index 5b9a9645e5..a3cc76d26f 100644 --- a/examples/wallets/src/lib.rs +++ b/examples/wallets/src/lib.rs @@ -134,14 +134,15 @@ mod tests { .transfer(wallets[1].address(), 1, asset_id, TxParameters::default()) .await?; + let wallet2_num_coins = 2; let wallet_2_final_coins = wallets[1] - .get_coins(BASE_ASSET_ID, 2)? + .get_coins(BASE_ASSET_ID, wallet2_num_coins)? .call() .await? .results; // Check that wallet 2 now has 2 coins - assert_eq!(wallet_2_final_coins.len(), 2); + assert_eq!(wallet_2_final_coins.len() as u64, wallet2_num_coins); // ANCHOR_END: wallet_transfer Ok(()) @@ -184,9 +185,10 @@ mod tests { // ANCHOR: wallet_contract_transfer // Check the current balance of the contract with id 'contract_id' + let num_coins = 1; let contract_balances = wallet .get_provider()? - .get_contract_balances(&contract_id, 1) + .get_contract_balances(&contract_id, num_coins) .call() .await? .results; @@ -202,14 +204,16 @@ mod tests { // Check that the contract now has 1 coin let contract_balances = wallet .get_provider()? - .get_contract_balances(&contract_id, 1) + .get_contract_balances(&contract_id, num_coins) .call() .await? .results; - assert_eq!(contract_balances.len(), 1); + assert_eq!(contract_balances.len() as u64, num_coins); - let random_asset_balance = contract_balances.get(&random_asset_id).unwrap(); - assert_eq!(*random_asset_balance, 300); + let random_asset_balance = contract_balances + .get(&random_asset_id) + .expect("could not find any balance for the provided asset_id"); + assert_eq!(*random_asset_balance, amount); // ANCHOR_END: wallet_contract_transfer Ok(()) @@ -324,12 +328,20 @@ mod tests { let asset_id: AssetId = BASE_ASSET_ID; let balance: u64 = wallet.get_asset_balance(&asset_id).await?; // ANCHOR_END: get_asset_balance + + // ANCHOR: get_spendable_coins + let asset_id: AssetId = BASE_ASSET_ID; + let amount = 32; + let coins = wallet.get_spendable_coins(&asset_id, amount).await?; + // ANCHOR_END: get_spendable_coins + // ANCHOR: get_balances - let balances: HashMap = wallet + let pager = wallet .get_balances(DEFAULT_NUM_COINS)? - .call() - .await? - .results; + .with_cursor(None) + .forward(); + let page = pager.call().await?; + let balances: HashMap = page.results; // ANCHOR_END: get_balances // ANCHOR: get_balance_hashmap diff --git a/packages/fuels-signers/src/lib.rs b/packages/fuels-signers/src/lib.rs index 7dabdd27a2..768faa0764 100644 --- a/packages/fuels-signers/src/lib.rs +++ b/packages/fuels-signers/src/lib.rs @@ -146,8 +146,11 @@ mod tests { let mut wallet_1 = WalletUnlocked::new_random(None); let mut wallet_2 = WalletUnlocked::new_random(None).lock(); - let mut coins_1 = setup_single_asset_coins(wallet_1.address(), BASE_ASSET_ID, 1, 1000000); - let coins_2 = setup_single_asset_coins(wallet_2.address(), BASE_ASSET_ID, 1, 1000000); + let num_coins = 1; + let mut coins_1 = + setup_single_asset_coins(wallet_1.address(), BASE_ASSET_ID, num_coins, 1000000); + let coins_2 = + setup_single_asset_coins(wallet_2.address(), BASE_ASSET_ID, num_coins, 1000000); coins_1.extend(coins_2); @@ -158,12 +161,20 @@ mod tests { wallet_1.set_provider(provider.clone()); wallet_2.set_provider(provider); - let wallet_1_initial_coins = wallet_1.get_coins(BASE_ASSET_ID, 1)?.call().await?.results; - let wallet_2_initial_coins = wallet_2.get_coins(BASE_ASSET_ID, 1)?.call().await?.results; + let wallet_1_initial_coins = wallet_1 + .get_coins(BASE_ASSET_ID, num_coins)? + .call() + .await? + .results; + let wallet_2_initial_coins = wallet_2 + .get_coins(BASE_ASSET_ID, num_coins)? + .call() + .await? + .results; // Check initial wallet state. - assert_eq!(wallet_1_initial_coins.len(), 1); - assert_eq!(wallet_2_initial_coins.len(), 1); + assert_eq!(wallet_1_initial_coins.len() as u64, num_coins); + assert_eq!(wallet_2_initial_coins.len() as u64, num_coins); // Configure transaction parameters. let gas_price = 1; @@ -193,14 +204,24 @@ mod tests { assert_eq!(res.transaction.maturity(), maturity); let wallet_1_spendable_coins = wallet_1.get_spendable_coins(&BASE_ASSET_ID, 0).await?; - let wallet_1_all_coins = wallet_1.get_coins(BASE_ASSET_ID, 2)?.call().await?.results; - let wallet_2_all_coins = wallet_2.get_coins(BASE_ASSET_ID, 2)?.call().await?.results; + let wallet_1_all_coins = wallet_1 + .get_coins(BASE_ASSET_ID, num_coins)? + .call() + .await? + .results; + + let wallet2_num_coins = 2; + let wallet_2_all_coins = wallet_2 + .get_coins(BASE_ASSET_ID, wallet2_num_coins)? + .call() + .await? + .results; // wallet_1 has now only 1 spent coin (so 0 spendable) assert_eq!(wallet_1_spendable_coins.len(), 0); - assert_eq!(wallet_1_all_coins.len(), 1); + assert_eq!(wallet_1_all_coins.len() as u64, num_coins); // Check that wallet two now has two coins. - assert_eq!(wallet_2_all_coins.len(), 2); + assert_eq!(wallet_2_all_coins.len() as u64, wallet2_num_coins); // Transferring more than balance should fail. let response = wallet_1 @@ -213,8 +234,12 @@ mod tests { .await; assert!(response.is_err()); - let wallet_2_coins = wallet_2.get_coins(BASE_ASSET_ID, 2)?.call().await?.results; - assert_eq!(wallet_2_coins.len(), 2); // Not changed + let wallet_2_coins = wallet_2 + .get_coins(BASE_ASSET_ID, wallet2_num_coins)? + .call() + .await? + .results; + assert_eq!(wallet_2_coins.len() as u64, wallet2_num_coins); // Not changed Ok(()) } @@ -224,8 +249,9 @@ mod tests { let mut wallet_1 = WalletUnlocked::new_random(None); let mut wallet_2 = WalletUnlocked::new_random(None).lock(); - let mut coins_1 = setup_single_asset_coins(wallet_1.address(), BASE_ASSET_ID, 1, 5); - let coins_2 = setup_single_asset_coins(wallet_2.address(), BASE_ASSET_ID, 1, 5); + let num_coins = 1; + let mut coins_1 = setup_single_asset_coins(wallet_1.address(), BASE_ASSET_ID, num_coins, 5); + let coins_2 = setup_single_asset_coins(wallet_2.address(), BASE_ASSET_ID, num_coins, 5); coins_1.extend(coins_2); @@ -235,11 +261,19 @@ mod tests { wallet_1.set_provider(provider.clone()); wallet_2.set_provider(provider); - let wallet_1_initial_coins = wallet_1.get_coins(BASE_ASSET_ID, 1)?.call().await?.results; - let wallet_2_initial_coins = wallet_2.get_coins(BASE_ASSET_ID, 1)?.call().await?.results; + let wallet_1_initial_coins = wallet_1 + .get_coins(BASE_ASSET_ID, num_coins)? + .call() + .await? + .results; + let wallet_2_initial_coins = wallet_2 + .get_coins(BASE_ASSET_ID, num_coins)? + .call() + .await? + .results; - assert_eq!(wallet_1_initial_coins.len(), 1); - assert_eq!(wallet_2_initial_coins.len(), 1); + assert_eq!(wallet_1_initial_coins.len() as u64, num_coins); + assert_eq!(wallet_2_initial_coins.len() as u64, num_coins); // Transfer 2 from wallet 1 to wallet 2. let _receipts = wallet_1 @@ -251,14 +285,23 @@ mod tests { ) .await?; - let wallet_1_final_coins = wallet_1.get_coins(BASE_ASSET_ID, 2)?.call().await?.results; + let wallet_1_final_coins = wallet_1 + .get_coins(BASE_ASSET_ID, num_coins)? + .call() + .await? + .results; // Assert that we've sent 2 from wallet 1, resulting in an amount of 3 in wallet 1. let resulting_amount = wallet_1_final_coins.first().unwrap(); assert_eq!(resulting_amount.amount.0, 3); - let wallet_2_final_coins = wallet_2.get_coins(BASE_ASSET_ID, 2)?.call().await?.results; - assert_eq!(wallet_2_final_coins.len(), 2); + let wallet2_num_coins = 2; + let wallet_2_final_coins = wallet_2 + .get_coins(BASE_ASSET_ID, wallet2_num_coins)? + .call() + .await? + .results; + assert_eq!(wallet_2_final_coins.len() as u64, wallet2_num_coins); // Check that wallet 2's amount is 7: // 5 initial + 2 that was sent to it. diff --git a/packages/fuels-signers/src/wallet.rs b/packages/fuels-signers/src/wallet.rs index a7b7d80582..d607a68ae0 100644 --- a/packages/fuels-signers/src/wallet.rs +++ b/packages/fuels-signers/src/wallet.rs @@ -618,10 +618,15 @@ impl WalletUnlocked { /// .await /// .unwrap(); /// - /// let wallet_2_final_coins = wallet_2.get_coins(BASE_ASSET_ID, 4)?.call().await?.results; + /// let wallet2_num_coins = 2; + /// let wallet_2_final_coins = wallet_2 + /// .get_coins(BASE_ASSET_ID, wallet2_num_coins)? + /// .call() + /// .await? + /// .results; /// /// // Check that wallet two now has two coins - /// assert_eq!(wallet_2_final_coins.len(), 2); + /// assert_eq!(wallet_2_final_coins.len() as u64, wallet2_num_coins); /// Ok(()) /// } /// ``` diff --git a/packages/fuels/tests/scripts.rs b/packages/fuels/tests/scripts.rs index 161495b388..2c6fb7b7b9 100644 --- a/packages/fuels/tests/scripts.rs +++ b/packages/fuels/tests/scripts.rs @@ -50,7 +50,7 @@ async fn test_multi_call_script_workflow() -> Result<(), Error> { let provider = &wallet.get_provider()?; let script = multi_call_handler.get_call_execution_script().await?; - let receipts = script.call(provider).await.unwrap(); + let receipts = script.call(provider).await?; let (counter, array) = multi_call_handler .get_response::<(u64, [u64; 2])>(receipts)? .value; @@ -72,9 +72,10 @@ async fn test_script_interface() -> Result<(), Error> { ) .await?; + let num_coins = 1; let contract_coins = wallet .get_provider()? - .get_contract_balances(&contract_id, 1) + .get_contract_balances(&contract_id, num_coins) .call() .await? .results; @@ -140,13 +141,15 @@ async fn test_script_interface() -> Result<(), Error> { let contract_balances = wallet .get_provider()? - .get_contract_balances(&contract_id, 1) + .get_contract_balances(&contract_id, num_coins) .call() .await? .results; - assert_eq!(contract_balances.len(), 1); + assert_eq!(contract_balances.len() as u64, num_coins); - let balance = contract_balances.get(&BASE_ASSET_ID).unwrap(); + let balance = contract_balances + .get(&BASE_ASSET_ID) + .expect("could not find any balance for the provided asset_id"); assert_eq!(*balance, 100); Ok(()) From e25546ddd255bc801a05602a1b69c09112a85418 Mon Sep 17 00:00:00 2001 From: hal3e Date: Fri, 28 Oct 2022 18:20:27 +0200 Subject: [PATCH 14/17] add pagination test --- packages/fuels-signers/src/provider.rs | 92 ++++++++++++++++++++------ 1 file changed, 73 insertions(+), 19 deletions(-) diff --git a/packages/fuels-signers/src/provider.rs b/packages/fuels-signers/src/provider.rs index 8c4dcc0dca..31f865d01d 100644 --- a/packages/fuels-signers/src/provider.rs +++ b/packages/fuels-signers/src/provider.rs @@ -55,25 +55,6 @@ pub struct Paginator<'a, T, U> { pub function: BoxFnFuture<'a, T, U>, } -#[derive(Debug)] -pub struct Page { - pub cursor: Option, - pub results: U, - pub has_next_page: bool, - pub has_previous_page: bool, -} - -impl From> for Page> { - fn from(pr: PaginatedResult) -> Self { - Self { - cursor: pr.cursor, - results: pr.results, - has_next_page: pr.has_next_page, - has_previous_page: pr.has_previous_page, - } - } -} - impl<'a, T, U> Paginator<'a, T, U> { fn new( results: u64, @@ -113,6 +94,25 @@ impl<'a, T, U> Paginator<'a, T, U> { } } +#[derive(Debug)] +pub struct Page { + pub cursor: Option, + pub results: U, + pub has_next_page: bool, + pub has_previous_page: bool, +} + +impl From> for Page> { + fn from(pr: PaginatedResult) -> Self { + Self { + cursor: pr.cursor, + results: pr.results, + has_next_page: pr.has_next_page, + has_previous_page: pr.has_previous_page, + } + } +} + /// Encapsulates common client operations in the SDK. /// Note that you may also use `client`, which is an instance /// of `FuelClient`, directly, which provides a broader API. @@ -253,6 +253,7 @@ impl Provider { let asset_id = Arc::new(asset_id.to_string()); let provider = Arc::new(self.clone()); Paginator::new(num_results, move |pr: PaginationRequest<_>| { + dbg!(&pr); let hash = Arc::clone(&hash); let asset_id_string = Arc::clone(&asset_id); let provider_clone = Arc::clone(&provider); @@ -610,6 +611,59 @@ mod tests { (wallet, (coins, asset_ids), provider) } + #[tokio::test] + async fn test_pagination() -> Result<(), Error> { + let (wallet, (_, asset_ids), provider) = setup_provider_api_test().await; + let asset_id = &asset_ids[0]; + + // Get Page with 2 coins + let coins_per_page = 2; + let response = provider + .get_coins(wallet.address(), asset_id, coins_per_page) + .call() + .await?; + + // assert_eq!(response.results.len() as u64, coins_per_page); + // assert!(response.has_next_page); + // assert!(!response.has_previous_page); + + dbg!(&response.results.len()); + dbg!(&response.has_previous_page); + dbg!(&response.has_next_page); + + // Get next Page with 2 coins + let response = provider + .get_coins(wallet.address(), asset_id, coins_per_page) + .with_cursor(response.cursor) + .call() + .await?; + + dbg!(&response.results.len()); + dbg!(&response.has_previous_page); + dbg!(&response.has_next_page); + + // assert_eq!(response.results.len() as u64, coins_per_page); + // assert!(!response.has_next_page); + // assert!(response.has_previous_page); + + // There should not be any coins left as the total num of coins is 4 + let response = provider + .get_coins(wallet.address(), asset_id, coins_per_page) + .with_cursor(response.cursor) + .call() + .await?; + + dbg!(&response.results.len()); + dbg!(&response.has_previous_page); + dbg!(&response.has_next_page); + + // assert!(response.results.is_empty()); + // assert!(!response.has_next_page); + // assert!(response.has_previous_page); + + Ok(()) + } + #[tokio::test] async fn test_coin_api() -> Result<(), Error> { let (_, (coins, _), provider) = setup_provider_api_test().await; From f85cb78a06e3ee1068b91ff03f51af8b525b2504 Mon Sep 17 00:00:00 2001 From: hal3e Date: Wed, 2 Nov 2022 09:45:59 +0100 Subject: [PATCH 15/17] add dbg for cursor --- packages/fuels-signers/src/provider.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/fuels-signers/src/provider.rs b/packages/fuels-signers/src/provider.rs index 31f865d01d..cbf189c0e9 100644 --- a/packages/fuels-signers/src/provider.rs +++ b/packages/fuels-signers/src/provider.rs @@ -628,6 +628,7 @@ mod tests { // assert!(!response.has_previous_page); dbg!(&response.results.len()); + dbg!(&response.cursor); dbg!(&response.has_previous_page); dbg!(&response.has_next_page); @@ -639,6 +640,7 @@ mod tests { .await?; dbg!(&response.results.len()); + dbg!(&response.cursor); dbg!(&response.has_previous_page); dbg!(&response.has_next_page); @@ -654,6 +656,7 @@ mod tests { .await?; dbg!(&response.results.len()); + dbg!(&response.cursor); dbg!(&response.has_previous_page); dbg!(&response.has_next_page); From 122f0435591592b1ba41debee30df6419c20f18a Mon Sep 17 00:00:00 2001 From: hal3e Date: Fri, 4 Nov 2022 11:39:21 +0100 Subject: [PATCH 16/17] input message test fix --- packages/fuels/tests/providers.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/fuels/tests/providers.rs b/packages/fuels/tests/providers.rs index efc7ca711e..2a0e502584 100644 --- a/packages/fuels/tests/providers.rs +++ b/packages/fuels/tests/providers.rs @@ -115,16 +115,16 @@ async fn test_input_message() -> Result<(), Error> { let (provider, _) = setup_test_provider(coins, messages.clone(), None).await; wallet.set_provider(provider); + let spendable_messages = wallet.get_spendable_messages().await?; + + assert!(compare_messages(spendable_messages, messages)); + setup_contract_test!( contract_instance, None, "packages/fuels/tests/contracts/contract_test" ); - let spendable_messages = wallet.get_spendable_messages().await?; - - assert!(compare_messages(spendable_messages, messages)); - let response = contract_instance .methods() .initialize_counter(42) // Build the ABI call From 81779d50cbecdb16822b9dfb5a9e9306543ab9a7 Mon Sep 17 00:00:00 2001 From: hal3e Date: Sat, 5 Nov 2022 19:52:36 +0100 Subject: [PATCH 17/17] fix merge --- packages/fuels-signers/src/provider.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/fuels-signers/src/provider.rs b/packages/fuels-signers/src/provider.rs index 6e4c20e77a..10acec3327 100644 --- a/packages/fuels-signers/src/provider.rs +++ b/packages/fuels-signers/src/provider.rs @@ -613,7 +613,7 @@ mod tests { ) { let mut wallet = WalletUnlocked::new_random(None); let (coins, asset_ids) = setup_multiple_assets_coins(wallet.address(), 2, 4, 8); - let (provider, _) = setup_test_provider(coins.clone(), vec![], None).await; + let (provider, _) = setup_test_provider(coins.clone(), vec![], None, None).await; wallet.set_provider(provider.clone()); (wallet, (coins, asset_ids), provider)