Merge branch 'staging' into add-xtz

# Conflicts:
#	lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart
#	lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart
#	lib/widgets/node_card.dart
This commit is contained in:
ryleedavis 2023-08-23 10:53:34 -06:00
commit cceab1a036
79 changed files with 1408 additions and 331 deletions

View file

@ -123,7 +123,7 @@ flutter run android
Note on Emulators: Only x86_64 emulators are supported, x86 emulators will not work
#### Linux
Plug in your android device or use the emulator available via Android Studio and then run the following commands:
Run the following commands or launch via Android Studio:
```
flutter pub get
flutter run linux

View file

@ -9,6 +9,7 @@
*/
import 'dart:convert';
import 'dart:math';
import 'package:stackwallet/db/hive/db.dart';
import 'package:stackwallet/electrumx_rpc/electrumx.dart';
@ -157,7 +158,6 @@ class CachedElectrumX {
Future<List<String>> getUsedCoinSerials({
required Coin coin,
int startNumber = 0,
}) async {
try {
final box = await DB.instance.getUsedSerialsCacheBox(coin: coin);
@ -168,7 +168,7 @@ class CachedElectrumX {
_list == null ? {} : List<String>.from(_list).toSet();
final startNumber =
cachedSerials.length - 10; // 10 being some arbitrary buffer
max(0, cachedSerials.length - 100); // 100 being some arbitrary buffer
final serials = await electrumXClient.getUsedCoinSerials(
startNumber: startNumber,

View file

@ -14,6 +14,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/notifications/show_flush_bar.dart';
import 'package:stackwallet/pages/add_wallet_views/create_or_restore_wallet_view/sub_widgets/coin_image.dart';
import 'package:stackwallet/pages/add_wallet_views/new_wallet_options/new_wallet_options_view.dart';
import 'package:stackwallet/pages/add_wallet_views/new_wallet_recovery_phrase_warning_view/new_wallet_recovery_phrase_warning_view.dart';
import 'package:stackwallet/pages/add_wallet_views/restore_wallet_view/restore_options_view/restore_options_view.dart';
import 'package:stackwallet/pages_desktop_specific/my_stack_view/exit_to_my_stack_button.dart';
@ -336,7 +337,11 @@ class _NameYourWalletViewState extends ConsumerState<NameYourWalletView> {
ref.read(walletsServiceChangeNotifierProvider);
final name = textEditingController.text;
if (await walletsService.checkForDuplicate(name)) {
final hasDuplicateName =
await walletsService.checkForDuplicate(name);
if (mounted) {
if (hasDuplicateName) {
unawaited(showFloatingFlushBar(
type: FlushBarType.warning,
message: "Wallet name already in use.",
@ -352,34 +357,44 @@ class _NameYourWalletViewState extends ConsumerState<NameYourWalletView> {
}
if (mounted) {
ref
.read(mnemonicWordCountStateProvider.state)
.state =
Constants.possibleLengthsForCoin(coin).last;
ref.read(pNewWalletOptions.notifier).state = null;
switch (widget.addWalletType) {
case AddWalletType.New:
unawaited(Navigator.of(context).pushNamed(
NewWalletRecoveryPhraseWarningView.routeName,
unawaited(
Navigator.of(context).pushNamed(
coin.hasMnemonicPassphraseSupport
? NewWalletOptionsView.routeName
: NewWalletRecoveryPhraseWarningView
.routeName,
arguments: Tuple2(
name,
coin,
),
));
),
);
break;
case AddWalletType.Restore:
ref
.read(mnemonicWordCountStateProvider.state)
.state = Constants.possibleLengthsForCoin(
coin)
.first;
unawaited(Navigator.of(context).pushNamed(
unawaited(
Navigator.of(context).pushNamed(
RestoreOptionsView.routeName,
arguments: Tuple2(
name,
coin,
),
));
),
);
break;
}
}
}
}
}
: null,
style: _nextEnabled
? Theme.of(context)

View file

@ -0,0 +1,410 @@
import 'package:dropdown_button2/dropdown_button2.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:stackwallet/pages/add_wallet_views/create_or_restore_wallet_view/sub_widgets/coin_image.dart';
import 'package:stackwallet/pages/add_wallet_views/new_wallet_recovery_phrase_warning_view/new_wallet_recovery_phrase_warning_view.dart';
import 'package:stackwallet/pages/add_wallet_views/restore_wallet_view/restore_options_view/sub_widgets/mobile_mnemonic_length_selector.dart';
import 'package:stackwallet/pages/add_wallet_views/restore_wallet_view/sub_widgets/mnemonic_word_count_select_sheet.dart';
import 'package:stackwallet/pages_desktop_specific/my_stack_view/exit_to_my_stack_button.dart';
import 'package:stackwallet/providers/ui/verify_recovery_phrase/mnemonic_word_count_state_provider.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/widgets/background.dart';
import 'package:stackwallet/widgets/conditional_parent.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
import 'package:stackwallet/widgets/desktop/desktop_app_bar.dart';
import 'package:stackwallet/widgets/desktop/desktop_scaffold.dart';
import 'package:stackwallet/widgets/desktop/primary_button.dart';
import 'package:stackwallet/widgets/rounded_white_container.dart';
import 'package:stackwallet/widgets/stack_text_field.dart';
import 'package:tuple/tuple.dart';
final pNewWalletOptions =
StateProvider<({String mnemonicPassphrase, int mnemonicWordsCount})?>(
(ref) => null);
enum NewWalletOptions {
Default,
Advanced;
}
class NewWalletOptionsView extends ConsumerStatefulWidget {
const NewWalletOptionsView({
Key? key,
required this.walletName,
required this.coin,
}) : super(key: key);
static const routeName = "/newWalletOptionsView";
final String walletName;
final Coin coin;
@override
ConsumerState<NewWalletOptionsView> createState() =>
_NewWalletOptionsViewState();
}
class _NewWalletOptionsViewState extends ConsumerState<NewWalletOptionsView> {
late final FocusNode passwordFocusNode;
late final TextEditingController passwordController;
bool hidePassword = true;
NewWalletOptions _selectedOptions = NewWalletOptions.Default;
@override
void initState() {
passwordController = TextEditingController();
passwordFocusNode = FocusNode();
super.initState();
}
@override
void dispose() {
passwordController.dispose();
passwordFocusNode.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final lengths = Constants.possibleLengthsForCoin(widget.coin).toList();
return ConditionalParent(
condition: Util.isDesktop,
builder: (child) => DesktopScaffold(
background: Theme.of(context).extension<StackColors>()!.background,
appBar: const DesktopAppBar(
isCompactHeight: false,
leading: AppBarBackButton(),
trailing: ExitToMyStackButton(),
),
body: SizedBox(
width: 480,
child: child,
),
),
child: ConditionalParent(
condition: !Util.isDesktop,
builder: (child) => Background(
child: Scaffold(
backgroundColor:
Theme.of(context).extension<StackColors>()!.background,
appBar: AppBar(
leading: const AppBarBackButton(),
title: Text(
"Wallet Options",
style: STextStyles.navBarTitle(context),
),
),
body: SafeArea(
child: LayoutBuilder(
builder: (context, constraints) {
return SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(
minHeight: constraints.maxHeight,
),
child: IntrinsicHeight(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: child,
),
),
),
);
},
),
),
),
),
child: Column(
children: [
if (Util.isDesktop)
const Spacer(
flex: 10,
),
if (!Util.isDesktop)
const SizedBox(
height: 16,
),
if (!Util.isDesktop)
CoinImage(
coin: widget.coin,
height: 100,
width: 100,
),
if (Util.isDesktop)
Text(
"Wallet options",
textAlign: TextAlign.center,
style: Util.isDesktop
? STextStyles.desktopH2(context)
: STextStyles.pageTitleH1(context),
),
SizedBox(
height: Util.isDesktop ? 32 : 16,
),
DropdownButtonHideUnderline(
child: DropdownButton2<NewWalletOptions>(
value: _selectedOptions,
items: [
...NewWalletOptions.values.map(
(e) => DropdownMenuItem(
value: e,
child: Text(
e.name,
style: STextStyles.desktopTextMedium(context),
),
),
),
],
onChanged: (value) {
if (value is NewWalletOptions) {
setState(() {
_selectedOptions = value;
});
}
},
isExpanded: true,
iconStyleData: IconStyleData(
icon: SvgPicture.asset(
Assets.svg.chevronDown,
width: 12,
height: 6,
color: Theme.of(context)
.extension<StackColors>()!
.textFieldActiveSearchIconRight,
),
),
dropdownStyleData: DropdownStyleData(
offset: const Offset(0, -10),
elevation: 0,
decoration: BoxDecoration(
color: Theme.of(context)
.extension<StackColors>()!
.textFieldDefaultBG,
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,
),
),
),
menuItemStyleData: const MenuItemStyleData(
padding: EdgeInsets.symmetric(
horizontal: 16,
vertical: 8,
),
),
),
),
const SizedBox(
height: 24,
),
if (_selectedOptions == NewWalletOptions.Advanced)
Column(
children: [
if (Util.isDesktop)
DropdownButtonHideUnderline(
child: DropdownButton2<int>(
value: ref
.watch(mnemonicWordCountStateProvider.state)
.state,
items: [
...lengths.map(
(e) => DropdownMenuItem(
value: e,
child: Text(
"$e word seed",
style: STextStyles.desktopTextMedium(context),
),
),
),
],
onChanged: (value) {
if (value is int) {
ref
.read(mnemonicWordCountStateProvider.state)
.state = value;
}
},
isExpanded: true,
iconStyleData: IconStyleData(
icon: SvgPicture.asset(
Assets.svg.chevronDown,
width: 12,
height: 6,
color: Theme.of(context)
.extension<StackColors>()!
.textFieldActiveSearchIconRight,
),
),
dropdownStyleData: DropdownStyleData(
offset: const Offset(0, -10),
elevation: 0,
decoration: BoxDecoration(
color: Theme.of(context)
.extension<StackColors>()!
.textFieldDefaultBG,
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,
),
),
),
menuItemStyleData: const MenuItemStyleData(
padding: EdgeInsets.symmetric(
horizontal: 16,
vertical: 8,
),
),
),
),
if (!Util.isDesktop)
MobileMnemonicLengthSelector(
chooseMnemonicLength: () {
showModalBottomSheet<dynamic>(
backgroundColor: Colors.transparent,
context: context,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(
top: Radius.circular(20),
),
),
builder: (_) {
return MnemonicWordCountSelectSheet(
lengthOptions: lengths,
);
},
);
},
),
const SizedBox(
height: 24,
),
RoundedWhiteContainer(
child: Center(
child: Text(
"You may add a BIP39 passphrase. This is optional. "
"You will need BOTH you seed and your passphrase to recover the wallet.",
style: Util.isDesktop
? STextStyles.desktopTextExtraSmall(context)
.copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textSubtitle1,
)
: STextStyles.itemSubtitle(context),
),
),
),
const SizedBox(
height: 8,
),
ClipRRect(
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,
),
child: TextField(
key: const Key("mnemonicPassphraseFieldKey1"),
focusNode: passwordFocusNode,
controller: passwordController,
style: Util.isDesktop
? STextStyles.desktopTextMedium(context).copyWith(
height: 2,
)
: STextStyles.field(context),
obscureText: hidePassword,
enableSuggestions: false,
autocorrect: false,
decoration: standardInputDecoration(
"BIP39 passphrase",
passwordFocusNode,
context,
).copyWith(
suffixIcon: UnconstrainedBox(
child: ConditionalParent(
condition: Util.isDesktop,
builder: (child) => SizedBox(
height: 70,
child: child,
),
child: Row(
children: [
SizedBox(
width: Util.isDesktop ? 24 : 16,
),
GestureDetector(
key: const Key(
"mnemonicPassphraseFieldShowPasswordButtonKey"),
onTap: () async {
setState(() {
hidePassword = !hidePassword;
});
},
child: SvgPicture.asset(
hidePassword
? Assets.svg.eye
: Assets.svg.eyeSlash,
color: Theme.of(context)
.extension<StackColors>()!
.textDark3,
width: Util.isDesktop ? 24 : 16,
height: Util.isDesktop ? 24 : 16,
),
),
const SizedBox(
width: 12,
),
],
),
),
),
),
),
),
],
),
if (!Util.isDesktop) const Spacer(),
SizedBox(
height: Util.isDesktop ? 32 : 16,
),
PrimaryButton(
label: "Continue",
onPressed: () {
if (_selectedOptions == NewWalletOptions.Advanced) {
ref.read(pNewWalletOptions.notifier).state = (
mnemonicWordsCount:
ref.read(mnemonicWordCountStateProvider.state).state,
mnemonicPassphrase: passwordController.text,
);
} else {
ref.read(pNewWalletOptions.notifier).state = null;
}
Navigator.of(context).pushNamed(
NewWalletRecoveryPhraseWarningView.routeName,
arguments: Tuple2(
widget.walletName,
widget.coin,
),
);
},
),
if (!Util.isDesktop)
const SizedBox(
height: 16,
),
if (Util.isDesktop)
const Spacer(
flex: 15,
),
],
),
),
);
}
}

View file

@ -13,6 +13,7 @@ import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:stackwallet/pages/add_wallet_views/new_wallet_options/new_wallet_options_view.dart';
import 'package:stackwallet/pages/add_wallet_views/new_wallet_recovery_phrase_view/new_wallet_recovery_phrase_view.dart';
import 'package:stackwallet/pages/add_wallet_views/new_wallet_recovery_phrase_warning_view/recovery_phrase_explanation_dialog.dart';
import 'package:stackwallet/pages_desktop_specific/my_stack_view/exit_to_my_stack_button.dart';
@ -38,7 +39,7 @@ import 'package:stackwallet/widgets/rounded_container.dart';
import 'package:stackwallet/widgets/rounded_white_container.dart';
import 'package:tuple/tuple.dart';
class NewWalletRecoveryPhraseWarningView extends StatefulWidget {
class NewWalletRecoveryPhraseWarningView extends ConsumerStatefulWidget {
const NewWalletRecoveryPhraseWarningView({
Key? key,
required this.coin,
@ -51,12 +52,12 @@ class NewWalletRecoveryPhraseWarningView extends StatefulWidget {
final String walletName;
@override
State<NewWalletRecoveryPhraseWarningView> createState() =>
ConsumerState<NewWalletRecoveryPhraseWarningView> createState() =>
_NewWalletRecoveryPhraseWarningViewState();
}
class _NewWalletRecoveryPhraseWarningViewState
extends State<NewWalletRecoveryPhraseWarningView> {
extends ConsumerState<NewWalletRecoveryPhraseWarningView> {
late final Coin coin;
late final String walletName;
late final bool isDesktop;
@ -72,6 +73,10 @@ class _NewWalletRecoveryPhraseWarningViewState
@override
Widget build(BuildContext context) {
debugPrint("BUILD: $runtimeType");
final options = ref.read(pNewWalletOptions.state).state;
final seedCount = options?.mnemonicWordsCount ??
Constants.defaultSeedPhraseLengthFor(coin: coin);
return MasterScaffold(
isDesktop: isDesktop,
@ -172,7 +177,7 @@ class _NewWalletRecoveryPhraseWarningViewState
child: isDesktop
? Text(
"On the next screen you will see "
"${Constants.defaultSeedPhraseLengthFor(coin: coin)} "
"$seedCount "
"words that make up your recovery phrase.\n\nPlease "
"write it down. Keep it safe and never share it with "
"anyone. Your recovery phrase is the only way you can"
@ -216,9 +221,7 @@ class _NewWalletRecoveryPhraseWarningViewState
),
),
TextSpan(
text:
"${Constants.defaultSeedPhraseLengthFor(coin: coin)}"
" words",
text: "$seedCount words",
style: STextStyles.desktopH3(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
@ -496,7 +499,24 @@ class _NewWalletRecoveryPhraseWarningViewState
final manager = Manager(wallet);
await manager.initializeNew();
if (coin.hasMnemonicPassphraseSupport &&
ref
.read(pNewWalletOptions.state)
.state !=
null) {
await manager.initializeNew((
mnemonicPassphrase: ref
.read(pNewWalletOptions.state)
.state!
.mnemonicPassphrase,
wordCount: ref
.read(pNewWalletOptions.state)
.state!
.mnemonicWordsCount,
));
} else {
await manager.initializeNew(null);
}
// pop progress dialog
if (mounted) {

View file

@ -535,7 +535,7 @@ class _RestoreOptionsViewState extends ConsumerState<RestoreOptionsView> {
enableSuggestions: false,
autocorrect: false,
decoration: standardInputDecoration(
"Recovery phrase password",
"BIP39 passphrase",
passwordFocusNode,
context,
).copyWith(
@ -586,7 +586,9 @@ class _RestoreOptionsViewState extends ConsumerState<RestoreOptionsView> {
RoundedWhiteContainer(
child: Center(
child: Text(
"If the recovery phrase you are about to restore was created with an optional passphrase you can enter it here.",
"If the recovery phrase you are about to restore "
"was created with an optional BIP39 passphrase "
"you can enter it here.",
style: isDesktop
? STextStyles.desktopTextExtraSmall(context)
.copyWith(

View file

@ -0,0 +1,218 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:stackwallet/notifications/show_flush_bar.dart';
import 'package:stackwallet/pages/add_wallet_views/new_wallet_options/new_wallet_options_view.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/widgets/conditional_parent.dart';
import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart';
import 'package:stackwallet/widgets/desktop/primary_button.dart';
import 'package:stackwallet/widgets/desktop/secondary_button.dart';
import 'package:stackwallet/widgets/stack_dialog.dart';
import 'package:stackwallet/widgets/stack_text_field.dart';
class VerifyMnemonicPassphraseDialog extends ConsumerStatefulWidget {
const VerifyMnemonicPassphraseDialog({super.key});
@override
ConsumerState<VerifyMnemonicPassphraseDialog> createState() =>
_VerifyMnemonicPassphraseDialogState();
}
class _VerifyMnemonicPassphraseDialogState
extends ConsumerState<VerifyMnemonicPassphraseDialog> {
late final FocusNode passwordFocusNode;
late final TextEditingController passwordController;
bool hidePassword = true;
bool _verifyLock = false;
void _verify() {
if (_verifyLock) {
return;
}
_verifyLock = true;
if (passwordController.text ==
ref.read(pNewWalletOptions.state).state!.mnemonicPassphrase) {
Navigator.of(context, rootNavigator: Util.isDesktop).pop("verified");
} else {
showFloatingFlushBar(
type: FlushBarType.warning,
message: "Passphrase does not match",
context: context,
);
}
_verifyLock = false;
}
@override
void initState() {
passwordController = TextEditingController();
passwordFocusNode = FocusNode();
super.initState();
}
@override
void dispose() {
passwordController.dispose();
passwordFocusNode.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return ConditionalParent(
condition: Util.isDesktop,
builder: (child) => DesktopDialog(
maxHeight: double.infinity,
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Padding(
padding: const EdgeInsets.only(
left: 32,
),
child: Text(
"Verify mnemonic passphrase",
style: STextStyles.desktopH3(context),
),
),
const DesktopDialogCloseButton(),
],
),
Padding(
padding: const EdgeInsets.only(
left: 32,
right: 32,
bottom: 32,
),
child: child,
),
],
),
),
child: ConditionalParent(
condition: !Util.isDesktop,
builder: (child) => StackDialogBase(
keyboardPaddingAmount: MediaQuery.of(context).viewInsets.bottom,
child: child,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (!Util.isDesktop)
Text(
"Verify BIP39 passphrase",
style: STextStyles.pageTitleH2(context),
),
const SizedBox(
height: 24,
),
ClipRRect(
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,
),
child: TextField(
key: const Key("mnemonicPassphraseFieldKey1"),
focusNode: passwordFocusNode,
controller: passwordController,
style: Util.isDesktop
? STextStyles.desktopTextMedium(context).copyWith(
height: 2,
)
: STextStyles.field(context),
obscureText: hidePassword,
enableSuggestions: false,
autocorrect: false,
decoration: standardInputDecoration(
"Enter your BIP39 passphrase",
passwordFocusNode,
context,
).copyWith(
suffixIcon: UnconstrainedBox(
child: ConditionalParent(
condition: Util.isDesktop,
builder: (child) => SizedBox(
height: 70,
child: child,
),
child: Row(
children: [
SizedBox(
width: Util.isDesktop ? 24 : 16,
),
GestureDetector(
key: const Key(
"mnemonicPassphraseFieldShowPasswordButtonKey"),
onTap: () async {
setState(() {
hidePassword = !hidePassword;
});
},
child: SvgPicture.asset(
hidePassword
? Assets.svg.eye
: Assets.svg.eyeSlash,
color: Theme.of(context)
.extension<StackColors>()!
.textDark3,
width: Util.isDesktop ? 24 : 16,
height: Util.isDesktop ? 24 : 16,
),
),
const SizedBox(
width: 12,
),
],
),
),
),
),
),
),
SizedBox(
height: Util.isDesktop ? 48 : 24,
),
ConditionalParent(
condition: !Util.isDesktop,
builder: (child) => Row(
children: [
Expanded(
child: SecondaryButton(
label: "Cancel",
onPressed: Navigator.of(
context,
rootNavigator: Util.isDesktop,
).pop,
),
),
const SizedBox(
width: 16,
),
Expanded(
child: child,
),
],
),
child: PrimaryButton(
label: "Verify",
onPressed: _verify,
),
),
],
),
),
);
}
}

View file

@ -16,9 +16,11 @@ import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/notifications/show_flush_bar.dart';
import 'package:stackwallet/pages/add_wallet_views/add_token_view/edit_wallet_tokens_view.dart';
import 'package:stackwallet/pages/add_wallet_views/new_wallet_options/new_wallet_options_view.dart';
import 'package:stackwallet/pages/add_wallet_views/new_wallet_recovery_phrase_view/new_wallet_recovery_phrase_view.dart';
import 'package:stackwallet/pages/add_wallet_views/select_wallet_for_token_view.dart';
import 'package:stackwallet/pages/add_wallet_views/verify_recovery_phrase_view/sub_widgets/word_table.dart';
import 'package:stackwallet/pages/add_wallet_views/verify_recovery_phrase_view/verify_mnemonic_passphrase_dialog.dart';
import 'package:stackwallet/pages/home_view/home_view.dart';
import 'package:stackwallet/pages_desktop_specific/desktop_home_view.dart';
import 'package:stackwallet/pages_desktop_specific/my_stack_view/exit_to_my_stack_button.dart';
@ -98,8 +100,25 @@ class _VerifyRecoveryPhraseViewState
// }
// }
Future<bool> _verifyMnemonicPassphrase() async {
final result = await showDialog<String?>(
context: context,
builder: (_) => const VerifyMnemonicPassphraseDialog(),
);
return result == "verified";
}
Future<void> _continue(bool isMatch) async {
if (isMatch) {
if (ref.read(pNewWalletOptions.state).state != null) {
final passphraseVerified = await _verifyMnemonicPassphrase();
if (!passphraseVerified) {
return;
}
}
await ref.read(walletsServiceChangeNotifierProvider).setMnemonicVerified(
walletId: _manager.walletId,
);

View file

@ -27,6 +27,7 @@ import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart';
import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/utilities/test_epic_box_connection.dart';
import 'package:stackwallet/utilities/test_monero_node_connection.dart';
import 'package:stackwallet/utilities/test_stellar_node_connection.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/widgets/background.dart';
@ -193,11 +194,16 @@ class _AddEditNodeViewState extends ConsumerState<AddEditNodeView> {
try {
// await client.getSyncStatus();
} catch (_) {}
break;
case Coin.stellar:
case Coin.stellarTestnet:
try {
testPassed = await testStellarNodeConnection(formData.host!, formData.port!);
} catch(_) {}
break;
case Coin.nano:
case Coin.banano:
case Coin.stellar:
case Coin.stellarTestNet:
throw UnimplementedError();
//TODO: check network/node
case Coin.tezos:
@ -732,18 +738,18 @@ class _NodeFormState extends ConsumerState<NodeForm> {
case Coin.namecoin:
case Coin.bitcoincash:
case Coin.particl:
case Coin.stellar:
case Coin.tezos:
case Coin.bitcoinTestNet:
case Coin.litecoinTestNet:
case Coin.bitcoincashTestnet:
case Coin.firoTestNet:
case Coin.dogecoinTestNet:
case Coin.stellarTestNet:
case Coin.epicCash:
case Coin.nano:
case Coin.banano:
case Coin.eCash:
case Coin.stellar:
case Coin.stellarTestnet:
return false;
case Coin.ethereum:

View file

@ -175,6 +175,15 @@ class _NodeDetailsViewState extends ConsumerState<NodeDetailsView> {
case Coin.tezos:
case Coin.stellar:
case Coin.stellarTestNet:
try {
testPassed = await testStellarNodeConnection(node!.host, node.port);
} catch(_) {
testPassed = false;
}
break;
case Coin.nano:
case Coin.banano:
throw UnimplementedError();
//TODO: check network/node
}

View file

@ -13,6 +13,7 @@ import 'dart:async';
import 'package:event_bus/event_bus.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/db/hive/db.dart';
import 'package:stackwallet/models/epicbox_config_model.dart';
import 'package:stackwallet/notifications/show_flush_bar.dart';
import 'package:stackwallet/pages/address_book_views/address_book_view.dart';
@ -36,11 +37,14 @@ import 'package:stackwallet/services/event_bus/global_event_bus.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/show_loading.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/widgets/background.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
import 'package:stackwallet/widgets/desktop/secondary_button.dart';
import 'package:stackwallet/widgets/rounded_white_container.dart';
import 'package:stackwallet/widgets/stack_dialog.dart';
import 'package:tuple/tuple.dart';
/// [eventBus] should only be set during testing
@ -306,6 +310,61 @@ class _WalletSettingsViewState extends ConsumerState<WalletSettingsView> {
);
},
),
if (coin == Coin.firo)
const SizedBox(
height: 8,
),
if (coin == Coin.firo)
Consumer(
builder: (_, ref, __) {
return SettingsListButton(
iconAssetName: Assets.svg.eye,
title: "Clear electrumx cache",
onPressed: () async {
String? result;
await showDialog<void>(
useSafeArea: false,
barrierDismissible: true,
context: context,
builder: (_) => StackOkDialog(
title:
"Are you sure you want to clear "
"${coin.prettyName} electrumx cache?",
onOkPressed: (value) {
result = value;
},
leftButton: SecondaryButton(
label: "Cancel",
onPressed: () {
Navigator.of(context).pop();
},
),
),
);
if (result == "OK" && mounted) {
await showLoading(
whileFuture: Future.wait<void>(
[
Future.delayed(
const Duration(
milliseconds: 1500,
),
),
DB.instance
.clearSharedTransactionCache(
coin: coin,
),
],
),
context: context,
message: "Clearing cache...",
);
}
},
);
},
),
if (coin == Coin.nano || coin == Coin.banano)
const SizedBox(
height: 8,

View file

@ -35,6 +35,7 @@ class TxIcon extends ConsumerWidget {
String _getAssetName(
bool isCancelled, bool isReceived, bool isPending, IThemeAssets assets) {
if (!isReceived && transaction.subType == TransactionSubType.mint) {
if (isCancelled) {
return Assets.svg.anonymizeFailed;
@ -47,7 +48,7 @@ class TxIcon extends ConsumerWidget {
if (isReceived) {
if (isCancelled) {
return assets.receive;
return assets.receiveCancelled;
}
if (isPending) {
return assets.receivePending;

View file

@ -358,8 +358,6 @@ class _TransactionDetailsViewState
final currentHeight = ref.watch(walletsChangeNotifierProvider
.select((value) => value.getManager(walletId).currentHeight));
print("THIS TRANSACTION IS $_transaction");
return ConditionalParent(
condition: !isDesktop,
builder: (child) => Background(
@ -1584,8 +1582,7 @@ class _TransactionDetailsViewState
coin.requiredConfirmations,
) ==
false &&
_transaction.isCancelled == false &&
_transaction.type == TransactionType.outgoing)
_transaction.isCancelled == false)
? ConditionalParent(
condition: isDesktop,
builder: (child) => Padding(

View file

@ -27,6 +27,7 @@ import 'package:stackwallet/pages/add_wallet_views/add_token_view/edit_wallet_to
import 'package:stackwallet/pages/add_wallet_views/add_wallet_view/add_wallet_view.dart';
import 'package:stackwallet/pages/add_wallet_views/create_or_restore_wallet_view/create_or_restore_wallet_view.dart';
import 'package:stackwallet/pages/add_wallet_views/name_your_wallet_view/name_your_wallet_view.dart';
import 'package:stackwallet/pages/add_wallet_views/new_wallet_options/new_wallet_options_view.dart';
import 'package:stackwallet/pages/add_wallet_views/new_wallet_recovery_phrase_view/new_wallet_recovery_phrase_view.dart';
import 'package:stackwallet/pages/add_wallet_views/new_wallet_recovery_phrase_warning_view/new_wallet_recovery_phrase_warning_view.dart';
import 'package:stackwallet/pages/add_wallet_views/restore_wallet_view/restore_options_view/restore_options_view.dart';
@ -1101,6 +1102,21 @@ class RouteGenerator {
}
return _routeError("${settings.name} invalid args: ${args.toString()}");
case NewWalletOptionsView.routeName:
if (args is Tuple2<String, Coin>) {
return getRoute(
shouldUseMaterialRoute: useMaterialPageRoute,
builder: (_) => NewWalletOptionsView(
walletName: args.item1,
coin: args.item2,
),
settings: RouteSettings(
name: settings.name,
),
);
}
return _routeError("${settings.name} invalid args: ${args.toString()}");
case RestoreWalletView.routeName:
if (args is Tuple5<String, Coin, int, DateTime, String>) {
return getRoute(

View file

@ -600,7 +600,9 @@ class BananoWallet extends CoinServiceAPI with WalletCache, WalletDB {
}
@override
Future<void> initializeNew() async {
Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data,
) async {
if ((await mnemonicString) != null || (await mnemonicPassphrase) != null) {
throw Exception(
"Attempted to overwrite mnemonic on generate new wallet!");

View file

@ -1290,7 +1290,9 @@ class BitcoinWallet extends CoinServiceAPI
bool get isConnected => _isConnected;
@override
Future<void> initializeNew() async {
Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data,
) async {
Logging.instance
.log("Generating new ${coin.prettyName} wallet.", level: LogLevel.Info);
@ -1301,7 +1303,7 @@ class BitcoinWallet extends CoinServiceAPI
await _prefs.init();
try {
await _generateNewWallet();
await _generateNewWallet(data);
} catch (e, s) {
Logging.instance.log("Exception rethrown from initializeNew(): $e\n$s",
level: LogLevel.Fatal);
@ -1499,7 +1501,9 @@ class BitcoinWallet extends CoinServiceAPI
}
}
Future<void> _generateNewWallet() async {
Future<void> _generateNewWallet(
({String mnemonicPassphrase, int wordCount})? data,
) async {
Logging.instance
.log("IS_INTEGRATION_TEST: $integrationTestFlag", level: LogLevel.Info);
if (!integrationTestFlag) {
@ -1533,10 +1537,21 @@ class BitcoinWallet extends CoinServiceAPI
throw Exception(
"Attempted to overwrite mnemonic on generate new wallet!");
}
final int strength;
if (data == null || data.wordCount == 12) {
strength = 128;
} else if (data.wordCount == 24) {
strength = 256;
} else {
throw Exception("Invalid word count");
}
await _secureStore.write(
key: '${_walletId}_mnemonic',
value: bip39.generateMnemonic(strength: 128));
await _secureStore.write(key: '${_walletId}_mnemonicPassphrase', value: "");
value: bip39.generateMnemonic(strength: strength));
await _secureStore.write(
key: '${_walletId}_mnemonicPassphrase',
value: data?.mnemonicPassphrase ?? "",
);
// Generate and add addresses to relevant arrays
final initialAddresses = await Future.wait([

View file

@ -1161,7 +1161,9 @@ class BitcoinCashWallet extends CoinServiceAPI
bool get isConnected => _isConnected;
@override
Future<void> initializeNew() async {
Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data,
) async {
Logging.instance
.log("Generating new ${coin.prettyName} wallet.", level: LogLevel.Info);
@ -1171,7 +1173,7 @@ class BitcoinCashWallet extends CoinServiceAPI
}
await _prefs.init();
try {
await _generateNewWallet();
await _generateNewWallet(data);
} catch (e, s) {
Logging.instance.log("Exception rethrown from initializeNew(): $e\n$s",
level: LogLevel.Fatal);
@ -1402,7 +1404,9 @@ class BitcoinCashWallet extends CoinServiceAPI
}
}
Future<void> _generateNewWallet() async {
Future<void> _generateNewWallet(
({String mnemonicPassphrase, int wordCount})? data,
) async {
Logging.instance
.log("IS_INTEGRATION_TEST: $integrationTestFlag", level: LogLevel.Info);
if (!integrationTestFlag) {
@ -1436,10 +1440,21 @@ class BitcoinCashWallet extends CoinServiceAPI
throw Exception(
"Attempted to overwrite mnemonic on generate new wallet!");
}
final int strength;
if (data == null || data.wordCount == 12) {
strength = 128;
} else if (data.wordCount == 24) {
strength = 256;
} else {
throw Exception("Invalid word count");
}
await _secureStore.write(
key: '${_walletId}_mnemonic',
value: bip39.generateMnemonic(strength: 128));
await _secureStore.write(key: '${_walletId}_mnemonicPassphrase', value: "");
value: bip39.generateMnemonic(strength: strength));
await _secureStore.write(
key: '${_walletId}_mnemonicPassphrase',
value: data?.mnemonicPassphrase ?? "",
);
// Generate and add addresses to relevant arrays
final initialAddresses = await Future.wait([

View file

@ -358,7 +358,9 @@ abstract class CoinServiceAPI {
required int height,
});
Future<void> initializeNew();
Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data,
);
Future<void> initializeExisting();
Future<void> exit();

View file

@ -1147,7 +1147,9 @@ class DogecoinWallet extends CoinServiceAPI
bool get isConnected => _isConnected;
@override
Future<void> initializeNew() async {
Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data,
) async {
Logging.instance
.log("Generating new ${coin.prettyName} wallet.", level: LogLevel.Info);
@ -1157,7 +1159,7 @@ class DogecoinWallet extends CoinServiceAPI
}
await _prefs.init();
try {
await _generateNewWallet();
await _generateNewWallet(data);
} catch (e, s) {
Logging.instance.log("Exception rethrown from initializeNew(): $e\n$s",
level: LogLevel.Fatal);
@ -1349,7 +1351,9 @@ class DogecoinWallet extends CoinServiceAPI
}
}
Future<void> _generateNewWallet() async {
Future<void> _generateNewWallet(
({String mnemonicPassphrase, int wordCount})? data,
) async {
Logging.instance
.log("IS_INTEGRATION_TEST: $integrationTestFlag", level: LogLevel.Info);
if (!integrationTestFlag) {
@ -1383,12 +1387,20 @@ class DogecoinWallet extends CoinServiceAPI
throw Exception(
"Attempted to overwrite mnemonic on generate new wallet!");
}
final int strength;
if (data == null || data.wordCount == 12) {
strength = 128;
} else if (data.wordCount == 24) {
strength = 256;
} else {
throw Exception("Invalid word count");
}
await _secureStore.write(
key: '${_walletId}_mnemonic',
value: bip39.generateMnemonic(strength: 128));
value: bip39.generateMnemonic(strength: strength));
await _secureStore.write(
key: '${_walletId}_mnemonicPassphrase',
value: "",
value: data?.mnemonicPassphrase ?? "",
);
// Generate and add addresses

View file

@ -506,7 +506,9 @@ class ECashWallet extends CoinServiceAPI
}
}
Future<void> _generateNewWallet() async {
Future<void> _generateNewWallet(
({String mnemonicPassphrase, int wordCount})? data,
) async {
Logging.instance
.log("IS_INTEGRATION_TEST: $integrationTestFlag", level: LogLevel.Info);
if (!integrationTestFlag) {
@ -544,10 +546,21 @@ class ECashWallet extends CoinServiceAPI
throw Exception(
"Attempted to overwrite mnemonic on generate new wallet!");
}
final int strength;
if (data == null || data.wordCount == 12) {
strength = 128;
} else if (data.wordCount == 24) {
strength = 256;
} else {
throw Exception("Invalid word count");
}
await _secureStore.write(
key: '${_walletId}_mnemonic',
value: bip39.generateMnemonic(strength: 128));
await _secureStore.write(key: '${_walletId}_mnemonicPassphrase', value: "");
value: bip39.generateMnemonic(strength: strength));
await _secureStore.write(
key: '${_walletId}_mnemonicPassphrase',
value: data?.mnemonicPassphrase ?? "",
);
const int startingIndex = 0;
const int receiveChain = 0;
@ -2778,7 +2791,9 @@ class ECashWallet extends CoinServiceAPI
bool get isConnected => _isConnected;
@override
Future<void> initializeNew() async {
Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data,
) async {
Logging.instance
.log("Generating new ${coin.prettyName} wallet.", level: LogLevel.Info);
@ -2789,7 +2804,7 @@ class ECashWallet extends CoinServiceAPI
await _prefs.init();
try {
await _generateNewWallet();
await _generateNewWallet(data);
} catch (e, s) {
Logging.instance.log("Exception rethrown from initializeNew(): $e\n$s",
level: LogLevel.Fatal);

View file

@ -766,7 +766,9 @@ class EpicCashWallet extends CoinServiceAPI
}
@override
Future<void> initializeNew() async {
Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data,
) async {
await _prefs.init();
await updateNode(false);
final mnemonic = await _getMnemonicList();
@ -1738,7 +1740,6 @@ class EpicCashWallet extends CoinServiceAPI
final isIncoming = (tx["tx_type"] == "TxReceived" ||
tx["tx_type"] == "TxReceivedCancelled");
final txn = isar_models.Transaction(
walletId: walletId,
txid: commitId ?? tx["id"].toString(),
@ -1763,7 +1764,9 @@ class EpicCashWallet extends CoinServiceAPI
otherData: tx['onChainNote'].toString(),
inputs: [],
outputs: [],
numberOfMessages: ((tx["numberOfMessages"] == null) ? 0 : tx["numberOfMessages"]) as int,
numberOfMessages: ((tx["numberOfMessages"] == null)
? 0
: tx["numberOfMessages"]) as int,
);
// txn.address =

View file

@ -310,7 +310,9 @@ class EthereumWallet extends CoinServiceAPI with WalletCache, WalletDB {
}
@override
Future<void> initializeNew() async {
Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data,
) async {
Logging.instance.log(
"Generating new ${coin.prettyName} wallet.",
level: LogLevel.Info,
@ -324,7 +326,7 @@ class EthereumWallet extends CoinServiceAPI with WalletCache, WalletDB {
await _prefs.init();
try {
await _generateNewWallet();
await _generateNewWallet(data);
} catch (e, s) {
Logging.instance.log(
"Exception rethrown from initializeNew(): $e\n$s",
@ -338,7 +340,9 @@ class EthereumWallet extends CoinServiceAPI with WalletCache, WalletDB {
]);
}
Future<void> _generateNewWallet() async {
Future<void> _generateNewWallet(
({String mnemonicPassphrase, int wordCount})? data,
) async {
// Logging.instance
// .log("IS_INTEGRATION_TEST: $integrationTestFlag", level: LogLevel.Info);
// if (!integrationTestFlag) {
@ -366,14 +370,23 @@ class EthereumWallet extends CoinServiceAPI with WalletCache, WalletDB {
"Attempted to overwrite mnemonic on generate new wallet!");
}
final String mnemonic = bip39.generateMnemonic(strength: 128);
final int strength;
if (data == null || data.wordCount == 12) {
strength = 128;
} else if (data.wordCount == 24) {
strength = 256;
} else {
throw Exception("Invalid word count");
}
final String mnemonic = bip39.generateMnemonic(strength: strength);
final String passphrase = data?.mnemonicPassphrase ?? "";
await _secureStore.write(key: '${_walletId}_mnemonic', value: mnemonic);
await _secureStore.write(
key: '${_walletId}_mnemonicPassphrase',
value: "",
value: passphrase,
);
await _generateAndSaveAddress(mnemonic, "");
await _generateAndSaveAddress(mnemonic, passphrase);
Logging.instance.log("_generateNewWalletFinished", level: LogLevel.Info);
}

View file

@ -1875,7 +1875,9 @@ class FiroWallet extends CoinServiceAPI
}
@override
Future<void> initializeNew() async {
Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data,
) async {
Logging.instance
.log("Generating new ${coin.prettyName} wallet.", level: LogLevel.Info);
@ -1886,7 +1888,7 @@ class FiroWallet extends CoinServiceAPI
await _prefs.init();
try {
await _generateNewWallet();
await _generateNewWallet(data);
} catch (e, s) {
Logging.instance.log("Exception rethrown from initializeNew(): $e\n$s",
level: LogLevel.Fatal);
@ -2124,7 +2126,9 @@ class FiroWallet extends CoinServiceAPI
}
/// Generates initial wallet values such as mnemonic, chain (receive/change) arrays and indexes.
Future<void> _generateNewWallet() async {
Future<void> _generateNewWallet(
({String mnemonicPassphrase, int wordCount})? data,
) async {
Logging.instance
.log("IS_INTEGRATION_TEST: $integrationTestFlag", level: LogLevel.Info);
if (!integrationTestFlag) {
@ -2158,12 +2162,20 @@ class FiroWallet extends CoinServiceAPI
longMutex = false;
throw Exception("Attempted to overwrite mnemonic on initialize new!");
}
final int strength;
if (data == null || data.wordCount == 12) {
strength = 128;
} else if (data.wordCount == 24) {
strength = 256;
} else {
throw Exception("Invalid word count");
}
await _secureStore.write(
key: '${_walletId}_mnemonic',
value: bip39.generateMnemonic(strength: 128));
value: bip39.generateMnemonic(strength: strength));
await _secureStore.write(
key: '${_walletId}_mnemonicPassphrase',
value: "",
value: data?.mnemonicPassphrase ?? "",
);
// Generate and add addresses to relevant arrays

View file

@ -1285,7 +1285,9 @@ class LitecoinWallet extends CoinServiceAPI
bool get isConnected => _isConnected;
@override
Future<void> initializeNew() async {
Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data,
) async {
Logging.instance
.log("Generating new ${coin.prettyName} wallet.", level: LogLevel.Info);
@ -1296,7 +1298,7 @@ class LitecoinWallet extends CoinServiceAPI
await _prefs.init();
try {
await _generateNewWallet();
await _generateNewWallet(data);
} catch (e, s) {
Logging.instance.log("Exception rethrown from initializeNew(): $e\n$s",
level: LogLevel.Fatal);
@ -1535,7 +1537,9 @@ class LitecoinWallet extends CoinServiceAPI
}
}
Future<void> _generateNewWallet() async {
Future<void> _generateNewWallet(
({String mnemonicPassphrase, int wordCount})? data,
) async {
Logging.instance
.log("IS_INTEGRATION_TEST: $integrationTestFlag", level: LogLevel.Info);
if (!integrationTestFlag) {
@ -1570,12 +1574,20 @@ class LitecoinWallet extends CoinServiceAPI
throw Exception(
"Attempted to overwrite mnemonic on generate new wallet!");
}
final int strength;
if (data == null || data.wordCount == 12) {
strength = 128;
} else if (data.wordCount == 24) {
strength = 256;
} else {
throw Exception("Invalid word count");
}
await _secureStore.write(
key: '${_walletId}_mnemonic',
value: bip39.generateMnemonic(strength: 128));
value: bip39.generateMnemonic(strength: strength));
await _secureStore.write(
key: '${_walletId}_mnemonicPassphrase',
value: "",
value: data?.mnemonicPassphrase ?? "",
);
// Generate and add addresses to relevant arrays

View file

@ -180,7 +180,9 @@ class Manager with ChangeNotifier {
Future<bool> testNetworkConnection() =>
_currentWallet.testNetworkConnection();
Future<void> initializeNew() => _currentWallet.initializeNew();
Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data) =>
_currentWallet.initializeNew(data);
Future<void> initializeExisting() => _currentWallet.initializeExisting();
Future<void> recoverFromMnemonic({
required String mnemonic,

View file

@ -307,7 +307,9 @@ class MoneroWallet extends CoinServiceAPI with WalletCache, WalletDB {
}
@override
Future<void> initializeNew() async {
Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data,
) async {
await _prefs.init();
// this should never fail

View file

@ -1268,7 +1268,9 @@ class NamecoinWallet extends CoinServiceAPI
bool get isConnected => _isConnected;
@override
Future<void> initializeNew() async {
Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data,
) async {
Logging.instance
.log("Generating new ${coin.prettyName} wallet.", level: LogLevel.Info);
@ -1279,7 +1281,7 @@ class NamecoinWallet extends CoinServiceAPI
await _prefs.init();
try {
await _generateNewWallet();
await _generateNewWallet(data);
} catch (e, s) {
Logging.instance.log("Exception rethrown from initializeNew(): $e\n$s",
level: LogLevel.Fatal);
@ -1517,7 +1519,9 @@ class NamecoinWallet extends CoinServiceAPI
}
}
Future<void> _generateNewWallet() async {
Future<void> _generateNewWallet(
({String mnemonicPassphrase, int wordCount})? data,
) async {
Logging.instance
.log("IS_INTEGRATION_TEST: $integrationTestFlag", level: LogLevel.Info);
if (!integrationTestFlag) {
@ -1544,12 +1548,20 @@ class NamecoinWallet extends CoinServiceAPI
throw Exception(
"Attempted to overwrite mnemonic on generate new wallet!");
}
final int strength;
if (data == null || data.wordCount == 12) {
strength = 128;
} else if (data.wordCount == 24) {
strength = 256;
} else {
throw Exception("Invalid word count");
}
await _secureStore.write(
key: '${_walletId}_mnemonic',
value: bip39.generateMnemonic(strength: 128));
value: bip39.generateMnemonic(strength: strength));
await _secureStore.write(
key: '${_walletId}_mnemonicPassphrase',
value: "",
value: data?.mnemonicPassphrase ?? "",
);
// Generate and add addresses to relevant arrays

View file

@ -607,7 +607,9 @@ class NanoWallet extends CoinServiceAPI with WalletCache, WalletDB {
}
@override
Future<void> initializeNew() async {
Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data,
) async {
if ((await mnemonicString) != null || (await mnemonicPassphrase) != null) {
throw Exception(
"Attempted to overwrite mnemonic on generate new wallet!");

View file

@ -1195,7 +1195,9 @@ class ParticlWallet extends CoinServiceAPI
bool get isConnected => _isConnected;
@override
Future<void> initializeNew() async {
Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data,
) async {
Logging.instance
.log("Generating new ${coin.prettyName} wallet.", level: LogLevel.Info);
@ -1206,7 +1208,7 @@ class ParticlWallet extends CoinServiceAPI
await _prefs.init();
try {
await _generateNewWallet();
await _generateNewWallet(data);
} catch (e, s) {
Logging.instance.log("Exception rethrown from initializeNew(): $e\n$s",
level: LogLevel.Fatal);
@ -1432,7 +1434,9 @@ class ParticlWallet extends CoinServiceAPI
}
}
Future<void> _generateNewWallet() async {
Future<void> _generateNewWallet(
({String mnemonicPassphrase, int wordCount})? data,
) async {
Logging.instance
.log("IS_INTEGRATION_TEST: $integrationTestFlag", level: LogLevel.Info);
if (!integrationTestFlag) {
@ -1459,12 +1463,20 @@ class ParticlWallet extends CoinServiceAPI
throw Exception(
"Attempted to overwrite mnemonic on generate new wallet!");
}
final int strength;
if (data == null || data.wordCount == 12) {
strength = 128;
} else if (data.wordCount == 24) {
strength = 256;
} else {
throw Exception("Invalid word count");
}
await _secureStore.write(
key: '${_walletId}_mnemonic',
value: bip39.generateMnemonic(strength: 128));
value: bip39.generateMnemonic(strength: strength));
await _secureStore.write(
key: '${_walletId}_mnemonicPassphrase',
value: "",
value: data?.mnemonicPassphrase ?? "",
);
// Generate and add addresses to relevant arrays

View file

@ -1,5 +1,5 @@
import 'dart:async';
import 'package:bip39/bip39.dart' as bip39;
import 'package:http/http.dart' as http;
import 'package:isar/isar.dart';
import 'package:stackwallet/db/isar/main_db.dart';
@ -37,6 +37,7 @@ class StellarWallet extends CoinServiceAPI with WalletCache, WalletDB {
late StellarSDK stellarSdk;
late Network stellarNetwork;
StellarWallet({
required String walletId,
required String walletName,
@ -53,20 +54,26 @@ class StellarWallet extends CoinServiceAPI with WalletCache, WalletDB {
initCache(walletId, coin);
initWalletDB(mockableOverride: mockableOverride);
if (coin.name == "stellarTestnet") {
stellarSdk = StellarSDK.TESTNET;
if (coin.isTestNet) {
stellarNetwork = Network.TESTNET;
} else {
stellarSdk = StellarSDK.PUBLIC;
stellarNetwork = Network.PUBLIC;
}
_updateNode();
}
void _updateNode() {
_xlmNode = NodeService(secureStorageInterface: _secureStore)
.getPrimaryNodeFor(coin: coin) ??
DefaultNodes.getNodeFor(coin);
stellarSdk = StellarSDK("${_xlmNode!.host}:${_xlmNode!.port}");
}
late final TransactionNotificationTracker txTracker;
late SecureStorageInterface _secureStore;
// final StellarSDK stellarSdk = StellarSDK.PUBLIC;
@override
bool get isFavorite => _isFavorite ??= getCachedIsFavorite();
bool? _isFavorite;
@ -206,10 +213,12 @@ class StellarWallet extends CoinServiceAPI with WalletCache, WalletDB {
transaction.sign(senderKeyPair, stellarNetwork);
try {
SubmitTransactionResponse response =
await stellarSdk.submitTransaction(transaction);
await stellarSdk.submitTransaction(transaction).onError((error, stackTrace) => throw (error.toString()));
if (!response.success) {
throw ("Unable to send transaction");
throw (
"${response.extras?.resultCodes?.transactionResultCode}"
" ::: ${response.extras?.resultCodes?.operationsResultCodes}"
);
}
return response.hash!;
} catch (e, s) {
@ -232,32 +241,14 @@ class StellarWallet extends CoinServiceAPI with WalletCache, WalletDB {
(await _currentReceivingAddress)?.value ?? await getAddressSW();
Future<int> getBaseFee() async {
// final nodeURI = Uri.parse("${getCurrentNode().host}:${getCurrentNode().port}");
final nodeURI = Uri.parse(getCurrentNode().host);
final httpClient = http.Client();
FeeStatsResponse fsp =
await FeeStatsRequestBuilder(httpClient, nodeURI).execute();
return int.parse(fsp.lastLedgerBaseFee);
var fees = await stellarSdk.feeStats.execute();
return int.parse(fees.lastLedgerBaseFee);
}
@override
Future<Amount> estimateFeeFor(Amount amount, int feeRate) async {
var baseFee = await getBaseFee();
int fee = 100;
switch (feeRate) {
case 0:
fee = baseFee * 10;
case 1:
case 2:
fee = baseFee * 50;
case 3:
fee = baseFee * 100;
case 4:
fee = baseFee * 200;
default:
fee = baseFee * 50;
}
return Amount(rawValue: BigInt.from(fee), fractionDigits: coin.decimals);
return Amount(rawValue: BigInt.from(baseFee), fractionDigits: coin.decimals);
}
@override
@ -285,20 +276,15 @@ class StellarWallet extends CoinServiceAPI with WalletCache, WalletDB {
@override
Future<FeeObject> get fees async {
// final nodeURI = Uri.parse("${getCurrentNode().host}:${getCurrentNode().port}");
final nodeURI = Uri.parse(getCurrentNode().host);
final httpClient = http.Client();
FeeStatsResponse fsp =
await FeeStatsRequestBuilder(httpClient, nodeURI).execute();
int fee = await getBaseFee();
return FeeObject(
numberOfBlocksFast: 0,
numberOfBlocksAverage: 0,
numberOfBlocksSlow: 0,
fast: int.parse(fsp.lastLedgerBaseFee) * 100,
medium: int.parse(fsp.lastLedgerBaseFee) * 50,
slow: int.parse(fsp.lastLedgerBaseFee) * 10);
numberOfBlocksFast: 10,
numberOfBlocksAverage: 10,
numberOfBlocksSlow: 10,
fast: fee,
medium: fee,
slow: fee);
}
@override
@ -326,7 +312,9 @@ class StellarWallet extends CoinServiceAPI with WalletCache, WalletDB {
}
@override
Future<void> initializeNew() async {
Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data,
) async {
if ((await mnemonicString) != null || (await mnemonicPassphrase) != null) {
throw Exception(
"Attempted to overwrite mnemonic on generate new wallet!");
@ -334,11 +322,26 @@ class StellarWallet extends CoinServiceAPI with WalletCache, WalletDB {
await _prefs.init();
String mnemonic = await Wallet.generate24WordsMnemonic();
final int strength;
if (data == null || data.wordCount == 12) {
strength = 128;
} else if (data.wordCount == 24) {
strength = 256;
} else {
throw Exception("Invalid word count");
}
final String mnemonic = bip39.generateMnemonic(strength: strength);
final String passphrase = data?.mnemonicPassphrase ?? "";
await _secureStore.write(key: '${_walletId}_mnemonic', value: mnemonic);
await _secureStore.write(key: '${_walletId}_mnemonicPassphrase', value: "");
await _secureStore.write(
key: '${_walletId}_mnemonicPassphrase',
value: passphrase,
);
Wallet wallet = await Wallet.from(mnemonic);
Wallet wallet = await Wallet.from(
mnemonic,
passphrase: passphrase,
);
KeyPair keyPair = await wallet.getKeyPair(index: 0);
String address = keyPair.accountId;
String secretSeed =
@ -399,6 +402,7 @@ class StellarWallet extends CoinServiceAPI with WalletCache, WalletDB {
{required String address,
required Amount amount,
Map<String, dynamic>? args}) async {
try {
final feeRate = args?["feeRate"];
var fee = 1000;
@ -495,13 +499,6 @@ class StellarWallet extends CoinServiceAPI with WalletCache, WalletDB {
if (response is PaymentOperationResponse) {
PaymentOperationResponse por = response;
Logging.instance.log(
"ALL TRANSACTIONS IS ${por.transactionSuccessful}",
level: LogLevel.Info);
Logging.instance.log("THIS TX HASH IS ${por.transactionHash}",
level: LogLevel.Info);
SWTransaction.TransactionType type;
if (por.sourceAccount == await getAddressSW()) {
type = SWTransaction.TransactionType.outgoing;
@ -750,10 +747,7 @@ class StellarWallet extends CoinServiceAPI with WalletCache, WalletDB {
@override
Future<void> updateNode(bool shouldRefresh) async {
_xlmNode = NodeService(secureStorageInterface: _secureStore)
.getPrimaryNodeFor(coin: coin) ??
DefaultNodes.getNodeFor(coin);
_updateNode();
if (shouldRefresh) {
unawaited(refresh());
}

View file

@ -333,7 +333,10 @@ class WowneroWallet extends CoinServiceAPI with WalletCache, WalletDB {
}
@override
Future<void> initializeNew({int seedWordsLength = 14}) async {
Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data, {
int seedWordsLength = 14,
}) async {
await _prefs.init();
// this should never fail

View file

@ -245,6 +245,35 @@ extension CoinExt on Coin {
}
}
bool get hasMnemonicPassphraseSupport {
switch (this) {
case Coin.bitcoin:
case Coin.bitcoinTestNet:
case Coin.litecoin:
case Coin.litecoinTestNet:
case Coin.bitcoincash:
case Coin.bitcoincashTestnet:
case Coin.dogecoin:
case Coin.dogecoinTestNet:
case Coin.firo:
case Coin.firoTestNet:
case Coin.namecoin:
case Coin.particl:
case Coin.ethereum:
case Coin.eCash:
case Coin.stellar:
case Coin.stellarTestnet:
return true;
case Coin.epicCash:
case Coin.monero:
case Coin.wownero:
case Coin.nano:
case Coin.banano:
return false;
}
}
bool get hasBuySupport {
switch (this) {
case Coin.bitcoin:

View file

@ -0,0 +1,34 @@
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:stellar_flutter_sdk/stellar_flutter_sdk.dart';
Future<bool> testStellarNodeConnection(String host, int port) async {
final client = http.Client();
Uri uri = Uri.parse("$host:$port");
final response = await client.get(
uri,
headers: {'Content-Type': 'application/json'},
).timeout(const Duration(milliseconds: 2000),
onTimeout: () async => http.Response('Error', 408));
if (response.statusCode == 200) {
//Get chain height for sdk
StellarSDK stellarSdk = StellarSDK(host);
final height = await stellarSdk.ledgers
.order(RequestBuilderOrder.DESC)
.limit(1)
.execute()
.then((value) => value.records!.first.sequence)
.onError((error, stackTrace) => throw ("Error getting chain height"));
if (height > 0) {
return true;
} else {
return false;
}
} else {
return false;
}
}

View file

@ -197,6 +197,15 @@ class _NodeCardState extends ConsumerState<NodeCard> {
case Coin.tezos:
case Coin.stellar:
case Coin.stellarTestNet:
try {
testPassed = await testStellarNodeConnection(node.host, node.port);
} catch(_) {
testPassed = false;
}
break;
case Coin.nano:
case Coin.banano:
throw UnimplementedError();
//TODO: check network/node
}

View file

@ -18,15 +18,22 @@ class StackDialogBase extends StatelessWidget {
Key? key,
this.child,
this.padding = const EdgeInsets.all(24),
this.keyboardPaddingAmount = 0,
}) : super(key: key);
final EdgeInsets padding;
final Widget? child;
final double keyboardPaddingAmount;
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(16),
padding: EdgeInsets.only(
top: 16,
left: 16,
right: 16,
bottom: 16 + keyboardPaddingAmount,
),
child: Column(
mainAxisAlignment:
!Util.isDesktop ? MainAxisAlignment.end : MainAxisAlignment.center,

View file

@ -11,7 +11,7 @@ description: Stack Wallet
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 1.7.17+185
version: 1.7.19+187
environment:
sdk: ">=3.0.2 <4.0.0"

View file

@ -1283,10 +1283,12 @@ class MockBitcoinWallet extends _i1.Mock implements _i27.BitcoinWallet {
returnValueForMissingStub: null,
);
@override
_i23.Future<void> initializeNew() => (super.noSuchMethod(
_i23.Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data) =>
(super.noSuchMethod(
Invocation.method(
#initializeNew,
[],
[data],
),
returnValue: _i23.Future<void>.value(),
returnValueForMissingStub: _i23.Future<void>.value(),
@ -3062,10 +3064,12 @@ class MockManager extends _i1.Mock implements _i6.Manager {
returnValue: _i23.Future<bool>.value(false),
) as _i23.Future<bool>);
@override
_i23.Future<void> initializeNew() => (super.noSuchMethod(
_i23.Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data) =>
(super.noSuchMethod(
Invocation.method(
#initializeNew,
[],
[data],
),
returnValue: _i23.Future<void>.value(),
returnValueForMissingStub: _i23.Future<void>.value(),
@ -3415,10 +3419,12 @@ class MockCoinServiceAPI extends _i1.Mock implements _i20.CoinServiceAPI {
returnValueForMissingStub: _i23.Future<void>.value(),
) as _i23.Future<void>);
@override
_i23.Future<void> initializeNew() => (super.noSuchMethod(
_i23.Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data) =>
(super.noSuchMethod(
Invocation.method(
#initializeNew,
[],
[data],
),
returnValue: _i23.Future<void>.value(),
returnValueForMissingStub: _i23.Future<void>.value(),

View file

@ -492,10 +492,12 @@ class MockManager extends _i1.Mock implements _i12.Manager {
returnValue: _i9.Future<bool>.value(false),
) as _i9.Future<bool>);
@override
_i9.Future<void> initializeNew() => (super.noSuchMethod(
_i9.Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data) =>
(super.noSuchMethod(
Invocation.method(
#initializeNew,
[],
[data],
),
returnValue: _i9.Future<void>.value(),
returnValueForMissingStub: _i9.Future<void>.value(),

View file

@ -453,10 +453,12 @@ class MockManager extends _i1.Mock implements _i10.Manager {
returnValue: _i8.Future<bool>.value(false),
) as _i8.Future<bool>);
@override
_i8.Future<void> initializeNew() => (super.noSuchMethod(
_i8.Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data) =>
(super.noSuchMethod(
Invocation.method(
#initializeNew,
[],
[data],
),
returnValue: _i8.Future<void>.value(),
returnValueForMissingStub: _i8.Future<void>.value(),

View file

@ -451,10 +451,12 @@ class MockManager extends _i1.Mock implements _i10.Manager {
returnValue: _i8.Future<bool>.value(false),
) as _i8.Future<bool>);
@override
_i8.Future<void> initializeNew() => (super.noSuchMethod(
_i8.Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data) =>
(super.noSuchMethod(
Invocation.method(
#initializeNew,
[],
[data],
),
returnValue: _i8.Future<void>.value(),
returnValueForMissingStub: _i8.Future<void>.value(),

View file

@ -771,10 +771,12 @@ class MockManager extends _i1.Mock implements _i13.Manager {
returnValue: _i8.Future<bool>.value(false),
) as _i8.Future<bool>);
@override
_i8.Future<void> initializeNew() => (super.noSuchMethod(
_i8.Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data) =>
(super.noSuchMethod(
Invocation.method(
#initializeNew,
[],
[data],
),
returnValue: _i8.Future<void>.value(),
returnValueForMissingStub: _i8.Future<void>.value(),

View file

@ -558,10 +558,12 @@ class MockManager extends _i1.Mock implements _i10.Manager {
returnValue: _i7.Future<bool>.value(false),
) as _i7.Future<bool>);
@override
_i7.Future<void> initializeNew() => (super.noSuchMethod(
_i7.Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data) =>
(super.noSuchMethod(
Invocation.method(
#initializeNew,
[],
[data],
),
returnValue: _i7.Future<void>.value(),
returnValueForMissingStub: _i7.Future<void>.value(),

View file

@ -558,10 +558,12 @@ class MockManager extends _i1.Mock implements _i10.Manager {
returnValue: _i7.Future<bool>.value(false),
) as _i7.Future<bool>);
@override
_i7.Future<void> initializeNew() => (super.noSuchMethod(
_i7.Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data) =>
(super.noSuchMethod(
Invocation.method(
#initializeNew,
[],
[data],
),
returnValue: _i7.Future<void>.value(),
returnValueForMissingStub: _i7.Future<void>.value(),

View file

@ -558,10 +558,12 @@ class MockManager extends _i1.Mock implements _i10.Manager {
returnValue: _i7.Future<bool>.value(false),
) as _i7.Future<bool>);
@override
_i7.Future<void> initializeNew() => (super.noSuchMethod(
_i7.Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data) =>
(super.noSuchMethod(
Invocation.method(
#initializeNew,
[],
[data],
),
returnValue: _i7.Future<void>.value(),
returnValueForMissingStub: _i7.Future<void>.value(),

View file

@ -325,10 +325,12 @@ class MockManager extends _i1.Mock implements _i6.Manager {
returnValue: _i8.Future<bool>.value(false),
) as _i8.Future<bool>);
@override
_i8.Future<void> initializeNew() => (super.noSuchMethod(
_i8.Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data) =>
(super.noSuchMethod(
Invocation.method(
#initializeNew,
[],
[data],
),
returnValue: _i8.Future<void>.value(),
returnValueForMissingStub: _i8.Future<void>.value(),

View file

@ -556,10 +556,12 @@ class MockManager extends _i1.Mock implements _i10.Manager {
returnValue: _i7.Future<bool>.value(false),
) as _i7.Future<bool>);
@override
_i7.Future<void> initializeNew() => (super.noSuchMethod(
_i7.Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data) =>
(super.noSuchMethod(
Invocation.method(
#initializeNew,
[],
[data],
),
returnValue: _i7.Future<void>.value(),
returnValueForMissingStub: _i7.Future<void>.value(),

View file

@ -771,10 +771,12 @@ class MockManager extends _i1.Mock implements _i13.Manager {
returnValue: _i8.Future<bool>.value(false),
) as _i8.Future<bool>);
@override
_i8.Future<void> initializeNew() => (super.noSuchMethod(
_i8.Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data) =>
(super.noSuchMethod(
Invocation.method(
#initializeNew,
[],
[data],
),
returnValue: _i8.Future<void>.value(),
returnValueForMissingStub: _i8.Future<void>.value(),

View file

@ -612,10 +612,12 @@ class MockManager extends _i1.Mock implements _i13.Manager {
returnValue: _i9.Future<bool>.value(false),
) as _i9.Future<bool>);
@override
_i9.Future<void> initializeNew() => (super.noSuchMethod(
_i9.Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data) =>
(super.noSuchMethod(
Invocation.method(
#initializeNew,
[],
[data],
),
returnValue: _i9.Future<void>.value(),
returnValueForMissingStub: _i9.Future<void>.value(),

View file

@ -325,10 +325,12 @@ class MockManager extends _i1.Mock implements _i6.Manager {
returnValue: _i8.Future<bool>.value(false),
) as _i8.Future<bool>);
@override
_i8.Future<void> initializeNew() => (super.noSuchMethod(
_i8.Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data) =>
(super.noSuchMethod(
Invocation.method(
#initializeNew,
[],
[data],
),
returnValue: _i8.Future<void>.value(),
returnValueForMissingStub: _i8.Future<void>.value(),

View file

@ -325,10 +325,12 @@ class MockManager extends _i1.Mock implements _i6.Manager {
returnValue: _i8.Future<bool>.value(false),
) as _i8.Future<bool>);
@override
_i8.Future<void> initializeNew() => (super.noSuchMethod(
_i8.Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data) =>
(super.noSuchMethod(
Invocation.method(
#initializeNew,
[],
[data],
),
returnValue: _i8.Future<void>.value(),
returnValueForMissingStub: _i8.Future<void>.value(),

View file

@ -540,10 +540,12 @@ class MockManager extends _i1.Mock implements _i12.Manager {
returnValue: _i9.Future<bool>.value(false),
) as _i9.Future<bool>);
@override
_i9.Future<void> initializeNew() => (super.noSuchMethod(
_i9.Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data) =>
(super.noSuchMethod(
Invocation.method(
#initializeNew,
[],
[data],
),
returnValue: _i9.Future<void>.value(),
returnValueForMissingStub: _i9.Future<void>.value(),

View file

@ -540,10 +540,12 @@ class MockManager extends _i1.Mock implements _i12.Manager {
returnValue: _i9.Future<bool>.value(false),
) as _i9.Future<bool>);
@override
_i9.Future<void> initializeNew() => (super.noSuchMethod(
_i9.Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data) =>
(super.noSuchMethod(
Invocation.method(
#initializeNew,
[],
[data],
),
returnValue: _i9.Future<void>.value(),
returnValueForMissingStub: _i9.Future<void>.value(),

View file

@ -325,10 +325,12 @@ class MockManager extends _i1.Mock implements _i6.Manager {
returnValue: _i8.Future<bool>.value(false),
) as _i8.Future<bool>);
@override
_i8.Future<void> initializeNew() => (super.noSuchMethod(
_i8.Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data) =>
(super.noSuchMethod(
Invocation.method(
#initializeNew,
[],
[data],
),
returnValue: _i8.Future<void>.value(),
returnValueForMissingStub: _i8.Future<void>.value(),

View file

@ -325,10 +325,12 @@ class MockManager extends _i1.Mock implements _i6.Manager {
returnValue: _i8.Future<bool>.value(false),
) as _i8.Future<bool>);
@override
_i8.Future<void> initializeNew() => (super.noSuchMethod(
_i8.Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data) =>
(super.noSuchMethod(
Invocation.method(
#initializeNew,
[],
[data],
),
returnValue: _i8.Future<void>.value(),
returnValueForMissingStub: _i8.Future<void>.value(),

View file

@ -556,10 +556,12 @@ class MockManager extends _i1.Mock implements _i10.Manager {
returnValue: _i7.Future<bool>.value(false),
) as _i7.Future<bool>);
@override
_i7.Future<void> initializeNew() => (super.noSuchMethod(
_i7.Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data) =>
(super.noSuchMethod(
Invocation.method(
#initializeNew,
[],
[data],
),
returnValue: _i7.Future<void>.value(),
returnValueForMissingStub: _i7.Future<void>.value(),

View file

@ -154,18 +154,12 @@ class MockCachedElectrumX extends _i1.Mock implements _i7.CachedElectrumX {
_i8.Future<Map<String, dynamic>>.value(<String, dynamic>{}),
) as _i8.Future<Map<String, dynamic>>);
@override
_i8.Future<List<String>> getUsedCoinSerials({
required _i9.Coin? coin,
int? startNumber = 0,
}) =>
_i8.Future<List<String>> getUsedCoinSerials({required _i9.Coin? coin}) =>
(super.noSuchMethod(
Invocation.method(
#getUsedCoinSerials,
[],
{
#coin: coin,
#startNumber: startNumber,
},
{#coin: coin},
),
returnValue: _i8.Future<List<String>>.value(<String>[]),
) as _i8.Future<List<String>>);
@ -792,10 +786,12 @@ class MockManager extends _i1.Mock implements _i15.Manager {
returnValue: _i8.Future<bool>.value(false),
) as _i8.Future<bool>);
@override
_i8.Future<void> initializeNew() => (super.noSuchMethod(
_i8.Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data) =>
(super.noSuchMethod(
Invocation.method(
#initializeNew,
[],
[data],
),
returnValue: _i8.Future<void>.value(),
returnValueForMissingStub: _i8.Future<void>.value(),

View file

@ -556,10 +556,12 @@ class MockManager extends _i1.Mock implements _i10.Manager {
returnValue: _i7.Future<bool>.value(false),
) as _i7.Future<bool>);
@override
_i7.Future<void> initializeNew() => (super.noSuchMethod(
_i7.Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data) =>
(super.noSuchMethod(
Invocation.method(
#initializeNew,
[],
[data],
),
returnValue: _i7.Future<void>.value(),
returnValueForMissingStub: _i7.Future<void>.value(),

View file

@ -327,10 +327,12 @@ class MockManager extends _i1.Mock implements _i6.Manager {
returnValue: _i8.Future<bool>.value(false),
) as _i8.Future<bool>);
@override
_i8.Future<void> initializeNew() => (super.noSuchMethod(
_i8.Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data) =>
(super.noSuchMethod(
Invocation.method(
#initializeNew,
[],
[data],
),
returnValue: _i8.Future<void>.value(),
returnValueForMissingStub: _i8.Future<void>.value(),

View file

@ -326,10 +326,12 @@ class MockManager extends _i1.Mock implements _i6.Manager {
returnValue: _i8.Future<bool>.value(false),
) as _i8.Future<bool>);
@override
_i8.Future<void> initializeNew() => (super.noSuchMethod(
_i8.Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data) =>
(super.noSuchMethod(
Invocation.method(
#initializeNew,
[],
[data],
),
returnValue: _i8.Future<void>.value(),
returnValueForMissingStub: _i8.Future<void>.value(),

View file

@ -325,10 +325,12 @@ class MockManager extends _i1.Mock implements _i6.Manager {
returnValue: _i8.Future<bool>.value(false),
) as _i8.Future<bool>);
@override
_i8.Future<void> initializeNew() => (super.noSuchMethod(
_i8.Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data) =>
(super.noSuchMethod(
Invocation.method(
#initializeNew,
[],
[data],
),
returnValue: _i8.Future<void>.value(),
returnValueForMissingStub: _i8.Future<void>.value(),

View file

@ -367,10 +367,12 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValue: _i8.Future<bool>.value(false),
) as _i8.Future<bool>);
@override
_i8.Future<void> initializeNew() => (super.noSuchMethod(
_i8.Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data) =>
(super.noSuchMethod(
Invocation.method(
#initializeNew,
[],
[data],
),
returnValue: _i8.Future<void>.value(),
returnValueForMissingStub: _i8.Future<void>.value(),

View file

@ -327,10 +327,12 @@ class MockManager extends _i1.Mock implements _i6.Manager {
returnValue: _i8.Future<bool>.value(false),
) as _i8.Future<bool>);
@override
_i8.Future<void> initializeNew() => (super.noSuchMethod(
_i8.Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data) =>
(super.noSuchMethod(
Invocation.method(
#initializeNew,
[],
[data],
),
returnValue: _i8.Future<void>.value(),
returnValueForMissingStub: _i8.Future<void>.value(),

View file

@ -485,18 +485,12 @@ class MockCachedElectrumX extends _i1.Mock implements _i5.CachedElectrumX {
_i4.Future<Map<String, dynamic>>.value(<String, dynamic>{}),
) as _i4.Future<Map<String, dynamic>>);
@override
_i4.Future<List<String>> getUsedCoinSerials({
required _i6.Coin? coin,
int? startNumber = 0,
}) =>
_i4.Future<List<String>> getUsedCoinSerials({required _i6.Coin? coin}) =>
(super.noSuchMethod(
Invocation.method(
#getUsedCoinSerials,
[],
{
#coin: coin,
#startNumber: startNumber,
},
{#coin: coin},
),
returnValue: _i4.Future<List<String>>.value(<String>[]),
) as _i4.Future<List<String>>);

View file

@ -626,7 +626,8 @@ void main() async {
await Hive.openBox<dynamic>(testWalletId);
await Hive.openBox<dynamic>(DB.boxNamePrefs);
await expectLater(() => bch?.initializeNew(), throwsA(isA<Exception>()))
await expectLater(
() => bch?.initializeNew(null), throwsA(isA<Exception>()))
.then((_) {
expect(secureStore.interactions, 2);
verifyNever(client?.ping()).called(0);

View file

@ -485,18 +485,12 @@ class MockCachedElectrumX extends _i1.Mock implements _i5.CachedElectrumX {
_i4.Future<Map<String, dynamic>>.value(<String, dynamic>{}),
) as _i4.Future<Map<String, dynamic>>);
@override
_i4.Future<List<String>> getUsedCoinSerials({
required _i6.Coin? coin,
int? startNumber = 0,
}) =>
_i4.Future<List<String>> getUsedCoinSerials({required _i6.Coin? coin}) =>
(super.noSuchMethod(
Invocation.method(
#getUsedCoinSerials,
[],
{
#coin: coin,
#startNumber: startNumber,
},
{#coin: coin},
),
returnValue: _i4.Future<List<String>>.value(<String>[]),
) as _i4.Future<List<String>>);

View file

@ -483,7 +483,8 @@ void main() {
await Hive.openBox<dynamic>(testWalletId);
await Hive.openBox<dynamic>(DB.boxNamePrefs);
await expectLater(() => doge?.initializeNew(), throwsA(isA<Exception>()))
await expectLater(
() => doge?.initializeNew(null), throwsA(isA<Exception>()))
.then((_) {
expect(secureStore.interactions, 2);
verifyNever(client?.ping()).called(0);

View file

@ -485,18 +485,12 @@ class MockCachedElectrumX extends _i1.Mock implements _i5.CachedElectrumX {
_i4.Future<Map<String, dynamic>>.value(<String, dynamic>{}),
) as _i4.Future<Map<String, dynamic>>);
@override
_i4.Future<List<String>> getUsedCoinSerials({
required _i6.Coin? coin,
int? startNumber = 0,
}) =>
_i4.Future<List<String>> getUsedCoinSerials({required _i6.Coin? coin}) =>
(super.noSuchMethod(
Invocation.method(
#getUsedCoinSerials,
[],
{
#coin: coin,
#startNumber: startNumber,
},
{#coin: coin},
),
returnValue: _i4.Future<List<String>>.value(<String>[]),
) as _i4.Future<List<String>>);

View file

@ -88,7 +88,9 @@ class FakeCoinServiceAPI extends CoinServiceAPI {
}
@override
Future<void> initializeNew() {
Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data,
) {
// TODO: implement initializeNew
throw UnimplementedError();
}

View file

@ -2286,8 +2286,8 @@ void main() {
when(cachedClient.getAnonymitySet(
groupId: "1", blockhash: "", coin: Coin.firo))
.thenAnswer((_) async => GetAnonymitySetSampleData.data);
when(cachedClient.getUsedCoinSerials(startNumber: 0, coin: Coin.firo))
.thenAnswer((_) async => List<String>.from(
when(cachedClient.getUsedCoinSerials(coin: Coin.firo)).thenAnswer(
(_) async => List<String>.from(
GetUsedSerialsSampleData.serials['serials'] as List));
final firo = FiroWallet(

View file

@ -512,18 +512,12 @@ class MockCachedElectrumX extends _i1.Mock implements _i6.CachedElectrumX {
_i5.Future<Map<String, dynamic>>.value(<String, dynamic>{}),
) as _i5.Future<Map<String, dynamic>>);
@override
_i5.Future<List<String>> getUsedCoinSerials({
required _i7.Coin? coin,
int? startNumber = 0,
}) =>
_i5.Future<List<String>> getUsedCoinSerials({required _i7.Coin? coin}) =>
(super.noSuchMethod(
Invocation.method(
#getUsedCoinSerials,
[],
{
#coin: coin,
#startNumber: startNumber,
},
{#coin: coin},
),
returnValue: _i5.Future<List<String>>.value(<String>[]),
) as _i5.Future<List<String>>);

View file

@ -304,6 +304,11 @@ class MockFiroWallet extends _i1.Mock implements _i10.FiroWallet {
),
) as _i5.CachedElectrumX);
@override
bool get lelantusCoinIsarRescanRequired => (super.noSuchMethod(
Invocation.getter(#lelantusCoinIsarRescanRequired),
returnValue: false,
) as bool);
@override
bool get isRefreshing => (super.noSuchMethod(
Invocation.getter(#isRefreshing),
returnValue: false,
@ -552,15 +557,35 @@ class MockFiroWallet extends _i1.Mock implements _i10.FiroWallet {
returnValueForMissingStub: _i11.Future<void>.value(),
) as _i11.Future<void>);
@override
_i11.Future<void> initializeNew() => (super.noSuchMethod(
_i11.Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data) =>
(super.noSuchMethod(
Invocation.method(
#initializeNew,
[data],
),
returnValue: _i11.Future<void>.value(),
returnValueForMissingStub: _i11.Future<void>.value(),
) as _i11.Future<void>);
@override
_i11.Future<void> setLelantusCoinIsarRescanRequiredDone() =>
(super.noSuchMethod(
Invocation.method(
#setLelantusCoinIsarRescanRequiredDone,
[],
),
returnValue: _i11.Future<void>.value(),
returnValueForMissingStub: _i11.Future<void>.value(),
) as _i11.Future<void>);
@override
_i11.Future<bool> firoRescanRecovery() => (super.noSuchMethod(
Invocation.method(
#firoRescanRecovery,
[],
),
returnValue: _i11.Future<bool>.value(false),
) as _i11.Future<bool>);
@override
_i11.Future<void> initializeExisting() => (super.noSuchMethod(
Invocation.method(
#initializeExisting,

View file

@ -485,18 +485,12 @@ class MockCachedElectrumX extends _i1.Mock implements _i5.CachedElectrumX {
_i4.Future<Map<String, dynamic>>.value(<String, dynamic>{}),
) as _i4.Future<Map<String, dynamic>>);
@override
_i4.Future<List<String>> getUsedCoinSerials({
required _i6.Coin? coin,
int? startNumber = 0,
}) =>
_i4.Future<List<String>> getUsedCoinSerials({required _i6.Coin? coin}) =>
(super.noSuchMethod(
Invocation.method(
#getUsedCoinSerials,
[],
{
#coin: coin,
#startNumber: startNumber,
},
{#coin: coin},
),
returnValue: _i4.Future<List<String>>.value(<String>[]),
) as _i4.Future<List<String>>);

View file

@ -485,18 +485,12 @@ class MockCachedElectrumX extends _i1.Mock implements _i5.CachedElectrumX {
_i4.Future<Map<String, dynamic>>.value(<String, dynamic>{}),
) as _i4.Future<Map<String, dynamic>>);
@override
_i4.Future<List<String>> getUsedCoinSerials({
required _i6.Coin? coin,
int? startNumber = 0,
}) =>
_i4.Future<List<String>> getUsedCoinSerials({required _i6.Coin? coin}) =>
(super.noSuchMethod(
Invocation.method(
#getUsedCoinSerials,
[],
{
#coin: coin,
#startNumber: startNumber,
},
{#coin: coin},
),
returnValue: _i4.Future<List<String>>.value(<String>[]),
) as _i4.Future<List<String>>);

View file

@ -1078,10 +1078,12 @@ class MockBitcoinWallet extends _i1.Mock implements _i26.BitcoinWallet {
returnValueForMissingStub: null,
);
@override
_i23.Future<void> initializeNew() => (super.noSuchMethod(
_i23.Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data) =>
(super.noSuchMethod(
Invocation.method(
#initializeNew,
[],
[data],
),
returnValue: _i23.Future<void>.value(),
returnValueForMissingStub: _i23.Future<void>.value(),
@ -3056,10 +3058,12 @@ class MockManager extends _i1.Mock implements _i6.Manager {
returnValue: _i23.Future<bool>.value(false),
) as _i23.Future<bool>);
@override
_i23.Future<void> initializeNew() => (super.noSuchMethod(
_i23.Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data) =>
(super.noSuchMethod(
Invocation.method(
#initializeNew,
[],
[data],
),
returnValue: _i23.Future<void>.value(),
returnValueForMissingStub: _i23.Future<void>.value(),
@ -3409,10 +3413,12 @@ class MockCoinServiceAPI extends _i1.Mock implements _i20.CoinServiceAPI {
returnValueForMissingStub: _i23.Future<void>.value(),
) as _i23.Future<void>);
@override
_i23.Future<void> initializeNew() => (super.noSuchMethod(
_i23.Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data) =>
(super.noSuchMethod(
Invocation.method(
#initializeNew,
[],
[data],
),
returnValue: _i23.Future<void>.value(),
returnValueForMissingStub: _i23.Future<void>.value(),

View file

@ -1162,10 +1162,12 @@ class MockBitcoinWallet extends _i1.Mock implements _i28.BitcoinWallet {
returnValueForMissingStub: null,
);
@override
_i22.Future<void> initializeNew() => (super.noSuchMethod(
_i22.Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data) =>
(super.noSuchMethod(
Invocation.method(
#initializeNew,
[],
[data],
),
returnValue: _i22.Future<void>.value(),
returnValueForMissingStub: _i22.Future<void>.value(),
@ -2302,10 +2304,12 @@ class MockManager extends _i1.Mock implements _i6.Manager {
returnValue: _i22.Future<bool>.value(false),
) as _i22.Future<bool>);
@override
_i22.Future<void> initializeNew() => (super.noSuchMethod(
_i22.Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data) =>
(super.noSuchMethod(
Invocation.method(
#initializeNew,
[],
[data],
),
returnValue: _i22.Future<void>.value(),
returnValueForMissingStub: _i22.Future<void>.value(),
@ -2655,10 +2659,12 @@ class MockCoinServiceAPI extends _i1.Mock implements _i19.CoinServiceAPI {
returnValueForMissingStub: _i22.Future<void>.value(),
) as _i22.Future<void>);
@override
_i22.Future<void> initializeNew() => (super.noSuchMethod(
_i22.Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data) =>
(super.noSuchMethod(
Invocation.method(
#initializeNew,
[],
[data],
),
returnValue: _i22.Future<void>.value(),
returnValueForMissingStub: _i22.Future<void>.value(),

View file

@ -689,10 +689,12 @@ class MockManager extends _i1.Mock implements _i6.Manager {
returnValue: _i19.Future<bool>.value(false),
) as _i19.Future<bool>);
@override
_i19.Future<void> initializeNew() => (super.noSuchMethod(
_i19.Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data) =>
(super.noSuchMethod(
Invocation.method(
#initializeNew,
[],
[data],
),
returnValue: _i19.Future<void>.value(),
returnValueForMissingStub: _i19.Future<void>.value(),
@ -1046,10 +1048,12 @@ class MockCoinServiceAPI extends _i1.Mock implements _i7.CoinServiceAPI {
returnValueForMissingStub: _i19.Future<void>.value(),
) as _i19.Future<void>);
@override
_i19.Future<void> initializeNew() => (super.noSuchMethod(
_i19.Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data) =>
(super.noSuchMethod(
Invocation.method(
#initializeNew,
[],
[data],
),
returnValue: _i19.Future<void>.value(),
returnValueForMissingStub: _i19.Future<void>.value(),
@ -1313,6 +1317,11 @@ class MockFiroWallet extends _i1.Mock implements _i23.FiroWallet {
),
) as _i13.CachedElectrumX);
@override
bool get lelantusCoinIsarRescanRequired => (super.noSuchMethod(
Invocation.getter(#lelantusCoinIsarRescanRequired),
returnValue: false,
) as bool);
@override
bool get isRefreshing => (super.noSuchMethod(
Invocation.getter(#isRefreshing),
returnValue: false,
@ -1561,15 +1570,35 @@ class MockFiroWallet extends _i1.Mock implements _i23.FiroWallet {
returnValueForMissingStub: _i19.Future<void>.value(),
) as _i19.Future<void>);
@override
_i19.Future<void> initializeNew() => (super.noSuchMethod(
_i19.Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data) =>
(super.noSuchMethod(
Invocation.method(
#initializeNew,
[data],
),
returnValue: _i19.Future<void>.value(),
returnValueForMissingStub: _i19.Future<void>.value(),
) as _i19.Future<void>);
@override
_i19.Future<void> setLelantusCoinIsarRescanRequiredDone() =>
(super.noSuchMethod(
Invocation.method(
#setLelantusCoinIsarRescanRequiredDone,
[],
),
returnValue: _i19.Future<void>.value(),
returnValueForMissingStub: _i19.Future<void>.value(),
) as _i19.Future<void>);
@override
_i19.Future<bool> firoRescanRecovery() => (super.noSuchMethod(
Invocation.method(
#firoRescanRecovery,
[],
),
returnValue: _i19.Future<bool>.value(false),
) as _i19.Future<bool>);
@override
_i19.Future<void> initializeExisting() => (super.noSuchMethod(
Invocation.method(
#initializeExisting,

View file

@ -817,10 +817,12 @@ class MockBitcoinWallet extends _i1.Mock implements _i24.BitcoinWallet {
returnValueForMissingStub: null,
);
@override
_i21.Future<void> initializeNew() => (super.noSuchMethod(
_i21.Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data) =>
(super.noSuchMethod(
Invocation.method(
#initializeNew,
[],
[data],
),
returnValue: _i21.Future<void>.value(),
returnValueForMissingStub: _i21.Future<void>.value(),

View file

@ -1072,10 +1072,12 @@ class MockBitcoinWallet extends _i1.Mock implements _i26.BitcoinWallet {
returnValueForMissingStub: null,
);
@override
_i23.Future<void> initializeNew() => (super.noSuchMethod(
_i23.Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data) =>
(super.noSuchMethod(
Invocation.method(
#initializeNew,
[],
[data],
),
returnValue: _i23.Future<void>.value(),
returnValueForMissingStub: _i23.Future<void>.value(),
@ -2411,10 +2413,12 @@ class MockManager extends _i1.Mock implements _i6.Manager {
returnValue: _i23.Future<bool>.value(false),
) as _i23.Future<bool>);
@override
_i23.Future<void> initializeNew() => (super.noSuchMethod(
_i23.Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data) =>
(super.noSuchMethod(
Invocation.method(
#initializeNew,
[],
[data],
),
returnValue: _i23.Future<void>.value(),
returnValueForMissingStub: _i23.Future<void>.value(),
@ -2764,10 +2768,12 @@ class MockCoinServiceAPI extends _i1.Mock implements _i20.CoinServiceAPI {
returnValueForMissingStub: _i23.Future<void>.value(),
) as _i23.Future<void>);
@override
_i23.Future<void> initializeNew() => (super.noSuchMethod(
_i23.Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data) =>
(super.noSuchMethod(
Invocation.method(
#initializeNew,
[],
[data],
),
returnValue: _i23.Future<void>.value(),
returnValueForMissingStub: _i23.Future<void>.value(),

View file

@ -1174,10 +1174,12 @@ class MockBitcoinWallet extends _i1.Mock implements _i29.BitcoinWallet {
returnValueForMissingStub: null,
);
@override
_i23.Future<void> initializeNew() => (super.noSuchMethod(
_i23.Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data) =>
(super.noSuchMethod(
Invocation.method(
#initializeNew,
[],
[data],
),
returnValue: _i23.Future<void>.value(),
returnValueForMissingStub: _i23.Future<void>.value(),
@ -2514,10 +2516,12 @@ class MockManager extends _i1.Mock implements _i6.Manager {
returnValue: _i23.Future<bool>.value(false),
) as _i23.Future<bool>);
@override
_i23.Future<void> initializeNew() => (super.noSuchMethod(
_i23.Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data) =>
(super.noSuchMethod(
Invocation.method(
#initializeNew,
[],
[data],
),
returnValue: _i23.Future<void>.value(),
returnValueForMissingStub: _i23.Future<void>.value(),
@ -2867,10 +2871,12 @@ class MockCoinServiceAPI extends _i1.Mock implements _i20.CoinServiceAPI {
returnValueForMissingStub: _i23.Future<void>.value(),
) as _i23.Future<void>);
@override
_i23.Future<void> initializeNew() => (super.noSuchMethod(
_i23.Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data) =>
(super.noSuchMethod(
Invocation.method(
#initializeNew,
[],
[data],
),
returnValue: _i23.Future<void>.value(),
returnValueForMissingStub: _i23.Future<void>.value(),