mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2024-12-23 03:49:22 +00:00
Merge pull request #1041 from cypherstack/frost-init-fix
Various fixes and tweaks
This commit is contained in:
commit
a74c565f9a
9 changed files with 314 additions and 252 deletions
|
@ -26,18 +26,20 @@ import '../../../services/transaction_notification_tracker.dart';
|
|||
import '../../../themes/stack_colors.dart';
|
||||
import '../../../utilities/assets.dart';
|
||||
import '../../../utilities/logger.dart';
|
||||
import '../../../utilities/show_loading.dart';
|
||||
import '../../../utilities/text_styles.dart';
|
||||
import '../../../utilities/util.dart';
|
||||
import '../../../wallets/crypto_currency/crypto_currency.dart';
|
||||
import '../../../wallets/isar/models/wallet_info.dart';
|
||||
import '../../../wallets/wallet/intermediate/lib_monero_wallet.dart';
|
||||
import '../../../wallets/wallet/wallet.dart';
|
||||
import '../../../wallets/wallet/wallet_mixin_interfaces/mnemonic_interface.dart';
|
||||
import '../../../widgets/custom_buttons/app_bar_icon_button.dart';
|
||||
import '../../../widgets/desktop/desktop_app_bar.dart';
|
||||
import '../../../widgets/desktop/desktop_scaffold.dart';
|
||||
import '../../../widgets/loading_indicator.dart';
|
||||
import '../../../widgets/rounded_container.dart';
|
||||
import '../../../widgets/rounded_white_container.dart';
|
||||
import '../../../widgets/stack_dialog.dart';
|
||||
import '../new_wallet_options/new_wallet_options_view.dart';
|
||||
import '../new_wallet_recovery_phrase_view/new_wallet_recovery_phrase_view.dart';
|
||||
import 'recovery_phrase_explanation_dialog.dart';
|
||||
|
@ -65,6 +67,221 @@ class _NewWalletRecoveryPhraseWarningViewState
|
|||
late final String walletName;
|
||||
late final bool isDesktop;
|
||||
|
||||
Future<void> _initNewWallet() async {
|
||||
Exception? ex;
|
||||
final result = await showLoading(
|
||||
whileFuture: _initNewFuture(),
|
||||
context: context,
|
||||
message: "Generating...",
|
||||
onException: (e) => ex = e,
|
||||
);
|
||||
|
||||
// on failure show error message
|
||||
if (result == null) {
|
||||
if (mounted) {
|
||||
await showDialog<void>(
|
||||
context: context,
|
||||
builder: (_) => StackOkDialog(
|
||||
title: "Create Wallet Error",
|
||||
message: ex?.toString() ?? "Unknown error",
|
||||
maxWidth: 600,
|
||||
),
|
||||
);
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
if (mounted) {
|
||||
final nav = Navigator.of(context);
|
||||
unawaited(
|
||||
nav.pushNamed(
|
||||
NewWalletRecoveryPhraseView.routeName,
|
||||
arguments: Tuple2(
|
||||
result.$1,
|
||||
result.$2,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<(Wallet, List<String>)> _initNewFuture() async {
|
||||
try {
|
||||
String? otherDataJsonString;
|
||||
if (widget.coin is Tezos) {
|
||||
otherDataJsonString = jsonEncode({
|
||||
WalletInfoKeys.tezosDerivationPath:
|
||||
Tezos.standardDerivationPath.value,
|
||||
});
|
||||
// }//todo: probably not needed (broken anyways)
|
||||
// else if (widget.coin is Epiccash) {
|
||||
// final int secondsSinceEpoch =
|
||||
// DateTime.now().millisecondsSinceEpoch ~/ 1000;
|
||||
// const int epicCashFirstBlock = 1565370278;
|
||||
// const double overestimateSecondsPerBlock = 61;
|
||||
// int chosenSeconds = secondsSinceEpoch - epicCashFirstBlock;
|
||||
// int approximateHeight = chosenSeconds ~/ overestimateSecondsPerBlock;
|
||||
// /
|
||||
// // debugPrint(
|
||||
// // "approximate height: $approximateHeight chosen_seconds: $chosenSeconds");
|
||||
// height = approximateHeight;
|
||||
// if (height < 0) {
|
||||
// height = 0;
|
||||
// }
|
||||
//
|
||||
// otherDataJsonString = jsonEncode(
|
||||
// {
|
||||
// WalletInfoKeys.epiccashData: jsonEncode(
|
||||
// ExtraEpiccashWalletInfo(
|
||||
// receivingIndex: 0,
|
||||
// changeIndex: 0,
|
||||
// slatesToAddresses: {},
|
||||
// slatesToCommits: {},
|
||||
// lastScannedBlock: epicCashFirstBlock,
|
||||
// restoreHeight: height,
|
||||
// creationHeight: height,
|
||||
// ).toMap(),
|
||||
// ),
|
||||
// },
|
||||
// );
|
||||
} else if (widget.coin is Firo) {
|
||||
otherDataJsonString = jsonEncode(
|
||||
{
|
||||
WalletInfoKeys.lelantusCoinIsarRescanRequired: false,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
final info = WalletInfo.createNew(
|
||||
coin: widget.coin,
|
||||
name: widget.walletName,
|
||||
otherDataJsonString: otherDataJsonString,
|
||||
);
|
||||
|
||||
var node = ref
|
||||
.read(
|
||||
nodeServiceChangeNotifierProvider,
|
||||
)
|
||||
.getPrimaryNodeFor(
|
||||
currency: coin,
|
||||
);
|
||||
|
||||
if (node == null) {
|
||||
node = coin.defaultNode;
|
||||
await ref
|
||||
.read(
|
||||
nodeServiceChangeNotifierProvider,
|
||||
)
|
||||
.setPrimaryNodeFor(
|
||||
coin: coin,
|
||||
node: node,
|
||||
);
|
||||
}
|
||||
|
||||
final txTracker = TransactionNotificationTracker(
|
||||
walletId: info.walletId,
|
||||
);
|
||||
|
||||
String? mnemonicPassphrase;
|
||||
String? mnemonic;
|
||||
String? privateKey;
|
||||
|
||||
// set some sane default
|
||||
int wordCount = info.coin.defaultSeedPhraseLength;
|
||||
|
||||
// TODO: Refactor these to generate each coin in their respective classes
|
||||
// This code should not be in a random view page file
|
||||
if (coin is Monero || coin is Wownero) {
|
||||
// currently a special case due to the
|
||||
// xmr/wow libraries handling their
|
||||
// own mnemonic generation
|
||||
wordCount = ref.read(pNewWalletOptions)?.mnemonicWordsCount ??
|
||||
info.coin.defaultSeedPhraseLength;
|
||||
} else if (wordCount > 0) {
|
||||
if (ref
|
||||
.read(
|
||||
pNewWalletOptions.state,
|
||||
)
|
||||
.state !=
|
||||
null) {
|
||||
if (coin.hasMnemonicPassphraseSupport) {
|
||||
mnemonicPassphrase = ref
|
||||
.read(
|
||||
pNewWalletOptions.state,
|
||||
)
|
||||
.state!
|
||||
.mnemonicPassphrase;
|
||||
} else {
|
||||
// this may not be epiccash specific?
|
||||
if (coin is Epiccash) {
|
||||
mnemonicPassphrase = "";
|
||||
}
|
||||
}
|
||||
|
||||
wordCount = ref
|
||||
.read(
|
||||
pNewWalletOptions.state,
|
||||
)
|
||||
.state!
|
||||
.mnemonicWordsCount;
|
||||
} else {
|
||||
mnemonicPassphrase = "";
|
||||
}
|
||||
|
||||
if (wordCount < 12 || 24 < wordCount || wordCount % 3 != 0) {
|
||||
throw Exception(
|
||||
"Invalid word count",
|
||||
);
|
||||
}
|
||||
|
||||
final strength = (wordCount ~/ 3) * 32;
|
||||
|
||||
mnemonic = bip39.generateMnemonic(
|
||||
strength: strength,
|
||||
);
|
||||
}
|
||||
|
||||
final wallet = await Wallet.create(
|
||||
walletInfo: info,
|
||||
mainDB: ref.read(mainDBProvider),
|
||||
secureStorageInterface: ref.read(secureStoreProvider),
|
||||
nodeService: ref.read(
|
||||
nodeServiceChangeNotifierProvider,
|
||||
),
|
||||
prefs: ref.read(
|
||||
prefsChangeNotifierProvider,
|
||||
),
|
||||
mnemonicPassphrase: mnemonicPassphrase,
|
||||
mnemonic: mnemonic,
|
||||
privateKey: privateKey,
|
||||
);
|
||||
|
||||
if (wallet is LibMoneroWallet) {
|
||||
await wallet.init(wordCount: wordCount);
|
||||
} else {
|
||||
await wallet.init();
|
||||
}
|
||||
|
||||
// set checkbox back to unchecked to annoy users to agree again :P
|
||||
ref
|
||||
.read(
|
||||
checkBoxStateProvider.state,
|
||||
)
|
||||
.state = false;
|
||||
|
||||
final fetchedMnemonic =
|
||||
await (wallet as MnemonicInterface).getMnemonicAsWords();
|
||||
|
||||
return (wallet, fetchedMnemonic);
|
||||
} catch (e, s) {
|
||||
Logging.instance.log(
|
||||
"$e\n$s",
|
||||
level: LogLevel.Fatal,
|
||||
);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
coin = widget.coin;
|
||||
|
@ -454,222 +671,7 @@ class _NewWalletRecoveryPhraseWarningViewState
|
|||
onPressed: ref
|
||||
.read(checkBoxStateProvider.state)
|
||||
.state
|
||||
? () async {
|
||||
try {
|
||||
unawaited(
|
||||
showDialog<dynamic>(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
useSafeArea: true,
|
||||
builder: (ctx) {
|
||||
return const Center(
|
||||
child: LoadingIndicator(
|
||||
width: 50,
|
||||
height: 50,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
String? otherDataJsonString;
|
||||
if (widget.coin is Tezos) {
|
||||
otherDataJsonString = jsonEncode({
|
||||
WalletInfoKeys
|
||||
.tezosDerivationPath:
|
||||
Tezos.standardDerivationPath
|
||||
.value,
|
||||
});
|
||||
// }//todo: probably not needed (broken anyways)
|
||||
// else if (widget.coin is Epiccash) {
|
||||
// final int secondsSinceEpoch =
|
||||
// DateTime.now().millisecondsSinceEpoch ~/ 1000;
|
||||
// const int epicCashFirstBlock = 1565370278;
|
||||
// const double overestimateSecondsPerBlock = 61;
|
||||
// int chosenSeconds = secondsSinceEpoch - epicCashFirstBlock;
|
||||
// int approximateHeight = chosenSeconds ~/ overestimateSecondsPerBlock;
|
||||
// /
|
||||
// // debugPrint(
|
||||
// // "approximate height: $approximateHeight chosen_seconds: $chosenSeconds");
|
||||
// height = approximateHeight;
|
||||
// if (height < 0) {
|
||||
// height = 0;
|
||||
// }
|
||||
//
|
||||
// otherDataJsonString = jsonEncode(
|
||||
// {
|
||||
// WalletInfoKeys.epiccashData: jsonEncode(
|
||||
// ExtraEpiccashWalletInfo(
|
||||
// receivingIndex: 0,
|
||||
// changeIndex: 0,
|
||||
// slatesToAddresses: {},
|
||||
// slatesToCommits: {},
|
||||
// lastScannedBlock: epicCashFirstBlock,
|
||||
// restoreHeight: height,
|
||||
// creationHeight: height,
|
||||
// ).toMap(),
|
||||
// ),
|
||||
// },
|
||||
// );
|
||||
} else if (widget.coin is Firo) {
|
||||
otherDataJsonString = jsonEncode(
|
||||
{
|
||||
WalletInfoKeys
|
||||
.lelantusCoinIsarRescanRequired:
|
||||
false,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
final info = WalletInfo.createNew(
|
||||
coin: widget.coin,
|
||||
name: widget.walletName,
|
||||
otherDataJsonString:
|
||||
otherDataJsonString,
|
||||
);
|
||||
|
||||
var node = ref
|
||||
.read(
|
||||
nodeServiceChangeNotifierProvider,
|
||||
)
|
||||
.getPrimaryNodeFor(
|
||||
currency: coin,
|
||||
);
|
||||
|
||||
if (node == null) {
|
||||
node = coin.defaultNode;
|
||||
await ref
|
||||
.read(
|
||||
nodeServiceChangeNotifierProvider,
|
||||
)
|
||||
.setPrimaryNodeFor(
|
||||
coin: coin,
|
||||
node: node,
|
||||
);
|
||||
}
|
||||
|
||||
final txTracker =
|
||||
TransactionNotificationTracker(
|
||||
walletId: info.walletId,
|
||||
);
|
||||
|
||||
int? wordCount;
|
||||
String? mnemonicPassphrase;
|
||||
String? mnemonic;
|
||||
String? privateKey;
|
||||
|
||||
wordCount = info
|
||||
.coin.defaultSeedPhraseLength;
|
||||
|
||||
// TODO: Refactor these to generate each coin in their respective classes
|
||||
// This code should not be in a random view page file
|
||||
if (coin is Monero ||
|
||||
coin is Wownero) {
|
||||
// currently a special case due to the
|
||||
// xmr/wow libraries handling their
|
||||
// own mnemonic generation
|
||||
} else if (wordCount > 0) {
|
||||
if (ref
|
||||
.read(
|
||||
pNewWalletOptions.state,
|
||||
)
|
||||
.state !=
|
||||
null) {
|
||||
if (coin
|
||||
.hasMnemonicPassphraseSupport) {
|
||||
mnemonicPassphrase = ref
|
||||
.read(
|
||||
pNewWalletOptions.state,
|
||||
)
|
||||
.state!
|
||||
.mnemonicPassphrase;
|
||||
} else {
|
||||
// this may not be epiccash specific?
|
||||
if (coin is Epiccash) {
|
||||
mnemonicPassphrase = "";
|
||||
}
|
||||
}
|
||||
|
||||
wordCount = ref
|
||||
.read(
|
||||
pNewWalletOptions.state,
|
||||
)
|
||||
.state!
|
||||
.mnemonicWordsCount;
|
||||
} else {
|
||||
mnemonicPassphrase = "";
|
||||
}
|
||||
|
||||
if (wordCount < 12 ||
|
||||
24 < wordCount ||
|
||||
wordCount % 3 != 0) {
|
||||
throw Exception(
|
||||
"Invalid word count",
|
||||
);
|
||||
}
|
||||
|
||||
final strength =
|
||||
(wordCount ~/ 3) * 32;
|
||||
|
||||
mnemonic = bip39.generateMnemonic(
|
||||
strength: strength,
|
||||
);
|
||||
}
|
||||
|
||||
final wallet = await Wallet.create(
|
||||
walletInfo: info,
|
||||
mainDB: ref.read(mainDBProvider),
|
||||
secureStorageInterface:
|
||||
ref.read(secureStoreProvider),
|
||||
nodeService: ref.read(
|
||||
nodeServiceChangeNotifierProvider,
|
||||
),
|
||||
prefs: ref.read(
|
||||
prefsChangeNotifierProvider,
|
||||
),
|
||||
mnemonicPassphrase:
|
||||
mnemonicPassphrase,
|
||||
mnemonic: mnemonic,
|
||||
privateKey: privateKey,
|
||||
);
|
||||
|
||||
await wallet.init();
|
||||
|
||||
// pop progress dialog
|
||||
if (context.mounted) {
|
||||
Navigator.pop(context);
|
||||
}
|
||||
// set checkbox back to unchecked to annoy users to agree again :P
|
||||
ref
|
||||
.read(
|
||||
checkBoxStateProvider.state,
|
||||
)
|
||||
.state = false;
|
||||
|
||||
if (context.mounted) {
|
||||
final nav = Navigator.of(context);
|
||||
unawaited(
|
||||
nav.pushNamed(
|
||||
NewWalletRecoveryPhraseView
|
||||
.routeName,
|
||||
arguments: Tuple2(
|
||||
wallet,
|
||||
await (wallet
|
||||
as MnemonicInterface)
|
||||
.getMnemonicAsWords(),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
} catch (e, s) {
|
||||
Logging.instance.log(
|
||||
"$e\n$s",
|
||||
level: LogLevel.Fatal,
|
||||
);
|
||||
// TODO: handle gracefully
|
||||
// any network/socket exception here will break new wallet creation
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
? _initNewWallet
|
||||
: null,
|
||||
style: ref
|
||||
.read(checkBoxStateProvider.state)
|
||||
|
|
|
@ -458,7 +458,7 @@ abstract class SWB {
|
|||
mnemonic: mnemonic,
|
||||
mnemonicPassphrase: mnemonicPassphrase,
|
||||
);
|
||||
|
||||
Wallet? wallet;
|
||||
try {
|
||||
String? serializedKeys;
|
||||
String? multisigConfig;
|
||||
|
@ -491,7 +491,7 @@ abstract class SWB {
|
|||
});
|
||||
}
|
||||
|
||||
final wallet = await Wallet.create(
|
||||
wallet = await Wallet.create(
|
||||
walletInfo: info,
|
||||
mainDB: MainDB.instance,
|
||||
secureStorageInterface: secureStorageInterface,
|
||||
|
@ -614,6 +614,8 @@ abstract class SWB {
|
|||
mnemonicPassphrase: mnemonicPassphrase,
|
||||
);
|
||||
return false;
|
||||
} finally {
|
||||
await wallet?.exit();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -316,9 +316,10 @@ class _WalletSettingsViewState extends ConsumerState<WalletSettingsView> {
|
|||
if (wallet is MnemonicInterface) {
|
||||
if (wallet
|
||||
is ViewOnlyOptionInterface &&
|
||||
!(wallet
|
||||
as ViewOnlyOptionInterface)
|
||||
(wallet as ViewOnlyOptionInterface)
|
||||
.isViewOnly) {
|
||||
// TODO: is something needed here?
|
||||
} else {
|
||||
mnemonic = await wallet
|
||||
.getMnemonicAsWords();
|
||||
}
|
||||
|
|
|
@ -85,12 +85,26 @@ class BitcoinFrostWallet<T extends FrostCurrency> extends Wallet<T>
|
|||
await mainDB.isar.frostWalletInfo.put(frostWalletInfo);
|
||||
});
|
||||
|
||||
final address = await _generateAddress(
|
||||
Address? address;
|
||||
int index = kFrostSecureStartingIndex;
|
||||
while (address == null) {
|
||||
try {
|
||||
address = await _generateAddress(
|
||||
change: 0,
|
||||
index: kFrostSecureStartingIndex,
|
||||
index: index,
|
||||
serializedKeys: serializedKeys,
|
||||
secure: true,
|
||||
);
|
||||
} on FrostdartException catch (e) {
|
||||
if (e.errorCode == 72) {
|
||||
// rust doesn't like the addressDerivationData
|
||||
index++;
|
||||
continue;
|
||||
} else {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await mainDB.putAddresses([address]);
|
||||
} catch (e, s) {
|
||||
|
|
|
@ -701,7 +701,7 @@ class EpiccashWallet extends Bip39Wallet {
|
|||
isar: mainDB.isar,
|
||||
);
|
||||
|
||||
unawaited(_startScans());
|
||||
unawaited(refresh(doScan: true));
|
||||
} else {
|
||||
await updateNode();
|
||||
final String password = generatePassword();
|
||||
|
@ -759,9 +759,8 @@ class EpiccashWallet extends Bip39Wallet {
|
|||
epicData.receivingIndex,
|
||||
);
|
||||
}
|
||||
unawaited(refresh(doScan: false));
|
||||
});
|
||||
|
||||
unawaited(refresh());
|
||||
} catch (e, s) {
|
||||
Logging.instance.log(
|
||||
"Exception rethrown from electrumx_mixin recover(): $e\n$s",
|
||||
|
@ -773,7 +772,7 @@ class EpiccashWallet extends Bip39Wallet {
|
|||
}
|
||||
|
||||
@override
|
||||
Future<void> refresh() async {
|
||||
Future<void> refresh({bool doScan = true}) async {
|
||||
// Awaiting this lock could be dangerous.
|
||||
// Since refresh is periodic (generally)
|
||||
if (refreshMutex.isLocked) {
|
||||
|
@ -803,9 +802,11 @@ class EpiccashWallet extends Bip39Wallet {
|
|||
final int curAdd = await _getCurrentIndex();
|
||||
await _generateAndStoreReceivingAddressForIndex(curAdd);
|
||||
|
||||
if (doScan) {
|
||||
await _startScans();
|
||||
|
||||
unawaited(_startSync());
|
||||
}
|
||||
|
||||
GlobalEventBus.instance.fire(RefreshPercentChangedEvent(0.0, walletId));
|
||||
await updateChainHeight();
|
||||
|
@ -1157,6 +1158,7 @@ class EpiccashWallet extends Bip39Wallet {
|
|||
|
||||
@override
|
||||
Future<void> exit() async {
|
||||
epiccash.LibEpiccash.stopEpicboxListener();
|
||||
timer?.cancel();
|
||||
timer = null;
|
||||
await super.exit();
|
||||
|
|
|
@ -75,13 +75,28 @@ class MoneroWallet extends LibMoneroWallet {
|
|||
Future<lib_monero.Wallet> getCreatedWallet({
|
||||
required String path,
|
||||
required String password,
|
||||
}) async =>
|
||||
await lib_monero.MoneroWallet.create(
|
||||
required int wordCount,
|
||||
}) async {
|
||||
final lib_monero.MoneroSeedType type;
|
||||
switch (wordCount) {
|
||||
case 16:
|
||||
type = lib_monero.MoneroSeedType.sixteen;
|
||||
break;
|
||||
|
||||
case 25:
|
||||
type = lib_monero.MoneroSeedType.twentyFive;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw Exception("Invalid mnemonic word count: $wordCount");
|
||||
}
|
||||
|
||||
return await lib_monero.MoneroWallet.create(
|
||||
path: path,
|
||||
password: password,
|
||||
seedType: lib_monero.MoneroSeedType
|
||||
.sixteen, // TODO: check we want to actually use 16 here
|
||||
seedType: type,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<lib_monero.Wallet> getRestoredWallet({
|
||||
|
|
|
@ -111,14 +111,33 @@ class WowneroWallet extends LibMoneroWallet {
|
|||
Future<lib_monero.Wallet> getCreatedWallet({
|
||||
required String path,
|
||||
required String password,
|
||||
}) async =>
|
||||
await lib_monero.WowneroWallet.create(
|
||||
required int wordCount,
|
||||
}) async {
|
||||
final lib_monero.WowneroSeedType type;
|
||||
switch (wordCount) {
|
||||
case 14:
|
||||
type = lib_monero.WowneroSeedType.fourteen;
|
||||
break;
|
||||
|
||||
case 16:
|
||||
type = lib_monero.WowneroSeedType.sixteen;
|
||||
break;
|
||||
|
||||
case 25:
|
||||
type = lib_monero.WowneroSeedType.twentyFive;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw Exception("Invalid mnemonic word count: $wordCount");
|
||||
}
|
||||
|
||||
return await lib_monero.WowneroWallet.create(
|
||||
path: path,
|
||||
password: password,
|
||||
seedType: lib_monero.WowneroSeedType
|
||||
.fourteen, // TODO: check we want to actually use 14 here
|
||||
seedType: type,
|
||||
overrideDeprecated14WordSeedException: true,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<lib_monero.Wallet> getRestoredWallet({
|
||||
|
|
|
@ -142,6 +142,7 @@ abstract class LibMoneroWallet<T extends CryptonoteCurrency>
|
|||
Future<lib_monero.Wallet> getCreatedWallet({
|
||||
required String path,
|
||||
required String password,
|
||||
required int wordCount,
|
||||
});
|
||||
|
||||
Future<lib_monero.Wallet> getRestoredWallet({
|
||||
|
@ -313,19 +314,26 @@ abstract class LibMoneroWallet<T extends CryptonoteCurrency>
|
|||
}
|
||||
|
||||
@override
|
||||
Future<void> init({bool? isRestore}) async {
|
||||
Future<void> init({bool? isRestore, int? wordCount}) async {
|
||||
final path = await pathForWallet(
|
||||
name: walletId,
|
||||
type: compatType,
|
||||
);
|
||||
if (!(walletExists(path)) && isRestore != true) {
|
||||
if (wordCount == null) {
|
||||
throw Exception("Missing word count for new xmr/wow wallet!");
|
||||
}
|
||||
try {
|
||||
final password = generatePassword();
|
||||
await secureStorageInterface.write(
|
||||
key: lib_monero_compat.libMoneroWalletPasswordKey(walletId),
|
||||
value: password,
|
||||
);
|
||||
final wallet = await getCreatedWallet(path: path, password: password);
|
||||
final wallet = await getCreatedWallet(
|
||||
path: path,
|
||||
password: password,
|
||||
wordCount: wordCount,
|
||||
);
|
||||
|
||||
final height = wallet.getRefreshFromBlockHeight();
|
||||
|
||||
|
|
|
@ -23,8 +23,7 @@
|
|||
android:requestLegacyExternalStorage="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:allowBackup="false"
|
||||
android:fullBackupContent="false"
|
||||
android:extractNativeLibs="true">
|
||||
android:fullBackupContent="false">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:screenOrientation="portrait"
|
||||
|
|
Loading…
Reference in a new issue