From ae758756d8e2f870dd43f2740234c432770f2de5 Mon Sep 17 00:00:00 2001 From: Konstantin Ullrich Date: Sat, 14 Dec 2024 00:32:36 +0100 Subject: [PATCH] Ledger monero fix (#1834) * Fix sending for monero ledger * Ignore no tx keys found error * re-add Monero to Ledger enabled wallets * Fix No Element Exception on requireHardwareWalletConnection check * Fix Showing connection screen again * Maybe fix Race condition * fix namespace * Maybe fix Race condition and add missing pop * Minor fixes * Minor fixes * Fix minor localization * Fix minor localization * Add Text prompt if device is not showing after 10 seconds. --------- Co-authored-by: OmarHatem Co-authored-by: Czarek Nakamoto --- android/app/build.gradle | 2 +- .../lib/hardware/device_connection_type.dart | 2 +- cw_monero/lib/api/transaction_history.dart | 13 +++- cw_monero/lib/ledger.dart | 70 +++++++++++++++++- cw_monero/lib/monero_wallet_service.dart | 56 +++++++-------- .../on_authentication_state_change.dart | 25 ++++--- .../connect_device/connect_device_page.dart | 71 ++++++++++++++----- .../screens/restore/restore_options_page.dart | 5 +- lib/src/screens/send/send_page.dart | 5 +- .../screens/wallet_list/wallet_list_page.dart | 10 +-- lib/store/authentication_store.dart | 8 ++- .../hardware_wallet/ledger_view_model.dart | 47 +++++++++--- lib/view_model/wallet_creation_vm.dart | 3 +- res/values/strings_ar.arb | 2 + res/values/strings_bg.arb | 2 + res/values/strings_cs.arb | 2 + res/values/strings_de.arb | 4 +- res/values/strings_en.arb | 2 + res/values/strings_es.arb | 2 + res/values/strings_fr.arb | 2 + res/values/strings_ha.arb | 2 + res/values/strings_hi.arb | 2 + res/values/strings_hr.arb | 2 + res/values/strings_hy.arb | 2 + res/values/strings_id.arb | 2 + res/values/strings_it.arb | 2 + res/values/strings_ja.arb | 2 + res/values/strings_ko.arb | 4 +- res/values/strings_my.arb | 2 + res/values/strings_nl.arb | 2 + res/values/strings_pl.arb | 2 + res/values/strings_pt.arb | 2 + res/values/strings_ru.arb | 2 + res/values/strings_th.arb | 2 + res/values/strings_tl.arb | 2 + res/values/strings_tr.arb | 2 + res/values/strings_uk.arb | 2 + res/values/strings_ur.arb | 2 + res/values/strings_vi.arb | 2 + res/values/strings_yo.arb | 2 + res/values/strings_zh.arb | 2 + 41 files changed, 287 insertions(+), 90 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 238dc769d..b65c54108 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -99,4 +99,4 @@ configurations { implementation.exclude module:'proto-google-common-protos' implementation.exclude module:'protolite-well-known-types' implementation.exclude module:'protobuf-javalite' -} \ No newline at end of file +} diff --git a/cw_core/lib/hardware/device_connection_type.dart b/cw_core/lib/hardware/device_connection_type.dart index 466d58e2a..76a501af1 100644 --- a/cw_core/lib/hardware/device_connection_type.dart +++ b/cw_core/lib/hardware/device_connection_type.dart @@ -7,7 +7,7 @@ enum DeviceConnectionType { static List supportedConnectionTypes(WalletType walletType, [bool isIOS = false]) { switch (walletType) { - // case WalletType.monero: + case WalletType.monero: case WalletType.bitcoin: case WalletType.litecoin: case WalletType.ethereum: diff --git a/cw_monero/lib/api/transaction_history.dart b/cw_monero/lib/api/transaction_history.dart index aa6cac18a..854ee01c3 100644 --- a/cw_monero/lib/api/transaction_history.dart +++ b/cw_monero/lib/api/transaction_history.dart @@ -200,9 +200,16 @@ String? commitTransactionFromPointerAddress({required int address, required bool commitTransaction(transactionPointer: monero.PendingTransaction.fromAddress(address), useUR: useUR); String? commitTransaction({required monero.PendingTransaction transactionPointer, required bool useUR}) { + final transactionPointerAddress = transactionPointer.address; final txCommit = useUR - ? monero.PendingTransaction_commitUR(transactionPointer, 120) - : monero.PendingTransaction_commit(transactionPointer, filename: '', overwrite: false); + ? monero.PendingTransaction_commitUR(transactionPointer, 120) + : Isolate.run(() { + monero.PendingTransaction_commit( + Pointer.fromAddress(transactionPointerAddress), + filename: '', + overwrite: false, + ); + }); String? error = (() { final status = monero.PendingTransaction_status(transactionPointer.cast()); @@ -221,7 +228,7 @@ String? commitTransaction({required monero.PendingTransaction transactionPointer })(); } - if (error != null) { + if (error != null && error != "no tx keys found for this txid") { throw CreationTransactionException(message: error); } if (useUR) { diff --git a/cw_monero/lib/ledger.dart b/cw_monero/lib/ledger.dart index e7af9f390..b95c655a0 100644 --- a/cw_monero/lib/ledger.dart +++ b/cw_monero/lib/ledger.dart @@ -2,11 +2,12 @@ import 'dart:async'; import 'dart:ffi'; import 'dart:typed_data'; +import 'package:collection/collection.dart'; +import 'package:cw_core/utils/print_verbose.dart'; import 'package:ffi/ffi.dart'; import 'package:ledger_flutter_plus/ledger_flutter_plus.dart'; import 'package:ledger_flutter_plus/ledger_flutter_plus_dart.dart'; import 'package:monero/monero.dart' as monero; -// import 'package:polyseed/polyseed.dart'; LedgerConnection? gLedger; @@ -28,9 +29,16 @@ void enableLedgerExchange(monero.wallet ptr, LedgerConnection connection) { ptr, emptyPointer.cast(), 0); malloc.free(emptyPointer); - // printV("> ${ledgerRequest.toHexString()}"); + _logLedgerCommand(ledgerRequest, false); final response = await exchange(connection, ledgerRequest); - // printV("< ${response.toHexString()}"); + _logLedgerCommand(response, true); + + if (ListEquality().equals(response, [0x55, 0x15])) { + await connection.disconnect(); + // // TODO: Show POPUP pls unlock your device + // await Future.delayed(Duration(seconds: 15)); + // response = await exchange(connection, ledgerRequest); + } final Pointer result = malloc(response.length); for (var i = 0; i < response.length; i++) { @@ -82,3 +90,59 @@ class ExchangeOperation extends LedgerRawOperation { @override Future> write(ByteDataWriter writer) async => [inputData]; } + +const _ledgerMoneroCommands = { + 0x00: "INS_NONE", + 0x02: "INS_RESET", + 0x20: "INS_GET_KEY", + 0x21: "INS_DISPLAY_ADDRESS", + 0x22: "INS_PUT_KEY", + 0x24: "INS_GET_CHACHA8_PREKEY", + 0x26: "INS_VERIFY_KEY", + 0x28: "INS_MANAGE_SEEDWORDS", + 0x30: "INS_SECRET_KEY_TO_PUBLIC_KEY", + 0x32: "INS_GEN_KEY_DERIVATION", + 0x34: "INS_DERIVATION_TO_SCALAR", + 0x36: "INS_DERIVE_PUBLIC_KEY", + 0x38: "INS_DERIVE_SECRET_KEY", + 0x3A: "INS_GEN_KEY_IMAGE", + 0x3B: "INS_DERIVE_VIEW_TAG", + 0x3C: "INS_SECRET_KEY_ADD", + 0x3E: "INS_SECRET_KEY_SUB", + 0x40: "INS_GENERATE_KEYPAIR", + 0x42: "INS_SECRET_SCAL_MUL_KEY", + 0x44: "INS_SECRET_SCAL_MUL_BASE", + 0x46: "INS_DERIVE_SUBADDRESS_PUBLIC_KEY", + 0x48: "INS_GET_SUBADDRESS", + 0x4A: "INS_GET_SUBADDRESS_SPEND_PUBLIC_KEY", + 0x4C: "INS_GET_SUBADDRESS_SECRET_KEY", + 0x70: "INS_OPEN_TX", + 0x72: "INS_SET_SIGNATURE_MODE", + 0x74: "INS_GET_ADDITIONAL_KEY", + 0x76: "INS_STEALTH", + 0x77: "INS_GEN_COMMITMENT_MASK", + 0x78: "INS_BLIND", + 0x7A: "INS_UNBLIND", + 0x7B: "INS_GEN_TXOUT_KEYS", + 0x7D: "INS_PREFIX_HASH", + 0x7C: "INS_VALIDATE", + 0x7E: "INS_MLSAG", + 0x7F: "INS_CLSAG", + 0x80: "INS_CLOSE_TX", + 0xA0: "INS_GET_TX_PROOF", + 0xC0: "INS_GET_RESPONSE" +}; + +void _logLedgerCommand(Uint8List command, [bool isResponse = true]) { + String toHexString(Uint8List data) => + data.map((e) => e.toRadixString(16).padLeft(2, '0')).join(); + + + + if (isResponse) { + printV("< ${toHexString(command)}"); + } else { + printV( + "> ${_ledgerMoneroCommands[command[1]]} ${toHexString(command.sublist(2))}"); + } +} diff --git a/cw_monero/lib/monero_wallet_service.dart b/cw_monero/lib/monero_wallet_service.dart index 6f2435258..18171a568 100644 --- a/cw_monero/lib/monero_wallet_service.dart +++ b/cw_monero/lib/monero_wallet_service.dart @@ -1,5 +1,7 @@ import 'dart:ffi'; import 'dart:io'; + +import 'package:cw_core/get_height_by_date.dart'; import 'package:cw_core/monero_wallet_utils.dart'; import 'package:cw_core/pathForWallet.dart'; import 'package:cw_core/unspent_coins_info.dart'; @@ -9,16 +11,16 @@ import 'package:cw_core/wallet_credentials.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_service.dart'; import 'package:cw_core/wallet_type.dart'; -import 'package:cw_core/get_height_by_date.dart'; import 'package:cw_monero/api/account_list.dart'; import 'package:cw_monero/api/wallet_manager.dart' as monero_wallet_manager; import 'package:cw_monero/api/wallet_manager.dart'; import 'package:cw_monero/ledger.dart'; import 'package:cw_monero/monero_wallet.dart'; +import 'package:collection/collection.dart'; import 'package:hive/hive.dart'; import 'package:ledger_flutter_plus/ledger_flutter_plus.dart'; -import 'package:polyseed/polyseed.dart'; import 'package:monero/monero.dart' as monero; +import 'package:polyseed/polyseed.dart'; class MoneroNewWalletCredentials extends WalletCredentials { MoneroNewWalletCredentials( @@ -133,14 +135,12 @@ class MoneroWalletService extends WalletService< try { final path = await pathForWallet(name: name, type: getType()); - if (walletFilesExist(path)) { - await repairOldAndroidWallet(name); - } + if (walletFilesExist(path)) await repairOldAndroidWallet(name); await monero_wallet_manager .openWalletAsync({'path': path, 'password': password}); - final walletInfo = walletInfoSource.values.firstWhere( - (info) => info.id == WalletBase.idFor(name, getType())); + final walletInfo = walletInfoSource.values + .firstWhere((info) => info.id == WalletBase.idFor(name, getType())); final wallet = MoneroWallet( walletInfo: walletInfo, unspentCoinsInfo: unspentCoinsInfoSource, @@ -204,7 +204,7 @@ class MoneroWalletService extends WalletService< @override Future rename(String currentName, String password, String newName) async { final currentWalletInfo = walletInfoSource.values.firstWhere( - (info) => info.id == WalletBase.idFor(currentName, getType())); + (info) => info.id == WalletBase.idFor(currentName, getType())); final currentWallet = MoneroWallet( walletInfo: currentWalletInfo, unspentCoinsInfo: unspentCoinsInfoSource, @@ -255,14 +255,14 @@ class MoneroWalletService extends WalletService< final password = credentials.password; final height = credentials.height; - if (wptr == null ) monero_wallet_manager.createWalletPointer(); + if (wptr == null) monero_wallet_manager.createWalletPointer(); enableLedgerExchange(wptr!, credentials.ledgerConnection); await monero_wallet_manager.restoreWalletFromHardwareWallet( - path: path, - password: password!, - restoreHeight: height!, - deviceName: 'Ledger'); + path: path, + password: password!, + restoreHeight: height!, + deviceName: 'Ledger'); final wallet = MoneroWallet( walletInfo: credentials.walletInfo!, @@ -279,7 +279,8 @@ class MoneroWalletService extends WalletService< } @override - Future restoreFromSeed(MoneroRestoreWalletFromSeedCredentials credentials, + Future restoreFromSeed( + MoneroRestoreWalletFromSeedCredentials credentials, {bool? isTestnet}) async { // Restore from Polyseed if (Polyseed.isValidSeed(credentials.mnemonic)) { @@ -313,7 +314,8 @@ class MoneroWalletService extends WalletService< final path = await pathForWallet(name: credentials.name, type: getType()); final polyseedCoin = PolyseedCoin.POLYSEED_MONERO; final lang = PolyseedLang.getByPhrase(credentials.mnemonic); - final polyseed = Polyseed.decode(credentials.mnemonic, lang, polyseedCoin); + final polyseed = + Polyseed.decode(credentials.mnemonic, lang, polyseedCoin); return _restoreFromPolyseed( path, credentials.password!, polyseed, credentials.walletInfo!, lang); @@ -355,24 +357,18 @@ class MoneroWalletService extends WalletService< Future repairOldAndroidWallet(String name) async { try { - if (!Platform.isAndroid) { - return; - } + if (!Platform.isAndroid) return; final oldAndroidWalletDirPath = await outdatedAndroidPathForWalletDir(name: name); final dir = Directory(oldAndroidWalletDirPath); - if (!dir.existsSync()) { - return; - } + if (!dir.existsSync()) return; final newWalletDirPath = await pathForWalletDir(name: name, type: getType()); dir.listSync().forEach((f) { final file = File(f.path); - final name = f.path - .split('/') - .last; + final name = f.path.split('/').last; final newPath = newWalletDirPath + '/$name'; final newFile = File(newPath); @@ -391,9 +387,7 @@ class MoneroWalletService extends WalletService< try { final path = await pathForWallet(name: name, type: getType()); - if (walletFilesExist(path)) { - await repairOldAndroidWallet(name); - } + if (walletFilesExist(path)) await repairOldAndroidWallet(name); await monero_wallet_manager.openWalletAsync({'path': path, 'password': password}); final walletInfo = walletInfoSource.values @@ -412,8 +406,10 @@ class MoneroWalletService extends WalletService< @override bool requireHardwareWalletConnection(String name) { - final walletInfo = walletInfoSource.values - .firstWhere((info) => info.id == WalletBase.idFor(name, getType())); - return walletInfo.isHardwareWallet; + return walletInfoSource.values + .firstWhereOrNull( + (info) => info.id == WalletBase.idFor(name, getType())) + ?.isHardwareWallet ?? + false; } } diff --git a/lib/reactions/on_authentication_state_change.dart b/lib/reactions/on_authentication_state_change.dart index 88b03ca59..c05f6fb0d 100644 --- a/lib/reactions/on_authentication_state_change.dart +++ b/lib/reactions/on_authentication_state_change.dart @@ -44,13 +44,16 @@ void startAuthenticationStateChange( } catch (error, stack) { loginError = error; await ExceptionHandler.resetLastPopupDate(); - await ExceptionHandler.onError(FlutterErrorDetails(exception: error, stack: stack)); + await ExceptionHandler.onError( + FlutterErrorDetails(exception: error, stack: stack)); } return; } - if (state == AuthenticationState.allowed) { - if (requireHardwareWalletConnection()) { + if ([AuthenticationState.allowed, AuthenticationState.allowedCreate] + .contains(state)) { + if (state == AuthenticationState.allowed && + requireHardwareWalletConnection()) { await navigatorKey.currentState!.pushNamedAndRemoveUntil( Routes.connectDevices, (route) => false, @@ -58,14 +61,14 @@ void startAuthenticationStateChange( walletType: WalletType.monero, onConnectDevice: (context, ledgerVM) async { monero!.setGlobalLedgerConnection(ledgerVM.connection); - showPopUp( - 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, - buttonAction: () => Navigator.of(context).pop()), - ); + showPopUp( + 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, + buttonAction: () => Navigator.of(context).pop()), + ); await loadCurrentWallet(); getIt.get().resetCurrentSheet(); await navigatorKey.currentState! diff --git a/lib/src/screens/connect_device/connect_device_page.dart b/lib/src/screens/connect_device/connect_device_page.dart index 109c5eee2..5e94c78a4 100644 --- a/lib/src/screens/connect_device/connect_device_page.dart +++ b/lib/src/screens/connect_device/connect_device_page.dart @@ -22,11 +22,13 @@ class ConnectDevicePageParams { final WalletType walletType; final OnConnectDevice onConnectDevice; final bool allowChangeWallet; + final bool isReconnect; ConnectDevicePageParams({ required this.walletType, required this.onConnectDevice, this.allowChangeWallet = false, + this.isReconnect = false, }); } @@ -34,19 +36,33 @@ class ConnectDevicePage extends BasePage { final WalletType walletType; final OnConnectDevice onConnectDevice; final bool allowChangeWallet; + final bool isReconnect; final LedgerViewModel ledgerVM; ConnectDevicePage(ConnectDevicePageParams params, this.ledgerVM) : walletType = params.walletType, onConnectDevice = params.onConnectDevice, - allowChangeWallet = params.allowChangeWallet; + allowChangeWallet = params.allowChangeWallet, + isReconnect = params.isReconnect; @override - String get title => S.current.restore_title_from_hardware_wallet; + String get title => isReconnect + ? S.current.reconnect_your_hardware_wallet + : S.current.restore_title_from_hardware_wallet; @override - Widget body(BuildContext context) => ConnectDevicePageBody( - walletType, onConnectDevice, allowChangeWallet, ledgerVM); + Widget? leading(BuildContext context) => + !isReconnect ? super.leading(context) : null; + + @override + Widget body(BuildContext context) => PopScope( + canPop: !isReconnect, + child: ConnectDevicePageBody( + walletType, + onConnectDevice, + allowChangeWallet, + ledgerVM, + )); } class ConnectDevicePageBody extends StatefulWidget { @@ -75,6 +91,8 @@ class ConnectDevicePageBodyState extends State { late Timer? _bleStateTimer = null; late StreamSubscription? _bleRefresh = null; + bool longWait = false; + @override void initState() { super.initState(); @@ -89,6 +107,11 @@ class ConnectDevicePageBodyState extends State { _usbRefreshTimer = Timer.periodic(Duration(seconds: 1), (_) => _refreshUsbDevices()); } + + Future.delayed(Duration(seconds: 10), () { + if (widget.ledgerVM.bleIsEnabled && bleDevices.isEmpty) + setState(() => longWait = true); + }); }); } @@ -98,6 +121,8 @@ class ConnectDevicePageBodyState extends State { _bleStateTimer?.cancel(); _usbRefreshTimer?.cancel(); _bleRefresh?.cancel(); + + widget.ledgerVM.stopScanning(); super.dispose(); } @@ -118,12 +143,14 @@ class ConnectDevicePageBodyState extends State { Future _refreshBleDevices() async { try { if (widget.ledgerVM.bleIsEnabled) { - _bleRefresh = widget.ledgerVM - .scanForBleDevices() - .listen((device) => setState(() => bleDevices.add(device))) - ..onError((e) { - throw e.toString(); - }); + _bleRefresh = + widget.ledgerVM.scanForBleDevices().listen((device) => setState(() { + bleDevices.add(device); + if (longWait) longWait = false; + })) + ..onError((e) { + throw e.toString(); + }); _bleRefreshTimer?.cancel(); _bleRefreshTimer = null; } @@ -175,15 +202,21 @@ class ConnectDevicePageBodyState extends State { textAlign: TextAlign.center, ), ), - // DeviceTile( - // onPressed: () => Navigator.of(context).push( - // MaterialPageRoute( - // builder: (BuildContext context) => DebugDevicePage(), - // ), - // ), - // title: "Debug Ledger", - // leading: imageLedger, - // ), + Offstage( + offstage: !longWait, + child: Padding( + padding: EdgeInsets.only(left: 20, right: 20, bottom: 20), + child: Text(S.of(context).if_you_dont_see_your_device, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Theme.of(context) + .extension()! + .titleColor), + textAlign: TextAlign.center, + ), + ), + ), Observer( builder: (_) => Offstage( offstage: widget.ledgerVM.bleIsEnabled, diff --git a/lib/src/screens/restore/restore_options_page.dart b/lib/src/screens/restore/restore_options_page.dart index 79714aa05..2e9e04acd 100644 --- a/lib/src/screens/restore/restore_options_page.dart +++ b/lib/src/screens/restore/restore_options_page.dart @@ -56,9 +56,8 @@ class _RestoreOptionsBodyState extends State<_RestoreOptionsBody> { } if (isMoneroOnly) { - // return DeviceConnectionType.supportedConnectionTypes(WalletType.monero, Platform.isIOS) - // .isNotEmpty; - return false; + return DeviceConnectionType.supportedConnectionTypes(WalletType.monero, Platform.isIOS) + .isNotEmpty; } return true; diff --git a/lib/src/screens/send/send_page.dart b/lib/src/screens/send/send_page.dart index ddf2d7c89..ca471c4f2 100644 --- a/lib/src/screens/send/send_page.dart +++ b/lib/src/screens/send/send_page.dart @@ -580,7 +580,10 @@ class SendPage extends BasePage { alertTitle: S.of(context).proceed_on_device, alertContent: S.of(context).proceed_on_device_description, buttonText: S.of(context).cancel, - buttonAction: () => Navigator.of(context).pop()); + buttonAction: () { + sendViewModel.state = InitialExecutionState(); + Navigator.of(context).pop(); + }); }); }); } diff --git a/lib/src/screens/wallet_list/wallet_list_page.dart b/lib/src/screens/wallet_list/wallet_list_page.dart index 63f28d285..9bf924f61 100644 --- a/lib/src/screens/wallet_list/wallet_list_page.dart +++ b/lib/src/screens/wallet_list/wallet_list_page.dart @@ -422,8 +422,9 @@ class WalletListBodyState extends State { if (!isAuthenticatedSuccessfully) return; try { - if (widget.walletListViewModel - .requireHardwareWalletConnection(wallet)) { + final requireHardwareWalletConnection = widget.walletListViewModel + .requireHardwareWalletConnection(wallet); + if (requireHardwareWalletConnection) { await Navigator.of(context).pushNamed( Routes.connectDevices, arguments: ConnectDevicePageParams( @@ -445,8 +446,6 @@ class WalletListBodyState extends State { ); } - - changeProcessText( S.of(context).wallet_list_loading_wallet(wallet.name)); await widget.walletListViewModel.loadWallet(wallet); @@ -456,6 +455,9 @@ class WalletListBodyState extends State { if (responsiveLayoutUtil.shouldRenderMobileUI) { WidgetsBinding.instance.addPostFrameCallback((_) { if (this.mounted) { + if (requireHardwareWalletConnection) { + Navigator.of(context).pop(); + } widget.onWalletLoaded.call(context); } }); diff --git a/lib/store/authentication_store.dart b/lib/store/authentication_store.dart index 815b1ed60..db4c4861e 100644 --- a/lib/store/authentication_store.dart +++ b/lib/store/authentication_store.dart @@ -4,7 +4,7 @@ part 'authentication_store.g.dart'; class AuthenticationStore = AuthenticationStoreBase with _$AuthenticationStore; -enum AuthenticationState { uninitialized, installed, allowed, _reset } +enum AuthenticationState { uninitialized, installed, allowed, allowedCreate, _reset } abstract class AuthenticationStoreBase with Store { AuthenticationStoreBase() : state = AuthenticationState.uninitialized; @@ -23,4 +23,10 @@ abstract class AuthenticationStoreBase with Store { state = AuthenticationState._reset; state = AuthenticationState.allowed; } + + @action + void allowedCreate() { + state = AuthenticationState._reset; + state = AuthenticationState.allowedCreate; + } } diff --git a/lib/view_model/hardware_wallet/ledger_view_model.dart b/lib/view_model/hardware_wallet/ledger_view_model.dart index 9a4bb6a45..b48f641a2 100644 --- a/lib/view_model/hardware_wallet/ledger_view_model.dart +++ b/lib/view_model/hardware_wallet/ledger_view_model.dart @@ -4,14 +4,18 @@ import 'dart:io'; import 'package:cake_wallet/bitcoin/bitcoin.dart'; import 'package:cake_wallet/ethereum/ethereum.dart'; import 'package:cake_wallet/generated/i18n.dart'; +import 'package:cake_wallet/main.dart'; import 'package:cake_wallet/monero/monero.dart'; import 'package:cake_wallet/polygon/polygon.dart'; +import 'package:cake_wallet/routes.dart'; +import 'package:cake_wallet/src/screens/connect_device/connect_device_page.dart'; import 'package:cake_wallet/utils/device_info.dart'; import 'package:cake_wallet/wallet_type_utils.dart'; import 'package:cw_core/hardware/device_connection_type.dart'; import 'package:cw_core/utils/print_verbose.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_type.dart'; +import 'package:flutter/widgets.dart'; import 'package:ledger_flutter_plus/ledger_flutter_plus.dart' as sdk; import 'package:mobx/mobx.dart'; @@ -59,15 +63,18 @@ abstract class LedgerViewModelBase with Store { bool _bleIsInitialized = false; Future _initBLE() async { if (bleIsEnabled && !_bleIsInitialized) { - ledgerPlusBLE = sdk.LedgerInterface.ble(onPermissionRequest: (_) async { - Map statuses = await [ - Permission.bluetoothScan, - Permission.bluetoothConnect, - Permission.bluetoothAdvertise, - ].request(); + ledgerPlusBLE = sdk.LedgerInterface.ble( + onPermissionRequest: (_) async { + Map statuses = await [ + Permission.bluetoothScan, + Permission.bluetoothConnect, + Permission.bluetoothAdvertise, + ].request(); - return statuses.values.where((status) => status.isDenied).isEmpty; - }); + return statuses.values.where((status) => status.isDenied).isEmpty; + }, + bleOptions: + sdk.BluetoothOptions(maxScanDuration: Duration(minutes: 5))); _bleIsInitialized = true; } } @@ -84,16 +91,26 @@ abstract class LedgerViewModelBase with Store { Stream scanForUsbDevices() => ledgerPlusUSB.scan(); + Future stopScanning() async { + await ledgerPlusBLE.stopScanning(); + if (!Platform.isIOS) { + await ledgerPlusUSB.stopScanning(); + } + } + Future connectLedger(sdk.LedgerDevice device, WalletType type) async { if (isConnected) { try { - await _connection!.disconnect(); + await _connectionChangeListener?.cancel(); + _connectionChangeListener = null; + await _connection!.disconnect().catchError((_) {}); } catch (_) {} } final ledger = device.connectionType == sdk.ConnectionType.ble ? ledgerPlusBLE : ledgerPlusUSB; + if (_connectionChangeListener == null) { _connectionChangeListener = ledger.deviceStateChanges.listen((event) { printV('Ledger Device State Changed: $event'); @@ -101,6 +118,18 @@ abstract class LedgerViewModelBase with Store { _connection = null; if (type == WalletType.monero) { monero!.resetLedgerConnection(); + + Navigator.of( navigatorKey.currentContext!).pushNamed( + Routes.connectDevices, + arguments: ConnectDevicePageParams( + walletType: WalletType.monero, + allowChangeWallet: true, + isReconnect: true, + onConnectDevice: (context, ledgerVM) async { + Navigator.of(context).pop(); + }, + ), + ); } } }); diff --git a/lib/view_model/wallet_creation_vm.dart b/lib/view_model/wallet_creation_vm.dart index 68548b64a..c2cfcbd24 100644 --- a/lib/view_model/wallet_creation_vm.dart +++ b/lib/view_model/wallet_creation_vm.dart @@ -8,7 +8,6 @@ import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/nano/nano.dart'; import 'package:cake_wallet/store/app_store.dart'; import 'package:cake_wallet/store/settings_store.dart'; -import 'package:cake_wallet/view_model/restore/restore_mode.dart'; import 'package:cake_wallet/view_model/restore/restore_wallet.dart'; import 'package:cake_wallet/view_model/seed_settings_view_model.dart'; import 'package:cw_core/pathForWallet.dart'; @@ -114,7 +113,7 @@ abstract class WalletCreationVMBase with Store { await _walletInfoSource.add(walletInfo); await _appStore.changeCurrentWallet(wallet); getIt.get().registerSyncTask(); - _appStore.authenticationStore.allowed(); + _appStore.authenticationStore.allowedCreate(); state = ExecutedSuccessfullyState(); } catch (e, s) { printV("error: $e"); diff --git a/res/values/strings_ar.arb b/res/values/strings_ar.arb index a57a4cd1f..1bb1ec5f1 100644 --- a/res/values/strings_ar.arb +++ b/res/values/strings_ar.arb @@ -355,6 +355,7 @@ "how_to_use": " ﻞﻤﻌﺘﺴﺗ ﻒﻴﻛ", "how_to_use_card": "كيفية استخدام هذه البطاقة", "id": "رقم المعرف:", + "if_you_dont_see_your_device": "إذا كنت لا ترى جهازك أعلاه ، فيرجى التأكد من أن دفتر الأستاذ الخاص بك مستيقظًا ومؤمنًا!", "ignor": "تجاهل", "import": "ﺩﺭﻮﺘﺴﻳ", "importNFTs": "NFTs ﺩﺍﺮﻴﺘﺳﺍ", @@ -538,6 +539,7 @@ "recipient_address": "عنوان المستلم", "reconnect": "أعد الاتصال", "reconnect_alert_text": "هل أنت متأكد من رغبتك في إعادة الاتصال؟", + "reconnect_your_hardware_wallet": "أعد توصيل محفظة الأجهزة الخاصة بك", "reconnection": "إعادة الاتصال", "red_dark_theme": "موضوع الظلام الأحمر", "red_light_theme": "موضوع الضوء الأحمر", diff --git a/res/values/strings_bg.arb b/res/values/strings_bg.arb index 2aca0f08e..b624c2b9a 100644 --- a/res/values/strings_bg.arb +++ b/res/values/strings_bg.arb @@ -355,6 +355,7 @@ "how_to_use": "Как да използвам", "how_to_use_card": "Как се ползва тази карта", "id": "ID: ", + "if_you_dont_see_your_device": "Ако не виждате устройството си по -горе, моля, уверете се, че вашата книга е будна и отключена!", "ignor": "Игнориране", "import": "Импортиране", "importNFTs": "Импортирайте NFT", @@ -538,6 +539,7 @@ "recipient_address": "Адрес на получател", "reconnect": "Reconnect", "reconnect_alert_text": "Сигурни ли сте, че искате да се свържете отново?", + "reconnect_your_hardware_wallet": "Свържете отново хардуерния си портфейл", "reconnection": "Свързване отново", "red_dark_theme": "Червена тъмна тема", "red_light_theme": "Тема на червената светлина", diff --git a/res/values/strings_cs.arb b/res/values/strings_cs.arb index 7ce5538ae..be273c4d9 100644 --- a/res/values/strings_cs.arb +++ b/res/values/strings_cs.arb @@ -355,6 +355,7 @@ "how_to_use": "Jak používat", "how_to_use_card": "Jak použít tuto kartu", "id": "ID: ", + "if_you_dont_see_your_device": "Pokud vaše zařízení nevidíte výše, ujistěte se, že vaše kniha je vzhůru a odemknutá!", "ignor": "Ignorovat", "import": "Import", "importNFTs": "Importujte NFT", @@ -538,6 +539,7 @@ "recipient_address": "Adresa příjemce", "reconnect": "Znovu připojit", "reconnect_alert_text": "Opravdu se chcete znovu připojit?", + "reconnect_your_hardware_wallet": "Znovu připojte svou hardwarovou peněženku", "reconnection": "Znovu připojit", "red_dark_theme": "Červené temné téma", "red_light_theme": "Téma červeného světla", diff --git a/res/values/strings_de.arb b/res/values/strings_de.arb index bc06b4a53..ec0a9bb1f 100644 --- a/res/values/strings_de.arb +++ b/res/values/strings_de.arb @@ -355,6 +355,7 @@ "how_to_use": "Wie benutzt man", "how_to_use_card": "Wie man diese Karte benutzt", "id": "ID: ", + "if_you_dont_see_your_device": "Wenn Sie Ihr Gerät nicht sehen, stellen Sie bitte sicher, dass Ihr Ledger an und entsperrt ist!", "ignor": "Ignorieren", "import": "Importieren", "importNFTs": "NFTs importieren", @@ -539,6 +540,7 @@ "recipient_address": "Empfängeradresse", "reconnect": "Erneut verbinden", "reconnect_alert_text": "Sind Sie sicher, dass Sie sich neu verbinden möchten?", + "reconnect_your_hardware_wallet": "Hardware-Wallet neu verbinden", "reconnection": "Neu verbinden", "red_dark_theme": "Red Dark Thema", "red_light_theme": "Red Light Thema", @@ -973,4 +975,4 @@ "you_will_get": "Konvertieren zu", "you_will_send": "Konvertieren von", "yy": "YY" -} \ No newline at end of file +} diff --git a/res/values/strings_en.arb b/res/values/strings_en.arb index 26771edf1..be732e3c0 100644 --- a/res/values/strings_en.arb +++ b/res/values/strings_en.arb @@ -355,6 +355,7 @@ "how_to_use": "How to use", "how_to_use_card": "How to use this card", "id": "ID: ", + "if_you_dont_see_your_device": "If you don't see your device above, please be sure your Ledger is awake and unlocked!", "ignor": "Ignore", "import": "Import", "importNFTs": "Import NFTs", @@ -538,6 +539,7 @@ "recipient_address": "Recipient address", "reconnect": "Reconnect", "reconnect_alert_text": "Are you sure you want to reconnect?", + "reconnect_your_hardware_wallet": "Reconnect your Hardware Wallet", "reconnection": "Reconnection", "red_dark_theme": "Red Dark Theme", "red_light_theme": "Red Light Theme", diff --git a/res/values/strings_es.arb b/res/values/strings_es.arb index 6f2bd60b9..7373baae9 100644 --- a/res/values/strings_es.arb +++ b/res/values/strings_es.arb @@ -355,6 +355,7 @@ "how_to_use": "Cómo utilizar", "how_to_use_card": "Cómo usar esta tarjeta", "id": "ID: ", + "if_you_dont_see_your_device": "Si no ve su dispositivo arriba, ¡asegúrese de que su libro mayor esté despierto y desbloqueado!", "ignor": "Pasar por alto", "import": "Importar", "importNFTs": "Importar NFT", @@ -539,6 +540,7 @@ "recipient_address": "Dirección del receptor", "reconnect": "Volver a conectar", "reconnect_alert_text": "¿Estás seguro de reconectar?", + "reconnect_your_hardware_wallet": "Vuelva a conectar su billetera de hardware", "reconnection": "Reconexión", "red_dark_theme": "Tema rojo oscuro", "red_light_theme": "Tema de la luz roja", diff --git a/res/values/strings_fr.arb b/res/values/strings_fr.arb index ff5c17cde..b50211d4b 100644 --- a/res/values/strings_fr.arb +++ b/res/values/strings_fr.arb @@ -355,6 +355,7 @@ "how_to_use": "Comment utiliser", "how_to_use_card": "Comment utiliser cette carte", "id": "ID : ", + "if_you_dont_see_your_device": "Si vous ne voyez pas votre appareil ci-dessus, assurez-vous que votre grand livre est éveillé et déverrouillé!", "ignor": "Ignorer", "import": "Importer", "importNFTs": "Importer des NFT", @@ -538,6 +539,7 @@ "recipient_address": "Adresse bénéficiaire", "reconnect": "Reconnecter", "reconnect_alert_text": "Êtes vous certain de vouloir vous reconnecter ?", + "reconnect_your_hardware_wallet": "Reconnectez votre portefeuille matériel", "reconnection": "Reconnexion", "red_dark_theme": "Thème rouge sombre", "red_light_theme": "Thème rouge clair", diff --git a/res/values/strings_ha.arb b/res/values/strings_ha.arb index a13ed2af4..71aa7f490 100644 --- a/res/values/strings_ha.arb +++ b/res/values/strings_ha.arb @@ -355,6 +355,7 @@ "how_to_use": "Yadda ake amfani da shi", "how_to_use_card": "Yadda ake amfani da wannan kati", "id": "ID:", + "if_you_dont_see_your_device": "Idan baku ga na'urarka da ke sama ba, da fatan za a tabbata Ledger dinku yana farkawa kuma a buɗe!", "ignor": "Yi watsi da shi", "import": "Shigo da", "importNFTs": "Shigo da NFTs", @@ -540,6 +541,7 @@ "recipient_address": "Adireshin mai karɓa", "reconnect": "Sake haɗawa", "reconnect_alert_text": "Shin kun tabbata kuna son sake haɗawa?", + "reconnect_your_hardware_wallet": "Sake kunnawa kayan aiki", "reconnection": "Sake haɗawa", "red_dark_theme": "Ja duhu taken", "red_light_theme": "Ja mai haske", diff --git a/res/values/strings_hi.arb b/res/values/strings_hi.arb index b73414dee..811d34cd1 100644 --- a/res/values/strings_hi.arb +++ b/res/values/strings_hi.arb @@ -355,6 +355,7 @@ "how_to_use": "का उपयोग कैसे करें", "how_to_use_card": "इस कार्ड का उपयोग कैसे करें", "id": "ID: ", + "if_you_dont_see_your_device": "यदि आप अपने डिवाइस को ऊपर नहीं देखते हैं, तो कृपया सुनिश्चित करें कि आपका लेजर जागृत और अनलॉक हो गया है!", "ignor": "नज़रअंदाज़ करना", "import": "आयात", "importNFTs": "एनएफटी आयात करें", @@ -540,6 +541,7 @@ "recipient_address": "प्राप्तकर्ता का पता", "reconnect": "रिकनेक्ट", "reconnect_alert_text": "क्या आप पुन: कनेक्ट होना सुनिश्चित करते हैं?", + "reconnect_your_hardware_wallet": "अपने हार्डवेयर वॉलेट को फिर से कनेक्ट करें", "reconnection": "पुनर्संयोजन", "red_dark_theme": "लाल डार्क थीम", "red_light_theme": "लाल प्रकाश थीम", diff --git a/res/values/strings_hr.arb b/res/values/strings_hr.arb index 87d66122c..71be8f531 100644 --- a/res/values/strings_hr.arb +++ b/res/values/strings_hr.arb @@ -355,6 +355,7 @@ "how_to_use": "Kako koristiti", "how_to_use_card": "Kako koristiti ovu karticu", "id": "ID: ", + "if_you_dont_see_your_device": "Ako svoj uređaj ne vidite gore, budite sigurni da je vaša knjiga budna i otključana!", "ignor": "Zanemariti", "import": "Uvoz", "importNFTs": "Uvoz NFT-ova", @@ -538,6 +539,7 @@ "recipient_address": "Primateljeva adresa", "reconnect": "Ponovno povezivanje", "reconnect_alert_text": "Jeste li sigurni da se želite ponovno povezati?", + "reconnect_your_hardware_wallet": "Ponovno spojite svoj hardverski novčanik", "reconnection": "Ponovno povezivanje", "red_dark_theme": "Crvena tamna tema", "red_light_theme": "Tema crvenog svjetla", diff --git a/res/values/strings_hy.arb b/res/values/strings_hy.arb index dfbd94cdc..f17c91878 100644 --- a/res/values/strings_hy.arb +++ b/res/values/strings_hy.arb @@ -355,6 +355,7 @@ "how_to_use": "Ինչպես օգտագործել", "how_to_use_card": "Ինչպես օգտագործել այս քարտը", "id": "ID: ", + "if_you_dont_see_your_device": "Եթե ​​ձեր սարքը վերեւում չեք տեսնում, համոզվեք, որ ձեր Ledger- ը արթուն է եւ բացված:", "ignor": "Անտեսել", "import": "Ներմուծել", "importNFTs": "Ներմուծել NFT-ներ", @@ -538,6 +539,7 @@ "recipient_address": "Ստացողի հասցե", "reconnect": "Վերակապվել", "reconnect_alert_text": "Դուք վստահ եք, որ ուզում եք վերակապվել?", + "reconnect_your_hardware_wallet": "Միացրեք ձեր ապարատային դրամապանակը", "reconnection": "Վերակապում", "red_dark_theme": "Կարմիր մութ տեսք", "red_light_theme": "Կարմիր պայծառ տեսք", diff --git a/res/values/strings_id.arb b/res/values/strings_id.arb index b3ef0c67b..66fbaa320 100644 --- a/res/values/strings_id.arb +++ b/res/values/strings_id.arb @@ -355,6 +355,7 @@ "how_to_use": "Cara Penggunaan", "how_to_use_card": "Bagaimana menggunakan kartu ini", "id": "ID: ", + "if_you_dont_see_your_device": "Jika Anda tidak melihat perangkat Anda di atas, pastikan buku besar Anda terjaga dan tidak terkunci!", "ignor": "Abaikan", "import": "Impor", "importNFTs": "Impor NFT", @@ -540,6 +541,7 @@ "recipient_address": "Alamat penerima", "reconnect": "Sambungkan kembali", "reconnect_alert_text": "Apakah Anda yakin ingin menyambungkan kembali?", + "reconnect_your_hardware_wallet": "Hubungkan kembali dompet perangkat keras Anda", "reconnection": "Koneksi kembali", "red_dark_theme": "Tema gelap merah", "red_light_theme": "Tema lampu merah", diff --git a/res/values/strings_it.arb b/res/values/strings_it.arb index 2cf07fdd7..84f2e6c3a 100644 --- a/res/values/strings_it.arb +++ b/res/values/strings_it.arb @@ -356,6 +356,7 @@ "how_to_use": "Come usare", "how_to_use_card": "Come usare questa carta", "id": "ID: ", + "if_you_dont_see_your_device": "Se non vedi il tuo dispositivo sopra, assicurati che il tuo libro mastro sia sveglio e sbloccato!", "ignor": "Ignorare", "import": "Importare", "importNFTs": "Importa NFT", @@ -540,6 +541,7 @@ "recipient_address": "Indirizzo di destinazione", "reconnect": "Riconnetti", "reconnect_alert_text": "Sei sicuro di volerti riconnettere?", + "reconnect_your_hardware_wallet": "Ricollega il tuo portafoglio hardware", "reconnection": "Riconnessione", "red_dark_theme": "Red Dark Theme", "red_light_theme": "Tema della luce rossa", diff --git a/res/values/strings_ja.arb b/res/values/strings_ja.arb index 3edb9f88d..36be2118e 100644 --- a/res/values/strings_ja.arb +++ b/res/values/strings_ja.arb @@ -356,6 +356,7 @@ "how_to_use": "使い方", "how_to_use_card": "このカードの使用方法", "id": "ID: ", + "if_you_dont_see_your_device": "上記のデバイスが表示されない場合は、元帳が目を覚ましてロック解除されていることを確認してください!", "ignor": "無視", "import": "輸入", "importNFTs": "NFTのインポート", @@ -539,6 +540,7 @@ "recipient_address": "受信者のアドレス", "reconnect": "再接続", "reconnect_alert_text": "再接続しますか?", + "reconnect_your_hardware_wallet": "ハードウェアウォレットを再接続します", "reconnection": "再接続", "red_dark_theme": "赤い暗いテーマ", "red_light_theme": "赤色光のテーマ", diff --git a/res/values/strings_ko.arb b/res/values/strings_ko.arb index 6e5fb4a7b..8f36fc56c 100644 --- a/res/values/strings_ko.arb +++ b/res/values/strings_ko.arb @@ -355,6 +355,7 @@ "how_to_use": "사용하는 방법", "how_to_use_card": "이 카드를 사용하는 방법", "id": "ID: ", + "if_you_dont_see_your_device": "위의 장치가 표시되지 않으면 원장이 깨어 있고 잠금 해제되었는지 확인하십시오!", "ignor": "무시하다", "import": "수입", "importNFTs": "NFT 가져오기", @@ -502,8 +503,8 @@ "placeholder_transactions": "거래가 여기에 표시됩니다", "please_fill_totp": "다른 기기에 있는 8자리 코드를 입력하세요.", "please_make_selection": "아래에서 선택하십시오 지갑 만들기 또는 복구.", - "please_reference_document": "자세한 내용은 아래 문서를 참조하십시오.", "Please_reference_document": "자세한 내용은 아래 문서를 참조하십시오.", + "please_reference_document": "자세한 내용은 아래 문서를 참조하십시오.", "please_select": "선택 해주세요:", "please_select_backup_file": "백업 파일을 선택하고 백업 암호를 입력하십시오.", "please_try_to_connect_to_another_node": "다른 노드에 연결을 시도하십시오", @@ -539,6 +540,7 @@ "recipient_address": "받는 사람 주소", "reconnect": "다시 연결", "reconnect_alert_text": "다시 연결 하시겠습니까?", + "reconnect_your_hardware_wallet": "하드웨어 지갑을 다시 연결하십시오", "reconnection": "재 연결", "red_dark_theme": "빨간 어두운 테마", "red_light_theme": "빨간불 테마", diff --git a/res/values/strings_my.arb b/res/values/strings_my.arb index a7ada97ef..c41ce87b3 100644 --- a/res/values/strings_my.arb +++ b/res/values/strings_my.arb @@ -355,6 +355,7 @@ "how_to_use": "အသုံးပြုနည်း", "how_to_use_card": "ဒီကတ်ကို ဘယ်လိုသုံးမလဲ။", "id": "ID:", + "if_you_dont_see_your_device": "သင်၏စက်ကိုအထက်တွင်မတွေ့ပါကသင်၏ Ledger သည်နိုးလာပြီးသော့ဖွင့်နေသည်ကိုသေချာပါစေ။", "ignor": "လျစ်လျူရှုပါ။", "import": "သွင်းကုန်", "importNFTs": "NFTs များကို တင်သွင်းပါ။", @@ -538,6 +539,7 @@ "recipient_address": "လက်ခံသူလိပ်စာ", "reconnect": "ပြန်လည်ချိတ်ဆက်ပါ။", "reconnect_alert_text": "ပြန်လည်ချိတ်ဆက်လိုသည်မှာ သေချာပါသလား။ ?", + "reconnect_your_hardware_wallet": "သင့်ရဲ့ hardware ပိုက်ဆံအိတ်ကိုပြန်လည်ချိတ်ဆက်ပါ", "reconnection": "ပြန်လည်ချိတ်ဆက်မှု", "red_dark_theme": "အနီရောင်မှောင်မိုက်ဆောင်ပုဒ်", "red_light_theme": "အနီရောင်အလင်းအကြောင်းအရာ", diff --git a/res/values/strings_nl.arb b/res/values/strings_nl.arb index ba20bb26a..d4f81e00f 100644 --- a/res/values/strings_nl.arb +++ b/res/values/strings_nl.arb @@ -355,6 +355,7 @@ "how_to_use": "Hoe te gebruiken", "how_to_use_card": "Hoe deze kaart te gebruiken", "id": "ID: ", + "if_you_dont_see_your_device": "Als u uw apparaat hierboven niet ziet, zorg er dan voor dat uw grootboek wakker is en ontgrendeld is!", "ignor": "Negeren", "import": "Importeren", "importNFTs": "NFT's importeren", @@ -538,6 +539,7 @@ "recipient_address": "Adres ontvanger", "reconnect": "Sluit", "reconnect_alert_text": "Weet u zeker dat u opnieuw verbinding wilt maken?", + "reconnect_your_hardware_wallet": "Sluit uw hardware -portemonnee opnieuw aan", "reconnection": "Reconnection", "red_dark_theme": "Rood donker thema", "red_light_theme": "Rood licht thema", diff --git a/res/values/strings_pl.arb b/res/values/strings_pl.arb index d50def305..aa2832a0e 100644 --- a/res/values/strings_pl.arb +++ b/res/values/strings_pl.arb @@ -355,6 +355,7 @@ "how_to_use": "Jak używać", "how_to_use_card": "Jak korzystać z tej karty?", "id": "ID: ", + "if_you_dont_see_your_device": "Jeśli nie widzisz swojego urządzenia powyżej, upewnij się, że Twoja księga nie śpi i odblokowana!", "ignor": "Ignorować", "import": "Import", "importNFTs": "Importuj NFT", @@ -538,6 +539,7 @@ "recipient_address": "Adres odbiorcy", "reconnect": "Połącz ponownie", "reconnect_alert_text": "Czy na pewno ponownie się ponownie połączysz?", + "reconnect_your_hardware_wallet": "Ponownie podłącz portfel sprzętowy", "reconnection": "Ponowne łączenie", "red_dark_theme": "Czerwony Mroczny motyw", "red_light_theme": "Motyw czerwony światło", diff --git a/res/values/strings_pt.arb b/res/values/strings_pt.arb index 7ff9fdc4e..929187ff3 100644 --- a/res/values/strings_pt.arb +++ b/res/values/strings_pt.arb @@ -355,6 +355,7 @@ "how_to_use": "Como usar", "how_to_use_card": "Como usar este cartão", "id": "ID: ", + "if_you_dont_see_your_device": "Se você não vê seu dispositivo acima, certifique -se de que seu livro esteja acordado e desbloqueado!", "ignor": "Ignorar", "import": "Importar", "importNFTs": "Importar NFTs", @@ -540,6 +541,7 @@ "recipient_address": "Endereço do destinatário", "reconnect": "Reconectar", "reconnect_alert_text": "Você tem certeza de que deseja reconectar?", + "reconnect_your_hardware_wallet": "Reconecte sua carteira de hardware", "reconnection": "Reconectar", "red_dark_theme": "Tema escuro vermelho", "red_light_theme": "Tema da luz vermelha", diff --git a/res/values/strings_ru.arb b/res/values/strings_ru.arb index b1d6c2461..459d3a843 100644 --- a/res/values/strings_ru.arb +++ b/res/values/strings_ru.arb @@ -355,6 +355,7 @@ "how_to_use": "Как использовать", "how_to_use_card": "Как использовать эту карту", "id": "ID: ", + "if_you_dont_see_your_device": "Если вы не видите свое устройство выше, пожалуйста, убедитесь, что ваша бухгалтерская книга бодрствует и разблокирована!", "ignor": "Игнорировать", "import": "Импортировать", "importNFTs": "Импортировать NFT", @@ -539,6 +540,7 @@ "recipient_address": "Адрес получателя", "reconnect": "Переподключиться", "reconnect_alert_text": "Вы хотите переподключиться?", + "reconnect_your_hardware_wallet": "Воссоедините свой аппаратный кошелек", "reconnection": "Переподключение", "red_dark_theme": "Красная темная тема", "red_light_theme": "Тема красного света", diff --git a/res/values/strings_th.arb b/res/values/strings_th.arb index b5587073b..12fef4d1c 100644 --- a/res/values/strings_th.arb +++ b/res/values/strings_th.arb @@ -355,6 +355,7 @@ "how_to_use": "วิธีใช้", "how_to_use_card": "วิธีใช้บัตรนี้", "id": "ID: ", + "if_you_dont_see_your_device": "หากคุณไม่เห็นอุปกรณ์ของคุณด้านบนโปรดตรวจสอบให้แน่ใจว่าบัญชีแยกประเภทของคุณตื่นและปลดล็อค!", "ignor": "ละเว้น", "import": "นำเข้า", "importNFTs": "นำเข้า NFT", @@ -538,6 +539,7 @@ "recipient_address": "ที่อยู่ผู้รับ", "reconnect": "เชื่อมต่อใหม่", "reconnect_alert_text": "คุณแน่ใจหรือไม่ว่าต้องการเชื่อมต่อใหม่?", + "reconnect_your_hardware_wallet": "เชื่อมต่อกระเป๋าเงินฮาร์ดแวร์ของคุณอีกครั้ง", "reconnection": "เชื่อมต่อใหม่", "red_dark_theme": "ธีมสีแดงเข้ม", "red_light_theme": "ธีมแสงสีแดง", diff --git a/res/values/strings_tl.arb b/res/values/strings_tl.arb index 774887859..1a9e17ad9 100644 --- a/res/values/strings_tl.arb +++ b/res/values/strings_tl.arb @@ -355,6 +355,7 @@ "how_to_use": "Paano gamitin", "how_to_use_card": "Paano gamitin ang card na ito", "id": "ID: ", + "if_you_dont_see_your_device": "Kung hindi mo nakikita ang iyong aparato sa itaas, siguraduhin na ang iyong ledger ay gising at naka -lock!", "ignor": "Huwag pansinin", "import": "Mag-import", "importNFTs": "Mag-import ng mga NFT", @@ -538,6 +539,7 @@ "recipient_address": "Address ng tatanggap", "reconnect": "Kumonekta muli", "reconnect_alert_text": "Sigurado ka bang gusto mong kumonekta uli?", + "reconnect_your_hardware_wallet": "Ikonekta muli ang iyong wallet ng hardware", "reconnection": "Muling pagkakakonekta", "red_dark_theme": "Red Dark Theme", "red_light_theme": "Red Light Theme", diff --git a/res/values/strings_tr.arb b/res/values/strings_tr.arb index 83d766347..b0341b6e0 100644 --- a/res/values/strings_tr.arb +++ b/res/values/strings_tr.arb @@ -355,6 +355,7 @@ "how_to_use": "Nasıl kullanılır", "how_to_use_card": "Bu kart nasıl kullanılır", "id": "ID: ", + "if_you_dont_see_your_device": "Cihazınızı yukarıda görmüyorsanız, lütfen defterinizin uyanık olduğundan ve kilidinin açıldığından emin olun!", "ignor": "Yoksay", "import": "İçe aktarmak", "importNFTs": "NFT'leri içe aktar", @@ -538,6 +539,7 @@ "recipient_address": "Alıcı adresi", "reconnect": "Yeniden Bağlan", "reconnect_alert_text": "Yeniden bağlanmak istediğinden emin misin?", + "reconnect_your_hardware_wallet": "Donanım cüzdanınızı yeniden bağlayın", "reconnection": "Yeniden bağlantı", "red_dark_theme": "Kırmızı Karanlık Tema", "red_light_theme": "Kırmızı Işık Teması", diff --git a/res/values/strings_uk.arb b/res/values/strings_uk.arb index fd69c6cbf..aa4aa7d5e 100644 --- a/res/values/strings_uk.arb +++ b/res/values/strings_uk.arb @@ -355,6 +355,7 @@ "how_to_use": "Як використовувати", "how_to_use_card": "Як використовувати цю картку", "id": "ID: ", + "if_you_dont_see_your_device": "Якщо ви не бачите свого пристрою вище, будь ласка, переконайтеся, що ваша книга прокинеться і розблокована!", "ignor": "Ігнорувати", "import": "Імпорт", "importNFTs": "Імпорт NFT", @@ -538,6 +539,7 @@ "recipient_address": "Адреса одержувача", "reconnect": "Перепідключитися", "reconnect_alert_text": "Ви хочете перепідключитися?", + "reconnect_your_hardware_wallet": "Повторно підключіть свій апаратний гаманець", "reconnection": "Перепідключення", "red_dark_theme": "Червона темна тема", "red_light_theme": "Тема червоного світла", diff --git a/res/values/strings_ur.arb b/res/values/strings_ur.arb index e4e8d8aee..2beef4559 100644 --- a/res/values/strings_ur.arb +++ b/res/values/strings_ur.arb @@ -355,6 +355,7 @@ "how_to_use": " ﮧﻘﯾﺮﻃ ﺎﮐ ﮯﻧﺮﮐ ﻝﺎﻤﻌﺘﺳﺍ", "how_to_use_card": "اس کارڈ کو استعمال کرنے کا طریقہ", "id": "ID:", + "if_you_dont_see_your_device": "اگر آپ اوپر اپنا آلہ نہیں دیکھتے ہیں تو ، براہ کرم یقینی بنائیں کہ آپ کا لیجر بیدار اور غیر مقفل ہے!", "ignor": "نظر انداز کرنا", "import": " ۔ﮟﯾﺮﮐ ﺪﻣﺁﺭﺩ", "importNFTs": "NFTs ۔ﮟﯾﺮﮐ ﺪﻣﺁﺭﺩ", @@ -540,6 +541,7 @@ "recipient_address": "وصول کنندہ کا پتہ", "reconnect": "دوبارہ جڑیں۔", "reconnect_alert_text": "کیا آپ واقعی دوبارہ جڑنا چاہتے ہیں؟", + "reconnect_your_hardware_wallet": "اپنے ہارڈ ویئر پرس کو دوبارہ مربوط کریں", "reconnection": "دوبارہ رابطہ", "red_dark_theme": "ریڈ ڈارک تھیم", "red_light_theme": "ریڈ لائٹ تھیم", diff --git a/res/values/strings_vi.arb b/res/values/strings_vi.arb index f74078746..8ea1d1672 100644 --- a/res/values/strings_vi.arb +++ b/res/values/strings_vi.arb @@ -354,6 +354,7 @@ "how_to_use": "Cách sử dụng", "how_to_use_card": "Cách sử dụng thẻ này", "id": "ID: ", + "if_you_dont_see_your_device": "Nếu bạn không thấy thiết bị của mình ở trên, xin hãy chắc chắn rằng sổ cái của bạn đã tỉnh táo và mở khóa!", "ignor": "Bỏ qua", "import": "Nhập", "importNFTs": "Nhập NFT", @@ -537,6 +538,7 @@ "recipient_address": "Địa chỉ người nhận", "reconnect": "Kết nối lại", "reconnect_alert_text": "Bạn có chắc chắn muốn kết nối lại không?", + "reconnect_your_hardware_wallet": "Kết nối lại ví phần cứng của bạn", "reconnection": "Kết nối lại", "red_dark_theme": "Chủ đề tối đỏ", "red_light_theme": "Chủ đề sáng đỏ", diff --git a/res/values/strings_yo.arb b/res/values/strings_yo.arb index 14f0e5cf6..5b7e9048e 100644 --- a/res/values/strings_yo.arb +++ b/res/values/strings_yo.arb @@ -356,6 +356,7 @@ "how_to_use": "Bawo ni lati lo", "how_to_use_card": "Báyìí ni wọ́n ṣe ń lo káàdì yìí.", "id": "Àmì Ìdánimọ̀: ", + "if_you_dont_see_your_device": "Ti o ko ba ri ẹrọ rẹ loke, jọwọ rii daju pe a le jiji rẹ ati ṣiṣi!", "ignor": "Ṣàìfiyèsí", "import": "gbe wọle", "importNFTs": "Gbe awọn NFT wọle", @@ -539,6 +540,7 @@ "recipient_address": "Àdírẹ́sì olùgbà", "reconnect": "Ṣe àtúnse", "reconnect_alert_text": "Ṣó dá ẹ lójú pé ẹ fẹ́ ṣe àtúnse?", + "reconnect_your_hardware_wallet": "Ṣe atunṣe apamọwọ ohun elo rẹ", "reconnection": "Àtúnṣe", "red_dark_theme": "Akọle dudu pupa", "red_light_theme": "Akori ina pupa", diff --git a/res/values/strings_zh.arb b/res/values/strings_zh.arb index 8d9828c6a..0ccd89271 100644 --- a/res/values/strings_zh.arb +++ b/res/values/strings_zh.arb @@ -355,6 +355,7 @@ "how_to_use": "如何使用", "how_to_use_card": "如何使用这张卡", "id": "ID: ", + "if_you_dont_see_your_device": "如果您在上面看不到设备,请确保您的分类帐已经清醒并解锁!", "ignor": "忽视", "import": "进口", "importNFTs": "导入 NFT", @@ -538,6 +539,7 @@ "recipient_address": "收件人地址", "reconnect": "重新连接", "reconnect_alert_text": "您确定要重新连接吗?", + "reconnect_your_hardware_wallet": "重新连接您的硬件钱包", "reconnection": "重新连接", "red_dark_theme": "红色的黑暗主题", "red_light_theme": "红灯主题",