my offers return open offers, improve synchronization

This commit is contained in:
woodser 2023-07-31 09:23:24 -04:00
parent 3aa5fef8ab
commit 26117c2d10
5 changed files with 35 additions and 46 deletions

View file

@ -380,20 +380,16 @@ public class CoreApi {
return coreOffersService.getOffer(id); return coreOffersService.getOffer(id);
} }
public Offer getMyOffer(String id) {
return coreOffersService.getMyOffer(id);
}
public List<Offer> getOffers(String direction, String currencyCode) { public List<Offer> getOffers(String direction, String currencyCode) {
return coreOffersService.getOffers(direction, currencyCode); return coreOffersService.getOffers(direction, currencyCode);
} }
public List<Offer> getMyOffers(String direction, String currencyCode) { public List<OpenOffer> getMyOffers(String direction, String currencyCode) {
return coreOffersService.getMyOffers(direction, currencyCode); return coreOffersService.getMyOffers(direction, currencyCode);
} }
public OpenOffer getMyOpenOffer(String id) { public OpenOffer getMyOffer(String id) {
return coreOffersService.getMyOpenOffer(id); return coreOffersService.getMyOffer(id);
} }
public void postOffer(String currencyCode, public void postOffer(String currencyCode,

View file

@ -64,6 +64,7 @@ import static java.util.Comparator.comparing;
public class CoreOffersService { public class CoreOffersService {
private final Supplier<Comparator<Offer>> priceComparator = () -> comparing(Offer::getPrice); private final Supplier<Comparator<Offer>> priceComparator = () -> comparing(Offer::getPrice);
private final Supplier<Comparator<OpenOffer>> openOfferPriceComparator = () -> comparing(openOffer -> openOffer.getOffer().getPrice());
private final Supplier<Comparator<Offer>> reversePriceComparator = () -> comparing(Offer::getPrice).reversed(); private final Supplier<Comparator<Offer>> reversePriceComparator = () -> comparing(Offer::getPrice).reversed();
private final CoreContext coreContext; private final CoreContext coreContext;
@ -125,31 +126,23 @@ public class CoreOffersService {
new IllegalStateException(format("offer with id '%s' not found", id))); new IllegalStateException(format("offer with id '%s' not found", id)));
} }
List<Offer> getMyOffers() { List<OpenOffer> getMyOffers() {
List<Offer> offers = openOfferManager.getOpenOffers().stream() List<OpenOffer> offers = openOfferManager.getOpenOffers().stream()
.map(OpenOffer::getOffer) .filter(o -> o.getOffer().isMyOffer(keyRing))
.filter(o -> o.isMyOffer(keyRing))
.collect(Collectors.toList()); .collect(Collectors.toList());
offers.removeAll(getOffersWithDuplicateKeyImages(offers)); Set<Offer> offersWithDuplicateKeyImages = getOffersWithDuplicateKeyImages(offers.stream().map(OpenOffer::getOffer).collect(Collectors.toList())); // TODO: this is hacky way of filtering offers with duplicate key images
return offers; Set<String> offerIdsWithDuplicateKeyImages = offersWithDuplicateKeyImages.stream().map(Offer::getId).collect(Collectors.toSet());
return offers.stream().filter(o -> !offerIdsWithDuplicateKeyImages.contains(o.getId())).collect(Collectors.toList());
}; };
List<Offer> getMyOffers(String direction, String currencyCode) { List<OpenOffer> getMyOffers(String direction, String currencyCode) {
return getMyOffers().stream() return getMyOffers().stream()
.filter(o -> offerMatchesDirectionAndCurrency(o, direction, currencyCode)) .filter(o -> offerMatchesDirectionAndCurrency(o.getOffer(), direction, currencyCode))
.sorted(priceComparator(direction)) .sorted(openOfferPriceComparator(direction, CurrencyUtil.isTraditionalCurrency(currencyCode)))
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
Offer getMyOffer(String id) { OpenOffer getMyOffer(String id) {
return getMyOffers().stream()
.filter(o -> o.getId().equals(id))
.findAny().orElseThrow(() ->
new IllegalStateException(format("offer with id '%s' not found", id)));
}
OpenOffer getMyOpenOffer(String id) {
getMyOffer(id); // ensure offer is valid
return openOfferManager.getOpenOfferById(id) return openOfferManager.getOpenOfferById(id)
.filter(open -> open.getOffer().isMyOffer(keyRing)) .filter(open -> open.getOffer().isMyOffer(keyRing))
.orElseThrow(() -> .orElseThrow(() ->
@ -229,7 +222,7 @@ public class CoreOffersService {
} }
void cancelOffer(String id) { void cancelOffer(String id) {
Offer offer = getMyOffer(id); Offer offer = getMyOffer(id).getOffer();
openOfferManager.removeOffer(offer, openOfferManager.removeOffer(offer,
() -> { () -> {
}, },
@ -303,6 +296,19 @@ public class CoreOffersService {
: priceComparator.get(); : priceComparator.get();
} }
private Comparator<OpenOffer> openOfferPriceComparator(String direction, boolean isTraditional) {
// 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();
}
private long priceStringToLong(String priceAsString, String currencyCode) { private long priceStringToLong(String priceAsString, String currencyCode) {
int precision = CurrencyUtil.isTraditionalCurrency(currencyCode) ? TraditionalMoney.SMALLEST_UNIT_EXPONENT : CryptoMoney.SMALLEST_UNIT_EXPONENT; int precision = CurrencyUtil.isTraditionalCurrency(currencyCode) ? TraditionalMoney.SMALLEST_UNIT_EXPONENT : CryptoMoney.SMALLEST_UNIT_EXPONENT;
double priceAsDouble = new BigDecimal(priceAsString).doubleValue(); double priceAsDouble = new BigDecimal(priceAsString).doubleValue();

View file

@ -209,11 +209,13 @@ public class CurrencyUtil {
public static boolean isFiatCurrency(String currencyCode) { public static boolean isFiatCurrency(String currencyCode) {
if (!isTraditionalCurrency(currencyCode)) return false; if (!isTraditionalCurrency(currencyCode)) return false;
if ("xag".equalsIgnoreCase(currencyCode) || "xau".equalsIgnoreCase(currencyCode)) return false; if ("XAG".equalsIgnoreCase(currencyCode) || "XAU".equalsIgnoreCase(currencyCode)) return false;
return true; return true;
} }
public static boolean isTraditionalCurrency(String currencyCode) { public static boolean isTraditionalCurrency(String currencyCode) {
if (currencyCode != null) currencyCode = currencyCode.toUpperCase();
if (currencyCode != null && isTraditionalCurrencyMap.containsKey(currencyCode)) { if (currencyCode != null && isTraditionalCurrencyMap.containsKey(currencyCode)) {
return isTraditionalCurrencyMap.get(currencyCode); return isTraditionalCurrencyMap.get(currencyCode);
} }
@ -473,18 +475,6 @@ public class CurrencyUtil {
return Res.get("shared.offerVolumeCode", currencyCode); return Res.get("shared.offerVolumeCode", currencyCode);
} }
public static boolean apiSupportsCryptoCurrency(String currencyCode) {
// Although this method is only used by the core.api package, its
// presence here avoids creating a new util class just for this method.
if (isCryptoCurrency(currencyCode))
return currencyCode.equals("BTC")
|| currencyCode.equals("XMR");
else
throw new IllegalArgumentException(
format("Method requires a crypto currency code, but was given '%s'.",
currencyCode));
}
public static List<TradeCurrency> getAllTransferwiseUSDCurrencies() { public static List<TradeCurrency> getAllTransferwiseUSDCurrencies() {
return List.of(new TraditionalCurrency("USD")); return List.of(new TraditionalCurrency("USD"));
} }

View file

@ -1032,7 +1032,6 @@ public class XmrWalletService {
boolean exists = xmrAddressEntryList.getAddressEntriesAsListImmutable().stream().filter(addressEntry -> addressEntry.getAddressString().equals(subaddress.getAddress())).findAny().isPresent(); boolean exists = xmrAddressEntryList.getAddressEntriesAsListImmutable().stream().filter(addressEntry -> addressEntry.getAddressString().equals(subaddress.getAddress())).findAny().isPresent();
if (!exists) { if (!exists) {
XmrAddressEntry entry = new XmrAddressEntry(subaddress.getIndex(), subaddress.getAddress(), subaddress.getIndex() == 0 ? XmrAddressEntry.Context.BASE_ADDRESS : XmrAddressEntry.Context.AVAILABLE, null, null); XmrAddressEntry entry = new XmrAddressEntry(subaddress.getIndex(), subaddress.getAddress(), subaddress.getIndex() == 0 ? XmrAddressEntry.Context.BASE_ADDRESS : XmrAddressEntry.Context.AVAILABLE, null, null);
log.info("Add XmrAddressEntry from existing subaddress: {}", entry);
xmrAddressEntryList.addAddressEntry(entry); xmrAddressEntryList.addAddressEntry(entry);
} }
} }

View file

@ -83,12 +83,11 @@ class GrpcOffersService extends OffersImplBase {
} }
} }
// TODO: merge with getOffer()?
@Override @Override
public void getMyOffer(GetMyOfferRequest req, public void getMyOffer(GetMyOfferRequest req,
StreamObserver<GetMyOfferReply> responseObserver) { StreamObserver<GetMyOfferReply> responseObserver) {
try { try {
OpenOffer openOffer = coreApi.getMyOpenOffer(req.getId()); OpenOffer openOffer = coreApi.getMyOffer(req.getId());
var reply = GetMyOfferReply.newBuilder() var reply = GetMyOfferReply.newBuilder()
.setOffer(OfferInfo.toMyOfferInfo(openOffer).toProtoMessage()) .setOffer(OfferInfo.toMyOfferInfo(openOffer).toProtoMessage())
.build(); .build();
@ -123,9 +122,8 @@ class GrpcOffersService extends OffersImplBase {
StreamObserver<GetMyOffersReply> responseObserver) { StreamObserver<GetMyOffersReply> responseObserver) {
try { try {
List<OfferInfo> result = new ArrayList<OfferInfo>(); List<OfferInfo> result = new ArrayList<OfferInfo>();
for (Offer offer : coreApi.getMyOffers(req.getDirection(), req.getCurrencyCode())) { for (OpenOffer offer : coreApi.getMyOffers(req.getDirection(), req.getCurrencyCode())) {
OpenOffer openOffer = coreApi.getMyOpenOffer(offer.getId()); result.add(OfferInfo.toMyOfferInfo(offer));
result.add(OfferInfo.toMyOfferInfo(openOffer));
} }
var reply = GetMyOffersReply.newBuilder() var reply = GetMyOffersReply.newBuilder()
.addAllOffers(result.stream() .addAllOffers(result.stream()
@ -163,7 +161,7 @@ class GrpcOffersService extends OffersImplBase {
offer -> { offer -> {
// This result handling consumer's accept operation will return // This result handling consumer's accept operation will return
// the new offer to the gRPC client after async placement is done. // the new offer to the gRPC client after async placement is done.
OpenOffer openOffer = coreApi.getMyOpenOffer(offer.getId()); OpenOffer openOffer = coreApi.getMyOffer(offer.getId());
OfferInfo offerInfo = OfferInfo.toMyOfferInfo(openOffer); OfferInfo offerInfo = OfferInfo.toMyOfferInfo(openOffer);
PostOfferReply reply = PostOfferReply.newBuilder() PostOfferReply reply = PostOfferReply.newBuilder()
.setOffer(offerInfo.toProtoMessage()) .setOffer(offerInfo.toProtoMessage())