mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2024-12-23 03:59:23 +00:00
feat: Implement sweep all
This commit is contained in:
parent
857e355ee6
commit
49734332a1
6 changed files with 166 additions and 63 deletions
|
@ -260,6 +260,17 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
|
|||
final amount =
|
||||
output.sendAll ? null : output.cryptoAmount!.replaceAll(',', '.');
|
||||
|
||||
final unlockedBalance = balance[currency]?.unlockedBalance;
|
||||
|
||||
if (unlockedBalance == null || unlockedBalance == 0) {
|
||||
final formattedBalance =
|
||||
moneroAmountToString(amount: unlockedBalance ?? 0);
|
||||
|
||||
throw MoneroTransactionCreationException(
|
||||
'You do not have enough unlocked balance. Unlocked: $formattedBalance. Transaction amount: ${output.cryptoAmount}.',
|
||||
);
|
||||
}
|
||||
|
||||
pendingTransactionDescription = await transaction_history.createTransaction(
|
||||
address: address!,
|
||||
amount: amount,
|
||||
|
@ -454,8 +465,10 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
|
|||
syncStatus = SyncedSyncStatus();
|
||||
//! Introduce completer
|
||||
if (!syncCompleter.isCompleted) {
|
||||
if (blocksLeft == 0) {
|
||||
syncCompleter.complete();
|
||||
}
|
||||
}
|
||||
if (!_hasSyncAfterStartup) {
|
||||
_hasSyncAfterStartup = true;
|
||||
await save();
|
||||
|
|
|
@ -19,6 +19,7 @@ import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_wallet
|
|||
import 'package:cake_wallet/src/screens/dashboard/widgets/transactions_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/restore/sweeping_wallet_page.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/display_settings_page.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/other_settings_page.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/privacy_page.dart';
|
||||
|
@ -59,6 +60,7 @@ 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_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/restore/restore_wallet.dart';
|
||||
import 'package:cake_wallet/view_model/set_up_2fa_viewmodel.dart';
|
||||
import 'package:cake_wallet/view_model/restore/restore_from_qr_vm.dart';
|
||||
import 'package:cake_wallet/view_model/settings/display_settings_view_model.dart';
|
||||
|
@ -808,6 +810,11 @@ Future setup({
|
|||
getIt.registerFactoryParam<RestoreOptionsPage, bool, void>(
|
||||
(bool isNewInstall, _) => RestoreOptionsPage(isNewInstall: isNewInstall));
|
||||
|
||||
getIt.registerFactoryParam<SweepingWalletPage, SweepingWalletPageData, void>(
|
||||
(sweepingWalletPageData, _) =>
|
||||
SweepingWalletPage(sweepingWalletPageData: sweepingWalletPageData),
|
||||
);
|
||||
|
||||
getIt.registerFactory(() => RestoreFromBackupViewModel(getIt.get<BackupService>()));
|
||||
|
||||
getIt.registerFactory(() => RestoreFromBackupPage(getIt.get<RestoreFromBackupViewModel>()));
|
||||
|
|
|
@ -199,7 +199,10 @@ Route<dynamic> createRoute(RouteSettings settings) {
|
|||
|
||||
case Routes.sweepingWalletPage:
|
||||
return CupertinoPageRoute<void>(
|
||||
builder: (_) => getIt.get<SweepingWalletPage>());
|
||||
builder: (_) => getIt.get<SweepingWalletPage>(
|
||||
param1: settings.arguments as SweepingWalletPageData,
|
||||
),
|
||||
);
|
||||
|
||||
case Routes.dashboard:
|
||||
return CupertinoPageRoute<void>(
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
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/screens/restore/sweeping_wallet_page.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/responsive_layout_util.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/wallet_type_utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
|
@ -37,8 +36,13 @@ class RestoreOptionsPage extends BasePage {
|
|||
child: Column(
|
||||
children: <Widget>[
|
||||
RestoreButton(
|
||||
onPressed: () => Navigator.pushNamed(context, Routes.restoreWalletFromSeedKeys,
|
||||
arguments: isNewInstall),
|
||||
onPressed: () {
|
||||
Navigator.pushNamed(
|
||||
context,
|
||||
Routes.restoreWalletFromSeedKeys,
|
||||
arguments: isNewInstall,
|
||||
);
|
||||
},
|
||||
image: imageSeedKeys,
|
||||
title: S.of(context).restore_title_from_seed_keys,
|
||||
description: S.of(context).restore_description_from_seed_keys),
|
||||
|
@ -49,7 +53,9 @@ class RestoreOptionsPage extends BasePage {
|
|||
onPressed: () => Navigator.pushNamed(context, Routes.restoreFromBackup),
|
||||
image: imageBackup,
|
||||
title: S.of(context).restore_title_from_backup,
|
||||
description: S.of(context).restore_description_from_backup),
|
||||
description:
|
||||
S.of(context).restore_description_from_backup,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 24),
|
||||
|
@ -61,24 +67,46 @@ class RestoreOptionsPage extends BasePage {
|
|||
arguments: (PinCodeState<PinCodeWidget> setupPinContext, String _) {
|
||||
setupPinContext.close();
|
||||
isPinSet = true;
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
if (!isNewInstall || isPinSet) {
|
||||
try {
|
||||
final restoreWallet =
|
||||
await WalletRestoreFromQRCode.scanQRCodeForRestoring(context);
|
||||
final restoreWallet = await WalletRestoreFromQRCode
|
||||
.scanQRCodeForRestoring(context);
|
||||
|
||||
final restoreFromQRViewModel =
|
||||
getIt.get<WalletRestorationFromQRVM>(param1: restoreWallet.type);
|
||||
getIt.get<WalletRestorationFromQRVM>(
|
||||
param1: restoreWallet.type,
|
||||
);
|
||||
|
||||
await restoreFromQRViewModel.create(restoreWallet: restoreWallet);
|
||||
if (restoreWallet.txId != null &&
|
||||
restoreWallet.txId!.isNotEmpty) {
|
||||
Navigator.pushNamed(
|
||||
context,
|
||||
Routes.sweepingWalletPage,
|
||||
arguments: SweepingWalletPageData(
|
||||
restorationFromQRVM: restoreFromQRViewModel,
|
||||
restoredWallet: restoreWallet,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
await restoreFromQRViewModel.create(
|
||||
restoreWallet: restoreWallet,
|
||||
);
|
||||
|
||||
if (restoreFromQRViewModel.state is FailureState) {
|
||||
final errorState = restoreFromQRViewModel.state as FailureState;
|
||||
_onWalletCreateFailure(context,
|
||||
'Create wallet state: ${errorState.error}');
|
||||
if (restoreFromQRViewModel.state
|
||||
is FailureState) {
|
||||
final errorState = restoreFromQRViewModel.state
|
||||
as FailureState;
|
||||
|
||||
_onWalletCreateFailure(
|
||||
context,
|
||||
'Create wallet state: ${errorState.error}',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
_onWalletCreateFailure(context, e.toString());
|
||||
}
|
||||
|
@ -94,15 +122,19 @@ class RestoreOptionsPage extends BasePage {
|
|||
);
|
||||
}
|
||||
|
||||
void _onWalletCreateFailure(BuildContext context, String error) {
|
||||
showPopUp<void>(
|
||||
void _onWalletCreateFailure(BuildContext context, String error) async {
|
||||
await 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());
|
||||
});
|
||||
buttonAction: () => Navigator.of(context).pop(),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
Navigator.pop(context);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +1,23 @@
|
|||
import 'package:cake_wallet/core/execution_state.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
|
||||
import 'package:cake_wallet/themes/theme_base.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/restore_wallet.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();
|
||||
SweepingWalletPage({required this.sweepingWalletPageData});
|
||||
|
||||
final SweepingWalletPageData sweepingWalletPageData;
|
||||
|
||||
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(
|
||||
|
@ -23,23 +28,31 @@ class SweepingWalletPage extends BasePage {
|
|||
|
||||
@override
|
||||
Widget body(BuildContext context) {
|
||||
final welcomeImage = currentTheme.type == ThemeType.dark ? welcomeImageDark : welcomeImageLight;
|
||||
final welcomeImage = currentTheme.type == ThemeType.dark
|
||||
? welcomeImageDark
|
||||
: welcomeImageLight;
|
||||
|
||||
return SweepingWalletWidget(
|
||||
aspectRatioImage: aspectRatioImage,
|
||||
welcomeImage: welcomeImage,
|
||||
restoredWallet: sweepingWalletPageData.restoredWallet,
|
||||
aspectRatioImage: aspectRatioImage,
|
||||
restoreFromQRViewModel: sweepingWalletPageData.restorationFromQRVM,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class SweepingWalletWidget extends StatefulWidget {
|
||||
const SweepingWalletWidget({
|
||||
required this.aspectRatioImage,
|
||||
required this.welcomeImage,
|
||||
required this.restoredWallet,
|
||||
required this.aspectRatioImage,
|
||||
required this.restoreFromQRViewModel,
|
||||
});
|
||||
|
||||
final double aspectRatioImage;
|
||||
final Image welcomeImage;
|
||||
final double aspectRatioImage;
|
||||
final RestoredWallet restoredWallet;
|
||||
final WalletRestorationFromQRVM restoreFromQRViewModel;
|
||||
|
||||
@override
|
||||
State<SweepingWalletWidget> createState() => _SweepingWalletWidgetState();
|
||||
|
@ -49,11 +62,42 @@ class _SweepingWalletWidgetState extends State<SweepingWalletWidget> {
|
|||
@override
|
||||
void initState() {
|
||||
SchedulerBinding.instance.addPostFrameCallback((_) async {
|
||||
|
||||
await _initializeRestoreFromQR();
|
||||
});
|
||||
super.initState();
|
||||
}
|
||||
|
||||
Future<void> _initializeRestoreFromQR() async {
|
||||
try {
|
||||
await widget.restoreFromQRViewModel
|
||||
.createFlowForSweepAll(restoreWallet: widget.restoredWallet);
|
||||
|
||||
if (widget.restoreFromQRViewModel.state is FailureState) {
|
||||
final errorState = widget.restoreFromQRViewModel.state as FailureState;
|
||||
_onWalletCreateFailure(
|
||||
context, 'Create wallet state: ${errorState.error}');
|
||||
}
|
||||
} catch (e) {
|
||||
_onWalletCreateFailure(context, e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
void _onWalletCreateFailure(BuildContext context, String error) async {
|
||||
await 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(),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
Navigator.pop(context);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return WillPopScope(
|
||||
|
@ -61,15 +105,20 @@ class _SweepingWalletWidgetState extends State<SweepingWalletWidget> {
|
|||
child: Container(
|
||||
padding: EdgeInsets.only(top: 64, bottom: 24, left: 24, right: 24),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Flexible(
|
||||
flex: 2,
|
||||
flex: 4,
|
||||
child: AspectRatio(
|
||||
aspectRatio: widget.aspectRatioImage,
|
||||
child: FittedBox(child: widget.welcomeImage, fit: BoxFit.fill))),
|
||||
child: FittedBox(
|
||||
child: widget.welcomeImage,
|
||||
fit: BoxFit.fill,
|
||||
),
|
||||
),
|
||||
),
|
||||
Flexible(
|
||||
flex: 3,
|
||||
flex: 2,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: <Widget>[
|
||||
|
@ -83,7 +132,7 @@ class _SweepingWalletWidgetState extends State<SweepingWalletWidget> {
|
|||
fontSize: 18,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Theme.of(context)
|
||||
.accentTextTheme!
|
||||
.accentTextTheme
|
||||
.displayMedium!
|
||||
.color,
|
||||
),
|
||||
|
@ -98,7 +147,7 @@ class _SweepingWalletWidgetState extends State<SweepingWalletWidget> {
|
|||
fontSize: 36,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Theme.of(context)
|
||||
.primaryTextTheme!
|
||||
.primaryTextTheme
|
||||
.titleLarge!
|
||||
.color!,
|
||||
),
|
||||
|
@ -113,7 +162,7 @@ class _SweepingWalletWidgetState extends State<SweepingWalletWidget> {
|
|||
fontSize: 16,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Theme.of(context)
|
||||
.accentTextTheme!
|
||||
.accentTextTheme
|
||||
.displayMedium!
|
||||
.color,
|
||||
),
|
||||
|
@ -129,4 +178,12 @@ class _SweepingWalletWidgetState extends State<SweepingWalletWidget> {
|
|||
}
|
||||
}
|
||||
|
||||
class SweepingWalletPageData {
|
||||
final WalletRestorationFromQRVM restorationFromQRVM;
|
||||
final RestoredWallet restoredWallet;
|
||||
|
||||
SweepingWalletPageData({
|
||||
required this.restorationFromQRVM,
|
||||
required this.restoredWallet,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -68,18 +68,7 @@ abstract class WalletCreationVMBase with Store {
|
|||
bool typeExists(WalletType type) => walletCreationService.typeExists(type);
|
||||
|
||||
Future<void> create({dynamic options, RestoredWallet? restoreWallet}) async {
|
||||
// if (restoreWallet != null &&
|
||||
// restoreWallet.restoreMode == WalletRestoreMode.txids) {
|
||||
await _createFlowForSweepAll(options, restoreWallet);
|
||||
// }
|
||||
|
||||
// await _createTransactionFlowNormally(options, restoreWallet);
|
||||
}
|
||||
|
||||
Future<void> _createTransactionFlowNormally(
|
||||
dynamic options,
|
||||
RestoredWallet? restoreWallet,
|
||||
) async {
|
||||
print('Inside normal create function');
|
||||
try {
|
||||
final restoredWallet = await _createNewWalletWithoutSwitching(
|
||||
options: options,
|
||||
|
@ -104,10 +93,11 @@ abstract class WalletCreationVMBase with Store {
|
|||
}
|
||||
}
|
||||
|
||||
Future<void> _createFlowForSweepAll(
|
||||
Future<void> createFlowForSweepAll({
|
||||
dynamic options,
|
||||
RestoredWallet? restoreWallet,
|
||||
) async {
|
||||
}) async {
|
||||
print('Inside sweep all create function');
|
||||
state = IsExecutingState();
|
||||
final type = restoreWallet?.type ?? this.type;
|
||||
|
||||
|
@ -195,7 +185,7 @@ abstract class WalletCreationVMBase with Store {
|
|||
name: name,
|
||||
type: type,
|
||||
//TODO(David): Ask Omar about this, was previous isRecovery
|
||||
isRecovery: restoreWallet != null ? true : false,
|
||||
isRecovery: restoreWallet != null,
|
||||
restoreHeight: credentials.height ?? 0,
|
||||
date: DateTime.now(),
|
||||
path: path,
|
||||
|
@ -311,7 +301,8 @@ abstract class WalletCreationVMBase with Store {
|
|||
Future<void> _createTransaction(WalletBase wallet, Object credentials) async {
|
||||
try {
|
||||
print('about to enter wallet create transaction function');
|
||||
pendingTransaction = await wallet.createTransaction(credentials);
|
||||
pendingTransaction =
|
||||
await wallet.createTransactionForSweepAll(credentials);
|
||||
} catch (e) {
|
||||
state = FailureState(e.toString());
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue