Merge pull request #325 from cypherstack/paynyms

Paynyms
This commit is contained in:
Diego Salazar 2023-01-27 18:18:32 -07:00 committed by GitHub
commit 352680ecc9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
76 changed files with 6268 additions and 4032 deletions

View file

@ -1,3 +1,4 @@
import 'package:flutter/foundation.dart';
import 'package:isar/isar.dart';
import 'package:stackwallet/models/isar/models/isar_models.dart';
import 'package:stackwallet/utilities/stack_file_system.dart';
@ -28,7 +29,7 @@ class MainDB {
AddressSchema,
],
directory: (await StackFileSystem.applicationIsarDirectory()).path,
inspector: false,
inspector: kDebugMode,
name: "wallet_data",
);
return true;
@ -47,6 +48,31 @@ class MainDB {
await isar.addresses.putAll(addresses);
});
Future<void> updateOrPutAddresses(List<Address> addresses) async {
await isar.writeTxn(() async {
for (final address in addresses) {
final storedAddress = await isar.addresses
.getByValueWalletId(address.value, address.walletId);
if (storedAddress == null) {
await isar.addresses.put(address);
} else {
address.id = storedAddress.id;
await storedAddress.transactions.load();
final txns = storedAddress.transactions.toList();
await isar.addresses.delete(storedAddress.id);
await isar.addresses.put(address);
address.transactions.addAll(txns);
await address.transactions.save();
}
}
});
}
Future<Address?> getAddress(String walletId, String address) async {
return isar.addresses.getByValueWalletId(address, walletId);
}
Future<void> updateAddress(Address oldAddress, Address newAddress) =>
isar.writeTxn(() async {
newAddress.id = oldAddress.id;
@ -73,6 +99,10 @@ class MainDB {
await isar.transactions.putAll(transactions);
});
Future<Transaction?> getTransaction(String walletId, String txid) async {
return isar.transactions.getByTxidWalletId(txid, walletId);
}
// utxos
QueryBuilder<UTXO, UTXO, QAfterWhereClause> getUTXOs(String walletId) =>
isar.utxos.where().walletIdEqualTo(walletId);

View file

@ -4,6 +4,7 @@ import 'dart:io';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:decimal/decimal.dart';
import 'package:stackwallet/electrumx_rpc/rpc.dart';
import 'package:stackwallet/exceptions/electrumx/no_such_transaction.dart';
import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/utilities/prefs.dart';
import 'package:uuid/uuid.dart';
@ -132,7 +133,17 @@ class ElectrumX {
final response = await _rpcClient!.request(jsonRequestString);
if (response["error"] != null) {
throw Exception("JSONRPC response error: $response");
if (response["error"]
.toString()
.contains("No such mempool or blockchain transaction")) {
throw NoSuchTransactionException(
"No such mempool or blockchain transaction",
args.first.toString(),
);
}
throw Exception(
"JSONRPC response \ncommand: $command \nargs: $args \nerror: $response");
}
currentFailoverIndex = -1;
@ -544,6 +555,10 @@ class ElectrumX {
verbose,
],
);
if (!verbose) {
return {"rawtx": response["result"] as String};
}
return Map<String, dynamic>.from(response["result"] as Map);
} catch (e) {
rethrow;

View file

@ -0,0 +1,5 @@
import 'package:stackwallet/exceptions/sw_exception.dart';
class AddressException extends SWException {
AddressException(super.message);
}

View file

@ -0,0 +1,7 @@
import 'package:stackwallet/exceptions/sw_exception.dart';
class NoSuchTransactionException extends SWException {
final String txid;
NoSuchTransactionException(super.message, this.txid);
}

View file

@ -0,0 +1,11 @@
// generic stack wallet exception which all other custom exceptions should
// extend from
class SWException with Exception {
SWException(this.message);
final String message;
@override
toString() => message;
}

View file

@ -0,0 +1,5 @@
import 'package:stackwallet/exceptions/sw_exception.dart';
class InsufficientBalanceException extends SWException {
InsufficientBalanceException(super.message);
}

View file

@ -0,0 +1,5 @@
import 'package:stackwallet/exceptions/sw_exception.dart';
class PaynymSendException extends SWException {
PaynymSendException(super.message);
}

View file

@ -254,6 +254,7 @@ class _MaterialAppWithThemeState extends ConsumerState<MaterialAppWithTheme>
_desktopHasPassword =
await ref.read(storageCryptoHandlerProvider).hasPassword();
}
await MainDB.instance.initMainDB();
}
Future<void> load() async {
@ -267,8 +268,6 @@ class _MaterialAppWithThemeState extends ConsumerState<MaterialAppWithTheme>
await loadShared();
}
await MainDB.instance.initMainDB();
_notificationsService = ref.read(notificationsProvider);
_nodeService = ref.read(nodeServiceChangeNotifierProvider);
_tradesService = ref.read(tradesServiceProvider);

View file

