From 0b40276a4c9dc6e168face165e5d4c50206b3b1d Mon Sep 17 00:00:00 2001 From: HenrikJannsen Date: Sun, 21 Jul 2024 19:55:23 +0700 Subject: [PATCH] Add check if dao is ready. Improve getBisqTxForAddr and fix nullpointer Signed-off-by: HenrikJannsen --- .../src/main/java/bisq/restapi/RestApi.java | 18 ++++++++++++ .../restapi/endpoints/ExplorerBlocksApi.java | 5 +++- .../restapi/endpoints/ExplorerDaoApi.java | 5 +++- .../endpoints/ExplorerTransactionsApi.java | 29 ++++++++++++------- 4 files changed, 44 insertions(+), 13 deletions(-) diff --git a/restapi/src/main/java/bisq/restapi/RestApi.java b/restapi/src/main/java/bisq/restapi/RestApi.java index e992b6cca2..ad68481293 100644 --- a/restapi/src/main/java/bisq/restapi/RestApi.java +++ b/restapi/src/main/java/bisq/restapi/RestApi.java @@ -26,8 +26,10 @@ import bisq.core.dao.governance.bond.role.BondedRolesRepository; import bisq.core.dao.governance.period.CycleService; import bisq.core.dao.governance.proposal.ProposalService; +import bisq.core.dao.state.DaoStateListener; import bisq.core.dao.state.DaoStateService; import bisq.core.dao.state.DaoStateSnapshotService; +import bisq.core.dao.state.model.blockchain.Block; import bisq.core.offer.OfferBookService; import bisq.core.provider.price.PriceFeedService; import bisq.core.trade.statistics.TradeStatisticsManager; @@ -39,6 +41,8 @@ import lombok.Getter; import lombok.extern.slf4j.Slf4j; +import static com.google.common.base.Preconditions.checkArgument; + @Slf4j public class RestApi extends ExecutableForAppWithP2p { @Getter @@ -64,6 +68,8 @@ public class RestApi extends ExecutableForAppWithP2p { @Getter private OfferBookService offerBookService; private PriceFeedService priceFeedService; + @Getter + private boolean parseBlockCompleteAfterBatchProcessing; public RestApi() { super("Bisq Rest Api", "bisq_restapi", "bisq_restapi", Version.VERSION); @@ -97,6 +103,14 @@ protected void applyInjector() { tradeStatisticsManager = injector.getInstance(TradeStatisticsManager.class); offerBookService = injector.getInstance(OfferBookService.class); priceFeedService = injector.getInstance(PriceFeedService.class); + + daoStateService.addDaoStateListener(new DaoStateListener() { + @Override + public void onParseBlockCompleteAfterBatchProcessing(Block block) { + log.error("onParseBlockCompleteAfterBatchProcessing"); + parseBlockCompleteAfterBatchProcessing = true; + } + }); } @Override @@ -114,4 +128,8 @@ protected void onHiddenServicePublished() { priceFeedService.setCurrencyCodeOnInit(); priceFeedService.initialRequestPriceFeed(); } + + public void checkDaoReady() { + checkArgument(parseBlockCompleteAfterBatchProcessing, "DAO not ready yet"); + } } diff --git a/restapi/src/main/java/bisq/restapi/endpoints/ExplorerBlocksApi.java b/restapi/src/main/java/bisq/restapi/endpoints/ExplorerBlocksApi.java index f7b159698e..2d65506f10 100644 --- a/restapi/src/main/java/bisq/restapi/endpoints/ExplorerBlocksApi.java +++ b/restapi/src/main/java/bisq/restapi/endpoints/ExplorerBlocksApi.java @@ -36,9 +36,10 @@ @Tag(name = "BLOCKS API") public class ExplorerBlocksApi { private final DaoStateService daoStateService; + private final RestApi restApi; public ExplorerBlocksApi(@Context Application application) { - RestApi restApi = ((RestApiMain) application).getRestApi(); + restApi = ((RestApiMain) application).getRestApi(); daoStateService = restApi.getDaoStateService(); } @@ -51,6 +52,7 @@ public ExplorerBlocksApi(@Context Application application) { @GET @Path("get-bsq-block-by-height/{block-height}") public JsonBlock getBsqBlockByHeight(@Parameter(description = "Block Height") @PathParam("block-height") int blockHeight) { + restApi.checkDaoReady(); List blocks = daoStateService.getBlocks(); Optional jsonBlock = checkNotNull(blocks.stream()) .filter(block -> block.getHeight() == blockHeight) @@ -68,6 +70,7 @@ public JsonBlock getBsqBlockByHeight(@Parameter(description = "Block Height") @P @GET @Path("get-bsq-block-by-hash/{block-hash}") public JsonBlock getBsqBlockByHash(@Parameter(description = "Block Hash") @PathParam("block-hash") String hash) { + restApi.checkDaoReady(); List blocks = daoStateService.getBlocks(); Optional jsonBlock = checkNotNull(blocks.stream()) .filter(block -> block.getHash().equalsIgnoreCase(hash)) diff --git a/restapi/src/main/java/bisq/restapi/endpoints/ExplorerDaoApi.java b/restapi/src/main/java/bisq/restapi/endpoints/ExplorerDaoApi.java index 662a9b4e03..8c761cd138 100644 --- a/restapi/src/main/java/bisq/restapi/endpoints/ExplorerDaoApi.java +++ b/restapi/src/main/java/bisq/restapi/endpoints/ExplorerDaoApi.java @@ -41,9 +41,10 @@ public class ExplorerDaoApi { private final DaoFacade daoFacade; private final ProposalService proposalService; private final CycleService cycleService; + private final RestApi restApi; public ExplorerDaoApi(@Context Application application) { - RestApi restApi = ((RestApiMain) application).getRestApi(); + restApi = ((RestApiMain) application).getRestApi(); daoStateService = restApi.getDaoStateService(); proposalService = restApi.getProposalService(); cycleService = restApi.getCycleService(); @@ -54,6 +55,7 @@ public ExplorerDaoApi(@Context Application application) { @GET @Path("get-bsq-stats") public BsqStatsDto getBsqStats() { + restApi.checkDaoReady(); long genesisSupply = daoFacade.getGenesisTotalSupply().getValue(); long issuedByCompensations = daoStateService.getIssuanceSetForType(IssuanceType.COMPENSATION).stream().mapToLong(Issuance::getAmount).sum(); long issuedByReimbursements = daoStateService.getIssuanceSetForType(IssuanceType.REIMBURSEMENT).stream().mapToLong(Issuance::getAmount).sum(); @@ -70,6 +72,7 @@ public BsqStatsDto getBsqStats() { @GET @Path("query-dao-cycles") public List queryDaoCycles() { + restApi.checkDaoReady(); Set cyclesAdded = new HashSet<>(); List result = new ArrayList<>(); // Creating our data structure is a bit expensive so we ensure to only create the CycleListItems once. diff --git a/restapi/src/main/java/bisq/restapi/endpoints/ExplorerTransactionsApi.java b/restapi/src/main/java/bisq/restapi/endpoints/ExplorerTransactionsApi.java index 2ba57bb0e7..3ce58aabdf 100644 --- a/restapi/src/main/java/bisq/restapi/endpoints/ExplorerTransactionsApi.java +++ b/restapi/src/main/java/bisq/restapi/endpoints/ExplorerTransactionsApi.java @@ -22,12 +22,11 @@ import bisq.core.dao.state.model.blockchain.Tx; import bisq.core.dao.state.model.blockchain.TxType; -import java.util.ArrayList; +import java.util.Collection; import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.Optional; -import java.util.Set; import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; @@ -54,9 +53,10 @@ @Tag(name = "TRANSACTIONS API") public class ExplorerTransactionsApi { private final DaoStateService daoStateService; + private final RestApi restApi; public ExplorerTransactionsApi(@Context Application application) { - RestApi restApi = ((RestApiMain) application).getRestApi(); + restApi = ((RestApiMain) application).getRestApi(); daoStateService = restApi.getDaoStateService(); } @@ -64,6 +64,7 @@ public ExplorerTransactionsApi(@Context Application application) { @Path("get-bsq-tx/{txid}") public JsonTx getTx(@Parameter(description = "TxId") @PathParam("txid") String txId) { + restApi.checkDaoReady(); Optional jsonTx = daoStateService.getUnorderedTxStream() .filter(t -> t.getId().equals(txId)) .map(tx -> BlockDataToJsonConverter.getJsonTx(daoStateService, tx)) @@ -79,14 +80,19 @@ public JsonTx getTx(@Parameter(description = "TxId") @GET @Path("get-bsq-tx-for-addr/{addr}") public List getBisqTxForAddr(@PathParam("addr") String address) { - Map> addressToTxIds = daoStateService.getTxIdSetByAddress(); - List result = new ArrayList<>(); - Set strings = addressToTxIds.get(address); - strings.forEach(txId -> { - daoStateService.getTx(txId).stream() - .map(tx -> BlockDataToJsonConverter.getJsonTx(daoStateService, tx)) - .forEach(result::add); - }); + restApi.checkDaoReady(); + // In case we get a prefixed address marking BSQ addresses we remove the prefix + if (address.startsWith("B")) { + address = address.substring(1, address.length()); + } + String finalAddress = address; + List result = daoStateService.getTxIdSetByAddress().entrySet().stream() + .filter(e -> e.getKey().equals(finalAddress)) + .map(Map.Entry::getValue) + .flatMap(Collection::stream) + .flatMap(txId -> daoStateService.getTx(txId).stream()) + .map(tx -> BlockDataToJsonConverter.getJsonTx(daoStateService, tx)) + .collect(Collectors.toList()); log.info("getBisqTxForAddr: returning {} items.", result.size()); return result; } @@ -96,6 +102,7 @@ public List getBisqTxForAddr(@PathParam("addr") String address) { public List queryTxsPaginated(@PathParam("start") int start, @PathParam("count") int count, @PathParam("filters") String filters) { + restApi.checkDaoReady(); log.info("filters: {}", filters); List jsonTxs = daoStateService.getUnorderedTxStream() .sorted(Comparator.comparing(BaseTx::getTime).reversed())