mirror of
https://github.com/haveno-dex/haveno.git
synced 2024-10-01 01:35:48 -04:00
trade fees are adjustable and persisted in offer payload
This commit is contained in:
parent
59fbd805a5
commit
7d7660414a
@ -189,7 +189,7 @@ abstract class AbstractTradeListBuilder extends AbstractTableBuilder {
|
||||
protected final Function<TradeInfo, Long> toTradeFeeBtc = (t) -> {
|
||||
var isMyOffer = t.getOffer().getIsMyOffer();
|
||||
if (isMyOffer) {
|
||||
return t.getOffer().getMakerFee();
|
||||
return t.getMakerFee();
|
||||
} else {
|
||||
return t.getTakerFee();
|
||||
}
|
||||
@ -198,7 +198,7 @@ abstract class AbstractTradeListBuilder extends AbstractTableBuilder {
|
||||
protected final Function<TradeInfo, Long> toMyMakerOrTakerFee = (t) -> {
|
||||
return isTaker.test(t)
|
||||
? t.getTakerFee()
|
||||
: t.getOffer().getMakerFee();
|
||||
: t.getMakerFee();
|
||||
};
|
||||
|
||||
protected final Function<TradeInfo, String> toOfferType = (t) -> {
|
||||
|
@ -143,18 +143,15 @@ class CoreTradesService {
|
||||
}
|
||||
|
||||
// synchronize access to take offer model // TODO (woodser): to avoid synchronizing, don't use stateful model
|
||||
BigInteger takerFee;
|
||||
BigInteger fundsNeededForTrade;
|
||||
synchronized (takeOfferModel) {
|
||||
takeOfferModel.initModel(offer, paymentAccount, amount, useSavingsWallet);
|
||||
takerFee = takeOfferModel.getTakerFee();
|
||||
fundsNeededForTrade = takeOfferModel.getFundsNeededForTrade();
|
||||
log.debug("Initiating take {} offer, {}", offer.isBuyOffer() ? "buy" : "sell", takeOfferModel);
|
||||
}
|
||||
|
||||
// take offer
|
||||
tradeManager.onTakeOffer(amount,
|
||||
takerFee,
|
||||
fundsNeededForTrade,
|
||||
offer,
|
||||
paymentAccountId,
|
||||
|
@ -52,8 +52,9 @@ public class OfferInfo implements Payload {
|
||||
private final long minAmount;
|
||||
private final String volume;
|
||||
private final String minVolume;
|
||||
private final long makerFee;
|
||||
@Nullable
|
||||
private final double makerFeePct;
|
||||
private final double takerFeePct;
|
||||
private final double penaltyFeePct;
|
||||
private final double buyerSecurityDepositPct;
|
||||
private final double sellerSecurityDepositPct;
|
||||
private final String triggerPrice;
|
||||
@ -86,11 +87,13 @@ public class OfferInfo implements Payload {
|
||||
this.marketPriceMarginPct = builder.getMarketPriceMarginPct();
|
||||
this.amount = builder.getAmount();
|
||||
this.minAmount = builder.getMinAmount();
|
||||
this.volume = builder.getVolume();
|
||||
this.minVolume = builder.getMinVolume();
|
||||
this.makerFee = builder.getMakerFee();
|
||||
this.makerFeePct = builder.getMakerFeePct();
|
||||
this.takerFeePct = builder.getTakerFeePct();
|
||||
this.penaltyFeePct = builder.getPenaltyFeePct();
|
||||
this.buyerSecurityDepositPct = builder.getBuyerSecurityDepositPct();
|
||||
this.sellerSecurityDepositPct = builder.getSellerSecurityDepositPct();
|
||||
this.volume = builder.getVolume();
|
||||
this.minVolume = builder.getMinVolume();
|
||||
this.triggerPrice = builder.getTriggerPrice();
|
||||
this.paymentAccountId = builder.getPaymentAccountId();
|
||||
this.paymentMethodId = builder.getPaymentMethodId();
|
||||
@ -155,11 +158,14 @@ public class OfferInfo implements Payload {
|
||||
.withMarketPriceMarginPct(marketPriceMarginAsPctLiteral)
|
||||
.withAmount(offer.getAmount().longValueExact())
|
||||
.withMinAmount(offer.getMinAmount().longValueExact())
|
||||
.withVolume(roundedVolume)
|
||||
.withMinVolume(roundedMinVolume)
|
||||
.withMakerFee(offer.getMakerFee().longValueExact())
|
||||
.withMakerFeePct(offer.getMakerFeePct())
|
||||
.withTakerFeePct(offer.getTakerFeePct())
|
||||
.withPenaltyFeePct(offer.getPenaltyFeePct())
|
||||
.withSellerSecurityDepositPct(offer.getSellerSecurityDepositPct())
|
||||
.withBuyerSecurityDepositPct(offer.getBuyerSecurityDepositPct())
|
||||
.withSellerSecurityDepositPct(offer.getSellerSecurityDepositPct())
|
||||
.withVolume(roundedVolume)
|
||||
.withMinVolume(roundedMinVolume)
|
||||
.withPaymentAccountId(offer.getMakerPaymentAccountId())
|
||||
.withPaymentMethodId(offer.getPaymentMethod().getId())
|
||||
.withPaymentMethodShortName(offer.getPaymentMethod().getShortName())
|
||||
@ -190,7 +196,9 @@ public class OfferInfo implements Payload {
|
||||
.setMinAmount(minAmount)
|
||||
.setVolume(volume)
|
||||
.setMinVolume(minVolume)
|
||||
.setMakerFee(makerFee)
|
||||
.setMakerFeePct(makerFeePct)
|
||||
.setTakerFeePct(takerFeePct)
|
||||
.setPenaltyFeePct(penaltyFeePct)
|
||||
.setBuyerSecurityDepositPct(buyerSecurityDepositPct)
|
||||
.setSellerSecurityDepositPct(sellerSecurityDepositPct)
|
||||
.setTriggerPrice(triggerPrice == null ? "0" : triggerPrice)
|
||||
@ -225,7 +233,9 @@ public class OfferInfo implements Payload {
|
||||
.withMinAmount(proto.getMinAmount())
|
||||
.withVolume(proto.getVolume())
|
||||
.withMinVolume(proto.getMinVolume())
|
||||
.withMakerFee(proto.getMakerFee())
|
||||
.withMakerFeePct(proto.getMakerFeePct())
|
||||
.withTakerFeePct(proto.getTakerFeePct())
|
||||
.withPenaltyFeePct(proto.getPenaltyFeePct())
|
||||
.withBuyerSecurityDepositPct(proto.getBuyerSecurityDepositPct())
|
||||
.withSellerSecurityDepositPct(proto.getSellerSecurityDepositPct())
|
||||
.withTriggerPrice(proto.getTriggerPrice())
|
||||
|
@ -64,11 +64,12 @@ public class TradeInfo implements Payload {
|
||||
private final String shortId;
|
||||
private final long date;
|
||||
private final String role;
|
||||
private final long takerFee;
|
||||
private final String makerDepositTxId;
|
||||
private final String takerDepositTxId;
|
||||
private final String payoutTxId;
|
||||
private final long amount;
|
||||
private final long makerFee;
|
||||
private final long takerFee;
|
||||
private final long buyerSecurityDeposit;
|
||||
private final long sellerSecurityDeposit;
|
||||
private final long buyerDepositTxFee;
|
||||
@ -104,11 +105,12 @@ public class TradeInfo implements Payload {
|
||||
this.shortId = builder.getShortId();
|
||||
this.date = builder.getDate();
|
||||
this.role = builder.getRole();
|
||||
this.takerFee = builder.getTakerFee();
|
||||
this.makerDepositTxId = builder.getMakerDepositTxId();
|
||||
this.takerDepositTxId = builder.getTakerDepositTxId();
|
||||
this.payoutTxId = builder.getPayoutTxId();
|
||||
this.amount = builder.getAmount();
|
||||
this.makerFee = builder.getMakerFee();
|
||||
this.takerFee = builder.getTakerFee();
|
||||
this.buyerSecurityDeposit = builder.getBuyerSecurityDeposit();
|
||||
this.sellerSecurityDeposit = builder.getSellerSecurityDeposit();
|
||||
this.buyerDepositTxFee = builder.getBuyerDepositTxFee();
|
||||
@ -166,11 +168,12 @@ public class TradeInfo implements Payload {
|
||||
.withShortId(trade.getShortId())
|
||||
.withDate(trade.getDate().getTime())
|
||||
.withRole(role == null ? "" : role)
|
||||
.withTakerFee(trade.getTakerFee().longValueExact())
|
||||
.withMakerDepositTxId(trade.getMaker().getDepositTxHash())
|
||||
.withTakerDepositTxId(trade.getTaker().getDepositTxHash())
|
||||
.withPayoutTxId(trade.getPayoutTxId())
|
||||
.withAmount(trade.getAmount().longValueExact())
|
||||
.withMakerFee(trade.getMakerFee().longValueExact())
|
||||
.withTakerFee(trade.getTakerFee().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())
|
||||
@ -216,11 +219,12 @@ public class TradeInfo implements Payload {
|
||||
.setShortId(shortId)
|
||||
.setDate(date)
|
||||
.setRole(role)
|
||||
.setTakerFee(takerFee)
|
||||
.setMakerDepositTxId(makerDepositTxId == null ? "" : makerDepositTxId)
|
||||
.setTakerDepositTxId(takerDepositTxId == null ? "" : takerDepositTxId)
|
||||
.setPayoutTxId(payoutTxId == null ? "" : payoutTxId)
|
||||
.setAmount(amount)
|
||||
.setMakerFee(makerFee)
|
||||
.setTakerFee(takerFee)
|
||||
.setBuyerSecurityDeposit(buyerSecurityDeposit)
|
||||
.setSellerSecurityDeposit(sellerSecurityDeposit)
|
||||
.setBuyerDepositTxFee(buyerDepositTxFee)
|
||||
@ -259,11 +263,12 @@ public class TradeInfo implements Payload {
|
||||
.withShortId(proto.getShortId())
|
||||
.withDate(proto.getDate())
|
||||
.withRole(proto.getRole())
|
||||
.withTakerFee(proto.getTakerFee())
|
||||
.withMakerDepositTxId(proto.getMakerDepositTxId())
|
||||
.withTakerDepositTxId(proto.getTakerDepositTxId())
|
||||
.withPayoutTxId(proto.getPayoutTxId())
|
||||
.withAmount(proto.getAmount())
|
||||
.withMakerFee(proto.getMakerFee())
|
||||
.withTakerFee(proto.getTakerFee())
|
||||
.withBuyerSecurityDeposit(proto.getBuyerSecurityDeposit())
|
||||
.withSellerSecurityDeposit(proto.getSellerSecurityDeposit())
|
||||
.withBuyerDepositTxFee(proto.getBuyerDepositTxFee())
|
||||
@ -302,11 +307,12 @@ public class TradeInfo implements Payload {
|
||||
", shortId='" + shortId + '\'' + "\n" +
|
||||
", date='" + date + '\'' + "\n" +
|
||||
", role='" + role + '\'' + "\n" +
|
||||
", takerFee='" + takerFee + '\'' + "\n" +
|
||||
", makerDepositTxId='" + makerDepositTxId + '\'' + "\n" +
|
||||
", takerDepositTxId='" + takerDepositTxId + '\'' + "\n" +
|
||||
", payoutTxId='" + payoutTxId + '\'' + "\n" +
|
||||
", amount='" + amount + '\'' + "\n" +
|
||||
", makerFee='" + makerFee + '\'' + "\n" +
|
||||
", takerFee='" + takerFee + '\'' + "\n" +
|
||||
", buyerSecurityDeposit='" + buyerSecurityDeposit + '\'' + "\n" +
|
||||
", sellerSecurityDeposit='" + sellerSecurityDeposit + '\'' + "\n" +
|
||||
", buyerDepositTxFee='" + buyerDepositTxFee + '\'' + "\n" +
|
||||
|
@ -38,7 +38,9 @@ public final class OfferInfoBuilder {
|
||||
private long minAmount;
|
||||
private String volume;
|
||||
private String minVolume;
|
||||
private long makerFee;
|
||||
private double makerFeePct;
|
||||
private double takerFeePct;
|
||||
private double penaltyFeePct;
|
||||
private double buyerSecurityDepositPct;
|
||||
private double sellerSecurityDepositPct;
|
||||
private String triggerPrice;
|
||||
@ -97,18 +99,18 @@ public final class OfferInfoBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public OfferInfoBuilder withVolume(String volume) {
|
||||
this.volume = volume;
|
||||
public OfferInfoBuilder withMakerFeePct(double makerFeePct) {
|
||||
this.makerFeePct = makerFeePct;
|
||||
return this;
|
||||
}
|
||||
|
||||
public OfferInfoBuilder withMinVolume(String minVolume) {
|
||||
this.minVolume = minVolume;
|
||||
public OfferInfoBuilder withTakerFeePct(double takerFeePct) {
|
||||
this.takerFeePct = takerFeePct;
|
||||
return this;
|
||||
}
|
||||
|
||||
public OfferInfoBuilder withMakerFee(long makerFee) {
|
||||
this.makerFee = makerFee;
|
||||
public OfferInfoBuilder withPenaltyFeePct(double penaltyFeePct) {
|
||||
this.penaltyFeePct = penaltyFeePct;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -122,6 +124,16 @@ public final class OfferInfoBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public OfferInfoBuilder withVolume(String volume) {
|
||||
this.volume = volume;
|
||||
return this;
|
||||
}
|
||||
|
||||
public OfferInfoBuilder withMinVolume(String minVolume) {
|
||||
this.minVolume = minVolume;
|
||||
return this;
|
||||
}
|
||||
|
||||
public OfferInfoBuilder withTriggerPrice(String triggerPrice) {
|
||||
this.triggerPrice = triggerPrice;
|
||||
return this;
|
||||
|
@ -38,6 +38,7 @@ public final class TradeInfoV1Builder {
|
||||
private String role;
|
||||
private boolean isCurrencyForTakerFeeBtc;
|
||||
private long totalTxFee;
|
||||
private long makerFee;
|
||||
private long takerFee;
|
||||
private long buyerSecurityDeposit;
|
||||
private long sellerSecurityDeposit;
|
||||
@ -108,6 +109,11 @@ public final class TradeInfoV1Builder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public TradeInfoV1Builder withMakerFee(long makerFee) {
|
||||
this.makerFee = makerFee;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TradeInfoV1Builder withTakerFee(long takerFee) {
|
||||
this.takerFee = takerFee;
|
||||
return this;
|
||||
|
@ -160,7 +160,6 @@ public class CreateOfferService {
|
||||
List<String> acceptedCountryCodes = PaymentAccountUtil.getAcceptedCountryCodes(paymentAccount);
|
||||
String bankId = PaymentAccountUtil.getBankId(paymentAccount);
|
||||
List<String> acceptedBanks = PaymentAccountUtil.getAcceptedBanks(paymentAccount);
|
||||
BigInteger makerFee = HavenoUtils.getMakerFee(amount);
|
||||
long maxTradePeriod = paymentAccount.getMaxTradePeriod();
|
||||
|
||||
// reserved for future use cases
|
||||
@ -178,8 +177,7 @@ public class CreateOfferService {
|
||||
offerUtil.validateOfferData(
|
||||
securityDepositAsDouble,
|
||||
paymentAccount,
|
||||
currencyCode,
|
||||
makerFee);
|
||||
currencyCode);
|
||||
|
||||
OfferPayload offerPayload = new OfferPayload(offerId,
|
||||
creationTime,
|
||||
@ -191,6 +189,11 @@ public class CreateOfferService {
|
||||
useMarketBasedPriceValue,
|
||||
amountAsLong,
|
||||
minAmountAsLong,
|
||||
HavenoUtils.MAKER_FEE_PCT,
|
||||
HavenoUtils.TAKER_FEE_PCT,
|
||||
HavenoUtils.PENALTY_FEE_PCT,
|
||||
securityDepositAsDouble,
|
||||
securityDepositAsDouble,
|
||||
baseCurrencyCode,
|
||||
counterCurrencyCode,
|
||||
paymentAccount.getPaymentMethod().getId(),
|
||||
@ -201,9 +204,6 @@ public class CreateOfferService {
|
||||
acceptedBanks,
|
||||
Version.VERSION,
|
||||
xmrWalletService.getWallet().getHeight(),
|
||||
makerFee.longValueExact(),
|
||||
securityDepositAsDouble,
|
||||
securityDepositAsDouble,
|
||||
maxTradeLimit,
|
||||
maxTradePeriod,
|
||||
useAutoClose,
|
||||
|
@ -39,6 +39,7 @@ import haveno.core.offer.availability.OfferAvailabilityProtocol;
|
||||
import haveno.core.payment.payload.PaymentMethod;
|
||||
import haveno.core.provider.price.MarketPrice;
|
||||
import haveno.core.provider.price.PriceFeedService;
|
||||
import haveno.core.trade.HavenoUtils;
|
||||
import haveno.core.util.VolumeUtil;
|
||||
import haveno.network.p2p.NodeAddress;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
@ -285,12 +286,12 @@ public class Offer implements NetworkPayload, PersistablePayload {
|
||||
public BigInteger getReserveAmount() {
|
||||
BigInteger reserveAmount = getDirection() == OfferDirection.BUY ? getMaxBuyerSecurityDeposit() : getMaxSellerSecurityDeposit();
|
||||
if (getDirection() == OfferDirection.SELL) reserveAmount = reserveAmount.add(getAmount());
|
||||
reserveAmount = reserveAmount.add(getMakerFee());
|
||||
reserveAmount = reserveAmount.add(getMaxMakerFee());
|
||||
return reserveAmount;
|
||||
}
|
||||
|
||||
public BigInteger getMakerFee() {
|
||||
return BigInteger.valueOf(offerPayload.getMakerFee());
|
||||
public BigInteger getMaxMakerFee() {
|
||||
return offerPayload.getMaxMakerFee();
|
||||
}
|
||||
|
||||
public BigInteger getMaxBuyerSecurityDeposit() {
|
||||
@ -301,6 +302,26 @@ public class Offer implements NetworkPayload, PersistablePayload {
|
||||
return offerPayload.getMaxSellerSecurityDeposit();
|
||||
}
|
||||
|
||||
public double getMakerFeePct() {
|
||||
return offerPayload.getMakerFeePct();
|
||||
}
|
||||
|
||||
public double getTakerFeePct() {
|
||||
return offerPayload.getTakerFeePct();
|
||||
}
|
||||
|
||||
public double getPenaltyFeePct() {
|
||||
return offerPayload.getPenaltyFeePct();
|
||||
}
|
||||
|
||||
public BigInteger getMakerFee(BigInteger tradeAmount) {
|
||||
return HavenoUtils.multiply(tradeAmount, getMakerFeePct());
|
||||
}
|
||||
|
||||
public BigInteger getTakerFee(BigInteger tradeAmount) {
|
||||
return HavenoUtils.multiply(tradeAmount, getTakerFeePct());
|
||||
}
|
||||
|
||||
public double getBuyerSecurityDepositPct() {
|
||||
return offerPayload.getBuyerSecurityDepositPct();
|
||||
}
|
||||
|
@ -132,7 +132,9 @@ public final class OfferPayload implements ProtectedStoragePayload, ExpirablePay
|
||||
@Nullable
|
||||
private final List<String> acceptedBankIds;
|
||||
private final long blockHeightAtOfferCreation;
|
||||
private final long makerFee;
|
||||
private final double makerFeePct;
|
||||
private final double takerFeePct;
|
||||
private final double penaltyFeePct;
|
||||
private final double buyerSecurityDepositPct;
|
||||
private final double sellerSecurityDepositPct;
|
||||
private final long maxTradeLimit;
|
||||
@ -168,6 +170,11 @@ public final class OfferPayload implements ProtectedStoragePayload, ExpirablePay
|
||||
boolean useMarketBasedPrice,
|
||||
long amount,
|
||||
long minAmount,
|
||||
double makerFeePct,
|
||||
double takerFeePct,
|
||||
double penaltyFeePct,
|
||||
double buyerSecurityDepositPct,
|
||||
double sellerSecurityDepositPct,
|
||||
String baseCurrencyCode,
|
||||
String counterCurrencyCode,
|
||||
String paymentMethodId,
|
||||
@ -178,9 +185,6 @@ public final class OfferPayload implements ProtectedStoragePayload, ExpirablePay
|
||||
@Nullable List<String> acceptedBankIds,
|
||||
String versionNr,
|
||||
long blockHeightAtOfferCreation,
|
||||
long makerFee,
|
||||
double buyerSecurityDepositPct,
|
||||
double sellerSecurityDepositPct,
|
||||
long maxTradeLimit,
|
||||
long maxTradePeriod,
|
||||
boolean useAutoClose,
|
||||
@ -204,6 +208,11 @@ public final class OfferPayload implements ProtectedStoragePayload, ExpirablePay
|
||||
this.price = price;
|
||||
this.amount = amount;
|
||||
this.minAmount = minAmount;
|
||||
this.makerFeePct = makerFeePct;
|
||||
this.takerFeePct = takerFeePct;
|
||||
this.penaltyFeePct = penaltyFeePct;
|
||||
this.buyerSecurityDepositPct = buyerSecurityDepositPct;
|
||||
this.sellerSecurityDepositPct = sellerSecurityDepositPct;
|
||||
this.paymentMethodId = paymentMethodId;
|
||||
this.makerPaymentAccountId = makerPaymentAccountId;
|
||||
this.extraDataMap = extraDataMap;
|
||||
@ -219,9 +228,6 @@ public final class OfferPayload implements ProtectedStoragePayload, ExpirablePay
|
||||
this.bankId = bankId;
|
||||
this.acceptedBankIds = acceptedBankIds;
|
||||
this.blockHeightAtOfferCreation = blockHeightAtOfferCreation;
|
||||
this.makerFee = makerFee;
|
||||
this.buyerSecurityDepositPct = buyerSecurityDepositPct;
|
||||
this.sellerSecurityDepositPct = sellerSecurityDepositPct;
|
||||
this.maxTradeLimit = maxTradeLimit;
|
||||
this.maxTradePeriod = maxTradePeriod;
|
||||
this.useAutoClose = useAutoClose;
|
||||
@ -253,6 +259,11 @@ public final class OfferPayload implements ProtectedStoragePayload, ExpirablePay
|
||||
false,
|
||||
amount,
|
||||
minAmount,
|
||||
makerFeePct,
|
||||
takerFeePct,
|
||||
penaltyFeePct,
|
||||
buyerSecurityDepositPct,
|
||||
sellerSecurityDepositPct,
|
||||
baseCurrencyCode,
|
||||
counterCurrencyCode,
|
||||
paymentMethodId,
|
||||
@ -263,9 +274,6 @@ public final class OfferPayload implements ProtectedStoragePayload, ExpirablePay
|
||||
acceptedBankIds,
|
||||
versionNr,
|
||||
blockHeightAtOfferCreation,
|
||||
makerFee,
|
||||
buyerSecurityDepositPct,
|
||||
sellerSecurityDepositPct,
|
||||
maxTradeLimit,
|
||||
maxTradePeriod,
|
||||
useAutoClose,
|
||||
@ -303,6 +311,10 @@ public final class OfferPayload implements ProtectedStoragePayload, ExpirablePay
|
||||
return getBaseCurrencyCode().equals("XMR") ? getCounterCurrencyCode() : getBaseCurrencyCode();
|
||||
}
|
||||
|
||||
public BigInteger getMaxMakerFee() {
|
||||
return HavenoUtils.multiply(BigInteger.valueOf(getAmount()), getMakerFeePct());
|
||||
}
|
||||
|
||||
public BigInteger getMaxBuyerSecurityDeposit() {
|
||||
return getBuyerSecurityDepositForTradeAmount(BigInteger.valueOf(getAmount()));
|
||||
}
|
||||
@ -312,12 +324,12 @@ public final class OfferPayload implements ProtectedStoragePayload, ExpirablePay
|
||||
}
|
||||
|
||||
public BigInteger getBuyerSecurityDepositForTradeAmount(BigInteger tradeAmount) {
|
||||
BigInteger securityDepositUnadjusted = HavenoUtils.xmrToAtomicUnits(HavenoUtils.atomicUnitsToXmr(tradeAmount) * getBuyerSecurityDepositPct());
|
||||
BigInteger securityDepositUnadjusted = HavenoUtils.multiply(tradeAmount, getBuyerSecurityDepositPct());
|
||||
return Restrictions.getMinBuyerSecurityDeposit().max(securityDepositUnadjusted);
|
||||
}
|
||||
|
||||
public BigInteger getSellerSecurityDepositForTradeAmount(BigInteger tradeAmount) {
|
||||
BigInteger securityDepositUnadjusted = HavenoUtils.xmrToAtomicUnits(HavenoUtils.atomicUnitsToXmr(tradeAmount) * getSellerSecurityDepositPct());
|
||||
BigInteger securityDepositUnadjusted = HavenoUtils.multiply(tradeAmount, getSellerSecurityDepositPct());
|
||||
return Restrictions.getMinSellerSecurityDeposit().max(securityDepositUnadjusted);
|
||||
}
|
||||
|
||||
@ -337,15 +349,17 @@ public final class OfferPayload implements ProtectedStoragePayload, ExpirablePay
|
||||
.setUseMarketBasedPrice(useMarketBasedPrice)
|
||||
.setAmount(amount)
|
||||
.setMinAmount(minAmount)
|
||||
.setMakerFeePct(makerFeePct)
|
||||
.setTakerFeePct(takerFeePct)
|
||||
.setPenaltyFeePct(penaltyFeePct)
|
||||
.setBuyerSecurityDepositPct(buyerSecurityDepositPct)
|
||||
.setSellerSecurityDepositPct(sellerSecurityDepositPct)
|
||||
.setBaseCurrencyCode(baseCurrencyCode)
|
||||
.setCounterCurrencyCode(counterCurrencyCode)
|
||||
.setPaymentMethodId(paymentMethodId)
|
||||
.setMakerPaymentAccountId(makerPaymentAccountId)
|
||||
.setVersionNr(versionNr)
|
||||
.setBlockHeightAtOfferCreation(blockHeightAtOfferCreation)
|
||||
.setMakerFee(makerFee)
|
||||
.setBuyerSecurityDepositPct(buyerSecurityDepositPct)
|
||||
.setSellerSecurityDepositPct(sellerSecurityDepositPct)
|
||||
.setMaxTradeLimit(maxTradeLimit)
|
||||
.setMaxTradePeriod(maxTradePeriod)
|
||||
.setUseAutoClose(useAutoClose)
|
||||
@ -387,6 +401,11 @@ public final class OfferPayload implements ProtectedStoragePayload, ExpirablePay
|
||||
proto.getUseMarketBasedPrice(),
|
||||
proto.getAmount(),
|
||||
proto.getMinAmount(),
|
||||
proto.getMakerFeePct(),
|
||||
proto.getTakerFeePct(),
|
||||
proto.getPenaltyFeePct(),
|
||||
proto.getBuyerSecurityDepositPct(),
|
||||
proto.getSellerSecurityDepositPct(),
|
||||
proto.getBaseCurrencyCode(),
|
||||
proto.getCounterCurrencyCode(),
|
||||
proto.getPaymentMethodId(),
|
||||
@ -397,9 +416,6 @@ public final class OfferPayload implements ProtectedStoragePayload, ExpirablePay
|
||||
acceptedBankIds,
|
||||
proto.getVersionNr(),
|
||||
proto.getBlockHeightAtOfferCreation(),
|
||||
proto.getMakerFee(),
|
||||
proto.getBuyerSecurityDepositPct(),
|
||||
proto.getSellerSecurityDepositPct(),
|
||||
proto.getMaxTradeLimit(),
|
||||
proto.getMaxTradePeriod(),
|
||||
proto.getUseAutoClose(),
|
||||
@ -425,6 +441,11 @@ public final class OfferPayload implements ProtectedStoragePayload, ExpirablePay
|
||||
",\r\n price=" + price +
|
||||
",\r\n amount=" + amount +
|
||||
",\r\n minAmount=" + minAmount +
|
||||
",\r\n makerFeePct=" + makerFeePct +
|
||||
",\r\n takerFeePct=" + takerFeePct +
|
||||
",\r\n penaltyFeePct=" + penaltyFeePct +
|
||||
",\r\n buyerSecurityDepositPct=" + buyerSecurityDepositPct +
|
||||
",\r\n sellerSecurityDeposiPct=" + sellerSecurityDepositPct +
|
||||
",\r\n paymentMethodId='" + paymentMethodId + '\'' +
|
||||
",\r\n makerPaymentAccountId='" + makerPaymentAccountId + '\'' +
|
||||
",\r\n ownerNodeAddress=" + ownerNodeAddress +
|
||||
@ -442,9 +463,6 @@ public final class OfferPayload implements ProtectedStoragePayload, ExpirablePay
|
||||
",\r\n bankId='" + bankId + '\'' +
|
||||
",\r\n acceptedBankIds=" + acceptedBankIds +
|
||||
",\r\n blockHeightAtOfferCreation=" + blockHeightAtOfferCreation +
|
||||
",\r\n makerFee=" + makerFee +
|
||||
",\r\n buyerSecurityDepositPct=" + buyerSecurityDepositPct +
|
||||
",\r\n sellerSecurityDeposiPct=" + sellerSecurityDepositPct +
|
||||
",\r\n maxTradeLimit=" + maxTradeLimit +
|
||||
",\r\n maxTradePeriod=" + maxTradePeriod +
|
||||
",\r\n useAutoClose=" + useAutoClose +
|
||||
@ -474,15 +492,17 @@ public final class OfferPayload implements ProtectedStoragePayload, ExpirablePay
|
||||
object.add("useMarketBasedPrice", context.serialize(offerPayload.isUseMarketBasedPrice()));
|
||||
object.add("amount", context.serialize(offerPayload.getAmount()));
|
||||
object.add("minAmount", context.serialize(offerPayload.getMinAmount()));
|
||||
object.add("makerFeePct", context.serialize(offerPayload.getMakerFeePct()));
|
||||
object.add("takerFeePct", context.serialize(offerPayload.getTakerFeePct()));
|
||||
object.add("penaltyFeePct", context.serialize(offerPayload.getPenaltyFeePct()));
|
||||
object.add("buyerSecurityDepositPct", context.serialize(offerPayload.getBuyerSecurityDepositPct()));
|
||||
object.add("sellerSecurityDepositPct", context.serialize(offerPayload.getSellerSecurityDepositPct()));
|
||||
object.add("baseCurrencyCode", context.serialize(offerPayload.getBaseCurrencyCode()));
|
||||
object.add("counterCurrencyCode", context.serialize(offerPayload.getCounterCurrencyCode()));
|
||||
object.add("paymentMethodId", context.serialize(offerPayload.getPaymentMethodId()));
|
||||
object.add("makerPaymentAccountId", context.serialize(offerPayload.getMakerPaymentAccountId()));
|
||||
object.add("versionNr", context.serialize(offerPayload.getVersionNr()));
|
||||
object.add("blockHeightAtOfferCreation", context.serialize(offerPayload.getBlockHeightAtOfferCreation()));
|
||||
object.add("makerFee", context.serialize(offerPayload.getMakerFee()));
|
||||
object.add("buyerSecurityDepositPct", context.serialize(offerPayload.getBuyerSecurityDepositPct()));
|
||||
object.add("sellerSecurityDepositPct", context.serialize(offerPayload.getSellerSecurityDepositPct()));
|
||||
object.add("maxTradeLimit", context.serialize(offerPayload.getMaxTradeLimit()));
|
||||
object.add("maxTradePeriod", context.serialize(offerPayload.getMaxTradePeriod()));
|
||||
object.add("useAutoClose", context.serialize(offerPayload.isUseAutoClose()));
|
||||
|
@ -211,9 +211,7 @@ public class OfferUtil {
|
||||
|
||||
public void validateOfferData(double buyerSecurityDeposit,
|
||||
PaymentAccount paymentAccount,
|
||||
String currencyCode,
|
||||
BigInteger makerFee) {
|
||||
checkNotNull(makerFee, "makerFee must not be null");
|
||||
String currencyCode) {
|
||||
checkNotNull(p2PService.getAddress(), "Address must not be null");
|
||||
checkArgument(buyerSecurityDeposit <= getMaxBuyerSecurityDepositAsPercent(),
|
||||
"securityDeposit must not exceed " +
|
||||
|
@ -538,7 +538,6 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
||||
boolean reserveExactAmount,
|
||||
TransactionResultHandler resultHandler,
|
||||
ErrorMessageHandler errorMessageHandler) {
|
||||
checkNotNull(offer.getMakerFee(), "makerFee must not be null");
|
||||
|
||||
// create open offer
|
||||
OpenOffer openOffer = new OpenOffer(offer, triggerPrice, reserveExactAmount);
|
||||
@ -1199,9 +1198,24 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
||||
|
||||
// verify maker's trade fee
|
||||
Offer offer = new Offer(request.getOfferPayload());
|
||||
BigInteger tradeFee = HavenoUtils.getMakerFee(offer.getAmount());
|
||||
if (!tradeFee.equals(offer.getMakerFee())) {
|
||||
errorMessage = "Wrong trade fee for offer " + request.offerId;
|
||||
if (offer.getMakerFeePct() != HavenoUtils.MAKER_FEE_PCT) {
|
||||
errorMessage = "Wrong maker fee for offer " + request.offerId;
|
||||
log.info(errorMessage);
|
||||
sendAckMessage(request.getClass(), peer, request.getPubKeyRing(), request.getOfferId(), request.getUid(), false, errorMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
// verify taker's trade fee
|
||||
if (offer.getTakerFeePct() != HavenoUtils.TAKER_FEE_PCT) {
|
||||
errorMessage = "Wrong taker fee for offer " + request.offerId;
|
||||
log.info(errorMessage);
|
||||
sendAckMessage(request.getClass(), peer, request.getPubKeyRing(), request.getOfferId(), request.getUid(), false, errorMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
// verify penalty fee
|
||||
if (offer.getPenaltyFeePct() != HavenoUtils.PENALTY_FEE_PCT) {
|
||||
errorMessage = "Wrong penalty fee for offer " + request.offerId;
|
||||
log.info(errorMessage);
|
||||
sendAckMessage(request.getClass(), peer, request.getPubKeyRing(), request.getOfferId(), request.getUid(), false, errorMessage);
|
||||
return;
|
||||
@ -1216,11 +1230,14 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
||||
}
|
||||
|
||||
// verify maker's reserve tx (double spend, trade fee, trade amount, mining fee)
|
||||
BigInteger penaltyFee = HavenoUtils.multiply(offer.getAmount(), HavenoUtils.PENALTY_FEE_PCT);
|
||||
BigInteger maxTradeFee = HavenoUtils.multiply(offer.getAmount(), HavenoUtils.MAKER_FEE_PCT);
|
||||
BigInteger sendAmount = offer.getDirection() == OfferDirection.BUY ? BigInteger.ZERO : offer.getAmount();
|
||||
BigInteger securityDeposit = offer.getDirection() == OfferDirection.BUY ? offer.getMaxBuyerSecurityDeposit() : offer.getMaxSellerSecurityDeposit();
|
||||
Tuple2<MoneroTx, BigInteger> txResult = xmrWalletService.verifyTradeTx(
|
||||
offer.getId(),
|
||||
tradeFee,
|
||||
penaltyFee,
|
||||
maxTradeFee,
|
||||
sendAmount,
|
||||
securityDeposit,
|
||||
request.getPayoutAddress(),
|
||||
@ -1240,7 +1257,7 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
||||
signedOfferPayload.getPubKeyRing().hashCode(), // trader id
|
||||
signedOfferPayload.getId(),
|
||||
offer.getAmount().longValueExact(),
|
||||
tradeFee.longValueExact(),
|
||||
maxTradeFee.longValueExact(),
|
||||
request.getReserveTxHash(),
|
||||
request.getReserveTxHex(),
|
||||
request.getReserveTxKeyImages(),
|
||||
@ -1549,6 +1566,11 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
||||
originalOfferPayload.isUseMarketBasedPrice(),
|
||||
originalOfferPayload.getAmount(),
|
||||
originalOfferPayload.getMinAmount(),
|
||||
originalOfferPayload.getMakerFeePct(),
|
||||
originalOfferPayload.getTakerFeePct(),
|
||||
originalOfferPayload.getPenaltyFeePct(),
|
||||
originalOfferPayload.getBuyerSecurityDepositPct(),
|
||||
originalOfferPayload.getSellerSecurityDepositPct(),
|
||||
originalOfferPayload.getBaseCurrencyCode(),
|
||||
originalOfferPayload.getCounterCurrencyCode(),
|
||||
originalOfferPayload.getPaymentMethodId(),
|
||||
@ -1559,9 +1581,6 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
||||
originalOfferPayload.getAcceptedBankIds(),
|
||||
originalOfferPayload.getVersionNr(),
|
||||
originalOfferPayload.getBlockHeightAtOfferCreation(),
|
||||
originalOfferPayload.getMakerFee(),
|
||||
originalOfferPayload.getBuyerSecurityDepositPct(),
|
||||
originalOfferPayload.getSellerSecurityDepositPct(),
|
||||
originalOfferPayload.getMaxTradeLimit(),
|
||||
originalOfferPayload.getMaxTradePeriod(),
|
||||
originalOfferPayload.isUseAutoClose(),
|
||||
|
@ -71,7 +71,6 @@ public class SendOfferAvailabilityRequest extends Task<OfferAvailabilityModel> {
|
||||
p2PService.getKeyRing().getPubKeyRing(),
|
||||
model.getTradeAmount().longValueExact(),
|
||||
price.getValue(),
|
||||
HavenoUtils.getTakerFee(model.getTradeAmount()).longValueExact(),
|
||||
user.getAccountId(),
|
||||
paymentAccountId,
|
||||
paymentMethodId,
|
||||
|
@ -22,6 +22,7 @@ import haveno.common.taskrunner.TaskRunner;
|
||||
import haveno.core.offer.Offer;
|
||||
import haveno.core.offer.OfferDirection;
|
||||
import haveno.core.offer.placeoffer.PlaceOfferModel;
|
||||
import haveno.core.trade.HavenoUtils;
|
||||
import haveno.core.xmr.model.XmrAddressEntry;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import monero.daemon.model.MoneroOutput;
|
||||
@ -50,13 +51,14 @@ public class MakerReserveOfferFunds extends Task<PlaceOfferModel> {
|
||||
model.getXmrWalletService().getConnectionService().verifyConnection();
|
||||
|
||||
// create reserve tx
|
||||
BigInteger makerFee = offer.getMakerFee();
|
||||
BigInteger penaltyFee = HavenoUtils.multiply(offer.getAmount(), offer.getPenaltyFeePct());
|
||||
BigInteger makerFee = offer.getMaxMakerFee();
|
||||
BigInteger sendAmount = offer.getDirection() == OfferDirection.BUY ? BigInteger.ZERO : offer.getAmount();
|
||||
BigInteger securityDeposit = offer.getDirection() == OfferDirection.BUY ? offer.getMaxBuyerSecurityDeposit() : offer.getMaxSellerSecurityDeposit();
|
||||
String returnAddress = model.getXmrWalletService().getOrCreateAddressEntry(offer.getId(), XmrAddressEntry.Context.TRADE_PAYOUT).getAddressString();
|
||||
XmrAddressEntry fundingEntry = model.getXmrWalletService().getAddressEntry(offer.getId(), XmrAddressEntry.Context.OFFER_FUNDING).orElse(null);
|
||||
Integer preferredSubaddressIndex = fundingEntry == null ? null : fundingEntry.getSubaddressIndex();
|
||||
MoneroTxWallet reserveTx = model.getXmrWalletService().createReserveTx(makerFee, sendAmount, securityDeposit, returnAddress, model.getOpenOffer().isReserveExactAmount(), preferredSubaddressIndex);
|
||||
MoneroTxWallet reserveTx = model.getXmrWalletService().createReserveTx(penaltyFee, makerFee, sendAmount, securityDeposit, returnAddress, model.getOpenOffer().isReserveExactAmount(), preferredSubaddressIndex);
|
||||
|
||||
// check for error in case creating reserve tx exceeded timeout // TODO: better way?
|
||||
if (!model.getXmrWalletService().getAddressEntry(offer.getId(), XmrAddressEntry.Context.TRADE_PAYOUT).isPresent()) {
|
||||
|
@ -44,11 +44,12 @@ public class ValidateOffer extends Task<PlaceOfferModel> {
|
||||
// Coins
|
||||
checkBINotNullOrZero(offer.getAmount(), "Amount");
|
||||
checkBINotNullOrZero(offer.getMinAmount(), "MinAmount");
|
||||
checkBINotNullOrZero(offer.getMakerFee(), "MakerFee");
|
||||
//checkCoinNotNullOrZero(offer.getTxFee(), "txFee"); // TODO: remove from data model
|
||||
checkBINotNullOrZero(offer.getMaxTradeLimit(), "MaxTradeLimit");
|
||||
if (offer.getBuyerSecurityDepositPct() <= 0) throw new IllegalArgumentException("Buyer security deposit must be positive but was " + offer.getBuyerSecurityDepositPct());
|
||||
if (offer.getSellerSecurityDepositPct() <= 0) throw new IllegalArgumentException("Seller security deposit must be positive but was " + offer.getSellerSecurityDepositPct());
|
||||
if (offer.getMakerFeePct() < 0) throw new IllegalArgumentException("Maker fee must be >= 0% but was " + offer.getMakerFeePct());
|
||||
if (offer.getTakerFeePct() < 0) throw new IllegalArgumentException("Taker fee must be >= 0% but was " + offer.getTakerFeePct());
|
||||
if (offer.getBuyerSecurityDepositPct() <= 0) throw new IllegalArgumentException("Buyer security deposit percent must be positive but was " + offer.getBuyerSecurityDepositPct());
|
||||
if (offer.getSellerSecurityDepositPct() <= 0) throw new IllegalArgumentException("Seller security deposit percent must be positive but was " + offer.getSellerSecurityDepositPct());
|
||||
|
||||
// We remove those checks to be more flexible with future changes.
|
||||
/*checkArgument(offer.getMakerFee().value >= FeeService.getMinMakerFee(offer.isCurrencyForMakerFeeBtc()).value,
|
||||
@ -84,7 +85,6 @@ public class ValidateOffer extends Task<PlaceOfferModel> {
|
||||
checkNotNull(offer.getPubKeyRing(), "pubKeyRing is null");
|
||||
checkNotNull(offer.getMinAmount(), "MinAmount is null");
|
||||
checkNotNull(offer.getPrice(), "Price is null");
|
||||
checkNotNull(offer.getMakerFee(), "MakerFee is null");
|
||||
checkNotNull(offer.getVersionNr(), "VersionNr is null");
|
||||
checkArgument(offer.getMaxTradePeriod() > 0,
|
||||
"maxTradePeriod must be positive. maxTradePeriod=" + offer.getMaxTradePeriod());
|
||||
@ -136,6 +136,6 @@ public class ValidateOffer extends Task<PlaceOfferModel> {
|
||||
}
|
||||
|
||||
public static void checkTradeId(String tradeId, TradeMessage tradeMessage) {
|
||||
checkArgument(tradeId.equals(tradeMessage.getTradeId()));
|
||||
checkArgument(tradeId.equals(tradeMessage.getOfferId()));
|
||||
}
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ public class TakeOfferModel implements Model {
|
||||
this.securityDeposit = offer.getDirection() == SELL
|
||||
? offer.getOfferPayload().getBuyerSecurityDepositForTradeAmount(amount)
|
||||
: offer.getOfferPayload().getSellerSecurityDepositForTradeAmount(amount);
|
||||
this.takerFee = HavenoUtils.getTakerFee(amount);
|
||||
this.takerFee = HavenoUtils.multiply(amount, offer.getTakerFeePct());
|
||||
|
||||
calculateVolume();
|
||||
calculateTotalToPay();
|
||||
|
@ -36,7 +36,6 @@ public class ArbitratorTrade extends Trade {
|
||||
|
||||
public ArbitratorTrade(Offer offer,
|
||||
BigInteger tradeAmount,
|
||||
BigInteger takerFee,
|
||||
long tradePrice,
|
||||
XmrWalletService xmrWalletService,
|
||||
ProcessModel processModel,
|
||||
@ -44,7 +43,7 @@ public class ArbitratorTrade extends Trade {
|
||||
NodeAddress makerNodeAddress,
|
||||
NodeAddress takerNodeAddress,
|
||||
NodeAddress arbitratorNodeAddress) {
|
||||
super(offer, tradeAmount, takerFee, tradePrice, xmrWalletService, processModel, uid, makerNodeAddress, takerNodeAddress, arbitratorNodeAddress);
|
||||
super(offer, tradeAmount, tradePrice, xmrWalletService, processModel, uid, makerNodeAddress, takerNodeAddress, arbitratorNodeAddress);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -76,7 +75,6 @@ public class ArbitratorTrade extends Trade {
|
||||
return fromProto(new ArbitratorTrade(
|
||||
Offer.fromProto(proto.getOffer()),
|
||||
BigInteger.valueOf(proto.getAmount()),
|
||||
BigInteger.valueOf(proto.getTakerFee()),
|
||||
proto.getPrice(),
|
||||
xmrWalletService,
|
||||
processModel,
|
||||
|
@ -37,7 +37,6 @@ public final class BuyerAsMakerTrade extends BuyerTrade implements MakerTrade {
|
||||
|
||||
public BuyerAsMakerTrade(Offer offer,
|
||||
BigInteger tradeAmount,
|
||||
BigInteger takeOfferFee,
|
||||
long tradePrice,
|
||||
XmrWalletService xmrWalletService,
|
||||
ProcessModel processModel,
|
||||
@ -47,7 +46,6 @@ public final class BuyerAsMakerTrade extends BuyerTrade implements MakerTrade {
|
||||
NodeAddress arbitratorNodeAddress) {
|
||||
super(offer,
|
||||
tradeAmount,
|
||||
takeOfferFee,
|
||||
tradePrice,
|
||||
xmrWalletService,
|
||||
processModel,
|
||||
@ -81,7 +79,6 @@ public final class BuyerAsMakerTrade extends BuyerTrade implements MakerTrade {
|
||||
BuyerAsMakerTrade trade = new BuyerAsMakerTrade(
|
||||
Offer.fromProto(proto.getOffer()),
|
||||
BigInteger.valueOf(proto.getAmount()),
|
||||
BigInteger.valueOf(proto.getTakerFee()),
|
||||
proto.getPrice(),
|
||||
xmrWalletService,
|
||||
processModel,
|
||||
|
@ -38,7 +38,6 @@ public final class BuyerAsTakerTrade extends BuyerTrade implements TakerTrade {
|
||||
|
||||
public BuyerAsTakerTrade(Offer offer,
|
||||
BigInteger tradeAmount,
|
||||
BigInteger takerFee,
|
||||
long tradePrice,
|
||||
XmrWalletService xmrWalletService,
|
||||
ProcessModel processModel,
|
||||
@ -48,7 +47,6 @@ public final class BuyerAsTakerTrade extends BuyerTrade implements TakerTrade {
|
||||
@Nullable NodeAddress arbitratorNodeAddress) {
|
||||
super(offer,
|
||||
tradeAmount,
|
||||
takerFee,
|
||||
tradePrice,
|
||||
xmrWalletService,
|
||||
processModel,
|
||||
@ -83,7 +81,6 @@ public final class BuyerAsTakerTrade extends BuyerTrade implements TakerTrade {
|
||||
return fromProto(new BuyerAsTakerTrade(
|
||||
Offer.fromProto(proto.getOffer()),
|
||||
BigInteger.valueOf(proto.getAmount()),
|
||||
BigInteger.valueOf(proto.getTakerFee()),
|
||||
proto.getPrice(),
|
||||
xmrWalletService,
|
||||
processModel,
|
||||
|
@ -32,7 +32,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
||||
public abstract class BuyerTrade extends Trade {
|
||||
BuyerTrade(Offer offer,
|
||||
BigInteger tradeAmount,
|
||||
BigInteger takerFee,
|
||||
long tradePrice,
|
||||
XmrWalletService xmrWalletService,
|
||||
ProcessModel processModel,
|
||||
@ -42,7 +41,6 @@ public abstract class BuyerTrade extends Trade {
|
||||
@Nullable NodeAddress arbitratorNodeAddress) {
|
||||
super(offer,
|
||||
tradeAmount,
|
||||
takerFee,
|
||||
tradePrice,
|
||||
xmrWalletService,
|
||||
processModel,
|
||||
|
@ -106,7 +106,7 @@ public class CleanupMailboxMessages {
|
||||
}
|
||||
|
||||
private boolean isMyMessage(TradeMessage message, Trade trade) {
|
||||
return message.getTradeId().equals(trade.getId());
|
||||
return message.getOfferId().equals(trade.getId());
|
||||
}
|
||||
|
||||
private boolean isMyMessage(AckMessage ackMessage, Trade trade) {
|
||||
|
@ -105,7 +105,7 @@ public class CleanupMailboxMessagesService {
|
||||
}
|
||||
|
||||
private boolean isMyMessage(TradeMessage message, Trade trade) {
|
||||
return message.getTradeId().equals(trade.getId());
|
||||
return message.getOfferId().equals(trade.getId());
|
||||
}
|
||||
|
||||
private boolean isMyMessage(AckMessage ackMessage, Trade trade) {
|
||||
|
@ -34,11 +34,9 @@ import haveno.core.trade.messages.InitTradeRequest;
|
||||
import haveno.core.trade.messages.PaymentReceivedMessage;
|
||||
import haveno.core.trade.messages.PaymentSentMessage;
|
||||
import haveno.core.util.JsonUtil;
|
||||
import haveno.core.util.ParsingUtils;
|
||||
import haveno.network.p2p.NodeAddress;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.math.RoundingMode;
|
||||
import java.net.URI;
|
||||
import java.security.PrivateKey;
|
||||
import java.text.DecimalFormat;
|
||||
@ -48,7 +46,6 @@ import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import javax.annotation.Nullable;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import monero.common.MoneroRpcConnection;
|
||||
import monero.wallet.model.MoneroDestination;
|
||||
@ -62,12 +59,17 @@ import org.bitcoinj.core.Coin;
|
||||
@Slf4j
|
||||
public class HavenoUtils {
|
||||
|
||||
// configurable
|
||||
// configure release date
|
||||
private static final String RELEASE_DATE = "01-03-2024 00:00:00"; // optionally set to release date of the network in format dd-mm-yyyy to impose temporary limits, etc. e.g. "01-03-2024 00:00:00"
|
||||
public static final int RELEASE_LIMIT_DAYS = 60; // number of days to limit sell offers to max buy limit for new accounts
|
||||
public static final int WARN_ON_OFFER_EXCEEDS_UNSIGNED_BUY_LIMIT_DAYS = 182; // number of days to warn if sell offer exceeds unsigned buy limit
|
||||
public static final int ARBITRATOR_ACK_TIMEOUT_SECONDS = 15;
|
||||
|
||||
// configure fees
|
||||
public static final double MAKER_FEE_PCT = 0.0015; // 0.15%
|
||||
public static final double TAKER_FEE_PCT = 0.0075; // 0.75%
|
||||
public static final double PENALTY_FEE_PCT = 0.02; // 2%
|
||||
|
||||
// non-configurable
|
||||
public static final DecimalFormatSymbols DECIMAL_FORMAT_SYMBOLS = DecimalFormatSymbols.getInstance(Locale.US); // use the US locale as a base for all DecimalFormats (commas should be omitted from number strings)
|
||||
public static int XMR_SMALLEST_UNIT_EXPONENT = 12;
|
||||
@ -125,7 +127,7 @@ public class HavenoUtils {
|
||||
}
|
||||
|
||||
public static long atomicUnitsToCentineros(long atomicUnits) {
|
||||
return atomicUnits / CENTINEROS_AU_MULTIPLIER;
|
||||
return atomicUnitsToCentineros(BigInteger.valueOf(atomicUnits));
|
||||
}
|
||||
|
||||
public static long atomicUnitsToCentineros(BigInteger atomicUnits) {
|
||||
@ -149,7 +151,7 @@ public class HavenoUtils {
|
||||
}
|
||||
|
||||
public static BigInteger xmrToAtomicUnits(double xmr) {
|
||||
return BigDecimal.valueOf(xmr).setScale(8, RoundingMode.DOWN).multiply(new BigDecimal(XMR_AU_MULTIPLIER)).toBigInteger();
|
||||
return new BigDecimal(xmr).multiply(new BigDecimal(XMR_AU_MULTIPLIER)).toBigInteger();
|
||||
}
|
||||
|
||||
public static long xmrToCentineros(double xmr) {
|
||||
@ -161,7 +163,11 @@ public class HavenoUtils {
|
||||
}
|
||||
|
||||
public static double divide(BigInteger auDividend, BigInteger auDivisor) {
|
||||
return (double) atomicUnitsToCentineros(auDividend) / (double) atomicUnitsToCentineros(auDivisor);
|
||||
return atomicUnitsToXmr(auDividend) / atomicUnitsToXmr(auDivisor);
|
||||
}
|
||||
|
||||
public static BigInteger multiply(BigInteger amount1, double amount2) {
|
||||
return amount1 == null ? null : new BigDecimal(amount1).multiply(BigDecimal.valueOf(amount2)).toBigInteger();
|
||||
}
|
||||
|
||||
// ------------------------- FORMAT UTILS ---------------------------------
|
||||
@ -221,56 +227,12 @@ public class HavenoUtils {
|
||||
public static BigInteger parseXmr(String input) {
|
||||
if (input == null || input.length() == 0) return BigInteger.ZERO;
|
||||
try {
|
||||
return xmrToAtomicUnits(new BigDecimal(ParsingUtils.parseNumberStringToDouble(input)).doubleValue());
|
||||
return new BigDecimal(input).multiply(new BigDecimal(XMR_AU_MULTIPLIER)).toBigInteger();
|
||||
} catch (Exception e) {
|
||||
return BigInteger.ZERO;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------ FEE UTILS -------------------------------
|
||||
|
||||
@Nullable
|
||||
public static BigInteger getMakerFee(@Nullable BigInteger amount) {
|
||||
if (amount != null) {
|
||||
BigInteger feePerXmr = getFeePerXmr(HavenoUtils.getMakerFeePerXmr(), amount);
|
||||
return feePerXmr.max(HavenoUtils.getMinMakerFee());
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static BigInteger getTakerFee(@Nullable BigInteger amount) {
|
||||
if (amount != null) {
|
||||
BigInteger feePerXmr = HavenoUtils.getFeePerXmr(HavenoUtils.getTakerFeePerXmr(), amount);
|
||||
return feePerXmr.max(HavenoUtils.getMinTakerFee());
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static BigInteger getMakerFeePerXmr() {
|
||||
return HavenoUtils.xmrToAtomicUnits(0.0015);
|
||||
}
|
||||
|
||||
public static BigInteger getMinMakerFee() {
|
||||
return HavenoUtils.xmrToAtomicUnits(0.00005);
|
||||
}
|
||||
|
||||
private static BigInteger getTakerFeePerXmr() {
|
||||
return HavenoUtils.xmrToAtomicUnits(0.0075);
|
||||
}
|
||||
|
||||
public static BigInteger getMinTakerFee() {
|
||||
return HavenoUtils.xmrToAtomicUnits(0.00005);
|
||||
}
|
||||
|
||||
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.ZERO : amount, HavenoUtils.xmrToAtomicUnits(1.0)));
|
||||
return feePerXmrAsDecimal.multiply(amountMultiplier).toBigInteger();
|
||||
}
|
||||
|
||||
// ------------------------ SIGNING AND VERIFYING -------------------------
|
||||
|
||||
public static byte[] sign(KeyRing keyRing, String message) {
|
||||
@ -351,12 +313,11 @@ public class HavenoUtils {
|
||||
|
||||
// re-create trade request with signed fields
|
||||
InitTradeRequest signedRequest = new InitTradeRequest(
|
||||
request.getTradeId(),
|
||||
request.getOfferId(),
|
||||
request.getSenderNodeAddress(),
|
||||
request.getPubKeyRing(),
|
||||
request.getTradeAmount(),
|
||||
request.getTradePrice(),
|
||||
request.getTradeFee(),
|
||||
request.getAccountId(),
|
||||
request.getPaymentAccountId(),
|
||||
request.getPaymentMethodId(),
|
||||
@ -380,7 +341,7 @@ public class HavenoUtils {
|
||||
// verify maker signature
|
||||
boolean isSignatureValid = isSignatureValid(makerPubKeyRing, tradeRequestAsJson, signature);
|
||||
if (!isSignatureValid) {
|
||||
log.warn("Invalid maker signature for trade request: " + request.getTradeId() + " from " + request.getSenderNodeAddress().getAddressForDisplay());
|
||||
log.warn("Invalid maker signature for trade request: " + request.getOfferId() + " from " + request.getSenderNodeAddress().getAddressForDisplay());
|
||||
log.warn("Trade request as json: " + tradeRequestAsJson);
|
||||
log.warn("Maker pub key ring: " + (makerPubKeyRing == null ? null : "..."));
|
||||
log.warn("Maker signature: " + (signature == null ? null : Utilities.bytesAsHexString(signature)));
|
||||
@ -413,7 +374,7 @@ public class HavenoUtils {
|
||||
}
|
||||
|
||||
// verify trade id
|
||||
if (!trade.getId().equals(message.getTradeId())) throw new IllegalArgumentException("The " + message.getClass().getSimpleName() + " has the wrong trade id, expected " + trade.getId() + " but was " + message.getTradeId());
|
||||
if (!trade.getId().equals(message.getOfferId())) throw new IllegalArgumentException("The " + message.getClass().getSimpleName() + " has the wrong trade id, expected " + trade.getId() + " but was " + message.getOfferId());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -441,7 +402,7 @@ public class HavenoUtils {
|
||||
}
|
||||
|
||||
// verify trade id
|
||||
if (!trade.getId().equals(message.getTradeId())) throw new IllegalArgumentException("The " + message.getClass().getSimpleName() + " has the wrong trade id, expected " + trade.getId() + " but was " + message.getTradeId());
|
||||
if (!trade.getId().equals(message.getOfferId())) throw new IllegalArgumentException("The " + message.getClass().getSimpleName() + " has the wrong trade id, expected " + trade.getId() + " but was " + message.getOfferId());
|
||||
|
||||
// verify buyer signature of payment sent message
|
||||
if (message.getPaymentSentMessage() != null) verifyPaymentSentMessage(trade, message.getPaymentSentMessage());
|
||||
|
@ -38,7 +38,6 @@ public final class SellerAsMakerTrade extends SellerTrade implements MakerTrade
|
||||
|
||||
public SellerAsMakerTrade(Offer offer,
|
||||
BigInteger tradeAmount,
|
||||
BigInteger takerFee,
|
||||
long tradePrice,
|
||||
XmrWalletService xmrWalletService,
|
||||
ProcessModel processModel,
|
||||
@ -48,7 +47,6 @@ public final class SellerAsMakerTrade extends SellerTrade implements MakerTrade
|
||||
@Nullable NodeAddress arbitratorNodeAddress) {
|
||||
super(offer,
|
||||
tradeAmount,
|
||||
takerFee,
|
||||
tradePrice,
|
||||
xmrWalletService,
|
||||
processModel,
|
||||
@ -83,7 +81,6 @@ public final class SellerAsMakerTrade extends SellerTrade implements MakerTrade
|
||||
SellerAsMakerTrade trade = new SellerAsMakerTrade(
|
||||
Offer.fromProto(proto.getOffer()),
|
||||
BigInteger.valueOf(proto.getAmount()),
|
||||
BigInteger.valueOf(proto.getTakerFee()),
|
||||
proto.getPrice(),
|
||||
xmrWalletService,
|
||||
processModel,
|
||||
|
@ -38,7 +38,6 @@ public final class SellerAsTakerTrade extends SellerTrade implements TakerTrade
|
||||
|
||||
public SellerAsTakerTrade(Offer offer,
|
||||
BigInteger tradeAmount,
|
||||
BigInteger takerFee,
|
||||
long tradePrice,
|
||||
XmrWalletService xmrWalletService,
|
||||
ProcessModel processModel,
|
||||
@ -48,7 +47,6 @@ public final class SellerAsTakerTrade extends SellerTrade implements TakerTrade
|
||||
@Nullable NodeAddress arbitratorNodeAddress) {
|
||||
super(offer,
|
||||
tradeAmount,
|
||||
takerFee,
|
||||
tradePrice,
|
||||
xmrWalletService,
|
||||
processModel,
|
||||
@ -83,7 +81,6 @@ public final class SellerAsTakerTrade extends SellerTrade implements TakerTrade
|
||||
return fromProto(new SellerAsTakerTrade(
|
||||
Offer.fromProto(proto.getOffer()),
|
||||
BigInteger.valueOf(proto.getAmount()),
|
||||
BigInteger.valueOf(proto.getTakerFee()),
|
||||
proto.getPrice(),
|
||||
xmrWalletService,
|
||||
processModel,
|
||||
|
@ -30,7 +30,6 @@ import java.math.BigInteger;
|
||||
public abstract class SellerTrade extends Trade {
|
||||
SellerTrade(Offer offer,
|
||||
BigInteger tradeAmount,
|
||||
BigInteger takerFee,
|
||||
long tradePrice,
|
||||
XmrWalletService xmrWalletService,
|
||||
ProcessModel processModel,
|
||||
@ -40,7 +39,6 @@ public abstract class SellerTrade extends Trade {
|
||||
@Nullable NodeAddress arbitratorNodeAddress) {
|
||||
super(offer,
|
||||
tradeAmount,
|
||||
takerFee,
|
||||
tradePrice,
|
||||
xmrWalletService,
|
||||
processModel,
|
||||
|
@ -65,7 +65,7 @@ public interface Tradable extends PersistablePayload {
|
||||
}
|
||||
|
||||
default Optional<BigInteger> getOptionalMakerFee() {
|
||||
return asTradeModel().map(Trade::getOffer).map(Offer::getMakerFee).or(() -> Optional.ofNullable(getOffer().getMakerFee()));
|
||||
return asTradeModel().map(Trade::getMakerFee);
|
||||
}
|
||||
|
||||
default Optional<NodeAddress> getOptionalTradePeerNodeAddress() {
|
||||
|
@ -345,7 +345,6 @@ public abstract class Trade implements Tradable, Model {
|
||||
private final ProcessModel processModel;
|
||||
@Getter
|
||||
private final Offer offer;
|
||||
private final long takerFee;
|
||||
|
||||
// Added in 1.5.1
|
||||
@Getter
|
||||
@ -490,7 +489,6 @@ public abstract class Trade implements Tradable, Model {
|
||||
// maker
|
||||
protected Trade(Offer offer,
|
||||
BigInteger tradeAmount,
|
||||
BigInteger takerFee,
|
||||
long tradePrice,
|
||||
XmrWalletService xmrWalletService,
|
||||
ProcessModel processModel,
|
||||
@ -500,7 +498,6 @@ public abstract class Trade implements Tradable, Model {
|
||||
@Nullable NodeAddress arbitratorNodeAddress) {
|
||||
this.offer = offer;
|
||||
this.amount = tradeAmount.longValueExact();
|
||||
this.takerFee = takerFee.longValueExact();
|
||||
this.price = tradePrice;
|
||||
this.xmrWalletService = xmrWalletService;
|
||||
this.xmrConnectionService = xmrWalletService.getConnectionService();
|
||||
@ -523,7 +520,6 @@ public abstract class Trade implements Tradable, Model {
|
||||
protected Trade(Offer offer,
|
||||
BigInteger tradeAmount,
|
||||
BigInteger txFee,
|
||||
BigInteger takerFee,
|
||||
long tradePrice,
|
||||
@Nullable NodeAddress mediatorNodeAddress, // TODO (woodser): remove mediator, refund agent from trade
|
||||
@Nullable NodeAddress refundAgentNodeAddress,
|
||||
@ -536,7 +532,6 @@ public abstract class Trade implements Tradable, Model {
|
||||
|
||||
this(offer,
|
||||
tradeAmount,
|
||||
takerFee,
|
||||
tradePrice,
|
||||
xmrWalletService,
|
||||
processModel,
|
||||
@ -552,7 +547,6 @@ public abstract class Trade implements Tradable, Model {
|
||||
protected Trade(Offer offer,
|
||||
BigInteger tradeAmount,
|
||||
Coin txFee,
|
||||
BigInteger takerFee,
|
||||
long tradePrice,
|
||||
NodeAddress makerNodeAddress,
|
||||
NodeAddress takerNodeAddress,
|
||||
@ -563,7 +557,6 @@ public abstract class Trade implements Tradable, Model {
|
||||
|
||||
this(offer,
|
||||
tradeAmount,
|
||||
takerFee,
|
||||
tradePrice,
|
||||
xmrWalletService,
|
||||
processModel,
|
||||
@ -926,7 +919,6 @@ public abstract class Trade implements Tradable, Model {
|
||||
|
||||
private void forceCloseWallet() {
|
||||
if (wallet != null) {
|
||||
log.warn("Force closing wallet for {} {}", getClass().getSimpleName(), getId());
|
||||
xmrWalletService.forceCloseWallet(wallet, wallet.getPath());
|
||||
wallet = null;
|
||||
}
|
||||
@ -960,7 +952,7 @@ public abstract class Trade implements Tradable, Model {
|
||||
throw new IllegalStateException("Refusing to delete wallet for " + getClass().getSimpleName() + " " + getId() + " because it has a balance");
|
||||
}
|
||||
|
||||
// force close wallet
|
||||
// force close wallet without warning
|
||||
forceCloseWallet();
|
||||
|
||||
// delete wallet
|
||||
@ -1138,7 +1130,7 @@ public abstract class Trade implements Tradable, Model {
|
||||
|
||||
// verify fee is within tolerance by recreating payout tx
|
||||
// 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 = createPayoutTx();;
|
||||
MoneroTxWallet feeEstimateTx = createPayoutTx();
|
||||
BigInteger feeEstimate = feeEstimateTx.getFee();
|
||||
double feeDiff = payoutTx.getFee().subtract(feeEstimate).abs().doubleValue() / feeEstimate.doubleValue(); // TODO: use BigDecimal?
|
||||
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 " + payoutTx.getFee());
|
||||
@ -1912,11 +1904,11 @@ public abstract class Trade implements Tradable, Model {
|
||||
}
|
||||
|
||||
public BigInteger getMakerFee() {
|
||||
return offer.getMakerFee();
|
||||
return offer.getMakerFee(getAmount());
|
||||
}
|
||||
|
||||
public BigInteger getTakerFee() {
|
||||
return BigInteger.valueOf(takerFee);
|
||||
return offer.getTakerFee(getAmount());
|
||||
}
|
||||
|
||||
public BigInteger getBuyerSecurityDepositBeforeMiningFee() {
|
||||
@ -2308,7 +2300,6 @@ public abstract class Trade implements Tradable, Model {
|
||||
public Message toProtoMessage() {
|
||||
protobuf.Trade.Builder builder = protobuf.Trade.newBuilder()
|
||||
.setOffer(offer.toProtoMessage())
|
||||
.setTakerFee(takerFee)
|
||||
.setTakeOfferDate(takeOfferDate)
|
||||
.setProcessModel(processModel.toProtoMessage())
|
||||
.setAmount(amount)
|
||||
@ -2371,7 +2362,6 @@ public abstract class Trade implements Tradable, Model {
|
||||
public String toString() {
|
||||
return "Trade{" +
|
||||
"\n offer=" + offer +
|
||||
",\n takerFee=" + takerFee +
|
||||
",\n totalTxFee=" + getTotalTxFee() +
|
||||
",\n takeOfferDate=" + takeOfferDate +
|
||||
",\n processModel=" + processModel +
|
||||
@ -2389,7 +2379,6 @@ public abstract class Trade implements Tradable, Model {
|
||||
",\n counterCurrencyTxId='" + counterCurrencyTxId + '\'' +
|
||||
",\n counterCurrencyExtraData='" + counterCurrencyExtraData + '\'' +
|
||||
",\n chatMessages=" + chatMessages +
|
||||
",\n takerFee=" + takerFee +
|
||||
",\n xmrWalletService=" + xmrWalletService +
|
||||
",\n stateProperty=" + stateProperty +
|
||||
",\n statePhaseProperty=" + phaseProperty +
|
||||
|
@ -283,7 +283,7 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi
|
||||
public void onDirectMessage(DecryptedMessageWithPubKey message, NodeAddress peer) {
|
||||
NetworkEnvelope networkEnvelope = message.getNetworkEnvelope();
|
||||
if (!(networkEnvelope instanceof TradeMessage)) return;
|
||||
String tradeId = ((TradeMessage) networkEnvelope).getTradeId();
|
||||
String tradeId = ((TradeMessage) networkEnvelope).getOfferId();
|
||||
ThreadUtils.execute(() -> {
|
||||
if (networkEnvelope instanceof InitTradeRequest) {
|
||||
handleInitTradeRequest((InitTradeRequest) networkEnvelope, peer);
|
||||
@ -532,10 +532,10 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi
|
||||
}
|
||||
|
||||
private void handleInitTradeRequest(InitTradeRequest request, NodeAddress sender) {
|
||||
log.info("Received InitTradeRequest from {} with tradeId {} and uid {}", sender, request.getTradeId(), request.getUid());
|
||||
log.info("Received InitTradeRequest from {} with tradeId {} and uid {}", sender, request.getOfferId(), request.getUid());
|
||||
|
||||
try {
|
||||
Validator.nonEmptyStringOf(request.getTradeId());
|
||||
Validator.nonEmptyStringOf(request.getOfferId());
|
||||
} catch (Throwable t) {
|
||||
log.warn("Invalid InitTradeRequest message " + request.toString());
|
||||
return;
|
||||
@ -549,19 +549,19 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi
|
||||
Arbitrator thisArbitrator = user.getRegisteredArbitrator();
|
||||
NodeAddress thisAddress = p2PService.getNetworkNode().getNodeAddress();
|
||||
if (thisArbitrator == null || !thisArbitrator.getNodeAddress().equals(thisAddress)) {
|
||||
log.warn("Ignoring InitTradeRequest from {} with tradeId {} because we are not an arbitrator", sender, request.getTradeId());
|
||||
log.warn("Ignoring InitTradeRequest from {} with tradeId {} because we are not an arbitrator", sender, request.getOfferId());
|
||||
return;
|
||||
}
|
||||
|
||||
// get offer associated with trade
|
||||
Offer offer = null;
|
||||
for (Offer anOffer : offerBookService.getOffers()) {
|
||||
if (anOffer.getId().equals(request.getTradeId())) {
|
||||
if (anOffer.getId().equals(request.getOfferId())) {
|
||||
offer = anOffer;
|
||||
}
|
||||
}
|
||||
if (offer == null) {
|
||||
log.warn("Ignoring InitTradeRequest from {} with tradeId {} because offer is not on the books", sender, request.getTradeId());
|
||||
log.warn("Ignoring InitTradeRequest from {} with tradeId {} because offer is not on the books", sender, request.getOfferId());
|
||||
return;
|
||||
}
|
||||
|
||||
@ -571,7 +571,7 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi
|
||||
// verify maker is offer owner
|
||||
// TODO (woodser): maker address might change if they disconnect and reconnect, should allow maker address to differ if pubKeyRing is same?
|
||||
if (!offer.getOwnerNodeAddress().equals(request.getMakerNodeAddress())) {
|
||||
log.warn("Ignoring InitTradeRequest from {} with tradeId {} because maker is not offer owner", sender, request.getTradeId());
|
||||
log.warn("Ignoring InitTradeRequest from {} with tradeId {} because maker is not offer owner", sender, request.getOfferId());
|
||||
return;
|
||||
}
|
||||
|
||||
@ -585,7 +585,7 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi
|
||||
if (!sender.equals(request.getMakerNodeAddress())) {
|
||||
|
||||
// send nack if trade already taken
|
||||
String errMsg = "Trade is already taken, tradeId=" + request.getTradeId();
|
||||
String errMsg = "Trade is already taken, tradeId=" + request.getOfferId();
|
||||
log.warn(errMsg);
|
||||
sendAckMessage(sender, request.getPubKeyRing(), request, false, errMsg);
|
||||
return;
|
||||
@ -594,17 +594,13 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi
|
||||
|
||||
// verify request is from taker
|
||||
if (!sender.equals(request.getTakerNodeAddress())) {
|
||||
log.warn("Ignoring InitTradeRequest from {} with tradeId {} because request must be from taker when trade is not initialized", sender, request.getTradeId());
|
||||
log.warn("Ignoring InitTradeRequest from {} with tradeId {} because request must be from taker when trade is not initialized", sender, request.getOfferId());
|
||||
return;
|
||||
}
|
||||
|
||||
// get expected taker fee
|
||||
BigInteger takerFee = HavenoUtils.getTakerFee(BigInteger.valueOf(request.getTradeAmount()));
|
||||
|
||||
// create arbitrator trade
|
||||
trade = new ArbitratorTrade(offer,
|
||||
BigInteger.valueOf(request.getTradeAmount()),
|
||||
takerFee,
|
||||
offer.getOfferPayload().getPrice(),
|
||||
xmrWalletService,
|
||||
getNewProcessModel(offer),
|
||||
@ -614,7 +610,7 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi
|
||||
request.getArbitratorNodeAddress());
|
||||
|
||||
// set reserve tx hash if available
|
||||
Optional<SignedOffer> signedOfferOptional = openOfferManager.getSignedOfferById(request.getTradeId());
|
||||
Optional<SignedOffer> signedOfferOptional = openOfferManager.getSignedOfferById(request.getOfferId());
|
||||
if (signedOfferOptional.isPresent()) {
|
||||
SignedOffer signedOffer = signedOfferOptional.get();
|
||||
trade.getMaker().setReserveTxHash(signedOffer.getReserveTxHash());
|
||||
@ -637,7 +633,7 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi
|
||||
// handle request as maker
|
||||
else {
|
||||
|
||||
Optional<OpenOffer> openOfferOptional = openOfferManager.getOpenOfferById(request.getTradeId());
|
||||
Optional<OpenOffer> openOfferOptional = openOfferManager.getOpenOfferById(request.getOfferId());
|
||||
if (!openOfferOptional.isPresent()) {
|
||||
return;
|
||||
}
|
||||
@ -652,28 +648,24 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi
|
||||
// verify request is from arbitrator
|
||||
Arbitrator arbitrator = user.getAcceptedArbitratorByAddress(sender);
|
||||
if (arbitrator == null) {
|
||||
log.warn("Ignoring InitTradeRequest from {} with tradeId {} because request is not from accepted arbitrator", sender, request.getTradeId());
|
||||
log.warn("Ignoring InitTradeRequest from {} with tradeId {} because request is not from accepted arbitrator", sender, request.getOfferId());
|
||||
return;
|
||||
}
|
||||
|
||||
Optional<Trade> tradeOptional = getOpenTrade(request.getTradeId());
|
||||
Optional<Trade> tradeOptional = getOpenTrade(request.getOfferId());
|
||||
if (tradeOptional.isPresent()) {
|
||||
log.warn("Maker trade already exists with id " + request.getTradeId() + ". This should never happen.");
|
||||
log.warn("Maker trade already exists with id " + request.getOfferId() + ". This should never happen.");
|
||||
return;
|
||||
}
|
||||
|
||||
// reserve open offer
|
||||
openOfferManager.reserveOpenOffer(openOffer);
|
||||
|
||||
// get expected taker fee
|
||||
BigInteger takerFee = HavenoUtils.getTakerFee(BigInteger.valueOf(request.getTradeAmount()));
|
||||
|
||||
// initialize trade
|
||||
Trade trade;
|
||||
if (offer.isBuyOffer())
|
||||
trade = new BuyerAsMakerTrade(offer,
|
||||
BigInteger.valueOf(request.getTradeAmount()),
|
||||
takerFee,
|
||||
offer.getOfferPayload().getPrice(),
|
||||
xmrWalletService,
|
||||
getNewProcessModel(offer),
|
||||
@ -684,7 +676,6 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi
|
||||
else
|
||||
trade = new SellerAsMakerTrade(offer,
|
||||
BigInteger.valueOf(request.getTradeAmount()),
|
||||
takerFee,
|
||||
offer.getOfferPayload().getPrice(),
|
||||
xmrWalletService,
|
||||
getNewProcessModel(offer),
|
||||
@ -720,18 +711,18 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi
|
||||
}
|
||||
|
||||
private void handleInitMultisigRequest(InitMultisigRequest request, NodeAddress peer) {
|
||||
log.info("Received {} for trade {} from {} with uid {}", request.getClass().getSimpleName(), request.getTradeId(), peer, request.getUid());
|
||||
log.info("Received {} for trade {} from {} with uid {}", request.getClass().getSimpleName(), request.getOfferId(), peer, request.getUid());
|
||||
|
||||
try {
|
||||
Validator.nonEmptyStringOf(request.getTradeId());
|
||||
Validator.nonEmptyStringOf(request.getOfferId());
|
||||
} catch (Throwable t) {
|
||||
log.warn("Invalid InitMultisigRequest " + request.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
Optional<Trade> tradeOptional = getOpenTrade(request.getTradeId());
|
||||
Optional<Trade> tradeOptional = getOpenTrade(request.getOfferId());
|
||||
if (!tradeOptional.isPresent()) {
|
||||
log.warn("No trade with id " + request.getTradeId() + " at node " + P2PService.getMyNodeAddress());
|
||||
log.warn("No trade with id " + request.getOfferId() + " at node " + P2PService.getMyNodeAddress());
|
||||
return;
|
||||
}
|
||||
Trade trade = tradeOptional.get();
|
||||
@ -739,18 +730,18 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi
|
||||
}
|
||||
|
||||
private void handleSignContractRequest(SignContractRequest request, NodeAddress peer) {
|
||||
log.info("Received {} for trade {} from {} with uid {}", request.getClass().getSimpleName(), request.getTradeId(), peer, request.getUid());
|
||||
log.info("Received {} for trade {} from {} with uid {}", request.getClass().getSimpleName(), request.getOfferId(), peer, request.getUid());
|
||||
|
||||
try {
|
||||
Validator.nonEmptyStringOf(request.getTradeId());
|
||||
Validator.nonEmptyStringOf(request.getOfferId());
|
||||
} catch (Throwable t) {
|
||||
log.warn("Invalid SignContractRequest message " + request.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
Optional<Trade> tradeOptional = getOpenTrade(request.getTradeId());
|
||||
Optional<Trade> tradeOptional = getOpenTrade(request.getOfferId());
|
||||
if (!tradeOptional.isPresent()) {
|
||||
log.warn("No trade with id " + request.getTradeId());
|
||||
log.warn("No trade with id " + request.getOfferId());
|
||||
return;
|
||||
}
|
||||
Trade trade = tradeOptional.get();
|
||||
@ -758,18 +749,18 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi
|
||||
}
|
||||
|
||||
private void handleSignContractResponse(SignContractResponse request, NodeAddress peer) {
|
||||
log.info("Received {} for trade {} from {} with uid {}", request.getClass().getSimpleName(), request.getTradeId(), peer, request.getUid());
|
||||
log.info("Received {} for trade {} from {} with uid {}", request.getClass().getSimpleName(), request.getOfferId(), peer, request.getUid());
|
||||
|
||||
try {
|
||||
Validator.nonEmptyStringOf(request.getTradeId());
|
||||
Validator.nonEmptyStringOf(request.getOfferId());
|
||||
} catch (Throwable t) {
|
||||
log.warn("Invalid SignContractResponse message " + request.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
Optional<Trade> tradeOptional = getOpenTrade(request.getTradeId());
|
||||
Optional<Trade> tradeOptional = getOpenTrade(request.getOfferId());
|
||||
if (!tradeOptional.isPresent()) {
|
||||
log.warn("No trade with id " + request.getTradeId());
|
||||
log.warn("No trade with id " + request.getOfferId());
|
||||
return;
|
||||
}
|
||||
Trade trade = tradeOptional.get();
|
||||
@ -777,18 +768,18 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi
|
||||
}
|
||||
|
||||
private void handleDepositRequest(DepositRequest request, NodeAddress peer) {
|
||||
log.info("Received {} for trade {} from {} with uid {}", request.getClass().getSimpleName(), request.getTradeId(), peer, request.getUid());
|
||||
log.info("Received {} for trade {} from {} with uid {}", request.getClass().getSimpleName(), request.getOfferId(), peer, request.getUid());
|
||||
|
||||
try {
|
||||
Validator.nonEmptyStringOf(request.getTradeId());
|
||||
Validator.nonEmptyStringOf(request.getOfferId());
|
||||
} catch (Throwable t) {
|
||||
log.warn("Invalid DepositRequest message " + request.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
Optional<Trade> tradeOptional = getOpenTrade(request.getTradeId());
|
||||
Optional<Trade> tradeOptional = getOpenTrade(request.getOfferId());
|
||||
if (!tradeOptional.isPresent()) {
|
||||
log.warn("No trade with id " + request.getTradeId());
|
||||
log.warn("No trade with id " + request.getOfferId());
|
||||
return;
|
||||
}
|
||||
Trade trade = tradeOptional.get();
|
||||
@ -796,18 +787,18 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi
|
||||
}
|
||||
|
||||
private void handleDepositResponse(DepositResponse response, NodeAddress peer) {
|
||||
log.info("Received {} for trade {} from {} with uid {}", response.getClass().getSimpleName(), response.getTradeId(), peer, response.getUid());
|
||||
log.info("Received {} for trade {} from {} with uid {}", response.getClass().getSimpleName(), response.getOfferId(), peer, response.getUid());
|
||||
|
||||
try {
|
||||
Validator.nonEmptyStringOf(response.getTradeId());
|
||||
Validator.nonEmptyStringOf(response.getOfferId());
|
||||
} catch (Throwable t) {
|
||||
log.warn("Invalid DepositResponse message " + response.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
Optional<Trade> tradeOptional = getOpenTrade(response.getTradeId());
|
||||
Optional<Trade> tradeOptional = getOpenTrade(response.getOfferId());
|
||||
if (!tradeOptional.isPresent()) {
|
||||
log.warn("No trade with id " + response.getTradeId());
|
||||
log.warn("No trade with id " + response.getOfferId());
|
||||
return;
|
||||
}
|
||||
Trade trade = tradeOptional.get();
|
||||
@ -829,7 +820,6 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi
|
||||
|
||||
// First we check if offer is still available then we create the trade with the protocol
|
||||
public void onTakeOffer(BigInteger amount,
|
||||
BigInteger takerFee,
|
||||
BigInteger fundsNeededForTrade,
|
||||
Offer offer,
|
||||
String paymentAccountId,
|
||||
@ -852,7 +842,6 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi
|
||||
if (offer.isBuyOffer()) {
|
||||
trade = new SellerAsTakerTrade(offer,
|
||||
amount,
|
||||
takerFee,
|
||||
model.getTradeRequest().getTradePrice(),
|
||||
xmrWalletService,
|
||||
getNewProcessModel(offer),
|
||||
@ -863,7 +852,6 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi
|
||||
} else {
|
||||
trade = new BuyerAsTakerTrade(offer,
|
||||
amount,
|
||||
takerFee,
|
||||
model.getTradeRequest().getTradePrice(),
|
||||
xmrWalletService,
|
||||
getNewProcessModel(offer),
|
||||
@ -1139,7 +1127,7 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi
|
||||
public void sendAckMessage(NodeAddress peer, PubKeyRing peersPubKeyRing, TradeMessage message, boolean result, @Nullable String errorMessage) {
|
||||
|
||||
// create ack message
|
||||
String tradeId = message.getTradeId();
|
||||
String tradeId = message.getOfferId();
|
||||
String sourceUid = message.getUid();
|
||||
AckMessage ackMessage = new AckMessage(P2PService.getMyNodeAddress(),
|
||||
AckMessageSourceType.TRADE_MESSAGE,
|
||||
|
@ -62,7 +62,7 @@ public final class DepositRequest extends TradeMessage implements DirectMessage
|
||||
@Override
|
||||
public protobuf.NetworkEnvelope toProtoNetworkEnvelope() {
|
||||
protobuf.DepositRequest.Builder builder = protobuf.DepositRequest.newBuilder()
|
||||
.setTradeId(tradeId)
|
||||
.setTradeId(offerId)
|
||||
.setUid(uid)
|
||||
.setDepositTxHex(depositTxHex)
|
||||
.setDepositTxKey(depositTxKey);
|
||||
|
@ -55,7 +55,7 @@ public final class DepositResponse extends TradeMessage implements DirectMessage
|
||||
@Override
|
||||
public protobuf.NetworkEnvelope toProtoNetworkEnvelope() {
|
||||
protobuf.DepositResponse.Builder builder = protobuf.DepositResponse.newBuilder()
|
||||
.setTradeId(tradeId)
|
||||
.setTradeId(offerId)
|
||||
.setUid(uid);
|
||||
builder.setCurrentDate(currentDate);
|
||||
builder.setBuyerSecurityDeposit(buyerSecurityDeposit);
|
||||
|
@ -61,7 +61,7 @@ public final class DepositsConfirmedMessage extends TradeMailboxMessage {
|
||||
@Override
|
||||
public protobuf.NetworkEnvelope toProtoNetworkEnvelope() {
|
||||
protobuf.DepositsConfirmedMessage.Builder builder = protobuf.DepositsConfirmedMessage.newBuilder()
|
||||
.setTradeId(tradeId)
|
||||
.setTradeId(offerId)
|
||||
.setSenderNodeAddress(senderNodeAddress.toProtoMessage())
|
||||
.setPubKeyRing(pubKeyRing.toProtoMessage())
|
||||
.setUid(uid);
|
||||
|
@ -59,7 +59,7 @@ public final class InitMultisigRequest extends TradeMessage implements DirectMes
|
||||
@Override
|
||||
public protobuf.NetworkEnvelope toProtoNetworkEnvelope() {
|
||||
protobuf.InitMultisigRequest.Builder builder = protobuf.InitMultisigRequest.newBuilder()
|
||||
.setTradeId(tradeId)
|
||||
.setTradeId(offerId)
|
||||
.setUid(uid);
|
||||
|
||||
Optional.ofNullable(preparedMultisigHex).ifPresent(e -> builder.setPreparedMultisigHex(preparedMultisigHex));
|
||||
|
@ -36,7 +36,6 @@ public final class InitTradeRequest extends TradeMessage implements DirectMessag
|
||||
private final NodeAddress senderNodeAddress;
|
||||
private final long tradeAmount;
|
||||
private final long tradePrice;
|
||||
private final long tradeFee;
|
||||
private final String accountId;
|
||||
private final String paymentAccountId;
|
||||
private final String paymentMethodId;
|
||||
@ -63,12 +62,11 @@ public final class InitTradeRequest extends TradeMessage implements DirectMessag
|
||||
@Nullable
|
||||
private final byte[] makerSignature;
|
||||
|
||||
public InitTradeRequest(String tradeId,
|
||||
public InitTradeRequest(String offerId,
|
||||
NodeAddress senderNodeAddress,
|
||||
PubKeyRing pubKeyRing,
|
||||
long tradeAmount,
|
||||
long tradePrice,
|
||||
long tradeFee,
|
||||
String accountId,
|
||||
String paymentAccountId,
|
||||
String paymentMethodId,
|
||||
@ -84,12 +82,11 @@ public final class InitTradeRequest extends TradeMessage implements DirectMessag
|
||||
@Nullable String reserveTxKey,
|
||||
@Nullable String payoutAddress,
|
||||
@Nullable byte[] makerSignature) {
|
||||
super(messageVersion, tradeId, uid);
|
||||
super(messageVersion, offerId, uid);
|
||||
this.senderNodeAddress = senderNodeAddress;
|
||||
this.pubKeyRing = pubKeyRing;
|
||||
this.tradeAmount = tradeAmount;
|
||||
this.tradePrice = tradePrice;
|
||||
this.tradeFee = tradeFee;
|
||||
this.accountId = accountId;
|
||||
this.paymentAccountId = paymentAccountId;
|
||||
this.paymentMethodId = paymentMethodId;
|
||||
@ -113,13 +110,12 @@ public final class InitTradeRequest extends TradeMessage implements DirectMessag
|
||||
@Override
|
||||
public protobuf.NetworkEnvelope toProtoNetworkEnvelope() {
|
||||
protobuf.InitTradeRequest.Builder builder = protobuf.InitTradeRequest.newBuilder()
|
||||
.setTradeId(tradeId)
|
||||
.setOfferId(offerId)
|
||||
.setSenderNodeAddress(senderNodeAddress.toProtoMessage())
|
||||
.setTakerNodeAddress(takerNodeAddress.toProtoMessage())
|
||||
.setMakerNodeAddress(makerNodeAddress.toProtoMessage())
|
||||
.setTradeAmount(tradeAmount)
|
||||
.setTradePrice(tradePrice)
|
||||
.setTradeFee(tradeFee)
|
||||
.setPubKeyRing(pubKeyRing.toProtoMessage())
|
||||
.setPaymentAccountId(paymentAccountId)
|
||||
.setPaymentMethodId(paymentMethodId)
|
||||
@ -141,12 +137,11 @@ public final class InitTradeRequest extends TradeMessage implements DirectMessag
|
||||
public static InitTradeRequest fromProto(protobuf.InitTradeRequest proto,
|
||||
CoreProtoResolver coreProtoResolver,
|
||||
String messageVersion) {
|
||||
return new InitTradeRequest(proto.getTradeId(),
|
||||
return new InitTradeRequest(proto.getOfferId(),
|
||||
NodeAddress.fromProto(proto.getSenderNodeAddress()),
|
||||
PubKeyRing.fromProto(proto.getPubKeyRing()),
|
||||
proto.getTradeAmount(),
|
||||
proto.getTradePrice(),
|
||||
proto.getTradeFee(),
|
||||
proto.getAccountId(),
|
||||
proto.getPaymentAccountId(),
|
||||
proto.getPaymentMethodId(),
|
||||
@ -168,9 +163,9 @@ public final class InitTradeRequest extends TradeMessage implements DirectMessag
|
||||
public String toString() {
|
||||
return "InitTradeRequest{" +
|
||||
"\n senderNodeAddress=" + senderNodeAddress +
|
||||
",\n offerId=" + offerId +
|
||||
",\n tradeAmount=" + tradeAmount +
|
||||
",\n tradePrice=" + tradePrice +
|
||||
",\n tradeFee=" + tradeFee +
|
||||
",\n pubKeyRing=" + pubKeyRing +
|
||||
",\n accountId='" + accountId + '\'' +
|
||||
",\n paymentAccountId=" + paymentAccountId +
|
||||
|
@ -61,7 +61,7 @@ public final class MediatedPayoutTxPublishedMessage extends TradeMailboxMessage
|
||||
public protobuf.NetworkEnvelope toProtoNetworkEnvelope() {
|
||||
return getNetworkEnvelopeBuilder()
|
||||
.setMediatedPayoutTxPublishedMessage(protobuf.MediatedPayoutTxPublishedMessage.newBuilder()
|
||||
.setTradeId(tradeId)
|
||||
.setTradeId(offerId)
|
||||
.setPayoutTx(ByteString.copyFrom(payoutTx))
|
||||
.setSenderNodeAddress(senderNodeAddress.toProtoMessage())
|
||||
.setUid(uid))
|
||||
|
@ -63,7 +63,7 @@ public class MediatedPayoutTxSignatureMessage extends TradeMailboxMessage {
|
||||
return getNetworkEnvelopeBuilder()
|
||||
.setMediatedPayoutTxSignatureMessage(protobuf.MediatedPayoutTxSignatureMessage.newBuilder()
|
||||
.setTxSignature(ByteString.copyFrom(txSignature))
|
||||
.setTradeId(tradeId)
|
||||
.setTradeId(offerId)
|
||||
.setSenderNodeAddress(senderNodeAddress.toProtoMessage())
|
||||
.setUid(uid))
|
||||
.build();
|
||||
@ -79,8 +79,8 @@ public class MediatedPayoutTxSignatureMessage extends TradeMailboxMessage {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTradeId() {
|
||||
return tradeId;
|
||||
public String getOfferId() {
|
||||
return offerId;
|
||||
}
|
||||
|
||||
|
||||
@ -88,7 +88,7 @@ public class MediatedPayoutTxSignatureMessage extends TradeMailboxMessage {
|
||||
public String toString() {
|
||||
return "MediatedPayoutSignatureMessage{" +
|
||||
"\n txSignature=" + Utilities.bytesAsHexString(txSignature) +
|
||||
",\n tradeId='" + tradeId + '\'' +
|
||||
",\n tradeId='" + offerId + '\'' +
|
||||
",\n senderNodeAddress=" + senderNodeAddress +
|
||||
"\n} " + super.toString();
|
||||
}
|
||||
|
@ -105,7 +105,7 @@ public final class PaymentReceivedMessage extends TradeMailboxMessage {
|
||||
@Override
|
||||
public protobuf.NetworkEnvelope toProtoNetworkEnvelope() {
|
||||
protobuf.PaymentReceivedMessage.Builder builder = protobuf.PaymentReceivedMessage.newBuilder()
|
||||
.setTradeId(tradeId)
|
||||
.setTradeId(offerId)
|
||||
.setSenderNodeAddress(senderNodeAddress.toProtoMessage())
|
||||
.setUid(uid)
|
||||
.setDeferPublishPayout(deferPublishPayout);
|
||||
|
@ -101,7 +101,7 @@ public final class PaymentSentMessage extends TradeMailboxMessage {
|
||||
@Override
|
||||
public protobuf.NetworkEnvelope toProtoNetworkEnvelope() {
|
||||
final protobuf.PaymentSentMessage.Builder builder = protobuf.PaymentSentMessage.newBuilder();
|
||||
builder.setTradeId(tradeId)
|
||||
builder.setTradeId(offerId)
|
||||
.setSenderNodeAddress(senderNodeAddress.toProtoMessage())
|
||||
.setUid(uid);
|
||||
|
||||
@ -141,7 +141,7 @@ public final class PaymentSentMessage extends TradeMailboxMessage {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PaymentSentMessage{" +
|
||||
",\n tradeId=" + tradeId +
|
||||
",\n tradeId=" + offerId +
|
||||
",\n uid='" + uid + '\'' +
|
||||
",\n senderNodeAddress=" + senderNodeAddress +
|
||||
",\n counterCurrencyTxId=" + counterCurrencyTxId +
|
||||
|
@ -64,7 +64,7 @@ public final class SignContractRequest extends TradeMessage implements DirectMes
|
||||
@Override
|
||||
public protobuf.NetworkEnvelope toProtoNetworkEnvelope() {
|
||||
protobuf.SignContractRequest.Builder builder = protobuf.SignContractRequest.newBuilder()
|
||||
.setTradeId(tradeId)
|
||||
.setTradeId(offerId)
|
||||
.setUid(uid)
|
||||
.setAccountId(accountId)
|
||||
.setPaymentAccountPayloadHash(ByteString.copyFrom(paymentAccountPayloadHash))
|
||||
|
@ -58,7 +58,7 @@ public final class SignContractResponse extends TradeMessage implements DirectMe
|
||||
@Override
|
||||
public protobuf.NetworkEnvelope toProtoNetworkEnvelope() {
|
||||
protobuf.SignContractResponse.Builder builder = protobuf.SignContractResponse.newBuilder()
|
||||
.setTradeId(tradeId)
|
||||
.setTradeId(offerId)
|
||||
.setUid(uid);
|
||||
|
||||
Optional.ofNullable(contractAsJson).ifPresent(e -> builder.setContractAsJson(contractAsJson));
|
||||
|
@ -27,12 +27,12 @@ import lombok.ToString;
|
||||
@Getter
|
||||
@ToString
|
||||
public abstract class TradeMessage extends NetworkEnvelope implements UidMessage {
|
||||
protected final String tradeId;
|
||||
protected final String offerId;
|
||||
protected final String uid;
|
||||
|
||||
protected TradeMessage(String messageVersion, String tradeId, String uid) {
|
||||
protected TradeMessage(String messageVersion, String offerId, String uid) {
|
||||
super(messageVersion);
|
||||
this.tradeId = tradeId;
|
||||
this.offerId = offerId;
|
||||
this.uid = uid;
|
||||
}
|
||||
}
|
||||
|
@ -109,7 +109,7 @@ public class ArbitratorProtocol extends DisputeProtocol {
|
||||
|
||||
@Override
|
||||
public void handleDepositResponse(DepositResponse response, NodeAddress sender) {
|
||||
log.warn("Arbitrator ignoring DepositResponse for trade " + response.getTradeId());
|
||||
log.warn("Arbitrator ignoring DepositResponse for trade " + response.getOfferId());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
@ -237,7 +237,7 @@ public class FluentProtocol {
|
||||
boolean isTradeIdValid = message == null || isTradeIdValid(trade.getId(), message);
|
||||
if (!isTradeIdValid) {
|
||||
String info = MessageFormat.format("TradeId does not match tradeId in message, TradeId={0}, tradeId in message={1}",
|
||||
trade.getId(), message.getTradeId());
|
||||
trade.getId(), message.getOfferId());
|
||||
result = Result.INVALID_TRADE_ID.info(info);
|
||||
return result;
|
||||
}
|
||||
|
@ -121,12 +121,12 @@ public abstract class TradeProtocol implements DecryptedDirectMessageListener, D
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
protected void onTradeMessage(TradeMessage message, NodeAddress peerNodeAddress) {
|
||||
log.info("Received {} as TradeMessage from {} with tradeId {} and uid {}", message.getClass().getSimpleName(), peerNodeAddress, message.getTradeId(), message.getUid());
|
||||
log.info("Received {} as TradeMessage from {} with tradeId {} and uid {}", message.getClass().getSimpleName(), peerNodeAddress, message.getOfferId(), message.getUid());
|
||||
ThreadUtils.execute(() -> handle(message, peerNodeAddress), trade.getId());
|
||||
}
|
||||
|
||||
protected void onMailboxMessage(TradeMessage message, NodeAddress peerNodeAddress) {
|
||||
log.info("Received {} as MailboxMessage from {} with tradeId {} and uid {}", message.getClass().getSimpleName(), peerNodeAddress, message.getTradeId(), message.getUid());
|
||||
log.info("Received {} as MailboxMessage from {} with tradeId {} and uid {}", message.getClass().getSimpleName(), peerNodeAddress, message.getOfferId(), message.getUid());
|
||||
ThreadUtils.execute(() -> handle(message, peerNodeAddress), trade.getId());
|
||||
}
|
||||
|
||||
@ -156,7 +156,7 @@ public abstract class TradeProtocol implements DecryptedDirectMessageListener, D
|
||||
|
||||
// notify trade listeners
|
||||
// TODO (woodser): better way to register message notifications for trade?
|
||||
if (((TradeMessage) networkEnvelope).getTradeId().equals(processModel.getOfferId())) {
|
||||
if (((TradeMessage) networkEnvelope).getOfferId().equals(processModel.getOfferId())) {
|
||||
trade.onVerifiedTradeMessage((TradeMessage) networkEnvelope, peer);
|
||||
}
|
||||
} else if (networkEnvelope instanceof AckMessage) {
|
||||
@ -862,7 +862,7 @@ public abstract class TradeProtocol implements DecryptedDirectMessageListener, D
|
||||
private boolean isMyMessage(NetworkEnvelope message) {
|
||||
if (message instanceof TradeMessage) {
|
||||
TradeMessage tradeMessage = (TradeMessage) message;
|
||||
return tradeMessage.getTradeId().equals(trade.getId());
|
||||
return tradeMessage.getOfferId().equals(trade.getId());
|
||||
} else if (message instanceof AckMessage) {
|
||||
AckMessage ackMessage = (AckMessage) message;
|
||||
return ackMessage.getSourceType() == AckMessageSourceType.TRADE_MESSAGE && ackMessage.getSourceId().equals(trade.getId());
|
||||
|
@ -89,6 +89,7 @@ public class ArbitratorProcessDepositRequest extends TradeTask {
|
||||
try {
|
||||
txResult = trade.getXmrWalletService().verifyTradeTx(
|
||||
offer.getId(),
|
||||
null,
|
||||
tradeFee,
|
||||
sendAmount,
|
||||
securityDeposit,
|
||||
|
@ -21,6 +21,7 @@ import haveno.common.taskrunner.TaskRunner;
|
||||
import haveno.common.util.Tuple2;
|
||||
import haveno.core.offer.Offer;
|
||||
import haveno.core.offer.OfferDirection;
|
||||
import haveno.core.trade.HavenoUtils;
|
||||
import haveno.core.trade.Trade;
|
||||
import haveno.core.trade.messages.InitTradeRequest;
|
||||
import haveno.core.trade.protocol.TradePeer;
|
||||
@ -54,13 +55,15 @@ public class ArbitratorProcessReserveTx extends TradeTask {
|
||||
// TODO (woodser): if signer online, should never be called by maker
|
||||
|
||||
// process reserve tx with expected values
|
||||
BigInteger tradeFee = isFromMaker ? trade.getMakerFee() : trade.getTakerFee();
|
||||
BigInteger penaltyFee = HavenoUtils.multiply(isFromMaker ? offer.getAmount() : trade.getAmount(), offer.getPenaltyFeePct());
|
||||
BigInteger tradeFee = isFromMaker ? offer.getMaxMakerFee() : trade.getTakerFee();
|
||||
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<MoneroTx, BigInteger> txResult;
|
||||
try {
|
||||
txResult = trade.getXmrWalletService().verifyTradeTx(
|
||||
offer.getId(),
|
||||
penaltyFee,
|
||||
tradeFee,
|
||||
sendAmount,
|
||||
securityDeposit,
|
||||
|
@ -60,7 +60,6 @@ public class ArbitratorSendInitTradeOrMultisigRequests extends TradeTask {
|
||||
request.getPubKeyRing(),
|
||||
trade.getAmount().longValueExact(),
|
||||
trade.getPrice().getValue(),
|
||||
trade.getTakerFee().longValueExact(),
|
||||
request.getAccountId(),
|
||||
request.getPaymentAccountId(),
|
||||
request.getPaymentMethodId(),
|
||||
@ -78,7 +77,7 @@ public class ArbitratorSendInitTradeOrMultisigRequests extends TradeTask {
|
||||
null);
|
||||
|
||||
// send request to maker
|
||||
log.info("Send {} with offerId {} and uid {} to maker {}", makerRequest.getClass().getSimpleName(), makerRequest.getTradeId(), makerRequest.getUid(), trade.getMaker().getNodeAddress());
|
||||
log.info("Send {} with offerId {} and uid {} to maker {}", makerRequest.getClass().getSimpleName(), makerRequest.getOfferId(), makerRequest.getUid(), trade.getMaker().getNodeAddress());
|
||||
processModel.getP2PService().sendEncryptedDirectMessage(
|
||||
trade.getMaker().getNodeAddress(), // TODO (woodser): maker's address might be different from original owner address if they disconnect and reconnect, need to validate and update address when requests received
|
||||
trade.getMaker().getPubKeyRing(),
|
||||
@ -86,7 +85,7 @@ public class ArbitratorSendInitTradeOrMultisigRequests extends TradeTask {
|
||||
new SendDirectMessageListener() {
|
||||
@Override
|
||||
public void onArrived() {
|
||||
log.info("{} arrived at maker: offerId={}; uid={}", makerRequest.getClass().getSimpleName(), makerRequest.getTradeId(), makerRequest.getUid());
|
||||
log.info("{} arrived at maker: offerId={}; uid={}", makerRequest.getClass().getSimpleName(), makerRequest.getOfferId(), makerRequest.getUid());
|
||||
complete();
|
||||
}
|
||||
@Override
|
||||
@ -136,7 +135,7 @@ public class ArbitratorSendInitTradeOrMultisigRequests extends TradeTask {
|
||||
null);
|
||||
|
||||
// send request to maker
|
||||
log.info("Send {} with offerId {} and uid {} to maker {}", initMultisigRequest.getClass().getSimpleName(), initMultisigRequest.getTradeId(), initMultisigRequest.getUid(), trade.getMaker().getNodeAddress());
|
||||
log.info("Send {} with offerId {} and uid {} to maker {}", initMultisigRequest.getClass().getSimpleName(), initMultisigRequest.getOfferId(), initMultisigRequest.getUid(), trade.getMaker().getNodeAddress());
|
||||
processModel.getP2PService().sendEncryptedDirectMessage(
|
||||
trade.getMaker().getNodeAddress(),
|
||||
trade.getMaker().getPubKeyRing(),
|
||||
@ -144,7 +143,7 @@ public class ArbitratorSendInitTradeOrMultisigRequests extends TradeTask {
|
||||
new SendDirectMessageListener() {
|
||||
@Override
|
||||
public void onArrived() {
|
||||
log.info("{} arrived at maker: offerId={}; uid={}", initMultisigRequest.getClass().getSimpleName(), initMultisigRequest.getTradeId(), initMultisigRequest.getUid());
|
||||
log.info("{} arrived at maker: offerId={}; uid={}", initMultisigRequest.getClass().getSimpleName(), initMultisigRequest.getOfferId(), initMultisigRequest.getUid());
|
||||
}
|
||||
@Override
|
||||
public void onFault(String errorMessage) {
|
||||
@ -154,7 +153,7 @@ public class ArbitratorSendInitTradeOrMultisigRequests extends TradeTask {
|
||||
);
|
||||
|
||||
// send request to taker
|
||||
log.info("Send {} with offerId {} and uid {} to taker {}", initMultisigRequest.getClass().getSimpleName(), initMultisigRequest.getTradeId(), initMultisigRequest.getUid(), trade.getTaker().getNodeAddress());
|
||||
log.info("Send {} with offerId {} and uid {} to taker {}", initMultisigRequest.getClass().getSimpleName(), initMultisigRequest.getOfferId(), initMultisigRequest.getUid(), trade.getTaker().getNodeAddress());
|
||||
processModel.getP2PService().sendEncryptedDirectMessage(
|
||||
trade.getTaker().getNodeAddress(),
|
||||
trade.getTaker().getPubKeyRing(),
|
||||
@ -162,7 +161,7 @@ public class ArbitratorSendInitTradeOrMultisigRequests extends TradeTask {
|
||||
new SendDirectMessageListener() {
|
||||
@Override
|
||||
public void onArrived() {
|
||||
log.info("{} arrived at taker: offerId={}; uid={}", initMultisigRequest.getClass().getSimpleName(), initMultisigRequest.getTradeId(), initMultisigRequest.getUid());
|
||||
log.info("{} arrived at taker: offerId={}; uid={}", initMultisigRequest.getClass().getSimpleName(), initMultisigRequest.getOfferId(), initMultisigRequest.getUid());
|
||||
}
|
||||
@Override
|
||||
public void onFault(String errorMessage) {
|
||||
|
@ -57,7 +57,6 @@ public class MakerSendInitTradeRequest extends TradeTask {
|
||||
processModel.getPubKeyRing(),
|
||||
trade.getAmount().longValueExact(),
|
||||
trade.getPrice().getValue(),
|
||||
offer.getMakerFee().longValueExact(),
|
||||
trade.getProcessModel().getAccountId(),
|
||||
offer.getMakerPaymentAccountId(),
|
||||
offer.getOfferPayload().getPaymentMethodId(),
|
||||
@ -75,7 +74,7 @@ public class MakerSendInitTradeRequest extends TradeTask {
|
||||
null);
|
||||
|
||||
// send request to arbitrator
|
||||
log.info("Sending {} with offerId {} and uid {} to arbitrator {}", arbitratorRequest.getClass().getSimpleName(), arbitratorRequest.getTradeId(), arbitratorRequest.getUid(), trade.getArbitrator().getNodeAddress());
|
||||
log.info("Sending {} with offerId {} and uid {} to arbitrator {}", arbitratorRequest.getClass().getSimpleName(), arbitratorRequest.getOfferId(), arbitratorRequest.getUid(), trade.getArbitrator().getNodeAddress());
|
||||
processModel.getP2PService().sendEncryptedDirectMessage(
|
||||
trade.getArbitrator().getNodeAddress(),
|
||||
trade.getArbitrator().getPubKeyRing(),
|
||||
|
@ -150,7 +150,7 @@ public class ProcessInitMultisigRequest extends TradeTask {
|
||||
sendInitMultisigRequest(peer1Address, peer1PubKeyRing, new SendDirectMessageListener() {
|
||||
@Override
|
||||
public void onArrived() {
|
||||
log.info("{} arrived: peer={}; offerId={}; uid={}", request.getClass().getSimpleName(), peer1Address, request.getTradeId(), request.getUid());
|
||||
log.info("{} arrived: peer={}; offerId={}; uid={}", request.getClass().getSimpleName(), peer1Address, request.getOfferId(), request.getUid());
|
||||
ack1 = true;
|
||||
if (ack1 && ack2) completeAux();
|
||||
}
|
||||
@ -166,7 +166,7 @@ public class ProcessInitMultisigRequest extends TradeTask {
|
||||
sendInitMultisigRequest(peer2Address, peer2PubKeyRing, new SendDirectMessageListener() {
|
||||
@Override
|
||||
public void onArrived() {
|
||||
log.info("{} arrived: peer={}; offerId={}; uid={}", request.getClass().getSimpleName(), peer2Address, request.getTradeId(), request.getUid());
|
||||
log.info("{} arrived: peer={}; offerId={}; uid={}", request.getClass().getSimpleName(), peer2Address, request.getOfferId(), request.getUid());
|
||||
ack2 = true;
|
||||
if (ack1 && ack2) completeAux();
|
||||
}
|
||||
@ -212,7 +212,7 @@ public class ProcessInitMultisigRequest extends TradeTask {
|
||||
trade.getSelf().getMadeMultisigHex(),
|
||||
trade.getSelf().getExchangedMultisigHex());
|
||||
|
||||
log.info("Send {} with offerId {} and uid {} to peer {}", request.getClass().getSimpleName(), request.getTradeId(), request.getUid(), recipient);
|
||||
log.info("Send {} with offerId {} and uid {} to peer {}", request.getClass().getSimpleName(), request.getOfferId(), request.getUid(), recipient);
|
||||
processModel.getP2PService().sendEncryptedDirectMessage(recipient, pubKeyRing, request, listener);
|
||||
}
|
||||
|
||||
|
@ -69,20 +69,20 @@ public abstract class SendMailboxMessageTask extends TradeTask {
|
||||
new SendMailboxMessageListener() {
|
||||
@Override
|
||||
public void onArrived() {
|
||||
log.info("{} arrived at peer {}. tradeId={}, uid={}", message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid());
|
||||
log.info("{} arrived at peer {}. tradeId={}, uid={}", message.getClass().getSimpleName(), peersNodeAddress, message.getOfferId(), message.getUid());
|
||||
setStateArrived();
|
||||
if (!task.isCompleted()) complete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStoredInMailbox() {
|
||||
log.info("{} stored in mailbox for peer {}. tradeId={}, uid={}", message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid());
|
||||
log.info("{} stored in mailbox for peer {}. tradeId={}, uid={}", message.getClass().getSimpleName(), peersNodeAddress, message.getOfferId(), message.getUid());
|
||||
SendMailboxMessageTask.this.onStoredInMailbox();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFault(String errorMessage) {
|
||||
log.error("{} failed: Peer {}. tradeId={}, uid={}, errorMessage={}", message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid(), errorMessage);
|
||||
log.error("{} failed: Peer {}. tradeId={}, uid={}, errorMessage={}", message.getClass().getSimpleName(), peersNodeAddress, message.getOfferId(), message.getUid(), errorMessage);
|
||||
SendMailboxMessageTask.this.onFault(errorMessage, message);
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ package haveno.core.trade.protocol.tasks;
|
||||
|
||||
import haveno.common.taskrunner.TaskRunner;
|
||||
import haveno.core.offer.OfferDirection;
|
||||
import haveno.core.trade.HavenoUtils;
|
||||
import haveno.core.trade.Trade;
|
||||
import haveno.core.trade.protocol.TradeProtocol;
|
||||
import haveno.core.xmr.model.XmrAddressEntry;
|
||||
@ -41,11 +42,12 @@ public class TakerReserveTradeFunds extends TradeTask {
|
||||
runInterceptHook();
|
||||
|
||||
// create reserve tx
|
||||
BigInteger penaltyFee = HavenoUtils.multiply(trade.getAmount(), trade.getOffer().getPenaltyFeePct());
|
||||
BigInteger takerFee = trade.getTakerFee();
|
||||
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);
|
||||
MoneroTxWallet reserveTx = model.getXmrWalletService().createReserveTx(penaltyFee, takerFee, sendAmount, securityDeposit, returnAddress, false, null);
|
||||
|
||||
// check if trade still exists
|
||||
if (!processModel.getTradeManager().hasOpenTrade(trade)) {
|
||||
|
@ -117,12 +117,11 @@ public class TakerSendInitTradeRequestToArbitrator extends TradeTask {
|
||||
// create request to arbitrator
|
||||
InitTradeRequest makerRequest = (InitTradeRequest) processModel.getTradeMessage(); // taker's InitTradeRequest to maker
|
||||
InitTradeRequest arbitratorRequest = new InitTradeRequest(
|
||||
makerRequest.getTradeId(),
|
||||
makerRequest.getOfferId(),
|
||||
makerRequest.getSenderNodeAddress(),
|
||||
makerRequest.getPubKeyRing(),
|
||||
makerRequest.getTradeAmount(),
|
||||
makerRequest.getTradePrice(),
|
||||
makerRequest.getTradeFee(),
|
||||
makerRequest.getAccountId(),
|
||||
makerRequest.getPaymentAccountId(),
|
||||
makerRequest.getPaymentMethodId(),
|
||||
@ -140,7 +139,7 @@ public class TakerSendInitTradeRequestToArbitrator extends TradeTask {
|
||||
processModel.getMakerSignature());
|
||||
|
||||
// send request to arbitrator
|
||||
log.info("Sending {} with offerId {} and uid {} to arbitrator {}", arbitratorRequest.getClass().getSimpleName(), arbitratorRequest.getTradeId(), arbitratorRequest.getUid(), trade.getArbitrator().getNodeAddress());
|
||||
log.info("Sending {} with offerId {} and uid {} to arbitrator {}", arbitratorRequest.getClass().getSimpleName(), arbitratorRequest.getOfferId(), arbitratorRequest.getUid(), trade.getArbitrator().getNodeAddress());
|
||||
processModel.getP2PService().sendEncryptedDirectMessage(
|
||||
arbitratorNodeAddress,
|
||||
arbitrator.getPubKeyRing(),
|
||||
|
@ -53,8 +53,8 @@ public class SendMediatedPayoutSignatureMessage extends TradeTask {
|
||||
trade.getId(),
|
||||
p2PService.getAddress(),
|
||||
UUID.randomUUID().toString());
|
||||
log.info("Send {} to peer {}. tradeId={}, uid={}",
|
||||
message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid());
|
||||
log.info("Send {} to peer {}. offerId={}, uid={}",
|
||||
message.getClass().getSimpleName(), peersNodeAddress, message.getOfferId(), message.getUid());
|
||||
|
||||
trade.setMediationResultState(MediationResultState.SIG_MSG_SENT);
|
||||
processModel.getTradeManager().requestPersistence();
|
||||
@ -64,8 +64,8 @@ public class SendMediatedPayoutSignatureMessage extends TradeTask {
|
||||
new SendMailboxMessageListener() {
|
||||
@Override
|
||||
public void onArrived() {
|
||||
log.info("{} arrived at peer {}. tradeId={}, uid={}",
|
||||
message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid());
|
||||
log.info("{} arrived at peer {}. offerId={}, uid={}",
|
||||
message.getClass().getSimpleName(), peersNodeAddress, message.getOfferId(), message.getUid());
|
||||
|
||||
trade.setMediationResultState(MediationResultState.SIG_MSG_ARRIVED);
|
||||
processModel.getTradeManager().requestPersistence();
|
||||
@ -74,8 +74,8 @@ public class SendMediatedPayoutSignatureMessage extends TradeTask {
|
||||
|
||||
@Override
|
||||
public void onStoredInMailbox() {
|
||||
log.info("{} stored in mailbox for peer {}. tradeId={}, uid={}",
|
||||
message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid());
|
||||
log.info("{} stored in mailbox for peer {}. offerId={}, uid={}",
|
||||
message.getClass().getSimpleName(), peersNodeAddress, message.getOfferId(), message.getUid());
|
||||
|
||||
trade.setMediationResultState(MediationResultState.SIG_MSG_IN_MAILBOX);
|
||||
processModel.getTradeManager().requestPersistence();
|
||||
@ -84,8 +84,8 @@ public class SendMediatedPayoutSignatureMessage extends TradeTask {
|
||||
|
||||
@Override
|
||||
public void onFault(String errorMessage) {
|
||||
log.error("{} failed: Peer {}. tradeId={}, uid={}, errorMessage={}",
|
||||
message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid(), errorMessage);
|
||||
log.error("{} failed: Peer {}. offerId={}, uid={}, errorMessage={}",
|
||||
message.getClass().getSimpleName(), peersNodeAddress, message.getOfferId(), message.getUid(), errorMessage);
|
||||
trade.setMediationResultState(MediationResultState.SIG_MSG_SEND_FAILED);
|
||||
appendToErrorMessage("Sending message failed: message=" + message + "\nerrorMessage=" + errorMessage);
|
||||
processModel.getTradeManager().requestPersistence();
|
||||
|
@ -56,6 +56,6 @@ public class Validator {
|
||||
}
|
||||
|
||||
public static boolean isTradeIdValid(String tradeId, TradeMessage tradeMessage) {
|
||||
return tradeId.equals(tradeMessage.getTradeId());
|
||||
return tradeId.equals(tradeMessage.getOfferId());
|
||||
}
|
||||
}
|
||||
|
@ -532,20 +532,21 @@ public class XmrWalletService {
|
||||
|
||||
/**
|
||||
* Create the reserve tx and freeze its inputs. The full amount is returned
|
||||
* to the sender's payout address less the security deposit and mining fee.
|
||||
* to the sender's payout address less the penalty and mining fees.
|
||||
*
|
||||
* @param penaltyFee penalty fee for breaking protocol
|
||||
* @param tradeFee trade fee
|
||||
* @param sendAmount amount to give peer
|
||||
* @param sendAmount amount to send peer
|
||||
* @param securityDeposit security deposit amount
|
||||
* @param returnAddress return address for reserved funds
|
||||
* @param reserveExactAmount specifies to reserve the exact input amount
|
||||
* @param preferredSubaddressIndex preferred source subaddress to spend from (optional)
|
||||
* @return a transaction to reserve a trade
|
||||
*/
|
||||
public MoneroTxWallet createReserveTx(BigInteger tradeFee, BigInteger sendAmount, BigInteger securityDeposit, String returnAddress, boolean reserveExactAmount, Integer preferredSubaddressIndex) {
|
||||
public MoneroTxWallet createReserveTx(BigInteger penaltyFee, BigInteger tradeFee, BigInteger sendAmount, BigInteger securityDeposit, String returnAddress, boolean reserveExactAmount, Integer preferredSubaddressIndex) {
|
||||
log.info("Creating reserve tx with preferred subaddress index={}, return address={}", preferredSubaddressIndex, returnAddress);
|
||||
long time = System.currentTimeMillis();
|
||||
MoneroTxWallet reserveTx = createTradeTx(tradeFee, sendAmount, securityDeposit, returnAddress, reserveExactAmount, preferredSubaddressIndex);
|
||||
MoneroTxWallet reserveTx = createTradeTx(penaltyFee, tradeFee, sendAmount, securityDeposit, returnAddress, reserveExactAmount, preferredSubaddressIndex);
|
||||
log.info("Done creating reserve tx in {} ms", System.currentTimeMillis() - time);
|
||||
return reserveTx;
|
||||
}
|
||||
@ -568,18 +569,18 @@ public class XmrWalletService {
|
||||
|
||||
// create deposit tx
|
||||
String multisigAddress = trade.getProcessModel().getMultisigAddress();
|
||||
BigInteger tradeFee = trade instanceof MakerTrade ? trade.getOffer().getMakerFee() : trade.getTakerFee();
|
||||
BigInteger tradeFee = trade instanceof MakerTrade ? trade.getMakerFee() : trade.getTakerFee();
|
||||
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);
|
||||
MoneroTxWallet depositTx = createTradeTx(tradeFee, sendAmount, securityDeposit, multisigAddress, reserveExactAmount, preferredSubaddressIndex);
|
||||
MoneroTxWallet depositTx = createTradeTx(null, tradeFee, sendAmount, securityDeposit, multisigAddress, reserveExactAmount, preferredSubaddressIndex);
|
||||
log.info("Done creating deposit tx for trade {} {} in {} ms", trade.getClass().getSimpleName(), trade.getId(), System.currentTimeMillis() - time);
|
||||
return depositTx;
|
||||
}
|
||||
}
|
||||
|
||||
private MoneroTxWallet createTradeTx(BigInteger tradeFee, BigInteger sendAmount, BigInteger securityDeposit, String address, boolean reserveExactAmount, Integer preferredSubaddressIndex) {
|
||||
private MoneroTxWallet createTradeTx(BigInteger penaltyFee, BigInteger tradeFee, BigInteger sendAmount, BigInteger securityDeposit, String address, boolean reserveExactAmount, Integer preferredSubaddressIndex) {
|
||||
synchronized (walletLock) {
|
||||
MoneroWallet wallet = getWallet();
|
||||
|
||||
@ -604,27 +605,31 @@ public class XmrWalletService {
|
||||
// first try preferred subaddressess
|
||||
for (int i = 0; i < subaddressIndices.size(); i++) {
|
||||
try {
|
||||
return createTradeTxFromSubaddress(tradeFee, sendAmount, securityDeposit, address, reserveExactAmount, subaddressIndices.get(i));
|
||||
return createTradeTxFromSubaddress(penaltyFee, tradeFee, sendAmount, securityDeposit, address, reserveExactAmount, subaddressIndices.get(i));
|
||||
} catch (Exception e) {
|
||||
if (i == subaddressIndices.size() - 1 && reserveExactAmount) throw e; // throw if no subaddress with exact output
|
||||
}
|
||||
}
|
||||
|
||||
// try any subaddress
|
||||
return createTradeTxFromSubaddress(tradeFee, sendAmount, securityDeposit, address, reserveExactAmount, null);
|
||||
return createTradeTxFromSubaddress(penaltyFee, tradeFee, sendAmount, securityDeposit, address, reserveExactAmount, null);
|
||||
}
|
||||
}
|
||||
|
||||
private MoneroTxWallet createTradeTxFromSubaddress(BigInteger tradeFee, BigInteger sendAmount, BigInteger securityDeposit, String address, boolean reserveExactAmount, Integer subaddressIndex) {
|
||||
private MoneroTxWallet createTradeTxFromSubaddress(BigInteger penaltyFee, BigInteger tradeFee, BigInteger sendAmount, BigInteger securityDeposit, String address, boolean reserveExactAmount, Integer subaddressIndex) {
|
||||
|
||||
// create tx
|
||||
MoneroTxWallet tradeTx = wallet.createTx(new MoneroTxConfig()
|
||||
boolean isDepositTx = penaltyFee == null;
|
||||
BigInteger feeAmount = isDepositTx ? tradeFee : penaltyFee;
|
||||
BigInteger transferAmount = isDepositTx ? sendAmount.add(securityDeposit) : sendAmount.add(securityDeposit).add(tradeFee).subtract(penaltyFee);
|
||||
MoneroTxConfig txConfig = new MoneroTxConfig()
|
||||
.setAccountIndex(0)
|
||||
.setSubaddressIndices(subaddressIndex)
|
||||
.addDestination(HavenoUtils.getTradeFeeAddress(), tradeFee)
|
||||
.addDestination(address, sendAmount.add(securityDeposit))
|
||||
.setSubtractFeeFrom(1)
|
||||
.setPriority(XmrWalletService.PROTOCOL_FEE_PRIORITY)); // pay fee from security deposit
|
||||
.addDestination(address, transferAmount)
|
||||
.setSubtractFeeFrom(0) // pay fee from transfer amount
|
||||
.setPriority(XmrWalletService.PROTOCOL_FEE_PRIORITY);
|
||||
if (!BigInteger.valueOf(0).equals(feeAmount)) txConfig.addDestination(HavenoUtils.getTradeFeeAddress(), feeAmount);
|
||||
MoneroTxWallet tradeTx = wallet.createTx(txConfig);
|
||||
|
||||
// freeze inputs
|
||||
List<String> keyImages = new ArrayList<String>();
|
||||
@ -639,6 +644,7 @@ public class XmrWalletService {
|
||||
* The transaction is submitted to the pool then flushed without relaying.
|
||||
*
|
||||
* @param offerId id of offer to verify trade tx
|
||||
* @param penaltyFee penalty fee for breaking protocol
|
||||
* @param tradeFee trade fee
|
||||
* @param sendAmount amount to give peer
|
||||
* @param securityDeposit security deposit amount
|
||||
@ -647,9 +653,9 @@ public class XmrWalletService {
|
||||
* @param txHex transaction hex
|
||||
* @param txKey transaction key
|
||||
* @param keyImages expected key images of inputs, ignored if null
|
||||
* @return tuple with the verified tx and its actual security deposit
|
||||
* @return tuple with the verified tx and the actual security deposit
|
||||
*/
|
||||
public Tuple2<MoneroTx, BigInteger> verifyTradeTx(String offerId, BigInteger tradeFee, BigInteger sendAmount, BigInteger securityDeposit, String address, String txHash, String txHex, String txKey, List<String> keyImages) {
|
||||
public Tuple2<MoneroTx, BigInteger> verifyTradeTx(String offerId, BigInteger penaltyFee, BigInteger tradeFee, BigInteger sendAmount, BigInteger securityDeposit, String address, String txHash, String txHex, String txKey, List<String> keyImages) {
|
||||
if (txHash == null) throw new IllegalArgumentException("Cannot verify trade tx with null id");
|
||||
MoneroDaemonRpc daemon = getDaemon();
|
||||
MoneroWallet wallet = getWallet();
|
||||
@ -681,39 +687,45 @@ public class XmrWalletService {
|
||||
if (!BigInteger.ZERO.equals(tx.getUnlockTime())) throw new RuntimeException("Unlock height must be 0");
|
||||
|
||||
// verify miner fee
|
||||
BigInteger feeEstimate = getElevatedFeeEstimate(tx.getWeight());
|
||||
double feeDiff = tx.getFee().subtract(feeEstimate).abs().doubleValue() / feeEstimate.doubleValue();
|
||||
if (feeDiff > MINER_FEE_TOLERANCE) throw new Error("Miner fee is not within " + (MINER_FEE_TOLERANCE * 100) + "% of estimated fee, expected " + feeEstimate + " but was " + tx.getFee());
|
||||
log.info("Trade tx fee {} is within tolerance, diff%={}", tx.getFee(), feeDiff);
|
||||
BigInteger minerFeeEstimate = getElevatedFeeEstimate(tx.getWeight());
|
||||
double minerFeeDiff = tx.getFee().subtract(minerFeeEstimate).abs().doubleValue() / minerFeeEstimate.doubleValue();
|
||||
if (minerFeeDiff > MINER_FEE_TOLERANCE) throw new Error("Miner fee is not within " + (MINER_FEE_TOLERANCE * 100) + "% of estimated fee, expected " + minerFeeEstimate + " but was " + tx.getFee());
|
||||
log.info("Trade tx fee {} is within tolerance, diff%={}", tx.getFee(), minerFeeDiff);
|
||||
|
||||
// verify transfer proof to fee address
|
||||
MoneroCheckTx tradeFeeCheck = wallet.checkTxKey(txHash, txKey, HavenoUtils.getTradeFeeAddress());
|
||||
if (!tradeFeeCheck.isGood()) throw new RuntimeException("Invalid proof to trade fee address");
|
||||
// verify proof to fee address
|
||||
MoneroCheckTx feeCheck = wallet.checkTxKey(txHash, txKey, HavenoUtils.getTradeFeeAddress());
|
||||
if (!feeCheck.isGood()) throw new RuntimeException("Invalid proof to trade fee address");
|
||||
|
||||
// verify transfer proof to address
|
||||
// verify proof to transfer address
|
||||
MoneroCheckTx transferCheck = wallet.checkTxKey(txHash, txKey, address);
|
||||
if (!transferCheck.isGood()) throw new RuntimeException("Invalid proof to transfer address");
|
||||
|
||||
// collect actual trade fee, send amount, and security deposit
|
||||
BigInteger actualTradeFee = tradeFeeCheck.getReceivedAmount();
|
||||
actualSecurityDeposit = transferCheck.getReceivedAmount().subtract(sendAmount);
|
||||
BigInteger actualSendAmount = transferCheck.getReceivedAmount().subtract(actualSecurityDeposit);
|
||||
// verify fee and transfer amounts
|
||||
BigInteger actualFee = feeCheck.getReceivedAmount();
|
||||
BigInteger actualTransferAmount = transferCheck.getReceivedAmount();
|
||||
boolean isDepositTx = penaltyFee == null;
|
||||
if (isDepositTx) {
|
||||
|
||||
// verify trade fee
|
||||
if (actualTradeFee.compareTo(tradeFee) < 0) {
|
||||
throw new RuntimeException("Insufficient trade fee, expected=" + tradeFee + ", actual=" + actualTradeFee + ", transfer address check=" + JsonUtils.serialize(transferCheck) + ", trade fee address check=" + JsonUtils.serialize(tradeFeeCheck));
|
||||
if (!actualFee.equals(tradeFee)) throw new RuntimeException("Invalid trade fee amount, expected " + tradeFee + " but was " + actualFee);
|
||||
|
||||
// verify multisig deposit amount
|
||||
BigInteger expectedTransferAmount = sendAmount.add(securityDeposit).subtract(tx.getFee());
|
||||
if (!actualTransferAmount.equals(expectedTransferAmount)) throw new RuntimeException("Invalid multisig deposit amount, expected " + expectedTransferAmount + " but was " + actualTransferAmount);
|
||||
actualSecurityDeposit = actualTransferAmount.subtract(sendAmount);
|
||||
} else {
|
||||
|
||||
// verify penalty fee
|
||||
if (!actualFee.equals(penaltyFee)) throw new RuntimeException("Invalid penalty fee amount, expected " + penaltyFee + " but was " + actualFee);
|
||||
|
||||
// verify return amount
|
||||
BigInteger expectedTransferAmount = sendAmount.add(securityDeposit).add(tradeFee).subtract(penaltyFee).subtract(tx.getFee());
|
||||
if (!actualTransferAmount.equals(expectedTransferAmount)) throw new RuntimeException("Invalid return amount, expected " + expectedTransferAmount + " but was " + actualTransferAmount);
|
||||
actualSecurityDeposit = actualTransferAmount.subtract(sendAmount).subtract(tradeFee);
|
||||
}
|
||||
|
||||
// verify send amount
|
||||
if (!actualSendAmount.equals(sendAmount)) {
|
||||
throw new RuntimeException("Unexpected send amount, expected " + sendAmount + " but was " + actualSendAmount);
|
||||
}
|
||||
|
||||
// verify security deposit
|
||||
BigInteger expectedSecurityDeposit = securityDeposit.subtract(tx.getFee()); // fee is paid from security deposit
|
||||
if (!actualSecurityDeposit.equals(expectedSecurityDeposit)) {
|
||||
throw new RuntimeException("Unexpected security deposit amount, expected " + expectedSecurityDeposit + " but was " + actualSecurityDeposit);
|
||||
}
|
||||
// return the result
|
||||
return new Tuple2<>(tx, actualSecurityDeposit);
|
||||
} catch (Exception e) {
|
||||
log.warn("Error verifying trade tx with offer id=" + offerId + (tx == null ? "" : ", tx=" + tx) + ": " + e.getMessage());
|
||||
throw e;
|
||||
@ -725,7 +737,6 @@ public class XmrWalletService {
|
||||
throw err.getCode().equals(-32601) ? new RuntimeException("Failed to flush tx from pool. Arbitrator must use trusted, unrestricted daemon") : err;
|
||||
}
|
||||
}
|
||||
return new Tuple2<>(tx, actualSecurityDeposit);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -46,6 +46,11 @@ public class OfferMaker {
|
||||
lookup.valueOf(useMarketBasedPrice, false),
|
||||
lookup.valueOf(amount, 100000L),
|
||||
lookup.valueOf(minAmount, 100000L),
|
||||
0L,
|
||||
0L,
|
||||
0L,
|
||||
0L,
|
||||
0L,
|
||||
lookup.valueOf(baseCurrencyCode, "XMR"),
|
||||
lookup.valueOf(counterCurrencyCode, "USD"),
|
||||
"SEPA",
|
||||
@ -58,9 +63,6 @@ public class OfferMaker {
|
||||
0L,
|
||||
0L,
|
||||
0L,
|
||||
0L,
|
||||
0L,
|
||||
0L,
|
||||
false,
|
||||
false,
|
||||
0L,
|
||||
|
@ -31,11 +31,26 @@ import static org.junit.jupiter.api.Assertions.fail;
|
||||
public class CoinUtilTest {
|
||||
|
||||
@Test
|
||||
public void testGetFeePerBtc() {
|
||||
assertEquals(HavenoUtils.xmrToAtomicUnits(1), HavenoUtils.getFeePerXmr(HavenoUtils.xmrToAtomicUnits(1), HavenoUtils.xmrToAtomicUnits(1)));
|
||||
assertEquals(HavenoUtils.xmrToAtomicUnits(0.1), HavenoUtils.getFeePerXmr(HavenoUtils.xmrToAtomicUnits(0.1), HavenoUtils.xmrToAtomicUnits(1)));
|
||||
assertEquals(HavenoUtils.xmrToAtomicUnits(0.01), HavenoUtils.getFeePerXmr(HavenoUtils.xmrToAtomicUnits(0.1), HavenoUtils.xmrToAtomicUnits(0.1)));
|
||||
assertEquals(HavenoUtils.xmrToAtomicUnits(0.015), HavenoUtils.getFeePerXmr(HavenoUtils.xmrToAtomicUnits(0.3), HavenoUtils.xmrToAtomicUnits(0.05)));
|
||||
public void testGetPercentOfAmount() {
|
||||
BigInteger bi = new BigInteger("703100000000");
|
||||
assertEquals(new BigInteger("105465000000"), HavenoUtils.multiply(bi, .15));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetFeePerXmr() {
|
||||
assertEquals(HavenoUtils.xmrToAtomicUnits(1), HavenoUtils.multiply(HavenoUtils.xmrToAtomicUnits(1), 1.0));
|
||||
assertEquals(HavenoUtils.xmrToAtomicUnits(0.1), HavenoUtils.multiply(HavenoUtils.xmrToAtomicUnits(0.1), 1.0));
|
||||
assertEquals(HavenoUtils.xmrToAtomicUnits(0.01), HavenoUtils.multiply(HavenoUtils.xmrToAtomicUnits(0.1), 0.1));
|
||||
assertEquals(HavenoUtils.xmrToAtomicUnits(0.015), HavenoUtils.multiply(HavenoUtils.xmrToAtomicUnits(0.3), 0.05));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseXmr() {
|
||||
String xmrStr = "0.266394780889";
|
||||
BigInteger au = HavenoUtils.parseXmr(xmrStr);
|
||||
assertEquals(new BigInteger("266394780889"), au);
|
||||
assertEquals(xmrStr, "" + HavenoUtils.atomicUnitsToXmr(au));
|
||||
assertEquals(xmrStr, HavenoUtils.formatXmr(au, false));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -545,7 +545,7 @@ public abstract class MutableOfferDataModel extends OfferDataModel {
|
||||
// Maker does not pay the mining fee for the trade txs because the mining fee might be different when maker
|
||||
// created the offer and reserved his funds, so that would not work well with dynamic fees.
|
||||
// The mining fee for the createOfferFee tx is deducted from the createOfferFee and not visible to the trader
|
||||
final BigInteger makerFee = getMakerFee();
|
||||
final BigInteger makerFee = getMaxMakerFee();
|
||||
if (direction != null && amount.get() != null && makerFee != null) {
|
||||
BigInteger feeAndSecDeposit = getSecurityDeposit().add(makerFee);
|
||||
BigInteger total = isBuyOffer() ? feeAndSecDeposit : feeAndSecDeposit.add(amount.get());
|
||||
@ -677,8 +677,8 @@ public abstract class MutableOfferDataModel extends OfferDataModel {
|
||||
this.marketPriceAvailable = marketPriceAvailable;
|
||||
}
|
||||
|
||||
public BigInteger getMakerFee() {
|
||||
return HavenoUtils.getMakerFee(amount.get());
|
||||
public BigInteger getMaxMakerFee() {
|
||||
return HavenoUtils.multiply(amount.get(), HavenoUtils.MAKER_FEE_PCT);
|
||||
}
|
||||
|
||||
boolean canPlaceOffer() {
|
||||
|
@ -491,7 +491,7 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
|
||||
tradeFeeCurrencyCode.set(Res.getBaseCurrencyCode());
|
||||
tradeFeeDescription.set(Res.get("createOffer.tradeFee.descriptionXMROnly"));
|
||||
|
||||
BigInteger makerFee = dataModel.getMakerFee();
|
||||
BigInteger makerFee = dataModel.getMaxMakerFee();
|
||||
if (makerFee == null) {
|
||||
return;
|
||||
}
|
||||
@ -499,7 +499,7 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
|
||||
isTradeFeeVisible.setValue(true);
|
||||
tradeFee.set(HavenoUtils.formatXmr(makerFee));
|
||||
tradeFeeInXmrWithFiat.set(OfferViewModelUtil.getTradeFeeWithFiatEquivalent(offerUtil,
|
||||
dataModel.getMakerFee(),
|
||||
dataModel.getMaxMakerFee(),
|
||||
btcFormatter));
|
||||
}
|
||||
|
||||
@ -1004,8 +1004,7 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
|
||||
return OfferViewModelUtil.getTradeFeeWithFiatEquivalentAndPercentage(offerUtil,
|
||||
dataModel.getSecurityDeposit(),
|
||||
dataModel.getAmount().get(),
|
||||
btcFormatter,
|
||||
Restrictions.getMinBuyerSecurityDeposit()
|
||||
btcFormatter
|
||||
);
|
||||
}
|
||||
|
||||
@ -1016,14 +1015,13 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
|
||||
|
||||
public String getTradeFee() {
|
||||
return OfferViewModelUtil.getTradeFeeWithFiatEquivalentAndPercentage(offerUtil,
|
||||
dataModel.getMakerFee(),
|
||||
dataModel.getMaxMakerFee(),
|
||||
dataModel.getAmount().get(),
|
||||
btcFormatter,
|
||||
HavenoUtils.getMinMakerFee());
|
||||
btcFormatter);
|
||||
}
|
||||
|
||||
public String getMakerFeePercentage() {
|
||||
final BigInteger makerFee = dataModel.getMakerFee();
|
||||
final BigInteger makerFee = dataModel.getMaxMakerFee();
|
||||
return GUIUtil.getPercentage(makerFee, dataModel.getAmount().get());
|
||||
}
|
||||
|
||||
|
@ -44,18 +44,10 @@ public class OfferViewModelUtil {
|
||||
public static String getTradeFeeWithFiatEquivalentAndPercentage(OfferUtil offerUtil,
|
||||
BigInteger tradeFee,
|
||||
BigInteger tradeAmount,
|
||||
CoinFormatter formatter,
|
||||
BigInteger minTradeFee) {
|
||||
CoinFormatter formatter) {
|
||||
String feeAsXmr = HavenoUtils.formatXmr(tradeFee, true);
|
||||
String percentage;
|
||||
if (tradeFee.compareTo(minTradeFee) <= 0) {
|
||||
percentage = Res.get("guiUtil.requiredMinimum")
|
||||
.replace("(", "")
|
||||
.replace(")", "");
|
||||
} else {
|
||||
percentage = GUIUtil.getPercentage(tradeFee, tradeAmount) +
|
||||
" " + Res.get("guiUtil.ofTradeAmount");
|
||||
}
|
||||
percentage = GUIUtil.getPercentage(tradeFee, tradeAmount) + " " + Res.get("guiUtil.ofTradeAmount");
|
||||
return offerUtil.getFeeInUserFiatCurrency(tradeFee,
|
||||
formatter)
|
||||
.map(VolumeUtil::formatAverageVolumeWithCode)
|
||||
|
@ -618,10 +618,6 @@ abstract class OfferBookViewModel extends ActivatableViewModel {
|
||||
return true;
|
||||
}
|
||||
|
||||
public String getMakerFeeAsString(Offer offer) {
|
||||
return HavenoUtils.formatXmr(offer.getMakerFee(), true);
|
||||
}
|
||||
|
||||
private static String getDirectionWithCodeDetailed(OfferDirection direction, String currencyCode) {
|
||||
if (CurrencyUtil.isTraditionalCurrency(currencyCode))
|
||||
return (direction == OfferDirection.BUY) ? Res.get("shared.buyingXMRWith", currencyCode) : Res.get("shared.sellingXMRFor", currencyCode);
|
||||
|
@ -248,7 +248,6 @@ class TakeOfferDataModel extends OfferDataModel {
|
||||
errorMsg = Res.get("offerbook.warning.offerWasAlreadyUsedInTrade");
|
||||
} else {
|
||||
tradeManager.onTakeOffer(amount.get(),
|
||||
getTakerFee(),
|
||||
fundsNeededForTrade,
|
||||
offer,
|
||||
paymentAccount.getId(),
|
||||
@ -404,7 +403,7 @@ class TakeOfferDataModel extends OfferDataModel {
|
||||
|
||||
@Nullable
|
||||
BigInteger getTakerFee() {
|
||||
return HavenoUtils.getTakerFee(this.amount.get());
|
||||
return HavenoUtils.multiply(this.amount.get(), offer.getTakerFeePct());
|
||||
}
|
||||
|
||||
public void swapTradeToSavings() {
|
||||
|
@ -38,7 +38,6 @@ import haveno.core.util.VolumeUtil;
|
||||
import haveno.core.util.coin.CoinFormatter;
|
||||
import haveno.core.util.coin.CoinUtil;
|
||||
import haveno.core.util.validation.InputValidator;
|
||||
import haveno.core.xmr.wallet.Restrictions;
|
||||
import haveno.desktop.Navigation;
|
||||
import haveno.desktop.common.model.ActivatableWithDataModel;
|
||||
import haveno.desktop.common.model.ViewModel;
|
||||
@ -656,9 +655,7 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
|
||||
return OfferViewModelUtil.getTradeFeeWithFiatEquivalentAndPercentage(offerUtil,
|
||||
dataModel.getSecurityDeposit(),
|
||||
dataModel.getAmount().get(),
|
||||
xmrFormatter,
|
||||
Restrictions.getMinBuyerSecurityDeposit()
|
||||
);
|
||||
xmrFormatter);
|
||||
}
|
||||
|
||||
public String getSecurityDepositWithCode() {
|
||||
@ -669,8 +666,7 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
|
||||
return OfferViewModelUtil.getTradeFeeWithFiatEquivalentAndPercentage(offerUtil,
|
||||
dataModel.getTakerFee(),
|
||||
dataModel.getAmount().get(),
|
||||
xmrFormatter,
|
||||
HavenoUtils.getMinMakerFee());
|
||||
xmrFormatter);
|
||||
}
|
||||
|
||||
public String getTakerFeePercentage() {
|
||||
|
@ -189,6 +189,11 @@ class EditOfferDataModel extends MutableOfferDataModel {
|
||||
newOfferPayload.isUseMarketBasedPrice(),
|
||||
offerPayload.getAmount(),
|
||||
offerPayload.getMinAmount(),
|
||||
offerPayload.getMakerFeePct(),
|
||||
offerPayload.getTakerFeePct(),
|
||||
offerPayload.getPenaltyFeePct(),
|
||||
offerPayload.getBuyerSecurityDepositPct(),
|
||||
offerPayload.getSellerSecurityDepositPct(),
|
||||
newOfferPayload.getBaseCurrencyCode(),
|
||||
newOfferPayload.getCounterCurrencyCode(),
|
||||
newOfferPayload.getPaymentMethodId(),
|
||||
@ -199,9 +204,6 @@ class EditOfferDataModel extends MutableOfferDataModel {
|
||||
newOfferPayload.getAcceptedBankIds(),
|
||||
offerPayload.getVersionNr(),
|
||||
offerPayload.getBlockHeightAtOfferCreation(),
|
||||
offerPayload.getMakerFee(),
|
||||
offerPayload.getBuyerSecurityDepositPct(),
|
||||
offerPayload.getSellerSecurityDepositPct(),
|
||||
offerPayload.getMaxTradeLimit(),
|
||||
offerPayload.getMaxTradePeriod(),
|
||||
offerPayload.isUseAutoClose(),
|
||||
|
@ -27,7 +27,6 @@ import haveno.core.locale.Res;
|
||||
import haveno.core.monetary.Price;
|
||||
import haveno.core.offer.Offer;
|
||||
import haveno.core.offer.OpenOffer;
|
||||
import haveno.core.trade.HavenoUtils;
|
||||
import haveno.core.util.FormattingUtils;
|
||||
import haveno.core.util.PriceUtil;
|
||||
import haveno.core.util.VolumeUtil;
|
||||
@ -155,11 +154,6 @@ class OpenOffersViewModel extends ActivatableWithDataModel<OpenOffersDataModel>
|
||||
return GUIUtil.isBootstrappedOrShowPopup(p2PService);
|
||||
}
|
||||
|
||||
public String getMakerFeeAsString(OpenOffer openOffer) {
|
||||
Offer offer = openOffer.getOffer();
|
||||
return HavenoUtils.formatXmr(offer.getMakerFee(), true);
|
||||
}
|
||||
|
||||
String getTriggerPrice(OpenOfferListItem item) {
|
||||
if ((item == null)) {
|
||||
return "";
|
||||
|
@ -271,7 +271,7 @@ public class PendingTradesDataModel extends ActivatableDataModel {
|
||||
Offer offer = trade.getOffer();
|
||||
if (isMaker()) {
|
||||
if (offer != null) {
|
||||
return offer.getMakerFee();
|
||||
return trade.getMakerFee();
|
||||
} else {
|
||||
log.error("offer is null");
|
||||
return BigInteger.ZERO;
|
||||
|
@ -38,7 +38,6 @@ import haveno.core.util.FormattingUtils;
|
||||
import haveno.core.util.VolumeUtil;
|
||||
import haveno.core.util.coin.CoinFormatter;
|
||||
import haveno.core.util.validation.BtcAddressValidator;
|
||||
import haveno.core.xmr.wallet.Restrictions;
|
||||
import haveno.desktop.Navigation;
|
||||
import haveno.desktop.common.model.ActivatableWithDataModel;
|
||||
import haveno.desktop.common.model.ViewModel;
|
||||
@ -272,12 +271,7 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
|
||||
|
||||
BigInteger tradeFeeInXmr = dataModel.getTradeFee();
|
||||
|
||||
BigInteger minTradeFee = dataModel.isMaker() ?
|
||||
HavenoUtils.getMinMakerFee() :
|
||||
HavenoUtils.getMinTakerFee();
|
||||
|
||||
String percentage = GUIUtil.getPercentageOfTradeAmount(tradeFeeInXmr, trade.getAmount(),
|
||||
minTradeFee);
|
||||
String percentage = GUIUtil.getPercentageOfTradeAmount(tradeFeeInXmr, trade.getAmount());
|
||||
return HavenoUtils.formatXmr(tradeFeeInXmr, true) + percentage;
|
||||
} else {
|
||||
return "";
|
||||
@ -292,13 +286,7 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
|
||||
offer.getMaxBuyerSecurityDeposit()
|
||||
: offer.getMaxSellerSecurityDeposit();
|
||||
|
||||
BigInteger minSecurityDeposit = dataModel.isBuyer() ?
|
||||
Restrictions.getMinBuyerSecurityDeposit() :
|
||||
Restrictions.getMinSellerSecurityDeposit();
|
||||
|
||||
String percentage = GUIUtil.getPercentageOfTradeAmount(securityDeposit,
|
||||
trade.getAmount(),
|
||||
minSecurityDeposit);
|
||||
String percentage = GUIUtil.getPercentageOfTradeAmount(securityDeposit, trade.getAmount());
|
||||
return HavenoUtils.formatXmr(securityDeposit, true) + percentage;
|
||||
} else {
|
||||
return "";
|
||||
|
@ -623,14 +623,10 @@ public class GUIUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static String getPercentageOfTradeAmount(BigInteger fee, BigInteger tradeAmount, BigInteger minFee) {
|
||||
public static String getPercentageOfTradeAmount(BigInteger fee, BigInteger tradeAmount) {
|
||||
String result = " (" + getPercentage(fee, tradeAmount) +
|
||||
" " + Res.get("guiUtil.ofTradeAmount") + ")";
|
||||
|
||||
if (fee.compareTo(minFee) <= 0) {
|
||||
result = " " + Res.get("guiUtil.requiredMinimum");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -67,6 +67,11 @@ public class TradesChartsViewModelTest {
|
||||
false,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
"XMR",
|
||||
"EUR",
|
||||
null,
|
||||
@ -79,9 +84,6 @@ public class TradesChartsViewModelTest {
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
false,
|
||||
false,
|
||||
0,
|
||||
|
@ -605,6 +605,11 @@ public class OfferBookViewModelTest {
|
||||
false,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
"BTC",
|
||||
tradeCurrencyCode,
|
||||
paymentMethodId,
|
||||
@ -617,9 +622,6 @@ public class OfferBookViewModelTest {
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
false,
|
||||
false,
|
||||
0,
|
||||
|
@ -60,9 +60,11 @@ public class OfferMaker {
|
||||
public static final Property<Offer, PubKeyRing> pubKeyRing = newProperty();
|
||||
public static final Property<Offer, Long> blockHeight = newProperty();
|
||||
public static final Property<Offer, Long> txFee = newProperty();
|
||||
public static final Property<Offer, Long> makerFee = newProperty();
|
||||
public static final Property<Offer, Long> buyerSecurityDeposit = newProperty();
|
||||
public static final Property<Offer, Long> sellerSecurityDeposit = newProperty();
|
||||
public static final Property<Offer, Double> makerFeePct = newProperty();
|
||||
public static final Property<Offer, Double> takerFeePct = newProperty();
|
||||
public static final Property<Offer, Double> penaltyFeePct = newProperty();
|
||||
public static final Property<Offer, Double> buyerSecurityDepositPct = newProperty();
|
||||
public static final Property<Offer, Double> sellerSecurityDepositPct = newProperty();
|
||||
public static final Property<Offer, Long> tradeLimit = newProperty();
|
||||
public static final Property<Offer, Long> maxTradePeriod = newProperty();
|
||||
public static final Property<Offer, Long> lowerClosePrice = newProperty();
|
||||
@ -80,6 +82,11 @@ public class OfferMaker {
|
||||
lookup.valueOf(useMarketBasedPrice, false),
|
||||
lookup.valueOf(amount, 100000L),
|
||||
lookup.valueOf(minAmount, 100000L),
|
||||
lookup.valueOf(makerFeePct, .0015),
|
||||
lookup.valueOf(takerFeePct, .0075),
|
||||
lookup.valueOf(penaltyFeePct, 0.03),
|
||||
lookup.valueOf(buyerSecurityDepositPct, .15),
|
||||
lookup.valueOf(sellerSecurityDepositPct, .15),
|
||||
lookup.valueOf(baseCurrencyCode, "XMR"),
|
||||
lookup.valueOf(counterCurrencyCode, "USD"),
|
||||
lookup.valueOf(paymentMethodId, "SEPA"),
|
||||
@ -92,9 +99,6 @@ public class OfferMaker {
|
||||
null,
|
||||
"2",
|
||||
lookup.valueOf(blockHeight, 700000L),
|
||||
lookup.valueOf(makerFee, 1000L),
|
||||
lookup.valueOf(buyerSecurityDeposit, 10000L),
|
||||
lookup.valueOf(sellerSecurityDeposit, 10000L),
|
||||
lookup.valueOf(tradeLimit, 0L),
|
||||
lookup.valueOf(maxTradePeriod, 0L),
|
||||
false,
|
||||
|
@ -103,30 +103,19 @@ public class GUIUtilTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void percentageOfTradeAmount_higherFeeAsMin() {
|
||||
public void percentageOfTradeAmount1() {
|
||||
|
||||
BigInteger fee = BigInteger.valueOf(200000000L);
|
||||
BigInteger min = BigInteger.valueOf(100000000L);
|
||||
|
||||
assertEquals(" (0.02% of trade amount)", GUIUtil.getPercentageOfTradeAmount(fee, HavenoUtils.xmrToAtomicUnits(1.0), min));
|
||||
assertEquals(" (0.02% of trade amount)", GUIUtil.getPercentageOfTradeAmount(fee, HavenoUtils.xmrToAtomicUnits(1.0)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void percentageOfTradeAmount_minFee() {
|
||||
|
||||
BigInteger fee = BigInteger.valueOf(100000000L);
|
||||
BigInteger min = BigInteger.valueOf(100000000L);
|
||||
|
||||
assertEquals(" (required minimum)",
|
||||
GUIUtil.getPercentageOfTradeAmount(fee, HavenoUtils.xmrToAtomicUnits(1.0), min));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void percentageOfTradeAmount_minFeeZERO() {
|
||||
public void percentageOfTradeAmount2() {
|
||||
|
||||
BigInteger fee = BigInteger.valueOf(100000000L);
|
||||
|
||||
assertEquals(" (0.01% of trade amount)",
|
||||
GUIUtil.getPercentageOfTradeAmount(fee, HavenoUtils.xmrToAtomicUnits(1.0), BigInteger.ZERO));
|
||||
GUIUtil.getPercentageOfTradeAmount(fee, HavenoUtils.xmrToAtomicUnits(1.0)));
|
||||
}
|
||||
}
|
||||
|
@ -538,28 +538,30 @@ message OfferInfo {
|
||||
double market_price_margin_pct = 5;
|
||||
uint64 amount = 6 [jstype = JS_STRING];
|
||||
uint64 min_amount = 7 [jstype = JS_STRING];
|
||||
string volume = 8;
|
||||
string min_volume = 9;
|
||||
double buyer_security_deposit_pct = 10;
|
||||
double seller_security_deposit_pct = 11;
|
||||
string trigger_price = 12;
|
||||
string payment_account_id = 13;
|
||||
string payment_method_id = 14;
|
||||
string payment_method_short_name = 15;
|
||||
string base_currency_code = 16;
|
||||
string counter_currency_code = 17;
|
||||
uint64 date = 18;
|
||||
string state = 19;
|
||||
uint64 maker_fee = 20 [jstype = JS_STRING];
|
||||
bool is_activated = 21;
|
||||
bool is_my_offer = 22;
|
||||
string owner_node_address = 23;
|
||||
string pub_key_ring = 24;
|
||||
string version_nr = 25;
|
||||
int32 protocol_version = 26;
|
||||
string arbitrator_signer = 27;
|
||||
string split_output_tx_hash = 28;
|
||||
uint64 split_output_tx_fee = 29 [jstype = JS_STRING];
|
||||
double maker_fee_pct = 8;
|
||||
double taker_fee_pct = 9;
|
||||
double penalty_fee_pct = 10;
|
||||
double buyer_security_deposit_pct = 11;
|
||||
double seller_security_deposit_pct = 12;
|
||||
string volume = 13;
|
||||
string min_volume = 14;
|
||||
string trigger_price = 15;
|
||||
string payment_account_id = 16;
|
||||
string payment_method_id = 17;
|
||||
string payment_method_short_name = 18;
|
||||
string base_currency_code = 19;
|
||||
string counter_currency_code = 20;
|
||||
uint64 date = 21;
|
||||
string state = 22;
|
||||
bool is_activated = 23;
|
||||
bool is_my_offer = 24;
|
||||
string owner_node_address = 25;
|
||||
string pub_key_ring = 26;
|
||||
string version_nr = 27;
|
||||
int32 protocol_version = 28;
|
||||
string arbitrator_signer = 29;
|
||||
string split_output_tx_hash = 30;
|
||||
uint64 split_output_tx_fee = 31 [jstype = JS_STRING];
|
||||
}
|
||||
|
||||
message AvailabilityResultWithDescription {
|
||||
@ -847,39 +849,40 @@ message TradeInfo {
|
||||
string short_id = 3;
|
||||
uint64 date = 4;
|
||||
string role = 5;
|
||||
uint64 taker_fee = 6 [jstype = JS_STRING];
|
||||
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;
|
||||
uint64 amount = 6 [jstype = JS_STRING];
|
||||
uint64 maker_fee = 7 [jstype = JS_STRING];
|
||||
uint64 taker_fee = 8 [jstype = JS_STRING];
|
||||
uint64 buyer_security_deposit = 9 [jstype = JS_STRING];
|
||||
uint64 seller_security_deposit = 10 [jstype = JS_STRING];
|
||||
uint64 buyer_deposit_tx_fee = 11 [jstype = JS_STRING];
|
||||
uint64 seller_deposit_tx_fee = 12 [jstype = JS_STRING];
|
||||
uint64 buyer_payout_tx_fee = 13 [jstype = JS_STRING];
|
||||
uint64 seller_payout_tx_fee = 14 [jstype = JS_STRING];
|
||||
uint64 buyer_payout_amount = 15 [jstype = JS_STRING];
|
||||
uint64 seller_payout_amount = 16 [jstype = JS_STRING];
|
||||
string price = 17;
|
||||
string arbitrator_node_address = 18;
|
||||
string trade_peer_node_address = 19;
|
||||
string state = 20;
|
||||
string phase = 21;
|
||||
string period_state = 22;
|
||||
string payout_state = 23;
|
||||
string dispute_state = 24;
|
||||
bool is_deposits_published = 25;
|
||||
bool is_deposits_confirmed = 26;
|
||||
bool is_deposits_unlocked = 27;
|
||||
bool is_payment_sent = 28;
|
||||
bool is_payment_received = 29;
|
||||
bool is_payout_published = 30;
|
||||
bool is_payout_confirmed = 31;
|
||||
bool is_payout_unlocked = 32;
|
||||
bool is_completed = 33;
|
||||
string contract_as_json = 34;
|
||||
ContractInfo contract = 35;
|
||||
string trade_volume = 36;
|
||||
string maker_deposit_tx_id = 37;
|
||||
string taker_deposit_tx_id = 38;
|
||||
string payout_tx_id = 39;
|
||||
}
|
||||
|
||||
message ContractInfo {
|
||||
|
@ -226,26 +226,25 @@ message PrefixedSealedAndSignedMessage {
|
||||
}
|
||||
|
||||
message InitTradeRequest {
|
||||
string trade_id = 1;
|
||||
string offer_id = 1;
|
||||
NodeAddress sender_node_address = 2;
|
||||
PubKeyRing pub_key_ring = 3;
|
||||
int64 trade_amount = 4;
|
||||
int64 trade_price = 5;
|
||||
int64 trade_fee = 6;
|
||||
string account_id = 7;
|
||||
string payment_account_id = 8;
|
||||
string payment_method_id = 9;
|
||||
string uid = 10;
|
||||
bytes account_age_witness_signature_of_offer_id = 11;
|
||||
int64 current_date = 12;
|
||||
NodeAddress maker_node_address = 13;
|
||||
NodeAddress taker_node_address = 14;
|
||||
NodeAddress arbitrator_node_address = 15;
|
||||
string reserve_tx_hash = 16;
|
||||
string reserve_tx_hex = 17;
|
||||
string reserve_tx_key = 18;
|
||||
string payout_address = 19;
|
||||
bytes maker_signature = 20;
|
||||
string account_id = 6;
|
||||
string payment_account_id = 7;
|
||||
string payment_method_id = 8;
|
||||
string uid = 9;
|
||||
bytes account_age_witness_signature_of_offer_id = 10;
|
||||
int64 current_date = 11;
|
||||
NodeAddress maker_node_address = 12;
|
||||
NodeAddress taker_node_address = 13;
|
||||
NodeAddress arbitrator_node_address = 14;
|
||||
string reserve_tx_hash = 15;
|
||||
string reserve_tx_hex = 16;
|
||||
string reserve_tx_key = 17;
|
||||
string payout_address = 18;
|
||||
bytes maker_signature = 19;
|
||||
}
|
||||
|
||||
message InitMultisigRequest {
|
||||
@ -623,29 +622,31 @@ message OfferPayload {
|
||||
bool use_market_based_price = 8;
|
||||
int64 amount = 9;
|
||||
int64 min_amount = 10;
|
||||
string base_currency_code = 11;
|
||||
string counter_currency_code = 12;
|
||||
string payment_method_id = 13;
|
||||
string maker_payment_account_id = 14;
|
||||
string country_code = 15;
|
||||
repeated string accepted_country_codes = 16;
|
||||
string bank_id = 17;
|
||||
repeated string accepted_bank_ids = 18;
|
||||
string version_nr = 19;
|
||||
int64 block_height_at_offer_creation = 20;
|
||||
int64 maker_fee = 21;
|
||||
double buyer_security_deposit_pct = 22;
|
||||
double seller_security_deposit_pct = 23;
|
||||
int64 max_trade_limit = 24;
|
||||
int64 max_trade_period = 25;
|
||||
bool use_auto_close = 26;
|
||||
bool use_re_open_after_auto_close = 27;
|
||||
int64 lower_close_price = 28;
|
||||
int64 upper_close_price = 29;
|
||||
bool is_private_offer = 30;
|
||||
string hash_of_challenge = 31;
|
||||
map<string, string> extra_data = 32;
|
||||
int32 protocol_version = 33;
|
||||
double maker_fee_pct = 11;
|
||||
double taker_fee_pct = 12;
|
||||
double penalty_fee_pct = 13;
|
||||
double buyer_security_deposit_pct = 14;
|
||||
double seller_security_deposit_pct = 15;
|
||||
string base_currency_code = 16;
|
||||
string counter_currency_code = 17;
|
||||
string payment_method_id = 18;
|
||||
string maker_payment_account_id = 19;
|
||||
string country_code = 20;
|
||||
repeated string accepted_country_codes = 21;
|
||||
string bank_id = 22;
|
||||
repeated string accepted_bank_ids = 23;
|
||||
string version_nr = 24;
|
||||
int64 block_height_at_offer_creation = 25;
|
||||
int64 max_trade_limit = 26;
|
||||
int64 max_trade_period = 27;
|
||||
bool use_auto_close = 28;
|
||||
bool use_re_open_after_auto_close = 29;
|
||||
int64 lower_close_price = 30;
|
||||
int64 upper_close_price = 31;
|
||||
bool is_private_offer = 32;
|
||||
string hash_of_challenge = 33;
|
||||
map<string, string> extra_data = 34;
|
||||
int32 protocol_version = 35;
|
||||
|
||||
NodeAddress arbitrator_signer = 1001;
|
||||
bytes arbitrator_signature = 1002;
|
||||
@ -1496,29 +1497,28 @@ message Trade {
|
||||
string payout_tx_hex = 4;
|
||||
string payout_tx_key = 5;
|
||||
int64 amount = 6;
|
||||
int64 taker_fee = 8;
|
||||
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;
|
||||
bool is_completed = 30;
|
||||
int64 take_offer_date = 7;
|
||||
int64 price = 8;
|
||||
State state = 9;
|
||||
PayoutState payout_state = 10;
|
||||
DisputeState dispute_state = 11;
|
||||
TradePeriodState period_state = 12;
|
||||
Contract contract = 13;
|
||||
string contract_as_json = 14;
|
||||
bytes contract_hash = 15;
|
||||
NodeAddress arbitrator_node_address = 16;
|
||||
NodeAddress mediator_node_address = 17;
|
||||
string error_message = 18;
|
||||
string counter_currency_tx_id = 19;
|
||||
repeated ChatMessage chat_message = 20;
|
||||
MediationResultState mediation_result_state = 21;
|
||||
int64 lock_time = 22;
|
||||
int64 start_time = 23;
|
||||
NodeAddress refund_agent_node_address = 24;
|
||||
RefundResultState refund_result_state = 25;
|
||||
string counter_currency_extra_data = 26;
|
||||
string uid = 27;
|
||||
bool is_completed = 28;
|
||||
}
|
||||
|
||||
message BuyerAsMakerTrade {
|
||||
|
Loading…
Reference in New Issue
Block a user