Merge pull request #104 from cypherstack/staging

Staging
This commit is contained in:
Rylee Davis 2022-09-29 18:20:04 -06:00 committed by GitHub
commit 4d946bfe6b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
66 changed files with 8525 additions and 4351 deletions

View file

@ -0,0 +1,7 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12 23.8456C18.5421 23.8456 23.8456 18.5421 23.8456 12C23.8456 5.45778 18.5421 0.154297 12 0.154297C5.45778 0.154297 0.154297 5.45778 0.154297 12C0.154297 18.5421 5.45778 23.8456 12 23.8456Z" fill="white"/>
<path d="M12 24C5.38264 24 0 18.6174 0 12C0 5.38264 5.38264 0 12 0C18.6174 0 24 5.38264 24 12C24 18.6174 18.6174 24 12 24ZM12 0.327974C5.55627 0.327974 0.327974 5.57556 0.327974 12C0.327974 18.4244 5.57556 23.672 12 23.672C18.4244 23.672 23.672 18.4244 23.672 12C23.672 5.57556 18.4437 0.327974 12 0.327974Z" fill="#D0509D"/>
<path d="M11.9995 0.154297C6.75195 0.154297 2.29536 3.58838 0.751953 8.31507H6.73266V15.7427L11.961 10.0707H12.0381L17.2664 15.762V8.31507H23.2471C21.7037 3.58838 17.2471 0.154297 11.9995 0.154297Z" fill="#FFCD05"/>
<path d="M6.56007 16.1672V8.48875H0.521484L0.598655 8.27653C2.19994 3.31833 6.79158 0 12.0006 0C17.2096 0 21.8012 3.31833 23.4025 8.27653L23.4797 8.48875H17.4411V16.1672L12.0006 10.283L6.56007 16.1672ZM11.9041 9.9164H12.1163L17.1131 15.3376V8.16077H23.036C21.3961 3.47267 16.9974 0.327974 12.0006 0.327974C7.0038 0.327974 2.60509 3.47267 0.965214 8.16077H6.88804V15.3376L11.9041 9.9164Z" fill="#D0509D"/>
<path d="M18.2473 18.2508L16.5495 16.418L11.9965 11.4791L7.4434 16.418L5.74565 18.2508V15.762V9.5498H1.59774C1.40482 10.3601 1.28906 11.209 1.28906 12.0964C1.28906 18 6.07363 22.8038 11.9965 22.8038C17.9193 22.8038 22.7039 18.0193 22.7039 12.0964C22.7039 11.2283 22.5881 10.3794 22.3952 9.5498H18.228V15.762V18.2508H18.2473Z" fill="#D0519D"/>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

25
assets/svg/drd-icon.svg Normal file
View file

@ -0,0 +1,25 @@
<svg width="99" height="70" viewBox="0 0 99 70" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_5372_11232)">
<path d="M91.2807 31.334H36.3926C32.1291 31.334 28.6729 34.8203 28.6729 39.1208V62.2128C28.6729 66.5134 32.1291 69.9996 36.3926 69.9996H91.2807C95.5442 69.9996 99.0004 66.5134 99.0004 62.2128V39.1208C99.0004 34.8203 95.5442 31.334 91.2807 31.334Z" fill="#E1E2E3"/>
<path d="M93.2051 28.6192V59.8664C93.2051 62.0499 91.4525 63.8177 89.2879 63.8177H25.0787C22.9088 63.8177 21.1562 62.0499 21.1562 59.8611V28.6245C21.1562 26.441 22.9088 24.668 25.0787 24.668H77.9639L89.3035 24.789C91.2856 24.81 93.0226 26.2937 93.1947 28.2773C93.2051 28.3877 93.2103 28.4982 93.2103 28.614L93.2051 28.6192Z" stroke="#222222" stroke-width="3" stroke-miterlimit="10"/>
<path d="M48.665 38.6689V49.8177" stroke="#222222" stroke-width="3" stroke-miterlimit="10" stroke-linecap="round"/>
<path d="M43.877 41.457L53.4483 47.0288" stroke="#222222" stroke-width="3" stroke-miterlimit="10" stroke-linecap="round"/>
<path d="M53.4483 41.457L43.877 47.0288" stroke="#222222" stroke-width="3" stroke-miterlimit="10" stroke-linecap="round"/>
<path d="M32.5166 38.6689V49.8177" stroke="#222222" stroke-width="3" stroke-miterlimit="10" stroke-linecap="round"/>
<path d="M27.7285 41.457L37.2999 47.0288" stroke="#222222" stroke-width="3" stroke-miterlimit="10" stroke-linecap="round"/>
<path d="M37.2999 41.457L27.7285 47.0288" stroke="#222222" stroke-width="3" stroke-miterlimit="10" stroke-linecap="round"/>
<path d="M64.9658 38.6689V49.8177" stroke="#222222" stroke-width="3" stroke-miterlimit="10" stroke-linecap="round"/>
<path d="M60.1777 41.457L69.7491 47.0288" stroke="#222222" stroke-width="3" stroke-miterlimit="10" stroke-linecap="round"/>
<path d="M69.7491 41.457L60.1777 47.0288" stroke="#222222" stroke-width="3" stroke-miterlimit="10" stroke-linecap="round"/>
<path d="M81.0518 38.6689V49.8177" stroke="#222222" stroke-width="3" stroke-miterlimit="10" stroke-linecap="round"/>
<path d="M76.2686 41.457L85.84 47.0288" stroke="#222222" stroke-width="3" stroke-miterlimit="10" stroke-linecap="round"/>
<path d="M85.84 41.457L76.2686 47.0288" stroke="#222222" stroke-width="3" stroke-miterlimit="10" stroke-linecap="round"/>
<path d="M21.1565 50.8068V56.1681C11.9085 54.3214 4.21483 47.3396 1.69028 37.6902C1.62247 37.4272 1.78417 37.1589 2.04497 37.0957L6.15519 36.0855C6.40556 36.0224 6.65071 36.175 6.71852 36.4275C8.64845 43.6987 14.2818 49.0548 21.1565 50.8068V50.8068Z" stroke="#222222" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M50.6117 24.6681H45.2027C43.93 20.8221 41.541 17.4443 38.2654 14.9504C33.9778 11.6883 28.6888 10.2941 23.3684 11.0412C23.045 11.0886 22.7164 11.1412 22.3983 11.2043L26.4146 16.0711L11.5333 17.0076C11.0534 17.0339 10.6831 16.5867 10.803 16.1131L14.5273 1.68652L18.7105 6.74268C19.9885 6.34282 21.3081 6.05344 22.6538 5.86403C29.346 4.92751 36.0016 6.67428 41.3898 10.7781C45.9747 14.2822 49.1877 19.1384 50.6117 24.6734V24.6681Z" stroke="#222222" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
</g>
<defs>
<clipPath id="clip0_5372_11232">
<rect width="99" height="70" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

@ -1 +1 @@
Subproject commit 4bffa40cb60ad3d98cf0ea5b5d819f3f4895dcd6
Subproject commit 8e3afd002968d21a3de788569356587a70818022

View file

@ -8,6 +8,7 @@ import 'package:cw_core/wallet_type.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_libmonero/monero/monero.dart';
import 'package:flutter_libmonero/wownero/wownero.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:hive_flutter/hive_flutter.dart';
@ -84,7 +85,6 @@ void main() async {
appDirectory = (await getLibraryDirectory());
}
// FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding);
await Hive.initFlutter(appDirectory.path);
if (!(Logging.isArmLinux || Logging.isTestEnv)) {
final isar = await Isar.open(
[LogSchema],
@ -128,11 +128,14 @@ void main() async {
Hive.registerAdapter(NodeAdapter());
Hive.registerAdapter(WalletInfoAdapter());
if (!Hive.isAdapterRegistered(WalletInfoAdapter().typeId)) {
Hive.registerAdapter(WalletInfoAdapter());
}
Hive.registerAdapter(WalletTypeAdapter());
Hive.registerAdapter(UnspentCoinsInfoAdapter());
await Hive.initFlutter(appDirectory.path);
await Hive.openBox<dynamic>(DB.boxNameDBInfo);
int dbVersion = DB.instance.get<dynamic>(
@ -143,6 +146,7 @@ void main() async {
}
monero.onStartup();
wownero.onStartup();
await Hive.openBox<dynamic>(DB.boxNameTheme);

View file

@ -37,9 +37,11 @@ class CreateOrRestoreWalletView extends StatelessWidget {
body: SizedBox(
width: 480,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const Spacer(
flex: 10,
),
CreateRestoreWalletTitle(
coin: coin,
isDesktop: isDesktop,
@ -67,6 +69,9 @@ class CreateOrRestoreWalletView extends StatelessWidget {
coin: coin,
isDesktop: isDesktop,
),
const Spacer(
flex: 15,
),
],
),
),

View file

@ -151,6 +151,10 @@ class _NameYourWalletViewState extends ConsumerState<NameYourWalletView> {
crossAxisAlignment:
isDesktop ? CrossAxisAlignment.center : CrossAxisAlignment.stretch,
children: [
if (isDesktop)
const Spacer(
flex: 10,
),
if (!isDesktop)
const Spacer(
flex: 1,
@ -163,7 +167,7 @@ class _NameYourWalletViewState extends ConsumerState<NameYourWalletView> {
height: 100,
),
SizedBox(
height: isDesktop ? 24 : 16,
height: isDesktop ? 0 : 16,
),
Text(
"Name your ${coin.prettyName} wallet",
@ -358,6 +362,10 @@ class _NameYourWalletViewState extends ConsumerState<NameYourWalletView> {
),
),
),
if (isDesktop)
const Spacer(
flex: 15,
),
],
);
}

View file

@ -90,224 +90,233 @@ class _NewWalletRecoveryPhraseViewState
Widget build(BuildContext context) {
debugPrint("BUILD: $runtimeType");
return WillPopScope(
onWillPop: onWillPop,
child: MasterScaffold(
isDesktop: isDesktop,
appBar: isDesktop
? DesktopAppBar(
isCompactHeight: false,
leading: AppBarBackButton(
onPressed: () async {
await delete();
onWillPop: onWillPop,
child: MasterScaffold(
isDesktop: isDesktop,
appBar: isDesktop
? DesktopAppBar(
isCompactHeight: false,
leading: AppBarBackButton(
onPressed: () async {
await delete();
if (mounted) {
Navigator.of(context).popUntil(
ModalRoute.withName(
NewWalletRecoveryPhraseWarningView.routeName,
),
);
}
// Navigator.of(context).pop();
},
),
trailing: ExitToMyStackButton(
onPressed: () async {
await delete();
if (mounted) {
Navigator.of(context).popUntil(
ModalRoute.withName(DesktopHomeView.routeName),
);
}
},
),
)
: AppBar(
leading: AppBarBackButton(
onPressed: () async {
await delete();
if (mounted) {
Navigator.of(context).popUntil(
ModalRoute.withName(
NewWalletRecoveryPhraseWarningView.routeName,
),
);
}
// Navigator.of(context).pop();
},
),
trailing: ExitToMyStackButton(
onPressed: () async {
await delete();
if (mounted) {
Navigator.of(context).popUntil(
ModalRoute.withName(DesktopHomeView.routeName),
);
}
},
),
)
: AppBar(
leading: AppBarBackButton(
onPressed: () async {
await delete();
if (mounted) {
Navigator.of(context).popUntil(
ModalRoute.withName(
NewWalletRecoveryPhraseWarningView.routeName,
),
);
}
},
),
actions: [
Padding(
padding: const EdgeInsets.all(10),
child: AspectRatio(
aspectRatio: 1,
child: AppBarIconButton(
if (mounted) {
Navigator.of(context).popUntil(
ModalRoute.withName(
NewWalletRecoveryPhraseWarningView.routeName,
),
);
}
},
),
actions: [
Padding(
padding: const EdgeInsets.all(10),
child: AspectRatio(
aspectRatio: 1,
child: AppBarIconButton(
color: Theme.of(context)
.extension<StackColors>()!
.background,
shadows: const [],
icon: SvgPicture.asset(
Assets.svg.copy,
width: 24,
height: 24,
color: Theme.of(context)
.extension<StackColors>()!
.background,
shadows: const [],
icon: SvgPicture.asset(
Assets.svg.copy,
width: 24,
height: 24,
color: Theme.of(context)
.extension<StackColors>()!
.topNavIconPrimary,
),
onPressed: () async {
await _copy();
},
.topNavIconPrimary,
),
),
),
],
),
body: Container(
color: Theme.of(context).extension<StackColors>()!.background,
width: isDesktop ? 600 : null,
child: Padding(
padding: isDesktop
? const EdgeInsets.all(0)
: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
if (!isDesktop)
const SizedBox(
height: 4,
),
if (!isDesktop)
Text(
_manager.walletName,
textAlign: TextAlign.center,
style: STextStyles.label(context).copyWith(
fontSize: 12,
),
),
SizedBox(
height: isDesktop ? 24 : 4,
),
Text(
"Recovery Phrase",
textAlign: TextAlign.center,
style: isDesktop
? STextStyles.desktopH2(context)
: STextStyles.pageTitleH1(context),
),
const SizedBox(
height: 16,
),
Container(
decoration: BoxDecoration(
color: isDesktop
? Theme.of(context)
.extension<StackColors>()!
.background
: Theme.of(context).extension<StackColors>()!.popupBG,
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius),
),
child: Padding(
padding: isDesktop
? const EdgeInsets.all(0)
: const EdgeInsets.all(12),
child: Text(
"Please write down your recovery phrase in the correct order and save it to keep your funds secure. You will also be asked to verify the words on the next screen.",
textAlign: TextAlign.center,
style: isDesktop
? STextStyles.desktopSubtitleH2(context)
: STextStyles.label(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.accentColorDark),
),
),
),
SizedBox(
height: isDesktop ? 21 : 8,
),
if (!isDesktop)
Expanded(
child: SingleChildScrollView(
child: MnemonicTable(
words: _mnemonic,
isDesktop: isDesktop,
),
),
),
if (isDesktop)
MnemonicTable(
words: _mnemonic,
isDesktop: isDesktop,
),
SizedBox(
height: isDesktop ? 24 : 16,
),
if (isDesktop)
SizedBox(
height: 70,
child: TextButton(
onPressed: () async {
await _copy();
},
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SvgPicture.asset(
Assets.svg.copy,
width: 20,
height: 20,
),
const SizedBox(
width: 10,
),
Text(
"Copy to clipboard",
style: STextStyles.desktopButtonSecondaryEnabled(
context),
)
],
),
),
),
if (isDesktop)
const SizedBox(
height: 16,
),
ConstrainedBox(
constraints: BoxConstraints(
minHeight: isDesktop ? 70 : 0,
),
child: TextButton(
onPressed: () async {
final int next = Random().nextInt(_mnemonic.length);
ref
.read(verifyMnemonicWordIndexStateProvider.state)
.update((state) => next);
ref
.read(verifyMnemonicCorrectWordStateProvider.state)
.update((state) => _mnemonic[next]);
unawaited(Navigator.of(context).pushNamed(
VerifyRecoveryPhraseView.routeName,
arguments: Tuple2(_manager, _mnemonic),
));
},
style: Theme.of(context)
.extension<StackColors>()!
.getPrimaryEnabledButtonColor(context),
child: Text(
"I saved my recovery phrase",
style: isDesktop
? STextStyles.desktopButtonEnabled(context)
: STextStyles.button(context),
),
),
),
],
),
body: Container(
color: Theme.of(context).extension<StackColors>()!.background,
width: isDesktop ? 600 : null,
child: Padding(
padding:
isDesktop ? const EdgeInsets.all(0) : const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
if (isDesktop)
const Spacer(
flex: 10,
),
if (!isDesktop)
const SizedBox(
height: 4,
),
if (!isDesktop)
Text(
_manager.walletName,
textAlign: TextAlign.center,
style: STextStyles.label(context).copyWith(
fontSize: 12,
),
),
SizedBox(
height: isDesktop ? 24 : 4,
),
Text(
"Recovery Phrase",
textAlign: TextAlign.center,
style: isDesktop
? STextStyles.desktopH2(context)
: STextStyles.pageTitleH1(context),
),
const SizedBox(
height: 16,
),
Container(
decoration: BoxDecoration(
color: isDesktop
? Theme.of(context).extension<StackColors>()!.background
: Theme.of(context).extension<StackColors>()!.popupBG,
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius),
),
child: Padding(
padding: isDesktop
? const EdgeInsets.all(0)
: const EdgeInsets.all(12),
child: Text(
"Please write down your recovery phrase in the correct order and save it to keep your funds secure. You will also be asked to verify the words on the next screen.",
textAlign: TextAlign.center,
style: isDesktop
? STextStyles.desktopSubtitleH2(context)
: STextStyles.label(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.accentColorDark),
),
),
),
SizedBox(
height: isDesktop ? 21 : 8,
),
if (!isDesktop)
Expanded(
child: SingleChildScrollView(
child: MnemonicTable(
words: _mnemonic,
isDesktop: isDesktop,
),
),
),
if (isDesktop)
MnemonicTable(
words: _mnemonic,
isDesktop: isDesktop,
),
SizedBox(
height: isDesktop ? 24 : 16,
),
if (isDesktop)
SizedBox(
height: 70,
child: TextButton(
onPressed: () async {
await _copy();
},
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SvgPicture.asset(
Assets.svg.copy,
width: 20,
height: 20,
color: Theme.of(context)
.extension<StackColors>()!
.buttonTextSecondary,
),
const SizedBox(
width: 10,
),
Text(
"Copy to clipboard",
style: STextStyles.desktopButtonSecondaryEnabled(
context),
)
],
),
),
),
if (isDesktop)
const SizedBox(
height: 16,
),
ConstrainedBox(
constraints: BoxConstraints(
minHeight: isDesktop ? 70 : 0,
),
child: TextButton(
onPressed: () async {
final int next = Random().nextInt(_mnemonic.length);
ref
.read(verifyMnemonicWordIndexStateProvider.state)
.update((state) => next);
ref
.read(verifyMnemonicCorrectWordStateProvider.state)
.update((state) => _mnemonic[next]);
unawaited(Navigator.of(context).pushNamed(
VerifyRecoveryPhraseView.routeName,
arguments: Tuple2(_manager, _mnemonic),
));
},
style: Theme.of(context)
.extension<StackColors>()!
.getPrimaryEnabledButtonColor(context),
child: Text(
"I saved my recovery phrase",
style: isDesktop
? STextStyles.desktopButtonEnabled(context)
: STextStyles.button(context),
),
),
),
if (isDesktop)
const Spacer(
flex: 15,
),
],
),
),
));
),
),
);
}
}

View file

@ -59,7 +59,9 @@ class _NewWalletRecoveryPhraseWarningViewState
final _numberOfPhraseWords = coin == Coin.monero
? Constants.seedPhraseWordCountMonero
: Constants.seedPhraseWordCountBip39;
: coin == Coin.wownero
? 14
: Constants.seedPhraseWordCountBip39;
return MasterScaffold(
isDesktop: isDesktop,
@ -79,9 +81,14 @@ class _NewWalletRecoveryPhraseWarningViewState
? CrossAxisAlignment.center
: CrossAxisAlignment.stretch,
children: [
const SizedBox(
height: 4,
),
if (isDesktop)
const Spacer(
flex: 10,
),
if (!isDesktop)
const SizedBox(
height: 4,
),
if (!isDesktop)
Text(
walletName,
@ -90,9 +97,10 @@ class _NewWalletRecoveryPhraseWarningViewState
fontSize: 12,
),
),
const SizedBox(
height: 4,
),
if (!isDesktop)
const SizedBox(
height: 4,
),
Text(
"Recovery Phrase",
textAlign: TextAlign.center,
@ -130,6 +138,7 @@ class _NewWalletRecoveryPhraseWarningViewState
builder: (_, ref, __) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisSize: MainAxisSize.min,
children: [
GestureDetector(
onTap: () {
@ -291,6 +300,10 @@ class _NewWalletRecoveryPhraseWarningViewState
},
),
),
if (isDesktop)
const Spacer(
flex: 15,
),
],
),
),

View file

@ -1,6 +1,13 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/utilities/util.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';
class ConfirmRecoveryDialog extends StatelessWidget {
@ -11,40 +18,94 @@ class ConfirmRecoveryDialog extends StatelessWidget {
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async {
return true;
},
child: StackDialog(
title: "Are you ready?",
message:
"Restoring your wallet may take a while. Please do not exit this screen once the process is started.",
leftButton: TextButton(
style: Theme.of(context)
.extension<StackColors>()!
.getSecondaryEnabledButtonColor(context),
child: Text(
"Cancel",
style: STextStyles.itemSubtitle12(context),
),
onPressed: () {
Navigator.of(context).pop();
},
if (Util.isDesktop) {
return DesktopDialog(
child: Column(
children: [
const DesktopDialogCloseButton(),
const SizedBox(
height: 5,
),
SvgPicture.asset(
Assets.svg.drd,
width: 99,
height: 70,
),
const Spacer(),
Text(
"Restore wallet",
style: STextStyles.desktopH2(context),
textAlign: TextAlign.center,
),
const SizedBox(
height: 16,
),
Text(
"Restoring your wallet may take a while.\nPlease do not exit this screen once the process is started.",
style: STextStyles.desktopTextMedium(context).copyWith(
color: Theme.of(context).extension<StackColors>()!.textDark3,
),
textAlign: TextAlign.center,
),
const Spacer(),
Padding(
padding: const EdgeInsets.only(
left: 32,
right: 32,
bottom: 32,
),
child: Row(
children: [
Expanded(
child: SecondaryButton(
label: "Cancel",
onPressed: () {
Navigator.of(context).pop();
},
),
),
const SizedBox(
width: 16,
),
Expanded(
child: PrimaryButton(
label: "Restore",
onPressed: () {
Navigator.of(context).pop();
onConfirm.call();
},
),
)
],
),
)
],
),
rightButton: TextButton(
style: Theme.of(context)
.extension<StackColors>()!
.getPrimaryEnabledButtonColor(context),
child: Text(
"Restore",
style: STextStyles.button(context),
);
} else {
return WillPopScope(
onWillPop: () async {
return true;
},
child: StackDialog(
title: "Are you ready?",
message:
"Restoring your wallet may take a while. Please do not exit this screen once the process is started.",
leftButton: SecondaryButton(
label: "Cancel",
onPressed: () {
Navigator.of(context).pop();
},
),
rightButton: PrimaryButton(
label: "Restore",
onPressed: () {
Navigator.of(context).pop();
onConfirm.call();
},
),
onPressed: () {
Navigator.of(context).pop();
onConfirm.call();
},
),
),
);
);
}
}
}

View file

@ -10,6 +10,7 @@ import 'package:stackwallet/pages/add_wallet_views/restore_wallet_view/restore_o
import 'package:stackwallet/pages/add_wallet_views/restore_wallet_view/restore_options_view/sub_widgets/restore_options_platform_layout.dart';
import 'package:stackwallet/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.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/home/my_stack_view/exit_to_my_stack_button.dart';
import 'package:stackwallet/providers/ui/color_theme_provider.dart';
import 'package:stackwallet/providers/ui/verify_recovery_phrase/mnemonic_word_count_state_provider.dart';
import 'package:stackwallet/utilities/assets.dart';
@ -79,59 +80,30 @@ class _RestoreOptionsViewState extends ConsumerState<RestoreOptionsView> {
colorArrowNext: Theme.of(context).extension<StackColors>()!.textSubtitle1,
colorArrowPrevious:
Theme.of(context).extension<StackColors>()!.textSubtitle1,
textStyleButtonNegative: GoogleFonts.inter(
textStyleButtonNegative: STextStyles.datePicker600(context).copyWith(
color: baseColor,
letterSpacing: 0.5,
fontSize: 16,
fontWeight: FontWeight.w600,
),
textStyleButtonPositive: GoogleFonts.inter(
textStyleButtonPositive: STextStyles.datePicker600(context).copyWith(
color: baseColor,
letterSpacing: 0.5,
fontSize: 16,
fontWeight: FontWeight.w600,
),
textStyleCurrentDayOnCalendar: GoogleFonts.inter(
fontSize: 12,
fontWeight: FontWeight.w400,
letterSpacing: 0.5,
color: Theme.of(context).extension<StackColors>()!.accentColorDark,
),
textStyleDayHeader: GoogleFonts.inter(
letterSpacing: 0.5,
color: Theme.of(context).extension<StackColors>()!.accentColorDark,
fontSize: 16,
fontWeight: FontWeight.w600,
),
textStyleDayOnCalendar: GoogleFonts.inter(
textStyleCurrentDayOnCalendar: STextStyles.datePicker400(context),
textStyleDayHeader: STextStyles.datePicker600(context),
textStyleDayOnCalendar: STextStyles.datePicker400(context).copyWith(
color: baseColor,
fontSize: 12,
fontWeight: FontWeight.w400,
letterSpacing: 0.5,
),
textStyleDayOnCalendarDisabled: GoogleFonts.inter(
fontSize: 12,
fontWeight: FontWeight.w400,
letterSpacing: 0.5,
textStyleDayOnCalendarDisabled:
STextStyles.datePicker400(context).copyWith(
color: Theme.of(context).extension<StackColors>()!.textSubtitle3,
),
textStyleDayOnCalendarSelected: GoogleFonts.inter(
fontSize: 12,
fontWeight: FontWeight.w400,
letterSpacing: 0.5,
textStyleDayOnCalendarSelected:
STextStyles.datePicker400(context).copyWith(
color: Theme.of(context).extension<StackColors>()!.popupBG,
),
textStyleMonthYearHeader: GoogleFonts.inter(
letterSpacing: 0.5,
textStyleMonthYearHeader: STextStyles.datePicker600(context).copyWith(
color: Theme.of(context).extension<StackColors>()!.textSubtitle1,
fontSize: 16,
fontWeight: FontWeight.w600,
),
textStyleYearButton: GoogleFonts.inter(
letterSpacing: 0.5,
textStyleYearButton: STextStyles.datePicker600(context).copyWith(
color: Theme.of(context).extension<StackColors>()!.textWhite,
fontSize: 16,
fontWeight: FontWeight.w600,
),
textStyleButtonAction: GoogleFonts.inter(),
);
@ -139,16 +111,10 @@ class _RestoreOptionsViewState extends ConsumerState<RestoreOptionsView> {
MaterialRoundedYearPickerStyle _buildYearPickerStyle() {
return MaterialRoundedYearPickerStyle(
textStyleYear: GoogleFonts.inter(
letterSpacing: 0.5,
textStyleYear: STextStyles.datePicker600(context).copyWith(
color: Theme.of(context).extension<StackColors>()!.textSubtitle2,
fontWeight: FontWeight.w600,
fontSize: 16,
),
textStyleYearSelected: GoogleFonts.inter(
letterSpacing: 0.5,
color: Theme.of(context).extension<StackColors>()!.accentColorDark,
fontWeight: FontWeight.w600,
textStyleYearSelected: STextStyles.datePicker600(context).copyWith(
fontSize: 18,
),
);
@ -232,11 +198,13 @@ class _RestoreOptionsViewState extends ConsumerState<RestoreOptionsView> {
final lengths = Constants.possibleLengthsForCoin(coin).toList();
return DesktopScaffold(
return MasterScaffold(
isDesktop: isDesktop,
appBar: isDesktop
? const DesktopAppBar(
isCompactHeight: false,
leading: AppBarBackButton(),
trailing: ExitToMyStackButton(),
)
: AppBar(
leading: AppBarBackButton(
@ -260,10 +228,9 @@ class _RestoreOptionsViewState extends ConsumerState<RestoreOptionsView> {
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
if (!isDesktop)
const Spacer(
flex: 1,
),
Spacer(
flex: isDesktop ? 10 : 1,
),
if (!isDesktop)
Image(
image: AssetImage(
@ -272,7 +239,7 @@ class _RestoreOptionsViewState extends ConsumerState<RestoreOptionsView> {
height: 100,
),
SizedBox(
height: isDesktop ? 24 : 16,
height: isDesktop ? 0 : 16,
),
Text(
"Restore options",
@ -417,6 +384,11 @@ class _RestoreOptionsViewState extends ConsumerState<RestoreOptionsView> {
isDesktop: isDesktop,
onPressed: _nextEnabled ? nextPressed : null,
),
if (isDesktop)
const Spacer(
flex: 15,
),
],
),
),

View file

@ -17,6 +17,7 @@ import 'package:stackwallet/pages/add_wallet_views/restore_wallet_view/sub_widge
import 'package:stackwallet/pages/add_wallet_views/restore_wallet_view/sub_widgets/restoring_dialog.dart';
import 'package:stackwallet/pages/home_view/home_view.dart';
import 'package:stackwallet/pages_desktop_specific/home/desktop_home_view.dart';
import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/exit_to_my_stack_button.dart';
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/services/coins/coin_service.dart';
import 'package:stackwallet/services/coins/manager.dart';
@ -36,8 +37,14 @@ import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/utilities/util.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/icon_widgets/clipboard_icon.dart';
import 'package:stackwallet/widgets/icon_widgets/qrcode_icon.dart';
import 'package:stackwallet/widgets/table_view/table_view.dart';
import 'package:stackwallet/widgets/table_view/table_view_cell.dart';
import 'package:stackwallet/widgets/table_view/table_view_row.dart';
import 'package:wakelock/wakelock.dart';
class RestoreWalletView extends ConsumerStatefulWidget {
@ -193,7 +200,7 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
// TODO: do actual check to make sure it is a valid mnemonic for monero
if (bip39.validateMnemonic(mnemonic) == false &&
!(widget.coin == Coin.monero)) {
!(widget.coin == Coin.monero || widget.coin == Coin.wownero)) {
unawaited(showFloatingFlushBar(
type: FlushBarType.warning,
message: "Invalid seed phrase!",
@ -404,6 +411,7 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
prefix,
style: STextStyles.fieldLabel(context).copyWith(
color: prefixColor,
fontSize: Util.isDesktop ? 16 : 14,
),
),
),
@ -412,7 +420,7 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
minWidth: 16,
minHeight: 16,
maxWidth: 36,
maxHeight: 20,
maxHeight: 32,
),
suffixIconConstraints: const BoxConstraints(
minWidth: 16,
@ -529,193 +537,483 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: AppBarBackButton(
onPressed: () async {
if (FocusScope.of(context).hasFocus) {
FocusScope.of(context).unfocus();
await Future<void>.delayed(const Duration(milliseconds: 50));
}
if (mounted) {
Navigator.of(context).pop();
}
},
),
actions: [
Padding(
padding: const EdgeInsets.only(
top: 10,
bottom: 10,
right: 10,
),
child: AspectRatio(
aspectRatio: 1,
child: AppBarIconButton(
key: const Key("restoreWalletViewQrCodeButton"),
size: 36,
shadows: const [],
color: Theme.of(context).extension<StackColors>()!.background,
icon: QrCodeIcon(
width: 20,
height: 20,
color: Theme.of(context)
.extension<StackColors>()!
.accentColorDark,
),
onPressed: scanMnemonicQr,
final isDesktop = Util.isDesktop;
return MasterScaffold(
isDesktop: isDesktop,
appBar: isDesktop
? const DesktopAppBar(
isCompactHeight: false,
leading: AppBarBackButton(),
trailing: ExitToMyStackButton(),
)
: AppBar(
leading: AppBarBackButton(
onPressed: () async {
if (FocusScope.of(context).hasFocus) {
FocusScope.of(context).unfocus();
await Future<void>.delayed(
const Duration(milliseconds: 50));
}
if (mounted) {
Navigator.of(context).pop();
}
},
),
),
),
Padding(
padding: const EdgeInsets.only(
top: 10,
bottom: 10,
right: 10,
),
child: AspectRatio(
aspectRatio: 1,
child: AppBarIconButton(
key: const Key("restoreWalletPasteButton"),
size: 36,
shadows: const [],
color: Theme.of(context).extension<StackColors>()!.background,
icon: ClipboardIcon(
width: 20,
height: 20,
color: Theme.of(context)
.extension<StackColors>()!
.accentColorDark,
actions: [
Padding(
padding: const EdgeInsets.only(
top: 10,
bottom: 10,
right: 10,
),
child: AspectRatio(
aspectRatio: 1,
child: AppBarIconButton(
key: const Key("restoreWalletViewQrCodeButton"),
size: 36,
shadows: const [],
color: Theme.of(context)
.extension<StackColors>()!
.background,
icon: QrCodeIcon(
width: 20,
height: 20,
color: Theme.of(context)
.extension<StackColors>()!
.accentColorDark,
),
onPressed: scanMnemonicQr,
),
),
),
onPressed: pasteMnemonic,
),
Padding(
padding: const EdgeInsets.only(
top: 10,
bottom: 10,
right: 10,
),
child: AspectRatio(
aspectRatio: 1,
child: AppBarIconButton(
key: const Key("restoreWalletPasteButton"),
size: 36,
shadows: const [],
color: Theme.of(context)
.extension<StackColors>()!
.background,
icon: ClipboardIcon(
width: 20,
height: 20,
color: Theme.of(context)
.extension<StackColors>()!
.accentColorDark,
),
onPressed: pasteMnemonic,
),
),
),
],
),
),
],
),
body: Container(
color: Theme.of(context).extension<StackColors>()!.background,
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Column(
children: [
Text(
widget.walletName,
style: STextStyles.itemSubtitle(context),
),
const SizedBox(
height: 4,
if (isDesktop)
const Spacer(
flex: 10,
),
if (!isDesktop)
Text(
widget.walletName,
style: STextStyles.itemSubtitle(context),
),
SizedBox(
height: isDesktop ? 0 : 4,
),
Text(
"Recovery phrase",
style: STextStyles.pageTitleH1(context),
style: isDesktop
? STextStyles.desktopH2(context)
: STextStyles.pageTitleH1(context),
),
const SizedBox(
height: 8,
SizedBox(
height: isDesktop ? 16 : 8,
),
Text(
"Enter your $_seedWordCount-word recovery phrase.",
style: STextStyles.subtitle(context),
style: isDesktop
? STextStyles.desktopSubtitleH2(context)
: STextStyles.subtitle(context),
),
const SizedBox(
height: 10,
SizedBox(
height: isDesktop ? 16 : 10,
),
Expanded(
child: SingleChildScrollView(
controller: controller,
child: Padding(
padding: const EdgeInsets.all(4.0),
child: Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
if (isDesktop)
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextButton(
onPressed: pasteMnemonic,
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 12,
),
child: Row(
children: [
SvgPicture.asset(
Assets.svg.clipboard,
width: 22,
height: 22,
color: Theme.of(context)
.extension<StackColors>()!
.buttonTextSecondary,
),
const SizedBox(
width: 8,
),
Text(
"Paste",
style: STextStyles
.desktopButtonSmallSecondaryEnabled(context),
)
],
),
),
),
],
),
if (isDesktop)
const SizedBox(
height: 20,
),
if (isDesktop)
ConstrainedBox(
constraints: const BoxConstraints(
maxWidth: 1008,
),
child: Builder(
builder: (BuildContext context) {
const cols = 4;
final int rows = _seedWordCount ~/ cols;
final int remainder = _seedWordCount % cols;
return Column(
children: [
for (int i = 1; i <= _seedWordCount; i++)
Column(
children: [
Padding(
padding:
const EdgeInsets.symmetric(vertical: 4),
child: TextFormField(
textCapitalization: TextCapitalization.none,
key: Key("restoreMnemonicFormField_$i"),
decoration: _getInputDecorationFor(
_inputStatuses[i - 1], "$i"),
autovalidateMode:
AutovalidateMode.onUserInteraction,
selectionControls:
i == 1 ? textSelectionControls : null,
onChanged: (value) {
if (value.isEmpty) {
setState(() {
_inputStatuses[i - 1] =
FormInputStatus.empty;
});
} else if (_isValidMnemonicWord(
value.trim().toLowerCase())) {
setState(() {
_inputStatuses[i - 1] =
FormInputStatus.valid;
});
} else {
setState(() {
_inputStatuses[i - 1] =
FormInputStatus.invalid;
});
}
},
controller: _controllers[i - 1],
style: STextStyles.field(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.overlay,
),
),
),
if (_inputStatuses[i - 1] ==
FormInputStatus.invalid)
Align(
alignment: Alignment.topLeft,
child: Padding(
padding: const EdgeInsets.only(
left: 12.0,
bottom: 4.0,
),
child: Text(
"Please check spelling",
textAlign: TextAlign.left,
style:
STextStyles.label(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textError,
Form(
key: _formKey,
child: TableView(
shrinkWrap: true,
rowSpacing: 20,
rows: [
for (int i = 0; i < rows; i++)
TableViewRow(
crossAxisAlignment:
CrossAxisAlignment.start,
spacing: 16,
cells: [
for (int j = 1; j <= cols; j++)
TableViewCell(
flex: 1,
child: Column(
children: [
TextFormField(
textCapitalization:
TextCapitalization.none,
key: Key(
"restoreMnemonicFormField_$i"),
decoration:
_getInputDecorationFor(
_inputStatuses[
i * 4 + j - 1],
"${i * 4 + j}"),
autovalidateMode:
AutovalidateMode
.onUserInteraction,
selectionControls:
i * 4 + j - 1 == 1
? textSelectionControls
: null,
onChanged: (value) {
if (value.isEmpty) {
setState(() {
_inputStatuses[
i * 4 + j - 1] =
FormInputStatus.empty;
});
} else if (_isValidMnemonicWord(
value
.trim()
.toLowerCase())) {
setState(() {
_inputStatuses[
i * 4 + j - 1] =
FormInputStatus.valid;
});
} else {
setState(() {
_inputStatuses[
i * 4 + j - 1] =
FormInputStatus
.invalid;
});
}
},
controller:
_controllers[i * 4 + j - 1],
style:
STextStyles.field(context)
.copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.overlay,
fontSize: isDesktop ? 16 : 14,
),
),
if (_inputStatuses[
i * 4 + j - 1] ==
FormInputStatus.invalid)
Align(
alignment: Alignment.topLeft,
child: Padding(
padding:
const EdgeInsets.only(
left: 12.0,
bottom: 4.0,
),
child: Text(
"Please check spelling",
textAlign: TextAlign.left,
style: STextStyles.label(
context)
.copyWith(
color: Theme.of(context)
.extension<
StackColors>()!
.textError,
),
),
),
)
],
),
),
),
),
)
],
expandingChild: null,
),
if (remainder > 0)
TableViewRow(
spacing: 16,
cells: [
for (int i = rows * cols;
i < _seedWordCount;
i++) ...[
TableViewCell(
flex: 1,
child: Column(
children: [
TextFormField(
textCapitalization:
TextCapitalization.none,
key: Key(
"restoreMnemonicFormField_$i"),
decoration:
_getInputDecorationFor(
_inputStatuses[i],
"${i + 1}"),
autovalidateMode:
AutovalidateMode
.onUserInteraction,
selectionControls: i == 1
? textSelectionControls
: null,
onChanged: (value) {
if (value.isEmpty) {
setState(() {
_inputStatuses[i] =
FormInputStatus.empty;
});
} else if (_isValidMnemonicWord(
value
.trim()
.toLowerCase())) {
setState(() {
_inputStatuses[i] =
FormInputStatus.valid;
});
} else {
setState(() {
_inputStatuses[i] =
FormInputStatus
.invalid;
});
}
},
controller: _controllers[i],
style:
STextStyles.field(context)
.copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.overlay,
fontSize: isDesktop ? 16 : 14,
),
),
if (_inputStatuses[i] ==
FormInputStatus.invalid)
Align(
alignment: Alignment.topLeft,
child: Padding(
padding:
const EdgeInsets.only(
left: 12.0,
bottom: 4.0,
),
child: Text(
"Please check spelling",
textAlign: TextAlign.left,
style: STextStyles.label(
context)
.copyWith(
color: Theme.of(context)
.extension<
StackColors>()!
.textError,
),
),
),
)
],
),
),
],
for (int i = remainder;
i < cols;
i++) ...[
TableViewCell(
flex: 1,
child: Container(),
),
],
],
expandingChild: null,
),
],
),
Padding(
padding: const EdgeInsets.only(
top: 8.0,
),
child: TextButton(
style: Theme.of(context)
.extension<StackColors>()!
.getPrimaryEnabledButtonColor(context),
onPressed: requestRestore,
child: Text(
"Restore",
style: STextStyles.button(context),
),
),
),
const SizedBox(
height: 32,
),
PrimaryButton(
label: "Restore wallet",
width: 480,
onPressed: requestRestore,
),
],
);
},
),
),
if (isDesktop)
const Spacer(
flex: 15,
),
if (!isDesktop)
Expanded(
child: SingleChildScrollView(
controller: controller,
child: Padding(
padding: const EdgeInsets.all(4.0),
child: Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
for (int i = 1; i <= _seedWordCount; i++)
Column(
children: [
Padding(
padding:
const EdgeInsets.symmetric(vertical: 4),
child: TextFormField(
textCapitalization:
TextCapitalization.none,
key: Key("restoreMnemonicFormField_$i"),
decoration: _getInputDecorationFor(
_inputStatuses[i - 1], "$i"),
autovalidateMode:
AutovalidateMode.onUserInteraction,
selectionControls:
i == 1 ? textSelectionControls : null,
onChanged: (value) {
if (value.isEmpty) {
setState(() {
_inputStatuses[i - 1] =
FormInputStatus.empty;
});
} else if (_isValidMnemonicWord(
value.trim().toLowerCase())) {
setState(() {
_inputStatuses[i - 1] =
FormInputStatus.valid;
});
} else {
setState(() {
_inputStatuses[i - 1] =
FormInputStatus.invalid;
});
}
},
controller: _controllers[i - 1],
style:
STextStyles.field(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.overlay,
fontSize: isDesktop ? 16 : 14,
),
),
),
if (_inputStatuses[i - 1] ==
FormInputStatus.invalid)
Align(
alignment: Alignment.topLeft,
child: Padding(
padding: const EdgeInsets.only(
left: 12.0,
bottom: 4.0,
),
child: Text(
"Please check spelling",
textAlign: TextAlign.left,
style: STextStyles.label(context)
.copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textError,
),
),
),
)
],
),
Padding(
padding: const EdgeInsets.only(
top: 8.0,
),
child: PrimaryButton(
onPressed: requestRestore,
label: "Restore",
),
),
],
),
),
),
),
),
),
],
),
),

View file

@ -3,6 +3,10 @@ import 'package:flutter_svg/svg.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/utilities/util.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/stack_dialog.dart';
class RestoreSucceededDialog extends StatelessWidget {
@ -10,27 +14,82 @@ class RestoreSucceededDialog extends StatelessWidget {
@override
Widget build(BuildContext context) {
return StackDialog(
title: "Wallet restored",
message: "You can use your wallet now.",
icon: SvgPicture.asset(
Assets.svg.checkCircle,
width: 24,
height: 24,
color: Theme.of(context).extension<StackColors>()!.accentColorGreen,
),
rightButton: TextButton(
style: Theme.of(context)
.extension<StackColors>()!
.getSecondaryEnabledButtonColor(context),
child: Text(
"Ok",
style: STextStyles.itemSubtitle12(context),
if (Util.isDesktop) {
return DesktopDialog(
child: Column(
children: [
const DesktopDialogCloseButton(),
const Spacer(
flex: 1,
),
SvgPicture.asset(
Assets.svg.checkCircle,
width: 40,
height: 40,
color:
Theme.of(context).extension<StackColors>()!.accentColorDark,
),
const Spacer(
flex: 2,
),
Text(
"Wallet restored",
style: STextStyles.desktopH2(context),
textAlign: TextAlign.center,
),
const SizedBox(
height: 16,
),
Text(
"You can use your wallet now.",
style: STextStyles.desktopTextMedium(context).copyWith(
color: Theme.of(context).extension<StackColors>()!.textDark3,
),
textAlign: TextAlign.center,
),
const Spacer(
flex: 2,
),
Padding(
padding: const EdgeInsets.only(
left: 32,
right: 32,
bottom: 32,
),
child: PrimaryButton(
width: 272.5,
label: "OK",
onPressed: () {
Navigator.of(context).pop();
},
),
),
],
),
onPressed: () {
Navigator.of(context).pop();
},
),
);
);
} else {
return StackDialog(
title: "Wallet restored",
message: "You can use your wallet now.",
icon: SvgPicture.asset(
Assets.svg.checkCircle,
width: 24,
height: 24,
color: Theme.of(context).extension<StackColors>()!.accentColorGreen,
),
rightButton: TextButton(
style: Theme.of(context)
.extension<StackColors>()!
.getSecondaryEnabledButtonColor(context),
child: Text(
"Ok",
style: STextStyles.itemSubtitle12(context),
),
onPressed: () {
Navigator.of(context).pop();
},
),
);
}
}
}

View file

@ -3,6 +3,10 @@ import 'package:flutter_svg/svg.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart';
import 'package:stackwallet/widgets/desktop/secondary_button.dart';
import 'package:stackwallet/widgets/stack_dialog.dart';
class RestoringDialog extends StatefulWidget {
@ -50,37 +54,105 @@ class _RestoringDialogState extends State<RestoringDialog>
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async {
return false;
},
child: StackDialog(
title: "Restoring wallet",
message: "This may take a while. Please do not exit this screen.",
icon: RotationTransition(
turns: _spinAnimation,
child: SvgPicture.asset(Assets.svg.arrowRotate3,
width: 24,
height: 24,
color:
Theme.of(context).extension<StackColors>()!.accentColorDark),
if (Util.isDesktop) {
return DesktopDialog(
child: Column(
children: [
DesktopDialogCloseButton(
onPressedOverride: () async {
await onCancel.call();
if (mounted) {
Navigator.of(context).pop();
}
},
),
const Spacer(
flex: 1,
),
RotationTransition(
turns: _spinAnimation,
child: SvgPicture.asset(Assets.svg.arrowRotate3,
width: 40,
height: 40,
color: Theme.of(context)
.extension<StackColors>()!
.accentColorDark),
),
const Spacer(
flex: 2,
),
Text(
"Restoring wallet...",
style: STextStyles.desktopH2(context),
textAlign: TextAlign.center,
),
const SizedBox(
height: 16,
),
Text(
"Restoring your wallet may take a while.\nPlease do not exit this screen.",
style: STextStyles.desktopTextMedium(context).copyWith(
color: Theme.of(context).extension<StackColors>()!.textDark3,
),
textAlign: TextAlign.center,
),
const Spacer(
flex: 2,
),
Padding(
padding: const EdgeInsets.only(
left: 32,
right: 32,
bottom: 32,
),
child: SecondaryButton(
label: "Cancel",
width: 272.5,
onPressed: () async {
await onCancel.call();
if (mounted) {
Navigator.of(context).pop();
}
},
),
),
],
),
rightButton: TextButton(
style: Theme.of(context)
.extension<StackColors>()!
.getSecondaryEnabledButtonColor(context),
child: Text(
"Cancel",
style: STextStyles.itemSubtitle12(context),
);
} else {
return WillPopScope(
onWillPop: () async {
return false;
},
child: StackDialog(
title: "Restoring wallet",
message: "This may take a while. Please do not exit this screen.",
icon: RotationTransition(
turns: _spinAnimation,
child: SvgPicture.asset(Assets.svg.arrowRotate3,
width: 24,
height: 24,
color: Theme.of(context)
.extension<StackColors>()!
.accentColorDark),
),
rightButton: TextButton(
style: Theme.of(context)
.extension<StackColors>()!
.getSecondaryEnabledButtonColor(context),
child: Text(
"Cancel",
style: STextStyles.itemSubtitle12(context),
),
onPressed: () async {
await onCancel.call();
if (mounted) {
Navigator.of(context).pop();
}
},
),
onPressed: () async {
await onCancel.call();
if (mounted) {
Navigator.of(context).pop();
}
},
),
),
);
);
}
}
}

View file

@ -56,10 +56,23 @@ class WordTableItem extends ConsumerWidget {
textAlign: TextAlign.center,
style: isDesktop
? STextStyles.desktopTextExtraSmall(context).copyWith(
color:
Theme.of(context).extension<StackColors>()!.textDark,
color: selectedWord == word
? Theme.of(context)
.extension<StackColors>()!
.textSelectedWordTableItem
: Theme.of(context)
.extension<StackColors>()!
.textDark,
)
: STextStyles.baseXS(context),
: STextStyles.baseXS(context).copyWith(
color: selectedWord == word
? Theme.of(context)
.extension<StackColors>()!
.textSelectedWordTableItem
: Theme.of(context)
.extension<StackColors>()!
.textDark,
),
),
],
),

View file

@ -236,6 +236,10 @@ class _VerifyRecoveryPhraseViewState
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
if (isDesktop)
const Spacer(
flex: 10,
),
SizedBox(
height: isDesktop ? 24 : 4,
),
@ -349,6 +353,10 @@ class _VerifyRecoveryPhraseViewState
),
],
),
if (isDesktop)
const Spacer(
flex: 15,
),
],
),
),

View file

@ -85,7 +85,7 @@ class _SendFromViewState extends ConsumerState<SendFromView> {
height: 8,
),
Text(
"You need to send ${amount.toStringAsFixed(coin == Coin.monero ? 12 : 8)} ${coin.ticker}",
"You need to send ${amount.toStringAsFixed(coin == Coin.monero ? Constants.satsPerCoinMonero : coin == Coin.wownero ? Constants.satsPerCoinWownero : Constants.satsPerCoin)} ${coin.ticker}",
style: STextStyles.itemSubtitle(context),
),
const SizedBox(
@ -307,7 +307,11 @@ class _SendFromCardState extends ConsumerState<SendFromCard> {
"${Format.localizedStringAsFixed(
value: snapshot.data!,
locale: locale,
decimalPlaces: coin == Coin.monero ? 12 : 8,
decimalPlaces: coin == Coin.monero
? Constants.satsPerCoinMonero
: coin == Coin.wownero
? Constants.satsPerCoinWownero
: Constants.satsPerCoin,
)} ${coin.ticker}",
style: STextStyles.itemSubtitle(context),
);

View file

@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
enum StepIndicatorStatus { current, completed, incomplete }
@ -39,9 +39,7 @@ class StepIndicator extends StatelessWidget {
case StepIndicatorStatus.current:
return Text(
step.toString(),
style: GoogleFonts.roboto(
fontWeight: FontWeight.w600,
fontSize: 8,
style: STextStyles.stepIndicator(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.stepIndicatorIconNumber,
@ -57,9 +55,7 @@ class StepIndicator extends StatelessWidget {
case StepIndicatorStatus.incomplete:
return Text(
step.toString(),
style: GoogleFonts.roboto(
fontWeight: FontWeight.w600,
fontSize: 8,
style: STextStyles.stepIndicator(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.stepIndicatorIconInactive,

View file

@ -4,7 +4,10 @@ import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/utilities/util.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/managed_favorite.dart';
class ManageFavoritesView extends StatelessWidget {
@ -15,142 +18,306 @@ class ManageFavoritesView extends StatelessWidget {
@override
Widget build(BuildContext context) {
debugPrint("BUILD: $runtimeType");
return Scaffold(
appBar: AppBar(
title: Text(
"Favorite wallets",
style: STextStyles.navBarTitle(context),
),
leading: AppBarBackButton(
onPressed: () {
Navigator.of(context).pop();
},
),
),
body: Container(
color: Theme.of(context).extension<StackColors>()!.background,
child: Padding(
padding: const EdgeInsets.only(
left: 12,
right: 12,
top: 4,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 4),
child: Container(
decoration: BoxDecoration(
color: Theme.of(context).extension<StackColors>()!.popupBG,
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,
),
),
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Text(
"Drag to change wallet order.",
style: STextStyles.label(context),
),
),
final isDesktop = Util.isDesktop;
return MasterScaffold(
isDesktop: isDesktop,
appBar: isDesktop
? DesktopAppBar(
background: Theme.of(context).extension<StackColors>()!.popupBG,
isCompactHeight: true,
leading: const AppBarBackButton(
isCompact: true,
),
center: Expanded(
child: Text(
"Favorite wallets",
style: STextStyles.desktopH3(context),
),
),
const SizedBox(
height: 8,
)
: AppBar(
title: Text(
"Favorite wallets",
style: STextStyles.navBarTitle(context),
),
Expanded(
child: Consumer(
builder: (_, ref, __) {
final favorites = ref.watch(favoritesProvider);
return ReorderableListView.builder(
key: key,
itemCount: favorites.length,
itemBuilder: (builderContext, index) {
final walletId = ref.read(favorites[index]).walletId;
return Padding(
key: Key(
"manageFavoriteWalletsItem_$walletId",
),
padding: const EdgeInsets.all(4.0),
child: ManagedFavorite(
walletId: walletId,
),
);
},
onReorder: (oldIndex, newIndex) {
ref
.read(walletsServiceChangeNotifierProvider)
.moveFavorite(
fromIndex: oldIndex, toIndex: newIndex);
leading: AppBarBackButton(
onPressed: () {
Navigator.of(context).pop();
},
),
),
body: isDesktop
? Consumer(
builder: (_, ref, __) {
final favorites = ref.watch(favoritesProvider);
final nonFavorites = ref.watch(nonFavoritesProvider);
ref
.read(favoritesProvider)
.reorder(oldIndex, newIndex, true);
},
proxyDecorator: (child, index, animation) {
return Material(
elevation: 15,
color: Colors.transparent,
// shadowColor: Colors.red,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(
Constants.size.circularBorderRadius * 1.5,
return Column(
children: [
const SizedBox(
height: 24,
),
Expanded(
child: ListView(
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 24),
child: Container(
decoration: BoxDecoration(
color: Theme.of(context)
.extension<StackColors>()!
.popupBG,
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,
),
),
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Text(
"Drag to change wallet order.",
style:
STextStyles.desktopTextExtraSmall(context)
.copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textSubtitle1,
),
),
),
),
),
child: child,
);
},
);
},
),
),
Padding(
padding: const EdgeInsets.only(
top: 30,
bottom: 12,
left: 4,
right: 4,
),
child: Text(
"Add to favorites",
style: STextStyles.itemSubtitle12(context).copyWith(
color:
Theme.of(context).extension<StackColors>()!.textDark3,
),
),
),
Expanded(
child: Consumer(
builder: (_, ref, __) {
final nonFavorites = ref.watch(nonFavoritesProvider);
const SizedBox(
height: 5,
),
ReorderableListView.builder(
buildDefaultDragHandles: false,
shrinkWrap: true,
primary: false,
key: key,
itemCount: favorites.length,
itemBuilder: (builderContext, index) {
final walletId =
ref.read(favorites[index]).walletId;
return Padding(
key: Key(
"manageFavoriteWalletsItem_$walletId",
),
padding: const EdgeInsets.symmetric(
vertical: 5,
horizontal: 24,
),
child: ReorderableDelayedDragStartListener(
index: index,
child: ManagedFavorite(
walletId: walletId,
),
),
);
},
onReorder: (oldIndex, newIndex) {
ref
.read(walletsServiceChangeNotifierProvider)
.moveFavorite(
fromIndex: oldIndex, toIndex: newIndex);
return ListView.builder(
itemCount: nonFavorites.length,
itemBuilder: (buildContext, index) {
// final walletId = ref.watch(
// nonFavorites[index].select((value) => value.walletId));
final walletId = ref.read(nonFavorites[index]).walletId;
return Padding(
key: Key(
"manageNonFavoriteWalletsItem_$walletId",
ref
.read(favoritesProvider)
.reorder(oldIndex, newIndex, true);
},
proxyDecorator: (child, index, animation) {
return Material(
elevation: 15,
color: Colors.transparent,
// shadowColor: Colors.red,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(
Constants.size.circularBorderRadius * 1.5,
),
),
),
child: child,
);
},
),
padding: const EdgeInsets.all(4.0),
child: ManagedFavorite(
walletId: walletId,
Padding(
padding: const EdgeInsets.only(
top: 32,
bottom: 11,
left: 24,
right: 24,
),
child: Text(
"Add to favorites",
style:
STextStyles.itemSubtitle12(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textDark3,
),
),
),
);
},
);
},
ListView.builder(
shrinkWrap: true,
primary: false,
itemCount: nonFavorites.length,
itemBuilder: (buildContext, index) {
// final walletId = ref.watch(
// nonFavorites[index].select((value) => value.walletId));
final walletId =
ref.read(nonFavorites[index]).walletId;
return Padding(
key: Key(
"manageNonFavoriteWalletsItem_$walletId",
),
padding: const EdgeInsets.symmetric(
horizontal: 24,
vertical: 5,
),
child: ManagedFavorite(
walletId: walletId,
),
);
},
)
],
),
),
],
);
},
)
: Container(
color: Theme.of(context).extension<StackColors>()!.background,
child: Padding(
padding: const EdgeInsets.only(
left: 12,
right: 12,
top: 4,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 4),
child: Container(
decoration: BoxDecoration(
color: Theme.of(context)
.extension<StackColors>()!
.popupBG,
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,
),
),
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Text(
"Drag to change wallet order.",
style: STextStyles.label(context),
),
),
),
),
const SizedBox(
height: 8,
),
Expanded(
child: Consumer(
builder: (_, ref, __) {
final favorites = ref.watch(favoritesProvider);
return ReorderableListView.builder(
key: key,
itemCount: favorites.length,
itemBuilder: (builderContext, index) {
final walletId =
ref.read(favorites[index]).walletId;
return Padding(
key: Key(
"manageFavoriteWalletsItem_$walletId",
),
padding: const EdgeInsets.all(4.0),
child: ManagedFavorite(
walletId: walletId,
),
);
},
onReorder: (oldIndex, newIndex) {
ref
.read(walletsServiceChangeNotifierProvider)
.moveFavorite(
fromIndex: oldIndex, toIndex: newIndex);
ref
.read(favoritesProvider)
.reorder(oldIndex, newIndex, true);
},
proxyDecorator: (child, index, animation) {
return Material(
elevation: 15,
color: Colors.transparent,
// shadowColor: Colors.red,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(
Constants.size.circularBorderRadius * 1.5,
),
),
),
child: child,
);
},
);
},
),
),
Padding(
padding: const EdgeInsets.only(
top: 30,
bottom: 12,
left: 4,
right: 4,
),
child: Text(
"Add to favorites",
style: STextStyles.itemSubtitle12(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textDark3,
),
),
),
Expanded(
child: Consumer(
builder: (_, ref, __) {
final nonFavorites = ref.watch(nonFavoritesProvider);
return ListView.builder(
itemCount: nonFavorites.length,
itemBuilder: (buildContext, index) {
// final walletId = ref.watch(
// nonFavorites[index].select((value) => value.walletId));
final walletId =
ref.read(nonFavorites[index]).walletId;
return Padding(
key: Key(
"manageNonFavoriteWalletsItem_$walletId",
),
padding: const EdgeInsets.all(4.0),
child: ManagedFavorite(
walletId: walletId,
),
);
},
);
},
),
),
],
),
),
],
),
),
),
),
);
}
}

View file

@ -3,7 +3,6 @@ import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:stackwallet/notifications/show_flush_bar.dart';
import 'package:stackwallet/pages/home_view/home_view.dart';
import 'package:stackwallet/providers/global/prefs_provider.dart';
@ -188,7 +187,10 @@ class _CreatePinViewState extends ConsumerState<CreatePinView> {
fieldsCount: Constants.pinLength,
eachFieldHeight: 12,
eachFieldWidth: 12,
textStyle: GoogleFonts.workSans(
textStyle: STextStyles.infoSmall(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textSubtitle3,
fontSize: 1,
),
focusNode: _pinPutFocusNode2,

View file

@ -90,6 +90,7 @@ class _AddEditNodeViewState extends ConsumerState<AddEditNodeView> {
break;
case Coin.monero:
case Coin.wownero:
try {
final uri = Uri.parse(formData.host!);
if (uri.scheme.startsWith("http")) {
@ -113,12 +114,12 @@ class _AddEditNodeViewState extends ConsumerState<AddEditNodeView> {
break;
case Coin.bitcoin:
// case Coin.bitcoincash:
case Coin.bitcoincash:
case Coin.dogecoin:
case Coin.firo:
case Coin.namecoin:
case Coin.bitcoinTestNet:
// case Coin.bitcoincashTestnet:
case Coin.bitcoincashTestnet:
case Coin.firoTestNet:
case Coin.dogecoinTestNet:
final client = ElectrumX(
@ -384,6 +385,7 @@ class _AddEditNodeViewState extends ConsumerState<AddEditNodeView> {
// strip unused path
String address = formData.host!;
if (coin == Coin.monero ||
coin == Coin.wownero ||
coin == Coin.epicCash) {
if (address.startsWith("http")) {
final uri = Uri.parse(address);
@ -530,15 +532,16 @@ class _NodeFormState extends ConsumerState<NodeForm> {
case Coin.dogecoin:
case Coin.firo:
case Coin.namecoin:
// case Coin.bitcoincash:
case Coin.bitcoincash:
case Coin.bitcoinTestNet:
// case Coin.bitcoincashTestnet:
case Coin.bitcoincashTestnet:
case Coin.firoTestNet:
case Coin.dogecoinTestNet:
return false;
case Coin.epicCash:
case Coin.monero:
case Coin.wownero:
return true;
}
}
@ -699,7 +702,9 @@ class _NodeFormState extends ConsumerState<NodeForm> {
focusNode: _hostFocusNode,
style: STextStyles.field(context),
decoration: standardInputDecoration(
(widget.coin != Coin.monero && widget.coin != Coin.epicCash)
(widget.coin != Coin.monero &&
widget.coin != Coin.wownero &&
widget.coin != Coin.epicCash)
? "IP address"
: "Url",
_hostFocusNode,
@ -880,7 +885,9 @@ class _NodeFormState extends ConsumerState<NodeForm> {
const SizedBox(
height: 8,
),
if (widget.coin != Coin.monero && widget.coin != Coin.epicCash)
if (widget.coin != Coin.monero &&
widget.coin != Coin.wownero &&
widget.coin != Coin.epicCash)
Row(
children: [
GestureDetector(
@ -931,11 +938,15 @@ class _NodeFormState extends ConsumerState<NodeForm> {
),
],
),
if (widget.coin != Coin.monero && widget.coin != Coin.epicCash)
if (widget.coin != Coin.monero &&
widget.coin != Coin.wownero &&
widget.coin != Coin.epicCash)
const SizedBox(
height: 8,
),
if (widget.coin != Coin.monero && widget.coin != Coin.epicCash)
if (widget.coin != Coin.monero &&
widget.coin != Coin.wownero &&
widget.coin != Coin.epicCash)
Row(
children: [
GestureDetector(

View file

@ -81,6 +81,7 @@ class _NodeDetailsViewState extends ConsumerState<NodeDetailsView> {
break;
case Coin.monero:
case Coin.wownero:
try {
final uri = Uri.parse(node!.host);
if (uri.scheme.startsWith("http")) {
@ -102,9 +103,9 @@ class _NodeDetailsViewState extends ConsumerState<NodeDetailsView> {
case Coin.bitcoinTestNet:
case Coin.firoTestNet:
case Coin.dogecoinTestNet:
// case Coin.bitcoincash:
case Coin.bitcoincash:
case Coin.namecoin:
// case Coin.bitcoincashTestnet:
case Coin.bitcoincashTestnet:
final client = ElectrumX(
host: node!.host,
port: node.port,

View file

@ -1,6 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:stackwallet/notifications/show_flush_bar.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/security_views/security_view.dart';
import 'package:stackwallet/utilities/assets.dart';
@ -168,7 +167,10 @@ class _ChangePinViewState extends State<ChangePinView> {
fieldsCount: Constants.pinLength,
eachFieldHeight: 12,
eachFieldWidth: 12,
textStyle: GoogleFonts.workSans(
textStyle: STextStyles.infoSmall(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textSubtitle3,
fontSize: 1,
),
focusNode: _pinPutFocusNode2,

View file

@ -12,6 +12,7 @@ import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_net
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/services/coins/epiccash/epiccash_wallet.dart';
import 'package:stackwallet/services/coins/monero/monero_wallet.dart';
import 'package:stackwallet/services/coins/wownero/wownero_wallet.dart';
import 'package:stackwallet/services/event_bus/events/global/blocks_remaining_event.dart';
import 'package:stackwallet/services/event_bus/events/global/node_connection_status_changed_event.dart';
import 'package:stackwallet/services/event_bus/events/global/refresh_percent_changed_event.dart';
@ -205,7 +206,7 @@ class _WalletNetworkSettingsViewState
.getManager(widget.walletId)
.coin;
if (coin == Coin.monero || coin == Coin.epicCash) {
if (coin == Coin.monero || coin == Coin.wownero || coin == Coin.epicCash) {
_blocksRemainingSubscription = eventBus.on<BlocksRemainingEvent>().listen(
(event) async {
if (event.walletId == widget.walletId) {
@ -271,6 +272,15 @@ class _WalletNetworkSettingsViewState
if (_percent < highestPercent) {
_percent = highestPercent.clamp(0.0, 1.0);
}
} else if (coin == Coin.wownero) {
double highestPercent = (ref
.read(walletsChangeNotifierProvider)
.getManager(widget.walletId)
.wallet as WowneroWallet)
.highestPercentCached;
if (_percent < highestPercent) {
_percent = highestPercent.clamp(0.0, 1.0);
}
} else if (coin == Coin.epicCash) {
double highestPercent = (ref
.read(walletsChangeNotifierProvider)
@ -545,6 +555,7 @@ class _WalletNetworkSettingsViewState
),
),
if (coin == Coin.monero ||
coin == Coin.wownero ||
coin == Coin.epicCash)
Text(
" (Blocks to go: ${_blocksRemaining == -1 ? "?" : _blocksRemaining})",

View file

@ -241,7 +241,9 @@ class _TransactionDetailsViewState
"$amountPrefix${Format.localizedStringAsFixed(
value: coin == Coin.monero
? (amount / 10000.toDecimal()).toDecimal()
: amount,
: coin == Coin.wownero
? (amount / 1000.toDecimal()).toDecimal()
: amount,
locale: ref.watch(
localeServiceChangeNotifierProvider
.select((value) => value.locale),
@ -254,7 +256,7 @@ class _TransactionDetailsViewState
height: 2,
),
SelectableText(
"${Format.localizedStringAsFixed(value: (coin == Coin.monero ? (amount / 10000.toDecimal()).toDecimal() : amount) * ref.watch(priceAnd24hChangeNotifierProvider.select((value) => value.getPrice(coin).item1)), locale: ref.watch(
"${Format.localizedStringAsFixed(value: (coin == Coin.monero ? (amount / 10000.toDecimal()).toDecimal() : coin == Coin.wownero ? (amount / 1000.toDecimal()).toDecimal() : amount) * ref.watch(priceAnd24hChangeNotifierProvider.select((value) => value.getPrice(coin).item1)), locale: ref.watch(
localeServiceChangeNotifierProvider
.select((value) => value.locale),
), decimalPlaces: 2)} ${ref.watch(
@ -298,14 +300,14 @@ class _TransactionDetailsViewState
],
),
),
if (!(coin == Coin.monero &&
if (!((coin == Coin.monero || coin == Coin.wownero) &&
_transaction.txType.toLowerCase() == "sent") &&
!((coin == Coin.firo || coin == Coin.firoTestNet) &&
_transaction.subType == "mint"))
const SizedBox(
height: 12,
),
if (!(coin == Coin.monero &&
if (!((coin == Coin.monero || coin == Coin.wownero) &&
_transaction.txType.toLowerCase() == "sent") &&
!((coin == Coin.firo || coin == Coin.firoTestNet) &&
_transaction.subType == "mint"))
@ -464,7 +466,10 @@ class _TransactionDetailsViewState
? Format.localizedStringAsFixed(
value: coin == Coin.monero
? (fee / 10000.toDecimal()).toDecimal()
: fee,
: coin == Coin.wownero
? (fee / 1000.toDecimal())
.toDecimal()
: fee,
locale: ref.watch(
localeServiceChangeNotifierProvider
.select((value) => value.locale)),
@ -473,7 +478,9 @@ class _TransactionDetailsViewState
: Format.localizedStringAsFixed(
value: coin == Coin.monero
? (fee / 10000.toDecimal()).toDecimal()
: fee,
: coin == Coin.wownero
? (fee / 1000.toDecimal()).toDecimal()
: fee,
locale: ref.watch(
localeServiceChangeNotifierProvider
.select((value) => value.locale)),

View file

@ -4,7 +4,6 @@ import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_rounded_date_picker/flutter_rounded_date_picker.dart';
import 'package:flutter_svg/svg.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:stackwallet/models/transaction_filter.dart';
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/providers/ui/color_theme_provider.dart';
@ -122,77 +121,43 @@ class _TransactionSearchViewState
colorArrowNext: Theme.of(context).extension<StackColors>()!.textSubtitle1,
colorArrowPrevious:
Theme.of(context).extension<StackColors>()!.textSubtitle1,
textStyleButtonNegative: GoogleFonts.inter(
letterSpacing: 0.5,
textStyleButtonNegative: STextStyles.datePicker600(context).copyWith(
color: baseColor,
fontSize: 16,
fontWeight: FontWeight.w600,
),
textStyleButtonPositive: GoogleFonts.inter(
letterSpacing: 0.5,
textStyleButtonPositive: STextStyles.datePicker600(context).copyWith(
color: baseColor,
fontSize: 16,
fontWeight: FontWeight.w600,
),
textStyleCurrentDayOnCalendar: GoogleFonts.inter(
letterSpacing: 0.5,
color: Theme.of(context).extension<StackColors>()!.accentColorDark,
fontWeight: FontWeight.w400,
fontSize: 12,
),
textStyleDayHeader: GoogleFonts.inter(
letterSpacing: 0.5,
color: Theme.of(context).extension<StackColors>()!.accentColorDark,
fontSize: 16,
fontWeight: FontWeight.w600,
),
textStyleDayOnCalendar: GoogleFonts.inter(
letterSpacing: 0.5,
textStyleCurrentDayOnCalendar: STextStyles.datePicker400(context),
textStyleDayHeader: STextStyles.datePicker600(context),
textStyleDayOnCalendar: STextStyles.datePicker400(context).copyWith(
color: baseColor,
fontSize: 12,
fontWeight: FontWeight.w400,
),
textStyleDayOnCalendarDisabled: GoogleFonts.inter(
letterSpacing: 0.5,
textStyleDayOnCalendarDisabled:
STextStyles.datePicker400(context).copyWith(
color: Theme.of(context).extension<StackColors>()!.textSubtitle3,
fontWeight: FontWeight.w400,
fontSize: 12,
),
textStyleDayOnCalendarSelected: GoogleFonts.inter(
letterSpacing: 0.5,
textStyleDayOnCalendarSelected:
STextStyles.datePicker400(context).copyWith(
color: Theme.of(context).extension<StackColors>()!.textWhite,
fontWeight: FontWeight.w400,
fontSize: 12,
),
textStyleMonthYearHeader: GoogleFonts.inter(
letterSpacing: 0.5,
textStyleMonthYearHeader: STextStyles.datePicker600(context).copyWith(
color: Theme.of(context).extension<StackColors>()!.textSubtitle1,
fontSize: 16,
fontWeight: FontWeight.w600,
),
textStyleYearButton: GoogleFonts.inter(
letterSpacing: 0.5,
textStyleYearButton: STextStyles.datePicker600(context).copyWith(
color: Theme.of(context).extension<StackColors>()!.textWhite,
fontSize: 16,
fontWeight: FontWeight.w600,
),
textStyleButtonAction: GoogleFonts.inter(),
// textStyleButtonAction: GoogleFonts.inter(),
);
}
MaterialRoundedYearPickerStyle _buildYearPickerStyle() {
return MaterialRoundedYearPickerStyle(
backgroundPicker: Theme.of(context).extension<StackColors>()!.popupBG,
textStyleYear: GoogleFonts.inter(
letterSpacing: 0.5,
textStyleYear: STextStyles.datePicker600(context).copyWith(
color: Theme.of(context).extension<StackColors>()!.textSubtitle2,
fontWeight: FontWeight.w600,
fontSize: 16,
),
textStyleYearSelected: GoogleFonts.inter(
letterSpacing: 0.5,
color: Theme.of(context).extension<StackColors>()!.accentColorDark,
fontWeight: FontWeight.w600,
textStyleYearSelected: STextStyles.datePicker600(context).copyWith(
fontSize: 18,
),
);
@ -790,6 +755,11 @@ class _TransactionSearchViewState
.floor()
.toBigInt()
.toInt();
} else if (widget.coin == Coin.wownero) {
amount = (amountDecimal * Decimal.fromInt(Constants.satsPerCoinWownero))
.floor()
.toBigInt()
.toInt();
} else {
amount = (amountDecimal * Decimal.fromInt(Constants.satsPerCoin))
.floor()

View file

@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/pages_desktop_specific/home/desktop_menu.dart';
import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/my_stack_view.dart';
import 'package:stackwallet/route_generator.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
class DesktopHomeView extends ConsumerStatefulWidget {
@ -16,12 +17,9 @@ class DesktopHomeView extends ConsumerStatefulWidget {
class _DesktopHomeViewState extends ConsumerState<DesktopHomeView> {
int currentViewIndex = 0;
final List<Widget> contentViews = [
// const Navigator(
// onGenerateRoute: RouteGenerator.generateRoute,
// initialRoute: MyStackView.routeName,
// ),
const MyStackView(
key: Key("myStackViewKey"),
const Navigator(
onGenerateRoute: RouteGenerator.generateRoute,
initialRoute: MyStackView.routeName,
),
Container(
color: Colors.green,

View file

@ -0,0 +1,137 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
import 'package:stackwallet/pages/manage_favorites_view/manage_favorites_view.dart';
import 'package:stackwallet/pages/wallets_view/sub_widgets/favorite_card.dart';
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart';
class DesktopFavoriteWallets extends ConsumerWidget {
const DesktopFavoriteWallets({Key? key}) : super(key: key);
static const cardWidth = 220.0;
static const cardHeight = 125.0;
static const standardPadding = 16.0;
@override
Widget build(BuildContext context, WidgetRef ref) {
debugPrint("BUILD: $runtimeType");
final favorites = ref.watch(favoritesProvider);
bool hasFavorites = favorites.length > 0;
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"Favorite wallets",
style: STextStyles.desktopTextExtraSmall(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textFieldActiveSearchIconRight,
),
),
BlueTextButton(
text: "Edit",
onTap: () {
Navigator.of(context).pushNamed(ManageFavoritesView.routeName);
},
),
],
),
const SizedBox(
height: 20,
),
ConstrainedBox(
constraints: const BoxConstraints(
maxHeight: (cardHeight * 2) + standardPadding,
minHeight: cardHeight,
),
child: hasFavorites
? SingleChildScrollView(
primary: false,
child: Wrap(
spacing: 16,
runSpacing: 16,
children: [
...favorites.map((p0) {
final walletId = ref.read(p0).walletId;
final managerProvider = ref
.read(walletsChangeNotifierProvider)
.getManagerProvider(walletId);
return FavoriteCard(
walletId: walletId,
width: cardWidth,
height: cardHeight,
managerProvider: managerProvider,
);
})
],
),
)
: Container(
height: cardHeight,
width: cardWidth,
decoration: BoxDecoration(
color: Theme.of(context)
.extension<StackColors>()!
.textFieldDefaultBG,
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,
),
),
child: MaterialButton(
splashColor:
Theme.of(context).extension<StackColors>()!.highlight,
key: const Key("favoriteWalletsAddFavoriteButtonKey"),
padding: const EdgeInsets.all(12),
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius),
),
onPressed: () {
Navigator.of(context)
.pushNamed(ManageFavoritesView.routeName);
},
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SvgPicture.asset(
Assets.svg.plus,
width: 14,
height: 14,
color: Theme.of(context)
.extension<StackColors>()!
.textSubtitle1,
),
const SizedBox(
width: 4,
),
Text(
"Add a favorite",
style: STextStyles.itemSubtitle(context).copyWith(
fontSize: 18,
),
),
],
),
),
),
),
const SizedBox(
height: 40,
),
],
);
}
}

View file

@ -3,7 +3,6 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:stackwallet/pages/wallets_view/sub_widgets/empty_wallets.dart';
import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/my_wallets.dart';
import 'package:stackwallet/providers/global/prefs_provider.dart';
import 'package:stackwallet/providers/global/wallets_provider.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/text_styles.dart';
@ -24,9 +23,6 @@ class _MyStackViewState extends ConsumerState<MyStackView> {
debugPrint("BUILD: $runtimeType");
final hasWallets = ref.watch(walletsChangeNotifierProvider).hasWallets;
final showFavorites = ref.watch(prefsChangeNotifierProvider
.select((value) => value.showFavoriteWallets));
return Column(
children: [
DesktopAppBar(

View file

@ -1,46 +1,32 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/pages/add_wallet_views/add_wallet_view/add_wallet_view.dart';
import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/desktop_favorite_wallets.dart';
import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/wallet_summary_table.dart';
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart';
class MyWallets extends StatefulWidget {
class MyWallets extends ConsumerStatefulWidget {
const MyWallets({Key? key}) : super(key: key);
@override
State<MyWallets> createState() => _MyWalletsState();
ConsumerState<MyWallets> createState() => _MyWalletsState();
}
class _MyWalletsState extends State<MyWallets> {
class _MyWalletsState extends ConsumerState<MyWallets> {
@override
Widget build(BuildContext context) {
final showFavorites = ref.watch(prefsChangeNotifierProvider
.select((value) => value.showFavoriteWallets));
return Padding(
padding: const EdgeInsets.all(24),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Favorite wallets",
style: STextStyles.desktopTextExtraSmall(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.textFieldActiveSearchIconRight,
),
),
const SizedBox(
height: 20,
),
// TODO favorites grid
Container(
color: Colors.deepPurpleAccent,
height: 210,
),
const SizedBox(
height: 40,
),
if (showFavorites) const DesktopFavoriteWallets(),
Row(
children: [
Text(
@ -55,12 +41,14 @@ class _MyWalletsState extends State<MyWallets> {
BlueTextButton(
text: "Add new wallet",
onTap: () {
Navigator.of(context).pushNamed(AddWalletView.routeName);
Navigator.of(
context,
rootNavigator: true,
).pushNamed(AddWalletView.routeName);
},
),
],
),
const SizedBox(
height: 20,
),

File diff suppressed because it is too large Load diff

View file

@ -4,10 +4,12 @@ import 'package:stackwallet/electrumx_rpc/electrumx.dart';
import 'package:stackwallet/models/models.dart';
import 'package:stackwallet/models/node_model.dart';
import 'package:stackwallet/services/coins/bitcoin/bitcoin_wallet.dart';
import 'package:stackwallet/services/coins/bitcoincash/bitcoincash_wallet.dart';
import 'package:stackwallet/services/coins/dogecoin/dogecoin_wallet.dart';
import 'package:stackwallet/services/coins/epiccash/epiccash_wallet.dart';
import 'package:stackwallet/services/coins/firo/firo_wallet.dart';
import 'package:stackwallet/services/coins/monero/monero_wallet.dart';
import 'package:stackwallet/services/coins/wownero/wownero_wallet.dart';
import 'package:stackwallet/services/coins/namecoin/namecoin_wallet.dart';
import 'package:stackwallet/services/transaction_notification_tracker.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
@ -98,25 +100,25 @@ abstract class CoinServiceAPI {
tracker: tracker,
);
// case Coin.bitcoincash:
// return BitcoinCashWallet(
// walletId: walletId,
// walletName: walletName,
// coin: coin,
// client: client,
// cachedClient: cachedClient,
// tracker: tracker,
// );
//
// case Coin.bitcoincashTestnet:
// return BitcoinCashWallet(
// walletId: walletId,
// walletName: walletName,
// coin: coin,
// client: client,
// cachedClient: cachedClient,
// tracker: tracker,
// );
case Coin.bitcoincash:
return BitcoinCashWallet(
walletId: walletId,
walletName: walletName,
coin: coin,
client: client,
cachedClient: cachedClient,
tracker: tracker,
);
case Coin.bitcoincashTestnet:
return BitcoinCashWallet(
walletId: walletId,
walletName: walletName,
coin: coin,
client: client,
cachedClient: cachedClient,
tracker: tracker,
);
case Coin.dogecoin:
return DogecoinWallet(
@ -144,6 +146,14 @@ abstract class CoinServiceAPI {
// tracker: tracker,
);
case Coin.wownero:
return WowneroWallet(
walletId: walletId,
walletName: walletName,
coin: coin,
// tracker: tracker,
);
case Coin.namecoin:
return NamecoinWallet(
walletId: walletId,

View file

@ -2443,7 +2443,11 @@ class NamecoinWallet extends CoinServiceAPI {
for (final out in tx["vout"] as List) {
if (prevOut == out["n"]) {
final address = out["scriptPubKey"]["addresses"][0] as String?;
String? address = out["scriptPubKey"]["address"] as String?;
if (address == null && out["scriptPubKey"]["addresses"] != null) {
address = out["scriptPubKey"]["addresses"][0] as String?;
}
if (address != null) {
sendersArray.add(address);
}
@ -2454,7 +2458,10 @@ class NamecoinWallet extends CoinServiceAPI {
Logging.instance.log("sendersArray: $sendersArray", level: LogLevel.Info);
for (final output in txObject["vout"] as List) {
final address = output["scriptPubKey"]["addresses"][0] as String?;
String? address = output["scriptPubKey"]["address"] as String?;
if (address == null && output["scriptPubKey"]["addresses"] != null) {
address = output["scriptPubKey"]["addresses"][0] as String?;
}
if (address != null) {
recipientsArray.add(address);
}
@ -2519,7 +2526,10 @@ class NamecoinWallet extends CoinServiceAPI {
// add up received tx value
for (final output in txObject["vout"] as List) {
final address = output["scriptPubKey"]["addresses"][0];
String? address = output["scriptPubKey"]["address"] as String?;
if (address == null && output["scriptPubKey"]["addresses"] != null) {
address = output["scriptPubKey"]["addresses"][0] as String?;
}
if (address != null) {
final value = (Decimal.parse(output["value"].toString()) *
Decimal.fromInt(Constants.satsPerCoin))

File diff suppressed because it is too large Load diff

View file

@ -79,8 +79,7 @@ class PriceAPI {
Map<Coin, Tuple2<Decimal, double>> result = {};
try {
final uri = Uri.parse(
"https://api.coingecko.com/api/v3/coins/markets?vs_currency=${baseCurrency.toLowerCase()}&ids=monero,bitcoin,epic-cash,zcoin,dogecoin,namecoin&order=market_cap_desc&per_page=10&page=1&sparkline=false");
// "https://api.coingecko.com/api/v3/coins/markets?vs_currency=${baseCurrency.toLowerCase()}&ids=monero,bitcoin,epic-cash,zcoin,dogecoin,bitcoin-cash,namecoin&order=market_cap_desc&per_page=10&page=1&sparkline=false");
"https://api.coingecko.com/api/v3/coins/markets?vs_currency=${baseCurrency.toLowerCase()}&ids=monero,bitcoin,epic-cash,zcoin,dogecoin,bitcoin-cash,namecoin,wownero&order=market_cap_desc&per_page=10&page=1&sparkline=false");
// final uri = Uri.parse(
// "https://api.coingecko.com/api/v3/coins/markets?vs_currency=${baseCurrency.toLowerCase()}&ids=monero%2Cbitcoin%2Cepic-cash%2Czcoin%2Cdogecoin&order=market_cap_desc&per_page=10&page=1&sparkline=false");

View file

@ -223,7 +223,7 @@ class Wallets extends ChangeNotifier {
final shouldSetAutoSync = shouldAutoSyncAll ||
walletIdsToEnableAutoSync.contains(manager.walletId);
if (manager.coin == Coin.monero) {
if (manager.coin == Coin.monero || manager.coin == Coin.wownero) {
walletsToInitLinearly.add(Tuple2(manager, shouldSetAutoSync));
} else {
walletInitFutures.add(manager.initializeExisting().then((value) {
@ -312,7 +312,7 @@ class Wallets extends ChangeNotifier {
final shouldSetAutoSync = shouldAutoSyncAll ||
walletIdsToEnableAutoSync.contains(manager.walletId);
if (manager.coin == Coin.monero) {
if (manager.coin == Coin.monero || manager.coin == Coin.wownero) {
walletsToInitLinearly.add(Tuple2(manager, shouldSetAutoSync));
} else {
walletInitFutures.add(manager.initializeExisting().then((value) {

View file

@ -2,6 +2,7 @@ import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_libmonero/monero/monero.dart';
import 'package:flutter_libmonero/wownero/wownero.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:stackwallet/hive/db.dart';
import 'package:stackwallet/services/coins/epiccash/epiccash_wallet.dart';
@ -367,8 +368,13 @@ class WalletsService extends ChangeNotifier {
await DB.instance.delete<dynamic>(
boxName: DB.boxNameAllWalletsData,
key: "${walletId}_mnemonicHasBeenVerified");
if (coinFromPrettyName(shell['coin'] as String) == Coin.monero) {
if (coinFromPrettyName(shell['coin'] as String) == Coin.wownero) {
final wowService =
wownero.createWowneroWalletService(DB.instance.moneroWalletInfoBox);
await wowService.remove(walletId);
Logging.instance
.log("monero wallet: $walletId deleted", level: LogLevel.Info);
} else if (coinFromPrettyName(shell['coin'] as String) == Coin.monero) {
final xmrService =
monero.createMoneroWalletService(DB.instance.moneroWalletInfoBox);
await xmrService.remove(walletId);

View file

@ -3,7 +3,7 @@ import 'dart:convert';
import 'package:bitcoindart/bitcoindart.dart';
import 'package:crypto/crypto.dart';
import 'package:flutter_libepiccash/epic_cash.dart';
// import 'package:stackwallet/services/coins/bitcoincash/bitcoincash_wallet.dart';
import 'package:stackwallet/services/coins/bitcoincash/bitcoincash_wallet.dart';
import 'package:stackwallet/services/coins/dogecoin/dogecoin_wallet.dart';
import 'package:stackwallet/services/coins/firo/firo_wallet.dart';
import 'package:stackwallet/services/coins/namecoin/namecoin_wallet.dart';
@ -42,8 +42,8 @@ class AddressUtils {
switch (coin) {
case Coin.bitcoin:
return Address.validateAddress(address, bitcoin);
// case Coin.bitcoincash:
// return Address.validateAddress(address, bitcoincash);
case Coin.bitcoincash:
return Address.validateAddress(address, bitcoincash);
case Coin.dogecoin:
return Address.validateAddress(address, dogecoin);
case Coin.epicCash:
@ -53,12 +53,15 @@ class AddressUtils {
case Coin.monero:
return RegExp("[a-zA-Z0-9]{95}").hasMatch(address) ||
RegExp("[a-zA-Z0-9]{106}").hasMatch(address);
case Coin.wownero:
return RegExp("[a-zA-Z0-9]{95}").hasMatch(address) ||
RegExp("[a-zA-Z0-9]{106}").hasMatch(address);
case Coin.namecoin:
return Address.validateAddress(address, namecoin, namecoin.bech32!);
case Coin.bitcoinTestNet:
return Address.validateAddress(address, testnet);
// case Coin.bitcoincashTestnet:
// return Address.validateAddress(address, bitcoincashtestnet);
case Coin.bitcoincashTestnet:
return Address.validateAddress(address, bitcoincashtestnet);
case Coin.firoTestNet:
return Address.validateAddress(address, firoTestNetwork);
case Coin.dogecoinTestNet:

View file

@ -51,6 +51,7 @@ class _SVG {
String txExchangeFailed(BuildContext context) =>
"assets/svg/${Theme.of(context).extension<StackColors>()!.themeType.name}/tx-exchange-icon-failed.svg";
String get drd => "assets/svg/drd-icon.svg";
String get plus => "assets/svg/plus.svg";
String get gear => "assets/svg/gear.svg";
String get bell => "assets/svg/bell.svg";
@ -127,6 +128,7 @@ class _SVG {
String get epicCash => "assets/svg/coin_icons/EpicCash.svg";
String get firo => "assets/svg/coin_icons/Firo.svg";
String get monero => "assets/svg/coin_icons/Monero.svg";
String get wownero => "assets/svg/coin_icons/Wownero.svg";
String get namecoin => "assets/svg/coin_icons/Namecoin.svg";
String get chevronRight => "assets/svg/chevron-right.svg";
@ -145,8 +147,8 @@ class _SVG {
switch (coin) {
case Coin.bitcoin:
return bitcoin;
// case Coin.bitcoincash:
// return bitcoincash;
case Coin.bitcoincash:
return bitcoincash;
case Coin.dogecoin:
return dogecoin;
case Coin.epicCash:
@ -155,12 +157,14 @@ class _SVG {
return firo;
case Coin.monero:
return monero;
case Coin.wownero:
return wownero;
case Coin.namecoin:
return namecoin;
case Coin.bitcoinTestNet:
return bitcoinTestnet;
// case Coin.bitcoincashTestnet:
// return bitcoincashTestnet;
case Coin.bitcoincashTestnet:
return bitcoincashTestnet;
case Coin.firoTestNet:
return firoTestnet;
case Coin.dogecoinTestNet:
@ -176,6 +180,7 @@ class _PNG {
String get splash => "assets/images/splash.png";
String get monero => "assets/images/monero.png";
String get wownero => "assets/images/wownero.png";
String get firo => "assets/images/firo.png";
String get dogecoin => "assets/images/doge.png";
String get bitcoin => "assets/images/bitcoin.png";
@ -188,9 +193,9 @@ class _PNG {
case Coin.bitcoin:
case Coin.bitcoinTestNet:
return bitcoin;
// case Coin.bitcoincash:
// case Coin.bitcoincashTestnet:
// return bitcoincash;
case Coin.bitcoincash:
case Coin.bitcoincashTestnet:
return bitcoincash;
case Coin.dogecoin:
case Coin.dogecoinTestNet:
return dogecoin;
@ -202,6 +207,8 @@ class _PNG {
return firo;
case Coin.monero:
return monero;
case Coin.wownero:
return wownero;
case Coin.namecoin:
return namecoin;
}

View file

@ -18,15 +18,17 @@ Uri getBlockExplorerTransactionUrlFor({
throw UnimplementedError("missing block explorer for epic cash");
case Coin.monero:
return Uri.parse("https://xmrchain.net/tx/$txid");
case Coin.wownero:
return Uri.parse("https://explore.wownero.com/search?value=$txid");
case Coin.firo:
return Uri.parse("https://explorer.firo.org/tx/$txid");
case Coin.firoTestNet:
return Uri.parse("https://testexplorer.firo.org/tx/$txid");
// case Coin.bitcoincash:
// return Uri.parse("https://blockchair.com/bitcoin-cash/transaction/$txid");
// case Coin.bitcoincashTestnet:
// return Uri.parse(
// "https://blockexplorer.one/bitcoin-cash/testnet/tx/$txid");
case Coin.bitcoincash:
return Uri.parse("https://blockchair.com/bitcoin-cash/transaction/$txid");
case Coin.bitcoincashTestnet:
return Uri.parse(
"https://blockexplorer.one/bitcoin-cash/testnet/tx/$txid");
case Coin.namecoin:
return Uri.parse("https://chainz.cryptoid.info/nmc/tx.dws?$txid.htm");
}

View file

@ -18,6 +18,7 @@ abstract class Constants {
//TODO: correct for monero?
static const int satsPerCoinMonero = 1000000000000;
static const int satsPerCoinWownero = 100000000000;
static const int satsPerCoin = 100000000;
static const int decimalPlaces = 8;
@ -39,8 +40,8 @@ abstract class Constants {
final List<int> values = [];
switch (coin) {
case Coin.bitcoin:
// case Coin.bitcoincash:
// case Coin.bitcoincashTestnet:
case Coin.bitcoincash:
case Coin.bitcoincashTestnet:
case Coin.dogecoin:
case Coin.firo:
case Coin.bitcoinTestNet:
@ -54,6 +55,9 @@ abstract class Constants {
case Coin.monero:
values.addAll([25]);
break;
case Coin.wownero:
values.addAll([14]);
break;
}
return values;
}
@ -65,9 +69,9 @@ abstract class Constants {
case Coin.bitcoinTestNet:
return 600;
// case Coin.bitcoincash:
// case Coin.bitcoincashTestnet:
// return 600;
case Coin.bitcoincash:
case Coin.bitcoincashTestnet:
return 600;
case Coin.dogecoin:
case Coin.dogecoinTestNet:
@ -83,6 +87,9 @@ abstract class Constants {
case Coin.monero:
return 120;
case Coin.wownero:
return 120;
case Coin.namecoin:
return 600;
}

View file

@ -13,10 +13,11 @@ abstract class DefaultNodes {
firo,
monero,
epicCash,
// bitcoincash,
bitcoincash,
namecoin,
wownero,
bitcoinTestnet,
// bitcoincashTestnet,
bitcoincashTestnet,
dogecoinTestnet,
firoTestnet,
];
@ -33,17 +34,17 @@ abstract class DefaultNodes {
isDown: false,
);
// static NodeModel get bitcoincash => NodeModel(
// host: "bitcoincash.stackwallet.com",
// port: 50002,
// name: defaultName,
// id: _nodeId(Coin.bitcoincash),
// useSSL: true,
// enabled: true,
// coinName: Coin.bitcoincash.name,
// isFailover: true,
// isDown: false,
// );
static NodeModel get bitcoincash => NodeModel(
host: "bitcoincash.stackwallet.com",
port: 50002,
name: defaultName,
id: _nodeId(Coin.bitcoincash),
useSSL: true,
enabled: true,
coinName: Coin.bitcoincash.name,
isFailover: true,
isDown: false,
);
static NodeModel get dogecoin => NodeModel(
host: "dogecoin.stackwallet.com",
@ -83,6 +84,20 @@ abstract class DefaultNodes {
isDown: false,
);
// TODO: eventually enable ssl and set scheme to https
// currently get certificate failure
static NodeModel get wownero => NodeModel(
host: "http://eu-west-2.wow.xmr.pm",
port: 34568,
name: defaultName,
id: _nodeId(Coin.wownero),
useSSL: false,
enabled: true,
coinName: Coin.wownero.name,
isFailover: true,
isDown: false,
);
static NodeModel get epicCash => NodeModel(
host: "http://epiccash.stackwallet.com",
port: 3413,
@ -143,25 +158,25 @@ abstract class DefaultNodes {
isDown: false,
);
// static NodeModel get bitcoincashTestnet => NodeModel(
// host: "testnet.hsmiths.com",
// port: 53012,
// name: defaultName,
// id: _nodeId(Coin.bitcoincash),
// useSSL: true,
// enabled: true,
// coinName: Coin.bitcoincash.name,
// isFailover: true,
// isDown: false,
// );
static NodeModel get bitcoincashTestnet => NodeModel(
host: "testnet.hsmiths.com",
port: 53012,
name: defaultName,
id: _nodeId(Coin.bitcoincashTestnet),
useSSL: true,
enabled: true,
coinName: Coin.bitcoincashTestnet.name,
isFailover: true,
isDown: false,
);
static NodeModel getNodeFor(Coin coin) {
switch (coin) {
case Coin.bitcoin:
return bitcoin;
//
// case Coin.bitcoincash:
// return bitcoincash;
case Coin.bitcoincash:
return bitcoincash;
case Coin.dogecoin:
return dogecoin;
@ -175,14 +190,17 @@ abstract class DefaultNodes {
case Coin.monero:
return monero;
case Coin.wownero:
return wownero;
case Coin.namecoin:
return namecoin;
case Coin.bitcoinTestNet:
return bitcoinTestnet;
// case Coin.bitcoincashTestnet:
// return bitcoincashTestnet;
case Coin.bitcoincashTestnet:
return bitcoincashTestnet;
case Coin.firoTestNet:
return firoTestnet;

View file

@ -1,4 +1,6 @@
import 'package:stackwallet/services/coins/bitcoin/bitcoin_wallet.dart' as btc;
import 'package:stackwallet/services/coins/bitcoincash/bitcoincash_wallet.dart'
as bch;
import 'package:stackwallet/services/coins/dogecoin/dogecoin_wallet.dart'
as doge;
import 'package:stackwallet/services/coins/epiccash/epiccash_wallet.dart'
@ -7,14 +9,16 @@ import 'package:stackwallet/services/coins/firo/firo_wallet.dart' as firo;
import 'package:stackwallet/services/coins/monero/monero_wallet.dart' as xmr;
import 'package:stackwallet/services/coins/namecoin/namecoin_wallet.dart'
as nmc;
import 'package:stackwallet/services/coins/wownero/wownero_wallet.dart' as wow;
enum Coin {
bitcoin,
// bitcoincash,
bitcoincash,
dogecoin,
epicCash,
firo,
monero,
wownero,
namecoin,
///
@ -22,21 +26,21 @@ enum Coin {
///
bitcoinTestNet,
// bitcoincashTestnet,
bitcoincashTestnet,
dogecoinTestNet,
firoTestNet,
}
// remove firotestnet for now
const int kTestNetCoinCount = 2;
const int kTestNetCoinCount = 3;
extension CoinExt on Coin {
String get prettyName {
switch (this) {
case Coin.bitcoin:
return "Bitcoin";
// case Coin.bitcoincash:
// return "Bitcoin Cash";
case Coin.bitcoincash:
return "Bitcoin Cash";
case Coin.dogecoin:
return "Dogecoin";
case Coin.epicCash:
@ -45,12 +49,14 @@ extension CoinExt on Coin {
return "Firo";
case Coin.monero:
return "Monero";
case Coin.wownero:
return "Wownero";
case Coin.namecoin:
return "Namecoin";
case Coin.bitcoinTestNet:
return "tBitcoin";
// case Coin.bitcoincashTestnet:
// return "tBitcoin Cash";
case Coin.bitcoincashTestnet:
return "tBitcoin Cash";
case Coin.firoTestNet:
return "tFiro";
case Coin.dogecoinTestNet:
@ -62,8 +68,8 @@ extension CoinExt on Coin {
switch (this) {
case Coin.bitcoin:
return "BTC";
// case Coin.bitcoincash:
// return "BCH";
case Coin.bitcoincash:
return "BCH";
case Coin.dogecoin:
return "DOGE";
case Coin.epicCash:
@ -72,12 +78,14 @@ extension CoinExt on Coin {
return "FIRO";
case Coin.monero:
return "XMR";
case Coin.wownero:
return "WOW";
case Coin.namecoin:
return "NMC";
case Coin.bitcoinTestNet:
return "tBTC";
// case Coin.bitcoincashTestnet:
// return "tBCH";
case Coin.bitcoincashTestnet:
return "tBCH";
case Coin.firoTestNet:
return "tFIRO";
case Coin.dogecoinTestNet:
@ -89,8 +97,8 @@ extension CoinExt on Coin {
switch (this) {
case Coin.bitcoin:
return "bitcoin";
// case Coin.bitcoincash:
// return "bitcoincash";
case Coin.bitcoincash:
return "bitcoincash";
case Coin.dogecoin:
return "dogecoin";
case Coin.epicCash:
@ -100,12 +108,14 @@ extension CoinExt on Coin {
return "firo";
case Coin.monero:
return "monero";
case Coin.wownero:
return "wownero";
case Coin.namecoin:
return "namecoin";
case Coin.bitcoinTestNet:
return "bitcoin";
// case Coin.bitcoincashTestnet:
// return "bitcoincash";
case Coin.bitcoincashTestnet:
return "bitcoincash";
case Coin.firoTestNet:
return "firo";
case Coin.dogecoinTestNet:
@ -116,18 +126,19 @@ extension CoinExt on Coin {
bool get isElectrumXCoin {
switch (this) {
case Coin.bitcoin:
// case Coin.bitcoincash:
case Coin.bitcoincash:
case Coin.dogecoin:
case Coin.firo:
case Coin.namecoin:
case Coin.bitcoinTestNet:
// case Coin.bitcoincashTestnet:
case Coin.bitcoincashTestnet:
case Coin.firoTestNet:
case Coin.dogecoinTestNet:
return true;
case Coin.epicCash:
case Coin.monero:
case Coin.wownero:
return false;
}
}
@ -138,9 +149,9 @@ extension CoinExt on Coin {
case Coin.bitcoinTestNet:
return btc.MINIMUM_CONFIRMATIONS;
// case Coin.bitcoincash:
// case Coin.bitcoincashTestnet:
// return bch.MINIMUM_CONFIRMATIONS;
case Coin.bitcoincash:
case Coin.bitcoincashTestnet:
return bch.MINIMUM_CONFIRMATIONS;
case Coin.firo:
case Coin.firoTestNet:
@ -155,6 +166,10 @@ extension CoinExt on Coin {
case Coin.monero:
return xmr.MINIMUM_CONFIRMATIONS;
case Coin.wownero:
return wow.MINIMUM_CONFIRMATIONS;
case Coin.namecoin:
return nmc.MINIMUM_CONFIRMATIONS;
}
@ -166,10 +181,10 @@ Coin coinFromPrettyName(String name) {
case "Bitcoin":
case "bitcoin":
return Coin.bitcoin;
// case "Bitcoincash":
// case "bitcoincash":
// case "Bitcoin Cash":
// return Coin.bitcoincash;
case "Bitcoincash":
case "bitcoincash":
case "Bitcoin Cash":
return Coin.bitcoincash;
case "Dogecoin":
case "dogecoin":
return Coin.dogecoin;
@ -190,10 +205,10 @@ Coin coinFromPrettyName(String name) {
case "bitcoinTestNet":
return Coin.bitcoinTestNet;
// case "Bitcoincash Testnet":
// case "tBitcoin Cash":
// case "Bitcoin Cash Testnet":
// return Coin.bitcoincashTestnet;
case "Bitcoincash Testnet":
case "tBitcoin Cash":
case "Bitcoin Cash Testnet":
return Coin.bitcoincashTestnet;
case "Firo Testnet":
case "tFiro":
case "firoTestNet":
@ -202,6 +217,10 @@ Coin coinFromPrettyName(String name) {
case "tDogecoin":
case "dogecoinTestNet":
return Coin.dogecoinTestNet;
case "Wownero":
case "tWownero":
case "wownero":
return Coin.wownero;
default:
throw ArgumentError.value(
name, "name", "No Coin enum value with that prettyName");
@ -212,8 +231,8 @@ Coin coinFromTickerCaseInsensitive(String ticker) {
switch (ticker.toLowerCase()) {
case "btc":
return Coin.bitcoin;
// case "bch":
// return Coin.bitcoincash;
case "bch":
return Coin.bitcoincash;
case "doge":
return Coin.dogecoin;
case "epic":
@ -226,12 +245,14 @@ Coin coinFromTickerCaseInsensitive(String ticker) {
return Coin.namecoin;
case "tbtc":
return Coin.bitcoinTestNet;
// case "tbch":
// return Coin.bitcoincashTestnet;
case "tbch":
return Coin.bitcoincashTestnet;
case "tfiro":
return Coin.firoTestNet;
case "tdoge":
return Coin.dogecoinTestNet;
case "wow":
return Coin.wownero;
default:
throw ArgumentError.value(
ticker, "name", "No Coin enum value with that ticker");

View file

@ -52,4 +52,8 @@ class ListenableList<T> extends ChangeNotifier {
notifyListeners();
}
}
Iterable<E> map<E>(E Function(T) toElement) {
return _list.map(toElement);
}
}

File diff suppressed because it is too large Load diff

View file

@ -174,6 +174,7 @@ abstract class StackColorTheme {
Color get loadingOverlayTextColor;
Color get myStackContactIconBG;
Color get textConfirmTotalAmount;
Color get textSelectedWordTableItem;
}
class CoinThemeColor {
@ -193,9 +194,9 @@ class CoinThemeColor {
case Coin.bitcoin:
case Coin.bitcoinTestNet:
return bitcoin;
// case Coin.bitcoincash:
// case Coin.bitcoincashTestnet:
// return bitcoincash;
case Coin.bitcoincash:
case Coin.bitcoincashTestnet:
return bitcoincash;
case Coin.dogecoin:
case Coin.dogecoinTestNet:
return dogecoin;
@ -208,8 +209,8 @@ class CoinThemeColor {
return monero;
case Coin.namecoin:
return namecoin;
// case Coin.wownero:
// return wownero;
case Coin.wownero:
return wownero;
}
}
}

View file

@ -301,4 +301,6 @@ class DarkColors extends StackColorTheme {
Color get myStackContactIconBG => const Color(0x88747778);
@override
Color get textConfirmTotalAmount => const Color(0xFF003921);
@override
Color get textSelectedWordTableItem => const Color(0xFF00297A);
}

View file

@ -301,4 +301,6 @@ class LightColors extends StackColorTheme {
Color get myStackContactIconBG => textFieldDefaultBG;
@override
Color get textConfirmTotalAmount => const Color(0xFF232323);
@override
Color get textSelectedWordTableItem => const Color(0xFF232323);
}

View file

@ -169,6 +169,7 @@ class StackColors extends ThemeExtension<StackColors> {
final Color loadingOverlayTextColor;
final Color myStackContactIconBG;
final Color textConfirmTotalAmount;
final Color textSelectedWordTableItem;
StackColors({
required this.themeType,
@ -300,6 +301,7 @@ class StackColors extends ThemeExtension<StackColors> {
required this.loadingOverlayTextColor,
required this.myStackContactIconBG,
required this.textConfirmTotalAmount,
required this.textSelectedWordTableItem,
});
factory StackColors.fromStackColorTheme(StackColorTheme colorTheme) {
@ -435,6 +437,7 @@ class StackColors extends ThemeExtension<StackColors> {
loadingOverlayTextColor: colorTheme.loadingOverlayTextColor,
myStackContactIconBG: colorTheme.myStackContactIconBG,
textConfirmTotalAmount: colorTheme.textConfirmTotalAmount,
textSelectedWordTableItem: colorTheme.textSelectedWordTableItem,
);
}
@ -569,6 +572,7 @@ class StackColors extends ThemeExtension<StackColors> {
Color? loadingOverlayTextColor,
Color? myStackContactIconBG,
Color? textConfirmTotalAmount,
Color? textSelectedWordTableItem,
}) {
return StackColors(
themeType: themeType ?? this.themeType,
@ -736,6 +740,8 @@ class StackColors extends ThemeExtension<StackColors> {
myStackContactIconBG: myStackContactIconBG ?? this.myStackContactIconBG,
textConfirmTotalAmount:
textConfirmTotalAmount ?? this.textConfirmTotalAmount,
textSelectedWordTableItem:
textSelectedWordTableItem ?? this.textSelectedWordTableItem,
);
}
@ -1388,6 +1394,11 @@ class StackColors extends ThemeExtension<StackColors> {
other.textConfirmTotalAmount,
t,
)!,
textSelectedWordTableItem: Color.lerp(
textSelectedWordTableItem,
other.textSelectedWordTableItem,
t,
)!,
);
}
@ -1396,9 +1407,9 @@ class StackColors extends ThemeExtension<StackColors> {
case Coin.bitcoin:
case Coin.bitcoinTestNet:
return _coin.bitcoin;
// case Coin.bitcoincash:
// case Coin.bitcoincashTestnet:
// return _coin.bitcoincash;
case Coin.bitcoincash:
case Coin.bitcoincashTestnet:
return _coin.bitcoincash;
case Coin.dogecoin:
case Coin.dogecoinTestNet:
return _coin.dogecoin;
@ -1411,8 +1422,8 @@ class StackColors extends ThemeExtension<StackColors> {
return _coin.monero;
case Coin.namecoin:
return _coin.namecoin;
// case Coin.wownero:
// return wownero;
case Coin.wownero:
return _coin.wownero;
}
}
@ -1463,6 +1474,13 @@ class StackColors extends ThemeExtension<StackColors> {
),
);
ButtonStyle? getSecondaryDisabledButtonColor(BuildContext context) =>
Theme.of(context).textButtonTheme.style?.copyWith(
backgroundColor: MaterialStateProperty.all<Color>(
buttonBackSecondaryDisabled,
),
);
ButtonStyle? getSmallSecondaryEnabledButtonColor(BuildContext context) =>
Theme.of(context).textButtonTheme.style?.copyWith(
backgroundColor: MaterialStateProperty.all<Color>(

View file

@ -47,9 +47,14 @@ class AppBarIconButton extends StatelessWidget {
}
class AppBarBackButton extends StatelessWidget {
const AppBarBackButton({Key? key, this.onPressed}) : super(key: key);
const AppBarBackButton({
Key? key,
this.onPressed,
this.isCompact = false,
}) : super(key: key);
final VoidCallback? onPressed;
final bool isCompact;
@override
Widget build(BuildContext context) {
@ -62,15 +67,19 @@ class AppBarBackButton extends StatelessWidget {
)
: const EdgeInsets.all(10),
child: AppBarIconButton(
size: isDesktop ? 56 : 32,
size: isDesktop
? isCompact
? 42
: 56
: 32,
color: isDesktop
? Theme.of(context).extension<StackColors>()!.textFieldDefaultBG
: Theme.of(context).extension<StackColors>()!.background,
shadows: const [],
icon: SvgPicture.asset(
Assets.svg.arrowLeft,
width: 24,
height: 24,
width: isCompact ? 18 : 24,
height: isCompact ? 18 : 24,
color: Theme.of(context).extension<StackColors>()!.topNavIconPrimary,
),
onPressed: onPressed ?? Navigator.of(context).pop,

View file

@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
class NumberKey extends StatefulWidget {
@ -72,12 +72,7 @@ class _NumberKeyState extends State<NumberKey> {
child: Center(
child: Text(
number,
style: GoogleFonts.roboto(
color:
Theme.of(context).extension<StackColors>()!.numberTextDefault,
fontWeight: FontWeight.w400,
fontSize: 26,
),
style: STextStyles.numberDefault(context),
),
),
),

View file

@ -0,0 +1,26 @@
import 'package:flutter/material.dart';
import 'package:stackwallet/utilities/util.dart';
class CustomTextButtonBase extends StatelessWidget {
const CustomTextButtonBase({
Key? key,
this.width,
this.height,
this.textButton,
}) : super(key: key);
final double? width;
final double? height;
final TextButton? textButton;
@override
Widget build(BuildContext context) {
final isDesktop = Util.isDesktop;
return SizedBox(
height: isDesktop && height == null ? 70 : height,
width: width,
child: textButton,
);
}
}

View file

@ -0,0 +1,38 @@
import 'package:flutter/material.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
class DesktopDialog extends StatelessWidget {
const DesktopDialog({Key? key, this.child}) : super(key: key);
final Widget? child;
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
ConstrainedBox(
constraints: const BoxConstraints(
maxWidth: 641,
maxHeight: 474,
),
child: Material(
borderRadius: BorderRadius.circular(
20,
),
child: Container(
decoration: BoxDecoration(
color: Theme.of(context).extension<StackColors>()!.popupBG,
borderRadius: BorderRadius.circular(
20,
),
),
child: child,
),
),
),
],
);
}
}

View file

@ -0,0 +1,44 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
class DesktopDialogCloseButton extends StatelessWidget {
const DesktopDialogCloseButton({
Key? key,
this.onPressedOverride,
}) : super(key: key);
final VoidCallback? onPressedOverride;
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(20.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
AppBarIconButton(
color:
Theme.of(context).extension<StackColors>()!.textFieldDefaultBG,
size: 40,
icon: SvgPicture.asset(
Assets.svg.x,
color: Theme.of(context).extension<StackColors>()!.textDark,
width: 22,
height: 22,
),
onPressed: () {
if (onPressedOverride == null) {
Navigator.of(context).pop();
} else {
onPressedOverride!.call();
}
},
),
],
),
);
}
}

View file

@ -0,0 +1,71 @@
import 'package:flutter/material.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/widgets/desktop/custom_text_button.dart';
class PrimaryButton extends StatelessWidget {
const PrimaryButton({
Key? key,
this.width,
this.height,
this.label,
this.icon,
this.onPressed,
this.enabled = true,
}) : super(key: key);
final double? width;
final double? height;
final String? label;
final VoidCallback? onPressed;
final bool enabled;
final Widget? icon;
@override
Widget build(BuildContext context) {
final isDesktop = Util.isDesktop;
return CustomTextButtonBase(
height: height,
width: width,
textButton: TextButton(
onPressed: enabled ? onPressed : null,
style: enabled
? Theme.of(context)
.extension<StackColors>()!
.getPrimaryEnabledButtonColor(context)
: Theme.of(context)
.extension<StackColors>()!
.getPrimaryDisabledButtonColor(context),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (icon != null) icon!,
if (icon != null && label != null)
const SizedBox(
width: 10,
),
if (label != null)
Text(
label!,
style: isDesktop
? enabled
? STextStyles.desktopButtonEnabled(context)
: STextStyles.desktopButtonDisabled(context)
: STextStyles.button(context).copyWith(
color: enabled
? Theme.of(context)
.extension<StackColors>()!
.buttonTextPrimary
: Theme.of(context)
.extension<StackColors>()!
.buttonTextPrimaryDisabled,
),
),
],
),
),
);
}
}

View file

@ -0,0 +1,71 @@
import 'package:flutter/material.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/widgets/desktop/custom_text_button.dart';
class SecondaryButton extends StatelessWidget {
const SecondaryButton({
Key? key,
this.width,
this.height,
this.label,
this.icon,
this.onPressed,
this.enabled = true,
}) : super(key: key);
final double? width;
final double? height;
final String? label;
final VoidCallback? onPressed;
final bool enabled;
final Widget? icon;
@override
Widget build(BuildContext context) {
final isDesktop = Util.isDesktop;
return CustomTextButtonBase(
height: height,
width: width,
textButton: TextButton(
onPressed: enabled ? onPressed : null,
style: enabled
? Theme.of(context)
.extension<StackColors>()!
.getSecondaryEnabledButtonColor(context)
: Theme.of(context)
.extension<StackColors>()!
.getSecondaryDisabledButtonColor(context),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (icon != null) icon!,
if (icon != null && label != null)
const SizedBox(
width: 10,
),
if (label != null)
Text(
label!,
style: isDesktop
? enabled
? STextStyles.desktopButtonSecondaryEnabled(context)
: STextStyles.desktopButtonSecondaryDisabled(context)
: STextStyles.button(context).copyWith(
color: enabled
? Theme.of(context)
.extension<StackColors>()!
.buttonTextSecondary
: Theme.of(context)
.extension<StackColors>()!
.buttonTextSecondaryDisabled,
),
),
],
),
),
);
}
}

View file

@ -8,6 +8,7 @@ import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/format.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/widgets/custom_buttons/favorite_toggle.dart';
import 'package:stackwallet/widgets/rounded_white_container.dart';
@ -30,8 +31,10 @@ class _ManagedFavoriteCardState extends ConsumerState<ManagedFavorite> {
.select((value) => value.getManager(widget.walletId)));
debugPrint("BUILD: $runtimeType with walletId ${widget.walletId}");
final isDesktop = Util.isDesktop;
return RoundedWhiteContainer(
padding: const EdgeInsets.all(4.0),
padding: EdgeInsets.all(isDesktop ? 0 : 4.0),
child: RawMaterialButton(
onPressed: () {
final provider = ref
@ -59,7 +62,12 @@ class _ManagedFavoriteCardState extends ConsumerState<ManagedFavorite> {
),
),
child: Padding(
padding: const EdgeInsets.all(8),
padding: isDesktop
? const EdgeInsets.symmetric(
horizontal: 20,
vertical: 12,
)
: const EdgeInsets.all(8),
child: Row(
children: [
Container(
@ -73,7 +81,7 @@ class _ManagedFavoriteCardState extends ConsumerState<ManagedFavorite> {
),
),
child: Padding(
padding: const EdgeInsets.all(4),
padding: EdgeInsets.all(isDesktop ? 6 : 4),
child: SvgPicture.asset(
Assets.svg.iconFor(coin: manager.coin),
width: 20,
@ -84,37 +92,79 @@ class _ManagedFavoriteCardState extends ConsumerState<ManagedFavorite> {
const SizedBox(
width: 12,
),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
manager.walletName,
style: STextStyles.titleBold12(context),
),
const SizedBox(
height: 2,
),
Text(
"${Format.localizedStringAsFixed(
value: manager.cachedTotalBalance,
locale: ref.watch(localeServiceChangeNotifierProvider
.select((value) => value.locale)),
decimalPlaces: 8,
)} ${manager.coin.ticker}",
style: STextStyles.itemSubtitle(context),
),
],
if (isDesktop)
Expanded(
child: Row(
children: [
Expanded(
child: Text(
manager.walletName,
style: STextStyles.titleBold12(context),
),
),
Expanded(
child: Text(
"${Format.localizedStringAsFixed(
value: manager.cachedTotalBalance,
locale: ref.watch(
localeServiceChangeNotifierProvider
.select((value) => value.locale)),
decimalPlaces: 8,
)} ${manager.coin.ticker}",
style: STextStyles.itemSubtitle(context),
),
),
Text(
manager.isFavorite
? "Remove from favorites"
: "Add to favorites",
style:
STextStyles.desktopTextExtraSmall(context).copyWith(
color: manager.isFavorite
? Theme.of(context)
.extension<StackColors>()!
.accentColorRed
: Theme.of(context)
.extension<StackColors>()!
.buttonTextBorderless,
),
)
],
),
),
),
FavoriteToggle(
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,
if (!isDesktop)
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
manager.walletName,
style: STextStyles.titleBold12(context),
),
const SizedBox(
height: 2,
),
Text(
"${Format.localizedStringAsFixed(
value: manager.cachedTotalBalance,
locale: ref.watch(localeServiceChangeNotifierProvider
.select((value) => value.locale)),
decimalPlaces: 8,
)} ${manager.coin.ticker}",
style: STextStyles.itemSubtitle(context),
),
],
),
),
if (!isDesktop)
FavoriteToggle(
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,
),
initialState: manager.isFavorite,
onChanged: null,
),
initialState: manager.isFavorite,
onChanged: null,
),
],
),
),

View file

@ -85,6 +85,7 @@ class NodeOptionsSheet extends ConsumerWidget {
break;
case Coin.monero:
case Coin.wownero:
try {
final uri = Uri.parse(node.host);
if (uri.scheme.startsWith("http")) {
@ -106,9 +107,9 @@ class NodeOptionsSheet extends ConsumerWidget {
case Coin.bitcoinTestNet:
case Coin.firoTestNet:
case Coin.dogecoinTestNet:
// case Coin.bitcoincash:
case Coin.bitcoincash:
case Coin.namecoin:
// case Coin.bitcoincashTestnet:
case Coin.bitcoincashTestnet:
final client = ElectrumX(
host: node.host,
port: node.port,

View file

@ -6,10 +6,12 @@ class TableView extends StatefulWidget {
Key? key,
required this.rows,
this.rowSpacing = 10.0,
this.shrinkWrap = false,
}) : super(key: key);
final List<TableViewRow> rows;
final double rowSpacing;
final bool shrinkWrap;
@override
State<TableView> createState() => _TableViewState();
@ -19,6 +21,7 @@ class _TableViewState extends State<TableView> {
@override
Widget build(BuildContext context) {
return ListView(
shrinkWrap: widget.shrinkWrap,
children: [
for (int i = 0; i < widget.rows.length; i++)
Column(

View file

@ -11,6 +11,8 @@ class TableViewRow extends StatelessWidget {
this.decoration,
this.onExpandChanged,
this.padding = const EdgeInsets.all(0),
this.spacing = 0.0,
this.crossAxisAlignment = CrossAxisAlignment.center,
}) : super(key: key);
final List<TableViewCell> cells;
@ -18,6 +20,8 @@ class TableViewRow extends StatelessWidget {
final Decoration? decoration;
final void Function(ExpandableState)? onExpandChanged;
final EdgeInsetsGeometry padding;
final double spacing;
final CrossAxisAlignment crossAxisAlignment;
@override
Widget build(BuildContext context) {
@ -27,13 +31,18 @@ class TableViewRow extends StatelessWidget {
? Padding(
padding: padding,
child: Row(
crossAxisAlignment: crossAxisAlignment,
children: [
...cells.map(
(e) => Expanded(
flex: e.flex,
child: e,
for (int i = 0; i < cells.length; i++) ...[
if (i != 0 && i != cells.length)
SizedBox(
width: spacing,
),
Expanded(
flex: cells[i].flex,
child: cells[i],
),
),
],
],
),
)
@ -43,12 +52,16 @@ class TableViewRow extends StatelessWidget {
padding: padding,
child: Row(
children: [
...cells.map(
(e) => Expanded(
flex: e.flex,
child: e,
for (int i = 0; i < cells.length; i++) ...[
if (i != 0 && i != cells.length)
SizedBox(
width: spacing,
),
Expanded(
flex: cells[i].flex,
child: cells[i],
),
),
],
],
),
),

View file

@ -172,7 +172,9 @@ class _TransactionCardState extends ConsumerState<TransactionCard> {
builder: (_) {
final amount = coin == Coin.monero
? (_transaction.amount ~/ 10000)
: _transaction.amount;
: coin == Coin.wownero
? (_transaction.amount ~/ 1000)
: _transaction.amount;
return Text(
"${Format.satoshiAmountToPrettyString(amount, locale)} ${coin.ticker}",
style:
@ -212,6 +214,8 @@ class _TransactionCardState extends ConsumerState<TransactionCard> {
int value = _transaction.amount;
if (coin == Coin.monero) {
value = (value ~/ 10000);
} else if (coin == Coin.wownero) {
value = (value ~/ 1000);
}
return Text(

View file

@ -317,6 +317,13 @@ packages:
relative: true
source: path
version: "0.0.1"
cw_wownero:
dependency: "direct main"
description:
path: "crypto_plugins/flutter_libmonero/cw_wownero"
relative: true
source: path
version: "0.0.1"
dart_numerics:
dependency: "direct main"
description:

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.4.49+64
version: 1.4.52+68
environment:
sdk: ">=2.17.0 <3.0.0"
@ -31,6 +31,9 @@ dependencies:
cw_monero:
path: ./crypto_plugins/flutter_libmonero/cw_monero
cw_wownero:
path: ./crypto_plugins/flutter_libmonero/cw_wownero
cw_core:
path: ./crypto_plugins/flutter_libmonero/cw_core
@ -189,6 +192,7 @@ flutter:
- assets/svg/clipboard.svg
- assets/images/stack.png
- assets/images/monero.png
- assets/images/wownero.png
- assets/images/firo.png
- assets/images/doge.png
- assets/images/bitcoin.png
@ -292,6 +296,7 @@ flutter:
- assets/svg/coin_icons/EpicCash.svg
- assets/svg/coin_icons/Firo.svg
- assets/svg/coin_icons/Monero.svg
- assets/svg/coin_icons/Wownero.svg
- assets/svg/coin_icons/Namecoin.svg
# lottie animations
- assets/lottie/test.json
@ -306,6 +311,7 @@ flutter:
- assets/svg/wallet-fa.svg
- assets/svg/exchange-3.svg
- assets/svg/message-question-1.svg
- assets/svg/drd-icon.svg
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.dev/assets-and-images/#resolution-aware.

View file

@ -1,7 +1,152 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:stackwallet/models/models.dart';
import '../services/coins/firo/sample_data/transaction_data_samples.dart';
void main() {
group("TransactionData", () {
test("TransactionData from Json", () {
final txChunk = TransactionChunk.fromJson({
"timestamp": 993260735,
"transactions": [
{
"txid": "txid",
"confirmed_status": true,
"timestamp": 1876352482,
"txType": "txType",
"amount": 10,
"worthNow": "1",
"worthAtBlockTimestamp": "1",
"fees": 1,
"inputSize": 1,
"outputSize": 1,
"inputs": [],
"outputs": [],
"address": "address",
"height": 1,
"confirmations": 1,
"aliens": [],
"subType": "mint",
"isCancelled": false,
"slateId": "slateId",
"otherData": "otherData",
}
]
});
final txdata =
TransactionData.fromJson({"dateTimeChunks": [], "txChunks": []});
txdata.findTransaction("txid");
txdata.getAllTransactions();
});
});
group("Timestamp", () {
test("Timestamp is now", () {
final date = extractDateFromTimestamp(0);
});
test("Timestamp is null", () {
final date = extractDateFromTimestamp(null);
});
test("Timestamp is a random date", () {
final date = extractDateFromTimestamp(1876352482);
});
});
group("Transaction", () {
test("Transaction from Json", () {
final tx = Transaction.fromJson({
"txid": "txid",
"confirmed_status": true,
"timestamp": 1876352482,
"txType": "txType",
"amount": 10,
"worthNow": "1",
"worthAtBlockTimestamp": "1",
"fees": 1,
"inputSize": 1,
"outputSize": 1,
"inputs": [],
"outputs": [],
"address": "address",
"height": 1,
"confirmations": 1,
"aliens": [],
"subType": "mint",
"isCancelled": false,
"slateId": "slateId",
"otherData": "otherData",
});
});
test("Transaction from Lelantus Json", () {
final tx = Transaction.fromLelantusJson({
"txid": "txid",
"confirmed_status": true,
"timestamp": 1876352482,
"txType": "txType",
"amount": 10,
"worthNow": "1",
"worthAtBlockTimestamp": "1",
"fees": 1,
"inputSize": 1,
"outputSize": 1,
"inputs": [],
"outputs": [],
"address": "address",
"height": 1,
"confirmations": 1,
"aliens": [],
"subType": "mint",
"isCancelled": false,
"slateId": "slateId",
"otherData": "otherData",
});
});
test("TransactionChunk", () {
final transactionchunk = TransactionChunk.fromJson({
"timestamp": 45920,
"transactions": [],
});
expect(
transactionchunk.toString(), "timestamp: 45920 transactions: [\n]");
});
test("TransactionChunk with a transaction", () {
final txChunk = TransactionChunk.fromJson({
"timestamp": 993260735,
"transactions": [
{
"txid": "txid",
"confirmed_status": true,
"timestamp": 1876352482,
"txType": "txType",
"amount": 10,
"worthNow": "1",
"worthAtBlockTimestamp": "1",
"fees": 1,
"inputSize": 1,
"outputSize": 1,
"inputs": [],
"outputs": [],
"address": "address",
"height": 1,
"confirmations": 1,
"aliens": [],
"subType": "mint",
"isCancelled": false,
"slateId": "slateId",
"otherData": "otherData",
}
]
});
expect(txChunk.toString(),
"timestamp: 993260735 transactions: [\n {txid: txid, type: txType, subType: mint, value: 10, fee: 1, height: 1, confirm: true, confirmations: 1, address: address, timestamp: 1876352482, worthNow: 1, inputs: [], slateid: slateId } \n]");
});
});
group("Transaction isMinting", () {
test("Transaction isMinting unconfirmed mint", () {
final tx = Transaction(
@ -94,4 +239,57 @@ void main() {
expect(tx1 == tx2, false);
expect(tx2.toString(), tx1.toString());
});
group("Input", () {
test("Input.toString", () {
final input = Input(
txid: "txid",
vout: 1,
prevout: null,
scriptsig: "scriptsig",
scriptsigAsm: "scriptsigAsm",
witness: [],
isCoinbase: false,
sequence: 1,
innerRedeemscriptAsm: "innerRedeemscriptAsm",
); //Input
expect(input.toString(), "{txid: txid}");
});
test("Input.toString", () {
final input = Input.fromJson({
"txid": "txid",
"vout": 1,
"prevout": null,
"scriptSig": {"hex": "somehexString", "asm": "someasmthing"},
"scriptsigAsm": "scriptsigAsm",
"witness": [],
"isCoinbase": false,
"sequence": 1,
"innerRedeemscriptAsm": "innerRedeemscriptAsm",
}); //Input
expect(input.toString(), "{txid: txid}");
});
});
group("Output", () {
test("Output.toString", () {
final output = Output.fromJson({
"scriptPubKey": {
"hex": "somehexSting",
"asm": "someasmthing",
"type": "sometype",
"addresses": "someaddresses",
},
"scriptpubkeyAsm": "scriptpubkeyAsm",
"scriptpubkeyType": "scriptpubkeyType",
"scriptpubkeyAddress": "address",
"value": 2,
}); //Input
expect(output.toString(), "Instance of \'Output\'");
});
});
}

View file

@ -23,8 +23,7 @@ void main() {
when(client.get(
Uri.parse(
"https://api.coingecko.com/api/v3/coins/markets?vs_currency=btc&ids=monero,bitcoin,epic-cash,zcoin,dogecoin,namecoin&order=market_cap_desc&per_page=10&page=1&sparkline=false"),
// "https://api.coingecko.com/api/v3/coins/markets?vs_currency=btc&ids=monero,bitcoin,epic-cash,zcoin,dogecoin,bitcoin-cash,namecoin&order=market_cap_desc&per_page=10&page=1&sparkline=false"),
"https://api.coingecko.com/api/v3/coins/markets?vs_currency=btc&ids=monero,bitcoin,epic-cash,zcoin,dogecoin,bitcoin-cash,namecoin,wownero&order=market_cap_desc&per_page=10&page=1&sparkline=false"),
headers: {
'Content-Type': 'application/json'
})).thenAnswer((_) async => Response(
@ -37,12 +36,10 @@ void main() {
final price = await priceAPI.getPricesAnd24hChange(baseCurrency: "btc");
expect(price.toString(),
'{Coin.bitcoin: [1, 0.0], Coin.dogecoin: [0.00000315, -2.68533], Coin.epicCash: [0.00002803, 7.27524], Coin.firo: [0.0001096, -0.89304], Coin.monero: [0.00717236, -0.77656], Coin.namecoin: [0, 0.0], Coin.bitcoinTestNet: [0, 0.0], Coin.dogecoinTestNet: [0, 0.0], Coin.firoTestNet: [0, 0.0]}');
// '{Coin.bitcoin: [1, 0.0], Coin.bitcoincash: [0, 0.0], Coin.dogecoin: [0.00000315, -2.68533], Coin.epicCash: [0.00002803, 7.27524], Coin.firo: [0.0001096, -0.89304], Coin.monero: [0.00717236, -0.77656], Coin.namecoin: [0, 0.0], Coin.bitcoinTestNet: [0, 0.0], Coin.bitcoincashTestnet: [0, 0.0], Coin.dogecoinTestNet: [0, 0.0], Coin.firoTestNet: [0, 0.0]}');
'{Coin.bitcoin: [1, 0.0], Coin.bitcoincash: [0, 0.0], Coin.dogecoin: [0.00000315, -2.68533], Coin.epicCash: [0.00002803, 7.27524], Coin.firo: [0.0001096, -0.89304], Coin.monero: [0.00717236, -0.77656], Coin.wownero: [0, 0.0], Coin.namecoin: [0, 0.0], Coin.bitcoinTestNet: [0, 0.0], Coin.bitcoincashTestnet: [0, 0.0], Coin.dogecoinTestNet: [0, 0.0], Coin.firoTestNet: [0, 0.0]}');
verify(client.get(
Uri.parse(
"https://api.coingecko.com/api/v3/coins/markets?vs_currency=btc&ids=monero,bitcoin,epic-cash,zcoin,dogecoin,namecoin&order=market_cap_desc&per_page=10&page=1&sparkline=false"),
// "https://api.coingecko.com/api/v3/coins/markets?vs_currency=btc&ids=monero,bitcoin,epic-cash,zcoin,dogecoin,bitcoin-cash,namecoin&order=market_cap_desc&per_page=10&page=1&sparkline=false"),
"https://api.coingecko.com/api/v3/coins/markets?vs_currency=btc&ids=monero,bitcoin,epic-cash,zcoin,dogecoin,bitcoin-cash,namecoin,wownero&order=market_cap_desc&per_page=10&page=1&sparkline=false"),
headers: {'Content-Type': 'application/json'})).called(1);
verifyNoMoreInteractions(client);
@ -53,8 +50,7 @@ void main() {
when(client.get(
Uri.parse(
"https://api.coingecko.com/api/v3/coins/markets?vs_currency=btc&ids=monero,bitcoin,epic-cash,zcoin,dogecoin,namecoin&order=market_cap_desc&per_page=10&page=1&sparkline=false"),
// "https://api.coingecko.com/api/v3/coins/markets?vs_currency=btc&ids=monero,bitcoin,epic-cash,zcoin,dogecoin,bitcoin-cash,namecoin&order=market_cap_desc&per_page=10&page=1&sparkline=false"),
"https://api.coingecko.com/api/v3/coins/markets?vs_currency=btc&ids=monero,bitcoin,epic-cash,zcoin,dogecoin,bitcoin-cash,namecoin,wownero&order=market_cap_desc&per_page=10&page=1&sparkline=false"),
headers: {
'Content-Type': 'application/json'
})).thenAnswer((_) async => Response(
@ -72,14 +68,12 @@ void main() {
await priceAPI.getPricesAnd24hChange(baseCurrency: "btc");
expect(cachedPrice.toString(),
'{Coin.bitcoin: [1, 0.0], Coin.dogecoin: [0.00000315, -2.68533], Coin.epicCash: [0.00002803, 7.27524], Coin.firo: [0.0001096, -0.89304], Coin.monero: [0.00717236, -0.77656], Coin.namecoin: [0, 0.0], Coin.bitcoinTestNet: [0, 0.0], Coin.dogecoinTestNet: [0, 0.0], Coin.firoTestNet: [0, 0.0]}');
// '{Coin.bitcoin: [1, 0.0], Coin.bitcoincash: [0, 0.0], Coin.dogecoin: [0.00000315, -2.68533], Coin.epicCash: [0.00002803, 7.27524], Coin.firo: [0.0001096, -0.89304], Coin.monero: [0.00717236, -0.77656], Coin.namecoin: [0, 0.0], Coin.bitcoinTestNet: [0, 0.0], Coin.bitcoincashTestnet: [0, 0.0], Coin.dogecoinTestNet: [0, 0.0], Coin.firoTestNet: [0, 0.0]}');
'{Coin.bitcoin: [1, 0.0], Coin.bitcoincash: [0, 0.0], Coin.dogecoin: [0.00000315, -2.68533], Coin.epicCash: [0.00002803, 7.27524], Coin.firo: [0.0001096, -0.89304], Coin.monero: [0.00717236, -0.77656], Coin.wownero: [0, 0.0], Coin.namecoin: [0, 0.0], Coin.bitcoinTestNet: [0, 0.0], Coin.bitcoincashTestnet: [0, 0.0], Coin.dogecoinTestNet: [0, 0.0], Coin.firoTestNet: [0, 0.0]}');
// verify only called once during filling of cache
verify(client.get(
Uri.parse(
"https://api.coingecko.com/api/v3/coins/markets?vs_currency=btc&ids=monero,bitcoin,epic-cash,zcoin,dogecoin,namecoin&order=market_cap_desc&per_page=10&page=1&sparkline=false"),
// "https://api.coingecko.com/api/v3/coins/markets?vs_currency=btc&ids=monero,bitcoin,epic-cash,zcoin,dogecoin,bitcoin-cash,namecoin&order=market_cap_desc&per_page=10&page=1&sparkline=false"),
"https://api.coingecko.com/api/v3/coins/markets?vs_currency=btc&ids=monero,bitcoin,epic-cash,zcoin,dogecoin,bitcoin-cash,namecoin,wownero&order=market_cap_desc&per_page=10&page=1&sparkline=false"),
headers: {'Content-Type': 'application/json'})).called(1);
verifyNoMoreInteractions(client);
@ -90,7 +84,7 @@ void main() {
when(client.get(
Uri.parse(
"https://api.coingecko.com/api/v3/coins/markets?vs_currency=btc&ids=monero,bitcoin,epic-cash,zcoin,dogecoin,bitcoin-cash,namecoin&order=market_cap_desc&per_page=10&page=1&sparkline=false"),
"https://api.coingecko.com/api/v3/coins/markets?vs_currency=btc&ids=monero,bitcoin,epic-cash,zcoin,dogecoin,bitcoin-cash,namecoin,wownero&order=market_cap_desc&per_page=10&page=1&sparkline=false"),
headers: {
'Content-Type': 'application/json'
})).thenAnswer((_) async => Response(
@ -103,8 +97,7 @@ void main() {
final price = await priceAPI.getPricesAnd24hChange(baseCurrency: "btc");
expect(price.toString(),
'{Coin.bitcoin: [0, 0.0], Coin.dogecoin: [0, 0.0], Coin.epicCash: [0, 0.0], Coin.firo: [0, 0.0], Coin.monero: [0, 0.0], Coin.namecoin: [0, 0.0], Coin.bitcoinTestNet: [0, 0.0], Coin.dogecoinTestNet: [0, 0.0], Coin.firoTestNet: [0, 0.0]}');
// '{Coin.bitcoin: [0, 0.0], Coin.bitcoincash: [0, 0.0], Coin.dogecoin: [0, 0.0], Coin.epicCash: [0, 0.0], Coin.firo: [0, 0.0], Coin.monero: [0, 0.0], Coin.namecoin: [0, 0.0], Coin.bitcoinTestNet: [0, 0.0], Coin.bitcoincashTestnet: [0, 0.0], Coin.dogecoinTestNet: [0, 0.0], Coin.firoTestNet: [0, 0.0]}');
'{Coin.bitcoin: [0, 0.0], Coin.bitcoincash: [0, 0.0], Coin.dogecoin: [0, 0.0], Coin.epicCash: [0, 0.0], Coin.firo: [0, 0.0], Coin.monero: [0, 0.0], Coin.wownero: [0, 0.0], Coin.namecoin: [0, 0.0], Coin.bitcoinTestNet: [0, 0.0], Coin.bitcoincashTestnet: [0, 0.0], Coin.dogecoinTestNet: [0, 0.0], Coin.firoTestNet: [0, 0.0]}');
});
test("no internet available", () async {
@ -112,8 +105,7 @@ void main() {
when(client.get(
Uri.parse(
"https://api.coingecko.com/api/v3/coins/markets?vs_currency=btc&ids=monero,bitcoin,epic-cash,zcoin,dogecoin,namecoin&order=market_cap_desc&per_page=10&page=1&sparkline=false"),
// "https://api.coingecko.com/api/v3/coins/markets?vs_currency=btc&ids=monero,bitcoin,epic-cash,zcoin,dogecoin,bitcoin-cash,namecoin&order=market_cap_desc&per_page=10&page=1&sparkline=false"),
"https://api.coingecko.com/api/v3/coins/markets?vs_currency=btc&ids=monero,bitcoin,epic-cash,zcoin,dogecoin,bitcoin-cash,namecoin,wownero&order=market_cap_desc&per_page=10&page=1&sparkline=false"),
headers: {
'Content-Type': 'application/json'
})).thenThrow(const SocketException(
@ -124,10 +116,8 @@ void main() {
final price = await priceAPI.getPricesAnd24hChange(baseCurrency: "btc");
expect(
price.toString(),
// '{Coin.bitcoin: [0, 0.0], Coin.bitcoincash: [0, 0.0], Coin.dogecoin: [0, 0.0], Coin.epicCash: [0, 0.0], Coin.firo: [0, 0.0], Coin.monero: [0, 0.0], Coin.namecoin: [0, 0.0], Coin.bitcoinTestNet: [0, 0.0], Coin.bitcoincashTestnet: [0, 0.0], Coin.dogecoinTestNet: [0, 0.0], Coin.firoTestNet: [0, 0.0]}');
'{Coin.bitcoin: [0, 0.0], Coin.dogecoin: [0, 0.0], Coin.epicCash: [0, 0.0], Coin.firo: [0, 0.0], Coin.monero: [0, 0.0], Coin.namecoin: [0, 0.0], Coin.bitcoinTestNet: [0, 0.0], Coin.dogecoinTestNet: [0, 0.0], Coin.firoTestNet: [0, 0.0]}');
expect(price.toString(),
'{Coin.bitcoin: [0, 0.0], Coin.bitcoincash: [0, 0.0], Coin.dogecoin: [0, 0.0], Coin.epicCash: [0, 0.0], Coin.firo: [0, 0.0], Coin.monero: [0, 0.0], Coin.wownero: [0, 0.0], Coin.namecoin: [0, 0.0], Coin.bitcoinTestNet: [0, 0.0], Coin.bitcoincashTestnet: [0, 0.0], Coin.dogecoinTestNet: [0, 0.0], Coin.firoTestNet: [0, 0.0]}');
});
tearDown(() async {

View file

@ -32,6 +32,40 @@ final Map<String, List<dynamic>> historyBatchArgs1 = {
"k_0_11": ["9d0163f011c1259568c188c4770606b25c823f8b76bbd262c1c7f3095ed24620"]
};
final Map<String, List<dynamic>> historyBatchArgs2 = {
"k_0_0": ["e47feb2ab9db7424d044dc5b2f29404ec35682dc7ea2100acab4b85eb15b8a84"],
"k_0_1": ["ff7f0d2a4b8e2805706ece77f4e672550fe4c505a150c781639814338eda1734"],
"k_0_2": ["68c84a2f0e8b52769e22270f9cf26bc1e3ffed55fe368e94c5d761403b86a7c5"],
"k_0_3": ["7ec0c8c9b961e481a3fd05b997997929a36c174857ba4f06e8ba55b5a29670fd"],
"k_0_4": ["42adc3dee3f1c8bc25384ab5254a75af64fc94b6e29d3ae6c0ccfb50c7910c88"],
"k_0_5": ["d3e419ee2b5ef5969a76d3e5ae14a15fe2dfa26ac434de95b0616416e4dc8955"],
"k_0_6": ["0cf8f653ae181c1a33d94787f7a34c0a95bd0465003488c1a6e7f81b87063573"],
"k_0_7": ["8c8e647009329da2c508aa08b2b28b2f83932efca4ed5a6c1b29ccec37fda9c1"],
"k_0_8": ["30c063757244ac50049d2604c7f9d671e9cbac53f4e76a9c1147112934336057"],
"k_0_9": ["2440d59c1dc1fd6dde77f52d8cf4f8f799005f53e8027f10828ef1eee739694e"],
"k_0_10": [
"1a2e9fd10dc64048e1bf86c58c37611920facf486e80a36a60e20eb3496c3aad"
],
"k_0_11": ["052e9116071688691bf12f2db3154f72562d957cf058bce2b88a144d67968da0"]
};
final Map<String, List<dynamic>> historyBatchArgs3 = {
"k_0_0": ["4694828a4841338b5921e10f9d97a9c6d2a4ff50593be21572391fefbd2179be"],
"k_0_1": ["1c2336c32dc62f00862ee6a75643e01017c86edece10b5a9d7defbd5f66b0a80"],
"k_0_2": ["e96b7f9655acc58d58ffc322626c9742f3941fef790e3d2836d5db74d3708427"],
"k_0_3": ["abc8d1cf0dc8f66678eb0d322eb4f907cb2552cde74ace5201c4978787db91e4"],
"k_0_4": ["421b02221022dd34081669fd21e7a9a83f8761e068f48b5291e0accf9d1b5867"],
"k_0_5": ["1233abcc5848b1bcf6a561984f1f0596d270ef47320c281a5abf7a2098dd5902"],
"k_0_6": ["963f002eddfb35100830f416c97605947a9df7ea885554923d6427b79d519079"],
"k_0_7": ["8b511de883d14c0f40b8eed22c23432b3d9c97ce521c4ad94338189065ae3e94"],
"k_0_8": ["954d176b775a925fcbceb36b717114b0f01af6ac082d89971379e789a4bba613"],
"k_0_9": ["3c8c79404dba45b8228547a5b3da306e1cdc3438e02f9e6ec1c88ba2fb6ef6df"],
"k_0_10": [
"a253190f30e26c482d3864d675da927a9df20c52172826ea630ca3f600da4642"
],
"k_0_11": ["bd39e800a3822ebaa5e33938b29cff5fcf867def7c0ac6d65af350b737357f65"]
};
final Map<String, List<Map<String, dynamic>>> historyBatchResponse = {
"k_0_0": [],
"s_0_0": [{}, {}],
@ -117,4 +151,8 @@ final List<String> activeScriptHashes = [
"26f92666caebb9a17b14f5b573b385348cdc80065472b8961091f3226d2f650f",
"2f18558e5d3015cb6578aee1c3e4b645725fa4e1d26ce22cb31c9949f3b4957c",
"bf5a6c56814e80eed11e1e459801515f8c2b83da812568aa9dc26e6356f6965b",
"f0c86f888f2aca0efaf1705247dbd1ebc02347c183e197310c9062ea2c9d2e34",
"ff7f0d2a4b8e2805706ece77f4e672550fe4c505a150c781639814338eda1734",
"04818da846fe5e03ac993d2e0c1ccc3848ff6073c3aba6a572df4efc5432ae8b",
"1c2336c32dc62f00862ee6a75643e01017c86edece10b5a9d7defbd5f66b0a80",
];

View file

@ -1,3 +1,5 @@
// import 'dart:convert';
//
// import 'package:bitcoindart/bitcoindart.dart';
// import 'package:decimal/decimal.dart';
// import 'package:flutter_test/flutter_test.dart';
@ -43,8 +45,9 @@ void main() {}
// });
//
// test("bitcoincash DerivePathType enum", () {
// expect(DerivePathType.values.length, 1);
// expect(DerivePathType.values.toString(), "[DerivePathType.bip44]");
// expect(DerivePathType.values.length, 2);
// expect(DerivePathType.values.toString(),
// "[DerivePathType.bip44, DerivePathType.bip49]");
// });
//
// group("bip32 node/root", () {
@ -1270,13 +1273,13 @@ void main() {}
// }
// expect(didThrow, false);
//
// verify(client?.getHistory(scripthash: anyNamed("scripthash"))).called(1);
// verify(client?.getHistory(scripthash: anyNamed("scripthash"))).called(2);
// verify(client?.getServerFeatures()).called(1);
// verifyNever(client?.ping()).called(0);
//
// expect(secureStore?.interactions, 11);
// expect(secureStore?.reads, 7);
// expect(secureStore?.writes, 4);
// expect(secureStore?.interactions, 20);
// expect(secureStore?.reads, 13);
// expect(secureStore?.writes, 7);
// expect(secureStore?.deletes, 0);
// verifyNoMoreInteractions(client);
// verifyNoMoreInteractions(cachedClient);
@ -1316,9 +1319,9 @@ void main() {}
// verify(client?.getServerFeatures()).called(1);
// verifyNever(client?.ping()).called(0);
//
// expect(secureStore?.interactions, 8);
// expect(secureStore?.reads, 5);
// expect(secureStore?.writes, 3);
// expect(secureStore?.interactions, 14);
// expect(secureStore?.reads, 9);
// expect(secureStore?.writes, 5);
// expect(secureStore?.deletes, 0);
// verifyNoMoreInteractions(client);
// verifyNoMoreInteractions(cachedClient);
@ -1365,13 +1368,13 @@ void main() {}
// }
// expect(didThrow, false);
//
// verify(client?.getHistory(scripthash: anyNamed("scripthash"))).called(1);
// verify(client?.getHistory(scripthash: anyNamed("scripthash"))).called(2);
// verify(client?.getServerFeatures()).called(1);
// verifyNever(client?.ping()).called(0);
//
// expect(secureStore?.interactions, 11);
// expect(secureStore?.reads, 7);
// expect(secureStore?.writes, 4);
// expect(secureStore?.interactions, 20);
// expect(secureStore?.reads, 13);
// expect(secureStore?.writes, 7);
// expect(secureStore?.deletes, 0);
// verifyNoMoreInteractions(client);
// verifyNoMoreInteractions(cachedClient);
@ -1412,9 +1415,9 @@ void main() {}
// verify(client?.getServerFeatures()).called(1);
// verifyNever(client?.ping()).called(0);
//
// expect(secureStore?.interactions, 8);
// expect(secureStore?.reads, 5);
// expect(secureStore?.writes, 3);
// expect(secureStore?.interactions, 14);
// expect(secureStore?.reads, 9);
// expect(secureStore?.writes, 5);
// expect(secureStore?.deletes, 0);
// verifyNoMoreInteractions(client);
// verifyNoMoreInteractions(cachedClient);
@ -1829,6 +1832,10 @@ void main() {}
// .thenAnswer((_) async => emptyHistoryBatchResponse);
// when(client?.getBatchHistory(args: historyBatchArgs1))
// .thenAnswer((_) async => emptyHistoryBatchResponse);
// when(client?.getBatchHistory(args: historyBatchArgs2))
// .thenAnswer((_) async => emptyHistoryBatchResponse);
// when(client?.getBatchHistory(args: historyBatchArgs3))
// .thenAnswer((_) async => emptyHistoryBatchResponse);
//
// final wallet = await Hive.openBox(testWalletId);
//
@ -1844,6 +1851,8 @@ void main() {}
// verify(client?.getServerFeatures()).called(1);
// verify(client?.getBatchHistory(args: historyBatchArgs0)).called(1);
// verify(client?.getBatchHistory(args: historyBatchArgs1)).called(1);
// verify(client?.getBatchHistory(args: historyBatchArgs2)).called(1);
// verify(client?.getBatchHistory(args: historyBatchArgs3)).called(1);
//
// verifyNoMoreInteractions(client);
// verifyNoMoreInteractions(cachedClient);
@ -1982,8 +1991,24 @@ void main() {}
// .thenAnswer((_) async => historyBatchResponse);
// when(client?.getBatchHistory(args: historyBatchArgs1))
// .thenAnswer((_) async => historyBatchResponse);
// when(client?.getBatchHistory(args: historyBatchArgs2))
// .thenAnswer((_) async => historyBatchResponse);
// when(client?.getBatchHistory(args: historyBatchArgs3))
// .thenAnswer((_) async => historyBatchResponse);
//
// final wallet = await Hive.openBox(testWalletId);
// List<dynamic> dynamicArgValues = [];
//
// when(client?.getBatchHistory(args: anyNamed("args")))
// .thenAnswer((realInvocation) async {
// if (realInvocation.namedArguments.values.first.length == 1) {
// dynamicArgValues.add(realInvocation.namedArguments.values.first);
// }
//
// return historyBatchResponse;
// });
//
// // final wallet = await Hive.openBox(testWalletId);
// await Hive.openBox<dynamic>(testWalletId);
//
// bool hasThrown = false;
// try {
@ -2000,10 +2025,20 @@ void main() {}
// verify(client?.getServerFeatures()).called(1);
// verify(client?.getBatchHistory(args: historyBatchArgs0)).called(1);
// verify(client?.getBatchHistory(args: historyBatchArgs1)).called(1);
// verify(client?.getBatchHistory(args: historyBatchArgs2)).called(1);
// verify(client?.getBatchHistory(args: historyBatchArgs3)).called(1);
//
// expect(secureStore?.interactions, 6);
// expect(secureStore?.writes, 3);
// expect(secureStore?.reads, 3);
// for (final arg in dynamicArgValues) {
// final map = Map<String, List<dynamic>>.from(arg as Map);
//
// verify(client?.getBatchHistory(args: map)).called(1);
// expect(activeScriptHashes.contains(map.values.first.first as String),
// true);
// }
//
// expect(secureStore?.interactions, 10);
// expect(secureStore?.writes, 5);
// expect(secureStore?.reads, 5);
// expect(secureStore?.deletes, 0);
//
// verifyNoMoreInteractions(client);
@ -2027,10 +2062,34 @@ void main() {}
// .thenAnswer((_) async => historyBatchResponse);
// when(client?.getBatchHistory(args: historyBatchArgs1))
// .thenAnswer((_) async => historyBatchResponse);
//
// when(client?.getBatchHistory(args: historyBatchArgs2))
// .thenAnswer((_) async => historyBatchResponse);
// when(client?.getBatchHistory(args: historyBatchArgs3))
// .thenAnswer((_) async => historyBatchResponse);
// when(cachedClient?.clearSharedTransactionCache(coin: Coin.bitcoincash))
// .thenAnswer((realInvocation) async {});
//
// when(client?.getBatchHistory(args: {
// "0": [
// "04818da846fe5e03ac993d2e0c1ccc3848ff6073c3aba6a572df4efc5432ae8b"
// ]
// })).thenAnswer((_) async => {"0": []});
// when(client?.getBatchHistory(args: {
// "0": [
// "f0c86f888f2aca0efaf1705247dbd1ebc02347c183e197310c9062ea2c9d2e34"
// ]
// })).thenAnswer((_) async => {"0": []});
// when(client?.getBatchHistory(args: {
// "0": [
// "ff7f0d2a4b8e2805706ece77f4e672550fe4c505a150c781639814338eda1734"
// ]
// })).thenAnswer((_) async => {"0": []});
// when(client?.getBatchHistory(args: {
// "0": [
// "1c2336c32dc62f00862ee6a75643e01017c86edece10b5a9d7defbd5f66b0a80"
// ]
// })).thenAnswer((_) async => {"0": []});
//
// final wallet = await Hive.openBox(testWalletId);
//
// // restore so we have something to rescan
@ -2046,25 +2105,51 @@ void main() {}
// final preChangeAddressesP2PKH = await wallet.get('changeAddressesP2PKH');
// final preReceivingIndexP2PKH = await wallet.get('receivingIndexP2PKH');
// final preChangeIndexP2PKH = await wallet.get('changeIndexP2PKH');
//
// final preReceivingAddressesP2SH =
// await wallet.get('receivingAddressesP2SH');
// final preChangeAddressesP2SH = await wallet.get('changeAddressesP2SH');
// final preReceivingIndexP2SH = await wallet.get('receivingIndexP2PKH');
// final preChangeIndexP2SH = await wallet.get('changeIndexP2SH');
//
// final preUtxoData = await wallet.get('latest_utxo_model');
// final preReceiveDerivationsStringP2PKH = await secureStore?.read(
// key: "${testWalletId}_receiveDerivationsP2PKH");
// final preChangeDerivationsStringP2PKH = await secureStore?.read(
// key: "${testWalletId}_changeDerivationsP2PKH");
//
// final preReceiveDerivationsStringP2SH = await secureStore?.read(
// key: "${testWalletId}_receiveDerivationsP2SH");
// final preChangeDerivationsStringP2SH =
// await secureStore?.read(key: "${testWalletId}_changeDerivationsP2SH");
//
// // destroy the data that the rescan will fix
// await wallet.put(
// 'receivingAddressesP2PKH', ["some address", "some other address"]);
// await wallet
// .put('changeAddressesP2PKH', ["some address", "some other address"]);
//
// await wallet.put(
// 'receivingAddressesP2SH', ["some address", "some other address"]);
// await wallet
// .put('changeAddressesP2SH', ["some address", "some other address"]);
//
// await wallet.put('receivingIndexP2PKH', 123);
// await wallet.put('changeIndexP2PKH', 123);
//
// await wallet.put('receivingIndexP2SH', 123);
// await wallet.put('changeIndexP2SH', 123);
//
// await secureStore?.write(
// key: "${testWalletId}_receiveDerivationsP2PKH", value: "{}");
// await secureStore?.write(
// key: "${testWalletId}_changeDerivationsP2PKH", value: "{}");
//
// await secureStore?.write(
// key: "${testWalletId}_receiveDerivationsP2SH", value: "{}");
// await secureStore?.write(
// key: "${testWalletId}_changeDerivationsP2SH", value: "{}");
//
// bool hasThrown = false;
// try {
// await bch?.fullRescan(2, 1000);
@ -2079,29 +2164,73 @@ void main() {}
// final changeAddressesP2PKH = await wallet.get('changeAddressesP2PKH');
// final receivingIndexP2PKH = await wallet.get('receivingIndexP2PKH');
// final changeIndexP2PKH = await wallet.get('changeIndexP2PKH');
//
// final receivingAddressesP2SH = await wallet.get('receivingAddressesP2SH');
// final changeAddressesP2SH = await wallet.get('changeAddressesP2SH');
// final receivingIndexP2SH = await wallet.get('receivingIndexP2SH');
// final changeIndexP2SH = await wallet.get('changeIndexP2SH');
//
// final utxoData = await wallet.get('latest_utxo_model');
// final receiveDerivationsStringP2PKH = await secureStore?.read(
// key: "${testWalletId}_receiveDerivationsP2PKH");
// final changeDerivationsStringP2PKH = await secureStore?.read(
// key: "${testWalletId}_changeDerivationsP2PKH");
//
// final receiveDerivationsStringP2SH = await secureStore?.read(
// key: "${testWalletId}_receiveDerivationsP2SH");
// final changeDerivationsStringP2SH =
// await secureStore?.read(key: "${testWalletId}_changeDerivationsP2SH");
//
// expect(preReceivingAddressesP2PKH, receivingAddressesP2PKH);
// expect(preChangeAddressesP2PKH, changeAddressesP2PKH);
// expect(preReceivingIndexP2PKH, receivingIndexP2PKH);
// expect(preChangeIndexP2PKH, changeIndexP2PKH);
//
// expect(preReceivingAddressesP2SH, receivingAddressesP2SH);
// expect(preChangeAddressesP2SH, changeAddressesP2SH);
// expect(preReceivingIndexP2SH, receivingIndexP2SH);
// expect(preChangeIndexP2SH, changeIndexP2SH);
//
// expect(preUtxoData, utxoData);
//
// expect(preReceiveDerivationsStringP2PKH, receiveDerivationsStringP2PKH);
// expect(preChangeDerivationsStringP2PKH, changeDerivationsStringP2PKH);
//
// expect(preReceiveDerivationsStringP2SH, receiveDerivationsStringP2SH);
// expect(preChangeDerivationsStringP2SH, changeDerivationsStringP2SH);
//
// verify(client?.getServerFeatures()).called(1);
// verify(client?.getBatchHistory(args: historyBatchArgs0)).called(2);
// verify(client?.getBatchHistory(args: historyBatchArgs1)).called(2);
// verify(client?.getBatchHistory(args: historyBatchArgs2)).called(2);
// verify(client?.getBatchHistory(args: historyBatchArgs3)).called(2);
// verify(cachedClient?.clearSharedTransactionCache(coin: Coin.bitcoincash))
// .called(1);
//
// expect(secureStore?.writes, 9);
// expect(secureStore?.reads, 12);
// expect(secureStore?.deletes, 2);
// verify(client?.getBatchHistory(args: {
// "0": [
// "04818da846fe5e03ac993d2e0c1ccc3848ff6073c3aba6a572df4efc5432ae8b"
// ]
// })).called(2);
// verify(client?.getBatchHistory(args: {
// "0": [
// "f0c86f888f2aca0efaf1705247dbd1ebc02347c183e197310c9062ea2c9d2e34"
// ]
// })).called(2);
// verify(client?.getBatchHistory(args: {
// "0": [
// "ff7f0d2a4b8e2805706ece77f4e672550fe4c505a150c781639814338eda1734"
// ]
// })).called(2);
// verify(client?.getBatchHistory(args: {
// "0": [
// "1c2336c32dc62f00862ee6a75643e01017c86edece10b5a9d7defbd5f66b0a80"
// ]
// })).called(2);
//
// expect(secureStore?.writes, 17);
// expect(secureStore?.reads, 22);
// expect(secureStore?.deletes, 4);
//
// verifyNoMoreInteractions(client);
// verifyNoMoreInteractions(cachedClient);
@ -2125,19 +2254,33 @@ void main() {}
// .thenAnswer((_) async => historyBatchResponse);
// when(client?.getBatchHistory(args: historyBatchArgs1))
// .thenAnswer((_) async => historyBatchResponse);
// when(client?.getBatchHistory(args: historyBatchArgs2))
// .thenAnswer((_) async => historyBatchResponse);
// when(client?.getBatchHistory(args: historyBatchArgs3))
// .thenAnswer((_) async => historyBatchResponse);
// when(cachedClient?.clearSharedTransactionCache(coin: Coin.bitcoincash))
// .thenAnswer((realInvocation) async {});
//
// when(client?.getBatchHistory(args: {
// "0": [
// "04818da846fe5e03ac993d2e0c1ccc3848ff6073c3aba6a572df4efc5432ae8b"
// ]
// })).thenAnswer((realInvocation) async => {"0": []});
//
// when(client?.getBatchHistory(args: {
// "0": [
// "f0c86f888f2aca0efaf1705247dbd1ebc02347c183e197310c9062ea2c9d2e34"
// ]
// })).thenAnswer((realInvocation) async => {"0": []});
// when(cachedClient?.clearSharedTransactionCache(coin: Coin.dogecoin))
// .thenAnswer((realInvocation) async {});
// })).thenAnswer((_) async => {"0": []});
// when(client?.getBatchHistory(args: {
// "0": [
// "ff7f0d2a4b8e2805706ece77f4e672550fe4c505a150c781639814338eda1734"
// ]
// })).thenAnswer((_) async => {"0": []});
// when(client?.getBatchHistory(args: {
// "0": [
// "1c2336c32dc62f00862ee6a75643e01017c86edece10b5a9d7defbd5f66b0a80"
// ]
// })).thenAnswer((_) async => {"0": []});
//
// final wallet = await Hive.openBox(testWalletId);
//
@ -2195,13 +2338,36 @@ void main() {}
//
// verify(client?.getServerFeatures()).called(1);
// verify(client?.getBatchHistory(args: historyBatchArgs0)).called(2);
// verify(client?.getBatchHistory(args: historyBatchArgs1)).called(1);
// verify(client?.getBatchHistory(args: historyBatchArgs1)).called(2);
// verify(client?.getBatchHistory(args: historyBatchArgs2)).called(2);
// verify(client?.getBatchHistory(args: historyBatchArgs3)).called(2);
// verify(cachedClient?.clearSharedTransactionCache(coin: Coin.bitcoincash))
// .called(1);
//
// expect(secureStore?.writes, 7);
// expect(secureStore?.reads, 12);
// expect(secureStore?.deletes, 4);
// verify(client?.getBatchHistory(args: {
// "0": [
// "04818da846fe5e03ac993d2e0c1ccc3848ff6073c3aba6a572df4efc5432ae8b"
// ]
// })).called(1);
// verify(client?.getBatchHistory(args: {
// "0": [
// "f0c86f888f2aca0efaf1705247dbd1ebc02347c183e197310c9062ea2c9d2e34"
// ]
// })).called(2);
// verify(client?.getBatchHistory(args: {
// "0": [
// "ff7f0d2a4b8e2805706ece77f4e672550fe4c505a150c781639814338eda1734"
// ]
// })).called(2);
// verify(client?.getBatchHistory(args: {
// "0": [
// "1c2336c32dc62f00862ee6a75643e01017c86edece10b5a9d7defbd5f66b0a80"
// ]
// })).called(2);
//
// expect(secureStore?.writes, 13);
// expect(secureStore?.reads, 18);
// expect(secureStore?.deletes, 8);
// });
//
// // // test("fetchBuildTxData succeeds", () async {
@ -2686,17 +2852,30 @@ void main() {}
// .thenAnswer((_) async => historyBatchResponse);
// when(client?.getBatchHistory(args: historyBatchArgs1))
// .thenAnswer((_) async => historyBatchResponse);
// when(client?.getBatchHistory(args: historyBatchArgs2))
// .thenAnswer((_) async => historyBatchResponse);
// when(client?.getBatchHistory(args: historyBatchArgs3))
// .thenAnswer((_) async => historyBatchResponse);
// when(client?.getBatchHistory(args: {
// "0": [
// "f0c86f888f2aca0efaf1705247dbd1ebc02347c183e197310c9062ea2c9d2e34"
// ]
// })).thenAnswer((realInvocation) async => {"0": []});
//
// when(client?.getBatchHistory(args: {
// "0": [
// "04818da846fe5e03ac993d2e0c1ccc3848ff6073c3aba6a572df4efc5432ae8b"
// ]
// })).thenAnswer((realInvocation) async => {"0": []});
// when(client?.getBatchHistory(args: {
// "0": [
// "ff7f0d2a4b8e2805706ece77f4e672550fe4c505a150c781639814338eda1734"
// ]
// })).thenAnswer((realInvocation) async => {"0": []});
// when(client?.getBatchHistory(args: {
// "0": [
// "1c2336c32dc62f00862ee6a75643e01017c86edece10b5a9d7defbd5f66b0a80"
// ]
// })).thenAnswer((realInvocation) async => {"0": []});
//
// final wallet = await Hive.openBox(testWalletId);
// // recover to fill data
@ -2713,10 +2892,33 @@ void main() {}
// verify(client?.getServerFeatures()).called(1);
// verify(client?.getBatchHistory(args: historyBatchArgs0)).called(1);
// verify(client?.getBatchHistory(args: historyBatchArgs1)).called(1);
// verify(client?.getBatchHistory(args: historyBatchArgs2)).called(1);
// verify(client?.getBatchHistory(args: historyBatchArgs3)).called(1);
//
// expect(secureStore?.interactions, 6);
// expect(secureStore?.writes, 3);
// expect(secureStore?.reads, 3);
// verify(client?.getBatchHistory(args: {
// "0": [
// "f0c86f888f2aca0efaf1705247dbd1ebc02347c183e197310c9062ea2c9d2e34"
// ]
// })).called(1);
// verify(client?.getBatchHistory(args: {
// "0": [
// "04818da846fe5e03ac993d2e0c1ccc3848ff6073c3aba6a572df4efc5432ae8b"
// ]
// })).called(1);
// verify(client?.getBatchHistory(args: {
// "0": [
// "ff7f0d2a4b8e2805706ece77f4e672550fe4c505a150c781639814338eda1734"
// ]
// })).called(1);
// verify(client?.getBatchHistory(args: {
// "0": [
// "1c2336c32dc62f00862ee6a75643e01017c86edece10b5a9d7defbd5f66b0a80"
// ]
// })).called(1);
//
// expect(secureStore?.interactions, 10);
// expect(secureStore?.writes, 5);
// expect(secureStore?.reads, 5);
// expect(secureStore?.deletes, 0);
//
// verifyNoMoreInteractions(client);
@ -2741,17 +2943,32 @@ void main() {}
// .thenAnswer((_) async => historyBatchResponse);
// when(client?.getBatchHistory(args: historyBatchArgs1))
// .thenAnswer((_) async => historyBatchResponse);
// when(client?.getBatchHistory(args: {
// "0": [
// "f0c86f888f2aca0efaf1705247dbd1ebc02347c183e197310c9062ea2c9d2e34"
// ]
// })).thenAnswer((realInvocation) async => {"0": []});
// when(client?.getBatchHistory(args: historyBatchArgs2))
// .thenAnswer((_) async => historyBatchResponse);
// when(client?.getBatchHistory(args: historyBatchArgs3))
// .thenAnswer((_) async => historyBatchResponse);
//
// when(client?.getBatchHistory(args: {
// "0": [
// "04818da846fe5e03ac993d2e0c1ccc3848ff6073c3aba6a572df4efc5432ae8b"
// ]
// })).thenAnswer((realInvocation) async => {"0": []});
// when(client?.getBatchHistory(args: {
// "0": [
// "f0c86f888f2aca0efaf1705247dbd1ebc02347c183e197310c9062ea2c9d2e34"
// ]
// })).thenAnswer((realInvocation) async => {"0": []});
// when(client?.getBatchHistory(args: {
// "0": [
// "ff7f0d2a4b8e2805706ece77f4e672550fe4c505a150c781639814338eda1734"
// ]
// })).thenAnswer((realInvocation) async => {"0": []});
// when(client?.getBatchHistory(args: {
// "0": [
// "1c2336c32dc62f00862ee6a75643e01017c86edece10b5a9d7defbd5f66b0a80"
// ]
// })).thenAnswer((realInvocation) async => {"0": []});
//
// when(client?.getHistory(scripthash: anyNamed("scripthash")))
// .thenThrow(Exception("some exception"));
//
@ -2769,12 +2986,36 @@ void main() {}
// verify(client?.getServerFeatures()).called(1);
// verify(client?.getBatchHistory(args: historyBatchArgs0)).called(1);
// verify(client?.getBatchHistory(args: historyBatchArgs1)).called(1);
// verify(client?.getBatchHistory(args: historyBatchArgs2)).called(1);
// verify(client?.getBatchHistory(args: historyBatchArgs3)).called(1);
//
// verify(client?.getBatchHistory(args: {
// "0": [
// "04818da846fe5e03ac993d2e0c1ccc3848ff6073c3aba6a572df4efc5432ae8b"
// ]
// })).called(1);
// verify(client?.getBatchHistory(args: {
// "0": [
// "f0c86f888f2aca0efaf1705247dbd1ebc02347c183e197310c9062ea2c9d2e34"
// ]
// })).called(1);
// verify(client?.getBatchHistory(args: {
// "0": [
// "ff7f0d2a4b8e2805706ece77f4e672550fe4c505a150c781639814338eda1734"
// ]
// })).called(1);
// verify(client?.getBatchHistory(args: {
// "0": [
// "1c2336c32dc62f00862ee6a75643e01017c86edece10b5a9d7defbd5f66b0a80"
// ]
// })).called(1);
//
// verify(client?.getBlockHeadTip()).called(1);
// verify(client?.getHistory(scripthash: anyNamed("scripthash"))).called(1);
//
// expect(secureStore?.interactions, 6);
// expect(secureStore?.writes, 3);
// expect(secureStore?.reads, 3);
// expect(secureStore?.interactions, 10);
// expect(secureStore?.writes, 5);
// expect(secureStore?.reads, 5);
// expect(secureStore?.deletes, 0);
//
// verifyNoMoreInteractions(client);