Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -654,7 +654,7 @@ private boolean verifyPeersTradeLimit(Offer offer,
Date peersCurrentDate,
ErrorMessageHandler errorMessageHandler) {
checkNotNull(offer);
final String currencyCode = offer.getCurrencyCode();
final String currencyCode = offer.getCounterCurrencyCode();
final BigInteger defaultMaxTradeLimit = offer.getPaymentMethod().getMaxTradeLimit(currencyCode);
BigInteger peersCurrentTradeLimit = defaultMaxTradeLimit;
if (!hasTradeLimitException(peersWitness)) {
Expand All @@ -673,7 +673,7 @@ private boolean verifyPeersTradeLimit(Offer offer,
"\nPeers trade limit=" + peersCurrentTradeLimit +
"\nOffer ID=" + offer.getShortId() +
"\nPaymentMethod=" + offer.getPaymentMethod().getId() +
"\nCurrencyCode=" + offer.getCurrencyCode();
"\nCurrencyCode=" + offer.getCounterCurrencyCode();
log.warn(msg);
errorMessageHandler.handleErrorMessage(msg);
}
Expand Down
20 changes: 7 additions & 13 deletions core/src/main/java/haveno/core/api/CoreOffersService.java
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ List<OpenOffer> getMyOffers() {
List<OpenOffer> getMyOffers(String direction, String currencyCode) {
return getMyOffers().stream()
.filter(o -> offerMatchesDirectionAndCurrency(o.getOffer(), direction, currencyCode))
.sorted(openOfferPriceComparator(direction, CurrencyUtil.isTraditionalCurrency(currencyCode)))
.sorted(openOfferPriceComparator(direction))
.collect(Collectors.toList());
}

Expand Down Expand Up @@ -336,7 +336,7 @@ private void placeOffer(Offer offer,
String sourceOfferId,
Consumer<Transaction> resultHandler,
ErrorMessageHandler errorMessageHandler) {
long triggerPriceAsLong = PriceUtil.getMarketPriceAsLong(triggerPriceAsString, offer.getCurrencyCode());
long triggerPriceAsLong = PriceUtil.getMarketPriceAsLong(triggerPriceAsString, offer.getCounterCurrencyCode());
openOfferManager.placeOffer(offer,
useSavingsWallet,
triggerPriceAsLong,
Expand All @@ -353,8 +353,7 @@ private boolean offerMatchesDirectionAndCurrency(Offer offer,
if ("".equals(direction)) direction = null;
if ("".equals(currencyCode)) currencyCode = null;
var offerOfWantedDirection = direction == null || offer.getDirection().name().equalsIgnoreCase(direction);
var counterAssetCode = CurrencyUtil.isCryptoCurrency(currencyCode) ? offer.getOfferPayload().getBaseCurrencyCode() : offer.getOfferPayload().getCounterCurrencyCode();
var offerInWantedCurrency = currencyCode == null || counterAssetCode.equalsIgnoreCase(currencyCode);
var offerInWantedCurrency = currencyCode == null || offer.getCounterCurrencyCode().equalsIgnoreCase(currencyCode);
return offerOfWantedDirection && offerInWantedCurrency;
}

Expand All @@ -366,17 +365,12 @@ private Comparator<Offer> priceComparator(String direction) {
: priceComparator.get();
}

private Comparator<OpenOffer> openOfferPriceComparator(String direction, boolean isTraditional) {
private Comparator<OpenOffer> openOfferPriceComparator(String direction) {
// A buyer probably wants to see sell orders in price ascending order.
// A seller probably wants to see buy orders in price descending order.
if (isTraditional)
return direction.equalsIgnoreCase(OfferDirection.BUY.name())
? openOfferPriceComparator.get().reversed()
: openOfferPriceComparator.get();
else
return direction.equalsIgnoreCase(OfferDirection.SELL.name())
? openOfferPriceComparator.get().reversed()
: openOfferPriceComparator.get();
return direction.equalsIgnoreCase(OfferDirection.BUY.name())
? openOfferPriceComparator.get().reversed()
: openOfferPriceComparator.get();
}

private long priceStringToLong(String priceAsString, String currencyCode) {
Expand Down
31 changes: 8 additions & 23 deletions core/src/main/java/haveno/core/api/CorePriceService.java
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public double getMarketPrice(String currencyCode) throws ExecutionException, Int
} else if (!marketPrice.isExternallyProvidedPrice()) {
throw new IllegalArgumentException("Price is not available externally: " + currencyCode); // TODO: return more complex Price type including price double and isExternal boolean
}
return mapPriceFeedServicePrice(marketPrice.getPrice(), marketPrice.getCurrencyCode());
return marketPrice.getPrice();
}

/**
Expand All @@ -87,8 +87,7 @@ public double getMarketPrice(String currencyCode) throws ExecutionException, Int
public List<MarketPriceInfo> getMarketPrices() throws ExecutionException, InterruptedException, TimeoutException {
return priceFeedService.requestAllPrices().values().stream()
.map(marketPrice -> {
double mappedPrice = mapPriceFeedServicePrice(marketPrice.getPrice(), marketPrice.getCurrencyCode());
return new MarketPriceInfo(marketPrice.getCurrencyCode(), mappedPrice);
return new MarketPriceInfo(marketPrice.getCurrencyCode(), marketPrice.getPrice());
})
.collect(Collectors.toList());
}
Expand All @@ -102,12 +101,13 @@ public MarketDepthInfo getMarketDepth(String currencyCode) throws ExecutionExcep
// Offer price can be null (if price feed unavailable), thus a null-tolerant comparator is used.
Comparator<Offer> offerPriceComparator = Comparator.comparing(Offer::getPrice, Comparator.nullsLast(Comparator.naturalOrder()));

// TODO: remove this!!!
// Trading xmr-traditional is considered as buying/selling XMR, but trading xmr-crypto is
// considered as buying/selling crypto. Because of this, when viewing a xmr-crypto pair,
// the buy column is actually the sell column and vice versa. To maintain the expected
// ordering, we have to reverse the price comparator.
boolean isCrypto = CurrencyUtil.isCryptoCurrency(currencyCode);
if (isCrypto) offerPriceComparator = offerPriceComparator.reversed();
//boolean isCrypto = CurrencyUtil.isCryptoCurrency(currencyCode);
//if (isCrypto) offerPriceComparator = offerPriceComparator.reversed();

// Offer amounts are used for the secondary sort. They are sorted from high to low.
Comparator<Offer> offerAmountComparator = Comparator.comparing(Offer::getAmount).reversed();
Expand All @@ -130,11 +130,11 @@ public MarketDepthInfo getMarketDepth(String currencyCode) throws ExecutionExcep
double amount = (double) offer.getAmount().longValueExact() / LongMath.pow(10, HavenoUtils.XMR_SMALLEST_UNIT_EXPONENT);
accumulatedAmount += amount;
double priceAsDouble = (double) price.getValue() / LongMath.pow(10, price.smallestUnitExponent());
buyTM.put(mapPriceFeedServicePrice(priceAsDouble, currencyCode), accumulatedAmount);
buyTM.put(priceAsDouble, accumulatedAmount);
}
};

// Create buyer hashmap {key:price, value:count}, uses TreeMap to sort by key (asc)
// Create seller hashmap {key:price, value:count}, uses TreeMap to sort by key (asc)
accumulatedAmount = 0;
LinkedHashMap<Double,Double> sellTM = new LinkedHashMap<Double,Double>();
for(Offer offer: sellOffers){
Expand All @@ -143,7 +143,7 @@ public MarketDepthInfo getMarketDepth(String currencyCode) throws ExecutionExcep
double amount = (double) offer.getAmount().longValueExact() / LongMath.pow(10, HavenoUtils.XMR_SMALLEST_UNIT_EXPONENT);
accumulatedAmount += amount;
double priceAsDouble = (double) price.getValue() / LongMath.pow(10, price.smallestUnitExponent());
sellTM.put(mapPriceFeedServicePrice(priceAsDouble, currencyCode), accumulatedAmount);
sellTM.put(priceAsDouble, accumulatedAmount);
}
};

Expand All @@ -157,20 +157,5 @@ public MarketDepthInfo getMarketDepth(String currencyCode) throws ExecutionExcep

return new MarketDepthInfo(currencyCode, buyPrices, buyDepth, sellPrices, sellDepth);
}

/**
* PriceProvider returns different values for crypto and traditional,
* e.g. 1 XMR = X USD
* but 1 DOGE = X XMR
* Here we convert all to:
* 1 XMR = X (FIAT or CRYPTO)
*/
private double mapPriceFeedServicePrice(double price, String currencyCode) {
if (CurrencyUtil.isTraditionalCurrency(currencyCode)) {
return price;
}
return price == 0 ? 0 : 1 / price;
// TODO PriceProvider.getAll() could provide these values directly when the original values are not needed for the 'desktop' UI anymore
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ void takeOffer(Offer offer,
BigInteger amount = amountAsLong == 0 ? offer.getAmount() : BigInteger.valueOf(amountAsLong);

// adjust amount for fixed-price offer (based on TakeOfferViewModel)
String currencyCode = offer.getCurrencyCode();
String currencyCode = offer.getCounterCurrencyCode();
OfferDirection direction = offer.getOfferPayload().getDirection();
BigInteger maxAmount = offerUtil.getMaxTradeLimit(paymentAccount, currencyCode, direction, offer.hasBuyerAsTakerWithoutDeposit());
if (offer.getPrice() != null) {
Expand Down
4 changes: 2 additions & 2 deletions core/src/main/java/haveno/core/api/model/OfferInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ public static OfferInfo toOfferInfo(Offer offer) {
public static OfferInfo toMyOfferInfo(OpenOffer openOffer) {
// An OpenOffer is always my offer.
var offer = openOffer.getOffer();
var currencyCode = offer.getCurrencyCode();
var currencyCode = offer.getCounterCurrencyCode();
var isActivated = !openOffer.isDeactivated();
Optional<Price> optionalTriggerPrice = openOffer.getTriggerPrice() > 0
? Optional.of(Price.valueOf(currencyCode, openOffer.getTriggerPrice()))
Expand All @@ -150,7 +150,7 @@ public static OfferInfo toMyOfferInfo(OpenOffer openOffer) {
private static OfferInfoBuilder getBuilder(Offer offer) {
// OfferInfo protos are passed to API client, and some field
// values are converted to displayable, unambiguous form.
var currencyCode = offer.getCurrencyCode();
var currencyCode = offer.getCounterCurrencyCode();
var preciseOfferPrice = reformatMarketPrice(
requireNonNull(offer.getPrice()).toPlainString(),
currencyCode);
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/java/haveno/core/api/model/TradeInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public class TradeInfo implements Payload {

private static final Function<Trade, String> toPreciseTradePrice = (trade) ->
reformatMarketPrice(requireNonNull(trade.getPrice()).toPlainString(),
trade.getOffer().getCurrencyCode());
trade.getOffer().getCounterCurrencyCode());

// Haveno v1 trade protocol fields (some are in common with the BSQ Swap protocol).
private final OfferInfo offer;
Expand Down
17 changes: 4 additions & 13 deletions core/src/main/java/haveno/core/locale/CurrencyUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ public static Optional<TraditionalCurrency> getTraditionalCurrency(String curren
}

/**
* We return true if it is BTC or any of our currencies available in the assetRegistry.
* We return true if it is XMR or any of our currencies available in the assetRegistry.
* For removed assets it would fail as they are not found but we don't want to conclude that they are traditional then.
* As the caller might not deal with the case that a currency can be neither a cryptoCurrency nor Traditional if not found
* we return true as well in case we have no traditional currency for the code.
Expand Down Expand Up @@ -514,28 +514,19 @@ public static List<CryptoCurrency> getActiveSortedCryptoCurrencies(FilterManager
}

public static String getCurrencyPair(String currencyCode) {
if (isTraditionalCurrency(currencyCode))
return Res.getBaseCurrencyCode() + "/" + currencyCode;
else
return currencyCode + "/" + Res.getBaseCurrencyCode();
return Res.getBaseCurrencyCode() + "/" + currencyCode;
}

public static String getCounterCurrency(String currencyCode) {
if (isTraditionalCurrency(currencyCode))
return currencyCode;
else
return Res.getBaseCurrencyCode();
return currencyCode;
}

public static String getPriceWithCurrencyCode(String currencyCode) {
return getPriceWithCurrencyCode(currencyCode, "shared.priceInCurForCur");
}

public static String getPriceWithCurrencyCode(String currencyCode, String translationKey) {
if (isCryptoCurrency(currencyCode))
return Res.get(translationKey, Res.getBaseCurrencyCode(), currencyCode);
else
return Res.get(translationKey, currencyCode, Res.getBaseCurrencyCode());
return Res.get(translationKey, currencyCode, Res.getBaseCurrencyCode());
}

public static String getOfferVolumeCode(String currencyCode) {
Expand Down
21 changes: 10 additions & 11 deletions core/src/main/java/haveno/core/monetary/CryptoExchangeRate.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public class CryptoExchangeRate {
*/

public final Coin coin;
public final CryptoMoney crypto;
public final CryptoMoney cryptoMoney;

/**
* Construct exchange rate. This amount of coin is worth that amount of crypto.
Expand All @@ -43,7 +43,7 @@ public CryptoExchangeRate(Coin coin, CryptoMoney crypto) {
checkArgument(crypto.isPositive());
checkArgument(crypto.currencyCode != null, "currency code required");
this.coin = coin;
this.crypto = crypto;
this.cryptoMoney = crypto;
}

/**
Expand All @@ -59,13 +59,13 @@ public CryptoExchangeRate(CryptoMoney crypto) {
* @throws ArithmeticException if the converted crypto amount is too high or too low.
*/
public CryptoMoney coinToCrypto(Coin convertCoin) {
BigInteger converted = BigInteger.valueOf(coin.value)
.multiply(BigInteger.valueOf(convertCoin.value))
.divide(BigInteger.valueOf(crypto.value));
final BigInteger converted = BigInteger.valueOf(convertCoin.value)
.multiply(BigInteger.valueOf(cryptoMoney.value))
.divide(BigInteger.valueOf(coin.value));
if (converted.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 0
|| converted.compareTo(BigInteger.valueOf(Long.MIN_VALUE)) < 0)
throw new ArithmeticException("Overflow");
return CryptoMoney.valueOf(crypto.currencyCode, converted.longValue());
return CryptoMoney.valueOf(cryptoMoney.currencyCode, converted.longValue());
}

/**
Expand All @@ -74,12 +74,11 @@ public CryptoMoney coinToCrypto(Coin convertCoin) {
* @throws ArithmeticException if the converted coin amount is too high or too low.
*/
public Coin cryptoToCoin(CryptoMoney convertCrypto) {
checkArgument(convertCrypto.currencyCode.equals(crypto.currencyCode), "Currency mismatch: %s vs %s",
convertCrypto.currencyCode, crypto.currencyCode);
checkArgument(convertCrypto.currencyCode.equals(cryptoMoney.currencyCode), "Currency mismatch: %s vs %s",
convertCrypto.currencyCode, cryptoMoney.currencyCode);
// Use BigInteger because it's much easier to maintain full precision without overflowing.
BigInteger converted = BigInteger.valueOf(crypto.value)
.multiply(BigInteger.valueOf(convertCrypto.value))
.divide(BigInteger.valueOf(coin.value));
final BigInteger converted = BigInteger.valueOf(convertCrypto.value).multiply(BigInteger.valueOf(coin.value))
.divide(BigInteger.valueOf(cryptoMoney.value));
if (converted.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 0
|| converted.compareTo(BigInteger.valueOf(Long.MIN_VALUE)) < 0)
throw new ArithmeticException("Overflow");
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/java/haveno/core/monetary/Price.java
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ public Price subtract(Price other) {

public String toFriendlyString() {
return monetary instanceof CryptoMoney ?
((CryptoMoney) monetary).toFriendlyString() + "/XMR" :
((CryptoMoney) monetary).toFriendlyString().replace(((CryptoMoney) monetary).currencyCode, "") + "XMR/" + ((CryptoMoney) monetary).currencyCode :
((TraditionalMoney) monetary).toFriendlyString().replace(((TraditionalMoney) monetary).currencyCode, "") + "XMR/" + ((TraditionalMoney) monetary).currencyCode;
}

Expand Down
Loading
Loading