From 15607fe5d7c44e944bf55727f53b12d42e07b91b Mon Sep 17 00:00:00 2001 From: woodser Date: Fri, 8 Dec 2023 05:45:27 -0500 Subject: [PATCH 01/10] set buyer and seller payout tx fee and amount, fix csv export #720 --- .../haveno/core/api/CoreDisputesService.java | 43 ++++------ .../java/haveno/core/api/model/TradeInfo.java | 37 +++++++++ .../api/model/builder/TradeInfoV1Builder.java | 36 +++++++++ .../core/support/dispute/DisputeManager.java | 65 +++++++-------- .../core/support/dispute/DisputeResult.java | 44 +++++------ .../arbitration/ArbitrationManager.java | 74 ++++++++--------- .../dispute/mediation/MediationManager.java | 8 +- .../java/haveno/core/trade/HavenoUtils.java | 11 +++ .../main/java/haveno/core/trade/Trade.java | 79 +++++++++++++------ .../haveno/core/trade/protocol/TradePeer.java | 33 +++++++- .../tasks/ProcessPaymentReceivedMessage.java | 8 +- .../SellerPreparePaymentReceivedMessage.java | 4 +- .../windows/DisputeSummaryWindow.java | 19 +++-- .../closedtrades/ClosedTradesView.java | 11 +-- .../pendingtrades/steps/TradeStepView.java | 4 +- .../main/support/dispute/DisputeView.java | 7 +- proto/src/main/proto/grpc.proto | 59 +++++++------- proto/src/main/proto/pb.proto | 79 ++++++++++--------- 18 files changed, 374 insertions(+), 247 deletions(-) diff --git a/core/src/main/java/haveno/core/api/CoreDisputesService.java b/core/src/main/java/haveno/core/api/CoreDisputesService.java index 0cb12417adb..a72e85ff8e7 100644 --- a/core/src/main/java/haveno/core/api/CoreDisputesService.java +++ b/core/src/main/java/haveno/core/api/CoreDisputesService.java @@ -163,9 +163,6 @@ public void resolveDispute(String tradeId, DisputeResult.Winner winner, DisputeR } applyPayoutAmountsToDisputeResult(payout, winningDispute, winnerDisputeResult, customWinnerAmount); - // create dispute payout tx - trade.getProcessModel().setUnsignedPayoutTx(arbitrationManager.createDisputePayoutTx(trade, winningDispute.getContract(), winnerDisputeResult, false)); - // close winning dispute ticket closeDisputeTicket(arbitrationManager, winningDispute, winnerDisputeResult, () -> { arbitrationManager.requestPersistence(); @@ -180,8 +177,8 @@ public void resolveDispute(String tradeId, DisputeResult.Winner winner, DisputeR if (!loserDisputeOptional.isPresent()) throw new IllegalStateException("could not find peer dispute"); var loserDispute = loserDisputeOptional.get(); var loserDisputeResult = createDisputeResult(loserDispute, winner, reason, summaryNotes, closeDate); - loserDisputeResult.setBuyerPayoutAmount(winnerDisputeResult.getBuyerPayoutAmount()); - loserDisputeResult.setSellerPayoutAmount(winnerDisputeResult.getSellerPayoutAmount()); + loserDisputeResult.setBuyerPayoutAmountBeforeCost(winnerDisputeResult.getBuyerPayoutAmountBeforeCost()); + loserDisputeResult.setSellerPayoutAmountBeforeCost(winnerDisputeResult.getSellerPayoutAmountBeforeCost()); loserDisputeResult.setSubtractFeeFrom(winnerDisputeResult.getSubtractFeeFrom()); closeDisputeTicket(arbitrationManager, loserDispute, loserDisputeResult, () -> { arbitrationManager.requestPersistence(); @@ -217,31 +214,23 @@ public void applyPayoutAmountsToDisputeResult(DisputePayout payout, Dispute disp BigInteger tradeAmount = contract.getTradeAmount(); disputeResult.setSubtractFeeFrom(DisputeResult.SubtractFeeFrom.BUYER_AND_SELLER); if (payout == DisputePayout.BUYER_GETS_TRADE_AMOUNT) { - disputeResult.setBuyerPayoutAmount(tradeAmount.add(buyerSecurityDeposit)); - disputeResult.setSellerPayoutAmount(sellerSecurityDeposit); + disputeResult.setBuyerPayoutAmountBeforeCost(tradeAmount.add(buyerSecurityDeposit)); + disputeResult.setSellerPayoutAmountBeforeCost(sellerSecurityDeposit); } else if (payout == DisputePayout.BUYER_GETS_ALL) { - disputeResult.setBuyerPayoutAmount(tradeAmount - .add(buyerSecurityDeposit) - .add(sellerSecurityDeposit)); // TODO (woodser): apply min payout to incentivize loser? (see post v1.1.7) - disputeResult.setSellerPayoutAmount(BigInteger.valueOf(0)); + disputeResult.setBuyerPayoutAmountBeforeCost(tradeAmount.add(buyerSecurityDeposit).add(sellerSecurityDeposit)); // TODO (woodser): apply min payout to incentivize loser? (see post v1.1.7) + disputeResult.setSellerPayoutAmountBeforeCost(BigInteger.valueOf(0)); } else if (payout == DisputePayout.SELLER_GETS_TRADE_AMOUNT) { - disputeResult.setBuyerPayoutAmount(buyerSecurityDeposit); - disputeResult.setSellerPayoutAmount(tradeAmount.add(sellerSecurityDeposit)); + disputeResult.setBuyerPayoutAmountBeforeCost(buyerSecurityDeposit); + disputeResult.setSellerPayoutAmountBeforeCost(tradeAmount.add(sellerSecurityDeposit)); } else if (payout == DisputePayout.SELLER_GETS_ALL) { - disputeResult.setBuyerPayoutAmount(BigInteger.valueOf(0)); - disputeResult.setSellerPayoutAmount(tradeAmount - .add(sellerSecurityDeposit) - .add(buyerSecurityDeposit)); + disputeResult.setBuyerPayoutAmountBeforeCost(BigInteger.valueOf(0)); + disputeResult.setSellerPayoutAmountBeforeCost(tradeAmount.add(sellerSecurityDeposit).add(buyerSecurityDeposit)); } else if (payout == DisputePayout.CUSTOM) { - if (customWinnerAmount > trade.getWallet().getBalance().longValueExact()) { - throw new RuntimeException("Winner payout is more than the trade wallet's balance"); - } + if (customWinnerAmount > trade.getWallet().getBalance().longValueExact()) throw new RuntimeException("Winner payout is more than the trade wallet's balance"); long loserAmount = tradeAmount.add(buyerSecurityDeposit).add(sellerSecurityDeposit).subtract(BigInteger.valueOf(customWinnerAmount)).longValueExact(); - if (loserAmount < 0) { - throw new RuntimeException("Loser payout cannot be negative"); - } - disputeResult.setBuyerPayoutAmount(BigInteger.valueOf(disputeResult.getWinner() == DisputeResult.Winner.BUYER ? customWinnerAmount : loserAmount)); - disputeResult.setSellerPayoutAmount(BigInteger.valueOf(disputeResult.getWinner() == DisputeResult.Winner.BUYER ? loserAmount : customWinnerAmount)); + if (loserAmount < 0) throw new RuntimeException("Loser payout cannot be negative"); + disputeResult.setBuyerPayoutAmountBeforeCost(BigInteger.valueOf(disputeResult.getWinner() == DisputeResult.Winner.BUYER ? customWinnerAmount : loserAmount)); + disputeResult.setSellerPayoutAmountBeforeCost(BigInteger.valueOf(disputeResult.getWinner() == DisputeResult.Winner.BUYER ? loserAmount : customWinnerAmount)); disputeResult.setSubtractFeeFrom(disputeResult.getWinner() == DisputeResult.Winner.BUYER ? SubtractFeeFrom.SELLER_ONLY : SubtractFeeFrom.BUYER_ONLY); // winner gets exact amount, loser pays mining fee } } @@ -263,8 +252,8 @@ public void closeDisputeTicket(DisputeManager disputeManager, Dispute dispute, D currencyCode, Res.get("disputeSummaryWindow.reason." + reason.name()), amount, - HavenoUtils.formatXmr(disputeResult.getBuyerPayoutAmount(), true), - HavenoUtils.formatXmr(disputeResult.getSellerPayoutAmount(), true), + HavenoUtils.formatXmr(disputeResult.getBuyerPayoutAmountBeforeCost(), true), + HavenoUtils.formatXmr(disputeResult.getSellerPayoutAmountBeforeCost(), true), disputeResult.summaryNotesProperty().get() ); diff --git a/core/src/main/java/haveno/core/api/model/TradeInfo.java b/core/src/main/java/haveno/core/api/model/TradeInfo.java index c4486aeda55..1642c60602d 100644 --- a/core/src/main/java/haveno/core/api/model/TradeInfo.java +++ b/core/src/main/java/haveno/core/api/model/TradeInfo.java @@ -71,6 +71,12 @@ public class TradeInfo implements Payload { private final long amount; private final long buyerSecurityDeposit; private final long sellerSecurityDeposit; + private final long buyerDepositTxFee; + private final long sellerDepositTxFee; + private final long buyerPayoutTxFee; + private final long sellerPayoutTxFee; + private final long buyerPayoutAmount; + private final long sellerPayoutAmount; private final String price; private final String volume; private final String arbitratorNodeAddress; @@ -105,6 +111,12 @@ public TradeInfo(TradeInfoV1Builder builder) { this.amount = builder.getAmount(); this.buyerSecurityDeposit = builder.getBuyerSecurityDeposit(); this.sellerSecurityDeposit = builder.getSellerSecurityDeposit(); + this.buyerDepositTxFee = builder.getBuyerDepositTxFee(); + this.sellerDepositTxFee = builder.getSellerDepositTxFee(); + this.buyerPayoutTxFee = builder.getBuyerPayoutTxFee(); + this.sellerPayoutTxFee = builder.getSellerPayoutTxFee(); + this.buyerPayoutAmount = builder.getBuyerPayoutAmount(); + this.sellerPayoutAmount = builder.getSellerPayoutAmount(); this.price = builder.getPrice(); this.volume = builder.getVolume(); this.arbitratorNodeAddress = builder.getArbitratorNodeAddress(); @@ -161,6 +173,13 @@ public static TradeInfo toTradeInfo(Trade trade, String role) { .withAmount(trade.getAmount().longValueExact()) .withBuyerSecurityDeposit(trade.getBuyer().getSecurityDeposit() == null ? -1 : trade.getBuyer().getSecurityDeposit().longValueExact()) .withSellerSecurityDeposit(trade.getSeller().getSecurityDeposit() == null ? -1 : trade.getSeller().getSecurityDeposit().longValueExact()) + .withBuyerDepositTxFee(trade.getBuyer().getDepositTxFee() == null ? -1 : trade.getBuyer().getDepositTxFee().longValueExact()) + .withSellerDepositTxFee(trade.getSeller().getDepositTxFee() == null ? -1 : trade.getSeller().getDepositTxFee().longValueExact()) + .withBuyerPayoutTxFee(trade.getBuyer().getPayoutTxFee() == null ? -1 : trade.getBuyer().getPayoutTxFee().longValueExact()) + .withSellerPayoutTxFee(trade.getSeller().getPayoutTxFee() == null ? -1 : trade.getSeller().getPayoutTxFee().longValueExact()) + .withBuyerPayoutAmount(trade.getBuyer().getPayoutAmount() == null ? -1 : trade.getBuyer().getPayoutAmount().longValueExact()) + .withSellerPayoutAmount(trade.getSeller().getPayoutAmount() == null ? -1 : trade.getSeller().getPayoutAmount().longValueExact()) + .withTotalTxFee(trade.getTotalTxFee().longValueExact()) .withPrice(toPreciseTradePrice.apply(trade)) .withVolume(toRoundedVolume.apply(trade)) .withArbitratorNodeAddress(toArbitratorNodeAddress.apply(trade)) @@ -204,6 +223,12 @@ public haveno.proto.grpc.TradeInfo toProtoMessage() { .setAmount(amount) .setBuyerSecurityDeposit(buyerSecurityDeposit) .setSellerSecurityDeposit(sellerSecurityDeposit) + .setBuyerDepositTxFee(buyerDepositTxFee) + .setSellerDepositTxFee(sellerDepositTxFee) + .setBuyerPayoutTxFee(buyerPayoutTxFee) + .setSellerPayoutTxFee(sellerPayoutTxFee) + .setBuyerPayoutAmount(buyerPayoutAmount) + .setSellerPayoutAmount(sellerPayoutAmount) .setPrice(price) .setTradeVolume(volume) .setArbitratorNodeAddress(arbitratorNodeAddress) @@ -241,6 +266,12 @@ public static TradeInfo fromProto(haveno.proto.grpc.TradeInfo proto) { .withAmount(proto.getAmount()) .withBuyerSecurityDeposit(proto.getBuyerSecurityDeposit()) .withSellerSecurityDeposit(proto.getSellerSecurityDeposit()) + .withBuyerDepositTxFee(proto.getBuyerDepositTxFee()) + .withSellerDepositTxFee(proto.getSellerDepositTxFee()) + .withBuyerPayoutTxFee(proto.getBuyerPayoutTxFee()) + .withSellerPayoutTxFee(proto.getSellerPayoutTxFee()) + .withBuyerPayoutAmount(proto.getBuyerPayoutAmount()) + .withSellerPayoutAmount(proto.getSellerPayoutAmount()) .withPrice(proto.getPrice()) .withVolume(proto.getTradeVolume()) .withPeriodState(proto.getPeriodState()) @@ -278,6 +309,12 @@ public String toString() { ", amount='" + amount + '\'' + "\n" + ", buyerSecurityDeposit='" + buyerSecurityDeposit + '\'' + "\n" + ", sellerSecurityDeposit='" + sellerSecurityDeposit + '\'' + "\n" + + ", buyerDepositTxFee='" + buyerDepositTxFee + '\'' + "\n" + + ", sellerDepositTxFee='" + sellerDepositTxFee + '\'' + "\n" + + ", buyerPayoutTxFee='" + buyerPayoutTxFee + '\'' + "\n" + + ", sellerPayoutTxFee='" + sellerPayoutTxFee + '\'' + "\n" + + ", buyerPayoutAmount='" + buyerPayoutAmount + '\'' + "\n" + + ", sellerPayoutAmount='" + sellerPayoutAmount + '\'' + "\n" + ", price='" + price + '\'' + "\n" + ", arbitratorNodeAddress='" + arbitratorNodeAddress + '\'' + "\n" + ", tradePeerNodeAddress='" + tradePeerNodeAddress + '\'' + "\n" + diff --git a/core/src/main/java/haveno/core/api/model/builder/TradeInfoV1Builder.java b/core/src/main/java/haveno/core/api/model/builder/TradeInfoV1Builder.java index 7987061806b..68d3a57e8f6 100644 --- a/core/src/main/java/haveno/core/api/model/builder/TradeInfoV1Builder.java +++ b/core/src/main/java/haveno/core/api/model/builder/TradeInfoV1Builder.java @@ -41,6 +41,12 @@ public final class TradeInfoV1Builder { private long takerFee; private long buyerSecurityDeposit; private long sellerSecurityDeposit; + private long buyerDepositTxFee; + private long sellerDepositTxFee; + private long buyerPayoutTxFee; + private long sellerPayoutTxFee; + private long buyerPayoutAmount; + private long sellerPayoutAmount; private String makerDepositTxId; private String takerDepositTxId; private String payoutTxId; @@ -117,6 +123,36 @@ public TradeInfoV1Builder withSellerSecurityDeposit(long sellerSecurityDeposit) return this; } + public TradeInfoV1Builder withBuyerDepositTxFee(long buyerDepositTxFee) { + this.buyerDepositTxFee = buyerDepositTxFee; + return this; + } + + public TradeInfoV1Builder withSellerDepositTxFee(long sellerDepositTxFee) { + this.sellerDepositTxFee = sellerDepositTxFee; + return this; + } + + public TradeInfoV1Builder withBuyerPayoutTxFee(long buyerPayoutTxFee) { + this.buyerPayoutTxFee = buyerPayoutTxFee; + return this; + } + + public TradeInfoV1Builder withSellerPayoutTxFee(long sellerPayoutTxFee) { + this.sellerPayoutTxFee = sellerPayoutTxFee; + return this; + } + + public TradeInfoV1Builder withBuyerPayoutAmount(long buyerPayoutAmount) { + this.buyerPayoutAmount = buyerPayoutAmount; + return this; + } + + public TradeInfoV1Builder withSellerPayoutAmount(long sellerPayoutAmount) { + this.sellerPayoutAmount = sellerPayoutAmount; + return this; + } + public TradeInfoV1Builder withMakerDepositTxId(String makerDepositTxId) { this.makerDepositTxId = makerDepositTxId; return this; diff --git a/core/src/main/java/haveno/core/support/dispute/DisputeManager.java b/core/src/main/java/haveno/core/support/dispute/DisputeManager.java index 6a1f69c9579..95ad78d6281 100644 --- a/core/src/main/java/haveno/core/support/dispute/DisputeManager.java +++ b/core/src/main/java/haveno/core/support/dispute/DisputeManager.java @@ -69,7 +69,6 @@ import java.security.KeyPair; import java.time.Instant; import java.util.ArrayList; -import java.util.Arrays; import java.util.Date; import java.util.List; import java.util.Optional; @@ -729,23 +728,21 @@ public void closeDisputeTicket(DisputeResult disputeResult, Dispute dispute, Str dispute.addAndPersistChatMessage(chatMessage); } - // create dispute payout tx if not published + // create dispute payout tx once per trader if we have their updated multisig hex TradePeer receiver = trade.getTradePeer(dispute.getTraderPubKeyRing()); - if (!trade.isPayoutPublished() && receiver.getUpdatedMultisigHex() != null) { - trade.getProcessModel().setUnsignedPayoutTx(createDisputePayoutTx(trade, dispute.getContract(), disputeResult, false)); // can be null if we don't have receiver's multisig hex + if (!trade.isPayoutPublished() && receiver.getUpdatedMultisigHex() != null && receiver.getUnsignedPayoutTxHex() == null) { + createDisputePayoutTx(trade, dispute.getContract(), disputeResult, true); } // create dispute closed message - MoneroTxWallet unsignedPayoutTx = receiver.getUpdatedMultisigHex() == null ? null : trade.getProcessModel().getUnsignedPayoutTx(); - String unsignedPayoutTxHex = unsignedPayoutTx == null ? null : unsignedPayoutTx.getTxSet().getMultisigTxHex(); TradePeer receiverPeer = receiver == trade.getBuyer() ? trade.getSeller() : trade.getBuyer(); - boolean deferPublishPayout = !exists && unsignedPayoutTxHex != null && receiverPeer.getUpdatedMultisigHex() != null && trade.getDisputeState().ordinal() >= Trade.DisputeState.ARBITRATOR_SAW_ARRIVED_DISPUTE_CLOSED_MSG.ordinal(); + boolean deferPublishPayout = !exists && receiver.getUnsignedPayoutTxHex() != null && receiverPeer.getUpdatedMultisigHex() != null && trade.getDisputeState().ordinal() >= Trade.DisputeState.ARBITRATOR_SAW_ARRIVED_DISPUTE_CLOSED_MSG.ordinal(); DisputeClosedMessage disputeClosedMessage = new DisputeClosedMessage(disputeResult, p2PService.getAddress(), UUID.randomUUID().toString(), getSupportType(), trade.getSelf().getUpdatedMultisigHex(), - unsignedPayoutTxHex, // include dispute payout tx if arbitrator has their updated multisig info + receiver.getUnsignedPayoutTxHex(), // include dispute payout tx if arbitrator has their updated multisig info deferPublishPayout); // instruct trader to defer publishing payout tx because peer is expected to publish imminently // send dispute closed message @@ -812,12 +809,6 @@ public void onFault(String errorMessage) { } } ); - - // save state - if (unsignedPayoutTx != null) { - trade.setPayoutTx(unsignedPayoutTx); - trade.setPayoutTxHex(unsignedPayoutTx.getTxSet().getMultisigTxHex()); - } trade.advanceDisputeState(Trade.DisputeState.ARBITRATOR_SENT_DISPUTE_CLOSED_MSG); requestPersistence(); } catch (Exception e) { @@ -829,7 +820,7 @@ public void onFault(String errorMessage) { // Utils /////////////////////////////////////////////////////////////////////////////////////////// - public MoneroTxWallet createDisputePayoutTx(Trade trade, Contract contract, DisputeResult disputeResult, boolean skipMultisigImport) { + public MoneroTxWallet createDisputePayoutTx(Trade trade, Contract contract, DisputeResult disputeResult, boolean updateState) { // import multisig hex trade.importMultisigHex(); @@ -848,42 +839,34 @@ public MoneroTxWallet createDisputePayoutTx(Trade trade, Contract contract, Disp // trade wallet must be synced if (trade.getWallet().isMultisigImportNeeded()) throw new RuntimeException("Arbitrator's wallet needs updated multisig hex to create payout tx which means a trader must have already broadcast the payout tx for trade " + trade.getId()); - // collect winner and loser payout address and amounts - String winnerPayoutAddress = disputeResult.getWinner() == Winner.BUYER ? - (contract.isBuyerMakerAndSellerTaker() ? contract.getMakerPayoutAddressString() : contract.getTakerPayoutAddressString()) : - (contract.isBuyerMakerAndSellerTaker() ? contract.getTakerPayoutAddressString() : contract.getMakerPayoutAddressString()); - String loserPayoutAddress = winnerPayoutAddress.equals(contract.getMakerPayoutAddressString()) ? contract.getTakerPayoutAddressString() : contract.getMakerPayoutAddressString(); - BigInteger winnerPayoutAmount = disputeResult.getWinner() == Winner.BUYER ? disputeResult.getBuyerPayoutAmount() : disputeResult.getSellerPayoutAmount(); - BigInteger loserPayoutAmount = disputeResult.getWinner() == Winner.BUYER ? disputeResult.getSellerPayoutAmount() : disputeResult.getBuyerPayoutAmount(); - - // check sufficient balance - if (winnerPayoutAmount.compareTo(BigInteger.ZERO) < 0) throw new RuntimeException("Winner payout cannot be negative"); - if (loserPayoutAmount.compareTo(BigInteger.ZERO) < 0) throw new RuntimeException("Loser payout cannot be negative"); - if (winnerPayoutAmount.add(loserPayoutAmount).compareTo(trade.getWallet().getUnlockedBalance()) > 0) { - throw new RuntimeException("The payout amounts are more than the wallet's unlocked balance, unlocked balance=" + trade.getWallet().getUnlockedBalance() + " vs " + winnerPayoutAmount + " + " + loserPayoutAmount + " = " + (winnerPayoutAmount.add(loserPayoutAmount))); + // check amounts + if (disputeResult.getBuyerPayoutAmountBeforeCost().compareTo(BigInteger.ZERO) < 0) throw new RuntimeException("Buyer payout cannot be negative"); + if (disputeResult.getSellerPayoutAmountBeforeCost().compareTo(BigInteger.ZERO) < 0) throw new RuntimeException("Seller payout cannot be negative"); + if (disputeResult.getBuyerPayoutAmountBeforeCost().add(disputeResult.getSellerPayoutAmountBeforeCost()).compareTo(trade.getWallet().getUnlockedBalance()) > 0) { + throw new RuntimeException("The payout amounts are more than the wallet's unlocked balance, unlocked balance=" + trade.getWallet().getUnlockedBalance() + " vs " + disputeResult.getBuyerPayoutAmountBeforeCost() + " + " + disputeResult.getSellerPayoutAmountBeforeCost() + " = " + (disputeResult.getBuyerPayoutAmountBeforeCost().add(disputeResult.getSellerPayoutAmountBeforeCost()))); } - // add any loss of precision to winner payout - winnerPayoutAmount = winnerPayoutAmount.add(trade.getWallet().getUnlockedBalance().subtract(winnerPayoutAmount.add(loserPayoutAmount))); - // create dispute payout tx config MoneroTxConfig txConfig = new MoneroTxConfig().setAccountIndex(0); + String buyerPayoutAddress = contract.isBuyerMakerAndSellerTaker() ? contract.getMakerPayoutAddressString() : contract.getTakerPayoutAddressString(); + String sellerPayoutAddress = contract.isBuyerMakerAndSellerTaker() ? contract.getTakerPayoutAddressString() : contract.getMakerPayoutAddressString(); txConfig.setPriority(XmrWalletService.PROTOCOL_FEE_PRIORITY); - if (winnerPayoutAmount.compareTo(BigInteger.ZERO) > 0) txConfig.addDestination(winnerPayoutAddress, winnerPayoutAmount); - if (loserPayoutAmount.compareTo(BigInteger.ZERO) > 0) txConfig.addDestination(loserPayoutAddress, loserPayoutAmount); + if (disputeResult.getBuyerPayoutAmountBeforeCost().compareTo(BigInteger.ZERO) > 0) txConfig.addDestination(buyerPayoutAddress, disputeResult.getBuyerPayoutAmountBeforeCost()); + if (disputeResult.getSellerPayoutAmountBeforeCost().compareTo(BigInteger.ZERO) > 0) txConfig.addDestination(sellerPayoutAddress, disputeResult.getSellerPayoutAmountBeforeCost()); // configure who pays mining fee + BigInteger loserPayoutAmount = disputeResult.getWinner() == Winner.BUYER ? disputeResult.getSellerPayoutAmountBeforeCost() : disputeResult.getBuyerPayoutAmountBeforeCost(); if (loserPayoutAmount.equals(BigInteger.ZERO)) txConfig.setSubtractFeeFrom(0); // winner pays fee if loser gets 0 else { switch (disputeResult.getSubtractFeeFrom()) { case BUYER_AND_SELLER: - txConfig.setSubtractFeeFrom(Arrays.asList(0, 1)); + txConfig.setSubtractFeeFrom(0, 1); break; case BUYER_ONLY: - txConfig.setSubtractFeeFrom(disputeResult.getWinner() == Winner.BUYER ? 0 : 1); + txConfig.setSubtractFeeFrom(0); break; case SELLER_ONLY: - txConfig.setSubtractFeeFrom(disputeResult.getWinner() == Winner.SELLER ? 0 : 1); + txConfig.setSubtractFeeFrom(1); break; } } @@ -897,8 +880,14 @@ public MoneroTxWallet createDisputePayoutTx(Trade trade, Contract contract, Disp throw new RuntimeException("Loser payout is too small to cover the mining fee"); } - // save updated multisig hex - trade.getSelf().setUpdatedMultisigHex(trade.getWallet().exportMultisigHex()); + // update trade state + if (updateState) { + trade.getProcessModel().setUnsignedPayoutTx(payoutTx); + trade.setPayoutTx(payoutTx); + trade.setPayoutTxHex(payoutTx.getTxSet().getMultisigTxHex()); + if (trade.getBuyer().getUpdatedMultisigHex() != null && trade.getBuyer().getUnsignedPayoutTxHex() == null) trade.getBuyer().setUnsignedPayoutTxHex(payoutTx.getTxSet().getMultisigTxHex()); + if (trade.getSeller().getUpdatedMultisigHex() != null && trade.getSeller().getUnsignedPayoutTxHex() == null) trade.getSeller().setUnsignedPayoutTxHex(payoutTx.getTxSet().getMultisigTxHex()); + } return payoutTx; } catch (Exception e) { trade.syncAndPollWallet(); diff --git a/core/src/main/java/haveno/core/support/dispute/DisputeResult.java b/core/src/main/java/haveno/core/support/dispute/DisputeResult.java index 7929b2b32e9..f428bfe1af1 100644 --- a/core/src/main/java/haveno/core/support/dispute/DisputeResult.java +++ b/core/src/main/java/haveno/core/support/dispute/DisputeResult.java @@ -86,8 +86,8 @@ public enum SubtractFeeFrom { @Setter @Nullable private byte[] arbitratorSignature; - private long buyerPayoutAmount; - private long sellerPayoutAmount; + private long buyerPayoutAmountBeforeCost; + private long sellerPayoutAmountBeforeCost; @Setter @Nullable private byte[] arbitratorPubKey; @@ -109,8 +109,8 @@ public DisputeResult(String tradeId, String summaryNotes, @Nullable ChatMessage chatMessage, @Nullable byte[] arbitratorSignature, - long buyerPayoutAmount, - long sellerPayoutAmount, + long buyerPayoutAmountBeforeCost, + long sellerPayoutAmountBeforeCost, @Nullable byte[] arbitratorPubKey, long closeDate) { this.tradeId = tradeId; @@ -124,8 +124,8 @@ public DisputeResult(String tradeId, this.summaryNotesProperty.set(summaryNotes); this.chatMessage = chatMessage; this.arbitratorSignature = arbitratorSignature; - this.buyerPayoutAmount = buyerPayoutAmount; - this.sellerPayoutAmount = sellerPayoutAmount; + this.buyerPayoutAmountBeforeCost = buyerPayoutAmountBeforeCost; + this.sellerPayoutAmountBeforeCost = sellerPayoutAmountBeforeCost; this.arbitratorPubKey = arbitratorPubKey; this.closeDate = closeDate; } @@ -147,8 +147,8 @@ public static DisputeResult fromProto(protobuf.DisputeResult proto) { proto.getSummaryNotes(), proto.getChatMessage() == null ? null : ChatMessage.fromPayloadProto(proto.getChatMessage()), proto.getArbitratorSignature().toByteArray(), - proto.getBuyerPayoutAmount(), - proto.getSellerPayoutAmount(), + proto.getBuyerPayoutAmountBeforeCost(), + proto.getSellerPayoutAmountBeforeCost(), proto.getArbitratorPubKey().toByteArray(), proto.getCloseDate()); } @@ -163,8 +163,8 @@ public protobuf.DisputeResult toProtoMessage() { .setIdVerification(idVerificationProperty.get()) .setScreenCast(screenCastProperty.get()) .setSummaryNotes(summaryNotesProperty.get()) - .setBuyerPayoutAmount(buyerPayoutAmount) - .setSellerPayoutAmount(sellerPayoutAmount) + .setBuyerPayoutAmountBeforeCost(buyerPayoutAmountBeforeCost) + .setSellerPayoutAmountBeforeCost(sellerPayoutAmountBeforeCost) .setCloseDate(closeDate); Optional.ofNullable(arbitratorSignature).ifPresent(arbitratorSignature -> builder.setArbitratorSignature(ByteString.copyFrom(arbitratorSignature))); @@ -213,22 +213,22 @@ public StringProperty summaryNotesProperty() { return summaryNotesProperty; } - public void setBuyerPayoutAmount(BigInteger buyerPayoutAmount) { - if (buyerPayoutAmount.compareTo(BigInteger.ZERO) < 0) throw new IllegalArgumentException("buyerPayoutAmount cannot be negative"); - this.buyerPayoutAmount = buyerPayoutAmount.longValueExact(); + public void setBuyerPayoutAmountBeforeCost(BigInteger buyerPayoutAmountBeforeCost) { + if (buyerPayoutAmountBeforeCost.compareTo(BigInteger.ZERO) < 0) throw new IllegalArgumentException("buyerPayoutAmountBeforeCost cannot be negative"); + this.buyerPayoutAmountBeforeCost = buyerPayoutAmountBeforeCost.longValueExact(); } - public BigInteger getBuyerPayoutAmount() { - return BigInteger.valueOf(buyerPayoutAmount); + public BigInteger getBuyerPayoutAmountBeforeCost() { + return BigInteger.valueOf(buyerPayoutAmountBeforeCost); } - public void setSellerPayoutAmount(BigInteger sellerPayoutAmount) { - if (sellerPayoutAmount.compareTo(BigInteger.ZERO) < 0) throw new IllegalArgumentException("sellerPayoutAmount cannot be negative"); - this.sellerPayoutAmount = sellerPayoutAmount.longValueExact(); + public void setSellerPayoutAmountBeforeCost(BigInteger sellerPayoutAmountBeforeCost) { + if (sellerPayoutAmountBeforeCost.compareTo(BigInteger.ZERO) < 0) throw new IllegalArgumentException("sellerPayoutAmountBeforeCost cannot be negative"); + this.sellerPayoutAmountBeforeCost = sellerPayoutAmountBeforeCost.longValueExact(); } - public BigInteger getSellerPayoutAmount() { - return BigInteger.valueOf(sellerPayoutAmount); + public BigInteger getSellerPayoutAmountBeforeCost() { + return BigInteger.valueOf(sellerPayoutAmountBeforeCost); } public void setCloseDate(Date closeDate) { @@ -253,8 +253,8 @@ public String toString() { ",\n summaryNotesProperty=" + summaryNotesProperty + ",\n chatMessage=" + chatMessage + ",\n arbitratorSignature=" + Utilities.bytesAsHexString(arbitratorSignature) + - ",\n buyerPayoutAmount=" + buyerPayoutAmount + - ",\n sellerPayoutAmount=" + sellerPayoutAmount + + ",\n buyerPayoutAmountBeforeCost=" + buyerPayoutAmountBeforeCost + + ",\n sellerPayoutAmountBeforeCost=" + sellerPayoutAmountBeforeCost + ",\n arbitratorPubKey=" + Utilities.bytesAsHexString(arbitratorPubKey) + ",\n closeDate=" + closeDate + "\n}"; diff --git a/core/src/main/java/haveno/core/support/dispute/arbitration/ArbitrationManager.java b/core/src/main/java/haveno/core/support/dispute/arbitration/ArbitrationManager.java index 57908663d60..fc7197da4c2 100644 --- a/core/src/main/java/haveno/core/support/dispute/arbitration/ArbitrationManager.java +++ b/core/src/main/java/haveno/core/support/dispute/arbitration/ArbitrationManager.java @@ -380,42 +380,22 @@ private MoneroTxSet signAndPublishDisputePayoutTx(Trade trade) { if (!arbitratorSignedPayoutTx.getOutputSum().equals(destinationSum.add(arbitratorSignedPayoutTx.getChangeAmount()))) throw new RuntimeException("Sum of outputs != destination amounts + change amount"); // get actual payout amounts - BigInteger actualWinnerAmount = disputeResult.getWinner() == Winner.BUYER ? buyerPayoutDestination.getAmount() : sellerPayoutDestination.getAmount(); - BigInteger actualLoserAmount = numDestinations == 1 ? BigInteger.ZERO : disputeResult.getWinner() == Winner.BUYER ? sellerPayoutDestination.getAmount() : buyerPayoutDestination.getAmount(); + BigInteger actualBuyerAmount = buyerPayoutDestination == null ? BigInteger.ZERO : buyerPayoutDestination.getAmount(); + BigInteger actualSellerAmount = sellerPayoutDestination == null ? BigInteger.ZERO : sellerPayoutDestination.getAmount(); // verify payouts sum to unlocked balance within loss of precision due to conversion to centineros - BigInteger txCost = arbitratorSignedPayoutTx.getFee().add(arbitratorSignedPayoutTx.getChangeAmount()); // fee + lost dust change - if (trade.getWallet().getUnlockedBalance().subtract(actualWinnerAmount.add(actualLoserAmount).add(txCost)).compareTo(BigInteger.valueOf(0)) > 0) { - throw new RuntimeException("The dispute payout amounts do not sum to the wallet's unlocked balance while verifying the dispute payout tx, unlocked balance=" + trade.getWallet().getUnlockedBalance() + " vs sum payout amount=" + actualWinnerAmount.add(actualLoserAmount) + ", winner payout=" + actualWinnerAmount + ", loser payout=" + actualLoserAmount); + BigInteger txCost = arbitratorSignedPayoutTx.getFee().add(arbitratorSignedPayoutTx.getChangeAmount()); // cost = fee + lost dust change + if (!arbitratorSignedPayoutTx.getChangeAmount().equals(BigInteger.ZERO)) log.warn("Dust left in multisig wallet for {} {}: {}", getClass().getSimpleName(), trade.getId(), arbitratorSignedPayoutTx.getChangeAmount()); + if (trade.getWallet().getUnlockedBalance().subtract(actualBuyerAmount.add(actualSellerAmount).add(txCost)).compareTo(BigInteger.valueOf(0)) > 0) { + throw new RuntimeException("The dispute payout amounts do not sum to the wallet's unlocked balance while verifying the dispute payout tx, unlocked balance=" + trade.getWallet().getUnlockedBalance() + " vs sum payout amount=" + actualBuyerAmount.add(actualSellerAmount) + ", buyer payout=" + actualBuyerAmount + ", seller payout=" + actualSellerAmount); } - // get expected payout amounts - BigInteger expectedWinnerAmount = disputeResult.getWinner() == Winner.BUYER ? disputeResult.getBuyerPayoutAmount() : disputeResult.getSellerPayoutAmount(); - BigInteger expectedLoserAmount = disputeResult.getWinner() == Winner.BUYER ? disputeResult.getSellerPayoutAmount() : disputeResult.getBuyerPayoutAmount(); - - // subtract mining fee from expected payouts - if (expectedLoserAmount.equals(BigInteger.ZERO)) expectedWinnerAmount = expectedWinnerAmount.subtract(txCost); // winner pays fee if loser gets 0 - else { - switch (disputeResult.getSubtractFeeFrom()) { - case BUYER_AND_SELLER: - BigInteger txCostSplit = txCost.divide(BigInteger.valueOf(2)); - expectedWinnerAmount = expectedWinnerAmount.subtract(txCostSplit); - expectedLoserAmount = expectedLoserAmount.subtract(txCostSplit); - break; - case BUYER_ONLY: - expectedWinnerAmount = expectedWinnerAmount.subtract(disputeResult.getWinner() == Winner.BUYER ? txCost : BigInteger.ZERO); - expectedLoserAmount = expectedLoserAmount.subtract(disputeResult.getWinner() == Winner.BUYER ? BigInteger.ZERO : txCost); - break; - case SELLER_ONLY: - expectedWinnerAmount = expectedWinnerAmount.subtract(disputeResult.getWinner() == Winner.BUYER ? BigInteger.ZERO : txCost); - expectedLoserAmount = expectedLoserAmount.subtract(disputeResult.getWinner() == Winner.BUYER ? txCost : BigInteger.ZERO); - break; - } - } - - // verify winner and loser payout amounts - if (!expectedWinnerAmount.equals(actualWinnerAmount)) throw new RuntimeException("Unexpected winner payout: " + expectedWinnerAmount + " vs " + actualWinnerAmount); - if (!expectedLoserAmount.equals(actualLoserAmount)) throw new RuntimeException("Unexpected loser payout: " + expectedLoserAmount + " vs " + actualLoserAmount); + // verify payout amounts + BigInteger[] buyerSellerPayoutTxCost = getBuyerSellerPayoutTxCost(disputeResult, txCost); + BigInteger expectedBuyerAmount = disputeResult.getBuyerPayoutAmountBeforeCost().subtract(buyerSellerPayoutTxCost[0]); + BigInteger expectedSellerAmount = disputeResult.getSellerPayoutAmountBeforeCost().subtract(buyerSellerPayoutTxCost[1]); + if (!expectedBuyerAmount.equals(actualBuyerAmount)) throw new RuntimeException("Unexpected buyer payout: " + expectedBuyerAmount + " vs " + actualBuyerAmount); + if (!expectedSellerAmount.equals(actualSellerAmount)) throw new RuntimeException("Unexpected seller payout: " + expectedSellerAmount + " vs " + actualSellerAmount); // check wallet's daemon connection trade.checkDaemonConnection(); @@ -431,7 +411,8 @@ private MoneroTxSet signAndPublishDisputePayoutTx(Trade trade) { boolean signed = trade.getPayoutTxHex() != null && !nonSignedDisputePayoutTxHexes.contains(trade.getPayoutTxHex()); // sign arbitrator-signed payout tx - if (!signed) { + if (signed) disputeTxSet.setMultisigTxHex(trade.getPayoutTxHex()); + else { MoneroMultisigSignResult result = multisigWallet.signMultisigTxHex(unsignedPayoutTxHex); if (result.getSignedMultisigTxHex() == null) throw new RuntimeException("Error signing arbitrator-signed payout tx"); String signedMultisigTxHex = result.getSignedMultisigTxHex(); @@ -443,8 +424,9 @@ private MoneroTxSet signAndPublishDisputePayoutTx(Trade trade) { // TODO (monero-project): creating tx will require exchanging updated multisig hex if message needs reprocessed. provide weight with describe_transfer so fee can be estimated? MoneroTxWallet feeEstimateTx = null; try { - feeEstimateTx = createDisputePayoutTx(trade, dispute.getContract(), disputeResult, true); + feeEstimateTx = createDisputePayoutTx(trade, dispute.getContract(), disputeResult, false); } catch (Exception e) { + e.printStackTrace(); log.warn("Could not recreate dispute payout tx to verify fee: " + e.getMessage()); } if (feeEstimateTx != null) { @@ -453,8 +435,6 @@ private MoneroTxSet signAndPublishDisputePayoutTx(Trade trade) { if (feeDiff > XmrWalletService.MINER_FEE_TOLERANCE) throw new IllegalArgumentException("Miner fee is not within " + (XmrWalletService.MINER_FEE_TOLERANCE * 100) + "% of estimated fee, expected " + feeEstimate + " but was " + arbitratorSignedPayoutTx.getFee()); log.info("Payout tx fee {} is within tolerance, diff %={}", arbitratorSignedPayoutTx.getFee(), feeDiff); } - } else { - disputeTxSet.setMultisigTxHex(trade.getPayoutTxHex()); } // submit fully signed payout tx to the network @@ -468,4 +448,26 @@ private MoneroTxSet signAndPublishDisputePayoutTx(Trade trade) { dispute.setDisputePayoutTxId(disputeTxSet.getTxs().get(0).getHash()); return disputeTxSet; } + + public static BigInteger[] getBuyerSellerPayoutTxCost(DisputeResult disputeResult, BigInteger payoutTxCost) { + boolean isBuyerWinner = disputeResult.getWinner() == Winner.BUYER; + BigInteger loserAmount = isBuyerWinner ? disputeResult.getSellerPayoutAmountBeforeCost() : disputeResult.getBuyerPayoutAmountBeforeCost(); + if (loserAmount.equals(BigInteger.valueOf(0))) { + BigInteger buyerPayoutTxFee = isBuyerWinner ? payoutTxCost : BigInteger.ZERO; + BigInteger sellerPayoutTxFee = isBuyerWinner ? BigInteger.ZERO : payoutTxCost; + return new BigInteger[] { buyerPayoutTxFee, sellerPayoutTxFee }; + } else { + switch (disputeResult.getSubtractFeeFrom()) { + case BUYER_AND_SELLER: + BigInteger payoutTxFeeSplit = payoutTxCost.divide(BigInteger.valueOf(2)); + return new BigInteger[] { payoutTxFeeSplit, payoutTxFeeSplit }; + case BUYER_ONLY: + return new BigInteger[] { payoutTxCost, BigInteger.ZERO }; + case SELLER_ONLY: + return new BigInteger[] { BigInteger.ZERO, payoutTxCost }; + default: + throw new RuntimeException("Unsupported subtract fee from: " + disputeResult.getSubtractFeeFrom()); + } + } + } } diff --git a/core/src/main/java/haveno/core/support/dispute/mediation/MediationManager.java b/core/src/main/java/haveno/core/support/dispute/mediation/MediationManager.java index 100deeac7bd..1d910fc800b 100644 --- a/core/src/main/java/haveno/core/support/dispute/mediation/MediationManager.java +++ b/core/src/main/java/haveno/core/support/dispute/mediation/MediationManager.java @@ -188,8 +188,8 @@ public void handleDisputeClosedMessage(DisputeClosedMessage disputeResultMessage Trade trade = tradeOptional.get(); if (trade.getDisputeState() == Trade.DisputeState.MEDIATION_REQUESTED || trade.getDisputeState() == Trade.DisputeState.MEDIATION_STARTED_BY_PEER) { - trade.getProcessModel().setBuyerPayoutAmountFromMediation(disputeResult.getBuyerPayoutAmount().longValueExact()); - trade.getProcessModel().setSellerPayoutAmountFromMediation(disputeResult.getSellerPayoutAmount().longValueExact()); + trade.getProcessModel().setBuyerPayoutAmountFromMediation(disputeResult.getBuyerPayoutAmountBeforeCost().longValueExact()); + trade.getProcessModel().setSellerPayoutAmountFromMediation(disputeResult.getSellerPayoutAmountBeforeCost().longValueExact()); trade.setDisputeState(Trade.DisputeState.MEDIATION_CLOSED); @@ -222,8 +222,8 @@ public void onAcceptMediationResult(Trade trade, Optional optionalDispute = findDispute(tradeId); checkArgument(optionalDispute.isPresent(), "dispute must be present"); DisputeResult disputeResult = optionalDispute.get().getDisputeResultProperty().get(); - BigInteger buyerPayoutAmount = disputeResult.getBuyerPayoutAmount(); - BigInteger sellerPayoutAmount = disputeResult.getSellerPayoutAmount(); + BigInteger buyerPayoutAmount = disputeResult.getBuyerPayoutAmountBeforeCost(); + BigInteger sellerPayoutAmount = disputeResult.getSellerPayoutAmountBeforeCost(); ProcessModel processModel = trade.getProcessModel(); processModel.setBuyerPayoutAmountFromMediation(buyerPayoutAmount.longValueExact()); processModel.setSellerPayoutAmountFromMediation(sellerPayoutAmount.longValueExact()); diff --git a/core/src/main/java/haveno/core/trade/HavenoUtils.java b/core/src/main/java/haveno/core/trade/HavenoUtils.java index 9991c66ecf3..246d9f2ae91 100644 --- a/core/src/main/java/haveno/core/trade/HavenoUtils.java +++ b/core/src/main/java/haveno/core/trade/HavenoUtils.java @@ -58,6 +58,9 @@ import javax.annotation.Nullable; import lombok.extern.slf4j.Slf4j; import monero.common.MoneroRpcConnection; +import monero.wallet.model.MoneroDestination; +import monero.wallet.model.MoneroTxWallet; + import org.bitcoinj.core.Coin; /** @@ -543,4 +546,12 @@ public static boolean connectionConfigsEqual(MoneroRpcConnection c1, MoneroRpcCo if (c1 == null) return false; return c1.equals(c2); // equality considers uri, username, and password } + + // TODO: move to monero-java MoneroTxWallet + public static MoneroDestination getDestination(String address, MoneroTxWallet tx) { + for (MoneroDestination destination : tx.getOutgoingTransfer().getDestinations()) { + if (address.equals(destination.getAddress())) return destination; + } + return null; + } } diff --git a/core/src/main/java/haveno/core/trade/Trade.java b/core/src/main/java/haveno/core/trade/Trade.java index e1538895705..c9a3ccbb528 100644 --- a/core/src/main/java/haveno/core/trade/Trade.java +++ b/core/src/main/java/haveno/core/trade/Trade.java @@ -37,6 +37,8 @@ import haveno.core.proto.CoreProtoResolver; import haveno.core.proto.network.CoreNetworkProtoResolver; import haveno.core.support.dispute.Dispute; +import haveno.core.support.dispute.DisputeResult; +import haveno.core.support.dispute.arbitration.ArbitrationManager; import haveno.core.support.dispute.mediation.MediationResultState; import haveno.core.support.dispute.refund.RefundResultState; import haveno.core.support.messages.ChatMessage; @@ -323,7 +325,6 @@ public static protobuf.Trade.TradePeriodState toProtoMessage(Trade.TradePeriodSt @Getter private final Offer offer; private final long takerFee; - private final long totalTxFee; // Added in 1.5.1 @Getter @@ -451,6 +452,7 @@ public static protobuf.Trade.TradePeriodState toProtoMessage(Trade.TradePeriodSt @Getter @Setter private String payoutTxKey; + private long payoutTxFee; private Long payoutHeight; private IdlePayoutSyncer idlePayoutSyncer; @@ -472,7 +474,6 @@ protected Trade(Offer offer, this.offer = offer; this.amount = tradeAmount.longValueExact(); this.takerFee = takerFee.longValueExact(); - this.totalTxFee = 0l; // TODO: sum tx fees this.price = tradePrice; this.xmrWalletService = xmrWalletService; this.processModel = processModel; @@ -941,20 +942,25 @@ public MoneroTxWallet createPayoutTx() { .setRelay(false) .setPriority(XmrWalletService.PROTOCOL_FEE_PRIORITY)); - // save updated multisig hex + // update state + BigInteger payoutTxFeeSplit = payoutTx.getFee().divide(BigInteger.valueOf(2)); + getBuyer().setPayoutTxFee(payoutTxFeeSplit); + getBuyer().setPayoutAmount(HavenoUtils.getDestination(buyerPayoutAddress, payoutTx).getAmount()); + getSeller().setPayoutTxFee(payoutTxFeeSplit); + getSeller().setPayoutAmount(HavenoUtils.getDestination(sellerPayoutAddress, payoutTx).getAmount()); getSelf().setUpdatedMultisigHex(multisigWallet.exportMultisigHex()); return payoutTx; } /** - * Verify a payout tx. + * Process a payout tx. * * @param payoutTxHex is the payout tx hex to verify * @param sign signs the payout tx if true * @param publish publishes the signed payout tx if true */ - public void verifyPayoutTx(String payoutTxHex, boolean sign, boolean publish) { - log.info("Verifying payout tx"); + public void processPayoutTx(String payoutTxHex, boolean sign, boolean publish) { + log.info("Processing payout tx for {} {}", getClass().getSimpleName(), getId()); // gather relevant info MoneroWallet wallet = getWallet(); @@ -981,6 +987,7 @@ public void verifyPayoutTx(String payoutTxHex, boolean sign, boolean publish) { if (!sellerPayoutDestination.getAddress().equals(contract.getSellerPayoutAddressString())) throw new IllegalArgumentException("Seller payout address does not match contract"); // verify change address is multisig's primary address + if (!payoutTx.getChangeAmount().equals(BigInteger.ZERO)) log.warn("Dust left in multisig wallet for {} {}: {}", getClass().getSimpleName(), getId(), payoutTx.getChangeAmount()); if (!payoutTx.getChangeAmount().equals(BigInteger.ZERO) && !payoutTx.getChangeAddress().equals(wallet.getPrimaryAddress())) throw new IllegalArgumentException("Change address is not multisig wallet's primary address"); // verify sum of outputs = destination amounts + change amount @@ -988,11 +995,12 @@ public void verifyPayoutTx(String payoutTxHex, boolean sign, boolean publish) { // verify buyer destination amount is deposit amount + this amount - 1/2 tx costs BigInteger txCost = payoutTx.getFee().add(payoutTx.getChangeAmount()); - BigInteger expectedBuyerPayout = buyerDepositAmount.add(tradeAmount).subtract(txCost.divide(BigInteger.valueOf(2))); + BigInteger txCostSplit = txCost.divide(BigInteger.valueOf(2)); + BigInteger expectedBuyerPayout = buyerDepositAmount.add(tradeAmount).subtract(txCostSplit); if (!buyerPayoutDestination.getAmount().equals(expectedBuyerPayout)) throw new IllegalArgumentException("Buyer destination amount is not deposit amount + trade amount - 1/2 tx costs, " + buyerPayoutDestination.getAmount() + " vs " + expectedBuyerPayout); // verify seller destination amount is deposit amount - this amount - 1/2 tx costs - BigInteger expectedSellerPayout = sellerDepositAmount.subtract(tradeAmount).subtract(txCost.divide(BigInteger.valueOf(2))); + BigInteger expectedSellerPayout = sellerDepositAmount.subtract(tradeAmount).subtract(txCostSplit); if (!sellerPayoutDestination.getAmount().equals(expectedSellerPayout)) throw new IllegalArgumentException("Seller destination amount is not deposit amount - trade amount - 1/2 tx costs, " + sellerPayoutDestination.getAmount() + " vs " + expectedSellerPayout); // check wallet connection @@ -1025,7 +1033,6 @@ public void verifyPayoutTx(String payoutTxHex, boolean sign, boolean publish) { // submit payout tx if (publish) { - //if (true) throw new RuntimeException("Let's pretend there's an error last second submitting tx to daemon, so we need to resubmit payout hex"); wallet.submitMultisigTxHex(payoutTxHex); pollWallet(); } @@ -1296,9 +1303,47 @@ public void setAmount(BigInteger tradeAmount) { public void setPayoutTx(MoneroTxWallet payoutTx) { this.payoutTx = payoutTx; payoutTxId = payoutTx.getHash(); - if ("".equals(payoutTxId)) payoutTxId = null; // tx hash is empty until signed + if ("".equals(payoutTxId)) payoutTxId = null; // tx id is empty until signed payoutTxKey = payoutTx.getKey(); + payoutTxFee = payoutTx.getFee().longValueExact(); for (Dispute dispute : getDisputes()) dispute.setDisputePayoutTxId(payoutTxId); + + // set final payout amounts + if (getDisputeState().isNotDisputed()) { + BigInteger splitTxFee = payoutTx.getFee().divide(BigInteger.valueOf(2)); + getBuyer().setPayoutTxFee(splitTxFee); + getSeller().setPayoutTxFee(splitTxFee); + getBuyer().setPayoutAmount(getBuyer().getSecurityDeposit().subtract(getBuyer().getPayoutTxFee()).add(getAmount())); + getSeller().setPayoutAmount(getSeller().getSecurityDeposit().subtract(getSeller().getPayoutTxFee())); + } else if (getDisputeState().isClosed()) { + DisputeResult disputeResult = getDisputeResult(); + BigInteger[] buyerSellerPayoutTxFees = ArbitrationManager.getBuyerSellerPayoutTxCost(disputeResult, payoutTx.getFee()); + getBuyer().setPayoutTxFee(buyerSellerPayoutTxFees[0]); + getSeller().setPayoutTxFee(buyerSellerPayoutTxFees[1]); + getBuyer().setPayoutAmount(disputeResult.getBuyerPayoutAmountBeforeCost().subtract(getBuyer().getPayoutTxFee())); + getSeller().setPayoutAmount(disputeResult.getSellerPayoutAmountBeforeCost().subtract(getSeller().getPayoutTxFee())); + } + } + + public DisputeResult getDisputeResult() { + if (getDisputes().isEmpty()) return null; + return getDisputes().get(getDisputes().size() - 1).getDisputeResultProperty().get(); + } + + @Nullable + public MoneroTx getPayoutTx() { + if (payoutTx == null) { + payoutTx = payoutTxId == null ? null : (this instanceof ArbitratorTrade) ? xmrWalletService.getTxWithCache(payoutTxId) : xmrWalletService.getWallet().getTx(payoutTxId); + } + return payoutTx; + } + + public void setPayoutTxFee(BigInteger payoutTxFee) { + this.payoutTxFee = payoutTxFee.longValueExact(); + } + + public BigInteger getPayoutTxFee() { + return BigInteger.valueOf(payoutTxFee); } public void setErrorMessage(String errorMessage) { @@ -1653,15 +1698,7 @@ public BigInteger getSellerSecurityDepositBeforeMiningFee() { @Override public BigInteger getTotalTxFee() { - return BigInteger.valueOf(totalTxFee); - } - - @Nullable - public MoneroTx getPayoutTx() { - if (payoutTx == null) { - payoutTx = payoutTxId == null ? null : (this instanceof ArbitratorTrade) ? xmrWalletService.getTxWithCache(payoutTxId) : xmrWalletService.getWallet().getTx(payoutTxId); - } - return payoutTx; + return getSelf().getDepositTxFee().add(getSelf().getPayoutTxFee()); // sum my tx fees } public boolean hasErrorMessage() { @@ -2019,7 +2056,6 @@ public Message toProtoMessage() { protobuf.Trade.Builder builder = protobuf.Trade.newBuilder() .setOffer(offer.toProtoMessage()) .setTakerFee(takerFee) - .setTotalTxFee(totalTxFee) .setTakeOfferDate(takeOfferDate) .setProcessModel(processModel.toProtoMessage()) .setAmount(amount) @@ -2081,7 +2117,7 @@ public String toString() { return "Trade{" + "\n offer=" + offer + ",\n takerFee=" + takerFee + - ",\n totalTxFee=" + totalTxFee + + ",\n totalTxFee=" + getTotalTxFee() + ",\n takeOfferDate=" + takeOfferDate + ",\n processModel=" + processModel + ",\n payoutTxId='" + payoutTxId + '\'' + @@ -2098,7 +2134,6 @@ public String toString() { ",\n counterCurrencyTxId='" + counterCurrencyTxId + '\'' + ",\n counterCurrencyExtraData='" + counterCurrencyExtraData + '\'' + ",\n chatMessages=" + chatMessages + - ",\n totalTxFee=" + totalTxFee + ",\n takerFee=" + takerFee + ",\n xmrWalletService=" + xmrWalletService + ",\n stateProperty=" + stateProperty + diff --git a/core/src/main/java/haveno/core/trade/protocol/TradePeer.java b/core/src/main/java/haveno/core/trade/protocol/TradePeer.java index 7a3818311d7..2a755be98c7 100644 --- a/core/src/main/java/haveno/core/trade/protocol/TradePeer.java +++ b/core/src/main/java/haveno/core/trade/protocol/TradePeer.java @@ -136,6 +136,11 @@ public final class TradePeer implements PersistablePayload { private long depositTxFee; private long securityDeposit; @Nullable + @Setter + private String unsignedPayoutTxHex; + private long payoutTxFee; + private long payoutAmount; + @Nullable private String updatedMultisigHex; @Getter @Setter @@ -161,6 +166,22 @@ public void setSecurityDeposit(BigInteger securityDeposit) { this.securityDeposit = securityDeposit.longValueExact(); } + public BigInteger getPayoutTxFee() { + return BigInteger.valueOf(payoutTxFee); + } + + public void setPayoutTxFee(BigInteger payoutTxFee) { + this.payoutTxFee = payoutTxFee.longValueExact(); + } + + public BigInteger getPayoutAmount() { + return BigInteger.valueOf(payoutAmount); + } + + public void setPayoutAmount(BigInteger payoutAmount) { + this.payoutAmount = payoutAmount.longValueExact(); + } + @Override public Message toProtoMessage() { final protobuf.TradePeer.Builder builder = protobuf.TradePeer.newBuilder(); @@ -191,12 +212,15 @@ public Message toProtoMessage() { Optional.ofNullable(preparedMultisigHex).ifPresent(e -> builder.setPreparedMultisigHex(preparedMultisigHex)); Optional.ofNullable(madeMultisigHex).ifPresent(e -> builder.setMadeMultisigHex(madeMultisigHex)); Optional.ofNullable(exchangedMultisigHex).ifPresent(e -> builder.setExchangedMultisigHex(exchangedMultisigHex)); + Optional.ofNullable(updatedMultisigHex).ifPresent(e -> builder.setUpdatedMultisigHex(updatedMultisigHex)); Optional.ofNullable(depositTxHash).ifPresent(e -> builder.setDepositTxHash(depositTxHash)); Optional.ofNullable(depositTxHex).ifPresent(e -> builder.setDepositTxHex(depositTxHex)); Optional.ofNullable(depositTxKey).ifPresent(e -> builder.setDepositTxKey(depositTxKey)); Optional.ofNullable(depositTxFee).ifPresent(e -> builder.setDepositTxFee(depositTxFee)); Optional.ofNullable(securityDeposit).ifPresent(e -> builder.setSecurityDeposit(securityDeposit)); - Optional.ofNullable(updatedMultisigHex).ifPresent(e -> builder.setUpdatedMultisigHex(updatedMultisigHex)); + Optional.ofNullable(unsignedPayoutTxHex).ifPresent(e -> builder.setUnsignedPayoutTxHex(unsignedPayoutTxHex)); + Optional.ofNullable(payoutTxFee).ifPresent(e -> builder.setPayoutTxFee(payoutTxFee)); + Optional.ofNullable(payoutAmount).ifPresent(e -> builder.setPayoutAmount(payoutAmount)); builder.setDepositsConfirmedMessageAcked(depositsConfirmedMessageAcked); builder.setCurrentDate(currentDate); @@ -237,13 +261,16 @@ public static TradePeer fromProto(protobuf.TradePeer proto, CoreProtoResolver co tradePeer.setPreparedMultisigHex(ProtoUtil.stringOrNullFromProto(proto.getPreparedMultisigHex())); tradePeer.setMadeMultisigHex(ProtoUtil.stringOrNullFromProto(proto.getMadeMultisigHex())); tradePeer.setExchangedMultisigHex(ProtoUtil.stringOrNullFromProto(proto.getExchangedMultisigHex())); + tradePeer.setUpdatedMultisigHex(ProtoUtil.stringOrNullFromProto(proto.getUpdatedMultisigHex())); + tradePeer.setDepositsConfirmedMessageAcked(proto.getDepositsConfirmedMessageAcked()); tradePeer.setDepositTxHash(ProtoUtil.stringOrNullFromProto(proto.getDepositTxHash())); tradePeer.setDepositTxHex(ProtoUtil.stringOrNullFromProto(proto.getDepositTxHex())); tradePeer.setDepositTxKey(ProtoUtil.stringOrNullFromProto(proto.getDepositTxKey())); tradePeer.setDepositTxFee(BigInteger.valueOf(proto.getDepositTxFee())); tradePeer.setSecurityDeposit(BigInteger.valueOf(proto.getSecurityDeposit())); - tradePeer.setUpdatedMultisigHex(ProtoUtil.stringOrNullFromProto(proto.getUpdatedMultisigHex())); - tradePeer.setDepositsConfirmedMessageAcked(proto.getDepositsConfirmedMessageAcked()); + tradePeer.setUnsignedPayoutTxHex(ProtoUtil.stringOrNullFromProto(proto.getUnsignedPayoutTxHex())); + tradePeer.setPayoutTxFee(BigInteger.valueOf(proto.getPayoutTxFee())); + tradePeer.setPayoutAmount(BigInteger.valueOf(proto.getPayoutAmount())); return tradePeer; } } diff --git a/core/src/main/java/haveno/core/trade/protocol/tasks/ProcessPaymentReceivedMessage.java b/core/src/main/java/haveno/core/trade/protocol/tasks/ProcessPaymentReceivedMessage.java index 79cd9890af0..b54febab9b6 100644 --- a/core/src/main/java/haveno/core/trade/protocol/tasks/ProcessPaymentReceivedMessage.java +++ b/core/src/main/java/haveno/core/trade/protocol/tasks/ProcessPaymentReceivedMessage.java @@ -136,17 +136,17 @@ private void processPayoutTx(PaymentReceivedMessage message) { if (!trade.isPayoutPublished()) { if (isSigned) { log.info("{} {} publishing signed payout tx from seller", trade.getClass().getSimpleName(), trade.getId()); - trade.verifyPayoutTx(message.getSignedPayoutTxHex(), false, true); + trade.processPayoutTx(message.getSignedPayoutTxHex(), false, true); } else { try { PaymentSentMessage paymentSentMessage = (trade.isArbitrator() ? trade.getBuyer() : trade.getArbitrator()).getPaymentSentMessage(); if (paymentSentMessage == null) throw new RuntimeException("Process model does not have payment sent message for " + trade.getClass().getSimpleName() + " " + trade.getId()); if (StringUtils.equals(trade.getPayoutTxHex(), paymentSentMessage.getPayoutTxHex())) { // unsigned log.info("{} {} verifying, signing, and publishing payout tx", trade.getClass().getSimpleName(), trade.getId()); - trade.verifyPayoutTx(message.getUnsignedPayoutTxHex(), true, true); + trade.processPayoutTx(message.getUnsignedPayoutTxHex(), true, true); } else { log.info("{} {} re-verifying and publishing payout tx", trade.getClass().getSimpleName(), trade.getId()); - trade.verifyPayoutTx(trade.getPayoutTxHex(), false, true); + trade.processPayoutTx(trade.getPayoutTxHex(), false, true); } } catch (Exception e) { trade.syncAndPollWallet(); @@ -157,7 +157,7 @@ private void processPayoutTx(PaymentReceivedMessage message) { } } else { log.info("Payout tx already published for {} {}", trade.getClass().getSimpleName(), trade.getId()); - if (message.getSignedPayoutTxHex() != null && !trade.isPayoutConfirmed()) trade.verifyPayoutTx(message.getSignedPayoutTxHex(), false, true); + if (message.getSignedPayoutTxHex() != null && !trade.isPayoutConfirmed()) trade.processPayoutTx(message.getSignedPayoutTxHex(), false, true); } } } diff --git a/core/src/main/java/haveno/core/trade/protocol/tasks/SellerPreparePaymentReceivedMessage.java b/core/src/main/java/haveno/core/trade/protocol/tasks/SellerPreparePaymentReceivedMessage.java index 5183a24b4be..a4d8bb728a7 100644 --- a/core/src/main/java/haveno/core/trade/protocol/tasks/SellerPreparePaymentReceivedMessage.java +++ b/core/src/main/java/haveno/core/trade/protocol/tasks/SellerPreparePaymentReceivedMessage.java @@ -48,7 +48,7 @@ protected void run() { if (trade.getPayoutTxHex() != null) { try { log.info("Seller verifying, signing, and publishing payout tx for trade {}", trade.getId()); - trade.verifyPayoutTx(trade.getPayoutTxHex(), true, true); + trade.processPayoutTx(trade.getPayoutTxHex(), true, true); } catch (Exception e) { log.warn("Error verifying, signing, and publishing payout tx for trade {}: {}. Creating unsigned payout tx", trade.getId(), e.getMessage()); createUnsignedPayoutTx(); @@ -60,7 +60,7 @@ protected void run() { // republish payout tx from previous message log.info("Seller re-verifying and publishing payout tx for trade {}", trade.getId()); - trade.verifyPayoutTx(trade.getArbitrator().getPaymentReceivedMessage().getSignedPayoutTxHex(), false, true); + trade.processPayoutTx(trade.getArbitrator().getPaymentReceivedMessage().getSignedPayoutTxHex(), false, true); } processModel.getTradeManager().requestPersistence(); diff --git a/desktop/src/main/java/haveno/desktop/main/overlays/windows/DisputeSummaryWindow.java b/desktop/src/main/java/haveno/desktop/main/overlays/windows/DisputeSummaryWindow.java index 1c4ab0e634a..a325e3b27e5 100644 --- a/desktop/src/main/java/haveno/desktop/main/overlays/windows/DisputeSummaryWindow.java +++ b/desktop/src/main/java/haveno/desktop/main/overlays/windows/DisputeSummaryWindow.java @@ -211,8 +211,8 @@ private void addContent() { if (applyPeersDisputeResult) { // If the other peers dispute has been closed we apply the result to ourselves DisputeResult peersDisputeResult = peersDisputeOptional.get().getDisputeResultProperty().get(); - disputeResult.setBuyerPayoutAmount(peersDisputeResult.getBuyerPayoutAmount()); - disputeResult.setSellerPayoutAmount(peersDisputeResult.getSellerPayoutAmount()); + disputeResult.setBuyerPayoutAmountBeforeCost(peersDisputeResult.getBuyerPayoutAmountBeforeCost()); + disputeResult.setSellerPayoutAmountBeforeCost(peersDisputeResult.getSellerPayoutAmountBeforeCost()); disputeResult.setWinner(peersDisputeResult.getWinner()); disputeResult.setReason(peersDisputeResult.getReason()); disputeResult.setSummaryNotes(peersDisputeResult.summaryNotesProperty().get()); @@ -402,8 +402,8 @@ private void applyCustomAmounts(InputTextField inputTextField, boolean oldFocusV buyerPayoutAmountInputTextField.setText(formattedCounterPartAmount); } - disputeResult.setBuyerPayoutAmount(buyerAmount); - disputeResult.setSellerPayoutAmount(sellerAmount); + disputeResult.setBuyerPayoutAmountBeforeCost(buyerAmount); + disputeResult.setSellerPayoutAmountBeforeCost(sellerAmount); disputeResult.setWinner(buyerAmount.compareTo(sellerAmount) > 0 ? DisputeResult.Winner.BUYER : DisputeResult.Winner.SELLER); // TODO: UI should allow selection of receiver of exact custom amount, otherwise defaulting to bigger receiver. could extend API to specify who pays payout tx fee: buyer, seller, or both disputeResult.setSubtractFeeFrom(buyerAmount.compareTo(sellerAmount) > 0 ? DisputeResult.SubtractFeeFrom.SELLER_ONLY : DisputeResult.SubtractFeeFrom.BUYER_ONLY); } @@ -587,8 +587,7 @@ private void addButtons(Contract contract) { !trade.isPayoutPublished()) { // create payout tx - MoneroTxWallet payoutTx = arbitrationManager.createDisputePayoutTx(trade, dispute.getContract(), disputeResult, false); - trade.getProcessModel().setUnsignedPayoutTx((MoneroTxWallet) payoutTx); + MoneroTxWallet payoutTx = arbitrationManager.createDisputePayoutTx(trade, dispute.getContract(), disputeResult, true); // show confirmation showPayoutTxConfirmation(contract, @@ -709,8 +708,8 @@ private void applyPayoutAmountsToDisputeResult(Toggle selectedTradeAmountToggle) throw new IllegalStateException("Unknown radio button"); } disputesService.applyPayoutAmountsToDisputeResult(payout, dispute, disputeResult, -1); - buyerPayoutAmountInputTextField.setText(HavenoUtils.formatXmr(disputeResult.getBuyerPayoutAmount())); - sellerPayoutAmountInputTextField.setText(HavenoUtils.formatXmr(disputeResult.getSellerPayoutAmount())); + buyerPayoutAmountInputTextField.setText(HavenoUtils.formatXmr(disputeResult.getBuyerPayoutAmountBeforeCost())); + sellerPayoutAmountInputTextField.setText(HavenoUtils.formatXmr(disputeResult.getSellerPayoutAmountBeforeCost())); } private void applyTradeAmountRadioButtonStates() { @@ -719,8 +718,8 @@ private void applyTradeAmountRadioButtonStates() { BigInteger sellerSecurityDeposit = trade.getSeller().getSecurityDeposit(); BigInteger tradeAmount = contract.getTradeAmount(); - BigInteger buyerPayoutAmount = disputeResult.getBuyerPayoutAmount(); - BigInteger sellerPayoutAmount = disputeResult.getSellerPayoutAmount(); + BigInteger buyerPayoutAmount = disputeResult.getBuyerPayoutAmountBeforeCost(); + BigInteger sellerPayoutAmount = disputeResult.getSellerPayoutAmountBeforeCost(); buyerPayoutAmountInputTextField.setText(HavenoUtils.formatXmr(buyerPayoutAmount)); sellerPayoutAmountInputTextField.setText(HavenoUtils.formatXmr(sellerPayoutAmount)); diff --git a/desktop/src/main/java/haveno/desktop/main/portfolio/closedtrades/ClosedTradesView.java b/desktop/src/main/java/haveno/desktop/main/portfolio/closedtrades/ClosedTradesView.java index e6fb43f516e..ce05b83187c 100644 --- a/desktop/src/main/java/haveno/desktop/main/portfolio/closedtrades/ClosedTradesView.java +++ b/desktop/src/main/java/haveno/desktop/main/portfolio/closedtrades/ClosedTradesView.java @@ -91,8 +91,7 @@ private enum ColumnNames { VOLUME(Res.get("shared.amount")), VOLUME_CURRENCY(Res.get("shared.currency")), TX_FEE(Res.get("shared.txFee")), - TRADE_FEE_BTC(Res.get("shared.tradeFee") + " BTC"), - TRADE_FEE_BSQ(Res.get("shared.tradeFee") + " BSQ"), + TRADE_FEE(Res.get("shared.tradeFee")), BUYER_SEC(Res.get("shared.buyerSecurityDeposit")), SELLER_SEC(Res.get("shared.sellerSecurityDeposit")), OFFER_TYPE(Res.get("shared.offerType")), @@ -158,7 +157,7 @@ public ClosedTradesView(ClosedTradesViewModel model, @Override public void initialize() { widthListener = (observable, oldValue, newValue) -> onWidthChange((double) newValue); - tradeFeeColumn.setGraphic(new AutoTooltipLabel(ColumnNames.TRADE_FEE_BTC.toString().replace(" BTC", ""))); + tradeFeeColumn.setGraphic(new AutoTooltipLabel(ColumnNames.TRADE_FEE.toString().replace(" BTC", ""))); buyerSecurityDepositColumn.setGraphic(new AutoTooltipLabel(ColumnNames.BUYER_SEC.toString())); sellerSecurityDepositColumn.setGraphic(new AutoTooltipLabel(ColumnNames.SELLER_SEC.toString())); priceColumn.setGraphic(new AutoTooltipLabel(ColumnNames.PRICE.toString())); @@ -275,11 +274,9 @@ protected void activate() { columns[ColumnNames.VOLUME_CURRENCY.ordinal()] = item.getVolumeCurrencyAsString(); columns[ColumnNames.TX_FEE.ordinal()] = item.getTxFeeAsString(); if (model.dataModel.isCurrencyForTradeFeeBtc(item.getTradable())) { - columns[ColumnNames.TRADE_FEE_BTC.ordinal()] = item.getTradeFeeAsString(false); - columns[ColumnNames.TRADE_FEE_BSQ.ordinal()] = ""; + columns[ColumnNames.TRADE_FEE.ordinal()] = item.getTradeFeeAsString(false); } else { - columns[ColumnNames.TRADE_FEE_BTC.ordinal()] = ""; - columns[ColumnNames.TRADE_FEE_BSQ.ordinal()] = item.getTradeFeeAsString(false); + columns[ColumnNames.TRADE_FEE.ordinal()] = ""; } columns[ColumnNames.BUYER_SEC.ordinal()] = item.getBuyerSecurityDepositAsString(); columns[ColumnNames.SELLER_SEC.ordinal()] = item.getSellerSecurityDepositAsString(); diff --git a/desktop/src/main/java/haveno/desktop/main/portfolio/pendingtrades/steps/TradeStepView.java b/desktop/src/main/java/haveno/desktop/main/portfolio/pendingtrades/steps/TradeStepView.java index c692259eb81..d236a6c373a 100644 --- a/desktop/src/main/java/haveno/desktop/main/portfolio/pendingtrades/steps/TradeStepView.java +++ b/desktop/src/main/java/haveno/desktop/main/portfolio/pendingtrades/steps/TradeStepView.java @@ -679,8 +679,8 @@ private void openMediationResultPopup(String headLine) { DisputeResult disputeResult = optionalDispute.get().getDisputeResultProperty().get(); Contract contract = checkNotNull(trade.getContract(), "contract must not be null"); boolean isMyRoleBuyer = contract.isMyRoleBuyer(model.dataModel.getPubKeyRingProvider().get()); - String buyerPayoutAmount = HavenoUtils.formatXmr(disputeResult.getBuyerPayoutAmount(), true); - String sellerPayoutAmount = HavenoUtils.formatXmr(disputeResult.getSellerPayoutAmount(), true); + String buyerPayoutAmount = HavenoUtils.formatXmr(disputeResult.getBuyerPayoutAmountBeforeCost(), true); + String sellerPayoutAmount = HavenoUtils.formatXmr(disputeResult.getSellerPayoutAmountBeforeCost(), true); String myPayoutAmount = isMyRoleBuyer ? buyerPayoutAmount : sellerPayoutAmount; String peersPayoutAmount = isMyRoleBuyer ? sellerPayoutAmount : buyerPayoutAmount; diff --git a/desktop/src/main/java/haveno/desktop/main/support/dispute/DisputeView.java b/desktop/src/main/java/haveno/desktop/main/support/dispute/DisputeView.java index 4117041e2b1..7491acce79b 100644 --- a/desktop/src/main/java/haveno/desktop/main/support/dispute/DisputeView.java +++ b/desktop/src/main/java/haveno/desktop/main/support/dispute/DisputeView.java @@ -639,10 +639,9 @@ private void showCompactReport() { String sellersRole = contract.isBuyerMakerAndSellerTaker() ? "Seller as taker" : "Seller as maker"; String opener = firstDispute.isDisputeOpenerIsBuyer() ? buyersRole : sellersRole; DisputeResult disputeResult = firstDispute.getDisputeResultProperty().get(); - String winner = disputeResult != null && - disputeResult.getWinner() == DisputeResult.Winner.BUYER ? "Buyer" : "Seller"; - String buyerPayoutAmount = disputeResult != null ? HavenoUtils.formatXmr(disputeResult.getBuyerPayoutAmount(), true) : ""; - String sellerPayoutAmount = disputeResult != null ? HavenoUtils.formatXmr(disputeResult.getSellerPayoutAmount(), true) : ""; + String winner = disputeResult != null && disputeResult.getWinner() == DisputeResult.Winner.BUYER ? "Buyer" : "Seller"; + String buyerPayoutAmount = disputeResult != null ? HavenoUtils.formatXmr(disputeResult.getBuyerPayoutAmountBeforeCost(), true) : ""; + String sellerPayoutAmount = disputeResult != null ? HavenoUtils.formatXmr(disputeResult.getSellerPayoutAmountBeforeCost(), true) : ""; int index = disputeIndex.incrementAndGet(); String tradeDateString = dateFormatter.format(firstDispute.getTradeDate()); diff --git a/proto/src/main/proto/grpc.proto b/proto/src/main/proto/grpc.proto index 20506eb2efe..dc7ab4c3ea6 100644 --- a/proto/src/main/proto/grpc.proto +++ b/proto/src/main/proto/grpc.proto @@ -831,33 +831,38 @@ message TradeInfo { uint64 date = 4; string role = 5; uint64 taker_fee = 6 [jstype = JS_STRING]; - string taker_fee_tx_id = 7; - string payout_tx_id = 8; - uint64 amount = 9 [jstype = JS_STRING]; - uint64 buyer_security_deposit = 10 [jstype = JS_STRING]; - uint64 seller_security_deposit = 11 [jstype = JS_STRING]; - string price = 12; - string arbitrator_node_address = 13; - string trade_peer_node_address = 14; - string state = 15; - string phase = 16; - string period_state = 17; - string payout_state = 18; - string dispute_state = 19; - bool is_deposits_published = 20; - bool is_deposits_confirmed = 21; - bool is_deposits_unlocked = 22; - bool is_payment_sent = 23; - bool is_payment_received = 24; - bool is_payout_published = 25; - bool is_payout_confirmed = 26; - bool is_payout_unlocked = 27; - bool is_completed = 28; - string contract_as_json = 29; - ContractInfo contract = 30; - string trade_volume = 31; - string maker_deposit_tx_id = 32; - string taker_deposit_tx_id = 33; + uint64 amount = 7 [jstype = JS_STRING]; + uint64 buyer_security_deposit = 8 [jstype = JS_STRING]; + uint64 seller_security_deposit = 9 [jstype = JS_STRING]; + uint64 buyer_deposit_tx_fee = 10 [jstype = JS_STRING]; + uint64 seller_deposit_tx_fee = 11 [jstype = JS_STRING]; + uint64 buyer_payout_tx_fee = 12 [jstype = JS_STRING]; + uint64 seller_payout_tx_fee = 13 [jstype = JS_STRING]; + uint64 buyer_payout_amount = 14 [jstype = JS_STRING]; + uint64 seller_payout_amount = 15 [jstype = JS_STRING]; + string price = 16; + string arbitrator_node_address = 17; + string trade_peer_node_address = 18; + string state = 19; + string phase = 20; + string period_state = 21; + string payout_state = 22; + string dispute_state = 23; + bool is_deposits_published = 24; + bool is_deposits_confirmed = 25; + bool is_deposits_unlocked = 26; + bool is_payment_sent = 27; + bool is_payment_received = 28; + bool is_payout_published = 29; + bool is_payout_confirmed = 30; + bool is_payout_unlocked = 31; + bool is_completed = 32; + string contract_as_json = 33; + ContractInfo contract = 34; + string trade_volume = 35; + string maker_deposit_tx_id = 36; + string taker_deposit_tx_id = 37; + string payout_tx_id = 38; } message ContractInfo { diff --git a/proto/src/main/proto/pb.proto b/proto/src/main/proto/pb.proto index 6420672da98..67320e799f5 100644 --- a/proto/src/main/proto/pb.proto +++ b/proto/src/main/proto/pb.proto @@ -758,8 +758,8 @@ message DisputeResult { string summary_notes = 8; ChatMessage chat_message = 9; bytes arbitrator_signature = 10; - int64 buyer_payout_amount = 11; - int64 seller_payout_amount = 12; + int64 buyer_payout_amount_before_cost = 11; + int64 seller_payout_amount_before_cost = 12; SubtractFeeFrom subtract_fee_from = 13; bytes arbitrator_pub_key = 14; int64 close_date = 15; @@ -1488,28 +1488,27 @@ message Trade { string payout_tx_key = 5; int64 amount = 6; int64 taker_fee = 8; - int64 total_tx_fee = 9; - int64 take_offer_date = 10; - int64 price = 11; - State state = 12; - PayoutState payout_state = 13; - DisputeState dispute_state = 14; - TradePeriodState period_state = 15; - Contract contract = 16; - string contract_as_json = 17; - bytes contract_hash = 18; - NodeAddress arbitrator_node_address = 19; - NodeAddress mediator_node_address = 20; - string error_message = 21; - string counter_currency_tx_id = 22; - repeated ChatMessage chat_message = 23; - MediationResultState mediation_result_state = 24; - int64 lock_time = 25; - int64 start_time = 26; - NodeAddress refund_agent_node_address = 27; - RefundResultState refund_result_state = 28; - string counter_currency_extra_data = 29; - string uid = 30; + int64 take_offer_date = 9; + int64 price = 10; + State state = 11; + PayoutState payout_state = 12; + DisputeState dispute_state = 13; + TradePeriodState period_state = 14; + Contract contract = 15; + string contract_as_json = 16; + bytes contract_hash = 17; + NodeAddress arbitrator_node_address = 18; + NodeAddress mediator_node_address = 19; + string error_message = 20; + string counter_currency_tx_id = 21; + repeated ChatMessage chat_message = 22; + MediationResultState mediation_result_state = 23; + int64 lock_time = 24; + int64 start_time = 25; + NodeAddress refund_agent_node_address = 26; + RefundResultState refund_result_state = 27; + string counter_currency_extra_data = 28; + string uid = 29; } message BuyerAsMakerTrade { @@ -1572,21 +1571,23 @@ message TradePeer { PaymentSentMessage payment_sent_message = 23; PaymentReceivedMessage payment_received_message = 24; DisputeClosedMessage dispute_closed_message = 25; - - string reserve_tx_hash = 1001; - string reserve_tx_hex = 1002; - string reserve_tx_key = 1003; - repeated string reserve_tx_key_images = 1004; - string prepared_multisig_hex = 1005; - string made_multisig_hex = 1006; - string exchanged_multisig_hex = 1007; - string deposit_tx_hash = 1008; - string deposit_tx_hex = 1009; - string deposit_tx_key = 1010; - int64 deposit_tx_fee = 1011; - int64 security_deposit = 1012; - string updated_multisig_hex = 1013; - bool deposits_confirmed_message_acked = 1014; + string reserve_tx_hash = 26; + string reserve_tx_hex = 27; + string reserve_tx_key = 28; + repeated string reserve_tx_key_images = 29; + string prepared_multisig_hex = 30; + string made_multisig_hex = 31; + string exchanged_multisig_hex = 32; + string updated_multisig_hex = 33; + bool deposits_confirmed_message_acked = 34; + string deposit_tx_hash = 35; + string deposit_tx_hex = 36; + string deposit_tx_key = 37; + int64 deposit_tx_fee = 38; + int64 security_deposit = 39; + string unsigned_payout_tx_hex = 40; + int64 payout_tx_fee = 41; + int64 payout_amount = 42; } /////////////////////////////////////////////////////////////////////////////////////////// From ce38c64f2f3467553a839c250f0aa08edc4fee78 Mon Sep 17 00:00:00 2001 From: woodser Date: Wed, 6 Dec 2023 14:22:12 -0500 Subject: [PATCH 02/10] update translation: Connecting to Haveno network --- core/src/main/java/haveno/core/xmr/wallet/XmrWalletService.java | 1 + core/src/main/resources/i18n/displayStrings.properties | 2 +- core/src/main/resources/i18n/displayStrings_cs.properties | 2 +- core/src/main/resources/i18n/displayStrings_de.properties | 2 +- core/src/main/resources/i18n/displayStrings_es.properties | 2 +- core/src/main/resources/i18n/displayStrings_fa.properties | 2 +- core/src/main/resources/i18n/displayStrings_fr.properties | 2 +- core/src/main/resources/i18n/displayStrings_it.properties | 2 +- core/src/main/resources/i18n/displayStrings_ja.properties | 2 +- core/src/main/resources/i18n/displayStrings_pt-br.properties | 2 +- core/src/main/resources/i18n/displayStrings_pt.properties | 2 +- core/src/main/resources/i18n/displayStrings_ru.properties | 2 +- core/src/main/resources/i18n/displayStrings_th.properties | 2 +- core/src/main/resources/i18n/displayStrings_vi.properties | 2 +- core/src/main/resources/i18n/displayStrings_zh-hans.properties | 2 +- core/src/main/resources/i18n/displayStrings_zh-hant.properties | 2 +- 16 files changed, 16 insertions(+), 15 deletions(-) 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 05c886718e3..138377f879a 100644 --- a/core/src/main/java/haveno/core/xmr/wallet/XmrWalletService.java +++ b/core/src/main/java/haveno/core/xmr/wallet/XmrWalletService.java @@ -890,6 +890,7 @@ private MoneroWalletRpc startWalletRpcInstance(Integer port, boolean applyProxyU cmd.add("--" + MONERO_NETWORK_TYPE.toString().toLowerCase()); } + // set connection flags MoneroRpcConnection connection = xmrConnectionService.getConnection(); if (connection != null) { cmd.add("--daemon-address"); diff --git a/core/src/main/resources/i18n/displayStrings.properties b/core/src/main/resources/i18n/displayStrings.properties index cd6babb75a3..7bb94bc6b20 100644 --- a/core/src/main/resources/i18n/displayStrings.properties +++ b/core/src/main/resources/i18n/displayStrings.properties @@ -267,7 +267,7 @@ mainView.footer.usingTor=(via Tor) mainView.footer.localhostMoneroNode=(localhost) mainView.footer.xmrInfo={0} {1} mainView.footer.xmrFeeRate=/ Fee rate: {0} sat/vB -mainView.footer.xmrInfo.initializing=Connecting to Monero network +mainView.footer.xmrInfo.initializing=Connecting to Haveno network mainView.footer.xmrInfo.synchronizingDaemonWith=Synchronizing daemon with {0} at block: {1} / {2} mainView.footer.xmrInfo.synchronizedDaemonWith=Daemon synchronized with {0} at block {1} mainView.footer.xmrInfo.synchronizingWalletWith=Synchronizing wallet with {0} at block: {1} / {2} diff --git a/core/src/main/resources/i18n/displayStrings_cs.properties b/core/src/main/resources/i18n/displayStrings_cs.properties index 83ca4639e61..2703e576fe6 100644 --- a/core/src/main/resources/i18n/displayStrings_cs.properties +++ b/core/src/main/resources/i18n/displayStrings_cs.properties @@ -248,7 +248,7 @@ mainView.footer.usingTor=(přes Tor) mainView.footer.localhostMoneroNode=(localhost) mainView.footer.xmrInfo={0} {1} mainView.footer.xmrFeeRate=/ Aktuální poplatek: {0} sat/vB -mainView.footer.xmrInfo.initializing=Připojování do Moneroové sítě +mainView.footer.xmrInfo.initializing=Připojování k síti Haveno mainView.footer.xmrInfo.synchronizingDaemonWith=Synchronizace s {0} v bloku: {1} / {2} mainView.footer.xmrInfo.synchronizedDaemonWith=Synchronizováno s {0} v bloku {1} mainView.footer.xmrInfo.connectingTo=Připojování diff --git a/core/src/main/resources/i18n/displayStrings_de.properties b/core/src/main/resources/i18n/displayStrings_de.properties index 639c52ca81a..720bf4a117a 100644 --- a/core/src/main/resources/i18n/displayStrings_de.properties +++ b/core/src/main/resources/i18n/displayStrings_de.properties @@ -248,7 +248,7 @@ mainView.footer.usingTor=(über Tor) mainView.footer.localhostMoneroNode=(localhost) mainView.footer.xmrInfo={0} {1} mainView.footer.xmrFeeRate=/ Aktuelle Gebühr: {0} sat/vB -mainView.footer.xmrInfo.initializing=Verbindung mit Monero-Netzwerk wird hergestellt +mainView.footer.xmrInfo.initializing=Verbindung mit Haveno-Netzwerk wird hergestellt mainView.footer.xmrInfo.synchronizingDaemonWith=Synchronisierung mit {0} bei Block: {1} / {2} mainView.footer.xmrInfo.synchronizedDaemonWith=Synchronisierung mit {0} bei Block {1} mainView.footer.xmrInfo.connectingTo=Verbinde mit diff --git a/core/src/main/resources/i18n/displayStrings_es.properties b/core/src/main/resources/i18n/displayStrings_es.properties index 4e40ec8fb7b..7925250b002 100644 --- a/core/src/main/resources/i18n/displayStrings_es.properties +++ b/core/src/main/resources/i18n/displayStrings_es.properties @@ -248,7 +248,7 @@ mainView.footer.usingTor=(via Tor) mainView.footer.localhostMoneroNode=(localhost) mainView.footer.xmrInfo={0} {1} mainView.footer.xmrFeeRate=/Tasas actuales: {0} sat/vB -mainView.footer.xmrInfo.initializing=Conectando a la red Monero +mainView.footer.xmrInfo.initializing=Conectando a la red Haveno mainView.footer.xmrInfo.synchronizingDaemonWith=Sincronizando con {0} en el bloque: {1} / {2} mainView.footer.xmrInfo.synchronizedDaemonWith=Sincronizado con {0} en el bloque {1} mainView.footer.xmrInfo.connectingTo=Conectando a diff --git a/core/src/main/resources/i18n/displayStrings_fa.properties b/core/src/main/resources/i18n/displayStrings_fa.properties index 4b44399a5a5..793f398e003 100644 --- a/core/src/main/resources/i18n/displayStrings_fa.properties +++ b/core/src/main/resources/i18n/displayStrings_fa.properties @@ -248,7 +248,7 @@ mainView.footer.usingTor=(via Tor) mainView.footer.localhostMoneroNode=(لوکال هاست) mainView.footer.xmrInfo={0} {1} mainView.footer.xmrFeeRate=/ Fee rate: {0} sat/vB -mainView.footer.xmrInfo.initializing=در حال ارتباط با شبکه بیت‌کوین +mainView.footer.xmrInfo.initializing=اتصال به شبکه Haveno mainView.footer.xmrInfo.synchronizingDaemonWith=Synchronizing with {0} at block: {1} / {2} mainView.footer.xmrInfo.synchronizedDaemonWith=Synced with {0} at block {1} mainView.footer.xmrInfo.connectingTo=در حال ایجاد ارتباط با diff --git a/core/src/main/resources/i18n/displayStrings_fr.properties b/core/src/main/resources/i18n/displayStrings_fr.properties index 1b973be3eeb..a0d281e96d9 100644 --- a/core/src/main/resources/i18n/displayStrings_fr.properties +++ b/core/src/main/resources/i18n/displayStrings_fr.properties @@ -248,7 +248,7 @@ mainView.footer.usingTor=(à travers Tor) mainView.footer.localhostMoneroNode=(localhost) mainView.footer.xmrInfo={0} {1} mainView.footer.xmrFeeRate=/ Taux des frais: {0} sat/vB -mainView.footer.xmrInfo.initializing=Connexion au réseau Monero en cours +mainView.footer.xmrInfo.initializing=Connexion au réseau Haveno en cours mainView.footer.xmrInfo.synchronizingDaemonWith=Synchronisation avec {0} au block: {1}/ {2} mainView.footer.xmrInfo.synchronizedDaemonWith=Synchronisé avec {0} au block {1} mainView.footer.xmrInfo.connectingTo=Se connecte à diff --git a/core/src/main/resources/i18n/displayStrings_it.properties b/core/src/main/resources/i18n/displayStrings_it.properties index 318345650c2..2f451074044 100644 --- a/core/src/main/resources/i18n/displayStrings_it.properties +++ b/core/src/main/resources/i18n/displayStrings_it.properties @@ -248,7 +248,7 @@ mainView.footer.usingTor=(via Tor) mainView.footer.localhostMoneroNode=(localhost) mainView.footer.xmrInfo={0} {1} mainView.footer.xmrFeeRate=/ Fee rate: {0} sat/vB -mainView.footer.xmrInfo.initializing=Connessione alla rete Monero +mainView.footer.xmrInfo.initializing=Connessione alla rete Haveno mainView.footer.xmrInfo.connectingTo=Connessione a mainView.footer.xmrInfo.connectionFailed=Connessione fallita mainView.footer.xmrPeers=Monero network peers: {0} diff --git a/core/src/main/resources/i18n/displayStrings_ja.properties b/core/src/main/resources/i18n/displayStrings_ja.properties index 8c282828f4e..9e767dbdb8e 100644 --- a/core/src/main/resources/i18n/displayStrings_ja.properties +++ b/core/src/main/resources/i18n/displayStrings_ja.properties @@ -248,7 +248,7 @@ mainView.footer.usingTor=(Tor経由で) mainView.footer.localhostMoneroNode=(ローカルホスト) mainView.footer.xmrInfo={0} {1} mainView.footer.xmrFeeRate=/ 手数料率: {0} サトシ/vB -mainView.footer.xmrInfo.initializing=ビットコインネットワークに接続中 +mainView.footer.xmrInfo.initializing=Havenoネットワークに接続中 mainView.footer.xmrInfo.synchronizingDaemonWith={0}と同期中、ブロック: {1} / {2} mainView.footer.xmrInfo.synchronizedDaemonWith={0}と同期されています、ブロック{1}に mainView.footer.xmrInfo.connectingTo=接続中: diff --git a/core/src/main/resources/i18n/displayStrings_pt-br.properties b/core/src/main/resources/i18n/displayStrings_pt-br.properties index ff4bc19b4f7..5b708168494 100644 --- a/core/src/main/resources/i18n/displayStrings_pt-br.properties +++ b/core/src/main/resources/i18n/displayStrings_pt-br.properties @@ -251,7 +251,7 @@ mainView.footer.usingTor=(via Tor) mainView.footer.localhostMoneroNode=(localhost) mainView.footer.xmrInfo={0} {1} mainView.footer.xmrFeeRate=/ Fee rate: {0} sat/vB -mainView.footer.xmrInfo.initializing=Conectando-se à rede Monero +mainView.footer.xmrInfo.initializing=Conectando-se à rede Haveno mainView.footer.xmrInfo.connectingTo=Conectando-se a mainView.footer.xmrInfo.connectionFailed=Falha na conexão à mainView.footer.xmrPeers=Monero network peers: {0} diff --git a/core/src/main/resources/i18n/displayStrings_pt.properties b/core/src/main/resources/i18n/displayStrings_pt.properties index 7b9fc333f22..47a57f58e45 100644 --- a/core/src/main/resources/i18n/displayStrings_pt.properties +++ b/core/src/main/resources/i18n/displayStrings_pt.properties @@ -248,7 +248,7 @@ mainView.footer.usingTor=(via Tor) mainView.footer.localhostMoneroNode=(localhost) mainView.footer.xmrInfo={0} {1} mainView.footer.xmrFeeRate=/ Fee rate: {0} sat/vB -mainView.footer.xmrInfo.initializing=Conectando à rede Monero +mainView.footer.xmrInfo.initializing=Conectando à rede Haveno mainView.footer.xmrInfo.connectingTo=Conectando à mainView.footer.xmrInfo.connectionFailed=Connection failed to mainView.footer.xmrPeers=Monero network peers: {0} diff --git a/core/src/main/resources/i18n/displayStrings_ru.properties b/core/src/main/resources/i18n/displayStrings_ru.properties index 75a9f072a44..8464467d418 100644 --- a/core/src/main/resources/i18n/displayStrings_ru.properties +++ b/core/src/main/resources/i18n/displayStrings_ru.properties @@ -248,7 +248,7 @@ mainView.footer.usingTor=(via Tor) mainView.footer.localhostMoneroNode=(локальный узел) mainView.footer.xmrInfo={0} {1} mainView.footer.xmrFeeRate=/ Fee rate: {0} sat/vB -mainView.footer.xmrInfo.initializing=Подключение к сети Биткойн +mainView.footer.xmrInfo.initializing=Подключение к сети Haveno mainView.footer.xmrInfo.connectingTo=Подключение к mainView.footer.xmrInfo.connectionFailed=Connection failed to mainView.footer.xmrPeers=Monero network peers: {0} diff --git a/core/src/main/resources/i18n/displayStrings_th.properties b/core/src/main/resources/i18n/displayStrings_th.properties index 6203e5f3531..3e787adb584 100644 --- a/core/src/main/resources/i18n/displayStrings_th.properties +++ b/core/src/main/resources/i18n/displayStrings_th.properties @@ -248,7 +248,7 @@ mainView.footer.usingTor=(via Tor) mainView.footer.localhostMoneroNode=(แม่ข่ายเฉพาะที่) mainView.footer.xmrInfo={0} {1} mainView.footer.xmrFeeRate=/ Fee rate: {0} sat/vB -mainView.footer.xmrInfo.initializing=Connecting to Monero network +mainView.footer.xmrInfo.initializing=เชื่อมต่อกับเครือข่าย Haveno mainView.footer.xmrInfo.connectingTo=Connecting to mainView.footer.xmrInfo.connectionFailed=Connection failed to mainView.footer.xmrPeers=Monero network peers: {0} diff --git a/core/src/main/resources/i18n/displayStrings_vi.properties b/core/src/main/resources/i18n/displayStrings_vi.properties index a12b210d1ff..f6019cbfc34 100644 --- a/core/src/main/resources/i18n/displayStrings_vi.properties +++ b/core/src/main/resources/i18n/displayStrings_vi.properties @@ -248,7 +248,7 @@ mainView.footer.usingTor=(via Tor) mainView.footer.localhostMoneroNode=(Máy chủ nội bộ) mainView.footer.xmrInfo={0} {1} mainView.footer.xmrFeeRate=/ Fee rate: {0} sat/vB -mainView.footer.xmrInfo.initializing=Đang kết nối với mạng Monero +mainView.footer.xmrInfo.initializing=Đang kết nối với mạng Haveno mainView.footer.xmrInfo.connectingTo=Đang kết nối với mainView.footer.xmrInfo.connectionFailed=Connection failed to mainView.footer.xmrPeers=Monero network peers: {0} diff --git a/core/src/main/resources/i18n/displayStrings_zh-hans.properties b/core/src/main/resources/i18n/displayStrings_zh-hans.properties index 959594e0fd4..f983ef76287 100644 --- a/core/src/main/resources/i18n/displayStrings_zh-hans.properties +++ b/core/src/main/resources/i18n/displayStrings_zh-hans.properties @@ -248,7 +248,7 @@ mainView.footer.usingTor=(通过 Tor) mainView.footer.localhostMoneroNode=(本地主机) mainView.footer.xmrInfo={0} {1} mainView.footer.xmrFeeRate=/ 矿工手费率:{0} 聪/字节 -mainView.footer.xmrInfo.initializing=连接至比特币网络 +mainView.footer.xmrInfo.initializing=连接到 Haveno 网络 mainView.footer.xmrInfo.synchronizingDaemonWith=正在通过{0}同步区块:{1}/{2} mainView.footer.xmrInfo.synchronizedDaemonWith=已通过{0}同步至区块{1} mainView.footer.xmrInfo.connectingTo=连接至 diff --git a/core/src/main/resources/i18n/displayStrings_zh-hant.properties b/core/src/main/resources/i18n/displayStrings_zh-hant.properties index ab6348592be..6f3f1c5f5c3 100644 --- a/core/src/main/resources/i18n/displayStrings_zh-hant.properties +++ b/core/src/main/resources/i18n/displayStrings_zh-hant.properties @@ -248,7 +248,7 @@ mainView.footer.usingTor=(via Tor) mainView.footer.localhostMoneroNode=(本地主機) mainView.footer.xmrInfo={0} {1} mainView.footer.xmrFeeRate=/ Fee rate: {0} sat/vB -mainView.footer.xmrInfo.initializing=連接至比特幣網絡 +mainView.footer.xmrInfo.initializing=連接到 Haveno 網路 mainView.footer.xmrInfo.connectingTo=連接至 mainView.footer.xmrInfo.connectionFailed=連接失敗: mainView.footer.xmrPeers=Monero網絡節點:{0} From ace3786fc2144c4e89d66087ed66700283608b37 Mon Sep 17 00:00:00 2001 From: woodser Date: Fri, 8 Dec 2023 07:43:24 -0500 Subject: [PATCH 03/10] update translations for startup syncs --- core/src/main/java/haveno/core/app/WalletAppSetup.java | 6 +++--- core/src/main/resources/i18n/displayStrings.properties | 5 ++--- core/src/main/resources/i18n/displayStrings_cs.properties | 5 +++-- core/src/main/resources/i18n/displayStrings_de.properties | 5 +++-- core/src/main/resources/i18n/displayStrings_es.properties | 5 +++-- core/src/main/resources/i18n/displayStrings_fa.properties | 5 +++-- core/src/main/resources/i18n/displayStrings_fr.properties | 5 +++-- core/src/main/resources/i18n/displayStrings_it.properties | 3 +++ core/src/main/resources/i18n/displayStrings_ja.properties | 5 +++-- .../src/main/resources/i18n/displayStrings_pt-br.properties | 3 +++ core/src/main/resources/i18n/displayStrings_pt.properties | 3 +++ core/src/main/resources/i18n/displayStrings_ru.properties | 3 +++ core/src/main/resources/i18n/displayStrings_th.properties | 3 +++ core/src/main/resources/i18n/displayStrings_vi.properties | 3 +++ .../main/resources/i18n/displayStrings_zh-hans.properties | 5 +++-- .../main/resources/i18n/displayStrings_zh-hant.properties | 3 +++ 16 files changed, 47 insertions(+), 20 deletions(-) diff --git a/core/src/main/java/haveno/core/app/WalletAppSetup.java b/core/src/main/java/haveno/core/app/WalletAppSetup.java index 992b25cab16..5ab6265f6e4 100644 --- a/core/src/main/java/haveno/core/app/WalletAppSetup.java +++ b/core/src/main/java/haveno/core/app/WalletAppSetup.java @@ -125,7 +125,7 @@ void init(@Nullable Consumer chainFileLockedExceptionHandler, Long bestWalletHeight = walletHeight == null ? null : (Long) walletHeight; String walletHeightAsString = bestWalletHeight != null && bestWalletHeight > 0 ? String.valueOf(bestWalletHeight) : ""; if (walletDownloadPercentageD == 1) { - String synchronizedWith = Res.get("mainView.footer.xmrInfo.synchronizedWalletWith", getXmrWalletNetworkAsString(), walletHeightAsString); + String synchronizedWith = Res.get("mainView.footer.xmrInfo.syncedWith", getXmrWalletNetworkAsString(), walletHeightAsString); String feeInfo = ""; // TODO: feeService.isFeeAvailable() returns true, disable result = Res.get("mainView.footer.xmrInfo", synchronizedWith, feeInfo); getXmrSplashSyncIconId().set("image-connection-synced"); @@ -142,12 +142,12 @@ void init(@Nullable Consumer chainFileLockedExceptionHandler, Long bestChainHeight = chainHeight == null ? null : (Long) chainHeight; String chainHeightAsString = bestChainHeight != null && bestChainHeight > 0 ? String.valueOf(bestChainHeight) : ""; if (chainDownloadPercentageD == 1) { - String synchronizedWith = Res.get("mainView.footer.xmrInfo.synchronizedDaemonWith", getXmrDaemonNetworkAsString(), chainHeightAsString); + String synchronizedWith = Res.get("mainView.footer.xmrInfo.syncedWith", getXmrDaemonNetworkAsString(), chainHeightAsString); String feeInfo = ""; // TODO: feeService.isFeeAvailable() returns true, disable result = Res.get("mainView.footer.xmrInfo", synchronizedWith, feeInfo); getXmrSplashSyncIconId().set("image-connection-synced"); } else if (chainDownloadPercentageD > 0.0) { - String synchronizingWith = Res.get("mainView.footer.xmrInfo.synchronizingDaemonWith", getXmrDaemonNetworkAsString(), chainHeightAsString, FormattingUtils.formatToRoundedPercentWithSymbol(chainDownloadPercentageD)); + String synchronizingWith = Res.get("mainView.footer.xmrInfo.synchronizingWith", getXmrDaemonNetworkAsString(), chainHeightAsString, FormattingUtils.formatToRoundedPercentWithSymbol(chainDownloadPercentageD)); result = Res.get("mainView.footer.xmrInfo", synchronizingWith, ""); } else { result = Res.get("mainView.footer.xmrInfo", diff --git a/core/src/main/resources/i18n/displayStrings.properties b/core/src/main/resources/i18n/displayStrings.properties index 7bb94bc6b20..31145795fe0 100644 --- a/core/src/main/resources/i18n/displayStrings.properties +++ b/core/src/main/resources/i18n/displayStrings.properties @@ -268,10 +268,9 @@ mainView.footer.localhostMoneroNode=(localhost) mainView.footer.xmrInfo={0} {1} mainView.footer.xmrFeeRate=/ Fee rate: {0} sat/vB mainView.footer.xmrInfo.initializing=Connecting to Haveno network -mainView.footer.xmrInfo.synchronizingDaemonWith=Synchronizing daemon with {0} at block: {1} / {2} -mainView.footer.xmrInfo.synchronizedDaemonWith=Daemon synchronized with {0} at block {1} +mainView.footer.xmrInfo.synchronizingWith=Synchronizing with {0} at block: {1} / {2} +mainView.footer.xmrInfo.syncedWith=Synced with {0} at block {1} mainView.footer.xmrInfo.synchronizingWalletWith=Synchronizing wallet with {0} at block: {1} / {2} -mainView.footer.xmrInfo.synchronizedWalletWith=Wallet synchronized with {0} at block {1} mainView.footer.xmrInfo.connectingTo=Connecting to mainView.footer.xmrInfo.connectionFailed=Connection failed to mainView.footer.xmrPeers=Monero network peers: {0} diff --git a/core/src/main/resources/i18n/displayStrings_cs.properties b/core/src/main/resources/i18n/displayStrings_cs.properties index 2703e576fe6..d138e76fe0b 100644 --- a/core/src/main/resources/i18n/displayStrings_cs.properties +++ b/core/src/main/resources/i18n/displayStrings_cs.properties @@ -249,8 +249,9 @@ mainView.footer.localhostMoneroNode=(localhost) mainView.footer.xmrInfo={0} {1} mainView.footer.xmrFeeRate=/ Aktuální poplatek: {0} sat/vB mainView.footer.xmrInfo.initializing=Připojování k síti Haveno -mainView.footer.xmrInfo.synchronizingDaemonWith=Synchronizace s {0} v bloku: {1} / {2} -mainView.footer.xmrInfo.synchronizedDaemonWith=Synchronizováno s {0} v bloku {1} +mainView.footer.xmrInfo.synchronizingWith=Synchronizace s {0} na bloku: {1} / {2} +mainView.footer.xmrInfo.syncedWith=Synchronizováno s {0} na bloku {1} +mainView.footer.xmrInfo.synchronizingWalletWith=Synchronizace peněženky s {0} na bloku: {1} / {2} mainView.footer.xmrInfo.connectingTo=Připojování mainView.footer.xmrInfo.connectionFailed=Připojení se nezdařilo mainView.footer.xmrPeers=Monero síťové nody: {0} diff --git a/core/src/main/resources/i18n/displayStrings_de.properties b/core/src/main/resources/i18n/displayStrings_de.properties index 720bf4a117a..35a89f9c218 100644 --- a/core/src/main/resources/i18n/displayStrings_de.properties +++ b/core/src/main/resources/i18n/displayStrings_de.properties @@ -249,8 +249,9 @@ mainView.footer.localhostMoneroNode=(localhost) mainView.footer.xmrInfo={0} {1} mainView.footer.xmrFeeRate=/ Aktuelle Gebühr: {0} sat/vB mainView.footer.xmrInfo.initializing=Verbindung mit Haveno-Netzwerk wird hergestellt -mainView.footer.xmrInfo.synchronizingDaemonWith=Synchronisierung mit {0} bei Block: {1} / {2} -mainView.footer.xmrInfo.synchronizedDaemonWith=Synchronisierung mit {0} bei Block {1} +mainView.footer.xmrInfo.synchronizingWith=Synchronisierung mit {0} bei Block: {1} / {2} +mainView.footer.xmrInfo.syncedWith=Synchronisiert mit {0} bei Block {1} +mainView.footer.xmrInfo.synchronizingWalletWith=Synchronisierung der Brieftasche mit {0} im Block: {1} / {2} mainView.footer.xmrInfo.connectingTo=Verbinde mit mainView.footer.xmrInfo.connectionFailed=Verbindung fehlgeschlagen zu mainView.footer.xmrPeers=Monero Netzwerk Peers: {0} diff --git a/core/src/main/resources/i18n/displayStrings_es.properties b/core/src/main/resources/i18n/displayStrings_es.properties index 7925250b002..116811e22f1 100644 --- a/core/src/main/resources/i18n/displayStrings_es.properties +++ b/core/src/main/resources/i18n/displayStrings_es.properties @@ -249,8 +249,9 @@ mainView.footer.localhostMoneroNode=(localhost) mainView.footer.xmrInfo={0} {1} mainView.footer.xmrFeeRate=/Tasas actuales: {0} sat/vB mainView.footer.xmrInfo.initializing=Conectando a la red Haveno -mainView.footer.xmrInfo.synchronizingDaemonWith=Sincronizando con {0} en el bloque: {1} / {2} -mainView.footer.xmrInfo.synchronizedDaemonWith=Sincronizado con {0} en el bloque {1} +mainView.footer.xmrInfo.synchronizingWith=Sincronizando con {0} en el bloque: {1} / {2} +mainView.footer.xmrInfo.syncedWith=Sincronizado con {0} en el bloque {1} +mainView.footer.xmrInfo.synchronizingWalletWith=Sincronizando la billetera con {0} en el bloque: {1} / {2} mainView.footer.xmrInfo.connectingTo=Conectando a mainView.footer.xmrInfo.connectionFailed=Conexión fallida a mainView.footer.xmrPeers=Pares de Monero: {0} diff --git a/core/src/main/resources/i18n/displayStrings_fa.properties b/core/src/main/resources/i18n/displayStrings_fa.properties index 793f398e003..8bfbe396a53 100644 --- a/core/src/main/resources/i18n/displayStrings_fa.properties +++ b/core/src/main/resources/i18n/displayStrings_fa.properties @@ -249,8 +249,9 @@ mainView.footer.localhostMoneroNode=(لوکال هاست) mainView.footer.xmrInfo={0} {1} mainView.footer.xmrFeeRate=/ Fee rate: {0} sat/vB mainView.footer.xmrInfo.initializing=اتصال به شبکه Haveno -mainView.footer.xmrInfo.synchronizingDaemonWith=Synchronizing with {0} at block: {1} / {2} -mainView.footer.xmrInfo.synchronizedDaemonWith=Synced with {0} at block {1} +mainView.footer.xmrInfo.synchronizingWith=همگام‌سازی با {0} در بلوک: {1} / {2} +mainView.footer.xmrInfo.syncedWith=همگام‌سازی با {0} در بلوک {1} انجام شده است +mainView.footer.xmrInfo.synchronizingWalletWith=همگام‌سازی کیف‌پول با {0} در بلوک: {1} / {2} mainView.footer.xmrInfo.connectingTo=در حال ایجاد ارتباط با mainView.footer.xmrInfo.connectionFailed=Connection failed to mainView.footer.xmrPeers=Monero network peers: {0} diff --git a/core/src/main/resources/i18n/displayStrings_fr.properties b/core/src/main/resources/i18n/displayStrings_fr.properties index a0d281e96d9..58225e91c28 100644 --- a/core/src/main/resources/i18n/displayStrings_fr.properties +++ b/core/src/main/resources/i18n/displayStrings_fr.properties @@ -249,8 +249,9 @@ mainView.footer.localhostMoneroNode=(localhost) mainView.footer.xmrInfo={0} {1} mainView.footer.xmrFeeRate=/ Taux des frais: {0} sat/vB mainView.footer.xmrInfo.initializing=Connexion au réseau Haveno en cours -mainView.footer.xmrInfo.synchronizingDaemonWith=Synchronisation avec {0} au block: {1}/ {2} -mainView.footer.xmrInfo.synchronizedDaemonWith=Synchronisé avec {0} au block {1} +mainView.footer.xmrInfo.synchronizingWith=Synchronisation avec {0} au bloc : {1} / {2} +mainView.footer.xmrInfo.syncedWith=Synchronisé avec {0} au bloc {1} +mainView.footer.xmrInfo.synchronizingWalletWith=Synchronisation du portefeuille avec {0} au bloc : {1} / {2} mainView.footer.xmrInfo.connectingTo=Se connecte à mainView.footer.xmrInfo.connectionFailed=Échec de la connexion à mainView.footer.xmrPeers=Pairs du réseau Monero: {0} diff --git a/core/src/main/resources/i18n/displayStrings_it.properties b/core/src/main/resources/i18n/displayStrings_it.properties index 2f451074044..12980d03ae5 100644 --- a/core/src/main/resources/i18n/displayStrings_it.properties +++ b/core/src/main/resources/i18n/displayStrings_it.properties @@ -249,6 +249,9 @@ mainView.footer.localhostMoneroNode=(localhost) mainView.footer.xmrInfo={0} {1} mainView.footer.xmrFeeRate=/ Fee rate: {0} sat/vB mainView.footer.xmrInfo.initializing=Connessione alla rete Haveno +mainView.footer.xmrInfo.synchronizingWith=Sincronizzazione con {0} al blocco: {1} / {2} +mainView.footer.xmrInfo.syncedWith=Sincronizzato con {0} al blocco {1} +mainView.footer.xmrInfo.synchronizingWalletWith=Sincronizzazione del portafoglio con {0} al blocco: {1} / {2} mainView.footer.xmrInfo.connectingTo=Connessione a mainView.footer.xmrInfo.connectionFailed=Connessione fallita mainView.footer.xmrPeers=Monero network peers: {0} diff --git a/core/src/main/resources/i18n/displayStrings_ja.properties b/core/src/main/resources/i18n/displayStrings_ja.properties index 9e767dbdb8e..f9ae72561e4 100644 --- a/core/src/main/resources/i18n/displayStrings_ja.properties +++ b/core/src/main/resources/i18n/displayStrings_ja.properties @@ -249,8 +249,9 @@ mainView.footer.localhostMoneroNode=(ローカルホスト) mainView.footer.xmrInfo={0} {1} mainView.footer.xmrFeeRate=/ 手数料率: {0} サトシ/vB mainView.footer.xmrInfo.initializing=Havenoネットワークに接続中 -mainView.footer.xmrInfo.synchronizingDaemonWith={0}と同期中、ブロック: {1} / {2} -mainView.footer.xmrInfo.synchronizedDaemonWith={0}と同期されています、ブロック{1}に +mainView.footer.xmrInfo.synchronizingWith=ブロック {1} / {2} で {0} と同期しています +mainView.footer.xmrInfo.syncedWith=ブロック {1} で {0} と同期しました +mainView.footer.xmrInfo.synchronizingWalletWith=ブロック {1} / {2} で {0} のウォレットを同期しています mainView.footer.xmrInfo.connectingTo=接続中: mainView.footer.xmrInfo.connectionFailed=接続失敗 mainView.footer.xmrPeers=Moneroネットワークピア: {0} diff --git a/core/src/main/resources/i18n/displayStrings_pt-br.properties b/core/src/main/resources/i18n/displayStrings_pt-br.properties index 5b708168494..e76dc042230 100644 --- a/core/src/main/resources/i18n/displayStrings_pt-br.properties +++ b/core/src/main/resources/i18n/displayStrings_pt-br.properties @@ -252,6 +252,9 @@ mainView.footer.localhostMoneroNode=(localhost) mainView.footer.xmrInfo={0} {1} mainView.footer.xmrFeeRate=/ Fee rate: {0} sat/vB mainView.footer.xmrInfo.initializing=Conectando-se à rede Haveno +mainView.footer.xmrInfo.synchronizingWith=Sincronizando com {0} no bloco: {1} / {2} +mainView.footer.xmrInfo.syncedWith=Sincronizado com {0} no bloco {1} +mainView.footer.xmrInfo.synchronizingWalletWith=Sincronizando a carteira com {0} no bloco: {1} / {2} mainView.footer.xmrInfo.connectingTo=Conectando-se a mainView.footer.xmrInfo.connectionFailed=Falha na conexão à mainView.footer.xmrPeers=Monero network peers: {0} diff --git a/core/src/main/resources/i18n/displayStrings_pt.properties b/core/src/main/resources/i18n/displayStrings_pt.properties index 47a57f58e45..b50b233cd1a 100644 --- a/core/src/main/resources/i18n/displayStrings_pt.properties +++ b/core/src/main/resources/i18n/displayStrings_pt.properties @@ -249,6 +249,9 @@ mainView.footer.localhostMoneroNode=(localhost) mainView.footer.xmrInfo={0} {1} mainView.footer.xmrFeeRate=/ Fee rate: {0} sat/vB mainView.footer.xmrInfo.initializing=Conectando à rede Haveno +mainView.footer.xmrInfo.synchronizingWith=Sincronizando com {0} no bloco: {1} / {2} +mainView.footer.xmrInfo.syncedWith=Sincronizado com {0} no bloco {1} +mainView.footer.xmrInfo.synchronizingWalletWith=Sincronizando a carteira com {0} no bloco: {1} / {2} mainView.footer.xmrInfo.connectingTo=Conectando à mainView.footer.xmrInfo.connectionFailed=Connection failed to mainView.footer.xmrPeers=Monero network peers: {0} diff --git a/core/src/main/resources/i18n/displayStrings_ru.properties b/core/src/main/resources/i18n/displayStrings_ru.properties index 8464467d418..dbb8886406f 100644 --- a/core/src/main/resources/i18n/displayStrings_ru.properties +++ b/core/src/main/resources/i18n/displayStrings_ru.properties @@ -249,6 +249,9 @@ mainView.footer.localhostMoneroNode=(локальный узел) mainView.footer.xmrInfo={0} {1} mainView.footer.xmrFeeRate=/ Fee rate: {0} sat/vB mainView.footer.xmrInfo.initializing=Подключение к сети Haveno +mainView.footer.xmrInfo.synchronizingWith=Синхронизация с {0} на блоке: {1} / {2} +mainView.footer.xmrInfo.syncedWith=Синхронизировано с {0} на блоке {1} +mainView.footer.xmrInfo.synchronizingWalletWith=Синхронизация кошелька с {0} на блоке: {1} / {2} mainView.footer.xmrInfo.connectingTo=Подключение к mainView.footer.xmrInfo.connectionFailed=Connection failed to mainView.footer.xmrPeers=Monero network peers: {0} diff --git a/core/src/main/resources/i18n/displayStrings_th.properties b/core/src/main/resources/i18n/displayStrings_th.properties index 3e787adb584..10ae0ec1edf 100644 --- a/core/src/main/resources/i18n/displayStrings_th.properties +++ b/core/src/main/resources/i18n/displayStrings_th.properties @@ -249,6 +249,9 @@ mainView.footer.localhostMoneroNode=(แม่ข่ายเฉพาะที mainView.footer.xmrInfo={0} {1} mainView.footer.xmrFeeRate=/ Fee rate: {0} sat/vB mainView.footer.xmrInfo.initializing=เชื่อมต่อกับเครือข่าย Haveno +mainView.footer.xmrInfo.synchronizingWith=กำลังซิงโครไนซ์กับ {0} ที่บล็อก: {1} / {2} +mainView.footer.xmrInfo.syncedWith=ซิงค์กับ {0} ที่บล็อก {1} เสร็จสมบูรณ์ +mainView.footer.xmrInfo.synchronizingWalletWith=กำลังซิงโครไนซ์กระเป๋าสตางค์กับ {0} ที่บล็อก: {1} / {2} mainView.footer.xmrInfo.connectingTo=Connecting to mainView.footer.xmrInfo.connectionFailed=Connection failed to mainView.footer.xmrPeers=Monero network peers: {0} diff --git a/core/src/main/resources/i18n/displayStrings_vi.properties b/core/src/main/resources/i18n/displayStrings_vi.properties index f6019cbfc34..d431e8d0677 100644 --- a/core/src/main/resources/i18n/displayStrings_vi.properties +++ b/core/src/main/resources/i18n/displayStrings_vi.properties @@ -249,6 +249,9 @@ mainView.footer.localhostMoneroNode=(Máy chủ nội bộ) mainView.footer.xmrInfo={0} {1} mainView.footer.xmrFeeRate=/ Fee rate: {0} sat/vB mainView.footer.xmrInfo.initializing=Đang kết nối với mạng Haveno +mainView.footer.xmrInfo.synchronizingWith=Đang đồng bộ với {0} tại khối: {1} / {2} +mainView.footer.xmrInfo.syncedWith=Đã đồng bộ với {0} tại khối {1} +mainView.footer.xmrInfo.synchronizingWalletWith=Đang đồng bộ hóa ví với {0} tại khối: {1} / {2} mainView.footer.xmrInfo.connectingTo=Đang kết nối với mainView.footer.xmrInfo.connectionFailed=Connection failed to mainView.footer.xmrPeers=Monero network peers: {0} diff --git a/core/src/main/resources/i18n/displayStrings_zh-hans.properties b/core/src/main/resources/i18n/displayStrings_zh-hans.properties index f983ef76287..ab7bbf13b0e 100644 --- a/core/src/main/resources/i18n/displayStrings_zh-hans.properties +++ b/core/src/main/resources/i18n/displayStrings_zh-hans.properties @@ -249,8 +249,9 @@ mainView.footer.localhostMoneroNode=(本地主机) mainView.footer.xmrInfo={0} {1} mainView.footer.xmrFeeRate=/ 矿工手费率:{0} 聪/字节 mainView.footer.xmrInfo.initializing=连接到 Haveno 网络 -mainView.footer.xmrInfo.synchronizingDaemonWith=正在通过{0}同步区块:{1}/{2} -mainView.footer.xmrInfo.synchronizedDaemonWith=已通过{0}同步至区块{1} +mainView.footer.xmrInfo.synchronizingWith=同步中,区块:{1} / {2},与 {0} 同步中 +mainView.footer.xmrInfo.syncedWith=已同步至 {0} 在区块 {1} +mainView.footer.xmrInfo.synchronizingWalletWith=同步中,区块:{1} / {2},与 {0} 的钱包同步中 mainView.footer.xmrInfo.connectingTo=连接至 mainView.footer.xmrInfo.connectionFailed=连接失败: mainView.footer.xmrPeers=Monero网络节点:{0} diff --git a/core/src/main/resources/i18n/displayStrings_zh-hant.properties b/core/src/main/resources/i18n/displayStrings_zh-hant.properties index 6f3f1c5f5c3..4f7d0cf7b3a 100644 --- a/core/src/main/resources/i18n/displayStrings_zh-hant.properties +++ b/core/src/main/resources/i18n/displayStrings_zh-hant.properties @@ -249,6 +249,9 @@ mainView.footer.localhostMoneroNode=(本地主機) mainView.footer.xmrInfo={0} {1} mainView.footer.xmrFeeRate=/ Fee rate: {0} sat/vB mainView.footer.xmrInfo.initializing=連接到 Haveno 網路 +mainView.footer.xmrInfo.synchronizingWith=同步中,區塊:{1} / {2},與 {0} 同步中 +mainView.footer.xmrInfo.syncedWith=已同步至 {0} 在區塊 {1} +mainView.footer.xmrInfo.synchronizingWalletWith=同步中,區塊:{1} / {2},與 {0} 的錢包同步中 mainView.footer.xmrInfo.connectingTo=連接至 mainView.footer.xmrInfo.connectionFailed=連接失敗: mainView.footer.xmrPeers=Monero網絡節點:{0} From c6eb13351ddf7972574fc419ee0e7b501fc9bb0d Mon Sep 17 00:00:00 2001 From: woodser Date: Fri, 8 Dec 2023 07:45:22 -0500 Subject: [PATCH 04/10] replace BigInteger.valueOf(0) with BigInteger.ZERO --- .../haveno/core/api/CoreDisputesService.java | 4 ++-- .../main/java/haveno/core/monetary/Price.java | 2 +- .../main/java/haveno/core/offer/OfferUtil.java | 4 ++-- .../haveno/core/offer/OpenOfferManager.java | 6 +++--- .../tasks/MakerReserveOfferFunds.java | 2 +- .../offer/placeoffer/tasks/ValidateOffer.java | 2 +- .../core/offer/takeoffer/TakeOfferModel.java | 6 +++--- .../core/payment/payload/PaymentMethod.java | 4 ++-- .../core/support/dispute/DisputeManager.java | 2 +- .../arbitration/ArbitrationManager.java | 4 ++-- .../core/trade/ClosedTradableManager.java | 4 ++-- .../java/haveno/core/trade/HavenoUtils.java | 6 +++--- .../src/main/java/haveno/core/trade/Trade.java | 4 ++-- .../tasks/ArbitratorProcessDepositRequest.java | 2 +- .../tasks/ArbitratorProcessReserveTx.java | 2 +- .../protocol/tasks/TakerReserveTradeFunds.java | 2 +- .../java/haveno/core/util/coin/CoinUtil.java | 8 ++++---- .../main/java/haveno/core/xmr/Balances.java | 10 +++++----- .../core/xmr/wallet/XmrWalletService.java | 14 +++++++------- .../account/sign/SignedWitnessServiceTest.java | 2 +- .../haveno/core/util/coin/CoinUtilTest.java | 2 +- .../desktop/components/AddressTextField.java | 4 ++-- .../transactions/TransactionsListItem.java | 18 +++++++++--------- .../main/funds/withdrawal/WithdrawalView.java | 10 +++++----- .../desktop/main/market/spread/SpreadView.java | 2 +- .../main/market/spread/SpreadViewModel.java | 2 +- .../main/offer/MutableOfferDataModel.java | 4 ++-- .../desktop/main/offer/MutableOfferView.java | 2 +- .../desktop/main/offer/OfferDataModel.java | 2 +- .../offer/takeoffer/TakeOfferDataModel.java | 2 +- .../main/offer/takeoffer/TakeOfferView.java | 2 +- .../overlays/windows/DisputeSummaryWindow.java | 16 ++++++++-------- .../pendingtrades/PendingTradesDataModel.java | 4 ++-- .../java/haveno/desktop/util/GUIUtilTest.java | 2 +- 34 files changed, 81 insertions(+), 81 deletions(-) diff --git a/core/src/main/java/haveno/core/api/CoreDisputesService.java b/core/src/main/java/haveno/core/api/CoreDisputesService.java index a72e85ff8e7..20c4ae48862 100644 --- a/core/src/main/java/haveno/core/api/CoreDisputesService.java +++ b/core/src/main/java/haveno/core/api/CoreDisputesService.java @@ -218,12 +218,12 @@ public void applyPayoutAmountsToDisputeResult(DisputePayout payout, Dispute disp disputeResult.setSellerPayoutAmountBeforeCost(sellerSecurityDeposit); } else if (payout == DisputePayout.BUYER_GETS_ALL) { disputeResult.setBuyerPayoutAmountBeforeCost(tradeAmount.add(buyerSecurityDeposit).add(sellerSecurityDeposit)); // TODO (woodser): apply min payout to incentivize loser? (see post v1.1.7) - disputeResult.setSellerPayoutAmountBeforeCost(BigInteger.valueOf(0)); + disputeResult.setSellerPayoutAmountBeforeCost(BigInteger.ZERO); } else if (payout == DisputePayout.SELLER_GETS_TRADE_AMOUNT) { disputeResult.setBuyerPayoutAmountBeforeCost(buyerSecurityDeposit); disputeResult.setSellerPayoutAmountBeforeCost(tradeAmount.add(sellerSecurityDeposit)); } else if (payout == DisputePayout.SELLER_GETS_ALL) { - disputeResult.setBuyerPayoutAmountBeforeCost(BigInteger.valueOf(0)); + disputeResult.setBuyerPayoutAmountBeforeCost(BigInteger.ZERO); disputeResult.setSellerPayoutAmountBeforeCost(tradeAmount.add(sellerSecurityDeposit).add(buyerSecurityDeposit)); } else if (payout == DisputePayout.CUSTOM) { if (customWinnerAmount > trade.getWallet().getBalance().longValueExact()) throw new RuntimeException("Winner payout is more than the trade wallet's balance"); diff --git a/core/src/main/java/haveno/core/monetary/Price.java b/core/src/main/java/haveno/core/monetary/Price.java index bfea2dbd17c..95fcd4f8b63 100644 --- a/core/src/main/java/haveno/core/monetary/Price.java +++ b/core/src/main/java/haveno/core/monetary/Price.java @@ -94,7 +94,7 @@ public BigInteger getAmountByVolume(Volume volume) { else if (monetary instanceof CryptoMoney && this.monetary instanceof CryptoMoney) return HavenoUtils.coinToAtomicUnits(new CryptoExchangeRate((CryptoMoney) this.monetary).cryptoToCoin((CryptoMoney) monetary)); else - return BigInteger.valueOf(0); + return BigInteger.ZERO; } public String getCurrencyCode() { diff --git a/core/src/main/java/haveno/core/offer/OfferUtil.java b/core/src/main/java/haveno/core/offer/OfferUtil.java index 6eca9ab42f4..857efbf3ec4 100644 --- a/core/src/main/java/haveno/core/offer/OfferUtil.java +++ b/core/src/main/java/haveno/core/offer/OfferUtil.java @@ -143,9 +143,9 @@ public boolean isBalanceSufficient(BigInteger cost, BigInteger balance) { public BigInteger getBalanceShortage(BigInteger cost, BigInteger balance) { if (cost != null) { BigInteger shortage = cost.subtract(balance); - return shortage.compareTo(BigInteger.valueOf(0)) < 0 ? BigInteger.valueOf(0) : shortage; + return shortage.compareTo(BigInteger.ZERO) < 0 ? BigInteger.ZERO : shortage; } else { - return BigInteger.valueOf(0); + return BigInteger.ZERO; } } diff --git a/core/src/main/java/haveno/core/offer/OpenOfferManager.java b/core/src/main/java/haveno/core/offer/OpenOfferManager.java index 802132e83d6..987158bfbe0 100644 --- a/core/src/main/java/haveno/core/offer/OpenOfferManager.java +++ b/core/src/main/java/haveno/core/offer/OpenOfferManager.java @@ -1029,7 +1029,7 @@ private void scheduleWithEarliestTxs(List openOffers, OpenOffer openO // get earliest unscheduled txs with sufficient incoming amount List scheduledTxHashes = new ArrayList(); - BigInteger scheduledAmount = BigInteger.valueOf(0); + BigInteger scheduledAmount = BigInteger.ZERO; for (MoneroTxWallet lockedTx : lockedTxs) { if (isTxScheduled(openOffers, lockedTx.getHash())) continue; if (lockedTx.getIncomingTransfers() == null || lockedTx.getIncomingTransfers().isEmpty()) continue; @@ -1048,7 +1048,7 @@ private void scheduleWithEarliestTxs(List openOffers, OpenOffer openO } private BigInteger getScheduledAmount(List openOffers) { - BigInteger scheduledAmount = BigInteger.valueOf(0); + BigInteger scheduledAmount = BigInteger.ZERO; for (OpenOffer openOffer : openOffers) { if (openOffer.getState() != OpenOffer.State.SCHEDULED) continue; if (openOffer.getScheduledTxHashes() == null) continue; @@ -1178,7 +1178,7 @@ private void handleSignOfferRequest(SignOfferRequest request, NodeAddress peer) } // verify maker's reserve tx (double spend, trade fee, trade amount, mining fee) - BigInteger sendAmount = offer.getDirection() == OfferDirection.BUY ? BigInteger.valueOf(0) : offer.getAmount(); + BigInteger sendAmount = offer.getDirection() == OfferDirection.BUY ? BigInteger.ZERO : offer.getAmount(); BigInteger securityDeposit = offer.getDirection() == OfferDirection.BUY ? offer.getMaxBuyerSecurityDeposit() : offer.getMaxSellerSecurityDeposit(); Tuple2 txResult = xmrWalletService.verifyTradeTx( offer.getId(), 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 f766fcce51a..51887920aa0 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 @@ -51,7 +51,7 @@ protected void run() { // create reserve tx BigInteger makerFee = offer.getMakerFee(); - BigInteger sendAmount = offer.getDirection() == OfferDirection.BUY ? BigInteger.valueOf(0) : offer.getAmount(); + 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); diff --git a/core/src/main/java/haveno/core/offer/placeoffer/tasks/ValidateOffer.java b/core/src/main/java/haveno/core/offer/placeoffer/tasks/ValidateOffer.java index 5ff2bba0bee..dfad9a08182 100644 --- a/core/src/main/java/haveno/core/offer/placeoffer/tasks/ValidateOffer.java +++ b/core/src/main/java/haveno/core/offer/placeoffer/tasks/ValidateOffer.java @@ -102,7 +102,7 @@ protected void run() { public static void checkBINotNullOrZero(BigInteger value, String name) { checkNotNull(value, name + " is null"); - checkArgument(value.compareTo(BigInteger.valueOf(0)) > 0, + checkArgument(value.compareTo(BigInteger.ZERO) > 0, name + " must be positive. " + name + "=" + value); } diff --git a/core/src/main/java/haveno/core/offer/takeoffer/TakeOfferModel.java b/core/src/main/java/haveno/core/offer/takeoffer/TakeOfferModel.java index 838ac1e32de..dff0b25743d 100644 --- a/core/src/main/java/haveno/core/offer/takeoffer/TakeOfferModel.java +++ b/core/src/main/java/haveno/core/offer/takeoffer/TakeOfferModel.java @@ -66,7 +66,7 @@ public class TakeOfferModel implements Model { @Getter private BigInteger totalToPay; @Getter - private BigInteger missingCoin = BigInteger.valueOf(0); + private BigInteger missingCoin = BigInteger.ZERO; @Getter private BigInteger totalAvailableBalance; @Getter @@ -156,7 +156,7 @@ private long getMaxTradeLimit() { @NotNull public BigInteger getFundsNeededForTrade() { // If taking a buy offer, taker needs to reserve the offer.amt too. - return securityDeposit.add(offer.isBuyOffer() ? amount : BigInteger.valueOf(0)); + return securityDeposit.add(offer.isBuyOffer() ? amount : BigInteger.ZERO); } private void validateModelInputs() { @@ -173,7 +173,7 @@ private void clearModel() { this.amount = null; this.availableBalance = null; this.isXmrWalletFunded = false; - this.missingCoin = BigInteger.valueOf(0); + this.missingCoin = BigInteger.ZERO; this.offer = null; this.paymentAccount = null; this.securityDeposit = null; diff --git a/core/src/main/java/haveno/core/payment/payload/PaymentMethod.java b/core/src/main/java/haveno/core/payment/payload/PaymentMethod.java index efe853ac888..342d36212b3 100644 --- a/core/src/main/java/haveno/core/payment/payload/PaymentMethod.java +++ b/core/src/main/java/haveno/core/payment/payload/PaymentMethod.java @@ -367,7 +367,7 @@ private static List getAssetCodes(List tradeCurrencies) { } public static PaymentMethod getDummyPaymentMethod(String id) { - return new PaymentMethod(id, 0, BigInteger.valueOf(0), Arrays.asList()); + return new PaymentMethod(id, 0, BigInteger.ZERO, Arrays.asList()); } @@ -417,7 +417,7 @@ private PaymentMethod(String id, long maxTradePeriod, BigInteger maxTradeLimit, // Used for dummy entries in payment methods list (SHOW_ALL) private PaymentMethod(String id) { - this(id, 0, BigInteger.valueOf(0), new ArrayList()); + this(id, 0, BigInteger.ZERO, new ArrayList()); } diff --git a/core/src/main/java/haveno/core/support/dispute/DisputeManager.java b/core/src/main/java/haveno/core/support/dispute/DisputeManager.java index 95ad78d6281..ba23f41e15c 100644 --- a/core/src/main/java/haveno/core/support/dispute/DisputeManager.java +++ b/core/src/main/java/haveno/core/support/dispute/DisputeManager.java @@ -1051,7 +1051,7 @@ protected void addPriceInfoMessage(Dispute dispute, int counter) { String optionTradeDetails; // We don't translate those strings (yet) as it is only displayed to mediators/arbitrators. String headline; - if (potentialGain.compareTo(BigInteger.valueOf(0)) > 0) { + if (potentialGain.compareTo(BigInteger.ZERO) > 0) { headline = "This might be a potential option trade!"; optionTradeDetails = "\nBTC amount calculated with price at dispute opening: " + HavenoUtils.formatXmr(potentialAmountAtDisputeOpening, true) + "\nMax loss of security deposit is: " + HavenoUtils.formatXmr(maxLossSecDeposit, true) + diff --git a/core/src/main/java/haveno/core/support/dispute/arbitration/ArbitrationManager.java b/core/src/main/java/haveno/core/support/dispute/arbitration/ArbitrationManager.java index fc7197da4c2..f20675f4617 100644 --- a/core/src/main/java/haveno/core/support/dispute/arbitration/ArbitrationManager.java +++ b/core/src/main/java/haveno/core/support/dispute/arbitration/ArbitrationManager.java @@ -386,7 +386,7 @@ private MoneroTxSet signAndPublishDisputePayoutTx(Trade trade) { // verify payouts sum to unlocked balance within loss of precision due to conversion to centineros BigInteger txCost = arbitratorSignedPayoutTx.getFee().add(arbitratorSignedPayoutTx.getChangeAmount()); // cost = fee + lost dust change if (!arbitratorSignedPayoutTx.getChangeAmount().equals(BigInteger.ZERO)) log.warn("Dust left in multisig wallet for {} {}: {}", getClass().getSimpleName(), trade.getId(), arbitratorSignedPayoutTx.getChangeAmount()); - if (trade.getWallet().getUnlockedBalance().subtract(actualBuyerAmount.add(actualSellerAmount).add(txCost)).compareTo(BigInteger.valueOf(0)) > 0) { + if (trade.getWallet().getUnlockedBalance().subtract(actualBuyerAmount.add(actualSellerAmount).add(txCost)).compareTo(BigInteger.ZERO) > 0) { throw new RuntimeException("The dispute payout amounts do not sum to the wallet's unlocked balance while verifying the dispute payout tx, unlocked balance=" + trade.getWallet().getUnlockedBalance() + " vs sum payout amount=" + actualBuyerAmount.add(actualSellerAmount) + ", buyer payout=" + actualBuyerAmount + ", seller payout=" + actualSellerAmount); } @@ -452,7 +452,7 @@ private MoneroTxSet signAndPublishDisputePayoutTx(Trade trade) { public static BigInteger[] getBuyerSellerPayoutTxCost(DisputeResult disputeResult, BigInteger payoutTxCost) { boolean isBuyerWinner = disputeResult.getWinner() == Winner.BUYER; BigInteger loserAmount = isBuyerWinner ? disputeResult.getSellerPayoutAmountBeforeCost() : disputeResult.getBuyerPayoutAmountBeforeCost(); - if (loserAmount.equals(BigInteger.valueOf(0))) { + if (loserAmount.equals(BigInteger.ZERO)) { BigInteger buyerPayoutTxFee = isBuyerWinner ? payoutTxCost : BigInteger.ZERO; BigInteger sellerPayoutTxFee = isBuyerWinner ? BigInteger.ZERO : payoutTxCost; return new BigInteger[] { buyerPayoutTxFee, sellerPayoutTxFee }; diff --git a/core/src/main/java/haveno/core/trade/ClosedTradableManager.java b/core/src/main/java/haveno/core/trade/ClosedTradableManager.java index a86b82aa2d8..ba90f41fb84 100644 --- a/core/src/main/java/haveno/core/trade/ClosedTradableManager.java +++ b/core/src/main/java/haveno/core/trade/ClosedTradableManager.java @@ -216,8 +216,8 @@ private BigInteger getTradeFee(Tradable tradable) { public BigInteger getXmrTradeFee(Tradable tradable) { return isMaker(tradable) ? - tradable.getOptionalMakerFee().orElse(BigInteger.valueOf(0)) : - tradable.getOptionalTakerFee().orElse(BigInteger.valueOf(0)); + tradable.getOptionalMakerFee().orElse(BigInteger.ZERO) : + tradable.getOptionalTakerFee().orElse(BigInteger.ZERO); } public boolean isMaker(Tradable tradable) { diff --git a/core/src/main/java/haveno/core/trade/HavenoUtils.java b/core/src/main/java/haveno/core/trade/HavenoUtils.java index 246d9f2ae91..247152bc29c 100644 --- a/core/src/main/java/haveno/core/trade/HavenoUtils.java +++ b/core/src/main/java/haveno/core/trade/HavenoUtils.java @@ -199,11 +199,11 @@ private static String getNumZeros(int numZeros) { } public static BigInteger parseXmr(String input) { - if (input == null || input.length() == 0) return BigInteger.valueOf(0); + if (input == null || input.length() == 0) return BigInteger.ZERO; try { return xmrToAtomicUnits(new BigDecimal(ParsingUtils.parseNumberStringToDouble(input)).doubleValue()); } catch (Exception e) { - return BigInteger.valueOf(0); + return BigInteger.ZERO; } } @@ -247,7 +247,7 @@ public static BigInteger getMinTakerFee() { public static BigInteger getFeePerXmr(BigInteger feePerXmr, BigInteger amount) { BigDecimal feePerXmrAsDecimal = feePerXmr == null ? BigDecimal.valueOf(0) : new BigDecimal(feePerXmr); - BigDecimal amountMultiplier = BigDecimal.valueOf(divide(amount == null ? BigInteger.valueOf(0) : amount, HavenoUtils.xmrToAtomicUnits(1.0))); + BigDecimal amountMultiplier = BigDecimal.valueOf(divide(amount == null ? BigInteger.ZERO : amount, HavenoUtils.xmrToAtomicUnits(1.0))); return feePerXmrAsDecimal.multiply(amountMultiplier).toBigInteger(); } diff --git a/core/src/main/java/haveno/core/trade/Trade.java b/core/src/main/java/haveno/core/trade/Trade.java index c9a3ccbb528..18a944b5843 100644 --- a/core/src/main/java/haveno/core/trade/Trade.java +++ b/core/src/main/java/haveno/core/trade/Trade.java @@ -1658,7 +1658,7 @@ public String getShortId() { } public BigInteger getFrozenAmount() { - BigInteger sum = BigInteger.valueOf(0); + BigInteger sum = BigInteger.ZERO; for (String keyImage : getSelf().getReserveTxKeyImages()) { List outputs = xmrWalletService.getWallet().getOutputs(new MoneroOutputQuery().setIsFrozen(true).setIsSpent(false).setKeyImage(new MoneroKeyImage(keyImage))); // TODO: will this check tx pool? avoid if (!outputs.isEmpty()) sum = sum.add(outputs.get(0).getAmount()); @@ -1667,7 +1667,7 @@ public BigInteger getFrozenAmount() { } public BigInteger getReservedAmount() { - if (isArbitrator() || !isDepositsPublished() || isPayoutPublished()) return BigInteger.valueOf(0); + if (isArbitrator() || !isDepositsPublished() || isPayoutPublished()) return BigInteger.ZERO; return isBuyer() ? getBuyer().getSecurityDeposit() : getAmount().add(getSeller().getSecurityDeposit()); } diff --git a/core/src/main/java/haveno/core/trade/protocol/tasks/ArbitratorProcessDepositRequest.java b/core/src/main/java/haveno/core/trade/protocol/tasks/ArbitratorProcessDepositRequest.java index 1ea81453fc5..4ae7aafab81 100644 --- a/core/src/main/java/haveno/core/trade/protocol/tasks/ArbitratorProcessDepositRequest.java +++ b/core/src/main/java/haveno/core/trade/protocol/tasks/ArbitratorProcessDepositRequest.java @@ -80,7 +80,7 @@ protected void run() { boolean isFromTaker = trader == trade.getTaker(); boolean isFromBuyer = trader == trade.getBuyer(); BigInteger tradeFee = isFromTaker ? trade.getTakerFee() : trade.getMakerFee(); - BigInteger sendAmount = isFromBuyer ? BigInteger.valueOf(0) : trade.getAmount(); + BigInteger sendAmount = isFromBuyer ? BigInteger.ZERO : trade.getAmount(); BigInteger securityDeposit = isFromBuyer ? trade.getBuyerSecurityDepositBeforeMiningFee() : trade.getSellerSecurityDepositBeforeMiningFee(); String depositAddress = processModel.getMultisigAddress(); diff --git a/core/src/main/java/haveno/core/trade/protocol/tasks/ArbitratorProcessReserveTx.java b/core/src/main/java/haveno/core/trade/protocol/tasks/ArbitratorProcessReserveTx.java index cb13af67830..aa2df99097d 100644 --- a/core/src/main/java/haveno/core/trade/protocol/tasks/ArbitratorProcessReserveTx.java +++ b/core/src/main/java/haveno/core/trade/protocol/tasks/ArbitratorProcessReserveTx.java @@ -55,7 +55,7 @@ protected void run() { // process reserve tx with expected values BigInteger tradeFee = isFromMaker ? trade.getMakerFee() : trade.getTakerFee(); - BigInteger sendAmount = isFromBuyer ? BigInteger.valueOf(0) : isFromMaker ? offer.getAmount() : trade.getAmount(); // maker reserve tx is for offer amount + BigInteger sendAmount = isFromBuyer ? BigInteger.ZERO : isFromMaker ? offer.getAmount() : trade.getAmount(); // maker reserve tx is for offer amount BigInteger securityDeposit = isFromMaker ? isFromBuyer ? offer.getMaxBuyerSecurityDeposit() : offer.getMaxSellerSecurityDeposit() : isFromBuyer ? trade.getBuyerSecurityDepositBeforeMiningFee() : trade.getSellerSecurityDepositBeforeMiningFee(); Tuple2 txResult; try { diff --git a/core/src/main/java/haveno/core/trade/protocol/tasks/TakerReserveTradeFunds.java b/core/src/main/java/haveno/core/trade/protocol/tasks/TakerReserveTradeFunds.java index 727472182c4..78daef5145f 100644 --- a/core/src/main/java/haveno/core/trade/protocol/tasks/TakerReserveTradeFunds.java +++ b/core/src/main/java/haveno/core/trade/protocol/tasks/TakerReserveTradeFunds.java @@ -41,7 +41,7 @@ protected void run() { // create reserve tx BigInteger takerFee = trade.getTakerFee(); - BigInteger sendAmount = trade.getOffer().getDirection() == OfferDirection.BUY ? trade.getAmount() : BigInteger.valueOf(0); + BigInteger sendAmount = trade.getOffer().getDirection() == OfferDirection.BUY ? trade.getAmount() : BigInteger.ZERO; BigInteger securityDeposit = trade.getOffer().getDirection() == OfferDirection.BUY ? trade.getSellerSecurityDepositBeforeMiningFee() : trade.getBuyerSecurityDepositBeforeMiningFee(); String returnAddress = model.getXmrWalletService().getOrCreateAddressEntry(trade.getOffer().getId(), XmrAddressEntry.Context.TRADE_PAYOUT).getAddressString(); MoneroTxWallet reserveTx = model.getXmrWalletService().createReserveTx(takerFee, sendAmount, securityDeposit, returnAddress, false, null); diff --git a/core/src/main/java/haveno/core/util/coin/CoinUtil.java b/core/src/main/java/haveno/core/util/coin/CoinUtil.java index b339337590d..65c8e4ec374 100644 --- a/core/src/main/java/haveno/core/util/coin/CoinUtil.java +++ b/core/src/main/java/haveno/core/util/coin/CoinUtil.java @@ -62,7 +62,7 @@ public static double getAsPercentPerBtc(BigInteger value) { * @return The percentage value as double (e.g. 1% is 0.01) */ public static double getAsPercentPerBtc(BigInteger part, BigInteger total) { - return MathUtils.roundDouble(HavenoUtils.divide(part == null ? BigInteger.valueOf(0) : part, total == null ? BigInteger.valueOf(1) : total), 4); + return MathUtils.roundDouble(HavenoUtils.divide(part == null ? BigInteger.ZERO : part, total == null ? BigInteger.valueOf(1) : total), 4); } /** @@ -71,7 +71,7 @@ public static double getAsPercentPerBtc(BigInteger part, BigInteger total) { * @return The percentage as atomic units (e.g. 1% of 1 BTC is 0.01 BTC) */ public static BigInteger getPercentOfAmount(double percent, BigInteger amount) { - if (amount == null) amount = BigInteger.valueOf(0); + if (amount == null) amount = BigInteger.ZERO; return BigDecimal.valueOf(percent).multiply(new BigDecimal(amount)).setScale(8, RoundingMode.DOWN).toBigInteger(); } @@ -134,7 +134,7 @@ static BigInteger getAdjustedAmount(BigInteger amount, Price price, long maxTrad // 10 EUR in case of HalCash. Volume smallestUnitForVolume = Volume.parse(String.valueOf(factor), price.getCurrencyCode()); if (smallestUnitForVolume.getValue() <= 0) - return BigInteger.valueOf(0); + return BigInteger.ZERO; BigInteger smallestUnitForAmount = price.getAmountByVolume(smallestUnitForVolume); long minTradeAmount = Restrictions.getMinTradeAmount().longValueExact(); @@ -152,7 +152,7 @@ static BigInteger getAdjustedAmount(BigInteger amount, Price price, long maxTrad ? getAdjustedVolumeUnit(price.getVolumeByAmount(smallestUnitForAmount), factor) : getAdjustedVolumeUnit(price.getVolumeByAmount(amount), factor); if (volume.getValue() <= 0) - return BigInteger.valueOf(0); + return BigInteger.ZERO; // From that adjusted volume we calculate back the amount. It might be a bit different as // the amount used as input before due rounding. diff --git a/core/src/main/java/haveno/core/xmr/Balances.java b/core/src/main/java/haveno/core/xmr/Balances.java index 1e3a99e4a75..e6662e479ca 100644 --- a/core/src/main/java/haveno/core/xmr/Balances.java +++ b/core/src/main/java/haveno/core/xmr/Balances.java @@ -101,12 +101,12 @@ private void updateBalances() { // TODO (woodser): converting to long should generally be avoided since can lose precision, but in practice these amounts are below max value private void updateAvailableBalance() { - availableBalance.set(xmrWalletService.getWallet() == null ? BigInteger.valueOf(0) : xmrWalletService.getWallet().getUnlockedBalance(0)); + availableBalance.set(xmrWalletService.getWallet() == null ? BigInteger.ZERO : xmrWalletService.getWallet().getUnlockedBalance(0)); } private void updatePendingBalance() { - BigInteger balance = xmrWalletService.getWallet() == null ? BigInteger.valueOf(0) : xmrWalletService.getWallet().getBalance(0); - BigInteger unlockedBalance = xmrWalletService.getWallet() == null ? BigInteger.valueOf(0) : xmrWalletService.getWallet().getUnlockedBalance(0); + BigInteger balance = xmrWalletService.getWallet() == null ? BigInteger.ZERO : xmrWalletService.getWallet().getBalance(0); + BigInteger unlockedBalance = xmrWalletService.getWallet() == null ? BigInteger.ZERO : xmrWalletService.getWallet().getUnlockedBalance(0); BigInteger pendingBalanceSum = balance.subtract(unlockedBalance); // add frozen trade balances - reserved amounts @@ -122,7 +122,7 @@ private void updatePendingBalance() { } private void updateReservedOfferBalance() { - BigInteger sum = BigInteger.valueOf(0); + BigInteger sum = BigInteger.ZERO; if (xmrWalletService.getWallet() != null) { List frozenOutputs = xmrWalletService.getWallet().getOutputs(new MoneroOutputQuery().setIsFrozen(true).setIsSpent(false)); for (MoneroOutputWallet frozenOutput : frozenOutputs) sum = sum.add(frozenOutput.getAmount()); @@ -138,7 +138,7 @@ private void updateReservedOfferBalance() { } private void updateReservedTradeBalance() { - BigInteger sum = BigInteger.valueOf(0); + BigInteger sum = BigInteger.ZERO; List trades = tradeManager.getTradesStreamWithFundsLockedIn().collect(Collectors.toList()); for (Trade trade : trades) { sum = sum.add(trade.getReservedAmount()); 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 138377f879a..aaeb8f693f7 100644 --- a/core/src/main/java/haveno/core/xmr/wallet/XmrWalletService.java +++ b/core/src/main/java/haveno/core/xmr/wallet/XmrWalletService.java @@ -424,7 +424,7 @@ public MoneroTxWallet createDepositTx(Trade trade, boolean reserveExactAmount, I // create deposit tx String multisigAddress = trade.getProcessModel().getMultisigAddress(); BigInteger tradeFee = trade instanceof MakerTrade ? trade.getOffer().getMakerFee() : trade.getTakerFee(); - BigInteger sendAmount = trade instanceof BuyerTrade ? BigInteger.valueOf(0) : trade.getAmount(); + BigInteger sendAmount = trade instanceof BuyerTrade ? BigInteger.ZERO : trade.getAmount(); BigInteger securityDeposit = trade instanceof BuyerTrade ? trade.getBuyerSecurityDepositBeforeMiningFee() : trade.getSellerSecurityDepositBeforeMiningFee(); long time = System.currentTimeMillis(); log.info("Creating deposit tx with multisig address={}", multisigAddress); @@ -449,7 +449,7 @@ private MoneroTxWallet createTradeTx(BigInteger tradeFee, BigInteger sendAmount, subaddressIndices.addAll(subaddressIndicesWithExactInput); } if (preferredSubaddressIndex != null) { - if (wallet.getBalance(0, preferredSubaddressIndex).compareTo(BigInteger.valueOf(0)) > 0) { + if (wallet.getBalance(0, preferredSubaddressIndex).compareTo(BigInteger.ZERO) > 0) { subaddressIndices.add(0, preferredSubaddressIndex); // try preferred subaddress first if funded } else if (reserveExactAmount) { subaddressIndices.add(preferredSubaddressIndex); // otherwise only try preferred subaddress if using exact output @@ -532,7 +532,7 @@ public Tuple2 verifyTradeTx(String offerId, BigInteger tra } // verify unlock height - if (!BigInteger.valueOf(0).equals(tx.getUnlockTime())) throw new RuntimeException("Unlock height must be 0"); + if (!BigInteger.ZERO.equals(tx.getUnlockTime())) throw new RuntimeException("Unlock height must be 0"); // verify miner fee BigInteger feeEstimate = getElevatedFeeEstimate(tx.getWeight()); @@ -603,7 +603,7 @@ private BigInteger getElevatedFeeEstimate(long txWeight) { // round up to multiple of quantization mask BigInteger[] quotientAndRemainder = baseFee.divideAndRemainder(qmask); BigInteger feeEstimate = qmask.multiply(quotientAndRemainder[0]); - if (quotientAndRemainder[1].compareTo(BigInteger.valueOf(0)) > 0) feeEstimate = feeEstimate.add(qmask); + if (quotientAndRemainder[1].compareTo(BigInteger.ZERO) > 0) feeEstimate = feeEstimate.add(qmask); return feeEstimate; } @@ -1105,7 +1105,7 @@ public List getAddressEntries(XmrAddressEntry.Context context) } public List getFundedAvailableAddressEntries() { - return getAvailableAddressEntries().stream().filter(addressEntry -> getBalanceForSubaddress(addressEntry.getSubaddressIndex()).compareTo(BigInteger.valueOf(0)) > 0).collect(Collectors.toList()); + return getAvailableAddressEntries().stream().filter(addressEntry -> getBalanceForSubaddress(addressEntry.getSubaddressIndex()).compareTo(BigInteger.ZERO) > 0).collect(Collectors.toList()); } public List getAddressEntryListAsImmutableList() { @@ -1147,7 +1147,7 @@ public int getNumOutputsForSubaddress(int subaddressIndex, List //if (tx.getTransfers(new MoneroTransferQuery().setSubaddressIndex(subaddressIndex)).isEmpty()) continue; // TODO monero-project: transfers are occluded by transfers from/to same account, so this will return unused when used numUnspentOutputs += tx.isConfirmed() ? tx.getOutputsWallet(new MoneroOutputQuery().setAccountIndex(0).setSubaddressIndex(subaddressIndex)).size() : 1; // TODO: monero-project does not provide outputs for unconfirmed txs } - boolean positiveBalance = wallet.getBalance(0, subaddressIndex).compareTo(BigInteger.valueOf(0)) > 0; + boolean positiveBalance = wallet.getBalance(0, subaddressIndex).compareTo(BigInteger.ZERO) > 0; if (positiveBalance && numUnspentOutputs == 0) return 1; // outputs do not appear until confirmed and internal transfers are occluded, so report 1 if positive balance return numUnspentOutputs; } @@ -1228,7 +1228,7 @@ public Stream getAddressEntriesForAvailableBalanceStream() { available = Stream.concat(available, getAddressEntries(XmrAddressEntry.Context.ARBITRATOR).stream()); available = Stream.concat(available, getAddressEntries(XmrAddressEntry.Context.OFFER_FUNDING).stream().filter(entry -> !tradeManager.getOpenOfferManager().getOpenOfferById(entry.getOfferId()).isPresent())); available = Stream.concat(available, getAddressEntries(XmrAddressEntry.Context.TRADE_PAYOUT).stream().filter(entry -> tradeManager.getTrade(entry.getOfferId()) == null || tradeManager.getTrade(entry.getOfferId()).isPayoutUnlocked())); - return available.filter(addressEntry -> getBalanceForSubaddress(addressEntry.getSubaddressIndex()).compareTo(BigInteger.valueOf(0)) > 0); + return available.filter(addressEntry -> getBalanceForSubaddress(addressEntry.getSubaddressIndex()).compareTo(BigInteger.ZERO) > 0); } public void addWalletListener(MoneroWalletListenerI listener) { diff --git a/core/src/test/java/haveno/core/account/sign/SignedWitnessServiceTest.java b/core/src/test/java/haveno/core/account/sign/SignedWitnessServiceTest.java index 40c991ed1f2..a84c1645e3e 100644 --- a/core/src/test/java/haveno/core/account/sign/SignedWitnessServiceTest.java +++ b/core/src/test/java/haveno/core/account/sign/SignedWitnessServiceTest.java @@ -353,7 +353,7 @@ public void testSignAccountAgeWitness_withTooLowTradeAmount() throws CryptoExcep when(keyRing.getSignatureKeyPair()).thenReturn(signerKeyPair); AccountAgeWitness accountAgeWitness = new AccountAgeWitness(account1DataHash, accountCreationTime); - signedWitnessService.signAndPublishAccountAgeWitness(BigInteger.valueOf(0), accountAgeWitness, peerKeyPair.getPublic()); + signedWitnessService.signAndPublishAccountAgeWitness(BigInteger.ZERO, accountAgeWitness, peerKeyPair.getPublic()); verify(p2pService, never()).addPersistableNetworkPayload(any(PersistableNetworkPayload.class), anyBoolean()); } diff --git a/core/src/test/java/haveno/core/util/coin/CoinUtilTest.java b/core/src/test/java/haveno/core/util/coin/CoinUtilTest.java index 29819580183..a27c7ac15ef 100644 --- a/core/src/test/java/haveno/core/util/coin/CoinUtilTest.java +++ b/core/src/test/java/haveno/core/util/coin/CoinUtilTest.java @@ -71,7 +71,7 @@ public void testGetAdjustedAmount() { try { CoinUtil.getAdjustedAmount( - BigInteger.valueOf(0), + BigInteger.ZERO, Price.valueOf("USD", 1000_0000), HavenoUtils.xmrToAtomicUnits(0.2).longValueExact(), 1); diff --git a/desktop/src/main/java/haveno/desktop/components/AddressTextField.java b/desktop/src/main/java/haveno/desktop/components/AddressTextField.java index 94faa4153e2..1e687759321 100644 --- a/desktop/src/main/java/haveno/desktop/components/AddressTextField.java +++ b/desktop/src/main/java/haveno/desktop/components/AddressTextField.java @@ -151,9 +151,9 @@ public void setPaymentLabel(String paymentLabel) { /////////////////////////////////////////////////////////////////////////////////////////// private String getMoneroURI() { - if (amount.get().compareTo(BigInteger.valueOf(0)) < 0) { + if (amount.get().compareTo(BigInteger.ZERO) < 0) { log.warn("Amount must not be negative"); - setAmount(BigInteger.valueOf(0)); + setAmount(BigInteger.ZERO); } return GUIUtil.getMoneroURI( address.get(), diff --git a/desktop/src/main/java/haveno/desktop/main/funds/transactions/TransactionsListItem.java b/desktop/src/main/java/haveno/desktop/main/funds/transactions/TransactionsListItem.java index 8bf772ba1ca..c0fcfedbbad 100644 --- a/desktop/src/main/java/haveno/desktop/main/funds/transactions/TransactionsListItem.java +++ b/desktop/src/main/java/haveno/desktop/main/funds/transactions/TransactionsListItem.java @@ -53,7 +53,7 @@ class TransactionsListItem { private String direction = ""; private boolean received; private boolean detailsAvailable; - private BigInteger amount = BigInteger.valueOf(0); + private BigInteger amount = BigInteger.ZERO; private String memo = ""; private long confirmations = 0; @Getter @@ -88,8 +88,8 @@ private LazyFields lazy() { Optional optionalTradable = Optional.ofNullable(transactionAwareTradable) .map(TransactionAwareTradable::asTradable); - BigInteger valueSentToMe = tx.getIncomingAmount() == null ? BigInteger.valueOf(0) : tx.getIncomingAmount(); - BigInteger valueSentFromMe = tx.getOutgoingAmount() == null ? BigInteger.valueOf(0) : tx.getOutgoingAmount(); + BigInteger valueSentToMe = tx.getIncomingAmount() == null ? BigInteger.ZERO : tx.getIncomingAmount(); + BigInteger valueSentFromMe = tx.getOutgoingAmount() == null ? BigInteger.ZERO : tx.getOutgoingAmount(); if (tx.getTransfers().get(0).isIncoming()) { addressString = ((MoneroIncomingTransfer) tx.getTransfers().get(0)).getAddress(); @@ -99,7 +99,7 @@ private LazyFields lazy() { else addressString = "unavailable"; } - if (valueSentFromMe.compareTo(BigInteger.valueOf(0)) == 0) { + if (valueSentFromMe.compareTo(BigInteger.ZERO) == 0) { amount = valueSentToMe; direction = Res.get("funds.tx.direction.receivedWith"); received = true; @@ -125,13 +125,13 @@ private LazyFields lazy() { } else if (trade.getPayoutTxId() != null && trade.getPayoutTxId().equals(txId)) { details = Res.get("funds.tx.multiSigPayout", tradeId); - if (amount.compareTo(BigInteger.valueOf(0)) == 0) { + if (amount.compareTo(BigInteger.ZERO) == 0) { initialTxConfidenceVisibility = false; } } else { Trade.DisputeState disputeState = trade.getDisputeState(); if (disputeState == Trade.DisputeState.DISPUTE_CLOSED) { - if (valueSentToMe.compareTo(BigInteger.valueOf(0)) > 0) { + if (valueSentToMe.compareTo(BigInteger.ZERO) > 0) { details = Res.get("funds.tx.disputePayout", tradeId); } else { details = Res.get("funds.tx.disputeLost", tradeId); @@ -139,7 +139,7 @@ private LazyFields lazy() { } else if (disputeState == Trade.DisputeState.REFUND_REQUEST_CLOSED || disputeState == Trade.DisputeState.REFUND_REQUESTED || disputeState == Trade.DisputeState.REFUND_REQUEST_STARTED_BY_PEER) { - if (valueSentToMe.compareTo(BigInteger.valueOf(0)) > 0) { + if (valueSentToMe.compareTo(BigInteger.ZERO) > 0) { details = Res.get("funds.tx.refund", tradeId); } else { // We have spent the deposit tx outputs to the Haveno donation address to enable @@ -147,7 +147,7 @@ private LazyFields lazy() { // already when funding the deposit tx we show 0 BTC as amount. // Confirmation is not known from the BitcoinJ side (not 100% clear why) as no funds // left our wallet nor we received funds. So we set indicator invisible. - amount = BigInteger.valueOf(0); + amount = BigInteger.ZERO; details = Res.get("funds.tx.collateralForRefund", tradeId); initialTxConfidenceVisibility = false; } @@ -157,7 +157,7 @@ private LazyFields lazy() { } } } else { - if (amount.compareTo(BigInteger.valueOf(0)) == 0) { + if (amount.compareTo(BigInteger.ZERO) == 0) { details = Res.get("funds.tx.noFundsFromDispute"); } } diff --git a/desktop/src/main/java/haveno/desktop/main/funds/withdrawal/WithdrawalView.java b/desktop/src/main/java/haveno/desktop/main/funds/withdrawal/WithdrawalView.java index 9b09e8c9637..daa027ca850 100644 --- a/desktop/src/main/java/haveno/desktop/main/funds/withdrawal/WithdrawalView.java +++ b/desktop/src/main/java/haveno/desktop/main/funds/withdrawal/WithdrawalView.java @@ -75,7 +75,7 @@ public class WithdrawalView extends ActivatableView { private final P2PService p2PService; private final WalletPasswordWindow walletPasswordWindow; private XmrBalanceListener balanceListener; - private BigInteger amount = BigInteger.valueOf(0); + private BigInteger amount = BigInteger.ZERO; private ChangeListener amountListener; private ChangeListener amountFocusListener; private ChangeListener feeToggleGroupListener; @@ -148,7 +148,7 @@ public void onBalanceChanged(BigInteger balance) { }; amountFocusListener = (observable, oldValue, newValue) -> { if (oldValue && !newValue) { - if (amount.compareTo(BigInteger.valueOf(0)) > 0) + if (amount.compareTo(BigInteger.ZERO) > 0) amountTextField.setText(HavenoUtils.formatXmr(amount)); else amountTextField.setText(""); @@ -200,7 +200,7 @@ private void onWithdraw() { final String withdrawToAddress = withdrawToTextField.getText(); // create tx - if (amount.compareTo(BigInteger.valueOf(0)) <= 0) throw new RuntimeException(Res.get("portfolio.pending.step5_buyer.amountTooLow")); + if (amount.compareTo(BigInteger.ZERO) <= 0) throw new RuntimeException(Res.get("portfolio.pending.step5_buyer.amountTooLow")); MoneroTxWallet tx = xmrWalletService.getWallet().createTx(new MoneroTxConfig() .setAccountIndex(0) .setAmount(amount) @@ -262,7 +262,7 @@ private void relayTx(MoneroTxWallet tx, String withdrawToAddress, BigInteger rec .filter(Trade::isPayoutPublished) .forEach(trade -> xmrWalletService.getAddressEntry(trade.getId(), XmrAddressEntry.Context.TRADE_PAYOUT) .ifPresent(addressEntry -> { - if (xmrWalletService.getBalanceForAddress(addressEntry.getAddressString()).compareTo(BigInteger.valueOf(0)) == 0) + if (xmrWalletService.getBalanceForAddress(addressEntry.getAddressString()).compareTo(BigInteger.ZERO) == 0) tradeManager.onTradeCompleted(trade); })); } catch (Exception e) { @@ -276,7 +276,7 @@ private void relayTx(MoneroTxWallet tx, String withdrawToAddress, BigInteger rec /////////////////////////////////////////////////////////////////////////////////////////// private void reset() { - amount = BigInteger.valueOf(0); + amount = BigInteger.ZERO; amountTextField.setText(""); amountTextField.setPromptText(Res.get("funds.withdrawal.setAmount")); diff --git a/desktop/src/main/java/haveno/desktop/main/market/spread/SpreadView.java b/desktop/src/main/java/haveno/desktop/main/market/spread/SpreadView.java index 7a680a68c26..1324142f99a 100644 --- a/desktop/src/main/java/haveno/desktop/main/market/spread/SpreadView.java +++ b/desktop/src/main/java/haveno/desktop/main/market/spread/SpreadView.java @@ -123,7 +123,7 @@ private void updateHeaders() { int numberOfBuyOffers = sortedList.stream().mapToInt(item -> item.numberOfBuyOffers).sum(); int numberOfSellOffers = sortedList.stream().mapToInt(item -> item.numberOfSellOffers).sum(); - BigInteger totalAmount = BigInteger.valueOf(0); + BigInteger totalAmount = BigInteger.ZERO; for (SpreadItem item : sortedList) totalAmount = totalAmount.add(item.totalAmount); String total = HavenoUtils.formatXmr(totalAmount); diff --git a/desktop/src/main/java/haveno/desktop/main/market/spread/SpreadViewModel.java b/desktop/src/main/java/haveno/desktop/main/market/spread/SpreadViewModel.java index 3529cb94c4c..00002880e71 100644 --- a/desktop/src/main/java/haveno/desktop/main/market/spread/SpreadViewModel.java +++ b/desktop/src/main/java/haveno/desktop/main/market/spread/SpreadViewModel.java @@ -129,7 +129,7 @@ private void update(ObservableList offerBookListItems) { } spreadItems.clear(); - BigInteger totalAmount = BigInteger.valueOf(0); + BigInteger totalAmount = BigInteger.ZERO; for (String key : offersByCurrencyMap.keySet()) { List offers = offersByCurrencyMap.get(key); diff --git a/desktop/src/main/java/haveno/desktop/main/offer/MutableOfferDataModel.java b/desktop/src/main/java/haveno/desktop/main/offer/MutableOfferDataModel.java index eaaa08de4d0..2c1e3a3b593 100644 --- a/desktop/src/main/java/haveno/desktop/main/offer/MutableOfferDataModel.java +++ b/desktop/src/main/java/haveno/desktop/main/offer/MutableOfferDataModel.java @@ -121,7 +121,7 @@ public abstract class MutableOfferDataModel extends OfferDataModel { protected boolean allowAmountUpdate = true; private final TradeStatisticsManager tradeStatisticsManager; - private final Predicate> isNonZeroAmount = (c) -> c.get() != null && c.get().compareTo(BigInteger.valueOf(0)) != 0; + private final Predicate> isNonZeroAmount = (c) -> c.get() != null && c.get().compareTo(BigInteger.ZERO) != 0; private final Predicate> isNonZeroPrice = (p) -> p.get() != null && !p.get().isZero(); private final Predicate> isNonZeroVolume = (v) -> v.get() != null && !v.get().isZero(); @Getter @@ -642,7 +642,7 @@ protected BigInteger getBuyerSecurityDeposit() { private BigInteger getSellerSecurityDeposit() { BigInteger amount = this.amount.get(); if (amount == null) - amount = BigInteger.valueOf(0); + amount = BigInteger.ZERO; BigInteger percentOfAmount = CoinUtil.getPercentOfAmount( createOfferService.getSellerSecurityDepositAsDouble(buyerSecurityDepositPct.get()), amount); diff --git a/desktop/src/main/java/haveno/desktop/main/offer/MutableOfferView.java b/desktop/src/main/java/haveno/desktop/main/offer/MutableOfferView.java index f7313adabf7..25a95fcad2b 100644 --- a/desktop/src/main/java/haveno/desktop/main/offer/MutableOfferView.java +++ b/desktop/src/main/java/haveno/desktop/main/offer/MutableOfferView.java @@ -330,7 +330,7 @@ public void initWithData(OfferDirection direction, TradeCurrency tradeCurrency, // called from parent as the view does not get notified when the tab is closed public void onClose() { // we use model.placeOfferCompleted to not react on close which was triggered by a successful placeOffer - if (model.getDataModel().getBalance().get().compareTo(BigInteger.valueOf(0)) > 0 && !model.placeOfferCompleted.get()) { + if (model.getDataModel().getBalance().get().compareTo(BigInteger.ZERO) > 0 && !model.placeOfferCompleted.get()) { model.getDataModel().swapTradeToSavings(); } } diff --git a/desktop/src/main/java/haveno/desktop/main/offer/OfferDataModel.java b/desktop/src/main/java/haveno/desktop/main/offer/OfferDataModel.java index ea507ee59ae..d530ea521cc 100644 --- a/desktop/src/main/java/haveno/desktop/main/offer/OfferDataModel.java +++ b/desktop/src/main/java/haveno/desktop/main/offer/OfferDataModel.java @@ -49,7 +49,7 @@ public abstract class OfferDataModel extends ActivatableDataModel { @Getter protected final ObjectProperty availableBalance = new SimpleObjectProperty<>(); @Getter - protected final ObjectProperty missingCoin = new SimpleObjectProperty<>(BigInteger.valueOf(0)); + protected final ObjectProperty missingCoin = new SimpleObjectProperty<>(BigInteger.ZERO); @Getter protected final BooleanProperty showWalletFundedNotification = new SimpleBooleanProperty(); @Getter diff --git a/desktop/src/main/java/haveno/desktop/main/offer/takeoffer/TakeOfferDataModel.java b/desktop/src/main/java/haveno/desktop/main/offer/takeoffer/TakeOfferDataModel.java index bba1117b379..5acbec9ee8f 100644 --- a/desktop/src/main/java/haveno/desktop/main/offer/takeoffer/TakeOfferDataModel.java +++ b/desktop/src/main/java/haveno/desktop/main/offer/takeoffer/TakeOfferDataModel.java @@ -353,7 +353,7 @@ private void removeListeners() { void calculateVolume() { if (tradePrice != null && offer != null && amount.get() != null && - amount.get().compareTo(BigInteger.valueOf(0)) != 0) { + amount.get().compareTo(BigInteger.ZERO) != 0) { Volume volumeByAmount = tradePrice.getVolumeByAmount(amount.get()); volumeByAmount = VolumeUtil.getAdjustedVolume(volumeByAmount, offer.getPaymentMethod().getId()); diff --git a/desktop/src/main/java/haveno/desktop/main/offer/takeoffer/TakeOfferView.java b/desktop/src/main/java/haveno/desktop/main/offer/takeoffer/TakeOfferView.java index 5b257f51cc8..38828f70b23 100644 --- a/desktop/src/main/java/haveno/desktop/main/offer/takeoffer/TakeOfferView.java +++ b/desktop/src/main/java/haveno/desktop/main/offer/takeoffer/TakeOfferView.java @@ -360,7 +360,7 @@ public void setCloseHandler(OfferView.CloseHandler closeHandler) { // Called from parent as the view does not get notified when the tab is closed public void onClose() { BigInteger availableBalance = model.dataModel.getAvailableBalance().get(); - if (availableBalance != null && availableBalance.compareTo(BigInteger.valueOf(0)) > 0 && !model.takeOfferCompleted.get() && !DevEnv.isDevMode()) { + if (availableBalance != null && availableBalance.compareTo(BigInteger.ZERO) > 0 && !model.takeOfferCompleted.get() && !DevEnv.isDevMode()) { model.dataModel.swapTradeToSavings(); } } diff --git a/desktop/src/main/java/haveno/desktop/main/overlays/windows/DisputeSummaryWindow.java b/desktop/src/main/java/haveno/desktop/main/overlays/windows/DisputeSummaryWindow.java index a325e3b27e5..a85b3bab078 100644 --- a/desktop/src/main/java/haveno/desktop/main/overlays/windows/DisputeSummaryWindow.java +++ b/desktop/src/main/java/haveno/desktop/main/overlays/windows/DisputeSummaryWindow.java @@ -364,7 +364,7 @@ private boolean isPayoutAmountValid() { // be made return totalAmount.compareTo(available) <= 0; } else { - if (totalAmount.compareTo(BigInteger.valueOf(0)) <= 0) { + if (totalAmount.compareTo(BigInteger.ZERO) <= 0) { return false; } return totalAmount.compareTo(available) == 0; @@ -612,23 +612,23 @@ private void showPayoutTxConfirmation(Contract contract, MoneroTxWallet payoutTx String sellerPayoutAddressString = contract.getSellerPayoutAddressString(); List destinations = payoutTx.getOutgoingTransfer().getDestinations(); boolean buyerFirst = destinations.get(0).getAddress().equals(buyerPayoutAddressString); - BigInteger buyerPayoutAmount = buyerFirst ? destinations.get(0).getAmount() : destinations.size() == 2 ? destinations.get(1).getAmount() : BigInteger.valueOf(0); - BigInteger sellerPayoutAmount = buyerFirst ? (destinations.size() == 2 ? destinations.get(1).getAmount() : BigInteger.valueOf(0)) : destinations.get(0).getAmount(); + BigInteger buyerPayoutAmount = buyerFirst ? destinations.get(0).getAmount() : destinations.size() == 2 ? destinations.get(1).getAmount() : BigInteger.ZERO; + BigInteger sellerPayoutAmount = buyerFirst ? (destinations.size() == 2 ? destinations.get(1).getAmount() : BigInteger.ZERO) : destinations.get(0).getAmount(); String buyerDetails = ""; - if (buyerPayoutAmount.compareTo(BigInteger.valueOf(0)) > 0) { + if (buyerPayoutAmount.compareTo(BigInteger.ZERO) > 0) { buyerDetails = Res.get("disputeSummaryWindow.close.txDetails.buyer", HavenoUtils.formatXmr(buyerPayoutAmount, true), buyerPayoutAddressString); } String sellerDetails = ""; - if (sellerPayoutAmount.compareTo(BigInteger.valueOf(0)) > 0) { + if (sellerPayoutAmount.compareTo(BigInteger.ZERO) > 0) { sellerDetails = Res.get("disputeSummaryWindow.close.txDetails.seller", HavenoUtils.formatXmr(sellerPayoutAmount, true), sellerPayoutAddressString); } BigInteger outputAmount = buyerPayoutAmount.add(sellerPayoutAmount).add(payoutTx.getFee()); - if (outputAmount.compareTo(BigInteger.valueOf(0)) > 0) { + if (outputAmount.compareTo(BigInteger.ZERO) > 0) { new Popup().width(900) .headLine(Res.get("disputeSummaryWindow.close.txDetails.headline")) .confirmation(Res.get("disputeSummaryWindow.close.txDetails", @@ -728,13 +728,13 @@ private void applyTradeAmountRadioButtonStates() { sellerPayoutAmount.equals(sellerSecurityDeposit)) { buyerGetsTradeAmountRadioButton.setSelected(true); } else if (buyerPayoutAmount.equals(tradeAmount.add(buyerSecurityDeposit).add(sellerSecurityDeposit)) && - sellerPayoutAmount.equals(BigInteger.valueOf(0))) { + sellerPayoutAmount.equals(BigInteger.ZERO)) { buyerGetsAllRadioButton.setSelected(true); } else if (sellerPayoutAmount.equals(tradeAmount.add(sellerSecurityDeposit)) && buyerPayoutAmount.equals(buyerSecurityDeposit)) { sellerGetsTradeAmountRadioButton.setSelected(true); } else if (sellerPayoutAmount.equals(tradeAmount.add(buyerSecurityDeposit).add(sellerSecurityDeposit)) - && buyerPayoutAmount.equals(BigInteger.valueOf(0))) { + && buyerPayoutAmount.equals(BigInteger.ZERO)) { sellerGetsAllRadioButton.setSelected(true); } else { customRadioButton.setSelected(true); diff --git a/desktop/src/main/java/haveno/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java b/desktop/src/main/java/haveno/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java index 5c1acd47540..5ca5cf0fd01 100644 --- a/desktop/src/main/java/haveno/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java +++ b/desktop/src/main/java/haveno/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java @@ -276,14 +276,14 @@ BigInteger getTradeFee() { return offer.getMakerFee(); } else { log.error("offer is null"); - return BigInteger.valueOf(0); + return BigInteger.ZERO; } } else { return trade.getTakerFee(); } } else { log.error("Trade is null at getTotalFees"); - return BigInteger.valueOf(0); + return BigInteger.ZERO; } } diff --git a/desktop/src/test/java/haveno/desktop/util/GUIUtilTest.java b/desktop/src/test/java/haveno/desktop/util/GUIUtilTest.java index e568d20aff2..26714798da8 100644 --- a/desktop/src/test/java/haveno/desktop/util/GUIUtilTest.java +++ b/desktop/src/test/java/haveno/desktop/util/GUIUtilTest.java @@ -127,6 +127,6 @@ public void percentageOfTradeAmount_minFeeZERO() { BigInteger fee = BigInteger.valueOf(100000000L); assertEquals(" (0.01% of trade amount)", - GUIUtil.getPercentageOfTradeAmount(fee, HavenoUtils.xmrToAtomicUnits(1.0), BigInteger.valueOf(0))); + GUIUtil.getPercentageOfTradeAmount(fee, HavenoUtils.xmrToAtomicUnits(1.0), BigInteger.ZERO)); } } From f4a46c7278a9fa5d60bf1eb653987351477fd57f Mon Sep 17 00:00:00 2001 From: woodser Date: Fri, 8 Dec 2023 15:34:29 -0500 Subject: [PATCH 05/10] mark dispute closed per ticket and sync for payout on ack --- .../core/support/dispute/DisputeManager.java | 2 + .../main/java/haveno/core/trade/Trade.java | 52 +++++++++++++------ .../windows/DisputeSummaryWindow.java | 2 + .../main/support/dispute/DisputeView.java | 17 +----- 4 files changed, 41 insertions(+), 32 deletions(-) diff --git a/core/src/main/java/haveno/core/support/dispute/DisputeManager.java b/core/src/main/java/haveno/core/support/dispute/DisputeManager.java index ba23f41e15c..7115540216d 100644 --- a/core/src/main/java/haveno/core/support/dispute/DisputeManager.java +++ b/core/src/main/java/haveno/core/support/dispute/DisputeManager.java @@ -764,6 +764,7 @@ public void onArrived() { disputeResult.getChatMessage().getUid()); clearPendingMessage(); + dispute.setIsClosed(); // We use the chatMessage wrapped inside the DisputeClosedMessage for // the state, as that is displayed to the user and we only persist that msg disputeResult.getChatMessage().setArrived(true); @@ -782,6 +783,7 @@ public void onStoredInMailbox() { disputeResult.getChatMessage().getUid()); clearPendingMessage(); + dispute.setIsClosed(); // We use the chatMessage wrapped inside the DisputeClosedMessage for // the state, as that is displayed to the user and we only persist that msg disputeResult.getChatMessage().setStoredInMailbox(true); diff --git a/core/src/main/java/haveno/core/trade/Trade.java b/core/src/main/java/haveno/core/trade/Trade.java index 18a944b5843..f315c6cb623 100644 --- a/core/src/main/java/haveno/core/trade/Trade.java +++ b/core/src/main/java/haveno/core/trade/Trade.java @@ -392,8 +392,8 @@ public static protobuf.Trade.TradePeriodState toProtoMessage(Trade.TradePeriodSt transient private Subscription tradePhaseSubscription; transient private Subscription payoutStateSubscription; transient private TaskLooper txPollLooper; - transient private Long walletRefreshPeriod; - transient private Long syncNormalStartTime; + transient private Long walletRefreshPeriodMs; + transient private Long syncNormalStartTimeMs; public static final long DEFER_PUBLISH_MS = 25000; // 25 seconds private static final long IDLE_SYNC_PERIOD_MS = 1680000; // 28 minutes (monero's default connection timeout is 30 minutes on a local connection, so beyond this the wallets will disconnect) @@ -775,7 +775,7 @@ public boolean isWalletConnected() { } public boolean isIdling() { - return this instanceof ArbitratorTrade && isDepositsConfirmed() && walletExists(); // arbitrator idles trade after deposits confirm + return this instanceof ArbitratorTrade && isDepositsConfirmed() && walletExists() && syncNormalStartTimeMs == null; // arbitrator idles trade after deposits confirm unless overriden } public void syncAndPollWallet() { @@ -783,11 +783,25 @@ public void syncAndPollWallet() { } public void syncWalletNormallyForMs(long syncNormalDuration) { - syncNormalStartTime = System.currentTimeMillis(); + syncNormalStartTimeMs = System.currentTimeMillis(); + + // override wallet refresh period setWalletRefreshPeriod(xmrWalletService.getConnectionService().getRefreshPeriodMs()); - UserThread.runAfter(() -> { - if (!isShutDown && System.currentTimeMillis() >= syncNormalStartTime + syncNormalDuration) updateWalletRefreshPeriod(); - }, syncNormalDuration); + + // reset wallet refresh period after duration + new Thread(() -> { + GenUtils.waitFor(syncNormalDuration); + if (!isShutDown && System.currentTimeMillis() >= syncNormalStartTimeMs + syncNormalDuration) { + syncNormalStartTimeMs = null; + updateWalletRefreshPeriod(); + } + }).start(); + + // TODO: sync wallet because `auto_refresh` will not sync wallet until end of last sync period (which could be a long idle) + new Thread(() -> { + GenUtils.waitFor(1000); + if (!isShutDownStarted) trySyncWallet(true); + }).start(); } public void importMultisigHex() { @@ -824,7 +838,7 @@ private void closeWallet() { stopPolling(); xmrWalletService.closeWallet(wallet, true); wallet = null; - walletRefreshPeriod = null; + walletRefreshPeriodMs = null; } } @@ -1317,11 +1331,14 @@ public void setPayoutTx(MoneroTxWallet payoutTx) { getSeller().setPayoutAmount(getSeller().getSecurityDeposit().subtract(getSeller().getPayoutTxFee())); } else if (getDisputeState().isClosed()) { DisputeResult disputeResult = getDisputeResult(); - BigInteger[] buyerSellerPayoutTxFees = ArbitrationManager.getBuyerSellerPayoutTxCost(disputeResult, payoutTx.getFee()); - getBuyer().setPayoutTxFee(buyerSellerPayoutTxFees[0]); - getSeller().setPayoutTxFee(buyerSellerPayoutTxFees[1]); - getBuyer().setPayoutAmount(disputeResult.getBuyerPayoutAmountBeforeCost().subtract(getBuyer().getPayoutTxFee())); - getSeller().setPayoutAmount(disputeResult.getSellerPayoutAmountBeforeCost().subtract(getSeller().getPayoutTxFee())); + if (disputeResult == null) log.warn("Dispute result is not set for {} {}", getClass().getSimpleName(), getId()); + else { + BigInteger[] buyerSellerPayoutTxFees = ArbitrationManager.getBuyerSellerPayoutTxCost(disputeResult, payoutTx.getFee()); + getBuyer().setPayoutTxFee(buyerSellerPayoutTxFees[0]); + getSeller().setPayoutTxFee(buyerSellerPayoutTxFees[1]); + getBuyer().setPayoutAmount(disputeResult.getBuyerPayoutAmountBeforeCost().subtract(getBuyer().getPayoutTxFee())); + getSeller().setPayoutAmount(disputeResult.getSellerPayoutAmountBeforeCost().subtract(getSeller().getPayoutTxFee())); + } } } @@ -1834,11 +1851,11 @@ public void updateWalletRefreshPeriod() { setWalletRefreshPeriod(getWalletRefreshPeriod()); } - private void setWalletRefreshPeriod(long walletRefreshPeriod) { + private void setWalletRefreshPeriod(long walletRefreshPeriodMs) { synchronized (walletLock) { if (this.isShutDownStarted) return; - if (this.walletRefreshPeriod != null && this.walletRefreshPeriod == walletRefreshPeriod) return; - this.walletRefreshPeriod = walletRefreshPeriod; + if (this.walletRefreshPeriodMs != null && this.walletRefreshPeriodMs == walletRefreshPeriodMs) return; + this.walletRefreshPeriodMs = walletRefreshPeriodMs; if (getWallet() != null) { log.info("Setting wallet refresh rate for {} {} to {}", getClass().getSimpleName(), getId(), getWalletRefreshPeriod()); getWallet().startSyncing(getWalletRefreshPeriod()); // TODO (monero-project): wallet rpc waits until last sync period finishes before starting new sync period @@ -1855,7 +1872,7 @@ private void startPolling() { if (isShutDownStarted || isPolling()) return; log.info("Starting to poll wallet for {} {}", getClass().getSimpleName(), getId()); txPollLooper = new TaskLooper(() -> pollWallet()); - txPollLooper.start(walletRefreshPeriod); + txPollLooper.start(walletRefreshPeriodMs); } } @@ -1961,6 +1978,7 @@ private void pollWallet() { } } catch (Exception e) { if (!isShutDownStarted && wallet != null && isWalletConnected()) { + e.printStackTrace(); log.warn("Error polling trade wallet for {} {}: {}. Monerod={}", getClass().getSimpleName(), getId(), e.getMessage(), getXmrWalletService().getConnectionService().getConnection()); } } diff --git a/desktop/src/main/java/haveno/desktop/main/overlays/windows/DisputeSummaryWindow.java b/desktop/src/main/java/haveno/desktop/main/overlays/windows/DisputeSummaryWindow.java index a85b3bab078..a5e4a68338e 100644 --- a/desktop/src/main/java/haveno/desktop/main/overlays/windows/DisputeSummaryWindow.java +++ b/desktop/src/main/java/haveno/desktop/main/overlays/windows/DisputeSummaryWindow.java @@ -581,6 +581,8 @@ private void addButtons(Contract contract) { Button cancelButton = tuple.second; closeTicketButton.setOnAction(e -> { + closeTicketButton.disableProperty().unbind(); + closeTicketButton.setDisable(true); if (dispute.getSupportType() == SupportType.ARBITRATION && peersDisputeOptional.isPresent() && !peersDisputeOptional.get().isClosed() && diff --git a/desktop/src/main/java/haveno/desktop/main/support/dispute/DisputeView.java b/desktop/src/main/java/haveno/desktop/main/support/dispute/DisputeView.java index 7491acce79b..7a259d84861 100644 --- a/desktop/src/main/java/haveno/desktop/main/support/dispute/DisputeView.java +++ b/desktop/src/main/java/haveno/desktop/main/support/dispute/DisputeView.java @@ -40,7 +40,6 @@ import haveno.core.trade.Contract; import haveno.core.trade.HavenoUtils; import haveno.core.trade.Trade; -import haveno.core.trade.Trade.DisputeState; import haveno.core.trade.TradeManager; import haveno.core.user.Preferences; import haveno.core.util.FormattingUtils; @@ -1353,7 +1352,7 @@ public void updateItem(final Dispute item, boolean empty) { // subscribe to trade's dispute state Trade trade = tradeManager.getTrade(item.getTradeId()); if (trade == null) log.warn("Dispute's trade is null for trade {}", item.getTradeId()); - else subscription = EasyBind.subscribe(trade.disputeStateProperty(), disputeState -> setText(getDisputeStateText(disputeState))); + else subscription = EasyBind.subscribe(item.isClosedProperty(), closedProp -> setText(getDisputeStateText(item))); } else { if (closedProperty != null) { closedProperty.removeListener(listener); @@ -1373,28 +1372,16 @@ public void updateItem(final Dispute item, boolean empty) { return column; } - private String getDisputeStateText(DisputeState disputeState) { - switch (disputeState) { - case DISPUTE_REQUESTED: - return Res.get("support.requested"); - case DISPUTE_CLOSED: - return Res.get("support.closed"); - default: - return Res.get("support.open"); - } - } - private String getDisputeStateText(Dispute dispute) { Trade trade = tradeManager.getTrade(dispute.getTradeId()); if (trade == null) { log.warn("Dispute's trade is null for trade {}", dispute.getTradeId()); return Res.get("support.closed"); } + if (dispute.isClosed()) return Res.get("support.closed"); switch (trade.getDisputeState()) { case DISPUTE_REQUESTED: return Res.get("support.requested"); - case DISPUTE_CLOSED: - return Res.get("support.closed"); default: return Res.get("support.open"); } From c0e86b6d2baa4243016bfd9c2f227226838db103 Mon Sep 17 00:00:00 2001 From: woodser Date: Sat, 9 Dec 2023 06:10:31 -0500 Subject: [PATCH 06/10] do not resend deposits confirmed message after payout published --- .../haveno/core/trade/protocol/TradeProtocol.java | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/core/src/main/java/haveno/core/trade/protocol/TradeProtocol.java b/core/src/main/java/haveno/core/trade/protocol/TradeProtocol.java index 2d0754302c2..ddce8e970ff 100644 --- a/core/src/main/java/haveno/core/trade/protocol/TradeProtocol.java +++ b/core/src/main/java/haveno/core/trade/protocol/TradeProtocol.java @@ -264,15 +264,10 @@ protected void onInitialized() { } private void maybeSendDepositsConfirmedMessage() { - if (trade.isDepositsConfirmed()) { + new Thread(() -> maybeSendDepositsConfirmedMessages()).start(); + EasyBind.subscribe(trade.stateProperty(), state -> { new Thread(() -> maybeSendDepositsConfirmedMessages()).start(); - } else { - EasyBind.subscribe(trade.stateProperty(), state -> { - if (trade.isDepositsConfirmed()) { - new Thread(() -> maybeSendDepositsConfirmedMessages()).start(); - } - }); - } + }); } public void maybeReprocessPaymentReceivedMessage(boolean reprocessOnError) { @@ -880,8 +875,8 @@ private boolean isMyMessage(NetworkEnvelope message) { } public void maybeSendDepositsConfirmedMessages() { + if (!trade.isDepositsConfirmed() || trade.isDepositsConfirmedAcked() || trade.isPayoutPublished()) return; synchronized (trade) { - if (trade.isDepositsConfirmedAcked()) return; if (!trade.isInitialized() || trade.isShutDownStarted()) return; // skip if shutting down latchTrade(); expect(new Condition(trade)) From 67695744bcba8ea36e5dd7b59b17034add227516 Mon Sep 17 00:00:00 2001 From: woodser Date: Sat, 9 Dec 2023 06:21:59 -0500 Subject: [PATCH 07/10] rename trade getPayoutAmount() to getPayoutAmountBeforeCost() --- core/src/main/java/haveno/core/trade/ArbitratorTrade.java | 2 +- core/src/main/java/haveno/core/trade/BuyerTrade.java | 2 +- core/src/main/java/haveno/core/trade/SellerTrade.java | 2 +- core/src/main/java/haveno/core/trade/Trade.java | 2 +- .../main/portfolio/pendingtrades/PendingTradesViewModel.java | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/haveno/core/trade/ArbitratorTrade.java b/core/src/main/java/haveno/core/trade/ArbitratorTrade.java index 03b0d202150..f46c4eb1b79 100644 --- a/core/src/main/java/haveno/core/trade/ArbitratorTrade.java +++ b/core/src/main/java/haveno/core/trade/ArbitratorTrade.java @@ -31,7 +31,7 @@ public ArbitratorTrade(Offer offer, } @Override - public BigInteger getPayoutAmount() { + public BigInteger getPayoutAmountBeforeCost() { throw new RuntimeException("Arbitrator does not have a payout amount"); } diff --git a/core/src/main/java/haveno/core/trade/BuyerTrade.java b/core/src/main/java/haveno/core/trade/BuyerTrade.java index df0ae0f1d45..6550bbb54e1 100644 --- a/core/src/main/java/haveno/core/trade/BuyerTrade.java +++ b/core/src/main/java/haveno/core/trade/BuyerTrade.java @@ -53,7 +53,7 @@ public abstract class BuyerTrade extends Trade { } @Override - public BigInteger getPayoutAmount() { + public BigInteger getPayoutAmountBeforeCost() { checkNotNull(getAmount(), "Invalid state: getTradeAmount() = null"); return getAmount().add(getBuyerSecurityDepositBeforeMiningFee()); } diff --git a/core/src/main/java/haveno/core/trade/SellerTrade.java b/core/src/main/java/haveno/core/trade/SellerTrade.java index 7b839180027..bb6080d2f5e 100644 --- a/core/src/main/java/haveno/core/trade/SellerTrade.java +++ b/core/src/main/java/haveno/core/trade/SellerTrade.java @@ -51,7 +51,7 @@ public abstract class SellerTrade extends Trade { } @Override - public BigInteger getPayoutAmount() { + public BigInteger getPayoutAmountBeforeCost() { return getSellerSecurityDepositBeforeMiningFee(); } diff --git a/core/src/main/java/haveno/core/trade/Trade.java b/core/src/main/java/haveno/core/trade/Trade.java index f315c6cb623..1efff6f714d 100644 --- a/core/src/main/java/haveno/core/trade/Trade.java +++ b/core/src/main/java/haveno/core/trade/Trade.java @@ -1200,7 +1200,7 @@ public void onComplete() { // Abstract /////////////////////////////////////////////////////////////////////////////////////////// - public abstract BigInteger getPayoutAmount(); + public abstract BigInteger getPayoutAmountBeforeCost(); public abstract boolean confirmPermitted(); diff --git a/desktop/src/main/java/haveno/desktop/main/portfolio/pendingtrades/PendingTradesViewModel.java b/desktop/src/main/java/haveno/desktop/main/portfolio/pendingtrades/PendingTradesViewModel.java index 84de9934f64..87208d6d263 100644 --- a/desktop/src/main/java/haveno/desktop/main/portfolio/pendingtrades/PendingTradesViewModel.java +++ b/desktop/src/main/java/haveno/desktop/main/portfolio/pendingtrades/PendingTradesViewModel.java @@ -223,9 +223,9 @@ ReadOnlyObjectProperty getSellerState() { return sellerState; } - public String getPayoutAmount() { + public String getPayoutAmountBeforeCost() { return dataModel.getTrade() != null - ? HavenoUtils.formatXmr(dataModel.getTrade().getPayoutAmount(), true) + ? HavenoUtils.formatXmr(dataModel.getTrade().getPayoutAmountBeforeCost(), true) : ""; } From af2691d305434b4073b31f8d94a6af32e4fa2c90 Mon Sep 17 00:00:00 2001 From: woodser Date: Sat, 9 Dec 2023 11:41:52 -0500 Subject: [PATCH 08/10] clear basic trade process data on payout unlocked --- .../main/java/haveno/core/trade/Trade.java | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/haveno/core/trade/Trade.java b/core/src/main/java/haveno/core/trade/Trade.java index 1efff6f714d..32d9542d50e 100644 --- a/core/src/main/java/haveno/core/trade/Trade.java +++ b/core/src/main/java/haveno/core/trade/Trade.java @@ -595,7 +595,7 @@ public void initialize(ProcessModelServiceProvider serviceProvider) { // check if done if (isPayoutUnlocked()) { - if (walletExists()) deleteWallet(); + maybeClearProcessData(); return; } @@ -662,6 +662,7 @@ public void initialize(ProcessModelServiceProvider serviceProvider) { if (!isInitialized) return; log.info("Payout unlocked for {} {}, deleting multisig wallet", getClass().getSimpleName(), getId()); deleteWallet(); + maybeClearProcessData(); if (idlePayoutSyncer != null) { xmrWalletService.removeWalletListener(idlePayoutSyncer); idlePayoutSyncer = null; @@ -1144,6 +1145,24 @@ public boolean mediationResultAppliedPenaltyToSeller() { return payoutAmountFromMediation < normalPayoutAmount; } + public void maybeClearProcessData() { + synchronized (walletLock) { + + // skip if already cleared + if (!walletExists()) return; + + // delete trade wallet + deleteWallet(); + + // TODO: clear other process data + setPayoutTxHex(null); + for (TradePeer peer : getPeers()) { + peer.setUnsignedPayoutTxHex(null); + peer.setUpdatedMultisigHex(null); + } + } + } + public void maybeClearSensitiveData() { String change = ""; if (removeAllChatMessages()) { From e4ddf5838e5555bdb2429969de76ae261ae6fa2b Mon Sep 17 00:00:00 2001 From: woodser Date: Sat, 9 Dec 2023 12:34:27 -0500 Subject: [PATCH 09/10] call wallet.sync() on startup after background sync with progress --- .../haveno/core/xmr/wallet/XmrWalletService.java | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) 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 aaeb8f693f7..68602343f6a 100644 --- a/core/src/main/java/haveno/core/xmr/wallet/XmrWalletService.java +++ b/core/src/main/java/haveno/core/xmr/wallet/XmrWalletService.java @@ -737,9 +737,13 @@ private void maybeInitMainWallet(boolean sync, int numAttempts) { long time = System.currentTimeMillis(); syncWalletWithProgress(); // blocking log.info("Done syncing main wallet in " + (System.currentTimeMillis() - time) + " ms"); - wallet.startSyncing(xmrConnectionService.getRefreshPeriodMs()); - wallet.getTxs(new MoneroTxQuery().setIsLocked(true)); // TODO: main wallet's balance does update on startup with 0 conf PaymentReceivedMessage until pool txs fetched? - if (getMoneroNetworkType() != MoneroNetworkType.MAINNET) log.info("Monero wallet balance={}, unlocked balance={}", wallet.getBalance(0), wallet.getUnlockedBalance(0)); + + // log wallet balances + if (getMoneroNetworkType() != MoneroNetworkType.MAINNET) { + BigInteger balance = wallet.getBalance(); + BigInteger unlockedBalance = wallet.getUnlockedBalance(); + log.info("Monero wallet unlocked balance={}, pending balance={}, total balance={}", unlockedBalance, balance.subtract(unlockedBalance), balance); + } // reapply connection after wallet synced onConnectionChanged(xmrConnectionService.getConnection()); @@ -782,14 +786,15 @@ private void maybeInitMainWallet(boolean sync, int numAttempts) { private void syncWalletWithProgress() { updateSyncProgress(); - wallet.startSyncing(); + wallet.startSyncing(xmrConnectionService.getRefreshPeriodMs()); CountDownLatch latch = new CountDownLatch(1); syncLooper = new TaskLooper(() -> { if (wallet.getHeight() < xmrConnectionService.getTargetHeight()) updateSyncProgress(); else { + syncLooper.stop(); + wallet.sync(); // necessary to fully sync wasWalletSynced = true; updateSyncProgress(); - syncLooper.stop(); latch.countDown(); } }); From 5fc7fb34131908baebac7189acd69ea421f04df2 Mon Sep 17 00:00:00 2001 From: woodser Date: Sat, 9 Dec 2023 14:44:46 -0500 Subject: [PATCH 10/10] bump version to v0.0.16 --- build.gradle | 2 +- common/src/main/java/haveno/common/app/Version.java | 2 +- desktop/package/macosx/Info.plist | 4 ++-- docs/deployment-guide.md | 2 +- docs/installing.md | 4 ++-- seednode/src/main/java/haveno/seednode/SeedNodeMain.java | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/build.gradle b/build.gradle index 9956840aff7..a868f914423 100644 --- a/build.gradle +++ b/build.gradle @@ -580,7 +580,7 @@ configure(project(':desktop')) { apply plugin: 'com.github.johnrengelman.shadow' apply from: 'package/package.gradle' - version = '1.0.15-SNAPSHOT' + version = '1.0.16-SNAPSHOT' jar.manifest.attributes( "Implementation-Title": project.name, diff --git a/common/src/main/java/haveno/common/app/Version.java b/common/src/main/java/haveno/common/app/Version.java index 2ffddf298e5..638dcaae885 100644 --- a/common/src/main/java/haveno/common/app/Version.java +++ b/common/src/main/java/haveno/common/app/Version.java @@ -28,7 +28,7 @@ public class Version { // The application versions // We use semantic versioning with major, minor and patch - public static final String VERSION = "1.0.15"; + public static final String VERSION = "1.0.16"; /** * Holds a list of the tagged resource files for optimizing the getData requests. diff --git a/desktop/package/macosx/Info.plist b/desktop/package/macosx/Info.plist index da2fa248d87..be308b46499 100644 --- a/desktop/package/macosx/Info.plist +++ b/desktop/package/macosx/Info.plist @@ -5,10 +5,10 @@ CFBundleVersion - 1.0.15 + 1.0.16 CFBundleShortVersionString - 1.0.15 + 1.0.16 CFBundleExecutable Haveno diff --git a/docs/deployment-guide.md b/docs/deployment-guide.md index 2d980c6a639..153608a0b88 100644 --- a/docs/deployment-guide.md +++ b/docs/deployment-guide.md @@ -139,7 +139,7 @@ To run Monero and Haveno binaries as system services, scripts are available for Set the mandatory minimum version for trading (optional) -If applicable, update the mandatory minimum version for trading, by entering `ctrl + f` to open the Filter window, enter a private key with developer privileges, and enter the minimum version (e.g. 1.0.15) in the field labeled "Min. version required for trading". +If applicable, update the mandatory minimum version for trading, by entering `ctrl + f` to open the Filter window, enter a private key with developer privileges, and enter the minimum version (e.g. 1.0.16) in the field labeled "Min. version required for trading". Send update alert diff --git a/docs/installing.md b/docs/installing.md index 884e1825d66..4fbc059edd8 100644 --- a/docs/installing.md +++ b/docs/installing.md @@ -28,7 +28,7 @@ If it's the first time you are building Haveno, run the following commands to do ``` git clone https://github.com/haveno-dex/haveno.git cd haveno -git checkout v0.0.15 +git checkout v0.0.16 make ``` @@ -37,7 +37,7 @@ make If you are updating from a previous version, run from the root of the repository: ``` -git checkout v0.0.15 +git checkout v0.0.16 git pull make clean && make ``` diff --git a/seednode/src/main/java/haveno/seednode/SeedNodeMain.java b/seednode/src/main/java/haveno/seednode/SeedNodeMain.java index d8cb542dd61..15d65109594 100644 --- a/seednode/src/main/java/haveno/seednode/SeedNodeMain.java +++ b/seednode/src/main/java/haveno/seednode/SeedNodeMain.java @@ -41,7 +41,7 @@ @Slf4j public class SeedNodeMain extends ExecutableForAppWithP2p { private static final long CHECK_CONNECTION_LOSS_SEC = 30; - private static final String VERSION = "0.0.15"; + private static final String VERSION = "0.0.16"; private SeedNode seedNode; private Timer checkConnectionLossTime;