mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-06-28 20:39:51 +00:00
feat: all address derivations
This commit is contained in:
parent
4a4250a905
commit
a3e131d369
18 changed files with 330 additions and 157 deletions
|
@ -1,6 +1,7 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:bitcoin_base/bitcoin_base.dart';
|
||||
import 'package:cw_bitcoin/electrum_wallet_addresses.dart';
|
||||
|
||||
abstract class BaseBitcoinAddressRecord {
|
||||
BaseBitcoinAddressRecord(
|
||||
|
@ -63,11 +64,13 @@ abstract class BaseBitcoinAddressRecord {
|
|||
|
||||
class BitcoinAddressRecord extends BaseBitcoinAddressRecord {
|
||||
final BitcoinDerivationInfo derivationInfo;
|
||||
final CWBitcoinDerivationType derivationType;
|
||||
|
||||
BitcoinAddressRecord(
|
||||
super.address, {
|
||||
required super.index,
|
||||
required this.derivationInfo,
|
||||
required this.derivationType,
|
||||
super.isHidden,
|
||||
super.isChange = false,
|
||||
super.txCount = 0,
|
||||
|
@ -94,6 +97,7 @@ class BitcoinAddressRecord extends BaseBitcoinAddressRecord {
|
|||
derivationInfo: BitcoinDerivationInfo.fromJSON(
|
||||
decoded['derivationInfo'] as Map<String, dynamic>,
|
||||
),
|
||||
derivationType: CWBitcoinDerivationType.values[decoded['derivationType'] as int],
|
||||
isHidden: decoded['isHidden'] as bool? ?? false,
|
||||
isChange: decoded['isChange'] as bool? ?? false,
|
||||
isUsed: decoded['isUsed'] as bool? ?? false,
|
||||
|
@ -115,6 +119,7 @@ class BitcoinAddressRecord extends BaseBitcoinAddressRecord {
|
|||
'address': address,
|
||||
'index': index,
|
||||
'derivationInfo': derivationInfo.toJSON(),
|
||||
'derivationType': derivationType.index,
|
||||
'isHidden': isHidden,
|
||||
'isChange': isChange,
|
||||
'isUsed': isUsed,
|
||||
|
|
|
@ -2,16 +2,14 @@ import 'dart:async';
|
|||
import 'dart:convert';
|
||||
import 'dart:isolate';
|
||||
|
||||
import 'package:bip39/bip39.dart' as bip39;
|
||||
import 'package:bitcoin_base/bitcoin_base.dart';
|
||||
import 'package:blockchain_utils/blockchain_utils.dart';
|
||||
import 'package:cw_bitcoin/bitcoin_address_record.dart';
|
||||
import 'package:cw_bitcoin/bitcoin_mnemonic.dart';
|
||||
import 'package:cw_bitcoin/psbt_transaction_builder.dart';
|
||||
import 'package:cw_bitcoin/bitcoin_transaction_priority.dart';
|
||||
import 'package:cw_bitcoin/bitcoin_unspent.dart';
|
||||
import 'package:cw_bitcoin/electrum_transaction_info.dart';
|
||||
// import 'package:cw_bitcoin/electrum_wallet_addresses.dart';
|
||||
import 'package:cw_bitcoin/electrum_wallet_addresses.dart';
|
||||
import 'package:cw_core/encryption_file_utils.dart';
|
||||
import 'package:cw_bitcoin/electrum_derivations.dart';
|
||||
import 'package:cw_bitcoin/bitcoin_wallet_addresses.dart';
|
||||
|
@ -60,6 +58,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
|
|||
int initialSilentAddressIndex = 0,
|
||||
bool? alwaysScan,
|
||||
required bool mempoolAPIEnabled,
|
||||
super.hdWallets,
|
||||
}) : super(
|
||||
mnemonic: mnemonic,
|
||||
passphrase: passphrase,
|
||||
|
@ -88,9 +87,9 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
|
|||
initialChangeAddressIndex: initialChangeAddressIndex,
|
||||
initialSilentAddresses: initialSilentAddresses,
|
||||
initialSilentAddressIndex: initialSilentAddressIndex,
|
||||
bip32: bip32,
|
||||
network: networkParam ?? network,
|
||||
isHardwareWallet: walletInfo.isHardwareWallet,
|
||||
hdWallets: hdWallets,
|
||||
);
|
||||
|
||||
autorun((_) {
|
||||
|
@ -116,15 +115,49 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
|
|||
required bool mempoolAPIEnabled,
|
||||
}) async {
|
||||
late List<int> seedBytes;
|
||||
final Map<CWBitcoinDerivationType, Bip32Slip10Secp256k1> hdWallets = {};
|
||||
|
||||
switch (walletInfo.derivationInfo?.derivationType) {
|
||||
case DerivationType.bip39:
|
||||
for (final derivation in walletInfo.derivations ?? <DerivationInfo>[]) {
|
||||
if (derivation.derivationType == DerivationType.bip39) {
|
||||
seedBytes = Bip39SeedGenerator.generateFromString(mnemonic, passphrase);
|
||||
hdWallets[CWBitcoinDerivationType.bip39] = Bip32Slip10Secp256k1.fromSeed(seedBytes);
|
||||
hdWallets[CWBitcoinDerivationType.old] = hdWallets[CWBitcoinDerivationType.bip39]!;
|
||||
|
||||
try {
|
||||
hdWallets[CWBitcoinDerivationType.old] = Bip32Slip10Secp256k1.fromSeed(
|
||||
seedBytes,
|
||||
ElectrumWalletBase.getKeyNetVersion(network ?? BitcoinNetwork.mainnet),
|
||||
).derivePath(
|
||||
_hardenedDerivationPath(derivation.derivationPath ?? electrum_path),
|
||||
) as Bip32Slip10Secp256k1;
|
||||
} catch (e) {
|
||||
print("bip39 seed error: $e");
|
||||
}
|
||||
break;
|
||||
case DerivationType.electrum:
|
||||
default:
|
||||
seedBytes = ElectrumV2SeedGenerator.generateFromString(mnemonic, passphrase);
|
||||
} else {
|
||||
try {
|
||||
seedBytes = ElectrumV2SeedGenerator.generateFromString(mnemonic, passphrase);
|
||||
hdWallets[CWBitcoinDerivationType.electrum] = Bip32Slip10Secp256k1.fromSeed(seedBytes);
|
||||
} catch (e) {
|
||||
print("electrum_v2 seed error: $e");
|
||||
|
||||
try {
|
||||
seedBytes = ElectrumV1SeedGenerator(mnemonic).generate();
|
||||
hdWallets[CWBitcoinDerivationType.electrum] = Bip32Slip10Secp256k1.fromSeed(seedBytes);
|
||||
} catch (e) {
|
||||
print("electrum_v1 seed error: $e");
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
hdWallets[CWBitcoinDerivationType.old] = Bip32Slip10Secp256k1.fromSeed(
|
||||
seedBytes,
|
||||
).derivePath(
|
||||
_hardenedDerivationPath(derivation.derivationPath ?? electrum_path),
|
||||
) as Bip32Slip10Secp256k1;
|
||||
} catch (_) {}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return BitcoinWallet(
|
||||
|
@ -144,6 +177,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
|
|||
addressPageType: addressPageType,
|
||||
networkParam: network,
|
||||
mempoolAPIEnabled: mempoolAPIEnabled,
|
||||
hdWallets: hdWallets,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -200,21 +234,52 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
|
|||
walletInfo.derivationInfo!.derivationType ??= snp?.derivationType ?? DerivationType.electrum;
|
||||
|
||||
List<int>? seedBytes = null;
|
||||
final Map<CWBitcoinDerivationType, Bip32Slip10Secp256k1> hdWallets = {};
|
||||
final mnemonic = keysData.mnemonic;
|
||||
final passphrase = keysData.passphrase;
|
||||
|
||||
if (mnemonic != null) {
|
||||
switch (walletInfo.derivationInfo!.derivationType) {
|
||||
case DerivationType.electrum:
|
||||
seedBytes = await mnemonicToSeedBytes(mnemonic, passphrase: passphrase ?? "");
|
||||
for (final derivation in walletInfo.derivations ?? <DerivationInfo>[]) {
|
||||
if (derivation.derivationType == DerivationType.bip39) {
|
||||
seedBytes = Bip39SeedGenerator.generateFromString(mnemonic, passphrase);
|
||||
hdWallets[CWBitcoinDerivationType.bip39] = Bip32Slip10Secp256k1.fromSeed(seedBytes);
|
||||
hdWallets[CWBitcoinDerivationType.old] = hdWallets[CWBitcoinDerivationType.bip39]!;
|
||||
|
||||
try {
|
||||
hdWallets[CWBitcoinDerivationType.old] = Bip32Slip10Secp256k1.fromSeed(
|
||||
seedBytes,
|
||||
ElectrumWalletBase.getKeyNetVersion(network),
|
||||
).derivePath(
|
||||
_hardenedDerivationPath(derivation.derivationPath ?? electrum_path),
|
||||
) as Bip32Slip10Secp256k1;
|
||||
} catch (e) {
|
||||
print("bip39 seed error: $e");
|
||||
}
|
||||
break;
|
||||
case DerivationType.bip39:
|
||||
default:
|
||||
seedBytes = await bip39.mnemonicToSeed(
|
||||
mnemonic,
|
||||
passphrase: passphrase ?? '',
|
||||
);
|
||||
} else {
|
||||
try {
|
||||
seedBytes = ElectrumV2SeedGenerator.generateFromString(mnemonic, passphrase);
|
||||
hdWallets[CWBitcoinDerivationType.electrum] = Bip32Slip10Secp256k1.fromSeed(seedBytes);
|
||||
} catch (e) {
|
||||
print("electrum_v2 seed error: $e");
|
||||
|
||||
try {
|
||||
seedBytes = ElectrumV1SeedGenerator(mnemonic).generate();
|
||||
hdWallets[CWBitcoinDerivationType.electrum] =
|
||||
Bip32Slip10Secp256k1.fromSeed(seedBytes);
|
||||
} catch (e) {
|
||||
print("electrum_v1 seed error: $e");
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
hdWallets[CWBitcoinDerivationType.old] =
|
||||
Bip32Slip10Secp256k1.fromSeed(seedBytes!).derivePath(
|
||||
_hardenedDerivationPath(derivation.derivationPath ?? electrum_path),
|
||||
) as Bip32Slip10Secp256k1;
|
||||
} catch (_) {}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -237,6 +302,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
|
|||
networkParam: network,
|
||||
alwaysScan: alwaysScan,
|
||||
mempoolAPIEnabled: mempoolAPIEnabled,
|
||||
hdWallets: hdWallets,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -784,6 +850,9 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
|
|||
super.syncStatusReaction(syncStatus);
|
||||
}
|
||||
}
|
||||
|
||||
static String _hardenedDerivationPath(String derivationPath) =>
|
||||
derivationPath.substring(0, derivationPath.lastIndexOf("'") + 1);
|
||||
}
|
||||
|
||||
Future<void> startRefresh(ScanData scanData) async {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import 'package:bitcoin_base/bitcoin_base.dart';
|
||||
import 'package:blockchain_utils/blockchain_utils.dart';
|
||||
import 'package:cw_bitcoin/electrum_wallet_addresses.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
|
@ -10,9 +11,9 @@ class BitcoinWalletAddresses = BitcoinWalletAddressesBase with _$BitcoinWalletAd
|
|||
abstract class BitcoinWalletAddressesBase extends ElectrumWalletAddresses with Store {
|
||||
BitcoinWalletAddressesBase(
|
||||
WalletInfo walletInfo, {
|
||||
required super.bip32,
|
||||
required super.network,
|
||||
required super.isHardwareWallet,
|
||||
required super.hdWallets,
|
||||
super.initialAddresses,
|
||||
super.initialRegularAddressIndex,
|
||||
super.initialChangeAddressIndex,
|
||||
|
@ -36,36 +37,61 @@ abstract class BitcoinWalletAddressesBase extends ElectrumWalletAddresses with S
|
|||
|
||||
@override
|
||||
BitcoinBaseAddress generateAddress({
|
||||
required CWBitcoinDerivationType derivationType,
|
||||
required bool isChange,
|
||||
required int index,
|
||||
required BitcoinAddressType addressType,
|
||||
required BitcoinDerivationInfo derivationInfo,
|
||||
}) {
|
||||
final hdWallet = hdWallets[derivationType]!;
|
||||
|
||||
if (derivationType == CWBitcoinDerivationType.old) {
|
||||
final pub = hdWallet
|
||||
.childKey(Bip32KeyIndex(isChange ? 1 : 0))
|
||||
.childKey(Bip32KeyIndex(index))
|
||||
.publicKey;
|
||||
|
||||
switch (addressType) {
|
||||
case P2pkhAddressType.p2pkh:
|
||||
return ECPublic.fromBip32(pub).toP2pkhAddress();
|
||||
case SegwitAddresType.p2tr:
|
||||
return ECPublic.fromBip32(pub).toP2trAddress();
|
||||
case SegwitAddresType.p2wsh:
|
||||
return ECPublic.fromBip32(pub).toP2wshAddress();
|
||||
case P2shAddressType.p2wpkhInP2sh:
|
||||
return ECPublic.fromBip32(pub).toP2wpkhInP2sh();
|
||||
case SegwitAddresType.p2wpkh:
|
||||
return ECPublic.fromBip32(pub).toP2wpkhAddress();
|
||||
default:
|
||||
throw ArgumentError('Invalid address type');
|
||||
}
|
||||
}
|
||||
|
||||
switch (addressType) {
|
||||
case P2pkhAddressType.p2pkh:
|
||||
return P2pkhAddress.fromDerivation(
|
||||
bip32: bip32,
|
||||
bip32: hdWallet,
|
||||
derivationInfo: derivationInfo,
|
||||
isChange: isChange,
|
||||
index: index,
|
||||
);
|
||||
case SegwitAddresType.p2tr:
|
||||
return P2trAddress.fromDerivation(
|
||||
bip32: bip32,
|
||||
bip32: hdWallet,
|
||||
derivationInfo: derivationInfo,
|
||||
isChange: isChange,
|
||||
index: index,
|
||||
);
|
||||
case SegwitAddresType.p2wsh:
|
||||
return P2wshAddress.fromDerivation(
|
||||
bip32: bip32,
|
||||
bip32: hdWallet,
|
||||
derivationInfo: derivationInfo,
|
||||
isChange: isChange,
|
||||
index: index,
|
||||
);
|
||||
case P2shAddressType.p2wpkhInP2sh:
|
||||
return P2shAddress.fromDerivation(
|
||||
bip32: bip32,
|
||||
bip32: hdWallet,
|
||||
derivationInfo: derivationInfo,
|
||||
isChange: isChange,
|
||||
index: index,
|
||||
|
@ -73,7 +99,7 @@ abstract class BitcoinWalletAddressesBase extends ElectrumWalletAddresses with S
|
|||
);
|
||||
case SegwitAddresType.p2wpkh:
|
||||
return P2wpkhAddress.fromDerivation(
|
||||
bip32: bip32,
|
||||
bip32: hdWallet,
|
||||
derivationInfo: derivationInfo,
|
||||
isChange: isChange,
|
||||
index: index,
|
||||
|
|
|
@ -26,6 +26,7 @@ class BitcoinRestoreWalletFromSeedCredentials extends WalletCredentials {
|
|||
required String name,
|
||||
required String password,
|
||||
required this.mnemonic,
|
||||
required super.derivations,
|
||||
WalletInfo? walletInfo,
|
||||
String? passphrase,
|
||||
}) : super(
|
||||
|
|
|
@ -61,6 +61,7 @@ abstract class ElectrumWalletBase
|
|||
required Box<UnspentCoinsInfo> unspentCoinsInfo,
|
||||
required this.network,
|
||||
required this.encryptionFileUtils,
|
||||
Map<CWBitcoinDerivationType, Bip32Slip10Secp256k1>? hdWallets,
|
||||
String? xpub,
|
||||
String? mnemonic,
|
||||
List<int>? seedBytes,
|
||||
|
@ -71,7 +72,16 @@ abstract class ElectrumWalletBase
|
|||
CryptoCurrency? currency,
|
||||
this.alwaysScan,
|
||||
required this.mempoolAPIEnabled,
|
||||
}) : bip32 = getAccountHDWallet(currency, network, seedBytes, xpub, walletInfo.derivationInfo),
|
||||
}) : hdWallets = hdWallets ??
|
||||
{
|
||||
CWBitcoinDerivationType.bip39: getAccountHDWallet(
|
||||
currency,
|
||||
network,
|
||||
seedBytes,
|
||||
xpub,
|
||||
walletInfo.derivationInfo,
|
||||
)
|
||||
},
|
||||
syncStatus = NotConnectedSyncStatus(),
|
||||
_password = password,
|
||||
_isTransactionUpdating = false,
|
||||
|
@ -175,24 +185,12 @@ abstract class ElectrumWalletBase
|
|||
}
|
||||
|
||||
if (seedBytes != null) {
|
||||
switch (currency) {
|
||||
case CryptoCurrency.btc:
|
||||
case CryptoCurrency.ltc:
|
||||
case CryptoCurrency.tbtc:
|
||||
return Bip32Slip10Secp256k1.fromSeed(seedBytes);
|
||||
case CryptoCurrency.bch:
|
||||
return bitcoinCashHDWallet(seedBytes);
|
||||
default:
|
||||
throw Exception("Unsupported currency");
|
||||
}
|
||||
return Bip32Slip10Secp256k1.fromSeed(seedBytes);
|
||||
}
|
||||
|
||||
return Bip32Slip10Secp256k1.fromExtendedKey(xpub!, getKeyNetVersion(network));
|
||||
}
|
||||
|
||||
static Bip32Slip10Secp256k1 bitcoinCashHDWallet(List<int> seedBytes) =>
|
||||
Bip32Slip10Secp256k1.fromSeed(seedBytes).derivePath("m/44'/145'/0'") as Bip32Slip10Secp256k1;
|
||||
|
||||
int estimatedTransactionSize(int inputsCount, int outputsCounts) =>
|
||||
inputsCount * 68 + outputsCounts * 34 + 10;
|
||||
|
||||
|
@ -208,7 +206,8 @@ abstract class ElectrumWalletBase
|
|||
bool? alwaysScan;
|
||||
bool mempoolAPIEnabled;
|
||||
|
||||
final Bip32Slip10Secp256k1 bip32;
|
||||
final Map<CWBitcoinDerivationType, Bip32Slip10Secp256k1> hdWallets;
|
||||
Bip32Slip10Secp256k1 get bip32 => walletAddresses.bip32;
|
||||
final String? _mnemonic;
|
||||
|
||||
final EncryptionFileUtils encryptionFileUtils;
|
||||
|
@ -1681,11 +1680,17 @@ abstract class ElectrumWalletBase
|
|||
|
||||
@action
|
||||
Future<void> onHistoriesResponse(List<AddressHistoriesResponse> histories) async {
|
||||
if (histories.isEmpty) {
|
||||
return;
|
||||
}
|
||||
|
||||
final firstAddress = histories.first;
|
||||
final isChange = firstAddress.addressRecord.isChange;
|
||||
final type = firstAddress.addressRecord.type;
|
||||
|
||||
final totalAddresses = histories.length;
|
||||
final totalAddresses = (isChange
|
||||
? walletAddresses.receiveAddresses.where((element) => element.type == type).length
|
||||
: walletAddresses.changeAddresses.where((element) => element.type == type).length);
|
||||
final gapLimit = (isChange
|
||||
? ElectrumWalletAddressesBase.defaultChangeAddressesCount
|
||||
: ElectrumWalletAddressesBase.defaultReceiveAddressesCount);
|
||||
|
@ -1717,7 +1722,7 @@ abstract class ElectrumWalletBase
|
|||
// Discover new addresses for the same address type until the gap limit is respected
|
||||
final newAddresses = await walletAddresses.discoverAddresses(
|
||||
isChange: isChange,
|
||||
gap: gapLimit,
|
||||
derivationType: firstAddress.addressRecord.derivationType,
|
||||
type: type,
|
||||
derivationInfo: BitcoinAddressUtils.getDerivationFromType(type),
|
||||
);
|
||||
|
|
|
@ -11,6 +11,8 @@ import 'package:mobx/mobx.dart';
|
|||
|
||||
part 'electrum_wallet_addresses.g.dart';
|
||||
|
||||
enum CWBitcoinDerivationType { old, electrum, bip39, mweb }
|
||||
|
||||
class ElectrumWalletAddresses = ElectrumWalletAddressesBase with _$ElectrumWalletAddresses;
|
||||
|
||||
const List<BitcoinAddressType> BITCOIN_ADDRESS_TYPES = [
|
||||
|
@ -33,7 +35,7 @@ const List<BitcoinAddressType> BITCOIN_CASH_ADDRESS_TYPES = [
|
|||
abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
||||
ElectrumWalletAddressesBase(
|
||||
WalletInfo walletInfo, {
|
||||
required this.bip32,
|
||||
required this.hdWallets,
|
||||
required this.network,
|
||||
required this.isHardwareWallet,
|
||||
List<BitcoinAddressRecord>? initialAddresses,
|
||||
|
@ -98,7 +100,11 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
|||
// TODO: add this variable in `litecoin_wallet_addresses` and just add a cast in cw_bitcoin to use it
|
||||
final ObservableList<BitcoinAddressRecord> mwebAddresses;
|
||||
final BasedUtxoNetwork network;
|
||||
final Bip32Slip10Secp256k1 bip32;
|
||||
|
||||
final Map<CWBitcoinDerivationType, Bip32Slip10Secp256k1> hdWallets;
|
||||
Bip32Slip10Secp256k1 get bip32 =>
|
||||
hdWallets[CWBitcoinDerivationType.bip39] ?? hdWallets[CWBitcoinDerivationType.electrum]!;
|
||||
|
||||
final bool isHardwareWallet;
|
||||
|
||||
@observable
|
||||
|
@ -331,6 +337,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
|||
final derivationInfo = BitcoinAddressUtils.getDerivationFromType(addressPageType);
|
||||
final address = BitcoinAddressRecord(
|
||||
getAddress(
|
||||
derivationType: CWBitcoinDerivationType.bip39,
|
||||
isChange: false,
|
||||
index: newAddressIndex,
|
||||
addressType: addressPageType,
|
||||
|
@ -342,6 +349,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
|||
type: addressPageType,
|
||||
network: network,
|
||||
derivationInfo: BitcoinAddressUtils.getDerivationFromType(addressPageType),
|
||||
derivationType: CWBitcoinDerivationType.bip39,
|
||||
);
|
||||
_allAddresses.add(address);
|
||||
Future.delayed(Duration.zero, () => updateAddressesByMatch());
|
||||
|
@ -349,6 +357,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
|||
}
|
||||
|
||||
BitcoinBaseAddress generateAddress({
|
||||
required CWBitcoinDerivationType derivationType,
|
||||
required bool isChange,
|
||||
required int index,
|
||||
required BitcoinAddressType addressType,
|
||||
|
@ -358,12 +367,14 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
|||
}
|
||||
|
||||
String getAddress({
|
||||
required CWBitcoinDerivationType derivationType,
|
||||
required bool isChange,
|
||||
required int index,
|
||||
required BitcoinAddressType addressType,
|
||||
required BitcoinDerivationInfo derivationInfo,
|
||||
}) {
|
||||
return generateAddress(
|
||||
derivationType: derivationType,
|
||||
isChange: isChange,
|
||||
index: index,
|
||||
addressType: addressType,
|
||||
|
@ -372,12 +383,14 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
|||
}
|
||||
|
||||
Future<String> getAddressAsync({
|
||||
required CWBitcoinDerivationType derivationType,
|
||||
required bool isChange,
|
||||
required int index,
|
||||
required BitcoinAddressType addressType,
|
||||
required BitcoinDerivationInfo derivationInfo,
|
||||
}) async =>
|
||||
getAddress(
|
||||
derivationType: derivationType,
|
||||
isChange: isChange,
|
||||
index: index,
|
||||
addressType: addressType,
|
||||
|
@ -569,12 +582,17 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
|||
|
||||
@action
|
||||
Future<List<BitcoinAddressRecord>> discoverAddresses({
|
||||
required CWBitcoinDerivationType derivationType,
|
||||
required bool isChange,
|
||||
required int gap,
|
||||
required BitcoinAddressType type,
|
||||
required BitcoinDerivationInfo derivationInfo,
|
||||
}) async {
|
||||
final gap = (isChange
|
||||
? ElectrumWalletAddressesBase.defaultChangeAddressesCount
|
||||
: ElectrumWalletAddressesBase.defaultReceiveAddressesCount);
|
||||
|
||||
final newAddresses = await _createNewAddresses(
|
||||
derivationType: derivationType,
|
||||
gap,
|
||||
isChange: isChange,
|
||||
type: type,
|
||||
|
@ -586,36 +604,44 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
|||
|
||||
@action
|
||||
Future<void> generateInitialAddresses({required BitcoinAddressType type}) async {
|
||||
// TODO: try all other derivations
|
||||
final derivationInfo = BitcoinAddressUtils.getDerivationFromType(type);
|
||||
for (final derivationType in hdWallets.keys) {
|
||||
final derivationInfo = BitcoinAddressUtils.getDerivationFromType(
|
||||
type,
|
||||
isElectrum: derivationType == CWBitcoinDerivationType.electrum,
|
||||
);
|
||||
|
||||
await discoverAddresses(
|
||||
isChange: false,
|
||||
gap: defaultReceiveAddressesCount,
|
||||
type: type,
|
||||
derivationInfo: derivationInfo,
|
||||
);
|
||||
await discoverAddresses(
|
||||
isChange: true,
|
||||
gap: defaultChangeAddressesCount,
|
||||
type: type,
|
||||
derivationInfo: derivationInfo,
|
||||
);
|
||||
await discoverAddresses(
|
||||
derivationType: derivationType,
|
||||
isChange: false,
|
||||
type: type,
|
||||
derivationInfo: derivationInfo,
|
||||
);
|
||||
await discoverAddresses(
|
||||
derivationType: derivationType,
|
||||
isChange: true,
|
||||
type: type,
|
||||
derivationInfo: derivationInfo,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@action
|
||||
Future<List<BitcoinAddressRecord>> _createNewAddresses(
|
||||
int count, {
|
||||
required CWBitcoinDerivationType derivationType,
|
||||
required BitcoinDerivationInfo derivationInfo,
|
||||
bool isChange = false,
|
||||
BitcoinAddressType? type,
|
||||
}) async {
|
||||
final list = <BitcoinAddressRecord>[];
|
||||
final startIndex = isChange ? totalCountOfChangeAddresses : totalCountOfReceiveAddresses;
|
||||
final startIndex = (isChange ? receiveAddresses : changeAddresses)
|
||||
.where((addr) => addr.derivationType == derivationType && addr.type == type)
|
||||
.length;
|
||||
|
||||
for (var i = startIndex; i < count + startIndex; i++) {
|
||||
final address = BitcoinAddressRecord(
|
||||
await getAddressAsync(
|
||||
derivationType: derivationType,
|
||||
isChange: isChange,
|
||||
index: i,
|
||||
addressType: type ?? addressPageType,
|
||||
|
@ -623,9 +649,11 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
|||
),
|
||||
index: i,
|
||||
isChange: isChange,
|
||||
isHidden: derivationType == CWBitcoinDerivationType.old,
|
||||
type: type ?? addressPageType,
|
||||
network: network,
|
||||
derivationInfo: derivationInfo,
|
||||
derivationType: derivationType,
|
||||
);
|
||||
list.add(address);
|
||||
}
|
||||
|
@ -646,6 +674,10 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
|||
updateAddressesByMatch();
|
||||
updateReceiveAddresses();
|
||||
updateChangeAddresses();
|
||||
|
||||
this.hiddenAddresses.addAll(addresses
|
||||
.where((addressRecord) => addressRecord.isHidden)
|
||||
.map((addressRecord) => addressRecord.address));
|
||||
}
|
||||
|
||||
@action
|
||||
|
|
|
@ -98,11 +98,11 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
|||
initialRegularAddressIndex: initialRegularAddressIndex,
|
||||
initialChangeAddressIndex: initialChangeAddressIndex,
|
||||
initialMwebAddresses: initialMwebAddresses,
|
||||
bip32: bip32,
|
||||
network: network,
|
||||
mwebHd: mwebHd,
|
||||
mwebEnabled: mwebEnabled,
|
||||
isHardwareWallet: walletInfo.isHardwareWallet,
|
||||
hdWallets: hdWallets,
|
||||
);
|
||||
autorun((_) {
|
||||
this.walletAddresses.isEnabledAutoGenerateSubaddress = this.isEnabledAutoGenerateSubaddress;
|
||||
|
@ -169,6 +169,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
|||
required bool mempoolAPIEnabled,
|
||||
}) async {
|
||||
late Uint8List seedBytes;
|
||||
late BitcoinDerivationType derivationType;
|
||||
|
||||
switch (walletInfo.derivationInfo?.derivationType) {
|
||||
case DerivationType.bip39:
|
||||
|
@ -176,10 +177,12 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
|||
mnemonic,
|
||||
passphrase: passphrase ?? "",
|
||||
);
|
||||
derivationType = BitcoinDerivationType.bip39;
|
||||
break;
|
||||
case DerivationType.electrum:
|
||||
default:
|
||||
seedBytes = await mnemonicToSeedBytes(mnemonic, passphrase: passphrase ?? "");
|
||||
derivationType = BitcoinDerivationType.electrum;
|
||||
break;
|
||||
}
|
||||
return LitecoinWallet(
|
||||
|
@ -246,6 +249,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
|||
walletInfo.derivationInfo!.derivationType ??= snp?.derivationType ?? DerivationType.electrum;
|
||||
|
||||
Uint8List? seedBytes = null;
|
||||
late BitcoinDerivationType derivationType;
|
||||
final mnemonic = keysData.mnemonic;
|
||||
final passphrase = keysData.passphrase;
|
||||
|
||||
|
@ -256,10 +260,12 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
|||
mnemonic,
|
||||
passphrase: passphrase ?? "",
|
||||
);
|
||||
derivationType = BitcoinDerivationType.bip39;
|
||||
break;
|
||||
case DerivationType.electrum:
|
||||
default:
|
||||
seedBytes = await mnemonicToSeedBytes(mnemonic, passphrase: passphrase ?? "");
|
||||
derivationType = BitcoinDerivationType.electrum;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,11 +19,11 @@ class LitecoinWalletAddresses = LitecoinWalletAddressesBase with _$LitecoinWalle
|
|||
abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with Store {
|
||||
LitecoinWalletAddressesBase(
|
||||
WalletInfo walletInfo, {
|
||||
required super.bip32,
|
||||
required super.network,
|
||||
required super.isHardwareWallet,
|
||||
required this.mwebHd,
|
||||
required this.mwebEnabled,
|
||||
required super.hdWallets,
|
||||
super.initialAddresses,
|
||||
super.initialMwebAddresses,
|
||||
super.initialRegularAddressIndex,
|
||||
|
@ -98,13 +98,16 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
|
|||
List<BitcoinAddressRecord> addressRecords = mwebAddrs
|
||||
.asMap()
|
||||
.entries
|
||||
.map((e) => BitcoinAddressRecord(
|
||||
e.value,
|
||||
index: e.key,
|
||||
type: SegwitAddresType.mweb,
|
||||
network: network,
|
||||
derivationInfo: BitcoinAddressUtils.getDerivationFromType(SegwitAddresType.p2wpkh),
|
||||
))
|
||||
.map(
|
||||
(e) => BitcoinAddressRecord(
|
||||
e.value,
|
||||
index: e.key,
|
||||
type: SegwitAddresType.mweb,
|
||||
network: network,
|
||||
derivationInfo: BitcoinAddressUtils.getDerivationFromType(SegwitAddresType.p2wpkh),
|
||||
derivationType: CWBitcoinDerivationType.bip39,
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
addMwebAddresses(addressRecords);
|
||||
print("set ${addressRecords.length} mweb addresses");
|
||||
|
@ -119,6 +122,7 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
|
|||
|
||||
@override
|
||||
BitcoinBaseAddress generateAddress({
|
||||
required CWBitcoinDerivationType derivationType,
|
||||
required bool isChange,
|
||||
required int index,
|
||||
required BitcoinAddressType addressType,
|
||||
|
@ -139,6 +143,7 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
|
|||
|
||||
@override
|
||||
Future<String> getAddressAsync({
|
||||
required CWBitcoinDerivationType derivationType,
|
||||
required bool isChange,
|
||||
required int index,
|
||||
required BitcoinAddressType addressType,
|
||||
|
@ -149,6 +154,7 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
|
|||
}
|
||||
|
||||
return getAddress(
|
||||
derivationType: derivationType,
|
||||
isChange: isChange,
|
||||
index: index,
|
||||
addressType: addressType,
|
||||
|
@ -208,6 +214,7 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
|
|||
type: SegwitAddresType.mweb,
|
||||
network: network,
|
||||
derivationInfo: BitcoinAddressUtils.getDerivationFromType(SegwitAddresType.p2wpkh),
|
||||
derivationType: CWBitcoinDerivationType.bip39,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import 'package:cw_bitcoin/bitcoin_mnemonics_bip39.dart';
|
|||
import 'package:cw_bitcoin/bitcoin_transaction_priority.dart';
|
||||
import 'package:cw_bitcoin/electrum_balance.dart';
|
||||
import 'package:cw_bitcoin/electrum_wallet.dart';
|
||||
import 'package:cw_bitcoin/electrum_wallet_addresses.dart';
|
||||
import 'package:cw_bitcoin/electrum_wallet_snapshot.dart';
|
||||
import 'package:cw_core/crypto_currency.dart';
|
||||
import 'package:cw_core/encryption_file_utils.dart';
|
||||
|
@ -51,16 +52,17 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store {
|
|||
encryptionFileUtils: encryptionFileUtils,
|
||||
passphrase: passphrase,
|
||||
mempoolAPIEnabled: mempoolAPIEnabled,
|
||||
hdWallets: {CWBitcoinDerivationType.bip39: bitcoinCashHDWallet(seedBytes)},
|
||||
) {
|
||||
walletAddresses = BitcoinCashWalletAddresses(
|
||||
walletInfo,
|
||||
initialAddresses: initialAddresses,
|
||||
initialRegularAddressIndex: initialRegularAddressIndex,
|
||||
initialChangeAddressIndex: initialChangeAddressIndex,
|
||||
bip32: bip32,
|
||||
network: network,
|
||||
initialAddressPageType: addressPageType,
|
||||
isHardwareWallet: walletInfo.isHardwareWallet,
|
||||
hdWallets: hdWallets,
|
||||
);
|
||||
autorun((_) {
|
||||
this.walletAddresses.isEnabledAutoGenerateSubaddress = this.isEnabledAutoGenerateSubaddress;
|
||||
|
@ -154,6 +156,7 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store {
|
|||
type: P2pkhAddressType.p2pkh,
|
||||
network: BitcoinCashNetwork.mainnet,
|
||||
derivationInfo: BitcoinAddressUtils.getDerivationFromType(P2pkhAddressType.p2pkh),
|
||||
derivationType: CWBitcoinDerivationType.bip39,
|
||||
);
|
||||
} catch (_) {
|
||||
return BitcoinAddressRecord(
|
||||
|
@ -163,6 +166,7 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store {
|
|||
type: P2pkhAddressType.p2pkh,
|
||||
network: BitcoinCashNetwork.mainnet,
|
||||
derivationInfo: BitcoinAddressUtils.getDerivationFromType(P2pkhAddressType.p2pkh),
|
||||
derivationType: CWBitcoinDerivationType.bip39,
|
||||
);
|
||||
}
|
||||
}).toList(),
|
||||
|
@ -253,4 +257,7 @@ abstract class BitcoinCashWalletBase extends ElectrumWallet with Store {
|
|||
network: network,
|
||||
memo: memo,
|
||||
);
|
||||
|
||||
static Bip32Slip10Secp256k1 bitcoinCashHDWallet(List<int> seedBytes) =>
|
||||
Bip32Slip10Secp256k1.fromSeed(seedBytes).derivePath("m/44'/145'/0'") as Bip32Slip10Secp256k1;
|
||||
}
|
||||
|
|
|
@ -10,9 +10,9 @@ class BitcoinCashWalletAddresses = BitcoinCashWalletAddressesBase with _$Bitcoin
|
|||
abstract class BitcoinCashWalletAddressesBase extends ElectrumWalletAddresses with Store {
|
||||
BitcoinCashWalletAddressesBase(
|
||||
WalletInfo walletInfo, {
|
||||
required super.bip32,
|
||||
required super.network,
|
||||
required super.isHardwareWallet,
|
||||
required super.hdWallets,
|
||||
super.initialAddresses,
|
||||
super.initialRegularAddressIndex,
|
||||
super.initialChangeAddressIndex,
|
||||
|
@ -21,6 +21,7 @@ abstract class BitcoinCashWalletAddressesBase extends ElectrumWalletAddresses wi
|
|||
|
||||
@override
|
||||
BitcoinBaseAddress generateAddress({
|
||||
required CWBitcoinDerivationType derivationType,
|
||||
required bool isChange,
|
||||
required int index,
|
||||
required BitcoinAddressType addressType,
|
||||
|
|
|
@ -9,6 +9,7 @@ abstract class WalletCredentials {
|
|||
this.password,
|
||||
this.passphrase,
|
||||
this.derivationInfo,
|
||||
this.derivations,
|
||||
this.hardwareWalletType,
|
||||
this.parentAddress,
|
||||
}) {
|
||||
|
@ -25,5 +26,6 @@ abstract class WalletCredentials {
|
|||
String? passphrase;
|
||||
WalletInfo? walletInfo;
|
||||
DerivationInfo? derivationInfo;
|
||||
List<DerivationInfo>? derivations;
|
||||
HardwareWalletType? hardwareWalletType;
|
||||
}
|
||||
|
|
|
@ -79,6 +79,7 @@ class WalletInfo extends HiveObject {
|
|||
this.yatLastUsedAddressRaw,
|
||||
this.showIntroCakePayCard,
|
||||
this.derivationInfo,
|
||||
this.derivations,
|
||||
this.hardwareWalletType,
|
||||
this.parentAddress,
|
||||
) : _yatLastUsedAddressController = StreamController<String>.broadcast();
|
||||
|
@ -97,6 +98,7 @@ class WalletInfo extends HiveObject {
|
|||
String yatEid = '',
|
||||
String yatLastUsedAddressRaw = '',
|
||||
DerivationInfo? derivationInfo,
|
||||
List<DerivationInfo>? derivations,
|
||||
HardwareWalletType? hardwareWalletType,
|
||||
String? parentAddress,
|
||||
}) {
|
||||
|
@ -114,6 +116,7 @@ class WalletInfo extends HiveObject {
|
|||
yatLastUsedAddressRaw,
|
||||
showIntroCakePayCard,
|
||||
derivationInfo,
|
||||
derivations,
|
||||
hardwareWalletType,
|
||||
parentAddress,
|
||||
);
|
||||
|
@ -196,6 +199,9 @@ class WalletInfo extends HiveObject {
|
|||
@HiveField(24)
|
||||
List<String>? manualAddresses;
|
||||
|
||||
@HiveField(25)
|
||||
List<DerivationInfo>? derivations;
|
||||
|
||||
String get yatLastUsedAddress => yatLastUsedAddressRaw ?? '';
|
||||
|
||||
set yatLastUsedAddress(String address) {
|
||||
|
|
|
@ -5,6 +5,7 @@ class CWBitcoin extends Bitcoin {
|
|||
required String name,
|
||||
required String mnemonic,
|
||||
required String password,
|
||||
required List<DerivationInfo>? derivations,
|
||||
String? passphrase,
|
||||
}) =>
|
||||
BitcoinRestoreWalletFromSeedCredentials(
|
||||
|
@ -12,6 +13,7 @@ class CWBitcoin extends Bitcoin {
|
|||
mnemonic: mnemonic,
|
||||
password: password,
|
||||
passphrase: passphrase,
|
||||
derivations: derivations,
|
||||
);
|
||||
|
||||
@override
|
||||
|
@ -342,20 +344,12 @@ class CWBitcoin extends Bitcoin {
|
|||
}
|
||||
|
||||
@override
|
||||
Future<List<DerivationInfo>> getDerivationsFromMnemonic({
|
||||
Future<List<BitcoinDerivationInfo>> getDerivationsFromMnemonic({
|
||||
required String mnemonic,
|
||||
required Node node,
|
||||
String? passphrase,
|
||||
}) async {
|
||||
List<DerivationInfo> list = [];
|
||||
|
||||
List<DerivationType> types = await compareDerivationMethods(mnemonic: mnemonic, node: node);
|
||||
if (types.length == 1 && types.first == DerivationType.electrum) {
|
||||
return [getElectrumDerivations()[DerivationType.electrum]!.first];
|
||||
}
|
||||
|
||||
final electrumClient = ElectrumClient();
|
||||
await electrumClient.connectToUri(node.uri, useSSL: node.useSSL);
|
||||
List<BitcoinDerivationInfo> list = [];
|
||||
|
||||
late BasedUtxoNetwork network;
|
||||
switch (node.type) {
|
||||
|
@ -368,77 +362,34 @@ class CWBitcoin extends Bitcoin {
|
|||
break;
|
||||
}
|
||||
|
||||
for (DerivationType dType in electrum_derivations.keys) {
|
||||
try {
|
||||
late List<int> seedBytes;
|
||||
if (dType == DerivationType.electrum) {
|
||||
seedBytes = ElectrumV2SeedGenerator.generateFromString(mnemonic, passphrase);
|
||||
} else if (dType == DerivationType.bip39) {
|
||||
seedBytes = Bip39SeedGenerator.generateFromString(mnemonic, passphrase);
|
||||
var electrumSeedBytes;
|
||||
try {
|
||||
electrumSeedBytes = ElectrumV2SeedGenerator.generateFromString(mnemonic, passphrase);
|
||||
} catch (e) {
|
||||
print("electrum_v2 seed error: $e");
|
||||
|
||||
if (passphrase != null && passphrase.isEmpty) {
|
||||
try {
|
||||
// TODO: language pick
|
||||
electrumSeedBytes = ElectrumV1SeedGenerator(mnemonic).generate();
|
||||
} catch (e) {
|
||||
print("electrum_v1 seed error: $e");
|
||||
}
|
||||
|
||||
for (DerivationInfo dInfo in electrum_derivations[dType]!) {
|
||||
try {
|
||||
DerivationInfo dInfoCopy = DerivationInfo(
|
||||
derivationType: dInfo.derivationType,
|
||||
derivationPath: dInfo.derivationPath,
|
||||
description: dInfo.description,
|
||||
scriptType: dInfo.scriptType,
|
||||
);
|
||||
|
||||
String balancePath = dInfoCopy.derivationPath!;
|
||||
int derivationDepth = _countCharOccurrences(balancePath, '/');
|
||||
|
||||
// for BIP44
|
||||
if (derivationDepth == 3 || derivationDepth == 1) {
|
||||
// we add "/0" so that we generate account 0
|
||||
balancePath += "/0";
|
||||
}
|
||||
|
||||
final bip32 = Bip32Slip10Secp256k1.fromSeed(seedBytes);
|
||||
final bip32BalancePath = Bip32PathParser.parse(balancePath);
|
||||
|
||||
// derive address at index 0:
|
||||
final path = bip32BalancePath.addElem(Bip32KeyIndex(0));
|
||||
String? address;
|
||||
switch (dInfoCopy.scriptType) {
|
||||
case "p2wpkh":
|
||||
address = P2wpkhAddress.fromPath(bip32: bip32, path: path).toAddress(network);
|
||||
break;
|
||||
case "p2pkh":
|
||||
address = P2pkhAddress.fromPath(bip32: bip32, path: path).toAddress(network);
|
||||
break;
|
||||
case "p2wpkh-p2sh":
|
||||
address = P2shAddress.fromPath(bip32: bip32, path: path).toAddress(network);
|
||||
break;
|
||||
case "p2tr":
|
||||
address = P2trAddress.fromPath(bip32: bip32, path: path).toAddress(network);
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
final sh = BitcoinAddressUtils.scriptHash(address, network: network);
|
||||
final history = await electrumClient.getHistory(sh);
|
||||
|
||||
final balance = await electrumClient.getBalance(sh);
|
||||
dInfoCopy.balance = balance.entries.firstOrNull?.value.toString() ?? "0";
|
||||
dInfoCopy.address = address;
|
||||
dInfoCopy.transactionsCount = history.length;
|
||||
|
||||
list.add(dInfoCopy);
|
||||
} catch (e, s) {
|
||||
print("derivationInfoError: $e");
|
||||
print("derivationInfoStack: $s");
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
print("seed error: $e");
|
||||
}
|
||||
}
|
||||
|
||||
// sort the list such that derivations with the most transactions are first:
|
||||
list.sort((a, b) => b.transactionsCount.compareTo(a.transactionsCount));
|
||||
if (electrumSeedBytes != null) {
|
||||
list.add(BitcoinDerivationInfos.ELECTRUM);
|
||||
}
|
||||
|
||||
var bip39SeedBytes;
|
||||
try {
|
||||
bip39SeedBytes = Bip39SeedGenerator.generateFromString(mnemonic, passphrase);
|
||||
} catch (_) {}
|
||||
|
||||
if (bip39SeedBytes != null) {
|
||||
list.add(BitcoinDerivationInfos.BIP84);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
|
|
@ -109,6 +109,7 @@ class WalletRestorePage extends BasePage {
|
|||
// DerivationType derivationType = DerivationType.unknown;
|
||||
// String? derivationPath = null;
|
||||
DerivationInfo? derivationInfo;
|
||||
List<DerivationInfo>? derivations;
|
||||
|
||||
@override
|
||||
Function(BuildContext)? get pushToNextWidget => (context) {
|
||||
|
@ -346,6 +347,7 @@ class WalletRestorePage extends BasePage {
|
|||
}
|
||||
|
||||
credentials['derivationInfo'] = this.derivationInfo;
|
||||
credentials['derivations'] = this.derivations;
|
||||
credentials['walletType'] = walletRestoreViewModel.type;
|
||||
return credentials;
|
||||
}
|
||||
|
@ -383,13 +385,13 @@ class WalletRestorePage extends BasePage {
|
|||
|
||||
walletRestoreViewModel.state = IsExecutingState();
|
||||
|
||||
// get info about the different derivations:
|
||||
List<DerivationInfo> derivations =
|
||||
await walletRestoreViewModel.getDerivationInfo(_credentials());
|
||||
|
||||
if (walletRestoreViewModel.type == WalletType.nano) {
|
||||
DerivationInfo? dInfo;
|
||||
|
||||
// get info about the different derivations:
|
||||
List<DerivationInfo> derivations =
|
||||
await walletRestoreViewModel.getDerivationInfo(_credentials());
|
||||
|
||||
int derivationsWithHistory = 0;
|
||||
int derivationWithHistoryIndex = 0;
|
||||
for (int i = 0; i < derivations.length; i++) {
|
||||
|
@ -416,6 +418,8 @@ class WalletRestorePage extends BasePage {
|
|||
}
|
||||
|
||||
this.derivationInfo = dInfo;
|
||||
} else {
|
||||
this.derivations = derivations;
|
||||
}
|
||||
|
||||
await walletRestoreViewModel.create(options: _credentials());
|
||||
|
|
|
@ -118,6 +118,7 @@ abstract class WalletRestorationFromQRVMBase extends WalletCreationVM with Store
|
|||
mnemonic: restoreWallet.mnemonicSeed ?? '',
|
||||
password: password,
|
||||
passphrase: restoreWallet.passphrase,
|
||||
derivations: [],
|
||||
);
|
||||
case WalletType.bitcoinCash:
|
||||
return bitcoinCash!.createBitcoinCashRestoreWalletFromSeedCredentials(
|
||||
|
|
|
@ -101,6 +101,7 @@ abstract class WalletCreationVMBase with Store {
|
|||
address: '',
|
||||
showIntroCakePayCard: (!walletCreationService.typeExists(type)) && type != WalletType.haven,
|
||||
derivationInfo: credentials.derivationInfo ?? getDefaultCreateDerivation(),
|
||||
derivations: credentials.derivations,
|
||||
hardwareWalletType: credentials.hardwareWalletType,
|
||||
parentAddress: credentials.parentAddress,
|
||||
);
|
||||
|
@ -200,15 +201,36 @@ abstract class WalletCreationVMBase with Store {
|
|||
switch (walletType) {
|
||||
case WalletType.bitcoin:
|
||||
case WalletType.litecoin:
|
||||
final derivationList = await bitcoin!.getDerivationsFromMnemonic(
|
||||
final bitcoinDerivations = await bitcoin!.getDerivationsFromMnemonic(
|
||||
mnemonic: restoreWallet.mnemonicSeed!,
|
||||
node: node,
|
||||
passphrase: restoreWallet.passphrase,
|
||||
);
|
||||
|
||||
if (derivationList.firstOrNull?.transactionsCount == 0 && derivationList.length > 1)
|
||||
return [];
|
||||
return derivationList;
|
||||
List<DerivationInfo> list = [];
|
||||
for (var derivation in bitcoinDerivations) {
|
||||
if (derivation.derivationType == DerivationType.electrum) {
|
||||
list.add(
|
||||
DerivationInfo(
|
||||
derivationType: DerivationType.electrum,
|
||||
derivationPath: "m/0'",
|
||||
description: "Electrum",
|
||||
scriptType: "p2wpkh",
|
||||
),
|
||||
);
|
||||
} else {
|
||||
list.add(
|
||||
DerivationInfo(
|
||||
derivationType: DerivationType.bip39,
|
||||
derivationPath: "m/84'/0'/0'",
|
||||
description: "Standard BIP84 native segwit",
|
||||
scriptType: "p2wpkh",
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
|
||||
case WalletType.nano:
|
||||
return nanoUtil!.getDerivationsFromMnemonic(
|
||||
|
|
|
@ -91,6 +91,7 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
|
|||
final height = options['height'] as int? ?? 0;
|
||||
name = options['name'] as String;
|
||||
DerivationInfo? derivationInfo = options["derivationInfo"] as DerivationInfo?;
|
||||
List<DerivationInfo>? derivations = options["derivations"] as List<DerivationInfo>?;
|
||||
|
||||
if (mode == WalletRestoreMode.seed) {
|
||||
final seed = options['seed'] as String;
|
||||
|
@ -105,6 +106,7 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
|
|||
mnemonic: seed,
|
||||
password: password,
|
||||
passphrase: passphrase,
|
||||
derivations: derivations,
|
||||
);
|
||||
case WalletType.haven:
|
||||
return haven!.createHavenRestoreWalletFromSeedCredentials(
|
||||
|
@ -254,11 +256,36 @@ abstract class WalletRestoreViewModelBase extends WalletCreationVM with Store {
|
|||
case WalletType.litecoin:
|
||||
String? mnemonic = credentials['seed'] as String?;
|
||||
String? passphrase = credentials['passphrase'] as String?;
|
||||
return bitcoin!.getDerivationsFromMnemonic(
|
||||
final bitcoinDerivations = await bitcoin!.getDerivationsFromMnemonic(
|
||||
mnemonic: mnemonic!,
|
||||
node: node,
|
||||
passphrase: passphrase,
|
||||
);
|
||||
|
||||
List<DerivationInfo> list = [];
|
||||
for (var derivation in bitcoinDerivations) {
|
||||
if (derivation.derivationType.toString().endsWith("electrum")) {
|
||||
list.add(
|
||||
DerivationInfo(
|
||||
derivationType: DerivationType.electrum,
|
||||
derivationPath: "m/0'",
|
||||
description: "Electrum",
|
||||
scriptType: "p2wpkh",
|
||||
),
|
||||
);
|
||||
} else {
|
||||
list.add(
|
||||
DerivationInfo(
|
||||
derivationType: DerivationType.bip39,
|
||||
derivationPath: "m/84'/0'/0'",
|
||||
description: "Standard BIP84 native segwit",
|
||||
scriptType: "p2wpkh",
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
case WalletType.nano:
|
||||
String? mnemonic = credentials['seed'] as String?;
|
||||
String? seedKey = credentials['private_key'] as String?;
|
||||
|
|
|
@ -148,6 +148,7 @@ abstract class Bitcoin {
|
|||
required String name,
|
||||
required String mnemonic,
|
||||
required String password,
|
||||
required List<DerivationInfo>? derivations,
|
||||
String? passphrase,
|
||||
});
|
||||
WalletCredentials createBitcoinRestoreWalletFromWIFCredentials({required String name, required String password, required String wif, WalletInfo? walletInfo});
|
||||
|
@ -199,7 +200,7 @@ abstract class Bitcoin {
|
|||
TransactionPriority getLitecoinTransactionPrioritySlow();
|
||||
Future<List<DerivationType>> compareDerivationMethods(
|
||||
{required String mnemonic, required Node node});
|
||||
Future<List<DerivationInfo>> getDerivationsFromMnemonic(
|
||||
Future<List<BitcoinDerivationInfo>> getDerivationsFromMnemonic(
|
||||
{required String mnemonic, required Node node, String? passphrase});
|
||||
Map<DerivationType, List<DerivationInfo>> getElectrumDerivations();
|
||||
Future<void> setAddressType(Object wallet, dynamic option);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue