mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2024-11-17 09:47:35 +00:00
Confirm sent txns
This commit is contained in:
parent
70b07b2d47
commit
b1f0334550
2 changed files with 61 additions and 15 deletions
|
@ -1,5 +1,6 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
import 'package:collection/collection.dart';
|
||||||
import 'package:convert/convert.dart';
|
import 'package:convert/convert.dart';
|
||||||
import 'package:crypto/crypto.dart';
|
import 'package:crypto/crypto.dart';
|
||||||
import 'package:fixnum/fixnum.dart';
|
import 'package:fixnum/fixnum.dart';
|
||||||
|
@ -122,6 +123,8 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int mwebUtxosHeight = 0;
|
||||||
|
|
||||||
@action
|
@action
|
||||||
@override
|
@override
|
||||||
Future<void> startSync() async {
|
Future<void> startSync() async {
|
||||||
|
@ -142,6 +145,10 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
||||||
} else {
|
} else {
|
||||||
syncStatus = SyncedSyncStatus();
|
syncStatus = SyncedSyncStatus();
|
||||||
}
|
}
|
||||||
|
if (resp.mwebUtxosHeight > mwebUtxosHeight) {
|
||||||
|
mwebUtxosHeight = resp.mwebUtxosHeight;
|
||||||
|
await checkMwebUtxosSpent();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
processMwebUtxos();
|
processMwebUtxos();
|
||||||
}
|
}
|
||||||
|
@ -170,14 +177,19 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
||||||
date = DateTime.fromMillisecondsSinceEpoch(utxo.blockTime * 1000);
|
date = DateTime.fromMillisecondsSinceEpoch(utxo.blockTime * 1000);
|
||||||
confirmations = status.blockHeaderHeight - utxo.height + 1;
|
confirmations = status.blockHeaderHeight - utxo.height + 1;
|
||||||
}
|
}
|
||||||
final tx = ElectrumTransactionInfo(WalletType.litecoin,
|
var tx = transactionHistory.transactions.values.firstWhereOrNull(
|
||||||
id: utxo.outputId, height: utxo.height,
|
(tx) => tx.outputAddresses?.contains(utxo.outputId) ?? false);
|
||||||
amount: utxo.value.toInt(), fee: 0,
|
if (tx == null)
|
||||||
direction: TransactionDirection.incoming,
|
tx = ElectrumTransactionInfo(WalletType.litecoin,
|
||||||
isPending: utxo.height == 0,
|
id: utxo.outputId, height: utxo.height,
|
||||||
date: date, confirmations: confirmations,
|
amount: utxo.value.toInt(), fee: 0,
|
||||||
inputAddresses: [],
|
direction: TransactionDirection.incoming,
|
||||||
outputAddresses: [utxo.address]);
|
isPending: utxo.height == 0,
|
||||||
|
date: date, confirmations: confirmations,
|
||||||
|
inputAddresses: [],
|
||||||
|
outputAddresses: [utxo.address]);
|
||||||
|
tx.isPending = utxo.height == 0;
|
||||||
|
tx.confirmations = confirmations;
|
||||||
if (transactionHistory.transactions[utxo.outputId] == null) {
|
if (transactionHistory.transactions[utxo.outputId] == null) {
|
||||||
final addressRecord = walletAddresses.allAddresses.firstWhere(
|
final addressRecord = walletAddresses.allAddresses.firstWhere(
|
||||||
(addressRecord) => addressRecord.address == utxo.address);
|
(addressRecord) => addressRecord.address == utxo.address);
|
||||||
|
@ -194,11 +206,12 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> checkMwebUtxosSpent() async {
|
Future<void> checkMwebUtxosSpent() async {
|
||||||
final List<String> outputIds = [];
|
while ((await Future.wait(transactionHistory.transactions.values
|
||||||
mwebUtxos.forEach((outputId, utxo) {
|
.where((tx) => tx.direction == TransactionDirection.outgoing && tx.isPending)
|
||||||
if (utxo.height > 0)
|
.map(checkPendingTransaction))).any((x) => x));
|
||||||
outputIds.add(outputId);
|
final outputIds = mwebUtxos.values
|
||||||
});
|
.where((utxo) => utxo.height > 0)
|
||||||
|
.map((utxo) => utxo.outputId).toList();
|
||||||
final stub = await CwMweb.stub();
|
final stub = await CwMweb.stub();
|
||||||
final resp = await stub.spent(SpentRequest(outputId: outputIds));
|
final resp = await stub.spent(SpentRequest(outputId: outputIds));
|
||||||
final spent = resp.outputId;
|
final spent = resp.outputId;
|
||||||
|
@ -212,8 +225,8 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
||||||
var output = AccumulatorSink<Digest>();
|
var output = AccumulatorSink<Digest>();
|
||||||
var input = sha256.startChunkedConversion(output);
|
var input = sha256.startChunkedConversion(output);
|
||||||
for (final outputId in spent) {
|
for (final outputId in spent) {
|
||||||
input.add(hex.decode(outputId));
|
final utxo = mwebUtxos[outputId];
|
||||||
final utxo = mwebUtxos[outputId]!;
|
if (utxo == null) continue;
|
||||||
final addressRecord = walletAddresses.allAddresses.firstWhere(
|
final addressRecord = walletAddresses.allAddresses.firstWhere(
|
||||||
(addressRecord) => addressRecord.address == utxo.address);
|
(addressRecord) => addressRecord.address == utxo.address);
|
||||||
if (!inputAddresses.contains(utxo.address))
|
if (!inputAddresses.contains(utxo.address))
|
||||||
|
@ -222,7 +235,9 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
||||||
amount += utxo.value.toInt();
|
amount += utxo.value.toInt();
|
||||||
inputAddresses.add(utxo.address);
|
inputAddresses.add(utxo.address);
|
||||||
mwebUtxos.remove(outputId);
|
mwebUtxos.remove(outputId);
|
||||||
|
input.add(hex.decode(outputId));
|
||||||
}
|
}
|
||||||
|
if (inputAddresses.isEmpty) return;
|
||||||
input.close();
|
input.close();
|
||||||
var digest = output.events.single;
|
var digest = output.events.single;
|
||||||
final tx = ElectrumTransactionInfo(WalletType.litecoin,
|
final tx = ElectrumTransactionInfo(WalletType.litecoin,
|
||||||
|
@ -238,6 +253,33 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
||||||
await transactionHistory.save();
|
await transactionHistory.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<bool> checkPendingTransaction(ElectrumTransactionInfo tx) async {
|
||||||
|
if (!tx.isPending) return false;
|
||||||
|
final outputId = <String>[], target = <String>{};
|
||||||
|
final isHash = RegExp(r'^[a-f0-9]{64}$').hasMatch;
|
||||||
|
final spendingOutputIds = tx.inputAddresses?.where(isHash) ?? [];
|
||||||
|
final payingToOutputIds = tx.outputAddresses?.where(isHash) ?? [];
|
||||||
|
outputId.addAll(spendingOutputIds);
|
||||||
|
outputId.addAll(payingToOutputIds);
|
||||||
|
target.addAll(spendingOutputIds);
|
||||||
|
for (final outputId in payingToOutputIds) {
|
||||||
|
final spendingTx = transactionHistory.transactions.values.firstWhereOrNull(
|
||||||
|
(tx) => tx.inputAddresses?.contains(outputId) ?? false);
|
||||||
|
if (spendingTx != null && !spendingTx.isPending)
|
||||||
|
target.add(outputId);
|
||||||
|
}
|
||||||
|
if (outputId.isEmpty) return false;
|
||||||
|
final stub = await CwMweb.stub();
|
||||||
|
final resp = await stub.spent(SpentRequest(outputId: outputId));
|
||||||
|
if (resp.outputId.toSet() != target) return false;
|
||||||
|
final status = await stub.status(StatusRequest());
|
||||||
|
if (!tx.isPending) return false;
|
||||||
|
tx.height = status.mwebUtxosHeight;
|
||||||
|
tx.confirmations = 1;
|
||||||
|
tx.isPending = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> updateUnspentCoins() async {
|
Future<void> updateUnspentCoins() async {
|
||||||
await super.updateUnspentCoins();
|
await super.updateUnspentCoins();
|
||||||
|
@ -341,6 +383,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
||||||
spendSecret: hex.decode(mwebHd.derive(0x80000001).privKey!),
|
spendSecret: hex.decode(mwebHd.derive(0x80000001).privKey!),
|
||||||
feeRatePerKb: Int64.parseInt(tx.feeRate) * 1000));
|
feeRatePerKb: Int64.parseInt(tx.feeRate) * 1000));
|
||||||
tx.hexOverride = hex.encode(resp.rawTx);
|
tx.hexOverride = hex.encode(resp.rawTx);
|
||||||
|
tx.outputs = resp.outputId;
|
||||||
return tx;
|
return tx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,7 @@ class PendingBitcoinTransaction with PendingTransaction {
|
||||||
final bool hasTaprootInputs;
|
final bool hasTaprootInputs;
|
||||||
String? idOverride;
|
String? idOverride;
|
||||||
String? hexOverride;
|
String? hexOverride;
|
||||||
|
List<String>? outputs;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get id => idOverride ?? _tx.txId();
|
String get id => idOverride ?? _tx.txId();
|
||||||
|
@ -110,5 +111,7 @@ class PendingBitcoinTransaction with PendingTransaction {
|
||||||
date: DateTime.now(),
|
date: DateTime.now(),
|
||||||
isPending: true,
|
isPending: true,
|
||||||
confirmations: 0,
|
confirmations: 0,
|
||||||
|
inputAddresses: _tx.inputs.map((input) => input.txId).toList(),
|
||||||
|
outputAddresses: outputs,
|
||||||
fee: fee);
|
fee: fee);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue