mirror of
https://github.com/Such-Software/hash-wallet.git
synced 2026-11-12 08:53:57 +01:00
Upstream reformatted its whole tree in 16ddc0837. Matching it removes
formatting from the conflict surface of this and every later sync.
215 lines
7.5 KiB
Dart
215 lines
7.5 KiB
Dart
import 'dart:io';
|
|
import 'package:bitcoin_base/bitcoin_base.dart';
|
|
import 'package:cw_bitcoin/bitcoin_mnemonics_bip39.dart';
|
|
import 'package:cw_bitcoin/mnemonic_is_incorrect_exception.dart';
|
|
import 'package:cw_core/encryption_file_utils.dart';
|
|
import 'package:cw_core/unspent_coins_info.dart';
|
|
import 'package:hive/hive.dart';
|
|
import 'package:cw_bitcoin/bitcoin_mnemonic.dart';
|
|
import 'package:cw_bitcoin/bitcoin_wallet_creation_credentials.dart';
|
|
import 'package:cw_bitcoin/litecoin_wallet.dart';
|
|
import 'package:cw_core/wallet_service.dart';
|
|
import 'package:cw_core/pathForWallet.dart';
|
|
import 'package:cw_core/wallet_type.dart';
|
|
import 'package:cw_core/wallet_info.dart';
|
|
import 'package:bip39/bip39.dart' as bip39;
|
|
import 'package:path_provider/path_provider.dart';
|
|
|
|
class LitecoinWalletService extends WalletService<
|
|
BitcoinNewWalletCredentials,
|
|
BitcoinRestoreWalletFromSeedCredentials,
|
|
LitecoinWalletFromKeysCredentials,
|
|
BitcoinRestoreWalletFromHardware> {
|
|
LitecoinWalletService(this.unspentCoinsInfoSource, this.isDirect);
|
|
|
|
final Box<UnspentCoinsInfo> unspentCoinsInfoSource;
|
|
final bool isDirect;
|
|
|
|
@override
|
|
WalletType getType() => WalletType.litecoin;
|
|
|
|
@override
|
|
Future<LitecoinWallet> create(BitcoinNewWalletCredentials credentials, {bool? isTestnet}) async {
|
|
final String mnemonic;
|
|
switch (credentials.derivationInfo?.derivationType) {
|
|
case DerivationType.bip39:
|
|
final strength = credentials.seedPhraseLength == 24 ? 256 : 128;
|
|
|
|
mnemonic = credentials.mnemonic ?? await MnemonicBip39.generate(strength: strength);
|
|
break;
|
|
case DerivationType.electrum:
|
|
default:
|
|
mnemonic = await generateElectrumMnemonic();
|
|
break;
|
|
}
|
|
|
|
final wallet = await LitecoinWalletBase.create(
|
|
mnemonic: mnemonic,
|
|
password: credentials.password!,
|
|
passphrase: credentials.passphrase,
|
|
walletInfo: credentials.walletInfo!,
|
|
derivationInfo:
|
|
credentials.derivationInfo ?? (await credentials.walletInfo!.getDerivationInfo()),
|
|
unspentCoinsInfo: unspentCoinsInfoSource,
|
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
|
);
|
|
await wallet.save();
|
|
await wallet.init();
|
|
|
|
return wallet;
|
|
}
|
|
|
|
@override
|
|
Future<bool> isWalletExit(String name) async =>
|
|
File(await pathForWallet(name: name, type: getType())).existsSync();
|
|
|
|
@override
|
|
Future<LitecoinWallet> openWallet(String name, String password) async {
|
|
final walletInfo = await WalletInfo.get(name, getType());
|
|
if (walletInfo == null) {
|
|
throw Exception('Wallet not found');
|
|
}
|
|
|
|
try {
|
|
final wallet = await LitecoinWalletBase.open(
|
|
password: password,
|
|
name: name,
|
|
walletInfo: walletInfo,
|
|
unspentCoinsInfo: unspentCoinsInfoSource,
|
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
|
);
|
|
await wallet.init();
|
|
saveBackup(name);
|
|
return wallet;
|
|
} catch (_) {
|
|
await restoreWalletFilesFromBackup(name);
|
|
final wallet = await LitecoinWalletBase.open(
|
|
password: password,
|
|
name: name,
|
|
walletInfo: walletInfo,
|
|
unspentCoinsInfo: unspentCoinsInfoSource,
|
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
|
);
|
|
await wallet.init();
|
|
return wallet;
|
|
}
|
|
}
|
|
|
|
@override
|
|
Future<void> remove(String wallet) async {
|
|
File(await pathForWalletDir(name: wallet, type: getType())).delete(recursive: true);
|
|
final walletInfo = await WalletInfo.get(wallet, getType());
|
|
if (walletInfo == null) {
|
|
throw Exception('Wallet not found');
|
|
}
|
|
await WalletInfo.delete(walletInfo);
|
|
|
|
// if there are no more litecoin wallets left, cleanup the neutrino db and other files created by mwebd:
|
|
if ((await WalletInfo.selectList('type = ?', [WalletType.litecoin.index])).isEmpty) {
|
|
final appDirPath = (await getApplicationSupportDirectory()).path;
|
|
File neturinoDb = File('$appDirPath/neutrino.db');
|
|
File blockHeaders = File('$appDirPath/block_headers.bin');
|
|
File regFilterHeaders = File('$appDirPath/reg_filter_headers.bin');
|
|
File mwebdLogs = File('$appDirPath/logs/debug.log');
|
|
if (neturinoDb.existsSync()) {
|
|
neturinoDb.deleteSync();
|
|
}
|
|
if (blockHeaders.existsSync()) {
|
|
blockHeaders.deleteSync();
|
|
}
|
|
if (regFilterHeaders.existsSync()) {
|
|
regFilterHeaders.deleteSync();
|
|
}
|
|
if (mwebdLogs.existsSync()) {
|
|
mwebdLogs.deleteSync();
|
|
}
|
|
}
|
|
|
|
final unspentCoinsToDelete = unspentCoinsInfoSource.values
|
|
.where((unspentCoin) => unspentCoin.walletId == walletInfo.id)
|
|
.toList();
|
|
|
|
final keysToDelete = unspentCoinsToDelete.map((unspentCoin) => unspentCoin.key).toList();
|
|
|
|
if (keysToDelete.isNotEmpty) {
|
|
await unspentCoinsInfoSource.deleteAll(keysToDelete);
|
|
}
|
|
}
|
|
|
|
@override
|
|
Future<void> rename(String currentName, String password, String newName) async {
|
|
if (currentName == newName) return;
|
|
|
|
await LitecoinWalletBase.copyMwebBox(fromName: currentName, toName: newName);
|
|
await super.rename(currentName, password, newName);
|
|
await LitecoinWalletBase.deleteMwebBox(currentName);
|
|
}
|
|
|
|
@override
|
|
Future<LitecoinWallet> restoreFromHardwareWallet(BitcoinRestoreWalletFromHardware credentials,
|
|
{bool? isTestnet}) async {
|
|
final network = isTestnet == true ? LitecoinNetwork.testnet : LitecoinNetwork.mainnet;
|
|
credentials.walletInfo?.network = network.value;
|
|
final derivationInfo = await credentials.walletInfo!.getDerivationInfo();
|
|
derivationInfo.derivationPath = credentials.hwAccountData.derivationPath;
|
|
await derivationInfo.save();
|
|
credentials.walletInfo!.save();
|
|
|
|
final wallet = await LitecoinWallet(
|
|
password: credentials.password!,
|
|
xpub: credentials.hwAccountData.xpub,
|
|
walletInfo: credentials.walletInfo!,
|
|
derivationInfo: derivationInfo,
|
|
unspentCoinsInfo: unspentCoinsInfoSource,
|
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
|
);
|
|
await wallet.save();
|
|
await wallet.init();
|
|
return wallet;
|
|
}
|
|
|
|
@override
|
|
Future<LitecoinWallet> restoreFromKeys(LitecoinWalletFromKeysCredentials credentials,
|
|
{bool? isTestnet}) async {
|
|
final network = isTestnet == true ? LitecoinNetwork.testnet : LitecoinNetwork.mainnet;
|
|
credentials.walletInfo?.network = network.value;
|
|
|
|
final wallet = await LitecoinWallet(
|
|
password: credentials.password!,
|
|
xpub: credentials.xpub,
|
|
scanSecretOverride: credentials.scanSecret,
|
|
spendPubkeyOverride: credentials.spendPubkey,
|
|
walletInfo: credentials.walletInfo!,
|
|
derivationInfo: await credentials.walletInfo!.getDerivationInfo(),
|
|
unspentCoinsInfo: unspentCoinsInfoSource,
|
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
|
);
|
|
|
|
await wallet.save();
|
|
await wallet.init();
|
|
return wallet;
|
|
}
|
|
|
|
@override
|
|
Future<LitecoinWallet> restoreFromSeed(BitcoinRestoreWalletFromSeedCredentials credentials,
|
|
{bool? isTestnet}) async {
|
|
if (!validateMnemonic(credentials.mnemonic) && !bip39.validateMnemonic(credentials.mnemonic)) {
|
|
throw LitecoinMnemonicIsIncorrectException();
|
|
}
|
|
|
|
final wallet = await LitecoinWalletBase.create(
|
|
password: credentials.password!,
|
|
passphrase: credentials.passphrase,
|
|
mnemonic: credentials.mnemonic,
|
|
walletInfo: credentials.walletInfo!,
|
|
derivationInfo:
|
|
credentials.derivationInfo ?? (await credentials.walletInfo!.getDerivationInfo()),
|
|
unspentCoinsInfo: unspentCoinsInfoSource,
|
|
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
|
|
);
|
|
await wallet.save();
|
|
await wallet.init();
|
|
return wallet;
|
|
}
|
|
}
|