remove Manager, add mnemonic based wallet mixin, and WIP SWB process

This commit is contained in:
julian 2023-11-03 19:18:22 -06:00
parent 5ba29b7299
commit f2715f3f5e
60 changed files with 296 additions and 569 deletions
lib
test

View file

@ -11,8 +11,8 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/models/wallet_restore_state.dart';
import 'package:stackwallet/services/coins/manager.dart';
import 'package:stackwallet/utilities/enums/stack_restoring_status.dart';
import 'package:stackwallet/wallets/wallet/wallet.dart';
class StackRestoringUIState extends ChangeNotifier {
bool _walletsWasSet = false;
@ -93,14 +93,14 @@ class StackRestoringUIState extends ChangeNotifier {
notifyListeners();
}
List<Manager> get managers {
List<Manager> _managers = [];
List<Wallet> get wallets {
List<Wallet> _wallets = [];
for (final item in _walletStates.values) {
if (item.manager != null) {
_managers.add(item.manager!);
if (item.wallet != null) {
_wallets.add(item.wallet!);
}
}
return _managers;
return _wallets;
}
Map<String, WalletRestoreState> _walletStates = {};
@ -132,15 +132,14 @@ class StackRestoringUIState extends ChangeNotifier {
void update({
required String walletId,
required StackRestoringStatus restoringStatus,
Manager? manager,
Wallet? wallet,
String? address,
String? mnemonic,
String? mnemonicPassphrase,
int? height,
}) {
_walletStates[walletId]!.restoringState = restoringStatus;
_walletStates[walletId]!.manager =
manager ?? _walletStates[walletId]!.manager;
_walletStates[walletId]!.wallet = wallet ?? _walletStates[walletId]!.wallet;
_walletStates[walletId]!.address =
address ?? _walletStates[walletId]!.address;
_walletStates[walletId]!.mnemonic =

View file

@ -8,17 +8,17 @@
*
*/
import 'package:flutter/cupertino.dart';
import 'package:stackwallet/services/coins/manager.dart';
import 'package:flutter/material.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/enums/stack_restoring_status.dart';
import 'package:stackwallet/wallets/wallet/wallet.dart';
class WalletRestoreState extends ChangeNotifier {
final String walletId;
final String walletName;
final Coin coin;
late StackRestoringStatus _restoringStatus;
Manager? manager;
Wallet? wallet;
String? address;
String? mnemonic;
String? mnemonicPassphrase;
@ -35,7 +35,7 @@ class WalletRestoreState extends ChangeNotifier {
required this.walletName,
required this.coin,
required StackRestoringStatus restoringStatus,
this.manager,
this.wallet,
this.address,
this.mnemonic,
this.mnemonicPassphrase,
@ -54,7 +54,7 @@ class WalletRestoreState extends ChangeNotifier {
walletName: walletName,
coin: coin,
restoringStatus: restoringStatus ?? _restoringStatus,
manager: manager,
wallet: wallet,
address: this.address,
mnemonic: mnemonic,
mnemonicPassphrase: mnemonicPassphrase,

View file

@ -30,7 +30,7 @@ import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/wallets/isar/models/wallet_info.dart';
import 'package:stackwallet/wallets/wallet/bip39_wallet.dart';
import 'package:stackwallet/wallets/wallet/mixins/mnemonic_based_wallet.dart';
import 'package:stackwallet/wallets/wallet/wallet.dart';
import 'package:stackwallet/widgets/conditional_parent.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
@ -531,7 +531,7 @@ class _NewWalletRecoveryPhraseWarningViewState
NewWalletRecoveryPhraseView.routeName,
arguments: Tuple2(
wallet.walletId,
await (wallet as Bip39Wallet)
await (wallet as MnemonicBasedWallet)
.getMnemonicAsWords(),
),
));

View file

@ -10,7 +10,7 @@
// import 'package:stackwallet/pages/wallet_view/wallet_view.dart';
// import 'package:stackwallet/providers/global/wallets_provider.dart';
// import 'package:stackwallet/services/coins/banano/banano_wallet.dart';
// import 'package:stackwallet/services/coins/manager.dart';
//
// import 'package:stackwallet/themes/stack_colors.dart';
// import 'package:stackwallet/utilities/assets.dart';
// import 'package:stackwallet/utilities/enums/coin_enum.dart';

View file

@ -29,7 +29,7 @@ import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
import 'package:stackwallet/wallets/wallet/bip39_hd_wallet.dart';
import 'package:stackwallet/wallets/wallet/intermediate/bip39_hd_wallet.dart';
import 'package:stackwallet/widgets/background.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart';

View file

@ -13,8 +13,10 @@ import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'package:isar/isar.dart';
import 'package:stack_wallet_backup/stack_wallet_backup.dart';
import 'package:stackwallet/db/hive/db.dart';
import 'package:stackwallet/db/isar/main_db.dart';
import 'package:stackwallet/models/exchange/change_now/exchange_transaction.dart';
import 'package:stackwallet/models/exchange/response_objects/trade.dart';
import 'package:stackwallet/models/isar/models/contact_entry.dart';
@ -23,16 +25,12 @@ import 'package:stackwallet/models/stack_restoring_ui_state.dart';
import 'package:stackwallet/models/trade_wallet_lookup.dart';
import 'package:stackwallet/models/wallet_restore_state.dart';
import 'package:stackwallet/services/address_book_service.dart';
import 'package:stackwallet/services/coins/coin_service.dart';
import 'package:stackwallet/services/coins/manager.dart';
import 'package:stackwallet/services/node_service.dart';
import 'package:stackwallet/services/notes_service.dart';
import 'package:stackwallet/services/trade_notes_service.dart';
import 'package:stackwallet/services/trade_sent_from_stack_service.dart';
import 'package:stackwallet/services/trade_service.dart';
import 'package:stackwallet/services/transaction_notification_tracker.dart';
import 'package:stackwallet/services/wallets.dart';
import 'package:stackwallet/services/wallets_service.dart';
import 'package:stackwallet/utilities/default_nodes.dart';
import 'package:stackwallet/utilities/enums/backup_frequency_type.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
@ -43,6 +41,10 @@ import 'package:stackwallet/utilities/format.dart';
import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/utilities/prefs.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/wallets/isar/models/wallet_info.dart';
import 'package:stackwallet/wallets/wallet/mixins/mnemonic_based_wallet.dart';
import 'package:stackwallet/wallets/wallet/private_key_based_wallet.dart';
import 'package:stackwallet/wallets/wallet/wallet.dart';
import 'package:tuple/tuple.dart';
import 'package:uuid/uuid.dart';
import 'package:wakelock/wakelock.dart';
@ -285,26 +287,30 @@ abstract class SWB {
);
List<dynamic> backupWallets = [];
for (var manager in _wallets.managers) {
for (var wallet in _wallets.wallets) {
Map<String, dynamic> backupWallet = {};
backupWallet['name'] = manager.walletName;
backupWallet['id'] = manager.walletId;
backupWallet['isFavorite'] = manager.isFavorite;
backupWallet['mnemonic'] = await manager.mnemonic;
backupWallet['mnemonicPassphrase'] = await manager.mnemonicPassphrase;
backupWallet['coinName'] = manager.coin.name;
backupWallet['storedChainHeight'] = DB.instance
.get<dynamic>(boxName: manager.walletId, key: 'storedChainHeight');
backupWallet['name'] = wallet.info.name;
backupWallet['id'] = wallet.walletId;
backupWallet['isFavorite'] = wallet.info.isFavourite;
backupWallet['txidList'] = DB.instance.get<dynamic>(
boxName: manager.walletId, key: "cachedTxids") as List?;
if (wallet is MnemonicBasedWallet) {
backupWallet['mnemonic'] = await wallet.getMnemonic();
backupWallet['mnemonicPassphrase'] =
await wallet.getMnemonicPassphrase();
} else if (wallet is PrivateKeyBasedWallet) {
backupWallet['privateKey'] = await wallet.getPrivateKey();
}
backupWallet['coinName'] = wallet.info.coin.name;
backupWallet['storedChainHeight'] = wallet.info.cachedChainHeight;
// backupWallet['txidList'] = DB.instance.get<dynamic>(
// boxName: wallet.walletId, key: "cachedTxids") as List?;
// the following can cause a deadlock
// (await manager.transactionData).getAllTransactions().keys.toList();
backupWallet['restoreHeight'] = DB.instance
.get<dynamic>(boxName: manager.walletId, key: 'restoreHeight');
backupWallet['restoreHeight'] = wallet.info.restoreHeight;
NotesService notesService = NotesService(walletId: manager.walletId);
NotesService notesService = NotesService(walletId: wallet.walletId);
var notes = await notesService.notes;
backupWallet['notes'] = notes;
@ -355,47 +361,69 @@ abstract class SWB {
}
static Future<bool> asyncRestore(
Tuple2<dynamic, Manager> tuple,
Tuple2<dynamic, WalletInfo> tuple,
Prefs prefs,
NodeService nodeService,
SecureStorageInterface secureStorageInterface,
StackRestoringUIState? uiState,
WalletsService walletsService,
) async {
final wallet = tuple.item2;
final info = tuple.item2;
final walletbackup = tuple.item1;
List<String> mnemonicList = (walletbackup['mnemonic'] as List<dynamic>)
.map<String>((e) => e as String)
.toList();
final String mnemonic = mnemonicList.join(" ").trim();
final String mnemonicPassphrase =
walletbackup['mnemonicPassphrase'] as String? ?? "";
String? mnemonic, mnemonicPassphrase, privateKey;
if (walletbackup['mnemonic'] == null) {
// probably private key based
privateKey = walletbackup['privateKey'] as String;
} else {
if (walletbackup['mnemonic'] is List) {
List<String> mnemonicList = (walletbackup['mnemonic'] as List<dynamic>)
.map<String>((e) => e as String)
.toList();
mnemonic = mnemonicList.join(" ").trim();
} else {
mnemonic = walletbackup['mnemonic'] as String;
}
mnemonicPassphrase = walletbackup['mnemonicPassphrase'] as String? ?? "";
}
uiState?.update(
walletId: manager.walletId,
walletId: info.walletId,
restoringStatus: StackRestoringStatus.restoring,
mnemonic: mnemonic,
mnemonicPassphrase: mnemonicPassphrase,
);
if (_shouldCancelRestore) {
return false;
}
try {
int restoreHeight = 0;
final wallet = await Wallet.create(
walletInfo: info,
mainDB: MainDB.instance,
secureStorageInterface: secureStorageInterface,
nodeService: nodeService,
prefs: prefs,
mnemonic: mnemonic,
mnemonicPassphrase: mnemonicPassphrase,
privateKey: privateKey,
);
restoreHeight = walletbackup['restoreHeight'] as int? ?? 0;
int restoreHeight = walletbackup['restoreHeight'] as int? ?? 0;
if (restoreHeight <= 0) {
restoreHeight = walletbackup['storedChainHeight'] as int? ?? 0;
}
manager.isFavorite = walletbackup['isFavorite'] == "false" ? false : true;
uiState?.update(
walletId: info.walletId,
restoringStatus: StackRestoringStatus.restoring,
wallet: wallet,
);
if (_shouldCancelRestore) {
return false;
}
// restore notes
NotesService notesService = NotesService(walletId: manager.walletId);
NotesService notesService = NotesService(walletId: info.walletId);
final notes = walletbackup["notes"] as Map?;
if (notes != null) {
for (final note in notes.entries) {
@ -408,39 +436,23 @@ abstract class SWB {
return false;
}
// TODO GUI option to set maxUnusedAddressGap?
// default is 20 but it may miss some transactions if
// the previous wallet software generated many addresses
// without using them
await manager.recoverFromMnemonic(
mnemonic: mnemonic,
mnemonicPassphrase: mnemonicPassphrase,
maxUnusedAddressGap: manager.coin == Coin.firo ? 50 : 20,
maxNumberOfIndexesToCheck: 1000,
height: restoreHeight,
);
if (_shouldCancelRestore) {
return false;
}
// if mnemonic verified does not get set the wallet will be deleted on app restart
await walletsService.setMnemonicVerified(walletId: manager.walletId);
await wallet.info.setMnemonicVerified(isar: MainDB.instance.isar);
if (_shouldCancelRestore) {
return false;
}
Logging.instance.log(
"SWB restored: ${manager.walletId} ${manager.walletName} ${manager.coin.prettyName}",
"SWB restored: ${info.walletId} ${info.name} ${info.coin.prettyName}",
level: LogLevel.Info);
final currentAddress = await manager.currentReceivingAddress;
final currentAddress = await wallet.getCurrentReceivingAddress();
uiState?.update(
walletId: manager.walletId,
walletId: info.walletId,
restoringStatus: StackRestoringStatus.success,
manager: manager,
address: currentAddress,
wallet: wallet,
address: currentAddress!.value,
height: restoreHeight,
mnemonic: mnemonic,
mnemonicPassphrase: mnemonicPassphrase,
@ -448,9 +460,8 @@ abstract class SWB {
} catch (e, s) {
Logging.instance.log("$e $s", level: LogLevel.Warning);
uiState?.update(
walletId: manager.walletId,
walletId: info.walletId,
restoringStatus: StackRestoringStatus.failed,
manager: manager,
mnemonic: mnemonic,
mnemonicPassphrase: mnemonicPassphrase,
);
@ -578,13 +589,10 @@ abstract class SWB {
level: LogLevel.Warning,
);
List<String> _currentWalletIds = Map<String, dynamic>.from(DB.instance
.get<dynamic>(
boxName: DB.boxNameAllWalletsData, key: "names") as Map? ??
{})
.values
.map((e) => e["id"] as String)
.toList();
List<String> _currentWalletIds = await MainDB.instance.isar.walletInfo
.where()
.walletIdProperty()
.findAll();
final preRestoreState =
PreRestoreState(_currentWalletIds.toSet(), preRestoreJSON);
@ -634,13 +642,11 @@ abstract class SWB {
final nodeService = NodeService(
secureStorageInterface: secureStorageInterface,
);
final walletsService = WalletsService(
secureStorageInterface: secureStorageInterface,
);
final _prefs = Prefs.instance;
await _prefs.init();
final List<Tuple2<dynamic, Manager>> managers = [];
final List<Tuple2<dynamic, WalletInfo>> managers = [];
Map<String, WalletRestoreState> walletStates = {};
@ -653,26 +659,21 @@ abstract class SWB {
return false;
}
Coin coin = Coin.values
final coin = Coin.values
.firstWhere((element) => element.name == walletbackup['coinName']);
String walletName = walletbackup['name'] as String;
final walletName = walletbackup['name'] as String;
final walletId = oldToNewWalletIdMap[walletbackup["id"] as String]!;
// TODO: use these for monero and possibly other coins later on?
// final List<String> txidList = List<String>.from(walletbackup['txidList'] as List? ?? []);
const int sanityCheckMax = 100;
int count = 0;
while (await walletsService.checkForDuplicate(walletName) &&
count < sanityCheckMax) {
walletName += " (restored)";
}
final restoreHeight = walletbackup['restoreHeight'] as int? ?? 0;
await walletsService.addExistingStackWallet(
name: walletName,
walletId: walletId,
final info = WalletInfo.createNew(
coin: coin,
shouldNotifyListeners: false,
name: walletName,
walletIdOverride: walletId,
restoreHeight: restoreHeight,
);
var node = nodeService.getPrimaryNodeFor(coin: coin);
@ -682,9 +683,9 @@ abstract class SWB {
await nodeService.setPrimaryNodeFor(coin: coin, node: node);
}
final txTracker = TransactionNotificationTracker(walletId: walletId);
final failovers = nodeService.failoverNodesFor(coin: coin);
// final txTracker = TransactionNotificationTracker(walletId: walletId);
//
// final failovers = nodeService.failoverNodesFor(coin: coin);
// check if cancel was requested and restore previous state
if (_checkShouldCancel(
@ -694,20 +695,7 @@ abstract class SWB {
return false;
}
final wallet = CoinServiceAPI.from(
coin,
walletId,
walletName,
secureStorageInterface,
node,
txTracker,
_prefs,
failovers,
);
final wallet = Manager(wallet);
managers.add(Tuple2(walletbackup, manager));
managers.add(Tuple2(walletbackup, info));
// check if cancel was requested and restore previous state
if (_checkShouldCancel(
preRestoreState,
@ -721,7 +709,6 @@ abstract class SWB {
restoringStatus: StackRestoringStatus.waiting,
walletId: walletId,
walletName: walletName,
manager: manager,
);
}
@ -746,7 +733,13 @@ abstract class SWB {
)) {
return false;
}
final bools = await asyncRestore(tuple, uiState, walletsService);
final bools = await asyncRestore(
tuple,
_prefs,
nodeService,
secureStorageInterface,
uiState,
);
restoreStatuses.add(Future(() => bools));
}
@ -781,7 +774,7 @@ abstract class SWB {
Logging.instance.log("done with SWB restore", level: LogLevel.Warning);
if (Util.isDesktop) {
await Wallets.sharedInstance
.loadAfterStackRestore(_prefs, managers.map((e) => e.item2).toList());
.loadAfterStackRestore(_prefs, uiState?.wallets ?? []);
}
return true;
}
@ -984,14 +977,16 @@ abstract class SWB {
}
// finally remove any added wallets
final walletsService =
WalletsService(secureStorageInterface: secureStorageInterface);
final namesData = await walletsService.walletNames;
for (final entry in namesData.entries) {
if (!revertToState.walletIds.contains(entry.value.walletId)) {
await walletsService.deleteWallet(entry.key, true);
}
}
final allWalletIds = (await MainDB.instance.isar.walletInfo
.where()
.walletIdProperty()
.findAll())
.toSet();
final walletIdsToDelete = allWalletIds.difference(revertToState.walletIds);
await MainDB.instance.isar.writeTxn(() async {
await MainDB.instance.isar.walletInfo
.deleteAllByWalletId(walletIdsToDelete.toList());
});
_cancelCompleter!.complete();
_shouldCancelRestore = false;

View file

@ -217,7 +217,7 @@ class _StackRestoreProgressViewState
void _addWalletsToHomeView() {
ref.read(pWallets).loadAfterStackRestore(
ref.read(prefsChangeNotifierProvider),
ref.read(stackRestoringUIStateProvider).managers,
ref.read(stackRestoringUIStateProvider).wallets,
);
}

View file

@ -105,49 +105,54 @@ class _RestoringWalletCardState extends ConsumerState<RestoringWalletCard> {
),
onRightTapped: restoringStatus == StackRestoringStatus.failed
? () async {
final wallet = ref.read(provider).manager!;
final wallet = ref.read(provider).wallet!;
ref.read(stackRestoringUIStateProvider).update(
walletId: wallet.walletId,
restoringStatus: StackRestoringStatus.restoring);
try {
final mnemonicList = await manager.mnemonic;
int maxUnusedAddressGap = 20;
if (coin == Coin.firo) {
maxUnusedAddressGap = 50;
}
const maxNumberOfIndexesToCheck = 1000;
// TODO: [prio=high] handle non mnemonic based wallets
// final mnemonicList = await (wallet as MnemonicBasedWallet)
// .getMnemonicAsWords();
// int maxUnusedAddressGap = 20;
// if (coin == Coin.firo) {
// maxUnusedAddressGap = 50;
// }
// const maxNumberOfIndexesToCheck = 1000;
//
// if (mnemonicList.isEmpty) {
// await manager.recoverFromMnemonic(
// mnemonic: ref.read(provider).mnemonic!,
// mnemonicPassphrase:
// ref.read(provider).mnemonicPassphrase!,
// maxUnusedAddressGap: maxUnusedAddressGap,
// maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck,
// height: ref.read(provider).height ?? 0,
// );
// } else {
// await manager.fullRescan(
// maxUnusedAddressGap,
// maxNumberOfIndexesToCheck,
// );
// }
if (mnemonicList.isEmpty) {
await manager.recoverFromMnemonic(
mnemonic: ref.read(provider).mnemonic!,
mnemonicPassphrase:
ref.read(provider).mnemonicPassphrase!,
maxUnusedAddressGap: maxUnusedAddressGap,
maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck,
height: ref.read(provider).height ?? 0,
);
} else {
await manager.fullRescan(
maxUnusedAddressGap,
maxNumberOfIndexesToCheck,
);
}
await wallet.recover(isRescan: true);
if (mounted) {
final address = await manager.currentReceivingAddress;
final address =
await wallet.getCurrentReceivingAddress();
ref.read(stackRestoringUIStateProvider).update(
walletId: manager.walletId,
walletId: wallet.walletId,
restoringStatus: StackRestoringStatus.success,
address: address,
address: address!.value,
);
}
} catch (_) {
if (mounted) {
ref.read(stackRestoringUIStateProvider).update(
walletId: manager.walletId,
walletId: wallet.walletId,
restoringStatus: StackRestoringStatus.failed,
);
}
@ -223,7 +228,7 @@ class _RestoringWalletCardState extends ConsumerState<RestoringWalletCard> {
: null,
)
: RoundedContainer(
padding: EdgeInsets.all(0),
padding: const EdgeInsets.all(0),
color: Theme.of(context).extension<StackColors>()!.popupBG,
borderColor: Theme.of(context).extension<StackColors>()!.background,
child: RestoringItemCard(
@ -250,50 +255,53 @@ class _RestoringWalletCardState extends ConsumerState<RestoringWalletCard> {
),
onRightTapped: restoringStatus == StackRestoringStatus.failed
? () async {
final wallet = ref.read(provider).manager!;
final wallet = ref.read(provider).wallet!;
ref.read(stackRestoringUIStateProvider).update(
walletId: manager.walletId,
walletId: wallet.walletId,
restoringStatus: StackRestoringStatus.restoring);
try {
final mnemonicList = await manager.mnemonic;
int maxUnusedAddressGap = 20;
if (coin == Coin.firo) {
maxUnusedAddressGap = 50;
}
const maxNumberOfIndexesToCheck = 1000;
// final mnemonicList = await manager.mnemonic;
// int maxUnusedAddressGap = 20;
// if (coin == Coin.firo) {
// maxUnusedAddressGap = 50;
// }
// const maxNumberOfIndexesToCheck = 1000;
//
// if (mnemonicList.isEmpty) {
// await manager.recoverFromMnemonic(
// mnemonic: ref.read(provider).mnemonic!,
// mnemonicPassphrase:
// ref.read(provider).mnemonicPassphrase!,
// maxUnusedAddressGap: maxUnusedAddressGap,
// maxNumberOfIndexesToCheck:
// maxNumberOfIndexesToCheck,
// height: ref.read(provider).height ?? 0,
// );
// } else {
// await manager.fullRescan(
// maxUnusedAddressGap,
// maxNumberOfIndexesToCheck,
// );
// }
if (mnemonicList.isEmpty) {
await manager.recoverFromMnemonic(
mnemonic: ref.read(provider).mnemonic!,
mnemonicPassphrase:
ref.read(provider).mnemonicPassphrase!,
maxUnusedAddressGap: maxUnusedAddressGap,
maxNumberOfIndexesToCheck:
maxNumberOfIndexesToCheck,
height: ref.read(provider).height ?? 0,
);
} else {
await manager.fullRescan(
maxUnusedAddressGap,
maxNumberOfIndexesToCheck,
);
}
await wallet.recover(isRescan: true);
if (mounted) {
final address = await manager.currentReceivingAddress;
final address =
await wallet.getCurrentReceivingAddress();
ref.read(stackRestoringUIStateProvider).update(
walletId: manager.walletId,
walletId: wallet.walletId,
restoringStatus: StackRestoringStatus.success,
address: address,
address: address!.value,
);
}
} catch (_) {
if (mounted) {
ref.read(stackRestoringUIStateProvider).update(
walletId: manager.walletId,
walletId: wallet.walletId,
restoringStatus: StackRestoringStatus.failed,
);
}

View file

@ -40,7 +40,7 @@ import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/show_loading.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/wallets/wallet/bip39_wallet.dart';
import 'package:stackwallet/wallets/wallet/mixins/mnemonic_based_wallet.dart';
import 'package:stackwallet/widgets/background.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
import 'package:stackwallet/widgets/desktop/secondary_button.dart';
@ -236,7 +236,7 @@ class _WalletSettingsViewState extends ConsumerState<WalletSettingsView> {
.read(pWallets)
.getWallet(widget.walletId);
// TODO: [prio=high] take wallets that don't have amnemonic into account
if (wallet is Bip39Wallet) {
if (wallet is MnemonicBasedWallet) {
final mnemonic =
await wallet.getMnemonicAsWords();

View file

@ -14,7 +14,7 @@ import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_set
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/wallets/wallet/bip39_wallet.dart';
import 'package:stackwallet/wallets/wallet/mixins/mnemonic_based_wallet.dart';
import 'package:stackwallet/widgets/background.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
import 'package:stackwallet/widgets/rounded_container.dart';
@ -100,8 +100,8 @@ class DeleteWalletWarningView extends ConsumerWidget {
.getPrimaryEnabledButtonStyle(context),
onPressed: () async {
final wallet = ref.read(pWallets).getWallet(walletId);
final mnemonic =
await (wallet as Bip39Wallet).getMnemonicAsWords();
final mnemonic = await (wallet as MnemonicBasedWallet)
.getMnemonicAsWords();
if (context.mounted) {
await Navigator.of(context).pushNamed(
DeleteWalletRecoveryPhraseView.routeName,

View file

@ -13,7 +13,7 @@ import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
import 'package:stackwallet/wallets/wallet/bip39_wallet.dart';
import 'package:stackwallet/wallets/wallet/mixins/mnemonic_based_wallet.dart';
import 'package:stackwallet/widgets/background.dart';
import 'package:stackwallet/widgets/conditional_parent.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
@ -259,7 +259,7 @@ class _FiroRescanRecoveryErrorViewState
final wallet =
ref.read(pWallets).getWallet(widget.walletId);
// TODO: [prio=high] take wallets that don't have amnemonic into account
if (wallet is Bip39Wallet) {
if (wallet is MnemonicBasedWallet) {
final mnemonic = await wallet.getMnemonicAsWords();
if (mounted) {

View file

@ -27,7 +27,6 @@ import 'package:stackwallet/providers/db/main_db_provider.dart';
import 'package:stackwallet/providers/global/address_book_service_provider.dart';
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/services/coins/epiccash/epiccash_wallet.dart';
import 'package:stackwallet/services/coins/manager.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/amount/amount.dart';
import 'package:stackwallet/utilities/amount/amount_formatter.dart';
@ -1597,8 +1596,7 @@ class _TransactionDetailsViewState
),
),
onPressed: () async {
final wallet =
ref.read(pWallets).getWallet(walletId);
final wallet = ref.read(pWallets).getWallet(walletId);
if (wallet is EpicCashWallet) {
final String? id = _transaction.slateId;

View file

@ -14,7 +14,7 @@ import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/sub
import 'package:stackwallet/providers/global/wallets_provider.dart';
import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/wallets/wallet/bip39_wallet.dart';
import 'package:stackwallet/wallets/wallet/mixins/mnemonic_based_wallet.dart';
import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart';
import 'package:stackwallet/widgets/desktop/primary_button.dart';
@ -114,7 +114,7 @@ class _DesktopAttentionDeleteWallet
final wallet =
ref.read(pWallets).getWallet(widget.walletId);
// TODO: [prio=high] handle other types wallet deletion
if (wallet is Bip39Wallet) {
if (wallet is MnemonicBasedWallet) {
final words = await wallet.getMnemonicAsWords();
if (mounted) {

View file

@ -29,7 +29,7 @@ import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/wallets/isar/providers/wallet_info_provider.dart';
import 'package:stackwallet/wallets/wallet/bip39_hd_wallet.dart';
import 'package:stackwallet/wallets/wallet/intermediate/bip39_hd_wallet.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
import 'package:stackwallet/widgets/custom_loading_overlay.dart';
import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';

View file

@ -21,7 +21,7 @@ import 'package:stackwallet/themes/stack_colors.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/wallets/wallet/bip39_wallet.dart';
import 'package:stackwallet/wallets/wallet/mixins/mnemonic_based_wallet.dart';
import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart';
import 'package:stackwallet/widgets/desktop/primary_button.dart';
@ -82,7 +82,7 @@ class _UnlockWalletKeysDesktopState
final wallet = ref.read(pWallets).getWallet(widget.walletId);
// TODO: [prio=high] handle wallets that don't have a mnemonic
if (wallet is! Bip39Wallet) {
if (wallet is! MnemonicBasedWallet) {
throw Exception("FIXME ~= see todo in code");
}
@ -277,10 +277,10 @@ class _UnlockWalletKeysDesktopState
unawaited(
showDialog(
context: context,
builder: (context) => Column(
builder: (context) => const Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: const [
children: [
LoadingIndicator(
width: 200,
height: 200,
@ -304,7 +304,7 @@ class _UnlockWalletKeysDesktopState
ref.read(pWallets).getWallet(widget.walletId);
// TODO: [prio=high] handle wallets that don't have a mnemonic
if (wallet is! Bip39Wallet) {
if (wallet is! MnemonicBasedWallet) {
throw Exception("FIXME ~= see todo in code");
}

View file

@ -12,8 +12,8 @@ import 'package:equatable/equatable.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:stackwallet/providers/db/main_db_provider.dart';
import 'package:stackwallet/providers/global/secure_store_provider.dart';
import 'package:stackwallet/providers/global/wallets_provider.dart';
import 'package:stackwallet/services/coins/ethereum/ethereum_wallet.dart';
import 'package:stackwallet/services/coins/manager.dart';
import 'package:stackwallet/services/ethereum/ethereum_token_service.dart';
import 'package:stackwallet/services/transaction_notification_tracker.dart';
import 'package:stackwallet/utilities/logger.dart';
@ -34,17 +34,11 @@ class ContractWalletId implements Equatable {
bool? get stringify => true;
}
/// provide the wallet for a given wallet id
final walletProvider =
ChangeNotifierProvider.family<Manager?, String>((ref, arg) => null);
/// provide the token wallet given a contract address and eth wallet id
final tokenWalletProvider =
ChangeNotifierProvider.family<EthTokenWallet?, ContractWalletId>(
(ref, arg) {
Provider.family<EthTokenWallet?, ContractWalletId>((ref, arg) {
final ethWallet =
ref.watch(walletProvider(arg.walletId).select((value) => value?.wallet))
as EthereumWallet?;
ref.watch(pWallets).getWallet(arg.walletId) as EthereumWallet?;
final contract =
ref.read(mainDBProvider).getEthContractSync(arg.tokenContractAddress);

View file

@ -1,283 +0,0 @@
/*
* This file is part of Stack Wallet.
*
* Copyright (c) 2023 Cypher Stack
* All Rights Reserved.
* The code is distributed under GPLv3 license, see LICENSE file for details.
* Generated by Cypher Stack on 2023-05-26
*
*/
import 'dart:async';
import 'package:event_bus/event_bus.dart';
import 'package:flutter/material.dart';
import 'package:stackwallet/db/hive/db.dart';
import 'package:stackwallet/models/balance.dart';
import 'package:stackwallet/models/isar/models/isar_models.dart' as isar_models;
import 'package:stackwallet/models/models.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/updated_in_background_event.dart';
import 'package:stackwallet/services/event_bus/global_event_bus.dart';
import 'package:stackwallet/services/mixins/coin_control_interface.dart';
import 'package:stackwallet/services/mixins/fusion_wallet_interface.dart';
import 'package:stackwallet/services/mixins/ordinals_interface.dart';
import 'package:stackwallet/services/mixins/paynym_wallet_interface.dart';
import 'package:stackwallet/services/mixins/xpubable.dart';
import 'package:stackwallet/utilities/amount/amount.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/logger.dart';
class Manager with ChangeNotifier {
final CoinServiceAPI _currentWallet;
StreamSubscription<dynamic>? _backgroundRefreshListener;
StreamSubscription<dynamic>? _nodeStatusListener;
/// optional eventbus parameter for testing only
Manager(this._currentWallet, [EventBus? globalEventBusForTesting]) {
final bus = globalEventBusForTesting ?? GlobalEventBus.instance;
_backgroundRefreshListener = bus.on<UpdatedInBackgroundEvent>().listen(
(event) async {
if (event.walletId == walletId) {
notifyListeners();
Logging.instance.log(
"UpdatedInBackgroundEvent activated notifyListeners() in Manager instance $hashCode $walletName with: ${event.message}",
level: LogLevel.Info);
}
},
);
_nodeStatusListener = bus.on<NodeConnectionStatusChangedEvent>().listen(
(event) async {
if (event.walletId == walletId) {
notifyListeners();
Logging.instance.log(
"NodeConnectionStatusChangedEvent activated notifyListeners() in Manager instance $hashCode $walletName with: ${event.newStatus}",
level: LogLevel.Info);
}
},
);
}
bool _isActiveWallet = false;
bool get isActiveWallet => _isActiveWallet;
set isActiveWallet(bool isActive) {
if (_isActiveWallet != isActive) {
_isActiveWallet = isActive;
_currentWallet.onIsActiveWalletChanged?.call(isActive);
//todo: check if print needed
debugPrint(
"wallet ID: ${_currentWallet.walletId} is active set to: $isActive");
} else {
debugPrint("wallet ID: ${_currentWallet.walletId} is still: $isActive");
}
}
Future<void> updateNode(bool shouldRefresh) async {
await _currentWallet.updateNode(shouldRefresh);
}
CoinServiceAPI get wallet => _currentWallet;
bool get hasBackgroundRefreshListener => _backgroundRefreshListener != null;
Coin get coin => _currentWallet.coin;
bool get isRefreshing => _currentWallet.isRefreshing;
bool get shouldAutoSync => _currentWallet.shouldAutoSync;
set shouldAutoSync(bool shouldAutoSync) =>
_currentWallet.shouldAutoSync = shouldAutoSync;
bool get isFavorite => _currentWallet.isFavorite;
set isFavorite(bool markFavorite) {
_currentWallet.isFavorite = markFavorite;
notifyListeners();
}
@override
dispose() async {
await exitCurrentWallet();
super.dispose();
}
Future<Map<String, dynamic>> prepareSend({
required String address,
required Amount amount,
Map<String, dynamic>? args,
}) async {
try {
final txInfo = await _currentWallet.prepareSend(
address: address,
amount: amount,
args: args,
);
// notifyListeners();
return txInfo;
} catch (e) {
// rethrow to pass error in alert
rethrow;
}
}
Future<String> confirmSend({required Map<String, dynamic> txData}) async {
try {
final txid = await _currentWallet.confirmSend(txData: txData);
try {
txData["txid"] = txid;
await _currentWallet.updateSentCachedTxData(txData);
} catch (e, s) {
// do not rethrow as that would get handled as a send failure further up
// also this is not critical code and transaction should show up on \
// refresh regardless
Logging.instance.log("$e\n$s", level: LogLevel.Warning);
}
notifyListeners();
return txid;
} catch (e) {
// rethrow to pass error in alert
rethrow;
}
}
Future<FeeObject> get fees => _currentWallet.fees;
Future<int> get maxFee => _currentWallet.maxFee;
Future<String> get currentReceivingAddress =>
_currentWallet.currentReceivingAddress;
Balance get balance => _currentWallet.balance;
Future<List<isar_models.Transaction>> get transactions =>
_currentWallet.transactions;
Future<List<isar_models.UTXO>> get utxos => _currentWallet.utxos;
Future<void> refresh() async {
await _currentWallet.refresh();
notifyListeners();
}
// setter for updating on rename
set walletName(String newName) {
if (newName != _currentWallet.walletName) {
_currentWallet.walletName = newName;
notifyListeners();
}
}
String get walletName => _currentWallet.walletName;
String get walletId => _currentWallet.walletId;
bool validateAddress(String address) =>
_currentWallet.validateAddress(address);
Future<List<String>> get mnemonic => _currentWallet.mnemonic;
Future<String?> get mnemonicPassphrase => _currentWallet.mnemonicPassphrase;
Future<bool> testNetworkConnection() =>
_currentWallet.testNetworkConnection();
Future<void> initializeNew(
({String mnemonicPassphrase, int wordCount})? data) =>
_currentWallet.initializeNew(data);
Future<void> initializeExisting() => _currentWallet.initializeExisting();
Future<void> recoverFromMnemonic({
required String mnemonic,
String? mnemonicPassphrase,
required int maxUnusedAddressGap,
required int maxNumberOfIndexesToCheck,
required int height,
}) async {
try {
await _currentWallet.recoverFromMnemonic(
mnemonic: mnemonic,
mnemonicPassphrase: mnemonicPassphrase,
maxUnusedAddressGap: maxUnusedAddressGap,
maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck,
height: height,
);
} catch (e, s) {
Logging.instance.log("e: $e, S: $s", level: LogLevel.Error);
rethrow;
}
}
Future<void> exitCurrentWallet() async {
final name = _currentWallet.walletName;
final id = _currentWallet.walletId;
await _backgroundRefreshListener?.cancel();
_backgroundRefreshListener = null;
await _nodeStatusListener?.cancel();
_nodeStatusListener = null;
await _currentWallet.exit();
Logging.instance.log("manager.exitCurrentWallet completed for $id $name",
level: LogLevel.Info);
}
Future<void> fullRescan(
int maxUnusedAddressGap, int maxNumberOfIndexesToCheck) async {
try {
await _currentWallet.fullRescan(
maxUnusedAddressGap, maxNumberOfIndexesToCheck);
} catch (e) {
rethrow;
}
}
bool get isConnected => _currentWallet.isConnected;
Future<Amount> estimateFeeFor(Amount amount, int feeRate) async {
return _currentWallet.estimateFeeFor(amount, feeRate);
}
Future<bool> generateNewAddress() async {
final success = await _currentWallet.generateNewAddress();
if (success) {
notifyListeners();
}
return success;
}
int get currentHeight => _currentWallet.storedChainHeight;
bool get hasPaynymSupport => _currentWallet is PaynymWalletInterface;
bool get hasCoinControlSupport => _currentWallet is CoinControlInterface;
bool get hasOrdinalsSupport => _currentWallet is OrdinalsInterface;
bool get hasTokenSupport => _currentWallet.coin == Coin.ethereum;
bool get hasWhirlpoolSupport => false;
bool get hasFusionSupport => _currentWallet is FusionWalletInterface;
int get rescanOnOpenVersion =>
DB.instance.get<dynamic>(
boxName: DB.boxNameDBInfo,
key: "rescan_on_open_$walletId",
) as int? ??
0;
Future<void> resetRescanOnOpen() async {
await DB.instance.delete<dynamic>(
key: "rescan_on_open_$walletId",
boxName: DB.boxNameDBInfo,
);
}
// TODO: re enable once xpubs have been redone
bool get hasXPub => false; //_currentWallet is XPubAble;
Future<String> get xpub async {
if (!hasXPub) {
throw Exception(
"Tried to read xpub from wallet that does not support it");
}
return (_currentWallet as XPubAble).xpub;
}
}

View file

@ -1,6 +1,6 @@
/*
/*
* This file is part of Stack Wallet.
*
*
* Copyright (c) 2023 Cypher Stack
* All Rights Reserved.
* The code is distributed under GPLv3 license, see LICENSE file for details.

View file

@ -50,6 +50,9 @@ class WalletInfo implements IsarId {
/// The highest block height the wallet has scanned.
final int cachedChainHeight;
/// The block at which this wallet was or should be restored from
final int restoreHeight;
// TODO: store these in other data s
// Should contain specific things based on certain coins only
@ -247,6 +250,7 @@ class WalletInfo implements IsarId {
this.cachedReceivingAddress = "",
this.favouriteOrderIndex = 0,
this.cachedChainHeight = 0,
this.restoreHeight = 0,
this.isMnemonicVerified = false,
this.cachedBalanceString,
this.otherDataJsonString,
@ -257,6 +261,8 @@ class WalletInfo implements IsarId {
static WalletInfo createNew({
required Coin coin,
required String name,
int restoreHeight = 0,
String? walletIdOverride,
}) {
// TODO: make Coin aware of these
// ex.
@ -293,10 +299,11 @@ class WalletInfo implements IsarId {
return WalletInfo(
coinName: coin.name,
walletId: const Uuid().v1(),
walletId: walletIdOverride ?? const Uuid().v1(),
name: name,
walletType: walletType,
mainAddressType: mainAddressType,
restoreHeight: restoreHeight,
);
}
@ -308,6 +315,7 @@ class WalletInfo implements IsarId {
bool? isMnemonicVerified,
String? cachedBalanceString,
String? cachedReceivingAddress,
int? restoreHeight,
Map<String, dynamic>? otherData,
}) {
return WalletInfo(
@ -320,6 +328,7 @@ class WalletInfo implements IsarId {
cachedChainHeight: cachedChainHeight ?? this.cachedChainHeight,
isMnemonicVerified: isMnemonicVerified ?? this.isMnemonicVerified,
cachedBalanceString: cachedBalanceString ?? this.cachedBalanceString,
restoreHeight: restoreHeight ?? this.restoreHeight,
cachedReceivingAddress:
cachedReceivingAddress ?? this.cachedReceivingAddress,
otherDataJsonString:

View file

@ -6,7 +6,7 @@ import 'package:stackwallet/services/node_service.dart';
import 'package:stackwallet/utilities/amount/amount.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/wallets/crypto_currency/coins/bitcoin.dart';
import 'package:stackwallet/wallets/wallet/bip39_hd_wallet.dart';
import 'package:stackwallet/wallets/wallet/intermediate/bip39_hd_wallet.dart';
import 'package:stackwallet/wallets/wallet/mixins/electrumx_mixin.dart';
import 'package:tuple/tuple.dart';

View file

@ -15,8 +15,8 @@ import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart';
import 'package:stackwallet/utilities/extensions/extensions.dart';
import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/wallets/crypto_currency/coins/bitcoin.dart';
import 'package:stackwallet/wallets/wallet/bip39_hd_wallet.dart';
import 'package:stackwallet/wallets/crypto_currency/coins/bitcoincash.dart';
import 'package:stackwallet/wallets/wallet/intermediate/bip39_hd_wallet.dart';
import 'package:stackwallet/wallets/wallet/mixins/electrumx_mixin.dart';
class BitcoincashWallet extends Bip39HDWallet with ElectrumXMixin {
@ -28,7 +28,7 @@ class BitcoincashWallet extends Bip39HDWallet with ElectrumXMixin {
required NodeService nodeService,
}) {
// TODO: [prio=low] ensure this hack isn't needed
assert(cryptoCurrency is Bitcoin);
assert(cryptoCurrency is Bitcoincash);
this.nodeService = nodeService;
}

View file

@ -5,7 +5,7 @@ import 'package:stackwallet/utilities/amount/amount.dart';
import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/utilities/test_epic_box_connection.dart';
import 'package:stackwallet/wallets/models/tx_data.dart';
import 'package:stackwallet/wallets/wallet/bip39_wallet.dart';
import 'package:stackwallet/wallets/wallet/intermediate/bip39_wallet.dart';
class EpiccashWallet extends Bip39Wallet {
final NodeService nodeService;

View file

@ -7,7 +7,7 @@ import 'package:stackwallet/utilities/amount/amount.dart';
import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart';
import 'package:stackwallet/wallets/crypto_currency/bip39_hd_currency.dart';
import 'package:stackwallet/wallets/models/tx_data.dart';
import 'package:stackwallet/wallets/wallet/bip39_wallet.dart';
import 'package:stackwallet/wallets/wallet/intermediate/bip39_wallet.dart';
abstract class Bip39HDWallet<T extends Bip39HDCurrency> extends Bip39Wallet<T> {
Bip39HDWallet(super.cryptoCurrency);

View file

@ -1,39 +1,11 @@
import 'package:stackwallet/exceptions/sw_exception.dart';
import 'package:stackwallet/wallets/crypto_currency/bip39_currency.dart';
import 'package:stackwallet/wallets/wallet/mixins/mnemonic_based_wallet.dart';
import 'package:stackwallet/wallets/wallet/wallet.dart';
abstract class Bip39Wallet<T extends Bip39Currency> extends Wallet<T> {
abstract class Bip39Wallet<T extends Bip39Currency> extends Wallet<T>
with MnemonicBasedWallet {
Bip39Wallet(super.cryptoCurrency);
Future<String> getMnemonic() async {
final mnemonic = await secureStorageInterface.read(
key: Wallet.mnemonicKey(walletId: info.walletId),
);
if (mnemonic == null) {
throw SWException("mnemonic has not been set");
}
return mnemonic;
}
Future<List<String>> getMnemonicAsWords() async {
final mnemonic = await getMnemonic();
return mnemonic.split(" ");
}
Future<String> getMnemonicPassphrase() async {
final mnemonicPassphrase = await secureStorageInterface.read(
key: Wallet.mnemonicPassphraseKey(walletId: info.walletId),
);
if (mnemonicPassphrase == null) {
throw SWException("mnemonicPassphrase has not been set");
}
return mnemonicPassphrase;
}
// ========== Private ========================================================
// ========== Overrides ======================================================

View file

@ -13,7 +13,7 @@ import 'package:stackwallet/utilities/amount/amount.dart';
import 'package:stackwallet/utilities/default_nodes.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/logger.dart';
import 'package:stackwallet/wallets/wallet/bip39_hd_wallet.dart';
import 'package:stackwallet/wallets/wallet/intermediate/bip39_hd_wallet.dart';
import 'package:uuid/uuid.dart';
mixin ElectrumXMixin on Bip39HDWallet {

View file

@ -0,0 +1,35 @@
import 'package:stackwallet/exceptions/sw_exception.dart';
import 'package:stackwallet/wallets/wallet/wallet.dart';
import '../../crypto_currency/crypto_currency.dart';
mixin MnemonicBasedWallet<T extends CryptoCurrency> on Wallet<T> {
Future<String> getMnemonic() async {
final mnemonic = await secureStorageInterface.read(
key: Wallet.mnemonicKey(walletId: info.walletId),
);
if (mnemonic == null) {
throw SWException("mnemonic has not been set");
}
return mnemonic;
}
Future<List<String>> getMnemonicAsWords() async {
final mnemonic = await getMnemonic();
return mnemonic.split(" ");
}
Future<String> getMnemonicPassphrase() async {
final mnemonicPassphrase = await secureStorageInterface.read(
key: Wallet.mnemonicPassphraseKey(walletId: info.walletId),
);
if (mnemonicPassphrase == null) {
throw SWException("mnemonicPassphrase has not been set");
}
return mnemonicPassphrase;
}
}

View file

@ -11,7 +11,7 @@ import 'package:stackwallet/pages/send_view/send_view.dart';
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/services/coins/bitcoin/bitcoin_wallet.dart';
import 'package:stackwallet/services/coins/coin_service.dart';
import 'package:stackwallet/services/coins/manager.dart';
import 'package:stackwallet/services/locale_service.dart';
import 'package:stackwallet/services/node_service.dart';
import 'package:stackwallet/services/wallets.dart';

View file

@ -9,7 +9,7 @@ import 'package:mockito/annotations.dart';
// import 'package:stackwallet/notifications/campfire_alert.dart';
// import 'package:stackwallet/pages/address_book_view/subviews/add_address_book_entry_view.dart';
import 'package:stackwallet/services/address_book_service.dart';
import 'package:stackwallet/services/coins/manager.dart';
import 'package:stackwallet/utilities/barcode_scanner_interface.dart';
// import 'package:stackwallet/utilities/clipboard_interface.dart';
// import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';

View file

@ -13,7 +13,7 @@ import 'package:mockito/annotations.dart';
// import 'package:stackwallet/models/models.dart';
// import 'package:stackwallet/pages/address_book_view/subviews/address_book_entry_details_view.dart';
import 'package:stackwallet/services/address_book_service.dart';
import 'package:stackwallet/services/coins/manager.dart';
import 'package:stackwallet/services/locale_service.dart';
import 'package:stackwallet/services/notes_service.dart';
// import 'package:stackwallet/utilities/clipboard_interface.dart';

View file

@ -10,7 +10,7 @@
// import 'package:stackwallet/services/address_book_service.dart';
import 'package:mockito/annotations.dart';
import 'package:stackwallet/services/address_book_service.dart';
import 'package:stackwallet/services/coins/manager.dart';
// import 'package:stackwallet/utilities/clipboard_interface.dart';
// import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
// import 'package:stackwallet/widgets/custom_buttons/gradient_button.dart';

View file

@ -1,7 +1,7 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
// import 'package:stackwallet/pages/pinpad_views/lock_screen_view.dart';
import 'package:stackwallet/services/coins/manager.dart';
import 'package:stackwallet/services/node_service.dart';
import 'package:stackwallet/services/wallets_service.dart';

View file

@ -5,7 +5,7 @@ import 'package:mockito/annotations.dart';
// import 'package:mockito/mockito.dart';
// import 'package:stackwallet/models/lelantus_fee_data.dart';
// import 'package:stackwallet/pages/main_view.dart';
import 'package:stackwallet/services/coins/manager.dart';
import 'package:stackwallet/services/locale_service.dart';
import 'package:stackwallet/services/notes_service.dart';
import 'package:stackwallet/services/wallets_service.dart';

View file

@ -5,7 +5,7 @@ import 'package:mockito/annotations.dart';
// import 'package:mockito/mockito.dart';
// import 'package:stackwallet/models/lelantus_fee_data.dart';
// import 'package:stackwallet/pages/main_view.dart';
import 'package:stackwallet/services/coins/manager.dart';
// import 'package:stackwallet/services/event_bus/events/node_connection_status_changed_event.dart';
// import 'package:stackwallet/services/event_bus/global_event_bus.dart';
import 'package:stackwallet/services/locale_service.dart';

View file

@ -5,7 +5,7 @@ import 'package:mockito/annotations.dart';
// import 'package:mockito/mockito.dart';
// import 'package:stackwallet/models/lelantus_fee_data.dart';
// import 'package:stackwallet/pages/main_view.dart';
import 'package:stackwallet/services/coins/manager.dart';
import 'package:stackwallet/services/locale_service.dart';
import 'package:stackwallet/services/notes_service.dart';
import 'package:stackwallet/services/wallets_service.dart';

View file

@ -6,7 +6,7 @@ import 'package:mockito/annotations.dart';
// import 'package:mockito/mockito.dart';
// import 'package:stackwallet/notifications/modal_popup_dialog.dart';
// import 'package:stackwallet/pages/onboarding_view/backup_key_view.dart';
import 'package:stackwallet/services/coins/manager.dart';
// import 'package:stackwallet/widgets/custom_buttons/gradient_button.dart';
// import 'package:pretty_qr_code/pretty_qr_code.dart';
// import 'package:provider/provider.dart';

View file

@ -4,7 +4,7 @@
import 'package:mockito/annotations.dart';
// import 'package:mockito/mockito.dart';
// import 'package:stackwallet/pages/onboarding_view/backup_key_warning_view.dart';
import 'package:stackwallet/services/coins/manager.dart';
import 'package:stackwallet/services/wallets_service.dart';
// import 'package:stackwallet/widgets/custom_buttons/gradient_button.dart';
// import 'package:provider/provider.dart';

View file

@ -5,7 +5,7 @@ import 'package:mockito/annotations.dart';
// import 'package:mockito/mockito.dart';
// import 'package:stackwallet/pages/onboarding_view/create_pin_view.dart';
// import 'package:stackwallet/pages/onboarding_view/helpers/create_wallet_type.dart';
import 'package:stackwallet/services/coins/manager.dart';
import 'package:stackwallet/services/node_service.dart';
import 'package:stackwallet/services/wallets_service.dart';
// import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart';

View file

@ -10,7 +10,7 @@ import 'package:mockito/annotations.dart';
// import 'package:stackwallet/notifications/campfire_alert.dart';
// import 'package:stackwallet/pages/onboarding_view/restore_wallet_form_view.dart';
// import 'package:stackwallet/services/coins/firo/firo_wallet.dart';
import 'package:stackwallet/services/coins/manager.dart';
import 'package:stackwallet/services/node_service.dart';
import 'package:stackwallet/services/wallets_service.dart';
import 'package:stackwallet/utilities/barcode_scanner_interface.dart';

View file

@ -5,7 +5,7 @@ import 'package:mockito/annotations.dart';
// import 'package:mockito/mockito.dart';
// import 'package:stackwallet/pages/main_view.dart';
// import 'package:stackwallet/pages/onboarding_view/verify_backup_key_view.dart';
import 'package:stackwallet/services/coins/manager.dart';
// import 'package:stackwallet/widgets/custom_buttons/gradient_button.dart';
// import 'package:provider/provider.dart';
//

View file

@ -4,7 +4,7 @@
import 'package:mockito/annotations.dart';
// import 'package:mockito/mockito.dart';
// import 'package:stackwallet/pages/settings_view/settings_subviews/currency_view.dart';
import 'package:stackwallet/services/coins/manager.dart';
// import 'package:provider/provider.dart';
//
// import 'currency_view_screen_test.mocks.dart';

View file

@ -5,7 +5,7 @@ import 'package:mockito/annotations.dart';
// import 'package:mockito/mockito.dart';
// import 'package:stackwallet/notifications/campfire_alert.dart';
// import 'package:stackwallet/pages/settings_view/settings_subviews/network_settings_subviews/add_custom_node_view.dart';
import 'package:stackwallet/services/coins/manager.dart';
import 'package:stackwallet/services/node_service.dart';
// import 'package:stackwallet/widgets/custom_buttons/gradient_button.dart';

View file

@ -7,7 +7,7 @@ import 'package:mockito/annotations.dart';
// import 'package:stackwallet/notifications/campfire_alert.dart';
// import 'package:stackwallet/notifications/modal_popup_dialog.dart';
// import 'package:stackwallet/pages/settings_view/settings_subviews/network_settings_subviews/node_details_view.dart';
import 'package:stackwallet/services/coins/manager.dart';
import 'package:stackwallet/services/node_service.dart';
// import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
// import 'package:stackwallet/widgets/custom_buttons/gradient_button.dart';

View file

@ -8,7 +8,7 @@ import 'package:mockito/annotations.dart';
// import 'package:mockito/mockito.dart';
// import 'package:stackwallet/notifications/modal_popup_dialog.dart';
// import 'package:stackwallet/pages/settings_view/settings_subviews/wallet_backup_view.dart';
import 'package:stackwallet/services/coins/manager.dart';
// import 'package:stackwallet/utilities/clipboard_interface.dart';
// import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
// import 'package:stackwallet/widgets/custom_buttons/simple_button.dart';

View file

@ -8,7 +8,7 @@ import 'package:mockito/annotations.dart';
// import 'package:mockito/mockito.dart';
// import 'package:stackwallet/notifications/modal_popup_dialog.dart';
// import 'package:stackwallet/pages/settings_view/settings_subviews/wallet_settings_subviews/rescan_warning_view.dart';
import 'package:stackwallet/services/coins/manager.dart';
// import 'package:stackwallet/utilities/clipboard_interface.dart';
// import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
// import 'package:stackwallet/widgets/custom_buttons/gradient_button.dart';

View file

@ -8,7 +8,7 @@ import 'package:mockito/annotations.dart';
// import 'package:mockito/mockito.dart';
// import 'package:stackwallet/notifications/modal_popup_dialog.dart';
// import 'package:stackwallet/pages/settings_view/settings_subviews/wallet_settings_subviews/wallet_delete_mnemonic_view.dart';
import 'package:stackwallet/services/coins/manager.dart';
import 'package:stackwallet/services/wallets_service.dart';
// import 'package:stackwallet/utilities/clipboard_interface.dart';
// import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';

View file

@ -9,7 +9,7 @@ import 'package:mockito/annotations.dart';
import 'package:stackwallet/electrumx_rpc/cached_electrumx.dart';
// import 'package:stackwallet/notifications/campfire_alert.dart';
// import 'package:stackwallet/pages/settings_view/settings_subviews/wallet_settings_view.dart';
import 'package:stackwallet/services/coins/manager.dart';
import 'package:stackwallet/services/wallets_service.dart';
import 'package:stackwallet/utilities/biometrics.dart';
// import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';

View file

@ -6,7 +6,7 @@ import 'package:mockito/annotations.dart';
// import 'package:mockito/mockito.dart';
// import 'package:stackwallet/notifications/modal_popup_dialog.dart';
// import 'package:stackwallet/pages/settings_view/settings_view.dart';
import 'package:stackwallet/services/coins/manager.dart';
import 'package:stackwallet/services/wallets_service.dart';
// import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
// import 'package:stackwallet/widgets/custom_buttons/gradient_button.dart';

View file

@ -6,7 +6,7 @@
import 'package:mockito/annotations.dart';
// import 'package:mockito/mockito.dart';
// import 'package:stackwallet/pages/transaction_subviews/transaction_search_results_view.dart';
import 'package:stackwallet/services/coins/manager.dart';
import 'package:stackwallet/services/locale_service.dart';
import 'package:stackwallet/services/notes_service.dart';
// import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';

View file

@ -6,7 +6,7 @@ import 'package:mockito/annotations.dart';
// import 'package:mockito/mockito.dart';
// import 'package:stackwallet/notifications/campfire_alert.dart';
// import 'package:stackwallet/pages/wallet_view/confirm_send_view.dart';
import 'package:stackwallet/services/coins/manager.dart';
import 'package:stackwallet/services/notes_service.dart';
// import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart';
// import 'package:stackwallet/widgets/custom_buttons/gradient_button.dart';

View file

@ -5,7 +5,7 @@ import 'package:mockito/annotations.dart';
// import 'package:mockito/mockito.dart';
// import 'package:stackwallet/notifications/modal_popup_dialog.dart';
// import 'package:stackwallet/pages/wallet_view/receive_view.dart';
import 'package:stackwallet/services/coins/manager.dart';
// import 'package:stackwallet/utilities/clipboard_interface.dart';
// import 'package:stackwallet/widgets/custom_buttons/gradient_button.dart';
// import 'package:stackwallet/widgets/custom_buttons/simple_button.dart';

View file

@ -10,7 +10,7 @@ import 'package:mockito/annotations.dart';
// import 'package:stackwallet/models/lelantus_fee_data.dart';
// import 'package:stackwallet/notifications/campfire_alert.dart';
// import 'package:stackwallet/pages/wallet_view/send_view.dart';
import 'package:stackwallet/services/coins/manager.dart';
import 'package:stackwallet/services/notes_service.dart';
import 'package:stackwallet/utilities/barcode_scanner_interface.dart';
// import 'package:stackwallet/utilities/clipboard_interface.dart';

View file

@ -9,7 +9,7 @@ import 'package:mockito/annotations.dart';
// import 'package:mockito/mockito.dart';
// import 'package:stackwallet/pages/transaction_subviews/transaction_search_view.dart';
// import 'package:stackwallet/pages/wallet_view/wallet_view.dart';
import 'package:stackwallet/services/coins/manager.dart';
// import 'package:stackwallet/services/event_bus/events/node_connection_status_changed_event.dart';
// import 'package:stackwallet/services/event_bus/global_event_bus.dart';
import 'package:stackwallet/services/locale_service.dart';

View file

@ -8,7 +8,7 @@ import 'package:stackwallet/models/isar/models/isar_models.dart';
import 'package:stackwallet/models/paymint/fee_object_model.dart';
import 'package:stackwallet/services/coins/coin_service.dart';
import 'package:stackwallet/services/coins/firo/firo_wallet.dart';
import 'package:stackwallet/services/coins/manager.dart';
import 'package:stackwallet/utilities/amount/amount.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';

View file

@ -11,7 +11,7 @@ import 'package:stackwallet/models/isar/stack_theme.dart';
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/services/coins/bitcoin/bitcoin_wallet.dart';
import 'package:stackwallet/services/coins/coin_service.dart';
import 'package:stackwallet/services/coins/manager.dart';
import 'package:stackwallet/services/locale_service.dart';
import 'package:stackwallet/services/node_service.dart';
import 'package:stackwallet/services/wallets.dart';

View file

@ -11,7 +11,7 @@ import 'package:stackwallet/pages_desktop_specific/my_stack_view/coin_wallets_ta
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/services/coins/bitcoin/bitcoin_wallet.dart';
import 'package:stackwallet/services/coins/coin_service.dart';
import 'package:stackwallet/services/coins/manager.dart';
import 'package:stackwallet/services/wallets.dart';
import 'package:stackwallet/services/wallets_service.dart';
import 'package:stackwallet/themes/coin_icon_provider.dart';

View file

@ -19,7 +19,7 @@ import 'package:stackwallet/providers/global/price_provider.dart';
import 'package:stackwallet/providers/global/wallets_provider.dart';
import 'package:stackwallet/services/coins/coin_service.dart';
import 'package:stackwallet/services/coins/firo/firo_wallet.dart';
import 'package:stackwallet/services/coins/manager.dart';
import 'package:stackwallet/services/locale_service.dart';
import 'package:stackwallet/services/notes_service.dart';
import 'package:stackwallet/services/price_service.dart';

View file

@ -11,7 +11,7 @@ import 'package:stackwallet/models/isar/stack_theme.dart';
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/services/coins/bitcoin/bitcoin_wallet.dart';
import 'package:stackwallet/services/coins/coin_service.dart';
import 'package:stackwallet/services/coins/manager.dart';
import 'package:stackwallet/services/locale_service.dart';
import 'package:stackwallet/services/wallets.dart';
import 'package:stackwallet/themes/coin_icon_provider.dart';

View file

@ -8,7 +8,7 @@ import 'package:stackwallet/models/isar/stack_theme.dart';
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/services/coins/bitcoin/bitcoin_wallet.dart';
import 'package:stackwallet/services/coins/coin_service.dart';
import 'package:stackwallet/services/coins/manager.dart';
import 'package:stackwallet/services/node_service.dart';
import 'package:stackwallet/services/wallets.dart';
import 'package:stackwallet/services/wallets_service.dart';

View file

@ -10,7 +10,7 @@ import 'package:stackwallet/models/isar/stack_theme.dart';
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/services/coins/bitcoin/bitcoin_wallet.dart';
import 'package:stackwallet/services/coins/coin_service.dart';
import 'package:stackwallet/services/coins/manager.dart';
import 'package:stackwallet/services/node_service.dart';
import 'package:stackwallet/services/wallets.dart';
import 'package:stackwallet/services/wallets_service.dart';