mirror of
https://github.com/Qortal/qortal.git
synced 2025-02-18 21:25:47 +00:00
added 2 endpoints providing sponsorship analytics
This commit is contained in:
parent
f14bc86b39
commit
d976904a8e
@ -23,6 +23,7 @@ import org.qortal.crypto.Crypto;
|
|||||||
import org.qortal.data.account.AccountData;
|
import org.qortal.data.account.AccountData;
|
||||||
import org.qortal.data.account.AccountPenaltyData;
|
import org.qortal.data.account.AccountPenaltyData;
|
||||||
import org.qortal.data.account.RewardShareData;
|
import org.qortal.data.account.RewardShareData;
|
||||||
|
import org.qortal.data.account.SponsorshipReport;
|
||||||
import org.qortal.data.network.OnlineAccountData;
|
import org.qortal.data.network.OnlineAccountData;
|
||||||
import org.qortal.data.network.OnlineAccountLevel;
|
import org.qortal.data.network.OnlineAccountLevel;
|
||||||
import org.qortal.data.transaction.PublicizeTransactionData;
|
import org.qortal.data.transaction.PublicizeTransactionData;
|
||||||
@ -52,6 +53,7 @@ import java.math.BigDecimal;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Path("/addresses")
|
@Path("/addresses")
|
||||||
@ -630,4 +632,70 @@ public class AddressesResource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("/sponsorship/{address}")
|
||||||
|
@Operation(
|
||||||
|
summary = "Returns sponsorship statistics for an account",
|
||||||
|
description = "Returns sponsorship statistics for an account",
|
||||||
|
responses = {
|
||||||
|
@ApiResponse(
|
||||||
|
description = "the statistics",
|
||||||
|
content = @Content(mediaType = MediaType.APPLICATION_JSON, array = @ArraySchema(schema = @Schema(implementation = SponsorshipReport.class)))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
@ApiErrors({ApiError.INVALID_ADDRESS, ApiError.ADDRESS_UNKNOWN, ApiError.REPOSITORY_ISSUE})
|
||||||
|
public SponsorshipReport getSponsorshipReport(@PathParam("address") String address) {
|
||||||
|
if (!Crypto.isValidAddress(address))
|
||||||
|
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_ADDRESS);
|
||||||
|
|
||||||
|
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||||
|
SponsorshipReport report = repository.getAccountRepository().getSponsorshipReport(address);
|
||||||
|
// Not found?
|
||||||
|
if (report == null)
|
||||||
|
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.ADDRESS_UNKNOWN);
|
||||||
|
|
||||||
|
return report;
|
||||||
|
} catch (DataException e) {
|
||||||
|
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("/sponsorship/{address}/sponsor")
|
||||||
|
@Operation(
|
||||||
|
summary = "Returns sponsorship statistics for an account's sponsor",
|
||||||
|
description = "Returns sponsorship statistics for an account's sponsor",
|
||||||
|
responses = {
|
||||||
|
@ApiResponse(
|
||||||
|
description = "the statistics",
|
||||||
|
content = @Content(mediaType = MediaType.APPLICATION_JSON, array = @ArraySchema(schema = @Schema(implementation = SponsorshipReport.class)))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
@ApiErrors({ApiError.INVALID_ADDRESS, ApiError.ADDRESS_UNKNOWN, ApiError.REPOSITORY_ISSUE})
|
||||||
|
public SponsorshipReport getSponsorshipReportForSponsor(@PathParam("address") String address) {
|
||||||
|
if (!Crypto.isValidAddress(address))
|
||||||
|
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_ADDRESS);
|
||||||
|
|
||||||
|
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||||
|
|
||||||
|
// get sponsor
|
||||||
|
Optional<String> sponsor = repository.getAccountRepository().getSponsor(address);
|
||||||
|
|
||||||
|
// if there is not sponsor, throw error
|
||||||
|
if(sponsor.isEmpty()) throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.ADDRESS_UNKNOWN);
|
||||||
|
|
||||||
|
// get report for sponsor
|
||||||
|
SponsorshipReport report = repository.getAccountRepository().getSponsorshipReport(sponsor.get());
|
||||||
|
|
||||||
|
// Not found?
|
||||||
|
if (report == null)
|
||||||
|
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.ADDRESS_UNKNOWN);
|
||||||
|
|
||||||
|
return report;
|
||||||
|
} catch (DataException e) {
|
||||||
|
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
148
src/main/java/org/qortal/data/account/SponsorshipReport.java
Normal file
148
src/main/java/org/qortal/data/account/SponsorshipReport.java
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
package org.qortal.data.account;
|
||||||
|
|
||||||
|
import javax.xml.bind.annotation.XmlAccessType;
|
||||||
|
import javax.xml.bind.annotation.XmlAccessorType;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
// All properties to be converted to JSON via JAXB
|
||||||
|
@XmlAccessorType(XmlAccessType.FIELD)
|
||||||
|
public class SponsorshipReport {
|
||||||
|
|
||||||
|
private String address;
|
||||||
|
|
||||||
|
private int level;
|
||||||
|
|
||||||
|
private int blocksMinted;
|
||||||
|
|
||||||
|
private int adjustments;
|
||||||
|
|
||||||
|
private int penalties;
|
||||||
|
|
||||||
|
private String[] names;
|
||||||
|
|
||||||
|
private int sponseeCount;
|
||||||
|
|
||||||
|
private int nonRegisteredCount;
|
||||||
|
|
||||||
|
private int avgBalance;
|
||||||
|
|
||||||
|
private int arbitraryCount;
|
||||||
|
|
||||||
|
private int transferAssetCount;
|
||||||
|
|
||||||
|
private int sellCount;
|
||||||
|
|
||||||
|
private int sellAmount;
|
||||||
|
|
||||||
|
private int buyCount;
|
||||||
|
|
||||||
|
private int buyAmount;
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
// For JAXB
|
||||||
|
protected SponsorshipReport() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public SponsorshipReport(String address, int level, int blocksMinted, int adjustments, int penalties, String[] names, int sponseeCount, int nonRegisteredCount, int avgBalance, int arbitraryCount, int transferAssetCount, int sellCount, int sellAmount, int buyCount, int buyAmount) {
|
||||||
|
this.address = address;
|
||||||
|
this.level = level;
|
||||||
|
this.blocksMinted = blocksMinted;
|
||||||
|
this.adjustments = adjustments;
|
||||||
|
this.penalties = penalties;
|
||||||
|
this.names = names;
|
||||||
|
this.sponseeCount = sponseeCount;
|
||||||
|
this.nonRegisteredCount = nonRegisteredCount;
|
||||||
|
this.avgBalance = avgBalance;
|
||||||
|
this.arbitraryCount = arbitraryCount;
|
||||||
|
this.transferAssetCount = transferAssetCount;
|
||||||
|
this.sellCount = sellCount;
|
||||||
|
this.sellAmount = sellAmount;
|
||||||
|
this.buyCount = buyCount;
|
||||||
|
this.buyAmount = buyAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Getters / setters
|
||||||
|
|
||||||
|
|
||||||
|
public String getAddress() {
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLevel() {
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBlocksMinted() {
|
||||||
|
return blocksMinted;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAdjustments() {
|
||||||
|
return adjustments;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPenalties() {
|
||||||
|
return penalties;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] getNames() {
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSponseeCount() {
|
||||||
|
return sponseeCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNonRegisteredCount() {
|
||||||
|
return nonRegisteredCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAvgBalance() {
|
||||||
|
return avgBalance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getArbitraryCount() {
|
||||||
|
return arbitraryCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTransferAssetCount() {
|
||||||
|
return transferAssetCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSellCount() {
|
||||||
|
return sellCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSellAmount() {
|
||||||
|
return sellAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBuyCount() {
|
||||||
|
return buyCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBuyAmount() {
|
||||||
|
return buyAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "SponsorshipReport{" +
|
||||||
|
"address='" + address + '\'' +
|
||||||
|
", level=" + level +
|
||||||
|
", blocksMinted=" + blocksMinted +
|
||||||
|
", adjustments=" + adjustments +
|
||||||
|
", penalties=" + penalties +
|
||||||
|
", names=" + Arrays.toString(names) +
|
||||||
|
", sponseeCount=" + sponseeCount +
|
||||||
|
", nonRegisteredCount=" + nonRegisteredCount +
|
||||||
|
", avgBalance=" + avgBalance +
|
||||||
|
", arbitraryCount=" + arbitraryCount +
|
||||||
|
", transferAssetCount=" + transferAssetCount +
|
||||||
|
", sellCount=" + sellCount +
|
||||||
|
", sellAmount=" + sellAmount +
|
||||||
|
", buyCount=" + buyCount +
|
||||||
|
", buyAmount=" + buyAmount +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,7 @@ package org.qortal.repository;
|
|||||||
import org.qortal.data.account.*;
|
import org.qortal.data.account.*;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public interface AccountRepository {
|
public interface AccountRepository {
|
||||||
@ -131,6 +132,39 @@ public interface AccountRepository {
|
|||||||
/** Returns all account balances for given assetID, optionally excluding zero balances. */
|
/** Returns all account balances for given assetID, optionally excluding zero balances. */
|
||||||
public List<AccountBalanceData> getAssetBalances(long assetId, Boolean excludeZero) throws DataException;
|
public List<AccountBalanceData> getAssetBalances(long assetId, Boolean excludeZero) throws DataException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Sponsorship Report
|
||||||
|
*
|
||||||
|
* @param address the sponsor's account address
|
||||||
|
*
|
||||||
|
* @return the report
|
||||||
|
*
|
||||||
|
* @throws DataException
|
||||||
|
*/
|
||||||
|
public SponsorshipReport getSponsorshipReport(String address) throws DataException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Sponsee Addresses
|
||||||
|
*
|
||||||
|
* @param account the sponsor's account address
|
||||||
|
*
|
||||||
|
* @return the sponsee addresses
|
||||||
|
*
|
||||||
|
* @throws DataException
|
||||||
|
*/
|
||||||
|
public List<String> getSponseeAddresses(String account) throws DataException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Sponsor
|
||||||
|
*
|
||||||
|
* @param address the address of the account
|
||||||
|
*
|
||||||
|
* @return the address of accounts sponsor, empty if not sponsored
|
||||||
|
*
|
||||||
|
* @throws DataException
|
||||||
|
*/
|
||||||
|
public Optional<String> getSponsor(String address) throws DataException;
|
||||||
|
|
||||||
/** How to order results when fetching asset balances. */
|
/** How to order results when fetching asset balances. */
|
||||||
public enum BalanceOrdering {
|
public enum BalanceOrdering {
|
||||||
/** assetID first, then balance, then account address */
|
/** assetID first, then balance, then account address */
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package org.qortal.repository.hsqldb;
|
package org.qortal.repository.hsqldb;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.qortal.asset.Asset;
|
import org.qortal.asset.Asset;
|
||||||
import org.qortal.data.account.*;
|
import org.qortal.data.account.*;
|
||||||
import org.qortal.repository.AccountRepository;
|
import org.qortal.repository.AccountRepository;
|
||||||
@ -8,7 +10,11 @@ import org.qortal.repository.DataException;
|
|||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@ -16,12 +22,15 @@ import static org.qortal.utils.Amounts.prettyAmount;
|
|||||||
|
|
||||||
public class HSQLDBAccountRepository implements AccountRepository {
|
public class HSQLDBAccountRepository implements AccountRepository {
|
||||||
|
|
||||||
|
public static final String SELL = "sell";
|
||||||
|
public static final String BUY = "buy";
|
||||||
protected HSQLDBRepository repository;
|
protected HSQLDBRepository repository;
|
||||||
|
|
||||||
public HSQLDBAccountRepository(HSQLDBRepository repository) {
|
public HSQLDBAccountRepository(HSQLDBRepository repository) {
|
||||||
this.repository = repository;
|
this.repository = repository;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected static final Logger LOGGER = LogManager.getLogger(HSQLDBAccountRepository.class);
|
||||||
// General account
|
// General account
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -1147,4 +1156,324 @@ public class HSQLDBAccountRepository implements AccountRepository {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SponsorshipReport getSponsorshipReport(String account) throws DataException {
|
||||||
|
|
||||||
|
try {
|
||||||
|
ResultSet accountResultSet = getAccountResultSet(account);
|
||||||
|
|
||||||
|
if( accountResultSet == null ) throw new DataException("Unable to fetch account info from repository");
|
||||||
|
|
||||||
|
int level = accountResultSet.getInt(2);
|
||||||
|
int blocksMinted = accountResultSet.getInt(3);
|
||||||
|
int adjustments = accountResultSet.getInt(4);
|
||||||
|
int penalties = accountResultSet.getInt(5);
|
||||||
|
|
||||||
|
List<String> sponseeAddresses = getSponseeAddresses(account);
|
||||||
|
|
||||||
|
if( sponseeAddresses.isEmpty() ){
|
||||||
|
return new SponsorshipReport(account, level, blocksMinted, adjustments, penalties, new String[0], 0, 0, 0, 0, 0, 0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return produceSponsorShipReport(account, level, blocksMinted, adjustments, penalties, sponseeAddresses);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
LOGGER.error(e.getMessage(), e);
|
||||||
|
throw new DataException("Unable to fetch account info from repository", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getSponseeAddresses(String account) throws DataException {
|
||||||
|
StringBuffer sponseeSql = new StringBuffer();
|
||||||
|
|
||||||
|
sponseeSql.append( "SELECT DISTINCT t.recipient sponsees " );
|
||||||
|
sponseeSql.append( "FROM REWARDSHARETRANSACTIONS t ");
|
||||||
|
sponseeSql.append( "INNER JOIN ACCOUNTS a on t.minter_public_key = a.public_key ");
|
||||||
|
sponseeSql.append( "WHERE account = ? and t.recipient != a.account");
|
||||||
|
|
||||||
|
try {
|
||||||
|
ResultSet sponseeResultSet = this.repository.checkedExecute(sponseeSql.toString(), account);
|
||||||
|
|
||||||
|
List<String> sponseeAddresses;
|
||||||
|
|
||||||
|
if( sponseeResultSet == null ) {
|
||||||
|
sponseeAddresses = new ArrayList<>(0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sponseeAddresses = new ArrayList<>();
|
||||||
|
|
||||||
|
do {
|
||||||
|
sponseeAddresses.add(sponseeResultSet.getString(1));
|
||||||
|
} while (sponseeResultSet.next());
|
||||||
|
}
|
||||||
|
|
||||||
|
return sponseeAddresses;
|
||||||
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
|
throw new DataException("can't get sponsees from blockchain data", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<String> getSponsor(String address) throws DataException {
|
||||||
|
|
||||||
|
StringBuffer sponsorSql = new StringBuffer();
|
||||||
|
|
||||||
|
sponsorSql.append( "SELECT DISTINCT account, level, blocks_minted, blocks_minted_adjustment, blocks_minted_penalty ");
|
||||||
|
sponsorSql.append( "FROM REWARDSHARETRANSACTIONS t ");
|
||||||
|
sponsorSql.append( "INNER JOIN ACCOUNTS a on a.public_key = t.minter_public_key ");
|
||||||
|
sponsorSql.append( "WHERE recipient = ? and recipient != account ");
|
||||||
|
|
||||||
|
try {
|
||||||
|
ResultSet sponseeResultSet = this.repository.checkedExecute(sponsorSql.toString(), address);
|
||||||
|
|
||||||
|
if( sponseeResultSet == null ){
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return Optional.ofNullable( sponseeResultSet.getString(1));
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new DataException("can't get sponsor from blockchain data", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Produce Sponsorship Report
|
||||||
|
*
|
||||||
|
* @param address the account address for the sponsor
|
||||||
|
* @param level the sponsor's level
|
||||||
|
* @param blocksMinted the blocks minted by the sponsor
|
||||||
|
* @param blocksMintedAdjustment
|
||||||
|
* @param blocksMintedPenalty
|
||||||
|
* @param sponseeAddresses
|
||||||
|
*
|
||||||
|
* @return the report
|
||||||
|
*
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
|
private SponsorshipReport produceSponsorShipReport(
|
||||||
|
String address,
|
||||||
|
int level,
|
||||||
|
int blocksMinted,
|
||||||
|
int blocksMintedAdjustment,
|
||||||
|
int blocksMintedPenalty,
|
||||||
|
List<String> sponseeAddresses) throws SQLException {
|
||||||
|
|
||||||
|
int sponseeCount = sponseeAddresses.size();
|
||||||
|
|
||||||
|
// get the registered nanmes of the sponsees
|
||||||
|
ResultSet namesResultSet = getNamesResultSet(sponseeAddresses, sponseeCount);
|
||||||
|
List<String> sponseeNames = getNames(namesResultSet, sponseeCount);
|
||||||
|
|
||||||
|
// get the average balance of the sponsees
|
||||||
|
ResultSet avgBalanceResultSet = getAverageBalanceResultSet(sponseeAddresses, sponseeCount);
|
||||||
|
int avgBalance = avgBalanceResultSet.getInt(1);
|
||||||
|
|
||||||
|
// count the arbitrary and transfer asset transactions for all sponsees
|
||||||
|
ResultSet txTypeResultSet = getTxTypeResultSet(sponseeAddresses, sponseeCount);
|
||||||
|
|
||||||
|
int arbitraryCount = 0;
|
||||||
|
int transferAssetCount = 0;
|
||||||
|
|
||||||
|
if( txTypeResultSet != null) {
|
||||||
|
int txType = txTypeResultSet.getInt(1);
|
||||||
|
|
||||||
|
// if arbitrary transaction type, then get the count and move to the next result
|
||||||
|
if (txType == 10) {
|
||||||
|
arbitraryCount = txTypeResultSet.getInt(2);
|
||||||
|
|
||||||
|
// if there is another result, then get
|
||||||
|
if (txTypeResultSet.next())
|
||||||
|
txType = txTypeResultSet.getInt(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if asset transfer type, then get the count and move to the next result
|
||||||
|
if (txType == 12) {
|
||||||
|
transferAssetCount = txTypeResultSet.getInt(2);
|
||||||
|
txTypeResultSet.next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// count up the each the buy and sell foreign coin exchanges for all sponsees
|
||||||
|
// also sum up the balances of these exchanges
|
||||||
|
ResultSet buySellResultSet = getBuySellResultSet(sponseeAddresses, sponseeCount);
|
||||||
|
|
||||||
|
// if there are results, then fill in the buy/sell amount/counts
|
||||||
|
if( buySellResultSet != null ) {
|
||||||
|
|
||||||
|
Map<String, Integer> countsByDirection = new HashMap<>(2);
|
||||||
|
Map<String, Integer> amountsByDirection = new HashMap<>(2);
|
||||||
|
|
||||||
|
do{
|
||||||
|
String direction = buySellResultSet.getString(1).trim();
|
||||||
|
|
||||||
|
if( direction != null ) {
|
||||||
|
countsByDirection.put(direction, buySellResultSet.getInt(2));
|
||||||
|
amountsByDirection.put(direction, buySellResultSet.getInt(3));
|
||||||
|
}
|
||||||
|
} while( buySellResultSet.next());
|
||||||
|
|
||||||
|
|
||||||
|
int sellCount = countsByDirection.getOrDefault(SELL, 0);
|
||||||
|
int sellAmount = amountsByDirection.getOrDefault(SELL, 0);
|
||||||
|
|
||||||
|
int buyCount = countsByDirection.getOrDefault(BUY, 0);
|
||||||
|
int buyAmount = amountsByDirection.getOrDefault(BUY, 0);
|
||||||
|
|
||||||
|
return new SponsorshipReport(
|
||||||
|
address,
|
||||||
|
level,
|
||||||
|
blocksMinted,
|
||||||
|
blocksMintedAdjustment,
|
||||||
|
blocksMintedPenalty,
|
||||||
|
sponseeNames.toArray(new String[sponseeNames.size()]),
|
||||||
|
sponseeCount,
|
||||||
|
sponseeCount - sponseeNames.size(),
|
||||||
|
avgBalance,
|
||||||
|
arbitraryCount,
|
||||||
|
transferAssetCount,
|
||||||
|
sellCount,
|
||||||
|
sellAmount,
|
||||||
|
buyCount,
|
||||||
|
buyAmount);
|
||||||
|
|
||||||
|
}
|
||||||
|
// otherwise use zeros for the counts and amounts
|
||||||
|
|
||||||
|
return new SponsorshipReport(
|
||||||
|
address,
|
||||||
|
level,
|
||||||
|
blocksMinted,
|
||||||
|
blocksMintedAdjustment,
|
||||||
|
blocksMintedPenalty,
|
||||||
|
sponseeNames.toArray(new String[sponseeNames.size()]),
|
||||||
|
sponseeCount,
|
||||||
|
sponseeCount - sponseeNames.size(),
|
||||||
|
avgBalance,
|
||||||
|
arbitraryCount,
|
||||||
|
transferAssetCount,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ResultSet getBuySellResultSet(List<String> sponseeAddresses, int sponseeCount) throws SQLException {
|
||||||
|
StringBuffer buySellSql = new StringBuffer();
|
||||||
|
buySellSql.append("SELECT ");
|
||||||
|
buySellSql.append("CASE ");
|
||||||
|
buySellSql.append(" WHEN participant = account THEN 'sell' ");
|
||||||
|
buySellSql.append(" WHEN participant != account THEN 'buy' ");
|
||||||
|
buySellSql.append("END AS direction, ");
|
||||||
|
buySellSql.append(" COUNT(*) as transactions, sum(tx.amount)/100000000 as amount ");
|
||||||
|
buySellSql.append("FROM TRANSACTIONPARTICIPANTS ");
|
||||||
|
buySellSql.append("INNER JOIN ATTRANSACTIONS tx using (signature) ");
|
||||||
|
buySellSql.append("INNER JOIN ATS ats using (at_address) ");
|
||||||
|
buySellSql.append("INNER JOIN ACCOUNTS a on ats.creator = a.public_key ");
|
||||||
|
buySellSql.append("WHERE participant in ( ");
|
||||||
|
buySellSql.append(String.join(", ", Collections.nCopies(sponseeCount, "?")));
|
||||||
|
buySellSql.append(") ");
|
||||||
|
buySellSql.append("GROUP BY ");
|
||||||
|
buySellSql.append("CASE ");
|
||||||
|
buySellSql.append(" WHEN participant = account THEN 'sell' ");
|
||||||
|
buySellSql.append(" WHEN participant != account THEN 'buy' ");
|
||||||
|
buySellSql.append("END; ");
|
||||||
|
|
||||||
|
String[] sponsees = sponseeAddresses.toArray(new String[sponseeCount]);
|
||||||
|
ResultSet buySellResultSet = this.repository.checkedExecute(buySellSql.toString(), sponsees);
|
||||||
|
|
||||||
|
return buySellResultSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ResultSet getAccountResultSet(String account) throws SQLException {
|
||||||
|
|
||||||
|
StringBuffer accountSql = new StringBuffer();
|
||||||
|
|
||||||
|
accountSql.append( "SELECT DISTINCT account, level, blocks_minted, blocks_minted_adjustment, blocks_minted_penalty ");
|
||||||
|
accountSql.append( "FROM ACCOUNTS ");
|
||||||
|
accountSql.append( "WHERE account = ? ");
|
||||||
|
|
||||||
|
ResultSet accountResultSet = this.repository.checkedExecute( accountSql.toString(), account);
|
||||||
|
|
||||||
|
return accountResultSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private ResultSet getTxTypeResultSet(List<String> sponseeAddresses, int sponseeCount) throws SQLException {
|
||||||
|
StringBuffer txTypeTotalsSql = new StringBuffer();
|
||||||
|
// Transaction Types, int values
|
||||||
|
// ARBITRARY = 10
|
||||||
|
// TRANSFER_ASSET = 12
|
||||||
|
// txTypeTotalsSql.append("
|
||||||
|
txTypeTotalsSql.append("SELECT type, count(*) ");
|
||||||
|
txTypeTotalsSql.append("FROM TRANSACTIONPARTICIPANTS ");
|
||||||
|
txTypeTotalsSql.append("INNER JOIN TRANSACTIONS USING (signature) ");
|
||||||
|
txTypeTotalsSql.append("where participant in ( ");
|
||||||
|
txTypeTotalsSql.append(String.join(", ", Collections.nCopies(sponseeCount, "?")));
|
||||||
|
txTypeTotalsSql.append(") and type in (10, 12) ");
|
||||||
|
txTypeTotalsSql.append("group by type order by type");
|
||||||
|
|
||||||
|
String[] sponsees = sponseeAddresses.toArray(new String[sponseeCount]);
|
||||||
|
ResultSet txTypeResultSet = this.repository.checkedExecute(txTypeTotalsSql.toString(), sponsees);
|
||||||
|
return txTypeResultSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ResultSet getAverageBalanceResultSet(List<String> sponseeAddresses, int sponseeCount) throws SQLException {
|
||||||
|
StringBuffer avgBalanceSql = new StringBuffer();
|
||||||
|
avgBalanceSql.append("SELECT avg(balance)/100000000 FROM ACCOUNTBALANCES ");
|
||||||
|
avgBalanceSql.append("WHERE account in (");
|
||||||
|
avgBalanceSql.append(String.join(", ", Collections.nCopies(sponseeCount, "?")));
|
||||||
|
avgBalanceSql.append(") and ASSET_ID = 0");
|
||||||
|
|
||||||
|
String[] sponsees = sponseeAddresses.toArray(new String[sponseeCount]);
|
||||||
|
return this.repository.checkedExecute(avgBalanceSql.toString(), sponsees);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Names
|
||||||
|
*
|
||||||
|
* @param namesResultSet the result set to get the names from
|
||||||
|
* @param count the number of potential names
|
||||||
|
*
|
||||||
|
* @return the names
|
||||||
|
*
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
|
private static List<String> getNames(ResultSet namesResultSet, int count) throws SQLException {
|
||||||
|
|
||||||
|
List<String> names = new ArrayList<>(count);
|
||||||
|
|
||||||
|
int nonRegisteredCount = 0;
|
||||||
|
|
||||||
|
do{
|
||||||
|
String name = namesResultSet.getString(1);
|
||||||
|
|
||||||
|
if( name != null ) {
|
||||||
|
names.add(name);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
nonRegisteredCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
} while( namesResultSet.next() );
|
||||||
|
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ResultSet getNamesResultSet(List<String> sponseeAddresses, int sponseeCount) throws SQLException {
|
||||||
|
StringBuffer namesSql = new StringBuffer();
|
||||||
|
namesSql.append("SELECT r.name ");
|
||||||
|
namesSql.append("FROM ACCOUNTS a ");
|
||||||
|
namesSql.append("LEFT JOIN REGISTERNAMETRANSACTIONS r on r.registrant = a.public_key ");
|
||||||
|
namesSql.append("WHERE account in (");
|
||||||
|
namesSql.append(String.join(", ", Collections.nCopies(sponseeCount, "?")));
|
||||||
|
namesSql.append(")");
|
||||||
|
|
||||||
|
String[] sponsees = sponseeAddresses.toArray(new String[sponseeCount]);
|
||||||
|
ResultSet namesResultSet = this.repository.checkedExecute(namesSql.toString(), sponsees);
|
||||||
|
return namesResultSet;
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user