@ -1,14 +1,10 @@
import 'package:isar/isar.dart';
import 'package:stackwallet/exceptions/address/address_exception.dart';
import 'package:stackwallet/models/isar/models/address/crypto_currency_address.dart';
import 'package:stackwallet/models/isar/models/blockchain_data/transaction.dart';
import 'package:stackwallet/services/coins/coin_paynym_extension.dart';
part 'address.g.dart';
class AddressException extends SWException {
AddressException(super.message);
}
@Collection(accessor: "addresses")
class Address extends CryptoCurrencyAddress {
Address({

View file

@ -5,16 +5,17 @@ import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
import 'package:qr_flutter/qr_flutter.dart';
import 'package:stackwallet/exceptions/wallet/insufficient_balance_exception.dart';
import 'package:stackwallet/models/paynym/paynym_account_lite.dart';
import 'package:stackwallet/notifications/show_flush_bar.dart';
import 'package:stackwallet/pages/paynym/dialogs/confirm_paynym_connect_dialog.dart';
import 'package:stackwallet/pages/paynym/paynym_home_view.dart';
import 'package:stackwallet/pages/paynym/subwidgets/paynym_bot.dart';
import 'package:stackwallet/pages/send_view/confirm_transaction_view.dart';
import 'package:stackwallet/pages/send_view/send_view.dart';
import 'package:stackwallet/providers/global/wallets_provider.dart';
import 'package:stackwallet/route_generator.dart';
import 'package:stackwallet/services/coins/coin_paynym_extension.dart';
import 'package:stackwallet/services/coins/dogecoin/dogecoin_wallet.dart';
import 'package:stackwallet/services/mixins/paynym_wallet_interface.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/text_styles.dart';
@ -25,6 +26,7 @@ import 'package:stackwallet/widgets/desktop/primary_button.dart';
import 'package:stackwallet/widgets/desktop/secondary_button.dart';
import 'package:stackwallet/widgets/loading_indicator.dart';
import 'package:stackwallet/widgets/rounded_container.dart';
import 'package:tuple/tuple.dart';
class PaynymDetailsPopup extends ConsumerStatefulWidget {
const PaynymDetailsPopup({
@ -43,6 +45,19 @@ class PaynymDetailsPopup extends ConsumerStatefulWidget {
class _PaynymDetailsPopupState extends ConsumerState<PaynymDetailsPopup> {
bool _showInsufficientFundsInfo = false;
Future<void> _onSend() async {
final manager =
ref.read(walletsChangeNotifierProvider).getManager(widget.walletId);
await Navigator.of(context).pushNamed(
SendView.routeName,
arguments: Tuple3(
manager.walletId,
manager.coin,
widget.accountLite,
),
);
}
Future<void> _onConnectPressed() async {
bool canPop = false;
unawaited(
@ -57,30 +72,24 @@ class _PaynymDetailsPopupState extends ConsumerState<PaynymDetailsPopup> {
),
);
final wallet = ref
.read(walletsChangeNotifierProvider)
.getManager(widget.walletId)
.wallet as DogecoinWallet;
final manager =
ref.read(walletsChangeNotifierProvider).getManager(widget.walletId);
// sanity check to prevent second notifcation tx
if (wallet.hasConnectedConfirmed(widget.accountLite.code)) {
canPop = true;
Navigator.of(context).pop();
// TODO show info popup
return;
} else if (wallet.hasConnected(widget.accountLite.code)) {
final wallet = manager.wallet as PaynymWalletInterface;
if (await wallet.hasConnected(widget.accountLite.code)) {
canPop = true;
Navigator.of(context).pop();
// TODO show info popup
return;
}
final rates = await wallet.fees;
final rates = await manager.fees;
Map<String, dynamic> preparedTx;
try {
preparedTx = await wallet.buildNotificationTx(
preparedTx = await wallet.prepareNotificationTx(
selectedTxFeeRate: rates.medium,
targetPaymentCodeString: widget.accountLite.code,
);
@ -117,7 +126,7 @@ class _PaynymDetailsPopupState extends ConsumerState<PaynymDetailsPopup> {
Navigator.of(context).push(
RouteGenerator.getRoute(
builder: (_) => ConfirmTransactionView(
walletId: wallet.walletId,
walletId: manager.walletId,
routeOnSuccessName: PaynymHomeView.routeName,
isPaynymNotificationTransaction: true,
transactionInfo: {
@ -133,7 +142,7 @@ class _PaynymDetailsPopupState extends ConsumerState<PaynymDetailsPopup> {
);
},
amount: (preparedTx["amount"] as int) + (preparedTx["fee"] as int),
coin: wallet.coin,
coin: manager.coin,
),
);
}
@ -141,6 +150,11 @@ class _PaynymDetailsPopupState extends ConsumerState<PaynymDetailsPopup> {
@override
Widget build(BuildContext context) {
final manager = ref.watch(walletsChangeNotifierProvider
.select((value) => value.getManager(widget.walletId)));
final wallet = manager.wallet as PaynymWalletInterface;
return DesktopDialog(
maxWidth: MediaQuery.of(context).size.width - 32,
maxHeight: double.infinity,
@ -173,20 +187,51 @@ class _PaynymDetailsPopupState extends ConsumerState<PaynymDetailsPopup> {
),
],
),
PrimaryButton(
label: "Connect",
buttonHeight: ButtonHeight.l,
icon: SvgPicture.asset(
Assets.svg.circlePlusFilled,
width: 10,
height: 10,
color: Theme.of(context)
.extension<StackColors>()!
.buttonTextPrimary,
),
iconSpacing: 4,
width: 86,
onPressed: _onConnectPressed,
FutureBuilder(
future: wallet.hasConnected(widget.accountLite.code),
builder: (context, AsyncSnapshot<bool> snapshot) {
if (snapshot.connectionState == ConnectionState.done &&
snapshot.hasData) {
if (snapshot.data!) {
return PrimaryButton(
label: "Send",
buttonHeight: ButtonHeight.l,
icon: SvgPicture.asset(
Assets.svg.circleArrowUpRight,
width: 10,
height: 10,
color: Theme.of(context)
.extension<StackColors>()!
.buttonTextPrimary,
),
iconSpacing: 4,
width: 86,
onPressed: _onSend,
);
} else {
return PrimaryButton(
label: "Connect",
buttonHeight: ButtonHeight.l,
icon: SvgPicture.asset(
Assets.svg.circlePlusFilled,
width: 10,
height: 10,
color: Theme.of(context)
.extension<StackColors>()!
.buttonTextPrimary,
),
iconSpacing: 4,
width: 86,
onPressed: _onConnectPressed,
);
}
} else {
return const SizedBox(
height: 32,
child: LoadingIndicator(),
);
}
},
),
],
),

View file

@ -9,9 +9,9 @@ import 'package:stackwallet/pages/wallet_view/wallet_view.dart';
import 'package:stackwallet/providers/global/paynym_api_provider.dart';
import 'package:stackwallet/providers/global/wallets_provider.dart';
import 'package:stackwallet/providers/wallet/my_paynym_account_state_provider.dart';
import 'package:stackwallet/services/coins/coin_paynym_extension.dart';
import 'package:stackwallet/services/coins/dogecoin/dogecoin_wallet.dart';
import 'package:stackwallet/services/mixins/paynym_wallet_interface.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/utilities/util.dart';
@ -159,16 +159,18 @@ class _PaynymClaimViewState extends ConsumerState<PaynymClaimView> {
).then((value) => shouldCancel = value == true),
);
// get wallet to access paynym calls
final wallet = ref
final manager = ref
.read(walletsChangeNotifierProvider)
.getManager(widget.walletId)
.wallet as DogecoinWallet;
.getManager(widget.walletId);
// get wallet to access paynym calls
final wallet = manager.wallet as PaynymWalletInterface;
if (shouldCancel) return;
// get payment code
final pCode = await wallet.getPaymentCode();
final pCode = await wallet.getPaymentCode(
DerivePathTypeExt.primaryFor(manager.coin));
if (shouldCancel) return;

View file

@ -5,14 +5,14 @@ import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
import 'package:qr_flutter/qr_flutter.dart';
import 'package:stackwallet/exceptions/wallet/insufficient_balance_exception.dart';
import 'package:stackwallet/models/paynym/paynym_account_lite.dart';
import 'package:stackwallet/notifications/show_flush_bar.dart';
import 'package:stackwallet/pages/paynym/dialogs/confirm_paynym_connect_dialog.dart';
import 'package:stackwallet/pages/paynym/subwidgets/paynym_bot.dart';
import 'package:stackwallet/pages/send_view/confirm_transaction_view.dart';
import 'package:stackwallet/providers/global/wallets_provider.dart';
import 'package:stackwallet/services/coins/coin_paynym_extension.dart';
import 'package:stackwallet/services/coins/dogecoin/dogecoin_wallet.dart';
import 'package:stackwallet/services/mixins/paynym_wallet_interface.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/text_styles.dart';
@ -57,30 +57,24 @@ class _PaynymDetailsPopupState extends ConsumerState<DesktopPaynymDetails> {
),
);
final wallet = ref
.read(walletsChangeNotifierProvider)
.getManager(widget.walletId)
.wallet as DogecoinWallet;
final manager =
ref.read(walletsChangeNotifierProvider).getManager(widget.walletId);
// sanity check to prevent second notification tx
if (wallet.hasConnectedConfirmed(widget.accountLite.code)) {
canPop = true;
Navigator.of(context, rootNavigator: true).pop();
// TODO show info popup
return;
} else if (wallet.hasConnected(widget.accountLite.code)) {
final wallet = manager.wallet as PaynymWalletInterface;
if (await wallet.hasConnected(widget.accountLite.code)) {
canPop = true;
Navigator.of(context, rootNavigator: true).pop();
// TODO show info popup
return;
}
final rates = await wallet.fees;
final rates = await manager.fees;
Map<String, dynamic> preparedTx;
try {
preparedTx = await wallet.buildNotificationTx(
preparedTx = await wallet.prepareNotificationTx(
selectedTxFeeRate: rates.medium,
targetPaymentCodeString: widget.accountLite.code,
);
@ -118,7 +112,7 @@ class _PaynymDetailsPopupState extends ConsumerState<DesktopPaynymDetails> {
maxHeight: double.infinity,
maxWidth: 580,
child: ConfirmTransactionView(
walletId: wallet.walletId,
walletId: manager.walletId,
isPaynymNotificationTransaction: true,
transactionInfo: {
"hex": preparedTx["hex"],
@ -147,7 +141,7 @@ class _PaynymDetailsPopupState extends ConsumerState<DesktopPaynymDetails> {
);
},
amount: (preparedTx["amount"] as int) + (preparedTx["fee"] as int),
coin: wallet.coin,
coin: manager.coin,
),
);
}
@ -159,10 +153,11 @@ class _PaynymDetailsPopupState extends ConsumerState<DesktopPaynymDetails> {
@override
Widget build(BuildContext context) {
final wallet = ref
.watch(walletsChangeNotifierProvider)
.getManager(widget.walletId)
.wallet as DogecoinWallet;
final manager = ref.watch(walletsChangeNotifierProvider
.select((value) => value.getManager(widget.walletId)));
final wallet = manager.wallet as PaynymWalletInterface;
return RoundedWhiteContainer(
padding: const EdgeInsets.all(0),
child: Column(
@ -192,40 +187,53 @@ class _PaynymDetailsPopupState extends ConsumerState<DesktopPaynymDetails> {
),
Row(
children: [
if (!wallet.hasConnected(widget.accountLite.code))
Expanded(
child: PrimaryButton(
label: "Connect",
buttonHeight: ButtonHeight.s,
icon: SvgPicture.asset(
Assets.svg.circlePlusFilled,
width: 16,
height: 16,
color: Theme.of(context)
.extension<StackColors>()!
.buttonTextPrimary,
),
iconSpacing: 6,
onPressed: _onConnectPressed,
),
),
if (wallet.hasConnected(widget.accountLite.code))
Expanded(
child: PrimaryButton(
label: "Send",
buttonHeight: ButtonHeight.s,
icon: SvgPicture.asset(
Assets.svg.circleArrowUpRight,
width: 16,
height: 16,
color: Theme.of(context)
.extension<StackColors>()!
.buttonTextPrimary,
),
iconSpacing: 6,
onPressed: _onSend,
),
Expanded(
child: FutureBuilder(
future: wallet.hasConnected(widget.accountLite.code),
builder: (context, AsyncSnapshot<bool> snapshot) {
if (snapshot.connectionState ==
ConnectionState.done &&
snapshot.hasData) {
if (snapshot.data!) {
return PrimaryButton(
label: "Send",
buttonHeight: ButtonHeight.s,
icon: SvgPicture.asset(
Assets.svg.circleArrowUpRight,
width: 16,
height: 16,
color: Theme.of(context)
.extension<StackColors>()!
.buttonTextPrimary,
),
iconSpacing: 6,
onPressed: _onSend,
);
} else {
return PrimaryButton(
label: "Connect",
buttonHeight: ButtonHeight.s,
icon: SvgPicture.asset(
Assets.svg.circlePlusFilled,
width: 16,
height: 16,
color: Theme.of(context)
.extension<StackColors>()!
.buttonTextPrimary,
),
iconSpacing: 6,
onPressed: _onConnectPressed,
);
}
} else {
return const SizedBox(
height: 100,
child: LoadingIndicator(),
);
}
},
),
),
const SizedBox(
width: 20,
),

View file

@ -4,6 +4,7 @@ import 'package:decimal/decimal.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
import 'package:stackwallet/models/paynym/paynym_account_lite.dart';
import 'package:stackwallet/notifications/show_flush_bar.dart';
import 'package:stackwallet/pages/pinpad_views/lock_screen_view.dart';
import 'package:stackwallet/pages/send_view/sub_widgets/sending_transaction_dialog.dart';
@ -12,10 +13,9 @@ import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/sub
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/providers/wallet/public_private_balance_state_provider.dart';
import 'package:stackwallet/route_generator.dart';
import 'package:stackwallet/services/coins/coin_paynym_extension.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/mixins/paynym_wallet_interface.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
@ -92,11 +92,10 @@ class _ConfirmTransactionViewState
try {
String txid;
if (widget.isPaynymNotificationTransaction) {
txid = await (manager.wallet as DogecoinWallet)
.confirmNotificationTx(preparedTx: transactionInfo);
txid = await (manager.wallet as PaynymWalletInterface)
.broadcastNotificationTx(preparedTx: transactionInfo);
} else if (widget.isPaynymTransaction) {
//
throw UnimplementedError("paynym send not implemented yet");
txid = await manager.confirmSend(txData: transactionInfo);
} else {
final coin = manager.coin;
if ((coin == Coin.firo || coin == Coin.firoTestNet) &&
@ -334,14 +333,20 @@ class _ConfirmTransactionViewState
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
"Recipient",
widget.isPaynymTransaction
? "PayNym recipient"
: "Recipient",
style: STextStyles.smallMed12(context),
),
const SizedBox(
height: 4,
),
Text(
"${transactionInfo["address"] ?? "ERROR"}",
widget.isPaynymTransaction
? (transactionInfo["paynymAccountLite"]
as PaynymAccountLite)
.nymName
: "${transactionInfo["address"] ?? "ERROR"}",
style: STextStyles.itemSubtitle12(context),
),
],

File diff suppressed because it is too large Load diff

View file

@ -2,6 +2,9 @@ import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/widgets/conditional_parent.dart';
import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
import 'package:stackwallet/widgets/stack_dialog.dart';
class RescanningDialog extends StatefulWidget {
@ -21,9 +24,12 @@ class _RescanningDialogState extends State<RescanningDialog>
late AnimationController? _spinController;
late Animation<double> _spinAnimation;
late final bool isDesktop;
// late final VoidCallback onCancel;
@override
void initState() {
isDesktop = Util.isDesktop;
// onCancel = widget.onCancel;
_spinController = AnimationController(
@ -53,33 +59,42 @@ class _RescanningDialogState extends State<RescanningDialog>
onWillPop: () async {
return false;
},
child: StackDialog(
title: "Rescanning blockchain",
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,
),
child: ConditionalParent(
condition: isDesktop,
builder: (child) => DesktopDialog(
maxHeight: 200,
maxWidth: 500,
child: child,
),
child: StackDialog(
title: "Rescanning blockchain",
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).textButtonTheme.style?.copyWith(
// backgroundColor: MaterialStateProperty.all<Color>(
// CFColors.buttonGray,
// ),
// ),
// child: Text(
// "Cancel",
// style: STextStyles.itemSubtitle12(context),
// ),
// onPressed: () {
// Navigator.of(context).pop();
// onCancel.call();
// },
// ),
),
// rightButton: TextButton(
// style: Theme.of(context).textButtonTheme.style?.copyWith(
// backgroundColor: MaterialStateProperty.all<Color>(
// CFColors.buttonGray,
// ),
// ),
// child: Text(
// "Cancel",
// style: STextStyles.itemSubtitle12(context),
// ),
// onPressed: () {
// Navigator.of(context).pop();
// onCancel.call();
// },
// ),
),
);
}

View file

@ -76,6 +76,8 @@ class _WalletNetworkSettingsViewState
StreamSubscription<dynamic>? _blocksRemainingSubscription;
// late StreamSubscription _nodeStatusSubscription;
late final bool isDesktop;
late double _percent;
late int _blocksRemaining;
bool _advancedIsExpanded = false;
@ -114,7 +116,7 @@ class _WalletNetworkSettingsViewState
if (mounted) {
// pop rescanning dialog
Navigator.pop(context);
Navigator.of(context, rootNavigator: isDesktop).pop();
// show success
await showDialog<dynamic>(
@ -132,7 +134,7 @@ class _WalletNetworkSettingsViewState
style: STextStyles.itemSubtitle12(context),
),
onPressed: () {
Navigator.of(context).pop();
Navigator.of(context, rootNavigator: isDesktop).pop();
},
),
),
@ -143,7 +145,7 @@ class _WalletNetworkSettingsViewState
if (mounted) {
// pop rescanning dialog
Navigator.pop(context);
Navigator.of(context, rootNavigator: isDesktop).pop();
// show error
await showDialog<dynamic>(
@ -162,7 +164,7 @@ class _WalletNetworkSettingsViewState
style: STextStyles.itemSubtitle12(context),
),
onPressed: () {
Navigator.of(context).pop();
Navigator.of(context, rootNavigator: isDesktop).pop();
},
),
),
@ -183,6 +185,7 @@ class _WalletNetworkSettingsViewState
@override
void initState() {
isDesktop = Util.isDesktop;
_currentSyncStatus = widget.initialSyncStatus;
// _currentNodeStatus = widget.initialNodeStatus;
if (_currentSyncStatus == WalletSyncStatus.synced) {
@ -270,7 +273,6 @@ class _WalletNetworkSettingsViewState
@override
Widget build(BuildContext context) {
final screenWidth = MediaQuery.of(context).size.width;
final bool isDesktop = Util.isDesktop;
final progressLength = isDesktop
? 430.0

View file

@ -8,16 +8,16 @@ import 'package:stackwallet/pages/paynym/paynym_home_view.dart';
import 'package:stackwallet/providers/global/paynym_api_provider.dart';
import 'package:stackwallet/providers/global/wallets_provider.dart';
import 'package:stackwallet/providers/wallet/my_paynym_account_state_provider.dart';
import 'package:stackwallet/services/coins/coin_paynym_extension.dart';
import 'package:stackwallet/services/coins/dogecoin/dogecoin_wallet.dart';
import 'package:stackwallet/services/mixins/paynym_wallet_interface.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart';
import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/widgets/loading_indicator.dart';
class WalletNavigationBar extends StatefulWidget {
class WalletNavigationBar extends ConsumerStatefulWidget {
const WalletNavigationBar({
Key? key,
required this.onReceivePressed,
@ -40,10 +40,11 @@ class WalletNavigationBar extends StatefulWidget {
final String walletId;
@override
State<WalletNavigationBar> createState() => _WalletNavigationBarState();
ConsumerState<WalletNavigationBar> createState() =>
_WalletNavigationBarState();
}
class _WalletNavigationBarState extends State<WalletNavigationBar> {
class _WalletNavigationBarState extends ConsumerState<WalletNavigationBar> {
double scale = 0;
final duration = const Duration(milliseconds: 200);
@ -61,41 +62,41 @@ class _WalletNavigationBarState extends State<WalletNavigationBar> {
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
AnimatedOpacity(
opacity: scale,
duration: duration,
child: GestureDetector(
onTap: () {},
child: Container(
padding: const EdgeInsets.all(16),
width: 146,
decoration: BoxDecoration(
color:
Theme.of(context).extension<StackColors>()!.popupBG,
boxShadow: [
Theme.of(context)
.extension<StackColors>()!
.standardBoxShadow
],
borderRadius: BorderRadius.circular(
widget.height / 2.0,
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"Whirlpool",
style: STextStyles.w600_12(context),
),
],
),
),
),
),
const SizedBox(
height: 8,
),
// AnimatedOpacity(
// opacity: scale,
// duration: duration,
// child: GestureDetector(
// onTap: () {},
// child: Container(
// padding: const EdgeInsets.all(16),
// width: 146,
// decoration: BoxDecoration(
// color:
// Theme.of(context).extension<StackColors>()!.popupBG,
// boxShadow: [
// Theme.of(context)
// .extension<StackColors>()!
// .standardBoxShadow
// ],
// borderRadius: BorderRadius.circular(
// widget.height / 2.0,
// ),
// ),
// child: Row(
// mainAxisAlignment: MainAxisAlignment.center,
// children: [
// Text(
// "Whirlpool",
// style: STextStyles.w600_12(context),
// ),
// ],
// ),
// ),
// ),
// ),
// const SizedBox(
// height: 8,
// ),
AnimatedOpacity(
opacity: scale,
duration: duration,
@ -114,13 +115,15 @@ class _WalletNavigationBarState extends State<WalletNavigationBar> {
),
);
// todo make generic and not doge specific
final wallet = (ref
final manager = ref
.read(walletsChangeNotifierProvider)
.getManager(widget.walletId)
.wallet as DogecoinWallet);
.getManager(widget.walletId);
final code = await wallet.getPaymentCode();
final paynymInterface =
manager.wallet as PaynymWalletInterface;
final code = await paynymInterface.getPaymentCode(
DerivePathTypeExt.primaryFor(manager.coin));
final account = await ref
.read(paynymAPIProvider)
@ -357,7 +360,8 @@ class _WalletNavigationBarState extends State<WalletNavigationBar> {
),
),
),
if (widget.coin.hasPaynymSupport)
if (ref.watch(walletsChangeNotifierProvider.select((value) =>
value.getManager(widget.walletId).hasPaynymSupport)))
RawMaterialButton(
constraints: const BoxConstraints(
minWidth: 66,

View file

@ -19,14 +19,14 @@ import 'package:stackwallet/providers/global/paynym_api_provider.dart';
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/providers/ui/transaction_filter_provider.dart';
import 'package:stackwallet/providers/wallet/my_paynym_account_state_provider.dart';
import 'package:stackwallet/services/coins/coin_paynym_extension.dart';
import 'package:stackwallet/services/coins/dogecoin/dogecoin_wallet.dart';
import 'package:stackwallet/services/coins/firo/firo_wallet.dart';
import 'package:stackwallet/services/event_bus/events/global/wallet_sync_status_changed_event.dart';
import 'package:stackwallet/services/event_bus/global_event_bus.dart';
import 'package:stackwallet/services/mixins/paynym_wallet_interface.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/enums/backup_frequency_type.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart';
import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
@ -209,13 +209,13 @@ class _DesktopWalletViewState extends ConsumerState<DesktopWalletView> {
),
);
// todo make generic and not doge specific
final wallet = (ref
.read(walletsChangeNotifierProvider)
.getManager(widget.walletId)
.wallet as DogecoinWallet);
final manager =
ref.read(walletsChangeNotifierProvider).getManager(widget.walletId);
final code = await wallet.getPaymentCode();
final wallet = manager.wallet as PaynymWalletInterface;
final code =
await wallet.getPaymentCode(DerivePathTypeExt.primaryFor(manager.coin));
final account = await ref.read(paynymAPIProvider).nym(code.toString());
@ -445,7 +445,8 @@ class _DesktopWalletViewState extends ConsumerState<DesktopWalletView> {
);
},
),
if (coin.hasPaynymSupport)
if (ref.watch(walletsChangeNotifierProvider.select((value) =>
value.getManager(widget.walletId).hasPaynymSupport)))
SecondaryButton(
label: "PayNym",
width: 160,

View file

@ -6,6 +6,7 @@ import 'package:stackwallet/models/buy/response_objects/quote.dart';
import 'package:stackwallet/models/contact_address_entry.dart';
import 'package:stackwallet/models/exchange/incomplete_exchange.dart';
import 'package:stackwallet/models/exchange/response_objects/trade.dart';
import 'package:stackwallet/models/paynym/paynym_account_lite.dart';
import 'package:stackwallet/models/send_view_auto_fill_data.dart';
import 'package:stackwallet/pages/add_wallet_views/add_wallet_view/add_wallet_view.dart';
import 'package:stackwallet/pages/add_wallet_views/create_or_restore_wallet_view/create_or_restore_wallet_view.dart';
@ -843,6 +844,18 @@ class RouteGenerator {
name: settings.name,
),
);
} else if (args is Tuple3<String, Coin, PaynymAccountLite>) {
return getRoute(
shouldUseMaterialRoute: useMaterialPageRoute,
builder: (_) => SendView(
walletId: args.item1,
coin: args.item2,
accountLite: args.item3,
),
settings: RouteSettings(
name: settings.name,
),
);
}
return _routeError("${settings.name} invalid args: ${args.toString()}");

View file

@ -13,16 +13,18 @@ import 'package:isar/isar.dart';
import 'package:stackwallet/db/main_db.dart';
import 'package:stackwallet/electrumx_rpc/cached_electrumx.dart';
import 'package:stackwallet/electrumx_rpc/electrumx.dart';
import 'package:stackwallet/exceptions/electrumx/no_such_transaction.dart';
import 'package:stackwallet/models/balance.dart';
import 'package:stackwallet/models/isar/models/isar_models.dart' as isar_models;
import 'package:stackwallet/models/paymint/fee_object_model.dart';
import 'package:stackwallet/services/coins/coin_paynym_extension.dart';
import 'package:stackwallet/services/coins/coin_service.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';
import 'package:stackwallet/services/event_bus/events/global/updated_in_background_event.dart';
import 'package:stackwallet/services/event_bus/events/global/wallet_sync_status_changed_event.dart';
import 'package:stackwallet/services/event_bus/global_event_bus.dart';
import 'package:stackwallet/services/mixins/electrum_x_parsing.dart';
import 'package:stackwallet/services/mixins/paynym_wallet_interface.dart';
import 'package:stackwallet/services/mixins/wallet_cache.dart';
import 'package:stackwallet/services/mixins/wallet_db.dart';
import 'package:stackwallet/services/node_service.dart';
@ -33,6 +35,7 @@ import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/default_nodes.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart';
import 'package:stackwallet/utilities/enums/fee_rate_type_enum.dart';
import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart';
import 'package:stackwallet/utilities/format.dart';
@ -50,8 +53,6 @@ const String GENESIS_HASH_MAINNET =
const String GENESIS_HASH_TESTNET =
"000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943";
enum DerivePathType { bip44, bip49, bip84 }
bip32.BIP32 getBip32Node(
int chain,
int index,
@ -138,7 +139,8 @@ bip32.BIP32 getBip32RootWrapper(Tuple2<String, NetworkType> args) {
return getBip32Root(args.item1, args.item2);
}
class BitcoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
class BitcoinWallet extends CoinServiceAPI
with WalletCache, WalletDB, ElectrumXParsing, PaynymWalletInterface {
static const integrationTestFlag =
bool.fromEnvironment("IS_INTEGRATION_TEST");
@ -178,8 +180,16 @@ class BitcoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
Future<List<isar_models.UTXO>> get utxos => db.getUTXOs(walletId).findAll();
@override
Future<List<isar_models.Transaction>> get transactions =>
db.getTransactions(walletId).sortByTimestampDesc().findAll();
Future<List<isar_models.Transaction>> get transactions => db
.getTransactions(walletId)
.filter()
.not()
.group((q) => q
.subTypeEqualTo(isar_models.TransactionSubType.bip47Notification)
.and()
.typeEqualTo(isar_models.TransactionType.incoming))
.sortByTimestampDesc()
.findAll();
@override
Future<String> get currentReceivingAddress async =>
@ -193,7 +203,7 @@ class BitcoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
.subTypeEqualTo(isar_models.AddressSubType.receiving)
.sortByDerivationIndexDesc()
.findFirst()) ??
await _generateAddressForChain(0, 0, DerivePathType.bip84);
await _generateAddressForChain(0, 0, DerivePathTypeExt.primaryFor(coin));
Future<String> get currentChangeAddress async =>
(await _currentChangeAddress).value;
@ -206,7 +216,7 @@ class BitcoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
.subTypeEqualTo(isar_models.AddressSubType.change)
.sortByDerivationIndexDesc()
.findFirst()) ??
await _generateAddressForChain(1, 0, DerivePathType.bip84);
await _generateAddressForChain(1, 0, DerivePathTypeExt.primaryFor(coin));
@override
Future<void> exit() async {
@ -673,6 +683,18 @@ class BitcoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
...p2shChangeAddressArray,
]);
// generate to ensure notification address is in db before refreshing transactions
await getMyNotificationAddress(DerivePathType.bip44);
// refresh transactions to pick up any received notification transactions
await _refreshTransactions();
// restore paynym transactions
await restoreAllHistory(
maxUnusedAddressGap: maxUnusedAddressGap,
maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck,
);
await _updateUTXOs();
await Future.wait([
@ -737,6 +759,13 @@ class BitcoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
}
}
return needsRefresh;
} on NoSuchTransactionException catch (e) {
// TODO: move direct transactions elsewhere
await db.isar.writeTxn(() async {
await db.isar.transactions.deleteByTxidWalletId(e.txid, walletId);
});
await txTracker.deleteTransaction(e.txid);
return true;
} catch (e, s) {
Logging.instance.log(
"Exception caught in refreshIfThereIsNewData: $e\n$s",
@ -906,6 +935,8 @@ class BitcoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
GlobalEventBus.instance.fire(RefreshPercentChangedEvent(0.3, walletId));
await _checkCurrentReceivingAddressesForTransactions();
await checkAllCurrentReceivingPaynymAddressesForTransactions();
final fetchFuture = _refreshTransactions();
final utxosRefreshFuture = _updateUTXOs();
GlobalEventBus.instance
@ -1264,6 +1295,26 @@ class BitcoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
_secureStore = secureStore;
initCache(walletId, coin);
initWalletDB(mockableOverride: mockableOverride);
initPaynymWalletInterface(
walletId: walletId,
walletName: walletName,
network: _network,
coin: coin,
db: db,
electrumXClient: electrumXClient,
secureStorage: secureStore,
getMnemonic: () => mnemonic,
getChainHeight: () => chainHeight,
getCurrentChangeAddress: () => currentChangeAddress,
estimateTxFee: estimateTxFee,
prepareSend: prepareSend,
getTxCount: getTxCount,
fetchBuildTxData: fetchBuildTxData,
refresh: refresh,
checkChangeAddressForTransactions: _checkChangeAddressForTransactions,
addDerivation: addDerivation,
addDerivations: addDerivations,
);
}
@override
@ -1324,62 +1375,11 @@ class BitcoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
.getAddresses(walletId)
.filter()
.not()
.typeEqualTo(isar_models.AddressType.unknown)
.and()
.not()
.typeEqualTo(isar_models.AddressType.nonWallet)
.and()
.group((q) => q
.subTypeEqualTo(isar_models.AddressSubType.receiving)
.or()
.subTypeEqualTo(isar_models.AddressSubType.change))
.not()
.subTypeEqualTo(isar_models.AddressSubType.nonWallet)
.findAll();
// final List<String> allAddresses = [];
// final receivingAddresses = DB.instance.get<dynamic>(
// boxName: walletId, key: 'receivingAddressesP2WPKH') as List<dynamic>;
// final changeAddresses = DB.instance.get<dynamic>(
// boxName: walletId, key: 'changeAddressesP2WPKH') as List<dynamic>;
// final receivingAddressesP2PKH = DB.instance.get<dynamic>(
// boxName: walletId, key: 'receivingAddressesP2PKH') as List<dynamic>;
// final changeAddressesP2PKH =
// DB.instance.get<dynamic>(boxName: walletId, key: 'changeAddressesP2PKH')
// as List<dynamic>;
// final receivingAddressesP2SH = DB.instance.get<dynamic>(
// boxName: walletId, key: 'receivingAddressesP2SH') as List<dynamic>;
// final changeAddressesP2SH =
// DB.instance.get<dynamic>(boxName: walletId, key: 'changeAddressesP2SH')
// as List<dynamic>;
//
// for (var i = 0; i < receivingAddresses.length; i++) {
// if (!allAddresses.contains(receivingAddresses[i])) {
// allAddresses.add(receivingAddresses[i] as String);
// }
// }
// for (var i = 0; i < changeAddresses.length; i++) {
// if (!allAddresses.contains(changeAddresses[i])) {
// allAddresses.add(changeAddresses[i] as String);
// }
// }
// for (var i = 0; i < receivingAddressesP2PKH.length; i++) {
// if (!allAddresses.contains(receivingAddressesP2PKH[i])) {
// allAddresses.add(receivingAddressesP2PKH[i] as String);
// }
// }
// for (var i = 0; i < changeAddressesP2PKH.length; i++) {
// if (!allAddresses.contains(changeAddressesP2PKH[i])) {
// allAddresses.add(changeAddressesP2PKH[i] as String);
// }
// }
// for (var i = 0; i < receivingAddressesP2SH.length; i++) {
// if (!allAddresses.contains(receivingAddressesP2SH[i])) {
// allAddresses.add(receivingAddressesP2SH[i] as String);
// }
// }
// for (var i = 0; i < changeAddressesP2SH.length; i++) {
// if (!allAddresses.contains(changeAddressesP2SH[i])) {
// allAddresses.add(changeAddressesP2SH[i] as String);
// }
// }
return allAddresses;
}
@ -1754,15 +1754,34 @@ class BitcoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
coin: coin,
);
// todo check here if we should mark as blocked
// fetch stored tx to see if paynym notification tx and block utxo
final storedTx = await db.getTransaction(
walletId,
fetchedUtxoList[i][j]["tx_hash"] as String,
);
bool shouldBlock = false;
String? blockReason;
if (storedTx?.subType ==
isar_models.TransactionSubType.bip47Notification &&
storedTx?.type == isar_models.TransactionType.incoming) {
// probably safe to assume this is an incoming tx as it is a utxo
// belonging to this wallet. The extra check may be redundant but
// just in case...
shouldBlock = true;
blockReason = "Incoming paynym notification transaction.";
}
final utxo = isar_models.UTXO(
walletId: walletId,
txid: txn["txid"] as String,
vout: fetchedUtxoList[i][j]["tx_pos"] as int,
value: fetchedUtxoList[i][j]["value"] as int,
name: "",
isBlocked: false,
blockedReason: null,
isBlocked: shouldBlock,
blockedReason: blockReason,
isCoinbase: txn["is_coinbase"] as bool? ?? false,
blockHash: txn["blockhash"] as String?,
blockHeight: fetchedUtxoList[i][j]["height"] as int?,
@ -1868,7 +1887,7 @@ class BitcoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
// Use new index to derive a new receiving address
final newReceivingAddress = await _generateAddressForChain(
0, newReceivingIndex, DerivePathType.bip84);
0, newReceivingIndex, DerivePathTypeExt.primaryFor(coin));
final existing = await db
.getAddresses(walletId)
@ -1887,7 +1906,7 @@ class BitcoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
}
} catch (e, s) {
Logging.instance.log(
"Exception rethrown from _checkReceivingAddressForTransactions(${DerivePathType.bip84}): $e\n$s",
"Exception rethrown from _checkReceivingAddressForTransactions(${DerivePathTypeExt.primaryFor(coin)}): $e\n$s",
level: LogLevel.Error);
rethrow;
}
@ -1907,7 +1926,7 @@ class BitcoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
// Use new index to derive a new change address
final newChangeAddress = await _generateAddressForChain(
1, newChangeIndex, DerivePathType.bip84);
1, newChangeIndex, DerivePathTypeExt.primaryFor(coin));
final existing = await db
.getAddresses(walletId)
@ -1926,12 +1945,12 @@ class BitcoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
}
} on SocketException catch (se, s) {
Logging.instance.log(
"SocketException caught in _checkReceivingAddressForTransactions(${DerivePathType.bip84}): $se\n$s",
"SocketException caught in _checkReceivingAddressForTransactions(${DerivePathTypeExt.primaryFor(coin)}): $se\n$s",
level: LogLevel.Error);
return;
} catch (e, s) {
Logging.instance.log(
"Exception rethrown from _checkReceivingAddressForTransactions(${DerivePathType.bip84}): $e\n$s",
"Exception rethrown from _checkReceivingAddressForTransactions(${DerivePathTypeExt.primaryFor(coin)}): $e\n$s",
level: LogLevel.Error);
rethrow;
}
@ -2269,7 +2288,7 @@ class BitcoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
utxoSigningData: utxoSigningData,
recipients: [
_recipientAddress,
await _getCurrentAddressForChain(1, DerivePathType.bip84),
await _getCurrentAddressForChain(1, DerivePathTypeExt.primaryFor(coin)),
],
satoshiAmounts: [
satoshiAmountToSend,
@ -2308,8 +2327,8 @@ class BitcoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
feeForTwoOutputs) {
// generate new change address if current change address has been used
await _checkChangeAddressForTransactions();
final String newChangeAddress =
await _getCurrentAddressForChain(1, DerivePathType.bip84);
final String newChangeAddress = await _getCurrentAddressForChain(
1, DerivePathTypeExt.primaryFor(coin));
int feeBeingPaid =
satoshisBeingUsed - satoshiAmountToSend - changeOutputSize;
@ -3035,7 +3054,7 @@ class BitcoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
// Use new index to derive a new receiving address
final newReceivingAddress = await _generateAddressForChain(
0, newReceivingIndex, DerivePathType.bip84);
0, newReceivingIndex, DerivePathTypeExt.primaryFor(coin));
// Add that new receiving address
await db.putAddress(newReceivingAddress);

View file

@ -34,6 +34,7 @@ import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/default_nodes.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart';
import 'package:stackwallet/utilities/enums/fee_rate_type_enum.dart';
import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart';
import 'package:stackwallet/utilities/format.dart';
@ -50,8 +51,6 @@ const String GENESIS_HASH_MAINNET =
const String GENESIS_HASH_TESTNET =
"000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943";
enum DerivePathType { bip44, bip49 }
bip32.BIP32 getBip32Node(int chain, int index, String mnemonic,
NetworkType network, DerivePathType derivePathType) {
final root = getBip32Root(mnemonic, network);
@ -170,7 +169,7 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
.subTypeEqualTo(isar_models.AddressSubType.receiving)
.sortByDerivationIndexDesc()
.findFirst()) ??
await _generateAddressForChain(0, 0, DerivePathType.bip44);
await _generateAddressForChain(0, 0, DerivePathTypeExt.primaryFor(coin));
Future<String> get currentChangeAddress async =>
(await _currentChangeAddress).value;
@ -183,7 +182,7 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
.subTypeEqualTo(isar_models.AddressSubType.change)
.sortByDerivationIndexDesc()
.findFirst()) ??
await _generateAddressForChain(1, 0, DerivePathType.bip44);
await _generateAddressForChain(1, 0, DerivePathTypeExt.primaryFor(coin));
@override
Future<void> exit() async {
@ -1421,9 +1420,8 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
.address!;
addrType = isar_models.AddressType.p2sh;
break;
// default:
// // should never hit this due to all enum cases handled
// return null;
case DerivePathType.bip84:
throw UnsupportedError("bip84 not supported by BCH");
}
// add generated address & info to derivations
@ -1466,6 +1464,8 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
case DerivePathType.bip49:
type = isar_models.AddressType.p2sh;
break;
case DerivePathType.bip84:
throw UnsupportedError("bip84 not supported by BCH");
}
final address = await db
@ -1491,6 +1491,8 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
case DerivePathType.bip49:
key = "${walletId}_${chainId}DerivationsP2SH";
break;
case DerivePathType.bip84:
throw UnsupportedError("bip84 not supported by BCH");
}
return key;
}
@ -1752,7 +1754,7 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
// Use new index to derive a new receiving address
final newReceivingAddress = await _generateAddressForChain(
0, newReceivingIndex, DerivePathType.bip44);
0, newReceivingIndex, DerivePathTypeExt.primaryFor(coin));
final existing = await db
.getAddresses(walletId)
@ -1771,12 +1773,12 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
}
} on SocketException catch (se, s) {
Logging.instance.log(
"SocketException caught in _checkReceivingAddressForTransactions(${DerivePathType.bip44}): $se\n$s",
"SocketException caught in _checkReceivingAddressForTransactions(${DerivePathTypeExt.primaryFor(coin)}): $se\n$s",
level: LogLevel.Error);
return;
} catch (e, s) {
Logging.instance.log(
"Exception rethrown from _checkReceivingAddressForTransactions(${DerivePathType.bip44}): $e\n$s",
"Exception rethrown from _checkReceivingAddressForTransactions(${DerivePathTypeExt.primaryFor(coin)}): $e\n$s",
level: LogLevel.Error);
rethrow;
}
@ -1796,7 +1798,7 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
// Use new index to derive a new change address
final newChangeAddress = await _generateAddressForChain(
1, newChangeIndex, DerivePathType.bip44);
1, newChangeIndex, DerivePathTypeExt.primaryFor(coin));
final existing = await db
.getAddresses(walletId)
@ -1815,12 +1817,12 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
}
} on SocketException catch (se, s) {
Logging.instance.log(
"SocketException caught in _checkReceivingAddressForTransactions(${DerivePathType.bip44}): $se\n$s",
"SocketException caught in _checkReceivingAddressForTransactions(${DerivePathTypeExt.primaryFor(coin)}): $se\n$s",
level: LogLevel.Error);
return;
} catch (e, s) {
Logging.instance.log(
"Exception rethrown from _checkReceivingAddressForTransactions(${DerivePathType.bip44}): $e\n$s",
"Exception rethrown from _checkReceivingAddressForTransactions(${DerivePathTypeExt.primaryFor(coin)}): $e\n$s",
level: LogLevel.Error);
rethrow;
}
@ -2346,7 +2348,7 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
utxoSigningData: utxoSigningData,
recipients: [
_recipientAddress,
await _getCurrentAddressForChain(1, DerivePathType.bip44),
await _getCurrentAddressForChain(1, DerivePathTypeExt.primaryFor(coin)),
],
satoshiAmounts: [
satoshiAmountToSend,
@ -2399,8 +2401,8 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
feeForTwoOutputs) {
// generate new change address if current change address has been used
await _checkChangeAddressForTransactions();
final String newChangeAddress =
await _getCurrentAddressForChain(1, DerivePathType.bip44);
final String newChangeAddress = await _getCurrentAddressForChain(
1, DerivePathTypeExt.primaryFor(coin));
int feeBeingPaid =
satoshisBeingUsed - satoshiAmountToSend - changeOutputSize;
@ -2611,6 +2613,8 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
case DerivePathType.bip49:
addressesP2SH.add(address);
break;
case DerivePathType.bip84:
throw UnsupportedError("bip84 not supported by BCH");
}
}
}
@ -2997,7 +3001,7 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
// Use new index to derive a new receiving address
final newReceivingAddress = await _generateAddressForChain(
0, newReceivingIndex, DerivePathType.bip44);
0, newReceivingIndex, DerivePathTypeExt.primaryFor(coin));
// Add that new receiving address
await db.putAddress(newReceivingAddress);

File diff suppressed because it is too large Load diff

View file

@ -14,16 +14,17 @@ import 'package:isar/isar.dart';
import 'package:stackwallet/db/main_db.dart';
import 'package:stackwallet/electrumx_rpc/cached_electrumx.dart';
import 'package:stackwallet/electrumx_rpc/electrumx.dart';
import 'package:stackwallet/exceptions/electrumx/no_such_transaction.dart';
import 'package:stackwallet/models/balance.dart';
import 'package:stackwallet/models/isar/models/isar_models.dart' as isar_models;
import 'package:stackwallet/models/paymint/fee_object_model.dart';
import 'package:stackwallet/services/coins/coin_paynym_extension.dart';
import 'package:stackwallet/services/coins/coin_service.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';
import 'package:stackwallet/services/event_bus/events/global/updated_in_background_event.dart';
import 'package:stackwallet/services/event_bus/events/global/wallet_sync_status_changed_event.dart';
import 'package:stackwallet/services/event_bus/global_event_bus.dart';
import 'package:stackwallet/services/mixins/electrum_x_parsing.dart';
import 'package:stackwallet/services/mixins/wallet_cache.dart';
import 'package:stackwallet/services/mixins/wallet_db.dart';
import 'package:stackwallet/services/node_service.dart';
@ -34,6 +35,7 @@ import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/default_nodes.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart';
import 'package:stackwallet/utilities/enums/fee_rate_type_enum.dart';
import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart';
import 'package:stackwallet/utilities/format.dart';
@ -50,8 +52,6 @@ const String GENESIS_HASH_MAINNET =
const String GENESIS_HASH_TESTNET =
"bb0a78264637406b6360aad926284d544d7049f45189db5664f3c4d07350559e";
enum DerivePathType { bip44 }
bip32.BIP32 getBip32Node(int chain, int index, String mnemonic,
NetworkType network, DerivePathType derivePathType) {
final root = getBip32Root(mnemonic, network);
@ -90,7 +90,7 @@ bip32.BIP32 getBip32NodeFromRoot(
case DerivePathType.bip44:
return root.derivePath("m/44'/$coinType'/0'/$chain/$index");
default:
throw Exception("DerivePathType must not be null.");
throw Exception("Unsupported DerivePathType");
}
}
@ -125,7 +125,8 @@ bip32.BIP32 getBip32RootWrapper(Tuple2<String, NetworkType> args) {
return getBip32Root(args.item1, args.item2);
}
class DogecoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
class DogecoinWallet extends CoinServiceAPI
with WalletCache, WalletDB, ElectrumXParsing {
static const integrationTestFlag =
bool.fromEnvironment("IS_INTEGRATION_TEST");
final _prefs = Prefs.instance;
@ -150,8 +151,16 @@ class DogecoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
Future<List<isar_models.UTXO>> get utxos => db.getUTXOs(walletId).findAll();
@override
Future<List<isar_models.Transaction>> get transactions =>
db.getTransactions(walletId).sortByTimestampDesc().findAll();
Future<List<isar_models.Transaction>> get transactions => db
.getTransactions(walletId)
.filter()
.not()
.group((q) => q
.subTypeEqualTo(isar_models.TransactionSubType.bip47Notification)
.and()
.typeEqualTo(isar_models.TransactionType.incoming))
.sortByTimestampDesc()
.findAll();
@override
Coin get coin => _coin;
@ -168,7 +177,7 @@ class DogecoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
.subTypeEqualTo(isar_models.AddressSubType.receiving)
.sortByDerivationIndexDesc()
.findFirst()) ??
await _generateAddressForChain(0, 0, DerivePathType.bip44);
await _generateAddressForChain(0, 0, DerivePathTypeExt.primaryFor(coin));
// @override
Future<String> get currentChangeAddress async =>
@ -182,7 +191,7 @@ class DogecoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
.subTypeEqualTo(isar_models.AddressSubType.change)
.sortByDerivationIndexDesc()
.findFirst()) ??
await _generateAddressForChain(1, 0, DerivePathType.bip44);
await _generateAddressForChain(1, 0, DerivePathTypeExt.primaryFor(coin));
@override
Future<void> exit() async {
@ -529,6 +538,19 @@ class DogecoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
...p2pkhChangeAddressArray,
]);
// paynym stuff
// // generate to ensure notification address is in db before refreshing transactions
// await getMyNotificationAddress(DerivePathType.bip44);
//
// // refresh transactions to pick up any received notification transactions
// await _refreshTransactions();
//
// // restore paynym transactions
// await restoreAllHistory(
// maxUnusedAddressGap: maxUnusedAddressGap,
// maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck,
// );
await _updateUTXOs();
await Future.wait([
@ -596,6 +618,13 @@ class DogecoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
}
}
return needsRefresh;
} on NoSuchTransactionException catch (e) {
// TODO: move direct transactions elsewhere
await db.isar.writeTxn(() async {
await db.isar.transactions.deleteByTxidWalletId(e.txid, walletId);
});
await txTracker.deleteTransaction(e.txid);
return true;
} catch (e, s) {
Logging.instance.log(
"Exception caught in refreshIfThereIsNewData: $e\n$s",
@ -761,6 +790,9 @@ class DogecoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
GlobalEventBus.instance.fire(RefreshPercentChangedEvent(0.3, walletId));
await _checkCurrentReceivingAddressesForTransactions();
// paynym stuff
// await checkAllCurrentReceivingPaynymAddressesForTransactions();
final fetchFuture = _refreshTransactions();
final utxosRefreshFuture = _updateUTXOs();
GlobalEventBus.instance
@ -1099,6 +1131,27 @@ class DogecoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
_secureStore = secureStore;
initCache(walletId, coin);
initWalletDB(mockableOverride: mockableOverride);
// paynym stuff
// initPaynymWalletInterface(
// walletId: walletId,
// walletName: walletName,
// network: network,
// coin: coin,
// db: db,
// electrumXClient: electrumXClient,
// getMnemonic: () => mnemonic,
// getChainHeight: () => chainHeight,
// getCurrentChangeAddress: () => currentChangeAddress,
// estimateTxFee: estimateTxFee,
// prepareSend: prepareSend,
// getTxCount: getTxCount,
// fetchBuildTxData: fetchBuildTxData,
// refresh: refresh,
// checkChangeAddressForTransactions: checkChangeAddressForTransactions,
// addDerivation: addDerivation,
// addDerivations: addDerivations,
// );
}
@override
@ -1161,10 +1214,8 @@ class DogecoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
.not()
.typeEqualTo(isar_models.AddressType.nonWallet)
.and()
.group((q) => q
.subTypeEqualTo(isar_models.AddressSubType.receiving)
.or()
.subTypeEqualTo(isar_models.AddressSubType.change))
.not()
.subTypeEqualTo(isar_models.AddressSubType.nonWallet)
.findAll();
return allAddresses;
}
@ -1274,9 +1325,8 @@ class DogecoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
case DerivePathType.bip44:
address = P2PKH(data: data, network: network).data.address!;
break;
// default:
// // should never hit this due to all enum cases handled
// return null;
default:
throw Exception("Unsupported DerivePathType");
}
// add generated address & info to derivations
@ -1321,6 +1371,8 @@ class DogecoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
.sortByDerivationIndexDesc()
.findFirst();
break;
default:
throw Exception("Unsupported DerivePathType");
}
return address!.value;
}
@ -1333,6 +1385,8 @@ class DogecoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
case DerivePathType.bip44:
key = "${walletId}_${chainId}DerivationsP2PKH";
break;
default:
throw Exception("Unsupported DerivePathType");
}
return key;
}
@ -1503,15 +1557,34 @@ class DogecoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
coin: coin,
);
// todo check here if we should mark as blocked
// fetch stored tx to see if paynym notification tx and block utxo
final storedTx = await db.getTransaction(
walletId,
fetchedUtxoList[i][j]["tx_hash"] as String,
);
bool shouldBlock = false;
String? blockReason;
if (storedTx?.subType ==
isar_models.TransactionSubType.bip47Notification &&
storedTx?.type == isar_models.TransactionType.incoming) {
// probably safe to assume this is an incoming tx as it is a utxo
// belonging to this wallet. The extra check may be redundant but
// just in case...
shouldBlock = true;
blockReason = "Incoming paynym notification transaction.";
}
final utxo = isar_models.UTXO(
walletId: walletId,
txid: txn["txid"] as String,
vout: fetchedUtxoList[i][j]["tx_pos"] as int,
value: fetchedUtxoList[i][j]["value"] as int,
name: "",
isBlocked: false,
blockedReason: null,
isBlocked: shouldBlock,
blockedReason: blockReason,
isCoinbase: txn["is_coinbase"] as bool? ?? false,
blockHash: txn["blockhash"] as String?,
blockHeight: fetchedUtxoList[i][j]["height"] as int?,
@ -1656,7 +1729,7 @@ class DogecoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
// Use new index to derive a new receiving address
final newReceivingAddress = await _generateAddressForChain(
0, newReceivingIndex, DerivePathType.bip44);
0, newReceivingIndex, DerivePathTypeExt.primaryFor(coin));
final existing = await db
.getAddresses(walletId)
@ -1675,12 +1748,12 @@ class DogecoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
}
} on SocketException catch (se, s) {
Logging.instance.log(
"SocketException caught in _checkReceivingAddressForTransactions($DerivePathType.bip44): $se\n$s",
"SocketException caught in _checkReceivingAddressForTransactions(${DerivePathTypeExt.primaryFor(coin)}): $se\n$s",
level: LogLevel.Error);
return;
} catch (e, s) {
Logging.instance.log(
"Exception rethrown from _checkReceivingAddressForTransactions($DerivePathType.bip44): $e\n$s",
"Exception rethrown from _checkReceivingAddressForTransactions(${DerivePathTypeExt.primaryFor(coin)}): $e\n$s",
level: LogLevel.Error);
rethrow;
}
@ -1700,7 +1773,7 @@ class DogecoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
// Use new index to derive a new change address
final newChangeAddress = await _generateAddressForChain(
1, newChangeIndex, DerivePathType.bip44);
1, newChangeIndex, DerivePathTypeExt.primaryFor(coin));
final existing = await db
.getAddresses(walletId)
@ -1719,7 +1792,7 @@ class DogecoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
}
} catch (e, s) {
Logging.instance.log(
"Exception rethrown from _checkChangeAddressForTransactions(${DerivePathType.bip44}): $e\n$s",
"Exception rethrown from _checkChangeAddressForTransactions(${DerivePathTypeExt.primaryFor(coin)}): $e\n$s",
level: LogLevel.Error);
rethrow;
}
@ -2088,7 +2161,7 @@ class DogecoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
utxoSigningData: utxoSigningData,
recipients: [
_recipientAddress,
await _getCurrentAddressForChain(1, DerivePathType.bip44),
await _getCurrentAddressForChain(1, DerivePathTypeExt.primaryFor(coin)),
],
satoshiAmounts: [
satoshiAmountToSend,
@ -2141,8 +2214,8 @@ class DogecoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
feeForTwoOutputs) {
// generate new change address if current change address has been used
await checkChangeAddressForTransactions();
final String newChangeAddress =
await _getCurrentAddressForChain(1, DerivePathType.bip44);
final String newChangeAddress = await _getCurrentAddressForChain(
1, DerivePathTypeExt.primaryFor(coin));
int feeBeingPaid =
satoshisBeingUsed - satoshiAmountToSend - changeOutputSize;
@ -2340,6 +2413,8 @@ class DogecoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
case DerivePathType.bip44:
addressesP2PKH.add(address);
break;
default:
throw Exception("Unsupported DerivePathType");
}
}
}
@ -2757,7 +2832,7 @@ class DogecoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
// Use new index to derive a new receiving address
final newReceivingAddress = await _generateAddressForChain(
0, newReceivingIndex, DerivePathType.bip44);
0, newReceivingIndex, DerivePathTypeExt.primaryFor(coin));
// Add that new receiving address
await db.putAddress(newReceivingAddress);
@ -2775,7 +2850,7 @@ class DogecoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
// Dogecoin Network
final dogecoin = NetworkType(
messagePrefix: '\x18Dogecoin Signed Message:\n',
bech32: 'bc',
// bech32: 'bc',
bip32: Bip32Type(public: 0x02facafd, private: 0x02fac398),
pubKeyHash: 0x1e,
scriptHash: 0x16,
@ -2783,7 +2858,7 @@ final dogecoin = NetworkType(
final dogecointestnet = NetworkType(
messagePrefix: '\x18Dogecoin Signed Message:\n',
bech32: 'tb',
// bech32: 'tb',
bip32: Bip32Type(public: 0x043587cf, private: 0x04358394),
pubKeyHash: 0x71,
scriptHash: 0xc4,

View file

@ -17,13 +17,13 @@ import 'package:stackwallet/electrumx_rpc/electrumx.dart';
import 'package:stackwallet/models/balance.dart';
import 'package:stackwallet/models/isar/models/isar_models.dart' as isar_models;
import 'package:stackwallet/models/paymint/fee_object_model.dart';
import 'package:stackwallet/services/coins/coin_paynym_extension.dart';
import 'package:stackwallet/services/coins/coin_service.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';
import 'package:stackwallet/services/event_bus/events/global/updated_in_background_event.dart';
import 'package:stackwallet/services/event_bus/events/global/wallet_sync_status_changed_event.dart';
import 'package:stackwallet/services/event_bus/global_event_bus.dart';
import 'package:stackwallet/services/mixins/electrum_x_parsing.dart';
import 'package:stackwallet/services/mixins/wallet_cache.dart';
import 'package:stackwallet/services/mixins/wallet_db.dart';
import 'package:stackwallet/services/node_service.dart';
@ -33,6 +33,7 @@ import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/default_nodes.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart';
import 'package:stackwallet/utilities/enums/fee_rate_type_enum.dart';
import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart';
import 'package:stackwallet/utilities/format.dart';
@ -50,8 +51,6 @@ const String GENESIS_HASH_MAINNET =
const String GENESIS_HASH_TESTNET =
"4966625a4b2851d9fdee139e56211a0d88575f59ed816ff5e6a63deb4e3e29a0";
enum DerivePathType { bip44, bip49, bip84 }
bip32.BIP32 getBip32Node(
int chain,
int index,
@ -138,7 +137,8 @@ bip32.BIP32 getBip32RootWrapper(Tuple2<String, NetworkType> args) {
return getBip32Root(args.item1, args.item2);
}
class LitecoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
class LitecoinWallet extends CoinServiceAPI
with WalletCache, WalletDB, ElectrumXParsing {
static const integrationTestFlag =
bool.fromEnvironment("IS_INTEGRATION_TEST");
@ -193,7 +193,7 @@ class LitecoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
.subTypeEqualTo(isar_models.AddressSubType.receiving)
.sortByDerivationIndexDesc()
.findFirst()) ??
await _generateAddressForChain(0, 0, DerivePathType.bip84);
await _generateAddressForChain(0, 0, DerivePathTypeExt.primaryFor(coin));
Future<String> get currentChangeAddress async =>
(await _currentChangeAddress).value;
@ -206,7 +206,7 @@ class LitecoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
.subTypeEqualTo(isar_models.AddressSubType.change)
.sortByDerivationIndexDesc()
.findFirst()) ??
await _generateAddressForChain(1, 0, DerivePathType.bip84);
await _generateAddressForChain(1, 0, DerivePathTypeExt.primaryFor(coin));
@override
Future<void> exit() async {
@ -1891,7 +1891,7 @@ class LitecoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
// Use new index to derive a new receiving address
final newReceivingAddress = await _generateAddressForChain(
0, newReceivingIndex, DerivePathType.bip84);
0, newReceivingIndex, DerivePathTypeExt.primaryFor(coin));
final existing = await db
.getAddresses(walletId)
@ -1910,7 +1910,7 @@ class LitecoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
}
} catch (e, s) {
Logging.instance.log(
"Exception rethrown from _checkReceivingAddressForTransactions(${DerivePathType.bip84}): $e\n$s",
"Exception rethrown from _checkReceivingAddressForTransactions(${DerivePathTypeExt.primaryFor(coin)}): $e\n$s",
level: LogLevel.Error);
rethrow;
}
@ -1930,7 +1930,7 @@ class LitecoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
// Use new index to derive a new change address
final newChangeAddress = await _generateAddressForChain(
1, newChangeIndex, DerivePathType.bip84);
1, newChangeIndex, DerivePathTypeExt.primaryFor(coin));
final existing = await db
.getAddresses(walletId)
@ -1949,12 +1949,12 @@ class LitecoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
}
} on SocketException catch (se, s) {
Logging.instance.log(
"SocketException caught in _checkReceivingAddressForTransactions(${DerivePathType.bip84}): $se\n$s",
"SocketException caught in _checkReceivingAddressForTransactions(${DerivePathTypeExt.primaryFor(coin)}): $se\n$s",
level: LogLevel.Error);
return;
} catch (e, s) {
Logging.instance.log(
"Exception rethrown from _checkReceivingAddressForTransactions(${DerivePathType.bip84}): $e\n$s",
"Exception rethrown from _checkReceivingAddressForTransactions(${DerivePathTypeExt.primaryFor(coin)}): $e\n$s",
level: LogLevel.Error);
rethrow;
}
@ -2349,7 +2349,7 @@ class LitecoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
utxoSigningData: utxoSigningData,
recipients: [
_recipientAddress,
await _getCurrentAddressForChain(1, DerivePathType.bip84),
await _getCurrentAddressForChain(1, DerivePathTypeExt.primaryFor(coin)),
],
satoshiAmounts: [
satoshiAmountToSend,
@ -2388,8 +2388,8 @@ class LitecoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
feeForTwoOutputs) {
// generate new change address if current change address has been used
await _checkChangeAddressForTransactions();
final String newChangeAddress =
await _getCurrentAddressForChain(1, DerivePathType.bip84);
final String newChangeAddress = await _getCurrentAddressForChain(
1, DerivePathTypeExt.primaryFor(coin));
int feeBeingPaid =
satoshisBeingUsed - satoshiAmountToSend - changeOutputSize;
@ -3345,7 +3345,7 @@ class LitecoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
// Use new index to derive a new receiving address
final newReceivingAddress = await _generateAddressForChain(
0, newReceivingIndex, DerivePathType.bip84);
0, newReceivingIndex, DerivePathTypeExt.primaryFor(coin));
// Add that new receiving address
await db.putAddress(newReceivingAddress);

