mirror of
https://github.com/haveno-dex/haveno.git
synced 2024-12-22 11:39:29 +00:00
show reserved amount in maker's offer details
This commit is contained in:
parent
e63141279c
commit
94ab3c1f9b
6 changed files with 51 additions and 22 deletions
|
@ -282,12 +282,18 @@ public class Offer implements NetworkPayload, PersistablePayload {
|
|||
// Getter
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// get the amount needed for the maker to reserve the offer
|
||||
public BigInteger getReserveAmount() {
|
||||
BigInteger reserveAmount = getDirection() == OfferDirection.BUY ? getMaxBuyerSecurityDeposit() : getMaxSellerSecurityDeposit();
|
||||
if (getDirection() == OfferDirection.SELL) reserveAmount = reserveAmount.add(getAmount());
|
||||
reserveAmount = reserveAmount.add(getMaxMakerFee());
|
||||
return reserveAmount;
|
||||
// amount needed for the maker to reserve the offer
|
||||
public BigInteger getAmountNeeded() {
|
||||
BigInteger amountNeeded = getDirection() == OfferDirection.BUY ? getMaxBuyerSecurityDeposit() : getMaxSellerSecurityDeposit();
|
||||
if (getDirection() == OfferDirection.SELL) amountNeeded = amountNeeded.add(getAmount());
|
||||
amountNeeded = amountNeeded.add(getMaxMakerFee());
|
||||
return amountNeeded;
|
||||
}
|
||||
|
||||
// amount reserved for offer
|
||||
public BigInteger getReservedAmount() {
|
||||
if (offerPayload.getReserveTxKeyImages() == null) return null;
|
||||
return HavenoUtils.xmrWalletService.getOutputsAmount(offerPayload.getReserveTxKeyImages());
|
||||
}
|
||||
|
||||
public BigInteger getMaxMakerFee() {
|
||||
|
|
|
@ -879,8 +879,8 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
|||
return;
|
||||
}
|
||||
|
||||
// get offer reserve amount
|
||||
BigInteger offerReserveAmount = openOffer.getOffer().getReserveAmount();
|
||||
// get amount needed to reserve offer
|
||||
BigInteger amountNeeded = openOffer.getOffer().getAmountNeeded();
|
||||
|
||||
// handle split output offer
|
||||
if (openOffer.isReserveExactAmount()) {
|
||||
|
@ -889,13 +889,13 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
|||
MoneroTxWallet splitOutputTx = findSplitOutputFundingTx(openOffers, openOffer);
|
||||
if (splitOutputTx != null && openOffer.getScheduledTxHashes() == null) {
|
||||
openOffer.setScheduledTxHashes(Arrays.asList(splitOutputTx.getHash()));
|
||||
openOffer.setScheduledAmount(offerReserveAmount.toString());
|
||||
openOffer.setScheduledAmount(amountNeeded.toString());
|
||||
openOffer.setState(OpenOffer.State.SCHEDULED);
|
||||
}
|
||||
|
||||
// if not found, create tx to split exact output
|
||||
if (splitOutputTx == null) {
|
||||
splitOrSchedule(openOffers, openOffer, offerReserveAmount);
|
||||
splitOrSchedule(openOffers, openOffer, amountNeeded);
|
||||
} else if (!splitOutputTx.isLocked()) {
|
||||
|
||||
// otherwise sign and post offer if split output available
|
||||
|
@ -905,7 +905,7 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
|||
if (openOffer.getSplitOutputTxHash() == null) {
|
||||
int offerSubaddress = xmrWalletService.getOrCreateAddressEntry(openOffer.getId(), XmrAddressEntry.Context.OFFER_FUNDING).getSubaddressIndex();
|
||||
log.warn("Splitting new output because spending scheduled output(s) failed for offer {}. Offer funding subadress={}", openOffer.getId(), offerSubaddress);
|
||||
splitOrSchedule(openOffers, openOffer, offerReserveAmount);
|
||||
splitOrSchedule(openOffers, openOffer, amountNeeded);
|
||||
resultHandler.handleResult(null);
|
||||
} else {
|
||||
errorMessageHandler.handleErrorMessage(errMsg);
|
||||
|
@ -916,7 +916,7 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
|||
} else {
|
||||
|
||||
// handle sufficient balance
|
||||
boolean hasSufficientBalance = xmrWalletService.getWallet().getUnlockedBalance(0).compareTo(offerReserveAmount) >= 0;
|
||||
boolean hasSufficientBalance = xmrWalletService.getWallet().getUnlockedBalance(0).compareTo(amountNeeded) >= 0;
|
||||
if (hasSufficientBalance) {
|
||||
signAndPostOffer(openOffer, true, resultHandler, errorMessageHandler);
|
||||
return;
|
||||
|
@ -936,7 +936,7 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
|||
|
||||
private MoneroTxWallet findSplitOutputFundingTx(List<OpenOffer> openOffers, OpenOffer openOffer) {
|
||||
XmrAddressEntry addressEntry = xmrWalletService.getOrCreateAddressEntry(openOffer.getId(), XmrAddressEntry.Context.OFFER_FUNDING);
|
||||
return findSplitOutputFundingTx(openOffers, openOffer, openOffer.getOffer().getReserveAmount(), addressEntry.getSubaddressIndex());
|
||||
return findSplitOutputFundingTx(openOffers, openOffer, openOffer.getOffer().getAmountNeeded(), addressEntry.getSubaddressIndex());
|
||||
}
|
||||
|
||||
private MoneroTxWallet findSplitOutputFundingTx(List<OpenOffer> openOffers, OpenOffer openOffer, BigInteger reserveAmount, Integer preferredSubaddressIndex) {
|
||||
|
@ -1035,7 +1035,7 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
|||
}
|
||||
|
||||
private MoneroTxWallet splitAndSchedule(OpenOffer openOffer) {
|
||||
BigInteger reserveAmount = openOffer.getOffer().getReserveAmount();
|
||||
BigInteger reserveAmount = openOffer.getOffer().getAmountNeeded();
|
||||
xmrWalletService.swapAddressEntryToAvailable(openOffer.getId(), XmrAddressEntry.Context.OFFER_FUNDING); // change funding subaddress in case funded with unsuitable output(s)
|
||||
MoneroTxWallet splitOutputTx = null;
|
||||
synchronized (XmrWalletService.WALLET_LOCK) {
|
||||
|
@ -1064,7 +1064,7 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
|||
openOffer.setSplitOutputTxHash(splitOutputTx.getHash());
|
||||
openOffer.setSplitOutputTxFee(splitOutputTx.getFee().longValueExact());
|
||||
openOffer.setScheduledTxHashes(Arrays.asList(splitOutputTx.getHash()));
|
||||
openOffer.setScheduledAmount(openOffer.getOffer().getReserveAmount().toString());
|
||||
openOffer.setScheduledAmount(openOffer.getOffer().getAmountNeeded().toString());
|
||||
openOffer.setState(OpenOffer.State.SCHEDULED);
|
||||
return splitOutputTx;
|
||||
}
|
||||
|
@ -1072,7 +1072,7 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
|||
private void scheduleWithEarliestTxs(List<OpenOffer> openOffers, OpenOffer openOffer) {
|
||||
|
||||
// check for sufficient balance - scheduled offers amount
|
||||
BigInteger offerReserveAmount = openOffer.getOffer().getReserveAmount();
|
||||
BigInteger offerReserveAmount = openOffer.getOffer().getAmountNeeded();
|
||||
if (xmrWalletService.getWallet().getBalance(0).subtract(getScheduledAmount(openOffers)).compareTo(offerReserveAmount) < 0) {
|
||||
throw new RuntimeException("Not enough money in Haveno wallet");
|
||||
}
|
||||
|
@ -1135,7 +1135,7 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
|||
|
||||
// create model
|
||||
PlaceOfferModel model = new PlaceOfferModel(openOffer,
|
||||
openOffer.getOffer().getReserveAmount(),
|
||||
openOffer.getOffer().getAmountNeeded(),
|
||||
useSavingsWallet,
|
||||
p2PService,
|
||||
btcWalletService,
|
||||
|
|
|
@ -36,6 +36,7 @@ import haveno.core.trade.messages.InitTradeRequest;
|
|||
import haveno.core.trade.messages.PaymentReceivedMessage;
|
||||
import haveno.core.trade.messages.PaymentSentMessage;
|
||||
import haveno.core.util.JsonUtil;
|
||||
import haveno.core.xmr.wallet.XmrWalletService;
|
||||
import haveno.network.p2p.NodeAddress;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
|
@ -93,8 +94,9 @@ public class HavenoUtils {
|
|||
public static final DecimalFormat XMR_FORMATTER = new DecimalFormat("##############0.000000000000", DECIMAL_FORMAT_SYMBOLS);
|
||||
public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
|
||||
|
||||
public static ArbitrationManager arbitrationManager; // TODO: better way to share references?
|
||||
public static HavenoSetup havenoSetup;
|
||||
public static ArbitrationManager arbitrationManager; // TODO: better way to share references?
|
||||
public static XmrWalletService xmrWalletService;
|
||||
|
||||
public static boolean isSeedNode() {
|
||||
return havenoSetup == null;
|
||||
|
|
|
@ -82,6 +82,7 @@ import monero.common.TaskLooper;
|
|||
import monero.daemon.MoneroDaemonRpc;
|
||||
import monero.daemon.model.MoneroDaemonInfo;
|
||||
import monero.daemon.model.MoneroFeeEstimate;
|
||||
import monero.daemon.model.MoneroKeyImage;
|
||||
import monero.daemon.model.MoneroNetworkType;
|
||||
import monero.daemon.model.MoneroOutput;
|
||||
import monero.daemon.model.MoneroSubmitTxResult;
|
||||
|
@ -196,6 +197,7 @@ public class XmrWalletService {
|
|||
this.rpcBindPort = rpcBindPort;
|
||||
this.useNativeXmrWallet = useNativeXmrWallet;
|
||||
this.xmrWalletFile = new File(walletDir, MONERO_WALLET_NAME);
|
||||
HavenoUtils.xmrWalletService = this;
|
||||
|
||||
// set monero logging
|
||||
if (MONERO_LOG_LEVEL >= 0) MoneroUtils.setLogLevel(MONERO_LOG_LEVEL);
|
||||
|
@ -535,6 +537,15 @@ public class XmrWalletService {
|
|||
}
|
||||
}
|
||||
|
||||
public BigInteger getOutputsAmount(Collection<String> keyImages) {
|
||||
BigInteger sum = BigInteger.ZERO;
|
||||
for (String keyImage : keyImages) {
|
||||
List<MoneroOutputWallet> outputs = getOutputs(new MoneroOutputQuery().setIsSpent(false).setKeyImage(new MoneroKeyImage(keyImage)));
|
||||
if (!outputs.isEmpty()) sum = sum.add(outputs.get(0).getAmount());
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
private List<Integer> getSubaddressesWithExactInput(BigInteger amount) {
|
||||
|
||||
// fetch unspent, unfrozen, unlocked outputs
|
||||
|
|
|
@ -173,6 +173,7 @@ shared.acceptedTakerCountries=Accepted taker countries
|
|||
shared.tradePrice=Trade price
|
||||
shared.tradeAmount=Trade amount
|
||||
shared.tradeVolume=Trade volume
|
||||
shared.reservedAmount=Reserved amount
|
||||
shared.invalidKey=The key you entered was not correct.
|
||||
shared.enterPrivKey=Enter private key to unlock
|
||||
shared.payoutTxId=Payout transaction ID
|
||||
|
|
|
@ -212,14 +212,14 @@ public class OfferDetailsWindow extends Overlay<OfferDetailsWindow> {
|
|||
addConfirmationLabelLabel(gridPane, rowIndex, offerTypeLabel,
|
||||
DisplayUtils.getDirectionBothSides(direction), firstRowDistance);
|
||||
}
|
||||
String btcAmount = Res.get("shared.xmrAmount");
|
||||
String amount = Res.get("shared.xmrAmount");
|
||||
if (takeOfferHandlerOptional.isPresent()) {
|
||||
addConfirmationLabelLabel(gridPane, ++rowIndex, btcAmount + xmrDirectionInfo,
|
||||
addConfirmationLabelLabel(gridPane, ++rowIndex, amount + xmrDirectionInfo,
|
||||
HavenoUtils.formatXmr(tradeAmount, true));
|
||||
addConfirmationLabelLabel(gridPane, ++rowIndex, VolumeUtil.formatVolumeLabel(currencyCode) + counterCurrencyDirectionInfo,
|
||||
VolumeUtil.formatVolumeWithCode(offer.getVolumeByAmount(tradeAmount)));
|
||||
} else {
|
||||
addConfirmationLabelLabel(gridPane, ++rowIndex, btcAmount + xmrDirectionInfo,
|
||||
addConfirmationLabelLabel(gridPane, ++rowIndex, amount + xmrDirectionInfo,
|
||||
HavenoUtils.formatXmr(offer.getAmount(), true));
|
||||
addConfirmationLabelLabel(gridPane, ++rowIndex, Res.get("offerDetailsWindow.minXmrAmount"),
|
||||
HavenoUtils.formatXmr(offer.getMinAmount(), true));
|
||||
|
@ -257,7 +257,8 @@ public class OfferDetailsWindow extends Overlay<OfferDetailsWindow> {
|
|||
final String makerPaymentAccountId = offer.getMakerPaymentAccountId();
|
||||
final PaymentAccount myPaymentAccount = user.getPaymentAccount(makerPaymentAccountId);
|
||||
String countryCode = offer.getCountryCode();
|
||||
if (offer.isMyOffer(keyRing) && makerPaymentAccountId != null && myPaymentAccount != null) {
|
||||
boolean isMyOffer = offer.isMyOffer(keyRing);
|
||||
if (isMyOffer && makerPaymentAccountId != null && myPaymentAccount != null) {
|
||||
addConfirmationLabelLabel(gridPane, ++rowIndex, Res.get("offerDetailsWindow.myTradingAccount"), myPaymentAccount.getAccountName());
|
||||
} else {
|
||||
final String method = Res.get(paymentMethod.getId());
|
||||
|
@ -316,11 +317,16 @@ public class OfferDetailsWindow extends Overlay<OfferDetailsWindow> {
|
|||
textArea.setEditable(false);
|
||||
}
|
||||
|
||||
// get amount reserved for the offer
|
||||
BigInteger reservedAmount = isMyOffer ? offer.getReservedAmount() : null;
|
||||
|
||||
rows = 3;
|
||||
if (countryCode != null)
|
||||
rows++;
|
||||
if (!isF2F)
|
||||
rows++;
|
||||
if (reservedAmount != null)
|
||||
rows++;
|
||||
|
||||
addTitledGroupBg(gridPane, ++rowIndex, rows, Res.get("shared.details"), Layout.GROUP_DISTANCE);
|
||||
addConfirmationLabelTextFieldWithCopyIcon(gridPane, rowIndex, Res.get("shared.offerId"), offer.getId(),
|
||||
|
@ -337,6 +343,9 @@ public class OfferDetailsWindow extends Overlay<OfferDetailsWindow> {
|
|||
" " +
|
||||
HavenoUtils.formatXmr(offer.getOfferPayload().getMaxSellerSecurityDeposit(), true);
|
||||
addConfirmationLabelLabel(gridPane, ++rowIndex, Res.get("shared.securityDeposit"), value);
|
||||
if (reservedAmount != null) {
|
||||
addConfirmationLabelLabel(gridPane, ++rowIndex, Res.get("shared.reservedAmount"), HavenoUtils.formatXmr(reservedAmount, true));
|
||||
}
|
||||
|
||||
if (countryCode != null && !isF2F)
|
||||
addConfirmationLabelLabel(gridPane, ++rowIndex, Res.get("offerDetailsWindow.countryBank"),
|
||||
|
|
Loading…
Reference in a new issue