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]
Omar Hatem committed
Apr 18, 2026 at 00:05 UTC
314eb36dd5dd8363a4af87de3bc70c32f4f43e8c
8 files changed
+49
-14
cw_evm/lib/clients/evm_chain_client.dart
+3
@@ -535,6 +535,9 @@ class EVMChainClient {
535
} on RangeError catch (_) {
536
throw Exception('Invalid token contract for this network.');
537
} catch (e) {
538
+ if (e.toString().contains("hostUnreachable")) {
539
+ return EVMChainERC20Balance(BigInt.zero);
540
+ }
541
throw Exception('Could not fetch balances: ${e.toString()}');
542
}
543
}
lib/exchange/provider/swaptrade_exchange_provider.dart
+3
@@ -94,6 +94,9 @@ class SwapTradeExchangeProvider extends ExchangeProvider {
94
}) async {
95
try {
96
if (amount == 0) return 0.0;
97
+ if (isFixedRateMode && !supportsFixedRate) {
98
+ return 0.0;
99
+ }
100
if(from == CryptoCurrency.btcln || to == CryptoCurrency.btcln) return 0;
101
102
final params = <String, dynamic>{};
lib/new-ui/pages/swap_page.dart
+2
-1
@@ -378,11 +378,12 @@ class _NewSwapPageState extends State<NewSwapPage> {
378
379
@override
380
void dispose() {
381
- super.dispose();
381
_depositAmountFocus.dispose();
382
_depositAddressFocus.dispose();
383
_receiveAmountFocus.dispose();
384
_receiveAddressFocus.dispose();
385
+ widget.exchangeViewModel.dispose();
386
+ super.dispose();
387
}
388
389
void _onCurrencyChange(CryptoCurrency currency, ExchangeViewModel exchangeViewModel,
lib/new-ui/widgets/send_page/send_address_input.dart
+5
-1
@@ -169,7 +169,11 @@ class _NewSendAddressInputState extends State<NewSendAddressInput> {
169
170
try {
171
final uri = Uri.parse(code);
172
- widget.addressController.text = uri.path;
172
+ // probably should remove this and let the `onURIScanned` handle it, but for now,
173
+ // will fix that it takes the token contract address
174
+ if (!uri.path.contains("/transfer")) {
175
+ widget.addressController.text = uri.path;
176
+ }
177
widget.onURIScanned?.call(uri);
178
} catch (_) {
179
widget.addressController.text = code;
lib/src/screens/settings/connection_sync_page.dart
+2
-2
@@ -100,7 +100,7 @@ class ConnectionSyncPage extends BasePage {
100
label: S.of(context).arbiscan_history,
101
value: _connectionSyncViewModel.useArbiScan,
102
onChanged: (val) {
103
- _connectionSyncViewModel.setUsePolygonScan(val);
103
+ _connectionSyncViewModel.setUseArbiScan(val);
104
}),
105
if (_connectionSyncViewModel.canUseBscScan)
106
ListItemToggle(
@@ -116,7 +116,7 @@ class ConnectionSyncPage extends BasePage {
116
label: S.of(context).trongrid_history,
117
value: _connectionSyncViewModel.useTronGrid,
118
onChanged: (val) {
119
- _connectionSyncViewModel.setUsePolygonScan(val);
119
+ _connectionSyncViewModel.setUseTronGrid(val);
120
}),
121
if (_connectionSyncViewModel.canUseMempoolFeeAPI)
122
ListItemToggle(
lib/src/widgets/bottom_sheet/token_selection_bottom_sheet.dart
+10
-2
@@ -15,6 +15,9 @@ import 'package:cake_wallet/wallet_types.g.dart';
15
import 'package:cw_core/crypto_currency.dart';
16
import 'package:cw_core/currency.dart';
17
import 'package:cw_core/currency_for_wallet_type.dart';
18
+import 'package:cw_core/erc20_token.dart';
19
+import 'package:cw_core/spl_token.dart';
20
+import 'package:cw_core/tron_token.dart';
21
import 'package:cw_core/utils/print_verbose.dart';
22
import 'package:cw_core/wallet_type.dart';
23
import 'package:flutter/material.dart';
@@ -78,7 +81,8 @@ class _TokenSelectionContentState extends State<_TokenSelectionContent> {
81
_autoSelectToken();
82
}
83
81
- bool get _isNetworkSelectable => widget.fixedNetwork == null || isEVMCompatibleChain(widget.fixedNetwork!);
84
+ bool get _isNetworkSelectable =>
85
+ widget.fixedNetwork == null || isEVMCompatibleChain(widget.fixedNetwork!);
86
87
Future<void> _autoSelectToken() async {
88
if (selectedNetwork == null) return;
@@ -102,7 +106,11 @@ class _TokenSelectionContentState extends State<_TokenSelectionContent> {
106
}
107
108
setState(() {
105
- selectedToken = tokens.first;
109
+ selectedToken = tokens.firstWhere((e) {
110
+ return (e is Erc20Token && e.contractAddress == widget.paymentRequest.contractAddress) ||
111
+ (e is SPLToken && e.mintAddress == widget.paymentRequest.contractAddress) ||
112
+ (e is TronToken && e.contractAddress == widget.paymentRequest.contractAddress);
113
+ }, orElse: () => tokens.first);
114
isLoadingTokens = false;
115
});
116
} catch (e) {
lib/utils/exception_handler.dart
+1
@@ -304,6 +304,7 @@ class ExceptionHandler {
304
"Image upload failed due to loss of GPU access",
305
"transport error",
306
"SdkError.sparkError(field0: Operator RPC error: Connection error: status: Unavailable, message: \"dns error\", details: []",
307
+ "the timeout of the request was reached",
308
309
"support for coin removed, your seedphrase:"
310
];
lib/view_model/exchange/exchange_view_model.dart
+23
-8
@@ -82,6 +82,16 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
82
// depositCurrency = wallet.currency;
83
}
84
85
+ final List<ReactionDisposer> _disposers = [];
86
+
87
+ void dispose() {
88
+ bestRateSync.cancel();
89
+ for (final disposer in _disposers) {
90
+ disposer();
91
+ }
92
+ _disposers.clear();
93
+ }
94
+
95
ExchangeViewModelBase(
96
this._appStore,
97
this.trades,
@@ -166,11 +176,11 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
176
depositAddress =
177
useSameWalletAddress(depositCurrency) ? wallet.walletAddresses.addressForExchange : '';
178
169
- reaction((_) => receiveAddress, (_) {
179
+ _disposers.add(reaction((_) => receiveAddress, (_) {
180
if(!(tradeState is TradeIsCreatedSuccessfully)) {
181
receiveAddressDisplayName = null;
182
}
173
- });
183
+ }));
184
185
provider = providerList.firstOrNull;
186
final initialProvider = provider;
@@ -184,9 +194,9 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
194
195
// providerDisplay is read by ui to display auto-selected provider.
196
// it's on a delay so it doesn't flicker.
187
- reaction((_)=>bestRateProvider,(val) {
197
+ _disposers.add(reaction((_) => bestRateProvider, (val) {
198
providerDisplay = val;
189
- },delay: 300);
199
+ }, delay: 300));
200
201
receiveCurrencies = CryptoCurrency.all
202
.where((cryptoCurrency) => !excludeReceiveCurrencies.contains(cryptoCurrency))
@@ -202,19 +212,19 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
212
_injectUserTronTokensIntoCurrencyLists();
213
_defineIsReceiveAmountEditable();
214
loadLimits();
205
- reaction((_) => isFixedRateMode, (Object _) {
215
+ _disposers.add(reaction((_) => isFixedRateMode, (Object _) {
216
bestRateProvider = null;
217
bestRate = 0.0;
218
loadLimits();
209
- });
219
+ }));
220
211
- reaction((_) => forceDecentralizedExchanges, (val) {
221
+ _disposers.add(reaction((_) => forceDecentralizedExchanges, (val) {
222
if (val && (bestRateProvider?.description.isCentralized ?? false)) {
223
bestRateProvider = null;
224
bestRate = 0.0;
225
loadLimits();
226
}
217
- });
227
+ }));
228
229
if (isElectrumWallet) {
230
bitcoin!.updateFeeRates(wallet);
@@ -1071,6 +1081,11 @@ abstract class ExchangeViewModelBase extends WalletChangeListenerViewModel with
1081
1082
printV('createTrade: trying provider=${provider.title}');
1083
1084
+ // should not happen but just as an extra check
1085
+ if (isFixedRateMode && provider.supportsFixedRate == false) {
1086
+ continue;
1087
+ }
1088
+
1089
// Skip Swaps.xyz when sending from external
1090
if (isSendFromExternal &&
1091
provider.description == ExchangeProviderDescription.swapsXyz) {