mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2024-11-17 01:37:54 +00:00
centralized and cleaned up bip32 utils, and added mnemonic password functionality
This commit is contained in:
parent
b0c00d8ec7
commit
5b5ee30e41
52 changed files with 4388 additions and 3958 deletions
|
@ -125,6 +125,7 @@ class StackRestoringUIState extends ChangeNotifier {
|
|||
Manager? manager,
|
||||
String? address,
|
||||
String? mnemonic,
|
||||
String? mnemonicPassphrase,
|
||||
int? height,
|
||||
}) {
|
||||
_walletStates[walletId]!.restoringState = restoringStatus;
|
||||
|
@ -134,6 +135,8 @@ class StackRestoringUIState extends ChangeNotifier {
|
|||
address ?? _walletStates[walletId]!.address;
|
||||
_walletStates[walletId]!.mnemonic =
|
||||
mnemonic ?? _walletStates[walletId]!.mnemonic;
|
||||
_walletStates[walletId]!.mnemonicPassphrase =
|
||||
mnemonicPassphrase ?? _walletStates[walletId]!.mnemonicPassphrase;
|
||||
_walletStates[walletId]!.height = height ?? _walletStates[walletId]!.height;
|
||||
notifyListeners();
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ class WalletRestoreState extends ChangeNotifier {
|
|||
Manager? manager;
|
||||
String? address;
|
||||
String? mnemonic;
|
||||
String? mnemonicPassphrase;
|
||||
int? height;
|
||||
|
||||
StackRestoringStatus get restoringState => _restoringStatus;
|
||||
|
@ -27,6 +28,7 @@ class WalletRestoreState extends ChangeNotifier {
|
|||
this.manager,
|
||||
this.address,
|
||||
this.mnemonic,
|
||||
this.mnemonicPassphrase,
|
||||
this.height,
|
||||
}) {
|
||||
_restoringStatus = restoringStatus;
|
||||
|
@ -45,6 +47,7 @@ class WalletRestoreState extends ChangeNotifier {
|
|||
manager: manager,
|
||||
address: this.address,
|
||||
mnemonic: mnemonic,
|
||||
mnemonicPassphrase: mnemonicPassphrase,
|
||||
height: this.height,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -290,6 +290,7 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
|
|||
// without using them
|
||||
await manager.recoverFromMnemonic(
|
||||
mnemonic: mnemonic,
|
||||
mnemonicPassphrase: "", // TODO add ui for certain coins
|
||||
maxUnusedAddressGap: widget.coin == Coin.firo ? 50 : 20,
|
||||
maxNumberOfIndexesToCheck: 1000,
|
||||
height: height,
|
||||
|
|
|
@ -357,7 +357,9 @@ abstract class SWB {
|
|||
List<String> mnemonicList = (walletbackup['mnemonic'] as List<dynamic>)
|
||||
.map<String>((e) => e as String)
|
||||
.toList();
|
||||
String mnemonic = mnemonicList.join(" ").trim();
|
||||
final String mnemonic = mnemonicList.join(" ").trim();
|
||||
final String mnemonicPassphrase =
|
||||
walletbackup['mnemonicPassphrase'] as String? ?? "";
|
||||
|
||||
uiState?.update(
|
||||
walletId: manager.walletId,
|
||||
|
@ -403,6 +405,7 @@ abstract class SWB {
|
|||
// without using them
|
||||
await manager.recoverFromMnemonic(
|
||||
mnemonic: mnemonic,
|
||||
mnemonicPassphrase: mnemonicPassphrase,
|
||||
maxUnusedAddressGap: manager.coin == Coin.firo ? 50 : 20,
|
||||
maxNumberOfIndexesToCheck: 1000,
|
||||
height: restoreHeight,
|
||||
|
|
|
@ -109,6 +109,8 @@ class _RestoringWalletCardState extends ConsumerState<RestoringWalletCard> {
|
|||
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,
|
||||
|
@ -250,6 +252,8 @@ class _RestoringWalletCardState extends ConsumerState<RestoringWalletCard> {
|
|||
if (mnemonicList.isEmpty) {
|
||||
await manager.recoverFromMnemonic(
|
||||
mnemonic: ref.read(provider).mnemonic!,
|
||||
mnemonicPassphrase:
|
||||
ref.read(provider).mnemonicPassphrase!,
|
||||
maxUnusedAddressGap: maxUnusedAddressGap,
|
||||
maxNumberOfIndexesToCheck:
|
||||
maxNumberOfIndexesToCheck,
|
||||
|
|
|
@ -33,6 +33,7 @@ import 'package:stackwallet/services/notifications_api.dart';
|
|||
import 'package:stackwallet/services/transaction_notification_tracker.dart';
|
||||
import 'package:stackwallet/utilities/address_utils.dart';
|
||||
import 'package:stackwallet/utilities/assets.dart';
|
||||
import 'package:stackwallet/utilities/bip32_utils.dart';
|
||||
import 'package:stackwallet/utilities/constants.dart';
|
||||
import 'package:stackwallet/utilities/default_nodes.dart';
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
|
@ -55,40 +56,15 @@ const String GENESIS_HASH_MAINNET =
|
|||
const String GENESIS_HASH_TESTNET =
|
||||
"000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943";
|
||||
|
||||
bip32.BIP32 getBip32Node(
|
||||
int chain,
|
||||
int index,
|
||||
String mnemonic,
|
||||
NetworkType network,
|
||||
DerivePathType derivePathType,
|
||||
) {
|
||||
final root = getBip32Root(mnemonic, network);
|
||||
|
||||
final node = getBip32NodeFromRoot(chain, index, root, derivePathType);
|
||||
return node;
|
||||
}
|
||||
|
||||
/// wrapper for compute()
|
||||
bip32.BIP32 getBip32NodeWrapper(
|
||||
Tuple5<int, int, String, NetworkType, DerivePathType> args,
|
||||
) {
|
||||
return getBip32Node(
|
||||
args.item1,
|
||||
args.item2,
|
||||
args.item3,
|
||||
args.item4,
|
||||
args.item5,
|
||||
);
|
||||
}
|
||||
|
||||
bip32.BIP32 getBip32NodeFromRoot(
|
||||
int chain,
|
||||
int index,
|
||||
bip32.BIP32 root,
|
||||
DerivePathType derivePathType,
|
||||
) {
|
||||
String constructDerivePath({
|
||||
required DerivePathType derivePathType,
|
||||
required int networkWIF,
|
||||
int account = 0,
|
||||
required int chain,
|
||||
required int index,
|
||||
}) {
|
||||
String coinType;
|
||||
switch (root.network.wif) {
|
||||
switch (networkWIF) {
|
||||
case 0x80: // btc mainnet wif
|
||||
coinType = "0"; // btc mainnet
|
||||
break;
|
||||
|
@ -96,49 +72,25 @@ bip32.BIP32 getBip32NodeFromRoot(
|
|||
coinType = "1"; // btc testnet
|
||||
break;
|
||||
default:
|
||||
throw Exception("Invalid Bitcoin network type used!");
|
||||
throw Exception("Invalid Bitcoin network wif used!");
|
||||
}
|
||||
|
||||
int purpose;
|
||||
switch (derivePathType) {
|
||||
case DerivePathType.bip44:
|
||||
return root.derivePath("m/44'/$coinType'/0'/$chain/$index");
|
||||
purpose = 44;
|
||||
break;
|
||||
case DerivePathType.bip49:
|
||||
return root.derivePath("m/49'/$coinType'/0'/$chain/$index");
|
||||
purpose = 49;
|
||||
break;
|
||||
case DerivePathType.bip84:
|
||||
return root.derivePath("m/84'/$coinType'/0'/$chain/$index");
|
||||
purpose = 84;
|
||||
break;
|
||||
default:
|
||||
throw Exception("DerivePathType $derivePathType not supported");
|
||||
}
|
||||
}
|
||||
|
||||
/// wrapper for compute()
|
||||
bip32.BIP32 getBip32NodeFromRootWrapper(
|
||||
Tuple4<int, int, bip32.BIP32, DerivePathType> args,
|
||||
) {
|
||||
return getBip32NodeFromRoot(
|
||||
args.item1,
|
||||
args.item2,
|
||||
args.item3,
|
||||
args.item4,
|
||||
);
|
||||
}
|
||||
|
||||
bip32.BIP32 getBip32Root(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;
|
||||
}
|
||||
|
||||
/// wrapper for compute()
|
||||
bip32.BIP32 getBip32RootWrapper(Tuple2<String, NetworkType> args) {
|
||||
return getBip32Root(args.item1, args.item2);
|
||||
return "m/$purpose'/$coinType'/$account'/$chain/$index";
|
||||
}
|
||||
|
||||
class BitcoinWallet extends CoinServiceAPI
|
||||
|
@ -261,6 +213,15 @@ class BitcoinWallet extends CoinServiceAPI
|
|||
@override
|
||||
Future<List<String>> get mnemonic => _getMnemonicList();
|
||||
|
||||
@override
|
||||
Future<String?> get mnemonicString =>
|
||||
_secureStore.read(key: '${_walletId}_mnemonic');
|
||||
|
||||
@override
|
||||
Future<String?> get mnemonicPassphrase => _secureStore.read(
|
||||
key: '${_walletId}_mnemonicPassphrase',
|
||||
);
|
||||
|
||||
Future<int> get chainHeight async {
|
||||
try {
|
||||
final result = await _electrumXClient.getBlockHeadTip();
|
||||
|
@ -325,6 +286,7 @@ class BitcoinWallet extends CoinServiceAPI
|
|||
@override
|
||||
Future<void> recoverFromMnemonic({
|
||||
required String mnemonic,
|
||||
String? mnemonicPassphrase,
|
||||
required int maxUnusedAddressGap,
|
||||
required int maxNumberOfIndexesToCheck,
|
||||
required int height,
|
||||
|
@ -355,14 +317,21 @@ class BitcoinWallet extends CoinServiceAPI
|
|||
}
|
||||
// check to make sure we aren't overwriting a mnemonic
|
||||
// this should never fail
|
||||
if ((await _secureStore.read(key: '${_walletId}_mnemonic')) != null) {
|
||||
if ((await mnemonicString) != null ||
|
||||
(await this.mnemonicPassphrase) != null) {
|
||||
longMutex = false;
|
||||
throw Exception("Attempted to overwrite mnemonic on restore!");
|
||||
}
|
||||
await _secureStore.write(
|
||||
key: '${_walletId}_mnemonic', value: mnemonic.trim());
|
||||
await _secureStore.write(
|
||||
key: '${_walletId}_mnemonicPassphrase',
|
||||
value: mnemonicPassphrase ?? "",
|
||||
);
|
||||
|
||||
await _recoverWalletFromBIP32SeedPhrase(
|
||||
mnemonic: mnemonic.trim(),
|
||||
mnemonicPassphrase: mnemonicPassphrase ?? "",
|
||||
maxUnusedAddressGap: maxUnusedAddressGap,
|
||||
maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck,
|
||||
);
|
||||
|
@ -405,15 +374,14 @@ class BitcoinWallet extends CoinServiceAPI
|
|||
final Map<String, dynamic> receivingNodes = {};
|
||||
|
||||
for (int j = 0; j < txCountBatchSize; j++) {
|
||||
final node = await compute(
|
||||
getBip32NodeFromRootWrapper,
|
||||
Tuple4(
|
||||
chain,
|
||||
index + j,
|
||||
root,
|
||||
type,
|
||||
),
|
||||
final derivePath = constructDerivePath(
|
||||
derivePathType: type,
|
||||
networkWIF: root.network.wif,
|
||||
chain: chain,
|
||||
index: index + j,
|
||||
);
|
||||
final node = await Bip32Utils.getBip32NodeFromRoot(root, derivePath);
|
||||
|
||||
String addressString;
|
||||
final data = PaymentData(pubkey: node.publicKey);
|
||||
isar_models.AddressType addrType;
|
||||
|
@ -522,6 +490,7 @@ class BitcoinWallet extends CoinServiceAPI
|
|||
|
||||
Future<void> _recoverWalletFromBIP32SeedPhrase({
|
||||
required String mnemonic,
|
||||
required String mnemonicPassphrase,
|
||||
int maxUnusedAddressGap = 20,
|
||||
int maxNumberOfIndexesToCheck = 1000,
|
||||
bool isRescan = false,
|
||||
|
@ -535,7 +504,11 @@ class BitcoinWallet extends CoinServiceAPI
|
|||
Map<String, Map<String, String>> p2shChangeDerivations = {};
|
||||
Map<String, Map<String, String>> p2wpkhChangeDerivations = {};
|
||||
|
||||
final root = await compute(getBip32RootWrapper, Tuple2(mnemonic, _network));
|
||||
final root = await Bip32Utils.getBip32Root(
|
||||
mnemonic,
|
||||
mnemonicPassphrase,
|
||||
_network,
|
||||
);
|
||||
|
||||
List<isar_models.Address> p2pkhReceiveAddressArray = [];
|
||||
List<isar_models.Address> p2shReceiveAddressArray = [];
|
||||
|
@ -1350,7 +1323,8 @@ class BitcoinWallet extends CoinServiceAPI
|
|||
db: db,
|
||||
electrumXClient: electrumXClient,
|
||||
secureStorage: secureStore,
|
||||
getMnemonic: () => mnemonic,
|
||||
getMnemonicString: () => mnemonicString,
|
||||
getMnemonicPassphrase: () => mnemonicPassphrase,
|
||||
getChainHeight: () => chainHeight,
|
||||
getCurrentChangeAddress: () => currentChangeAddressP2PKH,
|
||||
estimateTxFee: estimateTxFee,
|
||||
|
@ -1361,7 +1335,6 @@ class BitcoinWallet extends CoinServiceAPI
|
|||
checkChangeAddressForTransactions:
|
||||
_checkP2PKHChangeAddressForTransactions,
|
||||
addDerivation: addDerivation,
|
||||
addDerivations: addDerivations,
|
||||
dustLimitP2PKH: DUST_LIMIT_P2PKH,
|
||||
minConfirms: MINIMUM_CONFIRMATIONS,
|
||||
);
|
||||
|
@ -1397,12 +1370,11 @@ class BitcoinWallet extends CoinServiceAPI
|
|||
}
|
||||
|
||||
Future<List<String>> _getMnemonicList() async {
|
||||
final mnemonicString =
|
||||
await _secureStore.read(key: '${_walletId}_mnemonic');
|
||||
if (mnemonicString == null) {
|
||||
final _mnemonicString = await mnemonicString;
|
||||
if (_mnemonicString == null) {
|
||||
return [];
|
||||
}
|
||||
final List<String> data = mnemonicString.split(' ');
|
||||
final List<String> data = _mnemonicString.split(' ');
|
||||
return data;
|
||||
}
|
||||
|
||||
|
@ -1490,13 +1462,14 @@ class BitcoinWallet extends CoinServiceAPI
|
|||
}
|
||||
|
||||
// this should never fail
|
||||
if ((await _secureStore.read(key: '${_walletId}_mnemonic')) != null) {
|
||||
if ((await mnemonicString) != null || (await mnemonicPassphrase) != null) {
|
||||
throw Exception(
|
||||
"Attempted to overwrite mnemonic on generate new wallet!");
|
||||
}
|
||||
await _secureStore.write(
|
||||
key: '${_walletId}_mnemonic',
|
||||
value: bip39.generateMnemonic(strength: 256));
|
||||
await _secureStore.write(key: '${_walletId}_mnemonicPassphrase', value: "");
|
||||
|
||||
// Generate and add addresses to relevant arrays
|
||||
final initialAddresses = await Future.wait([
|
||||
|
@ -1526,17 +1499,22 @@ class BitcoinWallet extends CoinServiceAPI
|
|||
int index,
|
||||
DerivePathType derivePathType,
|
||||
) async {
|
||||
final mnemonic = await _secureStore.read(key: '${_walletId}_mnemonic');
|
||||
final node = await compute(
|
||||
getBip32NodeWrapper,
|
||||
Tuple5(
|
||||
chain,
|
||||
index,
|
||||
mnemonic!,
|
||||
_network,
|
||||
derivePathType,
|
||||
),
|
||||
final _mnemonic = await mnemonicString;
|
||||
final _mnemonicPassphrase = await mnemonicPassphrase;
|
||||
|
||||
final derivePath = constructDerivePath(
|
||||
derivePathType: derivePathType,
|
||||
networkWIF: _network.wif,
|
||||
chain: chain,
|
||||
index: index,
|
||||
);
|
||||
final node = await Bip32Utils.getBip32Node(
|
||||
_mnemonic!,
|
||||
_mnemonicPassphrase!,
|
||||
_network,
|
||||
derivePath,
|
||||
);
|
||||
|
||||
final data = PaymentData(pubkey: node.publicKey);
|
||||
String address;
|
||||
isar_models.AddressType addrType;
|
||||
|
@ -2925,9 +2903,12 @@ class BitcoinWallet extends CoinServiceAPI
|
|||
await _deleteDerivations();
|
||||
|
||||
try {
|
||||
final mnemonic = await _secureStore.read(key: '${_walletId}_mnemonic');
|
||||
final _mnemonic = await mnemonicString;
|
||||
final _mnemonicPassphrase = await mnemonicPassphrase;
|
||||
|
||||
await _recoverWalletFromBIP32SeedPhrase(
|
||||
mnemonic: mnemonic!,
|
||||
mnemonic: _mnemonic!,
|
||||
mnemonicPassphrase: _mnemonicPassphrase!,
|
||||
maxUnusedAddressGap: maxUnusedAddressGap,
|
||||
maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck,
|
||||
isRescan: true,
|
||||
|
|
|
@ -31,6 +31,7 @@ import 'package:stackwallet/services/notifications_api.dart';
|
|||
import 'package:stackwallet/services/transaction_notification_tracker.dart';
|
||||
import 'package:stackwallet/utilities/address_utils.dart';
|
||||
import 'package:stackwallet/utilities/assets.dart';
|
||||
import 'package:stackwallet/utilities/bip32_utils.dart';
|
||||
import 'package:stackwallet/utilities/constants.dart';
|
||||
import 'package:stackwallet/utilities/default_nodes.dart';
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
|
@ -51,31 +52,15 @@ const String GENESIS_HASH_MAINNET =
|
|||
const String GENESIS_HASH_TESTNET =
|
||||
"000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943";
|
||||
|
||||
bip32.BIP32 getBip32Node(int chain, int index, String mnemonic,
|
||||
NetworkType network, DerivePathType derivePathType) {
|
||||
final root = getBip32Root(mnemonic, network);
|
||||
|
||||
final node = getBip32NodeFromRoot(chain, index, root, derivePathType);
|
||||
return node;
|
||||
}
|
||||
|
||||
/// wrapper for compute()
|
||||
bip32.BIP32 getBip32NodeWrapper(
|
||||
Tuple5<int, int, String, NetworkType, DerivePathType> args,
|
||||
) {
|
||||
return getBip32Node(
|
||||
args.item1,
|
||||
args.item2,
|
||||
args.item3,
|
||||
args.item4,
|
||||
args.item5,
|
||||
);
|
||||
}
|
||||
|
||||
bip32.BIP32 getBip32NodeFromRoot(
|
||||
int chain, int index, bip32.BIP32 root, DerivePathType derivePathType) {
|
||||
String constructDerivePath({
|
||||
required DerivePathType derivePathType,
|
||||
required int networkWIF,
|
||||
int account = 0,
|
||||
required int chain,
|
||||
required int index,
|
||||
}) {
|
||||
String coinType;
|
||||
switch (root.network.wif) {
|
||||
switch (networkWIF) {
|
||||
case 0x80: // bch mainnet wif
|
||||
coinType =
|
||||
derivePathType == DerivePathType.bch44 ? "145" : "0"; // bch mainnet
|
||||
|
@ -84,48 +69,23 @@ bip32.BIP32 getBip32NodeFromRoot(
|
|||
coinType = "1"; // bch testnet
|
||||
break;
|
||||
default:
|
||||
throw Exception("Invalid Bitcoincash network type used!");
|
||||
throw Exception("Invalid Bitcoincash network wif used!");
|
||||
}
|
||||
|
||||
int purpose;
|
||||
switch (derivePathType) {
|
||||
case DerivePathType.bip44:
|
||||
case DerivePathType.bch44:
|
||||
return root.derivePath("m/44'/$coinType'/0'/$chain/$index");
|
||||
case DerivePathType.bip49:
|
||||
return root.derivePath("m/49'/$coinType'/0'/$chain/$index");
|
||||
purpose = 44;
|
||||
break;
|
||||
case DerivePathType.bip84:
|
||||
purpose = 84;
|
||||
break;
|
||||
default:
|
||||
throw Exception("DerivePathType must not be null.");
|
||||
throw Exception("DerivePathType $derivePathType not supported");
|
||||
}
|
||||
}
|
||||
|
||||
/// wrapper for compute()
|
||||
bip32.BIP32 getBip32NodeFromRootWrapper(
|
||||
Tuple4<int, int, bip32.BIP32, DerivePathType> args,
|
||||
) {
|
||||
return getBip32NodeFromRoot(
|
||||
args.item1,
|
||||
args.item2,
|
||||
args.item3,
|
||||
args.item4,
|
||||
);
|
||||
}
|
||||
|
||||
bip32.BIP32 getBip32Root(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;
|
||||
}
|
||||
|
||||
/// wrapper for compute()
|
||||
bip32.BIP32 getBip32RootWrapper(Tuple2<String, NetworkType> args) {
|
||||
return getBip32Root(args.item1, args.item2);
|
||||
return "m/$purpose'/$coinType'/$account'/$chain/$index";
|
||||
}
|
||||
|
||||
class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
|
||||
|
@ -214,6 +174,15 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
|
|||
@override
|
||||
Future<List<String>> get mnemonic => _getMnemonicList();
|
||||
|
||||
@override
|
||||
Future<String?> get mnemonicString =>
|
||||
_secureStore.read(key: '${_walletId}_mnemonic');
|
||||
|
||||
@override
|
||||
Future<String?> get mnemonicPassphrase => _secureStore.read(
|
||||
key: '${_walletId}_mnemonicPassphrase',
|
||||
);
|
||||
|
||||
Future<int> get chainHeight async {
|
||||
try {
|
||||
final result = await _electrumXClient.getBlockHeadTip();
|
||||
|
@ -250,7 +219,9 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
|
|||
throw ArgumentError('$address is not currently supported');
|
||||
}
|
||||
}
|
||||
} catch (e, s) {}
|
||||
} catch (_) {
|
||||
// invalid cash addr format
|
||||
}
|
||||
try {
|
||||
decodeBase58 = bs58check.decode(address);
|
||||
} catch (err) {
|
||||
|
@ -291,6 +262,7 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
|
|||
@override
|
||||
Future<void> recoverFromMnemonic({
|
||||
required String mnemonic,
|
||||
String? mnemonicPassphrase,
|
||||
required int maxUnusedAddressGap,
|
||||
required int maxNumberOfIndexesToCheck,
|
||||
required int height,
|
||||
|
@ -321,14 +293,21 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
|
|||
}
|
||||
// check to make sure we aren't overwriting a mnemonic
|
||||
// this should never fail
|
||||
if ((await _secureStore.read(key: '${_walletId}_mnemonic')) != null) {
|
||||
if ((await mnemonicString) != null ||
|
||||
(await this.mnemonicPassphrase) != null) {
|
||||
longMutex = false;
|
||||
throw Exception("Attempted to overwrite mnemonic on restore!");
|
||||
}
|
||||
await _secureStore.write(
|
||||
key: '${_walletId}_mnemonic', value: mnemonic.trim());
|
||||
await _secureStore.write(
|
||||
key: '${_walletId}_mnemonicPassphrase',
|
||||
value: mnemonicPassphrase ?? "",
|
||||
);
|
||||
|
||||
await _recoverWalletFromBIP32SeedPhrase(
|
||||
mnemonic: mnemonic.trim(),
|
||||
mnemonicPassphrase: mnemonicPassphrase ?? "",
|
||||
maxUnusedAddressGap: maxUnusedAddressGap,
|
||||
maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck,
|
||||
coin: coin,
|
||||
|
@ -372,15 +351,14 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
|
|||
final Map<String, dynamic> receivingNodes = {};
|
||||
|
||||
for (int j = 0; j < txCountBatchSize; j++) {
|
||||
final node = await compute(
|
||||
getBip32NodeFromRootWrapper,
|
||||
Tuple4(
|
||||
chain,
|
||||
index + j,
|
||||
root,
|
||||
type,
|
||||
),
|
||||
final derivePath = constructDerivePath(
|
||||
derivePathType: type,
|
||||
networkWIF: root.network.wif,
|
||||
chain: chain,
|
||||
index: index + j,
|
||||
);
|
||||
final node = await Bip32Utils.getBip32NodeFromRoot(root, derivePath);
|
||||
|
||||
String addressString;
|
||||
final data = PaymentData(pubkey: node.publicKey);
|
||||
isar_models.AddressType addrType;
|
||||
|
@ -493,6 +471,7 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
|
|||
|
||||
Future<void> _recoverWalletFromBIP32SeedPhrase({
|
||||
required String mnemonic,
|
||||
required String mnemonicPassphrase,
|
||||
int maxUnusedAddressGap = 20,
|
||||
int maxNumberOfIndexesToCheck = 1000,
|
||||
bool isRescan = false,
|
||||
|
@ -507,7 +486,11 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
|
|||
Map<String, Map<String, String>> bch44P2pkhChangeDerivations = {};
|
||||
Map<String, Map<String, String>> p2shChangeDerivations = {};
|
||||
|
||||
final root = await compute(getBip32RootWrapper, Tuple2(mnemonic, _network));
|
||||
final root = await Bip32Utils.getBip32Root(
|
||||
mnemonic,
|
||||
mnemonicPassphrase,
|
||||
_network,
|
||||
);
|
||||
|
||||
List<isar_models.Address> bip44P2pkhReceiveAddressArray = [];
|
||||
List<isar_models.Address> bch44P2pkhReceiveAddressArray = [];
|
||||
|
@ -531,7 +514,7 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
|
|||
const txCountBatchSize = 12;
|
||||
|
||||
try {
|
||||
bool testnet = ((coin ?? null) == Coin.bitcoincashTestnet) ? true : false;
|
||||
bool testnet = ((coin) == Coin.bitcoincashTestnet) ? true : false;
|
||||
// receiving addresses
|
||||
Logging.instance
|
||||
.log("checking receiving addresses...", level: LogLevel.Info);
|
||||
|
@ -1334,12 +1317,11 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
|
|||
}
|
||||
|
||||
Future<List<String>> _getMnemonicList() async {
|
||||
final mnemonicString =
|
||||
await _secureStore.read(key: '${_walletId}_mnemonic');
|
||||
if (mnemonicString == null) {
|
||||
final _mnemonicString = await mnemonicString;
|
||||
if (_mnemonicString == null) {
|
||||
return [];
|
||||
}
|
||||
final List<String> data = mnemonicString.split(' ');
|
||||
final List<String> data = _mnemonicString.split(' ');
|
||||
return data;
|
||||
}
|
||||
|
||||
|
@ -1440,13 +1422,14 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
|
|||
}
|
||||
|
||||
// this should never fail
|
||||
if ((await _secureStore.read(key: '${_walletId}_mnemonic')) != null) {
|
||||
if ((await mnemonicString) != null || (await mnemonicPassphrase) != null) {
|
||||
throw Exception(
|
||||
"Attempted to overwrite mnemonic on generate new wallet!");
|
||||
}
|
||||
await _secureStore.write(
|
||||
key: '${_walletId}_mnemonic',
|
||||
value: bip39.generateMnemonic(strength: 256));
|
||||
await _secureStore.write(key: '${_walletId}_mnemonicPassphrase', value: "");
|
||||
|
||||
// Generate and add addresses to relevant arrays
|
||||
final initialAddresses = await Future.wait([
|
||||
|
@ -1472,17 +1455,22 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
|
|||
int index,
|
||||
DerivePathType derivePathType,
|
||||
) async {
|
||||
final mnemonic = await _secureStore.read(key: '${_walletId}_mnemonic');
|
||||
final node = await compute(
|
||||
getBip32NodeWrapper,
|
||||
Tuple5(
|
||||
chain,
|
||||
index,
|
||||
mnemonic!,
|
||||
_network,
|
||||
derivePathType,
|
||||
),
|
||||
final _mnemonic = await mnemonicString;
|
||||
final _mnemonicPassphrase = await mnemonicPassphrase;
|
||||
|
||||
final derivePath = constructDerivePath(
|
||||
derivePathType: derivePathType,
|
||||
networkWIF: _network.wif,
|
||||
chain: chain,
|
||||
index: index,
|
||||
);
|
||||
final node = await Bip32Utils.getBip32Node(
|
||||
_mnemonic!,
|
||||
_mnemonicPassphrase!,
|
||||
_network,
|
||||
derivePath,
|
||||
);
|
||||
|
||||
final data = PaymentData(pubkey: node.publicKey);
|
||||
|
||||
String address;
|
||||
|
@ -2970,9 +2958,12 @@ class BitcoinCashWallet extends CoinServiceAPI with WalletCache, WalletDB {
|
|||
await _deleteDerivations();
|
||||
|
||||
try {
|
||||
final mnemonic = await _secureStore.read(key: '${_walletId}_mnemonic');
|
||||
final _mnemonic = await mnemonicString;
|
||||
final _mnemonicPassphrase = await mnemonicPassphrase;
|
||||
|
||||
await _recoverWalletFromBIP32SeedPhrase(
|
||||
mnemonic: mnemonic!,
|
||||
mnemonic: _mnemonic!,
|
||||
mnemonicPassphrase: _mnemonicPassphrase!,
|
||||
maxUnusedAddressGap: maxUnusedAddressGap,
|
||||
maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck,
|
||||
isRescan: true,
|
||||
|
|
|
@ -263,11 +263,14 @@ abstract class CoinServiceAPI {
|
|||
bool validateAddress(String address);
|
||||
|
||||
Future<List<String>> get mnemonic;
|
||||
Future<String?> get mnemonicString;
|
||||
Future<String?> get mnemonicPassphrase;
|
||||
|
||||
Future<bool> testNetworkConnection();
|
||||
|
||||
Future<void> recoverFromMnemonic({
|
||||
required String mnemonic,
|
||||
String? mnemonicPassphrase,
|
||||
required int maxUnusedAddressGap,
|
||||
required int maxNumberOfIndexesToCheck,
|
||||
required int height,
|
||||
|
|
|
@ -32,6 +32,7 @@ import 'package:stackwallet/services/notifications_api.dart';
|
|||
import 'package:stackwallet/services/transaction_notification_tracker.dart';
|
||||
import 'package:stackwallet/utilities/address_utils.dart';
|
||||
import 'package:stackwallet/utilities/assets.dart';
|
||||
import 'package:stackwallet/utilities/bip32_utils.dart';
|
||||
import 'package:stackwallet/utilities/constants.dart';
|
||||
import 'package:stackwallet/utilities/default_nodes.dart';
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
|
@ -52,31 +53,15 @@ const String GENESIS_HASH_MAINNET =
|
|||
const String GENESIS_HASH_TESTNET =
|
||||
"bb0a78264637406b6360aad926284d544d7049f45189db5664f3c4d07350559e";
|
||||
|
||||
bip32.BIP32 getBip32Node(int chain, int index, String mnemonic,
|
||||
NetworkType network, DerivePathType derivePathType) {
|
||||
final root = getBip32Root(mnemonic, network);
|
||||
|
||||
final node = getBip32NodeFromRoot(chain, index, root, derivePathType);
|
||||
return node;
|
||||
}
|
||||
|
||||
/// wrapper for compute()
|
||||
bip32.BIP32 getBip32NodeWrapper(
|
||||
Tuple5<int, int, String, NetworkType, DerivePathType> args,
|
||||
) {
|
||||
return getBip32Node(
|
||||
args.item1,
|
||||
args.item2,
|
||||
args.item3,
|
||||
args.item4,
|
||||
args.item5,
|
||||
);
|
||||
}
|
||||
|
||||
bip32.BIP32 getBip32NodeFromRoot(
|
||||
int chain, int index, bip32.BIP32 root, DerivePathType derivePathType) {
|
||||
String constructDerivePath({
|
||||
required DerivePathType derivePathType,
|
||||
required int networkWIF,
|
||||
int account = 0,
|
||||
required int chain,
|
||||
required int index,
|
||||
}) {
|
||||
String coinType;
|
||||
switch (root.network.wif) {
|
||||
switch (networkWIF) {
|
||||
case 0x9e: // doge mainnet wif
|
||||
coinType = "3"; // doge mainnet
|
||||
break;
|
||||
|
@ -84,46 +69,19 @@ bip32.BIP32 getBip32NodeFromRoot(
|
|||
coinType = "1"; // doge testnet
|
||||
break;
|
||||
default:
|
||||
throw Exception("Invalid Dogecoin network type used!");
|
||||
throw Exception("Invalid Dogecoin network wif used!");
|
||||
}
|
||||
|
||||
int purpose;
|
||||
switch (derivePathType) {
|
||||
case DerivePathType.bip44:
|
||||
return root.derivePath("m/44'/$coinType'/0'/$chain/$index");
|
||||
purpose = 44;
|
||||
break;
|
||||
default:
|
||||
throw Exception(
|
||||
"DerivePathType null or unsupported (${DerivePathType.bip44})");
|
||||
throw Exception("DerivePathType $derivePathType not supported");
|
||||
}
|
||||
}
|
||||
|
||||
/// wrapper for compute()
|
||||
bip32.BIP32 getBip32NodeFromRootWrapper(
|
||||
Tuple4<int, int, bip32.BIP32, DerivePathType> args,
|
||||
) {
|
||||
return getBip32NodeFromRoot(
|
||||
args.item1,
|
||||
args.item2,
|
||||
args.item3,
|
||||
args.item4,
|
||||
);
|
||||
}
|
||||
|
||||
bip32.BIP32 getBip32Root(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;
|
||||
}
|
||||
|
||||
/// wrapper for compute()
|
||||
bip32.BIP32 getBip32RootWrapper(Tuple2<String, NetworkType> args) {
|
||||
return getBip32Root(args.item1, args.item2);
|
||||
return "m/$purpose'/$coinType'/$account'/$chain/$index";
|
||||
}
|
||||
|
||||
class DogecoinWallet extends CoinServiceAPI
|
||||
|
@ -222,6 +180,15 @@ class DogecoinWallet extends CoinServiceAPI
|
|||
@override
|
||||
Future<List<String>> get mnemonic => _getMnemonicList();
|
||||
|
||||
@override
|
||||
Future<String?> get mnemonicString =>
|
||||
_secureStore.read(key: '${_walletId}_mnemonic');
|
||||
|
||||
@override
|
||||
Future<String?> get mnemonicPassphrase => _secureStore.read(
|
||||
key: '${_walletId}_mnemonicPassphrase',
|
||||
);
|
||||
|
||||
Future<int> get chainHeight async {
|
||||
try {
|
||||
final result = await _electrumXClient.getBlockHeadTip();
|
||||
|
@ -281,6 +248,7 @@ class DogecoinWallet extends CoinServiceAPI
|
|||
@override
|
||||
Future<void> recoverFromMnemonic({
|
||||
required String mnemonic,
|
||||
String? mnemonicPassphrase,
|
||||
required int maxUnusedAddressGap,
|
||||
required int maxNumberOfIndexesToCheck,
|
||||
required int height,
|
||||
|
@ -311,14 +279,20 @@ class DogecoinWallet extends CoinServiceAPI
|
|||
}
|
||||
// check to make sure we aren't overwriting a mnemonic
|
||||
// this should never fail
|
||||
if ((await _secureStore.read(key: '${_walletId}_mnemonic')) != null) {
|
||||
if ((await mnemonicString) != null ||
|
||||
(await this.mnemonicPassphrase) != null) {
|
||||
longMutex = false;
|
||||
throw Exception("Attempted to overwrite mnemonic on restore!");
|
||||
}
|
||||
await _secureStore.write(
|
||||
key: '${_walletId}_mnemonic', value: mnemonic.trim());
|
||||
await _secureStore.write(
|
||||
key: '${_walletId}_mnemonicPassphrase',
|
||||
value: mnemonicPassphrase ?? "",
|
||||
);
|
||||
await _recoverWalletFromBIP32SeedPhrase(
|
||||
mnemonic: mnemonic.trim(),
|
||||
mnemonicPassphrase: mnemonicPassphrase ?? "",
|
||||
maxUnusedAddressGap: maxUnusedAddressGap,
|
||||
maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck,
|
||||
);
|
||||
|
@ -361,15 +335,14 @@ class DogecoinWallet extends CoinServiceAPI
|
|||
final Map<String, dynamic> receivingNodes = {};
|
||||
|
||||
for (int j = 0; j < txCountBatchSize; j++) {
|
||||
final node = await compute(
|
||||
getBip32NodeFromRootWrapper,
|
||||
Tuple4(
|
||||
chain,
|
||||
index + j,
|
||||
root,
|
||||
type,
|
||||
),
|
||||
final derivePath = constructDerivePath(
|
||||
derivePathType: type,
|
||||
networkWIF: root.network.wif,
|
||||
chain: chain,
|
||||
index: index + j,
|
||||
);
|
||||
final node = await Bip32Utils.getBip32NodeFromRoot(root, derivePath);
|
||||
|
||||
isar_models.Address address;
|
||||
switch (type) {
|
||||
case DerivePathType.bip44:
|
||||
|
@ -463,6 +436,7 @@ class DogecoinWallet extends CoinServiceAPI
|
|||
|
||||
Future<void> _recoverWalletFromBIP32SeedPhrase({
|
||||
required String mnemonic,
|
||||
required String mnemonicPassphrase,
|
||||
int maxUnusedAddressGap = 20,
|
||||
int maxNumberOfIndexesToCheck = 1000,
|
||||
bool isRescan = false,
|
||||
|
@ -472,7 +446,11 @@ class DogecoinWallet extends CoinServiceAPI
|
|||
Map<String, Map<String, String>> p2pkhReceiveDerivations = {};
|
||||
Map<String, Map<String, String>> p2pkhChangeDerivations = {};
|
||||
|
||||
final root = await compute(getBip32RootWrapper, Tuple2(mnemonic, network));
|
||||
final root = await Bip32Utils.getBip32Root(
|
||||
mnemonic,
|
||||
mnemonicPassphrase,
|
||||
network,
|
||||
);
|
||||
|
||||
List<isar_models.Address> p2pkhReceiveAddressArray = [];
|
||||
int p2pkhReceiveIndex = -1;
|
||||
|
@ -1187,12 +1165,11 @@ class DogecoinWallet extends CoinServiceAPI
|
|||
}
|
||||
|
||||
Future<List<String>> _getMnemonicList() async {
|
||||
final mnemonicString =
|
||||
await _secureStore.read(key: '${_walletId}_mnemonic');
|
||||
if (mnemonicString == null) {
|
||||
final _mnemonicString = await mnemonicString;
|
||||
if (_mnemonicString == null) {
|
||||
return [];
|
||||
}
|
||||
final List<String> data = mnemonicString.split(' ');
|
||||
final List<String> data = _mnemonicString.split(' ');
|
||||
return data;
|
||||
}
|
||||
|
||||
|
@ -1280,13 +1257,17 @@ class DogecoinWallet extends CoinServiceAPI
|
|||
}
|
||||
|
||||
// this should never fail
|
||||
if ((await _secureStore.read(key: '${_walletId}_mnemonic')) != null) {
|
||||
if ((await mnemonicString) != null || (await mnemonicPassphrase) != null) {
|
||||
throw Exception(
|
||||
"Attempted to overwrite mnemonic on generate new wallet!");
|
||||
}
|
||||
await _secureStore.write(
|
||||
key: '${_walletId}_mnemonic',
|
||||
value: bip39.generateMnemonic(strength: 256));
|
||||
await _secureStore.write(
|
||||
key: '${_walletId}_mnemonicPassphrase',
|
||||
value: "",
|
||||
);
|
||||
|
||||
// Generate and add addresses
|
||||
final initialReceivingAddressP2PKH =
|
||||
|
@ -1310,17 +1291,22 @@ class DogecoinWallet extends CoinServiceAPI
|
|||
int index,
|
||||
DerivePathType derivePathType,
|
||||
) async {
|
||||
final mnemonic = await _secureStore.read(key: '${_walletId}_mnemonic');
|
||||
final node = await compute(
|
||||
getBip32NodeWrapper,
|
||||
Tuple5(
|
||||
chain,
|
||||
index,
|
||||
mnemonic!,
|
||||
network,
|
||||
derivePathType,
|
||||
),
|
||||
final _mnemonic = await mnemonicString;
|
||||
final _mnemonicPassphrase = await mnemonicPassphrase;
|
||||
|
||||
final derivePath = constructDerivePath(
|
||||
derivePathType: derivePathType,
|
||||
networkWIF: network.wif,
|
||||
chain: chain,
|
||||
index: index,
|
||||
);
|
||||
final node = await Bip32Utils.getBip32Node(
|
||||
_mnemonic!,
|
||||
_mnemonicPassphrase!,
|
||||
network,
|
||||
derivePath,
|
||||
);
|
||||
|
||||
final data = PaymentData(pubkey: node.publicKey);
|
||||
String address;
|
||||
|
||||
|
@ -2561,9 +2547,12 @@ class DogecoinWallet extends CoinServiceAPI
|
|||
await _deleteDerivations();
|
||||
|
||||
try {
|
||||
final mnemonic = await _secureStore.read(key: '${_walletId}_mnemonic');
|
||||
final _mnemonic = await mnemonicString;
|
||||
final _mnemonicPassphrase = await mnemonicPassphrase;
|
||||
|
||||
await _recoverWalletFromBIP32SeedPhrase(
|
||||
mnemonic: mnemonic!,
|
||||
mnemonic: _mnemonic!,
|
||||
mnemonicPassphrase: _mnemonicPassphrase!,
|
||||
maxUnusedAddressGap: maxUnusedAddressGap,
|
||||
maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck,
|
||||
isRescan: true,
|
||||
|
|
|
@ -1103,26 +1103,24 @@ class EpicCashWallet extends CoinServiceAPI
|
|||
bool get isRefreshing => refreshMutex;
|
||||
|
||||
@override
|
||||
// TODO: implement maxFee
|
||||
// unused for epic
|
||||
Future<int> get maxFee => throw UnimplementedError();
|
||||
|
||||
Future<List<String>> _getMnemonicList() async {
|
||||
if ((await _secureStore.read(key: '${_walletId}_mnemonic')) != null) {
|
||||
final mnemonicString =
|
||||
await _secureStore.read(key: '${_walletId}_mnemonic');
|
||||
final List<String> data = mnemonicString!.split(' ');
|
||||
String? _mnemonicString = await mnemonicString;
|
||||
if (_mnemonicString != null) {
|
||||
final List<String> data = _mnemonicString.split(' ');
|
||||
return data;
|
||||
} else {
|
||||
String? mnemonicString;
|
||||
await m.protect(() async {
|
||||
mnemonicString = await compute(
|
||||
_mnemonicString = await compute(
|
||||
_walletMnemonicWrapper,
|
||||
0,
|
||||
);
|
||||
});
|
||||
await _secureStore.write(
|
||||
key: '${_walletId}_mnemonic', value: mnemonicString);
|
||||
final List<String> data = mnemonicString!.split(' ');
|
||||
key: '${_walletId}_mnemonic', value: _mnemonicString);
|
||||
final List<String> data = _mnemonicString!.split(' ');
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
@ -1130,6 +1128,15 @@ class EpicCashWallet extends CoinServiceAPI
|
|||
@override
|
||||
Future<List<String>> get mnemonic => _getMnemonicList();
|
||||
|
||||
@override
|
||||
Future<String?> get mnemonicString =>
|
||||
_secureStore.read(key: '${_walletId}_mnemonic');
|
||||
|
||||
@override
|
||||
Future<String?> get mnemonicPassphrase => _secureStore.read(
|
||||
key: '${_walletId}_mnemonicPassphrase',
|
||||
);
|
||||
|
||||
@override
|
||||
Future<Map<String, dynamic>> prepareSend(
|
||||
{required String address,
|
||||
|
@ -1359,11 +1366,13 @@ class EpicCashWallet extends CoinServiceAPI
|
|||
double highestPercent = 0;
|
||||
|
||||
@override
|
||||
Future<void> recoverFromMnemonic(
|
||||
{required String mnemonic,
|
||||
required int maxUnusedAddressGap,
|
||||
required int maxNumberOfIndexesToCheck,
|
||||
required int height}) async {
|
||||
Future<void> recoverFromMnemonic({
|
||||
required String mnemonic,
|
||||
required String mnemonicPassphrase, // unused in epic
|
||||
required int maxUnusedAddressGap,
|
||||
required int maxNumberOfIndexesToCheck,
|
||||
required int height,
|
||||
}) async {
|
||||
try {
|
||||
await _prefs.init();
|
||||
await updateNode(false);
|
||||
|
|
|
@ -4,7 +4,6 @@ import 'dart:io';
|
|||
import 'dart:isolate';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:bip32/bip32.dart' as bip32;
|
||||
import 'package:bip39/bip39.dart' as bip39;
|
||||
import 'package:bitcoindart/bitcoindart.dart';
|
||||
import 'package:decimal/decimal.dart';
|
||||
|
@ -25,6 +24,7 @@ import 'package:stackwallet/services/event_bus/events/global/refresh_percent_cha
|
|||
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/firo_hive.dart';
|
||||
import 'package:stackwallet/services/mixins/wallet_cache.dart';
|
||||
import 'package:stackwallet/services/mixins/wallet_db.dart';
|
||||
import 'package:stackwallet/services/node_service.dart';
|
||||
|
@ -32,6 +32,7 @@ import 'package:stackwallet/services/notifications_api.dart';
|
|||
import 'package:stackwallet/services/transaction_notification_tracker.dart';
|
||||
import 'package:stackwallet/utilities/address_utils.dart';
|
||||
import 'package:stackwallet/utilities/assets.dart';
|
||||
import 'package:stackwallet/utilities/bip32_utils.dart';
|
||||
import 'package:stackwallet/utilities/constants.dart';
|
||||
import 'package:stackwallet/utilities/default_nodes.dart';
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
|
@ -43,8 +44,6 @@ import 'package:stackwallet/utilities/prefs.dart';
|
|||
import 'package:tuple/tuple.dart';
|
||||
import 'package:uuid/uuid.dart';
|
||||
|
||||
import '../../mixins/firo_hive.dart';
|
||||
|
||||
const DUST_LIMIT = 1000;
|
||||
const MINIMUM_CONFIRMATIONS = 1;
|
||||
const MINT_LIMIT = 100100000000;
|
||||
|
@ -102,6 +101,7 @@ Future<void> executeNative(Map<String, dynamic> arguments) async {
|
|||
final address = arguments['address'] as String;
|
||||
final subtractFeeFromAmount = arguments['subtractFeeFromAmount'] as bool;
|
||||
final mnemonic = arguments['mnemonic'] as String;
|
||||
final mnemonicPassphrase = arguments['mnemonicPassphrase'] as String;
|
||||
final index = arguments['index'] as int;
|
||||
final lelantusEntries =
|
||||
arguments['lelantusEntries'] as List<DartLelantusEntry>;
|
||||
|
@ -115,6 +115,7 @@ Future<void> executeNative(Map<String, dynamic> arguments) async {
|
|||
address,
|
||||
subtractFeeFromAmount,
|
||||
mnemonic,
|
||||
mnemonicPassphrase,
|
||||
index,
|
||||
lelantusEntries,
|
||||
locktime,
|
||||
|
@ -143,11 +144,13 @@ Future<void> executeNative(Map<String, dynamic> arguments) async {
|
|||
final setDataMap = arguments['setDataMap'] as Map;
|
||||
final usedSerialNumbers = arguments['usedSerialNumbers'] as List?;
|
||||
final mnemonic = arguments['mnemonic'] as String;
|
||||
final mnemonicPassphrase = arguments['mnemonicPassphrase'] as String;
|
||||
final coin = arguments['coin'] as Coin;
|
||||
final network = arguments['network'] as NetworkType?;
|
||||
if (!(usedSerialNumbers == null || network == null)) {
|
||||
var restoreData = await isolateRestore(
|
||||
mnemonic,
|
||||
mnemonicPassphrase,
|
||||
coin,
|
||||
latestSetId,
|
||||
setDataMap,
|
||||
|
@ -159,11 +162,13 @@ Future<void> executeNative(Map<String, dynamic> arguments) async {
|
|||
}
|
||||
} else if (function == "isolateDerive") {
|
||||
final mnemonic = arguments['mnemonic'] as String;
|
||||
final mnemonicPassphrase = arguments['mnemonicPassphrase'] as String;
|
||||
final from = arguments['from'] as int;
|
||||
final to = arguments['to'] as int;
|
||||
final network = arguments['network'] as NetworkType?;
|
||||
if (!(network == null)) {
|
||||
var derived = await isolateDerive(mnemonic, from, to, network);
|
||||
var derived = await isolateDerive(
|
||||
mnemonic, mnemonicPassphrase, from, to, network);
|
||||
sendPort.send(derived);
|
||||
return;
|
||||
}
|
||||
|
@ -192,13 +197,31 @@ void stop(ReceivePort port) {
|
|||
}
|
||||
|
||||
Future<Map<String, dynamic>> isolateDerive(
|
||||
String mnemonic, int from, int to, NetworkType _network) async {
|
||||
String mnemonic,
|
||||
String mnemonicPassphrase,
|
||||
int from,
|
||||
int to,
|
||||
NetworkType _network,
|
||||
) async {
|
||||
Map<String, dynamic> result = {};
|
||||
Map<String, dynamic> allReceive = {};
|
||||
Map<String, dynamic> allChange = {};
|
||||
final root = getBip32Root(mnemonic, _network);
|
||||
final root = await Bip32Utils.getBip32Root(
|
||||
mnemonic,
|
||||
mnemonicPassphrase,
|
||||
_network,
|
||||
);
|
||||
|
||||
for (int i = from; i < to; i++) {
|
||||
var currentNode = getBip32NodeFromRoot(0, i, root);
|
||||
final derivePathReceiving = constructDerivePath(
|
||||
networkWIF: _network.wif,
|
||||
chain: 0,
|
||||
index: i,
|
||||
);
|
||||
var currentNode = await Bip32Utils.getBip32NodeFromRoot(
|
||||
root,
|
||||
derivePathReceiving,
|
||||
);
|
||||
var address = P2PKH(
|
||||
network: _network, data: PaymentData(pubkey: currentNode.publicKey))
|
||||
.data
|
||||
|
@ -209,7 +232,15 @@ Future<Map<String, dynamic>> isolateDerive(
|
|||
"address": address,
|
||||
};
|
||||
|
||||
currentNode = getBip32NodeFromRoot(1, i, root);
|
||||
final derivePathChange = constructDerivePath(
|
||||
networkWIF: _network.wif,
|
||||
chain: 0,
|
||||
index: i,
|
||||
);
|
||||
currentNode = await Bip32Utils.getBip32NodeFromRoot(
|
||||
root,
|
||||
derivePathChange,
|
||||
);
|
||||
address = P2PKH(
|
||||
network: _network, data: PaymentData(pubkey: currentNode.publicKey))
|
||||
.data
|
||||
|
@ -230,6 +261,7 @@ Future<Map<String, dynamic>> isolateDerive(
|
|||
|
||||
Future<Map<String, dynamic>> isolateRestore(
|
||||
String mnemonic,
|
||||
String mnemonicPassphrase,
|
||||
Coin coin,
|
||||
int _latestSetId,
|
||||
Map<dynamic, dynamic> _setDataMap,
|
||||
|
@ -250,9 +282,19 @@ Future<Map<String, dynamic>> isolateRestore(
|
|||
usedSerialNumbersSet.add(usedSerialNumbers[ind]);
|
||||
}
|
||||
|
||||
final root = getBip32Root(mnemonic, network);
|
||||
final root = await Bip32Utils.getBip32Root(
|
||||
mnemonic,
|
||||
mnemonicPassphrase,
|
||||
network,
|
||||
);
|
||||
while (currentIndex < lastFoundIndex + 50) {
|
||||
final mintKeyPair = getBip32NodeFromRoot(MINT_INDEX, currentIndex, root);
|
||||
final _derivePath = constructDerivePath(
|
||||
networkWIF: network.wif,
|
||||
chain: MINT_INDEX,
|
||||
index: currentIndex,
|
||||
);
|
||||
final mintKeyPair =
|
||||
await Bip32Utils.getBip32NodeFromRoot(root, _derivePath);
|
||||
final mintTag = CreateTag(
|
||||
Format.uint8listToString(mintKeyPair.privateKey!),
|
||||
currentIndex,
|
||||
|
@ -300,7 +342,14 @@ Future<Map<String, dynamic>> isolateRestore(
|
|||
.log("amount $amount used $isUsed", level: LogLevel.Info);
|
||||
} else {
|
||||
final keyPath = GetAesKeyPath(foundCoin[0] as String);
|
||||
final aesKeyPair = getBip32NodeFromRoot(JMINT_INDEX, keyPath, root);
|
||||
final derivePath = constructDerivePath(
|
||||
networkWIF: network.wif,
|
||||
chain: JMINT_INDEX,
|
||||
index: keyPath,
|
||||
);
|
||||
final aesKeyPair =
|
||||
await Bip32Utils.getBip32NodeFromRoot(root, derivePath);
|
||||
|
||||
if (aesKeyPair.privateKey != null) {
|
||||
final aesPrivateKey =
|
||||
Format.uint8listToString(aesKeyPair.privateKey!);
|
||||
|
@ -491,6 +540,7 @@ Future<dynamic> isolateCreateJoinSplitTransaction(
|
|||
String address,
|
||||
bool subtractFeeFromAmount,
|
||||
String mnemonic,
|
||||
String mnemonicPassphrase,
|
||||
int index,
|
||||
List<DartLelantusEntry> lelantusEntries,
|
||||
int locktime,
|
||||
|
@ -521,8 +571,17 @@ Future<dynamic> isolateCreateJoinSplitTransaction(
|
|||
4294967295,
|
||||
Uint8List(0),
|
||||
);
|
||||
|
||||
final jmintKeyPair = getBip32Node(MINT_INDEX, index, mnemonic, _network);
|
||||
final derivePath = constructDerivePath(
|
||||
networkWIF: _network.wif,
|
||||
chain: MINT_INDEX,
|
||||
index: index,
|
||||
);
|
||||
final jmintKeyPair = await Bip32Utils.getBip32Node(
|
||||
mnemonic,
|
||||
mnemonicPassphrase,
|
||||
_network,
|
||||
derivePath,
|
||||
);
|
||||
|
||||
final String jmintprivatekey =
|
||||
Format.uint8listToString(jmintKeyPair.privateKey!);
|
||||
|
@ -530,7 +589,17 @@ Future<dynamic> isolateCreateJoinSplitTransaction(
|
|||
final keyPath = getMintKeyPath(changeToMint, jmintprivatekey, index,
|
||||
isTestnet: coin == Coin.firoTestNet);
|
||||
|
||||
final aesKeyPair = getBip32Node(JMINT_INDEX, keyPath, mnemonic, _network);
|
||||
final _derivePath = constructDerivePath(
|
||||
networkWIF: _network.wif,
|
||||
chain: JMINT_INDEX,
|
||||
index: keyPath,
|
||||
);
|
||||
final aesKeyPair = await Bip32Utils.getBip32Node(
|
||||
mnemonic,
|
||||
mnemonicPassphrase,
|
||||
_network,
|
||||
_derivePath,
|
||||
);
|
||||
final aesPrivateKey = Format.uint8listToString(aesKeyPair.privateKey!);
|
||||
|
||||
final jmintData = createJMintScript(
|
||||
|
@ -659,29 +728,15 @@ Future<int> getBlockHead(ElectrumX client) async {
|
|||
}
|
||||
// end of isolates
|
||||
|
||||
bip32.BIP32 getBip32Node(
|
||||
int chain, int index, String mnemonic, NetworkType network) {
|
||||
final root = getBip32Root(mnemonic, network);
|
||||
|
||||
final node = getBip32NodeFromRoot(chain, index, root);
|
||||
return node;
|
||||
}
|
||||
|
||||
/// wrapper for compute()
|
||||
bip32.BIP32 getBip32NodeWrapper(
|
||||
Tuple4<int, int, String, NetworkType> args,
|
||||
) {
|
||||
return getBip32Node(
|
||||
args.item1,
|
||||
args.item2,
|
||||
args.item3,
|
||||
args.item4,
|
||||
);
|
||||
}
|
||||
|
||||
bip32.BIP32 getBip32NodeFromRoot(int chain, int index, bip32.BIP32 root) {
|
||||
String constructDerivePath({
|
||||
// required DerivePathType derivePathType,
|
||||
required int networkWIF,
|
||||
int account = 0,
|
||||
required int chain,
|
||||
required int index,
|
||||
}) {
|
||||
String coinType;
|
||||
switch (root.network.wif) {
|
||||
switch (networkWIF) {
|
||||
case 0xd2: // firo mainnet wif
|
||||
coinType = "136"; // firo mainnet
|
||||
break;
|
||||
|
@ -689,41 +744,19 @@ bip32.BIP32 getBip32NodeFromRoot(int chain, int index, bip32.BIP32 root) {
|
|||
coinType = "1"; // firo testnet
|
||||
break;
|
||||
default:
|
||||
throw Exception("Invalid Bitcoin network type used!");
|
||||
throw Exception("Invalid Firo network wif used!");
|
||||
}
|
||||
|
||||
final node = root.derivePath("m/44'/$coinType'/0'/$chain/$index");
|
||||
return node;
|
||||
}
|
||||
int purpose;
|
||||
// switch (derivePathType) {
|
||||
// case DerivePathType.bip44:
|
||||
purpose = 44;
|
||||
// break;
|
||||
// default:
|
||||
// throw Exception("DerivePathType $derivePathType not supported");
|
||||
// }
|
||||
|
||||
/// wrapper for compute()
|
||||
bip32.BIP32 getBip32NodeFromRootWrapper(
|
||||
Tuple3<int, int, bip32.BIP32> args,
|
||||
) {
|
||||
return getBip32NodeFromRoot(
|
||||
args.item1,
|
||||
args.item2,
|
||||
args.item3,
|
||||
);
|
||||
}
|
||||
|
||||
bip32.BIP32 getBip32Root(String mnemonic, NetworkType network) {
|
||||
final seed = bip39.mnemonicToSeed(mnemonic);
|
||||
final firoNetworkType = bip32.NetworkType(
|
||||
wif: network.wif,
|
||||
bip32: bip32.Bip32Type(
|
||||
public: network.bip32.public,
|
||||
private: network.bip32.private,
|
||||
),
|
||||
);
|
||||
|
||||
final root = bip32.BIP32.fromSeed(seed, firoNetworkType);
|
||||
return root;
|
||||
}
|
||||
|
||||
/// wrapper for compute()
|
||||
bip32.BIP32 getBip32RootWrapper(Tuple2<String, NetworkType> args) {
|
||||
return getBip32Root(args.item1, args.item2);
|
||||
return "m/$purpose'/$coinType'/$account'/$chain/$index";
|
||||
}
|
||||
|
||||
Future<String> _getMintScriptWrapper(
|
||||
|
@ -795,6 +828,15 @@ class FiroWallet extends CoinServiceAPI with WalletCache, WalletDB, FiroHive {
|
|||
@override
|
||||
Future<List<String>> get mnemonic => _getMnemonicList();
|
||||
|
||||
@override
|
||||
Future<String?> get mnemonicString =>
|
||||
_secureStore.read(key: '${_walletId}_mnemonic');
|
||||
|
||||
@override
|
||||
Future<String?> get mnemonicPassphrase => _secureStore.read(
|
||||
key: '${_walletId}_mnemonicPassphrase',
|
||||
);
|
||||
|
||||
@override
|
||||
bool validateAddress(String address) {
|
||||
return Address.validateAddress(address, _network);
|
||||
|
@ -1178,12 +1220,11 @@ class FiroWallet extends CoinServiceAPI with WalletCache, WalletDB, FiroHive {
|
|||
// }
|
||||
|
||||
Future<List<String>> _getMnemonicList() async {
|
||||
final mnemonicString =
|
||||
await _secureStore.read(key: '${_walletId}_mnemonic');
|
||||
if (mnemonicString == null) {
|
||||
final _mnemonicString = await mnemonicString;
|
||||
if (_mnemonicString == null) {
|
||||
return [];
|
||||
}
|
||||
final List<String> data = mnemonicString.split(' ');
|
||||
final List<String> data = _mnemonicString.split(' ');
|
||||
return data;
|
||||
}
|
||||
|
||||
|
@ -2085,10 +2126,17 @@ class FiroWallet extends CoinServiceAPI with WalletCache, WalletDB, FiroHive {
|
|||
}
|
||||
|
||||
// this should never fail as overwriting a mnemonic is big bad
|
||||
assert((await _secureStore.read(key: '${_walletId}_mnemonic')) == null);
|
||||
if ((await mnemonicString) != null || (await mnemonicPassphrase) != null) {
|
||||
longMutex = false;
|
||||
throw Exception("Attempted to overwrite mnemonic on initialize new!");
|
||||
}
|
||||
await _secureStore.write(
|
||||
key: '${_walletId}_mnemonic',
|
||||
value: bip39.generateMnemonic(strength: 256));
|
||||
await _secureStore.write(
|
||||
key: '${_walletId}_mnemonicPassphrase',
|
||||
value: "",
|
||||
);
|
||||
|
||||
await firoUpdateJIndex(<dynamic>[]);
|
||||
// Generate and add addresses to relevant arrays
|
||||
|
@ -2134,9 +2182,14 @@ class FiroWallet extends CoinServiceAPI with WalletCache, WalletDB, FiroHive {
|
|||
receiveDerivationsString == "{}") {
|
||||
GlobalEventBus.instance
|
||||
.fire(RefreshPercentChangedEvent(0.05, walletId));
|
||||
final mnemonic = await _secureStore.read(key: '${_walletId}_mnemonic');
|
||||
await fillAddresses(mnemonic!,
|
||||
numberOfThreads: Platform.numberOfProcessors - isolates.length - 1);
|
||||
final mnemonic = await mnemonicString;
|
||||
final mnemonicPassphrase =
|
||||
await _secureStore.read(key: '${_walletId}_mnemonicPassphrase');
|
||||
await fillAddresses(
|
||||
mnemonic!,
|
||||
mnemonicPassphrase!,
|
||||
numberOfThreads: Platform.numberOfProcessors - isolates.length - 1,
|
||||
);
|
||||
}
|
||||
|
||||
await checkReceivingAddressForTransactions();
|
||||
|
@ -2226,24 +2279,25 @@ class FiroWallet extends CoinServiceAPI with WalletCache, WalletDB, FiroHive {
|
|||
}
|
||||
|
||||
Future<List<DartLelantusEntry>> _getLelantusEntry() async {
|
||||
final mnemonic = await _secureStore.read(key: '${_walletId}_mnemonic');
|
||||
final _mnemonic = await mnemonicString;
|
||||
final _mnemonicPassphrase = await mnemonicPassphrase;
|
||||
|
||||
final List<LelantusCoin> lelantusCoins = await _getUnspentCoins();
|
||||
final root = await compute(
|
||||
getBip32RootWrapper,
|
||||
Tuple2(
|
||||
mnemonic!,
|
||||
_network,
|
||||
),
|
||||
|
||||
final root = await Bip32Utils.getBip32Root(
|
||||
_mnemonic!,
|
||||
_mnemonicPassphrase!,
|
||||
_network,
|
||||
);
|
||||
|
||||
final waitLelantusEntries = lelantusCoins.map((coin) async {
|
||||
final keyPair = await compute(
|
||||
getBip32NodeFromRootWrapper,
|
||||
Tuple3(
|
||||
MINT_INDEX,
|
||||
coin.index,
|
||||
root,
|
||||
),
|
||||
final derivePath = constructDerivePath(
|
||||
networkWIF: _network.wif,
|
||||
chain: MINT_INDEX,
|
||||
index: coin.index,
|
||||
);
|
||||
final keyPair = await Bip32Utils.getBip32NodeFromRoot(root, derivePath);
|
||||
|
||||
if (keyPair.privateKey == null) {
|
||||
Logging.instance.log("error bad key", level: LogLevel.Error);
|
||||
return DartLelantusEntry(1, 0, 0, 0, 0, '');
|
||||
|
@ -2887,16 +2941,21 @@ class FiroWallet extends CoinServiceAPI with WalletCache, WalletDB, FiroHive {
|
|||
}
|
||||
|
||||
Future<String> _getMintHex(int amount, int index) async {
|
||||
final mnemonic = await _secureStore.read(key: '${_walletId}_mnemonic');
|
||||
final mintKeyPair = await compute(
|
||||
getBip32NodeWrapper,
|
||||
Tuple4(
|
||||
MINT_INDEX,
|
||||
index,
|
||||
mnemonic!,
|
||||
_network,
|
||||
),
|
||||
final _mnemonic = await mnemonicString;
|
||||
final _mnemonicPassphrase = await mnemonicPassphrase;
|
||||
|
||||
final derivePath = constructDerivePath(
|
||||
networkWIF: _network.wif,
|
||||
chain: MINT_INDEX,
|
||||
index: index,
|
||||
);
|
||||
final mintKeyPair = await Bip32Utils.getBip32Node(
|
||||
_mnemonic!,
|
||||
_mnemonicPassphrase!,
|
||||
_network,
|
||||
derivePath,
|
||||
);
|
||||
|
||||
String keydata = Format.uint8listToString(mintKeyPair.privateKey!);
|
||||
String seedID = Format.uint8listToString(mintKeyPair.identifier);
|
||||
|
||||
|
@ -3691,8 +3750,12 @@ class FiroWallet extends CoinServiceAPI with WalletCache, WalletDB, FiroHive {
|
|||
return address!.value;
|
||||
}
|
||||
|
||||
Future<void> fillAddresses(String suppliedMnemonic,
|
||||
{int perBatch = 50, int numberOfThreads = 4}) async {
|
||||
Future<void> fillAddresses(
|
||||
String suppliedMnemonic,
|
||||
String mnemonicPassphrase, {
|
||||
int perBatch = 50,
|
||||
int numberOfThreads = 4,
|
||||
}) async {
|
||||
if (numberOfThreads <= 0) {
|
||||
numberOfThreads = 1;
|
||||
}
|
||||
|
@ -3718,6 +3781,7 @@ class FiroWallet extends CoinServiceAPI with WalletCache, WalletDB, FiroHive {
|
|||
ReceivePort receivePort = await getIsolate({
|
||||
"function": "isolateDerive",
|
||||
"mnemonic": suppliedMnemonic,
|
||||
"mnemonicPassphrase": mnemonicPassphrase,
|
||||
"from": start + i * perBatch,
|
||||
"to": start + (i + 1) * perBatch,
|
||||
"network": _network,
|
||||
|
@ -3757,8 +3821,8 @@ class FiroWallet extends CoinServiceAPI with WalletCache, WalletDB, FiroHive {
|
|||
/// [index] - This can be any integer >= 0
|
||||
Future<isar_models.Address> _generateAddressForChain(
|
||||
int chain, int index) async {
|
||||
// final wallet = await Hive.openBox(this._walletId);
|
||||
final mnemonic = await _secureStore.read(key: '${_walletId}_mnemonic');
|
||||
final _mnemonic = await mnemonicString;
|
||||
final _mnemonicPassphrase = await mnemonicPassphrase;
|
||||
Map<String, dynamic>? derivations;
|
||||
if (chain == 0) {
|
||||
final receiveDerivationsString =
|
||||
|
@ -3774,8 +3838,11 @@ class FiroWallet extends CoinServiceAPI with WalletCache, WalletDB, FiroHive {
|
|||
|
||||
if (derivations!.isNotEmpty) {
|
||||
if (derivations["$index"] == null) {
|
||||
await fillAddresses(mnemonic!,
|
||||
numberOfThreads: Platform.numberOfProcessors - isolates.length - 1);
|
||||
await fillAddresses(
|
||||
_mnemonic!,
|
||||
_mnemonicPassphrase!,
|
||||
numberOfThreads: Platform.numberOfProcessors - isolates.length - 1,
|
||||
);
|
||||
Logging.instance.log("calling _generateAddressForChain recursively",
|
||||
level: LogLevel.Info);
|
||||
return _generateAddressForChain(chain, index);
|
||||
|
@ -3792,8 +3859,18 @@ class FiroWallet extends CoinServiceAPI with WalletCache, WalletDB, FiroHive {
|
|||
: isar_models.AddressSubType.change,
|
||||
);
|
||||
} else {
|
||||
final node = await compute(
|
||||
getBip32NodeWrapper, Tuple4(chain, index, mnemonic!, _network));
|
||||
final derivePath = constructDerivePath(
|
||||
networkWIF: _network.wif,
|
||||
chain: chain,
|
||||
index: index,
|
||||
);
|
||||
final node = await Bip32Utils.getBip32Node(
|
||||
_mnemonic!,
|
||||
_mnemonicPassphrase!,
|
||||
_network,
|
||||
derivePath,
|
||||
);
|
||||
|
||||
final address =
|
||||
P2PKH(network: _network, data: PaymentData(pubkey: node.publicKey))
|
||||
.data
|
||||
|
@ -3882,8 +3959,13 @@ class FiroWallet extends CoinServiceAPI with WalletCache, WalletDB, FiroHive {
|
|||
await _deleteDerivations();
|
||||
|
||||
try {
|
||||
final mnemonic = await _secureStore.read(key: '${_walletId}_mnemonic');
|
||||
await _recoverWalletFromBIP32SeedPhrase(mnemonic!, maxUnusedAddressGap);
|
||||
final _mnemonic = await mnemonicString;
|
||||
final _mnemonicPassphrase = await mnemonicPassphrase;
|
||||
await _recoverWalletFromBIP32SeedPhrase(
|
||||
_mnemonic!,
|
||||
_mnemonicPassphrase!,
|
||||
maxUnusedAddressGap,
|
||||
);
|
||||
|
||||
longMutex = false;
|
||||
await refresh();
|
||||
|
@ -4069,6 +4151,7 @@ class FiroWallet extends CoinServiceAPI with WalletCache, WalletDB, FiroHive {
|
|||
@override
|
||||
Future<void> recoverFromMnemonic({
|
||||
required String mnemonic,
|
||||
String? mnemonicPassphrase,
|
||||
required int maxUnusedAddressGap,
|
||||
required int maxNumberOfIndexesToCheck,
|
||||
required int height,
|
||||
|
@ -4109,13 +4192,22 @@ class FiroWallet extends CoinServiceAPI with WalletCache, WalletDB, FiroHive {
|
|||
// }
|
||||
}
|
||||
// this should never fail
|
||||
if ((await _secureStore.read(key: '${_walletId}_mnemonic')) != null) {
|
||||
if ((await mnemonicString) != null ||
|
||||
(await this.mnemonicPassphrase) != null) {
|
||||
longMutex = false;
|
||||
throw Exception("Attempted to overwrite mnemonic on restore!");
|
||||
}
|
||||
await _secureStore.write(
|
||||
key: '${_walletId}_mnemonic', value: mnemonic.trim());
|
||||
await _secureStore.write(
|
||||
key: '${_walletId}_mnemonicPassphrase',
|
||||
value: mnemonicPassphrase ?? "",
|
||||
);
|
||||
await _recoverWalletFromBIP32SeedPhrase(
|
||||
mnemonic.trim(), maxUnusedAddressGap);
|
||||
mnemonic.trim(),
|
||||
mnemonicPassphrase ?? "",
|
||||
maxUnusedAddressGap,
|
||||
);
|
||||
|
||||
await compute(
|
||||
_setTestnetWrapper,
|
||||
|
@ -4151,6 +4243,7 @@ class FiroWallet extends CoinServiceAPI with WalletCache, WalletDB, FiroHive {
|
|||
|
||||
Future<void> _makeDerivations(
|
||||
String suppliedMnemonic,
|
||||
String mnemonicPassphrase,
|
||||
int maxUnusedAddressGap,
|
||||
) async {
|
||||
List<isar_models.Address> receivingAddressArray = [];
|
||||
|
@ -4163,7 +4256,7 @@ class FiroWallet extends CoinServiceAPI with WalletCache, WalletDB, FiroHive {
|
|||
int receivingGapCounter = 0;
|
||||
int changeGapCounter = 0;
|
||||
|
||||
await fillAddresses(suppliedMnemonic,
|
||||
await fillAddresses(suppliedMnemonic, mnemonicPassphrase,
|
||||
numberOfThreads: Platform.numberOfProcessors - isolates.length - 1);
|
||||
|
||||
final receiveDerivationsString =
|
||||
|
@ -4276,7 +4369,10 @@ class FiroWallet extends CoinServiceAPI with WalletCache, WalletDB, FiroHive {
|
|||
|
||||
/// Recovers wallet from [suppliedMnemonic]. Expects a valid mnemonic.
|
||||
Future<void> _recoverWalletFromBIP32SeedPhrase(
|
||||
String suppliedMnemonic, int maxUnusedAddressGap) async {
|
||||
String suppliedMnemonic,
|
||||
String mnemonicPassphrase,
|
||||
int maxUnusedAddressGap,
|
||||
) async {
|
||||
longMutex = true;
|
||||
Logging.instance
|
||||
.log("PROCESSORS ${Platform.numberOfProcessors}", level: LogLevel.Info);
|
||||
|
@ -4284,8 +4380,8 @@ class FiroWallet extends CoinServiceAPI with WalletCache, WalletDB, FiroHive {
|
|||
final latestSetId = await getLatestSetId();
|
||||
final setDataMap = getSetDataMap(latestSetId);
|
||||
final usedSerialNumbers = getUsedCoinSerials();
|
||||
final makeDerivations =
|
||||
_makeDerivations(suppliedMnemonic, maxUnusedAddressGap);
|
||||
final makeDerivations = _makeDerivations(
|
||||
suppliedMnemonic, mnemonicPassphrase, maxUnusedAddressGap);
|
||||
|
||||
await Future.wait([
|
||||
updateCachedId(walletId),
|
||||
|
@ -4307,12 +4403,15 @@ class FiroWallet extends CoinServiceAPI with WalletCache, WalletDB, FiroHive {
|
|||
|
||||
Future<void> _restore(int latestSetId, Map<dynamic, dynamic> setDataMap,
|
||||
dynamic usedSerialNumbers) async {
|
||||
final mnemonic = await _secureStore.read(key: '${_walletId}_mnemonic');
|
||||
final _mnemonic = await mnemonicString;
|
||||
final _mnemonicPassphrase = await mnemonicPassphrase;
|
||||
|
||||
final dataFuture = _refreshTransactions();
|
||||
|
||||
ReceivePort receivePort = await getIsolate({
|
||||
"function": "restore",
|
||||
"mnemonic": mnemonic,
|
||||
"mnemonic": _mnemonic,
|
||||
"mnemonicPassphrase": _mnemonicPassphrase,
|
||||
"coin": coin,
|
||||
"latestSetId": latestSetId,
|
||||
"setDataMap": setDataMap,
|
||||
|
@ -4422,8 +4521,8 @@ class FiroWallet extends CoinServiceAPI with WalletCache, WalletDB, FiroHive {
|
|||
|
||||
Future<dynamic> _createJoinSplitTransaction(
|
||||
int spendAmount, String address, bool subtractFeeFromAmount) async {
|
||||
// final price = await firoPrice;
|
||||
final mnemonic = await _secureStore.read(key: '${_walletId}_mnemonic');
|
||||
final _mnemonic = await mnemonicString;
|
||||
final _mnemonicPassphrase = await mnemonicPassphrase;
|
||||
final index = firoGetMintIndex();
|
||||
final lelantusEntry = await _getLelantusEntry();
|
||||
final anonymitySets = await fetchAnonymitySets();
|
||||
|
@ -4436,7 +4535,8 @@ class FiroWallet extends CoinServiceAPI with WalletCache, WalletDB, FiroHive {
|
|||
"spendAmount": spendAmount,
|
||||
"address": address,
|
||||
"subtractFeeFromAmount": subtractFeeFromAmount,
|
||||
"mnemonic": mnemonic,
|
||||
"mnemonic": _mnemonic,
|
||||
"mnemonicPassphrase": _mnemonicPassphrase,
|
||||
"index": index,
|
||||
// "price": price,
|
||||
"lelantusEntries": lelantusEntry,
|
||||
|
|
|
@ -30,6 +30,7 @@ import 'package:stackwallet/services/node_service.dart';
|
|||
import 'package:stackwallet/services/notifications_api.dart';
|
||||
import 'package:stackwallet/services/transaction_notification_tracker.dart';
|
||||
import 'package:stackwallet/utilities/assets.dart';
|
||||
import 'package:stackwallet/utilities/bip32_utils.dart';
|
||||
import 'package:stackwallet/utilities/constants.dart';
|
||||
import 'package:stackwallet/utilities/default_nodes.dart';
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
|
@ -51,40 +52,15 @@ const String GENESIS_HASH_MAINNET =
|
|||
const String GENESIS_HASH_TESTNET =
|
||||
"4966625a4b2851d9fdee139e56211a0d88575f59ed816ff5e6a63deb4e3e29a0";
|
||||
|
||||
bip32.BIP32 getBip32Node(
|
||||
int chain,
|
||||
int index,
|
||||
String mnemonic,
|
||||
NetworkType network,
|
||||
DerivePathType derivePathType,
|
||||
) {
|
||||
final root = getBip32Root(mnemonic, network);
|
||||
|
||||
final node = getBip32NodeFromRoot(chain, index, root, derivePathType);
|
||||
return node;
|
||||
}
|
||||
|
||||
/// wrapper for compute()
|
||||
bip32.BIP32 getBip32NodeWrapper(
|
||||
Tuple5<int, int, String, NetworkType, DerivePathType> args,
|
||||
) {
|
||||
return getBip32Node(
|
||||
args.item1,
|
||||
args.item2,
|
||||
args.item3,
|
||||
args.item4,
|
||||
args.item5,
|
||||
);
|
||||
}
|
||||
|
||||
bip32.BIP32 getBip32NodeFromRoot(
|
||||
int chain,
|
||||
int index,
|
||||
bip32.BIP32 root,
|
||||
DerivePathType derivePathType,
|
||||
) {
|
||||
String constructDerivePath({
|
||||
required DerivePathType derivePathType,
|
||||
required int networkWIF,
|
||||
int account = 0,
|
||||
required int chain,
|
||||
required int index,
|
||||
}) {
|
||||
String coinType;
|
||||
switch (root.network.wif) {
|
||||
switch (networkWIF) {
|
||||
case 0xb0: // ltc mainnet wif
|
||||
coinType = "2"; // ltc mainnet
|
||||
break;
|
||||
|
@ -92,49 +68,25 @@ bip32.BIP32 getBip32NodeFromRoot(
|
|||
coinType = "1"; // ltc testnet
|
||||
break;
|
||||
default:
|
||||
throw Exception("Invalid Litecoin network type used!");
|
||||
throw Exception("Invalid Litecoin network wif used!");
|
||||
}
|
||||
|
||||
int purpose;
|
||||
switch (derivePathType) {
|
||||
case DerivePathType.bip44:
|
||||
return root.derivePath("m/44'/$coinType'/0'/$chain/$index");
|
||||
purpose = 44;
|
||||
break;
|
||||
case DerivePathType.bip49:
|
||||
return root.derivePath("m/49'/$coinType'/0'/$chain/$index");
|
||||
purpose = 49;
|
||||
break;
|
||||
case DerivePathType.bip84:
|
||||
return root.derivePath("m/84'/$coinType'/0'/$chain/$index");
|
||||
purpose = 84;
|
||||
break;
|
||||
default:
|
||||
throw Exception("DerivePathType unsupported");
|
||||
throw Exception("DerivePathType $derivePathType not supported");
|
||||
}
|
||||
}
|
||||
|
||||
/// wrapper for compute()
|
||||
bip32.BIP32 getBip32NodeFromRootWrapper(
|
||||
Tuple4<int, int, bip32.BIP32, DerivePathType> args,
|
||||
) {
|
||||
return getBip32NodeFromRoot(
|
||||
args.item1,
|
||||
args.item2,
|
||||
args.item3,
|
||||
args.item4,
|
||||
);
|
||||
}
|
||||
|
||||
bip32.BIP32 getBip32Root(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;
|
||||
}
|
||||
|
||||
/// wrapper for compute()
|
||||
bip32.BIP32 getBip32RootWrapper(Tuple2<String, NetworkType> args) {
|
||||
return getBip32Root(args.item1, args.item2);
|
||||
return "m/$purpose'/$coinType'/$account'/$chain/$index";
|
||||
}
|
||||
|
||||
class LitecoinWallet extends CoinServiceAPI
|
||||
|
@ -236,6 +188,15 @@ class LitecoinWallet extends CoinServiceAPI
|
|||
@override
|
||||
Future<List<String>> get mnemonic => _getMnemonicList();
|
||||
|
||||
@override
|
||||
Future<String?> get mnemonicString =>
|
||||
_secureStore.read(key: '${_walletId}_mnemonic');
|
||||
|
||||
@override
|
||||
Future<String?> get mnemonicPassphrase => _secureStore.read(
|
||||
key: '${_walletId}_mnemonicPassphrase',
|
||||
);
|
||||
|
||||
Future<int> get chainHeight async {
|
||||
try {
|
||||
final result = await _electrumXClient.getBlockHeadTip();
|
||||
|
@ -300,6 +261,7 @@ class LitecoinWallet extends CoinServiceAPI
|
|||
@override
|
||||
Future<void> recoverFromMnemonic({
|
||||
required String mnemonic,
|
||||
String? mnemonicPassphrase,
|
||||
required int maxUnusedAddressGap,
|
||||
required int maxNumberOfIndexesToCheck,
|
||||
required int height,
|
||||
|
@ -339,14 +301,20 @@ class LitecoinWallet extends CoinServiceAPI
|
|||
}
|
||||
// check to make sure we aren't overwriting a mnemonic
|
||||
// this should never fail
|
||||
if ((await _secureStore.read(key: '${_walletId}_mnemonic')) != null) {
|
||||
if ((await mnemonicString) != null ||
|
||||
(await this.mnemonicPassphrase) != null) {
|
||||
longMutex = false;
|
||||
throw Exception("Attempted to overwrite mnemonic on restore!");
|
||||
}
|
||||
await _secureStore.write(
|
||||
key: '${_walletId}_mnemonic', value: mnemonic.trim());
|
||||
await _secureStore.write(
|
||||
key: '${_walletId}_mnemonicPassphrase',
|
||||
value: mnemonicPassphrase ?? "",
|
||||
);
|
||||
await _recoverWalletFromBIP32SeedPhrase(
|
||||
mnemonic: mnemonic.trim(),
|
||||
mnemonicPassphrase: mnemonicPassphrase ?? "",
|
||||
maxUnusedAddressGap: maxUnusedAddressGap,
|
||||
maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck,
|
||||
);
|
||||
|
@ -389,15 +357,14 @@ class LitecoinWallet extends CoinServiceAPI
|
|||
final Map<String, dynamic> receivingNodes = {};
|
||||
|
||||
for (int j = 0; j < txCountBatchSize; j++) {
|
||||
final node = await compute(
|
||||
getBip32NodeFromRootWrapper,
|
||||
Tuple4(
|
||||
chain,
|
||||
index + j,
|
||||
root,
|
||||
type,
|
||||
),
|
||||
final derivePath = constructDerivePath(
|
||||
derivePathType: type,
|
||||
networkWIF: root.network.wif,
|
||||
chain: chain,
|
||||
index: index + j,
|
||||
);
|
||||
final node = await Bip32Utils.getBip32NodeFromRoot(root, derivePath);
|
||||
|
||||
String addressString;
|
||||
final data = PaymentData(pubkey: node.publicKey);
|
||||
isar_models.AddressType addrType;
|
||||
|
@ -515,6 +482,7 @@ class LitecoinWallet extends CoinServiceAPI
|
|||
|
||||
Future<void> _recoverWalletFromBIP32SeedPhrase({
|
||||
required String mnemonic,
|
||||
required String mnemonicPassphrase,
|
||||
int maxUnusedAddressGap = 20,
|
||||
int maxNumberOfIndexesToCheck = 1000,
|
||||
bool isRescan = false,
|
||||
|
@ -528,7 +496,11 @@ class LitecoinWallet extends CoinServiceAPI
|
|||
Map<String, Map<String, String>> p2shChangeDerivations = {};
|
||||
Map<String, Map<String, String>> p2wpkhChangeDerivations = {};
|
||||
|
||||
final root = await compute(getBip32RootWrapper, Tuple2(mnemonic, _network));
|
||||
final root = await Bip32Utils.getBip32Root(
|
||||
mnemonic,
|
||||
mnemonicPassphrase,
|
||||
_network,
|
||||
);
|
||||
|
||||
List<isar_models.Address> p2pkhReceiveAddressArray = [];
|
||||
List<isar_models.Address> p2shReceiveAddressArray = [];
|
||||
|
@ -1321,12 +1293,11 @@ class LitecoinWallet extends CoinServiceAPI
|
|||
}
|
||||
|
||||
Future<List<String>> _getMnemonicList() async {
|
||||
final mnemonicString =
|
||||
await _secureStore.read(key: '${_walletId}_mnemonic');
|
||||
if (mnemonicString == null) {
|
||||
final _mnemonicString = await mnemonicString;
|
||||
if (_mnemonicString == null) {
|
||||
return [];
|
||||
}
|
||||
final List<String> data = mnemonicString.split(' ');
|
||||
final List<String> data = _mnemonicString.split(' ');
|
||||
return data;
|
||||
}
|
||||
|
||||
|
@ -1463,13 +1434,17 @@ class LitecoinWallet extends CoinServiceAPI
|
|||
}
|
||||
|
||||
// this should never fail
|
||||
if ((await _secureStore.read(key: '${_walletId}_mnemonic')) != null) {
|
||||
if ((await mnemonicString) != null || (await mnemonicPassphrase) != null) {
|
||||
throw Exception(
|
||||
"Attempted to overwrite mnemonic on generate new wallet!");
|
||||
}
|
||||
await _secureStore.write(
|
||||
key: '${_walletId}_mnemonic',
|
||||
value: bip39.generateMnemonic(strength: 256));
|
||||
await _secureStore.write(
|
||||
key: '${_walletId}_mnemonicPassphrase',
|
||||
value: "",
|
||||
);
|
||||
|
||||
// Generate and add addresses to relevant arrays
|
||||
final initialAddresses = await Future.wait([
|
||||
|
@ -1499,17 +1474,22 @@ class LitecoinWallet extends CoinServiceAPI
|
|||
int index,
|
||||
DerivePathType derivePathType,
|
||||
) async {
|
||||
final mnemonic = await _secureStore.read(key: '${_walletId}_mnemonic');
|
||||
final node = await compute(
|
||||
getBip32NodeWrapper,
|
||||
Tuple5(
|
||||
chain,
|
||||
index,
|
||||
mnemonic!,
|
||||
_network,
|
||||
derivePathType,
|
||||
),
|
||||
final _mnemonic = await mnemonicString;
|
||||
final _mnemonicPassphrase = await mnemonicPassphrase;
|
||||
|
||||
final derivePath = constructDerivePath(
|
||||
derivePathType: derivePathType,
|
||||
networkWIF: _network.wif,
|
||||
chain: chain,
|
||||
index: index,
|
||||
);
|
||||
final node = await Bip32Utils.getBip32Node(
|
||||
_mnemonic!,
|
||||
_mnemonicPassphrase!,
|
||||
_network,
|
||||
derivePath,
|
||||
);
|
||||
|
||||
final data = PaymentData(pubkey: node.publicKey);
|
||||
String address;
|
||||
isar_models.AddressType addrType;
|
||||
|
@ -2888,9 +2868,12 @@ class LitecoinWallet extends CoinServiceAPI
|
|||
await _deleteDerivations();
|
||||
|
||||
try {
|
||||
final mnemonic = await _secureStore.read(key: '${_walletId}_mnemonic');
|
||||
final _mnemonic = await mnemonicString;
|
||||
final _mnemonicPassphrase = await mnemonicPassphrase;
|
||||
|
||||
await _recoverWalletFromBIP32SeedPhrase(
|
||||
mnemonic: mnemonic!,
|
||||
mnemonic: _mnemonic!,
|
||||
mnemonicPassphrase: _mnemonicPassphrase!,
|
||||
maxUnusedAddressGap: maxUnusedAddressGap,
|
||||
maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck,
|
||||
isRescan: true,
|
||||
|
|
|
@ -160,6 +160,7 @@ class Manager with ChangeNotifier {
|
|||
_currentWallet.validateAddress(address);
|
||||
|
||||
Future<List<String>> get mnemonic => _currentWallet.mnemonic;
|
||||
Future<String?> get mnemonicPassphrase => _currentWallet.mnemonicPassphrase;
|
||||
|
||||
Future<bool> testNetworkConnection() =>
|
||||
_currentWallet.testNetworkConnection();
|
||||
|
@ -168,6 +169,7 @@ class Manager with ChangeNotifier {
|
|||
Future<void> initializeExisting() => _currentWallet.initializeExisting();
|
||||
Future<void> recoverFromMnemonic({
|
||||
required String mnemonic,
|
||||
String? mnemonicPassphrase,
|
||||
required int maxUnusedAddressGap,
|
||||
required int maxNumberOfIndexesToCheck,
|
||||
required int height,
|
||||
|
@ -175,6 +177,7 @@ class Manager with ChangeNotifier {
|
|||
try {
|
||||
await _currentWallet.recoverFromMnemonic(
|
||||
mnemonic: mnemonic,
|
||||
mnemonicPassphrase: mnemonicPassphrase,
|
||||
maxUnusedAddressGap: maxUnusedAddressGap,
|
||||
maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck,
|
||||
height: height,
|
||||
|
|
|
@ -314,7 +314,7 @@ class MoneroWallet extends CoinServiceAPI with WalletCache, WalletDB {
|
|||
await _prefs.init();
|
||||
|
||||
// this should never fail
|
||||
if ((await _secureStorage.read(key: '${_walletId}_mnemonic')) != null) {
|
||||
if ((await mnemonicString) != null || (await mnemonicPassphrase) != null) {
|
||||
throw Exception(
|
||||
"Attempted to overwrite mnemonic on generate new wallet!");
|
||||
}
|
||||
|
@ -365,6 +365,10 @@ class MoneroWallet extends CoinServiceAPI with WalletCache, WalletDB {
|
|||
|
||||
await _secureStorage.write(
|
||||
key: '${_walletId}_mnemonic', value: wallet?.seed.trim());
|
||||
await _secureStorage.write(
|
||||
key: '${_walletId}_mnemonicPassphrase',
|
||||
value: "",
|
||||
);
|
||||
walletInfo.address = wallet?.walletAddresses.address;
|
||||
await DB.instance
|
||||
.add<WalletInfo>(boxName: WalletInfo.boxName, value: walletInfo);
|
||||
|
@ -419,15 +423,23 @@ class MoneroWallet extends CoinServiceAPI with WalletCache, WalletDB {
|
|||
|
||||
@override
|
||||
Future<List<String>> get mnemonic async {
|
||||
final mnemonicString =
|
||||
await _secureStorage.read(key: '${_walletId}_mnemonic');
|
||||
if (mnemonicString == null) {
|
||||
final _mnemonicString = await mnemonicString;
|
||||
if (_mnemonicString == null) {
|
||||
return [];
|
||||
}
|
||||
final List<String> data = mnemonicString.split(' ');
|
||||
final List<String> data = _mnemonicString.split(' ');
|
||||
return data;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String?> get mnemonicString =>
|
||||
_secureStorage.read(key: '${_walletId}_mnemonic');
|
||||
|
||||
@override
|
||||
Future<String?> get mnemonicPassphrase => _secureStorage.read(
|
||||
key: '${_walletId}_mnemonicPassphrase',
|
||||
);
|
||||
|
||||
@override
|
||||
Future<Map<String, dynamic>> prepareSend({
|
||||
required String address,
|
||||
|
@ -519,6 +531,7 @@ class MoneroWallet extends CoinServiceAPI with WalletCache, WalletDB {
|
|||
@override
|
||||
Future<void> recoverFromMnemonic({
|
||||
required String mnemonic,
|
||||
String? mnemonicPassphrase, // not used at the moment
|
||||
required int maxUnusedAddressGap,
|
||||
required int maxNumberOfIndexesToCheck,
|
||||
required int height,
|
||||
|
@ -543,12 +556,17 @@ class MoneroWallet extends CoinServiceAPI with WalletCache, WalletDB {
|
|||
// }
|
||||
// check to make sure we aren't overwriting a mnemonic
|
||||
// this should never fail
|
||||
if ((await _secureStorage.read(key: '${_walletId}_mnemonic')) != null) {
|
||||
if ((await mnemonicString) != null ||
|
||||
(await this.mnemonicPassphrase) != null) {
|
||||
longMutex = false;
|
||||
throw Exception("Attempted to overwrite mnemonic on restore!");
|
||||
}
|
||||
await _secureStorage.write(
|
||||
key: '${_walletId}_mnemonic', value: mnemonic.trim());
|
||||
await _secureStorage.write(
|
||||
key: '${_walletId}_mnemonicPassphrase',
|
||||
value: mnemonicPassphrase ?? "",
|
||||
);
|
||||
|
||||
await DB.instance
|
||||
.put<dynamic>(boxName: walletId, key: "restoreHeight", value: height);
|
||||
|
|
|
@ -30,6 +30,7 @@ import 'package:stackwallet/services/node_service.dart';
|
|||
import 'package:stackwallet/services/notifications_api.dart';
|
||||
import 'package:stackwallet/services/transaction_notification_tracker.dart';
|
||||
import 'package:stackwallet/utilities/assets.dart';
|
||||
import 'package:stackwallet/utilities/bip32_utils.dart';
|
||||
import 'package:stackwallet/utilities/constants.dart';
|
||||
import 'package:stackwallet/utilities/default_nodes.dart';
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
|
@ -51,87 +52,38 @@ const String GENESIS_HASH_MAINNET =
|
|||
const String GENESIS_HASH_TESTNET =
|
||||
"00000007199508e34a9ff81e6ec0c477a4cccff2a4767a8eee39c11db367b008";
|
||||
|
||||
bip32.BIP32 getBip32Node(
|
||||
int chain,
|
||||
int index,
|
||||
String mnemonic,
|
||||
NetworkType network,
|
||||
DerivePathType derivePathType,
|
||||
) {
|
||||
final root = getBip32Root(mnemonic, network);
|
||||
|
||||
final node = getBip32NodeFromRoot(chain, index, root, derivePathType);
|
||||
return node;
|
||||
}
|
||||
|
||||
/// wrapper for compute()
|
||||
bip32.BIP32 getBip32NodeWrapper(
|
||||
Tuple5<int, int, String, NetworkType, DerivePathType> args,
|
||||
) {
|
||||
return getBip32Node(
|
||||
args.item1,
|
||||
args.item2,
|
||||
args.item3,
|
||||
args.item4,
|
||||
args.item5,
|
||||
);
|
||||
}
|
||||
|
||||
bip32.BIP32 getBip32NodeFromRoot(
|
||||
int chain,
|
||||
int index,
|
||||
bip32.BIP32 root,
|
||||
DerivePathType derivePathType,
|
||||
) {
|
||||
String constructDerivePath({
|
||||
required DerivePathType derivePathType,
|
||||
required int networkWIF,
|
||||
int account = 0,
|
||||
required int chain,
|
||||
required int index,
|
||||
}) {
|
||||
String coinType;
|
||||
switch (root.network.wif) {
|
||||
switch (networkWIF) {
|
||||
case 0xb4: // nmc mainnet wif
|
||||
coinType = "7"; // nmc mainnet
|
||||
break;
|
||||
default:
|
||||
throw Exception("Invalid Namecoin network type used!");
|
||||
throw Exception("Invalid Namecoin network wif used!");
|
||||
}
|
||||
|
||||
int purpose;
|
||||
switch (derivePathType) {
|
||||
case DerivePathType.bip44:
|
||||
return root.derivePath("m/44'/$coinType'/0'/$chain/$index");
|
||||
purpose = 44;
|
||||
break;
|
||||
case DerivePathType.bip49:
|
||||
return root.derivePath("m/49'/$coinType'/0'/$chain/$index");
|
||||
purpose = 49;
|
||||
break;
|
||||
case DerivePathType.bip84:
|
||||
return root.derivePath("m/84'/$coinType'/0'/$chain/$index");
|
||||
purpose = 84;
|
||||
break;
|
||||
default:
|
||||
throw Exception("DerivePathType must not be null.");
|
||||
throw Exception("DerivePathType $derivePathType not supported");
|
||||
}
|
||||
}
|
||||
|
||||
/// wrapper for compute()
|
||||
bip32.BIP32 getBip32NodeFromRootWrapper(
|
||||
Tuple4<int, int, bip32.BIP32, DerivePathType> args,
|
||||
) {
|
||||
return getBip32NodeFromRoot(
|
||||
args.item1,
|
||||
args.item2,
|
||||
args.item3,
|
||||
args.item4,
|
||||
);
|
||||
}
|
||||
|
||||
bip32.BIP32 getBip32Root(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;
|
||||
}
|
||||
|
||||
/// wrapper for compute()
|
||||
bip32.BIP32 getBip32RootWrapper(Tuple2<String, NetworkType> args) {
|
||||
return getBip32Root(args.item1, args.item2);
|
||||
return "m/$purpose'/$coinType'/$account'/$chain/$index";
|
||||
}
|
||||
|
||||
class NamecoinWallet extends CoinServiceAPI
|
||||
|
@ -231,6 +183,15 @@ class NamecoinWallet extends CoinServiceAPI
|
|||
@override
|
||||
Future<List<String>> get mnemonic => _getMnemonicList();
|
||||
|
||||
@override
|
||||
Future<String?> get mnemonicString =>
|
||||
_secureStore.read(key: '${_walletId}_mnemonic');
|
||||
|
||||
@override
|
||||
Future<String?> get mnemonicPassphrase => _secureStore.read(
|
||||
key: '${_walletId}_mnemonicPassphrase',
|
||||
);
|
||||
|
||||
Future<int> get chainHeight async {
|
||||
try {
|
||||
final result = await _electrumXClient.getBlockHeadTip();
|
||||
|
@ -295,6 +256,7 @@ class NamecoinWallet extends CoinServiceAPI
|
|||
@override
|
||||
Future<void> recoverFromMnemonic({
|
||||
required String mnemonic,
|
||||
String? mnemonicPassphrase,
|
||||
required int maxUnusedAddressGap,
|
||||
required int maxNumberOfIndexesToCheck,
|
||||
required int height,
|
||||
|
@ -326,14 +288,21 @@ class NamecoinWallet extends CoinServiceAPI
|
|||
}
|
||||
// check to make sure we aren't overwriting a mnemonic
|
||||
// this should never fail
|
||||
if ((await _secureStore.read(key: '${_walletId}_mnemonic')) != null) {
|
||||
if ((await mnemonicString) != null ||
|
||||
(await this.mnemonicPassphrase) != null) {
|
||||
longMutex = false;
|
||||
throw Exception("Attempted to overwrite mnemonic on restore!");
|
||||
}
|
||||
await _secureStore.write(
|
||||
key: '${_walletId}_mnemonic', value: mnemonic.trim());
|
||||
await _secureStore.write(
|
||||
key: '${_walletId}_mnemonicPassphrase',
|
||||
value: mnemonicPassphrase ?? "",
|
||||
);
|
||||
|
||||
await _recoverWalletFromBIP32SeedPhrase(
|
||||
mnemonic: mnemonic.trim(),
|
||||
mnemonicPassphrase: mnemonicPassphrase ?? "",
|
||||
maxUnusedAddressGap: maxUnusedAddressGap,
|
||||
maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck,
|
||||
);
|
||||
|
@ -376,15 +345,14 @@ class NamecoinWallet extends CoinServiceAPI
|
|||
final Map<String, dynamic> receivingNodes = {};
|
||||
|
||||
for (int j = 0; j < txCountBatchSize; j++) {
|
||||
final node = await compute(
|
||||
getBip32NodeFromRootWrapper,
|
||||
Tuple4(
|
||||
chain,
|
||||
index + j,
|
||||
root,
|
||||
type,
|
||||
),
|
||||
final derivePath = constructDerivePath(
|
||||
derivePathType: type,
|
||||
networkWIF: root.network.wif,
|
||||
chain: chain,
|
||||
index: index + j,
|
||||
);
|
||||
final node = await Bip32Utils.getBip32NodeFromRoot(root, derivePath);
|
||||
|
||||
String addressString;
|
||||
isar_models.AddressType addrType;
|
||||
switch (type) {
|
||||
|
@ -505,6 +473,7 @@ class NamecoinWallet extends CoinServiceAPI
|
|||
|
||||
Future<void> _recoverWalletFromBIP32SeedPhrase({
|
||||
required String mnemonic,
|
||||
required String mnemonicPassphrase,
|
||||
int maxUnusedAddressGap = 20,
|
||||
int maxNumberOfIndexesToCheck = 1000,
|
||||
bool isRescan = false,
|
||||
|
@ -518,7 +487,11 @@ class NamecoinWallet extends CoinServiceAPI
|
|||
Map<String, Map<String, String>> p2shChangeDerivations = {};
|
||||
Map<String, Map<String, String>> p2wpkhChangeDerivations = {};
|
||||
|
||||
final root = await compute(getBip32RootWrapper, Tuple2(mnemonic, _network));
|
||||
final root = await Bip32Utils.getBip32Root(
|
||||
mnemonic,
|
||||
mnemonicPassphrase,
|
||||
_network,
|
||||
);
|
||||
|
||||
List<isar_models.Address> p2pkhReceiveAddressArray = [];
|
||||
List<isar_models.Address> p2shReceiveAddressArray = [];
|
||||
|
@ -1310,12 +1283,11 @@ class NamecoinWallet extends CoinServiceAPI
|
|||
}
|
||||
|
||||
Future<List<String>> _getMnemonicList() async {
|
||||
final mnemonicString =
|
||||
await _secureStore.read(key: '${_walletId}_mnemonic');
|
||||
if (mnemonicString == null) {
|
||||
final _mnemonicString = await mnemonicString;
|
||||
if (_mnemonicString == null) {
|
||||
return [];
|
||||
}
|
||||
final List<String> data = mnemonicString.split(' ');
|
||||
final List<String> data = _mnemonicString.split(' ');
|
||||
return data;
|
||||
}
|
||||
|
||||
|
@ -1444,13 +1416,17 @@ class NamecoinWallet extends CoinServiceAPI
|
|||
}
|
||||
|
||||
// this should never fail
|
||||
if ((await _secureStore.read(key: '${_walletId}_mnemonic')) != null) {
|
||||
if ((await mnemonicString) != null || (await mnemonicPassphrase) != null) {
|
||||
throw Exception(
|
||||
"Attempted to overwrite mnemonic on generate new wallet!");
|
||||
}
|
||||
await _secureStore.write(
|
||||
key: '${_walletId}_mnemonic',
|
||||
value: bip39.generateMnemonic(strength: 256));
|
||||
await _secureStore.write(
|
||||
key: '${_walletId}_mnemonicPassphrase',
|
||||
value: "",
|
||||
);
|
||||
|
||||
// Generate and add addresses to relevant arrays
|
||||
final initialAddresses = await Future.wait([
|
||||
|
@ -1480,17 +1456,22 @@ class NamecoinWallet extends CoinServiceAPI
|
|||
int index,
|
||||
DerivePathType derivePathType,
|
||||
) async {
|
||||
final mnemonic = await _secureStore.read(key: '${_walletId}_mnemonic');
|
||||
final node = await compute(
|
||||
getBip32NodeWrapper,
|
||||
Tuple5(
|
||||
chain,
|
||||
index,
|
||||
mnemonic!,
|
||||
_network,
|
||||
derivePathType,
|
||||
),
|
||||
final _mnemonic = await mnemonicString;
|
||||
final _mnemonicPassphrase = await mnemonicPassphrase;
|
||||
|
||||
final derivePath = constructDerivePath(
|
||||
derivePathType: derivePathType,
|
||||
networkWIF: _network.wif,
|
||||
chain: chain,
|
||||
index: index,
|
||||
);
|
||||
final node = await Bip32Utils.getBip32Node(
|
||||
_mnemonic!,
|
||||
_mnemonicPassphrase!,
|
||||
_network,
|
||||
derivePath,
|
||||
);
|
||||
|
||||
final data = PaymentData(pubkey: node.publicKey);
|
||||
String address;
|
||||
isar_models.AddressType addrType;
|
||||
|
@ -2602,6 +2583,8 @@ class NamecoinWallet extends CoinServiceAPI
|
|||
case DerivePathType.bip84:
|
||||
addressesP2WPKH.add(address);
|
||||
break;
|
||||
default:
|
||||
throw Exception("DerivePathType unsupported");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2881,9 +2864,11 @@ class NamecoinWallet extends CoinServiceAPI
|
|||
await _deleteDerivations();
|
||||
|
||||
try {
|
||||
final mnemonic = await _secureStore.read(key: '${_walletId}_mnemonic');
|
||||
final _mnemonic = await mnemonicString;
|
||||
final _mnemonicPassphrase = await mnemonicPassphrase;
|
||||
await _recoverWalletFromBIP32SeedPhrase(
|
||||
mnemonic: mnemonic!,
|
||||
mnemonic: _mnemonic!,
|
||||
mnemonicPassphrase: _mnemonicPassphrase!,
|
||||
maxUnusedAddressGap: maxUnusedAddressGap,
|
||||
maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck,
|
||||
isRescan: true,
|
||||
|
|
|
@ -29,6 +29,7 @@ import 'package:stackwallet/services/node_service.dart';
|
|||
import 'package:stackwallet/services/notifications_api.dart';
|
||||
import 'package:stackwallet/services/transaction_notification_tracker.dart';
|
||||
import 'package:stackwallet/utilities/assets.dart';
|
||||
import 'package:stackwallet/utilities/bip32_utils.dart';
|
||||
import 'package:stackwallet/utilities/constants.dart';
|
||||
import 'package:stackwallet/utilities/default_nodes.dart';
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
|
@ -49,85 +50,35 @@ const String GENESIS_HASH_MAINNET =
|
|||
const String GENESIS_HASH_TESTNET =
|
||||
"0000594ada5310b367443ee0afd4fa3d0bbd5850ea4e33cdc7d6a904a7ec7c90";
|
||||
|
||||
bip32.BIP32 getBip32Node(
|
||||
int chain,
|
||||
int index,
|
||||
String mnemonic,
|
||||
NetworkType network,
|
||||
DerivePathType derivePathType,
|
||||
) {
|
||||
final root = getBip32Root(mnemonic, network);
|
||||
|
||||
final node = getBip32NodeFromRoot(chain, index, root, derivePathType);
|
||||
return node;
|
||||
}
|
||||
|
||||
/// wrapper for compute()
|
||||
bip32.BIP32 getBip32NodeWrapper(
|
||||
Tuple5<int, int, String, NetworkType, DerivePathType> args,
|
||||
) {
|
||||
return getBip32Node(
|
||||
args.item1,
|
||||
args.item2,
|
||||
args.item3,
|
||||
args.item4,
|
||||
args.item5,
|
||||
);
|
||||
}
|
||||
|
||||
bip32.BIP32 getBip32NodeFromRoot(
|
||||
int chain,
|
||||
int index,
|
||||
bip32.BIP32 root,
|
||||
DerivePathType derivePathType,
|
||||
) {
|
||||
String constructDerivePath({
|
||||
required DerivePathType derivePathType,
|
||||
required int networkWIF,
|
||||
int account = 0,
|
||||
required int chain,
|
||||
required int index,
|
||||
}) {
|
||||
String coinType;
|
||||
switch (root.network.wif) {
|
||||
switch (networkWIF) {
|
||||
case 0x6c: // PART mainnet wif
|
||||
coinType = "44"; // PART mainnet
|
||||
break;
|
||||
default:
|
||||
throw Exception("Invalid Particl network type used!");
|
||||
throw Exception("Invalid Particl network wif used!");
|
||||
}
|
||||
|
||||
int purpose;
|
||||
switch (derivePathType) {
|
||||
case DerivePathType.bip44:
|
||||
return root.derivePath("m/44'/$coinType'/0'/$chain/$index");
|
||||
purpose = 44;
|
||||
break;
|
||||
case DerivePathType.bip84:
|
||||
return root.derivePath("m/84'/$coinType'/0'/$chain/$index");
|
||||
purpose = 84;
|
||||
break;
|
||||
default:
|
||||
throw Exception("DerivePathType $derivePathType not supported");
|
||||
}
|
||||
}
|
||||
|
||||
/// wrapper for compute()
|
||||
bip32.BIP32 getBip32NodeFromRootWrapper(
|
||||
Tuple4<int, int, bip32.BIP32, DerivePathType> args,
|
||||
) {
|
||||
return getBip32NodeFromRoot(
|
||||
args.item1,
|
||||
args.item2,
|
||||
args.item3,
|
||||
args.item4,
|
||||
);
|
||||
}
|
||||
|
||||
bip32.BIP32 getBip32Root(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;
|
||||
}
|
||||
|
||||
/// wrapper for compute()
|
||||
bip32.BIP32 getBip32RootWrapper(Tuple2<String, NetworkType> args) {
|
||||
return getBip32Root(args.item1, args.item2);
|
||||
return "m/$purpose'/$coinType'/$account'/$chain/$index";
|
||||
}
|
||||
|
||||
class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB {
|
||||
|
@ -226,6 +177,15 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB {
|
|||
@override
|
||||
Future<List<String>> get mnemonic => _getMnemonicList();
|
||||
|
||||
@override
|
||||
Future<String?> get mnemonicString =>
|
||||
_secureStore.read(key: '${_walletId}_mnemonic');
|
||||
|
||||
@override
|
||||
Future<String?> get mnemonicPassphrase => _secureStore.read(
|
||||
key: '${_walletId}_mnemonicPassphrase',
|
||||
);
|
||||
|
||||
Future<int> get chainHeight async {
|
||||
try {
|
||||
final result = await _electrumXClient.getBlockHeadTip();
|
||||
|
@ -288,6 +248,7 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB {
|
|||
@override
|
||||
Future<void> recoverFromMnemonic({
|
||||
required String mnemonic,
|
||||
String? mnemonicPassphrase,
|
||||
required int maxUnusedAddressGap,
|
||||
required int maxNumberOfIndexesToCheck,
|
||||
required int height,
|
||||
|
@ -322,14 +283,21 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB {
|
|||
}
|
||||
// check to make sure we aren't overwriting a mnemonic
|
||||
// this should never fail
|
||||
if ((await _secureStore.read(key: '${_walletId}_mnemonic')) != null) {
|
||||
if ((await mnemonicString) != null ||
|
||||
(await this.mnemonicPassphrase) != null) {
|
||||
longMutex = false;
|
||||
throw Exception("Attempted to overwrite mnemonic on restore!");
|
||||
}
|
||||
await _secureStore.write(
|
||||
key: '${_walletId}_mnemonic', value: mnemonic.trim());
|
||||
await _secureStore.write(
|
||||
key: '${_walletId}_mnemonicPassphrase',
|
||||
value: mnemonicPassphrase ?? "",
|
||||
);
|
||||
|
||||
await _recoverWalletFromBIP32SeedPhrase(
|
||||
mnemonic: mnemonic.trim(),
|
||||
mnemonicPassphrase: mnemonicPassphrase ?? "",
|
||||
maxUnusedAddressGap: maxUnusedAddressGap,
|
||||
maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck,
|
||||
);
|
||||
|
@ -372,15 +340,14 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB {
|
|||
final Map<String, dynamic> receivingNodes = {};
|
||||
|
||||
for (int j = 0; j < txCountBatchSize; j++) {
|
||||
final node = await compute(
|
||||
getBip32NodeFromRootWrapper,
|
||||
Tuple4(
|
||||
chain,
|
||||
index + j,
|
||||
root,
|
||||
type,
|
||||
),
|
||||
final derivePath = constructDerivePath(
|
||||
derivePathType: type,
|
||||
networkWIF: root.network.wif,
|
||||
chain: chain,
|
||||
index: index + j,
|
||||
);
|
||||
final node = await Bip32Utils.getBip32NodeFromRoot(root, derivePath);
|
||||
|
||||
String addressString;
|
||||
isar_models.AddressType addrType;
|
||||
switch (type) {
|
||||
|
@ -487,6 +454,7 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB {
|
|||
|
||||
Future<void> _recoverWalletFromBIP32SeedPhrase({
|
||||
required String mnemonic,
|
||||
required String mnemonicPassphrase,
|
||||
int maxUnusedAddressGap = 20,
|
||||
int maxNumberOfIndexesToCheck = 1000,
|
||||
bool isRescan = false,
|
||||
|
@ -498,7 +466,11 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB {
|
|||
Map<String, Map<String, String>> p2pkhChangeDerivations = {};
|
||||
Map<String, Map<String, String>> p2wpkhChangeDerivations = {};
|
||||
|
||||
final root = await compute(getBip32RootWrapper, Tuple2(mnemonic, _network));
|
||||
final root = await Bip32Utils.getBip32Root(
|
||||
mnemonic,
|
||||
mnemonicPassphrase,
|
||||
_network,
|
||||
);
|
||||
|
||||
List<isar_models.Address> p2pkhReceiveAddressArray = [];
|
||||
List<isar_models.Address> p2wpkhReceiveAddressArray = [];
|
||||
|
@ -1238,12 +1210,11 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB {
|
|||
}
|
||||
|
||||
Future<List<String>> _getMnemonicList() async {
|
||||
final mnemonicString =
|
||||
await _secureStore.read(key: '${_walletId}_mnemonic');
|
||||
if (mnemonicString == null) {
|
||||
final _mnemonicString = await mnemonicString;
|
||||
if (_mnemonicString == null) {
|
||||
return [];
|
||||
}
|
||||
final List<String> data = mnemonicString.split(' ');
|
||||
final List<String> data = _mnemonicString.split(' ');
|
||||
return data;
|
||||
}
|
||||
|
||||
|
@ -1359,13 +1330,17 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB {
|
|||
}
|
||||
|
||||
// this should never fail
|
||||
if ((await _secureStore.read(key: '${_walletId}_mnemonic')) != null) {
|
||||
if ((await mnemonicString) != null || (await mnemonicPassphrase) != null) {
|
||||
throw Exception(
|
||||
"Attempted to overwrite mnemonic on generate new wallet!");
|
||||
}
|
||||
await _secureStore.write(
|
||||
key: '${_walletId}_mnemonic',
|
||||
value: bip39.generateMnemonic(strength: 256));
|
||||
await _secureStore.write(
|
||||
key: '${_walletId}_mnemonicPassphrase',
|
||||
value: "",
|
||||
);
|
||||
|
||||
// Generate and add addresses to relevant arrays
|
||||
final initialAddresses = await Future.wait([
|
||||
|
@ -1391,17 +1366,22 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB {
|
|||
int index,
|
||||
DerivePathType derivePathType,
|
||||
) async {
|
||||
final mnemonic = await _secureStore.read(key: '${_walletId}_mnemonic');
|
||||
final node = await compute(
|
||||
getBip32NodeWrapper,
|
||||
Tuple5(
|
||||
chain,
|
||||
index,
|
||||
mnemonic!,
|
||||
_network,
|
||||
derivePathType,
|
||||
),
|
||||
final _mnemonic = await mnemonicString;
|
||||
final _mnemonicPassphrase = await mnemonicPassphrase;
|
||||
|
||||
final derivePath = constructDerivePath(
|
||||
derivePathType: derivePathType,
|
||||
networkWIF: _network.wif,
|
||||
chain: chain,
|
||||
index: index,
|
||||
);
|
||||
final node = await Bip32Utils.getBip32Node(
|
||||
_mnemonic!,
|
||||
_mnemonicPassphrase!,
|
||||
_network,
|
||||
derivePath,
|
||||
);
|
||||
|
||||
final data = PaymentData(pubkey: node.publicKey);
|
||||
String address;
|
||||
isar_models.AddressType addrType;
|
||||
|
@ -2976,9 +2956,12 @@ class ParticlWallet extends CoinServiceAPI with WalletCache, WalletDB {
|
|||
await _deleteDerivations();
|
||||
|
||||
try {
|
||||
final mnemonic = await _secureStore.read(key: '${_walletId}_mnemonic');
|
||||
final _mnemonic = await mnemonicString;
|
||||
final _mnemonicPassphrase = await mnemonicPassphrase;
|
||||
|
||||
await _recoverWalletFromBIP32SeedPhrase(
|
||||
mnemonic: mnemonic!,
|
||||
mnemonic: _mnemonic!,
|
||||
mnemonicPassphrase: _mnemonicPassphrase!,
|
||||
maxUnusedAddressGap: maxUnusedAddressGap,
|
||||
maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck,
|
||||
isRescan: true,
|
||||
|
|
|
@ -319,7 +319,7 @@ class WowneroWallet extends CoinServiceAPI with WalletCache, WalletDB {
|
|||
await _prefs.init();
|
||||
|
||||
// this should never fail
|
||||
if ((await _secureStorage.read(key: '${_walletId}_mnemonic')) != null) {
|
||||
if ((await mnemonicString) != null || (await mnemonicPassphrase) != null) {
|
||||
throw Exception(
|
||||
"Attempted to overwrite mnemonic on generate new wallet!");
|
||||
}
|
||||
|
@ -377,6 +377,10 @@ class WowneroWallet extends CoinServiceAPI with WalletCache, WalletDB {
|
|||
|
||||
await _secureStorage.write(
|
||||
key: '${_walletId}_mnemonic', value: wallet?.seed.trim());
|
||||
await _secureStorage.write(
|
||||
key: '${_walletId}_mnemonicPassphrase',
|
||||
value: "",
|
||||
);
|
||||
|
||||
walletInfo.address = wallet?.walletAddresses.address;
|
||||
await DB.instance
|
||||
|
@ -427,15 +431,23 @@ class WowneroWallet extends CoinServiceAPI with WalletCache, WalletDB {
|
|||
|
||||
@override
|
||||
Future<List<String>> get mnemonic async {
|
||||
final mnemonicString =
|
||||
await _secureStorage.read(key: '${_walletId}_mnemonic');
|
||||
if (mnemonicString == null) {
|
||||
final _mnemonicString = await mnemonicString;
|
||||
if (_mnemonicString == null) {
|
||||
return [];
|
||||
}
|
||||
final List<String> data = mnemonicString.split(' ');
|
||||
final List<String> data = _mnemonicString.split(' ');
|
||||
return data;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String?> get mnemonicString =>
|
||||
_secureStorage.read(key: '${_walletId}_mnemonic');
|
||||
|
||||
@override
|
||||
Future<String?> get mnemonicPassphrase => _secureStorage.read(
|
||||
key: '${_walletId}_mnemonicPassphrase',
|
||||
);
|
||||
|
||||
@override
|
||||
Future<Map<String, dynamic>> prepareSend({
|
||||
required String address,
|
||||
|
@ -528,6 +540,7 @@ class WowneroWallet extends CoinServiceAPI with WalletCache, WalletDB {
|
|||
@override
|
||||
Future<void> recoverFromMnemonic({
|
||||
required String mnemonic,
|
||||
String? mnemonicPassphrase, // not used at the moment
|
||||
required int maxUnusedAddressGap,
|
||||
required int maxNumberOfIndexesToCheck,
|
||||
required int height,
|
||||
|
@ -543,12 +556,17 @@ class WowneroWallet extends CoinServiceAPI with WalletCache, WalletDB {
|
|||
try {
|
||||
// check to make sure we aren't overwriting a mnemonic
|
||||
// this should never fail
|
||||
if ((await _secureStorage.read(key: '${_walletId}_mnemonic')) != null) {
|
||||
if ((await mnemonicString) != null ||
|
||||
(await this.mnemonicPassphrase) != null) {
|
||||
longMutex = false;
|
||||
throw Exception("Attempted to overwrite mnemonic on restore!");
|
||||
}
|
||||
await _secureStorage.write(
|
||||
key: '${_walletId}_mnemonic', value: mnemonic.trim());
|
||||
await _secureStorage.write(
|
||||
key: '${_walletId}_mnemonicPassphrase',
|
||||
value: mnemonicPassphrase ?? "",
|
||||
);
|
||||
|
||||
// extract seed height from 14 word seed
|
||||
if (seedLength == 14) {
|
||||
|
|
|
@ -39,7 +39,8 @@ mixin PaynymWalletInterface {
|
|||
late final int _minConfirms;
|
||||
|
||||
// passed in wallet functions
|
||||
late final Future<List<String>> Function() _getMnemonic;
|
||||
late final Future<String?> Function() _getMnemonicString;
|
||||
late final Future<String?> Function() _getMnemonicPassphrase;
|
||||
late final Future<int> Function() _getChainHeight;
|
||||
late final Future<String> Function() _getCurrentChangeAddress;
|
||||
late final int Function({
|
||||
|
@ -66,11 +67,6 @@ mixin PaynymWalletInterface {
|
|||
required String wif,
|
||||
required DerivePathType derivePathType,
|
||||
}) _addDerivation;
|
||||
late final Future<void> Function({
|
||||
required int chain,
|
||||
required DerivePathType derivePathType,
|
||||
required Map<String, dynamic> derivationsToAdd,
|
||||
}) _addDerivations;
|
||||
|
||||
// initializer
|
||||
void initPaynymWalletInterface({
|
||||
|
@ -83,7 +79,8 @@ mixin PaynymWalletInterface {
|
|||
required SecureStorageInterface secureStorage,
|
||||
required int dustLimitP2PKH,
|
||||
required int minConfirms,
|
||||
required Future<List<String>> Function() getMnemonic,
|
||||
required Future<String?> Function() getMnemonicString,
|
||||
required Future<String?> Function() getMnemonicPassphrase,
|
||||
required Future<int> Function() getChainHeight,
|
||||
required Future<String> Function() getCurrentChangeAddress,
|
||||
required int Function({
|
||||
|
@ -115,12 +112,6 @@ mixin PaynymWalletInterface {
|
|||
required DerivePathType derivePathType,
|
||||
})
|
||||
addDerivation,
|
||||
required Future<void> Function({
|
||||
required int chain,
|
||||
required DerivePathType derivePathType,
|
||||
required Map<String, dynamic> derivationsToAdd,
|
||||
})
|
||||
addDerivations,
|
||||
}) {
|
||||
_walletId = walletId;
|
||||
_walletName = walletName;
|
||||
|
@ -131,7 +122,8 @@ mixin PaynymWalletInterface {
|
|||
_secureStorage = secureStorage;
|
||||
_dustLimitP2PKH = dustLimitP2PKH;
|
||||
_minConfirms = minConfirms;
|
||||
_getMnemonic = getMnemonic;
|
||||
_getMnemonicString = getMnemonicString;
|
||||
_getMnemonicPassphrase = getMnemonicPassphrase;
|
||||
_getChainHeight = getChainHeight;
|
||||
_getCurrentChangeAddress = getCurrentChangeAddress;
|
||||
_estimateTxFee = estimateTxFee;
|
||||
|
@ -141,7 +133,6 @@ mixin PaynymWalletInterface {
|
|||
_refresh = refresh;
|
||||
_checkChangeAddressForTransactions = checkChangeAddressForTransactions;
|
||||
_addDerivation = addDerivation;
|
||||
_addDerivations = addDerivations;
|
||||
}
|
||||
|
||||
// convenience getter
|
||||
|
@ -186,7 +177,8 @@ mixin PaynymWalletInterface {
|
|||
int index,
|
||||
) async {
|
||||
final myPrivateKey = await deriveReceivingPrivateKey(
|
||||
mnemonic: await _getMnemonic(),
|
||||
mnemonic: (await _getMnemonicString())!,
|
||||
mnemonicPassphrase: (await _getMnemonicPassphrase())!,
|
||||
index: index,
|
||||
);
|
||||
|
||||
|
@ -244,26 +236,39 @@ mixin PaynymWalletInterface {
|
|||
}
|
||||
|
||||
// generate bip32 payment code root
|
||||
Future<bip32.BIP32> getRootNode({
|
||||
required List<String> mnemonic,
|
||||
Future<bip32.BIP32> _getRootNode({
|
||||
required String mnemonic,
|
||||
required String mnemonicPassphrase,
|
||||
}) async {
|
||||
final root = await Bip32Utils.getBip32Root(mnemonic.join(" "), _network);
|
||||
final root = await Bip32Utils.getBip32Root(
|
||||
mnemonic,
|
||||
mnemonicPassphrase,
|
||||
_network,
|
||||
);
|
||||
return root;
|
||||
}
|
||||
|
||||
Future<Uint8List> deriveNotificationPrivateKey({
|
||||
required List<String> mnemonic,
|
||||
required String mnemonic,
|
||||
required String mnemonicPassphrase,
|
||||
}) async {
|
||||
final root = await getRootNode(mnemonic: mnemonic);
|
||||
final root = await _getRootNode(
|
||||
mnemonic: mnemonic,
|
||||
mnemonicPassphrase: mnemonicPassphrase,
|
||||
);
|
||||
final node = root.derivePath(kPaynymDerivePath).derive(0);
|
||||
return node.privateKey!;
|
||||
}
|
||||
|
||||
Future<Uint8List> deriveReceivingPrivateKey({
|
||||
required List<String> mnemonic,
|
||||
required String mnemonic,
|
||||
required String mnemonicPassphrase,
|
||||
required int index,
|
||||
}) async {
|
||||
final root = await getRootNode(mnemonic: mnemonic);
|
||||
final root = await _getRootNode(
|
||||
mnemonic: mnemonic,
|
||||
mnemonicPassphrase: mnemonicPassphrase,
|
||||
);
|
||||
final node = root.derivePath(kPaynymDerivePath).derive(index);
|
||||
return node.privateKey!;
|
||||
}
|
||||
|
@ -282,8 +287,10 @@ mixin PaynymWalletInterface {
|
|||
}
|
||||
|
||||
Future<Uint8List> signWithNotificationKey(Uint8List data) async {
|
||||
final privateKey =
|
||||
await deriveNotificationPrivateKey(mnemonic: await _getMnemonic());
|
||||
final privateKey = await deriveNotificationPrivateKey(
|
||||
mnemonic: (await _getMnemonicString())!,
|
||||
mnemonicPassphrase: (await _getMnemonicPassphrase())!,
|
||||
);
|
||||
final pair = btc_dart.ECPair.fromPrivateKey(privateKey, network: _network);
|
||||
final signed = pair.sign(SHA256Digest().process(data));
|
||||
return signed;
|
||||
|
@ -303,8 +310,10 @@ mixin PaynymWalletInterface {
|
|||
throw PaynymSendException(
|
||||
"No notification transaction sent to $paymentCode");
|
||||
} else {
|
||||
final myPrivateKey =
|
||||
await deriveNotificationPrivateKey(mnemonic: await _getMnemonic());
|
||||
final myPrivateKey = await deriveNotificationPrivateKey(
|
||||
mnemonic: (await _getMnemonicString())!,
|
||||
mnemonicPassphrase: (await _getMnemonicPassphrase())!,
|
||||
);
|
||||
final sendToAddress = await nextUnusedSendAddressFrom(
|
||||
pCode: paymentCode,
|
||||
privateKey: myPrivateKey,
|
||||
|
@ -749,8 +758,10 @@ mixin PaynymWalletInterface {
|
|||
|
||||
final pubKey = designatedInput.scriptSigAsm!.split(" ")[1].fromHex;
|
||||
|
||||
final myPrivateKey =
|
||||
await deriveNotificationPrivateKey(mnemonic: await _getMnemonic());
|
||||
final myPrivateKey = await deriveNotificationPrivateKey(
|
||||
mnemonic: (await _getMnemonicString())!,
|
||||
mnemonicPassphrase: (await _getMnemonicPassphrase())!,
|
||||
);
|
||||
|
||||
final S = SecretPoint(myPrivateKey, pubKey);
|
||||
|
||||
|
@ -888,12 +899,18 @@ mixin PaynymWalletInterface {
|
|||
const maxCount = 2147483647;
|
||||
assert(maxNumberOfIndexesToCheck < maxCount);
|
||||
|
||||
final mnemonic = await _getMnemonic();
|
||||
final mnemonic = (await _getMnemonicString())!;
|
||||
final mnemonicPassphrase = (await _getMnemonicPassphrase())!;
|
||||
|
||||
final mySendPrivateKey =
|
||||
await deriveNotificationPrivateKey(mnemonic: mnemonic);
|
||||
final receivingNode =
|
||||
(await getRootNode(mnemonic: mnemonic)).derivePath(kPaynymDerivePath);
|
||||
final mySendPrivateKey = await deriveNotificationPrivateKey(
|
||||
mnemonic: mnemonic,
|
||||
mnemonicPassphrase: mnemonicPassphrase,
|
||||
);
|
||||
final receivingNode = (await _getRootNode(
|
||||
mnemonic: mnemonic,
|
||||
mnemonicPassphrase: mnemonicPassphrase,
|
||||
))
|
||||
.derivePath(kPaynymDerivePath);
|
||||
|
||||
List<Address> addresses = [];
|
||||
int receivingGapCounter = 0;
|
||||
|
@ -1140,7 +1157,10 @@ mixin PaynymWalletInterface {
|
|||
if (storedAddress != null) {
|
||||
return storedAddress;
|
||||
} else {
|
||||
final root = await getRootNode(mnemonic: await _getMnemonic());
|
||||
final root = await _getRootNode(
|
||||
mnemonic: (await _getMnemonicString())!,
|
||||
mnemonicPassphrase: (await _getMnemonicPassphrase())!,
|
||||
);
|
||||
final node = root.derivePath(kPaynymDerivePath);
|
||||
final paymentCode = PaymentCode.initFromPubKey(
|
||||
node.publicKey,
|
||||
|
|
|
@ -5,28 +5,124 @@ 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,
|
||||
// =============================== get root ==================================
|
||||
static bip32.BIP32 getBip32RootSync(
|
||||
String mnemonic,
|
||||
String mnemonicPassphrase,
|
||||
NetworkType networkType,
|
||||
) {
|
||||
final seed = bip39.mnemonicToSeed(mnemonic, passphrase: mnemonicPassphrase);
|
||||
final _networkType = bip32.NetworkType(
|
||||
wif: networkType.wif,
|
||||
bip32: bip32.Bip32Type(
|
||||
public: network.bip32.public,
|
||||
private: network.bip32.private,
|
||||
public: networkType.bip32.public,
|
||||
private: networkType.bip32.private,
|
||||
),
|
||||
);
|
||||
|
||||
final root = bip32.BIP32.fromSeed(seed, networkType);
|
||||
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));
|
||||
String mnemonic,
|
||||
String mnemonicPassphrase,
|
||||
NetworkType networkType,
|
||||
) async {
|
||||
final root = await compute(
|
||||
_getBip32RootWrapper,
|
||||
Tuple3(
|
||||
mnemonic,
|
||||
mnemonicPassphrase,
|
||||
networkType,
|
||||
),
|
||||
);
|
||||
return root;
|
||||
}
|
||||
|
||||
/// wrapper for compute()
|
||||
static bip32.BIP32 _getBip32RootWrapper(Tuple2<String, NetworkType> args) {
|
||||
return getBip32RootSync(args.item1, args.item2);
|
||||
static bip32.BIP32 _getBip32RootWrapper(
|
||||
Tuple3<String, String, NetworkType> args,
|
||||
) {
|
||||
return getBip32RootSync(
|
||||
args.item1,
|
||||
args.item2,
|
||||
args.item3,
|
||||
);
|
||||
}
|
||||
|
||||
// =========================== get node from root ============================
|
||||
static bip32.BIP32 getBip32NodeFromRootSync(
|
||||
bip32.BIP32 root,
|
||||
String derivePath,
|
||||
) {
|
||||
return root.derivePath(derivePath);
|
||||
}
|
||||
|
||||
static Future<bip32.BIP32> getBip32NodeFromRoot(
|
||||
bip32.BIP32 root,
|
||||
String derivePath,
|
||||
) async {
|
||||
final node = await compute(
|
||||
_getBip32NodeFromRootWrapper,
|
||||
Tuple2(
|
||||
root,
|
||||
derivePath,
|
||||
),
|
||||
);
|
||||
return node;
|
||||
}
|
||||
|
||||
/// wrapper for compute()
|
||||
static bip32.BIP32 _getBip32NodeFromRootWrapper(
|
||||
Tuple2<bip32.BIP32, String> args,
|
||||
) {
|
||||
return getBip32NodeFromRootSync(
|
||||
args.item1,
|
||||
args.item2,
|
||||
);
|
||||
}
|
||||
|
||||
// =============================== get node ==================================
|
||||
static bip32.BIP32 getBip32NodeSync(
|
||||
String mnemonic,
|
||||
String mnemonicPassphrase,
|
||||
NetworkType network,
|
||||
String derivePath,
|
||||
) {
|
||||
final root = getBip32RootSync(mnemonic, mnemonicPassphrase, network);
|
||||
|
||||
final node = getBip32NodeFromRootSync(root, derivePath);
|
||||
return node;
|
||||
}
|
||||
|
||||
static Future<bip32.BIP32> getBip32Node(
|
||||
String mnemonic,
|
||||
String mnemonicPassphrase,
|
||||
NetworkType networkType,
|
||||
String derivePath,
|
||||
) async {
|
||||
final node = await compute(
|
||||
_getBip32NodeWrapper,
|
||||
Tuple4(
|
||||
mnemonic,
|
||||
mnemonicPassphrase,
|
||||
networkType,
|
||||
derivePath,
|
||||
),
|
||||
);
|
||||
return node;
|
||||
}
|
||||
|
||||
/// wrapper for compute()
|
||||
static bip32.BIP32 _getBip32NodeWrapper(
|
||||
Tuple4<String, String, NetworkType, String> args,
|
||||
) {
|
||||
return getBip32NodeSync(
|
||||
args.item1,
|
||||
args.item2,
|
||||
args.item3,
|
||||
args.item4,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -353,6 +353,11 @@ class MockManager extends _i1.Mock implements _i11.Manager {
|
|||
returnValue: _i8.Future<List<String>>.value(<String>[]),
|
||||
) as _i8.Future<List<String>>);
|
||||
@override
|
||||
_i8.Future<String?> get mnemonicPassphrase => (super.noSuchMethod(
|
||||
Invocation.getter(#mnemonicPassphrase),
|
||||
returnValue: _i8.Future<String?>.value(),
|
||||
) as _i8.Future<String?>);
|
||||
@override
|
||||
bool get isConnected => (super.noSuchMethod(
|
||||
Invocation.getter(#isConnected),
|
||||
returnValue: false,
|
||||
|
@ -464,6 +469,7 @@ class MockManager extends _i1.Mock implements _i11.Manager {
|
|||
@override
|
||||
_i8.Future<void> recoverFromMnemonic({
|
||||
required String? mnemonic,
|
||||
String? mnemonicPassphrase,
|
||||
required int? maxUnusedAddressGap,
|
||||
required int? maxNumberOfIndexesToCheck,
|
||||
required int? height,
|
||||
|
@ -474,6 +480,7 @@ class MockManager extends _i1.Mock implements _i11.Manager {
|
|||
[],
|
||||
{
|
||||
#mnemonic: mnemonic,
|
||||
#mnemonicPassphrase: mnemonicPassphrase,
|
||||
#maxUnusedAddressGap: maxUnusedAddressGap,
|
||||
#maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck,
|
||||
#height: height,
|
||||
|
|
|
@ -314,6 +314,11 @@ class MockManager extends _i1.Mock implements _i9.Manager {
|
|||
returnValue: _i7.Future<List<String>>.value(<String>[]),
|
||||
) as _i7.Future<List<String>>);
|
||||
@override
|
||||
_i7.Future<String?> get mnemonicPassphrase => (super.noSuchMethod(
|
||||
Invocation.getter(#mnemonicPassphrase),
|
||||
returnValue: _i7.Future<String?>.value(),
|
||||
) as _i7.Future<String?>);
|
||||
@override
|
||||
bool get isConnected => (super.noSuchMethod(
|
||||
Invocation.getter(#isConnected),
|
||||
returnValue: false,
|
||||
|
@ -425,6 +430,7 @@ class MockManager extends _i1.Mock implements _i9.Manager {
|
|||
@override
|
||||
_i7.Future<void> recoverFromMnemonic({
|
||||
required String? mnemonic,
|
||||
String? mnemonicPassphrase,
|
||||
required int? maxUnusedAddressGap,
|
||||
required int? maxNumberOfIndexesToCheck,
|
||||
required int? height,
|
||||
|
@ -435,6 +441,7 @@ class MockManager extends _i1.Mock implements _i9.Manager {
|
|||
[],
|
||||
{
|
||||
#mnemonic: mnemonic,
|
||||
#mnemonicPassphrase: mnemonicPassphrase,
|
||||
#maxUnusedAddressGap: maxUnusedAddressGap,
|
||||
#maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck,
|
||||
#height: height,
|
||||
|
|
|
@ -312,6 +312,11 @@ class MockManager extends _i1.Mock implements _i9.Manager {
|
|||
returnValue: _i7.Future<List<String>>.value(<String>[]),
|
||||
) as _i7.Future<List<String>>);
|
||||
@override
|
||||
_i7.Future<String?> get mnemonicPassphrase => (super.noSuchMethod(
|
||||
Invocation.getter(#mnemonicPassphrase),
|
||||
returnValue: _i7.Future<String?>.value(),
|
||||
) as _i7.Future<String?>);
|
||||
@override
|
||||
bool get isConnected => (super.noSuchMethod(
|
||||
Invocation.getter(#isConnected),
|
||||
returnValue: false,
|
||||
|
@ -423,6 +428,7 @@ class MockManager extends _i1.Mock implements _i9.Manager {
|
|||
@override
|
||||
_i7.Future<void> recoverFromMnemonic({
|
||||
required String? mnemonic,
|
||||
String? mnemonicPassphrase,
|
||||
required int? maxUnusedAddressGap,
|
||||
required int? maxNumberOfIndexesToCheck,
|
||||
required int? height,
|
||||
|
@ -433,6 +439,7 @@ class MockManager extends _i1.Mock implements _i9.Manager {
|
|||
[],
|
||||
{
|
||||
#mnemonic: mnemonic,
|
||||
#mnemonicPassphrase: mnemonicPassphrase,
|
||||
#maxUnusedAddressGap: maxUnusedAddressGap,
|
||||
#maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck,
|
||||
#height: height,
|
||||
|
|
|
@ -621,6 +621,11 @@ class MockManager extends _i1.Mock implements _i12.Manager {
|
|||
returnValue: _i7.Future<List<String>>.value(<String>[]),
|
||||
) as _i7.Future<List<String>>);
|
||||
@override
|
||||
_i7.Future<String?> get mnemonicPassphrase => (super.noSuchMethod(
|
||||
Invocation.getter(#mnemonicPassphrase),
|
||||
returnValue: _i7.Future<String?>.value(),
|
||||
) as _i7.Future<String?>);
|
||||
@override
|
||||
bool get isConnected => (super.noSuchMethod(
|
||||
Invocation.getter(#isConnected),
|
||||
returnValue: false,
|
||||
|
@ -732,6 +737,7 @@ class MockManager extends _i1.Mock implements _i12.Manager {
|
|||
@override
|
||||
_i7.Future<void> recoverFromMnemonic({
|
||||
required String? mnemonic,
|
||||
String? mnemonicPassphrase,
|
||||
required int? maxUnusedAddressGap,
|
||||
required int? maxNumberOfIndexesToCheck,
|
||||
required int? height,
|
||||
|
@ -742,6 +748,7 @@ class MockManager extends _i1.Mock implements _i12.Manager {
|
|||
[],
|
||||
{
|
||||
#mnemonic: mnemonic,
|
||||
#mnemonicPassphrase: mnemonicPassphrase,
|
||||
#maxUnusedAddressGap: maxUnusedAddressGap,
|
||||
#maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck,
|
||||
#height: height,
|
||||
|
|
|
@ -408,6 +408,11 @@ class MockManager extends _i1.Mock implements _i9.Manager {
|
|||
returnValue: _i6.Future<List<String>>.value(<String>[]),
|
||||
) as _i6.Future<List<String>>);
|
||||
@override
|
||||
_i6.Future<String?> get mnemonicPassphrase => (super.noSuchMethod(
|
||||
Invocation.getter(#mnemonicPassphrase),
|
||||
returnValue: _i6.Future<String?>.value(),
|
||||
) as _i6.Future<String?>);
|
||||
@override
|
||||
bool get isConnected => (super.noSuchMethod(
|
||||
Invocation.getter(#isConnected),
|
||||
returnValue: false,
|
||||
|
@ -519,6 +524,7 @@ class MockManager extends _i1.Mock implements _i9.Manager {
|
|||
@override
|
||||
_i6.Future<void> recoverFromMnemonic({
|
||||
required String? mnemonic,
|
||||
String? mnemonicPassphrase,
|
||||
required int? maxUnusedAddressGap,
|
||||
required int? maxNumberOfIndexesToCheck,
|
||||
required int? height,
|
||||
|
@ -529,6 +535,7 @@ class MockManager extends _i1.Mock implements _i9.Manager {
|
|||
[],
|
||||
{
|
||||
#mnemonic: mnemonic,
|
||||
#mnemonicPassphrase: mnemonicPassphrase,
|
||||
#maxUnusedAddressGap: maxUnusedAddressGap,
|
||||
#maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck,
|
||||
#height: height,
|
||||
|
|
|
@ -408,6 +408,11 @@ class MockManager extends _i1.Mock implements _i9.Manager {
|
|||
returnValue: _i6.Future<List<String>>.value(<String>[]),
|
||||
) as _i6.Future<List<String>>);
|
||||
@override
|
||||
_i6.Future<String?> get mnemonicPassphrase => (super.noSuchMethod(
|
||||
Invocation.getter(#mnemonicPassphrase),
|
||||
returnValue: _i6.Future<String?>.value(),
|
||||
) as _i6.Future<String?>);
|
||||
@override
|
||||
bool get isConnected => (super.noSuchMethod(
|
||||
Invocation.getter(#isConnected),
|
||||
returnValue: false,
|
||||
|
@ -519,6 +524,7 @@ class MockManager extends _i1.Mock implements _i9.Manager {
|
|||
@override
|
||||
_i6.Future<void> recoverFromMnemonic({
|
||||
required String? mnemonic,
|
||||
String? mnemonicPassphrase,
|
||||
required int? maxUnusedAddressGap,
|
||||
required int? maxNumberOfIndexesToCheck,
|
||||
required int? height,
|
||||
|
@ -529,6 +535,7 @@ class MockManager extends _i1.Mock implements _i9.Manager {
|
|||
[],
|
||||
{
|
||||
#mnemonic: mnemonic,
|
||||
#mnemonicPassphrase: mnemonicPassphrase,
|
||||
#maxUnusedAddressGap: maxUnusedAddressGap,
|
||||
#maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck,
|
||||
#height: height,
|
||||
|
|
|
@ -408,6 +408,11 @@ class MockManager extends _i1.Mock implements _i9.Manager {
|
|||
returnValue: _i6.Future<List<String>>.value(<String>[]),
|
||||
) as _i6.Future<List<String>>);
|
||||
@override
|
||||
_i6.Future<String?> get mnemonicPassphrase => (super.noSuchMethod(
|
||||
Invocation.getter(#mnemonicPassphrase),
|
||||
returnValue: _i6.Future<String?>.value(),
|
||||
) as _i6.Future<String?>);
|
||||
@override
|
||||
bool get isConnected => (super.noSuchMethod(
|
||||
Invocation.getter(#isConnected),
|
||||
returnValue: false,
|
||||
|
@ -519,6 +524,7 @@ class MockManager extends _i1.Mock implements _i9.Manager {
|
|||
@override
|
||||
_i6.Future<void> recoverFromMnemonic({
|
||||
required String? mnemonic,
|
||||
String? mnemonicPassphrase,
|
||||
required int? maxUnusedAddressGap,
|
||||
required int? maxNumberOfIndexesToCheck,
|
||||
required int? height,
|
||||
|
@ -529,6 +535,7 @@ class MockManager extends _i1.Mock implements _i9.Manager {
|
|||
[],
|
||||
{
|
||||
#mnemonic: mnemonic,
|
||||
#mnemonicPassphrase: mnemonicPassphrase,
|
||||
#maxUnusedAddressGap: maxUnusedAddressGap,
|
||||
#maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck,
|
||||
#height: height,
|
||||
|
|
|
@ -183,6 +183,11 @@ class MockManager extends _i1.Mock implements _i5.Manager {
|
|||
returnValue: _i7.Future<List<String>>.value(<String>[]),
|
||||
) as _i7.Future<List<String>>);
|
||||
@override
|
||||
_i7.Future<String?> get mnemonicPassphrase => (super.noSuchMethod(
|
||||
Invocation.getter(#mnemonicPassphrase),
|
||||
returnValue: _i7.Future<String?>.value(),
|
||||
) as _i7.Future<String?>);
|
||||
@override
|
||||
bool get isConnected => (super.noSuchMethod(
|
||||
Invocation.getter(#isConnected),
|
||||
returnValue: false,
|
||||
|
@ -294,6 +299,7 @@ class MockManager extends _i1.Mock implements _i5.Manager {
|
|||
@override
|
||||
_i7.Future<void> recoverFromMnemonic({
|
||||
required String? mnemonic,
|
||||
String? mnemonicPassphrase,
|
||||
required int? maxUnusedAddressGap,
|
||||
required int? maxNumberOfIndexesToCheck,
|
||||
required int? height,
|
||||
|
@ -304,6 +310,7 @@ class MockManager extends _i1.Mock implements _i5.Manager {
|
|||
[],
|
||||
{
|
||||
#mnemonic: mnemonic,
|
||||
#mnemonicPassphrase: mnemonicPassphrase,
|
||||
#maxUnusedAddressGap: maxUnusedAddressGap,
|
||||
#maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck,
|
||||
#height: height,
|
||||
|
|
|
@ -406,6 +406,11 @@ class MockManager extends _i1.Mock implements _i9.Manager {
|
|||
returnValue: _i6.Future<List<String>>.value(<String>[]),
|
||||
) as _i6.Future<List<String>>);
|
||||
@override
|
||||
_i6.Future<String?> get mnemonicPassphrase => (super.noSuchMethod(
|
||||
Invocation.getter(#mnemonicPassphrase),
|
||||
returnValue: _i6.Future<String?>.value(),
|
||||
) as _i6.Future<String?>);
|
||||
@override
|
||||
bool get isConnected => (super.noSuchMethod(
|
||||
Invocation.getter(#isConnected),
|
||||
returnValue: false,
|
||||
|
@ -517,6 +522,7 @@ class MockManager extends _i1.Mock implements _i9.Manager {
|
|||
@override
|
||||
_i6.Future<void> recoverFromMnemonic({
|
||||
required String? mnemonic,
|
||||
String? mnemonicPassphrase,
|
||||
required int? maxUnusedAddressGap,
|
||||
required int? maxNumberOfIndexesToCheck,
|
||||
required int? height,
|
||||
|
@ -527,6 +533,7 @@ class MockManager extends _i1.Mock implements _i9.Manager {
|
|||
[],
|
||||
{
|
||||
#mnemonic: mnemonic,
|
||||
#mnemonicPassphrase: mnemonicPassphrase,
|
||||
#maxUnusedAddressGap: maxUnusedAddressGap,
|
||||
#maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck,
|
||||
#height: height,
|
||||
|
|
|
@ -621,6 +621,11 @@ class MockManager extends _i1.Mock implements _i12.Manager {
|
|||
returnValue: _i7.Future<List<String>>.value(<String>[]),
|
||||
) as _i7.Future<List<String>>);
|
||||
@override
|
||||
_i7.Future<String?> get mnemonicPassphrase => (super.noSuchMethod(
|
||||
Invocation.getter(#mnemonicPassphrase),
|
||||
returnValue: _i7.Future<String?>.value(),
|
||||
) as _i7.Future<String?>);
|
||||
@override
|
||||
bool get isConnected => (super.noSuchMethod(
|
||||
Invocation.getter(#isConnected),
|
||||
returnValue: false,
|
||||
|
@ -732,6 +737,7 @@ class MockManager extends _i1.Mock implements _i12.Manager {
|
|||
@override
|
||||
_i7.Future<void> recoverFromMnemonic({
|
||||
required String? mnemonic,
|
||||
String? mnemonicPassphrase,
|
||||
required int? maxUnusedAddressGap,
|
||||
required int? maxNumberOfIndexesToCheck,
|
||||
required int? height,
|
||||
|
@ -742,6 +748,7 @@ class MockManager extends _i1.Mock implements _i12.Manager {
|
|||
[],
|
||||
{
|
||||
#mnemonic: mnemonic,
|
||||
#mnemonicPassphrase: mnemonicPassphrase,
|
||||
#maxUnusedAddressGap: maxUnusedAddressGap,
|
||||
#maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck,
|
||||
#height: height,
|
||||
|
|
|
@ -462,6 +462,11 @@ class MockManager extends _i1.Mock implements _i12.Manager {
|
|||
returnValue: _i8.Future<List<String>>.value(<String>[]),
|
||||
) as _i8.Future<List<String>>);
|
||||
@override
|
||||
_i8.Future<String?> get mnemonicPassphrase => (super.noSuchMethod(
|
||||
Invocation.getter(#mnemonicPassphrase),
|
||||
returnValue: _i8.Future<String?>.value(),
|
||||
) as _i8.Future<String?>);
|
||||
@override
|
||||
bool get isConnected => (super.noSuchMethod(
|
||||
Invocation.getter(#isConnected),
|
||||
returnValue: false,
|
||||
|
@ -573,6 +578,7 @@ class MockManager extends _i1.Mock implements _i12.Manager {
|
|||
@override
|
||||
_i8.Future<void> recoverFromMnemonic({
|
||||
required String? mnemonic,
|
||||
String? mnemonicPassphrase,
|
||||
required int? maxUnusedAddressGap,
|
||||
required int? maxNumberOfIndexesToCheck,
|
||||
required int? height,
|
||||
|
@ -583,6 +589,7 @@ class MockManager extends _i1.Mock implements _i12.Manager {
|
|||
[],
|
||||
{
|
||||
#mnemonic: mnemonic,
|
||||
#mnemonicPassphrase: mnemonicPassphrase,
|
||||
#maxUnusedAddressGap: maxUnusedAddressGap,
|
||||
#maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck,
|
||||
#height: height,
|
||||
|
|
|
@ -183,6 +183,11 @@ class MockManager extends _i1.Mock implements _i5.Manager {
|
|||
returnValue: _i7.Future<List<String>>.value(<String>[]),
|
||||
) as _i7.Future<List<String>>);
|
||||
@override
|
||||
_i7.Future<String?> get mnemonicPassphrase => (super.noSuchMethod(
|
||||
Invocation.getter(#mnemonicPassphrase),
|
||||
returnValue: _i7.Future<String?>.value(),
|
||||
) as _i7.Future<String?>);
|
||||
@override
|
||||
bool get isConnected => (super.noSuchMethod(
|
||||
Invocation.getter(#isConnected),
|
||||
returnValue: false,
|
||||
|
@ -294,6 +299,7 @@ class MockManager extends _i1.Mock implements _i5.Manager {
|
|||
@override
|
||||
_i7.Future<void> recoverFromMnemonic({
|
||||
required String? mnemonic,
|
||||
String? mnemonicPassphrase,
|
||||
required int? maxUnusedAddressGap,
|
||||
required int? maxNumberOfIndexesToCheck,
|
||||
required int? height,
|
||||
|
@ -304,6 +310,7 @@ class MockManager extends _i1.Mock implements _i5.Manager {
|
|||
[],
|
||||
{
|
||||
#mnemonic: mnemonic,
|
||||
#mnemonicPassphrase: mnemonicPassphrase,
|
||||
#maxUnusedAddressGap: maxUnusedAddressGap,
|
||||
#maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck,
|
||||
#height: height,
|
||||
|
|
|
@ -183,6 +183,11 @@ class MockManager extends _i1.Mock implements _i5.Manager {
|
|||
returnValue: _i7.Future<List<String>>.value(<String>[]),
|
||||
) as _i7.Future<List<String>>);
|
||||
@override
|
||||
_i7.Future<String?> get mnemonicPassphrase => (super.noSuchMethod(
|
||||
Invocation.getter(#mnemonicPassphrase),
|
||||
returnValue: _i7.Future<String?>.value(),
|
||||
) as _i7.Future<String?>);
|
||||
@override
|
||||
bool get isConnected => (super.noSuchMethod(
|
||||
Invocation.getter(#isConnected),
|
||||
returnValue: false,
|
||||
|
@ -294,6 +299,7 @@ class MockManager extends _i1.Mock implements _i5.Manager {
|
|||
@override
|
||||
_i7.Future<void> recoverFromMnemonic({
|
||||
required String? mnemonic,
|
||||
String? mnemonicPassphrase,
|
||||
required int? maxUnusedAddressGap,
|
||||
required int? maxNumberOfIndexesToCheck,
|
||||
required int? height,
|
||||
|
@ -304,6 +310,7 @@ class MockManager extends _i1.Mock implements _i5.Manager {
|
|||
[],
|
||||
{
|
||||
#mnemonic: mnemonic,
|
||||
#mnemonicPassphrase: mnemonicPassphrase,
|
||||
#maxUnusedAddressGap: maxUnusedAddressGap,
|
||||
#maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck,
|
||||
#height: height,
|
||||
|
|
|
@ -398,6 +398,11 @@ class MockManager extends _i1.Mock implements _i11.Manager {
|
|||
returnValue: _i8.Future<List<String>>.value(<String>[]),
|
||||
) as _i8.Future<List<String>>);
|
||||
@override
|
||||
_i8.Future<String?> get mnemonicPassphrase => (super.noSuchMethod(
|
||||
Invocation.getter(#mnemonicPassphrase),
|
||||
returnValue: _i8.Future<String?>.value(),
|
||||
) as _i8.Future<String?>);
|
||||
@override
|
||||
bool get isConnected => (super.noSuchMethod(
|
||||
Invocation.getter(#isConnected),
|
||||
returnValue: false,
|
||||
|
@ -509,6 +514,7 @@ class MockManager extends _i1.Mock implements _i11.Manager {
|
|||
@override
|
||||
_i8.Future<void> recoverFromMnemonic({
|
||||
required String? mnemonic,
|
||||
String? mnemonicPassphrase,
|
||||
required int? maxUnusedAddressGap,
|
||||
required int? maxNumberOfIndexesToCheck,
|
||||
required int? height,
|
||||
|
@ -519,6 +525,7 @@ class MockManager extends _i1.Mock implements _i11.Manager {
|
|||
[],
|
||||
{
|
||||
#mnemonic: mnemonic,
|
||||
#mnemonicPassphrase: mnemonicPassphrase,
|
||||
#maxUnusedAddressGap: maxUnusedAddressGap,
|
||||
#maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck,
|
||||
#height: height,
|
||||
|
|
|
@ -398,6 +398,11 @@ class MockManager extends _i1.Mock implements _i11.Manager {
|
|||
returnValue: _i8.Future<List<String>>.value(<String>[]),
|
||||
) as _i8.Future<List<String>>);
|
||||
@override
|
||||
_i8.Future<String?> get mnemonicPassphrase => (super.noSuchMethod(
|
||||
Invocation.getter(#mnemonicPassphrase),
|
||||
returnValue: _i8.Future<String?>.value(),
|
||||
) as _i8.Future<String?>);
|
||||
@override
|
||||
bool get isConnected => (super.noSuchMethod(
|
||||
Invocation.getter(#isConnected),
|
||||
returnValue: false,
|
||||
|
@ -509,6 +514,7 @@ class MockManager extends _i1.Mock implements _i11.Manager {
|
|||
@override
|
||||
_i8.Future<void> recoverFromMnemonic({
|
||||
required String? mnemonic,
|
||||
String? mnemonicPassphrase,
|
||||
required int? maxUnusedAddressGap,
|
||||
required int? maxNumberOfIndexesToCheck,
|
||||
required int? height,
|
||||
|
@ -519,6 +525,7 @@ class MockManager extends _i1.Mock implements _i11.Manager {
|
|||
[],
|
||||
{
|
||||
#mnemonic: mnemonic,
|
||||
#mnemonicPassphrase: mnemonicPassphrase,
|
||||
#maxUnusedAddressGap: maxUnusedAddressGap,
|
||||
#maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck,
|
||||
#height: height,
|
||||
|
|
|
@ -183,6 +183,11 @@ class MockManager extends _i1.Mock implements _i5.Manager {
|
|||
returnValue: _i7.Future<List<String>>.value(<String>[]),
|
||||
) as _i7.Future<List<String>>);
|
||||
@override
|
||||
_i7.Future<String?> get mnemonicPassphrase => (super.noSuchMethod(
|
||||
Invocation.getter(#mnemonicPassphrase),
|
||||
returnValue: _i7.Future<String?>.value(),
|
||||
) as _i7.Future<String?>);
|
||||
@override
|
||||
bool get isConnected => (super.noSuchMethod(
|
||||
Invocation.getter(#isConnected),
|
||||
returnValue: false,
|
||||
|
@ -294,6 +299,7 @@ class MockManager extends _i1.Mock implements _i5.Manager {
|
|||
@override
|
||||
_i7.Future<void> recoverFromMnemonic({
|
||||
required String? mnemonic,
|
||||
String? mnemonicPassphrase,
|
||||
required int? maxUnusedAddressGap,
|
||||
required int? maxNumberOfIndexesToCheck,
|
||||
required int? height,
|
||||
|
@ -304,6 +310,7 @@ class MockManager extends _i1.Mock implements _i5.Manager {
|
|||
[],
|
||||
{
|
||||
#mnemonic: mnemonic,
|
||||
#mnemonicPassphrase: mnemonicPassphrase,
|
||||
#maxUnusedAddressGap: maxUnusedAddressGap,
|
||||
#maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck,
|
||||
#height: height,
|
||||
|
|
|
@ -183,6 +183,11 @@ class MockManager extends _i1.Mock implements _i5.Manager {
|
|||
returnValue: _i7.Future<List<String>>.value(<String>[]),
|
||||
) as _i7.Future<List<String>>);
|
||||
@override
|
||||
_i7.Future<String?> get mnemonicPassphrase => (super.noSuchMethod(
|
||||
Invocation.getter(#mnemonicPassphrase),
|
||||
returnValue: _i7.Future<String?>.value(),
|
||||
) as _i7.Future<String?>);
|
||||
@override
|
||||
bool get isConnected => (super.noSuchMethod(
|
||||
Invocation.getter(#isConnected),
|
||||
returnValue: false,
|
||||
|
@ -294,6 +299,7 @@ class MockManager extends _i1.Mock implements _i5.Manager {
|
|||
@override
|
||||
_i7.Future<void> recoverFromMnemonic({
|
||||
required String? mnemonic,
|
||||
String? mnemonicPassphrase,
|
||||
required int? maxUnusedAddressGap,
|
||||
required int? maxNumberOfIndexesToCheck,
|
||||
required int? height,
|
||||
|
@ -304,6 +310,7 @@ class MockManager extends _i1.Mock implements _i5.Manager {
|
|||
[],
|
||||
{
|
||||
#mnemonic: mnemonic,
|
||||
#mnemonicPassphrase: mnemonicPassphrase,
|
||||
#maxUnusedAddressGap: maxUnusedAddressGap,
|
||||
#maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck,
|
||||
#height: height,
|
||||
|
|
|
@ -406,6 +406,11 @@ class MockManager extends _i1.Mock implements _i9.Manager {
|
|||
returnValue: _i6.Future<List<String>>.value(<String>[]),
|
||||
) as _i6.Future<List<String>>);
|
||||
@override
|
||||
_i6.Future<String?> get mnemonicPassphrase => (super.noSuchMethod(
|
||||
Invocation.getter(#mnemonicPassphrase),
|
||||
returnValue: _i6.Future<String?>.value(),
|
||||
) as _i6.Future<String?>);
|
||||
@override
|
||||
bool get isConnected => (super.noSuchMethod(
|
||||
Invocation.getter(#isConnected),
|
||||
returnValue: false,
|
||||
|
@ -517,6 +522,7 @@ class MockManager extends _i1.Mock implements _i9.Manager {
|
|||
@override
|
||||
_i6.Future<void> recoverFromMnemonic({
|
||||
required String? mnemonic,
|
||||
String? mnemonicPassphrase,
|
||||
required int? maxUnusedAddressGap,
|
||||
required int? maxNumberOfIndexesToCheck,
|
||||
required int? height,
|
||||
|
@ -527,6 +533,7 @@ class MockManager extends _i1.Mock implements _i9.Manager {
|
|||
[],
|
||||
{
|
||||
#mnemonic: mnemonic,
|
||||
#mnemonicPassphrase: mnemonicPassphrase,
|
||||
#maxUnusedAddressGap: maxUnusedAddressGap,
|
||||
#maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck,
|
||||
#height: height,
|
||||
|
|
|
@ -663,6 +663,11 @@ class MockManager extends _i1.Mock implements _i15.Manager {
|
|||
returnValue: _i8.Future<List<String>>.value(<String>[]),
|
||||
) as _i8.Future<List<String>>);
|
||||
@override
|
||||
_i8.Future<String?> get mnemonicPassphrase => (super.noSuchMethod(
|
||||
Invocation.getter(#mnemonicPassphrase),
|
||||
returnValue: _i8.Future<String?>.value(),
|
||||
) as _i8.Future<String?>);
|
||||
@override
|
||||
bool get isConnected => (super.noSuchMethod(
|
||||
Invocation.getter(#isConnected),
|
||||
returnValue: false,
|
||||
|
@ -774,6 +779,7 @@ class MockManager extends _i1.Mock implements _i15.Manager {
|
|||
@override
|
||||
_i8.Future<void> recoverFromMnemonic({
|
||||
required String? mnemonic,
|
||||
String? mnemonicPassphrase,
|
||||
required int? maxUnusedAddressGap,
|
||||
required int? maxNumberOfIndexesToCheck,
|
||||
required int? height,
|
||||
|
@ -784,6 +790,7 @@ class MockManager extends _i1.Mock implements _i15.Manager {
|
|||
[],
|
||||
{
|
||||
#mnemonic: mnemonic,
|
||||
#mnemonicPassphrase: mnemonicPassphrase,
|
||||
#maxUnusedAddressGap: maxUnusedAddressGap,
|
||||
#maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck,
|
||||
#height: height,
|
||||
|
|
|
@ -406,6 +406,11 @@ class MockManager extends _i1.Mock implements _i9.Manager {
|
|||
returnValue: _i6.Future<List<String>>.value(<String>[]),
|
||||
) as _i6.Future<List<String>>);
|
||||
@override
|
||||
_i6.Future<String?> get mnemonicPassphrase => (super.noSuchMethod(
|
||||
Invocation.getter(#mnemonicPassphrase),
|
||||
returnValue: _i6.Future<String?>.value(),
|
||||
) as _i6.Future<String?>);
|
||||
@override
|
||||
bool get isConnected => (super.noSuchMethod(
|
||||
Invocation.getter(#isConnected),
|
||||
returnValue: false,
|
||||
|
@ -517,6 +522,7 @@ class MockManager extends _i1.Mock implements _i9.Manager {
|
|||
@override
|
||||
_i6.Future<void> recoverFromMnemonic({
|
||||
required String? mnemonic,
|
||||
String? mnemonicPassphrase,
|
||||
required int? maxUnusedAddressGap,
|
||||
required int? maxNumberOfIndexesToCheck,
|
||||
required int? height,
|
||||
|
@ -527,6 +533,7 @@ class MockManager extends _i1.Mock implements _i9.Manager {
|
|||
[],
|
||||
{
|
||||
#mnemonic: mnemonic,
|
||||
#mnemonicPassphrase: mnemonicPassphrase,
|
||||
#maxUnusedAddressGap: maxUnusedAddressGap,
|
||||
#maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck,
|
||||
#height: height,
|
||||
|
|
|
@ -185,6 +185,11 @@ class MockManager extends _i1.Mock implements _i5.Manager {
|
|||
returnValue: _i7.Future<List<String>>.value(<String>[]),
|
||||
) as _i7.Future<List<String>>);
|
||||
@override
|
||||
_i7.Future<String?> get mnemonicPassphrase => (super.noSuchMethod(
|
||||
Invocation.getter(#mnemonicPassphrase),
|
||||
returnValue: _i7.Future<String?>.value(),
|
||||
) as _i7.Future<String?>);
|
||||
@override
|
||||
bool get isConnected => (super.noSuchMethod(
|
||||
Invocation.getter(#isConnected),
|
||||
returnValue: false,
|
||||
|
@ -296,6 +301,7 @@ class MockManager extends _i1.Mock implements _i5.Manager {
|
|||
@override
|
||||
_i7.Future<void> recoverFromMnemonic({
|
||||
required String? mnemonic,
|
||||
String? mnemonicPassphrase,
|
||||
required int? maxUnusedAddressGap,
|
||||
required int? maxNumberOfIndexesToCheck,
|
||||
required int? height,
|
||||
|
@ -306,6 +312,7 @@ class MockManager extends _i1.Mock implements _i5.Manager {
|
|||
[],
|
||||
{
|
||||
#mnemonic: mnemonic,
|
||||
#mnemonicPassphrase: mnemonicPassphrase,
|
||||
#maxUnusedAddressGap: maxUnusedAddressGap,
|
||||
#maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck,
|
||||
#height: height,
|
||||
|
|
|
@ -184,6 +184,11 @@ class MockManager extends _i1.Mock implements _i5.Manager {
|
|||
returnValue: _i7.Future<List<String>>.value(<String>[]),
|
||||
) as _i7.Future<List<String>>);
|
||||
@override
|
||||
_i7.Future<String?> get mnemonicPassphrase => (super.noSuchMethod(
|
||||
Invocation.getter(#mnemonicPassphrase),
|
||||
returnValue: _i7.Future<String?>.value(),
|
||||
) as _i7.Future<String?>);
|
||||
@override
|
||||
bool get isConnected => (super.noSuchMethod(
|
||||
Invocation.getter(#isConnected),
|
||||
returnValue: false,
|
||||
|
@ -295,6 +300,7 @@ class MockManager extends _i1.Mock implements _i5.Manager {
|
|||
@override
|
||||
_i7.Future<void> recoverFromMnemonic({
|
||||
required String? mnemonic,
|
||||
String? mnemonicPassphrase,
|
||||
required int? maxUnusedAddressGap,
|
||||
required int? maxNumberOfIndexesToCheck,
|
||||
required int? height,
|
||||
|
@ -305,6 +311,7 @@ class MockManager extends _i1.Mock implements _i5.Manager {
|
|||
[],
|
||||
{
|
||||
#mnemonic: mnemonic,
|
||||
#mnemonicPassphrase: mnemonicPassphrase,
|
||||
#maxUnusedAddressGap: maxUnusedAddressGap,
|
||||
#maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck,
|
||||
#height: height,
|
||||
|
|
|
@ -183,6 +183,11 @@ class MockManager extends _i1.Mock implements _i5.Manager {
|
|||
returnValue: _i7.Future<List<String>>.value(<String>[]),
|
||||
) as _i7.Future<List<String>>);
|
||||
@override
|
||||
_i7.Future<String?> get mnemonicPassphrase => (super.noSuchMethod(
|
||||
Invocation.getter(#mnemonicPassphrase),
|
||||
returnValue: _i7.Future<String?>.value(),
|
||||
) as _i7.Future<String?>);
|
||||
@override
|
||||
bool get isConnected => (super.noSuchMethod(
|
||||
Invocation.getter(#isConnected),
|
||||
returnValue: false,
|
||||
|
@ -294,6 +299,7 @@ class MockManager extends _i1.Mock implements _i5.Manager {
|
|||
@override
|
||||
_i7.Future<void> recoverFromMnemonic({
|
||||
required String? mnemonic,
|
||||
String? mnemonicPassphrase,
|
||||
required int? maxUnusedAddressGap,
|
||||
required int? maxNumberOfIndexesToCheck,
|
||||
required int? height,
|
||||
|
@ -304,6 +310,7 @@ class MockManager extends _i1.Mock implements _i5.Manager {
|
|||
[],
|
||||
{
|
||||
#mnemonic: mnemonic,
|
||||
#mnemonicPassphrase: mnemonicPassphrase,
|
||||
#maxUnusedAddressGap: maxUnusedAddressGap,
|
||||
#maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck,
|
||||
#height: height,
|
||||
|
|
|
@ -225,6 +225,11 @@ class MockManager extends _i1.Mock implements _i8.Manager {
|
|||
returnValue: _i7.Future<List<String>>.value(<String>[]),
|
||||
) as _i7.Future<List<String>>);
|
||||
@override
|
||||
_i7.Future<String?> get mnemonicPassphrase => (super.noSuchMethod(
|
||||
Invocation.getter(#mnemonicPassphrase),
|
||||
returnValue: _i7.Future<String?>.value(),
|
||||
) as _i7.Future<String?>);
|
||||
@override
|
||||
bool get isConnected => (super.noSuchMethod(
|
||||
Invocation.getter(#isConnected),
|
||||
returnValue: false,
|
||||
|
@ -336,6 +341,7 @@ class MockManager extends _i1.Mock implements _i8.Manager {
|
|||
@override
|
||||
_i7.Future<void> recoverFromMnemonic({
|
||||
required String? mnemonic,
|
||||
String? mnemonicPassphrase,
|
||||
required int? maxUnusedAddressGap,
|
||||
required int? maxNumberOfIndexesToCheck,
|
||||
required int? height,
|
||||
|
@ -346,6 +352,7 @@ class MockManager extends _i1.Mock implements _i8.Manager {
|
|||
[],
|
||||
{
|
||||
#mnemonic: mnemonic,
|
||||
#mnemonicPassphrase: mnemonicPassphrase,
|
||||
#maxUnusedAddressGap: maxUnusedAddressGap,
|
||||
#maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck,
|
||||
#height: height,
|
||||
|
|
|
@ -185,6 +185,11 @@ class MockManager extends _i1.Mock implements _i5.Manager {
|
|||
returnValue: _i7.Future<List<String>>.value(<String>[]),
|
||||
) as _i7.Future<List<String>>);
|
||||
@override
|
||||
_i7.Future<String?> get mnemonicPassphrase => (super.noSuchMethod(
|
||||
Invocation.getter(#mnemonicPassphrase),
|
||||
returnValue: _i7.Future<String?>.value(),
|
||||
) as _i7.Future<String?>);
|
||||
@override
|
||||
bool get isConnected => (super.noSuchMethod(
|
||||
Invocation.getter(#isConnected),
|
||||
returnValue: false,
|
||||
|
@ -296,6 +301,7 @@ class MockManager extends _i1.Mock implements _i5.Manager {
|
|||
@override
|
||||
_i7.Future<void> recoverFromMnemonic({
|
||||
required String? mnemonic,
|
||||
String? mnemonicPassphrase,
|
||||
required int? maxUnusedAddressGap,
|
||||
required int? maxNumberOfIndexesToCheck,
|
||||
required int? height,
|
||||
|
@ -306,6 +312,7 @@ class MockManager extends _i1.Mock implements _i5.Manager {
|
|||
[],
|
||||
{
|
||||
#mnemonic: mnemonic,
|
||||
#mnemonicPassphrase: mnemonicPassphrase,
|
||||
#maxUnusedAddressGap: maxUnusedAddressGap,
|
||||
#maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck,
|
||||
#height: height,
|
||||
|
|
|
@ -211,6 +211,16 @@ class MockFiroWallet extends _i1.Mock implements _i9.FiroWallet {
|
|||
returnValue: _i10.Future<List<String>>.value(<String>[]),
|
||||
) as _i10.Future<List<String>>);
|
||||
@override
|
||||
_i10.Future<String?> get mnemonicString => (super.noSuchMethod(
|
||||
Invocation.getter(#mnemonicString),
|
||||
returnValue: _i10.Future<String?>.value(),
|
||||
) as _i10.Future<String?>);
|
||||
@override
|
||||
_i10.Future<String?> get mnemonicPassphrase => (super.noSuchMethod(
|
||||
Invocation.getter(#mnemonicPassphrase),
|
||||
returnValue: _i10.Future<String?>.value(),
|
||||
) as _i10.Future<String?>);
|
||||
@override
|
||||
_i10.Future<int> get maxFee => (super.noSuchMethod(
|
||||
Invocation.getter(#maxFee),
|
||||
returnValue: _i10.Future<int>.value(0),
|
||||
|
@ -634,14 +644,18 @@ class MockFiroWallet extends _i1.Mock implements _i9.FiroWallet {
|
|||
) as _i10.Future<void>);
|
||||
@override
|
||||
_i10.Future<void> fillAddresses(
|
||||
String? suppliedMnemonic, {
|
||||
String? suppliedMnemonic,
|
||||
String? mnemonicPassphrase, {
|
||||
int? perBatch = 50,
|
||||
int? numberOfThreads = 4,
|
||||
}) =>
|
||||
(super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#fillAddresses,
|
||||
[suppliedMnemonic],
|
||||
[
|
||||
suppliedMnemonic,
|
||||
mnemonicPassphrase,
|
||||
],
|
||||
{
|
||||
#perBatch: perBatch,
|
||||
#numberOfThreads: numberOfThreads,
|
||||
|
@ -669,6 +683,7 @@ class MockFiroWallet extends _i1.Mock implements _i9.FiroWallet {
|
|||
@override
|
||||
_i10.Future<void> recoverFromMnemonic({
|
||||
required String? mnemonic,
|
||||
String? mnemonicPassphrase,
|
||||
required int? maxUnusedAddressGap,
|
||||
required int? maxNumberOfIndexesToCheck,
|
||||
required int? height,
|
||||
|
@ -679,6 +694,7 @@ class MockFiroWallet extends _i1.Mock implements _i9.FiroWallet {
|
|||
[],
|
||||
{
|
||||
#mnemonic: mnemonic,
|
||||
#mnemonicPassphrase: mnemonicPassphrase,
|
||||
#maxUnusedAddressGap: maxUnusedAddressGap,
|
||||
#maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck,
|
||||
#height: height,
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -528,6 +528,11 @@ class MockManager extends _i1.Mock implements _i6.Manager {
|
|||
returnValue: _i18.Future<List<String>>.value(<String>[]),
|
||||
) as _i18.Future<List<String>>);
|
||||
@override
|
||||
_i18.Future<String?> get mnemonicPassphrase => (super.noSuchMethod(
|
||||
Invocation.getter(#mnemonicPassphrase),
|
||||
returnValue: _i18.Future<String?>.value(),
|
||||
) as _i18.Future<String?>);
|
||||
@override
|
||||
bool get isConnected => (super.noSuchMethod(
|
||||
Invocation.getter(#isConnected),
|
||||
returnValue: false,
|
||||
|
@ -639,6 +644,7 @@ class MockManager extends _i1.Mock implements _i6.Manager {
|
|||
@override
|
||||
_i18.Future<void> recoverFromMnemonic({
|
||||
required String? mnemonic,
|
||||
String? mnemonicPassphrase,
|
||||
required int? maxUnusedAddressGap,
|
||||
required int? maxNumberOfIndexesToCheck,
|
||||
required int? height,
|
||||
|
@ -649,6 +655,7 @@ class MockManager extends _i1.Mock implements _i6.Manager {
|
|||
[],
|
||||
{
|
||||
#mnemonic: mnemonic,
|
||||
#mnemonicPassphrase: mnemonicPassphrase,
|
||||
#maxUnusedAddressGap: maxUnusedAddressGap,
|
||||
#maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck,
|
||||
#height: height,
|
||||
|
@ -845,6 +852,16 @@ class MockCoinServiceAPI extends _i1.Mock implements _i7.CoinServiceAPI {
|
|||
returnValue: _i18.Future<List<String>>.value(<String>[]),
|
||||
) as _i18.Future<List<String>>);
|
||||
@override
|
||||
_i18.Future<String?> get mnemonicString => (super.noSuchMethod(
|
||||
Invocation.getter(#mnemonicString),
|
||||
returnValue: _i18.Future<String?>.value(),
|
||||
) as _i18.Future<String?>);
|
||||
@override
|
||||
_i18.Future<String?> get mnemonicPassphrase => (super.noSuchMethod(
|
||||
Invocation.getter(#mnemonicPassphrase),
|
||||
returnValue: _i18.Future<String?>.value(),
|
||||
) as _i18.Future<String?>);
|
||||
@override
|
||||
bool get hasCalledExit => (super.noSuchMethod(
|
||||
Invocation.getter(#hasCalledExit),
|
||||
returnValue: false,
|
||||
|
@ -925,6 +942,7 @@ class MockCoinServiceAPI extends _i1.Mock implements _i7.CoinServiceAPI {
|
|||
@override
|
||||
_i18.Future<void> recoverFromMnemonic({
|
||||
required String? mnemonic,
|
||||
String? mnemonicPassphrase,
|
||||
required int? maxUnusedAddressGap,
|
||||
required int? maxNumberOfIndexesToCheck,
|
||||
required int? height,
|
||||
|
@ -935,6 +953,7 @@ class MockCoinServiceAPI extends _i1.Mock implements _i7.CoinServiceAPI {
|
|||
[],
|
||||
{
|
||||
#mnemonic: mnemonic,
|
||||
#mnemonicPassphrase: mnemonicPassphrase,
|
||||
#maxUnusedAddressGap: maxUnusedAddressGap,
|
||||
#maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck,
|
||||
#height: height,
|
||||
|
@ -1130,6 +1149,16 @@ class MockFiroWallet extends _i1.Mock implements _i22.FiroWallet {
|
|||
returnValue: _i18.Future<List<String>>.value(<String>[]),
|
||||
) as _i18.Future<List<String>>);
|
||||
@override
|
||||
_i18.Future<String?> get mnemonicString => (super.noSuchMethod(
|
||||
Invocation.getter(#mnemonicString),
|
||||
returnValue: _i18.Future<String?>.value(),
|
||||
) as _i18.Future<String?>);
|
||||
@override
|
||||
_i18.Future<String?> get mnemonicPassphrase => (super.noSuchMethod(
|
||||
Invocation.getter(#mnemonicPassphrase),
|
||||
returnValue: _i18.Future<String?>.value(),
|
||||
) as _i18.Future<String?>);
|
||||
@override
|
||||
_i18.Future<int> get maxFee => (super.noSuchMethod(
|
||||
Invocation.getter(#maxFee),
|
||||
returnValue: _i18.Future<int>.value(0),
|
||||
|
@ -1553,14 +1582,18 @@ class MockFiroWallet extends _i1.Mock implements _i22.FiroWallet {
|
|||
) as _i18.Future<void>);
|
||||
@override
|
||||
_i18.Future<void> fillAddresses(
|
||||
String? suppliedMnemonic, {
|
||||
String? suppliedMnemonic,
|
||||
String? mnemonicPassphrase, {
|
||||
int? perBatch = 50,
|
||||
int? numberOfThreads = 4,
|
||||
}) =>
|
||||
(super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#fillAddresses,
|
||||
[suppliedMnemonic],
|
||||
[
|
||||
suppliedMnemonic,
|
||||
mnemonicPassphrase,
|
||||
],
|
||||
{
|
||||
#perBatch: perBatch,
|
||||
#numberOfThreads: numberOfThreads,
|
||||
|
@ -1588,6 +1621,7 @@ class MockFiroWallet extends _i1.Mock implements _i22.FiroWallet {
|
|||
@override
|
||||
_i18.Future<void> recoverFromMnemonic({
|
||||
required String? mnemonic,
|
||||
String? mnemonicPassphrase,
|
||||
required int? maxUnusedAddressGap,
|
||||
required int? maxNumberOfIndexesToCheck,
|
||||
required int? height,
|
||||
|
@ -1598,6 +1632,7 @@ class MockFiroWallet extends _i1.Mock implements _i22.FiroWallet {
|
|||
[],
|
||||
{
|
||||
#mnemonic: mnemonic,
|
||||
#mnemonicPassphrase: mnemonicPassphrase,
|
||||
#maxUnusedAddressGap: maxUnusedAddressGap,
|
||||
#maxNumberOfIndexesToCheck: maxNumberOfIndexesToCheck,
|
||||
#height: height,
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue