mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2024-11-17 09:47:37 +00:00
dirty WIP notification tx creation
This commit is contained in:
parent
8c0366904a
commit
915458dbf3
2 changed files with 393 additions and 174 deletions
|
@ -2,12 +2,19 @@ import 'dart:convert';
|
|||
import 'dart:typed_data';
|
||||
|
||||
import 'package:bip47/bip47.dart';
|
||||
import 'package:bip47/src/util.dart';
|
||||
import 'package:bitcoindart/bitcoindart.dart';
|
||||
import 'package:bitcoindart/src/utils/constants/op.dart' as op;
|
||||
import 'package:bitcoindart/src/utils/script.dart' as bscript;
|
||||
import 'package:decimal/decimal.dart';
|
||||
import 'package:pointycastle/digests/sha256.dart';
|
||||
import 'package:stackwallet/hive/db.dart';
|
||||
import 'package:stackwallet/services/coins/dogecoin/dogecoin_wallet.dart';
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
import 'package:stackwallet/utilities/format.dart';
|
||||
|
||||
import 'package:stackwallet/models/paymint/utxo_model.dart';
|
||||
|
||||
extension PayNym on DogecoinWallet {
|
||||
// fetch or generate this wallet's bip47 payment code
|
||||
Future<PaymentCode> getPaymentCode() async {
|
||||
|
@ -48,4 +55,204 @@ extension PayNym on DogecoinWallet {
|
|||
|
||||
// Future<Map<String, dynamic>> prepareNotificationTransaction(
|
||||
// String targetPaymentCode) async {}
|
||||
|
||||
Future<String> createNotificationTx(
|
||||
String targetPaymentCodeString,
|
||||
List<UtxoObject> utxosToUse,
|
||||
) async {
|
||||
final utxoSigningData = await fetchBuildTxData(utxosToUse);
|
||||
final targetPaymentCode =
|
||||
PaymentCode.fromPaymentCode(targetPaymentCodeString, network);
|
||||
final myCode = await getPaymentCode();
|
||||
|
||||
final utxo = utxosToUse.first;
|
||||
final txPoint = utxo.txid.fromHex.toList();
|
||||
final txPointIndex = utxo.vout;
|
||||
|
||||
final rev = Uint8List(txPoint.length + 4);
|
||||
Util.copyBytes(Uint8List.fromList(txPoint), 0, rev, 0, txPoint.length);
|
||||
final buffer = rev.buffer.asByteData();
|
||||
buffer.setUint32(txPoint.length, txPointIndex, Endian.little);
|
||||
|
||||
final myKeyPair = utxoSigningData[utxo.txid]["keyPair"] as ECPair;
|
||||
|
||||
final S = SecretPoint(
|
||||
myKeyPair.privateKey!,
|
||||
targetPaymentCode.notificationPublicKey(),
|
||||
);
|
||||
|
||||
final blindingMask = PaymentCode.getMask(S.ecdhSecret(), rev);
|
||||
|
||||
final blindedPaymentCode = PaymentCode.blind(
|
||||
myCode.getPayload(),
|
||||
blindingMask,
|
||||
);
|
||||
|
||||
final opReturnScript = bscript.compile([
|
||||
(op.OPS["OP_RETURN"] as int),
|
||||
blindedPaymentCode,
|
||||
]);
|
||||
|
||||
final bobP2PKH = P2PKH(
|
||||
data: PaymentData(
|
||||
pubkey: targetPaymentCode.notificationPublicKey(),
|
||||
),
|
||||
).data;
|
||||
final notificationScript = bscript.compile([bobP2PKH.output]);
|
||||
|
||||
// build a notification tx
|
||||
final txb = TransactionBuilder();
|
||||
txb.setVersion(1);
|
||||
|
||||
txb.addInput(
|
||||
"9c6000d597c5008f7bfc2618aed5e4a6ae57677aab95078aae708e1cab11f486",
|
||||
txPointIndex,
|
||||
);
|
||||
|
||||
txb.addOutput(targetPaymentCode.notificationAddress(),
|
||||
Format.decimalAmountToSatoshis(Decimal.one, coin));
|
||||
txb.addOutput(
|
||||
opReturnScript, Format.decimalAmountToSatoshis(Decimal.one, coin));
|
||||
|
||||
txb.sign(
|
||||
vin: 0,
|
||||
keyPair: myKeyPair,
|
||||
);
|
||||
|
||||
final builtTx = txb.build();
|
||||
|
||||
return builtTx.toHex();
|
||||
}
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> parseTransaction(
|
||||
Map<String, dynamic> txData,
|
||||
dynamic electrumxClient,
|
||||
Set<String> myAddresses,
|
||||
Set<String> myChangeAddresses,
|
||||
Coin coin,
|
||||
int minConfirms,
|
||||
Decimal currentPrice,
|
||||
) async {
|
||||
Set<String> inputAddresses = {};
|
||||
Set<String> outputAddresses = {};
|
||||
|
||||
int totalInputValue = 0;
|
||||
int totalOutputValue = 0;
|
||||
|
||||
int amountSentFromWallet = 0;
|
||||
int amountReceivedInWallet = 0;
|
||||
|
||||
// parse inputs
|
||||
for (final input in txData["vin"] as List) {
|
||||
final prevTxid = input["txid"] as String;
|
||||
final prevOut = input["vout"] as int;
|
||||
|
||||
// fetch input tx to get address
|
||||
final inputTx = await electrumxClient.getTransaction(
|
||||
txHash: prevTxid,
|
||||
coin: coin,
|
||||
);
|
||||
|
||||
for (final output in inputTx["vout"] as List) {
|
||||
// check matching output
|
||||
if (prevOut == output["n"]) {
|
||||
// get value
|
||||
final value = Format.decimalAmountToSatoshis(
|
||||
Decimal.parse(output["value"].toString()),
|
||||
coin,
|
||||
);
|
||||
|
||||
// add value to total
|
||||
totalInputValue += value;
|
||||
|
||||
// get input(prevOut) address
|
||||
final address = output["scriptPubKey"]?["addresses"]?[0] as String? ??
|
||||
output["scriptPubKey"]?["address"] as String?;
|
||||
if (address != null) {
|
||||
inputAddresses.add(address);
|
||||
|
||||
// if input was from my wallet, add value to amount sent
|
||||
if (myAddresses.contains(address)) {
|
||||
amountSentFromWallet += value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// parse outputs
|
||||
for (final output in txData["vout"] as List) {
|
||||
// get value
|
||||
final value = Format.decimalAmountToSatoshis(
|
||||
Decimal.parse(output["value"].toString()),
|
||||
coin,
|
||||
);
|
||||
|
||||
// add value to total
|
||||
totalOutputValue += value;
|
||||
|
||||
// get output address
|
||||
final address = output["scriptPubKey"]["addresses"][0] as String? ??
|
||||
output["scriptPubKey"]["address"] as String?;
|
||||
if (address != null) {
|
||||
outputAddresses.add(address);
|
||||
|
||||
// if output was from my wallet, add value to amount received
|
||||
if (myAddresses.contains(address)) {
|
||||
amountReceivedInWallet += value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final mySentFromAddresses = myAddresses.intersection(inputAddresses);
|
||||
final myReceivedOnAddresses = myAddresses.intersection(outputAddresses);
|
||||
|
||||
final fee = totalInputValue - totalOutputValue;
|
||||
|
||||
// create normalized tx data map
|
||||
Map<String, dynamic> normalizedTx = {};
|
||||
|
||||
final int confirms = txData["confirmations"] as int? ?? 0;
|
||||
|
||||
normalizedTx["txid"] = txData["txid"] as String;
|
||||
normalizedTx["confirmed_status"] = confirms >= minConfirms;
|
||||
normalizedTx["confirmations"] = confirms;
|
||||
normalizedTx["timestamp"] = txData["blocktime"] as int? ??
|
||||
(DateTime.now().millisecondsSinceEpoch ~/ 1000);
|
||||
normalizedTx["aliens"] = <dynamic>[];
|
||||
normalizedTx["fees"] = fee;
|
||||
normalizedTx["address"] = txData["address"] as String;
|
||||
normalizedTx["inputSize"] = txData["vin"].length;
|
||||
normalizedTx["outputSize"] = txData["vout"].length;
|
||||
normalizedTx["inputs"] = txData["vin"];
|
||||
normalizedTx["outputs"] = txData["vout"];
|
||||
normalizedTx["height"] = txData["height"] as int;
|
||||
|
||||
int amount;
|
||||
String type;
|
||||
if (mySentFromAddresses.isNotEmpty && myReceivedOnAddresses.isNotEmpty) {
|
||||
// tx is sent to self
|
||||
type = "Sent to self";
|
||||
amount = amountReceivedInWallet - amountSentFromWallet;
|
||||
} else if (mySentFromAddresses.isNotEmpty) {
|
||||
// outgoing tx
|
||||
type = "Sent";
|
||||
amount = amountSentFromWallet;
|
||||
} else {
|
||||
// incoming tx
|
||||
type = "Received";
|
||||
amount = amountReceivedInWallet;
|
||||
}
|
||||
|
||||
normalizedTx["txType"] = type;
|
||||
normalizedTx["amount"] = amount;
|
||||
normalizedTx["worthNow"] = (Format.satoshisToAmount(
|
||||
amount,
|
||||
coin: coin,
|
||||
) *
|
||||
currentPrice)
|
||||
.toStringAsFixed(2);
|
||||
|
||||
return normalizedTx;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import 'package:stackwallet/models/models.dart' as models;
|
|||
import 'package:stackwallet/models/paymint/fee_object_model.dart';
|
||||
import 'package:stackwallet/models/paymint/transactions_model.dart';
|
||||
import 'package:stackwallet/models/paymint/utxo_model.dart';
|
||||
import 'package:stackwallet/services/coins/coin_paynym_extension.dart';
|
||||
import 'package:stackwallet/services/coins/coin_service.dart';
|
||||
import 'package:stackwallet/services/event_bus/events/global/node_connection_status_changed_event.dart';
|
||||
import 'package:stackwallet/services/event_bus/events/global/refresh_percent_changed_event.dart';
|
||||
|
@ -1063,7 +1064,8 @@ class DogecoinWallet extends CoinServiceAPI {
|
|||
final priceData =
|
||||
await _priceAPI.getPricesAnd24hChange(baseCurrency: _prefs.currency);
|
||||
Decimal currentPrice = priceData[coin]?.item1 ?? Decimal.zero;
|
||||
final locale = Platform.isWindows ? "en_US" : await Devicelocale.currentLocale;
|
||||
final locale =
|
||||
Platform.isWindows ? "en_US" : await Devicelocale.currentLocale;
|
||||
final String worthNow = Format.localizedStringAsFixed(
|
||||
value:
|
||||
((currentPrice * Decimal.fromInt(txData["recipientAmt"] as int)) /
|
||||
|
@ -2091,180 +2093,190 @@ class DogecoinWallet extends CoinServiceAPI {
|
|||
await fastFetch(vHashes.toList());
|
||||
|
||||
for (final txObject in allTransactions) {
|
||||
List<String> sendersArray = [];
|
||||
List<String> recipientsArray = [];
|
||||
// List<String> sendersArray = [];
|
||||
// List<String> recipientsArray = [];
|
||||
//
|
||||
// // Usually only has value when txType = 'Send'
|
||||
// int inputAmtSentFromWallet = 0;
|
||||
// // Usually has value regardless of txType due to change addresses
|
||||
// int outputAmtAddressedToWallet = 0;
|
||||
// int fee = 0;
|
||||
//
|
||||
// Map<String, dynamic> midSortedTx = {};
|
||||
//
|
||||
// for (int i = 0; i < (txObject["vin"] as List).length; i++) {
|
||||
// final input = txObject["vin"][i] as Map;
|
||||
// final prevTxid = input["txid"] as String;
|
||||
// final prevOut = input["vout"] as int;
|
||||
//
|
||||
// final tx = await _cachedElectrumXClient.getTransaction(
|
||||
// txHash: prevTxid, coin: coin);
|
||||
//
|
||||
// for (final out in tx["vout"] as List) {
|
||||
// if (prevOut == out["n"]) {
|
||||
// final address = out["scriptPubKey"]["addresses"][0] as String?;
|
||||
// if (address != null) {
|
||||
// sendersArray.add(address);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Logging.instance.log("sendersArray: $sendersArray", level: LogLevel.Info);
|
||||
//
|
||||
// for (final output in txObject["vout"] as List) {
|
||||
// final address = output["scriptPubKey"]["addresses"][0] as String?;
|
||||
// if (address != null) {
|
||||
// recipientsArray.add(address);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Logging.instance
|
||||
// .log("recipientsArray: $recipientsArray", level: LogLevel.Info);
|
||||
//
|
||||
// final foundInSenders =
|
||||
// allAddresses.any((element) => sendersArray.contains(element));
|
||||
// Logging.instance
|
||||
// .log("foundInSenders: $foundInSenders", level: LogLevel.Info);
|
||||
//
|
||||
// // If txType = Sent, then calculate inputAmtSentFromWallet
|
||||
// if (foundInSenders) {
|
||||
// int totalInput = 0;
|
||||
// for (int i = 0; i < (txObject["vin"] as List).length; i++) {
|
||||
// final input = txObject["vin"][i] as Map;
|
||||
// final prevTxid = input["txid"] as String;
|
||||
// final prevOut = input["vout"] as int;
|
||||
// final tx = await _cachedElectrumXClient.getTransaction(
|
||||
// txHash: prevTxid,
|
||||
// coin: coin,
|
||||
// );
|
||||
//
|
||||
// for (final out in tx["vout"] as List) {
|
||||
// if (prevOut == out["n"]) {
|
||||
// inputAmtSentFromWallet +=
|
||||
// (Decimal.parse(out["value"].toString()) *
|
||||
// Decimal.fromInt(Constants.satsPerCoin(coin)))
|
||||
// .toBigInt()
|
||||
// .toInt();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// totalInput = inputAmtSentFromWallet;
|
||||
// int totalOutput = 0;
|
||||
//
|
||||
// for (final output in txObject["vout"] as List) {
|
||||
// final address = output["scriptPubKey"]["addresses"][0];
|
||||
// final value = output["value"];
|
||||
// final _value = (Decimal.parse(value.toString()) *
|
||||
// Decimal.fromInt(Constants.satsPerCoin(coin)))
|
||||
// .toBigInt()
|
||||
// .toInt();
|
||||
// totalOutput += _value;
|
||||
// if (changeAddressesP2PKH.contains(address)) {
|
||||
// inputAmtSentFromWallet -= _value;
|
||||
// } else {
|
||||
// // change address from 'sent from' to the 'sent to' address
|
||||
// txObject["address"] = address;
|
||||
// }
|
||||
// }
|
||||
// // calculate transaction fee
|
||||
// fee = totalInput - totalOutput;
|
||||
// // subtract fee from sent to calculate correct value of sent tx
|
||||
// inputAmtSentFromWallet -= fee;
|
||||
// } else {
|
||||
// // counters for fee calculation
|
||||
// int totalOut = 0;
|
||||
// int totalIn = 0;
|
||||
//
|
||||
// // add up received tx value
|
||||
// for (final output in txObject["vout"] as List) {
|
||||
// final address = output["scriptPubKey"]["addresses"][0];
|
||||
// if (address != null) {
|
||||
// final value = (Decimal.parse(output["value"].toString()) *
|
||||
// Decimal.fromInt(Constants.satsPerCoin(coin)))
|
||||
// .toBigInt()
|
||||
// .toInt();
|
||||
// totalOut += value;
|
||||
// if (allAddresses.contains(address)) {
|
||||
// outputAmtAddressedToWallet += value;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // calculate fee for received tx
|
||||
// for (int i = 0; i < (txObject["vin"] as List).length; i++) {
|
||||
// final input = txObject["vin"][i] as Map;
|
||||
// final prevTxid = input["txid"] as String;
|
||||
// final prevOut = input["vout"] as int;
|
||||
// final tx = await _cachedElectrumXClient.getTransaction(
|
||||
// txHash: prevTxid,
|
||||
// coin: coin,
|
||||
// );
|
||||
//
|
||||
// for (final out in tx["vout"] as List) {
|
||||
// if (prevOut == out["n"]) {
|
||||
// totalIn += (Decimal.parse(out["value"].toString()) *
|
||||
// Decimal.fromInt(Constants.satsPerCoin(coin)))
|
||||
// .toBigInt()
|
||||
// .toInt();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// fee = totalIn - totalOut;
|
||||
// }
|
||||
//
|
||||
// // create final tx map
|
||||
// midSortedTx["txid"] = txObject["txid"];
|
||||
// midSortedTx["confirmed_status"] = (txObject["confirmations"] != null) &&
|
||||
// (txObject["confirmations"] as int >= MINIMUM_CONFIRMATIONS);
|
||||
// midSortedTx["confirmations"] = txObject["confirmations"] ?? 0;
|
||||
// midSortedTx["timestamp"] = txObject["blocktime"] ??
|
||||
// (DateTime.now().millisecondsSinceEpoch ~/ 1000);
|
||||
//
|
||||
// if (foundInSenders) {
|
||||
// midSortedTx["txType"] = "Sent";
|
||||
// midSortedTx["amount"] = inputAmtSentFromWallet;
|
||||
// final String worthNow =
|
||||
// ((currentPrice * Decimal.fromInt(inputAmtSentFromWallet)) /
|
||||
// Decimal.fromInt(Constants.satsPerCoin(coin)))
|
||||
// .toDecimal(scaleOnInfinitePrecision: 2)
|
||||
// .toStringAsFixed(2);
|
||||
// midSortedTx["worthNow"] = worthNow;
|
||||
// midSortedTx["worthAtBlockTimestamp"] = worthNow;
|
||||
// } else {
|
||||
// midSortedTx["txType"] = "Received";
|
||||
// midSortedTx["amount"] = outputAmtAddressedToWallet;
|
||||
// final worthNow =
|
||||
// ((currentPrice * Decimal.fromInt(outputAmtAddressedToWallet)) /
|
||||
// Decimal.fromInt(Constants.satsPerCoin(coin)))
|
||||
// .toDecimal(scaleOnInfinitePrecision: 2)
|
||||
// .toStringAsFixed(2);
|
||||
// midSortedTx["worthNow"] = worthNow;
|
||||
// }
|
||||
// midSortedTx["aliens"] = <dynamic>[];
|
||||
// midSortedTx["fees"] = fee;
|
||||
// midSortedTx["address"] = txObject["address"];
|
||||
// midSortedTx["inputSize"] = txObject["vin"].length;
|
||||
// midSortedTx["outputSize"] = txObject["vout"].length;
|
||||
// midSortedTx["inputs"] = txObject["vin"];
|
||||
// midSortedTx["outputs"] = txObject["vout"];
|
||||
//
|
||||
// final int height = txObject["height"] as int;
|
||||
// midSortedTx["height"] = height;
|
||||
//
|
||||
// if (height >= latestTxnBlockHeight) {
|
||||
// latestTxnBlockHeight = height;
|
||||
// }
|
||||
|
||||
// Usually only has value when txType = 'Send'
|
||||
int inputAmtSentFromWallet = 0;
|
||||
// Usually has value regardless of txType due to change addresses
|
||||
int outputAmtAddressedToWallet = 0;
|
||||
int fee = 0;
|
||||
|
||||
Map<String, dynamic> midSortedTx = {};
|
||||
|
||||
for (int i = 0; i < (txObject["vin"] as List).length; i++) {
|
||||
final input = txObject["vin"][i] as Map;
|
||||
final prevTxid = input["txid"] as String;
|
||||
final prevOut = input["vout"] as int;
|
||||
|
||||
final tx = await _cachedElectrumXClient.getTransaction(
|
||||
txHash: prevTxid, coin: coin);
|
||||
|
||||
for (final out in tx["vout"] as List) {
|
||||
if (prevOut == out["n"]) {
|
||||
final address = out["scriptPubKey"]["addresses"][0] as String?;
|
||||
if (address != null) {
|
||||
sendersArray.add(address);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Logging.instance.log("sendersArray: $sendersArray", level: LogLevel.Info);
|
||||
|
||||
for (final output in txObject["vout"] as List) {
|
||||
final address = output["scriptPubKey"]["addresses"][0] as String?;
|
||||
if (address != null) {
|
||||
recipientsArray.add(address);
|
||||
}
|
||||
}
|
||||
|
||||
Logging.instance
|
||||
.log("recipientsArray: $recipientsArray", level: LogLevel.Info);
|
||||
|
||||
final foundInSenders =
|
||||
allAddresses.any((element) => sendersArray.contains(element));
|
||||
Logging.instance
|
||||
.log("foundInSenders: $foundInSenders", level: LogLevel.Info);
|
||||
|
||||
// If txType = Sent, then calculate inputAmtSentFromWallet
|
||||
if (foundInSenders) {
|
||||
int totalInput = 0;
|
||||
for (int i = 0; i < (txObject["vin"] as List).length; i++) {
|
||||
final input = txObject["vin"][i] as Map;
|
||||
final prevTxid = input["txid"] as String;
|
||||
final prevOut = input["vout"] as int;
|
||||
final tx = await _cachedElectrumXClient.getTransaction(
|
||||
txHash: prevTxid,
|
||||
coin: coin,
|
||||
);
|
||||
|
||||
for (final out in tx["vout"] as List) {
|
||||
if (prevOut == out["n"]) {
|
||||
inputAmtSentFromWallet +=
|
||||
(Decimal.parse(out["value"].toString()) *
|
||||
Decimal.fromInt(Constants.satsPerCoin(coin)))
|
||||
.toBigInt()
|
||||
.toInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
totalInput = inputAmtSentFromWallet;
|
||||
int totalOutput = 0;
|
||||
|
||||
for (final output in txObject["vout"] as List) {
|
||||
final address = output["scriptPubKey"]["addresses"][0];
|
||||
final value = output["value"];
|
||||
final _value = (Decimal.parse(value.toString()) *
|
||||
Decimal.fromInt(Constants.satsPerCoin(coin)))
|
||||
.toBigInt()
|
||||
.toInt();
|
||||
totalOutput += _value;
|
||||
if (changeAddressesP2PKH.contains(address)) {
|
||||
inputAmtSentFromWallet -= _value;
|
||||
} else {
|
||||
// change address from 'sent from' to the 'sent to' address
|
||||
txObject["address"] = address;
|
||||
}
|
||||
}
|
||||
// calculate transaction fee
|
||||
fee = totalInput - totalOutput;
|
||||
// subtract fee from sent to calculate correct value of sent tx
|
||||
inputAmtSentFromWallet -= fee;
|
||||
} else {
|
||||
// counters for fee calculation
|
||||
int totalOut = 0;
|
||||
int totalIn = 0;
|
||||
|
||||
// add up received tx value
|
||||
for (final output in txObject["vout"] as List) {
|
||||
final address = output["scriptPubKey"]["addresses"][0];
|
||||
if (address != null) {
|
||||
final value = (Decimal.parse(output["value"].toString()) *
|
||||
Decimal.fromInt(Constants.satsPerCoin(coin)))
|
||||
.toBigInt()
|
||||
.toInt();
|
||||
totalOut += value;
|
||||
if (allAddresses.contains(address)) {
|
||||
outputAmtAddressedToWallet += value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// calculate fee for received tx
|
||||
for (int i = 0; i < (txObject["vin"] as List).length; i++) {
|
||||
final input = txObject["vin"][i] as Map;
|
||||
final prevTxid = input["txid"] as String;
|
||||
final prevOut = input["vout"] as int;
|
||||
final tx = await _cachedElectrumXClient.getTransaction(
|
||||
txHash: prevTxid,
|
||||
coin: coin,
|
||||
);
|
||||
|
||||
for (final out in tx["vout"] as List) {
|
||||
if (prevOut == out["n"]) {
|
||||
totalIn += (Decimal.parse(out["value"].toString()) *
|
||||
Decimal.fromInt(Constants.satsPerCoin(coin)))
|
||||
.toBigInt()
|
||||
.toInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
fee = totalIn - totalOut;
|
||||
}
|
||||
|
||||
// create final tx map
|
||||
midSortedTx["txid"] = txObject["txid"];
|
||||
midSortedTx["confirmed_status"] = (txObject["confirmations"] != null) &&
|
||||
(txObject["confirmations"] as int >= MINIMUM_CONFIRMATIONS);
|
||||
midSortedTx["confirmations"] = txObject["confirmations"] ?? 0;
|
||||
midSortedTx["timestamp"] = txObject["blocktime"] ??
|
||||
(DateTime.now().millisecondsSinceEpoch ~/ 1000);
|
||||
|
||||
if (foundInSenders) {
|
||||
midSortedTx["txType"] = "Sent";
|
||||
midSortedTx["amount"] = inputAmtSentFromWallet;
|
||||
final String worthNow =
|
||||
((currentPrice * Decimal.fromInt(inputAmtSentFromWallet)) /
|
||||
Decimal.fromInt(Constants.satsPerCoin(coin)))
|
||||
.toDecimal(scaleOnInfinitePrecision: 2)
|
||||
.toStringAsFixed(2);
|
||||
midSortedTx["worthNow"] = worthNow;
|
||||
midSortedTx["worthAtBlockTimestamp"] = worthNow;
|
||||
} else {
|
||||
midSortedTx["txType"] = "Received";
|
||||
midSortedTx["amount"] = outputAmtAddressedToWallet;
|
||||
final worthNow =
|
||||
((currentPrice * Decimal.fromInt(outputAmtAddressedToWallet)) /
|
||||
Decimal.fromInt(Constants.satsPerCoin(coin)))
|
||||
.toDecimal(scaleOnInfinitePrecision: 2)
|
||||
.toStringAsFixed(2);
|
||||
midSortedTx["worthNow"] = worthNow;
|
||||
}
|
||||
midSortedTx["aliens"] = <dynamic>[];
|
||||
midSortedTx["fees"] = fee;
|
||||
midSortedTx["address"] = txObject["address"];
|
||||
midSortedTx["inputSize"] = txObject["vin"].length;
|
||||
midSortedTx["outputSize"] = txObject["vout"].length;
|
||||
midSortedTx["inputs"] = txObject["vin"];
|
||||
midSortedTx["outputs"] = txObject["vout"];
|
||||
|
||||
final int height = txObject["height"] as int;
|
||||
midSortedTx["height"] = height;
|
||||
|
||||
if (height >= latestTxnBlockHeight) {
|
||||
latestTxnBlockHeight = height;
|
||||
}
|
||||
final midSortedTx = await parseTransaction(
|
||||
txObject,
|
||||
cachedElectrumXClient,
|
||||
allAddresses.toSet(),
|
||||
(changeAddressesP2PKH as List<String>).toSet(),
|
||||
coin,
|
||||
MINIMUM_CONFIRMATIONS,
|
||||
currentPrice,
|
||||
);
|
||||
|
||||
midSortedArray.add(midSortedTx);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue