mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-06-28 12:29:51 +00:00
CW-1090-ledger-issues (#2314)
* build: bump ledger_flutter_plus dependencies * fix: handle connection errors occurring during connecting to a ledger device * fix: enhance ledger error handling and improve wallet connection reliability * fix: enhance ledger error handling and improve wallet connection reliability * feat: add localized strings for "Try again" and update Ledger error handling on auth * fix: handle rethrow behavior in onAuthenticationStateChange * fix: improve Ledger error handling and refine error code interpretation * fix: refine Ledger error code interpretation and enhance error handling [skip-ci] * add missing ledger error codes --------- Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>
This commit is contained in:
parent
4b137bc968
commit
18c2ba9366
36 changed files with 159 additions and 31 deletions
|
@ -73,8 +73,11 @@ class WalletLoadingService {
|
|||
return wallet;
|
||||
} catch (error, stack) {
|
||||
await ExceptionHandler.resetLastPopupDate();
|
||||
final isLedgerError = await ExceptionHandler.isLedgerError(error);
|
||||
if (isLedgerError) rethrow;
|
||||
await ExceptionHandler.onError(FlutterErrorDetails(exception: error, stack: stack));
|
||||
|
||||
|
||||
// try fetching the seeds of the corrupted wallet to show it to the user
|
||||
String corruptedWalletsSeeds = "Corrupted wallets seeds (if retrievable, empty otherwise):";
|
||||
try {
|
||||
|
|
|
@ -9,6 +9,7 @@ import 'package:cake_wallet/routes.dart';
|
|||
import 'package:cake_wallet/src/screens/connect_device/connect_device_page.dart';
|
||||
import 'package:cake_wallet/src/screens/wallet_connect/services/bottom_sheet_service.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
|
||||
import 'package:cake_wallet/store/authentication_store.dart';
|
||||
import 'package:cake_wallet/store/settings_store.dart';
|
||||
import 'package:cake_wallet/utils/exception_handler.dart';
|
||||
|
@ -63,14 +64,49 @@ void startAuthenticationStateChange(
|
|||
monero!.setGlobalLedgerConnection(ledgerVM.connection);
|
||||
showPopUp<void>(
|
||||
context: context,
|
||||
builder: (BuildContext context) => AlertWithOneAction(
|
||||
alertTitle: S.of(context).proceed_on_device,
|
||||
alertContent: S.of(context).proceed_on_device_description,
|
||||
buttonText: S.of(context).cancel,
|
||||
alertBarrierDismissible: false,
|
||||
buttonAction: () => Navigator.of(context).pop()),
|
||||
builder: (context) => AlertWithOneAction(
|
||||
alertTitle: S.of(context).proceed_on_device,
|
||||
alertContent: S.of(context).proceed_on_device_description,
|
||||
buttonText: S.of(context).cancel,
|
||||
alertBarrierDismissible: false,
|
||||
buttonAction: () => Navigator.of(context).pop(),
|
||||
),
|
||||
);
|
||||
await loadCurrentWallet();
|
||||
bool tryOpening = true;
|
||||
while (tryOpening) {
|
||||
try {
|
||||
await loadCurrentWallet();
|
||||
tryOpening = false;
|
||||
} on Exception catch (e) {
|
||||
final errorCode = RegExp(r'0x\S*?(?= )').firstMatch(
|
||||
e.toString());
|
||||
|
||||
final errorMessage = ledgerVM.interpretErrorCode(
|
||||
errorCode?.group(0).toString().replaceAll("0x", "") ??
|
||||
"");
|
||||
if (errorMessage != null) {
|
||||
await showPopUp<void>(
|
||||
context: context,
|
||||
builder: (context) => AlertWithTwoActions(
|
||||
alertTitle: "Ledger Error",
|
||||
alertContent: errorMessage,
|
||||
leftButtonText: S.of(context).try_again,
|
||||
alertBarrierDismissible: false,
|
||||
actionLeftButton: () => Navigator.of(context).pop(),
|
||||
rightButtonText: S.of(context).cancel,
|
||||
actionRightButton: () {
|
||||
tryOpening = false;
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
);
|
||||
} else {
|
||||
tryOpening = false;
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getIt.get<BottomSheetService>().showNext();
|
||||
await navigatorKey.currentState!
|
||||
.pushNamedAndRemoveUntil(Routes.dashboard, (route) => false);
|
||||
|
|
|
@ -165,8 +165,9 @@ class ConnectDevicePageBodyState extends State<ConnectDevicePageBody> {
|
|||
}
|
||||
|
||||
Future<void> _connectToDevice(LedgerDevice device) async {
|
||||
await widget.ledgerVM.connectLedger(device, widget.walletType);
|
||||
widget.onConnectDevice(context, widget.ledgerVM);
|
||||
final isConnected =
|
||||
await widget.ledgerVM.connectLedger(device, widget.walletType);
|
||||
if (isConnected) widget.onConnectDevice(context, widget.ledgerVM);
|
||||
}
|
||||
|
||||
String _getDeviceTileLeading(LedgerDeviceType deviceInfo) {
|
||||
|
|
|
@ -4,8 +4,10 @@ import 'package:cake_wallet/di.dart';
|
|||
import 'package:cake_wallet/entities/preferences_key.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/main.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
|
||||
import 'package:cake_wallet/store/app_store.dart';
|
||||
import 'package:cake_wallet/utils/package_info.dart';
|
||||
import 'package:cake_wallet/utils/show_bar.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:cw_core/root_dir.dart';
|
||||
|
@ -15,7 +17,6 @@ import 'package:flutter/foundation.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_mailer/flutter_mailer.dart';
|
||||
import 'package:cake_wallet/utils/package_info.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
class ExceptionHandler {
|
||||
|
@ -113,6 +114,8 @@ class ExceptionHandler {
|
|||
}
|
||||
|
||||
static Future<void> onError(FlutterErrorDetails errorDetails) async {
|
||||
if (await onLedgerError(errorDetails)) return;
|
||||
|
||||
if (kDebugMode || kProfileMode) {
|
||||
FlutterError.presentError(errorDetails);
|
||||
printV(errorDetails.toString());
|
||||
|
@ -183,6 +186,57 @@ class ExceptionHandler {
|
|||
_hasError = false;
|
||||
}
|
||||
|
||||
static const List<String> _ledgerErrors = [
|
||||
'Wrong Device Status',
|
||||
'PlatformException(133, Failed to write: (Unknown Error: 133), null, null)',
|
||||
'PlatformException(IllegalArgument, Unknown deviceId:',
|
||||
'ServiceNotSupportedException(ConnectionType.ble, Required service not supported. Write characteristic: false, Notify characteristic: false)',
|
||||
'Exception: 6e01', // Wrong App
|
||||
'Exception: 6d02',
|
||||
'Exception: 6511',
|
||||
'Exception: 6e00',
|
||||
'Exception: 6985',
|
||||
'Exception: 5515',
|
||||
];
|
||||
|
||||
static bool isLedgerError(Object exception) =>
|
||||
_ledgerErrors.any((element) => exception.toString().contains(element));
|
||||
|
||||
static Future<bool> onLedgerError(FlutterErrorDetails errorDetails) async {
|
||||
if (!isLedgerError(errorDetails.exception)) return false;
|
||||
|
||||
String? interpretErrorCode(String errorCode) {
|
||||
if (errorCode.contains("6985")) {
|
||||
return S.current.ledger_error_tx_rejected_by_user;
|
||||
} else if (errorCode.contains("5515")) {
|
||||
return S.current.ledger_error_device_locked;
|
||||
} else
|
||||
if (["6e01", "6d02", "6511", "6e00"].any((e) => errorCode.contains(e))) {
|
||||
return S.current.ledger_error_wrong_app;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
printV(errorDetails.exception);
|
||||
|
||||
if (navigatorKey.currentContext != null) {
|
||||
await showPopUp<void>(
|
||||
context: navigatorKey.currentContext!,
|
||||
builder: (context) => AlertWithOneAction(
|
||||
alertTitle: "Ledger Error",
|
||||
alertContent:
|
||||
interpretErrorCode(errorDetails.exception.toString()) ??
|
||||
S.of(context).ledger_connection_error,
|
||||
buttonText: S.of(context).close,
|
||||
buttonAction: () => Navigator.of(context).pop(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
_hasError = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Ignore User related errors or system errors
|
||||
static bool _ignoreError(String error) =>
|
||||
_ignoredErrors.any((element) => error.contains(element));
|
||||
|
@ -227,6 +281,7 @@ class ExceptionHandler {
|
|||
"core/auth_service.dart:64",
|
||||
"core/key_service.dart:14",
|
||||
"core/wallet_loading_service.dart:139",
|
||||
"Wrong Device Status: 0x5515 (UNKNOWN)",
|
||||
];
|
||||
|
||||
static Future<void> _addDeviceInfo(File file) async {
|
||||
|
|
|
@ -96,7 +96,8 @@ abstract class LedgerViewModelBase with Store {
|
|||
if (!Platform.isIOS) await ledgerPlusUSB.stopScanning();
|
||||
}
|
||||
|
||||
Future<void> connectLedger(sdk.LedgerDevice device, WalletType type) async {
|
||||
Future<bool> connectLedger(sdk.LedgerDevice device, WalletType type) async {
|
||||
if (_isConnecting) return false;
|
||||
_isConnecting = true;
|
||||
_connectingWalletType = type;
|
||||
if (isConnected) {
|
||||
|
@ -110,17 +111,25 @@ abstract class LedgerViewModelBase with Store {
|
|||
: ledgerPlusUSB;
|
||||
|
||||
if (_connectionChangeSubscription == null) {
|
||||
_connectionChangeSubscription =
|
||||
ledger.deviceStateChanges.listen(_connectionChangeListener);
|
||||
_connectionChangeSubscription = ledger
|
||||
.deviceStateChanges(device.id)
|
||||
.listen(_connectionChangeListener);
|
||||
}
|
||||
|
||||
_connection = await ledger.connect(device);
|
||||
try {
|
||||
_connection = await ledger.connect(device);
|
||||
_isConnecting = false;
|
||||
return true;
|
||||
} catch (e) {
|
||||
printV(e);
|
||||
}
|
||||
_isConnecting = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
StreamSubscription<sdk.BleConnectionState>? _connectionChangeSubscription;
|
||||
sdk.LedgerConnection? _connection;
|
||||
bool _isConnecting = true;
|
||||
bool _isConnecting = false;
|
||||
WalletType? _connectingWalletType;
|
||||
|
||||
void _connectionChangeListener(sdk.BleConnectionState event) {
|
||||
|
@ -168,17 +177,14 @@ abstract class LedgerViewModelBase with Store {
|
|||
}
|
||||
|
||||
String? interpretErrorCode(String errorCode) {
|
||||
switch (errorCode) {
|
||||
case "6985":
|
||||
return S.current.ledger_error_tx_rejected_by_user;
|
||||
case "5515":
|
||||
return S.current.ledger_error_device_locked;
|
||||
case "6d02": // UNKNOWN_APDU
|
||||
case "6511":
|
||||
case "6e00":
|
||||
return S.current.ledger_error_wrong_app;
|
||||
default:
|
||||
return null;
|
||||
if (errorCode.contains("6985")) {
|
||||
return S.current.ledger_error_tx_rejected_by_user;
|
||||
} else if (errorCode.contains("5515")) {
|
||||
return S.current.ledger_error_device_locked;
|
||||
} else
|
||||
if (["6e01", "6a87", "6d02", "6511", "6e00"].any((e) => errorCode.contains(e))) {
|
||||
return S.current.ledger_error_wrong_app;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -80,11 +80,9 @@ abstract class WalletHardwareRestoreViewModelBase extends WalletCreationVM with
|
|||
|
||||
availableAccounts.addAll(accounts);
|
||||
_nextIndex += limit;
|
||||
// } on LedgerException catch (e) {
|
||||
// error = ledgerViewModel.interpretErrorCode(e.errorCode.toRadixString(16));
|
||||
} catch (e) {
|
||||
printV(e);
|
||||
error = S.current.ledger_connection_error;
|
||||
error = ledgerViewModel.interpretErrorCode(e.toString()) ?? S.current.ledger_connection_error;
|
||||
}
|
||||
|
||||
isLoadingMoreAccounts = false;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue