mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2024-12-23 03:59:23 +00:00
Change way for fetch electrum transactions.
This commit is contained in:
parent
22d285966d
commit
0ccc78ae70
3 changed files with 110 additions and 19 deletions
|
@ -217,23 +217,16 @@ class ElectrumClient {
|
||||||
return <String, Object>{};
|
return <String, Object>{};
|
||||||
});
|
});
|
||||||
|
|
||||||
Future<Map<String, Object>> getTransactionExpanded(
|
Future<String> getTransactionHex(
|
||||||
{@required String hash}) async {
|
{@required String hash}) async =>
|
||||||
try {
|
call(method: 'blockchain.transaction.get', params: [hash, false])
|
||||||
final originalTx = await getTransactionRaw(hash: hash);
|
.then((dynamic result) {
|
||||||
final vins = originalTx['vin'] as List<Object>;
|
if (result is String) {
|
||||||
|
return result;
|
||||||
for (dynamic vin in vins) {
|
|
||||||
if (vin is Map<String, Object>) {
|
|
||||||
vin['tx'] = await getTransactionRaw(hash: vin['txid'] as String);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return originalTx;
|
return '';
|
||||||
} catch (_) {
|
});
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<String> broadcastTransaction(
|
Future<String> broadcastTransaction(
|
||||||
{@required String transactionRaw}) async =>
|
{@required String transactionRaw}) async =>
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import 'dart:typed_data';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin;
|
import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin;
|
||||||
import 'package:bitcoin_flutter/src/payments/index.dart' show PaymentData;
|
import 'package:bitcoin_flutter/src/payments/index.dart' show PaymentData;
|
||||||
|
@ -8,6 +9,34 @@ import 'package:cw_core/transaction_info.dart';
|
||||||
import 'package:cw_core/format_amount.dart';
|
import 'package:cw_core/format_amount.dart';
|
||||||
import 'package:cw_core/wallet_type.dart';
|
import 'package:cw_core/wallet_type.dart';
|
||||||
|
|
||||||
|
String addressFromOutput(Uint8List script) {
|
||||||
|
try {
|
||||||
|
return bitcoin.P2PKH(
|
||||||
|
data: PaymentData(output: script),
|
||||||
|
network: bitcoin.bitcoin)
|
||||||
|
.data
|
||||||
|
.address;
|
||||||
|
} catch (_) {}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return bitcoin.P2WPKH(
|
||||||
|
data: PaymentData(output: script),
|
||||||
|
network: bitcoin.bitcoin)
|
||||||
|
.data
|
||||||
|
.address;
|
||||||
|
} catch(_) {}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ElectrumTransactionBundle {
|
||||||
|
ElectrumTransactionBundle(this.originalTransaction, {this.ins, this.time, this.confirmations});
|
||||||
|
final bitcoin.Transaction originalTransaction;
|
||||||
|
final List<bitcoin.Transaction> ins;
|
||||||
|
final int time;
|
||||||
|
final int confirmations;
|
||||||
|
}
|
||||||
|
|
||||||
class ElectrumTransactionInfo extends TransactionInfo {
|
class ElectrumTransactionInfo extends TransactionInfo {
|
||||||
ElectrumTransactionInfo(this.type,
|
ElectrumTransactionInfo(this.type,
|
||||||
{@required String id,
|
{@required String id,
|
||||||
|
@ -84,6 +113,49 @@ class ElectrumTransactionInfo extends TransactionInfo {
|
||||||
confirmations: confirmations);
|
confirmations: confirmations);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
factory ElectrumTransactionInfo.fromElectrumBundle(
|
||||||
|
ElectrumTransactionBundle bundle, WalletType type,
|
||||||
|
{@required Set<String> addresses, int height}) {
|
||||||
|
final date = DateTime.fromMillisecondsSinceEpoch(bundle.time * 1000);
|
||||||
|
var direction = TransactionDirection.incoming;
|
||||||
|
var amount = 0;
|
||||||
|
var inputAmount = 0;
|
||||||
|
var totalOutAmount = 0;
|
||||||
|
|
||||||
|
for (var i = 0; i < bundle.originalTransaction.ins.length; i++) {
|
||||||
|
final input = bundle.originalTransaction.ins[i];
|
||||||
|
final inputTransaction = bundle.ins[i];
|
||||||
|
final vout = input.index;
|
||||||
|
final outTransaction = inputTransaction.outs[vout];
|
||||||
|
final address = addressFromOutput(outTransaction.script);
|
||||||
|
inputAmount += outTransaction.value;
|
||||||
|
if (addresses.contains(address)) {
|
||||||
|
direction = TransactionDirection.outgoing;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (final out in bundle.originalTransaction.outs) {
|
||||||
|
totalOutAmount += out.value;
|
||||||
|
final address = addressFromOutput(out.script);
|
||||||
|
final addressExists = addresses.contains(address);
|
||||||
|
if ((direction == TransactionDirection.incoming && addressExists) ||
|
||||||
|
(direction == TransactionDirection.outgoing && !addressExists)) {
|
||||||
|
amount += out.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final fee = inputAmount - totalOutAmount;
|
||||||
|
return ElectrumTransactionInfo(type,
|
||||||
|
id: bundle.originalTransaction.getId(),
|
||||||
|
height: height,
|
||||||
|
isPending: false,
|
||||||
|
fee: fee,
|
||||||
|
direction: direction,
|
||||||
|
amount: amount,
|
||||||
|
date: date,
|
||||||
|
confirmations: bundle.confirmations);
|
||||||
|
}
|
||||||
|
|
||||||
factory ElectrumTransactionInfo.fromHexAndHeader(WalletType type, String hex,
|
factory ElectrumTransactionInfo.fromHexAndHeader(WalletType type, String hex,
|
||||||
{List<String> addresses, int height, int timestamp, int confirmations}) {
|
{List<String> addresses, int height, int timestamp, int confirmations}) {
|
||||||
final tx = bitcoin.Transaction.fromHex(hex);
|
final tx = bitcoin.Transaction.fromHex(hex);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
import 'dart:typed_data';
|
||||||
import 'package:cw_core/unspent_coins_info.dart';
|
import 'package:cw_core/unspent_coins_info.dart';
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
import 'package:cw_bitcoin/electrum_wallet_addresses.dart';
|
import 'package:cw_bitcoin/electrum_wallet_addresses.dart';
|
||||||
|
@ -31,6 +32,7 @@ import 'package:cw_core/sync_status.dart';
|
||||||
import 'package:cw_core/transaction_priority.dart';
|
import 'package:cw_core/transaction_priority.dart';
|
||||||
import 'package:cw_core/wallet_info.dart';
|
import 'package:cw_core/wallet_info.dart';
|
||||||
import 'package:cw_bitcoin/electrum.dart';
|
import 'package:cw_bitcoin/electrum.dart';
|
||||||
|
import 'package:hex/hex.dart';
|
||||||
|
|
||||||
part 'electrum_wallet.g.dart';
|
part 'electrum_wallet.g.dart';
|
||||||
|
|
||||||
|
@ -479,11 +481,35 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<ElectrumTransactionBundle> getTransactionExpanded(
|
||||||
|
{@required String hash, @required int height}) async {
|
||||||
|
final verboseTransaction = await electrumClient.getTransactionRaw(hash: hash);
|
||||||
|
final transactionHex = verboseTransaction['hex'] as String;
|
||||||
|
final original = bitcoin.Transaction.fromHex(transactionHex);
|
||||||
|
final ins = <bitcoin.Transaction>[];
|
||||||
|
final time = verboseTransaction['time'] as int;
|
||||||
|
final confirmations = verboseTransaction['time'] as int;
|
||||||
|
|
||||||
|
for (final vin in original.ins) {
|
||||||
|
final id = HEX.encode(vin.hash.reversed.toList());
|
||||||
|
final txHex = await electrumClient.getTransactionHex(hash: id);
|
||||||
|
final tx = bitcoin.Transaction.fromHex(txHex);
|
||||||
|
ins.add(tx);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ElectrumTransactionBundle(
|
||||||
|
original,
|
||||||
|
ins: ins,
|
||||||
|
time: time,
|
||||||
|
confirmations: confirmations);
|
||||||
|
}
|
||||||
|
|
||||||
Future<ElectrumTransactionInfo> fetchTransactionInfo(
|
Future<ElectrumTransactionInfo> fetchTransactionInfo(
|
||||||
{@required String hash, @required int height}) async {
|
{@required String hash, @required int height}) async {
|
||||||
final tx = await electrumClient.getTransactionExpanded(hash: hash);
|
final tx = await getTransactionExpanded(hash: hash, height: height);
|
||||||
return ElectrumTransactionInfo.fromElectrumVerbose(tx, walletInfo.type,
|
final addresses = walletAddresses.addresses.map((addr) => addr.address).toSet();
|
||||||
height: height, addresses: walletAddresses.addresses);
|
return ElectrumTransactionInfo.fromElectrumBundle(
|
||||||
|
tx,walletInfo.type, addresses: addresses, height: height);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -524,7 +550,7 @@ abstract class ElectrumWalletBase extends WalletBase<ElectrumBalance,
|
||||||
scriptHashes.forEach((sh) async {
|
scriptHashes.forEach((sh) async {
|
||||||
await _scripthashesUpdateSubject[sh]?.close();
|
await _scripthashesUpdateSubject[sh]?.close();
|
||||||
_scripthashesUpdateSubject[sh] = electrumClient.scripthashUpdate(sh);
|
_scripthashesUpdateSubject[sh] = electrumClient.scripthashUpdate(sh);
|
||||||
_scripthashesUpdateSubject[sh].listen((event) async {
|
_scripthashesUpdateSubject[sh]?.listen((event) async {
|
||||||
try {
|
try {
|
||||||
await _updateBalance();
|
await _updateBalance();
|
||||||
await updateUnspent();
|
await updateUnspent();
|
||||||
|
|
Loading…
Reference in a new issue