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