View file

@ -9,6 +9,7 @@ import 'package:stackwallet/services/coins/coin_service.dart';
import 'package:stackwallet/services/event_bus/events/global/node_connection_status_changed_event.dart';
import 'package:stackwallet/services/event_bus/events/global/updated_in_background_event.dart';
import 'package:stackwallet/services/event_bus/global_event_bus.dart';
import 'package:stackwallet/services/mixins/paynym_wallet_interface.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/logger.dart';
@ -214,4 +215,6 @@ class Manager with ChangeNotifier {
}
int get currentHeight => _currentWallet.storedChainHeight;
bool get hasPaynymSupport => _currentWallet is PaynymWalletInterface;
}

View file

@ -17,13 +17,13 @@ import 'package:stackwallet/electrumx_rpc/electrumx.dart';
import 'package:stackwallet/models/balance.dart';
import 'package:stackwallet/models/isar/models/isar_models.dart' as isar_models;
import 'package:stackwallet/models/paymint/fee_object_model.dart';
import 'package:stackwallet/services/coins/coin_paynym_extension.dart';
import 'package:stackwallet/services/coins/coin_service.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';
import 'package:stackwallet/services/event_bus/events/global/updated_in_background_event.dart';
import 'package:stackwallet/services/event_bus/events/global/wallet_sync_status_changed_event.dart';
import 'package:stackwallet/services/event_bus/global_event_bus.dart';
import 'package:stackwallet/services/mixins/electrum_x_parsing.dart';
import 'package:stackwallet/services/mixins/wallet_cache.dart';
import 'package:stackwallet/services/mixins/wallet_db.dart';
import 'package:stackwallet/services/node_service.dart';
@ -33,6 +33,7 @@ import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/default_nodes.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart';
import 'package:stackwallet/utilities/enums/fee_rate_type_enum.dart';
import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart';
import 'package:stackwallet/utilities/format.dart';
@ -50,8 +51,6 @@ const String GENESIS_HASH_MAINNET =
const String GENESIS_HASH_TESTNET =
"00000007199508e34a9ff81e6ec0c477a4cccff2a4767a8eee39c11db367b008";
enum DerivePathType { bip44, bip49, bip84 }
bip32.BIP32 getBip32Node(
int chain,
int index,
@ -135,7 +134,8 @@ bip32.BIP32 getBip32RootWrapper(Tuple2<String, NetworkType> args) {
return getBip32Root(args.item1, args.item2);
}
class NamecoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
class NamecoinWallet extends CoinServiceAPI
with WalletCache, WalletDB, ElectrumXParsing {
static const integrationTestFlag =
bool.fromEnvironment("IS_INTEGRATION_TEST");
@ -188,7 +188,7 @@ class NamecoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
.subTypeEqualTo(isar_models.AddressSubType.receiving)
.sortByDerivationIndexDesc()
.findFirst()) ??
await _generateAddressForChain(0, 0, DerivePathType.bip84);
await _generateAddressForChain(0, 0, DerivePathTypeExt.primaryFor(coin));
Future<String> get currentChangeAddress async =>
(await _currentChangeAddress).value;
@ -201,7 +201,7 @@ class NamecoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
.subTypeEqualTo(isar_models.AddressSubType.change)
.sortByDerivationIndexDesc()
.findFirst()) ??
await _generateAddressForChain(1, 0, DerivePathType.bip84);
await _generateAddressForChain(1, 0, DerivePathTypeExt.primaryFor(coin));
@override
Future<void> exit() async {
@ -1873,7 +1873,7 @@ class NamecoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
// Use new index to derive a new receiving address
final newReceivingAddress = await _generateAddressForChain(
0, newReceivingIndex, DerivePathType.bip84);
0, newReceivingIndex, DerivePathTypeExt.primaryFor(coin));
final existing = await db
.getAddresses(walletId)
@ -1892,7 +1892,7 @@ class NamecoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
}
} catch (e, s) {
Logging.instance.log(
"Exception rethrown from _checkReceivingAddressForTransactions(${DerivePathType.bip84}): $e\n$s",
"Exception rethrown from _checkReceivingAddressForTransactions(${DerivePathTypeExt.primaryFor(coin)}): $e\n$s",
level: LogLevel.Error);
rethrow;
}
@ -1912,7 +1912,7 @@ class NamecoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
// Use new index to derive a new change address
final newChangeAddress = await _generateAddressForChain(
1, newChangeIndex, DerivePathType.bip84);
1, newChangeIndex, DerivePathTypeExt.primaryFor(coin));
final existing = await db
.getAddresses(walletId)
@ -1932,12 +1932,12 @@ class NamecoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
}
} on SocketException catch (se, s) {
Logging.instance.log(
"SocketException caught in _checkReceivingAddressForTransactions(${DerivePathType.bip84}): $se\n$s",
"SocketException caught in _checkReceivingAddressForTransactions(${DerivePathTypeExt.primaryFor(coin)}): $se\n$s",
level: LogLevel.Error);
return;
} catch (e, s) {
Logging.instance.log(
"Exception rethrown from _checkReceivingAddressForTransactions(${DerivePathType.bip84}): $e\n$s",
"Exception rethrown from _checkReceivingAddressForTransactions(${DerivePathTypeExt.primaryFor(coin)}): $e\n$s",
level: LogLevel.Error);
rethrow;
}
@ -2336,7 +2336,7 @@ class NamecoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
utxoSigningData: utxoSigningData,
recipients: [
_recipientAddress,
await _getCurrentAddressForChain(1, DerivePathType.bip84),
await _getCurrentAddressForChain(1, DerivePathTypeExt.primaryFor(coin)),
],
satoshiAmounts: [
satoshiAmountToSend,
@ -2375,8 +2375,8 @@ class NamecoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
feeForTwoOutputs) {
// generate new change address if current change address has been used
await _checkChangeAddressForTransactions();
final String newChangeAddress =
await _getCurrentAddressForChain(1, DerivePathType.bip84);
final String newChangeAddress = await _getCurrentAddressForChain(
1, DerivePathTypeExt.primaryFor(coin));
int feeBeingPaid =
satoshisBeingUsed - satoshiAmountToSend - changeOutputSize;
@ -3336,7 +3336,7 @@ class NamecoinWallet extends CoinServiceAPI with WalletCache, WalletDB {
// Use new index to derive a new receiving address
final newReceivingAddress = await _generateAddressForChain(
0, newReceivingIndex, DerivePathType.bip84);
0, newReceivingIndex, DerivePathTypeExt.primaryFor(coin));
// Add that new receiving address
await db.putAddress(newReceivingAddress);

View file

@ -32,6 +32,7 @@ import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/default_nodes.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart';
import 'package:stackwallet/utilities/enums/fee_rate_type_enum.dart';
import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart';
import 'package:stackwallet/utilities/format.dart';
@ -48,8 +49,6 @@ const String GENESIS_HASH_MAINNET =
const String GENESIS_HASH_TESTNET =
"0000594ada5310b367443ee0afd4fa3d0bbd5850ea4e33cdc7d6a904a7ec7c90";
enum DerivePathType { bip44, bip84 }
bip32.BIP32 getBip32Node(
int chain,
int index,
@ -184,7 +183,7 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB {
.subTypeEqualTo(isar_models.AddressSubType.receiving)
.sortByDerivationIndexDesc()
.findFirst()) ??
await _generateAddressForChain(0, 0, DerivePathType.bip84);
await _generateAddressForChain(0, 0, DerivePathTypeExt.primaryFor(coin));
Future<String> get currentChangeAddress async =>
(await _currentChangeAddress).value;
@ -197,7 +196,7 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB {
.subTypeEqualTo(isar_models.AddressSubType.change)
.sortByDerivationIndexDesc()
.findFirst()) ??
await _generateAddressForChain(1, 0, DerivePathType.bip84);
await _generateAddressForChain(1, 0, DerivePathTypeExt.primaryFor(coin));
@override
Future<void> exit() async {
@ -1407,6 +1406,8 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB {
address = P2WPKH(network: _network, data: data).data.address!;
addrType = isar_models.AddressType.p2wpkh;
break;
default:
throw Exception("Unsupported DerivePathType");
}
// add generated address & info to derivations
@ -1450,6 +1451,8 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB {
case DerivePathType.bip84:
type = isar_models.AddressType.p2wpkh;
break;
default:
throw Exception("Unsupported DerivePathType");
}
address = await db
.getAddresses(walletId)
@ -1475,6 +1478,8 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB {
case DerivePathType.bip84:
key = "${walletId}_${chainId}DerivationsP2WPKH";
break;
default:
throw Exception("Unsupported DerivePathType");
}
return key;
}
@ -1761,7 +1766,7 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB {
// Use new index to derive a new receiving address
final newReceivingAddress = await _generateAddressForChain(
0, newReceivingIndex, DerivePathType.bip84);
0, newReceivingIndex, DerivePathTypeExt.primaryFor(coin));
final existing = await db
.getAddresses(walletId)
@ -1780,7 +1785,7 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB {
}
} catch (e, s) {
Logging.instance.log(
"Exception rethrown from _checkReceivingAddressForTransactions(${DerivePathType.bip84}): $e\n$s",
"Exception rethrown from _checkReceivingAddressForTransactions(${DerivePathTypeExt.primaryFor(coin)}): $e\n$s",
level: LogLevel.Error);
rethrow;
}
@ -1800,7 +1805,7 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB {
// Use new index to derive a new change address
final newChangeAddress = await _generateAddressForChain(
1, newChangeIndex, DerivePathType.bip84);
1, newChangeIndex, DerivePathTypeExt.primaryFor(coin));
final existing = await db
.getAddresses(walletId)
@ -1819,12 +1824,12 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB {
}
} on SocketException catch (se, s) {
Logging.instance.log(
"SocketException caught in _checkReceivingAddressForTransactions(${DerivePathType.bip84}): $se\n$s",
"SocketException caught in _checkReceivingAddressForTransactions(${DerivePathTypeExt.primaryFor(coin)}): $se\n$s",
level: LogLevel.Error);
return;
} catch (e, s) {
Logging.instance.log(
"Exception rethrown from _checkReceivingAddressForTransactions(${DerivePathType.bip84}): $e\n$s",
"Exception rethrown from _checkReceivingAddressForTransactions(${DerivePathTypeExt.primaryFor(coin)}): $e\n$s",
level: LogLevel.Error);
rethrow;
}
@ -2501,7 +2506,7 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB {
utxoSigningData: utxoSigningData,
recipients: [
_recipientAddress,
await _getCurrentAddressForChain(1, DerivePathType.bip84),
await _getCurrentAddressForChain(1, DerivePathTypeExt.primaryFor(coin)),
],
satoshiAmounts: [
satoshiAmountToSend,
@ -2540,8 +2545,8 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB {
feeForTwoOutputs) {
// generate new change address if current change address has been used
await _checkChangeAddressForTransactions();
final String newChangeAddress =
await _getCurrentAddressForChain(1, DerivePathType.bip84);
final String newChangeAddress = await _getCurrentAddressForChain(
1, DerivePathTypeExt.primaryFor(coin));
int feeBeingPaid =
satoshisBeingUsed - satoshiAmountToSend - changeOutputSize;
@ -2743,6 +2748,8 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB {
case DerivePathType.bip84:
addressesP2WPKH.add(address);
break;
default:
throw Exception("Unsupported DerivePathType");
}
}
}
@ -3328,7 +3335,7 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB {
// Use new index to derive a new receiving address
final newReceivingAddress = await _generateAddressForChain(
0, newReceivingIndex, DerivePathType.bip84);
0, newReceivingIndex, DerivePathTypeExt.primaryFor(coin));
// Add that new receiving address
await db.putAddress(newReceivingAddress);

View file

@ -0,0 +1,222 @@
import 'package:bip47/src/util.dart';
import 'package:decimal/decimal.dart';
import 'package:stackwallet/models/isar/models/isar_models.dart';
import 'package:stackwallet/services/mixins/paynym_wallet_interface.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/format.dart';
import 'package:tuple/tuple.dart';
mixin ElectrumXParsing {
Future<Tuple4<Transaction, List<Output>, List<Input>, Address>>
parseTransaction(
Map<String, dynamic> txData,
dynamic electrumxClient,
List<Address> myAddresses,
Coin coin,
int minConfirms,
String walletId,
) async {
Set<String> receivingAddresses = myAddresses
.where((e) =>
e.subType == AddressSubType.receiving ||
e.subType == AddressSubType.paynymReceive ||
e.subType == AddressSubType.paynymNotification)
.map((e) => e.value)
.toSet();
Set<String> changeAddresses = myAddresses
.where((e) => e.subType == AddressSubType.change)
.map((e) => e.value)
.toSet();
Set<String> inputAddresses = {};
Set<String> outputAddresses = {};
int totalInputValue = 0;
int totalOutputValue = 0;
int amountSentFromWallet = 0;
int amountReceivedInWallet = 0;
int changeAmount = 0;
// parse inputs
for (final input in txData["vin"] as List) {
final prevTxid = input["txid"] as String;
final prevOut = input["vout"] as int;
// fetch input tx to get address
final inputTx = await electrumxClient.getTransaction(
txHash: prevTxid,
coin: coin,
);
for (final output in inputTx["vout"] as List) {
// check matching output
if (prevOut == output["n"]) {
// get value
final value = Format.decimalAmountToSatoshis(
Decimal.parse(output["value"].toString()),
coin,
);
// add value to total
totalInputValue += value;
// get input(prevOut) address
final address = output["scriptPubKey"]?["addresses"]?[0] as String? ??
output["scriptPubKey"]?["address"] as String?;
if (address != null) {
inputAddresses.add(address);
// if input was from my wallet, add value to amount sent
if (receivingAddresses.contains(address) ||
changeAddresses.contains(address)) {
amountSentFromWallet += value;
}
}
}
}
}
// parse outputs
for (final output in txData["vout"] as List) {
// get value
final value = Format.decimalAmountToSatoshis(
Decimal.parse(output["value"].toString()),
coin,
);
// add value to total
totalOutputValue += value;
// get output address
final address = output["scriptPubKey"]?["addresses"]?[0] as String? ??
output["scriptPubKey"]?["address"] as String?;
if (address != null) {
outputAddresses.add(address);
// if output was to my wallet, add value to amount received
if (receivingAddresses.contains(address)) {
amountReceivedInWallet += value;
} else if (changeAddresses.contains(address)) {
changeAmount += value;
}
}
}
final mySentFromAddresses = [
...receivingAddresses.intersection(inputAddresses),
...changeAddresses.intersection(inputAddresses)
];
final myReceivedOnAddresses =
receivingAddresses.intersection(outputAddresses);
final myChangeReceivedOnAddresses =
changeAddresses.intersection(outputAddresses);
final fee = totalInputValue - totalOutputValue;
// this is the address initially used to fetch the txid
Address transactionAddress = txData["address"] as Address;
TransactionType type;
int amount;
if (mySentFromAddresses.isNotEmpty && myReceivedOnAddresses.isNotEmpty) {
// tx is sent to self
type = TransactionType.sentToSelf;
// should be 0
amount =
amountSentFromWallet - amountReceivedInWallet - fee - changeAmount;
} else if (mySentFromAddresses.isNotEmpty) {
// outgoing tx
type = TransactionType.outgoing;
amount = amountSentFromWallet - changeAmount - fee;
final possible =
outputAddresses.difference(myChangeReceivedOnAddresses).first;
if (transactionAddress.value != possible) {
transactionAddress = Address(
walletId: walletId,
value: possible,
derivationIndex: -1,
subType: AddressSubType.nonWallet,
type: AddressType.nonWallet,
publicKey: [],
);
}
} else {
// incoming tx
type = TransactionType.incoming;
amount = amountReceivedInWallet;
}
List<Output> outs = [];
List<Input> ins = [];
for (final json in txData["vin"] as List) {
bool isCoinBase = json['coinbase'] != null;
final input = Input(
walletId: walletId,
txid: json['txid'] as String,
vout: json['vout'] as int? ?? -1,
scriptSig: json['scriptSig']?['hex'] as String?,
scriptSigAsm: json['scriptSig']?['asm'] as String?,
isCoinbase: isCoinBase ? isCoinBase : json['is_coinbase'] as bool?,
sequence: json['sequence'] as int?,
innerRedeemScriptAsm: json['innerRedeemscriptAsm'] as String?,
);
ins.add(input);
}
for (final json in txData["vout"] as List) {
final output = Output(
walletId: walletId,
scriptPubKey: json['scriptPubKey']?['hex'] as String?,
scriptPubKeyAsm: json['scriptPubKey']?['asm'] as String?,
scriptPubKeyType: json['scriptPubKey']?['type'] as String?,
scriptPubKeyAddress:
json["scriptPubKey"]?["addresses"]?[0] as String? ??
json['scriptPubKey']?['type'] as String? ??
"",
value: Format.decimalAmountToSatoshis(
Decimal.parse(json["value"].toString()),
coin,
),
);
outs.add(output);
}
TransactionSubType txSubType = TransactionSubType.none;
if (this is PaynymWalletInterface && outs.length > 1 && ins.isNotEmpty) {
List<String>? scriptChunks = outs[1].scriptPubKeyAsm?.split(" ");
if (scriptChunks?.length == 2 && scriptChunks?[0] == "OP_RETURN") {
final blindedPaymentCode = scriptChunks![1];
final bytes = blindedPaymentCode.fromHex;
// https://en.bitcoin.it/wiki/BIP_0047#Sending
if (bytes.length == 80 && bytes.first == 1) {
txSubType = TransactionSubType.bip47Notification;
}
}
}
final tx = Transaction(
walletId: walletId,
txid: txData["txid"] as String,
timestamp: txData["blocktime"] as int? ??
(DateTime.now().millisecondsSinceEpoch ~/ 1000),
type: type,
subType: txSubType,
amount: amount,
fee: fee,
height: txData["height"] as int?,
isCancelled: false,
isLelantus: false,
slateId: null,
otherData: null,
);
return Tuple4(tx, outs, ins, transactionAddress);
}
}

File diff suppressed because it is too large Load diff

View file

@ -2,6 +2,7 @@ import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:stackwallet/electrumx_rpc/electrumx.dart';
import 'package:stackwallet/exceptions/electrumx/no_such_transaction.dart';
import 'package:stackwallet/hive/db.dart';
import 'package:stackwallet/models/exchange/response_objects/trade.dart';
import 'package:stackwallet/models/notification_model.dart';
@ -169,12 +170,14 @@ class NotificationsService extends ChangeNotifier {
}
// replaces the current notification with the updated one
add(updatedNotification, true);
await add(updatedNotification, true);
}
} else {
// TODO: check non electrumx coins
}
}
} on NoSuchTransactionException catch (e, s) {
await _deleteWatchedTxNotification(notification);
} catch (e, s) {
Logging.instance.log("$e $s", level: LogLevel.Error);
}

