diff --git a/lib/electrumx_rpc/electrumx_client.dart b/lib/electrumx_rpc/electrumx_client.dart index 98c6614f9..9ca3dfeb1 100644 --- a/lib/electrumx_rpc/electrumx_client.dart +++ b/lib/electrumx_rpc/electrumx_client.dart @@ -1020,18 +1020,6 @@ class ElectrumXClient { ], ); try { - // If the response is -1 or null, return a temporary hardcoded value for - // Dogecoin. This is a temporary fix until the fee estimation is fixed. - if (coin == Coin.dogecoin && - (response == null || - response == -1 || - Decimal.parse(response.toString()) == Decimal.parse("-1"))) { - // Return 0.05 for slow, 0.2 for average, and 1 for fast txs. - // These numbers produce tx fees in line with txs in the wild on - // https://dogechain.info/ - return Decimal.parse((1 / blocks).toString()); - // TODO [prio=med]: Fix fee estimation. - } return Decimal.parse(response.toString()); } catch (e, s) { final String msg = "Error parsing fee rate. Response: $response" diff --git a/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart b/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart index 9d40e4106..e025d621b 100644 --- a/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart +++ b/lib/pages/add_wallet_views/restore_wallet_view/restore_wallet_view.dart @@ -56,6 +56,7 @@ import 'package:stackwallet/wallets/wallet/impl/monero_wallet.dart'; import 'package:stackwallet/wallets/wallet/impl/wownero_wallet.dart'; import 'package:stackwallet/wallets/wallet/supporting/epiccash_wallet_info_extension.dart'; import 'package:stackwallet/wallets/wallet/wallet.dart'; +import 'package:stackwallet/widgets/conditional_parent.dart'; import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart'; import 'package:stackwallet/widgets/desktop/desktop_app_bar.dart'; import 'package:stackwallet/widgets/desktop/desktop_scaffold.dart'; @@ -726,350 +727,378 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> { color: Theme.of(context).extension<StackColors>()!.background, child: Padding( padding: const EdgeInsets.all(12.0), - child: SingleChildScrollView( - child: Column( - children: [ - /*if (isDesktop) + child: ConditionalParent( + condition: isDesktop, + builder: (child) => Expanded( + child: child, + ), + child: SingleChildScrollView( + controller: controller, + child: Column( + children: [ + /*if (isDesktop) const Spacer( flex: 10, ),*/ - if (!isDesktop) - Text( - widget.walletName, - style: STextStyles.itemSubtitle(context), - ), - SizedBox( - height: isDesktop ? 0 : 4, - ), - Text( - "Recovery phrase", - style: isDesktop - ? STextStyles.desktopH2(context) - : STextStyles.pageTitleH1(context), - ), - SizedBox( - height: isDesktop ? 16 : 8, - ), - Text( - "Enter your $_seedWordCount-word recovery phrase.", - style: isDesktop - ? STextStyles.desktopSubtitleH2(context) - : STextStyles.subtitle(context), - ), - SizedBox( - height: isDesktop ? 16 : 10, - ), - 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) + Text( + widget.walletName, + style: STextStyles.itemSubtitle(context), ), - ], - ), - if (isDesktop) - const SizedBox( - height: 20, - ), - if (isDesktop) - ConstrainedBox( - constraints: const BoxConstraints( - maxWidth: 1008, + SizedBox( + height: isDesktop ? 0 : 4, ), - child: Builder( - builder: (BuildContext context) { - const cols = 4; - final int rows = _seedWordCount ~/ cols; - final int remainder = _seedWordCount % cols; - - return Column( - children: [ - 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( - autocorrect: !isDesktop, - enableSuggestions: !isDesktop, - 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, - // focusNode: - // _focusNodes[i * 4 + j - 1], - onChanged: (value) { - final FormInputStatus - formInputStatus; - - if (value.isEmpty) { - formInputStatus = - FormInputStatus.empty; - } else if (_isValidMnemonicWord( - value - .trim() - .toLowerCase())) { - formInputStatus = - FormInputStatus.valid; - } else { - formInputStatus = - FormInputStatus.invalid; - } - - // if (formInputStatus == - // FormInputStatus.valid) { - // if (i * 4 + j < - // _focusNodes.length) { - // _focusNodes[i * 4 + j] - // .requestFocus(); - // } else if (i * 4 + j == - // _focusNodes.length) { - // _focusNodes[i * 4 + j - 1] - // .unfocus(); - // } - // } - setState(() { - _inputStatuses[i * 4 + - j - - 1] = formInputStatus; - }); - }, - controller: - _controllers[i * 4 + j - 1], - style: - STextStyles.field(context) - .copyWith( - color: Theme.of(context) - .extension<StackColors>()! - .textRestore, - 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( - autocorrect: !isDesktop, - enableSuggestions: !isDesktop, - textCapitalization: - TextCapitalization.none, - key: Key( - "restoreMnemonicFormField_$i"), - decoration: - _getInputDecorationFor( - _inputStatuses[i], - "${i + 1}"), - autovalidateMode: - AutovalidateMode - .onUserInteraction, - selectionControls: i == 1 - ? textSelectionControls - : null, - // focusNode: _focusNodes[i], - onChanged: (value) { - final FormInputStatus - formInputStatus; - - if (value.isEmpty) { - formInputStatus = - FormInputStatus.empty; - } else if (_isValidMnemonicWord( - value - .trim() - .toLowerCase())) { - formInputStatus = - FormInputStatus.valid; - } else { - formInputStatus = - FormInputStatus.invalid; - } - - // if (formInputStatus == - // FormInputStatus - // .valid && - // (i - 1) < - // _focusNodes.length) { - // Focus.of(context) - // .requestFocus( - // _focusNodes[i]); - // } - - // if (formInputStatus == - // FormInputStatus.valid) { - // if (i + 1 < - // _focusNodes.length) { - // _focusNodes[i + 1] - // .requestFocus(); - // } else if (i + 1 == - // _focusNodes.length) { - // _focusNodes[i].unfocus(); - // } - // } - }, - 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, - ), + Text( + "Recovery phrase", + style: isDesktop + ? STextStyles.desktopH2(context) + : STextStyles.pageTitleH1(context), + ), + SizedBox( + height: isDesktop ? 16 : 8, + ), + Text( + "Enter your $_seedWordCount-word recovery phrase.", + style: isDesktop + ? STextStyles.desktopSubtitleH2(context) + : STextStyles.subtitle(context), + ), + SizedBox( + height: isDesktop ? 16 : 10, + ), + 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), + ) ], ), ), - const SizedBox( - height: 32, - ), - PrimaryButton( - label: "Restore wallet", - width: 480, - onPressed: requestRestore, - ), - ], - ); - }, - ), - ), - /*if (isDesktop) + ), + ], + ), + 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: [ + 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( + autocorrect: !isDesktop, + enableSuggestions: + !isDesktop, + 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, + // focusNode: + // _focusNodes[i * 4 + j - 1], + onChanged: (value) { + final FormInputStatus + formInputStatus; + + if (value.isEmpty) { + formInputStatus = + FormInputStatus + .empty; + } else if (_isValidMnemonicWord( + value + .trim() + .toLowerCase())) { + formInputStatus = + FormInputStatus + .valid; + } else { + formInputStatus = + FormInputStatus + .invalid; + } + + // if (formInputStatus == + // FormInputStatus.valid) { + // if (i * 4 + j < + // _focusNodes.length) { + // _focusNodes[i * 4 + j] + // .requestFocus(); + // } else if (i * 4 + j == + // _focusNodes.length) { + // _focusNodes[i * 4 + j - 1] + // .unfocus(); + // } + // } + setState(() { + _inputStatuses[ + i * 4 + j - 1] = + formInputStatus; + }); + }, + controller: _controllers[ + i * 4 + j - 1], + style: STextStyles.field( + context) + .copyWith( + color: Theme.of(context) + .extension< + StackColors>()! + .textRestore, + 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( + autocorrect: !isDesktop, + enableSuggestions: + !isDesktop, + textCapitalization: + TextCapitalization.none, + key: Key( + "restoreMnemonicFormField_$i"), + decoration: + _getInputDecorationFor( + _inputStatuses[i], + "${i + 1}"), + autovalidateMode: + AutovalidateMode + .onUserInteraction, + selectionControls: i == 1 + ? textSelectionControls + : null, + // focusNode: _focusNodes[i], + onChanged: (value) { + final FormInputStatus + formInputStatus; + + if (value.isEmpty) { + formInputStatus = + FormInputStatus + .empty; + } else if (_isValidMnemonicWord( + value + .trim() + .toLowerCase())) { + formInputStatus = + FormInputStatus + .valid; + } else { + formInputStatus = + FormInputStatus + .invalid; + } + + // if (formInputStatus == + // FormInputStatus + // .valid && + // (i - 1) < + // _focusNodes.length) { + // Focus.of(context) + // .requestFocus( + // _focusNodes[i]); + // } + + // if (formInputStatus == + // FormInputStatus.valid) { + // if (i + 1 < + // _focusNodes.length) { + // _focusNodes[i + 1] + // .requestFocus(); + // } else if (i + 1 == + // _focusNodes.length) { + // _focusNodes[i].unfocus(); + // } + // } + }, + 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, + ), + ], + ), + ), + 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( + if (!isDesktop) + Padding( padding: const EdgeInsets.all(4.0), child: Form( key: _formKey, @@ -1169,13 +1198,12 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> { ), ), ), - ), - ), - ], + ], + ), + ), ), ), ), - ), ); } } diff --git a/lib/wallets/crypto_currency/coins/ecash.dart b/lib/wallets/crypto_currency/coins/ecash.dart index 6858796cb..07e164c6e 100644 --- a/lib/wallets/crypto_currency/coins/ecash.dart +++ b/lib/wallets/crypto_currency/coins/ecash.dart @@ -185,7 +185,8 @@ class Ecash extends Bip39HDCurrency { addr = cashAddr.split(":").last; } - return addr.startsWith("q") || addr.startsWith("p"); + return addr.startsWith("q") /*|| addr.startsWith("p")*/; + // Do not validate "p" (P2SH) addresses. } @override diff --git a/pubspec.lock b/pubspec.lock index 2bba3135a..07ee80f19 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -528,8 +528,8 @@ packages: dependency: "direct main" description: path: "." - ref: "0a34f7f48d921fb33f551cb11dfc9b2930522240" - resolved-ref: "0a34f7f48d921fb33f551cb11dfc9b2930522240" + ref: "2897c6448e131241d4d91fe23fdab83305134225" + resolved-ref: "2897c6448e131241d4d91fe23fdab83305134225" url: "https://github.com/cypherstack/electrum_adapter.git" source: git version: "3.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index 223c9a95b..13b50ee5e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -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.10.1+209 +version: 1.10.1+212 environment: sdk: ">=3.0.2 <4.0.0" @@ -176,7 +176,7 @@ dependencies: electrum_adapter: git: url: https://github.com/cypherstack/electrum_adapter.git - ref: 0a34f7f48d921fb33f551cb11dfc9b2930522240 + ref: 2897c6448e131241d4d91fe23fdab83305134225 stream_channel: ^2.1.0 dev_dependencies: