diff --git a/src/main/java/org/qora/api/resource/AddressesResource.java b/src/main/java/org/qora/api/resource/AddressesResource.java index aab503f5..03759b28 100644 --- a/src/main/java/org/qora/api/resource/AddressesResource.java +++ b/src/main/java/org/qora/api/resource/AddressesResource.java @@ -294,8 +294,8 @@ public class AddressesResource { @GET @Path("/proxying") @Operation( - summary = "List accounts involved in proxy forging, with reward percentage", - description = "Returns list of accounts. At least one of \"proxiedFor\" or \"proxiedBy\" needs to be supplied.", + summary = "List proxy forging relationships", + description = "Returns list of accounts, with reward share percentage and proxy public key.", responses = { @ApiResponse( content = @Content(mediaType = MediaType.APPLICATION_JSON, array = @ArraySchema(schema = @Schema(implementation = ProxyForgerData.class))) @@ -312,9 +312,6 @@ public class AddressesResource { ) @QueryParam("offset") Integer offset, @Parameter( ref = "reverse" ) @QueryParam("reverse") Boolean reverse) { - if (recipients.isEmpty() && forgers.isEmpty()) - throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_CRITERIA); - try (final Repository repository = RepositoryManager.getRepository()) { return repository.getAccountRepository().findProxyAccounts(recipients, forgers, limit, offset, reverse); } catch (DataException e) { diff --git a/src/main/java/org/qora/api/resource/BlocksResource.java b/src/main/java/org/qora/api/resource/BlocksResource.java index 7d292fd1..e73ecbea 100644 --- a/src/main/java/org/qora/api/resource/BlocksResource.java +++ b/src/main/java/org/qora/api/resource/BlocksResource.java @@ -569,6 +569,7 @@ public class BlocksResource { @Path("/forgers") @Operation( summary = "Show summary of block forgers", + description = "Returns count of blocks forged, optionally limited to generators/recipients in passed address(es).", responses = { @ApiResponse( content = @Content( @@ -581,15 +582,20 @@ public class BlocksResource { ) } ) - public List getBlockForgers(@Parameter( - ref = "limit" + public List getBlockForgers(@QueryParam("address") List addresses, + @Parameter( + ref = "limit" ) @QueryParam("limit") Integer limit, @Parameter( ref = "offset" ) @QueryParam("offset") Integer offset, @Parameter( ref = "reverse" ) @QueryParam("reverse") Boolean reverse) { try (final Repository repository = RepositoryManager.getRepository()) { - return repository.getBlockRepository().getBlockForgers(limit, offset, reverse); + for (String address : addresses) + if (!Crypto.isValidAddress(address)) + throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_ADDRESS); + + return repository.getBlockRepository().getBlockForgers(addresses, limit, offset, reverse); } catch (DataException e) { throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e); } diff --git a/src/main/java/org/qora/repository/BlockRepository.java b/src/main/java/org/qora/repository/BlockRepository.java index 459c72ed..e072ff2f 100644 --- a/src/main/java/org/qora/repository/BlockRepository.java +++ b/src/main/java/org/qora/repository/BlockRepository.java @@ -103,9 +103,9 @@ public interface BlockRepository { public int countForgedBlocks(byte[] publicKey) throws DataException; /** - * Returns summaries of block forgers. + * Returns summaries of block forgers, optionally limited to passed addresses. */ - public List getBlockForgers(Integer limit, Integer offset, Boolean reverse) throws DataException; + public List getBlockForgers(List addresses, Integer limit, Integer offset, Boolean reverse) throws DataException; /** * Returns blocks with passed generator public key. diff --git a/src/main/java/org/qora/repository/hsqldb/HSQLDBBlockRepository.java b/src/main/java/org/qora/repository/hsqldb/HSQLDBBlockRepository.java index d8ec9e9c..223bce25 100644 --- a/src/main/java/org/qora/repository/hsqldb/HSQLDBBlockRepository.java +++ b/src/main/java/org/qora/repository/hsqldb/HSQLDBBlockRepository.java @@ -4,6 +4,7 @@ import java.math.BigDecimal; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import org.qora.api.model.BlockForgerSummary; @@ -168,19 +169,28 @@ public class HSQLDBBlockRepository implements BlockRepository { } @Override - public List getBlockForgers(Integer limit, Integer offset, Boolean reverse) throws DataException { + public List getBlockForgers(List addresses, Integer limit, Integer offset, Boolean reverse) throws DataException { String subquerySql = "SELECT generator, COUNT(signature) FROM Blocks GROUP BY generator ORDER BY COUNT(signature) "; if (reverse != null && reverse) subquerySql += " DESC"; - String sql = "SELECT generator, n_blocks, forger, recipient FROM (" + subquerySql + ") AS Forgers (generator, n_blocks) " + String sql = "SELECT DISTINCT generator, n_blocks, forger, recipient FROM (" + subquerySql + ") AS Forgers (generator, n_blocks) " + " LEFT OUTER JOIN ProxyForgers ON proxy_public_key = generator "; + if (addresses != null && !addresses.isEmpty()) { + sql += " LEFT OUTER JOIN Accounts AS GeneratorAccounts ON GeneratorAccounts.public_key = generator " + + " LEFT OUTER JOIN Accounts AS ForgerAccounts ON ForgerAccounts.public_key = forger " + + " JOIN (VALUES " + String.join(", ", Collections.nCopies(addresses.size(), "(?)")) + ") AS FilterAccounts (account) " + + " ON FilterAccounts.account IN (recipient, GeneratorAccounts.account, ForgerAccounts.account) "; + } else { + addresses = Collections.emptyList(); + } + sql += HSQLDBRepository.limitOffsetSql(limit, offset); List summaries = new ArrayList<>(); - try (ResultSet resultSet = this.repository.checkedExecute(sql)) { + try (ResultSet resultSet = this.repository.checkedExecute(sql, addresses.toArray())) { if (resultSet == null) return summaries;