From 82f9fa6d671c5d2e19117128ad55e9fe68f5a352 Mon Sep 17 00:00:00 2001 From: Reuben Yap Date: Wed, 23 Sep 2026 15:29:32 +0800 Subject: [PATCH 1/3] feat: generate per-app Ethereum token defaults --- lib/app_config.dart | 4 + .../edit_wallet_tokens_view.dart | 4 +- .../add_wallet_view/add_wallet_view.dart | 3 +- .../shopinbit/shopinbit_payment_shared.dart | 4 +- lib/utilities/default_eth_tokens.dart | 79 ++++++++++--------- scripts/app_config/configure_campfire.sh | 9 ++- scripts/app_config/configure_stack_duo.sh | 4 +- scripts/app_config/configure_stack_wallet.sh | 11 ++- scripts/ensure_test_app_config.sh | 9 +++ 9 files changed, 80 insertions(+), 47 deletions(-) diff --git a/lib/app_config.dart b/lib/app_config.dart index 4e926ad8ea..d594cf5d9e 100644 --- a/lib/app_config.dart +++ b/lib/app_config.dart @@ -1,6 +1,8 @@ // ignore: unused_import import 'dart:io'; +import 'models/isar/models/ethereum/eth_contract.dart'; +import 'utilities/default_eth_tokens.dart'; import 'wallets/crypto_currency/crypto_currency.dart'; import 'wallets/crypto_currency/intermediate/frost_currency.dart'; @@ -28,6 +30,8 @@ abstract class AppConfig { static List get coins => _supportedCoins; + static List get defaultEthTokens => _defaultEthTokens; + static ({String from, String fromFuzzyNet, String to, String toFuzzyNet}) get swapDefaults => _swapDefaults; 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 d81afe51e5..457f37c6bf 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 @@ -15,6 +15,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; import 'package:isar_community/isar.dart'; +import '../../../app_config.dart'; import '../../../db/isar/main_db.dart'; import '../../../models/isar/models/ethereum/eth_contract.dart'; import '../../../models/isar/models/solana/sol_contract.dart'; @@ -25,7 +26,6 @@ import '../../../providers/global/wallets_provider.dart'; import '../../../themes/stack_colors.dart'; import '../../../utilities/assets.dart'; import '../../../utilities/constants.dart'; -import '../../../utilities/default_eth_tokens.dart'; import '../../../utilities/default_sol_tokens.dart'; import '../../../utilities/text_styles.dart'; import '../../../utilities/util.dart'; @@ -268,7 +268,7 @@ class _EditWalletTokensViewState extends ConsumerState { .findAllSync(); if (contracts.isEmpty) { - contracts.addAll(DefaultTokens.list); + contracts.addAll(AppConfig.defaultEthTokens); MainDB.instance .putEthContracts(contracts) .then( diff --git a/lib/pages/add_wallet_views/add_wallet_view/add_wallet_view.dart b/lib/pages/add_wallet_views/add_wallet_view/add_wallet_view.dart index 13cb7a022e..648ba3fcee 100644 --- a/lib/pages/add_wallet_views/add_wallet_view/add_wallet_view.dart +++ b/lib/pages/add_wallet_views/add_wallet_view/add_wallet_view.dart @@ -28,7 +28,6 @@ import '../../../providers/providers.dart'; import '../../../themes/stack_colors.dart'; import '../../../utilities/assets.dart'; import '../../../utilities/constants.dart'; -import '../../../utilities/default_eth_tokens.dart'; import '../../../utilities/default_sol_tokens.dart'; import '../../../utilities/text_styles.dart'; import '../../../utilities/util.dart'; @@ -180,7 +179,7 @@ class _AddWalletViewState extends ConsumerState { MainDB.instance.getEthContracts().sortByName().findAllSync(); if (contracts.isEmpty) { - contracts.addAll(DefaultTokens.list); + contracts.addAll(AppConfig.defaultEthTokens); MainDB.instance .putEthContracts(contracts) .then( diff --git a/lib/pages/shopinbit/shopinbit_payment_shared.dart b/lib/pages/shopinbit/shopinbit_payment_shared.dart index db5172ccd8..5eaef38019 100644 --- a/lib/pages/shopinbit/shopinbit_payment_shared.dart +++ b/lib/pages/shopinbit/shopinbit_payment_shared.dart @@ -20,9 +20,7 @@ import '../../widgets/background.dart'; import '../../widgets/custom_buttons/app_bar_icon_button.dart'; import 'shopinbit_send_from_view.dart'; -final String kShopInBitUsdtContractAddress = DefaultTokens.list - .firstWhere((t) => t.symbol == "USDT") - .address; +final String kShopInBitUsdtContractAddress = DefaultTokens.usdt.address; // Address + amount pulled out of one of the API's payment_links entries. class ShopInBitPaymentTarget { diff --git a/lib/utilities/default_eth_tokens.dart b/lib/utilities/default_eth_tokens.dart index 63cd7f62b3..98ccbd42bf 100644 --- a/lib/utilities/default_eth_tokens.dart +++ b/lib/utilities/default_eth_tokens.dart @@ -11,41 +11,46 @@ import '../models/isar/models/ethereum/eth_contract.dart'; abstract class DefaultTokens { - static List list = [ - EthContract( - address: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", - name: "USD Coin", - symbol: "USDC", - decimals: 6, - type: EthContractType.erc20, - ), - EthContract( - address: "0xdac17f958d2ee523a2206206994597c13d831ec7", - name: "Tether", - symbol: "USDT", - decimals: 6, - type: EthContractType.erc20, - ), - EthContract( - address: "0x95ad61b0a150d79219dcf64e1e6cc01f0b64c4ce", - name: "Shiba Inu", - symbol: "SHIB", - decimals: 18, - type: EthContractType.erc20, - ), - EthContract( - address: "0x514910771af9ca656af840dff83e8264ecf986ca", - name: "Chainlink", - symbol: "LINK", - decimals: 18, - type: EthContractType.erc20, - ), - EthContract( - address: "0x1f9840a85d5af5bf1d1762f925bdaddc4201f984", - name: "Uniswap", - symbol: "UNI", - decimals: 18, - type: EthContractType.erc20, - ), - ]; + static final usdc = EthContract( + address: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", + name: "USD Coin", + symbol: "USDC", + decimals: 6, + type: EthContractType.erc20, + ); + static final usdt = EthContract( + address: "0xdac17f958d2ee523a2206206994597c13d831ec7", + name: "Tether", + symbol: "USDT", + decimals: 6, + type: EthContractType.erc20, + ); + static final shib = EthContract( + address: "0x95ad61b0a150d79219dcf64e1e6cc01f0b64c4ce", + name: "Shiba Inu", + symbol: "SHIB", + decimals: 18, + type: EthContractType.erc20, + ); + static final link = EthContract( + address: "0x514910771af9ca656af840dff83e8264ecf986ca", + name: "Chainlink", + symbol: "LINK", + decimals: 18, + type: EthContractType.erc20, + ); + static final uni = EthContract( + address: "0x1f9840a85d5af5bf1d1762f925bdaddc4201f984", + name: "Uniswap", + symbol: "UNI", + decimals: 18, + type: EthContractType.erc20, + ); + static final rsFiro = EthContract( + address: "0x2744ea5ac9b11cb5e3cd63d3a88e858336aeddc2", + name: "rsFIRO", + symbol: "rsFIRO", + decimals: 8, + type: EthContractType.erc20, + ); } diff --git a/scripts/app_config/configure_campfire.sh b/scripts/app_config/configure_campfire.sh index 40e03dfe26..6af9e01ec8 100755 --- a/scripts/app_config/configure_campfire.sh +++ b/scripts/app_config/configure_campfire.sh @@ -75,8 +75,15 @@ const ({String light, String dark})? _appIconAsset = ( final List _supportedCoins = List.unmodifiable([ Firo(CryptoCurrencyNetwork.main), + Ethereum(CryptoCurrencyNetwork.main), ]); +final List _defaultEthTokens = [ + DefaultTokens.rsFiro, + DefaultTokens.usdc, + DefaultTokens.usdt, +]; + final ({String from, String fromFuzzyNet, String to, String toFuzzyNet}) _swapDefaults = ( from: "BTC", @@ -85,4 +92,4 @@ _swapDefaults = ( toFuzzyNet: "firo", ); -EOF \ No newline at end of file +EOF diff --git a/scripts/app_config/configure_stack_duo.sh b/scripts/app_config/configure_stack_duo.sh index d0bf3694e6..2949d80cd0 100755 --- a/scripts/app_config/configure_stack_duo.sh +++ b/scripts/app_config/configure_stack_duo.sh @@ -80,6 +80,8 @@ final List _supportedCoins = List.unmodifiable([ BitcoinFrost(CryptoCurrencyNetwork.test4), ]); +const List _defaultEthTokens = []; + final ({String from, String fromFuzzyNet, String to, String toFuzzyNet}) _swapDefaults = ( from: "BTC", @@ -88,4 +90,4 @@ _swapDefaults = ( toFuzzyNet: "xmr", ); -EOF \ No newline at end of file +EOF diff --git a/scripts/app_config/configure_stack_wallet.sh b/scripts/app_config/configure_stack_wallet.sh index ae16b70ae1..6f41d27b7c 100755 --- a/scripts/app_config/configure_stack_wallet.sh +++ b/scripts/app_config/configure_stack_wallet.sh @@ -135,6 +135,15 @@ final List _supportedCoins = List.unmodifiable([ Xelis(CryptoCurrencyNetwork.test), ]); +final List _defaultEthTokens = [ + DefaultTokens.usdc, + DefaultTokens.usdt, + DefaultTokens.shib, + DefaultTokens.link, + DefaultTokens.uni, + DefaultTokens.rsFiro, +]; + final ({String from, String fromFuzzyNet, String to, String toFuzzyNet}) _swapDefaults = ( from: "BTC", @@ -143,4 +152,4 @@ _swapDefaults = ( toFuzzyNet: "xmr", ); -EOF \ No newline at end of file +EOF diff --git a/scripts/ensure_test_app_config.sh b/scripts/ensure_test_app_config.sh index 417da291a3..696c853b4e 100755 --- a/scripts/ensure_test_app_config.sh +++ b/scripts/ensure_test_app_config.sh @@ -80,6 +80,15 @@ final List _supportedCoins = List.unmodifiable([ Xelis(CryptoCurrencyNetwork.test), ]); +final List _defaultEthTokens = [ + DefaultTokens.usdc, + DefaultTokens.usdt, + DefaultTokens.shib, + DefaultTokens.link, + DefaultTokens.uni, + DefaultTokens.rsFiro, +]; + final ({String from, String fromFuzzyNet, String to, String toFuzzyNet}) _swapDefaults = ( from: "BTC", From 4bf55f6a70019b1ba44f1955ed8012ceed2e440b Mon Sep 17 00:00:00 2001 From: Reuben Yap Date: Wed, 23 Sep 2026 15:31:52 +0800 Subject: [PATCH 2/3] feat: load rsFIRO icons from per-app asset sources --- asset_sources/svg/campfire/rsfiro.svg | 16 ++++++++++ asset_sources/svg/stack_duo/rsfiro.svg | 1 + asset_sources/svg/stack_wallet/rsfiro.svg | 16 ++++++++++ .../sub_widgets/add_token_list_element.dart | 12 ++++++- .../sub_widgets/coin_select_item.dart | 8 ++++- lib/utilities/assets.dart | 2 ++ lib/widgets/icon_widgets/eth_token_icon.dart | 13 ++++++++ test/widgets/eth_token_icon_test.dart | 32 +++++++++++++++++++ 8 files changed, 98 insertions(+), 2 deletions(-) create mode 100644 asset_sources/svg/campfire/rsfiro.svg create mode 100644 asset_sources/svg/stack_duo/rsfiro.svg create mode 100644 asset_sources/svg/stack_wallet/rsfiro.svg create mode 100644 test/widgets/eth_token_icon_test.dart diff --git a/asset_sources/svg/campfire/rsfiro.svg b/asset_sources/svg/campfire/rsfiro.svg new file mode 100644 index 0000000000..03d755176a --- /dev/null +++ b/asset_sources/svg/campfire/rsfiro.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/asset_sources/svg/stack_duo/rsfiro.svg b/asset_sources/svg/stack_duo/rsfiro.svg new file mode 100644 index 0000000000..c805622a6e --- /dev/null +++ b/asset_sources/svg/stack_duo/rsfiro.svg @@ -0,0 +1 @@ + diff --git a/asset_sources/svg/stack_wallet/rsfiro.svg b/asset_sources/svg/stack_wallet/rsfiro.svg new file mode 100644 index 0000000000..03d755176a --- /dev/null +++ b/asset_sources/svg/stack_wallet/rsfiro.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/lib/pages/add_wallet_views/add_token_view/sub_widgets/add_token_list_element.dart b/lib/pages/add_wallet_views/add_token_view/sub_widgets/add_token_list_element.dart index eecf914d73..11a674fb17 100644 --- a/lib/pages/add_wallet_views/add_token_view/sub_widgets/add_token_list_element.dart +++ b/lib/pages/add_wallet_views/add_token_view/sub_widgets/add_token_list_element.dart @@ -20,6 +20,7 @@ import '../../../../services/exchange/change_now/change_now_exchange.dart'; import '../../../../services/exchange/exchange_data_loading_service.dart'; import '../../../../themes/stack_colors.dart'; import '../../../../utilities/assets.dart'; +import '../../../../utilities/default_eth_tokens.dart'; import '../../../../utilities/text_styles.dart'; import '../../../../utilities/util.dart'; import '../../../../widgets/app_icon.dart'; @@ -95,7 +96,16 @@ class _AddTokenListElementState extends ConsumerState { children: [ Row( children: [ - currency != null + if (widget.data.token is EthContract && + widget.data.token.address.toLowerCase() == + DefaultTokens.rsFiro.address) + SvgPicture.asset( + Assets.svg.rsFiro, + width: iconSize, + height: iconSize, + ) + else + currency != null ? SvgPicture.network( currency!.image, width: iconSize, diff --git a/lib/pages/add_wallet_views/add_wallet_view/sub_widgets/coin_select_item.dart b/lib/pages/add_wallet_views/add_wallet_view/sub_widgets/coin_select_item.dart index 9254847fcb..d22383a231 100644 --- a/lib/pages/add_wallet_views/add_wallet_view/sub_widgets/coin_select_item.dart +++ b/lib/pages/add_wallet_views/add_wallet_view/sub_widgets/coin_select_item.dart @@ -26,6 +26,7 @@ import '../../../../themes/coin_icon_provider.dart'; import '../../../../themes/stack_colors.dart'; import '../../../../utilities/assets.dart'; import '../../../../utilities/constants.dart'; +import '../../../../utilities/default_eth_tokens.dart'; import '../../../../utilities/text_styles.dart'; import '../../../../utilities/util.dart'; import '../../../../widgets/app_icon.dart'; @@ -137,7 +138,12 @@ class _CoinSelectItemState extends ConsumerState { constraints: BoxConstraints(minHeight: isDesktop ? 70 : 0), child: Row( children: [ - tokenImageUri != null + if (widget.entity is EthTokenEntity && + (widget.entity as EthTokenEntity).token.address.toLowerCase() == + DefaultTokens.rsFiro.address) + SvgPicture.asset(Assets.svg.rsFiro, width: 26, height: 26) + else + tokenImageUri != null ? tokenImageUri!.toLowerCase().endsWith(".svg") ? SvgPicture.network( tokenImageUri!, diff --git a/lib/utilities/assets.dart b/lib/utilities/assets.dart index ac6693a02e..509c9d6c01 100644 --- a/lib/utilities/assets.dart +++ b/lib/utilities/assets.dart @@ -117,6 +117,8 @@ class _SVG { final coinControl = const _COIN_CONTROL(); + String get rsFiro => "assets/svg/rsfiro.svg"; + String get peers => "assets/svg/peers.svg"; String get fusing => "assets/svg/fusing.svg"; String get upFromLine => "assets/svg/up-from-line.svg"; diff --git a/lib/widgets/icon_widgets/eth_token_icon.dart b/lib/widgets/icon_widgets/eth_token_icon.dart index 856474283e..eb88200916 100644 --- a/lib/widgets/icon_widgets/eth_token_icon.dart +++ b/lib/widgets/icon_widgets/eth_token_icon.dart @@ -19,6 +19,8 @@ import '../../models/isar/exchange_cache/currency.dart'; import '../../services/exchange/change_now/change_now_exchange.dart'; import '../../services/exchange/exchange_data_loading_service.dart'; import '../../themes/coin_icon_provider.dart'; +import '../../utilities/assets.dart'; +import '../../utilities/default_eth_tokens.dart'; import '../../wallets/crypto_currency/crypto_currency.dart'; import '../loading_indicator.dart'; @@ -38,10 +40,13 @@ class EthTokenIcon extends ConsumerStatefulWidget { class _EthTokenIconState extends ConsumerState { String? imageUrl; + bool get _isRsFiro => + widget.contractAddress.toLowerCase() == DefaultTokens.rsFiro.address; @override void initState() { super.initState(); + if (_isRsFiro) return; ExchangeDataLoadingService.instance.isar.then((isar) async { final currency = await isar.currencies @@ -67,6 +72,14 @@ class _EthTokenIconState extends ConsumerState { @override Widget build(BuildContext context) { + if (_isRsFiro) { + return SvgPicture.asset( + Assets.svg.rsFiro, + width: widget.size, + height: widget.size, + ); + } + if (imageUrl == null || imageUrl!.isEmpty) { return SvgPicture.file( File(ref.watch(coinIconProvider(Ethereum(.main)))), diff --git a/test/widgets/eth_token_icon_test.dart b/test/widgets/eth_token_icon_test.dart new file mode 100644 index 0000000000..af6a062e05 --- /dev/null +++ b/test/widgets/eth_token_icon_test.dart @@ -0,0 +1,32 @@ +import 'package:flutter/widgets.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:stackwallet/utilities/assets.dart'; +import 'package:stackwallet/utilities/default_eth_tokens.dart'; +import 'package:stackwallet/widgets/icon_widgets/eth_token_icon.dart'; + +void main() { + testWidgets('rsFIRO uses the per-app SVG by contract address', ( + tester, + ) async { + final token = DefaultTokens.rsFiro; + expect(token.address, '0x2744ea5ac9b11cb5e3cd63d3a88e858336aeddc2'); + expect(token.decimals, 8); + await tester.pumpWidget( + ProviderScope( + child: Center( + child: EthTokenIcon( + contractAddress: token.address.toUpperCase(), + size: 26, + ), + ), + ), + ); + await tester.pumpAndSettle(); + final svg = tester.widget(find.byType(SvgPicture)); + expect((svg.bytesLoader as SvgAssetLoader).assetName, Assets.svg.rsFiro); + expect(tester.getSize(find.byType(SvgPicture)), const Size.square(26)); + expect(tester.takeException(), isNull); + }); +} From 015a801199b0421fd95bbb4b69f8fedd011c0f78 Mon Sep 17 00:00:00 2001 From: Reuben Yap Date: Wed, 23 Sep 2026 21:42:35 +0800 Subject: [PATCH 3/3] ci: format touched files and reuse test key stubs --- .github/workflows/test.yaml | 12 - .../edit_wallet_tokens_view.dart | 59 ++--- .../sub_widgets/add_token_list_element.dart | 100 ++++---- .../add_wallet_view/add_wallet_view.dart | 229 +++++++++--------- .../sub_widgets/coin_select_item.dart | 65 ++--- 5 files changed, 221 insertions(+), 244 deletions(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 53b0a10648..77b62bd5d8 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -49,18 +49,6 @@ jobs: run: | if [ -n "$CHANGE_NOW" ]; then echo "$CHANGE_NOW" | base64 --decode > lib/external_api_keys.dart - else - cat > lib/external_api_keys.dart << 'EOF' - const String kChangeNowApiKey = ""; - const String kSimpleSwapApiKey = ""; - const String kNanswapApiKey = ""; - const String kNanoSwapRpcApiKey = ""; - const String kWizSwapApiKey = ""; - const kShopInBitAccessKey = ""; - const kShopInBitPartnerSecret = ""; - const kCakePayApiToken = ""; - const kExolixApiKey = ""; - EOF fi - name: Ensure app config for tests 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 457f37c6bf..749f2351f3 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 @@ -100,11 +100,10 @@ class _EditWalletTokensViewState extends ConsumerState { } Future onNextPressed() async { - final selectedTokens = - tokenEntities - .where((e) => e.selected) - .map((e) => e.token.address) - .toList(); + final selectedTokens = tokenEntities + .where((e) => e.selected) + .map((e) => e.token.address) + .toList(); final wallet = ref.read(pWallets).getWallet(widget.walletId); @@ -119,13 +118,11 @@ class _EditWalletTokensViewState extends ConsumerState { Navigator.of(context).pop(42); } else { if (isDesktop) { - Navigator.of( - context, - ).popUntil(ModalRoute.withName(DesktopHomeView.routeName)); + Navigator.of(context) + .popUntil(ModalRoute.withName(DesktopHomeView.routeName)); } else { - await Navigator.of( - context, - ).pushNamedAndRemoveUntil(HomeView.routeName, (route) => false); + await Navigator.of(context) + .pushNamedAndRemoveUntil(HomeView.routeName, (route) => false); } if (mounted) { unawaited( @@ -160,9 +157,8 @@ class _EditWalletTokensViewState extends ConsumerState { ), ); } else { - final result = await Navigator.of( - context, - ).pushNamed(AddCustomTokenView.routeName); + final result = await Navigator.of(context) + .pushNamed(AddCustomTokenView.routeName); contract = result as EthContract?; } @@ -177,7 +173,9 @@ class _EditWalletTokensViewState extends ConsumerState { tokenEntities.add( AddTokenListElementData(contract!)..selected = true, ); - tokenEntities.sort((a, b) => a.token.name.compareTo(b.token.name)); + tokenEntities.sort( + (a, b) => a.token.name.compareTo(b.token.name), + ); } }); } @@ -199,9 +197,7 @@ class _EditWalletTokensViewState extends ConsumerState { ), ); } else { - final result = await Navigator.of( - context, - ).pushNamed( + final result = await Navigator.of(context).pushNamed( AddCustomSolanaTokenView.routeName, arguments: widget.walletId, ); @@ -228,9 +224,7 @@ class _EditWalletTokensViewState extends ConsumerState { if (tokenEntities .where((e) => e.token.address == token!.address) .isEmpty) { - tokenEntities.add( - AddTokenListElementData(token!)..selected = true, - ); + tokenEntities.add(AddTokenListElementData(token!)..selected = true); tokenEntities.sort((a, b) => a.token.name.compareTo(b.token.name)); } }); @@ -448,9 +442,8 @@ class _EditWalletTokensViewState extends ConsumerState { _searchTerm = value; }); }, - style: STextStyles.desktopTextMedium( - context, - ).copyWith(height: 2), + style: STextStyles.desktopTextMedium(context) + .copyWith(height: 2), decoration: standardInputDecoration( "Search", @@ -516,9 +509,9 @@ class _EditWalletTokensViewState extends ConsumerState { } else { return Background( child: Scaffold( - backgroundColor: Theme.of( - context, - ).extension()!.background, + backgroundColor: Theme.of(context) + .extension()! + .background, appBar: AppBar( leading: AppBarBackButton( onPressed: () { @@ -533,14 +526,14 @@ class _EditWalletTokensViewState extends ConsumerState { child: AppBarIconButton( size: 36, shadows: const [], - color: Theme.of( - context, - ).extension()!.background, + color: Theme.of(context) + .extension()! + .background, icon: SvgPicture.asset( Assets.svg.circlePlusFilled, - color: Theme.of( - context, - ).extension()!.topNavIconPrimary, + color: Theme.of(context) + .extension()! + .topNavIconPrimary, width: 20, height: 20, ), diff --git a/lib/pages/add_wallet_views/add_token_view/sub_widgets/add_token_list_element.dart b/lib/pages/add_wallet_views/add_token_view/sub_widgets/add_token_list_element.dart index 11a674fb17..65088fbc94 100644 --- a/lib/pages/add_wallet_views/add_token_view/sub_widgets/add_token_list_element.dart +++ b/lib/pages/add_wallet_views/add_token_view/sub_widgets/add_token_list_element.dart @@ -55,18 +55,14 @@ class _AddTokenListElementState extends ConsumerState { super.initState(); ExchangeDataLoadingService.instance.isar.then((isar) async { - final currency = - await isar.currencies - .where() - .exchangeNameEqualTo(ChangeNowExchange.exchangeName) - .filter() - .tokenContractEqualTo( - widget.data.token.address, - caseSensitive: false, - ) - .and() - .imageIsNotEmpty() - .findFirst(); + final currency = await isar.currencies + .where() + .exchangeNameEqualTo(ChangeNowExchange.exchangeName) + .filter() + .tokenContractEqualTo(widget.data.token.address, caseSensitive: false) + .and() + .imageIsNotEmpty() + .findFirst(); if (mounted) { WidgetsBinding.instance.addPostFrameCallback((_) { @@ -87,10 +83,9 @@ class _AddTokenListElementState extends ConsumerState { return RoundedWhiteContainer( padding: EdgeInsets.all(isDesktop ? 16 : 12), - borderColor: - isDesktop - ? Theme.of(context).extension()!.backgroundAppBar - : null, + borderColor: isDesktop + ? Theme.of(context).extension()!.backgroundAppBar + : null, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -106,40 +101,36 @@ class _AddTokenListElementState extends ConsumerState { ) else currency != null - ? SvgPicture.network( - currency!.image, - width: iconSize, - height: iconSize, - placeholderBuilder: - (_) => AppIcon(width: iconSize, height: iconSize), - ) - : AppIcon(width: iconSize, height: iconSize), + ? SvgPicture.network( + currency!.image, + width: iconSize, + height: iconSize, + placeholderBuilder: (_) => + AppIcon(width: iconSize, height: iconSize), + ) + : AppIcon(width: iconSize, height: iconSize), const SizedBox(width: 12), ConditionalParent( condition: isDesktop, - builder: - (child) => Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - child, - const SizedBox(height: 2), - Text( - widget.data.token.symbol, - style: STextStyles.desktopTextExtraExtraSmall( - context, - ), - overflow: TextOverflow.ellipsis, - ), - ], + builder: (child) => Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + child, + const SizedBox(height: 2), + Text( + widget.data.token.symbol, + style: STextStyles.desktopTextExtraExtraSmall(context), + overflow: TextOverflow.ellipsis, ), + ], + ), child: Text( isDesktop ? mainLabel : "$mainLabel (${widget.data.token.symbol})", - style: - isDesktop - ? STextStyles.desktopTextSmall(context) - : STextStyles.w600_14(context), + style: isDesktop + ? STextStyles.desktopTextSmall(context) + : STextStyles.w600_14(context), overflow: TextOverflow.ellipsis, ), ), @@ -148,21 +139,20 @@ class _AddTokenListElementState extends ConsumerState { const SizedBox(width: 4), isDesktop ? Checkbox( - value: widget.data.selected, - onChanged: - (newValue) => - setState(() => widget.data.selected = newValue!), - ) + value: widget.data.selected, + onChanged: (newValue) => + setState(() => widget.data.selected = newValue!), + ) : SizedBox( - height: 20, - width: 40, - child: DraggableSwitchButton( - isOn: widget.data.selected, - onValueChanged: (newValue) { - widget.data.selected = newValue; - }, + height: 20, + width: 40, + child: DraggableSwitchButton( + isOn: widget.data.selected, + onValueChanged: (newValue) { + widget.data.selected = newValue; + }, + ), ), - ), ], ), ); diff --git a/lib/pages/add_wallet_views/add_wallet_view/add_wallet_view.dart b/lib/pages/add_wallet_views/add_wallet_view/add_wallet_view.dart index 648ba3fcee..6c8b8079c8 100644 --- a/lib/pages/add_wallet_views/add_wallet_view/add_wallet_view.dart +++ b/lib/pages/add_wallet_views/add_wallet_view/add_wallet_view.dart @@ -102,17 +102,15 @@ class _AddWalletViewState extends ConsumerState { if (isDesktop) { contract = await showDialog( context: context, - builder: - (context) => const DesktopDialog( - maxWidth: 580, - maxHeight: 500, - child: AddCustomTokenView(), - ), + builder: (context) => const DesktopDialog( + maxWidth: 580, + maxHeight: 500, + child: AddCustomTokenView(), + ), ); } else { - contract = await Navigator.of( - context, - ).pushNamed(AddCustomTokenView.routeName); + contract = await Navigator.of(context) + .pushNamed(AddCustomTokenView.routeName); } if (contract != null) { @@ -136,17 +134,15 @@ class _AddWalletViewState extends ConsumerState { if (isDesktop) { token = await showDialog( context: context, - builder: - (context) => const DesktopDialog( - maxWidth: 580, - maxHeight: 500, - child: AddCustomSolanaTokenView(), - ), + builder: (context) => const DesktopDialog( + maxWidth: 580, + maxHeight: 500, + child: AddCustomSolanaTokenView(), + ), ); } else { - token = await Navigator.of( - context, - ).pushNamed(AddCustomSolanaTokenView.routeName); + token = await Navigator.of(context) + .pushNamed(AddCustomSolanaTokenView.routeName); } if (token != null) { @@ -175,8 +171,10 @@ class _AddWalletViewState extends ConsumerState { } if (AppConfig.coins.whereType().isNotEmpty) { - final contracts = - MainDB.instance.getEthContracts().sortByName().findAllSync(); + final contracts = MainDB.instance + .getEthContracts() + .sortByName() + .findAllSync(); if (contracts.isEmpty) { contracts.addAll(AppConfig.defaultEthTokens); @@ -273,60 +271,60 @@ class _AddWalletViewState extends ConsumerState { _searchTerm = value; }); }, - style: STextStyles.desktopTextMedium( - context, - ).copyWith(height: 2), - decoration: standardInputDecoration( - "Search", - _searchFocusNode, - context, - ).copyWith( - contentPadding: const EdgeInsets.symmetric( - vertical: 10, - ), - prefixIcon: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 16, - // vertical: 20, - ), - child: SvgPicture.asset( - Assets.svg.search, - width: 24, - height: 24, - color: - Theme.of(context) + style: STextStyles.desktopTextMedium(context) + .copyWith(height: 2), + decoration: + standardInputDecoration( + "Search", + _searchFocusNode, + context, + ).copyWith( + contentPadding: const EdgeInsets.symmetric( + vertical: 10, + ), + prefixIcon: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 16, + // vertical: 20, + ), + child: SvgPicture.asset( + Assets.svg.search, + width: 24, + height: 24, + color: Theme.of(context) .extension()! .textFieldDefaultSearchIconLeft, - ), - ), - suffixIcon: - _searchFieldController.text.isNotEmpty + ), + ), + suffixIcon: + _searchFieldController.text.isNotEmpty ? Padding( - padding: const EdgeInsets.only( - right: 10, - ), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon( - width: 24, - height: 24, + padding: const EdgeInsets.only( + right: 10, + ), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon( + width: 24, + height: 24, + ), + onTap: () async { + setState(() { + _searchFieldController + .text = + ""; + _searchTerm = ""; + }); + }, ), - onTap: () async { - setState(() { - _searchFieldController - .text = ""; - _searchTerm = ""; - }); - }, - ), - ], + ], + ), ), - ), - ) + ) : null, - ), + ), ), ), ), @@ -364,7 +362,10 @@ class _AddWalletViewState extends ConsumerState { if (solTokenEntities.isNotEmpty) ExpandingSubListItem( title: "Solana tokens", - entities: filter(_searchTerm, solTokenEntities), + entities: filter( + _searchTerm, + solTokenEntities, + ), initialState: ExpandableState.expanded, animationDurationMultiplier: 0.5, trailing: AddCustomTokenSelector( @@ -394,8 +395,9 @@ class _AddWalletViewState extends ConsumerState { } else { return Background( child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, + backgroundColor: Theme.of(context) + .extension()! + .background, appBar: AppBar( leading: AppBarBackButton( onPressed: () { @@ -418,8 +420,7 @@ class _AddWalletViewState extends ConsumerState { Constants.size.circularBorderRadius, ), child: Semantics( - label: - "Search Text Field. Inputs Text To Search In Wallets.", + label: "Search Text Field. Inputs Text To Search In Wallets.", excludeSemantics: true, child: TextField( autofocus: isDesktop, @@ -427,49 +428,53 @@ class _AddWalletViewState extends ConsumerState { enableSuggestions: !isDesktop, controller: _searchFieldController, focusNode: _searchFocusNode, - onChanged: - (value) => setState(() => _searchTerm = value), + onChanged: (value) => + setState(() => _searchTerm = value), style: STextStyles.field(context), - decoration: standardInputDecoration( - "Search", - _searchFocusNode, - context, - desktopMed: isDesktop, - ).copyWith( - prefixIcon: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 10, - vertical: 16, - ), - child: SvgPicture.asset( - Assets.svg.search, - width: 16, - height: 16, - ), - ), - suffixIcon: - _searchFieldController.text.isNotEmpty + decoration: + standardInputDecoration( + "Search", + _searchFocusNode, + context, + desktopMed: isDesktop, + ).copyWith( + prefixIcon: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 16, + ), + child: SvgPicture.asset( + Assets.svg.search, + width: 16, + height: 16, + ), + ), + suffixIcon: + _searchFieldController.text.isNotEmpty ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - _searchFieldController.text = - ""; - _searchTerm = ""; - }); - }, - ), - ], + padding: const EdgeInsets.only( + right: 0, + ), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + _searchFieldController + .text = + ""; + _searchTerm = ""; + }); + }, + ), + ], + ), ), - ), - ) + ) : null, - ), + ), ), ), ), diff --git a/lib/pages/add_wallet_views/add_wallet_view/sub_widgets/coin_select_item.dart b/lib/pages/add_wallet_views/add_wallet_view/sub_widgets/coin_select_item.dart index d22383a231..95f3f4a790 100644 --- a/lib/pages/add_wallet_views/add_wallet_view/sub_widgets/coin_select_item.dart +++ b/lib/pages/add_wallet_views/add_wallet_view/sub_widgets/coin_select_item.dart @@ -139,44 +139,45 @@ class _CoinSelectItemState extends ConsumerState { child: Row( children: [ if (widget.entity is EthTokenEntity && - (widget.entity as EthTokenEntity).token.address.toLowerCase() == + (widget.entity as EthTokenEntity).token.address + .toLowerCase() == DefaultTokens.rsFiro.address) SvgPicture.asset(Assets.svg.rsFiro, width: 26, height: 26) else tokenImageUri != null - ? tokenImageUri!.toLowerCase().endsWith(".svg") - ? SvgPicture.network( - tokenImageUri!, - width: 26, - height: 26, - placeholderBuilder: (_) => - const AppIcon(width: 26, height: 26), - ) - : Image.network( - tokenImageUri!, - width: 26, - height: 26, - errorBuilder: (_, _, _) => SvgPicture.file( - File( - ref.watch( - coinIconProvider( - widget.entity.cryptoCurrency, + ? tokenImageUri!.toLowerCase().endsWith(".svg") + ? SvgPicture.network( + tokenImageUri!, + width: 26, + height: 26, + placeholderBuilder: (_) => + const AppIcon(width: 26, height: 26), + ) + : Image.network( + tokenImageUri!, + width: 26, + height: 26, + errorBuilder: (_, _, _) => SvgPicture.file( + File( + ref.watch( + coinIconProvider( + widget.entity.cryptoCurrency, + ), ), ), + width: 26, + height: 26, ), - width: 26, - height: 26, - ), - ) - : SvgPicture.file( - File( - ref.watch( - coinIconProvider(widget.entity.cryptoCurrency), + ) + : SvgPicture.file( + File( + ref.watch( + coinIconProvider(widget.entity.cryptoCurrency), + ), ), + width: 26, + height: 26, ), - width: 26, - height: 26, - ), SizedBox(width: isDesktop ? 12 : 10), Text( "${widget.entity.name} (${widget.entity.ticker})", @@ -193,9 +194,9 @@ class _CoinSelectItemState extends ConsumerState { height: 24, child: SvgPicture.asset( Assets.svg.check, - color: Theme.of( - context, - ).extension()!.accentColorDark, + color: Theme.of(context) + .extension()! + .accentColorDark, ), ), ),