mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-05-03 15:12:14 +00:00
CW-229 Improved restore options from QR code (#793)
* add restoring wallet from qr * add restore mode * add alert for exceptions * add restore from seed * add check for create wallet state * convert sweeping page into stateful * fix parsing url * restoration flow update * update restoring from key mode * update config * fix restor of BTC and LTC wallets * fix pin code issue * wallet Seed/keys uri or code fix * fix key restore credentials * update the restore workflow * update from main * PR coments fixes * update * update * PR fixes
This commit is contained in:
parent
f2b8dd21a1
commit
1eb8d0c698
38 changed files with 698 additions and 51 deletions
13
lib/di.dart
13
lib/di.dart
|
@ -53,6 +53,8 @@ import 'package:cake_wallet/src/screens/dashboard/widgets/balance_page.dart';
|
||||||
import 'package:cake_wallet/view_model/ionia/ionia_account_view_model.dart';
|
import 'package:cake_wallet/view_model/ionia/ionia_account_view_model.dart';
|
||||||
import 'package:cake_wallet/view_model/ionia/ionia_gift_cards_list_view_model.dart';
|
import 'package:cake_wallet/view_model/ionia/ionia_gift_cards_list_view_model.dart';
|
||||||
import 'package:cake_wallet/view_model/ionia/ionia_purchase_merch_view_model.dart';
|
import 'package:cake_wallet/view_model/ionia/ionia_purchase_merch_view_model.dart';
|
||||||
|
import 'package:cake_wallet/view_model/restore/restore_from_qr_vm.dart';
|
||||||
|
import 'package:cake_wallet/view_model/restore/restore_wallet.dart';
|
||||||
import 'package:cake_wallet/view_model/settings/display_settings_view_model.dart';
|
import 'package:cake_wallet/view_model/settings/display_settings_view_model.dart';
|
||||||
import 'package:cake_wallet/view_model/settings/other_settings_view_model.dart';
|
import 'package:cake_wallet/view_model/settings/other_settings_view_model.dart';
|
||||||
import 'package:cake_wallet/view_model/settings/privacy_settings_view_model.dart';
|
import 'package:cake_wallet/view_model/settings/privacy_settings_view_model.dart';
|
||||||
|
@ -320,6 +322,13 @@ Future setup(
|
||||||
type: type, language: language);
|
type: type, language: language);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
getIt
|
||||||
|
.registerFactoryParam<WalletRestorationFromQRVM, WalletType, void>((WalletType type, _) {
|
||||||
|
return WalletRestorationFromQRVM(getIt.get<AppStore>(),
|
||||||
|
getIt.get<WalletCreationService>(param1: type),
|
||||||
|
_walletInfoSource, type);
|
||||||
|
});
|
||||||
|
|
||||||
getIt.registerFactory<WalletAddressListViewModel>(() =>
|
getIt.registerFactory<WalletAddressListViewModel>(() =>
|
||||||
WalletAddressListViewModel(
|
WalletAddressListViewModel(
|
||||||
appStore: getIt.get<AppStore>(), yatStore: getIt.get<YatStore>(),
|
appStore: getIt.get<AppStore>(), yatStore: getIt.get<YatStore>(),
|
||||||
|
@ -743,7 +752,9 @@ Future setup(
|
||||||
getIt.registerFactory(
|
getIt.registerFactory(
|
||||||
() => EditBackupPasswordPage(getIt.get<EditBackupPasswordViewModel>()));
|
() => EditBackupPasswordPage(getIt.get<EditBackupPasswordViewModel>()));
|
||||||
|
|
||||||
getIt.registerFactory(() => RestoreOptionsPage());
|
getIt.registerFactoryParam<RestoreOptionsPage, bool, void>((bool isNewInstall, _) =>
|
||||||
|
RestoreOptionsPage(isNewInstall: isNewInstall));
|
||||||
|
|
||||||
|
|
||||||
getIt.registerFactory(
|
getIt.registerFactory(
|
||||||
() => RestoreFromBackupViewModel(getIt.get<BackupService>()));
|
() => RestoreFromBackupViewModel(getIt.get<BackupService>()));
|
||||||
|
|
|
@ -33,7 +33,7 @@ class AddressResolver {
|
||||||
final addressPattern = AddressValidator.getAddressFromStringPattern(type);
|
final addressPattern = AddressValidator.getAddressFromStringPattern(type);
|
||||||
|
|
||||||
if (addressPattern == null) {
|
if (addressPattern == null) {
|
||||||
throw 'Unexpected token: $type for getAddressFromStringPattern';
|
throw Exception('Unexpected token: $type for getAddressFromStringPattern');
|
||||||
}
|
}
|
||||||
|
|
||||||
final match = RegExp(addressPattern).firstMatch(raw);
|
final match = RegExp(addressPattern).firstMatch(raw);
|
||||||
|
|
|
@ -10,6 +10,7 @@ import 'package:cake_wallet/src/screens/buy/buy_webview_page.dart';
|
||||||
import 'package:cake_wallet/src/screens/buy/onramper_page.dart';
|
import 'package:cake_wallet/src/screens/buy/onramper_page.dart';
|
||||||
import 'package:cake_wallet/src/screens/buy/payfura_page.dart';
|
import 'package:cake_wallet/src/screens/buy/payfura_page.dart';
|
||||||
import 'package:cake_wallet/src/screens/buy/pre_order_page.dart';
|
import 'package:cake_wallet/src/screens/buy/pre_order_page.dart';
|
||||||
|
import 'package:cake_wallet/src/screens/restore/sweeping_wallet_page.dart';
|
||||||
import 'package:cake_wallet/src/screens/receive/anonpay_invoice_page.dart';
|
import 'package:cake_wallet/src/screens/receive/anonpay_invoice_page.dart';
|
||||||
import 'package:cake_wallet/src/screens/receive/anonpay_receive_page.dart';
|
import 'package:cake_wallet/src/screens/receive/anonpay_receive_page.dart';
|
||||||
import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_dashboard_actions.dart';
|
import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_dashboard_actions.dart';
|
||||||
|
@ -40,6 +41,8 @@ import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
|
||||||
import 'package:cake_wallet/view_model/monero_account_list/account_list_item.dart';
|
import 'package:cake_wallet/view_model/monero_account_list/account_list_item.dart';
|
||||||
import 'package:cake_wallet/view_model/node_list/node_create_or_edit_view_model.dart';
|
import 'package:cake_wallet/view_model/node_list/node_create_or_edit_view_model.dart';
|
||||||
import 'package:cake_wallet/view_model/advanced_privacy_settings_view_model.dart';
|
import 'package:cake_wallet/view_model/advanced_privacy_settings_view_model.dart';
|
||||||
|
import 'package:cake_wallet/view_model/restore/restore_from_qr_vm.dart';
|
||||||
|
import 'package:cake_wallet/view_model/restore/restore_wallet.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:cake_wallet/routes.dart';
|
import 'package:cake_wallet/routes.dart';
|
||||||
|
@ -158,8 +161,9 @@ Route<dynamic> createRoute(RouteSettings settings) {
|
||||||
param2: false));
|
param2: false));
|
||||||
|
|
||||||
case Routes.restoreOptions:
|
case Routes.restoreOptions:
|
||||||
|
final isNewInstall = settings.arguments as bool;
|
||||||
return CupertinoPageRoute<void>(
|
return CupertinoPageRoute<void>(
|
||||||
builder: (_) => getIt.get<RestoreOptionsPage>());
|
builder: (_) => getIt.get<RestoreOptionsPage>(param1: isNewInstall));
|
||||||
|
|
||||||
case Routes.restoreWalletOptions:
|
case Routes.restoreWalletOptions:
|
||||||
final type = WalletType.monero; //settings.arguments as WalletType;
|
final type = WalletType.monero; //settings.arguments as WalletType;
|
||||||
|
@ -189,12 +193,18 @@ Route<dynamic> createRoute(RouteSettings settings) {
|
||||||
}));
|
}));
|
||||||
|
|
||||||
case Routes.restoreWalletOptionsFromWelcome:
|
case Routes.restoreWalletOptionsFromWelcome:
|
||||||
return CupertinoPageRoute<void>(
|
final isNewInstall = settings.arguments as bool;
|
||||||
|
return isNewInstall ? CupertinoPageRoute<void>(
|
||||||
builder: (_) => getIt.get<SetupPinCodePage>(
|
builder: (_) => getIt.get<SetupPinCodePage>(
|
||||||
param1: (PinCodeState<PinCodeWidget> context, dynamic _) =>
|
param1: (PinCodeState<PinCodeWidget> context, dynamic _) =>
|
||||||
Navigator.pushNamed(
|
Navigator.pushNamed(
|
||||||
context.context, Routes.restoreWalletType)),
|
context.context, Routes.restoreWalletType)),
|
||||||
fullscreenDialog: true);
|
fullscreenDialog: true) : CupertinoPageRoute<void>(
|
||||||
|
builder: (_) => getIt.get<NewWalletTypePage>(
|
||||||
|
param1: (BuildContext context, WalletType type) =>
|
||||||
|
Navigator.of(context)
|
||||||
|
.pushNamed(Routes.restoreWallet, arguments: type),
|
||||||
|
param2: false));
|
||||||
|
|
||||||
case Routes.seed:
|
case Routes.seed:
|
||||||
return MaterialPageRoute<void>(
|
return MaterialPageRoute<void>(
|
||||||
|
@ -224,6 +234,10 @@ Route<dynamic> createRoute(RouteSettings settings) {
|
||||||
builder: (_) => RestoreWalletFromKeysPage(
|
builder: (_) => RestoreWalletFromKeysPage(
|
||||||
walletRestorationFromKeysVM: walletRestorationFromKeysVM));
|
walletRestorationFromKeysVM: walletRestorationFromKeysVM));
|
||||||
|
|
||||||
|
case Routes.sweepingWalletPage:
|
||||||
|
return CupertinoPageRoute<void>(
|
||||||
|
builder: (_) => getIt.get<SweepingWalletPage>());
|
||||||
|
|
||||||
case Routes.dashboard:
|
case Routes.dashboard:
|
||||||
return CupertinoPageRoute<void>(
|
return CupertinoPageRoute<void>(
|
||||||
builder: (_) => getIt.get<DashboardPage>());
|
builder: (_) => getIt.get<DashboardPage>());
|
||||||
|
|
|
@ -84,6 +84,7 @@ class Routes {
|
||||||
static const displaySettingsPage = '/display_settings_page';
|
static const displaySettingsPage = '/display_settings_page';
|
||||||
static const otherSettingsPage = '/other_settings_page';
|
static const otherSettingsPage = '/other_settings_page';
|
||||||
static const advancedPrivacySettings = '/advanced_privacy_settings';
|
static const advancedPrivacySettings = '/advanced_privacy_settings';
|
||||||
|
static const sweepingWalletPage = '/sweeping_wallet_page';
|
||||||
static const anonPayInvoicePage = '/anon_pay_invoice_page';
|
static const anonPayInvoicePage = '/anon_pay_invoice_page';
|
||||||
static const anonPayReceivePage = '/anon_pay_receive_page';
|
static const anonPayReceivePage = '/anon_pay_receive_page';
|
||||||
static const anonPayDetailsPage = '/anon_pay_details_page';
|
static const anonPayDetailsPage = '/anon_pay_details_page';
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
import 'package:cake_wallet/core/execution_state.dart';
|
||||||
|
import 'package:cake_wallet/di.dart';
|
||||||
|
import 'package:cake_wallet/src/screens/pin_code/pin_code_widget.dart';
|
||||||
|
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
|
||||||
|
import 'package:cake_wallet/utils/language_list.dart';
|
||||||
|
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||||
|
import 'package:cake_wallet/view_model/restore/restore_from_qr_vm.dart';
|
||||||
|
import 'package:cake_wallet/view_model/restore/wallet_restore_from_qr_code.dart';
|
||||||
import 'package:cake_wallet/utils/responsive_layout_util.dart';
|
import 'package:cake_wallet/utils/responsive_layout_util.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:cake_wallet/routes.dart';
|
import 'package:cake_wallet/routes.dart';
|
||||||
|
@ -7,15 +15,16 @@ import 'package:cake_wallet/src/screens/base_page.dart';
|
||||||
import 'package:cake_wallet/generated/i18n.dart';
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
|
|
||||||
class RestoreOptionsPage extends BasePage {
|
class RestoreOptionsPage extends BasePage {
|
||||||
RestoreOptionsPage();
|
RestoreOptionsPage({required this.isNewInstall});
|
||||||
|
|
||||||
static const _aspectRatioImage = 2.086;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get title => S.current.restore_restore_wallet;
|
String get title => S.current.restore_restore_wallet;
|
||||||
|
|
||||||
|
|
||||||
|
final bool isNewInstall;
|
||||||
final imageSeedKeys = Image.asset('assets/images/restore_wallet_image.png');
|
final imageSeedKeys = Image.asset('assets/images/restore_wallet_image.png');
|
||||||
final imageBackup = Image.asset('assets/images/backup.png');
|
final imageBackup = Image.asset('assets/images/backup.png');
|
||||||
|
final qrCode = Image.asset('assets/images/qr_code_icon.png');
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget body(BuildContext context) {
|
Widget body(BuildContext context) {
|
||||||
|
@ -28,24 +37,69 @@ class RestoreOptionsPage extends BasePage {
|
||||||
child: Column(
|
child: Column(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
RestoreButton(
|
RestoreButton(
|
||||||
onPressed: () =>
|
onPressed: () => Navigator.pushNamed(
|
||||||
Navigator.pushNamed(context, Routes.restoreWalletOptionsFromWelcome),
|
context, Routes.restoreWalletOptionsFromWelcome,
|
||||||
|
arguments: isNewInstall),
|
||||||
image: imageSeedKeys,
|
image: imageSeedKeys,
|
||||||
title: S.of(context).restore_title_from_seed_keys,
|
title: S.of(context).restore_title_from_seed_keys,
|
||||||
description:
|
description: S.of(context).restore_description_from_seed_keys),
|
||||||
S.of(context).restore_description_from_seed_keys),
|
if (isNewInstall)
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(top: 24),
|
||||||
|
child: RestoreButton(
|
||||||
|
onPressed: () => Navigator.pushNamed(context, Routes.restoreFromBackup),
|
||||||
|
image: imageBackup,
|
||||||
|
title: S.of(context).restore_title_from_backup,
|
||||||
|
description: S.of(context).restore_description_from_backup),
|
||||||
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.only(top: 24),
|
padding: EdgeInsets.only(top: 24),
|
||||||
child: RestoreButton(
|
child: RestoreButton(
|
||||||
onPressed: () =>
|
onPressed: () async {
|
||||||
Navigator.pushNamed(context, Routes.restoreFromBackup),
|
bool isPinSet = false;
|
||||||
image: imageBackup,
|
if (isNewInstall) {
|
||||||
title: S.of(context).restore_title_from_backup,
|
await Navigator.pushNamed(context, Routes.setupPin,
|
||||||
description: S.of(context).restore_description_from_backup),
|
arguments: (PinCodeState<PinCodeWidget> setupPinContext, String _) {
|
||||||
|
setupPinContext.close();
|
||||||
|
isPinSet = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (!isNewInstall || isPinSet) {
|
||||||
|
try {
|
||||||
|
final restoreWallet =
|
||||||
|
await WalletRestoreFromQRCode.scanQRCodeForRestoring(context);
|
||||||
|
|
||||||
|
final restoreFromQRViewModel = getIt.get<WalletRestorationFromQRVM>(param1: restoreWallet.type);
|
||||||
|
|
||||||
|
await restoreFromQRViewModel.create(restoreWallet: restoreWallet);
|
||||||
|
if (restoreFromQRViewModel.state is FailureState) {
|
||||||
|
_onWalletCreateFailure(context,
|
||||||
|
'Create wallet state: ${restoreFromQRViewModel.state.runtimeType.toString()}');
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
_onWalletCreateFailure(context, e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
image: qrCode,
|
||||||
|
title: S.of(context).scan_qr_code,
|
||||||
|
description: S.of(context).cold_or_recover_wallet),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
)),
|
)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _onWalletCreateFailure(BuildContext context, String error) {
|
||||||
|
showPopUp<void>(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return AlertWithOneAction(
|
||||||
|
alertTitle: S.current.error,
|
||||||
|
alertContent: error,
|
||||||
|
buttonText: S.of(context).ok,
|
||||||
|
buttonAction: () => Navigator.of(context).pop());
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
123
lib/src/screens/restore/sweeping_wallet_page.dart
Normal file
123
lib/src/screens/restore/sweeping_wallet_page.dart
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
import 'package:cake_wallet/themes/theme_base.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||||
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
|
import 'package:flutter/scheduler.dart';
|
||||||
|
|
||||||
|
class SweepingWalletPage extends BasePage {
|
||||||
|
SweepingWalletPage();
|
||||||
|
|
||||||
|
static const aspectRatioImage = 1.25;
|
||||||
|
final welcomeImageLight = Image.asset('assets/images/welcome_light.png');
|
||||||
|
final welcomeImageDark = Image.asset('assets/images/welcome.png');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: Theme.of(context).backgroundColor,
|
||||||
|
resizeToAvoidBottomInset: false,
|
||||||
|
body: body(context));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget body(BuildContext context) {
|
||||||
|
final welcomeImage = currentTheme.type == ThemeType.dark ? welcomeImageDark : welcomeImageLight;
|
||||||
|
|
||||||
|
return SweepingWalletWidget(
|
||||||
|
aspectRatioImage: aspectRatioImage,
|
||||||
|
welcomeImage: welcomeImage,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SweepingWalletWidget extends StatefulWidget {
|
||||||
|
const SweepingWalletWidget({
|
||||||
|
required this.aspectRatioImage,
|
||||||
|
required this.welcomeImage,
|
||||||
|
});
|
||||||
|
|
||||||
|
final double aspectRatioImage;
|
||||||
|
final Image welcomeImage;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<SweepingWalletWidget> createState() => _SweepingWalletWidgetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _SweepingWalletWidgetState extends State<SweepingWalletWidget> {
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
SchedulerBinding.instance.addPostFrameCallback((_) async {
|
||||||
|
|
||||||
|
});
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return WillPopScope(
|
||||||
|
onWillPop: () async => false,
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.only(top: 64, bottom: 24, left: 24, right: 24),
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: <Widget>[
|
||||||
|
Flexible(
|
||||||
|
flex: 2,
|
||||||
|
child: AspectRatio(
|
||||||
|
aspectRatio: widget.aspectRatioImage,
|
||||||
|
child: FittedBox(child: widget.welcomeImage, fit: BoxFit.fill))),
|
||||||
|
Flexible(
|
||||||
|
flex: 3,
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: <Widget>[
|
||||||
|
Column(
|
||||||
|
children: <Widget>[
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(top: 24),
|
||||||
|
child: Text(
|
||||||
|
S.of(context).please_wait,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
color: Theme.of(context).accentTextTheme!.headline2!.color!,
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(top: 5),
|
||||||
|
child: Text(
|
||||||
|
S.of(context).sweeping_wallet,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 36,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: Theme.of(context).primaryTextTheme!.headline6!.color!,
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(top: 5),
|
||||||
|
child: Text(
|
||||||
|
S.of(context).sweeping_wallet_alert,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
color: Theme.of(context).accentTextTheme!.headline2!.color!,
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
))
|
||||||
|
],
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ import 'package:cake_wallet/core/validator.dart';
|
||||||
import 'package:cake_wallet/generated/i18n.dart';
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
|
import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
|
||||||
import 'package:cake_wallet/core/seed_validator.dart';
|
import 'package:cake_wallet/core/seed_validator.dart';
|
||||||
|
import 'package:cake_wallet/view_model/restore/restore_mode.dart';
|
||||||
|
|
||||||
class WalletRestorePage extends BasePage {
|
class WalletRestorePage extends BasePage {
|
||||||
WalletRestorePage(this.walletRestoreViewModel)
|
WalletRestorePage(this.walletRestoreViewModel)
|
||||||
|
|
|
@ -178,7 +178,7 @@ class WalletListBodyState extends State<WalletListBody> {
|
||||||
Navigator.of(context).pushNamed(Routes.restoreWallet,
|
Navigator.of(context).pushNamed(Routes.restoreWallet,
|
||||||
arguments: widget.walletListViewModel.currentWalletType);
|
arguments: widget.walletListViewModel.currentWalletType);
|
||||||
} else {
|
} else {
|
||||||
Navigator.of(context).pushNamed(Routes.restoreWalletType);
|
Navigator.of(context).pushNamed(Routes.restoreOptions, arguments: false);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
image: restoreWalletImage,
|
image: restoreWalletImage,
|
||||||
|
|
|
@ -148,7 +148,8 @@ class WelcomePage extends BasePage {
|
||||||
padding: EdgeInsets.only(top: 10),
|
padding: EdgeInsets.only(top: 10),
|
||||||
child: PrimaryImageButton(
|
child: PrimaryImageButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.pushNamed(context, Routes.restoreOptions);
|
Navigator.pushNamed(context, Routes.restoreOptions,
|
||||||
|
arguments: true);
|
||||||
},
|
},
|
||||||
image: restoreWalletImage,
|
image: restoreWalletImage,
|
||||||
text: S.of(context).restore_wallet,
|
text: S.of(context).restore_wallet,
|
||||||
|
|
106
lib/view_model/restore/restore_from_qr_vm.dart
Normal file
106
lib/view_model/restore/restore_from_qr_vm.dart
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
import 'package:cake_wallet/bitcoin/bitcoin.dart';
|
||||||
|
import 'package:cake_wallet/view_model/restore/restore_mode.dart';
|
||||||
|
import 'package:cake_wallet/view_model/restore/restore_wallet.dart';
|
||||||
|
import 'package:hive/hive.dart';
|
||||||
|
import 'package:mobx/mobx.dart';
|
||||||
|
import 'package:cake_wallet/monero/monero.dart';
|
||||||
|
import 'package:cake_wallet/store/app_store.dart';
|
||||||
|
import 'package:cw_core/wallet_base.dart';
|
||||||
|
import 'package:cake_wallet/core/generate_wallet_password.dart';
|
||||||
|
import 'package:cake_wallet/core/wallet_creation_service.dart';
|
||||||
|
import 'package:cw_core/wallet_credentials.dart';
|
||||||
|
import 'package:cw_core/wallet_type.dart';
|
||||||
|
import 'package:cake_wallet/view_model/wallet_creation_vm.dart';
|
||||||
|
import 'package:cw_core/wallet_info.dart';
|
||||||
|
|
||||||
|
part 'restore_from_qr_vm.g.dart';
|
||||||
|
|
||||||
|
class WalletRestorationFromQRVM = WalletRestorationFromQRVMBase with _$WalletRestorationFromQRVM;
|
||||||
|
|
||||||
|
abstract class WalletRestorationFromQRVMBase extends WalletCreationVM with Store {
|
||||||
|
WalletRestorationFromQRVMBase(AppStore appStore, WalletCreationService walletCreationService,
|
||||||
|
Box<WalletInfo> walletInfoSource, WalletType type)
|
||||||
|
: height = 0,
|
||||||
|
viewKey = '',
|
||||||
|
spendKey = '',
|
||||||
|
wif = '',
|
||||||
|
address = '',
|
||||||
|
super(appStore, walletInfoSource, walletCreationService,
|
||||||
|
type: type, isRecovery: true);
|
||||||
|
|
||||||
|
@observable
|
||||||
|
int height;
|
||||||
|
|
||||||
|
@observable
|
||||||
|
String viewKey;
|
||||||
|
|
||||||
|
@observable
|
||||||
|
String spendKey;
|
||||||
|
|
||||||
|
@observable
|
||||||
|
String wif;
|
||||||
|
|
||||||
|
@observable
|
||||||
|
String address;
|
||||||
|
|
||||||
|
bool get hasRestorationHeight => type == WalletType.monero;
|
||||||
|
|
||||||
|
@override
|
||||||
|
WalletCredentials getCredentialsFromRestoredWallet(dynamic options, RestoredWallet restoreWallet) {
|
||||||
|
final password = generateWalletPassword();
|
||||||
|
|
||||||
|
switch (restoreWallet.restoreMode) {
|
||||||
|
case WalletRestoreMode.keys:
|
||||||
|
switch (restoreWallet.type) {
|
||||||
|
case WalletType.monero:
|
||||||
|
return monero!.createMoneroRestoreWalletFromKeysCredentials(
|
||||||
|
name: name,
|
||||||
|
password: password,
|
||||||
|
language: 'English',
|
||||||
|
address: restoreWallet.address ?? '',
|
||||||
|
viewKey: restoreWallet.viewKey ?? '',
|
||||||
|
spendKey: restoreWallet.spendKey ?? '',
|
||||||
|
height: restoreWallet.height ?? 0);
|
||||||
|
case WalletType.bitcoin:
|
||||||
|
case WalletType.litecoin:
|
||||||
|
return bitcoin!.createBitcoinRestoreWalletFromWIFCredentials(
|
||||||
|
name: name, password: password, wif: wif);
|
||||||
|
default:
|
||||||
|
throw Exception('Unexpected type: ${restoreWallet.type.toString()}');
|
||||||
|
}
|
||||||
|
case WalletRestoreMode.seed:
|
||||||
|
switch (restoreWallet.type) {
|
||||||
|
case WalletType.monero:
|
||||||
|
return monero!.createMoneroRestoreWalletFromSeedCredentials(
|
||||||
|
name: name,
|
||||||
|
height: restoreWallet.height ?? 0,
|
||||||
|
mnemonic: restoreWallet.mnemonicSeed ?? '',
|
||||||
|
password: password);
|
||||||
|
case WalletType.bitcoin:
|
||||||
|
case WalletType.litecoin:
|
||||||
|
return bitcoin!.createBitcoinRestoreWalletFromSeedCredentials(
|
||||||
|
name: name, mnemonic: restoreWallet.mnemonicSeed ?? '', password: password);
|
||||||
|
default:
|
||||||
|
throw Exception('Unexpected type: ${type.toString()}');
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw Exception('Unexpected type: ${type.toString()}');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<WalletBase> processFromRestoredWallet(WalletCredentials credentials, RestoredWallet restoreWallet) async {
|
||||||
|
try {
|
||||||
|
switch (restoreWallet.restoreMode) {
|
||||||
|
case WalletRestoreMode.keys:
|
||||||
|
return walletCreationService.restoreFromKeys(credentials);
|
||||||
|
case WalletRestoreMode.seed:
|
||||||
|
return walletCreationService.restoreFromSeed(credentials);
|
||||||
|
default:
|
||||||
|
throw Exception('Unexpected restore mode: ${restoreWallet.restoreMode.toString()}');
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
throw Exception('Unexpected restore mode: ${e.toString()}');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1
lib/view_model/restore/restore_mode.dart
Normal file
1
lib/view_model/restore/restore_mode.dart
Normal file
|
@ -0,0 +1 @@
|
||||||
|
enum WalletRestoreMode { seed, keys, txids }
|
66
lib/view_model/restore/restore_wallet.dart
Normal file
66
lib/view_model/restore/restore_wallet.dart
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
import 'package:cake_wallet/view_model/restore/restore_mode.dart';
|
||||||
|
import 'package:cw_core/wallet_type.dart';
|
||||||
|
|
||||||
|
class RestoredWallet {
|
||||||
|
RestoredWallet(
|
||||||
|
{required this.restoreMode,
|
||||||
|
required this.type,
|
||||||
|
required this.address,
|
||||||
|
this.txId,
|
||||||
|
this.spendKey,
|
||||||
|
this.viewKey,
|
||||||
|
this.mnemonicSeed,
|
||||||
|
this.txAmount,
|
||||||
|
this.txDescription,
|
||||||
|
this.recipientName,
|
||||||
|
this.height});
|
||||||
|
|
||||||
|
final WalletRestoreMode restoreMode;
|
||||||
|
final WalletType type;
|
||||||
|
final String? address;
|
||||||
|
final String? txId;
|
||||||
|
final String? spendKey;
|
||||||
|
final String? viewKey;
|
||||||
|
final String? mnemonicSeed;
|
||||||
|
final String? txAmount;
|
||||||
|
final String? txDescription;
|
||||||
|
final String? recipientName;
|
||||||
|
final int? height;
|
||||||
|
|
||||||
|
factory RestoredWallet.fromKey(Map<String, dynamic> json) {
|
||||||
|
final height = json['height'] as String?;
|
||||||
|
return RestoredWallet(
|
||||||
|
restoreMode: json['mode'] as WalletRestoreMode,
|
||||||
|
type: json['type'] as WalletType,
|
||||||
|
address: json['address'] as String?,
|
||||||
|
spendKey: json['spend_key'] as String?,
|
||||||
|
viewKey: json['view_key'] as String?,
|
||||||
|
height: height != null ? int.parse(height) : 0,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
factory RestoredWallet.fromSeed(Map<String, dynamic> json) {
|
||||||
|
final height = json['height'] as String?;
|
||||||
|
final mnemonic_seed = json['mnemonic_seed'] as String?;
|
||||||
|
final seed = json['seed'] as String?;
|
||||||
|
return RestoredWallet(
|
||||||
|
restoreMode: json['mode'] as WalletRestoreMode,
|
||||||
|
type: json['type'] as WalletType,
|
||||||
|
address: json['address'] as String?,
|
||||||
|
mnemonicSeed: mnemonic_seed ?? seed,
|
||||||
|
height: height != null ? int.parse(height) : 0,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
factory RestoredWallet.fromTxIds(Map<String, dynamic> json) {
|
||||||
|
return RestoredWallet(
|
||||||
|
restoreMode: json['mode'] as WalletRestoreMode,
|
||||||
|
type: json['type'] as WalletType,
|
||||||
|
address: json['address'] as String?,
|
||||||
|
txId: json['tx_payment_id'] as String,
|
||||||
|
txAmount: json['tx_amount'] as String,
|
||||||
|
txDescription: json['tx_description'] as String?,
|
||||||
|
recipientName: json['recipient_name'] as String?,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
159
lib/view_model/restore/wallet_restore_from_qr_code.dart
Normal file
159
lib/view_model/restore/wallet_restore_from_qr_code.dart
Normal file
|
@ -0,0 +1,159 @@
|
||||||
|
import 'package:cake_wallet/core/address_validator.dart';
|
||||||
|
import 'package:cake_wallet/core/seed_validator.dart';
|
||||||
|
import 'package:cake_wallet/entities/mnemonic_item.dart';
|
||||||
|
import 'package:cake_wallet/entities/parse_address_from_domain.dart';
|
||||||
|
import 'package:cake_wallet/entities/qr_scanner.dart';
|
||||||
|
import 'package:cake_wallet/view_model/restore/restore_mode.dart';
|
||||||
|
import 'package:cake_wallet/view_model/restore/restore_wallet.dart';
|
||||||
|
import 'package:cw_bitcoin/bitcoin_mnemonic.dart';
|
||||||
|
import 'package:cw_core/wallet_type.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
|
||||||
|
class WalletRestoreFromQRCode {
|
||||||
|
WalletRestoreFromQRCode();
|
||||||
|
|
||||||
|
static Future<RestoredWallet> scanQRCodeForRestoring(BuildContext context) async {
|
||||||
|
String code = await presentQRScanner();
|
||||||
|
Map<String, dynamic> credentials = {};
|
||||||
|
|
||||||
|
if (code.isEmpty) {
|
||||||
|
throw Exception('Unexpected scan QR code value: value is empty');
|
||||||
|
}
|
||||||
|
final formattedUri = getFormattedUri(code);
|
||||||
|
final uri = Uri.parse(formattedUri);
|
||||||
|
final queryParameters = uri.queryParameters;
|
||||||
|
credentials['type'] = getWalletTypeFromUrl(uri.scheme);
|
||||||
|
|
||||||
|
final address = getAddressFromUrl(
|
||||||
|
type: credentials['type'] as WalletType,
|
||||||
|
rawString: queryParameters.toString(),
|
||||||
|
);
|
||||||
|
if (address != null) {
|
||||||
|
credentials['address'] = address;
|
||||||
|
}
|
||||||
|
|
||||||
|
final seed =
|
||||||
|
getSeedPhraseFromUrl(queryParameters.toString(), credentials['type'] as WalletType);
|
||||||
|
if (seed != null) {
|
||||||
|
credentials['seed'] = seed;
|
||||||
|
}
|
||||||
|
credentials.addAll(queryParameters);
|
||||||
|
credentials['mode'] = getWalletRestoreMode(credentials);
|
||||||
|
|
||||||
|
switch (credentials['mode']) {
|
||||||
|
case WalletRestoreMode.txids:
|
||||||
|
return RestoredWallet.fromTxIds(credentials);
|
||||||
|
case WalletRestoreMode.seed:
|
||||||
|
return RestoredWallet.fromSeed(credentials);
|
||||||
|
case WalletRestoreMode.keys:
|
||||||
|
return RestoredWallet.fromKey(credentials);
|
||||||
|
default:
|
||||||
|
throw Exception('Unexpected restore mode: ${credentials['mode']}');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static String getFormattedUri(String code) {
|
||||||
|
final index = code.indexOf(':');
|
||||||
|
final scheme = code.substring(0, index).replaceAll('_', '-');
|
||||||
|
final query = code.substring(index + 1).replaceAll('?', '&');
|
||||||
|
final formattedUri = '$scheme:?$query';
|
||||||
|
return formattedUri;
|
||||||
|
}
|
||||||
|
|
||||||
|
static WalletType getWalletTypeFromUrl(String scheme) {
|
||||||
|
switch (scheme) {
|
||||||
|
case 'monero':
|
||||||
|
case 'monero-wallet':
|
||||||
|
return WalletType.monero;
|
||||||
|
case 'bitcoin':
|
||||||
|
case 'bitcoin-wallet':
|
||||||
|
return WalletType.bitcoin;
|
||||||
|
case 'litecoin':
|
||||||
|
case 'litecoin-wallet':
|
||||||
|
return WalletType.litecoin;
|
||||||
|
default:
|
||||||
|
throw Exception('Unexpected wallet type: ${scheme.toString()}');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static String? getAddressFromUrl({required WalletType type, required String rawString}) {
|
||||||
|
return AddressResolver.extractAddressByType(
|
||||||
|
raw: rawString, type: walletTypeToCryptoCurrency(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
static String? getSeedPhraseFromUrl(String rawString, WalletType walletType) {
|
||||||
|
switch (walletType) {
|
||||||
|
case WalletType.monero:
|
||||||
|
RegExp regex25 = RegExp(r'\b(\S+\b\s+){24}\S+\b');
|
||||||
|
RegExp regex14 = RegExp(r'\b(\S+\b\s+){13}\S+\b');
|
||||||
|
RegExp regex13 = RegExp(r'\b(\S+\b\s+){12}\S+\b');
|
||||||
|
|
||||||
|
if (regex25.firstMatch(rawString) == null) {
|
||||||
|
if (regex14.firstMatch(rawString) == null) {
|
||||||
|
if (regex13.firstMatch(rawString) == null) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return regex13.firstMatch(rawString)!.group(0)!;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return regex14.firstMatch(rawString)!.group(0)!;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return regex25.firstMatch(rawString)!.group(0)!;
|
||||||
|
}
|
||||||
|
case WalletType.bitcoin:
|
||||||
|
case WalletType.litecoin:
|
||||||
|
RegExp regex24 = RegExp(r'\b(\S+\b\s+){23}\S+\b');
|
||||||
|
RegExp regex18 = RegExp(r'\b(\S+\b\s+){17}\S+\b');
|
||||||
|
RegExp regex12 = RegExp(r'\b(\S+\b\s+){11}\S+\b');
|
||||||
|
|
||||||
|
if (regex24.firstMatch(rawString) == null) {
|
||||||
|
if (regex18.firstMatch(rawString) == null) {
|
||||||
|
if (regex12.firstMatch(rawString) == null) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return regex12.firstMatch(rawString)!.group(0)!;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return regex18.firstMatch(rawString)!.group(0)!;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return regex24.firstMatch(rawString)!.group(0)!;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static WalletRestoreMode getWalletRestoreMode(Map<String, dynamic> credentials) {
|
||||||
|
final type = credentials['type'] as WalletType;
|
||||||
|
if (credentials.containsKey('tx_payment_id')) {
|
||||||
|
final txIdValue = credentials['tx_payment_id'] as String? ?? '';
|
||||||
|
return txIdValue.isNotEmpty
|
||||||
|
? WalletRestoreMode.txids
|
||||||
|
: throw Exception('Unexpected restore mode: tx_payment_id is invalid');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (credentials.containsKey('seed')) {
|
||||||
|
final seedValue = credentials['seed'] as String;
|
||||||
|
final words = SeedValidator.getWordList(type: type, language: 'english');
|
||||||
|
seedValue.split(' ').forEach((element) {
|
||||||
|
if (!words.contains(element)) {
|
||||||
|
throw Exception('Unexpected restore mode: mnemonic_seed is invalid');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return WalletRestoreMode.seed;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (credentials.containsKey('spend_key') || credentials.containsKey('view_key')) {
|
||||||
|
final spendKeyValue = credentials['spend_key'] as String? ?? '';
|
||||||
|
final viewKeyValue = credentials['view_key'] as String? ?? '';
|
||||||
|
|
||||||
|
return spendKeyValue.isNotEmpty || viewKeyValue.isNotEmpty
|
||||||
|
? WalletRestoreMode.keys
|
||||||
|
: throw Exception('Unexpected restore mode: spend_key or view_key is invalid');
|
||||||
|
}
|
||||||
|
|
||||||
|
throw Exception('Unexpected restore mode: restore params are invalid');
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
import 'package:cake_wallet/core/wallet_creation_service.dart';
|
import 'package:cake_wallet/core/wallet_creation_service.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:cake_wallet/view_model/restore/restore_wallet.dart';
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
import 'package:mobx/mobx.dart';
|
import 'package:mobx/mobx.dart';
|
||||||
import 'package:cake_wallet/core/execution_state.dart';
|
import 'package:cake_wallet/core/execution_state.dart';
|
||||||
|
@ -39,7 +39,8 @@ abstract class WalletCreationVMBase with Store {
|
||||||
bool typeExists(WalletType type)
|
bool typeExists(WalletType type)
|
||||||
=> walletCreationService.typeExists(type);
|
=> walletCreationService.typeExists(type);
|
||||||
|
|
||||||
Future<void> create({dynamic options}) async {
|
Future<void> create({dynamic options, RestoredWallet? restoreWallet}) async {
|
||||||
|
final type = restoreWallet?.type ?? this.type;
|
||||||
try {
|
try {
|
||||||
state = IsExecutingState();
|
state = IsExecutingState();
|
||||||
if (name.isEmpty) {
|
if (name.isEmpty) {
|
||||||
|
@ -49,7 +50,9 @@ abstract class WalletCreationVMBase with Store {
|
||||||
walletCreationService.checkIfExists(name);
|
walletCreationService.checkIfExists(name);
|
||||||
final dirPath = await pathForWalletDir(name: name, type: type);
|
final dirPath = await pathForWalletDir(name: name, type: type);
|
||||||
final path = await pathForWallet(name: name, type: type);
|
final path = await pathForWallet(name: name, type: type);
|
||||||
final credentials = getCredentials(options);
|
final credentials = restoreWallet != null
|
||||||
|
? getCredentialsFromRestoredWallet(options, restoreWallet)
|
||||||
|
: getCredentials(options);
|
||||||
final walletInfo = WalletInfo.external(
|
final walletInfo = WalletInfo.external(
|
||||||
id: WalletBase.idFor(name, type),
|
id: WalletBase.idFor(name, type),
|
||||||
name: name,
|
name: name,
|
||||||
|
@ -62,7 +65,9 @@ abstract class WalletCreationVMBase with Store {
|
||||||
address: '',
|
address: '',
|
||||||
showIntroCakePayCard: (!walletCreationService.typeExists(type)) && type != WalletType.haven);
|
showIntroCakePayCard: (!walletCreationService.typeExists(type)) && type != WalletType.haven);
|
||||||
credentials.walletInfo = walletInfo;
|
credentials.walletInfo = walletInfo;
|
||||||
final wallet = await process(credentials);
|
final wallet = restoreWallet != null
|
||||||
|
? await processFromRestoredWallet(credentials, restoreWallet)
|
||||||
|
: await process(credentials);
|
||||||
walletInfo.address = wallet.walletAddresses.address;
|
walletInfo.address = wallet.walletAddresses.address;
|
||||||
await _walletInfoSource.add(walletInfo);
|
await _walletInfoSource.add(walletInfo);
|
||||||
_appStore.changeCurrentWallet(wallet);
|
_appStore.changeCurrentWallet(wallet);
|
||||||
|
@ -72,10 +77,15 @@ abstract class WalletCreationVMBase with Store {
|
||||||
state = FailureState(e.toString());
|
state = FailureState(e.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WalletCredentials getCredentials(dynamic options) =>
|
WalletCredentials getCredentials(dynamic options) =>
|
||||||
throw UnimplementedError();
|
throw UnimplementedError();
|
||||||
|
|
||||||
Future<WalletBase> process(WalletCredentials credentials) =>
|
Future<WalletBase> process(WalletCredentials credentials) =>
|
||||||
throw UnimplementedError();
|
throw UnimplementedError();
|
||||||
|
|
||||||
|
WalletCredentials getCredentialsFromRestoredWallet(dynamic options, RestoredWallet restoreWallet) =>
|
||||||
|
throw UnimplementedError();
|
||||||
|
|
||||||
|
Future<WalletBase> processFromRestoredWallet(WalletCredentials credentials, RestoredWallet restoreWallet) =>
|
||||||
|
throw UnimplementedError();
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,16 +88,17 @@ abstract class WalletKeysViewModelBase with Store {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
String get _path {
|
|
||||||
|
String get _scheme {
|
||||||
switch (_appStore.wallet!.type) {
|
switch (_appStore.wallet!.type) {
|
||||||
case WalletType.monero:
|
case WalletType.monero:
|
||||||
return 'monero_wallet:';
|
return 'monero-wallet';
|
||||||
case WalletType.bitcoin:
|
case WalletType.bitcoin:
|
||||||
return 'bitcoin_wallet:';
|
return 'bitcoin-wallet';
|
||||||
case WalletType.litecoin:
|
case WalletType.litecoin:
|
||||||
return 'litecoin_wallet:';
|
return 'litecoin-wallet';
|
||||||
case WalletType.haven:
|
case WalletType.haven:
|
||||||
return 'haven_wallet:';
|
return 'haven-wallet';
|
||||||
default:
|
default:
|
||||||
throw Exception('Unexpected wallet type: ${_appStore.wallet!.toString()}');
|
throw Exception('Unexpected wallet type: ${_appStore.wallet!.toString()}');
|
||||||
}
|
}
|
||||||
|
@ -124,7 +125,7 @@ abstract class WalletKeysViewModelBase with Store {
|
||||||
|
|
||||||
Future<Uri> get url async {
|
Future<Uri> get url async {
|
||||||
return Uri(
|
return Uri(
|
||||||
path: _path,
|
scheme: _scheme,
|
||||||
queryParameters: await _queryParams,
|
queryParameters: await _queryParams,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import 'package:cake_wallet/view_model/restore/restore_wallet.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
import 'package:mobx/mobx.dart';
|
import 'package:mobx/mobx.dart';
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import 'package:cake_wallet/view_model/restore/restore_wallet.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
import 'package:mobx/mobx.dart';
|
import 'package:mobx/mobx.dart';
|
||||||
|
@ -66,7 +67,7 @@ abstract class WalletRestorationFromKeysVMBase extends WalletCreationVM
|
||||||
return bitcoin!.createBitcoinRestoreWalletFromWIFCredentials(
|
return bitcoin!.createBitcoinRestoreWalletFromWIFCredentials(
|
||||||
name: name, password: password, wif: wif);
|
name: name, password: password, wif: wif);
|
||||||
default:
|
default:
|
||||||
throw Exception('Unexpected type: ${type.toString()}');;
|
throw Exception('Unexpected type: ${type.toString()}');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import 'package:cake_wallet/view_model/restore/restore_wallet.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
import 'package:mobx/mobx.dart';
|
import 'package:mobx/mobx.dart';
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import 'package:cake_wallet/bitcoin/bitcoin.dart';
|
import 'package:cake_wallet/bitcoin/bitcoin.dart';
|
||||||
import 'package:cake_wallet/core/mnemonic_length.dart';
|
import 'package:cake_wallet/core/mnemonic_length.dart';
|
||||||
|
import 'package:cake_wallet/view_model/restore/restore_wallet.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
import 'package:mobx/mobx.dart';
|
import 'package:mobx/mobx.dart';
|
||||||
|
@ -13,10 +14,10 @@ import 'package:cw_core/wallet_info.dart';
|
||||||
import 'package:cake_wallet/view_model/wallet_creation_vm.dart';
|
import 'package:cake_wallet/view_model/wallet_creation_vm.dart';
|
||||||
import 'package:cake_wallet/monero/monero.dart';
|
import 'package:cake_wallet/monero/monero.dart';
|
||||||
import 'package:cake_wallet/haven/haven.dart';
|
import 'package:cake_wallet/haven/haven.dart';
|
||||||
|
import 'package:cake_wallet/view_model/restore/restore_mode.dart';
|
||||||
|
|
||||||
part 'wallet_restore_view_model.g.dart';
|
part 'wallet_restore_view_model.g.dart';
|
||||||
|
|
||||||
enum WalletRestoreMode { seed, keys }
|
|
||||||
|
|
||||||
class WalletRestoreViewModel = WalletRestoreViewModelBase
|
class WalletRestoreViewModel = WalletRestoreViewModelBase
|
||||||
with _$WalletRestoreViewModel;
|
with _$WalletRestoreViewModel;
|
||||||
|
|
|
@ -150,7 +150,7 @@
|
||||||
"receive_amount":"المقدار",
|
"receive_amount":"المقدار",
|
||||||
"subaddresses":"العناوين الفرعية",
|
"subaddresses":"العناوين الفرعية",
|
||||||
"addresses":"عناوين",
|
"addresses":"عناوين",
|
||||||
"scan_qr_code":"امسح ال QR للحصول على العنوان",
|
"scan_qr_code_to_get_address":"امسح ال QR للحصول على العنوان",
|
||||||
"qr_fullscreen":"انقر لفتح ال QR بملء الشاشة",
|
"qr_fullscreen":"انقر لفتح ال QR بملء الشاشة",
|
||||||
"rename":"إعادة تسمية",
|
"rename":"إعادة تسمية",
|
||||||
"choose_account":"اختر حساب",
|
"choose_account":"اختر حساب",
|
||||||
|
@ -683,6 +683,11 @@
|
||||||
"arrive_in_this_address" : "سيصل ${currency} ${tag}إلى هذا العنوان",
|
"arrive_in_this_address" : "سيصل ${currency} ${tag}إلى هذا العنوان",
|
||||||
"do_not_send": "لا ترسل",
|
"do_not_send": "لا ترسل",
|
||||||
"error_dialog_content": "عفوًا ، لقد حصلنا على بعض الخطأ.\n\nيرجى إرسال تقرير التعطل إلى فريق الدعم لدينا لتحسين التطبيق.",
|
"error_dialog_content": "عفوًا ، لقد حصلنا على بعض الخطأ.\n\nيرجى إرسال تقرير التعطل إلى فريق الدعم لدينا لتحسين التطبيق.",
|
||||||
|
"scan_qr_code": "امسح رمز QR ضوئيًا",
|
||||||
|
"cold_or_recover_wallet": "أضف محفظة باردة أو استعد محفظة ورقية",
|
||||||
|
"please_wait": "انتظر من فضلك",
|
||||||
|
"sweeping_wallet": "كنس المحفظة",
|
||||||
|
"sweeping_wallet_alert": "لن يستغرق هذا وقتًا طويلاً. لا تترك هذه الشاشة وإلا فقد يتم فقد أموال سويبت",
|
||||||
"decimal_places_error": "عدد كبير جدًا من المنازل العشرية",
|
"decimal_places_error": "عدد كبير جدًا من المنازل العشرية",
|
||||||
"edit_node": "تحرير العقدة",
|
"edit_node": "تحرير العقدة",
|
||||||
"frozen_balance": "الرصيد المجمد",
|
"frozen_balance": "الرصيد المجمد",
|
||||||
|
|
|
@ -150,7 +150,7 @@
|
||||||
"receive_amount" : "Betrag",
|
"receive_amount" : "Betrag",
|
||||||
"subaddresses" : "Unteradressen",
|
"subaddresses" : "Unteradressen",
|
||||||
"addresses" : "Adressen",
|
"addresses" : "Adressen",
|
||||||
"scan_qr_code" : "Scannen Sie den QR-Code, um die Adresse zu erhalten",
|
"scan_qr_code_to_get_address" : "Scannen Sie den QR-Code, um die Adresse zu erhalten",
|
||||||
"qr_fullscreen" : "Tippen Sie hier, um den QR-Code im Vollbildmodus zu öffnen",
|
"qr_fullscreen" : "Tippen Sie hier, um den QR-Code im Vollbildmodus zu öffnen",
|
||||||
"rename" : "Umbenennen",
|
"rename" : "Umbenennen",
|
||||||
"choose_account" : "Konto auswählen",
|
"choose_account" : "Konto auswählen",
|
||||||
|
@ -685,6 +685,11 @@
|
||||||
"arrive_in_this_address" : "${currency} ${tag}wird an dieser Adresse ankommen",
|
"arrive_in_this_address" : "${currency} ${tag}wird an dieser Adresse ankommen",
|
||||||
"do_not_send": "Nicht senden",
|
"do_not_send": "Nicht senden",
|
||||||
"error_dialog_content": "Hoppla, wir haben einen Fehler.\n\nBitte senden Sie den Absturzbericht an unser Support-Team, um die Anwendung zu verbessern.",
|
"error_dialog_content": "Hoppla, wir haben einen Fehler.\n\nBitte senden Sie den Absturzbericht an unser Support-Team, um die Anwendung zu verbessern.",
|
||||||
|
"scan_qr_code": "QR-Code scannen",
|
||||||
|
"cold_or_recover_wallet": "Fügen Sie eine Cold Wallet hinzu oder stellen Sie eine Paper Wallet wieder her",
|
||||||
|
"please_wait": "Warten Sie mal",
|
||||||
|
"sweeping_wallet": "Kehre Geldbörse",
|
||||||
|
"sweeping_wallet_alert": "Das sollte nicht lange dauern. VERLASSEN SIE DIESEN BILDSCHIRM NICHT, ANDERNFALLS KÖNNEN DIE SWEPT-GELDER VERLOREN GEHEN",
|
||||||
"decimal_places_error": "Zu viele Nachkommastellen",
|
"decimal_places_error": "Zu viele Nachkommastellen",
|
||||||
"edit_node": "Knoten bearbeiten",
|
"edit_node": "Knoten bearbeiten",
|
||||||
"frozen_balance": "Gefrorenes Gleichgewicht",
|
"frozen_balance": "Gefrorenes Gleichgewicht",
|
||||||
|
|
|
@ -150,7 +150,7 @@
|
||||||
"receive_amount" : "Amount",
|
"receive_amount" : "Amount",
|
||||||
"subaddresses" : "Subaddresses",
|
"subaddresses" : "Subaddresses",
|
||||||
"addresses" : "Addresses",
|
"addresses" : "Addresses",
|
||||||
"scan_qr_code" : "Scan the QR code to get the address",
|
"scan_qr_code_to_get_address" : "Scan the QR code to get the address",
|
||||||
"qr_fullscreen" : "Tap to open full screen QR code",
|
"qr_fullscreen" : "Tap to open full screen QR code",
|
||||||
"rename" : "Rename",
|
"rename" : "Rename",
|
||||||
"choose_account" : "Choose account",
|
"choose_account" : "Choose account",
|
||||||
|
@ -685,6 +685,11 @@
|
||||||
"arrive_in_this_address" : "${currency} ${tag}will arrive in this address",
|
"arrive_in_this_address" : "${currency} ${tag}will arrive in this address",
|
||||||
"do_not_send": "Don't send",
|
"do_not_send": "Don't send",
|
||||||
"error_dialog_content": "Oops, we got some error.\n\nPlease send the crash report to our support team to make the application better.",
|
"error_dialog_content": "Oops, we got some error.\n\nPlease send the crash report to our support team to make the application better.",
|
||||||
|
"scan_qr_code": "Scan QR code",
|
||||||
|
"cold_or_recover_wallet": "Add a cold wallet or recover a paper wallet",
|
||||||
|
"please_wait": "Please wait",
|
||||||
|
"sweeping_wallet": "Sweeping wallet",
|
||||||
|
"sweeping_wallet_alert": "This shouldn’t take long. DO NOT LEAVE THIS SCREEN OR THE SWEPT FUNDS MAY BE LOST.",
|
||||||
"invoice_details": "Invoice details",
|
"invoice_details": "Invoice details",
|
||||||
"donation_link_details": "Donation link details",
|
"donation_link_details": "Donation link details",
|
||||||
"anonpay_description": "Generate ${type}. The recipient can ${method} with any supported cryptocurrency, and you will receive funds in this wallet.",
|
"anonpay_description": "Generate ${type}. The recipient can ${method} with any supported cryptocurrency, and you will receive funds in this wallet.",
|
||||||
|
|
|
@ -150,7 +150,7 @@
|
||||||
"receive_amount" : "Cantidad",
|
"receive_amount" : "Cantidad",
|
||||||
"subaddresses" : "Subdirecciones",
|
"subaddresses" : "Subdirecciones",
|
||||||
"addresses" : "Direcciones",
|
"addresses" : "Direcciones",
|
||||||
"scan_qr_code" : "Escanee el código QR para obtener la dirección",
|
"scan_qr_code_to_get_address" : "Escanee el código QR para obtener la dirección",
|
||||||
"qr_fullscreen" : "Toque para abrir el código QR en pantalla completa",
|
"qr_fullscreen" : "Toque para abrir el código QR en pantalla completa",
|
||||||
"rename" : "Rebautizar",
|
"rename" : "Rebautizar",
|
||||||
"choose_account" : "Elegir cuenta",
|
"choose_account" : "Elegir cuenta",
|
||||||
|
@ -685,6 +685,11 @@
|
||||||
"arrive_in_this_address" : "${currency} ${tag}llegará a esta dirección",
|
"arrive_in_this_address" : "${currency} ${tag}llegará a esta dirección",
|
||||||
"do_not_send": "no enviar",
|
"do_not_send": "no enviar",
|
||||||
"error_dialog_content": "Vaya, tenemos un error.\n\nEnvíe el informe de bloqueo a nuestro equipo de soporte para mejorar la aplicación.",
|
"error_dialog_content": "Vaya, tenemos un error.\n\nEnvíe el informe de bloqueo a nuestro equipo de soporte para mejorar la aplicación.",
|
||||||
|
"scan_qr_code": "Escanear código QR",
|
||||||
|
"cold_or_recover_wallet": "Agregue una billetera fría o recupere una billetera de papel",
|
||||||
|
"please_wait": "Espere por favor",
|
||||||
|
"sweeping_wallet": "Billetera de barrido",
|
||||||
|
"sweeping_wallet_alert": "Esto no debería llevar mucho tiempo. NO DEJES ESTA PANTALLA O SE PUEDEN PERDER LOS FONDOS BARRIDOS",
|
||||||
"decimal_places_error": "Demasiados lugares decimales",
|
"decimal_places_error": "Demasiados lugares decimales",
|
||||||
"edit_node": "Editar nodo",
|
"edit_node": "Editar nodo",
|
||||||
"frozen_balance": "Balance congelado",
|
"frozen_balance": "Balance congelado",
|
||||||
|
|
|
@ -150,7 +150,7 @@
|
||||||
"receive_amount" : "Montant",
|
"receive_amount" : "Montant",
|
||||||
"subaddresses" : "Sous-adresses",
|
"subaddresses" : "Sous-adresses",
|
||||||
"addresses" : "Adresses",
|
"addresses" : "Adresses",
|
||||||
"scan_qr_code" : "Scannez le QR code pour obtenir l'adresse",
|
"scan_qr_code_to_get_address" : "Scannez le QR code pour obtenir l'adresse",
|
||||||
"qr_fullscreen" : "Appuyez pour ouvrir le QR code en mode plein écran",
|
"qr_fullscreen" : "Appuyez pour ouvrir le QR code en mode plein écran",
|
||||||
"rename" : "Renommer",
|
"rename" : "Renommer",
|
||||||
"choose_account" : "Choisir le compte",
|
"choose_account" : "Choisir le compte",
|
||||||
|
@ -685,6 +685,11 @@
|
||||||
"arrive_in_this_address" : "${currency} ${tag}arrivera à cette adresse",
|
"arrive_in_this_address" : "${currency} ${tag}arrivera à cette adresse",
|
||||||
"do_not_send": "Ne pas envoyer",
|
"do_not_send": "Ne pas envoyer",
|
||||||
"error_dialog_content": "Oups, nous avons rencontré une erreur.\n\nMerci d'envoyer le rapport d'erreur à notre équipe d'assistance afin de nous permettre d'améliorer l'application.",
|
"error_dialog_content": "Oups, nous avons rencontré une erreur.\n\nMerci d'envoyer le rapport d'erreur à notre équipe d'assistance afin de nous permettre d'améliorer l'application.",
|
||||||
|
"scan_qr_code": "Scannez le code QR",
|
||||||
|
"cold_or_recover_wallet": "Ajoutez un cold wallet ou récupérez un paper wallet",
|
||||||
|
"please_wait": "S'il vous plaît, attendez",
|
||||||
|
"sweeping_wallet": "Portefeuille de balayage",
|
||||||
|
"sweeping_wallet_alert": "Cela ne devrait pas prendre longtemps. NE QUITTEZ PAS CET ÉCRAN OU LES FONDS BALAYÉS POURRAIENT ÊTRE PERDUS",
|
||||||
"decimal_places_error": "Trop de décimales",
|
"decimal_places_error": "Trop de décimales",
|
||||||
"edit_node": "Modifier le nœud",
|
"edit_node": "Modifier le nœud",
|
||||||
"frozen_balance": "Équilibre gelé",
|
"frozen_balance": "Équilibre gelé",
|
||||||
|
|
|
@ -150,7 +150,7 @@
|
||||||
"receive_amount" : "रकम",
|
"receive_amount" : "रकम",
|
||||||
"subaddresses" : "उप पते",
|
"subaddresses" : "उप पते",
|
||||||
"addresses" : "पतों",
|
"addresses" : "पतों",
|
||||||
"scan_qr_code" : "पता प्राप्त करने के लिए QR कोड स्कैन करें",
|
"scan_qr_code_to_get_address" : "पता प्राप्त करने के लिए QR कोड स्कैन करें",
|
||||||
"qr_fullscreen" : "फ़ुल स्क्रीन क्यूआर कोड खोलने के लिए टैप करें",
|
"qr_fullscreen" : "फ़ुल स्क्रीन क्यूआर कोड खोलने के लिए टैप करें",
|
||||||
"rename" : "नाम बदलें",
|
"rename" : "नाम बदलें",
|
||||||
"choose_account" : "खाता चुनें",
|
"choose_account" : "खाता चुनें",
|
||||||
|
@ -685,6 +685,11 @@
|
||||||
"arrive_in_this_address" : "${currency} ${tag}इस पते पर पहुंचेंगे",
|
"arrive_in_this_address" : "${currency} ${tag}इस पते पर पहुंचेंगे",
|
||||||
"do_not_send": "मत भेजो",
|
"do_not_send": "मत भेजो",
|
||||||
"error_dialog_content": "ओह, हमसे कुछ गड़बड़ी हुई है.\n\nएप्लिकेशन को बेहतर बनाने के लिए कृपया क्रैश रिपोर्ट हमारी सहायता टीम को भेजें।",
|
"error_dialog_content": "ओह, हमसे कुछ गड़बड़ी हुई है.\n\nएप्लिकेशन को बेहतर बनाने के लिए कृपया क्रैश रिपोर्ट हमारी सहायता टीम को भेजें।",
|
||||||
|
"scan_qr_code": "स्कैन क्यू आर कोड",
|
||||||
|
"cold_or_recover_wallet": "कोल्ड वॉलेट जोड़ें या पेपर वॉलेट पुनर्प्राप्त करें",
|
||||||
|
"please_wait": "कृपया प्रतीक्षा करें",
|
||||||
|
"sweeping_wallet": "स्वीपिंग वॉलेट",
|
||||||
|
"sweeping_wallet_alert": "इसमें अधिक समय नहीं लगना चाहिए। इस स्क्रीन को न छोड़ें या स्वैप्ट फंड खो सकते हैं",
|
||||||
"decimal_places_error": "बहुत अधिक दशमलव स्थान",
|
"decimal_places_error": "बहुत अधिक दशमलव स्थान",
|
||||||
"edit_node": "नोड संपादित करें",
|
"edit_node": "नोड संपादित करें",
|
||||||
"frozen_balance": "जमे हुए संतुलन",
|
"frozen_balance": "जमे हुए संतुलन",
|
||||||
|
|
|
@ -150,7 +150,7 @@
|
||||||
"receive_amount" : "Iznos",
|
"receive_amount" : "Iznos",
|
||||||
"subaddresses" : "Podadrese",
|
"subaddresses" : "Podadrese",
|
||||||
"addresses" : "Adrese",
|
"addresses" : "Adrese",
|
||||||
"scan_qr_code" : "Skeniraj QR kod za dobivanje adrese",
|
"scan_qr_code_to_get_address" : "Skeniraj QR kod za dobivanje adrese",
|
||||||
"qr_fullscreen" : "Dodirnite za otvaranje QR koda preko cijelog zaslona",
|
"qr_fullscreen" : "Dodirnite za otvaranje QR koda preko cijelog zaslona",
|
||||||
"rename" : "Preimenuj",
|
"rename" : "Preimenuj",
|
||||||
"choose_account" : "Odaberi račun",
|
"choose_account" : "Odaberi račun",
|
||||||
|
@ -685,6 +685,11 @@
|
||||||
"arrive_in_this_address" : "${currency} ${tag}će stići na ovu adresu",
|
"arrive_in_this_address" : "${currency} ${tag}će stići na ovu adresu",
|
||||||
"do_not_send": "Ne šalji",
|
"do_not_send": "Ne šalji",
|
||||||
"error_dialog_content": "Ups, imamo grešku.\n\nPošaljite izvješće o padu našem timu za podršku kako bismo poboljšali aplikaciju.",
|
"error_dialog_content": "Ups, imamo grešku.\n\nPošaljite izvješće o padu našem timu za podršku kako bismo poboljšali aplikaciju.",
|
||||||
|
"scan_qr_code": "Skenirajte QR kod",
|
||||||
|
"cold_or_recover_wallet": "Dodajte hladni novčanik ili povratite papirnati novčanik",
|
||||||
|
"please_wait": "Molimo pričekajte",
|
||||||
|
"sweeping_wallet": "Čisti novčanik",
|
||||||
|
"sweeping_wallet_alert": "Ovo ne bi trebalo dugo trajati. NE NAPUŠTAJTE OVAJ ZASLON INAČE SE POBREŠENA SREDSTVA MOGU IZGUBITI",
|
||||||
"decimal_places_error": "Previše decimalnih mjesta",
|
"decimal_places_error": "Previše decimalnih mjesta",
|
||||||
"edit_node": "Uredi čvor",
|
"edit_node": "Uredi čvor",
|
||||||
"frozen_balance": "Zamrznuti saldo",
|
"frozen_balance": "Zamrznuti saldo",
|
||||||
|
|
|
@ -150,7 +150,7 @@
|
||||||
"receive_amount" : "Ammontare",
|
"receive_amount" : "Ammontare",
|
||||||
"subaddresses" : "Sottoindirizzi",
|
"subaddresses" : "Sottoindirizzi",
|
||||||
"addresses" : "Indirizzi",
|
"addresses" : "Indirizzi",
|
||||||
"scan_qr_code" : "Scansiona il codice QR per ottenere l'indirizzo",
|
"scan_qr_code_to_get_address" : "Scansiona il codice QR per ottenere l'indirizzo",
|
||||||
"qr_fullscreen" : "Tocca per aprire il codice QR a schermo intero",
|
"qr_fullscreen" : "Tocca per aprire il codice QR a schermo intero",
|
||||||
"rename" : "Rinomina",
|
"rename" : "Rinomina",
|
||||||
"choose_account" : "Scegli account",
|
"choose_account" : "Scegli account",
|
||||||
|
@ -685,6 +685,11 @@
|
||||||
"arrive_in_this_address" : "${currency} ${tag}arriverà a questo indirizzo",
|
"arrive_in_this_address" : "${currency} ${tag}arriverà a questo indirizzo",
|
||||||
"do_not_send": "Non inviare",
|
"do_not_send": "Non inviare",
|
||||||
"error_dialog_content": "Spiacenti, abbiamo riscontrato un errore.\n\nSi prega di inviare il rapporto sull'arresto anomalo al nostro team di supporto per migliorare l'applicazione.",
|
"error_dialog_content": "Spiacenti, abbiamo riscontrato un errore.\n\nSi prega di inviare il rapporto sull'arresto anomalo al nostro team di supporto per migliorare l'applicazione.",
|
||||||
|
"scan_qr_code": "Scansiona il codice QR",
|
||||||
|
"cold_or_recover_wallet": "Aggiungi un cold wallet o recupera un paper wallet",
|
||||||
|
"please_wait": "Attendere prego",
|
||||||
|
"sweeping_wallet": "Portafoglio ampio",
|
||||||
|
"sweeping_wallet_alert": "Questo non dovrebbe richiedere molto tempo. NON LASCIARE QUESTA SCHERMATA O I FONDI SPAZZATI POTREBBERO ANDARE PERSI",
|
||||||
"decimal_places_error": "Troppe cifre decimali",
|
"decimal_places_error": "Troppe cifre decimali",
|
||||||
"edit_node": "Modifica nodo",
|
"edit_node": "Modifica nodo",
|
||||||
"frozen_balance": "Equilibrio congelato",
|
"frozen_balance": "Equilibrio congelato",
|
||||||
|
|
|
@ -150,7 +150,7 @@
|
||||||
"receive_amount" : "量",
|
"receive_amount" : "量",
|
||||||
"subaddresses" : "サブアドレス",
|
"subaddresses" : "サブアドレス",
|
||||||
"addresses" : "住所",
|
"addresses" : "住所",
|
||||||
"scan_qr_code" : "QRコードをスキャンして住所を取得します",
|
"scan_qr_code_to_get_address" : "QRコードをスキャンして住所を取得します",
|
||||||
"qr_fullscreen" : "タップして全画面QRコードを開く",
|
"qr_fullscreen" : "タップして全画面QRコードを開く",
|
||||||
"rename" : "リネーム",
|
"rename" : "リネーム",
|
||||||
"choose_account" : "アカウントを選択",
|
"choose_account" : "アカウントを選択",
|
||||||
|
@ -685,6 +685,11 @@
|
||||||
"arrive_in_this_address" : "${currency} ${tag}はこの住所に到着します",
|
"arrive_in_this_address" : "${currency} ${tag}はこの住所に到着します",
|
||||||
"do_not_send": "送信しない",
|
"do_not_send": "送信しない",
|
||||||
"error_dialog_content": "エラーが発生しました。\n\nアプリケーションを改善するために、クラッシュ レポートをサポート チームに送信してください。",
|
"error_dialog_content": "エラーが発生しました。\n\nアプリケーションを改善するために、クラッシュ レポートをサポート チームに送信してください。",
|
||||||
|
"scan_qr_code": "QRコードをスキャン",
|
||||||
|
"cold_or_recover_wallet": "コールド ウォレットを追加するか、ペーパー ウォレットを復元する",
|
||||||
|
"please_wait": "お待ちください",
|
||||||
|
"sweeping_wallet": "スイープウォレット",
|
||||||
|
"sweeping_wallet_alert": "これには時間がかかりません。この画面から離れないでください。そうしないと、スイープ ファンドが失われる可能性があります",
|
||||||
"decimal_places_error": "小数点以下の桁数が多すぎる",
|
"decimal_places_error": "小数点以下の桁数が多すぎる",
|
||||||
"edit_node": "ノードを編集",
|
"edit_node": "ノードを編集",
|
||||||
"frozen_balance": "冷凍残高",
|
"frozen_balance": "冷凍残高",
|
||||||
|
|
|
@ -150,7 +150,7 @@
|
||||||
"receive_amount" : "양",
|
"receive_amount" : "양",
|
||||||
"subaddresses" : "하위 주소",
|
"subaddresses" : "하위 주소",
|
||||||
"addresses" : "구애",
|
"addresses" : "구애",
|
||||||
"scan_qr_code" : "QR 코드를 스캔하여 주소를 얻습니다.",
|
"scan_qr_code_to_get_address" : "QR 코드를 스캔하여 주소를 얻습니다.",
|
||||||
"qr_fullscreen" : "전체 화면 QR 코드를 열려면 탭하세요.",
|
"qr_fullscreen" : "전체 화면 QR 코드를 열려면 탭하세요.",
|
||||||
"rename" : "이름 바꾸기",
|
"rename" : "이름 바꾸기",
|
||||||
"choose_account" : "계정을 선택하십시오",
|
"choose_account" : "계정을 선택하십시오",
|
||||||
|
@ -685,6 +685,11 @@
|
||||||
"arrive_in_this_address" : "${currency} ${tag}이(가) 이 주소로 도착합니다",
|
"arrive_in_this_address" : "${currency} ${tag}이(가) 이 주소로 도착합니다",
|
||||||
"do_not_send": "보내지 마세요",
|
"do_not_send": "보내지 마세요",
|
||||||
"error_dialog_content": "죄송합니다. 오류가 발생했습니다.\n\n응용 프로그램을 개선하려면 지원 팀에 충돌 보고서를 보내주십시오.",
|
"error_dialog_content": "죄송합니다. 오류가 발생했습니다.\n\n응용 프로그램을 개선하려면 지원 팀에 충돌 보고서를 보내주십시오.",
|
||||||
|
"scan_qr_code": "QR 코드 스캔",
|
||||||
|
"cold_or_recover_wallet": "콜드 지갑 추가 또는 종이 지갑 복구",
|
||||||
|
"please_wait": "기다리세요",
|
||||||
|
"sweeping_wallet": "스위핑 지갑",
|
||||||
|
"sweeping_wallet_alert": "오래 걸리지 않습니다. 이 화면을 떠나지 마십시오. 그렇지 않으면 스웹트 자금이 손실될 수 있습니다.",
|
||||||
"decimal_places_error": "소수점 이하 자릿수가 너무 많습니다.",
|
"decimal_places_error": "소수점 이하 자릿수가 너무 많습니다.",
|
||||||
"edit_node": "노드 편집",
|
"edit_node": "노드 편집",
|
||||||
"frozen_balance": "얼어붙은 균형",
|
"frozen_balance": "얼어붙은 균형",
|
||||||
|
|
|
@ -150,7 +150,7 @@
|
||||||
"receive_amount" : "ပမာဏ",
|
"receive_amount" : "ပမာဏ",
|
||||||
"subaddresses" : "လိပ်စာများ",
|
"subaddresses" : "လိပ်စာများ",
|
||||||
"addresses" : "လိပ်စာများ",
|
"addresses" : "လိပ်စာများ",
|
||||||
"scan_qr_code" : "လိပ်စာရယူရန် QR ကုဒ်ကို စကင်န်ဖတ်ပါ။",
|
"scan_qr_code_to_get_address" : "လိပ်စာရယူရန် QR ကုဒ်ကို စကင်န်ဖတ်ပါ။",
|
||||||
"qr_fullscreen" : "မျက်နှာပြင်အပြည့် QR ကုဒ်ကိုဖွင့်ရန် တို့ပါ။",
|
"qr_fullscreen" : "မျက်နှာပြင်အပြည့် QR ကုဒ်ကိုဖွင့်ရန် တို့ပါ။",
|
||||||
"rename" : "အမည်ပြောင်းပါ။",
|
"rename" : "အမည်ပြောင်းပါ။",
|
||||||
"choose_account" : "အကောင့်ကို ရွေးပါ။",
|
"choose_account" : "အကောင့်ကို ရွေးပါ။",
|
||||||
|
@ -685,6 +685,11 @@
|
||||||
"arrive_in_this_address" : "${currency} ${tag}ဤလိပ်စာသို့ ရောက်ရှိပါမည်။",
|
"arrive_in_this_address" : "${currency} ${tag}ဤလိပ်စာသို့ ရောက်ရှိပါမည်။",
|
||||||
"do_not_send": "မပို့ပါနှင့်",
|
"do_not_send": "မပို့ပါနှင့်",
|
||||||
"error_dialog_content": "အိုး၊ ကျွန်ုပ်တို့တွင် အမှားအယွင်းအချို့ရှိသည်။\n\nအပလီကေးရှင်းကို ပိုမိုကောင်းမွန်စေရန်အတွက် ပျက်စီးမှုအစီရင်ခံစာကို ကျွန်ုပ်တို့၏ပံ့ပိုးကူညီရေးအဖွဲ့ထံ ပေးပို့ပါ။",
|
"error_dialog_content": "အိုး၊ ကျွန်ုပ်တို့တွင် အမှားအယွင်းအချို့ရှိသည်။\n\nအပလီကေးရှင်းကို ပိုမိုကောင်းမွန်စေရန်အတွက် ပျက်စီးမှုအစီရင်ခံစာကို ကျွန်ုပ်တို့၏ပံ့ပိုးကူညီရေးအဖွဲ့ထံ ပေးပို့ပါ။",
|
||||||
|
"scan_qr_code": "QR ကုဒ်ကို စကင်န်ဖတ်ပါ။",
|
||||||
|
"cold_or_recover_wallet": "အေးသောပိုက်ဆံအိတ်ထည့်ပါ သို့မဟုတ် စက္ကူပိုက်ဆံအိတ်ကို ပြန်ယူပါ။",
|
||||||
|
"please_wait": "ကျေးဇူးပြုပြီးခဏစောင့်ပါ",
|
||||||
|
"sweeping_wallet": "ိုက်ဆံအိတ် တံမြက်လှည်း",
|
||||||
|
"sweeping_wallet_alert": "ဒါက ကြာကြာမခံသင့်ပါဘူး။ ဤစခရင်ကို ချန်မထားပါနှင့် သို့မဟုတ် ထုတ်ယူထားသော ရန်ပုံငွေများ ဆုံးရှုံးနိုင်သည်",
|
||||||
"decimal_places_error": "ဒဿမနေရာများ များလွန်းသည်။",
|
"decimal_places_error": "ဒဿမနေရာများ များလွန်းသည်။",
|
||||||
"edit_node": "Node ကို တည်းဖြတ်ပါ။",
|
"edit_node": "Node ကို တည်းဖြတ်ပါ။",
|
||||||
"frozen_balance": "ေးခဲမှူ",
|
"frozen_balance": "ေးခဲမှူ",
|
||||||
|
|
|
@ -151,7 +151,7 @@
|
||||||
"subaddresses" : "Subadressen",
|
"subaddresses" : "Subadressen",
|
||||||
"rename" : "Hernoemen",
|
"rename" : "Hernoemen",
|
||||||
"addresses" : "Adressen",
|
"addresses" : "Adressen",
|
||||||
"scan_qr_code" : "Scan de QR-code om het adres te krijgen",
|
"scan_qr_code_to_get_address" : "Scan de QR-code om het adres te krijgen",
|
||||||
"qr_fullscreen" : "Tik om de QR-code op volledig scherm te openen",
|
"qr_fullscreen" : "Tik om de QR-code op volledig scherm te openen",
|
||||||
"choose_account" : "Kies account",
|
"choose_account" : "Kies account",
|
||||||
"create_new_account" : "Creëer een nieuw account",
|
"create_new_account" : "Creëer een nieuw account",
|
||||||
|
@ -685,6 +685,11 @@
|
||||||
"arrive_in_this_address" : "${currency} ${tag}komt aan op dit adres",
|
"arrive_in_this_address" : "${currency} ${tag}komt aan op dit adres",
|
||||||
"do_not_send": "Niet sturen",
|
"do_not_send": "Niet sturen",
|
||||||
"error_dialog_content": "Oeps, er is een fout opgetreden.\n\nStuur het crashrapport naar ons ondersteuningsteam om de applicatie te verbeteren.",
|
"error_dialog_content": "Oeps, er is een fout opgetreden.\n\nStuur het crashrapport naar ons ondersteuningsteam om de applicatie te verbeteren.",
|
||||||
|
"scan_qr_code": "Scan QR-code",
|
||||||
|
"cold_or_recover_wallet": "Voeg een cold wallet toe of herstel een paper wallet",
|
||||||
|
"please_wait": "Even geduld aub",
|
||||||
|
"sweeping_wallet": "Vegende portemonnee",
|
||||||
|
"sweeping_wallet_alert": "Dit duurt niet lang. VERLAAT DIT SCHERM NIET, ANDERS KAN HET SWEPT-GELD VERLOREN WORDEN",
|
||||||
"decimal_places_error": "Te veel decimalen",
|
"decimal_places_error": "Te veel decimalen",
|
||||||
"edit_node": "Knooppunt bewerken",
|
"edit_node": "Knooppunt bewerken",
|
||||||
"frozen_balance": "Bevroren saldo",
|
"frozen_balance": "Bevroren saldo",
|
||||||
|
|
|
@ -150,7 +150,7 @@
|
||||||
"receive_amount" : "Ilość",
|
"receive_amount" : "Ilość",
|
||||||
"subaddresses" : "Podadresy",
|
"subaddresses" : "Podadresy",
|
||||||
"addresses" : "Adresy",
|
"addresses" : "Adresy",
|
||||||
"scan_qr_code" : "Zeskanuj kod QR, aby uzyskać adres",
|
"scan_qr_code_to_get_address" : "Zeskanuj kod QR, aby uzyskać adres",
|
||||||
"qr_fullscreen" : "Dotknij, aby otworzyć pełnoekranowy kod QR",
|
"qr_fullscreen" : "Dotknij, aby otworzyć pełnoekranowy kod QR",
|
||||||
"rename" : "Zmień nazwę",
|
"rename" : "Zmień nazwę",
|
||||||
"choose_account" : "Wybierz konto",
|
"choose_account" : "Wybierz konto",
|
||||||
|
@ -685,6 +685,11 @@
|
||||||
"arrive_in_this_address" : "${currency} ${tag}dotrze na ten adres",
|
"arrive_in_this_address" : "${currency} ${tag}dotrze na ten adres",
|
||||||
"do_not_send": "Nie wysyłaj",
|
"do_not_send": "Nie wysyłaj",
|
||||||
"error_dialog_content": "Ups, wystąpił błąd.\n\nPrześlij raport o awarii do naszego zespołu wsparcia, aby ulepszyć aplikację.",
|
"error_dialog_content": "Ups, wystąpił błąd.\n\nPrześlij raport o awarii do naszego zespołu wsparcia, aby ulepszyć aplikację.",
|
||||||
|
"scan_qr_code": "Skanowania QR code",
|
||||||
|
"cold_or_recover_wallet": "Dodaj zimny portfel lub odzyskaj portfel papierowy",
|
||||||
|
"please_wait": "Proszę czekać",
|
||||||
|
"sweeping_wallet": "Zamiatanie portfela",
|
||||||
|
"sweeping_wallet_alert": "To nie powinno zająć dużo czasu. NIE WYCHODŹ Z TEGO EKRANU, W PRZECIWNYM WYPADKU MOŻE ZOSTAĆ UTRACONA ŚRODKI",
|
||||||
"decimal_places_error": "Za dużo miejsc dziesiętnych",
|
"decimal_places_error": "Za dużo miejsc dziesiętnych",
|
||||||
"edit_node": "Edytuj węzeł",
|
"edit_node": "Edytuj węzeł",
|
||||||
"frozen_balance": "Zamrożona równowaga",
|
"frozen_balance": "Zamrożona równowaga",
|
||||||
|
|
|
@ -150,7 +150,7 @@
|
||||||
"receive_amount" : "Quantia",
|
"receive_amount" : "Quantia",
|
||||||
"subaddresses" : "Sub-endereços",
|
"subaddresses" : "Sub-endereços",
|
||||||
"addresses" : "Endereços",
|
"addresses" : "Endereços",
|
||||||
"scan_qr_code" : "Digitalize o código QR para obter o endereço",
|
"scan_qr_code_to_get_address" : "Digitalize o código QR para obter o endereço",
|
||||||
"qr_fullscreen" : "Toque para abrir o código QR em tela cheia",
|
"qr_fullscreen" : "Toque para abrir o código QR em tela cheia",
|
||||||
"rename" : "Renomear",
|
"rename" : "Renomear",
|
||||||
"choose_account" : "Escolha uma conta",
|
"choose_account" : "Escolha uma conta",
|
||||||
|
@ -684,6 +684,11 @@
|
||||||
"arrive_in_this_address" : "${currency} ${tag}chegará neste endereço",
|
"arrive_in_this_address" : "${currency} ${tag}chegará neste endereço",
|
||||||
"do_not_send": "não envie",
|
"do_not_send": "não envie",
|
||||||
"error_dialog_content": "Ops, houve algum erro.\n\nPor favor, envie o relatório de falha para nossa equipe de suporte para melhorar o aplicativo.",
|
"error_dialog_content": "Ops, houve algum erro.\n\nPor favor, envie o relatório de falha para nossa equipe de suporte para melhorar o aplicativo.",
|
||||||
|
"scan_qr_code": "Escanear código QR",
|
||||||
|
"cold_or_recover_wallet": "Adicione uma cold wallet ou recupere uma paper wallet",
|
||||||
|
"please_wait": "Por favor, aguarde",
|
||||||
|
"sweeping_wallet": "Carteira varrendo",
|
||||||
|
"sweeping_wallet_alert": "To nie powinno zająć dużo czasu. NIE WYCHODŹ Z TEGO EKRANU, W PRZECIWNYM WYPADKU MOŻE ZOSTAĆ UTRACONA ŚRODKI",
|
||||||
"decimal_places_error": "Muitas casas decimais",
|
"decimal_places_error": "Muitas casas decimais",
|
||||||
"edit_node": "Editar nó",
|
"edit_node": "Editar nó",
|
||||||
"frozen_balance": "Saldo Congelado",
|
"frozen_balance": "Saldo Congelado",
|
||||||
|
|
|
@ -150,7 +150,7 @@
|
||||||
"receive_amount" : "Сумма",
|
"receive_amount" : "Сумма",
|
||||||
"subaddresses" : "Субадреса",
|
"subaddresses" : "Субадреса",
|
||||||
"addresses" : "Адреса",
|
"addresses" : "Адреса",
|
||||||
"scan_qr_code" : "Отсканируйте QR-код для получения адреса",
|
"scan_qr_code_to_get_address" : "Отсканируйте QR-код для получения адреса",
|
||||||
"qr_fullscreen" : "Нажмите, чтобы открыть полноэкранный QR-код",
|
"qr_fullscreen" : "Нажмите, чтобы открыть полноэкранный QR-код",
|
||||||
"rename" : "Переименовать",
|
"rename" : "Переименовать",
|
||||||
"choose_account" : "Выберите аккаунт",
|
"choose_account" : "Выберите аккаунт",
|
||||||
|
@ -685,6 +685,11 @@
|
||||||
"arrive_in_this_address" : "${currency} ${tag}придет на этот адрес",
|
"arrive_in_this_address" : "${currency} ${tag}придет на этот адрес",
|
||||||
"do_not_send": "Не отправлять",
|
"do_not_send": "Не отправлять",
|
||||||
"error_dialog_content": "Ой, у нас какая-то ошибка.\n\nПожалуйста, отправьте отчет о сбое в нашу службу поддержки, чтобы сделать приложение лучше.",
|
"error_dialog_content": "Ой, у нас какая-то ошибка.\n\nПожалуйста, отправьте отчет о сбое в нашу службу поддержки, чтобы сделать приложение лучше.",
|
||||||
|
"scan_qr_code": "Сканировать QR-код",
|
||||||
|
"cold_or_recover_wallet": "Добавьте холодный кошелек или восстановите бумажный кошелек",
|
||||||
|
"please_wait": "Пожалуйста, подождите",
|
||||||
|
"sweeping_wallet": "Подметание кошелька",
|
||||||
|
"sweeping_wallet_alert": "Это не должно занять много времени. НЕ ПОКИДАЙТЕ ЭТОТ ЭКРАН, ИНАЧЕ ВЫЧИСЛЕННЫЕ СРЕДСТВА МОГУТ БЫТЬ ПОТЕРЯНЫ",
|
||||||
"decimal_places_error": "Слишком много десятичных знаков",
|
"decimal_places_error": "Слишком много десятичных знаков",
|
||||||
"edit_node": "Редактировать узел",
|
"edit_node": "Редактировать узел",
|
||||||
"frozen_balance": "Замороженный баланс",
|
"frozen_balance": "Замороженный баланс",
|
||||||
|
|
|
@ -150,7 +150,7 @@
|
||||||
"receive_amount" : "จำนวน",
|
"receive_amount" : "จำนวน",
|
||||||
"subaddresses" : "ที่อยู่ย่อย",
|
"subaddresses" : "ที่อยู่ย่อย",
|
||||||
"addresses" : "ที่อยู่",
|
"addresses" : "ที่อยู่",
|
||||||
"scan_qr_code" : "สแกน QR code เพื่อรับที่อยู่",
|
"scan_qr_code_to_get_address" : "สแกน QR code เพื่อรับที่อยู่",
|
||||||
"qr_fullscreen" : "แตะเพื่อเปิดหน้าจอ QR code แบบเต็มจอ",
|
"qr_fullscreen" : "แตะเพื่อเปิดหน้าจอ QR code แบบเต็มจอ",
|
||||||
"rename" : "เปลี่ยนชื่อ",
|
"rename" : "เปลี่ยนชื่อ",
|
||||||
"choose_account" : "เลือกบัญชี",
|
"choose_account" : "เลือกบัญชี",
|
||||||
|
@ -683,6 +683,11 @@
|
||||||
"arrive_in_this_address" : "${currency} ${tag}จะมาถึงที่อยู่นี้",
|
"arrive_in_this_address" : "${currency} ${tag}จะมาถึงที่อยู่นี้",
|
||||||
"do_not_send": "อย่าส่ง",
|
"do_not_send": "อย่าส่ง",
|
||||||
"error_dialog_content": "อ๊ะ เราพบข้อผิดพลาดบางอย่าง\n\nโปรดส่งรายงานข้อขัดข้องไปยังทีมสนับสนุนของเราเพื่อปรับปรุงแอปพลิเคชันให้ดียิ่งขึ้น",
|
"error_dialog_content": "อ๊ะ เราพบข้อผิดพลาดบางอย่าง\n\nโปรดส่งรายงานข้อขัดข้องไปยังทีมสนับสนุนของเราเพื่อปรับปรุงแอปพลิเคชันให้ดียิ่งขึ้น",
|
||||||
|
"scan_qr_code": "สแกนรหัส QR",
|
||||||
|
"cold_or_recover_wallet": "เพิ่มกระเป๋าเงินเย็นหรือกู้คืนกระเป๋าเงินกระดาษ",
|
||||||
|
"please_wait": "โปรดรอ",
|
||||||
|
"sweeping_wallet": "กวาดกระเป๋าสตางค์",
|
||||||
|
"sweeping_wallet_alert": "การดำเนินการนี้ใช้เวลาไม่นาน อย่าออกจากหน้าจอนี้ มิฉะนั้นเงินที่กวาดไปอาจสูญหาย",
|
||||||
"decimal_places_error": "ทศนิยมมากเกินไป",
|
"decimal_places_error": "ทศนิยมมากเกินไป",
|
||||||
"edit_node": "แก้ไขโหนด",
|
"edit_node": "แก้ไขโหนด",
|
||||||
"frozen_balance": "ยอดคงเหลือแช่แข็ง",
|
"frozen_balance": "ยอดคงเหลือแช่แข็ง",
|
||||||
|
|
|
@ -150,7 +150,7 @@
|
||||||
"receive_amount" : "Miktar",
|
"receive_amount" : "Miktar",
|
||||||
"subaddresses" : "Alt adresler",
|
"subaddresses" : "Alt adresler",
|
||||||
"addresses" : "Adresler",
|
"addresses" : "Adresler",
|
||||||
"scan_qr_code" : "Adresi getirmek için QR kodunu tara",
|
"scan_qr_code_to_get_address" : "Adresi getirmek için QR kodunu tara",
|
||||||
"qr_fullscreen" : "QR kodunu tam ekranda açmak için dokun",
|
"qr_fullscreen" : "QR kodunu tam ekranda açmak için dokun",
|
||||||
"rename" : "Yeniden adlandır",
|
"rename" : "Yeniden adlandır",
|
||||||
"choose_account" : "Hesabı seç",
|
"choose_account" : "Hesabı seç",
|
||||||
|
@ -685,6 +685,11 @@
|
||||||
"arrive_in_this_address" : "${currency} ${tag}bu adrese ulaşacak",
|
"arrive_in_this_address" : "${currency} ${tag}bu adrese ulaşacak",
|
||||||
"do_not_send": "Gönderme",
|
"do_not_send": "Gönderme",
|
||||||
"error_dialog_content": "Hay aksi, bir hatamız var.\n\nUygulamayı daha iyi hale getirmek için lütfen kilitlenme raporunu destek ekibimize gönderin.",
|
"error_dialog_content": "Hay aksi, bir hatamız var.\n\nUygulamayı daha iyi hale getirmek için lütfen kilitlenme raporunu destek ekibimize gönderin.",
|
||||||
|
"scan_qr_code": "QR kodunu tarayın",
|
||||||
|
"cold_or_recover_wallet": "Soğuk bir cüzdan ekleyin veya bir kağıt cüzdanı kurtarın",
|
||||||
|
"please_wait": "Lütfen bekleyin",
|
||||||
|
"sweeping_wallet": "Süpürme cüzdanı",
|
||||||
|
"sweeping_wallet_alert": "Bu uzun sürmemeli. BU EKRANDAN BIRAKMAYIN YOKSA SÜPÜRÜLEN FONLAR KAYBOLABİLİR",
|
||||||
"decimal_places_error": "Çok fazla ondalık basamak",
|
"decimal_places_error": "Çok fazla ondalık basamak",
|
||||||
"edit_node": "Düğümü Düzenle",
|
"edit_node": "Düğümü Düzenle",
|
||||||
"frozen_balance": "Dondurulmuş Bakiye",
|
"frozen_balance": "Dondurulmuş Bakiye",
|
||||||
|
|
|
@ -150,7 +150,7 @@
|
||||||
"receive_amount" : "Сума",
|
"receive_amount" : "Сума",
|
||||||
"subaddresses" : "Субадреси",
|
"subaddresses" : "Субадреси",
|
||||||
"addresses" : "Адреси",
|
"addresses" : "Адреси",
|
||||||
"scan_qr_code" : "Скануйте QR-код для одержання адреси",
|
"scan_qr_code_to_get_address" : "Скануйте QR-код для одержання адреси",
|
||||||
"qr_fullscreen" : "Торкніться, щоб відкрити QR-код на весь екран",
|
"qr_fullscreen" : "Торкніться, щоб відкрити QR-код на весь екран",
|
||||||
"rename" : "Перейменувати",
|
"rename" : "Перейменувати",
|
||||||
"choose_account" : "Оберіть акаунт",
|
"choose_account" : "Оберіть акаунт",
|
||||||
|
@ -684,6 +684,11 @@
|
||||||
"arrive_in_this_address" : "${currency} ${tag}надійде на цю адресу",
|
"arrive_in_this_address" : "${currency} ${tag}надійде на цю адресу",
|
||||||
"do_not_send": "Не надсилайте",
|
"do_not_send": "Не надсилайте",
|
||||||
"error_dialog_content": "На жаль, ми отримали помилку.\n\nБудь ласка, надішліть звіт про збій нашій команді підтримки, щоб покращити додаток.",
|
"error_dialog_content": "На жаль, ми отримали помилку.\n\nБудь ласка, надішліть звіт про збій нашій команді підтримки, щоб покращити додаток.",
|
||||||
|
"scan_qr_code": "Відскануйте QR-код",
|
||||||
|
"cold_or_recover_wallet": "Додайте холодний гаманець або відновіть паперовий гаманець",
|
||||||
|
"please_wait": "Будь ласка, зачекайте",
|
||||||
|
"sweeping_wallet": "Підмітаня гаманця",
|
||||||
|
"sweeping_wallet_alert": "Це не повинно зайняти багато часу. НЕ ЗАЛИШАЙТЕ ЦЬОГО ЕКРАНУ, АБО КОШТИ МОЖУТЬ БУТИ ВТРАЧЕНІ",
|
||||||
"decimal_places_error": "Забагато знаків після коми",
|
"decimal_places_error": "Забагато знаків після коми",
|
||||||
"edit_node": "Редагувати вузол",
|
"edit_node": "Редагувати вузол",
|
||||||
"frozen_balance": "Заморожений баланс",
|
"frozen_balance": "Заморожений баланс",
|
||||||
|
|
|
@ -150,7 +150,7 @@
|
||||||
"receive_amount" : "金额",
|
"receive_amount" : "金额",
|
||||||
"subaddresses" : "子地址",
|
"subaddresses" : "子地址",
|
||||||
"addresses" : "地址",
|
"addresses" : "地址",
|
||||||
"scan_qr_code" : "扫描二维码获取地址",
|
"scan_qr_code_to_get_address" : "扫描二维码获取地址",
|
||||||
"qr_fullscreen" : "点击打开全屏二维码",
|
"qr_fullscreen" : "点击打开全屏二维码",
|
||||||
"rename" : "重命名",
|
"rename" : "重命名",
|
||||||
"choose_account" : "选择账户",
|
"choose_account" : "选择账户",
|
||||||
|
@ -684,6 +684,11 @@
|
||||||
"arrive_in_this_address" : "${currency} ${tag}将到达此地址",
|
"arrive_in_this_address" : "${currency} ${tag}将到达此地址",
|
||||||
"do_not_send": "不要发送",
|
"do_not_send": "不要发送",
|
||||||
"error_dialog_content": "糟糕,我们遇到了一些错误。\n\n请将崩溃报告发送给我们的支持团队,以改进应用程序。",
|
"error_dialog_content": "糟糕,我们遇到了一些错误。\n\n请将崩溃报告发送给我们的支持团队,以改进应用程序。",
|
||||||
|
"scan_qr_code": "扫描二维码",
|
||||||
|
"cold_or_recover_wallet": "添加冷钱包或恢复纸钱包",
|
||||||
|
"please_wait": "请稍等",
|
||||||
|
"sweeping_wallet": "扫一扫钱包",
|
||||||
|
"sweeping_wallet_alert": "\n这应该不会花很长时间。请勿离开此屏幕,否则可能会丢失所掠取的资金",
|
||||||
"decimal_places_error": "小数位太多",
|
"decimal_places_error": "小数位太多",
|
||||||
"edit_node": "编辑节点",
|
"edit_node": "编辑节点",
|
||||||
"frozen_balance": "冻结余额",
|
"frozen_balance": "冻结余额",
|
||||||
|
|
Loading…
Reference in a new issue