View file

@ -54,4 +54,25 @@ class TransactionNotificationTracker {
key: "notifiedConfirmedTransactions",
value: notifiedConfirmedTransactions);
}
Future<void> deleteTransaction(String txid) async {
final notifiedPendingTransactions = DB.instance.get<dynamic>(
boxName: walletId, key: "notifiedPendingTransactions") as Map? ??
{};
final notifiedConfirmedTransactions = DB.instance.get<dynamic>(
boxName: walletId, key: "notifiedConfirmedTransactions") as Map? ??
{};
notifiedPendingTransactions.remove(txid);
notifiedConfirmedTransactions.remove(txid);
await DB.instance.put<dynamic>(
boxName: walletId,
key: "notifiedConfirmedTransactions",
value: notifiedConfirmedTransactions);
await DB.instance.put<dynamic>(
boxName: walletId,
key: "notifiedPendingTransactions",
value: notifiedPendingTransactions);
}
}

View file

@ -0,0 +1,32 @@
import 'package:bip32/bip32.dart' as bip32;
import 'package:bip39/bip39.dart' as bip39;
import 'package:bitcoindart/bitcoindart.dart';
import 'package:flutter/foundation.dart';
import 'package:tuple/tuple.dart';
abstract class Bip32Utils {
static bip32.BIP32 getBip32RootSync(String mnemonic, NetworkType network) {
final seed = bip39.mnemonicToSeed(mnemonic);
final networkType = bip32.NetworkType(
wif: network.wif,
bip32: bip32.Bip32Type(
public: network.bip32.public,
private: network.bip32.private,
),
);
final root = bip32.BIP32.fromSeed(seed, networkType);
return root;
}
static Future<bip32.BIP32> getBip32Root(
String mnemonic, NetworkType network) async {
final root = await compute(_getBip32RootWrapper, Tuple2(mnemonic, network));
return root;
}
/// wrapper for compute()
static bip32.BIP32 _getBip32RootWrapper(Tuple2<String, NetworkType> args) {
return getBip32RootSync(args.item1, args.item2);
}
}

