mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-06-29 04:49:51 +00:00
fix: _address vs address, missing p2sh
This commit is contained in:
parent
2e6ba71e57
commit
f8cadfa112
9 changed files with 87 additions and 47 deletions
|
@ -11,6 +11,8 @@ String addressFromOutputScript(Script script, BasedUtxoNetwork network) {
|
|||
return P2shAddress.fromScriptPubkey(script: script).toAddress(network);
|
||||
case SegwitAddresType.p2wpkh:
|
||||
return P2wpkhAddress.fromScriptPubkey(script: script).toAddress(network);
|
||||
case P2shAddressType.p2pkhInP2sh:
|
||||
return P2shAddress.fromScriptPubkey(script: script).toAddress(network);
|
||||
case SegwitAddresType.p2wsh:
|
||||
return P2wshAddress.fromScriptPubkey(script: script).toAddress(network);
|
||||
case SegwitAddresType.p2tr:
|
||||
|
|
|
@ -12,7 +12,7 @@ class BitcoinAddressRecord {
|
|||
int balance = 0,
|
||||
String name = '',
|
||||
bool isUsed = false,
|
||||
this.type,
|
||||
required this.type,
|
||||
}) : _txCount = txCount,
|
||||
_balance = balance,
|
||||
_name = name,
|
||||
|
@ -32,7 +32,7 @@ class BitcoinAddressRecord {
|
|||
type: decoded['type'] != null && decoded['type'] != ''
|
||||
? BitcoinAddressType.values
|
||||
.firstWhere((type) => type.toString() == decoded['type'] as String)
|
||||
: null,
|
||||
: SegwitAddresType.p2wpkh,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -67,7 +67,7 @@ class BitcoinAddressRecord {
|
|||
|
||||
String get cashAddr => bitbox.Address.toCashAddress(address);
|
||||
|
||||
BitcoinAddressType? type;
|
||||
BitcoinAddressType type;
|
||||
|
||||
String toJSON() => json.encode({
|
||||
'address': address,
|
||||
|
@ -77,6 +77,6 @@ class BitcoinAddressRecord {
|
|||
'txCount': txCount,
|
||||
'name': name,
|
||||
'balance': balance,
|
||||
'type': type?.toString() ?? '',
|
||||
'type': type.toString(),
|
||||
});
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ import 'package:cw_core/receive_page_option.dart';
|
|||
|
||||
class BitcoinReceivePageOption implements ReceivePageOption {
|
||||
static const p2wpkh = BitcoinReceivePageOption._('Segwit (P2WPKH)');
|
||||
static const p2sh = BitcoinReceivePageOption._('Segwit-Compatible (P2SH)');
|
||||
static const p2tr = BitcoinReceivePageOption._('Taproot (P2TR)');
|
||||
static const p2wsh = BitcoinReceivePageOption._('Segwit (P2WSH)');
|
||||
static const p2pkh = BitcoinReceivePageOption._('Legacy (P2PKH)');
|
||||
|
@ -17,6 +18,7 @@ class BitcoinReceivePageOption implements ReceivePageOption {
|
|||
|
||||
static const all = [
|
||||
BitcoinReceivePageOption.p2wpkh,
|
||||
BitcoinReceivePageOption.p2sh,
|
||||
BitcoinReceivePageOption.p2tr,
|
||||
BitcoinReceivePageOption.p2wsh,
|
||||
BitcoinReceivePageOption.p2pkh
|
||||
|
@ -30,6 +32,8 @@ class BitcoinReceivePageOption implements ReceivePageOption {
|
|||
return BitcoinReceivePageOption.p2wsh;
|
||||
case P2pkhAddressType.p2pkh:
|
||||
return BitcoinReceivePageOption.p2pkh;
|
||||
case P2shAddressType.p2wpkhInP2sh:
|
||||
return BitcoinReceivePageOption.p2pkh;
|
||||
case SegwitAddresType.p2wpkh:
|
||||
default:
|
||||
return BitcoinReceivePageOption.p2wpkh;
|
||||
|
|
|
@ -32,6 +32,9 @@ abstract class BitcoinWalletAddressesBase extends ElectrumWalletAddresses with S
|
|||
if (addressType == SegwitAddresType.p2wsh)
|
||||
return generateP2WSHAddress(hd: hd, index: index, network: network);
|
||||
|
||||
if (addressType == P2shAddressType.p2wpkhInP2sh)
|
||||
return generateP2SHAddress(hd: hd, index: index, network: network);
|
||||
|
||||
return generateP2WPKHAddress(hd: hd, index: index, network: network);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -157,7 +157,7 @@ abstract class ElectrumWalletBase
|
|||
Future<void> startSync() async {
|
||||
try {
|
||||
syncStatus = AttemptingSyncStatus();
|
||||
await walletAddresses.discoverAddresses();
|
||||
await walletAddresses.discoverAddressesAll();
|
||||
await updateTransactions();
|
||||
_subscribeForUpdates();
|
||||
await updateUnspent();
|
||||
|
@ -849,6 +849,8 @@ class EstimatedTxResult {
|
|||
BitcoinBaseAddress _addressTypeFromStr(String address, BasedUtxoNetwork network) {
|
||||
if (P2pkhAddress.regex.hasMatch(address)) {
|
||||
return P2pkhAddress.fromAddress(address: address, network: network);
|
||||
} else if (P2shAddress.regex.hasMatch(address)) {
|
||||
return P2shAddress.fromAddress(address: address, network: network);
|
||||
} else if (P2wshAddress.regex.hasMatch(address)) {
|
||||
return P2wshAddress.fromAddress(address: address, network: network);
|
||||
} else if (P2trAddress.regex.hasMatch(address)) {
|
||||
|
@ -861,6 +863,8 @@ BitcoinBaseAddress _addressTypeFromStr(String address, BasedUtxoNetwork network)
|
|||
BitcoinAddressType _getScriptType(BitcoinBaseAddress type) {
|
||||
if (type is P2pkhAddress) {
|
||||
return P2pkhAddressType.p2pkh;
|
||||
} else if (type is P2shAddress) {
|
||||
return P2shAddressType.p2wpkhInP2sh;
|
||||
} else if (type is P2wshAddress) {
|
||||
return SegwitAddresType.p2wsh;
|
||||
} else if (type is P2trAddress) {
|
||||
|
|
|
@ -65,7 +65,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
|||
String get addressPageTypeStr => addressPageType.toString();
|
||||
|
||||
@computed
|
||||
List<BitcoinAddressRecord> get addresses => _addresses.where(_isAddressTypeMatch).toList();
|
||||
List<BitcoinAddressRecord> get addresses => _addresses.where(_isAddressPageTypeMatch).toList();
|
||||
|
||||
@computed
|
||||
List<BitcoinAddressRecord> get allAddresses => _addresses;
|
||||
|
@ -80,7 +80,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
|||
String get address {
|
||||
String receiveAddress;
|
||||
|
||||
final typeMatchingReceiveAddresses = receiveAddresses.where(_isAddressTypeMatch);
|
||||
final typeMatchingReceiveAddresses = receiveAddresses.where(_isAddressPageTypeMatch);
|
||||
|
||||
if ((isEnabledAutoGenerateSubaddress && receiveAddresses.isEmpty) ||
|
||||
typeMatchingReceiveAddresses.isEmpty) {
|
||||
|
@ -151,15 +151,28 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
|||
return acc;
|
||||
});
|
||||
|
||||
Future<void> discoverAddresses() async {
|
||||
Future<void> discoverAddressesAll() async {
|
||||
await _discoverAddresses(false);
|
||||
await _discoverAddresses(true);
|
||||
await _discoverAddresses(false, type: P2pkhAddressType.p2pkh);
|
||||
await _discoverAddresses(true, type: P2pkhAddressType.p2pkh);
|
||||
await _discoverAddresses(false, type: P2shAddressType.p2wpkhInP2sh);
|
||||
await _discoverAddresses(true, type: P2shAddressType.p2wpkhInP2sh);
|
||||
await _discoverAddresses(false, type: SegwitAddresType.p2tr);
|
||||
await _discoverAddresses(true, type: SegwitAddresType.p2tr);
|
||||
await _discoverAddresses(false, type: SegwitAddresType.p2wsh);
|
||||
await _discoverAddresses(true, type: SegwitAddresType.p2wsh);
|
||||
updateReceiveAddresses();
|
||||
await updateAddressesInBox();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> init() async {
|
||||
await _generateInitialAddresses();
|
||||
await _generateInitialAddresses(type: P2pkhAddressType.p2pkh);
|
||||
await _generateInitialAddresses(type: P2shAddressType.p2wpkhInP2sh);
|
||||
await _generateInitialAddresses(type: SegwitAddresType.p2tr);
|
||||
await _generateInitialAddresses(type: SegwitAddresType.p2wsh);
|
||||
updateReceiveAddresses();
|
||||
updateChangeAddresses();
|
||||
await updateAddressesInBox();
|
||||
|
@ -199,11 +212,11 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
|||
0, (int acc, addressRecord) => addressRecord.isHidden == false ? acc + 1 : acc);
|
||||
|
||||
final address = BitcoinAddressRecord(
|
||||
getAddress(index: newAddressIndex, hd: mainHd, addressType: addressPageType),
|
||||
index: newAddressIndex,
|
||||
isHidden: false,
|
||||
name: label,
|
||||
);
|
||||
getAddress(index: newAddressIndex, hd: mainHd, addressType: addressPageType),
|
||||
index: newAddressIndex,
|
||||
isHidden: false,
|
||||
name: label,
|
||||
type: addressPageType);
|
||||
addresses.add(address);
|
||||
return address;
|
||||
}
|
||||
|
@ -240,31 +253,36 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
|||
void updateReceiveAddresses() {
|
||||
receiveAddresses.removeRange(0, receiveAddresses.length);
|
||||
final newAddresses =
|
||||
addresses.where((addressRecord) => !addressRecord.isHidden && !addressRecord.isUsed);
|
||||
_addresses.where((addressRecord) => !addressRecord.isHidden && !addressRecord.isUsed);
|
||||
receiveAddresses.addAll(newAddresses);
|
||||
}
|
||||
|
||||
@action
|
||||
void updateChangeAddresses() {
|
||||
changeAddresses.removeRange(0, changeAddresses.length);
|
||||
final newAddresses =
|
||||
addresses.where((addressRecord) => addressRecord.isHidden && !addressRecord.isUsed);
|
||||
final newAddresses = _addresses.where((addressRecord) =>
|
||||
addressRecord.isHidden &&
|
||||
!addressRecord.isUsed &&
|
||||
// TODO: feature to change change address type. For now fixed to p2wpkh, the cheapest type
|
||||
addressRecord.type == SegwitAddresType.p2wpkh);
|
||||
changeAddresses.addAll(newAddresses);
|
||||
}
|
||||
|
||||
@action
|
||||
Future<void> _discoverAddresses(bool isHidden) async {
|
||||
Future<void> _discoverAddresses(bool isHidden,
|
||||
{BitcoinAddressType type = SegwitAddresType.p2wpkh}) async {
|
||||
var hasAddrUse = true;
|
||||
List<BitcoinAddressRecord> addrs;
|
||||
final matchingAddresses = _addresses.where((addr) => _addressMatchHidden(addr, isHidden, type));
|
||||
|
||||
if (addresses.where((addr) => addr.isHidden == isHidden).isNotEmpty) {
|
||||
addrs = addresses.where((addr) => addr.isHidden == isHidden).toList();
|
||||
if (matchingAddresses.isNotEmpty) {
|
||||
addrs = matchingAddresses.toList();
|
||||
} else {
|
||||
addrs = await _createNewAddresses(
|
||||
isHidden ? defaultChangeAddressesCount : defaultReceiveAddressesCount,
|
||||
startIndex: 0,
|
||||
isHidden: isHidden,
|
||||
);
|
||||
isHidden ? defaultChangeAddressesCount : defaultReceiveAddressesCount,
|
||||
startIndex: 0,
|
||||
isHidden: isHidden,
|
||||
type: type);
|
||||
}
|
||||
|
||||
while (hasAddrUse) {
|
||||
|
@ -277,51 +295,55 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
|||
|
||||
final start = addrs.length;
|
||||
final count = start + gap;
|
||||
final batch = await _createNewAddresses(count, startIndex: start, isHidden: isHidden);
|
||||
final batch =
|
||||
await _createNewAddresses(count, startIndex: start, isHidden: isHidden, type: type);
|
||||
addrs.addAll(batch);
|
||||
}
|
||||
|
||||
addAddresses(addrs);
|
||||
}
|
||||
|
||||
Future<void> _generateInitialAddresses() async {
|
||||
Future<void> _generateInitialAddresses(
|
||||
{BitcoinAddressType type = SegwitAddresType.p2wpkh}) async {
|
||||
var countOfReceiveAddresses = 0;
|
||||
var countOfHiddenAddresses = 0;
|
||||
|
||||
addresses.forEach((addr) {
|
||||
if (addr.isHidden) {
|
||||
countOfHiddenAddresses += 1;
|
||||
return;
|
||||
}
|
||||
_addresses.forEach((addr) {
|
||||
if (_isAddressByType(addr, type)) {
|
||||
if (addr.isHidden) {
|
||||
countOfHiddenAddresses += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
countOfReceiveAddresses += 1;
|
||||
countOfReceiveAddresses += 1;
|
||||
}
|
||||
});
|
||||
|
||||
if (countOfReceiveAddresses < defaultReceiveAddressesCount) {
|
||||
final addressesCount = defaultReceiveAddressesCount - countOfReceiveAddresses;
|
||||
final newAddresses = await _createNewAddresses(addressesCount,
|
||||
startIndex: countOfReceiveAddresses, isHidden: false);
|
||||
addresses.addAll(newAddresses);
|
||||
startIndex: countOfReceiveAddresses, isHidden: false, type: type);
|
||||
_addresses.addAll(newAddresses);
|
||||
}
|
||||
|
||||
if (countOfHiddenAddresses < defaultChangeAddressesCount) {
|
||||
final addressesCount = defaultChangeAddressesCount - countOfHiddenAddresses;
|
||||
final newAddresses = await _createNewAddresses(addressesCount,
|
||||
startIndex: countOfHiddenAddresses, isHidden: true);
|
||||
addresses.addAll(newAddresses);
|
||||
startIndex: countOfHiddenAddresses, isHidden: true, type: type);
|
||||
_addresses.addAll(newAddresses);
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<BitcoinAddressRecord>> _createNewAddresses(int count,
|
||||
{int startIndex = 0, bool isHidden = false}) async {
|
||||
{int startIndex = 0, bool isHidden = false, BitcoinAddressType? type}) async {
|
||||
final list = <BitcoinAddressRecord>[];
|
||||
|
||||
for (var i = startIndex; i < count + startIndex; i++) {
|
||||
final address = BitcoinAddressRecord(
|
||||
getAddress(index: i, hd: _getHd(isHidden), addressType: addressPageType),
|
||||
getAddress(index: i, hd: _getHd(isHidden), addressType: type ?? addressPageType),
|
||||
index: i,
|
||||
isHidden: isHidden,
|
||||
type: addressPageType,
|
||||
type: type ?? addressPageType,
|
||||
);
|
||||
list.add(address);
|
||||
}
|
||||
|
@ -346,17 +368,15 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
|||
@action
|
||||
Future<void> setAddressType(BitcoinAddressType type) async {
|
||||
_addressPageType = type;
|
||||
|
||||
await discoverAddresses();
|
||||
await saveAddressesInBox();
|
||||
}
|
||||
|
||||
bool _isAddressTypeMatch(BitcoinAddressRecord addressRecord) {
|
||||
// Old wallets before address types were introduced will have an empty address record type
|
||||
return addressPageType == SegwitAddresType.p2wpkh
|
||||
? addressRecord.type == null || addressRecord.type == addressPageType
|
||||
: addressRecord.type == addressPageType;
|
||||
bool _isAddressPageTypeMatch(BitcoinAddressRecord addressRecord) {
|
||||
return _isAddressByType(addressRecord, addressPageType);
|
||||
}
|
||||
|
||||
bitcoin.HDWallet _getHd(bool isHidden) => isHidden ? sideHd : mainHd;
|
||||
bool _isAddressByType(BitcoinAddressRecord addr, BitcoinAddressType type) =>
|
||||
addr.type == type || (addr.type == null && type == SegwitAddresType.p2wpkh);
|
||||
bool _addressMatchHidden(BitcoinAddressRecord addr, bool isHidden, BitcoinAddressType type) =>
|
||||
_isAddressByType(addr, type) && addr.isHidden == isHidden;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,10 @@ String generateP2WPKHAddress(
|
|||
{required bitcoin.HDWallet hd, required int index, required BasedUtxoNetwork network}) =>
|
||||
ECPublic.fromHex(hd.derive(index).pubKey!).toP2wpkhAddress().toAddress(network);
|
||||
|
||||
String generateP2SHAddress(
|
||||
{required bitcoin.HDWallet hd, required int index, required BasedUtxoNetwork network}) =>
|
||||
ECPublic.fromHex(hd.derive(index).pubKey!).toP2wpkhInP2sh().toAddress(network);
|
||||
|
||||
String generateP2WSHAddress(
|
||||
{required bitcoin.HDWallet hd, required int index, required BasedUtxoNetwork network}) =>
|
||||
ECPublic.fromHex(hd.derive(index).pubKey!).toP2wshAddress().toAddress(network);
|
||||
|
|
|
@ -80,7 +80,7 @@ packages:
|
|||
description:
|
||||
path: "."
|
||||
ref: cake-update-v1
|
||||
resolved-ref: "318986da9cb03e4c18da2e6c0daf3e62aef7eb72"
|
||||
resolved-ref: "9611e9db77e92a8434e918cdfb620068f6fcb1aa"
|
||||
url: "https://github.com/cake-tech/bitcoin_base.git"
|
||||
source: git
|
||||
version: "4.0.0"
|
||||
|
|
|
@ -233,6 +233,9 @@ class AddressPage extends BasePage {
|
|||
case BitcoinReceivePageOption.p2pkh:
|
||||
addressListViewModel.setAddressType(P2pkhAddressType.p2pkh);
|
||||
break;
|
||||
case BitcoinReceivePageOption.p2sh:
|
||||
addressListViewModel.setAddressType(P2shAddressType.p2wpkhInP2sh);
|
||||
break;
|
||||
case BitcoinReceivePageOption.p2wpkh:
|
||||
addressListViewModel.setAddressType(SegwitAddresType.p2wpkh);
|
||||
break;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue