Including unconfirmed transactions for wallet balances while spending foreign coin. This is for sends and for responding to trade sell orders. This is not for any other stages in the trading process after the initial response.

This commit is contained in:
kennycud 2024-07-27 12:50:22 -07:00
parent 211fc0d5a4
commit da889f2905
12 changed files with 30 additions and 30 deletions

View File

@ -157,7 +157,7 @@ public class CrossChainHtlcResource {
htlcStatus.bitcoinP2shAddress = p2shAddress;
htlcStatus.bitcoinP2shBalance = BigDecimal.valueOf(p2shBalance, 8);
List<TransactionOutput> fundingOutputs = bitcoiny.getUnspentOutputs(p2shAddress.toString());
List<TransactionOutput> fundingOutputs = bitcoiny.getUnspentOutputs(p2shAddress.toString(), false);
if (p2shBalance > 0L && !fundingOutputs.isEmpty()) {
htlcStatus.canRedeem = now >= medianBlockTime * 1000L;
@ -401,7 +401,7 @@ public class CrossChainHtlcResource {
case FUNDED: {
Coin redeemAmount = Coin.valueOf(crossChainTradeData.expectedForeignAmount);
ECKey redeemKey = ECKey.fromPrivate(decodedTradePrivateKey);
List<TransactionOutput> fundingOutputs = bitcoiny.getUnspentOutputs(p2shAddressA);
List<TransactionOutput> fundingOutputs = bitcoiny.getUnspentOutputs(p2shAddressA, false);
Transaction p2shRedeemTransaction = BitcoinyHTLC.buildRedeemTransaction(bitcoiny.getNetworkParameters(), redeemAmount, redeemKey,
fundingOutputs, redeemScriptA, decodedSecret, foreignBlockchainReceivingAccountInfo);
@ -664,7 +664,7 @@ public class CrossChainHtlcResource {
// ElectrumX coins
ECKey refundKey = ECKey.fromPrivate(tradeBotData.getTradePrivateKey());
List<TransactionOutput> fundingOutputs = bitcoiny.getUnspentOutputs(p2shAddressA);
List<TransactionOutput> fundingOutputs = bitcoiny.getUnspentOutputs(p2shAddressA, false);
// Validate the destination foreign blockchain address
Address receiving = Address.fromString(bitcoiny.getNetworkParameters(), receiveAddress);

View File

@ -894,7 +894,7 @@ public class BitcoinACCTv1TradeBot implements AcctTradeBot {
// Redeem P2SH-B using secret-B
Coin redeemAmount = Coin.valueOf(P2SH_B_OUTPUT_AMOUNT); // An actual amount to avoid dust filter, remaining used as fees. The real funds are in P2SH-A.
ECKey redeemKey = ECKey.fromPrivate(tradeBotData.getTradePrivateKey());
List<TransactionOutput> fundingOutputs = bitcoin.getUnspentOutputs(p2shAddressB);
List<TransactionOutput> fundingOutputs = bitcoin.getUnspentOutputs(p2shAddressB, false);
byte[] receivingAccountInfo = tradeBotData.getReceivingAccountInfo();
Transaction p2shRedeemTransaction = BitcoinyHTLC.buildRedeemTransaction(bitcoin.getNetworkParameters(), redeemAmount, redeemKey,
@ -1064,7 +1064,7 @@ public class BitcoinACCTv1TradeBot implements AcctTradeBot {
case FUNDED: {
Coin redeemAmount = Coin.valueOf(crossChainTradeData.expectedForeignAmount - P2SH_B_OUTPUT_AMOUNT);
ECKey redeemKey = ECKey.fromPrivate(tradeBotData.getTradePrivateKey());
List<TransactionOutput> fundingOutputs = bitcoin.getUnspentOutputs(p2shAddressA);
List<TransactionOutput> fundingOutputs = bitcoin.getUnspentOutputs(p2shAddressA, false);
Transaction p2shRedeemTransaction = BitcoinyHTLC.buildRedeemTransaction(bitcoin.getNetworkParameters(), redeemAmount, redeemKey,
fundingOutputs, redeemScriptA, secretA, receivingAccountInfo);
@ -1136,7 +1136,7 @@ public class BitcoinACCTv1TradeBot implements AcctTradeBot {
case FUNDED:{
Coin refundAmount = Coin.valueOf(P2SH_B_OUTPUT_AMOUNT); // An actual amount to avoid dust filter, remaining used as fees.
ECKey refundKey = ECKey.fromPrivate(tradeBotData.getTradePrivateKey());
List<TransactionOutput> fundingOutputs = bitcoin.getUnspentOutputs(p2shAddressB);
List<TransactionOutput> fundingOutputs = bitcoin.getUnspentOutputs(p2shAddressB, false);
// Determine receive address for refund
String receiveAddress = bitcoin.getUnusedReceiveAddress(tradeBotData.getForeignKey());
@ -1202,7 +1202,7 @@ public class BitcoinACCTv1TradeBot implements AcctTradeBot {
case FUNDED:{
Coin refundAmount = Coin.valueOf(crossChainTradeData.expectedForeignAmount - P2SH_B_OUTPUT_AMOUNT);
ECKey refundKey = ECKey.fromPrivate(tradeBotData.getTradePrivateKey());
List<TransactionOutput> fundingOutputs = bitcoin.getUnspentOutputs(p2shAddressA);
List<TransactionOutput> fundingOutputs = bitcoin.getUnspentOutputs(p2shAddressA, false);
// Determine receive address for refund
String receiveAddress = bitcoin.getUnusedReceiveAddress(tradeBotData.getForeignKey());

View File

@ -752,7 +752,7 @@ public class BitcoinACCTv3TradeBot implements AcctTradeBot {
case FUNDED: {
Coin redeemAmount = Coin.valueOf(crossChainTradeData.expectedForeignAmount);
ECKey redeemKey = ECKey.fromPrivate(tradeBotData.getTradePrivateKey());
List<TransactionOutput> fundingOutputs = bitcoin.getUnspentOutputs(p2shAddressA);
List<TransactionOutput> fundingOutputs = bitcoin.getUnspentOutputs(p2shAddressA, false);
Transaction p2shRedeemTransaction = BitcoinyHTLC.buildRedeemTransaction(bitcoin.getNetworkParameters(), redeemAmount, redeemKey,
fundingOutputs, redeemScriptA, secretA, receivingAccountInfo);
@ -816,7 +816,7 @@ public class BitcoinACCTv3TradeBot implements AcctTradeBot {
case FUNDED:{
Coin refundAmount = Coin.valueOf(crossChainTradeData.expectedForeignAmount);
ECKey refundKey = ECKey.fromPrivate(tradeBotData.getTradePrivateKey());
List<TransactionOutput> fundingOutputs = bitcoin.getUnspentOutputs(p2shAddressA);
List<TransactionOutput> fundingOutputs = bitcoin.getUnspentOutputs(p2shAddressA, false);
// Determine receive address for refund
String receiveAddress = bitcoin.getUnusedReceiveAddress(tradeBotData.getForeignKey());

View File

@ -753,7 +753,7 @@ public class DigibyteACCTv3TradeBot implements AcctTradeBot {
case FUNDED: {
Coin redeemAmount = Coin.valueOf(crossChainTradeData.expectedForeignAmount);
ECKey redeemKey = ECKey.fromPrivate(tradeBotData.getTradePrivateKey());
List<TransactionOutput> fundingOutputs = digibyte.getUnspentOutputs(p2shAddressA);
List<TransactionOutput> fundingOutputs = digibyte.getUnspentOutputs(p2shAddressA, false);
Transaction p2shRedeemTransaction = BitcoinyHTLC.buildRedeemTransaction(digibyte.getNetworkParameters(), redeemAmount, redeemKey,
fundingOutputs, redeemScriptA, secretA, receivingAccountInfo);
@ -817,7 +817,7 @@ public class DigibyteACCTv3TradeBot implements AcctTradeBot {
case FUNDED:{
Coin refundAmount = Coin.valueOf(crossChainTradeData.expectedForeignAmount);
ECKey refundKey = ECKey.fromPrivate(tradeBotData.getTradePrivateKey());
List<TransactionOutput> fundingOutputs = digibyte.getUnspentOutputs(p2shAddressA);
List<TransactionOutput> fundingOutputs = digibyte.getUnspentOutputs(p2shAddressA, false);
// Determine receive address for refund
String receiveAddress = digibyte.getUnusedReceiveAddress(tradeBotData.getForeignKey());

View File

@ -794,7 +794,7 @@ public class DogecoinACCTv1TradeBot implements AcctTradeBot {
case FUNDED: {
Coin redeemAmount = Coin.valueOf(crossChainTradeData.expectedForeignAmount);
ECKey redeemKey = ECKey.fromPrivate(tradeBotData.getTradePrivateKey());
List<TransactionOutput> fundingOutputs = dogecoin.getUnspentOutputs(p2shAddressA);
List<TransactionOutput> fundingOutputs = dogecoin.getUnspentOutputs(p2shAddressA, false);
Transaction p2shRedeemTransaction = BitcoinyHTLC.buildRedeemTransaction(dogecoin.getNetworkParameters(), redeemAmount, redeemKey,
fundingOutputs, redeemScriptA, secretA, receivingAccountInfo);
@ -858,7 +858,7 @@ public class DogecoinACCTv1TradeBot implements AcctTradeBot {
case FUNDED:{
Coin refundAmount = Coin.valueOf(crossChainTradeData.expectedForeignAmount);
ECKey refundKey = ECKey.fromPrivate(tradeBotData.getTradePrivateKey());
List<TransactionOutput> fundingOutputs = dogecoin.getUnspentOutputs(p2shAddressA);
List<TransactionOutput> fundingOutputs = dogecoin.getUnspentOutputs(p2shAddressA, false);
// Determine receive address for refund
String receiveAddress = dogecoin.getUnusedReceiveAddress(tradeBotData.getForeignKey());

View File

@ -753,7 +753,7 @@ public class DogecoinACCTv3TradeBot implements AcctTradeBot {
case FUNDED: {
Coin redeemAmount = Coin.valueOf(crossChainTradeData.expectedForeignAmount);
ECKey redeemKey = ECKey.fromPrivate(tradeBotData.getTradePrivateKey());
List<TransactionOutput> fundingOutputs = dogecoin.getUnspentOutputs(p2shAddressA);
List<TransactionOutput> fundingOutputs = dogecoin.getUnspentOutputs(p2shAddressA, false);
Transaction p2shRedeemTransaction = BitcoinyHTLC.buildRedeemTransaction(dogecoin.getNetworkParameters(), redeemAmount, redeemKey,
fundingOutputs, redeemScriptA, secretA, receivingAccountInfo);
@ -817,7 +817,7 @@ public class DogecoinACCTv3TradeBot implements AcctTradeBot {
case FUNDED:{
Coin refundAmount = Coin.valueOf(crossChainTradeData.expectedForeignAmount);
ECKey refundKey = ECKey.fromPrivate(tradeBotData.getTradePrivateKey());
List<TransactionOutput> fundingOutputs = dogecoin.getUnspentOutputs(p2shAddressA);
List<TransactionOutput> fundingOutputs = dogecoin.getUnspentOutputs(p2shAddressA, false);
// Determine receive address for refund
String receiveAddress = dogecoin.getUnusedReceiveAddress(tradeBotData.getForeignKey());

View File

@ -757,7 +757,7 @@ public class LitecoinACCTv1TradeBot implements AcctTradeBot {
case FUNDED: {
Coin redeemAmount = Coin.valueOf(crossChainTradeData.expectedForeignAmount);
ECKey redeemKey = ECKey.fromPrivate(tradeBotData.getTradePrivateKey());
List<TransactionOutput> fundingOutputs = litecoin.getUnspentOutputs(p2shAddressA);
List<TransactionOutput> fundingOutputs = litecoin.getUnspentOutputs(p2shAddressA, false);
Transaction p2shRedeemTransaction = BitcoinyHTLC.buildRedeemTransaction(litecoin.getNetworkParameters(), redeemAmount, redeemKey,
fundingOutputs, redeemScriptA, secretA, receivingAccountInfo);
@ -821,7 +821,7 @@ public class LitecoinACCTv1TradeBot implements AcctTradeBot {
case FUNDED:{
Coin refundAmount = Coin.valueOf(crossChainTradeData.expectedForeignAmount);
ECKey refundKey = ECKey.fromPrivate(tradeBotData.getTradePrivateKey());
List<TransactionOutput> fundingOutputs = litecoin.getUnspentOutputs(p2shAddressA);
List<TransactionOutput> fundingOutputs = litecoin.getUnspentOutputs(p2shAddressA, false);
// Determine receive address for refund
String receiveAddress = litecoin.getUnusedReceiveAddress(tradeBotData.getForeignKey());

View File

@ -752,7 +752,7 @@ public class LitecoinACCTv3TradeBot implements AcctTradeBot {
case FUNDED: {
Coin redeemAmount = Coin.valueOf(crossChainTradeData.expectedForeignAmount);
ECKey redeemKey = ECKey.fromPrivate(tradeBotData.getTradePrivateKey());
List<TransactionOutput> fundingOutputs = litecoin.getUnspentOutputs(p2shAddressA);
List<TransactionOutput> fundingOutputs = litecoin.getUnspentOutputs(p2shAddressA, false);
Transaction p2shRedeemTransaction = BitcoinyHTLC.buildRedeemTransaction(litecoin.getNetworkParameters(), redeemAmount, redeemKey,
fundingOutputs, redeemScriptA, secretA, receivingAccountInfo);
@ -816,7 +816,7 @@ public class LitecoinACCTv3TradeBot implements AcctTradeBot {
case FUNDED:{
Coin refundAmount = Coin.valueOf(crossChainTradeData.expectedForeignAmount);
ECKey refundKey = ECKey.fromPrivate(tradeBotData.getTradePrivateKey());
List<TransactionOutput> fundingOutputs = litecoin.getUnspentOutputs(p2shAddressA);
List<TransactionOutput> fundingOutputs = litecoin.getUnspentOutputs(p2shAddressA, false);
// Determine receive address for refund
String receiveAddress = litecoin.getUnusedReceiveAddress(tradeBotData.getForeignKey());

View File

@ -753,7 +753,7 @@ public class RavencoinACCTv3TradeBot implements AcctTradeBot {
case FUNDED: {
Coin redeemAmount = Coin.valueOf(crossChainTradeData.expectedForeignAmount);
ECKey redeemKey = ECKey.fromPrivate(tradeBotData.getTradePrivateKey());
List<TransactionOutput> fundingOutputs = ravencoin.getUnspentOutputs(p2shAddressA);
List<TransactionOutput> fundingOutputs = ravencoin.getUnspentOutputs(p2shAddressA, false);
Transaction p2shRedeemTransaction = BitcoinyHTLC.buildRedeemTransaction(ravencoin.getNetworkParameters(), redeemAmount, redeemKey,
fundingOutputs, redeemScriptA, secretA, receivingAccountInfo);
@ -817,7 +817,7 @@ public class RavencoinACCTv3TradeBot implements AcctTradeBot {
case FUNDED:{
Coin refundAmount = Coin.valueOf(crossChainTradeData.expectedForeignAmount);
ECKey refundKey = ECKey.fromPrivate(tradeBotData.getTradePrivateKey());
List<TransactionOutput> fundingOutputs = ravencoin.getUnspentOutputs(p2shAddressA);
List<TransactionOutput> fundingOutputs = ravencoin.getUnspentOutputs(p2shAddressA, false);
// Determine receive address for refund
String receiveAddress = ravencoin.getUnusedReceiveAddress(tradeBotData.getForeignKey());

View File

@ -208,8 +208,8 @@ public abstract class Bitcoiny implements ForeignBlockchain {
* @throws ForeignBlockchainException if there was an error.
*/
// TODO: don't return bitcoinj-based objects like TransactionOutput, use BitcoinyTransaction.Output instead
public List<TransactionOutput> getUnspentOutputs(String base58Address) throws ForeignBlockchainException {
List<UnspentOutput> unspentOutputs = this.blockchainProvider.getUnspentOutputs(addressToScriptPubKey(base58Address), false);
public List<TransactionOutput> getUnspentOutputs(String base58Address, boolean includeUnconfirmed) throws ForeignBlockchainException {
List<UnspentOutput> unspentOutputs = this.blockchainProvider.getUnspentOutputs(addressToScriptPubKey(base58Address), includeUnconfirmed);
List<TransactionOutput> unspentTransactionOutputs = new ArrayList<>();
for (UnspentOutput unspentOutput : unspentOutputs) {
@ -430,7 +430,7 @@ public abstract class Bitcoiny implements ForeignBlockchain {
List<TransactionOutput> allUnspentOutputs = new ArrayList<>();
Set<String> walletAddresses = this.getWalletAddresses(key58);
for (String address : walletAddresses) {
allUnspentOutputs.addAll(this.getUnspentOutputs(address));
allUnspentOutputs.addAll(this.getUnspentOutputs(address, true));
}
for (TransactionOutput output : allUnspentOutputs) {
if (!output.isAvailableForSpending()) {
@ -504,7 +504,7 @@ public abstract class Bitcoiny implements ForeignBlockchain {
byte[] script = ScriptBuilder.createOutputScript(address).getProgram();
// Ask for transaction history - if it's empty then key has never been used
List<TransactionHash> historicTransactionHashes = this.getAddressTransactions(script, false);
List<TransactionHash> historicTransactionHashes = this.getAddressTransactions(script, true);
if (!historicTransactionHashes.isEmpty()) {
areAllKeysUnused = false;
@ -608,7 +608,7 @@ public abstract class Bitcoiny implements ForeignBlockchain {
byte[] script = ScriptBuilder.createOutputScript(address).getProgram();
// Ask for transaction history - if it's empty then key has never been used
List<TransactionHash> historicTransactionHashes = this.getAddressTransactions(script, false);
List<TransactionHash> historicTransactionHashes = this.getAddressTransactions(script, true);
if (!historicTransactionHashes.isEmpty()) {
areAllKeysUnused = false;
@ -842,7 +842,7 @@ public abstract class Bitcoiny implements ForeignBlockchain {
List<UnspentOutput> unspentOutputs;
try {
unspentOutputs = this.bitcoiny.blockchainProvider.getUnspentOutputs(script, false);
unspentOutputs = this.bitcoiny.blockchainProvider.getUnspentOutputs(script, true);
} catch (ForeignBlockchainException e) {
throw new UTXOProviderException(String.format("Unable to fetch unspent outputs for %s", address));
}
@ -932,7 +932,7 @@ public abstract class Bitcoiny implements ForeignBlockchain {
}
private Long summingUnspentOutputs(String walletAddress) throws ForeignBlockchainException {
return this.getUnspentOutputs(walletAddress).stream()
return this.getUnspentOutputs(walletAddress, true).stream()
.map(TransactionOutput::getValue)
.mapToLong(Coin::longValue)
.sum();

View File

@ -30,7 +30,7 @@ public class BitcoinyUTXOProvider implements UTXOProvider {
byte[] script = ScriptBuilder.createOutputScript(address).getProgram();
// collection UTXO's for all confirmed unspent outputs
for (UnspentOutput output : this.bitcoiny.blockchainProvider.getUnspentOutputs(script, false)) {
for (UnspentOutput output : this.bitcoiny.blockchainProvider.getUnspentOutputs(script, true)) {
utxos.add(toUTXO(output));
}
}

View File

@ -92,7 +92,7 @@ public abstract class Common {
List<TransactionOutput> unspentOutputs = Collections.emptyList();
try {
unspentOutputs = bitcoiny.getUnspentOutputs(address58);
unspentOutputs = bitcoiny.getUnspentOutputs(address58, false);
} catch (ForeignBlockchainException e) {
System.err.println(String.format("Can't find unspent outputs for %s: %s", address58, e.getMessage()));
return unspentOutputs;