View file

@ -171,30 +171,6 @@ extension CoinExt on Coin {
}
}
bool get hasPaynymSupport {
switch (this) {
case Coin.bitcoin:
case Coin.litecoin:
case Coin.bitcoincash:
case Coin.firo:
case Coin.namecoin:
case Coin.particl:
case Coin.bitcoinTestNet:
case Coin.litecoinTestNet:
case Coin.bitcoincashTestnet:
case Coin.firoTestNet:
case Coin.epicCash:
case Coin.monero:
case Coin.wownero:
return false;
case Coin.dogecoin:
case Coin.dogecoinTestNet:
// return true;
return false;
}
}
bool get hasBuySupport {
switch (this) {
case Coin.bitcoin:

View file

@ -0,0 +1,35 @@
import 'package:stackwallet/utilities/enums/coin_enum.dart';
enum DerivePathType {
bip44,
bip49,
bip84,
}
extension DerivePathTypeExt on DerivePathType {
static DerivePathType primaryFor(Coin coin) {
switch (coin) {
case Coin.bitcoincash:
case Coin.bitcoincashTestnet:
case Coin.dogecoin:
case Coin.dogecoinTestNet:
case Coin.firo:
case Coin.firoTestNet:
return DerivePathType.bip44;
case Coin.bitcoin:
case Coin.bitcoinTestNet:
case Coin.litecoin:
case Coin.litecoinTestNet:
case Coin.namecoin:
case Coin.particl:
return DerivePathType.bip84;
case Coin.epicCash:
case Coin.monero:
case Coin.wownero:
throw UnsupportedError(
"$coin does not use bitcoin style derivation paths");
}
}
}

View file

@ -1,12 +1,12 @@
abstract class FeaturedPaynyms {
// TODO: replace with actual values
static const String samouraiWalletDevFund =
"PM8TJYkuSdYXJnwDBq8ChfinfXv3srxhQrx3eoEwbSw51wMjdo9JJ2DsycwT3gt3zHQ7cV1grvabMmmf1Btj6fY7tgkgSz9B8MZuR3kjYfgMLMURJCXN";
// TODO: replace with actual value
// static const String samouraiWalletDevFund =
// "PM8TJYkuSdYXJnwDBq8ChfinfXv3srxhQrx3eoEwbSw51wMjdo9JJ2DsycwT3gt3zHQ7cV1grvabMmmf1Btj6fY7tgkgSz9B8MZuR3kjYfgMLMURJCXN";
static const String stackWallet =
"PM8TJYkuSdYXJnwDBq8ChfinfXv3srxhQrx3eoEwbSw51wMjdo9JJ2DsycwT3gt3zHQ7cV1grvabMmmf1Btj6fY7tgkgSz9B8MZuR3kjYfgMLMURJCXN";
"PM8TJPdEeH3A77h4xJYQeXPWix2W5yAJrzVQ8ggET1n92utnc57FXCoH94Z2wUSJNfGwkX1kNDTCQLkHecVsjQHGkDE8MUyWE4xWJcc1EDDYCeSSBfLL";
static Map<String, String> get featured => {
"Stack Wallet": stackWallet,
"Samourai Wallet Dev Fund": samouraiWalletDevFund,
// "Samourai Wallet Dev Fund": samouraiWalletDevFund,
};
}

View file

@ -46,6 +46,8 @@ abstract class SecureStorageInterface {
MacOsOptions? mOptions,
WindowsOptions? wOptions,
});
Future<List<String>> get keys;
}
class DesktopSecureStore {
@ -110,6 +112,10 @@ class DesktopSecureStore {
await isar.encryptedStringValues.deleteByKey(key);
});
}
Future<List<String>> get keys async {
return await isar.encryptedStringValues.where().keyProperty().findAll();
}
}
/// all *Options params ignored on desktop
@ -229,6 +235,15 @@ class SecureStorageWrapper implements SecureStorageInterface {
);
}
}
@override
Future<List<String>> get keys async {
if (_isDesktop) {
return (_store as DesktopSecureStore).keys;
} else {
return (await (_store as FlutterSecureStorage).readAll()).keys.toList();
}
}
}
// Mock class for testing purposes
@ -305,4 +320,7 @@ class FakeSecureStorage implements SecureStorageInterface {
@override
dynamic get store => throw UnimplementedError();
@override
Future<List<String>> get keys => Future(() => _store.keys.toList());
}

View file

@ -9,9 +9,9 @@ import 'package:stackwallet/notifications/show_flush_bar.dart';
import 'package:stackwallet/providers/global/paynym_api_provider.dart';
import 'package:stackwallet/providers/global/wallets_provider.dart';
import 'package:stackwallet/providers/wallet/my_paynym_account_state_provider.dart';
import 'package:stackwallet/services/coins/coin_paynym_extension.dart';
import 'package:stackwallet/services/coins/dogecoin/dogecoin_wallet.dart';
import 'package:stackwallet/services/mixins/paynym_wallet_interface.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/widgets/desktop/primary_button.dart';
@ -58,16 +58,18 @@ class _PaynymFollowToggleButtonState
),
);
final wallet = ref
.read(walletsChangeNotifierProvider)
.getManager(widget.walletId)
.wallet as DogecoinWallet;
final manager =
ref.read(walletsChangeNotifierProvider).getManager(widget.walletId);
// get wallet to access paynym calls
final wallet = manager.wallet as PaynymWalletInterface;
final followedAccount = await ref
.read(paynymAPIProvider)
.nym(widget.paymentCodeStringToFollow, true);
final myPCode = await wallet.getPaymentCode();
final myPCode =
await wallet.getPaymentCode(DerivePathTypeExt.primaryFor(manager.coin));
PaynymResponse<String> token =
await ref.read(paynymAPIProvider).token(myPCode.toString());
@ -158,16 +160,17 @@ class _PaynymFollowToggleButtonState
),
);
final wallet = ref
.read(walletsChangeNotifierProvider)
.getManager(widget.walletId)
.wallet as DogecoinWallet;
final manager =
ref.read(walletsChangeNotifierProvider).getManager(widget.walletId);
final wallet = manager.wallet as PaynymWalletInterface;
final followedAccount = await ref
.read(paynymAPIProvider)
.nym(widget.paymentCodeStringToFollow, true);
final myPCode = await wallet.getPaymentCode();
final myPCode =
await wallet.getPaymentCode(DerivePathTypeExt.primaryFor(manager.coin));
PaynymResponse<String> token =
await ref.read(paynymAPIProvider).token(myPCode.toString());

View file

@ -100,8 +100,8 @@ packages:
dependency: "direct main"
description:
path: "."
ref: testing
resolved-ref: "8ed2f6245c71a4457ed4ffdd3a74e4bcb9f9d2d0"
ref: "87bb760be323228aed6ca7bd4532a709a4f10690"
resolved-ref: "87bb760be323228aed6ca7bd4532a709a4f10690"
url: "https://github.com/cypherstack/bip47.git"
source: git
version: "1.0.0"
@ -1408,8 +1408,8 @@ packages:
dependency: "direct main"
description:
path: "."
ref: "93e2687bcc10fc7258c7dab038c363fc9ff8ba5d"
resolved-ref: "93e2687bcc10fc7258c7dab038c363fc9ff8ba5d"
ref: e4b08d2b8965a5ae49bd57f598fa9011dd0c25e9
resolved-ref: e4b08d2b8965a5ae49bd57f598fa9011dd0c25e9
url: "https://github.com/cypherstack/stack_wallet_backup.git"
source: git
version: "0.0.1"

View file

@ -59,7 +59,7 @@ dependencies:
bip47:
git:
url: https://github.com/cypherstack/bip47.git
ref: testing
ref: 87bb760be323228aed6ca7bd4532a709a4f10690
# Utility plugins
# provider: ^6.0.1

File diff suppressed because it is too large Load diff

View file

