From 908607c77948909ffd0341fcb225dcacc0ef0501 Mon Sep 17 00:00:00 2001 From: reasje Date: Tue, 3 Oct 2023 00:22:51 +0330 Subject: [PATCH 01/10] feat: Added loadDataDashProviders functionality --- lib/core/src/providers/providers_loader.dart | 26 +++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/lib/core/src/providers/providers_loader.dart b/lib/core/src/providers/providers_loader.dart index bbe7fccd..778b1dbe 100644 --- a/lib/core/src/providers/providers_loader.dart +++ b/lib/core/src/providers/providers_loader.dart @@ -3,6 +3,7 @@ part of 'providers.dart'; DatadashCache? _datadashCache; GlobalCache? _globalCache; DatadashSetupStore? _datadashSetupStore; +CacheManager? _cacheManager; class _ProviderLoader { Future getCacheManager() async { @@ -13,9 +14,9 @@ class _ProviderLoader { } Future loadProviders() async { - final cacheManager = await getCacheManager(); + _cacheManager = await getCacheManager(); _datadashSetupStore = DatadashSetupStore(); - await _datadashSetupStore!.load(cacheManager); + await _datadashSetupStore!.load(_cacheManager!); final currentNetwork = _datadashSetupStore?.getNetwork ?? Network.fixedNetworks().where((item) => item.enabled).first; @@ -23,14 +24,31 @@ class _ProviderLoader { '${currentNetwork.chainId}_${_datadashSetupStore?.publicAddress}'; _datadashCache = await DatadashCache.load( - cacheManager, + _cacheManager!, username, ); - _globalCache = await GlobalCache.load(cacheManager); + _globalCache = await GlobalCache.load(_cacheManager!); + } + + Future loadDataDashProviders() async { + final currentNetwork = _datadashSetupStore?.getNetwork ?? + Network.fixedNetworks().where((item) => item.enabled).first; + final username = + '${currentNetwork.chainId}_${_datadashSetupStore?.publicAddress}'; + + _datadashCache = await DatadashCache.load( + _cacheManager!, + username, + ); } } Future loadProviders() async { await _ProviderLoader().loadProviders(); } + +Future loadDataDashProviders(Network network) async { + _datadashSetupStore!.network = network; + await _ProviderLoader().loadDataDashProviders(); +} From fb82dc6be9832ef7355c04e76ad2901137201f22 Mon Sep 17 00:00:00 2001 From: reasje Date: Tue, 3 Oct 2023 00:23:48 +0330 Subject: [PATCH 02/10] feat: Added reactive field update from database side stream --- lib/core/src/use_case/reactive_use_case.dart | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/lib/core/src/use_case/reactive_use_case.dart b/lib/core/src/use_case/reactive_use_case.dart index 00f3252e..ab292293 100644 --- a/lib/core/src/use_case/reactive_use_case.dart +++ b/lib/core/src/use_case/reactive_use_case.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:meta/meta.dart'; import 'package:mxc_logic/mxc_logic.dart'; import 'package:datadashwallet/core/core.dart'; @@ -6,6 +8,7 @@ export 'package:rxdart/rxdart.dart'; class ReactiveUseCase implements Disposable { final Map _streamToController = {}; + final List listeners = []; ValueStream reactive([T? value]) { final controller = ReactiveController(value); @@ -18,6 +21,9 @@ class ReactiveUseCase implements Disposable { final controller = ReactiveFieldController(field); final stream = controller.stream; _streamToController[stream] = controller; + + initUpdater(stream, field); + return stream; } @@ -35,6 +41,10 @@ class ReactiveUseCase implements Disposable { @override Future dispose() async { + for (final l in listeners) { + l.cancel(); + } + for (final c in _streamToController.values) { await c.dispose(); } @@ -42,4 +52,12 @@ class ReactiveUseCase implements Disposable { await d.dispose(); } } + + /// This listener is initialized to update the reactive field value + /// via the data base updates. + void initUpdater(ValueStream stream, Field field) { + listeners.add(field.valueStream.listen((event) { + _streamToController[stream]!.save(event); + })); + } } From 2d33fa5d533b357758f25c33c6d4400d3f185307 Mon Sep 17 00:00:00 2001 From: reasje Date: Tue, 3 Oct 2023 00:30:23 +0330 Subject: [PATCH 03/10] fix: custom & default tokenList balance & price updates --- .../contract/token_contract_use_case.dart | 78 +++++++++++++++---- .../domain/custom_tokens_use_case.dart | 5 ++ 2 files changed, 69 insertions(+), 14 deletions(-) diff --git a/lib/features/common/contract/token_contract_use_case.dart b/lib/features/common/contract/token_contract_use_case.dart index 12602a4d..d726c303 100644 --- a/lib/features/common/contract/token_contract_use_case.dart +++ b/lib/features/common/contract/token_contract_use_case.dart @@ -26,6 +26,8 @@ class TokenContractUseCase extends ReactiveUseCase { late final ValueStream> tokensList = reactive([]); + List customTokenList = []; + late final ValueStream name = reactive(); late final ValueStream totalBalanceInXsd = reactive(0.0); @@ -57,9 +59,11 @@ class TokenContractUseCase extends ReactiveUseCase { .getTokenTransfersByAddress(address, TokenType.erc_20); } - Future getDefaultTokens(String walletAddress) async { - final result = await _repository.tokenContract.getDefaultTokens(); + Future> getDefaultTokens(String walletAddress) async { tokensList.value.clear(); + tokensList.value.addAll(customTokenList); + final result = await _repository.tokenContract.getDefaultTokens(); + final cNetwork = _repository.tokenContract.getCurrentNetwork(); final chainNativeToken = Token( @@ -73,11 +77,13 @@ class TokenContractUseCase extends ReactiveUseCase { if (result != null) { if (result.tokens != null) { tokensList.value.addAll(result.tokens!); + tokensList.value.unique((token) => token.symbol); } } update(tokensList, tokensList.value); - return result; + result?.tokens?.add(chainNativeToken); + return result?.tokens ?? []; } Future getToken(String address) async => @@ -99,17 +105,47 @@ class TokenContractUseCase extends ReactiveUseCase { } Future getTokensBalance( - String walletAddress, bool shouldGetPrice) async { - final result = await _repository.tokenContract - .getTokensBalance(tokensList.value, walletAddress); - update(tokensList, result); + List? tokenList, + String walletAddress, + bool shouldGetPrice, + ) async { + late List result; + if (tokenList != null) { + // Check if tokenList and enwList values are the same + await _repository.tokenContract + .getTokensBalance(tokenList, walletAddress); + updateTokensList(tokenList); + } else { + result = await _repository.tokenContract + .getTokensBalance(tokensList.value, walletAddress); + update(tokensList, result); + } + if (shouldGetPrice) { - getTokensPrice(); + getTokensPrice(tokenList); } else { resetTokenPrice(); } } + void updateTokensList( + List tokenList, + ) { + for (int i = 0; i < tokensList.value.length; i++) { + final index = tokenList.indexWhere((element) { + final result = element.address == tokensList.value[i].address; + return result; + }); + if (index != -1) { + final newListItem = tokenList[index]; + if (newListItem.address == tokensList.value[i].address) { + tokensList.value[i] = newListItem; + } + } + } + update(tokensList, tokensList.value); + } + void resetTokenPrice() { final List newList = []; for (Token token in tokensList.value) { @@ -119,18 +155,32 @@ class TokenContractUseCase extends ReactiveUseCase { calculateTotalBalanceInXsd(); } - Future getTokensPrice() async { - final result = - await _repository.pricingRepository.getTokensPrice(tokensList.value); - update(tokensList, result); + Future getTokensPrice( + List? tokenList, + ) async { + if (tokenList != null) { + await _repository.pricingRepository.getTokensPrice(tokenList); + updateTokensList(tokenList); + } else { + final result = + await _repository.pricingRepository.getTokensPrice(tokensList.value); + update(tokensList, result); + } calculateTotalBalanceInXsd(); } - void addCustomTokens(List customTokens) { + void addCustomTokens( + List customTokens, String walletAddress, bool shouldGetPrice) { tokensList.value.addAll(customTokens); tokensList.value.unique((token) => token.address); - + customTokenList = customTokens; update(tokensList, tokensList.value); + + getTokensBalance( + customTokens, + walletAddress, + shouldGetPrice, + ); } Future getGasPrice() async => diff --git a/lib/features/portfolio/subfeatures/token/add_token/domain/custom_tokens_use_case.dart b/lib/features/portfolio/subfeatures/token/add_token/domain/custom_tokens_use_case.dart index f753788f..cb3d3460 100644 --- a/lib/features/portfolio/subfeatures/token/add_token/domain/custom_tokens_use_case.dart +++ b/lib/features/portfolio/subfeatures/token/add_token/domain/custom_tokens_use_case.dart @@ -22,4 +22,9 @@ class CustomTokensUseCase extends ReactiveUseCase { _repository.removeItem(item); update(tokens, _repository.items); } + + void removeAll() { + _repository.removeAll(); + update(tokens, _repository.items); + } } From feee70e1aaf1b79c12a15b5893d6e05595fbe1a9 Mon Sep 17 00:00:00 2001 From: reasje Date: Tue, 3 Oct 2023 00:32:46 +0330 Subject: [PATCH 04/10] feat: Added loadDataDashProviders to switch network events --- .../dapps/subfeatures/open_dapp/open_dapp_presenter.dart | 1 + .../token/add_token/domain/custom_tokens_repository.dart | 2 ++ .../chain_configuration/chain_configuration_presenter.dart | 1 + .../subfeatures/add_network/add_network_presenter.dart | 1 + .../delete_custom_network/delete_custom_network_presenter.dart | 2 ++ 5 files changed, 7 insertions(+) diff --git a/lib/features/dapps/subfeatures/open_dapp/open_dapp_presenter.dart b/lib/features/dapps/subfeatures/open_dapp/open_dapp_presenter.dart index a74a0e2a..5b34488f 100644 --- a/lib/features/dapps/subfeatures/open_dapp/open_dapp_presenter.dart +++ b/lib/features/dapps/subfeatures/open_dapp/open_dapp_presenter.dart @@ -287,6 +287,7 @@ class OpenDAppPresenter extends CompletePresenter { _chainConfigurationUseCase.switchDefaultNetwork(toNetwork); _transactionHistoryUseCase.checkChainAvailability(toNetwork.chainId); _authUseCase.resetNetwork(toNetwork); + loadDataDashProviders(toNetwork); notify(() => state.network = toNetwork); setChain(id); diff --git a/lib/features/portfolio/subfeatures/token/add_token/domain/custom_tokens_repository.dart b/lib/features/portfolio/subfeatures/token/add_token/domain/custom_tokens_repository.dart index 0bb77a42..e9d21fad 100644 --- a/lib/features/portfolio/subfeatures/token/add_token/domain/custom_tokens_repository.dart +++ b/lib/features/portfolio/subfeatures/token/add_token/domain/custom_tokens_repository.dart @@ -36,6 +36,8 @@ class CustomTokensRepository extends ControlledCacheRepository { void addItem(Token item) => tokens.value = [...tokens.value, item]; + void removeAll() => tokens.value = []; + void removeItem(Token item) => tokens.value = tokens.value.where((e) => e.name != item.name).toList(); } diff --git a/lib/features/settings/subfeatures/chain_configuration/chain_configuration_presenter.dart b/lib/features/settings/subfeatures/chain_configuration/chain_configuration_presenter.dart index a2f86204..8254ccf8 100644 --- a/lib/features/settings/subfeatures/chain_configuration/chain_configuration_presenter.dart +++ b/lib/features/settings/subfeatures/chain_configuration/chain_configuration_presenter.dart @@ -61,6 +61,7 @@ class ChainConfigurationPresenter _transactionHistoryUseCase.checkChainAvailability(newDefault.chainId); _authUseCase.resetNetwork(newDefault); _webviewUseCase.clearCache(); + loadDataDashProviders(newDefault); addMessage( translate('x_is_now_active')!.replaceFirst( diff --git a/lib/features/settings/subfeatures/chain_configuration/subfeatures/add_network/add_network_presenter.dart b/lib/features/settings/subfeatures/chain_configuration/subfeatures/add_network/add_network_presenter.dart index dadc1b8c..29ef22ef 100644 --- a/lib/features/settings/subfeatures/chain_configuration/subfeatures/add_network/add_network_presenter.dart +++ b/lib/features/settings/subfeatures/chain_configuration/subfeatures/add_network/add_network_presenter.dart @@ -49,6 +49,7 @@ class AddNetworkPresenter extends CompletePresenter { _transactionHistoryUseCase.checkChainAvailability(newDefault.chainId); _authUseCase.resetNetwork(newDefault); _webviewUseCase.clearCache(); + loadDataDashProviders(newDefault); addMessage( translate('x_is_now_active')!.replaceFirst( diff --git a/lib/features/settings/subfeatures/chain_configuration/subfeatures/delete_custom_network/delete_custom_network_presenter.dart b/lib/features/settings/subfeatures/chain_configuration/subfeatures/delete_custom_network/delete_custom_network_presenter.dart index 05728e3a..4f289e69 100644 --- a/lib/features/settings/subfeatures/chain_configuration/subfeatures/delete_custom_network/delete_custom_network_presenter.dart +++ b/lib/features/settings/subfeatures/chain_configuration/subfeatures/delete_custom_network/delete_custom_network_presenter.dart @@ -155,6 +155,8 @@ class DeleteCustomNetworkPresenter _chainConfigurationUseCase.switchDefaultNetwork(selectedNetwork!); _transactionHistoryUseCase.checkChainAvailability(selectedNetwork!.chainId); _authUseCase.resetNetwork(selectedNetwork!); + loadDataDashProviders(selectedNetwork!); + addMessage(translate('x_is_now_active')!.replaceFirst( '{0}', selectedNetwork!.label ?? From b7e14da730cb8b22421e3e74e7c903e3c0b3568e Mon Sep 17 00:00:00 2001 From: reasje Date: Tue, 3 Oct 2023 09:58:34 +0330 Subject: [PATCH 05/10] fix: tokens list balance & price update fixed for custom tokens --- .../choose_crypto_presenter.dart | 2 +- .../transaction_history_presenter.dart | 4 +--- .../presentation/wallet_page_presenter.dart | 20 +++++++++++-------- packages/shared | 2 +- 4 files changed, 15 insertions(+), 13 deletions(-) diff --git a/lib/features/portfolio/subfeatures/token/send_token/choose_crypto/choose_crypto_presenter.dart b/lib/features/portfolio/subfeatures/token/send_token/choose_crypto/choose_crypto_presenter.dart index af4b501e..0bb9810e 100644 --- a/lib/features/portfolio/subfeatures/token/send_token/choose_crypto/choose_crypto_presenter.dart +++ b/lib/features/portfolio/subfeatures/token/send_token/choose_crypto/choose_crypto_presenter.dart @@ -52,7 +52,7 @@ class ChooseCryptoPresenter extends CompletePresenter { final shouldGetPrice = Config.isMxcChains(chainId) || Config.isEthereumMainnet(chainId); await _tokenContractUseCase.getTokensBalance( - state.account!.address, shouldGetPrice); + null, state.account!.address, shouldGetPrice); } void fliterTokenByName(String value) { diff --git a/lib/features/portfolio/subfeatures/transaction_history/transaction_history_presenter.dart b/lib/features/portfolio/subfeatures/transaction_history/transaction_history_presenter.dart index 543c0a20..8c091dd2 100644 --- a/lib/features/portfolio/subfeatures/transaction_history/transaction_history_presenter.dart +++ b/lib/features/portfolio/subfeatures/transaction_history/transaction_history_presenter.dart @@ -41,10 +41,8 @@ class TransactionHistoryPresenter await _tokenContractUseCase .getDefaultTokens(state.account!.address) .then((value) { - if (value != null) { - notify(() => state.tokens = value.tokens!); + notify(() => state.tokens = value); getTransactions(); - } }); } diff --git a/lib/features/wallet/presentation/wallet_page_presenter.dart b/lib/features/wallet/presentation/wallet_page_presenter.dart index 7b217519..5592e371 100644 --- a/lib/features/wallet/presentation/wallet_page_presenter.dart +++ b/lib/features/wallet/presentation/wallet_page_presenter.dart @@ -80,9 +80,11 @@ class WalletPresenter extends CompletePresenter { }); listen(_customTokenUseCase.tokens, (customTokens) { - if (customTokens.isNotEmpty) { - _tokenContractUseCase.addCustomTokens(customTokens); - } + _tokenContractUseCase.addCustomTokens( + customTokens, + state.walletAddress ?? _accountUserCase.account.value!.address, + Config.isMxcChains(state.network!.chainId) || + Config.isEthereumMainnet(state.network!.chainId)); }); } @@ -192,7 +194,7 @@ class WalletPresenter extends CompletePresenter { case 'balance': final wannseeBalanceEvent = WannseeBalanceModel.fromJson(event.payload); - getWalletTokensBalance(true); + getWalletTokensBalance(null, true); break; default: } @@ -305,12 +307,13 @@ class WalletPresenter extends CompletePresenter { } initializeBalancePanelAndTokens() { - getDefaultTokens().then((value) => getWalletTokensBalance( + getDefaultTokens().then((tokenList) => getWalletTokensBalance( + tokenList, Config.isMxcChains(state.network!.chainId) || Config.isEthereumMainnet(state.network!.chainId))); } - Future getDefaultTokens() async { + Future> getDefaultTokens() async { return await _tokenContractUseCase.getDefaultTokens(state.walletAddress!); } @@ -444,8 +447,9 @@ class WalletPresenter extends CompletePresenter { } } - void getWalletTokensBalance(bool shouldGetPrice) async { + void getWalletTokensBalance( + List? tokenList, bool shouldGetPrice) async { _tokenContractUseCase.getTokensBalance( - state.walletAddress!, shouldGetPrice); + tokenList, state.walletAddress!, shouldGetPrice); } } diff --git a/packages/shared b/packages/shared index c99e243f..ee3ab1ad 160000 --- a/packages/shared +++ b/packages/shared @@ -1 +1 @@ -Subproject commit c99e243f8dd199e0d8af7276bdaf7ddac90cca44 +Subproject commit ee3ab1ad39d02231db265d1e38c206c403ddce64 From 3a6da36a4b19c1f914de77132ac34cf6d20dcccc Mon Sep 17 00:00:00 2001 From: reasje Date: Tue, 3 Oct 2023 12:21:50 +0330 Subject: [PATCH 06/10] impv: Removed chain mapping from transaction history --- .../domain/transactions_repository.dart | 40 +++------- .../domain/transactions_use_case.dart | 79 +++++++------------ .../entity/transaction_history_model.dart | 11 --- .../recent_transactions.dart | 1 - .../open_dapp/open_dapp_presenter.dart | 9 ++- .../send_crypto/send_crypto_presenter.dart | 4 +- .../chain_configuration_presenter.dart | 1 - .../add_network/add_network_presenter.dart | 1 - .../delete_custom_network_presenter.dart | 2 - .../presentation/wallet_page_presenter.dart | 17 +--- 10 files changed, 54 insertions(+), 111 deletions(-) delete mode 100644 lib/common/components/recent_transactions/entity/transaction_history_model.dart diff --git a/lib/common/components/recent_transactions/domain/transactions_repository.dart b/lib/common/components/recent_transactions/domain/transactions_repository.dart index 008ffade..2d497e4c 100644 --- a/lib/common/components/recent_transactions/domain/transactions_repository.dart +++ b/lib/common/components/recent_transactions/domain/transactions_repository.dart @@ -1,4 +1,3 @@ -import 'package:datadashwallet/common/components/recent_transactions/entity/transaction_history_model.dart'; import 'package:mxc_logic/mxc_logic.dart'; import 'package:datadashwallet/core/core.dart'; @@ -6,52 +5,37 @@ class TransactionsHistoryRepository extends ControlledCacheRepository { @override final String zone = 'transaction-history'; - late final Field> transactionsHistory = - fieldWithDefault>('items', [], + late final Field> transactionsHistory = + fieldWithDefault>('items', [], serializer: (b) => b - .map((e) => { - 'chainId': e.chainId, - 'txList': e.txList.map((e) => e.toMap()).toList() - }) + .map((e) => e.toMap()) .toList(), deserializer: (b) => (b as List) - .map((e) => TransactionHistoryModel( - chainId: e['chainId'], - txList: (e['txList'] as List) - .map((e) => TransactionModel.fromMap(e)) - .toList(), - )) + .map((e) => TransactionModel.fromMap(e) + ) .toList()); - List get items => transactionsHistory.value; + List get items => transactionsHistory.value; - void addItem(TransactionHistoryModel item) => - transactionsHistory.value = [...transactionsHistory.value, item]; - void addItemTx(TransactionModel item, int index) { - final newList = transactionsHistory.value; - newList[index].txList.insert(0, item); - transactionsHistory.value = newList; - } - void updateItem(TransactionHistoryModel item, int index) { + void addItem(TransactionModel item, int index) { final newList = transactionsHistory.value; - newList.removeAt(index); - newList.insert(index, item); + newList.insert(0, item); transactionsHistory.value = newList; } - void updateItemTx(TransactionModel item, int index, int txIndex) { + void updateItem(TransactionModel item, int index,) { final newList = transactionsHistory.value; - newList[index].txList[txIndex] = item; + newList[index] = item; transactionsHistory.value = newList; } - void removeItem(TransactionHistoryModel item) => + void removeItem(TransactionModel item) => transactionsHistory.value = transactionsHistory.value - .where((e) => e.chainId != item.chainId) + .where((e) => e.hash != item.hash) .toList(); void removeAll() => transactionsHistory.value = []; diff --git a/lib/common/components/recent_transactions/domain/transactions_use_case.dart b/lib/common/components/recent_transactions/domain/transactions_use_case.dart index 8390c8a5..09e2c2df 100644 --- a/lib/common/components/recent_transactions/domain/transactions_use_case.dart +++ b/lib/common/components/recent_transactions/domain/transactions_use_case.dart @@ -1,8 +1,6 @@ import 'package:datadashwallet/common/common.dart'; import 'package:datadashwallet/core/core.dart'; import 'package:mxc_logic/mxc_logic.dart'; -import '../entity/transaction_history_model.dart'; -import 'transactions_repository.dart'; import 'package:web3dart/web3dart.dart'; class TransactionsHistoryUseCase extends ReactiveUseCase { @@ -12,36 +10,27 @@ class TransactionsHistoryUseCase extends ReactiveUseCase { final TransactionsHistoryRepository _repository; - late final ValueStream> transactionsHistory = + late final ValueStream> transactionsHistory = reactiveField(_repository.transactionsHistory); - List getTransactionsHistory() => _repository.items; + List getTransactionsHistory() => _repository.items; List updatingTxList = []; - void addItem(TransactionHistoryModel item) { - _repository.addItem(item); - update(transactionsHistory, _repository.items); - } - - void updateItem(TransactionHistoryModel item, int index) { - _repository.updateItem(item, index); - update(transactionsHistory, _repository.items); - } - - void updateItemTx(TransactionModel item, int selectedNetworkChainId) { - final txHistory = transactionsHistory.value - .firstWhere((element) => element.chainId == selectedNetworkChainId); - - final index = transactionsHistory.value.indexOf(txHistory); - final txIndex = txHistory.txList.indexWhere( + void updateItem( + TransactionModel item, + ) { + final index = transactionsHistory.value.indexWhere( (element) => element.hash == item.hash, ); - if (txIndex == -1) { - _repository.addItemTx(item, index); + if (index == -1) { + _repository.addItem(item, index); } else { - _repository.updateItemTx(item, index, txIndex); + _repository.updateItem( + item, + index, + ); } update(transactionsHistory, _repository.items); @@ -52,19 +41,23 @@ class TransactionsHistoryUseCase extends ReactiveUseCase { update(transactionsHistory, _repository.items); } - void removeItem(TransactionHistoryModel item) { + void removeItem(TransactionModel item) { _repository.removeItem(item); update(transactionsHistory, _repository.items); } - void spyOnTransaction(TransactionModel item, int chainId) { + void spyOnTransaction( + TransactionModel item, + ) { if (!updatingTxList.contains(item.hash)) { updatingTxList.add(item.hash); final stream = _web3Repository.tokenContract.spyTransaction(item.hash); stream.onData((succeeded) { if (succeeded) { final updatedItem = item.copyWith(status: TransactionStatus.done); - updateItemTx(updatedItem, chainId); + updateItem( + updatedItem, + ); updatingTxList.remove(item.hash); stream.cancel(); } @@ -74,16 +67,13 @@ class TransactionsHistoryUseCase extends ReactiveUseCase { void checkForPendingTransactions(int chainId) { if (!Config.isMxcChains(chainId)) { - final index = transactionsHistory.value - .indexWhere((element) => element.chainId == chainId); - - if (index != -1) { - final chainTx = transactionsHistory.value[index]; - final pendingTxList = chainTx.txList - .where((element) => element.status == TransactionStatus.pending); - for (TransactionModel pendingTx in pendingTxList) { - spyOnTransaction(pendingTx, chainId); - } + final txList = transactionsHistory.value; + final pendingTxList = txList + .where((element) => element.status == TransactionStatus.pending); + for (TransactionModel pendingTx in pendingTxList) { + spyOnTransaction( + pendingTx, + ); } } } @@ -97,19 +87,10 @@ class TransactionsHistoryUseCase extends ReactiveUseCase { if (receipt != null) { final tx = TransactionModel.fromTransaction(receipt, address, token); - spyOnTransaction(tx, chainId); - updateItemTx(tx, chainId); + spyOnTransaction(tx); + updateItem( + tx, + ); } } - - void checkChainAvailability(int chainId) { - final index = transactionsHistory.value - .indexWhere((element) => element.chainId == chainId); - - if (index == -1) { - addItem(TransactionHistoryModel(chainId: chainId, txList: [])); - return; - } - update(transactionsHistory, _repository.items); - } } diff --git a/lib/common/components/recent_transactions/entity/transaction_history_model.dart b/lib/common/components/recent_transactions/entity/transaction_history_model.dart deleted file mode 100644 index b7a8ecd2..00000000 --- a/lib/common/components/recent_transactions/entity/transaction_history_model.dart +++ /dev/null @@ -1,11 +0,0 @@ -import 'package:mxc_logic/mxc_logic.dart'; - -class TransactionHistoryModel { - TransactionHistoryModel({ - required this.chainId, - required this.txList, - }); - - int chainId; - List txList; -} diff --git a/lib/common/components/recent_transactions/recent_transactions.dart b/lib/common/components/recent_transactions/recent_transactions.dart index 900bccff..c24ea3b7 100644 --- a/lib/common/components/recent_transactions/recent_transactions.dart +++ b/lib/common/components/recent_transactions/recent_transactions.dart @@ -11,7 +11,6 @@ import 'package:mxc_ui/mxc_ui.dart'; export 'domain/transactions_use_case.dart'; export 'domain/transactions_repository.dart'; -export 'entity/transaction_history_model.dart'; class RecentTransactions extends HookConsumerWidget { const RecentTransactions({ diff --git a/lib/features/dapps/subfeatures/open_dapp/open_dapp_presenter.dart b/lib/features/dapps/subfeatures/open_dapp/open_dapp_presenter.dart index 5b34488f..053b7b36 100644 --- a/lib/features/dapps/subfeatures/open_dapp/open_dapp_presenter.dart +++ b/lib/features/dapps/subfeatures/open_dapp/open_dapp_presenter.dart @@ -143,8 +143,12 @@ class OpenDAppPresenter extends CompletePresenter { token: token, ); - _transactionHistoryUseCase.spyOnTransaction(tx, chainId); - _transactionHistoryUseCase.updateItemTx(tx, chainId); + _transactionHistoryUseCase.spyOnTransaction( + tx, + ); + _transactionHistoryUseCase.updateItem( + tx, + ); } void signTransaction({ @@ -285,7 +289,6 @@ class OpenDAppPresenter extends CompletePresenter { void switchNetwork(dynamic id, Network toNetwork, String rawChainId) { // "{"id":1692336424091,"name":"switchEthereumChain","object":{"chainId":"0x66eed"},"network":"ethereum"}" _chainConfigurationUseCase.switchDefaultNetwork(toNetwork); - _transactionHistoryUseCase.checkChainAvailability(toNetwork.chainId); _authUseCase.resetNetwork(toNetwork); loadDataDashProviders(toNetwork); notify(() => state.network = toNetwork); diff --git a/lib/features/portfolio/subfeatures/token/send_token/send_crypto/send_crypto_presenter.dart b/lib/features/portfolio/subfeatures/token/send_token/send_crypto/send_crypto_presenter.dart index 096385ba..7832e1ec 100644 --- a/lib/features/portfolio/subfeatures/token/send_token/send_crypto/send_crypto_presenter.dart +++ b/lib/features/portfolio/subfeatures/token/send_token/send_crypto/send_crypto_presenter.dart @@ -234,9 +234,9 @@ class SendCryptoPresenter extends CompletePresenter { token: token, timeStamp: DateTime.now()); - _transactionHistoryUseCase.updateItemTx(tx, state.network!.chainId); + _transactionHistoryUseCase.updateItem(tx,); - _transactionHistoryUseCase.spyOnTransaction(tx, state.network!.chainId); + _transactionHistoryUseCase.spyOnTransaction(tx,); } return res; diff --git a/lib/features/settings/subfeatures/chain_configuration/chain_configuration_presenter.dart b/lib/features/settings/subfeatures/chain_configuration/chain_configuration_presenter.dart index 8254ccf8..0d491d92 100644 --- a/lib/features/settings/subfeatures/chain_configuration/chain_configuration_presenter.dart +++ b/lib/features/settings/subfeatures/chain_configuration/chain_configuration_presenter.dart @@ -58,7 +58,6 @@ class ChainConfigurationPresenter Future setAsDefault(Network newDefault) async { _chainConfigurationUseCase.switchDefaultNetwork(newDefault); - _transactionHistoryUseCase.checkChainAvailability(newDefault.chainId); _authUseCase.resetNetwork(newDefault); _webviewUseCase.clearCache(); loadDataDashProviders(newDefault); diff --git a/lib/features/settings/subfeatures/chain_configuration/subfeatures/add_network/add_network_presenter.dart b/lib/features/settings/subfeatures/chain_configuration/subfeatures/add_network/add_network_presenter.dart index 29ef22ef..3c74ae66 100644 --- a/lib/features/settings/subfeatures/chain_configuration/subfeatures/add_network/add_network_presenter.dart +++ b/lib/features/settings/subfeatures/chain_configuration/subfeatures/add_network/add_network_presenter.dart @@ -46,7 +46,6 @@ class AddNetworkPresenter extends CompletePresenter { void switchNetwork(Network newDefault) { _chainConfigurationUseCase.switchDefaultNetwork(newDefault); - _transactionHistoryUseCase.checkChainAvailability(newDefault.chainId); _authUseCase.resetNetwork(newDefault); _webviewUseCase.clearCache(); loadDataDashProviders(newDefault); diff --git a/lib/features/settings/subfeatures/chain_configuration/subfeatures/delete_custom_network/delete_custom_network_presenter.dart b/lib/features/settings/subfeatures/chain_configuration/subfeatures/delete_custom_network/delete_custom_network_presenter.dart index 4f289e69..0518094f 100644 --- a/lib/features/settings/subfeatures/chain_configuration/subfeatures/delete_custom_network/delete_custom_network_presenter.dart +++ b/lib/features/settings/subfeatures/chain_configuration/subfeatures/delete_custom_network/delete_custom_network_presenter.dart @@ -153,7 +153,6 @@ class DeleteCustomNetworkPresenter void setAsDefault() { _chainConfigurationUseCase.switchDefaultNetwork(selectedNetwork!); - _transactionHistoryUseCase.checkChainAvailability(selectedNetwork!.chainId); _authUseCase.resetNetwork(selectedNetwork!); loadDataDashProviders(selectedNetwork!); @@ -166,7 +165,6 @@ class DeleteCustomNetworkPresenter void setNewDefault() { final newDefault = state.networks[0]; _chainConfigurationUseCase.switchDefaultNetwork(newDefault); - _transactionHistoryUseCase.checkChainAvailability(newDefault.chainId); addMessage(translate('x_is_now_active')!.replaceFirst( '{0}', newDefault.label ?? diff --git a/lib/features/wallet/presentation/wallet_page_presenter.dart b/lib/features/wallet/presentation/wallet_page_presenter.dart index 5592e371..0c8f5a15 100644 --- a/lib/features/wallet/presentation/wallet_page_presenter.dart +++ b/lib/features/wallet/presentation/wallet_page_presenter.dart @@ -49,7 +49,7 @@ class WalletPresenter extends CompletePresenter { }); listen(_transactionHistoryUseCase.transactionsHistory, (value) { - if (value.isNotEmpty && state.network != null) { + if (state.network != null) { if (!Config.isMxcChains(state.network!.chainId)) { getCustomChainsTransactions(value); } @@ -211,23 +211,14 @@ class WalletPresenter extends CompletePresenter { } } - void getCustomChainsTransactions(List? txHistory) { + void getCustomChainsTransactions(List? txHistory) { txHistory = txHistory ?? _transactionHistoryUseCase.getTransactionsHistory(); if (state.network != null) { - final index = txHistory - .indexWhere((element) => element.chainId == state.network!.chainId); + final chainTxHistory = txHistory; - if (index == -1) { - _transactionHistoryUseCase - .checkChainAvailability(state.network!.chainId); - return; - } - - final chainTxHistory = txHistory[index]; - - notify(() => state.txList = chainTxHistory.txList); + notify(() => state.txList = chainTxHistory); } } From a2cb69376d66680122bded6210fd5d669e5451a7 Mon Sep 17 00:00:00 2001 From: reasje Date: Tue, 3 Oct 2023 12:22:21 +0330 Subject: [PATCH 07/10] fix: Native token balance update missing on custom chains --- lib/features/common/contract/token_contract_use_case.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/features/common/contract/token_contract_use_case.dart b/lib/features/common/contract/token_contract_use_case.dart index d726c303..3bfe4977 100644 --- a/lib/features/common/contract/token_contract_use_case.dart +++ b/lib/features/common/contract/token_contract_use_case.dart @@ -83,7 +83,7 @@ class TokenContractUseCase extends ReactiveUseCase { update(tokensList, tokensList.value); result?.tokens?.add(chainNativeToken); - return result?.tokens ?? []; + return result?.tokens ?? [chainNativeToken]; } Future getToken(String address) async => From ee6a9f53aaacc1e24c02a9d03206134f5d3ee186 Mon Sep 17 00:00:00 2001 From: reasje Date: Tue, 3 Oct 2023 12:32:25 +0330 Subject: [PATCH 08/10] feat: Added merge url to formatter --- lib/common/utils/formatter.dart | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/common/utils/formatter.dart b/lib/common/utils/formatter.dart index 56b99215..d98b6f38 100644 --- a/lib/common/utils/formatter.dart +++ b/lib/common/utils/formatter.dart @@ -103,4 +103,12 @@ class Formatter { final splitValue = value.split('.'); return '${splitValue[0]}.${splitValue[1].substring(0, 8)}'; } + + static Uri mergeUrl(String first, String second) { + return Uri.parse(first).resolve(second); + } + + static String mergeUrlString(String first, String second) { + return Uri.parse(first).resolve(second).toString(); + } } From 91303e2e41a95d2a2042f1abc10307d71b5b9a64 Mon Sep 17 00:00:00 2001 From: reasje Date: Tue, 3 Oct 2023 12:33:29 +0330 Subject: [PATCH 09/10] imprv: merging explorer urls --- .../open_dapp/open_dapp_presenter.dart | 10 ++++----- .../send_crypto/send_crypto_presenter.dart | 21 +++++++++--------- .../presentation/wallet_page_presenter.dart | 22 ++++++++----------- 3 files changed, 24 insertions(+), 29 deletions(-) diff --git a/lib/features/dapps/subfeatures/open_dapp/open_dapp_presenter.dart b/lib/features/dapps/subfeatures/open_dapp/open_dapp_presenter.dart index 053b7b36..f7c450a8 100644 --- a/lib/features/dapps/subfeatures/open_dapp/open_dapp_presenter.dart +++ b/lib/features/dapps/subfeatures/open_dapp/open_dapp_presenter.dart @@ -335,13 +335,11 @@ class OpenDAppPresenter extends CompletePresenter { void launchAddress(String address) { final chainExplorerUrl = state.network!.explorerUrl!; - final explorerUrl = chainExplorerUrl.endsWith('/') - ? chainExplorerUrl - : '$chainExplorerUrl/'; + final address = state.account!.address!; + final addressExplorer = Config.addressExplorer(address); + final launchUri = Formatter.mergeUrl(chainExplorerUrl, addressExplorer); - final addressUrl = '$explorerUrl${Config.addressExplorer(address)}'; - state.webviewController! - .loadUrl(urlRequest: URLRequest(url: Uri.parse(addressUrl))); + state.webviewController!.loadUrl(urlRequest: URLRequest(url: launchUri)); } bool isAddress(String address) { diff --git a/lib/features/portfolio/subfeatures/token/send_token/send_crypto/send_crypto_presenter.dart b/lib/features/portfolio/subfeatures/token/send_token/send_crypto/send_crypto_presenter.dart index 7832e1ec..8121db28 100644 --- a/lib/features/portfolio/subfeatures/token/send_token/send_crypto/send_crypto_presenter.dart +++ b/lib/features/portfolio/subfeatures/token/send_token/send_crypto/send_crypto_presenter.dart @@ -234,9 +234,13 @@ class SendCryptoPresenter extends CompletePresenter { token: token, timeStamp: DateTime.now()); - _transactionHistoryUseCase.updateItem(tx,); + _transactionHistoryUseCase.updateItem( + tx, + ); - _transactionHistoryUseCase.spyOnTransaction(tx,); + _transactionHistoryUseCase.spyOnTransaction( + tx, + ); } return res; @@ -254,14 +258,11 @@ class SendCryptoPresenter extends CompletePresenter { void launchAddress(String address) async { final chainExplorerUrl = state.network!.explorerUrl!; - final explorerUrl = chainExplorerUrl.endsWith('/') - ? chainExplorerUrl - : '$chainExplorerUrl/'; - - final addressUrl = - Uri.parse('$explorerUrl${Config.addressExplorer(address)}'); - if ((await canLaunchUrl(addressUrl))) { - await launchUrl(addressUrl, mode: LaunchMode.inAppWebView); + final addressExplorer = Config.addressExplorer(address); + final launchUri = Formatter.mergeUrl(chainExplorerUrl, addressExplorer); + + if ((await canLaunchUrl(launchUri))) { + await launchUrl(launchUri, mode: LaunchMode.inAppWebView); } } diff --git a/lib/features/wallet/presentation/wallet_page_presenter.dart b/lib/features/wallet/presentation/wallet_page_presenter.dart index 0c8f5a15..f4e0e66b 100644 --- a/lib/features/wallet/presentation/wallet_page_presenter.dart +++ b/lib/features/wallet/presentation/wallet_page_presenter.dart @@ -1,5 +1,6 @@ import 'package:datadashwallet/common/components/components.dart'; import 'package:datadashwallet/common/config.dart'; +import 'package:datadashwallet/common/utils/formatter.dart'; import 'package:datadashwallet/core/core.dart'; import 'package:datadashwallet/features/wallet/wallet.dart'; import 'package:fl_chart/fl_chart.dart'; @@ -314,27 +315,22 @@ class WalletPresenter extends CompletePresenter { void viewTransaction(String txHash) async { final chainExplorerUrl = state.network!.explorerUrl!; - final explorerUrl = chainExplorerUrl.endsWith('/') - ? chainExplorerUrl - : '$chainExplorerUrl/'; + final txExplorer = Config.txExplorer(txHash); + final launchUri = Formatter.mergeUrl(chainExplorerUrl, txExplorer); - final addressUrl = Uri.parse('$explorerUrl${Config.txExplorer(txHash)}'); - - if ((await canLaunchUrl(addressUrl))) { - await launchUrl(addressUrl, mode: LaunchMode.inAppWebView); + if ((await canLaunchUrl(launchUri))) { + await launchUrl(launchUri, mode: LaunchMode.inAppWebView); } } String getViewOtherTransactionsLink() { final chainExplorerUrl = state.network!.explorerUrl!; - final explorerUrl = chainExplorerUrl.endsWith('/') - ? chainExplorerUrl - : '$chainExplorerUrl/'; - final address = state.walletAddress!; + final addressExplorer = Config.addressExplorer(address); + final launchUri = + Formatter.mergeUrlString(chainExplorerUrl, addressExplorer); - final addressUrl = '$explorerUrl${Config.addressExplorer(address)}'; - return addressUrl; + return launchUri; } void generateChartData(List balanceData) { From f807b1a0eaa531a64ac04e211e6a4dd72fbc9eff Mon Sep 17 00:00:00 2001 From: reasje Date: Tue, 3 Oct 2023 13:18:51 +0330 Subject: [PATCH 10/10] fix: Transaction history not showing in chains other than mxc --- .../open_dapp/open_dapp_presenter.dart | 2 +- .../transaction_history_presenter.dart | 38 +++++++++++++++++-- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/lib/features/dapps/subfeatures/open_dapp/open_dapp_presenter.dart b/lib/features/dapps/subfeatures/open_dapp/open_dapp_presenter.dart index f7c450a8..62148be3 100644 --- a/lib/features/dapps/subfeatures/open_dapp/open_dapp_presenter.dart +++ b/lib/features/dapps/subfeatures/open_dapp/open_dapp_presenter.dart @@ -335,7 +335,7 @@ class OpenDAppPresenter extends CompletePresenter { void launchAddress(String address) { final chainExplorerUrl = state.network!.explorerUrl!; - final address = state.account!.address!; + final address = state.account!.address; final addressExplorer = Config.addressExplorer(address); final launchUri = Formatter.mergeUrl(chainExplorerUrl, addressExplorer); diff --git a/lib/features/portfolio/subfeatures/transaction_history/transaction_history_presenter.dart b/lib/features/portfolio/subfeatures/transaction_history/transaction_history_presenter.dart index 8c091dd2..5e0e0601 100644 --- a/lib/features/portfolio/subfeatures/transaction_history/transaction_history_presenter.dart +++ b/lib/features/portfolio/subfeatures/transaction_history/transaction_history_presenter.dart @@ -1,4 +1,4 @@ -import 'package:datadashwallet/common/components/recent_transactions/utils.dart'; +import 'package:datadashwallet/common/config.dart'; import 'package:datadashwallet/core/core.dart'; import 'package:mxc_logic/mxc_logic.dart'; @@ -18,6 +18,8 @@ class TransactionHistoryPresenter ref.read(chainConfigurationUseCaseProvider); late final _tokenContractUseCase = ref.read(tokenContractUseCaseProvider); late final _accountUserCase = ref.read(accountUseCaseProvider); + late final _transactionHistoryUseCase = + ref.read(transactionHistoryUseCaseProvider); @override void initState() { @@ -35,18 +37,48 @@ class TransactionHistoryPresenter loadPage(); } }); + + listen(_transactionHistoryUseCase.transactionsHistory, (value) { + if (state.network != null) { + if (!Config.isMxcChains(state.network!.chainId)) { + getCustomChainsTransactions(value); + } + } + }); } Future loadPage() async { await _tokenContractUseCase .getDefaultTokens(state.account!.address) .then((value) { - notify(() => state.tokens = value); - getTransactions(); + notify(() => state.tokens = value); + getTransactions(); }); } void getTransactions() async { + if (Config.isMxcChains(state.network!.chainId)) { + getMXCTransactions(); + } else { + getCustomChainsTransactions(null); + } + } + + void getCustomChainsTransactions(List? txHistory) { + txHistory = + txHistory ?? _transactionHistoryUseCase.getTransactionsHistory(); + + if (state.network != null) { + final chainTxHistory = txHistory; + + notify(() { + state.transactions = chainTxHistory; + state.filterTransactions = chainTxHistory; + }); + } + } + + void getMXCTransactions() async { // final walletAddress = await _walletUserCase.getPublicAddress(); // transactions list contains all the kind of transactions // It's going to be filtered to only have native coin transfer