fix: correct date (#2367)
rafael_xmr committed
Jul 10, 2025 at 10:06 UTC
15491e8c61ffb6bc399d5f31546e72e002571ca7
1 file changed
+46
-205
cw_bitcoin/lib/electrum_wallet.dart
+46
-205
@@ -370,6 +370,7 @@ abstract class ElectrumWalletBase
370
existingTxInfo.amount = tx.amount;
371
existingTxInfo.confirmations = tx.confirmations;
372
existingTxInfo.height = tx.height;
373
+ existingTxInfo.date = tx.date;
374
375
final newUnspents = tx.unspents!
376
.where((unspent) => !(existingTxInfo.unspents?.any((element) =>
@@ -1879,20 +1880,24 @@ abstract class ElectrumWalletBase
1880
1881
if (height != null && height > 0 && await checkIfMempoolAPIIsEnabled()) {
1882
try {
1882
- final blockHash = await ProxyWrapper().get(
1883
- clearnetUri: Uri.parse(
1884
- "https://mempool.cakewallet.com/api/v1/block-height/$height",
1885
- ),
1886
- ).timeout(Duration(seconds: 15));
1883
+ final blockHash = await ProxyWrapper()
1884
+ .get(
1885
+ clearnetUri: Uri.parse(
1886
+ "https://mempool.cakewallet.com/api/v1/block-height/$height",
1887
+ ),
1888
+ )
1889
+ .timeout(Duration(seconds: 15));
1890
1891
if (blockHash.statusCode == 200 &&
1892
blockHash.body.isNotEmpty &&
1893
jsonDecode(blockHash.body) != null) {
1891
- final blockResponse = await ProxyWrapper().get(
1892
- clearnetUri: Uri.parse(
1893
- "https://mempool.cakewallet.com/api/v1/block/${blockHash.body}",
1894
- ),
1895
- ).timeout(Duration(seconds: 15));
1894
+ final blockResponse = await ProxyWrapper()
1895
+ .get(
1896
+ clearnetUri: Uri.parse(
1897
+ "https://mempool.cakewallet.com/api/v1/block/${blockHash.body}",
1898
+ ),
1899
+ )
1900
+ .timeout(Duration(seconds: 15));
1901
if (blockResponse.statusCode == 200 &&
1902
blockResponse.body.isNotEmpty &&
1903
jsonDecode(blockResponse.body)['timestamp'] != null) {
@@ -2614,7 +2619,7 @@ Future<void> _handleScanSilentPayments(ScanData scanData) async {
2619
2620
var _scanningStream = await scanningClient.subscribe(req);
2621
2617
- void listenFn(Map<String, dynamic> event, ElectrumTweaksSubscribe req) {
2622
+ void listenFn(Map<String, dynamic> event, ElectrumTweaksSubscribe req) async {
2623
final response = req.onResponse(event);
2624
2625
if (response == null || _scanningStream == null) {
@@ -2695,6 +2700,35 @@ Future<void> _handleScanSilentPayments(ScanData scanData) async {
2700
continue;
2701
}
2702
2703
+ var txDate = DateTime.now();
2704
+ bool isDateNow = true;
2705
+
2706
+ final tweakBlockHash = await ProxyWrapper()
2707
+ .get(
2708
+ clearnetUri: Uri.parse(
2709
+ "https://mempool.cakewallet.com/api/v1/block-height/$tweakHeight",
2710
+ ),
2711
+ )
2712
+ .timeout(Duration(seconds: 15));
2713
+ final blockResponse = await ProxyWrapper()
2714
+ .get(
2715
+ clearnetUri: Uri.parse(
2716
+ "https://mempool.cakewallet.com/api/v1/block/${tweakBlockHash.body}",
2717
+ ),
2718
+ )
2719
+ .timeout(Duration(seconds: 15));
2720
+
2721
+ if (blockResponse.statusCode == 200 &&
2722
+ blockResponse.body.isNotEmpty &&
2723
+ jsonDecode(blockResponse.body)['timestamp'] != null) {
2724
+ try {
2725
+ txDate = DateTime.fromMillisecondsSinceEpoch(
2726
+ int.parse(jsonDecode(blockResponse.body)['timestamp'].toString()) * 1000,
2727
+ );
2728
+ isDateNow = false;
2729
+ } catch (_) {}
2730
+ }
2731
+
2732
// initial placeholder ElectrumTransactionInfo object to update values based on new scanned unspent(s) on the following loop
2733
final txInfo = ElectrumTransactionInfo(
2734
WalletType.bitcoin,
@@ -2706,7 +2740,7 @@ Future<void> _handleScanSilentPayments(ScanData scanData) async {
2740
isReplaced: false,
2741
// TODO: fetch block data and get the date from it
2742
date: scanData.network == BitcoinNetwork.mainnet
2709
- ? getDateByBitcoinHeight(tweakHeight)
2743
+ ? (isDateNow ? getDateByBitcoinHeight(tweakHeight) : txDate)
2744
: DateTime.now(),
2745
confirmations: scanData.chainTip - tweakHeight + 1,
2746
isReceivedSilentPayment: true,
@@ -2803,199 +2837,6 @@ Future<void> _handleScanSilentPayments(ScanData scanData) async {
2837
}
2838
}
2839
2806
-Future<void> startRefresh(ScanData scanData) async {
2807
- int syncHeight = scanData.height;
2808
- int initialSyncHeight = syncHeight;
2809
-
2810
- BehaviorSubject<Object>? tweaksSubscription = null;
2811
-
2812
- final electrumClient = scanData.electrumClient;
2813
- await electrumClient.connectToUri(
2814
- scanData.node?.uri ?? Uri.parse("tcp://electrs.cakewallet.com:50001"),
2815
- useSSL: scanData.node?.useSSL ?? false,
2816
- );
2817
-
2818
- int getCountToScanPerRequest(int syncHeight) {
2819
- if (scanData.isSingleScan) {
2820
- return 1;
2821
- }
2822
-
2823
- final amountLeft = scanData.chainTip - syncHeight + 1;
2824
- return amountLeft;
2825
- }
2826
-
2827
- if (tweaksSubscription == null) {
2828
- final receiver = Receiver(
2829
- scanData.silentAddress.b_scan.toHex(),
2830
- scanData.silentAddress.B_spend.toHex(),
2831
- scanData.network == BitcoinNetwork.testnet,
2832
- scanData.labelIndexes,
2833
- scanData.labelIndexes.length,
2834
- );
2835
-
2836
- // Initial status UI update, send how many blocks in total to scan
2837
- final initialCount = getCountToScanPerRequest(syncHeight);
2838
- scanData.sendPort.send(SyncResponse(syncHeight, StartingScanSyncStatus(syncHeight)));
2839
-
2840
- tweaksSubscription = await electrumClient.tweaksSubscribe(
2841
- height: syncHeight,
2842
- count: initialCount,
2843
- );
2844
-
2845
- Future<void> listenFn(t) async {
2846
- final tweaks = t as Map<String, dynamic>;
2847
- final msg = tweaks["message"];
2848
-
2849
- // is success or error msg
2850
- final noData = msg != null;
2851
-
2852
- if (noData) {
2853
- if (scanData.isSingleScan) {
2854
- return;
2855
- }
2856
-
2857
- // re-subscribe to continue receiving messages, starting from the next unscanned height
2858
- final nextHeight = syncHeight + 1;
2859
-
2860
- if (nextHeight <= scanData.chainTip) {
2861
- final nextStream = electrumClient.tweaksSubscribe(
2862
- height: nextHeight,
2863
- count: getCountToScanPerRequest(nextHeight),
2864
- );
2865
- nextStream?.listen(listenFn);
2866
- }
2867
-
2868
- return;
2869
- }
2870
-
2871
- // Continuous status UI update, send how many blocks left to scan
2872
- final syncingStatus = scanData.isSingleScan
2873
- ? SyncingSyncStatus(1, 0)
2874
- : SyncingSyncStatus.fromHeightValues(scanData.chainTip, initialSyncHeight, syncHeight);
2875
- scanData.sendPort.send(SyncResponse(syncHeight, syncingStatus));
2876
-
2877
- final blockHeight = tweaks.keys.first;
2878
- final tweakHeight = int.parse(blockHeight);
2879
-
2880
- try {
2881
- final blockTweaks = tweaks[blockHeight] as Map<String, dynamic>;
2882
-
2883
- for (var j = 0; j < blockTweaks.keys.length; j++) {
2884
- final txid = blockTweaks.keys.elementAt(j);
2885
- final details = blockTweaks[txid] as Map<String, dynamic>;
2886
- final outputPubkeys = (details["output_pubkeys"] as Map<dynamic, dynamic>);
2887
- final tweak = details["tweak"].toString();
2888
-
2889
- try {
2890
- // scanOutputs called from rust here
2891
- final addToWallet = scanOutputs(
2892
- outputPubkeys.values.toList(),
2893
- tweak,
2894
- receiver,
2895
- );
2896
-
2897
- if (addToWallet.isEmpty) {
2898
- // no results tx, continue to next tx
2899
- continue;
2900
- }
2901
-
2902
- // placeholder ElectrumTransactionInfo object to update values based on new scanned unspent(s)
2903
- final txInfo = ElectrumTransactionInfo(
2904
- WalletType.bitcoin,
2905
- id: txid,
2906
- height: tweakHeight,
2907
- amount: 0,
2908
- fee: 0,
2909
- direction: TransactionDirection.incoming,
2910
- isPending: false,
2911
- isReplaced: false,
2912
- date: scanData.network == BitcoinNetwork.mainnet
2913
- ? getDateByBitcoinHeight(tweakHeight)
2914
- : DateTime.now(),
2915
- confirmations: scanData.chainTip - tweakHeight + 1,
2916
- unspents: [],
2917
- isReceivedSilentPayment: true,
2918
- );
2919
-
2920
- addToWallet.forEach((label, value) {
2921
- (value as Map<String, dynamic>).forEach((output, tweak) {
2922
- final t_k = tweak.toString();
2923
-
2924
- final receivingOutputAddress = ECPublic.fromHex(output)
2925
- .toTaprootAddress(tweak: false)
2926
- .toAddress(scanData.network);
2927
-
2928
- int? amount;
2929
- int? pos;
2930
- outputPubkeys.entries.firstWhere((k) {
2931
- final isMatchingOutput = k.value[0] == output;
2932
- if (isMatchingOutput) {
2933
- amount = int.parse(k.value[1].toString());
2934
- pos = int.parse(k.key.toString());
2935
- return true;
2936
- }
2937
- return false;
2938
- });
2939
-
2940
- final receivedAddressRecord = BitcoinSilentPaymentAddressRecord(
2941
- receivingOutputAddress,
2942
- index: 0,
2943
- isHidden: false,
2944
- isUsed: true,
2945
- network: scanData.network,
2946
- silentPaymentTweak: t_k,
2947
- type: SegwitAddresType.p2tr,
2948
- txCount: 1,
2949
- balance: amount!,
2950
- );
2951
-
2952
- final unspent = BitcoinSilentPaymentsUnspent(
2953
- receivedAddressRecord,
2954
- txid,
2955
- amount!,
2956
- pos!,
2957
- silentPaymentTweak: t_k,
2958
- silentPaymentLabel: label == "None" ? null : label,
2959
- );
2960
-
2961
- txInfo.unspents!.add(unspent);
2962
- txInfo.amount += unspent.value;
2963
- });
2964
- });
2965
-
2966
- scanData.sendPort.send({txInfo.id: txInfo});
2967
- } catch (_) {}
2968
- }
2969
- } catch (_) {}
2970
-
2971
- syncHeight = tweakHeight;
2972
-
2973
- if (tweakHeight >= scanData.chainTip || scanData.isSingleScan) {
2974
- if (tweakHeight >= scanData.chainTip)
2975
- scanData.sendPort.send(SyncResponse(
2976
- syncHeight,
2977
- SyncedTipSyncStatus(scanData.chainTip),
2978
- ));
2979
-
2980
- if (scanData.isSingleScan) {
2981
- scanData.sendPort.send(SyncResponse(syncHeight, SyncedSyncStatus()));
2982
- }
2983
-
2984
- await tweaksSubscription!.close();
2985
- await electrumClient.close();
2986
- }
2987
- }
2988
-
2989
- tweaksSubscription?.listen(listenFn);
2990
- }
2991
-
2992
- if (tweaksSubscription == null) {
2993
- return scanData.sendPort.send(
2994
- SyncResponse(syncHeight, UnsupportedSyncStatus()),
2995
- );
2996
- }
2997
-}
2998
-
2840
class EstimatedTxResult {
2841
EstimatedTxResult({
2842
required this.utxos,