mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2024-11-18 02:07:43 +00:00
refactor interface changes back into the interface
This commit is contained in:
parent
ef38e58b57
commit
4180cf6c44
3 changed files with 131 additions and 125 deletions
|
@ -11,18 +11,11 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:decimal/decimal.dart';
|
|
||||||
import 'package:fusiondart/src/models/address.dart' as fusion_address;
|
|
||||||
import 'package:fusiondart/src/models/input.dart' as fusion_input;
|
|
||||||
import 'package:fusiondart/src/models/output.dart' as fusion_output;
|
|
||||||
import 'package:fusiondart/src/models/transaction.dart' as fusion_tx;
|
|
||||||
import 'package:isar/isar.dart';
|
import 'package:isar/isar.dart';
|
||||||
import 'package:stackwallet/electrumx_rpc/cached_electrumx.dart';
|
|
||||||
import 'package:stackwallet/models/isar/models/blockchain_data/address.dart';
|
import 'package:stackwallet/models/isar/models/blockchain_data/address.dart';
|
||||||
import 'package:stackwallet/models/isar/models/blockchain_data/input.dart';
|
import 'package:stackwallet/models/isar/models/blockchain_data/input.dart';
|
||||||
import 'package:stackwallet/models/isar/models/blockchain_data/output.dart';
|
import 'package:stackwallet/models/isar/models/blockchain_data/output.dart';
|
||||||
import 'package:stackwallet/utilities/amount/amount.dart';
|
import 'package:stackwallet/utilities/amount/amount.dart';
|
||||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
|
||||||
import 'package:tuple/tuple.dart';
|
import 'package:tuple/tuple.dart';
|
||||||
|
|
||||||
part 'transaction.g.dart';
|
part 'transaction.g.dart';
|
||||||
|
@ -238,108 +231,6 @@ class Transaction {
|
||||||
return Tuple2(transaction, address);
|
return Tuple2(transaction, address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert to fusiondart's Transaction type.
|
|
||||||
//
|
|
||||||
// This is bad because in the FusionWalletInterface in getTransactionsByAddress
|
|
||||||
// we already getAllTransactions, then for each transaction here we also getTransaction
|
|
||||||
// for each transaction again. But the data we need--the input's value--isn't
|
|
||||||
// here anyways.
|
|
||||||
Future<fusion_tx.Transaction> toFusionTransaction(
|
|
||||||
CachedElectrumX cachedElectrumX) async {
|
|
||||||
// Initialize Fusion Dart's Transaction object.
|
|
||||||
fusion_tx.Transaction fusionTransaction = fusion_tx.Transaction();
|
|
||||||
|
|
||||||
// Map the Inputs and Outputs to Fusion Dart's format.
|
|
||||||
//
|
|
||||||
// This takes an exqcessive amount of time because we have to get the
|
|
||||||
// transaction for each input. We already have the transaction for each
|
|
||||||
// input in getTransactionsByAddress, but we don't have the input's value.
|
|
||||||
// So we have to get the transaction again here.
|
|
||||||
fusionTransaction.Inputs = await Future.wait(inputs.map((e) async {
|
|
||||||
// Find input amount.
|
|
||||||
print("2 getting tx ${e.txid}");
|
|
||||||
Map<String, dynamic> _tx = await cachedElectrumX.getTransaction(
|
|
||||||
coin: Coin.bitcoincash,
|
|
||||||
txHash: e.txid,
|
|
||||||
verbose: true); // TODO is verbose needed?
|
|
||||||
|
|
||||||
// Check if output amount is available.
|
|
||||||
if (_tx == null) {
|
|
||||||
throw Exception("Transaction not found for input: ${e.txid}");
|
|
||||||
}
|
|
||||||
if (_tx["vout"] == null) {
|
|
||||||
throw Exception("Vout in transaction ${e.txid} is null");
|
|
||||||
}
|
|
||||||
if (_tx["vout"][e.vout] == null) {
|
|
||||||
throw Exception("Vout index ${e.vout} in transaction is null");
|
|
||||||
}
|
|
||||||
if (_tx["vout"][e.vout]["value"] == null) {
|
|
||||||
throw Exception("Value of vout index ${e.vout} in transaction is null");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assign vout value to amount.
|
|
||||||
final value = Amount.fromDecimal(
|
|
||||||
Decimal.parse(_tx["vout"][e.vout]["value"].toString()),
|
|
||||||
fractionDigits: Coin.bitcoincash.decimals,
|
|
||||||
);
|
|
||||||
|
|
||||||
return fusion_input.Input(
|
|
||||||
prevTxid: utf8.encode(e.txid), // TODO verify this is what we want.
|
|
||||||
prevIndex: e.vout, // TODO verify this is what we want.
|
|
||||||
pubKey: utf8.encode(address.value.toString()), // TODO fix public key.
|
|
||||||
amount: value.raw.toInt(),
|
|
||||||
);
|
|
||||||
}).toList());
|
|
||||||
|
|
||||||
fusionTransaction.Outputs = outputs.map((e) {
|
|
||||||
/*
|
|
||||||
if (e.scriptPubKey == null) {
|
|
||||||
// TODO calculate scriptPubKey if it is null.
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
fusion_address.DerivationPath? derivationPath;
|
|
||||||
List<int>? pubKey;
|
|
||||||
|
|
||||||
// Validate that we have all the required data.
|
|
||||||
if (address.value == null) {
|
|
||||||
// TODO calculate address if it is null.
|
|
||||||
throw Exception(
|
|
||||||
"address value is null for input: ${e.scriptPubKeyAddress}");
|
|
||||||
} else {
|
|
||||||
if (address.value!.publicKey.isEmpty || e.scriptPubKey != null) {
|
|
||||||
pubKey = utf8.encode(e.scriptPubKey!);
|
|
||||||
// TODO is this valid?
|
|
||||||
} else {
|
|
||||||
pubKey = address.value!.publicKey;
|
|
||||||
}
|
|
||||||
if (address.value!.derivationPath != null) {
|
|
||||||
derivationPath = fusion_address.DerivationPath(
|
|
||||||
address.value!.derivationPath!.toString());
|
|
||||||
} else {
|
|
||||||
// TODO calculate derivation path if it is null.
|
|
||||||
/*
|
|
||||||
throw Exception(
|
|
||||||
"derivationPath is null for input: ${e.scriptPubKeyAddress}");
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO handle case where address.value.publicKey is empty and e.scriptPubKey is null
|
|
||||||
|
|
||||||
return fusion_output.Output(
|
|
||||||
addr: fusion_address.Address(
|
|
||||||
addr: e.scriptPubKeyAddress,
|
|
||||||
publicKey: pubKey,
|
|
||||||
derivationPath: derivationPath,
|
|
||||||
),
|
|
||||||
value: e.value,
|
|
||||||
);
|
|
||||||
}).toList();
|
|
||||||
|
|
||||||
return fusionTransaction;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used in Isar db and stored there as int indexes so adding/removing values
|
// Used in Isar db and stored there as int indexes so adding/removing values
|
||||||
|
|
|
@ -8,10 +8,8 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import 'dart:convert';
|
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:fusiondart/src/models/input.dart' as FusionInput;
|
|
||||||
import 'package:isar/isar.dart';
|
import 'package:isar/isar.dart';
|
||||||
|
|
||||||
part 'utxo.g.dart';
|
part 'utxo.g.dart';
|
||||||
|
@ -147,14 +145,3 @@ class UTXO {
|
||||||
@ignore
|
@ignore
|
||||||
int get hashCode => Object.hashAll([walletId, txid, vout]);
|
int get hashCode => Object.hashAll([walletId, txid, vout]);
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ToFusionInput on UTXO {
|
|
||||||
FusionInput.Input toFusionInput({required List<int> pubKey}) {
|
|
||||||
return FusionInput.Input(
|
|
||||||
prevTxid: utf8.encode(txid),
|
|
||||||
prevIndex: vout,
|
|
||||||
pubKey: pubKey,
|
|
||||||
amount: value,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -2,16 +2,18 @@ import 'dart:async';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:decimal/decimal.dart';
|
||||||
import 'package:fusiondart/fusiondart.dart';
|
import 'package:fusiondart/fusiondart.dart';
|
||||||
import 'package:fusiondart/src/models/address.dart' as fusion_address;
|
import 'package:fusiondart/src/models/address.dart' as fusion_address;
|
||||||
import 'package:fusiondart/src/models/input.dart' as fusion_input;
|
import 'package:fusiondart/src/models/input.dart' as fusion_input;
|
||||||
|
import 'package:fusiondart/src/models/output.dart' as fusion_output;
|
||||||
import 'package:fusiondart/src/models/transaction.dart' as fusion_tx;
|
import 'package:fusiondart/src/models/transaction.dart' as fusion_tx;
|
||||||
import 'package:isar/isar.dart';
|
import 'package:isar/isar.dart';
|
||||||
import 'package:stackwallet/db/isar/main_db.dart';
|
import 'package:stackwallet/db/isar/main_db.dart';
|
||||||
import 'package:stackwallet/electrumx_rpc/cached_electrumx.dart';
|
import 'package:stackwallet/electrumx_rpc/cached_electrumx.dart';
|
||||||
import 'package:stackwallet/electrumx_rpc/electrumx.dart';
|
|
||||||
import 'package:stackwallet/models/isar/models/isar_models.dart';
|
import 'package:stackwallet/models/isar/models/isar_models.dart';
|
||||||
import 'package:stackwallet/services/tor_service.dart';
|
import 'package:stackwallet/services/tor_service.dart';
|
||||||
|
import 'package:stackwallet/utilities/amount/amount.dart';
|
||||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||||
import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart';
|
import 'package:stackwallet/utilities/enums/derive_path_type_enum.dart';
|
||||||
import 'package:stackwallet/utilities/stack_file_system.dart';
|
import 'package:stackwallet/utilities/stack_file_system.dart';
|
||||||
|
@ -243,8 +245,10 @@ mixin FusionWalletInterface {
|
||||||
|
|
||||||
// Find public key.
|
// Find public key.
|
||||||
print("1 getting tx ${e.txid}");
|
print("1 getting tx ${e.txid}");
|
||||||
Map<String, dynamic> tx = await _cachedElectrumX.getTransaction(coin: _coin,
|
Map<String, dynamic> tx = await _cachedElectrumX.getTransaction(
|
||||||
txHash: e.txid, verbose: true); // TODO is verbose needed?
|
coin: _coin,
|
||||||
|
txHash: e.txid,
|
||||||
|
verbose: true); // TODO is verbose needed?
|
||||||
|
|
||||||
// Check if scriptPubKey is available.
|
// Check if scriptPubKey is available.
|
||||||
if (tx["vout"] == null) {
|
if (tx["vout"] == null) {
|
||||||
|
@ -380,3 +384,127 @@ mixin FusionWalletInterface {
|
||||||
"TODO refreshFusion eg look up number of fusion participants connected/coordinating");
|
"TODO refreshFusion eg look up number of fusion participants connected/coordinating");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An extension of Stack Wallet's Transaction class that adds CashFusion functionality.
|
||||||
|
extension FusionTransaction on Transaction {
|
||||||
|
// WIP.
|
||||||
|
Future<fusion_tx.Transaction> toFusionTransaction(
|
||||||
|
CachedElectrumX cachedElectrumX) async {
|
||||||
|
// Initialize Fusion Dart's Transaction object.
|
||||||
|
fusion_tx.Transaction fusionTransaction = fusion_tx.Transaction();
|
||||||
|
|
||||||
|
// WIP.
|
||||||
|
fusionTransaction.Inputs = await Future.wait(inputs.map((e) async {
|
||||||
|
// Find input amount.
|
||||||
|
Map<String, dynamic> _tx = await cachedElectrumX.getTransaction(
|
||||||
|
coin: Coin.bitcoincash,
|
||||||
|
txHash: e.txid,
|
||||||
|
verbose: true); // TODO is verbose needed?
|
||||||
|
|
||||||
|
// Check if output amount is available.
|
||||||
|
if (_tx.isEmpty) {
|
||||||
|
throw Exception("Transaction not found for input: ${e.txid}");
|
||||||
|
}
|
||||||
|
if (_tx["vout"] == null) {
|
||||||
|
throw Exception("Vout in transaction ${e.txid} is null");
|
||||||
|
}
|
||||||
|
if (_tx["vout"][e.vout] == null) {
|
||||||
|
throw Exception("Vout index ${e.vout} in transaction is null");
|
||||||
|
}
|
||||||
|
if (_tx["vout"][e.vout]["value"] == null) {
|
||||||
|
throw Exception("Value of vout index ${e.vout} in transaction is null");
|
||||||
|
}
|
||||||
|
// TODO replace with conditional chaining?
|
||||||
|
|
||||||
|
// Assign vout value to amount.
|
||||||
|
final value = Amount.fromDecimal(
|
||||||
|
Decimal.parse(_tx["vout"][e.vout]["value"].toString()),
|
||||||
|
fractionDigits: Coin.bitcoincash.decimals,
|
||||||
|
);
|
||||||
|
|
||||||
|
return fusion_input.Input(
|
||||||
|
prevTxid: utf8.encode(e.txid), // TODO verify this is what we want.
|
||||||
|
prevIndex: e.vout, // TODO verify this is what we want.
|
||||||
|
pubKey: utf8.encode(address.value.toString()), // TODO fix public key.
|
||||||
|
amount: value.raw.toInt(),
|
||||||
|
);
|
||||||
|
}).toList());
|
||||||
|
|
||||||
|
fusionTransaction.Outputs = outputs.map((e) {
|
||||||
|
/*
|
||||||
|
if (e.scriptPubKey == null) {
|
||||||
|
// TODO calculate scriptPubKey if it is null.
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
fusion_address.DerivationPath? derivationPath;
|
||||||
|
List<int>? pubKey;
|
||||||
|
|
||||||
|
// Validate that we have all the required data.
|
||||||
|
if (address.value == null) {
|
||||||
|
// TODO calculate address if it is null.
|
||||||
|
throw Exception(
|
||||||
|
"address value is null for input: ${e.scriptPubKeyAddress}");
|
||||||
|
} else {
|
||||||
|
if (address.value!.publicKey.isEmpty || e.scriptPubKey != null) {
|
||||||
|
pubKey = utf8.encode(e.scriptPubKey!);
|
||||||
|
// TODO is this valid?
|
||||||
|
} else {
|
||||||
|
pubKey = address.value!
|
||||||
|
.publicKey; // TODO IMPORTANT: this address may not be *the* address in question :)
|
||||||
|
}
|
||||||
|
if (address.value!.derivationPath != null) {
|
||||||
|
derivationPath = fusion_address.DerivationPath(
|
||||||
|
address.value!.derivationPath!.toString());
|
||||||
|
} else {
|
||||||
|
// TODO calculate derivation path if it is null.
|
||||||
|
/*
|
||||||
|
throw Exception(
|
||||||
|
"derivationPath is null for input: ${e.scriptPubKeyAddress}");
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO handle case where address.value.publicKey is empty and e.scriptPubKey is null
|
||||||
|
|
||||||
|
return fusion_output.Output(
|
||||||
|
addr: fusion_address.Address(
|
||||||
|
addr: e.scriptPubKeyAddress,
|
||||||
|
publicKey: pubKey,
|
||||||
|
derivationPath: derivationPath,
|
||||||
|
),
|
||||||
|
value: e.value,
|
||||||
|
);
|
||||||
|
}).toList();
|
||||||
|
|
||||||
|
return fusionTransaction;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An extension of Stack Wallet's UTXO class that adds CashFusion functionality.
|
||||||
|
///
|
||||||
|
/// This class is used to convert Stack Wallet's UTXO class to FusionDart's
|
||||||
|
/// Input and Output classes.
|
||||||
|
extension FusionUTXO on UTXO {
|
||||||
|
/// Converts a Stack Wallet UTXO to a FusionDart Input.
|
||||||
|
fusion_input.Input toFusionInput({required List<int> pubKey}) {
|
||||||
|
return fusion_input.Input(
|
||||||
|
prevTxid: utf8.encode(txid), // TODO verify this is what we want.
|
||||||
|
prevIndex: vout, // TODO verify this is what we want.
|
||||||
|
pubKey: pubKey, // TODO fix public key.
|
||||||
|
amount: value,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Converts a Stack Wallet UTXO to a FusionDart Output.
|
||||||
|
fusion_output.Output toFusionOutput({required String address}) {
|
||||||
|
return fusion_output.Output(
|
||||||
|
addr: fusion_address.Address(
|
||||||
|
addr: address,
|
||||||
|
publicKey: utf8.encode(address.toString()), // TODO fix public key.
|
||||||
|
derivationPath: null, // TODO fix derivation path.
|
||||||
|
),
|
||||||
|
value: value,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue