mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2024-11-16 09:17:35 +00:00
feat: rescan a specific address
This commit is contained in:
parent
fc7bea6830
commit
bf0dcc8d7b
6 changed files with 85 additions and 10 deletions
|
@ -63,6 +63,7 @@ class BitcoinAddressRecord extends BaseBitcoinAddressRecord {
|
|||
super.isUsed = false,
|
||||
required super.type,
|
||||
String? scriptHash,
|
||||
this.spendKey,
|
||||
required super.network,
|
||||
}) : scriptHash = scriptHash ??
|
||||
(network != null ? BitcoinAddressUtils.scriptHash(address, network: network) : null);
|
||||
|
@ -88,6 +89,7 @@ class BitcoinAddressRecord extends BaseBitcoinAddressRecord {
|
|||
}
|
||||
|
||||
String? scriptHash;
|
||||
ECPrivate? spendKey;
|
||||
|
||||
String getScriptHash(BasedUtxoNetwork network) {
|
||||
if (scriptHash != null) return scriptHash!;
|
||||
|
|
|
@ -602,7 +602,11 @@ abstract class ElectrumWalletBase
|
|||
spendsSilentPayment = true;
|
||||
isSilentPayment = true;
|
||||
} else if (!isHardwareWallet) {
|
||||
privkey =
|
||||
final spendKey = (utx.bitcoinAddressRecord as BitcoinAddressRecord).spendKey;
|
||||
// if spend key is present, this is needed to disable tweaking the key during signing
|
||||
isSilentPayment = spendKey != null;
|
||||
|
||||
privkey = spendKey ??
|
||||
generateECPrivate(hd: hd, index: utx.bitcoinAddressRecord.index, network: network);
|
||||
}
|
||||
|
||||
|
@ -1266,14 +1270,22 @@ abstract class ElectrumWalletBase
|
|||
if (hasSilentPaymentsScanning) {
|
||||
// Update unspents stored from scanned silent payment transactions
|
||||
transactionHistory.transactions.values.forEach((tx) {
|
||||
if (tx.unspents != null) {
|
||||
if (tx.unspents != null && tx.unspents!.isNotEmpty) {
|
||||
updatedUnspentCoins.addAll(tx.unspents!);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
await Future.wait(walletAddresses.allAddresses.map((address) async {
|
||||
updatedUnspentCoins.addAll(await fetchUnspent(address));
|
||||
final unspentList = await fetchUnspent(address);
|
||||
|
||||
if (unspentList.isNotEmpty) {
|
||||
for (final unspent in unspentList) {
|
||||
if (!updatedUnspentCoins.any((element) => element.hash == unspent.hash)) {
|
||||
updatedUnspentCoins.add(unspent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
unspentCoins = updatedUnspentCoins;
|
||||
|
@ -1860,6 +1872,12 @@ abstract class ElectrumWalletBase
|
|||
}
|
||||
}
|
||||
|
||||
Future<void> fullAddressUpdate(BitcoinAddressRecord address) async {
|
||||
await updateUnspents(address);
|
||||
await _fetchBalance(address);
|
||||
await _fetchAddressHistory(address, await getCurrentChainTip());
|
||||
}
|
||||
|
||||
Future<void> _subscribeForUpdates() async {
|
||||
final unsubscribedScriptHashes = walletAddresses.allAddresses.where(
|
||||
(address) => !_scripthashesUpdateSubject.containsKey(address.getScriptHash(network)),
|
||||
|
@ -1871,11 +1889,7 @@ abstract class ElectrumWalletBase
|
|||
_scripthashesUpdateSubject[sh] = await electrumClient.scripthashUpdate(sh);
|
||||
_scripthashesUpdateSubject[sh]?.listen((event) async {
|
||||
try {
|
||||
await updateUnspents(address);
|
||||
|
||||
await updateBalance();
|
||||
|
||||
await _fetchAddressHistory(address, await getCurrentChainTip());
|
||||
await fullAddressUpdate(address);
|
||||
} catch (e, s) {
|
||||
print(e.toString());
|
||||
_onError?.call(FlutterErrorDetails(
|
||||
|
@ -1888,6 +1902,20 @@ abstract class ElectrumWalletBase
|
|||
}));
|
||||
}
|
||||
|
||||
Future<ElectrumBalance> _fetchBalance(BitcoinAddressRecord address) async {
|
||||
final sh = address.getScriptHash(network);
|
||||
final balance = await electrumClient.getBalance(sh);
|
||||
|
||||
final totalConfirmed = balance['confirmed'] as int? ?? 0;
|
||||
final totalUnconfirmed = balance['unconfirmed'] as int? ?? 0;
|
||||
|
||||
if (totalConfirmed > 0 || totalUnconfirmed > 0) {
|
||||
address.setAsUsed();
|
||||
}
|
||||
|
||||
return ElectrumBalance(confirmed: totalConfirmed, unconfirmed: totalUnconfirmed, frozen: 0);
|
||||
}
|
||||
|
||||
Future<ElectrumBalance> _fetchBalances() async {
|
||||
final addresses = walletAddresses.allAddresses.toList();
|
||||
final balanceFutures = <Future<Map<String, dynamic>>>[];
|
||||
|
|
|
@ -588,7 +588,6 @@ class CWBitcoin extends Bitcoin {
|
|||
}
|
||||
|
||||
final updatedOutputs = outputs.map((output) {
|
||||
|
||||
try {
|
||||
final pendingOut = pendingTx!.outputs[outputs.indexOf(output)];
|
||||
final updatedOutput = output;
|
||||
|
@ -609,4 +608,31 @@ class CWBitcoin extends Bitcoin {
|
|||
final tx = txInfo as ElectrumTransactionInfo;
|
||||
return tx.isReceivedSilentPayment;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> fullAddressUpdate(Object wallet, String address) async {
|
||||
final bitcoinWallet = wallet as ElectrumWallet;
|
||||
final spAddressRecord =
|
||||
bitcoinWallet.walletAddresses.silentAddresses.firstWhere((addr) => addr.address == address);
|
||||
|
||||
final bitcoinAddressRecord = BitcoinAddressRecord(
|
||||
address,
|
||||
index: spAddressRecord.index,
|
||||
isHidden: spAddressRecord.isHidden,
|
||||
txCount: spAddressRecord.txCount,
|
||||
balance: spAddressRecord.balance,
|
||||
name: spAddressRecord.name,
|
||||
isUsed: spAddressRecord.isUsed,
|
||||
type: spAddressRecord.type,
|
||||
network: spAddressRecord.network,
|
||||
spendKey: bitcoinWallet.walletAddresses.silentAddress!.b_spend.tweakAdd(
|
||||
BigintUtils.fromBytes(
|
||||
BytesUtils.fromHexString(spAddressRecord.silentPaymentTweak!),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
bitcoinWallet.walletAddresses.addAddresses([bitcoinAddressRecord]);
|
||||
bitcoinWallet.fullAddressUpdate(bitcoinAddressRecord);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ class AddressCell extends StatelessWidget {
|
|||
this.onTap,
|
||||
this.onEdit,
|
||||
this.onDelete,
|
||||
this.onRescan,
|
||||
this.txCount,
|
||||
this.balance,
|
||||
this.isChange = false,
|
||||
|
@ -30,6 +31,7 @@ class AddressCell extends StatelessWidget {
|
|||
bool hasBalance = false,
|
||||
Function()? onEdit,
|
||||
Function()? onDelete,
|
||||
Function()? onRescan,
|
||||
}) =>
|
||||
AddressCell(
|
||||
address: item.address,
|
||||
|
@ -41,6 +43,7 @@ class AddressCell extends StatelessWidget {
|
|||
onTap: onTap,
|
||||
onEdit: onEdit,
|
||||
onDelete: onDelete,
|
||||
onRescan: onRescan,
|
||||
txCount: item.txCount,
|
||||
balance: item.balance,
|
||||
isChange: item.isChange,
|
||||
|
@ -55,6 +58,7 @@ class AddressCell extends StatelessWidget {
|
|||
final Function(String)? onTap;
|
||||
final Function()? onEdit;
|
||||
final Function()? onDelete;
|
||||
final Function()? onRescan;
|
||||
final int? txCount;
|
||||
final String? balance;
|
||||
final bool isChange;
|
||||
|
@ -89,7 +93,9 @@ class AddressCell extends StatelessWidget {
|
|||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: name.isNotEmpty ? MainAxisAlignment.spaceBetween : MainAxisAlignment.center,
|
||||
mainAxisAlignment: name.isNotEmpty
|
||||
? MainAxisAlignment.spaceBetween
|
||||
: MainAxisAlignment.center,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Row(
|
||||
|
@ -196,6 +202,14 @@ class AddressCell extends StatelessWidget {
|
|||
icon: Icons.edit,
|
||||
label: S.of(context).edit,
|
||||
),
|
||||
if (onRescan != null)
|
||||
SlidableAction(
|
||||
onPressed: (_) => onRescan!.call(),
|
||||
backgroundColor: Colors.green,
|
||||
foregroundColor: Colors.white,
|
||||
icon: Icons.refresh,
|
||||
label: S.of(context).rescan,
|
||||
),
|
||||
if (onDelete != null)
|
||||
SlidableAction(
|
||||
onPressed: (_) => onDelete!.call(),
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import 'package:cake_wallet/bitcoin/bitcoin.dart';
|
||||
import 'package:cake_wallet/di.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
|
@ -102,6 +103,9 @@ class AddressList extends StatelessWidget {
|
|||
onEdit: editable
|
||||
? () => Navigator.of(context).pushNamed(Routes.newSubaddress, arguments: item)
|
||||
: null,
|
||||
onRescan: (item.isOneTimeReceiveAddress ?? false)
|
||||
? () => bitcoin!.fullAddressUpdate(addressListViewModel.wallet, item.address)
|
||||
: null,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -224,6 +224,7 @@ abstract class Bitcoin {
|
|||
Future<List<HardwareAccountData>> getHardwareWalletAccounts(LedgerViewModel ledgerVM, {int index = 0, int limit = 5});
|
||||
List<Output> updateOutputs(PendingTransaction pendingTransaction, List<Output> outputs);
|
||||
bool txIsReceivedSilentPayment(TransactionInfo txInfo);
|
||||
Future<void> fullAddressUpdate(Object wallet, String address);
|
||||
}
|
||||
""";
|
||||
|
||||
|
|
Loading…
Reference in a new issue