diff --git a/l10n.yaml b/l10n.yaml index 729534066..60c206665 100644 --- a/l10n.yaml +++ b/l10n.yaml @@ -1,3 +1,4 @@ arb-dir: lib/l10n template-arb-file: intl_en.arb output-localization-file: localizations.dart +untranslated-messages-file: untranslated_messages.txt diff --git a/lib/application/aeswap/dex_token.dart b/lib/application/aeswap/dex_token.dart index e01c44c74..24469eeda 100644 --- a/lib/application/aeswap/dex_token.dart +++ b/lib/application/aeswap/dex_token.dart @@ -83,10 +83,10 @@ Future _estimateTokenInFiat( String tokenAddress, ) async { if (tokenAddress.isUCO) { - return ref.watch( - aedappfm.ArchethicOracleUCOProviders.archethicOracleUCO - .select((value) => value.usd), - ); + return (await ref.watch( + aedappfm.ArchethicOracleUCOProviders.archethicOracleUCO.future, + )) + .usd; } else { final environment = ref.watch(environmentProvider); return await ref.watch( diff --git a/lib/application/aeswap/dex_token.g.dart b/lib/application/aeswap/dex_token.g.dart index ed5d2b63f..596979ff1 100644 --- a/lib/application/aeswap/dex_token.g.dart +++ b/lib/application/aeswap/dex_token.g.dart @@ -476,7 +476,7 @@ class _GetTokenIconProviderElement } String _$estimateTokenInFiatHash() => - r'5db90f36ed2ee0e92c7ad158166d169c2cbe7c8b'; + r'2f22e5eecfbf9315132fcec98e6812153f0ae01e'; /// See also [_estimateTokenInFiat]. @ProviderFor(_estimateTokenInFiat) diff --git a/lib/application/market_price.dart b/lib/application/market_price.dart index f38fcb28c..d7b7aafbe 100644 --- a/lib/application/market_price.dart +++ b/lib/application/market_price.dart @@ -40,8 +40,9 @@ Future _currencyMarketPrice( Future _selectedCurrencyMarketPrice( Ref ref, ) async { - final archethicOracleUCO = - ref.watch(aedappfm.ArchethicOracleUCOProviders.archethicOracleUCO); + final archethicOracleUCO = await ref.watch( + aedappfm.ArchethicOracleUCOProviders.archethicOracleUCO.future, + ); return MarketPrice( amount: archethicOracleUCO.usd, lastLoading: archethicOracleUCO.timestamp, diff --git a/lib/application/market_price.g.dart b/lib/application/market_price.g.dart index 842212d28..6f8eb90e9 100644 --- a/lib/application/market_price.g.dart +++ b/lib/application/market_price.g.dart @@ -197,7 +197,7 @@ class _CurrencyMarketPriceProviderElement } String _$selectedCurrencyMarketPriceHash() => - r'69f0af143b31a1721384a52e02f83754d998c655'; + r'0cf631f6520aad26b955dad70be91fd811a7da87'; /// See also [_selectedCurrencyMarketPrice]. @ProviderFor(_selectedCurrencyMarketPrice) diff --git a/lib/domain/repositories/transaction_remote.dart b/lib/domain/repositories/transaction_remote.dart index 3986f764b..af9867e8d 100644 --- a/lib/domain/repositories/transaction_remote.dart +++ b/lib/domain/repositories/transaction_remote.dart @@ -9,11 +9,9 @@ import 'package:aewallet/model/data/account.dart'; import 'package:archethic_lib_dart/archethic_lib_dart.dart' as archethic; typedef TransactionConfirmationHandler = Future Function( - archethic.TransactionSenderInterface sender, archethic.TransactionConfirmation confirmation, ); typedef TransactionErrorHandler = Future Function( - archethic.TransactionSenderInterface sender, archethic.TransactionError error, ); @@ -22,11 +20,16 @@ abstract class TransactionRemoteRepositoryInterface { Future> calculateFees(Transaction transaction); - Future send({ + Future send({ required Transaction transaction, Duration timeout = const Duration(seconds: 10), - required TransactionConfirmationHandler onConfirmation, - required TransactionErrorHandler onError, + TransactionConfirmationHandler? onConfirmation, + }); + + Future sendSignedRaw({ + required archethic.Transaction transaction, + Duration timeout = const Duration(seconds: 10), + TransactionConfirmationHandler? onConfirmation, }); Future buildTransactionRaw( @@ -36,13 +39,6 @@ abstract class TransactionRemoteRepositoryInterface { String serviceName, ); - Future sendSignedRaw({ - required archethic.Transaction transactionSignedRaw, - Duration timeout = const Duration(seconds: 10), - required TransactionConfirmationHandler onConfirmation, - required TransactionErrorHandler onError, - }); - Future getLastTransactionAddress({ required String genesisAddress, }); diff --git a/lib/domain/repositories/transaction_validation_ratios.dart b/lib/domain/repositories/transaction_validation_ratios.dart deleted file mode 100644 index c3874f753..000000000 --- a/lib/domain/repositories/transaction_validation_ratios.dart +++ /dev/null @@ -1,15 +0,0 @@ -class TransactionValidationRatios { - static const addFungibleToken = 0.5; - static const addAccount = 0.5; - static const addNFT = 0.5; - static const transfer = 0.5; - static const createKeychain = 0.5; - static const createKeychainAccess = 0.5; - static const swap = 0.5; - static const addLiquidity = 0.5; - static const removeLiquidity = 0.5; - static const depositFarmLock = 0.5; - static const claimFarmLock = 0.5; - static const levelUpFarmLock = 0.5; - static const withdrawFarmLock = 0.5; -} diff --git a/lib/domain/usecases/aeswap/add_liquidity.usecase.dart b/lib/domain/usecases/aeswap/add_liquidity.usecase.dart index 336e9da57..4e4db63e1 100644 --- a/lib/domain/usecases/aeswap/add_liquidity.usecase.dart +++ b/lib/domain/usecases/aeswap/add_liquidity.usecase.dart @@ -2,7 +2,6 @@ import 'dart:async'; import 'package:aewallet/domain/repositories/transaction_remote.dart'; -import 'package:aewallet/domain/repositories/transaction_validation_ratios.dart'; import 'package:aewallet/model/blockchain/keychain_secured_infos.dart'; import 'package:aewallet/model/data/account.dart'; import 'package:aewallet/modules/aeswap/application/contracts/archethic_contract.dart'; @@ -95,67 +94,57 @@ class AddLiquidityCase with aedappfm.TransactionMixin { liquidityAddNotifier.setTransactionAddLiquidity(transationSignedRaw); - await transactionRepository.sendSignedRaw( - transactionSignedRaw: transationSignedRaw, - onConfirmation: (sender, confirmation) async { - if (archethic.TransactionConfirmation.isEnoughConfirmations( - confirmation.nbConfirmations, - confirmation.maxConfirmations, - TransactionValidationRatios.addLiquidity, - )) { - sender.close(); + final confirmation = await transactionRepository.sendSignedRaw( + transaction: transationSignedRaw, + ); - liquidityAddNotifier - ..setResumeProcess(false) - ..setProcessInProgress(false) - ..setLiquidityAddOk(true); + if (confirmation == null) return; + liquidityAddNotifier + ..setResumeProcess(false) + ..setLiquidityAddOk(true); - notificationService.start( - operationId, - DexNotification.addLiquidity( - txAddress: transationSignedRaw.address!.address, - ), - ); + notificationService.start( + operationId, + DexNotification.addLiquidity( + txAddress: transationSignedRaw.address!.address, + ), + ); - final amount = await aedappfm.PeriodicFuture.periodic( - () => getAmountFromTxInput( - transationSignedRaw.address!.address!, - lpToken.address, - apiService, - ), - sleepDuration: const Duration(seconds: 3), - until: (amount) => amount > 0, - timeout: const Duration(minutes: 1), - ); + final amount = await aedappfm.PeriodicFuture.periodic( + () => getAmountFromTxInput( + transationSignedRaw.address!.address!, + lpToken.address, + apiService, + ), + sleepDuration: const Duration(seconds: 3), + until: (amount) => amount > 0, + timeout: const Duration(minutes: 1), + ); - liquidityAddNotifier.setFinalAmount(amount); + liquidityAddNotifier.setFinalAmount(amount); - notificationService.succeed( - operationId, - DexNotification.addLiquidity( - txAddress: transationSignedRaw.address!.address, - lpToken: lpToken, - amount: amount, - ), - ); - } - }, - onError: (sender, error) async { - notificationService.failed( - operationId, - aedappfm.Failure.fromError(error.messageLabel), - ); - liquidityAddNotifier - ..setResumeProcess(false) - ..setProcessInProgress(false) - ..setLiquidityAddOk(false) - ..setFailure( - aedappfm.Failure.other( - cause: error.messageLabel.capitalize(), - ), - ); - }, + notificationService.succeed( + operationId, + DexNotification.addLiquidity( + txAddress: transationSignedRaw.address!.address, + lpToken: lpToken, + amount: amount, + ), + ); + } on archethic.TransactionError catch (error) { + notificationService.failed( + operationId, + aedappfm.Failure.fromError(error.messageLabel), ); + liquidityAddNotifier + ..setResumeProcess(false) + ..setProcessInProgress(false) + ..setLiquidityAddOk(false) + ..setFailure( + aedappfm.Failure.other( + cause: error.messageLabel.capitalize(), + ), + ); } catch (e) { liquidityAddNotifier ..setResumeProcess(false) diff --git a/lib/domain/usecases/aeswap/claim_farm_lock.usecase.dart b/lib/domain/usecases/aeswap/claim_farm_lock.usecase.dart index b91d7dfa2..d2aab0088 100644 --- a/lib/domain/usecases/aeswap/claim_farm_lock.usecase.dart +++ b/lib/domain/usecases/aeswap/claim_farm_lock.usecase.dart @@ -1,7 +1,7 @@ /// SPDX-License-Identifier: AGPL-3.0-or-later import 'dart:async'; + import 'package:aewallet/domain/repositories/transaction_remote.dart'; -import 'package:aewallet/domain/repositories/transaction_validation_ratios.dart'; import 'package:aewallet/model/blockchain/keychain_secured_infos.dart'; import 'package:aewallet/model/data/account.dart'; import 'package:aewallet/modules/aeswap/application/contracts/archethic_contract.dart'; @@ -91,78 +91,68 @@ class ClaimFarmLockCase with aedappfm.TransactionMixin { transationSignedRaw, ); - await transactionRepository.sendSignedRaw( - transactionSignedRaw: transationSignedRaw, - onConfirmation: (sender, confirmation) async { - if (archethic.TransactionConfirmation.isEnoughConfirmations( - confirmation.nbConfirmations, - confirmation.maxConfirmations, - TransactionValidationRatios.claimFarmLock, - )) { - sender.close(); - - farmClaimLockNotifier - ..setResumeProcess(false) - ..setProcessInProgress(false) - ..setFarmLockClaimOk(true); - - notificationService.start( - operationId, - DexNotification.claimFarmLock( - txAddress: transationSignedRaw.address!.address, - ), - ); + final confirmation = await transactionRepository.sendSignedRaw( + transaction: transationSignedRaw, + ); - await aedappfm.PeriodicFuture.periodic( - () => isSCCallExecuted( - apiService, - farmGenesisAddress, - transationSignedRaw.address!.address!, - ), - sleepDuration: const Duration(seconds: 3), - until: (depositOk) => depositOk == true, - timeout: const Duration(minutes: 1), - ); + if (confirmation == null) return; + farmClaimLockNotifier + ..setResumeProcess(false) + ..setFarmLockClaimOk(true); - final amount = await aedappfm.PeriodicFuture.periodic( - () => getAmountFromTxInput( - transationSignedRaw.address!.address!, - rewardToken.address, - apiService, - ), - sleepDuration: const Duration(seconds: 3), - until: (amount) => amount > 0, - timeout: const Duration(minutes: 1), - ); + notificationService.start( + operationId, + DexNotification.claimFarmLock( + txAddress: transationSignedRaw.address!.address, + ), + ); - farmClaimLockNotifier.setFinalAmount(amount); + await aedappfm.PeriodicFuture.periodic( + () => isSCCallExecuted( + apiService, + farmGenesisAddress, + transationSignedRaw.address!.address!, + ), + sleepDuration: const Duration(seconds: 3), + until: (depositOk) => depositOk == true, + timeout: const Duration(minutes: 1), + ); - notificationService.succeed( - operationId, - DexNotification.claimFarmLock( - txAddress: transationSignedRaw.address!.address, - amount: amount, - rewardToken: rewardToken, - ), - ); - } - }, - onError: (sender, error) async { - notificationService.failed( - operationId, - aedappfm.Failure.fromError(error.messageLabel), - ); - farmClaimLockNotifier - ..setResumeProcess(false) - ..setProcessInProgress(false) - ..setFarmLockClaimOk(false) - ..setFailure( - aedappfm.Failure.other( - cause: error.messageLabel.capitalize(), - ), - ); - }, + final amount = await aedappfm.PeriodicFuture.periodic( + () => getAmountFromTxInput( + transationSignedRaw.address!.address!, + rewardToken.address, + apiService, + ), + sleepDuration: const Duration(seconds: 3), + until: (amount) => amount > 0, + timeout: const Duration(minutes: 1), ); + + farmClaimLockNotifier.setFinalAmount(amount); + + notificationService.succeed( + operationId, + DexNotification.claimFarmLock( + txAddress: transationSignedRaw.address!.address, + amount: amount, + rewardToken: rewardToken, + ), + ); + } on archethic.TransactionError catch (error) { + notificationService.failed( + operationId, + aedappfm.Failure.fromError(error.messageLabel), + ); + farmClaimLockNotifier + ..setResumeProcess(false) + ..setProcessInProgress(false) + ..setFarmLockClaimOk(false) + ..setFailure( + aedappfm.Failure.other( + cause: error.messageLabel.capitalize(), + ), + ); } catch (e) { farmClaimLockNotifier ..setResumeProcess(false) diff --git a/lib/domain/usecases/aeswap/deposit_farm_lock.usecase.dart b/lib/domain/usecases/aeswap/deposit_farm_lock.usecase.dart index 55d6ab3a3..1727a121b 100644 --- a/lib/domain/usecases/aeswap/deposit_farm_lock.usecase.dart +++ b/lib/domain/usecases/aeswap/deposit_farm_lock.usecase.dart @@ -2,7 +2,6 @@ import 'dart:async'; import 'package:aewallet/domain/repositories/transaction_remote.dart'; -import 'package:aewallet/domain/repositories/transaction_validation_ratios.dart'; import 'package:aewallet/model/blockchain/keychain_secured_infos.dart'; import 'package:aewallet/model/data/account.dart'; import 'package:aewallet/modules/aeswap/application/contracts/archethic_contract.dart'; @@ -96,70 +95,60 @@ class DepositFarmLockCase with aedappfm.TransactionMixin { farmLockDepositNotifier .setTransactionFarmLockDeposit(transationSignedRaw); - await transactionRepository.sendSignedRaw( - transactionSignedRaw: transationSignedRaw, - onConfirmation: (sender, confirmation) async { - if (archethic.TransactionConfirmation.isEnoughConfirmations( - confirmation.nbConfirmations, - confirmation.maxConfirmations, - TransactionValidationRatios.depositFarmLock, - )) { - sender.close(); + final confirmation = await transactionRepository.sendSignedRaw( + transaction: transationSignedRaw, + ); - farmLockDepositNotifier - ..setResumeProcess(false) - ..setProcessInProgress(false) - ..setFarmLockDepositOk(true); + if (confirmation == null) return; + farmLockDepositNotifier + ..setResumeProcess(false) + ..setFarmLockDepositOk(true); - notificationService.start( - operationId, - DexNotification.depositFarmLock( - txAddress: transationSignedRaw.address!.address, - farmAddress: farmAddress, - isUCO: isUCO, - ), - ); + notificationService.start( + operationId, + DexNotification.depositFarmLock( + txAddress: transationSignedRaw.address!.address, + farmAddress: farmAddress, + isUCO: isUCO, + ), + ); - await aedappfm.PeriodicFuture.periodic( - () => isSCCallExecuted( - apiService, - farmAddress, - transationSignedRaw.address!.address!, - ), - sleepDuration: const Duration(seconds: 3), - until: (depositOk) => depositOk == true, - timeout: const Duration(minutes: 1), - ); + await aedappfm.PeriodicFuture.periodic( + () => isSCCallExecuted( + apiService, + farmAddress, + transationSignedRaw.address!.address!, + ), + sleepDuration: const Duration(seconds: 3), + until: (depositOk) => depositOk == true, + timeout: const Duration(minutes: 1), + ); - farmLockDepositNotifier.setFinalAmount(amount); + farmLockDepositNotifier.setFinalAmount(amount); - notificationService.succeed( - operationId, - DexNotification.depositFarmLock( - txAddress: transationSignedRaw.address!.address, - amount: amount, - farmAddress: farmAddress, - isUCO: isUCO, - ), - ); - } - }, - onError: (sender, error) async { - notificationService.failed( - operationId, - aedappfm.Failure.fromError(error.messageLabel), - ); - farmLockDepositNotifier - ..setResumeProcess(false) - ..setProcessInProgress(false) - ..setFarmLockDepositOk(false) - ..setFailure( - aedappfm.Failure.other( - cause: error.messageLabel.capitalize(), - ), - ); - }, + notificationService.succeed( + operationId, + DexNotification.depositFarmLock( + txAddress: transationSignedRaw.address!.address, + amount: amount, + farmAddress: farmAddress, + isUCO: isUCO, + ), + ); + } on archethic.TransactionError catch (error) { + notificationService.failed( + operationId, + aedappfm.Failure.fromError(error.messageLabel), ); + farmLockDepositNotifier + ..setResumeProcess(false) + ..setProcessInProgress(false) + ..setFarmLockDepositOk(false) + ..setFailure( + aedappfm.Failure.other( + cause: error.messageLabel.capitalize(), + ), + ); } catch (e) { farmLockDepositNotifier ..setResumeProcess(false) diff --git a/lib/domain/usecases/aeswap/level_up_farm_lock.usecase.dart b/lib/domain/usecases/aeswap/level_up_farm_lock.usecase.dart index f8619e0da..9a29e0bc8 100644 --- a/lib/domain/usecases/aeswap/level_up_farm_lock.usecase.dart +++ b/lib/domain/usecases/aeswap/level_up_farm_lock.usecase.dart @@ -2,7 +2,6 @@ import 'dart:async'; import 'package:aewallet/domain/repositories/transaction_remote.dart'; -import 'package:aewallet/domain/repositories/transaction_validation_ratios.dart'; import 'package:aewallet/model/blockchain/keychain_secured_infos.dart'; import 'package:aewallet/model/data/account.dart'; import 'package:aewallet/modules/aeswap/application/contracts/archethic_contract.dart'; @@ -99,70 +98,60 @@ class LevelUpFarmLockCase with aedappfm.TransactionMixin { farmLevelUpNotifier.setTransactionFarmLockLevelUp(transationSignedRaw); - await transactionRepository.sendSignedRaw( - transactionSignedRaw: transationSignedRaw, - onConfirmation: (sender, confirmation) async { - if (archethic.TransactionConfirmation.isEnoughConfirmations( - confirmation.nbConfirmations, - confirmation.maxConfirmations, - TransactionValidationRatios.levelUpFarmLock, - )) { - sender.close(); + final confirmation = await transactionRepository.sendSignedRaw( + transaction: transationSignedRaw, + ); - farmLevelUpNotifier - ..setResumeProcess(false) - ..setProcessInProgress(false) - ..setFarmLockLevelUpOk(true); + if (confirmation == null) return; + farmLevelUpNotifier + ..setResumeProcess(false) + ..setFarmLockLevelUpOk(true); - notificationService.start( - operationId, - DexNotification.levelUpFarmLock( - txAddress: transationSignedRaw.address!.address, - farmAddress: farmAddress, - isUCO: isUCO, - ), - ); + notificationService.start( + operationId, + DexNotification.levelUpFarmLock( + txAddress: transationSignedRaw.address!.address, + farmAddress: farmAddress, + isUCO: isUCO, + ), + ); - await aedappfm.PeriodicFuture.periodic( - () => isSCCallExecuted( - apiService, - farmAddress, - transationSignedRaw.address!.address!, - ), - sleepDuration: const Duration(seconds: 3), - until: (depositOk) => depositOk == true, - timeout: const Duration(minutes: 1), - ); + await aedappfm.PeriodicFuture.periodic( + () => isSCCallExecuted( + apiService, + farmAddress, + transationSignedRaw.address!.address!, + ), + sleepDuration: const Duration(seconds: 3), + until: (depositOk) => depositOk == true, + timeout: const Duration(minutes: 1), + ); - farmLevelUpNotifier.setFinalAmount(amount); + farmLevelUpNotifier.setFinalAmount(amount); - notificationService.succeed( - operationId, - DexNotification.levelUpFarmLock( - txAddress: transationSignedRaw.address!.address, - amount: amount, - farmAddress: farmAddress, - isUCO: isUCO, - ), - ); - } - }, - onError: (sender, error) async { - notificationService.failed( - operationId, - aedappfm.Failure.fromError(error.messageLabel), - ); - farmLevelUpNotifier - ..setResumeProcess(false) - ..setProcessInProgress(false) - ..setFarmLockLevelUpOk(false) - ..setFailure( - aedappfm.Failure.other( - cause: error.messageLabel.capitalize(), - ), - ); - }, + notificationService.succeed( + operationId, + DexNotification.levelUpFarmLock( + txAddress: transationSignedRaw.address!.address, + amount: amount, + farmAddress: farmAddress, + isUCO: isUCO, + ), ); + } on archethic.TransactionError catch (error) { + notificationService.failed( + operationId, + aedappfm.Failure.fromError(error.messageLabel), + ); + farmLevelUpNotifier + ..setResumeProcess(false) + ..setProcessInProgress(false) + ..setFarmLockLevelUpOk(false) + ..setFailure( + aedappfm.Failure.other( + cause: error.messageLabel.capitalize(), + ), + ); } catch (e) { farmLevelUpNotifier ..setResumeProcess(false) diff --git a/lib/domain/usecases/aeswap/remove_liquidity.usecase.dart b/lib/domain/usecases/aeswap/remove_liquidity.usecase.dart index e7411a0dc..3ce5649b5 100644 --- a/lib/domain/usecases/aeswap/remove_liquidity.usecase.dart +++ b/lib/domain/usecases/aeswap/remove_liquidity.usecase.dart @@ -2,7 +2,6 @@ import 'dart:async'; import 'package:aewallet/domain/repositories/transaction_remote.dart'; -import 'package:aewallet/domain/repositories/transaction_validation_ratios.dart'; import 'package:aewallet/model/blockchain/keychain_secured_infos.dart'; import 'package:aewallet/model/data/account.dart'; import 'package:aewallet/modules/aeswap/application/contracts/archethic_contract.dart'; @@ -96,99 +95,87 @@ class RemoveLiquidityCase with aedappfm.TransactionMixin { liquidityRemoveNotifier .setTransactionRemoveLiquidity(transationSignedRaw); - await transactionRepository.sendSignedRaw( - transactionSignedRaw: transationSignedRaw, - onConfirmation: (sender, confirmation) async { - if (archethic.TransactionConfirmation.isEnoughConfirmations( - confirmation.nbConfirmations, - confirmation.maxConfirmations, - TransactionValidationRatios.removeLiquidity, - )) { - sender.close(); + final confirmation = await transactionRepository.sendSignedRaw( + transaction: transationSignedRaw, + ); - liquidityRemoveNotifier - ..setResumeProcess(false) - ..setProcessInProgress(false) - ..setLiquidityRemoveOk(true); + if (confirmation == null) return; - notificationService.start( - operationId, - DexNotification.removeLiquidity( - txAddress: transationSignedRaw.address!.address, - ), - ); + liquidityRemoveNotifier + ..setResumeProcess(false) + ..setLiquidityRemoveOk(true); - final amounts = - await aedappfm.PeriodicFuture.periodic>( - () => Future.wait([ - getAmountFromTxInput( - transationSignedRaw.address!.address!, - token1.address, - apiService, - ), - getAmountFromTxInput( - transationSignedRaw.address!.address!, - token2.address, - apiService, - ), - getAmountFromTx( - apiService, - transationSignedRaw.address!.address!, - false, - '00000000000000000000000000000000000000000000000000000000000000000000', - ), - ]), - sleepDuration: const Duration(seconds: 3), - until: (amounts) { - final amountToken1 = amounts[0]; - final amountToken2 = amounts[1]; - final amountLPToken = amounts[2]; - return amountToken1 > 0 && - amountToken2 > 0 && - amountLPToken > 0; - }, - timeout: const Duration(minutes: 1), - ); + notificationService.start( + operationId, + DexNotification.removeLiquidity( + txAddress: transationSignedRaw.address!.address, + ), + ); - final amountToken1 = amounts[0]; - final amountToken2 = amounts[1]; - final amountLPToken = amounts[2]; + final amounts = await aedappfm.PeriodicFuture.periodic>( + () => Future.wait([ + getAmountFromTxInput( + transationSignedRaw.address!.address!, + token1.address, + apiService, + ), + getAmountFromTxInput( + transationSignedRaw.address!.address!, + token2.address, + apiService, + ), + getAmountFromTx( + apiService, + transationSignedRaw.address!.address!, + false, + '00000000000000000000000000000000000000000000000000000000000000000000', + ), + ]), + sleepDuration: const Duration(seconds: 3), + until: (amounts) { + final amountToken1 = amounts[0]; + final amountToken2 = amounts[1]; + final amountLPToken = amounts[2]; + return amountToken1 > 0 && amountToken2 > 0 && amountLPToken > 0; + }, + timeout: const Duration(minutes: 1), + ); - liquidityRemoveNotifier - ..setFinalAmountToken1(amountToken1) - ..setFinalAmountToken2(amountToken2) - ..setFinalAmountLPToken(amountLPToken); + final amountToken1 = amounts[0]; + final amountToken2 = amounts[1]; + final amountLPToken = amounts[2]; - notificationService.succeed( - operationId, - DexNotification.removeLiquidity( - txAddress: transationSignedRaw.address!.address, - token1: token1, - token2: token2, - lpToken: lpToken, - amountToken1: amountToken1, - amountToken2: amountToken2, - amountLPToken: amountLPToken, - ), - ); - } - }, - onError: (sender, error) async { - notificationService.failed( - operationId, - aedappfm.Failure.fromError(error.messageLabel), - ); - liquidityRemoveNotifier - ..setResumeProcess(false) - ..setProcessInProgress(false) - ..setLiquidityRemoveOk(false) - ..setFailure( - aedappfm.Failure.other( - cause: error.messageLabel.capitalize(), - ), - ); - }, + liquidityRemoveNotifier + ..setFinalAmountToken1(amountToken1) + ..setFinalAmountToken2(amountToken2) + ..setFinalAmountLPToken(amountLPToken); + + notificationService.succeed( + operationId, + DexNotification.removeLiquidity( + txAddress: transationSignedRaw.address!.address, + token1: token1, + token2: token2, + lpToken: lpToken, + amountToken1: amountToken1, + amountToken2: amountToken2, + amountLPToken: amountLPToken, + ), ); + } on archethic.TransactionError catch (error) { + notificationService.failed( + operationId, + aedappfm.Failure.fromError(error.messageLabel), + ); + liquidityRemoveNotifier + ..setResumeProcess(false) + ..setProcessInProgress(false) + ..setLiquidityRemoveOk(false) + ..setFailure( + aedappfm.Failure.other( + cause: error.messageLabel.capitalize(), + ), + ); } catch (e) { liquidityRemoveNotifier ..setResumeProcess(false) diff --git a/lib/domain/usecases/aeswap/swap.usecase.dart b/lib/domain/usecases/aeswap/swap.usecase.dart index a31f75362..663e00237 100644 --- a/lib/domain/usecases/aeswap/swap.usecase.dart +++ b/lib/domain/usecases/aeswap/swap.usecase.dart @@ -3,7 +3,6 @@ import 'dart:async'; import 'dart:ui'; import 'package:aewallet/domain/repositories/transaction_remote.dart'; -import 'package:aewallet/domain/repositories/transaction_validation_ratios.dart'; import 'package:aewallet/model/blockchain/keychain_secured_infos.dart'; import 'package:aewallet/model/data/account.dart'; import 'package:aewallet/modules/aeswap/application/contracts/archethic_contract.dart'; @@ -126,70 +125,61 @@ class SwapCase with aedappfm.TransactionMixin { swapNotifier.setRecoveryTransactionSwap(transationSignedRaw); - await transactionRepository.sendSignedRaw( - transactionSignedRaw: transationSignedRaw, - onConfirmation: (sender, confirmation) async { - if (archethic.TransactionConfirmation.isEnoughConfirmations( - confirmation.nbConfirmations, - confirmation.maxConfirmations, - TransactionValidationRatios.swap, - )) { - sender.close(); + final confirmation = await transactionRepository.sendSignedRaw( + transaction: transationSignedRaw, + ); - swapNotifier - ..setResumeProcess(false) - ..setProcessInProgress(false) - ..setSwapOk(true); + if (confirmation == null) return; - notificationService.start( - operationId, - DexNotification.swap( - txAddress: transationSignedRaw.address!.address, - tokenSwapped: tokenSwapped, - ), - ); + swapNotifier + ..setResumeProcess(false) + ..setSwapOk(true); - final amount = await aedappfm.PeriodicFuture.periodic( - () => getAmountFromTxInput( - transationSignedRaw.address!.address!, - tokenSwapped.address, - apiService, - ), - sleepDuration: const Duration(seconds: 3), - until: (amount) => amount > 0, - timeout: const Duration(minutes: 1), - ); + notificationService.start( + operationId, + DexNotification.swap( + txAddress: transationSignedRaw.address!.address, + tokenSwapped: tokenSwapped, + ), + ); - swapNotifier.setFinalAmount(amount); + final amount = await aedappfm.PeriodicFuture.periodic( + () => getAmountFromTxInput( + transationSignedRaw.address!.address!, + tokenSwapped.address, + apiService, + ), + sleepDuration: const Duration(seconds: 3), + until: (amount) => amount > 0, + timeout: const Duration(minutes: 1), + ); - notificationService.succeed( - operationId, - DexNotification.swap( - txAddress: transationSignedRaw.address!.address, - tokenSwapped: tokenSwapped, - amountSwapped: amount, - ), - ); - onDone(); - } - }, - onError: (sender, error) async { - notificationService.failed( - operationId, - aedappfm.Failure.fromError(error.messageLabel), - ); - swapNotifier - ..setResumeProcess(false) - ..setProcessInProgress(false) - ..setSwapOk(false) - ..setFailure( - aedappfm.Failure.other( - cause: error.messageLabel.capitalize(), - ), - ); - onDone(); - }, + swapNotifier.setFinalAmount(amount); + + notificationService.succeed( + operationId, + DexNotification.swap( + txAddress: transationSignedRaw.address!.address, + tokenSwapped: tokenSwapped, + amountSwapped: amount, + ), ); + onDone(); + } on archethic.TransactionError catch (error) { + notificationService.failed( + operationId, + aedappfm.Failure.fromError(error.messageLabel), + ); + swapNotifier + ..setResumeProcess(false) + ..setProcessInProgress(false) + ..setSwapOk(false) + ..setFailure( + aedappfm.Failure.other( + cause: error.messageLabel.capitalize(), + ), + ); + onDone(); } catch (e) { swapNotifier ..setResumeProcess(false) diff --git a/lib/domain/usecases/aeswap/withdraw_farm_lock.usecase.dart b/lib/domain/usecases/aeswap/withdraw_farm_lock.usecase.dart index 4d3915fa5..8edabd2f2 100644 --- a/lib/domain/usecases/aeswap/withdraw_farm_lock.usecase.dart +++ b/lib/domain/usecases/aeswap/withdraw_farm_lock.usecase.dart @@ -2,7 +2,6 @@ import 'dart:async'; import 'package:aewallet/domain/repositories/transaction_remote.dart'; -import 'package:aewallet/domain/repositories/transaction_validation_ratios.dart'; import 'package:aewallet/model/blockchain/keychain_secured_infos.dart'; import 'package:aewallet/model/data/account.dart'; import 'package:aewallet/modules/aeswap/application/contracts/archethic_contract.dart'; @@ -98,97 +97,86 @@ class WithdrawFarmLockCase with aedappfm.TransactionMixin { farmLockWithdrawNotifier .setTransactionWithdrawFarmLock(transationSignedRaw); - await transactionRepository.sendSignedRaw( - transactionSignedRaw: transationSignedRaw, - onConfirmation: (sender, confirmation) async { - if (archethic.TransactionConfirmation.isEnoughConfirmations( - confirmation.nbConfirmations, - confirmation.maxConfirmations, - TransactionValidationRatios.withdrawFarmLock, - )) { - sender.close(); + final confirmation = await transactionRepository.sendSignedRaw( + transaction: transationSignedRaw, + ); + if (confirmation == null) return; - farmLockWithdrawNotifier - ..setResumeProcess(false) - ..setProcessInProgress(false) - ..setFarmLockWithdrawOk(true); + farmLockWithdrawNotifier + ..setResumeProcess(false) + ..setFarmLockWithdrawOk(true); - notificationService.start( - operationId, - DexNotification.withdrawFarmLock( - txAddress: transationSignedRaw.address!.address, - rewardToken: rewardToken, - isFarmClose: isFarmClose, - ), - ); + notificationService.start( + operationId, + DexNotification.withdrawFarmLock( + txAddress: transationSignedRaw.address!.address, + rewardToken: rewardToken, + isFarmClose: isFarmClose, + ), + ); - await aedappfm.PeriodicFuture.periodic( - () => isSCCallExecuted( - apiService, - farmGenesisAddress, - transationSignedRaw.address!.address!, - ), - sleepDuration: const Duration(seconds: 3), - until: (depositOk) => depositOk == true, - timeout: const Duration(minutes: 1), - ); + await aedappfm.PeriodicFuture.periodic( + () => isSCCallExecuted( + apiService, + farmGenesisAddress, + transationSignedRaw.address!.address!, + ), + sleepDuration: const Duration(seconds: 3), + until: (depositOk) => depositOk == true, + timeout: const Duration(minutes: 1), + ); - final amounts = - await aedappfm.PeriodicFuture.periodic>( - () => Future.wait([ - getAmountFromTxInput( - transationSignedRaw.address!.address!, - rewardToken.address, - apiService, - ), - getAmountFromTxInput( - transationSignedRaw.address!.address!, - lpTokenAddress, - apiService, - ), - ]), - sleepDuration: const Duration(seconds: 3), - until: (amounts) { - return amounts[1] > 0; - }, - timeout: const Duration(minutes: 1), - ); + final amounts = await aedappfm.PeriodicFuture.periodic>( + () => Future.wait([ + getAmountFromTxInput( + transationSignedRaw.address!.address!, + rewardToken.address, + apiService, + ), + getAmountFromTxInput( + transationSignedRaw.address!.address!, + lpTokenAddress, + apiService, + ), + ]), + sleepDuration: const Duration(seconds: 3), + until: (amounts) { + return amounts[1] > 0; + }, + timeout: const Duration(minutes: 1), + ); - final amountReward = amounts[0]; - final amountWithdraw = amounts[1]; + final amountReward = amounts[0]; + final amountWithdraw = amounts[1]; - farmLockWithdrawNotifier - ..setFinalAmountReward(amountReward) - ..setFinalAmountWithdraw(amountWithdraw); + farmLockWithdrawNotifier + ..setFinalAmountReward(amountReward) + ..setFinalAmountWithdraw(amountWithdraw); - notificationService.succeed( - operationId, - DexNotification.withdrawFarmLock( - txAddress: transationSignedRaw.address!.address, - amountReward: amountReward, - amountWithdraw: amountWithdraw, - rewardToken: rewardToken, - isFarmClose: isFarmClose, - ), - ); - } - }, - onError: (sender, error) async { - notificationService.failed( - operationId, - aedappfm.Failure.fromError(error.messageLabel), - ); - farmLockWithdrawNotifier - ..setResumeProcess(false) - ..setProcessInProgress(false) - ..setFarmLockWithdrawOk(false) - ..setFailure( - aedappfm.Failure.other( - cause: error.messageLabel.capitalize(), - ), - ); - }, + notificationService.succeed( + operationId, + DexNotification.withdrawFarmLock( + txAddress: transationSignedRaw.address!.address, + amountReward: amountReward, + amountWithdraw: amountWithdraw, + rewardToken: rewardToken, + isFarmClose: isFarmClose, + ), + ); + } on archethic.TransactionError catch (error) { + notificationService.failed( + operationId, + aedappfm.Failure.fromError(error.messageLabel), ); + farmLockWithdrawNotifier + ..setResumeProcess(false) + ..setProcessInProgress(false) + ..setFarmLockWithdrawOk(false) + ..setFailure( + aedappfm.Failure.other( + cause: error.messageLabel.capitalize(), + ), + ); } catch (e) { farmLockWithdrawNotifier ..setResumeProcess(false) diff --git a/lib/domain/usecases/transaction/send_transaction.dart b/lib/domain/usecases/transaction/send_transaction.dart index 961930ad0..f2724d90b 100644 --- a/lib/domain/usecases/transaction/send_transaction.dart +++ b/lib/domain/usecases/transaction/send_transaction.dart @@ -120,21 +120,6 @@ class SendTransactionUseCase }) async { final _logger = Logger('SendTransactionUseCase'); - final operationCompleter = - Completer>(); - - void _fail(TransactionError error) { - operationCompleter.complete( - Result.failure(error), - ); - } - - final transactionSender = ArchethicTransactionSender( - phoenixHttpEndpoint: networkSettings.getPhoenixHttpLink(), - websocketEndpoint: networkSettings.getWebsocketUri(), - apiService: apiService, - ); - final transaction = await command.toArchethicTransaction( wallet: wallet, apiService: apiService, @@ -147,8 +132,9 @@ class SendTransactionUseCase } try { - // ignore: cascade_invocations - await transactionSender.send( + final confirmation = await ArchethicTransactionSender( + apiService: apiService, + ).send( transaction: transaction, onConfirmation: (confirmation) async { onProgress?.call( @@ -157,25 +143,22 @@ class SendTransactionUseCase progress: confirmation.nbConfirmations, ), ); - if (confirmation.isFullyConfirmed) { - _logger.info('Final confirmation received : $confirmation'); - operationCompleter.complete( - Result.success(confirmation), - ); - return; - } _logger.info('Confirmation received : $confirmation'); }, - onError: (error) async { - _logger.severe('Transaction error received', error); - _fail(error); - }, ); + if (confirmation == null) { + return const Result.failure(TransactionError.userRejected()); + } + + _logger.info('Final confirmation received : $confirmation'); + return Result.success(confirmation); + } on TransactionError catch (error) { + _logger.severe('Transaction error received', error); + return Result.failure(error); } catch (e) { - _fail(const TransactionError.other()); + _logger.severe('Transaction error received', e); + return const Result.failure(TransactionError.other()); } - - return operationCompleter.future; } } diff --git a/lib/infrastructure/repositories/transaction/archethic_transaction.dart b/lib/infrastructure/repositories/transaction/archethic_transaction.dart index a398746e4..c725782ed 100644 --- a/lib/infrastructure/repositories/transaction/archethic_transaction.dart +++ b/lib/infrastructure/repositories/transaction/archethic_transaction.dart @@ -271,56 +271,28 @@ class ArchethicTransactionRepository } @override - Future send({ + Future send({ required Transaction transaction, Duration timeout = const Duration(seconds: 10), - required TransactionConfirmationHandler onConfirmation, - required TransactionErrorHandler onError, - }) async { - final transactionSender = archethic.ArchethicTransactionSender( - phoenixHttpEndpoint: phoenixHttpEndpoint, - websocketEndpoint: websocketEndpoint, - apiService: apiService, - ); - - await transactionSender.send( - timeout: timeout, - transaction: await _buildTransaction(transaction), - onConfirmation: (transactionConfirmation) => onConfirmation( - transactionSender, - transactionConfirmation, - ), - onError: (error) => onError( - transactionSender, - error, - ), - ); - } + TransactionConfirmationHandler? onConfirmation, + }) async => + sendSignedRaw( + transaction: await _buildTransaction(transaction), + timeout: timeout, + onConfirmation: onConfirmation, + ); @override - Future sendSignedRaw({ - required archethic.Transaction transactionSignedRaw, + Future sendSignedRaw({ + required archethic.Transaction transaction, Duration timeout = const Duration(seconds: 10), - required TransactionConfirmationHandler onConfirmation, - required TransactionErrorHandler onError, - }) async { - final transactionSender = archethic.ArchethicTransactionSender( - phoenixHttpEndpoint: phoenixHttpEndpoint, - websocketEndpoint: websocketEndpoint, - apiService: apiService, - ); - - await transactionSender.send( - timeout: timeout, - transaction: transactionSignedRaw, - onConfirmation: (transactionConfirmation) => onConfirmation( - transactionSender, - transactionConfirmation, - ), - onError: (error) => onError( - transactionSender, - error, - ), - ); - } + TransactionConfirmationHandler? onConfirmation, + }) => + archethic.ArchethicTransactionSender( + apiService: apiService, + ).send( + timeout: timeout, + transaction: transaction, + onConfirmation: onConfirmation, + ); } diff --git a/lib/infrastructure/rpc/send_transaction/command_handler.dart b/lib/infrastructure/rpc/send_transaction/command_handler.dart index d26a7d1f6..20b93c017 100644 --- a/lib/infrastructure/rpc/send_transaction/command_handler.dart +++ b/lib/infrastructure/rpc/send_transaction/command_handler.dart @@ -10,18 +10,24 @@ class RPCSendTransactionCommandHandler extends RPCCommandHandler< @override RPCCommand commandToModel(awc.Request dto) { - if ((dto.payload['data'] as Map) - .containsKey('recipients')) { - dto.payload['data']['actionRecipients'] = - dto.payload['data']['recipients']; - (dto.payload['data'] as Map).remove('recipients'); - } + const _handledTypes = { + 'keychain', + 'transfer', + 'token', + 'contract', + }; + final type = dto.payload['type']; + + assert( + _handledTypes.contains(type), + 'SendTransaction only supports transactions of types $_handledTypes', + ); return RPCCommand( origin: dto.origin.toModel, data: awc.SendTransactionRequest( data: archethic.Data.fromJson(dto.payload['data']), - type: dto.payload['type'], + type: type, version: dto.version, generateEncryptedSeedSC: dto.payload['generateEncryptedSeedSC'], ), diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb index 978767dce..e2249ebdf 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -434,7 +434,7 @@ "bottomMainMenuSwap": "Swap", "bottomMainMenuEarn": "Earn", "bottomMainMenuBridge": "Bridge", - "tokenDetailMenuEarn": "Earn %1", + "tokenDetailMenuEarn": "Earn", "localDataMigrationMessage": "Update your current application.\nPlease wait...", "nftNotOwnerInfo": "You are not the owner of this NFT", "accountsListWarningRemoveAccount": "Click on the trash icon to remove the account from your keychain", diff --git a/lib/l10n/intl_fr.arb b/lib/l10n/intl_fr.arb index 7ce837134..8477f5510 100644 --- a/lib/l10n/intl_fr.arb +++ b/lib/l10n/intl_fr.arb @@ -453,8 +453,8 @@ "aeBridgeHeader": "Bridge", "aeSwapEarnHeader": "Gagner des UCO", "price": "Prix", - "aeSwapLaunchMessage": "Veuillez lancer l'application aeSwap pour continuer. Elle s'ouvrira dans votre navigateur par défaut.", - "aeSwapLaunchButton": "Lancer aeSwap", + "aeBridgeLaunchMessage": "Veuillez lancer l'application aeBridge pour continuer. Elle s'ouvrira dans votre navigateur par défaut.", + "aeBridgeLaunchButton": "Lancer aeBridge", "receiveHeader": "Recevoir des actifs sur Archethic", "receiveCopy": "Cliquez pour copier l'adresse", "earnValueLbl": "Gagner", diff --git a/lib/main.dart b/lib/main.dart index 8fec8db0b..28cfcfb5a 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -171,17 +171,6 @@ class AppState extends ConsumerState with WidgetsBindingObserver { switch (state) { case AppLifecycleState.paused: isDeviceSecured = await SecurityManager().isDeviceSecured(); - - await ref - .read( - aedappfm.ArchethicOracleUCOProviders.archethicOracleUCO.notifier, - ) - .stopSubscription(); - await ref - .read( - aedappfm.CoinPriceProviders.coinPrices.notifier, - ) - .stopTimer(); break; case AppLifecycleState.resumed: updateDefaultLocale(); @@ -192,17 +181,6 @@ class AppState extends ConsumerState with WidgetsBindingObserver { rootNavigatorKey.currentState!.overlay!.context, ); } - - await ref - .read( - aedappfm.ArchethicOracleUCOProviders.archethicOracleUCO.notifier, - ) - .startSubscription(); - await ref - .read( - aedappfm.CoinPriceProviders.coinPrices.notifier, - ) - .startTimer(); break; case AppLifecycleState.inactive: case AppLifecycleState.detached: diff --git a/lib/modules/aeswap/application/pool/dex_pool.g.dart b/lib/modules/aeswap/application/pool/dex_pool.g.dart index 4ae110304..562897fe9 100644 --- a/lib/modules/aeswap/application/pool/dex_pool.g.dart +++ b/lib/modules/aeswap/application/pool/dex_pool.g.dart @@ -899,7 +899,7 @@ class _GetPoolListForSearchProviderElement (origin as _GetPoolListForSearchProvider).poolList; } -String _$getPoolTxListHash() => r'7ea87f8baff442f09d90df6ecf6bd47be33bc4d5'; +String _$getPoolTxListHash() => r'86be07f288bf7a7ad8c651feda039965ed38c02b'; /// See also [_getPoolTxList]. @ProviderFor(_getPoolTxList) diff --git a/lib/modules/aeswap/application/pool/dex_pool_tx_list.dart b/lib/modules/aeswap/application/pool/dex_pool_tx_list.dart index 72322411a..d1dca41ca 100644 --- a/lib/modules/aeswap/application/pool/dex_pool_tx_list.dart +++ b/lib/modules/aeswap/application/pool/dex_pool_tx_list.dart @@ -58,8 +58,8 @@ Future> _getPoolTxList( if (transactionAction != null && transactionAction.data != null && - transactionAction.data!.actionRecipients.isNotEmpty && - transactionAction.data!.actionRecipients[0].action != null) { + transactionAction.data!.recipients.isNotEmpty && + transactionAction.data!.recipients[0].action != null) { var token1Amount = 0.0; var token2Amount = 0.0; double? totalValue; @@ -68,7 +68,7 @@ Future> _getPoolTxList( DexToken? token1; DexToken? token2; DexActionType? typeTx; - switch (transactionAction.data!.actionRecipients[0].action) { + switch (transactionAction.data!.recipients[0].action) { case 'swap': for (final transactionMovement in transactionAction .validationStamp!.ledgerOperations!.transactionMovements) { diff --git a/lib/service/app_service.dart b/lib/service/app_service.dart index c36f20267..f53381d5e 100644 --- a/lib/service/app_service.dart +++ b/lib/service/app_service.dart @@ -251,7 +251,7 @@ class AppService { nbTrf++; } if (nbTrf == 0) { - for (final contractRecipient in transaction.data!.actionRecipients) { + for (final contractRecipient in transaction.data!.recipients) { final recentTransaction = RecentTransaction() ..address = transaction.address!.address ..typeTx = RecentTransaction.transferOutput diff --git a/lib/ui/util/transaction_send_event_error_localization.dart b/lib/ui/util/transaction_send_event_error_localization.dart new file mode 100644 index 000000000..66211a51a --- /dev/null +++ b/lib/ui/util/transaction_send_event_error_localization.dart @@ -0,0 +1,31 @@ +import 'package:aewallet/bus/transaction_send_event.dart'; +import 'package:archethic_lib_dart/archethic_lib_dart.dart'; +import 'package:flutter_gen/gen_l10n/localizations.dart'; + +extension TransactionSendEventErrorLocalization on TransactionError { + TransactionSendEvent localizedEvent( + AppLocalizations localizations, + TransactionSendEventType transactionType, + ) => + TransactionSendEvent( + transactionType: transactionType, + maxConfirmations: maybeMap( + invalidConfirmation: (_) => 0, + orElse: () => null, + ), + response: maybeMap( + connectivity: (_) => localizations.noConnection, + consensusNotReached: (_) => localizations.consensusNotReached, + timeout: (_) => localizations.transactionTimeOut, + invalidConfirmation: (_) => 'ko', + rpcError: (error) => localizations.rpcError + .replaceFirst('%1', error.code.toString()) + .replaceFirst( + '%2', + '${error.message} ${error.data ?? ''}', + ), + other: (_) => localizations.genericError, + orElse: () => '', + ), + ); +} diff --git a/lib/ui/views/add_account/bloc/provider.dart b/lib/ui/views/add_account/bloc/provider.dart index 8edd31cd9..a83abdf90 100644 --- a/lib/ui/views/add_account/bloc/provider.dart +++ b/lib/ui/views/add_account/bloc/provider.dart @@ -5,8 +5,8 @@ import 'package:aewallet/application/session/session.dart'; import 'package:aewallet/application/transaction_repository.dart'; import 'package:aewallet/bus/transaction_send_event.dart'; import 'package:aewallet/domain/models/transaction.dart'; -import 'package:aewallet/domain/repositories/transaction_validation_ratios.dart'; import 'package:aewallet/model/data/account.dart'; +import 'package:aewallet/ui/util/transaction_send_event_error_localization.dart'; import 'package:aewallet/ui/views/add_account/bloc/state.dart'; import 'package:archethic_lib_dart/archethic_lib_dart.dart' as archethic; import 'package:event_taxi/event_taxi.dart'; @@ -107,86 +107,29 @@ class AddAccountFormNotifier extends AutoDisposeNotifier { seed: state.seed, ); - await transactionRepository.send( - transaction: transaction, - onConfirmation: (sender, confirmation) async { - if (archethic.TransactionConfirmation.isEnoughConfirmations( - confirmation.nbConfirmations, - confirmation.maxConfirmations, - TransactionValidationRatios.addAccount, - )) { - sender.close(); - EventTaxiImpl.singleton().fire( - TransactionSendEvent( - transactionType: TransactionSendEventType.keychain, - response: 'ok', - nbConfirmations: confirmation.nbConfirmations, - transactionAddress: confirmation.transactionAddress, - maxConfirmations: confirmation.maxConfirmations, - ), - ); - } - }, - onError: (sender, error) async { - error.maybeMap( - connectivity: (_) { - EventTaxiImpl.singleton().fire( - TransactionSendEvent( - transactionType: TransactionSendEventType.keychain, - response: localizations.noConnection, - nbConfirmations: 0, - ), - ); - }, - consensusNotReached: (_) { - EventTaxiImpl.singleton().fire( - TransactionSendEvent( - transactionType: TransactionSendEventType.keychain, - response: localizations.consensusNotReached, - nbConfirmations: 0, - ), - ); - }, - timeout: (_) { - EventTaxiImpl.singleton().fire( - TransactionSendEvent( - transactionType: TransactionSendEventType.keychain, - response: localizations.transactionTimeOut, - nbConfirmations: 0, - ), - ); - }, - invalidConfirmation: (_) { - EventTaxiImpl.singleton().fire( - TransactionSendEvent( - transactionType: TransactionSendEventType.keychain, - nbConfirmations: 0, - maxConfirmations: 0, - response: 'ko', - ), - ); - }, - other: (error) { - EventTaxiImpl.singleton().fire( - TransactionSendEvent( - transactionType: TransactionSendEventType.keychain, - response: localizations.genericError, - nbConfirmations: 0, - ), - ); - }, - orElse: () { - EventTaxiImpl.singleton().fire( - TransactionSendEvent( - transactionType: TransactionSendEventType.keychain, - response: '', - nbConfirmations: 0, - ), - ); - }, + try { + final confirmation = await transactionRepository.send( + transaction: transaction, + ); + if (confirmation != null) { + EventTaxiImpl.singleton().fire( + TransactionSendEvent( + transactionType: TransactionSendEventType.keychain, + response: 'ok', + nbConfirmations: confirmation.nbConfirmations, + transactionAddress: confirmation.transactionAddress, + maxConfirmations: confirmation.maxConfirmations, + ), ); - }, - ); + } + } on archethic.TransactionError catch (error) { + EventTaxiImpl.singleton().fire( + error.localizedEvent( + localizations, + TransactionSendEventType.keychain, + ), + ); + } } Future removeAccount(BuildContext context, String account) async { @@ -202,86 +145,29 @@ class AddAccountFormNotifier extends AutoDisposeNotifier { seed: state.seed, ); - await transactionRepository.send( - transaction: transaction, - onConfirmation: (sender, confirmation) async { - if (archethic.TransactionConfirmation.isEnoughConfirmations( - confirmation.nbConfirmations, - confirmation.maxConfirmations, - TransactionValidationRatios.addAccount, - )) { - sender.close(); - EventTaxiImpl.singleton().fire( - TransactionSendEvent( - transactionType: TransactionSendEventType.keychain, - response: 'ok', - nbConfirmations: confirmation.nbConfirmations, - transactionAddress: confirmation.transactionAddress, - maxConfirmations: confirmation.maxConfirmations, - ), - ); - } - }, - onError: (sender, error) async { - error.maybeMap( - connectivity: (_) { - EventTaxiImpl.singleton().fire( - TransactionSendEvent( - transactionType: TransactionSendEventType.keychain, - response: localizations.noConnection, - nbConfirmations: 0, - ), - ); - }, - consensusNotReached: (_) { - EventTaxiImpl.singleton().fire( - TransactionSendEvent( - transactionType: TransactionSendEventType.keychain, - response: localizations.consensusNotReached, - nbConfirmations: 0, - ), - ); - }, - timeout: (_) { - EventTaxiImpl.singleton().fire( - TransactionSendEvent( - transactionType: TransactionSendEventType.keychain, - response: localizations.transactionTimeOut, - nbConfirmations: 0, - ), - ); - }, - invalidConfirmation: (_) { - EventTaxiImpl.singleton().fire( - TransactionSendEvent( - transactionType: TransactionSendEventType.keychain, - nbConfirmations: 0, - maxConfirmations: 0, - response: 'ko', - ), - ); - }, - other: (error) { - EventTaxiImpl.singleton().fire( - TransactionSendEvent( - transactionType: TransactionSendEventType.keychain, - response: localizations.genericError, - nbConfirmations: 0, - ), - ); - }, - orElse: () { - EventTaxiImpl.singleton().fire( - TransactionSendEvent( - transactionType: TransactionSendEventType.keychain, - response: '', - nbConfirmations: 0, - ), - ); - }, + try { + final confirmation = await transactionRepository.send( + transaction: transaction, + ); + if (confirmation != null) { + EventTaxiImpl.singleton().fire( + TransactionSendEvent( + transactionType: TransactionSendEventType.keychain, + response: 'ok', + nbConfirmations: confirmation.nbConfirmations, + transactionAddress: confirmation.transactionAddress, + maxConfirmations: confirmation.maxConfirmations, + ), ); - }, - ); + } + } on archethic.TransactionError catch (error) { + EventTaxiImpl.singleton().fire( + error.localizedEvent( + localizations, + TransactionSendEventType.keychain, + ), + ); + } } } diff --git a/lib/ui/views/aeswap_earn/layouts/components/farm_lock_block_list_single_line_lock.dart b/lib/ui/views/aeswap_earn/layouts/components/farm_lock_block_list_single_line_lock.dart index 974b8e1ce..1e56eadb4 100644 --- a/lib/ui/views/aeswap_earn/layouts/components/farm_lock_block_list_single_line_lock.dart +++ b/lib/ui/views/aeswap_earn/layouts/components/farm_lock_block_list_single_line_lock.dart @@ -1,4 +1,3 @@ -import 'dart:ui'; import 'package:aewallet/modules/aeswap/domain/models/dex_farm_lock.dart'; import 'package:aewallet/modules/aeswap/domain/models/dex_farm_lock_user_infos.dart'; import 'package:aewallet/modules/aeswap/domain/models/dex_pool.dart'; diff --git a/lib/ui/views/main/bloc/providers.dart b/lib/ui/views/main/bloc/providers.dart index 74a847afd..98e69d6e9 100644 --- a/lib/ui/views/main/bloc/providers.dart +++ b/lib/ui/views/main/bloc/providers.dart @@ -21,86 +21,78 @@ part 'providers.g.dart'; /// /// Add Watch here for any provider you want to init when app is displayed. /// Those providers will be kept alive during application lifetime. + @riverpod -Future homePage(Ref ref) async { - ref - ..onCancel(() { - ref - .read( - aedappfm.ArchethicOracleUCOProviders.archethicOracleUCO.notifier, - ) - .stopSubscription(); - ref - .read( - aedappfm.CoinPriceProviders.coinPrices.notifier, - ) - .stopTimer(); - }) - ..watch(DexPoolProviders.getPoolList) - ..watch(DexPoolProviders.getPoolListRaw) - ..watch(DexTokensProviders.tokensCommonBases) - ..watch(verifiedTokensProvider) - ..watch(DexTokensProviders.tokensFromAccount) - ..watch(farmLockFormFarmLockProvider) - ..watch( - aedappfm.ArchethicOracleUCOProviders.archethicOracleUCO.notifier, - ) - ..watch(aedappfm.CoinPriceProviders.coinPrices) - ..listen( - connectivityStatusProviders, - (previous, next) async { - if (previous != next && next == ConnectivityStatus.isConnected) { - ref - ..invalidate(environmentProvider) - ..invalidate(ContactProviders.fetchContacts) - ..invalidate(MarketPriceProviders.currencyMarketPrice); - - final poolListRaw = - await ref.read(DexPoolProviders.getPoolListRaw.future); - - await (await ref - .read(AccountProviders.accounts.notifier) - .selectedAccountNotifier) - ?.refreshRecentTransactions(poolListRaw); - } - if (next == ConnectivityStatus.isDisconnected) { - /// When network becomes offline, start the subscriptions again - - // TODO(Chralu): Uncomment when https://github.com/archethic-foundation/libdart/issues/155 is fixed - // ref - // .read( - // aedappfm - // .ArchethicOracleUCOProviders.archethicOracleUCO.notifier, - // ) - // .stopSubscription(); - - await ref - .read( - aedappfm.CoinPriceProviders.coinPrices.notifier, - ) - .stopTimer(); - - return; - } - - /// When network becomes online, start the subscriptions again - await ref - .read( - aedappfm.ArchethicOracleUCOProviders.archethicOracleUCO.notifier, - ) - .startSubscription(); - - ref.invalidate(aedappfm.ArchethicOracleUCOProviders.archethicOracleUCO); - - await ref - .read( - aedappfm.CoinPriceProviders.coinPrices.notifier, - ) - .startTimer(); - - ref.invalidate(aedappfm.CoinPriceProviders.coinPrices); - }, - ); +class HomePage extends _$HomePage { + @override + Future build() async { + ref + ..watch(DexPoolProviders.getPoolList) + ..watch(DexPoolProviders.getPoolListRaw) + ..watch(DexTokensProviders.tokensCommonBases) + ..watch(verifiedTokensProvider) + ..watch(DexTokensProviders.tokensFromAccount) + ..watch(farmLockFormFarmLockProvider) + ..watch( + aedappfm.ArchethicOracleUCOProviders.archethicOracleUCO, + ) + ..watch(aedappfm.CoinPriceProviders.coinPrices) + ..listen( + connectivityStatusProviders, + (previous, next) async { + if (previous != next && next == ConnectivityStatus.isConnected) { + ref + ..invalidate(environmentProvider) + ..invalidate(ContactProviders.fetchContacts) + ..invalidate(MarketPriceProviders.currencyMarketPrice); + + final poolListRaw = + await ref.read(DexPoolProviders.getPoolListRaw.future); + + await (await ref + .read(AccountProviders.accounts.notifier) + .selectedAccountNotifier) + ?.refreshRecentTransactions(poolListRaw); + } + if (next == ConnectivityStatus.isDisconnected) { + /// When network becomes offline, stops subscriptions. + await stopSubscriptions(); + return; + } + + /// When network becomes online, start the subscriptions again + await startSubscriptions(); + }, + ); + } + + Future startSubscriptions() async { + await ref + .read( + aedappfm.ArchethicOracleUCOProviders.archethicOracleUCO.notifier, + ) + .startSubscription(); + + await ref + .read( + aedappfm.CoinPriceProviders.coinPrices.notifier, + ) + .startTimer(); + } + + Future stopSubscriptions() async { + await ref + .read( + aedappfm.ArchethicOracleUCOProviders.archethicOracleUCO.notifier, + ) + .stopSubscription(); + + await ref + .read( + aedappfm.CoinPriceProviders.coinPrices.notifier, + ) + .stopTimer(); + } } final mainTabControllerProvider = diff --git a/lib/ui/views/main/bloc/providers.g.dart b/lib/ui/views/main/bloc/providers.g.dart index df438ca63..3ae7c039e 100644 --- a/lib/ui/views/main/bloc/providers.g.dart +++ b/lib/ui/views/main/bloc/providers.g.dart @@ -6,17 +6,18 @@ part of 'providers.dart'; // RiverpodGenerator // ************************************************************************** -String _$homePageHash() => r'cdb981d053b2716c3dd56bf694b41edae6ae722e'; +String _$homePageHash() => r'483fa6063706ac3d4da2155ef26c597adfd752db'; /// Eagerly initializes providers (https://riverpod.dev/docs/essentials/eager_initialization). /// /// Add Watch here for any provider you want to init when app is displayed. /// Those providers will be kept alive during application lifetime. /// -/// Copied from [homePage]. -@ProviderFor(homePage) -final homePageProvider = AutoDisposeFutureProvider.internal( - homePage, +/// Copied from [HomePage]. +@ProviderFor(HomePage) +final homePageProvider = + AutoDisposeAsyncNotifierProvider.internal( + HomePage.new, name: r'homePageProvider', debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') ? null : _$homePageHash, @@ -24,8 +25,6 @@ final homePageProvider = AutoDisposeFutureProvider.internal( allTransitiveDependencies: null, ); -@Deprecated('Will be removed in 3.0. Use Ref instead') -// ignore: unused_element -typedef HomePageRef = AutoDisposeFutureProviderRef; +typedef _$HomePage = AutoDisposeAsyncNotifier; // ignore_for_file: type=lint // ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package diff --git a/lib/ui/views/main/components/home_providers_keepalive.dart b/lib/ui/views/main/components/home_providers_keepalive.dart new file mode 100644 index 000000000..e2d14b1b8 --- /dev/null +++ b/lib/ui/views/main/components/home_providers_keepalive.dart @@ -0,0 +1,59 @@ +import 'package:aewallet/ui/views/main/bloc/providers.dart'; +import 'package:flutter/widgets.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +/// Eagerly initializes providers (https://riverpod.dev/docs/essentials/eager_initialization). +/// +/// Add Watch here for any provider you want to init when app is displayed. +/// Those providers will be kept alive during application lifetime. +class HomeProvidersKeepalive extends ConsumerStatefulWidget { + const HomeProvidersKeepalive({required this.child, super.key}); + + final Widget child; + + @override + ConsumerState createState() => + _LoggedInProvidersState(); +} + +class _LoggedInProvidersState extends ConsumerState + with WidgetsBindingObserver { + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addObserver(this); + } + + @override + void dispose() { + WidgetsBinding.instance.removeObserver(this); + super.dispose(); + } + + @override + void didChangeAppLifecycleState(AppLifecycleState state) { + didChangeAppLifecycleStateAsync(state); + } + + Future didChangeAppLifecycleStateAsync(AppLifecycleState state) async { + switch (state) { + case AppLifecycleState.paused: + await ref.read(homePageProvider.notifier).stopSubscriptions(); + break; + case AppLifecycleState.resumed: + await ref.read(homePageProvider.notifier).startSubscriptions(); + break; + case AppLifecycleState.inactive: + case AppLifecycleState.detached: + case AppLifecycleState.hidden: + break; + } + super.didChangeAppLifecycleState(state); + } + + @override + Widget build(BuildContext context) { + ref.watch(homePageProvider); + return widget.child; + } +} diff --git a/lib/ui/views/main/home_page.dart b/lib/ui/views/main/home_page.dart index db5807ef8..db71070b0 100755 --- a/lib/ui/views/main/home_page.dart +++ b/lib/ui/views/main/home_page.dart @@ -12,6 +12,7 @@ import 'package:aewallet/ui/views/aeswap_earn/layouts/earn_tab.dart'; import 'package:aewallet/ui/views/aeswap_swap/layouts/swap_tab.dart'; import 'package:aewallet/ui/views/main/account_tab.dart'; import 'package:aewallet/ui/views/main/bloc/providers.dart'; +import 'package:aewallet/ui/views/main/components/home_providers_keepalive.dart'; import 'package:aewallet/ui/views/main/components/main_appbar.dart'; import 'package:aewallet/ui/views/main/components/recovery_phrase_banner.dart'; import 'package:aewallet/ui/views/main/transactions_tab.dart'; @@ -56,18 +57,14 @@ class _HomePageState extends ConsumerState @override Widget build(BuildContext context) { - /// Eagerly initializes providers (https://riverpod.dev/docs/essentials/eager_initialization). - /// - /// Add Watch here for any provider you want to init when app is displayed. - /// Those providers will be kept alive during application lifetime. - ref.watch(homePageProvider); - - return SheetSkeleton( - appBar: getAppBar(context, ref), - bottomNavigationBar: getFloatingActionButton(context, ref), - sheetContent: getSheetContent(context, ref), - menu: true, - floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, + return HomeProvidersKeepalive( + child: SheetSkeleton( + appBar: getAppBar(context, ref), + bottomNavigationBar: getFloatingActionButton(context, ref), + sheetContent: getSheetContent(context, ref), + menu: true, + floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, + ), ); } diff --git a/lib/ui/views/nft_creation/bloc/provider.dart b/lib/ui/views/nft_creation/bloc/provider.dart index 42bee7e74..f3901cf8a 100644 --- a/lib/ui/views/nft_creation/bloc/provider.dart +++ b/lib/ui/views/nft_creation/bloc/provider.dart @@ -13,10 +13,10 @@ import 'package:aewallet/domain/models/token.dart'; import 'package:aewallet/domain/models/token_property.dart'; import 'package:aewallet/domain/models/token_property_access.dart'; import 'package:aewallet/domain/models/transaction.dart'; -import 'package:aewallet/domain/repositories/transaction_validation_ratios.dart'; import 'package:aewallet/domain/usecases/transaction/calculate_fees.dart'; import 'package:aewallet/infrastructure/datasources/contacts.hive.dart'; import 'package:aewallet/ui/util/delayed_task.dart'; +import 'package:aewallet/ui/util/transaction_send_event_error_localization.dart'; import 'package:aewallet/ui/views/nft_creation/bloc/state.dart'; import 'package:aewallet/util/mime_util.dart'; import 'package:archethic_lib_dart/archethic_lib_dart.dart' as archethic; @@ -783,98 +783,45 @@ class NftCreationFormNotifier ), ); - await transactionRepository.send( - transaction: transaction, - onConfirmation: (sender, confirmation) async { - if (archethic.TransactionConfirmation.isEnoughConfirmations( - confirmation.nbConfirmations, - confirmation.maxConfirmations, - TransactionValidationRatios.addNFT, - )) { - sender.close(); + try { + final confirmation = await transactionRepository.send( + transaction: transaction, + ); + + if (confirmation == null) return; + EventTaxiImpl.singleton().fire( + TransactionSendEvent( + transactionType: TransactionSendEventType.token, + response: 'ok', + nbConfirmations: confirmation.nbConfirmations, + transactionAddress: confirmation.transactionAddress, + maxConfirmations: confirmation.maxConfirmations, + ), + ); + } on archethic.TransactionError catch (error) { + error.maybeMap( + insufficientFunds: (error) { EventTaxiImpl.singleton().fire( TransactionSendEvent( transactionType: TransactionSendEventType.token, - response: 'ok', - nbConfirmations: confirmation.nbConfirmations, - transactionAddress: confirmation.transactionAddress, - maxConfirmations: confirmation.maxConfirmations, + response: localizations.insufficientBalance.replaceAll( + '%1', + state.symbolFees(context), + ), + nbConfirmations: 0, ), ); - } - }, - onError: (sender, error) async { - error.maybeMap( - connectivity: (_) { - EventTaxiImpl.singleton().fire( - TransactionSendEvent( - transactionType: TransactionSendEventType.token, - response: localizations.noConnection, - nbConfirmations: 0, - ), - ); - }, - consensusNotReached: (_) { - EventTaxiImpl.singleton().fire( - TransactionSendEvent( - transactionType: TransactionSendEventType.token, - response: localizations.consensusNotReached, - nbConfirmations: 0, - ), - ); - }, - timeout: (_) { - EventTaxiImpl.singleton().fire( - TransactionSendEvent( - transactionType: TransactionSendEventType.token, - response: localizations.transactionTimeOut, - nbConfirmations: 0, - ), - ); - }, - invalidConfirmation: (_) { - EventTaxiImpl.singleton().fire( - TransactionSendEvent( - transactionType: TransactionSendEventType.token, - nbConfirmations: 0, - maxConfirmations: 0, - response: 'ko', - ), - ); - }, - insufficientFunds: (error) { - EventTaxiImpl.singleton().fire( - TransactionSendEvent( - transactionType: TransactionSendEventType.token, - response: localizations.insufficientBalance.replaceAll( - '%1', - state.symbolFees(context), - ), - nbConfirmations: 0, - ), - ); - }, - other: (error) { - EventTaxiImpl.singleton().fire( - TransactionSendEvent( - transactionType: TransactionSendEventType.token, - response: localizations.genericError, - nbConfirmations: 0, - ), - ); - }, - orElse: () { - EventTaxiImpl.singleton().fire( - TransactionSendEvent( - transactionType: TransactionSendEventType.token, - response: '', - nbConfirmations: 0, - ), - ); - }, - ); - }, - ); + }, + orElse: () { + EventTaxiImpl.singleton().fire( + error.localizedEvent( + localizations, + TransactionSendEventType.token, + ), + ); + }, + ); + } } } diff --git a/lib/ui/views/rpc_command_receiver/util/transaction_raw.dart b/lib/ui/views/rpc_command_receiver/util/transaction_raw.dart index 99d6122d2..4db9252c0 100644 --- a/lib/ui/views/rpc_command_receiver/util/transaction_raw.dart +++ b/lib/ui/views/rpc_command_receiver/util/transaction_raw.dart @@ -262,7 +262,7 @@ class TransactionRawState extends ConsumerState { .toList(), ), ), - if (transactionData.actionRecipients.isNotEmpty) + if (transactionData.recipients.isNotEmpty) ListTile( title: SelectableText( localizations.transactionRawSmartContractCalls, @@ -270,7 +270,7 @@ class TransactionRawState extends ConsumerState { ), subtitle: Column( crossAxisAlignment: CrossAxisAlignment.start, - children: transactionData.actionRecipients + children: transactionData.recipients .map( (actionRecipient) => Padding( padding: const EdgeInsets.only(left: 16), diff --git a/lib/ui/views/sheets/dapp_sheet.dart b/lib/ui/views/sheets/dapp_sheet.dart index 4faf32bf8..8710bfa05 100755 --- a/lib/ui/views/sheets/dapp_sheet.dart +++ b/lib/ui/views/sheets/dapp_sheet.dart @@ -90,8 +90,6 @@ class DAppSheetState extends ConsumerState Future.delayed(Duration.zero, () async { var dappKey = widget.dappKey; - if (!DAppSheet.isAvailable) dappKey = '${dappKey}Ext'; - final networkSettings = ref.watch( SettingsProviders.settings.select((settings) => settings.network), ); @@ -103,7 +101,9 @@ class DAppSheetState extends ConsumerState featureCode, ).future, ); - if (bridgeFlag == null || bridgeFlag == false) dappKey = '${dappKey}Ext'; + if (bridgeFlag == null || bridgeFlag == false || !DAppSheet.isAvailable) { + dappKey = '${dappKey}Ext'; + } final connectivityStatusProvider = ref.watch(connectivityStatusProviders); DApp? dapp; @@ -111,7 +111,6 @@ class DAppSheetState extends ConsumerState dapp = await ref.read( DAppsProviders.getDApp(dappKey).future, ); - setState(() { featureFlags = bridgeFlag; aeBridgeUrl = dapp!.url; diff --git a/lib/ui/views/tokens_fungibles/bloc/provider.dart b/lib/ui/views/tokens_fungibles/bloc/provider.dart index e46268393..4dc653877 100644 --- a/lib/ui/views/tokens_fungibles/bloc/provider.dart +++ b/lib/ui/views/tokens_fungibles/bloc/provider.dart @@ -8,9 +8,9 @@ import 'package:aewallet/application/transaction_repository.dart'; import 'package:aewallet/bus/transaction_send_event.dart'; import 'package:aewallet/domain/models/token.dart'; import 'package:aewallet/domain/models/transaction.dart'; -import 'package:aewallet/domain/repositories/transaction_validation_ratios.dart'; import 'package:aewallet/domain/usecases/transaction/calculate_fees.dart'; import 'package:aewallet/ui/util/delayed_task.dart'; +import 'package:aewallet/ui/util/transaction_send_event_error_localization.dart'; import 'package:aewallet/ui/views/tokens_fungibles/bloc/state.dart'; import 'package:archethic_lib_dart/archethic_lib_dart.dart' as archethic; import 'package:event_taxi/event_taxi.dart'; @@ -288,98 +288,45 @@ class AddTokenFormNotifier extends AutoDisposeNotifier { ), ); - await transactionRepository.send( - transaction: transaction, - onConfirmation: (sender, confirmation) async { - if (archethic.TransactionConfirmation.isEnoughConfirmations( - confirmation.nbConfirmations, - confirmation.maxConfirmations, - TransactionValidationRatios.addFungibleToken, - )) { - sender.close(); + try { + final confirmation = await transactionRepository.send( + transaction: transaction, + ); + + if (confirmation == null) return; + EventTaxiImpl.singleton().fire( + TransactionSendEvent( + transactionType: TransactionSendEventType.token, + response: 'ok', + nbConfirmations: confirmation.nbConfirmations, + transactionAddress: confirmation.transactionAddress, + maxConfirmations: confirmation.maxConfirmations, + ), + ); + } on archethic.TransactionError catch (error) { + error.maybeMap( + insufficientFunds: (error) { EventTaxiImpl.singleton().fire( TransactionSendEvent( transactionType: TransactionSendEventType.token, - response: 'ok', - nbConfirmations: confirmation.nbConfirmations, - transactionAddress: confirmation.transactionAddress, - maxConfirmations: confirmation.maxConfirmations, + response: localizations.insufficientBalance.replaceAll( + '%1', + state.symbolFees(context), + ), + nbConfirmations: 0, ), ); - } - }, - onError: (sender, error) async { - error.maybeMap( - connectivity: (_) { - EventTaxiImpl.singleton().fire( - TransactionSendEvent( - transactionType: TransactionSendEventType.token, - response: localizations.noConnection, - nbConfirmations: 0, - ), - ); - }, - consensusNotReached: (_) { - EventTaxiImpl.singleton().fire( - TransactionSendEvent( - transactionType: TransactionSendEventType.token, - response: localizations.consensusNotReached, - nbConfirmations: 0, - ), - ); - }, - timeout: (_) { - EventTaxiImpl.singleton().fire( - TransactionSendEvent( - transactionType: TransactionSendEventType.token, - response: localizations.transactionTimeOut, - nbConfirmations: 0, - ), - ); - }, - invalidConfirmation: (_) { - EventTaxiImpl.singleton().fire( - TransactionSendEvent( - transactionType: TransactionSendEventType.token, - nbConfirmations: 0, - maxConfirmations: 0, - response: 'ko', - ), - ); - }, - insufficientFunds: (error) { - EventTaxiImpl.singleton().fire( - TransactionSendEvent( - transactionType: TransactionSendEventType.token, - response: localizations.insufficientBalance.replaceAll( - '%1', - state.symbolFees(context), - ), - nbConfirmations: 0, - ), - ); - }, - other: (error) { - EventTaxiImpl.singleton().fire( - TransactionSendEvent( - transactionType: TransactionSendEventType.token, - response: localizations.genericError, - nbConfirmations: 0, - ), - ); - }, - orElse: () { - EventTaxiImpl.singleton().fire( - TransactionSendEvent( - transactionType: TransactionSendEventType.token, - response: '', - nbConfirmations: 0, - ), - ); - }, - ); - }, - ); + }, + orElse: () { + EventTaxiImpl.singleton().fire( + error.localizedEvent( + localizations, + TransactionSendEventType.token, + ), + ); + }, + ); + } } } diff --git a/lib/ui/views/transfer/bloc/provider.dart b/lib/ui/views/transfer/bloc/provider.dart index 25b5c9998..f6345220c 100644 --- a/lib/ui/views/transfer/bloc/provider.dart +++ b/lib/ui/views/transfer/bloc/provider.dart @@ -9,13 +9,12 @@ import 'package:aewallet/application/transaction_repository.dart'; import 'package:aewallet/bus/transaction_send_event.dart'; import 'package:aewallet/domain/models/transaction.dart'; import 'package:aewallet/domain/models/transfer.dart'; -import 'package:aewallet/domain/repositories/transaction_validation_ratios.dart'; import 'package:aewallet/domain/usecases/transaction/calculate_fees.dart'; import 'package:aewallet/infrastructure/datasources/contacts.hive.dart'; import 'package:aewallet/model/data/account.dart'; import 'package:aewallet/model/primary_currency.dart'; - import 'package:aewallet/ui/util/delayed_task.dart'; +import 'package:aewallet/ui/util/transaction_send_event_error_localization.dart'; import 'package:aewallet/ui/views/transfer/bloc/state.dart'; import 'package:archethic_dapp_framework_flutter/archethic_dapp_framework_flutter.dart' as aedappfm; @@ -812,113 +811,44 @@ class TransferFormNotifier extends AutoDisposeNotifier { case null: break; } - - await transferRepository.send( - transaction: transaction, - onConfirmation: (sender, confirmation) async { - if (archethic.TransactionConfirmation.isEnoughConfirmations( - confirmation.nbConfirmations, - confirmation.maxConfirmations, - TransactionValidationRatios.transfer, - )) { - sender.close(); + try { + final confirmation = await transferRepository.send( + transaction: transaction, + ); + if (confirmation == null) return; + EventTaxiImpl.singleton().fire( + TransactionSendEvent( + transactionType: TransactionSendEventType.transfer, + response: 'ok', + nbConfirmations: confirmation.nbConfirmations, + transactionAddress: confirmation.transactionAddress, + maxConfirmations: confirmation.maxConfirmations, + ), + ); + } on archethic.TransactionError catch (error) { + error.maybeMap( + insufficientFunds: (error) { EventTaxiImpl.singleton().fire( TransactionSendEvent( transactionType: TransactionSendEventType.transfer, - response: 'ok', - nbConfirmations: confirmation.nbConfirmations, - transactionAddress: confirmation.transactionAddress, - maxConfirmations: confirmation.maxConfirmations, + response: localizations.insufficientBalance.replaceAll( + '%1', + state.symbol(context), + ), + nbConfirmations: 0, ), ); - } - }, - onError: (sender, error) async { - error.maybeMap( - connectivity: (_) { - EventTaxiImpl.singleton().fire( - TransactionSendEvent( - transactionType: TransactionSendEventType.transfer, - response: localizations.noConnection, - nbConfirmations: 0, - ), - ); - }, - consensusNotReached: (_) { - EventTaxiImpl.singleton().fire( - TransactionSendEvent( - transactionType: TransactionSendEventType.transfer, - response: localizations.consensusNotReached, - nbConfirmations: 0, - ), - ); - }, - timeout: (_) { - EventTaxiImpl.singleton().fire( - TransactionSendEvent( - transactionType: TransactionSendEventType.transfer, - response: localizations.transactionTimeOut, - nbConfirmations: 0, - ), - ); - }, - invalidConfirmation: (_) { - EventTaxiImpl.singleton().fire( - TransactionSendEvent( - transactionType: TransactionSendEventType.transfer, - nbConfirmations: 0, - maxConfirmations: 0, - response: 'ko', - ), - ); - }, - insufficientFunds: (error) { - EventTaxiImpl.singleton().fire( - TransactionSendEvent( - transactionType: TransactionSendEventType.transfer, - response: localizations.insufficientBalance.replaceAll( - '%1', - state.symbol(context), - ), - nbConfirmations: 0, - ), - ); - }, - rpcError: (error) { - EventTaxiImpl.singleton().fire( - TransactionSendEvent( - transactionType: TransactionSendEventType.transfer, - response: localizations.rpcError - .replaceFirst('%1', error.code.toString()) - .replaceFirst( - '%2', - '${error.message} ${error.data ?? ''}', - ), - nbConfirmations: 0, - ), - ); - }, - other: (error) { - EventTaxiImpl.singleton().fire( - TransactionSendEvent( - transactionType: TransactionSendEventType.transfer, - response: '${localizations.genericError})', - nbConfirmations: 0, - ), - ); - }, - orElse: () { - EventTaxiImpl.singleton().fire( - TransactionSendEvent( - transactionType: TransactionSendEventType.transfer, - response: '', - nbConfirmations: 0, - ), - ); - }, - ); - }, - ); + }, + orElse: () { + EventTaxiImpl.singleton().fire( + error.localizedEvent( + localizations, + TransactionSendEventType.transfer, + ), + ); + }, + ); + } } } diff --git a/lib/util/keychain_util.dart b/lib/util/keychain_util.dart index b8940c7d5..7dd9b6fc3 100644 --- a/lib/util/keychain_util.dart +++ b/lib/util/keychain_util.dart @@ -5,7 +5,6 @@ import 'dart:math'; import 'dart:typed_data'; import 'package:aewallet/bus/transaction_send_event.dart'; -import 'package:aewallet/domain/repositories/transaction_validation_ratios.dart'; import 'package:aewallet/infrastructure/datasources/appwallet.hive.dart'; import 'package:aewallet/infrastructure/datasources/contacts.hive.dart'; import 'package:aewallet/infrastructure/repositories/transaction/transaction_keychain_builder.dart'; @@ -47,42 +46,29 @@ class KeychainUtil with KeychainServiceMixin { blockchainTxVersion, ); - final TransactionSenderInterface transactionSender = - ArchethicTransactionSender( - phoenixHttpEndpoint: networkSettings.getPhoenixHttpLink(), - websocketEndpoint: networkSettings.getWebsocketUri(), - apiService: apiService, - ); - _logger.info('>>> Create access <<< ${accessKeychainTx.address}'); - await transactionSender.send( - transaction: accessKeychainTx, - onConfirmation: (event) async { - if (TransactionConfirmation.isEnoughConfirmations( - event.nbConfirmations, - event.maxConfirmations, - TransactionValidationRatios.createKeychainAccess, - )) { - transactionSender.close(); - onConfirmation( - event, - transactionSender, - TransactionSendEventType.keychainAccess, - params: { - 'keychainAddress': keychainAddress, - 'keychain': keychain, - }, - ); - } - }, - onError: (error) async { - onError( - error, - transactionSender, - TransactionSendEventType.keychainAccess, - ); - }, - ); + try { + final confirmation = await ArchethicTransactionSender( + apiService: apiService, + ).send( + transaction: accessKeychainTx, + ); + + if (confirmation == null) return; + onConfirmation( + confirmation, + TransactionSendEventType.keychainAccess, + params: { + 'keychainAddress': keychainAddress, + 'keychain': keychain, + }, + ); + } on TransactionError catch (error) { + onError( + error, + TransactionSendEventType.keychainAccess, + ); + } } Future createKeyChain( @@ -125,44 +111,31 @@ class KeychainUtil with KeychainServiceMixin { derivationPath: kDerivationPath, ); - final TransactionSenderInterface transactionSender = - ArchethicTransactionSender( - phoenixHttpEndpoint: networkSettings.getPhoenixHttpLink(), - websocketEndpoint: networkSettings.getWebsocketUri(), - apiService: apiService, - ); - _logger.info('>>> Create keychain <<< ${keychainTransaction.address}'); - await transactionSender.send( - transaction: keychainTransaction, - onConfirmation: (event) async { - if (TransactionConfirmation.isEnoughConfirmations( - event.nbConfirmations, - event.maxConfirmations, - TransactionValidationRatios.createKeychain, - )) { - transactionSender.close(); - onConfirmation( - event, - transactionSender, - TransactionSendEventType.keychain, - params: { - 'keychainAddress': - keychainTransaction.address!.address!.toUpperCase(), - 'originPrivateKey': originPrivateKey, - 'keychain': keychain, - }, - ); - } - }, - onError: (error) async { - onError( - error, - transactionSender, - TransactionSendEventType.keychain, - ); - }, - ); + try { + final confirmation = await ArchethicTransactionSender( + apiService: apiService, + ).send( + transaction: keychainTransaction, + ); + + if (confirmation == null) return; + onConfirmation( + confirmation, + TransactionSendEventType.keychain, + params: { + 'keychainAddress': + keychainTransaction.address!.address!.toUpperCase(), + 'originPrivateKey': originPrivateKey, + 'keychain': keychain, + }, + ); + } on TransactionError catch (error) { + onError( + error, + TransactionSendEventType.keychain, + ); + } } Future removeService( @@ -180,42 +153,29 @@ class KeychainUtil with KeychainServiceMixin { apiService: apiService, ); - final TransactionSenderInterface transactionSender = - ArchethicTransactionSender( - phoenixHttpEndpoint: networkSettings.getPhoenixHttpLink(), - websocketEndpoint: networkSettings.getWebsocketUri(), - apiService: apiService, - ); + try { + final confirmation = await ArchethicTransactionSender( + apiService: apiService, + ).send( + transaction: transaction, + ); - await transactionSender.send( - transaction: transaction, - onConfirmation: (event) async { - if (TransactionConfirmation.isEnoughConfirmations( - event.nbConfirmations, - event.maxConfirmations, - TransactionValidationRatios.createKeychain, - )) { - transactionSender.close(); - onConfirmation( - event, - transactionSender, - TransactionSendEventType.keychain, - params: { - 'keychainAddress': transaction.address!.address!.toUpperCase(), - 'originPrivateKey': originPrivateKey, - 'keychain': keychain, - }, - ); - } - }, - onError: (error) async { - onError( - error, - transactionSender, - TransactionSendEventType.keychain, - ); - }, - ); + if (confirmation == null) return; + onConfirmation( + confirmation, + TransactionSendEventType.keychain, + params: { + 'keychainAddress': transaction.address!.address!.toUpperCase(), + 'originPrivateKey': originPrivateKey, + 'keychain': keychain, + }, + ); + } on TransactionError catch (error) { + onError( + error, + TransactionSendEventType.keychain, + ); + } } Future getListAccountsFromKeychain( @@ -381,7 +341,6 @@ class KeychainUtil with KeychainServiceMixin { void onConfirmation( TransactionConfirmation confirmation, - TransactionSenderInterface transactionSender, TransactionSendEventType transactionSendEventType, { Map? params, }) { @@ -398,7 +357,6 @@ class KeychainUtil with KeychainServiceMixin { void onError( TransactionError error, - TransactionSenderInterface transactionSender, TransactionSendEventType transactionSendEventType, { Map? params, }) { diff --git a/pubspec.lock b/pubspec.lock index b54dd30ea..dddcc14f3 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -66,26 +66,26 @@ packages: dependency: "direct main" description: name: archethic_dapp_framework_flutter - sha256: dc9954b16cd36544345a1ea606e0054ebeb6b83853efb15a241eca6508e00b3e + sha256: "490911c87e8c74fddd04d63a9e4daec69d0c966687e6e562cfbde03385fe29b2" url: "https://pub.dev" source: hosted - version: "3.2.5" + version: "3.2.6-beta" archethic_lib_dart: dependency: transitive description: name: archethic_lib_dart - sha256: "9200c8b49322c01e765ecd44cca97658a0436767abb76cbeda5f742d23d0e61e" + sha256: "39e8e8ccfc23db9d4b5f09815a42e82085d2356037411d5a1d7aae383a42af44" url: "https://pub.dev" source: hosted - version: "5.0.2" + version: "6.0.0-beta" archethic_wallet_client: dependency: "direct main" description: name: archethic_wallet_client - sha256: "69463fe1716b365b17623745fadc7e8ca37135c0bbd908e88fb9d68b05030a85" + sha256: "5b92a861a527f02233a4bc9b797fca67cd9a72f0dd06ae398ea2eb12fad1f475" url: "https://pub.dev" source: hosted - version: "2.1.7" + version: "2.1.8-beta" archive: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 851d9f728..5862dde6f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,7 @@ dependencies: # Retrieve version and url for local app update against store app Android and iOS app_version_update: ^5.0.2 - archethic_dapp_framework_flutter: ^3.2.5 + archethic_dapp_framework_flutter: ^3.2.6-beta #archethic_dapp_framework_flutter: # git: # url: https://github.com/archethic-foundation/archethic-dapp-framework-flutter.git @@ -25,7 +25,7 @@ dependencies: # path: ../../packages/archethic-dapp-framework-flutter # RPC datastructures. - archethic_wallet_client: ^2.1.7 + archethic_wallet_client: ^2.1.8-beta #archethic_wallet_client: # git: # url: https://github.com/archethic-foundation/archethic-wallet-client-dart.git diff --git a/untranslated_messages.txt b/untranslated_messages.txt new file mode 100644 index 000000000..9e26dfeeb --- /dev/null +++ b/untranslated_messages.txt @@ -0,0 +1 @@ +{} \ No newline at end of file