@ -363,6 +363,11 @@ class MockManager extends _i1.Mock implements _i11.Manager {
returnValue: 0,
) as int);
@override
bool get hasPaynymSupport => (super.noSuchMethod(
Invocation.getter(#hasPaynymSupport),
returnValue: false,
) as bool);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,

View file

@ -324,6 +324,11 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValue: 0,
) as int);
@override
bool get hasPaynymSupport => (super.noSuchMethod(
Invocation.getter(#hasPaynymSupport),
returnValue: false,
) as bool);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,

View file

@ -322,6 +322,11 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValue: 0,
) as int);
@override
bool get hasPaynymSupport => (super.noSuchMethod(
Invocation.getter(#hasPaynymSupport),
returnValue: false,
) as bool);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,

View file

@ -631,6 +631,11 @@ class MockManager extends _i1.Mock implements _i12.Manager {
returnValue: 0,
) as int);
@override
bool get hasPaynymSupport => (super.noSuchMethod(
Invocation.getter(#hasPaynymSupport),
returnValue: false,
) as bool);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,

View file

@ -418,6 +418,11 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValue: 0,
) as int);
@override
bool get hasPaynymSupport => (super.noSuchMethod(
Invocation.getter(#hasPaynymSupport),
returnValue: false,
) as bool);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,

View file

@ -418,6 +418,11 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValue: 0,
) as int);
@override
bool get hasPaynymSupport => (super.noSuchMethod(
Invocation.getter(#hasPaynymSupport),
returnValue: false,
) as bool);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,

View file

@ -418,6 +418,11 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValue: 0,
) as int);
@override
bool get hasPaynymSupport => (super.noSuchMethod(
Invocation.getter(#hasPaynymSupport),
returnValue: false,
) as bool);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,

View file

@ -193,6 +193,11 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValue: 0,
) as int);
@override
bool get hasPaynymSupport => (super.noSuchMethod(
Invocation.getter(#hasPaynymSupport),
returnValue: false,
) as bool);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,

View file

@ -416,6 +416,11 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValue: 0,
) as int);
@override
bool get hasPaynymSupport => (super.noSuchMethod(
Invocation.getter(#hasPaynymSupport),
returnValue: false,
) as bool);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,

View file

@ -631,6 +631,11 @@ class MockManager extends _i1.Mock implements _i12.Manager {
returnValue: 0,
) as int);
@override
bool get hasPaynymSupport => (super.noSuchMethod(
Invocation.getter(#hasPaynymSupport),
returnValue: false,
) as bool);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,

View file

@ -472,6 +472,11 @@ class MockManager extends _i1.Mock implements _i12.Manager {
returnValue: 0,
) as int);
@override
bool get hasPaynymSupport => (super.noSuchMethod(
Invocation.getter(#hasPaynymSupport),
returnValue: false,
) as bool);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,

View file

@ -193,6 +193,11 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValue: 0,
) as int);
@override
bool get hasPaynymSupport => (super.noSuchMethod(
Invocation.getter(#hasPaynymSupport),
returnValue: false,
) as bool);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,

View file

@ -193,6 +193,11 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValue: 0,
) as int);
@override
bool get hasPaynymSupport => (super.noSuchMethod(
Invocation.getter(#hasPaynymSupport),
returnValue: false,
) as bool);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,

View file

@ -408,6 +408,11 @@ class MockManager extends _i1.Mock implements _i11.Manager {
returnValue: 0,
) as int);
@override
bool get hasPaynymSupport => (super.noSuchMethod(
Invocation.getter(#hasPaynymSupport),
returnValue: false,
) as bool);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,

View file

@ -408,6 +408,11 @@ class MockManager extends _i1.Mock implements _i11.Manager {
returnValue: 0,
) as int);
@override
bool get hasPaynymSupport => (super.noSuchMethod(
Invocation.getter(#hasPaynymSupport),
returnValue: false,
) as bool);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,

View file

@ -193,6 +193,11 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValue: 0,
) as int);
@override
bool get hasPaynymSupport => (super.noSuchMethod(
Invocation.getter(#hasPaynymSupport),
returnValue: false,
) as bool);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,

View file

@ -193,6 +193,11 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValue: 0,
) as int);
@override
bool get hasPaynymSupport => (super.noSuchMethod(
Invocation.getter(#hasPaynymSupport),
returnValue: false,
) as bool);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,

View file

@ -416,6 +416,11 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValue: 0,
) as int);
@override
bool get hasPaynymSupport => (super.noSuchMethod(
Invocation.getter(#hasPaynymSupport),
returnValue: false,
) as bool);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,

View file

@ -673,6 +673,11 @@ class MockManager extends _i1.Mock implements _i15.Manager {
returnValue: 0,
) as int);
@override
bool get hasPaynymSupport => (super.noSuchMethod(
Invocation.getter(#hasPaynymSupport),
returnValue: false,
) as bool);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,

View file

@ -416,6 +416,11 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValue: 0,
) as int);
@override
bool get hasPaynymSupport => (super.noSuchMethod(
Invocation.getter(#hasPaynymSupport),
returnValue: false,
) as bool);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,

View file

@ -195,6 +195,11 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValue: 0,
) as int);
@override
bool get hasPaynymSupport => (super.noSuchMethod(
Invocation.getter(#hasPaynymSupport),
returnValue: false,
) as bool);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,

View file

@ -194,6 +194,11 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValue: 0,
) as int);
@override
bool get hasPaynymSupport => (super.noSuchMethod(
Invocation.getter(#hasPaynymSupport),
returnValue: false,
) as bool);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,

View file

@ -193,6 +193,11 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValue: 0,
) as int);
@override
bool get hasPaynymSupport => (super.noSuchMethod(
Invocation.getter(#hasPaynymSupport),
returnValue: false,
) as bool);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,

View file

@ -235,6 +235,11 @@ class MockManager extends _i1.Mock implements _i8.Manager {
returnValue: 0,
) as int);
@override
bool get hasPaynymSupport => (super.noSuchMethod(
Invocation.getter(#hasPaynymSupport),
returnValue: false,
) as bool);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,

View file

@ -195,6 +195,11 @@ class MockManager extends _i1.Mock implements _i5.Manager {
returnValue: 0,
) as int);
@override
bool get hasPaynymSupport => (super.noSuchMethod(
Invocation.getter(#hasPaynymSupport),
returnValue: false,
) as bool);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,

View file

@ -11,6 +11,7 @@ import 'package:stackwallet/models/paymint/fee_object_model.dart';
import 'package:stackwallet/services/coins/bitcoin/bitcoin_wallet.dart';
import 'package:stackwallet/services/transaction_notification_tracker.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart';
import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart';
import 'bitcoin_wallet_test.mocks.dart';
@ -39,12 +40,6 @@ void main() async {
});
});
test("bitcoin DerivePathType enum", () {
expect(DerivePathType.values.length, 3);
expect(DerivePathType.values.toString(),
"[DerivePathType.bip44, DerivePathType.bip49, DerivePathType.bip84]");
});
group("bip32 node/root", () {
test("getBip32Root", () {
final root = getBip32Root(TEST_MNEMONIC, bitcoin);

View file

@ -11,6 +11,7 @@ import 'package:stackwallet/models/paymint/fee_object_model.dart';
import 'package:stackwallet/services/coins/bitcoincash/bitcoincash_wallet.dart';
import 'package:stackwallet/services/transaction_notification_tracker.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart';
import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart';
import 'bitcoincash_wallet_test.mocks.dart';
@ -40,12 +41,6 @@ void main() async {
});
});
test("bitcoincash DerivePathType enum", () {
expect(DerivePathType.values.length, 2);
expect(DerivePathType.values.toString(),
"[DerivePathType.bip44, DerivePathType.bip49]");
});
group("bip32 node/root", () {
test("getBip32Root", () {
final root = getBip32Root(TEST_MNEMONIC, bitcoincash);

View file

@ -11,6 +11,7 @@ import 'package:stackwallet/models/paymint/fee_object_model.dart';
import 'package:stackwallet/services/coins/dogecoin/dogecoin_wallet.dart';
import 'package:stackwallet/services/transaction_notification_tracker.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart';
import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart';
import 'dogecoin_wallet_test.mocks.dart';
@ -39,11 +40,6 @@ void main() {
});
});
test("dogecoin DerivePathType enum", () {
expect(DerivePathType.values.length, 1);
expect(DerivePathType.values.toString(), "[DerivePathType.bip44]");
});
group("bip32 node/root", () {
test("getBip32Root", () {
final root = getBip32Root(TEST_MNEMONIC, dogecoin);

View file

@ -10,6 +10,7 @@ import 'package:stackwallet/models/paymint/fee_object_model.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';
import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart';
import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart';
import 'namecoin_wallet_test.mocks.dart';
@ -38,12 +39,6 @@ void main() {
});
});
test("namecoin DerivePathType enum", () {
expect(DerivePathType.values.length, 3);
expect(DerivePathType.values.toString(),
"[DerivePathType.bip44, DerivePathType.bip49, DerivePathType.bip84]");
});
group("bip32 node/root", () {
test("getBip32Root", () {
final root = getBip32Root(TEST_MNEMONIC, namecoin);

View file

@ -10,6 +10,7 @@ import 'package:stackwallet/models/paymint/fee_object_model.dart';
import 'package:stackwallet/services/coins/particl/particl_wallet.dart';
import 'package:stackwallet/services/transaction_notification_tracker.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart';
import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart';
import 'particl_wallet_test.mocks.dart';
@ -39,12 +40,6 @@ void main() {
});
});
test("particl DerivePathType enum", () {
expect(DerivePathType.values.length, 2);
expect(DerivePathType.values.toString(),
"[DerivePathType.bip44, DerivePathType.bip84]");
});
group("bip32 node/root", () {
test("getBip32Root", () {
final root = getBip32Root(TEST_MNEMONIC, particl);

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -538,6 +538,11 @@ class MockManager extends _i1.Mock implements _i6.Manager {
returnValue: 0,
) as int);
@override
bool get hasPaynymSupport => (super.noSuchMethod(
Invocation.getter(#hasPaynymSupport),
returnValue: false,
) as bool);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,

View file

@ -3,8 +3,8 @@
// Do not manually edit this file.
// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'dart:async' as _i15;
import 'dart:ui' as _i17;
import 'dart:async' as _i16;
import 'dart:ui' as _i18;
import 'package:flutter/foundation.dart' as _i4;
import 'package:flutter_riverpod/flutter_riverpod.dart' as _i5;
@ -13,18 +13,20 @@ import 'package:stackwallet/db/main_db.dart' as _i12;
import 'package:stackwallet/electrumx_rpc/cached_electrumx.dart' as _i10;
import 'package:stackwallet/electrumx_rpc/electrumx.dart' as _i9;
import 'package:stackwallet/models/balance.dart' as _i11;
import 'package:stackwallet/models/isar/models/isar_models.dart' as _i19;
import 'package:stackwallet/models/isar/models/isar_models.dart' as _i20;
import 'package:stackwallet/models/paymint/fee_object_model.dart' as _i8;
import 'package:stackwallet/services/coins/bitcoin/bitcoin_wallet.dart' as _i18;
import 'package:stackwallet/services/coins/bitcoin/bitcoin_wallet.dart' as _i19;
import 'package:stackwallet/services/coins/manager.dart' as _i6;
import 'package:stackwallet/services/locale_service.dart' as _i20;
import 'package:stackwallet/services/locale_service.dart' as _i22;
import 'package:stackwallet/services/node_service.dart' as _i3;
import 'package:stackwallet/services/transaction_notification_tracker.dart'
as _i7;
import 'package:stackwallet/services/wallets.dart' as _i13;
import 'package:stackwallet/services/wallets.dart' as _i14;
import 'package:stackwallet/services/wallets_service.dart' as _i2;
import 'package:stackwallet/utilities/enums/coin_enum.dart' as _i14;
import 'package:stackwallet/utilities/prefs.dart' as _i16;
import 'package:stackwallet/utilities/enums/coin_enum.dart' as _i15;
import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart' as _i21;
import 'package:stackwallet/utilities/prefs.dart' as _i17;
import 'package:tuple/tuple.dart' as _i13;
// ignore_for_file: type=lint
// ignore_for_file: avoid_redundant_argument_values
@ -151,10 +153,21 @@ class _FakeElectrumXNode_10 extends _i1.SmartFake implements _i9.ElectrumXNode {
);
}
class _FakeTuple4_11<T1, T2, T3, T4> extends _i1.SmartFake
implements _i13.Tuple4<T1, T2, T3, T4> {
_FakeTuple4_11(
Object parent,
Invocation parentInvocation,
) : super(
parent,
parentInvocation,
);
}
/// A class which mocks [Wallets].
///
/// See the documentation for Mockito's code generation for more information.
class MockWallets extends _i1.Mock implements _i13.Wallets {
class MockWallets extends _i1.Mock implements _i14.Wallets {
MockWallets() {
_i1.throwOnMissingStub(this);
}
@ -221,7 +234,7 @@ class MockWallets extends _i1.Mock implements _i13.Wallets {
returnValueForMissingStub: null,
);
@override
List<String> getWalletIdsFor({required _i14.Coin? coin}) =>
List<String> getWalletIdsFor({required _i15.Coin? coin}) =>
(super.noSuchMethod(
Invocation.method(
#getWalletIdsFor,
@ -231,18 +244,18 @@ class MockWallets extends _i1.Mock implements _i13.Wallets {
returnValue: <String>[],
) as List<String>);
@override
Map<_i14.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>>
Map<_i15.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>>
getManagerProvidersByCoin() => (super.noSuchMethod(
Invocation.method(
#getManagerProvidersByCoin,
[],
),
returnValue: <_i14.Coin,
returnValue: <_i15.Coin,
List<_i5.ChangeNotifierProvider<_i6.Manager>>>{},
) as Map<_i14.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>>);
) as Map<_i15.Coin, List<_i5.ChangeNotifierProvider<_i6.Manager>>>);
@override
List<_i5.ChangeNotifierProvider<_i6.Manager>> getManagerProvidersForCoin(
_i14.Coin? coin) =>
_i15.Coin? coin) =>
(super.noSuchMethod(
Invocation.method(
#getManagerProvidersForCoin,
@ -306,17 +319,17 @@ class MockWallets extends _i1.Mock implements _i13.Wallets {
returnValueForMissingStub: null,
);
@override
_i15.Future<void> load(_i16.Prefs? prefs) => (super.noSuchMethod(
_i16.Future<void> load(_i17.Prefs? prefs) => (super.noSuchMethod(
Invocation.method(
#load,
[prefs],
),
returnValue: _i15.Future<void>.value(),
returnValueForMissingStub: _i15.Future<void>.value(),
) as _i15.Future<void>);
returnValue: _i16.Future<void>.value(),
returnValueForMissingStub: _i16.Future<void>.value(),
) as _i16.Future<void>);
@override
_i15.Future<void> loadAfterStackRestore(
_i16.Prefs? prefs,
_i16.Future<void> loadAfterStackRestore(
_i17.Prefs? prefs,
List<_i6.Manager>? managers,
) =>
(super.noSuchMethod(
@ -327,11 +340,11 @@ class MockWallets extends _i1.Mock implements _i13.Wallets {
managers,
],
),
returnValue: _i15.Future<void>.value(),
returnValueForMissingStub: _i15.Future<void>.value(),
) as _i15.Future<void>);
returnValue: _i16.Future<void>.value(),
returnValueForMissingStub: _i16.Future<void>.value(),
) as _i16.Future<void>);
@override
void addListener(_i17.VoidCallback? listener) => super.noSuchMethod(
void addListener(_i18.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#addListener,
[listener],
@ -339,7 +352,7 @@ class MockWallets extends _i1.Mock implements _i13.Wallets {
returnValueForMissingStub: null,
);
@override
void removeListener(_i17.VoidCallback? listener) => super.noSuchMethod(
void removeListener(_i18.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#removeListener,
[listener],
@ -359,13 +372,13 @@ class MockWallets extends _i1.Mock implements _i13.Wallets {
/// A class which mocks [BitcoinWallet].
///
/// See the documentation for Mockito's code generation for more information.
class MockBitcoinWallet extends _i1.Mock implements _i18.BitcoinWallet {
class MockBitcoinWallet extends _i1.Mock implements _i19.BitcoinWallet {
MockBitcoinWallet() {
_i1.throwOnMissingStub(this);
}
@override
set timer(_i15.Timer? _timer) => super.noSuchMethod(
set timer(_i16.Timer? _timer) => super.noSuchMethod(
Invocation.setter(
#timer,
_timer,
@ -442,59 +455,59 @@ class MockBitcoinWallet extends _i1.Mock implements _i18.BitcoinWallet {
returnValue: false,
) as bool);
@override
_i14.Coin get coin => (super.noSuchMethod(
_i15.Coin get coin => (super.noSuchMethod(
Invocation.getter(#coin),
returnValue: _i14.Coin.bitcoin,
) as _i14.Coin);
returnValue: _i15.Coin.bitcoin,
) as _i15.Coin);
@override
_i15.Future<List<_i19.UTXO>> get utxos => (super.noSuchMethod(
_i16.Future<List<_i20.UTXO>> get utxos => (super.noSuchMethod(
Invocation.getter(#utxos),
returnValue: _i15.Future<List<_i19.UTXO>>.value(<_i19.UTXO>[]),
) as _i15.Future<List<_i19.UTXO>>);
returnValue: _i16.Future<List<_i20.UTXO>>.value(<_i20.UTXO>[]),
) as _i16.Future<List<_i20.UTXO>>);
@override
_i15.Future<List<_i19.Transaction>> get transactions => (super.noSuchMethod(
_i16.Future<List<_i20.Transaction>> get transactions => (super.noSuchMethod(
Invocation.getter(#transactions),
returnValue:
_i15.Future<List<_i19.Transaction>>.value(<_i19.Transaction>[]),
) as _i15.Future<List<_i19.Transaction>>);
_i16.Future<List<_i20.Transaction>>.value(<_i20.Transaction>[]),
) as _i16.Future<List<_i20.Transaction>>);
@override
_i15.Future<String> get currentReceivingAddress => (super.noSuchMethod(
_i16.Future<String> get currentReceivingAddress => (super.noSuchMethod(
Invocation.getter(#currentReceivingAddress),
returnValue: _i15.Future<String>.value(''),
) as _i15.Future<String>);
returnValue: _i16.Future<String>.value(''),
) as _i16.Future<String>);
@override
_i15.Future<String> get currentChangeAddress => (super.noSuchMethod(
_i16.Future<String> get currentChangeAddress => (super.noSuchMethod(
Invocation.getter(#currentChangeAddress),
returnValue: _i15.Future<String>.value(''),
) as _i15.Future<String>);
returnValue: _i16.Future<String>.value(''),
) as _i16.Future<String>);
@override
bool get hasCalledExit => (super.noSuchMethod(
Invocation.getter(#hasCalledExit),
returnValue: false,
) as bool);
@override
_i15.Future<_i8.FeeObject> get fees => (super.noSuchMethod(
_i16.Future<_i8.FeeObject> get fees => (super.noSuchMethod(
Invocation.getter(#fees),
returnValue: _i15.Future<_i8.FeeObject>.value(_FakeFeeObject_5(
returnValue: _i16.Future<_i8.FeeObject>.value(_FakeFeeObject_5(
this,
Invocation.getter(#fees),
)),
) as _i15.Future<_i8.FeeObject>);
) as _i16.Future<_i8.FeeObject>);
@override
_i15.Future<int> get maxFee => (super.noSuchMethod(
_i16.Future<int> get maxFee => (super.noSuchMethod(
Invocation.getter(#maxFee),
returnValue: _i15.Future<int>.value(0),
) as _i15.Future<int>);
returnValue: _i16.Future<int>.value(0),
) as _i16.Future<int>);
@override
_i15.Future<List<String>> get mnemonic => (super.noSuchMethod(
_i16.Future<List<String>> get mnemonic => (super.noSuchMethod(
Invocation.getter(#mnemonic),
returnValue: _i15.Future<List<String>>.value(<String>[]),
) as _i15.Future<List<String>>);
returnValue: _i16.Future<List<String>>.value(<String>[]),
) as _i16.Future<List<String>>);
@override
_i15.Future<int> get chainHeight => (super.noSuchMethod(
_i16.Future<int> get chainHeight => (super.noSuchMethod(
Invocation.getter(#chainHeight),
returnValue: _i15.Future<int>.value(0),
) as _i15.Future<int>);
returnValue: _i16.Future<int>.value(0),
) as _i16.Future<int>);
@override
int get storedChainHeight => (super.noSuchMethod(
Invocation.getter(#storedChainHeight),
@ -583,26 +596,26 @@ class MockBitcoinWallet extends _i1.Mock implements _i18.BitcoinWallet {
),
) as _i12.MainDB);
@override
_i15.Future<void> exit() => (super.noSuchMethod(
_i16.Future<void> exit() => (super.noSuchMethod(
Invocation.method(
#exit,
[],
),
returnValue: _i15.Future<void>.value(),
returnValueForMissingStub: _i15.Future<void>.value(),
) as _i15.Future<void>);
returnValue: _i16.Future<void>.value(),
returnValueForMissingStub: _i16.Future<void>.value(),
) as _i16.Future<void>);
@override
_i18.DerivePathType addressType({required String? address}) =>
_i21.DerivePathType addressType({required String? address}) =>
(super.noSuchMethod(
Invocation.method(
#addressType,
[],
{#address: address},
),
returnValue: _i18.DerivePathType.bip44,
) as _i18.DerivePathType);
returnValue: _i21.DerivePathType.bip44,
) as _i21.DerivePathType);
@override
_i15.Future<void> recoverFromMnemonic({
_i16.Future<void> recoverFromMnemonic({
required String? mnemonic,
required int? maxUnusedAddressGap,
required int? maxNumberOfIndexesToCheck,
@ -619,47 +632,47 @@ class MockBitcoinWallet extends _i1.Mock implements _i18.BitcoinWallet {
#height: height,
},
),
returnValue: _i15.Future<void>.value(),
returnValueForMissingStub: _i15.Future<void>.value(),
) as _i15.Future<void>);
returnValue: _i16.Future<void>.value(),
returnValueForMissingStub: _i16.Future<void>.value(),
) as _i16.Future<void>);
@override
_i15.Future<void> getTransactionCacheEarly(List<String>? allAddresses) =>
_i16.Future<void> getTransactionCacheEarly(List<String>? allAddresses) =>
(super.noSuchMethod(
Invocation.method(
#getTransactionCacheEarly,
[allAddresses],
),
returnValue: _i15.Future<void>.value(),
returnValueForMissingStub: _i15.Future<void>.value(),
) as _i15.Future<void>);
returnValue: _i16.Future<void>.value(),
returnValueForMissingStub: _i16.Future<void>.value(),
) as _i16.Future<void>);
@override
_i15.Future<bool> refreshIfThereIsNewData() => (super.noSuchMethod(
_i16.Future<bool> refreshIfThereIsNewData() => (super.noSuchMethod(
Invocation.method(
#refreshIfThereIsNewData,
[],
),
returnValue: _i15.Future<bool>.value(false),
) as _i15.Future<bool>);
returnValue: _i16.Future<bool>.value(false),
) as _i16.Future<bool>);
@override
_i15.Future<void> getAllTxsToWatch() => (super.noSuchMethod(
_i16.Future<void> getAllTxsToWatch() => (super.noSuchMethod(
Invocation.method(
#getAllTxsToWatch,
[],
),
returnValue: _i15.Future<void>.value(),
returnValueForMissingStub: _i15.Future<void>.value(),
) as _i15.Future<void>);
returnValue: _i16.Future<void>.value(),
returnValueForMissingStub: _i16.Future<void>.value(),
) as _i16.Future<void>);
@override
_i15.Future<void> refresh() => (super.noSuchMethod(
_i16.Future<void> refresh() => (super.noSuchMethod(
Invocation.method(
#refresh,
[],
),
returnValue: _i15.Future<void>.value(),
returnValueForMissingStub: _i15.Future<void>.value(),
) as _i15.Future<void>);
returnValue: _i16.Future<void>.value(),
returnValueForMissingStub: _i16.Future<void>.value(),
) as _i16.Future<void>);
@override
_i15.Future<Map<String, dynamic>> prepareSend({
_i16.Future<Map<String, dynamic>> prepareSend({
required String? address,
required int? satoshiAmount,
Map<String, dynamic>? args,
@ -675,26 +688,26 @@ class MockBitcoinWallet extends _i1.Mock implements _i18.BitcoinWallet {
},
),
returnValue:
_i15.Future<Map<String, dynamic>>.value(<String, dynamic>{}),
) as _i15.Future<Map<String, dynamic>>);
_i16.Future<Map<String, dynamic>>.value(<String, dynamic>{}),
) as _i16.Future<Map<String, dynamic>>);
@override
_i15.Future<String> confirmSend({required Map<String, dynamic>? txData}) =>
_i16.Future<String> confirmSend({required Map<String, dynamic>? txData}) =>
(super.noSuchMethod(
Invocation.method(
#confirmSend,
[],
{#txData: txData},
),
returnValue: _i15.Future<String>.value(''),
) as _i15.Future<String>);
returnValue: _i16.Future<String>.value(''),
) as _i16.Future<String>);
@override
_i15.Future<bool> testNetworkConnection() => (super.noSuchMethod(
_i16.Future<bool> testNetworkConnection() => (super.noSuchMethod(
Invocation.method(
#testNetworkConnection,
[],
),
returnValue: _i15.Future<bool>.value(false),
) as _i15.Future<bool>);
returnValue: _i16.Future<bool>.value(false),
) as _i16.Future<bool>);
@override
void startNetworkAlivePinging() => super.noSuchMethod(
Invocation.method(
@ -712,33 +725,33 @@ class MockBitcoinWallet extends _i1.Mock implements _i18.BitcoinWallet {
returnValueForMissingStub: null,
);
@override
_i15.Future<void> initializeNew() => (super.noSuchMethod(
_i16.Future<void> initializeNew() => (super.noSuchMethod(
Invocation.method(
#initializeNew,
[],
),
returnValue: _i15.Future<void>.value(),
returnValueForMissingStub: _i15.Future<void>.value(),
) as _i15.Future<void>);
returnValue: _i16.Future<void>.value(),
returnValueForMissingStub: _i16.Future<void>.value(),
) as _i16.Future<void>);
@override
_i15.Future<void> initializeExisting() => (super.noSuchMethod(
_i16.Future<void> initializeExisting() => (super.noSuchMethod(
Invocation.method(
#initializeExisting,
[],
),
returnValue: _i15.Future<void>.value(),
returnValueForMissingStub: _i15.Future<void>.value(),
) as _i15.Future<void>);
returnValue: _i16.Future<void>.value(),
returnValueForMissingStub: _i16.Future<void>.value(),
) as _i16.Future<void>);
@override
_i15.Future<void> updateSentCachedTxData(Map<String, dynamic>? txData) =>
_i16.Future<void> updateSentCachedTxData(Map<String, dynamic>? txData) =>
(super.noSuchMethod(
Invocation.method(
#updateSentCachedTxData,
[txData],
),
returnValue: _i15.Future<void>.value(),
returnValueForMissingStub: _i15.Future<void>.value(),
) as _i15.Future<void>);
returnValue: _i16.Future<void>.value(),
returnValueForMissingStub: _i16.Future<void>.value(),
) as _i16.Future<void>);
@override
bool validateAddress(String? address) => (super.noSuchMethod(
Invocation.method(
@ -748,35 +761,35 @@ class MockBitcoinWallet extends _i1.Mock implements _i18.BitcoinWallet {
returnValue: false,
) as bool);
@override
_i15.Future<void> updateNode(bool? shouldRefresh) => (super.noSuchMethod(
_i16.Future<void> updateNode(bool? shouldRefresh) => (super.noSuchMethod(
Invocation.method(
#updateNode,
[shouldRefresh],
),
returnValue: _i15.Future<void>.value(),
returnValueForMissingStub: _i15.Future<void>.value(),
) as _i15.Future<void>);
returnValue: _i16.Future<void>.value(),
returnValueForMissingStub: _i16.Future<void>.value(),
) as _i16.Future<void>);
@override
_i15.Future<_i9.ElectrumXNode> getCurrentNode() => (super.noSuchMethod(
_i16.Future<_i9.ElectrumXNode> getCurrentNode() => (super.noSuchMethod(
Invocation.method(
#getCurrentNode,
[],
),
returnValue: _i15.Future<_i9.ElectrumXNode>.value(_FakeElectrumXNode_10(
returnValue: _i16.Future<_i9.ElectrumXNode>.value(_FakeElectrumXNode_10(
this,
Invocation.method(
#getCurrentNode,
[],
),
)),
) as _i15.Future<_i9.ElectrumXNode>);
) as _i16.Future<_i9.ElectrumXNode>);
@override
_i15.Future<void> addDerivation({
_i16.Future<void> addDerivation({
required int? chain,
required String? address,
required String? pubKey,
required String? wif,
required _i18.DerivePathType? derivePathType,
required _i21.DerivePathType? derivePathType,
}) =>
(super.noSuchMethod(
Invocation.method(
@ -790,13 +803,13 @@ class MockBitcoinWallet extends _i1.Mock implements _i18.BitcoinWallet {
#derivePathType: derivePathType,
},
),
returnValue: _i15.Future<void>.value(),
returnValueForMissingStub: _i15.Future<void>.value(),
) as _i15.Future<void>);
returnValue: _i16.Future<void>.value(),
returnValueForMissingStub: _i16.Future<void>.value(),
) as _i16.Future<void>);
@override
_i15.Future<void> addDerivations({
_i16.Future<void> addDerivations({
required int? chain,
required _i18.DerivePathType? derivePathType,
required _i21.DerivePathType? derivePathType,
required Map<String, dynamic>? derivationsToAdd,
}) =>
(super.noSuchMethod(
@ -809,50 +822,50 @@ class MockBitcoinWallet extends _i1.Mock implements _i18.BitcoinWallet {
#derivationsToAdd: derivationsToAdd,
},
),
returnValue: _i15.Future<void>.value(),
returnValueForMissingStub: _i15.Future<void>.value(),
) as _i15.Future<void>);
returnValue: _i16.Future<void>.value(),
returnValueForMissingStub: _i16.Future<void>.value(),
) as _i16.Future<void>);
@override
_i15.Future<List<Map<String, dynamic>>> fastFetch(
_i16.Future<List<Map<String, dynamic>>> fastFetch(
List<String>? allTxHashes) =>
(super.noSuchMethod(
Invocation.method(
#fastFetch,
[allTxHashes],
),
returnValue: _i15.Future<List<Map<String, dynamic>>>.value(
returnValue: _i16.Future<List<Map<String, dynamic>>>.value(
<Map<String, dynamic>>[]),
) as _i15.Future<List<Map<String, dynamic>>>);
) as _i16.Future<List<Map<String, dynamic>>>);
@override
_i15.Future<int> getTxCount({required String? address}) =>
_i16.Future<int> getTxCount({required String? address}) =>
(super.noSuchMethod(
Invocation.method(
#getTxCount,
[],
{#address: address},
),
returnValue: _i15.Future<int>.value(0),
) as _i15.Future<int>);
returnValue: _i16.Future<int>.value(0),
) as _i16.Future<int>);
@override
_i15.Future<void> checkCurrentReceivingAddressesForTransactions() =>
_i16.Future<void> checkCurrentReceivingAddressesForTransactions() =>
(super.noSuchMethod(
Invocation.method(
#checkCurrentReceivingAddressesForTransactions,
[],
),
returnValue: _i15.Future<void>.value(),
returnValueForMissingStub: _i15.Future<void>.value(),
) as _i15.Future<void>);
returnValue: _i16.Future<void>.value(),
returnValueForMissingStub: _i16.Future<void>.value(),
) as _i16.Future<void>);
@override
_i15.Future<void> checkCurrentChangeAddressesForTransactions() =>
_i16.Future<void> checkCurrentChangeAddressesForTransactions() =>
(super.noSuchMethod(
Invocation.method(
#checkCurrentChangeAddressesForTransactions,
[],
),
returnValue: _i15.Future<void>.value(),
returnValueForMissingStub: _i15.Future<void>.value(),
) as _i15.Future<void>);
returnValue: _i16.Future<void>.value(),
returnValueForMissingStub: _i16.Future<void>.value(),
) as _i16.Future<void>);
@override
int estimateTxFee({
required int? vSize,
@ -876,7 +889,7 @@ class MockBitcoinWallet extends _i1.Mock implements _i18.BitcoinWallet {
String? _recipientAddress,
bool? isSendAll, {
int? additionalOutputs = 0,
List<_i19.UTXO>? utxos,
List<_i20.UTXO>? utxos,
}) =>
super.noSuchMethod(Invocation.method(
#coinSelection,
@ -892,19 +905,19 @@ class MockBitcoinWallet extends _i1.Mock implements _i18.BitcoinWallet {
},
));
@override
_i15.Future<Map<String, dynamic>> fetchBuildTxData(
List<_i19.UTXO>? utxosToUse) =>
_i16.Future<Map<String, dynamic>> fetchBuildTxData(
List<_i20.UTXO>? utxosToUse) =>
(super.noSuchMethod(
Invocation.method(
#fetchBuildTxData,
[utxosToUse],
),
returnValue:
_i15.Future<Map<String, dynamic>>.value(<String, dynamic>{}),
) as _i15.Future<Map<String, dynamic>>);
_i16.Future<Map<String, dynamic>>.value(<String, dynamic>{}),
) as _i16.Future<Map<String, dynamic>>);
@override
_i15.Future<Map<String, dynamic>> buildTransaction({
required List<_i19.UTXO>? utxosToUse,
_i16.Future<Map<String, dynamic>> buildTransaction({
required List<_i20.UTXO>? utxosToUse,
required Map<String, dynamic>? utxoSigningData,
required List<String>? recipients,
required List<int>? satoshiAmounts,
@ -921,10 +934,10 @@ class MockBitcoinWallet extends _i1.Mock implements _i18.BitcoinWallet {
},
),
returnValue:
_i15.Future<Map<String, dynamic>>.value(<String, dynamic>{}),
) as _i15.Future<Map<String, dynamic>>);
_i16.Future<Map<String, dynamic>>.value(<String, dynamic>{}),
) as _i16.Future<Map<String, dynamic>>);
@override
_i15.Future<void> fullRescan(
_i16.Future<void> fullRescan(
int? maxUnusedAddressGap,
int? maxNumberOfIndexesToCheck,
) =>
@ -936,11 +949,11 @@ class MockBitcoinWallet extends _i1.Mock implements _i18.BitcoinWallet {
maxNumberOfIndexesToCheck,
],
),
returnValue: _i15.Future<void>.value(),
returnValueForMissingStub: _i15.Future<void>.value(),
) as _i15.Future<void>);
returnValue: _i16.Future<void>.value(),
returnValueForMissingStub: _i16.Future<void>.value(),
) as _i16.Future<void>);
@override
_i15.Future<int> estimateFeeFor(
_i16.Future<int> estimateFeeFor(
int? satoshiAmount,
int? feeRate,
) =>
@ -952,8 +965,8 @@ class MockBitcoinWallet extends _i1.Mock implements _i18.BitcoinWallet {
feeRate,
],
),
returnValue: _i15.Future<int>.value(0),
) as _i15.Future<int>);
returnValue: _i16.Future<int>.value(0),
) as _i16.Future<int>);
@override
int roughFeeEstimate(
int? inputCount,
@ -972,25 +985,25 @@ class MockBitcoinWallet extends _i1.Mock implements _i18.BitcoinWallet {
returnValue: 0,
) as int);
@override
_i15.Future<int> sweepAllEstimate(int? feeRate) => (super.noSuchMethod(
_i16.Future<int> sweepAllEstimate(int? feeRate) => (super.noSuchMethod(
Invocation.method(
#sweepAllEstimate,
[feeRate],
),
returnValue: _i15.Future<int>.value(0),
) as _i15.Future<int>);
returnValue: _i16.Future<int>.value(0),
) as _i16.Future<int>);
@override
_i15.Future<bool> generateNewAddress() => (super.noSuchMethod(
_i16.Future<bool> generateNewAddress() => (super.noSuchMethod(
Invocation.method(
#generateNewAddress,
[],
),
returnValue: _i15.Future<bool>.value(false),
) as _i15.Future<bool>);
returnValue: _i16.Future<bool>.value(false),
) as _i16.Future<bool>);
@override
void initCache(
String? walletId,
_i14.Coin? coin,
_i15.Coin? coin,
) =>
super.noSuchMethod(
Invocation.method(
@ -1003,14 +1016,14 @@ class MockBitcoinWallet extends _i1.Mock implements _i18.BitcoinWallet {
returnValueForMissingStub: null,
);
@override
_i15.Future<void> updateCachedId(String? id) => (super.noSuchMethod(
_i16.Future<void> updateCachedId(String? id) => (super.noSuchMethod(
Invocation.method(
#updateCachedId,
[id],
),
returnValue: _i15.Future<void>.value(),
returnValueForMissingStub: _i15.Future<void>.value(),
) as _i15.Future<void>);
returnValue: _i16.Future<void>.value(),
returnValueForMissingStub: _i16.Future<void>.value(),
) as _i16.Future<void>);
@override
int getCachedChainHeight() => (super.noSuchMethod(
Invocation.method(
@ -1020,14 +1033,14 @@ class MockBitcoinWallet extends _i1.Mock implements _i18.BitcoinWallet {
returnValue: 0,
) as int);
@override
_i15.Future<void> updateCachedChainHeight(int? height) => (super.noSuchMethod(
_i16.Future<void> updateCachedChainHeight(int? height) => (super.noSuchMethod(
Invocation.method(
#updateCachedChainHeight,
[height],
),
returnValue: _i15.Future<void>.value(),
returnValueForMissingStub: _i15.Future<void>.value(),
) as _i15.Future<void>);
returnValue: _i16.Future<void>.value(),
returnValueForMissingStub: _i16.Future<void>.value(),
) as _i16.Future<void>);
@override
bool getCachedIsFavorite() => (super.noSuchMethod(
Invocation.method(
@ -1037,15 +1050,15 @@ class MockBitcoinWallet extends _i1.Mock implements _i18.BitcoinWallet {
returnValue: false,
) as bool);
@override
_i15.Future<void> updateCachedIsFavorite(bool? isFavorite) =>
_i16.Future<void> updateCachedIsFavorite(bool? isFavorite) =>
(super.noSuchMethod(
Invocation.method(
#updateCachedIsFavorite,
[isFavorite],
),
returnValue: _i15.Future<void>.value(),
returnValueForMissingStub: _i15.Future<void>.value(),
) as _i15.Future<void>);
returnValue: _i16.Future<void>.value(),
returnValueForMissingStub: _i16.Future<void>.value(),
) as _i16.Future<void>);
@override
_i11.Balance getCachedBalance() => (super.noSuchMethod(
Invocation.method(
@ -1061,15 +1074,15 @@ class MockBitcoinWallet extends _i1.Mock implements _i18.BitcoinWallet {
),
) as _i11.Balance);
@override
_i15.Future<void> updateCachedBalance(_i11.Balance? balance) =>
_i16.Future<void> updateCachedBalance(_i11.Balance? balance) =>
(super.noSuchMethod(
Invocation.method(
#updateCachedBalance,
[balance],
),
returnValue: _i15.Future<void>.value(),
returnValueForMissingStub: _i15.Future<void>.value(),
) as _i15.Future<void>);
returnValue: _i16.Future<void>.value(),
returnValueForMissingStub: _i16.Future<void>.value(),
) as _i16.Future<void>);
@override
_i11.Balance getCachedBalanceSecondary() => (super.noSuchMethod(
Invocation.method(
@ -1085,15 +1098,15 @@ class MockBitcoinWallet extends _i1.Mock implements _i18.BitcoinWallet {
),
) as _i11.Balance);
@override
_i15.Future<void> updateCachedBalanceSecondary(_i11.Balance? balance) =>
_i16.Future<void> updateCachedBalanceSecondary(_i11.Balance? balance) =>
(super.noSuchMethod(
Invocation.method(
#updateCachedBalanceSecondary,
[balance],
),
returnValue: _i15.Future<void>.value(),
returnValueForMissingStub: _i15.Future<void>.value(),
) as _i15.Future<void>);
returnValue: _i16.Future<void>.value(),
returnValueForMissingStub: _i16.Future<void>.value(),
) as _i16.Future<void>);
@override
void initWalletDB({_i12.MainDB? mockableOverride}) => super.noSuchMethod(
Invocation.method(
@ -1103,12 +1116,55 @@ class MockBitcoinWallet extends _i1.Mock implements _i18.BitcoinWallet {
),
returnValueForMissingStub: null,
);
@override
_i16.Future<
_i13.Tuple4<_i20.Transaction, List<_i20.Output>, List<_i20.Input>,
_i20.Address>> parseTransaction(
Map<String, dynamic>? txData,
dynamic electrumxClient,
List<_i20.Address>? myAddresses,
_i15.Coin? coin,
int? minConfirms,
String? walletId,
) =>
(super.noSuchMethod(
Invocation.method(
#parseTransaction,
[
txData,
electrumxClient,
myAddresses,
coin,
minConfirms,
walletId,
],
),
returnValue: _i16.Future<
_i13.Tuple4<_i20.Transaction, List<_i20.Output>, List<_i20.Input>,
_i20.Address>>.value(_FakeTuple4_11<_i20.Transaction,
List<_i20.Output>, List<_i20.Input>, _i20.Address>(
this,
Invocation.method(
#parseTransaction,
[
txData,
electrumxClient,
myAddresses,
coin,
minConfirms,
walletId,
],
),
)),
) as _i16.Future<
_i13.Tuple4<_i20.Transaction, List<_i20.Output>, List<_i20.Input>,
_i20.Address>>);
}
/// A class which mocks [LocaleService].
///
/// See the documentation for Mockito's code generation for more information.
class MockLocaleService extends _i1.Mock implements _i20.LocaleService {
class MockLocaleService extends _i1.Mock implements _i22.LocaleService {
MockLocaleService() {
_i1.throwOnMissingStub(this);
}
@ -1124,17 +1180,17 @@ class MockLocaleService extends _i1.Mock implements _i20.LocaleService {
returnValue: false,
) as bool);
@override
_i15.Future<void> loadLocale({bool? notify = true}) => (super.noSuchMethod(
_i16.Future<void> loadLocale({bool? notify = true}) => (super.noSuchMethod(
Invocation.method(
#loadLocale,
[],
{#notify: notify},
),
returnValue: _i15.Future<void>.value(),
returnValueForMissingStub: _i15.Future<void>.value(),
) as _i15.Future<void>);
returnValue: _i16.Future<void>.value(),
returnValueForMissingStub: _i16.Future<void>.value(),
) as _i16.Future<void>);
@override
void addListener(_i17.VoidCallback? listener) => super.noSuchMethod(
void addListener(_i18.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#addListener,
[listener],
@ -1142,7 +1198,7 @@ class MockLocaleService extends _i1.Mock implements _i20.LocaleService {
returnValueForMissingStub: null,
);
@override
void removeListener(_i17.VoidCallback? listener) => super.noSuchMethod(
void removeListener(_i18.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#removeListener,
[listener],