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);
}
public Offer getMyOffer(String id) {
return coreOffersService.getMyOffer(id);
}
public List<Offer> getOffers(String direction, String 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);
}
public OpenOffer getMyOpenOffer(String id) {
return coreOffersService.getMyOpenOffer(id);
public OpenOffer getMyOffer(String id) {
return coreOffersService.getMyOffer(id);
}
public void postOffer(String currencyCode,

View file

@ -64,6 +64,7 @@ import static java.util.Comparator.comparing;
public class CoreOffersService {
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 CoreContext coreContext;
@ -125,31 +126,23 @@ public class CoreOffersService {
new IllegalStateException(format("offer with id '%s' not found", id)));
}
List<Offer> getMyOffers() {
List<Offer> offers = openOfferManager.getOpenOffers().stream()
.map(OpenOffer::getOffer)
.filter(o -> o.isMyOffer(keyRing))
List<OpenOffer> getMyOffers() {
List<OpenOffer> offers = openOfferManager.getOpenOffers().stream()
.filter(o -> o.getOffer().isMyOffer(keyRing))
.collect(Collectors.toList());
offers.removeAll(getOffersWithDuplicateKeyImages(offers));
return 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
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()
.filter(o -> offerMatchesDirectionAndCurrency(o, direction, currencyCode))
.sorted(priceComparator(direction))
.filter(o -> offerMatchesDirectionAndCurrency(o.getOffer(), direction, currencyCode))
.sorted(openOfferPriceComparator(direction, CurrencyUtil.isTraditionalCurrency(currencyCode)))
.collect(Collectors.toList());
}
Offer 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
OpenOffer getMyOffer(String id) {
return openOfferManager.getOpenOfferById(id)
.filter(open -> open.getOffer().isMyOffer(keyRing))
.orElseThrow(() ->
@ -229,7 +222,7 @@ public class CoreOffersService {
}
void cancelOffer(String id) {
Offer offer = getMyOffer(id);
Offer offer = getMyOffer(id).getOffer();
openOfferManager.removeOffer(offer,
() -> {
},
@ -303,6 +296,19 @@ public class CoreOffersService {
: 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) {
int precision = CurrencyUtil.isTraditionalCurrency(currencyCode) ? TraditionalMoney.SMALLEST_UNIT_EXPONENT : CryptoMoney.SMALLEST_UNIT_EXPONENT;
double priceAsDouble = new BigDecimal(priceAsString).doubleValue();

View file

@ -209,11 +209,13 @@ public class CurrencyUtil {
public static boolean isFiatCurrency(String currencyCode) {
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;
}
public static boolean isTraditionalCurrency(String currencyCode) {
if (currencyCode != null) currencyCode = currencyCode.toUpperCase();
if (currencyCode != null && isTraditionalCurrencyMap.containsKey(currencyCode)) {
return isTraditionalCurrencyMap.get(currencyCode);
}
@ -473,18 +475,6 @@ public class CurrencyUtil {
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() {
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();
if (!exists) {
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);
}
}

View file

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