diff --git a/core/src/main/java/haveno/core/offer/placeoffer/tasks/MakerReserveOfferFunds.java b/core/src/main/java/haveno/core/offer/placeoffer/tasks/MakerReserveOfferFunds.java index d4ad40288e..b8f9b7c182 100644 --- a/core/src/main/java/haveno/core/offer/placeoffer/tasks/MakerReserveOfferFunds.java +++ b/core/src/main/java/haveno/core/offer/placeoffer/tasks/MakerReserveOfferFunds.java @@ -20,18 +20,11 @@ package haveno.core.offer.placeoffer.tasks; import haveno.common.taskrunner.Task; import haveno.common.taskrunner.TaskRunner; import haveno.core.offer.Offer; -import haveno.core.offer.OfferDirection; import haveno.core.offer.placeoffer.PlaceOfferModel; -import haveno.core.trade.HavenoUtils; import haveno.core.xmr.model.XmrAddressEntry; import lombok.extern.slf4j.Slf4j; -import monero.daemon.model.MoneroOutput; import monero.wallet.model.MoneroTxWallet; -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.List; - @Slf4j public class MakerReserveOfferFunds extends Task { @@ -51,14 +44,8 @@ public class MakerReserveOfferFunds extends Task { model.getXmrWalletService().getConnectionService().verifyConnection(); // create reserve tx - BigInteger penaltyFee = HavenoUtils.multiply(offer.getAmount(), offer.getPenaltyFeePct()); - BigInteger makerFee = offer.getMaxMakerFee(); - BigInteger sendAmount = offer.getDirection() == OfferDirection.BUY ? BigInteger.ZERO : offer.getAmount(); - BigInteger securityDeposit = offer.getDirection() == OfferDirection.BUY ? offer.getMaxBuyerSecurityDeposit() : offer.getMaxSellerSecurityDeposit(); - String returnAddress = model.getXmrWalletService().getOrCreateAddressEntry(offer.getId(), XmrAddressEntry.Context.TRADE_PAYOUT).getAddressString(); - XmrAddressEntry fundingEntry = model.getXmrWalletService().getAddressEntry(offer.getId(), XmrAddressEntry.Context.OFFER_FUNDING).orElse(null); - Integer preferredSubaddressIndex = fundingEntry == null ? null : fundingEntry.getSubaddressIndex(); - MoneroTxWallet reserveTx = model.getXmrWalletService().createReserveTx(penaltyFee, makerFee, sendAmount, securityDeposit, returnAddress, model.getOpenOffer().isReserveExactAmount(), preferredSubaddressIndex); + MoneroTxWallet reserveTx = model.getXmrWalletService().createReserveTx(model.getOpenOffer()); + model.setReserveTx(reserveTx); // check for error in case creating reserve tx exceeded timeout // TODO: better way? if (!model.getXmrWalletService().getAddressEntry(offer.getId(), XmrAddressEntry.Context.TRADE_PAYOUT).isPresent()) { @@ -67,17 +54,6 @@ public class MakerReserveOfferFunds extends Task { // reset protocol timeout model.getProtocol().startTimeoutTimer(); - - // collect reserved key images - List reservedKeyImages = new ArrayList(); - for (MoneroOutput input : reserveTx.getInputs()) reservedKeyImages.add(input.getKeyImage().getHex()); - - // save offer state - model.setReserveTx(reserveTx); - model.getOpenOffer().setReserveTxHash(reserveTx.getHash()); - model.getOpenOffer().setReserveTxHex(reserveTx.getFullHex()); - model.getOpenOffer().setReserveTxKey(reserveTx.getKey()); - offer.getOfferPayload().setReserveTxKeyImages(reservedKeyImages); complete(); } catch (Throwable t) { offer.setErrorMessage("An error occurred.\n" + diff --git a/core/src/main/java/haveno/core/xmr/wallet/XmrWalletService.java b/core/src/main/java/haveno/core/xmr/wallet/XmrWalletService.java index 7cc7d19272..aa28314d67 100644 --- a/core/src/main/java/haveno/core/xmr/wallet/XmrWalletService.java +++ b/core/src/main/java/haveno/core/xmr/wallet/XmrWalletService.java @@ -33,6 +33,8 @@ import haveno.common.util.Utilities; import haveno.core.api.AccountServiceListener; import haveno.core.api.CoreAccountService; import haveno.core.api.XmrConnectionService; +import haveno.core.offer.Offer; +import haveno.core.offer.OfferDirection; import haveno.core.offer.OpenOffer; import haveno.core.trade.BuyerTrade; import haveno.core.trade.HavenoUtils; @@ -546,6 +548,40 @@ public class XmrWalletService { return new ArrayList(subaddressIndices); } + /** + * Create a reserve tx for an open offer and freeze its inputs. + * + * @param openOffer is the open offer to create a reserve tx for + */ + public MoneroTxWallet createReserveTx(OpenOffer openOffer) { + synchronized (walletLock) { + + // collect offer data + Offer offer = openOffer.getOffer(); + BigInteger penaltyFee = HavenoUtils.multiply(offer.getAmount(), offer.getPenaltyFeePct()); + BigInteger makerFee = offer.getMaxMakerFee(); + BigInteger sendAmount = offer.getDirection() == OfferDirection.BUY ? BigInteger.ZERO : offer.getAmount(); + BigInteger securityDeposit = offer.getDirection() == OfferDirection.BUY ? offer.getMaxBuyerSecurityDeposit() : offer.getMaxSellerSecurityDeposit(); + String returnAddress = getOrCreateAddressEntry(offer.getId(), XmrAddressEntry.Context.TRADE_PAYOUT).getAddressString(); + XmrAddressEntry fundingEntry = getAddressEntry(offer.getId(), XmrAddressEntry.Context.OFFER_FUNDING).orElse(null); + Integer preferredSubaddressIndex = fundingEntry == null ? null : fundingEntry.getSubaddressIndex(); + + // create reserve tx + MoneroTxWallet reserveTx = createReserveTx(penaltyFee, makerFee, sendAmount, securityDeposit, returnAddress, openOffer.isReserveExactAmount(), preferredSubaddressIndex); + + // collect reserved key images + List reservedKeyImages = new ArrayList(); + for (MoneroOutput input : reserveTx.getInputs()) reservedKeyImages.add(input.getKeyImage().getHex()); + + // save offer state + openOffer.setReserveTxHash(reserveTx.getHash()); + openOffer.setReserveTxHex(reserveTx.getFullHex()); + openOffer.setReserveTxKey(reserveTx.getKey()); + offer.getOfferPayload().setReserveTxKeyImages(reservedKeyImages); + return reserveTx; + } + } + /** * Create the reserve tx and freeze its inputs. The full amount is returned * to the sender's payout address less the penalty and mining fees.