diff --git a/Dockerfile b/Dockerfile index bc2595e..891ef50 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,6 +15,6 @@ RUN mvn -f /home/app/pom.xml clean package -DskipTests FROM openjdk:17.0.2-slim COPY --from=build /home/app/target/serum-data-1.2.0-SNAPSHOT.jar /usr/local/lib/serumdata.jar ENV JAVA_TOOL_OPTIONS -agentlib:jdwp=transport=dt_socket,address=*:8000,server=y,suspend=n -ENV OPENSERUM_ENDPOINT=GENESYSGO +ENV OPENSERUM_ENDPOINT=PROJECT_SERUM EXPOSE 8080 ENTRYPOINT ["java","-jar","/usr/local/lib/serumdata.jar"] \ No newline at end of file diff --git a/src/main/java/com/mmorrell/serumdata/controller/ApiController.java b/src/main/java/com/mmorrell/serumdata/controller/ApiController.java index 5182300..40cf5e9 100644 --- a/src/main/java/com/mmorrell/serumdata/controller/ApiController.java +++ b/src/main/java/com/mmorrell/serumdata/controller/ApiController.java @@ -109,7 +109,8 @@ public List getMarketBids(@PathVariable String marketId, HttpServlet final Optional orderBook = marketManager.getCachedBidOrderBook(marketPublicKey); if (orderBook.isPresent()) { - List serumOrders = MarketUtil.convertOrderBookToSerumOrders(orderBook.get(), true); + boolean isZeta = marketManager.isZetaMarket(marketPublicKey); + List serumOrders = MarketUtil.convertOrderBookToSerumOrders(orderBook.get(), true, isZeta); // Calculate aggregate percentages for each quote, add to metadata float aggregateNotional = serumOrders.stream() @@ -140,7 +141,8 @@ public List getMarketAsks(@PathVariable String marketId, HttpServlet final Optional orderBook = marketManager.getCachedAskOrderBook(marketPublicKey); if (orderBook.isPresent()) { - List serumOrders = MarketUtil.convertOrderBookToSerumOrders(orderBook.get(), false); + boolean isZeta = marketManager.isZetaMarket(marketPublicKey); + List serumOrders = MarketUtil.convertOrderBookToSerumOrders(orderBook.get(), false, isZeta); // Calculate aggregate percentages for each quote, add to metadata float aggregateNotional = serumOrders.stream() @@ -271,8 +273,9 @@ public MarketDepth getMarketDepth(@PathVariable String marketId, HttpServletResp } // isBid = false on the bids since chart JS library expects ascending order - final List bids = MarketUtil.convertOrderBookToSerumOrders(bidOrderBook.get(), false); - final List asks = MarketUtil.convertOrderBookToSerumOrders(askOrderBook.get(), false); + boolean isZeta = marketManager.isZetaMarket(marketPubkey); + final List bids = MarketUtil.convertOrderBookToSerumOrders(bidOrderBook.get(), false, isZeta); + final List asks = MarketUtil.convertOrderBookToSerumOrders(askOrderBook.get(), false, isZeta); float bestBid = bids.size() > 0 ? bidOrderBook.get().getBestBid().getFloatPrice() : 0.0f; float bestAsk = asks.size() > 0 ? askOrderBook.get().getBestAsk().getFloatPrice() : 0.0f; diff --git a/src/main/java/com/mmorrell/serumdata/controller/IndexController.java b/src/main/java/com/mmorrell/serumdata/controller/IndexController.java index 1ad727f..257ce6f 100644 --- a/src/main/java/com/mmorrell/serumdata/controller/IndexController.java +++ b/src/main/java/com/mmorrell/serumdata/controller/IndexController.java @@ -65,6 +65,20 @@ public String markets(Model model) { return "markets"; } + @RequestMapping("/zeta/{market}") + public String zetaMarket(Model model, @PathVariable String market) { + String sanitized = market.replaceAll("[^a-zA-Z\\d]", ""); + PublicKey zetaMarketPublicKey = new PublicKey(sanitized); + + model.addAttribute(DEFAULT_TOKEN_ATTRIBUTE_NAME, DEFAULT_TOKEN_SEARCH.toBase58()); + model.addAttribute("tokens", activeTokenMap); + model.addAttribute(marketRankManager); + + model.addAttribute(MARKET_ID_ATTRIBUTE_NAME, zetaMarketPublicKey.toBase58()); + + return "index"; + } + // for now, return index with the market determined. @RequestMapping("/{market}") public String market(Model model, @PathVariable String market) { diff --git a/src/main/java/com/mmorrell/serumdata/manager/MarketManager.java b/src/main/java/com/mmorrell/serumdata/manager/MarketManager.java index 42ef855..467834a 100644 --- a/src/main/java/com/mmorrell/serumdata/manager/MarketManager.java +++ b/src/main/java/com/mmorrell/serumdata/manager/MarketManager.java @@ -47,6 +47,8 @@ public class MarketManager { private final Map bidOrderBookMinContextSlot = new HashMap<>(); private final Map eventQueueMinContextSlot = new HashMap<>(); + private List zetaAccounts = new ArrayList<>(); + // Caching for individual bid and asks orderbooks. final LoadingCache bidOrderBookLoadingCache = CacheBuilder.newBuilder() .refreshAfterWrite(ORDER_BOOK_CACHE_DURATION_SECONDS, TimeUnit.SECONDS) @@ -204,6 +206,21 @@ public void updateMarkets() { throw new RuntimeException(e); } + try { + List zetaAccounts = new ArrayList<>( + client.getApi().getProgramAccounts( + new PublicKey("zDEXqXEG7gAyxb1Kg9mK5fPnUdENCGKzWrM21RMdWRq"), + Collections.emptyList(), + 1476 + ) + ); + + this.zetaAccounts = zetaAccounts; + programAccounts.addAll(zetaAccounts); + } catch (RpcException e) { + throw new RuntimeException(e); + } + for (ProgramAccount programAccount : programAccounts) { Market market = Market.readMarket(programAccount.getAccount().getDecodedData()); @@ -212,16 +229,22 @@ public void updateMarkets() { continue; } - market.setBaseDecimals( - (byte) tokenManager.getDecimals( - market.getBaseMint() - ) - ); - market.setQuoteDecimals( - (byte) tokenManager.getDecimals( - market.getQuoteMint() - ) - ); + if (!zetaAccounts.contains(programAccount)) { + market.setBaseDecimals( + (byte) tokenManager.getDecimals( + market.getBaseMint() + ) + ); + market.setQuoteDecimals( + (byte) tokenManager.getDecimals( + market.getQuoteMint() + ) + ); + } else { + // zeta, hardcode decimals for poc + market.setBaseDecimals((byte) 0); + market.setQuoteDecimals((byte) 6); + } marketCache.put(market.getOwnAddress(), market); // marketMapCache is a baseMint to List map which powers the token search. @@ -396,4 +419,9 @@ public long getBidContext(PublicKey publicKey) { public long getAskContext(PublicKey publicKey) { return bidOrderBookMinContextSlot.getOrDefault(publicKey, DEFAULT_MIN_CONTEXT_SLOT); } + + public boolean isZetaMarket(PublicKey marketPublicKey) { + return zetaAccounts.stream() + .anyMatch(programAccount -> programAccount.getPubkey().equalsIgnoreCase(marketPublicKey.toBase58())); + } } diff --git a/src/main/java/com/mmorrell/serumdata/util/MarketUtil.java b/src/main/java/com/mmorrell/serumdata/util/MarketUtil.java index bf3520e..ded88fd 100644 --- a/src/main/java/com/mmorrell/serumdata/util/MarketUtil.java +++ b/src/main/java/com/mmorrell/serumdata/util/MarketUtil.java @@ -26,12 +26,12 @@ public class MarketUtil { PublicKey.valueOf("61CjGbapEVoyCC51x5tPZGZHCYsgtPSSssCatHEEUWeG"); - public static List convertOrderBookToSerumOrders(OrderBook orderBook, boolean isBid) { + public static List convertOrderBookToSerumOrders(OrderBook orderBook, boolean isBid, boolean isZeta) { return orderBook.getOrders().stream() .map(order -> { SerumOrder serumOrder = new SerumOrder(); serumOrder.setPrice(order.getFloatPrice()); - serumOrder.setQuantity(order.getFloatQuantity()); + serumOrder.setQuantity(isZeta ? order.getFloatQuantity() / 1000 : order.getFloatQuantity()); serumOrder.setOwner(order.getOwner()); return serumOrder; }) diff --git a/src/main/resources/templates/index.jsp b/src/main/resources/templates/index.jsp index fd45cbf..a1c4377 100644 --- a/src/main/resources/templates/index.jsp +++ b/src/main/resources/templates/index.jsp @@ -5,32 +5,32 @@ Openserum - Project Serum Market Data - + - - - + + + - - + + - - + + - - + + - + - - - + + + - + - + + - - + + +