diff --git a/lib/pages/add_wallet_views/add_token_view/edit_wallet_tokens_view.dart b/lib/pages/add_wallet_views/add_token_view/edit_wallet_tokens_view.dart index ca3b776d5..4a5dcae28 100644 --- a/lib/pages/add_wallet_views/add_token_view/edit_wallet_tokens_view.dart +++ b/lib/pages/add_wallet_views/add_token_view/edit_wallet_tokens_view.dart @@ -180,10 +180,7 @@ class _EditWalletTokensViewState extends ConsumerState { tokenEntities.addAll(contracts.map((e) => AddTokenListElementData(e))); - final walletContracts = - (ref.read(pWallets).getWallet(widget.walletId) as EthereumWallet) - .info - .tokenContractAddresses; + final walletContracts = ref.read(pWalletTokenAddresses(widget.walletId)); final shouldMarkAsSelectedContracts = [ ...walletContracts, diff --git a/lib/pages/token_view/my_tokens_view.dart b/lib/pages/token_view/my_tokens_view.dart index 9813e3eff..35168b9f7 100644 --- a/lib/pages/token_view/my_tokens_view.dart +++ b/lib/pages/token_view/my_tokens_view.dart @@ -15,14 +15,12 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; import 'package:stackwallet/pages/add_wallet_views/add_token_view/edit_wallet_tokens_view.dart'; import 'package:stackwallet/pages/token_view/sub_widgets/my_tokens_list.dart'; -import 'package:stackwallet/providers/global/wallets_provider.dart'; import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/constants.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/util.dart'; import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart'; -import 'package:stackwallet/wallets/wallet/impl/ethereum_wallet.dart'; import 'package:stackwallet/widgets/background.dart'; import 'package:stackwallet/widgets/conditional_parent.dart'; import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart'; @@ -233,11 +231,7 @@ class _MyTokensViewState extends ConsumerState { child: MyTokensList( walletId: widget.walletId, searchTerm: _searchString, - tokenContracts: ref - .watch(pWallets.select((value) => - value.getWallet(widget.walletId) as EthereumWallet)) - .info - .tokenContractAddresses, + tokenContracts: ref.watch(pWalletTokenAddresses(widget.walletId)), ), ), ], diff --git a/lib/pages/token_view/sub_widgets/my_token_select_item.dart b/lib/pages/token_view/sub_widgets/my_token_select_item.dart index 0907a4adc..b9316773f 100644 --- a/lib/pages/token_view/sub_widgets/my_token_select_item.dart +++ b/lib/pages/token_view/sub_widgets/my_token_select_item.dart @@ -13,6 +13,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:stackwallet/models/isar/models/ethereum/eth_contract.dart'; import 'package:stackwallet/pages/token_view/token_view.dart'; import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/desktop_token_view.dart'; +import 'package:stackwallet/providers/db/main_db_provider.dart'; import 'package:stackwallet/providers/global/secure_store_provider.dart'; import 'package:stackwallet/providers/providers.dart'; import 'package:stackwallet/services/ethereum/cached_eth_token_balance.dart'; @@ -25,6 +26,7 @@ import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:stackwallet/utilities/show_loading.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/util.dart'; +import 'package:stackwallet/wallets/isar/providers/eth/token_balance_provider.dart'; import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart'; import 'package:stackwallet/wallets/wallet/impl/ethereum_wallet.dart'; import 'package:stackwallet/widgets/desktop/primary_button.dart'; @@ -116,10 +118,13 @@ class _MyTokenSelectItemState extends ConsumerState { cachedBalance = CachedEthTokenBalance(widget.walletId, widget.token); WidgetsBinding.instance.addPostFrameCallback((_) async { - final address = ref.read(pWalletReceivingAddress(widget.walletId)); - await cachedBalance.fetchAndUpdateCachedBalance(address); if (mounted) { - setState(() {}); + final address = ref.read(pWalletReceivingAddress(widget.walletId)); + await cachedBalance.fetchAndUpdateCachedBalance( + address, ref.read(mainDBProvider)); + if (mounted) { + setState(() {}); + } } }); @@ -172,7 +177,14 @@ class _MyTokenSelectItemState extends ConsumerState { const Spacer(), Text( ref.watch(pAmountFormatter(Coin.ethereum)).format( - cachedBalance.getCachedBalance().total, + ref + .watch(pTokenBalance( + ( + walletId: widget.walletId, + contractAddress: widget.token.address + ), + )) + .total, ethContract: widget.token, ), style: isDesktop diff --git a/lib/pages/wallets_view/wallets_overview.dart b/lib/pages/wallets_view/wallets_overview.dart index 7b05aaf24..0f6cef1a6 100644 --- a/lib/pages/wallets_view/wallets_overview.dart +++ b/lib/pages/wallets_view/wallets_overview.dart @@ -25,7 +25,7 @@ import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/util.dart'; import 'package:stackwallet/wallets/isar/models/wallet_info.dart'; -import 'package:stackwallet/wallets/wallet/impl/ethereum_wallet.dart'; +import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart'; import 'package:stackwallet/wallets/wallet/wallet.dart'; import 'package:stackwallet/widgets/background.dart'; import 'package:stackwallet/widgets/conditional_parent.dart'; @@ -119,9 +119,8 @@ class _EthWalletsOverviewState extends ConsumerState { if (widget.coin == Coin.ethereum) { for (final data in walletsData) { final List contracts = []; - final wallet = ref.read(pWallets).getWallet(data.walletId); final contractAddresses = - (wallet as EthereumWallet).info.tokenContractAddresses; + ref.read(pWalletTokenAddresses(data.walletId)); // fetch each contract for (final contractAddress in contractAddresses) { diff --git a/lib/services/ethereum/cached_eth_token_balance.dart b/lib/services/ethereum/cached_eth_token_balance.dart index aad4b3f68..dbcda1131 100644 --- a/lib/services/ethereum/cached_eth_token_balance.dart +++ b/lib/services/ethereum/cached_eth_token_balance.dart @@ -8,29 +8,37 @@ * */ +import 'package:isar/isar.dart'; +import 'package:stackwallet/db/isar/main_db.dart'; import 'package:stackwallet/models/balance.dart'; import 'package:stackwallet/models/isar/models/ethereum/eth_contract.dart'; import 'package:stackwallet/services/ethereum/ethereum_api.dart'; -import 'package:stackwallet/services/mixins/eth_token_cache.dart'; import 'package:stackwallet/utilities/amount/amount.dart'; import 'package:stackwallet/utilities/logger.dart'; +import 'package:stackwallet/wallets/isar/models/token_wallet_info.dart'; -class CachedEthTokenBalance with EthTokenCache { +class CachedEthTokenBalance { final String walletId; final EthContract token; - CachedEthTokenBalance(this.walletId, this.token) { - initCache(walletId, token); - } + CachedEthTokenBalance(this.walletId, this.token); - Future fetchAndUpdateCachedBalance(String address) async { + Future fetchAndUpdateCachedBalance( + String address, + MainDB mainDB, + ) async { final response = await EthereumAPI.getWalletTokenBalance( address: address, contractAddress: token.address, ); - if (response.value != null) { - await updateCachedBalance( + final info = await mainDB.isar.tokenWalletInfo + .where() + .walletIdTokenAddressEqualTo(walletId, token.address) + .findFirst(); + + if (response.value != null && info != null) { + await info.updateCachedBalance( Balance( total: response.value!, spendable: response.value!, @@ -43,6 +51,7 @@ class CachedEthTokenBalance with EthTokenCache { fractionDigits: token.decimals, ), ), + isar: mainDB.isar, ); } else { Logging.instance.log( diff --git a/lib/services/mixins/eth_token_cache.dart b/lib/services/mixins/eth_token_cache.dart index fde3cb9e9..d6efa1fd2 100644 --- a/lib/services/mixins/eth_token_cache.dart +++ b/lib/services/mixins/eth_token_cache.dart @@ -1,70 +1,70 @@ -/* - * This file is part of Stack Wallet. - * - * Copyright (c) 2023 Cypher Stack - * All Rights Reserved. - * The code is distributed under GPLv3 license, see LICENSE file for details. - * Generated by Cypher Stack on 2023-05-26 - * - */ - -import 'package:stackwallet/db/hive/db.dart'; -import 'package:stackwallet/models/balance.dart'; -import 'package:stackwallet/models/isar/models/ethereum/eth_contract.dart'; -import 'package:stackwallet/utilities/amount/amount.dart'; - -abstract class TokenCacheKeys { - static String tokenBalance(String contractAddress) { - return "tokenBalanceCache_$contractAddress"; - } -} - -mixin EthTokenCache { - late final String _walletId; - late final EthContract _token; - - void initCache(String walletId, EthContract token) { - _walletId = walletId; - _token = token; - } - - // token balance cache - Balance getCachedBalance() { - final jsonString = DB.instance.get( - boxName: _walletId, - key: TokenCacheKeys.tokenBalance(_token.address), - ) as String?; - if (jsonString == null) { - return Balance( - total: Amount( - rawValue: BigInt.zero, - fractionDigits: _token.decimals, - ), - spendable: Amount( - rawValue: BigInt.zero, - fractionDigits: _token.decimals, - ), - blockedTotal: Amount( - rawValue: BigInt.zero, - fractionDigits: _token.decimals, - ), - pendingSpendable: Amount( - rawValue: BigInt.zero, - fractionDigits: _token.decimals, - ), - ); - } - return Balance.fromJson( - jsonString, - _token.decimals, - ); - } - - Future updateCachedBalance(Balance balance) async { - await DB.instance.put( - boxName: _walletId, - key: TokenCacheKeys.tokenBalance(_token.address), - value: balance.toJsonIgnoreCoin(), - ); - } -} +// /* +// * This file is part of Stack Wallet. +// * +// * Copyright (c) 2023 Cypher Stack +// * All Rights Reserved. +// * The code is distributed under GPLv3 license, see LICENSE file for details. +// * Generated by Cypher Stack on 2023-05-26 +// * +// */ +// +// import 'package:stackwallet/db/hive/db.dart'; +// import 'package:stackwallet/models/balance.dart'; +// import 'package:stackwallet/models/isar/models/ethereum/eth_contract.dart'; +// import 'package:stackwallet/utilities/amount/amount.dart'; +// +// abstract class TokenCacheKeys { +// static String tokenBalance(String contractAddress) { +// return "tokenBalanceCache_$contractAddress"; +// } +// } +// +// mixin EthTokenCache { +// late final String _walletId; +// late final EthContract _token; +// +// void initCache(String walletId, EthContract token) { +// _walletId = walletId; +// _token = token; +// } +// +// // token balance cache +// Balance getCachedBalance() { +// final jsonString = DB.instance.get( +// boxName: _walletId, +// key: TokenCacheKeys.tokenBalance(_token.address), +// ) as String?; +// if (jsonString == null) { +// return Balance( +// total: Amount( +// rawValue: BigInt.zero, +// fractionDigits: _token.decimals, +// ), +// spendable: Amount( +// rawValue: BigInt.zero, +// fractionDigits: _token.decimals, +// ), +// blockedTotal: Amount( +// rawValue: BigInt.zero, +// fractionDigits: _token.decimals, +// ), +// pendingSpendable: Amount( +// rawValue: BigInt.zero, +// fractionDigits: _token.decimals, +// ), +// ); +// } +// return Balance.fromJson( +// jsonString, +// _token.decimals, +// ); +// } +// +// Future updateCachedBalance(Balance balance) async { +// await DB.instance.put( +// boxName: _walletId, +// key: TokenCacheKeys.tokenBalance(_token.address), +// value: balance.toJsonIgnoreCoin(), +// ); +// } +// } diff --git a/lib/wallets/isar/providers/eth/token_balance_provider.dart b/lib/wallets/isar/providers/eth/token_balance_provider.dart new file mode 100644 index 000000000..70504623b --- /dev/null +++ b/lib/wallets/isar/providers/eth/token_balance_provider.dart @@ -0,0 +1,40 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:isar/isar.dart'; +import 'package:stackwallet/models/balance.dart'; +import 'package:stackwallet/providers/db/main_db_provider.dart'; +import 'package:stackwallet/wallets/isar/models/token_wallet_info.dart'; +import 'package:stackwallet/wallets/isar/providers/util/watcher.dart'; + +final _twiProvider = ChangeNotifierProvider.family( + (ref, data) { + final collection = ref.watch(mainDBProvider).isar.tokenWalletInfo; + + final watcher = Watcher( + collection + .where() + .walletIdTokenAddressEqualTo(data.walletId, data.contractAddress) + .findFirstSync()!, + collection: collection, + ); + + ref.onDispose(() => watcher.dispose()); + + return watcher; + }, +); + +final pTokenWalletInfo = Provider.family( + (ref, data) { + return ref.watch(_twiProvider(data)).value as TokenWalletInfo; + }, +); + +final pTokenBalance = + Provider.family( + (ref, data) { + return ref.watch(_twiProvider(data).select( + (value) => (value.value as TokenWalletInfo).getCachedBalance())); + }, +); diff --git a/lib/wallets/isar/providers/wallet_info_provider.dart b/lib/wallets/isar/providers/wallet_info_provider.dart index 3cfeb1be2..b2c39ec21 100644 --- a/lib/wallets/isar/providers/wallet_info_provider.dart +++ b/lib/wallets/isar/providers/wallet_info_provider.dart @@ -82,3 +82,10 @@ final pWalletReceivingAddress = Provider.family( .select((value) => (value.value as WalletInfo).cachedReceivingAddress)); }, ); + +final pWalletTokenAddresses = Provider.family, String>( + (ref, walletId) { + return ref.watch(_wiProvider(walletId) + .select((value) => (value.value as WalletInfo).tokenContractAddresses)); + }, +); diff --git a/lib/widgets/master_wallet_card.dart b/lib/widgets/master_wallet_card.dart index ec73604d4..f6d37d27a 100644 --- a/lib/widgets/master_wallet_card.dart +++ b/lib/widgets/master_wallet_card.dart @@ -11,12 +11,11 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:stackwallet/providers/providers.dart'; import 'package:stackwallet/themes/stack_colors.dart'; import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/constants.dart'; import 'package:stackwallet/utilities/util.dart'; -import 'package:stackwallet/wallets/wallet/impl/ethereum_wallet.dart'; +import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart'; import 'package:stackwallet/widgets/animated_widgets/rotate_icon.dart'; import 'package:stackwallet/widgets/expandable.dart'; import 'package:stackwallet/widgets/rounded_white_container.dart'; @@ -40,17 +39,6 @@ class MasterWalletCard extends ConsumerStatefulWidget { class _MasterWalletCardState extends ConsumerState { final expandableController = ExpandableController(); final rotateIconController = RotateIconController(); - late final List tokenContractAddresses; - - @override - void initState() { - final ethWallet = - ref.read(pWallets).getWallet(widget.walletId) as EthereumWallet; - - tokenContractAddresses = ethWallet.info.tokenContractAddresses; - - super.initState(); - } @override Widget build(BuildContext context) { @@ -130,20 +118,20 @@ class _MasterWalletCardState extends ConsumerState { popPrevious: true, ), ), - ...tokenContractAddresses.map( - (e) => Padding( - padding: const EdgeInsets.only( - left: 7, - right: 7, - bottom: 7, + ...ref.watch(pWalletTokenAddresses(widget.walletId)).map( + (e) => Padding( + padding: const EdgeInsets.only( + left: 7, + right: 7, + bottom: 7, + ), + child: SimpleWalletCard( + walletId: widget.walletId, + contractAddress: e, + popPrevious: Util.isDesktop, + ), + ), ), - child: SimpleWalletCard( - walletId: widget.walletId, - contractAddress: e, - popPrevious: Util.isDesktop, - ), - ), - ), ], ), ),