mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2024-11-17 09:47:37 +00:00
dirty hack for showing firo transactions right away until we can add functionality to sparkmobile
This commit is contained in:
parent
3cf0d82085
commit
b11694220b
5 changed files with 282 additions and 28 deletions
|
@ -1,4 +1,5 @@
|
||||||
import 'package:cw_wownero/pending_wownero_transaction.dart';
|
import 'package:cw_wownero/pending_wownero_transaction.dart';
|
||||||
|
import 'package:stackwallet/models/isar/models/blockchain_data/v2/transaction_v2.dart';
|
||||||
import 'package:stackwallet/models/isar/models/isar_models.dart';
|
import 'package:stackwallet/models/isar/models/isar_models.dart';
|
||||||
import 'package:stackwallet/models/paynym/paynym_account_lite.dart';
|
import 'package:stackwallet/models/paynym/paynym_account_lite.dart';
|
||||||
import 'package:stackwallet/utilities/amount/amount.dart';
|
import 'package:stackwallet/utilities/amount/amount.dart';
|
||||||
|
@ -64,6 +65,8 @@ class TxData {
|
||||||
})>? sparkRecipients;
|
})>? sparkRecipients;
|
||||||
final List<TxData>? sparkMints;
|
final List<TxData>? sparkMints;
|
||||||
|
|
||||||
|
final TransactionV2? tempTx;
|
||||||
|
|
||||||
TxData({
|
TxData({
|
||||||
this.feeRateType,
|
this.feeRateType,
|
||||||
this.feeRateAmount,
|
this.feeRateAmount,
|
||||||
|
@ -96,6 +99,7 @@ class TxData {
|
||||||
this.tezosOperationsList,
|
this.tezosOperationsList,
|
||||||
this.sparkRecipients,
|
this.sparkRecipients,
|
||||||
this.sparkMints,
|
this.sparkMints,
|
||||||
|
this.tempTx,
|
||||||
});
|
});
|
||||||
|
|
||||||
Amount? get amount => recipients != null && recipients!.isNotEmpty
|
Amount? get amount => recipients != null && recipients!.isNotEmpty
|
||||||
|
@ -153,6 +157,7 @@ class TxData {
|
||||||
})>?
|
})>?
|
||||||
sparkRecipients,
|
sparkRecipients,
|
||||||
List<TxData>? sparkMints,
|
List<TxData>? sparkMints,
|
||||||
|
TransactionV2? tempTx,
|
||||||
}) {
|
}) {
|
||||||
return TxData(
|
return TxData(
|
||||||
feeRateType: feeRateType ?? this.feeRateType,
|
feeRateType: feeRateType ?? this.feeRateType,
|
||||||
|
@ -187,6 +192,7 @@ class TxData {
|
||||||
tezosOperationsList: tezosOperationsList ?? this.tezosOperationsList,
|
tezosOperationsList: tezosOperationsList ?? this.tezosOperationsList,
|
||||||
sparkRecipients: sparkRecipients ?? this.sparkRecipients,
|
sparkRecipients: sparkRecipients ?? this.sparkRecipients,
|
||||||
sparkMints: sparkMints ?? this.sparkMints,
|
sparkMints: sparkMints ?? this.sparkMints,
|
||||||
|
tempTx: tempTx ?? this.tempTx,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,5 +229,6 @@ class TxData {
|
||||||
'tezosOperationsList: $tezosOperationsList, '
|
'tezosOperationsList: $tezosOperationsList, '
|
||||||
'sparkRecipients: $sparkRecipients, '
|
'sparkRecipients: $sparkRecipients, '
|
||||||
'sparkMints: $sparkMints, '
|
'sparkMints: $sparkMints, '
|
||||||
|
'tempTx: $tempTx, '
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ import 'package:stackwallet/utilities/util.dart';
|
||||||
import 'package:stackwallet/wallets/crypto_currency/coins/firo.dart';
|
import 'package:stackwallet/wallets/crypto_currency/coins/firo.dart';
|
||||||
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
|
import 'package:stackwallet/wallets/crypto_currency/crypto_currency.dart';
|
||||||
import 'package:stackwallet/wallets/isar/models/spark_coin.dart';
|
import 'package:stackwallet/wallets/isar/models/spark_coin.dart';
|
||||||
|
import 'package:stackwallet/wallets/models/tx_data.dart';
|
||||||
import 'package:stackwallet/wallets/wallet/intermediate/bip39_hd_wallet.dart';
|
import 'package:stackwallet/wallets/wallet/intermediate/bip39_hd_wallet.dart';
|
||||||
import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart';
|
import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/electrumx_interface.dart';
|
||||||
import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/lelantus_interface.dart';
|
import 'package:stackwallet/wallets/wallet/wallet_mixin_interfaces/lelantus_interface.dart';
|
||||||
|
@ -41,8 +42,23 @@ class FiroWallet extends Bip39HDWallet
|
||||||
FilterOperation? get receivingAddressFilterOperation =>
|
FilterOperation? get receivingAddressFilterOperation =>
|
||||||
FilterGroup.and(standardReceivingAddressFilters);
|
FilterGroup.and(standardReceivingAddressFilters);
|
||||||
|
|
||||||
|
final Set<String> _unconfirmedTxids = {};
|
||||||
|
|
||||||
// ===========================================================================
|
// ===========================================================================
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<TxData> updateSentCachedTxData({required TxData txData}) async {
|
||||||
|
if (txData.tempTx != null) {
|
||||||
|
await mainDB.updateOrPutTransactionV2s([txData.tempTx!]);
|
||||||
|
_unconfirmedTxids.add(txData.tempTx!.txid);
|
||||||
|
Logging.instance.log(
|
||||||
|
"Added firo unconfirmed: ${txData.tempTx!.txid}",
|
||||||
|
level: LogLevel.Info,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return txData;
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> updateTransactions() async {
|
Future<void> updateTransactions() async {
|
||||||
List<Address> allAddressesOld = await fetchAddressesForElectrumXScan();
|
List<Address> allAddressesOld = await fetchAddressesForElectrumXScan();
|
||||||
|
@ -487,7 +503,16 @@ class FiroWallet extends Bip39HDWallet
|
||||||
otherData: otherData,
|
otherData: otherData,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (_unconfirmedTxids.contains(tx.txid)) {
|
||||||
|
if (tx.isConfirmed(await chainHeight, cryptoCurrency.minConfirms)) {
|
||||||
txns.add(tx);
|
txns.add(tx);
|
||||||
|
_unconfirmedTxids.removeWhere((e) => e == tx.txid);
|
||||||
|
} else {
|
||||||
|
// don't update in db until confirmed
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
txns.add(tx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await mainDB.updateOrPutTransactionV2s(txns);
|
await mainDB.updateOrPutTransactionV2s(txns);
|
||||||
|
|
|
@ -368,7 +368,7 @@ abstract class Wallet<T extends CryptoCurrency> {
|
||||||
Future<void> updateTransactions();
|
Future<void> updateTransactions();
|
||||||
Future<void> updateBalance();
|
Future<void> updateBalance();
|
||||||
|
|
||||||
// returns true if new utxos were added to local db
|
/// returns true if new utxos were added to local db
|
||||||
Future<bool> updateUTXOs();
|
Future<bool> updateUTXOs();
|
||||||
|
|
||||||
/// updates the wallet info's cachedChainHeight
|
/// updates the wallet info's cachedChainHeight
|
||||||
|
@ -381,6 +381,14 @@ abstract class Wallet<T extends CryptoCurrency> {
|
||||||
Future<bool> pingCheck();
|
Future<bool> pingCheck();
|
||||||
|
|
||||||
//===========================================
|
//===========================================
|
||||||
|
/// add transaction to local db temporarily. Used for quickly updating ui
|
||||||
|
/// before refresh can fetch data from server
|
||||||
|
Future<TxData> updateSentCachedTxData({required TxData txData}) async {
|
||||||
|
if (txData.tempTx != null) {
|
||||||
|
await mainDB.updateOrPutTransactionV2s([txData.tempTx!]);
|
||||||
|
}
|
||||||
|
return txData;
|
||||||
|
}
|
||||||
|
|
||||||
NodeModel getCurrentNode() {
|
NodeModel getCurrentNode() {
|
||||||
final node = nodeService.getPrimaryNodeFor(coin: cryptoCurrency.coin) ??
|
final node = nodeService.getPrimaryNodeFor(coin: cryptoCurrency.coin) ??
|
||||||
|
|
|
@ -8,6 +8,9 @@ import 'package:decimal/decimal.dart';
|
||||||
import 'package:isar/isar.dart';
|
import 'package:isar/isar.dart';
|
||||||
import 'package:stackwallet/electrumx_rpc/cached_electrumx_client.dart';
|
import 'package:stackwallet/electrumx_rpc/cached_electrumx_client.dart';
|
||||||
import 'package:stackwallet/electrumx_rpc/electrumx_client.dart';
|
import 'package:stackwallet/electrumx_rpc/electrumx_client.dart';
|
||||||
|
import 'package:stackwallet/models/isar/models/blockchain_data/v2/input_v2.dart';
|
||||||
|
import 'package:stackwallet/models/isar/models/blockchain_data/v2/output_v2.dart';
|
||||||
|
import 'package:stackwallet/models/isar/models/blockchain_data/v2/transaction_v2.dart';
|
||||||
import 'package:stackwallet/models/isar/models/isar_models.dart';
|
import 'package:stackwallet/models/isar/models/isar_models.dart';
|
||||||
import 'package:stackwallet/models/paymint/fee_object_model.dart';
|
import 'package:stackwallet/models/paymint/fee_object_model.dart';
|
||||||
import 'package:stackwallet/models/signing_data.dart';
|
import 'package:stackwallet/models/signing_data.dart';
|
||||||
|
@ -172,7 +175,7 @@ mixin ElectrumXInterface on Bip39HDWallet {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
final int vSizeForOneOutput = buildTransaction(
|
final int vSizeForOneOutput = (await buildTransaction(
|
||||||
utxoSigningData: utxoSigningData,
|
utxoSigningData: utxoSigningData,
|
||||||
txData: txData.copyWith(
|
txData: txData.copyWith(
|
||||||
recipients: _helperRecipientsConvert(
|
recipients: _helperRecipientsConvert(
|
||||||
|
@ -180,7 +183,8 @@ mixin ElectrumXInterface on Bip39HDWallet {
|
||||||
[satoshisBeingUsed - 1],
|
[satoshisBeingUsed - 1],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
).vSize!;
|
))
|
||||||
|
.vSize!;
|
||||||
int feeForOneOutput = satsPerVByte != null
|
int feeForOneOutput = satsPerVByte != null
|
||||||
? (satsPerVByte * vSizeForOneOutput)
|
? (satsPerVByte * vSizeForOneOutput)
|
||||||
: estimateTxFee(
|
: estimateTxFee(
|
||||||
|
@ -200,7 +204,7 @@ mixin ElectrumXInterface on Bip39HDWallet {
|
||||||
}
|
}
|
||||||
|
|
||||||
final int amount = satoshiAmountToSend - feeForOneOutput;
|
final int amount = satoshiAmountToSend - feeForOneOutput;
|
||||||
final data = buildTransaction(
|
final data = await buildTransaction(
|
||||||
txData: txData.copyWith(
|
txData: txData.copyWith(
|
||||||
recipients: _helperRecipientsConvert(
|
recipients: _helperRecipientsConvert(
|
||||||
[recipientAddress],
|
[recipientAddress],
|
||||||
|
@ -221,7 +225,7 @@ mixin ElectrumXInterface on Bip39HDWallet {
|
||||||
|
|
||||||
final int vSizeForOneOutput;
|
final int vSizeForOneOutput;
|
||||||
try {
|
try {
|
||||||
vSizeForOneOutput = buildTransaction(
|
vSizeForOneOutput = (await buildTransaction(
|
||||||
utxoSigningData: utxoSigningData,
|
utxoSigningData: utxoSigningData,
|
||||||
txData: txData.copyWith(
|
txData: txData.copyWith(
|
||||||
recipients: _helperRecipientsConvert(
|
recipients: _helperRecipientsConvert(
|
||||||
|
@ -229,7 +233,8 @@ mixin ElectrumXInterface on Bip39HDWallet {
|
||||||
[satoshisBeingUsed - 1],
|
[satoshisBeingUsed - 1],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
).vSize!;
|
))
|
||||||
|
.vSize!;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Logging.instance.log("vSizeForOneOutput: $e", level: LogLevel.Error);
|
Logging.instance.log("vSizeForOneOutput: $e", level: LogLevel.Error);
|
||||||
rethrow;
|
rethrow;
|
||||||
|
@ -237,7 +242,7 @@ mixin ElectrumXInterface on Bip39HDWallet {
|
||||||
|
|
||||||
final int vSizeForTwoOutPuts;
|
final int vSizeForTwoOutPuts;
|
||||||
try {
|
try {
|
||||||
vSizeForTwoOutPuts = buildTransaction(
|
vSizeForTwoOutPuts = (await buildTransaction(
|
||||||
utxoSigningData: utxoSigningData,
|
utxoSigningData: utxoSigningData,
|
||||||
txData: txData.copyWith(
|
txData: txData.copyWith(
|
||||||
recipients: _helperRecipientsConvert(
|
recipients: _helperRecipientsConvert(
|
||||||
|
@ -248,7 +253,8 @@ mixin ElectrumXInterface on Bip39HDWallet {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
).vSize!;
|
))
|
||||||
|
.vSize!;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Logging.instance.log("vSizeForTwoOutPuts: $e", level: LogLevel.Error);
|
Logging.instance.log("vSizeForTwoOutPuts: $e", level: LogLevel.Error);
|
||||||
rethrow;
|
rethrow;
|
||||||
|
@ -312,7 +318,7 @@ mixin ElectrumXInterface on Bip39HDWallet {
|
||||||
Logging.instance
|
Logging.instance
|
||||||
.log('Estimated fee: $feeForTwoOutputs', level: LogLevel.Info);
|
.log('Estimated fee: $feeForTwoOutputs', level: LogLevel.Info);
|
||||||
|
|
||||||
var txn = buildTransaction(
|
var txn = await buildTransaction(
|
||||||
utxoSigningData: utxoSigningData,
|
utxoSigningData: utxoSigningData,
|
||||||
txData: txData.copyWith(
|
txData: txData.copyWith(
|
||||||
recipients: _helperRecipientsConvert(
|
recipients: _helperRecipientsConvert(
|
||||||
|
@ -343,7 +349,7 @@ mixin ElectrumXInterface on Bip39HDWallet {
|
||||||
level: LogLevel.Info);
|
level: LogLevel.Info);
|
||||||
Logging.instance.log('Adjusted Estimated fee: $feeForTwoOutputs',
|
Logging.instance.log('Adjusted Estimated fee: $feeForTwoOutputs',
|
||||||
level: LogLevel.Info);
|
level: LogLevel.Info);
|
||||||
txn = buildTransaction(
|
txn = await buildTransaction(
|
||||||
utxoSigningData: utxoSigningData,
|
utxoSigningData: utxoSigningData,
|
||||||
txData: txData.copyWith(
|
txData: txData.copyWith(
|
||||||
recipients: _helperRecipientsConvert(
|
recipients: _helperRecipientsConvert(
|
||||||
|
@ -374,7 +380,7 @@ mixin ElectrumXInterface on Bip39HDWallet {
|
||||||
level: LogLevel.Info);
|
level: LogLevel.Info);
|
||||||
Logging.instance
|
Logging.instance
|
||||||
.log('Estimated fee: $feeForOneOutput', level: LogLevel.Info);
|
.log('Estimated fee: $feeForOneOutput', level: LogLevel.Info);
|
||||||
final txn = buildTransaction(
|
final txn = await buildTransaction(
|
||||||
utxoSigningData: utxoSigningData,
|
utxoSigningData: utxoSigningData,
|
||||||
txData: txData.copyWith(
|
txData: txData.copyWith(
|
||||||
recipients: _helperRecipientsConvert(
|
recipients: _helperRecipientsConvert(
|
||||||
|
@ -406,7 +412,7 @@ mixin ElectrumXInterface on Bip39HDWallet {
|
||||||
level: LogLevel.Info);
|
level: LogLevel.Info);
|
||||||
Logging.instance
|
Logging.instance
|
||||||
.log('Estimated fee: $feeForOneOutput', level: LogLevel.Info);
|
.log('Estimated fee: $feeForOneOutput', level: LogLevel.Info);
|
||||||
final txn = buildTransaction(
|
final txn = await buildTransaction(
|
||||||
utxoSigningData: utxoSigningData,
|
utxoSigningData: utxoSigningData,
|
||||||
txData: txData.copyWith(
|
txData: txData.copyWith(
|
||||||
recipients: _helperRecipientsConvert(
|
recipients: _helperRecipientsConvert(
|
||||||
|
@ -438,7 +444,7 @@ mixin ElectrumXInterface on Bip39HDWallet {
|
||||||
level: LogLevel.Info);
|
level: LogLevel.Info);
|
||||||
Logging.instance
|
Logging.instance
|
||||||
.log('Estimated fee: $feeForOneOutput', level: LogLevel.Info);
|
.log('Estimated fee: $feeForOneOutput', level: LogLevel.Info);
|
||||||
final txn = buildTransaction(
|
final txn = await buildTransaction(
|
||||||
utxoSigningData: utxoSigningData,
|
utxoSigningData: utxoSigningData,
|
||||||
txData: txData.copyWith(
|
txData: txData.copyWith(
|
||||||
recipients: _helperRecipientsConvert(
|
recipients: _helperRecipientsConvert(
|
||||||
|
@ -615,10 +621,10 @@ mixin ElectrumXInterface on Bip39HDWallet {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builds and signs a transaction
|
/// Builds and signs a transaction
|
||||||
TxData buildTransaction({
|
Future<TxData> buildTransaction({
|
||||||
required TxData txData,
|
required TxData txData,
|
||||||
required List<SigningData> utxoSigningData,
|
required List<SigningData> utxoSigningData,
|
||||||
}) {
|
}) async {
|
||||||
Logging.instance
|
Logging.instance
|
||||||
.log("Starting buildTransaction ----------", level: LogLevel.Info);
|
.log("Starting buildTransaction ----------", level: LogLevel.Info);
|
||||||
|
|
||||||
|
@ -637,7 +643,12 @@ mixin ElectrumXInterface on Bip39HDWallet {
|
||||||
wif: cryptoCurrency.networkParams.wifPrefix,
|
wif: cryptoCurrency.networkParams.wifPrefix,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
txb.setVersion(1); // TODO possibly override this for certain coins?
|
const version = 1; // TODO possibly override this for certain coins?
|
||||||
|
txb.setVersion(version);
|
||||||
|
|
||||||
|
// temp tx data to show in gui while waiting for real data from server
|
||||||
|
final List<InputV2> tempInputs = [];
|
||||||
|
final List<OutputV2> tempOutputs = [];
|
||||||
|
|
||||||
// Add transaction inputs
|
// Add transaction inputs
|
||||||
for (var i = 0; i < utxoSigningData.length; i++) {
|
for (var i = 0; i < utxoSigningData.length; i++) {
|
||||||
|
@ -649,6 +660,25 @@ mixin ElectrumXInterface on Bip39HDWallet {
|
||||||
utxoSigningData[i].output!,
|
utxoSigningData[i].output!,
|
||||||
cryptoCurrency.networkParams.bech32Hrp,
|
cryptoCurrency.networkParams.bech32Hrp,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
tempInputs.add(
|
||||||
|
InputV2.isarCantDoRequiredInDefaultConstructor(
|
||||||
|
scriptSigHex: txb.inputs.first.script?.toHex,
|
||||||
|
sequence: 0xffffffff - 1,
|
||||||
|
outpoint: OutpointV2.isarCantDoRequiredInDefaultConstructor(
|
||||||
|
txid: utxoSigningData[i].utxo.txid,
|
||||||
|
vout: utxoSigningData[i].utxo.vout,
|
||||||
|
),
|
||||||
|
addresses: utxoSigningData[i].utxo.address == null
|
||||||
|
? []
|
||||||
|
: [utxoSigningData[i].utxo.address!],
|
||||||
|
valueStringSats: utxoSigningData[i].utxo.value.toString(),
|
||||||
|
witness: null,
|
||||||
|
innerRedeemScriptAsm: null,
|
||||||
|
coinbase: null,
|
||||||
|
walletOwns: true,
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add transaction output
|
// Add transaction output
|
||||||
|
@ -658,6 +688,24 @@ mixin ElectrumXInterface on Bip39HDWallet {
|
||||||
txData.recipients![i].amount.raw.toInt(),
|
txData.recipients![i].amount.raw.toInt(),
|
||||||
cryptoCurrency.networkParams.bech32Hrp,
|
cryptoCurrency.networkParams.bech32Hrp,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
tempOutputs.add(
|
||||||
|
OutputV2.isarCantDoRequiredInDefaultConstructor(
|
||||||
|
scriptPubKeyHex: "000000",
|
||||||
|
valueStringSats: txData.recipients![i].amount.raw.toString(),
|
||||||
|
addresses: [
|
||||||
|
txData.recipients![i].address.toString(),
|
||||||
|
],
|
||||||
|
walletOwns: (await mainDB.isar.addresses
|
||||||
|
.where()
|
||||||
|
.walletIdEqualTo(walletId)
|
||||||
|
.filter()
|
||||||
|
.valueEqualTo(txData.recipients![i].address)
|
||||||
|
.valueProperty()
|
||||||
|
.findFirst()) !=
|
||||||
|
null,
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -683,6 +731,22 @@ mixin ElectrumXInterface on Bip39HDWallet {
|
||||||
return txData.copyWith(
|
return txData.copyWith(
|
||||||
raw: builtTx.toHex(),
|
raw: builtTx.toHex(),
|
||||||
vSize: vSize,
|
vSize: vSize,
|
||||||
|
tempTx: TransactionV2(
|
||||||
|
walletId: walletId,
|
||||||
|
blockHash: null,
|
||||||
|
hash: builtTx.getId(),
|
||||||
|
txid: builtTx.getId(),
|
||||||
|
height: null,
|
||||||
|
timestamp: DateTime.timestamp().millisecondsSinceEpoch ~/ 1000,
|
||||||
|
inputs: List.unmodifiable(tempInputs),
|
||||||
|
outputs: List.unmodifiable(tempOutputs),
|
||||||
|
version: version,
|
||||||
|
type: tempOutputs.map((e) => e.walletOwns).fold(true, (p, e) => p &= e)
|
||||||
|
? TransactionType.sentToSelf
|
||||||
|
: TransactionType.outgoing,
|
||||||
|
subType: TransactionSubType.none,
|
||||||
|
otherData: null,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1749,7 +1813,7 @@ mixin ElectrumXInterface on Bip39HDWallet {
|
||||||
// mark utxos as used
|
// mark utxos as used
|
||||||
await mainDB.putUTXOs(txData.usedUTXOs!);
|
await mainDB.putUTXOs(txData.usedUTXOs!);
|
||||||
|
|
||||||
return txData;
|
return await updateSentCachedTxData(txData: txData);
|
||||||
} catch (e, s) {
|
} catch (e, s) {
|
||||||
Logging.instance.log("Exception rethrown from confirmSend(): $e\n$s",
|
Logging.instance.log("Exception rethrown from confirmSend(): $e\n$s",
|
||||||
level: LogLevel.Error);
|
level: LogLevel.Error);
|
||||||
|
|
|
@ -7,6 +7,9 @@ import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter_libsparkmobile/flutter_libsparkmobile.dart';
|
import 'package:flutter_libsparkmobile/flutter_libsparkmobile.dart';
|
||||||
import 'package:isar/isar.dart';
|
import 'package:isar/isar.dart';
|
||||||
import 'package:stackwallet/models/balance.dart';
|
import 'package:stackwallet/models/balance.dart';
|
||||||
|
import 'package:stackwallet/models/isar/models/blockchain_data/v2/input_v2.dart';
|
||||||
|
import 'package:stackwallet/models/isar/models/blockchain_data/v2/output_v2.dart';
|
||||||
|
import 'package:stackwallet/models/isar/models/blockchain_data/v2/transaction_v2.dart';
|
||||||
import 'package:stackwallet/models/isar/models/isar_models.dart';
|
import 'package:stackwallet/models/isar/models/isar_models.dart';
|
||||||
import 'package:stackwallet/models/signing_data.dart';
|
import 'package:stackwallet/models/signing_data.dart';
|
||||||
import 'package:stackwallet/utilities/amount/amount.dart';
|
import 'package:stackwallet/utilities/amount/amount.dart';
|
||||||
|
@ -331,6 +334,10 @@ mixin SparkInterface on Bip39HDWallet, ElectrumXInterface {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// temp tx data to show in gui while waiting for real data from server
|
||||||
|
final List<InputV2> tempInputs = [];
|
||||||
|
final List<OutputV2> tempOutputs = [];
|
||||||
|
|
||||||
for (int i = 0; i < (txData.recipients?.length ?? 0); i++) {
|
for (int i = 0; i < (txData.recipients?.length ?? 0); i++) {
|
||||||
if (txData.recipients![i].amount.raw == BigInt.zero) {
|
if (txData.recipients![i].amount.raw == BigInt.zero) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -354,8 +361,62 @@ mixin SparkInterface on Bip39HDWallet, ElectrumXInterface {
|
||||||
scriptPubKey,
|
scriptPubKey,
|
||||||
recipientsWithFeeSubtracted[i].amount.raw.toInt(),
|
recipientsWithFeeSubtracted[i].amount.raw.toInt(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
tempOutputs.add(
|
||||||
|
OutputV2.isarCantDoRequiredInDefaultConstructor(
|
||||||
|
scriptPubKeyHex: scriptPubKey.toHex,
|
||||||
|
valueStringSats: recipientsWithFeeSubtracted[i].amount.raw.toString(),
|
||||||
|
addresses: [
|
||||||
|
recipientsWithFeeSubtracted[i].address.toString(),
|
||||||
|
],
|
||||||
|
walletOwns: (await mainDB.isar.addresses
|
||||||
|
.where()
|
||||||
|
.walletIdEqualTo(walletId)
|
||||||
|
.filter()
|
||||||
|
.valueEqualTo(recipientsWithFeeSubtracted[i].address)
|
||||||
|
.valueProperty()
|
||||||
|
.findFirst()) !=
|
||||||
|
null,
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sparkRecipientsWithFeeSubtracted != null) {
|
||||||
|
for (final recip in sparkRecipientsWithFeeSubtracted) {
|
||||||
|
tempOutputs.add(
|
||||||
|
OutputV2.isarCantDoRequiredInDefaultConstructor(
|
||||||
|
scriptPubKeyHex: Uint8List.fromList([OP_SPARKSMINT]).toHex,
|
||||||
|
valueStringSats: recip.amount.raw.toString(),
|
||||||
|
addresses: [
|
||||||
|
recip.address.toString(),
|
||||||
|
],
|
||||||
|
walletOwns: (await mainDB.isar.addresses
|
||||||
|
.where()
|
||||||
|
.walletIdEqualTo(walletId)
|
||||||
|
.filter()
|
||||||
|
.valueEqualTo(recip.address)
|
||||||
|
.valueProperty()
|
||||||
|
.findFirst()) !=
|
||||||
|
null,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tempInputs.add(
|
||||||
|
InputV2.isarCantDoRequiredInDefaultConstructor(
|
||||||
|
scriptSigHex: "d3",
|
||||||
|
sequence: 0xffffffff,
|
||||||
|
outpoint: null,
|
||||||
|
addresses: [],
|
||||||
|
valueStringSats: "0",
|
||||||
|
witness: null,
|
||||||
|
innerRedeemScriptAsm: null,
|
||||||
|
coinbase: null,
|
||||||
|
walletOwns: true,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
final extractedTx = txb.buildIncomplete();
|
final extractedTx = txb.buildIncomplete();
|
||||||
extractedTx.addInput(
|
extractedTx.addInput(
|
||||||
'0000000000000000000000000000000000000000000000000000000000000000'
|
'0000000000000000000000000000000000000000000000000000000000000000'
|
||||||
|
@ -412,12 +473,33 @@ mixin SparkInterface on Bip39HDWallet, ElectrumXInterface {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final fee = Amount(
|
||||||
|
rawValue: BigInt.from(spend.fee),
|
||||||
|
fractionDigits: cryptoCurrency.fractionDigits,
|
||||||
|
);
|
||||||
return txData.copyWith(
|
return txData.copyWith(
|
||||||
raw: rawTxHex,
|
raw: rawTxHex,
|
||||||
vSize: extractedTx.virtualSize(),
|
vSize: extractedTx.virtualSize(),
|
||||||
fee: Amount(
|
fee: fee,
|
||||||
rawValue: BigInt.from(spend.fee),
|
tempTx: TransactionV2(
|
||||||
fractionDigits: cryptoCurrency.fractionDigits,
|
walletId: walletId,
|
||||||
|
blockHash: null,
|
||||||
|
hash: extractedTx.getId(),
|
||||||
|
txid: extractedTx.getId(),
|
||||||
|
timestamp: DateTime.timestamp().millisecondsSinceEpoch ~/ 1000,
|
||||||
|
inputs: List.unmodifiable(tempInputs),
|
||||||
|
outputs: List.unmodifiable(tempOutputs),
|
||||||
|
type: tempOutputs.map((e) => e.walletOwns).fold(true, (p, e) => p &= e)
|
||||||
|
? TransactionType.sentToSelf
|
||||||
|
: TransactionType.outgoing,
|
||||||
|
subType: TransactionSubType.sparkSpend,
|
||||||
|
otherData: jsonEncode(
|
||||||
|
{
|
||||||
|
"anonFees": fee.toJsonString(),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
height: null,
|
||||||
|
version: 3,
|
||||||
),
|
),
|
||||||
// TODO used coins
|
// TODO used coins
|
||||||
);
|
);
|
||||||
|
@ -448,7 +530,7 @@ mixin SparkInterface on Bip39HDWallet, ElectrumXInterface {
|
||||||
// // mark utxos as used
|
// // mark utxos as used
|
||||||
// await mainDB.putUTXOs(txData.usedUTXOs!);
|
// await mainDB.putUTXOs(txData.usedUTXOs!);
|
||||||
|
|
||||||
return txData;
|
return await updateSentCachedTxData(txData: txData);
|
||||||
} catch (e, s) {
|
} catch (e, s) {
|
||||||
Logging.instance.log("Exception rethrown from confirmSend(): $e\n$s",
|
Logging.instance.log("Exception rethrown from confirmSend(): $e\n$s",
|
||||||
level: LogLevel.Error);
|
level: LogLevel.Error);
|
||||||
|
@ -702,7 +784,7 @@ mixin SparkInterface on Bip39HDWallet, ElectrumXInterface {
|
||||||
: currentHeight;
|
: currentHeight;
|
||||||
const txVersion = 1;
|
const txVersion = 1;
|
||||||
final List<SigningData> vin = [];
|
final List<SigningData> vin = [];
|
||||||
final List<(dynamic, int)> vout = [];
|
final List<(dynamic, int, String?)> vout = [];
|
||||||
|
|
||||||
BigInt nFeeRet = BigInt.zero;
|
BigInt nFeeRet = BigInt.zero;
|
||||||
|
|
||||||
|
@ -821,13 +903,15 @@ mixin SparkInterface on Bip39HDWallet, ElectrumXInterface {
|
||||||
final dummyTxb = btc.TransactionBuilder(network: _bitcoinDartNetwork);
|
final dummyTxb = btc.TransactionBuilder(network: _bitcoinDartNetwork);
|
||||||
dummyTxb.setVersion(txVersion);
|
dummyTxb.setVersion(txVersion);
|
||||||
dummyTxb.setLockTime(lockTime);
|
dummyTxb.setLockTime(lockTime);
|
||||||
for (final recipient in dummyRecipients) {
|
for (int i = 0; i < dummyRecipients.length; i++) {
|
||||||
|
final recipient = dummyRecipients[i];
|
||||||
if (recipient.amount < cryptoCurrency.dustLimit.raw.toInt()) {
|
if (recipient.amount < cryptoCurrency.dustLimit.raw.toInt()) {
|
||||||
throw Exception("Output amount too small");
|
throw Exception("Output amount too small");
|
||||||
}
|
}
|
||||||
vout.add((
|
vout.add((
|
||||||
recipient.scriptPubKey,
|
recipient.scriptPubKey,
|
||||||
recipient.amount,
|
recipient.amount,
|
||||||
|
singleTxOutputs[i].address,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -860,7 +944,7 @@ mixin SparkInterface on Bip39HDWallet, ElectrumXInterface {
|
||||||
final changeAddress = await getCurrentChangeAddress();
|
final changeAddress = await getCurrentChangeAddress();
|
||||||
vout.insert(
|
vout.insert(
|
||||||
nChangePosInOut,
|
nChangePosInOut,
|
||||||
(changeAddress!.value, nChange.toInt()),
|
(changeAddress!.value, nChange.toInt(), null),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -942,8 +1026,13 @@ mixin SparkInterface on Bip39HDWallet, ElectrumXInterface {
|
||||||
);
|
);
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (final recipient in recipients) {
|
for (int i = 0; i < recipients.length; i++) {
|
||||||
final out = (recipient.scriptPubKey, recipient.amount);
|
final recipient = recipients[i];
|
||||||
|
final out = (
|
||||||
|
recipient.scriptPubKey,
|
||||||
|
recipient.amount,
|
||||||
|
singleTxOutputs[i].address,
|
||||||
|
);
|
||||||
while (i < vout.length) {
|
while (i < vout.length) {
|
||||||
if (vout[i].$1 is Uint8List &&
|
if (vout[i].$1 is Uint8List &&
|
||||||
(vout[i].$1 as Uint8List).isNotEmpty &&
|
(vout[i].$1 as Uint8List).isNotEmpty &&
|
||||||
|
@ -973,6 +1062,10 @@ mixin SparkInterface on Bip39HDWallet, ElectrumXInterface {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// temp tx data to show in gui while waiting for real data from server
|
||||||
|
final List<InputV2> tempInputs = [];
|
||||||
|
final List<OutputV2> tempOutputs = [];
|
||||||
|
|
||||||
// sign
|
// sign
|
||||||
final txb = btc.TransactionBuilder(network: _bitcoinDartNetwork);
|
final txb = btc.TransactionBuilder(network: _bitcoinDartNetwork);
|
||||||
txb.setVersion(txVersion);
|
txb.setVersion(txVersion);
|
||||||
|
@ -985,10 +1078,50 @@ mixin SparkInterface on Bip39HDWallet, ElectrumXInterface {
|
||||||
1, // minus 1 is important. 0xffffffff on its own will burn funds
|
1, // minus 1 is important. 0xffffffff on its own will burn funds
|
||||||
input.output,
|
input.output,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
tempInputs.add(
|
||||||
|
InputV2.isarCantDoRequiredInDefaultConstructor(
|
||||||
|
scriptSigHex: txb.inputs.first.script?.toHex,
|
||||||
|
sequence: 0xffffffff - 1,
|
||||||
|
outpoint: OutpointV2.isarCantDoRequiredInDefaultConstructor(
|
||||||
|
txid: input.utxo.txid,
|
||||||
|
vout: input.utxo.vout,
|
||||||
|
),
|
||||||
|
addresses: input.utxo.address == null ? [] : [input.utxo.address!],
|
||||||
|
valueStringSats: input.utxo.value.toString(),
|
||||||
|
witness: null,
|
||||||
|
innerRedeemScriptAsm: null,
|
||||||
|
coinbase: null,
|
||||||
|
walletOwns: true,
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (final output in vout) {
|
for (final output in vout) {
|
||||||
txb.addOutput(output.$1, output.$2);
|
final addressOrScript = output.$1;
|
||||||
|
final value = output.$2;
|
||||||
|
txb.addOutput(addressOrScript, value);
|
||||||
|
|
||||||
|
tempOutputs.add(
|
||||||
|
OutputV2.isarCantDoRequiredInDefaultConstructor(
|
||||||
|
scriptPubKeyHex:
|
||||||
|
addressOrScript is Uint8List ? addressOrScript.toHex : "000000",
|
||||||
|
valueStringSats: value.toString(),
|
||||||
|
addresses: [
|
||||||
|
if (addressOrScript is String) addressOrScript.toString(),
|
||||||
|
],
|
||||||
|
walletOwns: (await mainDB.isar.addresses
|
||||||
|
.where()
|
||||||
|
.walletIdEqualTo(walletId)
|
||||||
|
.filter()
|
||||||
|
.valueEqualTo(addressOrScript is Uint8List
|
||||||
|
? output.$3!
|
||||||
|
: addressOrScript as String)
|
||||||
|
.valueProperty()
|
||||||
|
.findFirst()) !=
|
||||||
|
null,
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -1035,6 +1168,23 @@ mixin SparkInterface on Bip39HDWallet, ElectrumXInterface {
|
||||||
fractionDigits: cryptoCurrency.fractionDigits,
|
fractionDigits: cryptoCurrency.fractionDigits,
|
||||||
),
|
),
|
||||||
usedUTXOs: vin.map((e) => e.utxo).toList(),
|
usedUTXOs: vin.map((e) => e.utxo).toList(),
|
||||||
|
tempTx: TransactionV2(
|
||||||
|
walletId: walletId,
|
||||||
|
blockHash: null,
|
||||||
|
hash: builtTx.getId(),
|
||||||
|
txid: builtTx.getId(),
|
||||||
|
timestamp: DateTime.timestamp().millisecondsSinceEpoch ~/ 1000,
|
||||||
|
inputs: List.unmodifiable(tempInputs),
|
||||||
|
outputs: List.unmodifiable(tempOutputs),
|
||||||
|
type:
|
||||||
|
tempOutputs.map((e) => e.walletOwns).fold(true, (p, e) => p &= e)
|
||||||
|
? TransactionType.sentToSelf
|
||||||
|
: TransactionType.outgoing,
|
||||||
|
subType: TransactionSubType.sparkMint,
|
||||||
|
otherData: null,
|
||||||
|
height: null,
|
||||||
|
version: 3,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (nFeeRet.toInt() < data.vSize!) {
|
if (nFeeRet.toInt() < data.vSize!) {
|
||||||
|
|
Loading…
Reference in a new issue