mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-06-29 04:49:51 +00:00
apply some changes from SP Fix pr
This commit is contained in:
parent
d2f0a97764
commit
46c1d6fd8d
6 changed files with 286 additions and 47 deletions
|
@ -4,9 +4,7 @@ import 'dart:io';
|
||||||
import 'dart:isolate';
|
import 'dart:isolate';
|
||||||
|
|
||||||
import 'package:bitcoin_base/bitcoin_base.dart';
|
import 'package:bitcoin_base/bitcoin_base.dart';
|
||||||
import 'package:cw_core/utils/proxy_wrapper.dart';
|
|
||||||
import 'package:cw_bitcoin/bitcoin_amount_format.dart';
|
import 'package:cw_bitcoin/bitcoin_amount_format.dart';
|
||||||
import 'package:cw_core/format_amount.dart';
|
|
||||||
import 'package:cw_core/utils/print_verbose.dart';
|
import 'package:cw_core/utils/print_verbose.dart';
|
||||||
import 'package:cw_bitcoin/bitcoin_wallet.dart';
|
import 'package:cw_bitcoin/bitcoin_wallet.dart';
|
||||||
import 'package:cw_bitcoin/litecoin_wallet.dart';
|
import 'package:cw_bitcoin/litecoin_wallet.dart';
|
||||||
|
@ -19,7 +17,7 @@ import 'package:cw_bitcoin/bitcoin_transaction_credentials.dart';
|
||||||
import 'package:cw_bitcoin/bitcoin_transaction_priority.dart';
|
import 'package:cw_bitcoin/bitcoin_transaction_priority.dart';
|
||||||
import 'package:cw_bitcoin/bitcoin_unspent.dart';
|
import 'package:cw_bitcoin/bitcoin_unspent.dart';
|
||||||
import 'package:cw_bitcoin/bitcoin_wallet_keys.dart';
|
import 'package:cw_bitcoin/bitcoin_wallet_keys.dart';
|
||||||
import 'package:cw_bitcoin/electrum.dart';
|
import 'package:cw_bitcoin/electrum.dart' as electrum;
|
||||||
import 'package:cw_bitcoin/electrum_balance.dart';
|
import 'package:cw_bitcoin/electrum_balance.dart';
|
||||||
import 'package:cw_bitcoin/electrum_derivations.dart';
|
import 'package:cw_bitcoin/electrum_derivations.dart';
|
||||||
import 'package:cw_bitcoin/electrum_transaction_history.dart';
|
import 'package:cw_bitcoin/electrum_transaction_history.dart';
|
||||||
|
@ -50,6 +48,7 @@ import 'package:mobx/mobx.dart';
|
||||||
import 'package:rxdart/subjects.dart';
|
import 'package:rxdart/subjects.dart';
|
||||||
import 'package:sp_scanner/sp_scanner.dart';
|
import 'package:sp_scanner/sp_scanner.dart';
|
||||||
import 'package:hex/hex.dart';
|
import 'package:hex/hex.dart';
|
||||||
|
import 'package:http/http.dart' as http;
|
||||||
|
|
||||||
part 'electrum_wallet.g.dart';
|
part 'electrum_wallet.g.dart';
|
||||||
|
|
||||||
|
@ -69,7 +68,7 @@ abstract class ElectrumWalletBase
|
||||||
Uint8List? seedBytes,
|
Uint8List? seedBytes,
|
||||||
this.passphrase,
|
this.passphrase,
|
||||||
List<BitcoinAddressRecord>? initialAddresses,
|
List<BitcoinAddressRecord>? initialAddresses,
|
||||||
ElectrumClient? electrumClient,
|
electrum.ElectrumClient? electrumClient,
|
||||||
ElectrumBalance? initialBalance,
|
ElectrumBalance? initialBalance,
|
||||||
CryptoCurrency? currency,
|
CryptoCurrency? currency,
|
||||||
this.alwaysScan,
|
this.alwaysScan,
|
||||||
|
@ -96,7 +95,7 @@ abstract class ElectrumWalletBase
|
||||||
this.isTestnet = !network.isMainnet,
|
this.isTestnet = !network.isMainnet,
|
||||||
this._mnemonic = mnemonic,
|
this._mnemonic = mnemonic,
|
||||||
super(walletInfo) {
|
super(walletInfo) {
|
||||||
this.electrumClient = electrumClient ?? ElectrumClient();
|
this.electrumClient = electrumClient ?? electrum.ElectrumClient();
|
||||||
this.walletInfo = walletInfo;
|
this.walletInfo = walletInfo;
|
||||||
transactionHistory = ElectrumTransactionHistory(
|
transactionHistory = ElectrumTransactionHistory(
|
||||||
walletInfo: walletInfo,
|
walletInfo: walletInfo,
|
||||||
|
@ -167,7 +166,7 @@ abstract class ElectrumWalletBase
|
||||||
@observable
|
@observable
|
||||||
bool isEnabledAutoGenerateSubaddress;
|
bool isEnabledAutoGenerateSubaddress;
|
||||||
|
|
||||||
late ElectrumClient electrumClient;
|
late electrum.ElectrumClient electrumClient;
|
||||||
Box<UnspentCoinsInfo> unspentCoinsInfo;
|
Box<UnspentCoinsInfo> unspentCoinsInfo;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -333,14 +332,14 @@ abstract class ElectrumWalletBase
|
||||||
|
|
||||||
final receivePort = ReceivePort();
|
final receivePort = ReceivePort();
|
||||||
_isolate = Isolate.spawn(
|
_isolate = Isolate.spawn(
|
||||||
startRefresh,
|
_handleScanSilentPayments,
|
||||||
ScanData(
|
ScanData(
|
||||||
sendPort: receivePort.sendPort,
|
sendPort: receivePort.sendPort,
|
||||||
silentAddress: walletAddresses.silentAddress!,
|
silentAddress: walletAddresses.silentAddress!,
|
||||||
network: network,
|
network: network,
|
||||||
height: height,
|
height: height,
|
||||||
chainTip: chainTip,
|
chainTip: chainTip,
|
||||||
electrumClient: ElectrumClient(),
|
electrumClient: electrum.ElectrumClient(),
|
||||||
transactionHistoryIds: transactionHistory.transactions.keys.toList(),
|
transactionHistoryIds: transactionHistory.transactions.keys.toList(),
|
||||||
node: (await getNodeSupportsSilentPayments()) == true
|
node: (await getNodeSupportsSilentPayments()) == true
|
||||||
? ScanNode(node!.uri, node!.useSSL)
|
? ScanNode(node!.uri, node!.useSSL)
|
||||||
|
@ -492,9 +491,10 @@ abstract class ElectrumWalletBase
|
||||||
Future<void> updateFeeRates() async {
|
Future<void> updateFeeRates() async {
|
||||||
if (await checkIfMempoolAPIIsEnabled() && type == WalletType.bitcoin) {
|
if (await checkIfMempoolAPIIsEnabled() && type == WalletType.bitcoin) {
|
||||||
try {
|
try {
|
||||||
final response = await ProxyWrapper()
|
final response = await http
|
||||||
.get(clearnetUri: Uri.parse("https://mempool.cakewallet.com/api/v1/fees/recommended"))
|
.get(Uri.parse("https://mempool.cakewallet.com/api/v1/fees/recommended"))
|
||||||
.timeout(Duration(seconds: 15));
|
.timeout(Duration(seconds: 5));
|
||||||
|
|
||||||
final result = json.decode(response.body) as Map<String, dynamic>;
|
final result = json.decode(response.body) as Map<String, dynamic>;
|
||||||
final slowFee = (result['economyFee'] as num?)?.toInt() ?? 0;
|
final slowFee = (result['economyFee'] as num?)?.toInt() ?? 0;
|
||||||
int mediumFee = (result['hourFee'] as num?)?.toInt() ?? 0;
|
int mediumFee = (result['hourFee'] as num?)?.toInt() ?? 0;
|
||||||
|
@ -562,7 +562,7 @@ abstract class ElectrumWalletBase
|
||||||
node!.save();
|
node!.save();
|
||||||
return node!.supportsSilentPayments!;
|
return node!.supportsSilentPayments!;
|
||||||
}
|
}
|
||||||
} on RequestFailedTimeoutException catch (_) {
|
} on electrum.RequestFailedTimeoutException catch (_) {
|
||||||
node!.supportsSilentPayments = false;
|
node!.supportsSilentPayments = false;
|
||||||
node!.save();
|
node!.save();
|
||||||
return node!.supportsSilentPayments!;
|
return node!.supportsSilentPayments!;
|
||||||
|
@ -1876,17 +1876,20 @@ abstract class ElectrumWalletBase
|
||||||
|
|
||||||
if (height != null && height > 0 && await checkIfMempoolAPIIsEnabled()) {
|
if (height != null && height > 0 && await checkIfMempoolAPIIsEnabled()) {
|
||||||
try {
|
try {
|
||||||
final blockHash = await ProxyWrapper()
|
final blockHash = await http.get(
|
||||||
.get(clearnetUri: Uri.parse("https://mempool.cakewallet.com/api/v1/block-height/$height"))
|
Uri.parse(
|
||||||
.timeout(Duration(seconds: 15));
|
"https://mempool.cakewallet.com/api/v1/block-height/$height",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
if (blockHash.statusCode == 200 &&
|
if (blockHash.statusCode == 200 &&
|
||||||
blockHash.body.isNotEmpty &&
|
blockHash.body.isNotEmpty &&
|
||||||
jsonDecode(blockHash.body) != null) {
|
jsonDecode(blockHash.body) != null) {
|
||||||
final blockResponse = await ProxyWrapper()
|
final blockResponse = await http.get(
|
||||||
.get(clearnetUri: Uri.parse("https://mempool.cakewallet.com/api/v1/block/${blockHash}"))
|
Uri.parse(
|
||||||
.timeout(Duration(seconds: 15));
|
"https://mempool.cakewallet.com/api/v1/block/${blockHash.body}",
|
||||||
|
),
|
||||||
|
);
|
||||||
if (blockResponse.statusCode == 200 &&
|
if (blockResponse.statusCode == 200 &&
|
||||||
blockResponse.body.isNotEmpty &&
|
blockResponse.body.isNotEmpty &&
|
||||||
jsonDecode(blockResponse.body)['timestamp'] != null) {
|
jsonDecode(blockResponse.body)['timestamp'] != null) {
|
||||||
|
@ -2389,9 +2392,9 @@ abstract class ElectrumWalletBase
|
||||||
derivationPath.substring(0, derivationPath.lastIndexOf("'") + 1);
|
derivationPath.substring(0, derivationPath.lastIndexOf("'") + 1);
|
||||||
|
|
||||||
@action
|
@action
|
||||||
void _onConnectionStatusChange(ConnectionStatus status) {
|
void _onConnectionStatusChange(electrum.ConnectionStatus status) {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case ConnectionStatus.connected:
|
case electrum.ConnectionStatus.connected:
|
||||||
if (syncStatus is NotConnectedSyncStatus ||
|
if (syncStatus is NotConnectedSyncStatus ||
|
||||||
syncStatus is LostConnectionSyncStatus ||
|
syncStatus is LostConnectionSyncStatus ||
|
||||||
syncStatus is ConnectingSyncStatus) {
|
syncStatus is ConnectingSyncStatus) {
|
||||||
|
@ -2399,19 +2402,19 @@ abstract class ElectrumWalletBase
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ConnectionStatus.disconnected:
|
case electrum.ConnectionStatus.disconnected:
|
||||||
if (syncStatus is! NotConnectedSyncStatus &&
|
if (syncStatus is! NotConnectedSyncStatus &&
|
||||||
syncStatus is! ConnectingSyncStatus &&
|
syncStatus is! ConnectingSyncStatus &&
|
||||||
syncStatus is! SyncronizingSyncStatus) {
|
syncStatus is! SyncronizingSyncStatus) {
|
||||||
syncStatus = NotConnectedSyncStatus();
|
syncStatus = NotConnectedSyncStatus();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ConnectionStatus.failed:
|
case electrum.ConnectionStatus.failed:
|
||||||
if (syncStatus is! LostConnectionSyncStatus) {
|
if (syncStatus is! LostConnectionSyncStatus) {
|
||||||
syncStatus = LostConnectionSyncStatus();
|
syncStatus = LostConnectionSyncStatus();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ConnectionStatus.connecting:
|
case electrum.ConnectionStatus.connecting:
|
||||||
if (syncStatus is! ConnectingSyncStatus) {
|
if (syncStatus is! ConnectingSyncStatus) {
|
||||||
syncStatus = ConnectingSyncStatus();
|
syncStatus = ConnectingSyncStatus();
|
||||||
}
|
}
|
||||||
|
@ -2523,7 +2526,7 @@ class ScanData {
|
||||||
final ScanNode? node;
|
final ScanNode? node;
|
||||||
final BasedUtxoNetwork network;
|
final BasedUtxoNetwork network;
|
||||||
final int chainTip;
|
final int chainTip;
|
||||||
final ElectrumClient electrumClient;
|
final electrum.ElectrumClient electrumClient;
|
||||||
final List<String> transactionHistoryIds;
|
final List<String> transactionHistoryIds;
|
||||||
final Map<String, String> labels;
|
final Map<String, String> labels;
|
||||||
final List<int> labelIndexes;
|
final List<int> labelIndexes;
|
||||||
|
@ -2567,6 +2570,235 @@ class SyncResponse {
|
||||||
SyncResponse(this.height, this.syncStatus);
|
SyncResponse(this.height, this.syncStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _handleScanSilentPayments(ScanData scanData) async {
|
||||||
|
try {
|
||||||
|
// if (scanData.shouldSwitchNodes) {
|
||||||
|
var scanningClient = await ElectrumProvider.connect(
|
||||||
|
ElectrumTCPService.connect(
|
||||||
|
Uri.parse("tcp://electrs.cakewallet.com:50001"),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
// }
|
||||||
|
|
||||||
|
int syncHeight = scanData.height;
|
||||||
|
int initialSyncHeight = syncHeight;
|
||||||
|
|
||||||
|
final receiver = Receiver(
|
||||||
|
scanData.silentAddress.b_scan.toHex(),
|
||||||
|
scanData.silentAddress.B_spend.toHex(),
|
||||||
|
scanData.network == BitcoinNetwork.testnet,
|
||||||
|
scanData.labelIndexes,
|
||||||
|
scanData.labelIndexes.length,
|
||||||
|
);
|
||||||
|
|
||||||
|
int getCountToScanPerRequest(int syncHeight) {
|
||||||
|
if (scanData.isSingleScan) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
final amountLeft = scanData.chainTip - syncHeight + 1;
|
||||||
|
return amountLeft;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initial status UI update, send how many blocks in total to scan
|
||||||
|
scanData.sendPort.send(SyncResponse(syncHeight, StartingScanSyncStatus(syncHeight)));
|
||||||
|
|
||||||
|
final req = ElectrumTweaksSubscribe(
|
||||||
|
height: syncHeight,
|
||||||
|
count: getCountToScanPerRequest(syncHeight),
|
||||||
|
historicalMode: false,
|
||||||
|
);
|
||||||
|
|
||||||
|
var _scanningStream = await scanningClient.subscribe(req);
|
||||||
|
|
||||||
|
void listenFn(Map<String, dynamic> event, ElectrumTweaksSubscribe req) {
|
||||||
|
final response = req.onResponse(event);
|
||||||
|
|
||||||
|
if (response == null || _scanningStream == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// is success or error msg
|
||||||
|
final noData = response.message != null;
|
||||||
|
|
||||||
|
if (noData) {
|
||||||
|
if (scanData.isSingleScan) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// re-subscribe to continue receiving messages, starting from the next unscanned height
|
||||||
|
final nextHeight = syncHeight + 1;
|
||||||
|
|
||||||
|
if (nextHeight <= scanData.chainTip) {
|
||||||
|
final nextStream = scanningClient.subscribe(
|
||||||
|
ElectrumTweaksSubscribe(
|
||||||
|
height: nextHeight,
|
||||||
|
count: getCountToScanPerRequest(nextHeight),
|
||||||
|
historicalMode: false,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (nextStream != null) {
|
||||||
|
nextStream.listen((event) => listenFn(event, req));
|
||||||
|
} else {
|
||||||
|
scanData.sendPort.send(
|
||||||
|
SyncResponse(scanData.height, LostConnectionSyncStatus()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final tweakHeight = response.block;
|
||||||
|
|
||||||
|
if (initialSyncHeight < tweakHeight) initialSyncHeight = tweakHeight;
|
||||||
|
|
||||||
|
// Continuous status UI update, send how many blocks left to scan
|
||||||
|
final syncingStatus = scanData.isSingleScan
|
||||||
|
? SyncingSyncStatus(1, 0)
|
||||||
|
: SyncingSyncStatus.fromHeightValues(scanData.chainTip, initialSyncHeight, tweakHeight);
|
||||||
|
|
||||||
|
scanData.sendPort.send(SyncResponse(syncHeight, syncingStatus));
|
||||||
|
|
||||||
|
try {
|
||||||
|
final blockTweaks = response.blockTweaks;
|
||||||
|
|
||||||
|
for (final txid in blockTweaks.keys) {
|
||||||
|
final tweakData = blockTweaks[txid];
|
||||||
|
final outputPubkeys = tweakData!.outputPubkeys;
|
||||||
|
final tweak = tweakData.tweak;
|
||||||
|
|
||||||
|
try {
|
||||||
|
final addToWallet = {};
|
||||||
|
|
||||||
|
// receivers.forEach((receiver) {
|
||||||
|
// NOTE: scanOutputs, from sp_scanner package, called from rust here
|
||||||
|
final scanResult = scanOutputs([outputPubkeys.keys.toList()], tweak, receiver);
|
||||||
|
|
||||||
|
if (scanResult.isEmpty) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addToWallet[receiver.BSpend] == null) {
|
||||||
|
addToWallet[receiver.BSpend] = scanResult;
|
||||||
|
} else {
|
||||||
|
addToWallet[receiver.BSpend].addAll(scanResult);
|
||||||
|
}
|
||||||
|
// });
|
||||||
|
|
||||||
|
if (addToWallet.isEmpty) {
|
||||||
|
// no results tx, continue to next tx
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// initial placeholder ElectrumTransactionInfo object to update values based on new scanned unspent(s) on the following loop
|
||||||
|
final txInfo = ElectrumTransactionInfo(
|
||||||
|
WalletType.bitcoin,
|
||||||
|
id: txid,
|
||||||
|
height: tweakHeight,
|
||||||
|
amount: 0,
|
||||||
|
fee: 0,
|
||||||
|
direction: TransactionDirection.incoming,
|
||||||
|
isReplaced: false,
|
||||||
|
date: DateTime.fromMillisecondsSinceEpoch(
|
||||||
|
DateTime.now().millisecondsSinceEpoch * 1000,
|
||||||
|
),
|
||||||
|
confirmations: scanData.chainTip - tweakHeight + 1,
|
||||||
|
isReceivedSilentPayment: true,
|
||||||
|
isPending: false,
|
||||||
|
unspents: [],
|
||||||
|
);
|
||||||
|
|
||||||
|
List<BitcoinUnspent> unspents = [];
|
||||||
|
|
||||||
|
addToWallet.forEach((BSpend, scanResultPerLabel) {
|
||||||
|
scanResultPerLabel.forEach((label, scanOutput) {
|
||||||
|
final labelValue = label == "None" ? null : label.toString();
|
||||||
|
|
||||||
|
(scanOutput as Map<String, dynamic>).forEach((outputPubkey, tweak) {
|
||||||
|
final t_k = tweak as String;
|
||||||
|
|
||||||
|
final receivingOutputAddress = ECPublic.fromHex(outputPubkey)
|
||||||
|
.toTaprootAddress(tweak: false)
|
||||||
|
.toAddress(scanData.network);
|
||||||
|
|
||||||
|
final matchingOutput = outputPubkeys[outputPubkey]!;
|
||||||
|
final amount = matchingOutput.amount;
|
||||||
|
final pos = matchingOutput.vout;
|
||||||
|
|
||||||
|
// final matchingSPWallet = scanData.silentPaymentsWallets.firstWhere(
|
||||||
|
// (receiver) => receiver.B_spend.toHex() == BSpend.toString(),
|
||||||
|
// );
|
||||||
|
|
||||||
|
// final labelIndex = labelValue != null ? scanData.labels[label] : 0;
|
||||||
|
// final balance = ElectrumBalance();
|
||||||
|
// balance.confirmed = amount;
|
||||||
|
|
||||||
|
final receivedAddressRecord = BitcoinSilentPaymentAddressRecord(
|
||||||
|
receivingOutputAddress,
|
||||||
|
index: 0,
|
||||||
|
isHidden: false,
|
||||||
|
isUsed: true,
|
||||||
|
network: scanData.network,
|
||||||
|
silentPaymentTweak: t_k,
|
||||||
|
type: SegwitAddressType.p2tr,
|
||||||
|
txCount: 1,
|
||||||
|
balance: amount,
|
||||||
|
);
|
||||||
|
|
||||||
|
final unspent = BitcoinSilentPaymentsUnspent(
|
||||||
|
receivedAddressRecord,
|
||||||
|
txid,
|
||||||
|
amount,
|
||||||
|
pos,
|
||||||
|
silentPaymentTweak: t_k,
|
||||||
|
silentPaymentLabel: labelValue,
|
||||||
|
);
|
||||||
|
|
||||||
|
unspents.add(unspent);
|
||||||
|
txInfo.unspents!.add(unspent);
|
||||||
|
txInfo.amount += unspent.value;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
scanData.sendPort.send({txInfo.id: txInfo});
|
||||||
|
} catch (e, stacktrace) {
|
||||||
|
printV(stacktrace);
|
||||||
|
printV(e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e, stacktrace) {
|
||||||
|
printV(stacktrace);
|
||||||
|
printV(e.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
syncHeight = tweakHeight;
|
||||||
|
|
||||||
|
if ((tweakHeight >= scanData.chainTip) || scanData.isSingleScan) {
|
||||||
|
if (tweakHeight >= scanData.chainTip)
|
||||||
|
scanData.sendPort.send(
|
||||||
|
SyncResponse(syncHeight, SyncedTipSyncStatus(scanData.chainTip)),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (scanData.isSingleScan) {
|
||||||
|
scanData.sendPort.send(SyncResponse(syncHeight, SyncedSyncStatus()));
|
||||||
|
}
|
||||||
|
|
||||||
|
_scanningStream?.close();
|
||||||
|
_scanningStream = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_scanningStream?.listen((event) => listenFn(event, req));
|
||||||
|
} catch (e) {
|
||||||
|
printV("Error in _handleScanSilentPayments: $e");
|
||||||
|
scanData.sendPort.send(SyncResponse(scanData.height, LostConnectionSyncStatus()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> startRefresh(ScanData scanData) async {
|
Future<void> startRefresh(ScanData scanData) async {
|
||||||
int syncHeight = scanData.height;
|
int syncHeight = scanData.height;
|
||||||
int initialSyncHeight = syncHeight;
|
int initialSyncHeight = syncHeight;
|
||||||
|
@ -2579,7 +2811,7 @@ Future<void> startRefresh(ScanData scanData) async {
|
||||||
useSSL: scanData.node?.useSSL ?? false,
|
useSSL: scanData.node?.useSSL ?? false,
|
||||||
);
|
);
|
||||||
|
|
||||||
int getCountPerRequest(int syncHeight) {
|
int getCountToScanPerRequest(int syncHeight) {
|
||||||
if (scanData.isSingleScan) {
|
if (scanData.isSingleScan) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -2598,7 +2830,7 @@ Future<void> startRefresh(ScanData scanData) async {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Initial status UI update, send how many blocks in total to scan
|
// Initial status UI update, send how many blocks in total to scan
|
||||||
final initialCount = getCountPerRequest(syncHeight);
|
final initialCount = getCountToScanPerRequest(syncHeight);
|
||||||
scanData.sendPort.send(SyncResponse(syncHeight, StartingScanSyncStatus(syncHeight)));
|
scanData.sendPort.send(SyncResponse(syncHeight, StartingScanSyncStatus(syncHeight)));
|
||||||
|
|
||||||
tweaksSubscription = await electrumClient.tweaksSubscribe(
|
tweaksSubscription = await electrumClient.tweaksSubscribe(
|
||||||
|
@ -2609,22 +2841,24 @@ Future<void> startRefresh(ScanData scanData) async {
|
||||||
Future<void> listenFn(t) async {
|
Future<void> listenFn(t) async {
|
||||||
final tweaks = t as Map<String, dynamic>;
|
final tweaks = t as Map<String, dynamic>;
|
||||||
final msg = tweaks["message"];
|
final msg = tweaks["message"];
|
||||||
// success or error msg
|
|
||||||
|
// is success or error msg
|
||||||
final noData = msg != null;
|
final noData = msg != null;
|
||||||
|
|
||||||
if (noData) {
|
if (noData) {
|
||||||
|
if (scanData.isSingleScan) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// re-subscribe to continue receiving messages, starting from the next unscanned height
|
// re-subscribe to continue receiving messages, starting from the next unscanned height
|
||||||
final nextHeight = syncHeight + 1;
|
final nextHeight = syncHeight + 1;
|
||||||
final nextCount = getCountPerRequest(nextHeight);
|
|
||||||
|
|
||||||
if (nextCount > 0) {
|
if (nextHeight <= scanData.chainTip) {
|
||||||
tweaksSubscription?.close();
|
final nextStream = electrumClient.tweaksSubscribe(
|
||||||
|
|
||||||
final nextTweaksSubscription = electrumClient.tweaksSubscribe(
|
|
||||||
height: nextHeight,
|
height: nextHeight,
|
||||||
count: nextCount,
|
count: getCountToScanPerRequest(nextHeight),
|
||||||
);
|
);
|
||||||
nextTweaksSubscription?.listen(listenFn);
|
nextStream?.listen(listenFn);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -3,7 +3,6 @@ import 'dart:io' show Platform;
|
||||||
import 'package:bitcoin_base/bitcoin_base.dart';
|
import 'package:bitcoin_base/bitcoin_base.dart';
|
||||||
import 'package:blockchain_utils/blockchain_utils.dart';
|
import 'package:blockchain_utils/blockchain_utils.dart';
|
||||||
import 'package:cw_bitcoin/bitcoin_address_record.dart';
|
import 'package:cw_bitcoin/bitcoin_address_record.dart';
|
||||||
import 'package:cw_bitcoin/electrum_wallet.dart';
|
|
||||||
import 'package:cw_core/unspent_coin_type.dart';
|
import 'package:cw_core/unspent_coin_type.dart';
|
||||||
import 'package:cw_core/utils/print_verbose.dart';
|
import 'package:cw_core/utils/print_verbose.dart';
|
||||||
import 'package:cw_bitcoin/bitcoin_unspent.dart';
|
import 'package:cw_bitcoin/bitcoin_unspent.dart';
|
||||||
|
@ -71,9 +70,12 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
||||||
super(walletInfo) {
|
super(walletInfo) {
|
||||||
if (masterHd != null) {
|
if (masterHd != null) {
|
||||||
silentAddress = SilentPaymentOwner.fromPrivateKeys(
|
silentAddress = SilentPaymentOwner.fromPrivateKeys(
|
||||||
b_scan: ECPrivate.fromHex(masterHd.derivePath(SCAN_PATH).privateKey.toHex()),
|
b_scan: ECPrivate.fromHex(
|
||||||
b_spend: ECPrivate.fromHex(masterHd.derivePath(SPEND_PATH).privateKey.toHex()),
|
masterHd.derivePath("m/352'/1'/0'/1'/0").privateKey.toHex(),
|
||||||
network: network,
|
),
|
||||||
|
b_spend: ECPrivate.fromHex(
|
||||||
|
masterHd.derivePath("m/352'/1'/0'/0'/0").privateKey.toHex(),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (silentAddresses.length == 0) {
|
if (silentAddresses.length == 0) {
|
||||||
|
@ -109,8 +111,10 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
||||||
final ObservableList<BaseBitcoinAddressRecord> addressesByReceiveType;
|
final ObservableList<BaseBitcoinAddressRecord> addressesByReceiveType;
|
||||||
final ObservableList<BitcoinAddressRecord> receiveAddresses;
|
final ObservableList<BitcoinAddressRecord> receiveAddresses;
|
||||||
final ObservableList<BitcoinAddressRecord> changeAddresses;
|
final ObservableList<BitcoinAddressRecord> changeAddresses;
|
||||||
|
|
||||||
// TODO: add this variable in `bitcoin_wallet_addresses` and just add a cast in cw_bitcoin to use it
|
// TODO: add this variable in `bitcoin_wallet_addresses` and just add a cast in cw_bitcoin to use it
|
||||||
final ObservableList<BitcoinSilentPaymentAddressRecord> silentAddresses;
|
final ObservableList<BitcoinSilentPaymentAddressRecord> silentAddresses;
|
||||||
|
|
||||||
// TODO: add this variable in `litecoin_wallet_addresses` and just add a cast in cw_bitcoin to use it
|
// TODO: add this variable in `litecoin_wallet_addresses` and just add a cast in cw_bitcoin to use it
|
||||||
final ObservableList<BitcoinAddressRecord> mwebAddresses;
|
final ObservableList<BitcoinAddressRecord> mwebAddresses;
|
||||||
final BasedUtxoNetwork network;
|
final BasedUtxoNetwork network;
|
||||||
|
@ -144,12 +148,13 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
||||||
return silentAddress.toString();
|
return silentAddress.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
final typeMatchingAddresses = _addresses.where((addr) => !addr.isHidden && _isAddressPageTypeMatch(addr)).toList();
|
final typeMatchingAddresses =
|
||||||
final typeMatchingReceiveAddresses = typeMatchingAddresses.where((addr) => !addr.isUsed).toList();
|
_addresses.where((addr) => !addr.isHidden && _isAddressPageTypeMatch(addr)).toList();
|
||||||
|
final typeMatchingReceiveAddresses =
|
||||||
|
typeMatchingAddresses.where((addr) => !addr.isUsed).toList();
|
||||||
|
|
||||||
if (!isEnabledAutoGenerateSubaddress) {
|
if (!isEnabledAutoGenerateSubaddress) {
|
||||||
if (previousAddressRecord != null &&
|
if (previousAddressRecord != null && previousAddressRecord!.type == addressPageType) {
|
||||||
previousAddressRecord!.type == addressPageType) {
|
|
||||||
return previousAddressRecord!.address;
|
return previousAddressRecord!.address;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ import 'dart:isolate';
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
|
|
||||||
import 'package:bitcoin_base/bitcoin_base.dart';
|
import 'package:bitcoin_base_old/bitcoin_base.dart';
|
||||||
import 'package:cw_bitcoin/bitcoin_wallet.dart';
|
import 'package:cw_bitcoin/bitcoin_wallet.dart';
|
||||||
import 'package:cw_bitcoin/bitcoin_wallet_addresses.dart';
|
import 'package:cw_bitcoin/bitcoin_wallet_addresses.dart';
|
||||||
import 'package:cw_bitcoin/payjoin/payjoin_persister.dart';
|
import 'package:cw_bitcoin/payjoin/payjoin_persister.dart';
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
|
|
||||||
import 'package:bitcoin_base/bitcoin_base.dart';
|
import 'package:bitcoin_base_old/bitcoin_base.dart';
|
||||||
import 'package:blockchain_utils/blockchain_utils.dart';
|
import 'package:blockchain_utils/blockchain_utils.dart';
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:cw_bitcoin/bitcoin_address_record.dart';
|
import 'package:cw_bitcoin/bitcoin_address_record.dart';
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
|
|
||||||
import 'package:bitcoin_base/bitcoin_base.dart';
|
import 'package:bitcoin_base_old/bitcoin_base.dart';
|
||||||
import 'package:convert/convert.dart';
|
import 'package:convert/convert.dart';
|
||||||
import 'package:cw_core/utils/print_verbose.dart';
|
import 'package:cw_core/utils/print_verbose.dart';
|
||||||
import 'package:ledger_bitcoin/psbt.dart';
|
import 'package:ledger_bitcoin/psbt.dart';
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:bitcoin_base/bitcoin_base.dart';
|
import 'package:bitcoin_base_old/bitcoin_base.dart';
|
||||||
import 'package:blockchain_utils/blockchain_utils.dart';
|
import 'package:blockchain_utils/blockchain_utils.dart';
|
||||||
import 'package:cw_bitcoin/bitcoin_wallet.dart';
|
import 'package:cw_bitcoin/bitcoin_wallet.dart';
|
||||||
import 'package:cw_bitcoin/psbt/v0_deserialize.dart';
|
import 'package:cw_bitcoin/psbt/v0_deserialize.dart';
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue