Skip to content

Commit 7e29dc1

Browse files
committed
fix scheduling offers by computing spendable amount from txs
1 parent 544d698 commit 7e29dc1

File tree

2 files changed

+38
-29
lines changed

2 files changed

+38
-29
lines changed

core/src/main/java/haveno/core/offer/CreateOfferService.java

-1
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,6 @@ public Offer createAndGetOffer(String offerId,
127127
isPrivateOffer,
128128
buyerAsTakerWithoutDeposit);
129129

130-
131130
// verify buyer as taker security deposit
132131
boolean isBuyerMaker = offerUtil.isBuyOffer(direction);
133132
if (!isBuyerMaker && !isPrivateOffer && buyerAsTakerWithoutDeposit) {

core/src/main/java/haveno/core/offer/OpenOfferManager.java

+38-28
Original file line numberDiff line numberDiff line change
@@ -948,7 +948,7 @@ private void doProcessPendingOffer(List<OpenOffer> openOffers, OpenOffer openOff
948948
if (openOffer.getScheduledTxHashes() != null) {
949949
boolean scheduledTxsAvailable = true;
950950
for (MoneroTxWallet tx : xmrWalletService.getTxs(openOffer.getScheduledTxHashes())) {
951-
if (!tx.isLocked() && !isOutputsAvailable(tx)) {
951+
if (!tx.isLocked() && !hasSpendableAmount(tx)) {
952952
scheduledTxsAvailable = false;
953953
break;
954954
}
@@ -1165,31 +1165,21 @@ private void scheduleWithEarliestTxs(List<OpenOffer> openOffers, OpenOffer openO
11651165
throw new RuntimeException("Not enough money in Haveno wallet");
11661166
}
11671167

1168-
// get earliest available or pending txs with sufficient incoming amount
1168+
// get earliest available or pending txs with sufficient spendable amount
11691169
BigInteger scheduledAmount = BigInteger.ZERO;
11701170
Set<MoneroTxWallet> scheduledTxs = new HashSet<MoneroTxWallet>();
11711171
for (MoneroTxWallet tx : xmrWalletService.getTxs()) {
11721172

1173-
// skip if no funds available
1174-
BigInteger sentToSelfAmount = xmrWalletService.getAmountSentToSelf(tx); // amount sent to self always shows 0, so compute from destinations manually
1175-
if (sentToSelfAmount.equals(BigInteger.ZERO) && (tx.getIncomingTransfers() == null || tx.getIncomingTransfers().isEmpty())) continue;
1176-
if (!isOutputsAvailable(tx)) continue;
1173+
// get spendable amount
1174+
BigInteger spendableAmount = getSpendableAmount(tx);
1175+
1176+
// skip if no spendable amount or already scheduled
1177+
if (spendableAmount.equals(BigInteger.ZERO)) continue;
11771178
if (isTxScheduledByOtherOffer(openOffers, openOffer, tx.getHash())) continue;
11781179

1179-
// schedule transaction if funds sent to self, because they are not included in incoming transfers // TODO: fix in libraries?
1180-
if (sentToSelfAmount.compareTo(BigInteger.ZERO) > 0) {
1181-
scheduledAmount = scheduledAmount.add(sentToSelfAmount);
1182-
scheduledTxs.add(tx);
1183-
} else if (tx.getIncomingTransfers() != null) {
1184-
1185-
// schedule transaction if incoming tranfers to account 0
1186-
for (MoneroIncomingTransfer transfer : tx.getIncomingTransfers()) {
1187-
if (transfer.getAccountIndex() == 0) {
1188-
scheduledAmount = scheduledAmount.add(transfer.getAmount());
1189-
scheduledTxs.add(tx);
1190-
}
1191-
}
1192-
}
1180+
// schedule tx
1181+
scheduledAmount = scheduledAmount.add(spendableAmount);
1182+
scheduledTxs.add(tx);
11931183

11941184
// break if sufficient funds
11951185
if (scheduledAmount.compareTo(offerReserveAmount) >= 0) break;
@@ -1202,6 +1192,34 @@ private void scheduleWithEarliestTxs(List<OpenOffer> openOffers, OpenOffer openO
12021192
openOffer.setState(OpenOffer.State.PENDING);
12031193
}
12041194

1195+
private BigInteger getSpendableAmount(MoneroTxWallet tx) {
1196+
1197+
// compute spendable amount from outputs if confirmed
1198+
if (tx.isConfirmed()) {
1199+
BigInteger spendableAmount = BigInteger.ZERO;
1200+
if (tx.getOutputsWallet() != null) {
1201+
for (MoneroOutputWallet output : tx.getOutputsWallet()) {
1202+
if (!output.isSpent() && !output.isFrozen() && output.getAccountIndex() == 0) {
1203+
spendableAmount = spendableAmount.add(output.getAmount());
1204+
}
1205+
}
1206+
}
1207+
return spendableAmount;
1208+
}
1209+
1210+
// funds sent to self always show 0 incoming amount, so compute from destinations manually
1211+
// TODO: this excludes change output, so change is missing from spendable amount until confirmed
1212+
BigInteger sentToSelfAmount = xmrWalletService.getAmountSentToSelf(tx);
1213+
if (sentToSelfAmount.compareTo(BigInteger.ZERO) > 0) return sentToSelfAmount;
1214+
1215+
// if not confirmed and not sent to self, return incoming amount
1216+
return tx.getIncomingAmount() == null ? BigInteger.ZERO : tx.getIncomingAmount();
1217+
}
1218+
1219+
private boolean hasSpendableAmount(MoneroTxWallet tx) {
1220+
return getSpendableAmount(tx).compareTo(BigInteger.ZERO) > 0;
1221+
}
1222+
12051223
private BigInteger getScheduledAmount(List<OpenOffer> openOffers) {
12061224
BigInteger scheduledAmount = BigInteger.ZERO;
12071225
for (OpenOffer openOffer : openOffers) {
@@ -1233,14 +1251,6 @@ private boolean isTxScheduledByOtherOffer(List<OpenOffer> openOffers, OpenOffer
12331251
return false;
12341252
}
12351253

1236-
private boolean isOutputsAvailable(MoneroTxWallet tx) {
1237-
if (tx.getOutputsWallet() == null) return false;
1238-
for (MoneroOutputWallet output : tx.getOutputsWallet()) {
1239-
if (output.isSpent() || output.isFrozen()) return false;
1240-
}
1241-
return true;
1242-
}
1243-
12441254
private void signAndPostOffer(OpenOffer openOffer,
12451255
boolean useSavingsWallet, // TODO: remove this?
12461256
TransactionResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {

0 commit comments

Comments
 (0)