From 9aa5ef83316d20f51479b3f66e947490e98a84a0 Mon Sep 17 00:00:00 2001
From: Hector Chu <hectorchu@gmail.com>
Date: Mon, 22 Apr 2024 17:18:18 +0100
Subject: [PATCH] Show utxos in tx list

---
 cw_bitcoin/lib/electrum.dart        |  9 +++++++--
 cw_bitcoin/lib/litecoin_wallet.dart | 31 +++++++++++++++++++++++++++--
 2 files changed, 36 insertions(+), 4 deletions(-)

diff --git a/cw_bitcoin/lib/electrum.dart b/cw_bitcoin/lib/electrum.dart
index 0553170cc..359f9b36d 100644
--- a/cw_bitcoin/lib/electrum.dart
+++ b/cw_bitcoin/lib/electrum.dart
@@ -2,6 +2,7 @@ import 'dart:async';
 import 'dart:convert';
 import 'dart:io';
 import 'dart:typed_data';
+import 'package:convert/convert.dart';
 import 'package:bitcoin_base/bitcoin_base.dart';
 import 'package:cw_bitcoin/bitcoin_amount_format.dart';
 import 'package:cw_bitcoin/script_hash.dart';
@@ -263,8 +264,12 @@ class ElectrumClient {
       await call(method: 'blockchain.transaction.get_merkle', params: [hash, height])
           as Map<String, dynamic>;
 
-  Future<Map<String, dynamic>> getHeader({required int height}) async =>
-      await call(method: 'blockchain.block.get_header', params: [height]) as Map<String, dynamic>;
+  Future<DateTime> getBlockTime({required int height}) async {
+    final header = await call(method: 'blockchain.block.header', params: [height]) as String;
+    final bd = ByteData.sublistView(Uint8List.fromList(hex.decode(header)));
+    final timestamp = bd.getUint32(68, Endian.little) * 1000;
+    return DateTime.fromMillisecondsSinceEpoch(timestamp, isUtc: true);
+  }
 
   Future<double> estimatefee({required int p}) =>
       call(method: 'blockchain.estimatefee', params: [p]).then((dynamic result) {
diff --git a/cw_bitcoin/lib/litecoin_wallet.dart b/cw_bitcoin/lib/litecoin_wallet.dart
index 1608a3dba..e71a68dee 100644
--- a/cw_bitcoin/lib/litecoin_wallet.dart
+++ b/cw_bitcoin/lib/litecoin_wallet.dart
@@ -1,9 +1,12 @@
 import 'dart:async';
+import 'package:convert/convert.dart';
 import 'package:bitcoin_base/bitcoin_base.dart';
 import 'package:cw_bitcoin/bitcoin_mnemonic.dart';
 import 'package:cw_bitcoin/bitcoin_transaction_priority.dart';
+import 'package:cw_bitcoin/electrum_transaction_info.dart';
 import 'package:cw_core/crypto_currency.dart';
 import 'package:cw_core/sync_status.dart';
+import 'package:cw_core/transaction_direction.dart';
 import 'package:cw_core/unspent_coins_info.dart';
 import 'package:cw_bitcoin/litecoin_wallet_addresses.dart';
 import 'package:cw_core/transaction_priority.dart';
@@ -11,6 +14,7 @@ import 'package:flutter/foundation.dart';
 import 'package:hive/hive.dart';
 import 'package:mobx/mobx.dart';
 import 'package:cw_core/wallet_info.dart';
+import 'package:cw_core/wallet_type.dart';
 import 'package:cw_bitcoin/electrum_wallet_snapshot.dart';
 import 'package:cw_bitcoin/electrum_wallet.dart';
 import 'package:cw_bitcoin/bitcoin_address_record.dart';
@@ -36,7 +40,9 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
     ElectrumBalance? initialBalance,
     Map<String, int>? initialRegularAddressIndex,
     Map<String, int>? initialChangeAddressIndex,
-  }) : super(
+  }) : mwebHd = bitcoin.HDWallet.fromSeed(seedBytes,
+            network: litecoinNetwork).derivePath("m/1000'"),
+       super(
             mnemonic: mnemonic,
             password: password,
             walletInfo: walletInfo,
@@ -54,7 +60,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
       initialChangeAddressIndex: initialChangeAddressIndex,
       mainHd: hd,
       sideHd: bitcoin.HDWallet.fromSeed(seedBytes, network: networkType).derivePath("m/0'/1"),
-      mwebHd: bitcoin.HDWallet.fromSeed(seedBytes, network: networkType).derivePath("m/1000'"),
+      mwebHd: mwebHd,
       network: network,
     );
     autorun((_) {
@@ -62,6 +68,8 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
     });
   }
 
+  final bitcoin.HDWallet mwebHd;
+
   static Future<LitecoinWallet> create(
       {required String mnemonic,
       required String password,
@@ -129,6 +137,25 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
           syncStatus = SyncedSyncStatus();
         }
       });
+    final scanSecret = mwebHd.derive(0x80000000).privKey!;
+    final req = UtxosRequest(scanSecret: hex.decode(scanSecret));
+    await for (var utxo in stub.utxos(req)) {
+      final status = await stub.status(StatusRequest());
+      var date = DateTime.now();
+      var confirmations = 0;
+      if (utxo.height > 0) {
+        date = await electrumClient.getBlockTime(height: utxo.height);
+        confirmations = status.blockHeaderHeight - utxo.height + 1;
+      }
+      final tx = ElectrumTransactionInfo(WalletType.litecoin,
+        id: utxo.outputId, height: utxo.height,
+        amount: utxo.value.toInt(),
+        direction: TransactionDirection.incoming,
+        isPending: utxo.height == 0,
+        date: date, confirmations: confirmations);
+      transactionHistory.addOne(tx);
+      await transactionHistory.save();
+    }
   }
 
   @override