From 314eb36dd5dd8363a4af87de3bc70c32f4f43e8c Mon Sep 17 00:00:00 2001 From: Omar Hatem Date: Sat, 18 Apr 2026 00:05:14 +0200 Subject: [PATCH] 6.1.0 fixes (#3190) * - Fix swap state not maintained (fixed rate can be on or off at the same time) - Fix Pay Anything putting contract address - Pick the token of the URI * fix incorrect function calls [skip ci] --- cw_evm/lib/clients/evm_chain_client.dart | 3 ++ .../provider/swaptrade_exchange_provider.dart | 3 ++ lib/new-ui/pages/swap_page.dart | 3 +- .../widgets/send_page/send_address_input.dart | 6 +++- .../settings/connection_sync_page.dart | 4 +-- .../token_selection_bottom_sheet.dart | 12 +++++-- lib/utils/exception_handler.dart | 1 + .../exchange/exchange_view_model.dart | 31 ++++++++++++++----- 8 files changed, 49 insertions(+), 14 deletions(-) diff --git a/cw_evm/lib/clients/evm_chain_client.dart b/cw_evm/lib/clients/evm_chain_client.dart index 7795e3981..0d51e8f17 100644 --- a/cw_evm/lib/clients/evm_chain_client.dart +++ b/cw_evm/lib/clients/evm_chain_client.dart @@ -535,6 +535,9 @@ class EVMChainClient { } on RangeError catch (_) { throw Exception('Invalid token contract for this network.'); } catch (e) { + if (e.toString().contains("hostUnreachable")) { + return EVMChainERC20Balance(BigInt.zero); + } throw Exception('Could not fetch balances: ${e.toString()}'); } } diff --git a/lib/exchange/provider/swaptrade_exchange_provider.dart b/lib/exchange/provider/swaptrade_exchange_provider.dart index 159c5ac45..99e6883b2 100644 --- a/lib/exchange/provider/swaptrade_exchange_provider.dart +++ b/lib/exchange/provider/swaptrade_exchange_provider.dart @@ -94,6 +94,9 @@ class SwapTradeExchangeProvider extends ExchangeProvider { }) async { try { if (amount == 0) return 0.0; + if (isFixedRateMode && !supportsFixedRate) { + return 0.0; + } if(from == CryptoCurrency.btcln || to == CryptoCurrency.btcln) return 0; final params = {}; diff --git a/lib/new-ui/pages/swap_page.dart b/lib/new-ui/pages/swap_page.dart index 2e4ab06de..a0fdd685b 100644 --- a/lib/new-ui/pages/swap_page.dart +++ b/lib/new-ui/pages/swap_page.dart @@ -378,11 +378,12 @@ class _NewSwapPageState extends State { @override void dispose() { - super.dispose(); _depositAmountFocus.dispose(); _depositAddressFocus.dispose(); _receiveAmountFocus.dispose(); _receiveAddressFocus.dispose(); + widget.exchangeViewModel.dispose(); + super.dispose(); } void _onCurrencyChange(CryptoCurrency currency, ExchangeViewModel exchangeViewModel, diff --git a/lib/new-ui/widgets/send_page/send_address_input.dart b/lib/new-ui/widgets/send_page/send_address_input.dart index feb0eaeaa..d02b71052 100644 --- a/lib/new-ui/widgets/send_page/send_address_input.dart +++ b/lib/new-ui/widgets/send_page/send_address_input.dart @@ -169,7 +169,11 @@ class _NewSendAddressInputState extends State { try { final uri = Uri.parse(code); - widget.addressController.text = uri.path; + // probably should remove this and let the `onURIScanned` handle it, but for now, + // will fix that it takes the token contract address + if (!uri.path.contains("/transfer")) { + widget.addressController.text = uri.path; + } widget.onURIScanned?.call(uri); } catch (_) { widget.addressController.text = code; diff --git a/lib/src/screens/settings/connection_sync_page.dart b/lib/src/screens/settings/connection_sync_page.dart index e609810f6..75d4d066e 100644 --- a/lib/src/screens/settings/connection_sync_page.dart +++ b/lib/src/screens/settings/connection_sync_page.dart @@ -100,7 +100,7 @@ class ConnectionSyncPage extends BasePage { label: S.of(context).arbiscan_history, value: _connectionSyncViewModel.useArbiScan, onChanged: (val) { - _connectionSyncViewModel.setUsePolygonScan(val); + _connectionSyncViewModel.setUseArbiScan(val); }), if (_connectionSyncViewModel.canUseBscScan) ListItemToggle( @@ -116,7 +116,7 @@ class ConnectionSyncPage extends BasePage { label: S.of(context).trongrid_history, value: _connectionSyncViewModel.useTronGrid, onChanged: (val) { - _connectionSyncViewModel.setUsePolygonScan(val); + _connectionSyncViewModel.setUseTronGrid(val); }), if (_connectionSyncViewModel.canUseMempoolFeeAPI) ListItemToggle( diff --git a/lib/src/widgets/bottom_sheet/token_selection_bottom_sheet.dart b/lib/src/widgets/bottom_sheet/token_selection_bottom_sheet.dart index bd41ea989..ea21c69f3 100644 --- a/lib/src/widgets/bottom_sheet/token_selection_bottom_sheet.dart +++ b/lib/src/widgets/bottom_sheet/token_selection_bottom_sheet.dart @@ -15,6 +15,9 @@ import 'package:cake_wallet/wallet_types.g.dart'; import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/currency.dart'; import 'package:cw_core/currency_for_wallet_type.dart'; +import 'package:cw_core/erc20_token.dart'; +import 'package:cw_core/spl_token.dart'; +import 'package:cw_core/tron_token.dart'; import 'package:cw_core/utils/print_verbose.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:flutter/material.dart'; @@ -78,7 +81,8 @@ class _TokenSelectionContentState extends State<_TokenSelectionContent> { _autoSelectToken(); } - bool get _isNetworkSelectable => widget.fixedNetwork == null || isEVMCompatibleChain(widget.fixedNetwork!); + bool get _isNetworkSelectable => + widget.fixedNetwork == null || isEVMCompatibleChain(widget.fixedNetwork!); Future _autoSelectToken() async { if (selectedNetwork == null) return; @@ -102,7 +106,11 @@ class _TokenSelectionContentState extends State<_TokenSelectionContent> { } setState(() { - selectedToken = tokens.first; + selectedToken = tokens.firstWhere((e) { + return (e is Erc20Token && e.contractAddress == widget.paymentRequest.contractAddress) || + (e is SPLToken && e.mintAddress == widget.paymentRequest.contractAddress) || + (e is TronToken && e.contractAddress == widget.paymentRequest.contractAddress); + }, orElse: () => tokens.first); isLoadingTokens = false; }); } catch (e) { diff --git a/lib/utils/exception_handler.dart b/lib/utils/exception_handler.dart index 44f421709..e3f101c1d 100644 --- a/lib/utils/exception_handler.dart +++ b/lib/utils/exception_handler.dart @@ -304,6 +304,7 @@ class ExceptionHandler { "Image upload failed due to loss of GPU access", "transport error", "SdkError.sparkError(field0: Operator RPC error: Connection error: status: Unavailable, message: \"dns error\", details: []", + "the timeout of the request was reached", "support for coin removed, your seedphrase:" ]; diff --git a/lib/view_model/exchange/exchange_view_model.dart b/lib/view_model/exchange/exchange_view_model.dart index df83af02a..dd34f51b9 100644 --- a/lib/view_model/exchange/exchange_view_model.dart +++ b/lib/view_model/exchange/exchange_view_model.dart @@ -82,6 +82,16 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with // depositCurrency = wallet.currency; } + final List _disposers = []; + + void dispose() { + bestRateSync.cancel(); + for (final disposer in _disposers) { + disposer(); + } + _disposers.clear(); + } + ExchangeViewModelBase( this._appStore, this.trades, @@ -166,11 +176,11 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with depositAddress = useSameWalletAddress(depositCurrency) ? wallet.walletAddresses.addressForExchange : ''; - reaction((_) => receiveAddress, (_) { + _disposers.add(reaction((_) => receiveAddress, (_) { if(!(tradeState is TradeIsCreatedSuccessfully)) { receiveAddressDisplayName = null; } - }); + })); provider = providerList.firstOrNull; final initialProvider = provider; @@ -184,9 +194,9 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with // providerDisplay is read by ui to display auto-selected provider. // it's on a delay so it doesn't flicker. - reaction((_)=>bestRateProvider,(val) { + _disposers.add(reaction((_) => bestRateProvider, (val) { providerDisplay = val; - },delay: 300); + }, delay: 300)); receiveCurrencies = CryptoCurrency.all .where((cryptoCurrency) => !excludeReceiveCurrencies.contains(cryptoCurrency)) @@ -202,19 +212,19 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with _injectUserTronTokensIntoCurrencyLists(); _defineIsReceiveAmountEditable(); loadLimits(); - reaction((_) => isFixedRateMode, (Object _) { + _disposers.add(reaction((_) => isFixedRateMode, (Object _) { bestRateProvider = null; bestRate = 0.0; loadLimits(); - }); + })); - reaction((_) => forceDecentralizedExchanges, (val) { + _disposers.add(reaction((_) => forceDecentralizedExchanges, (val) { if (val && (bestRateProvider?.description.isCentralized ?? false)) { bestRateProvider = null; bestRate = 0.0; loadLimits(); } - }); + })); if (isElectrumWallet) { bitcoin!.updateFeeRates(wallet); @@ -1071,6 +1081,11 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with printV('createTrade: trying provider=${provider.title}'); + // should not happen but just as an extra check + if (isFixedRateMode && provider.supportsFixedRate == false) { + continue; + } + // Skip Swaps.xyz when sending from external if (isSendFromExternal && provider.description == ExchangeProviderDescription.swapsXyz) {