mirror of
https://github.com/Qortal/qortal.git
synced 2025-07-22 20:26:50 +00:00
API modifications, remove blockchain defaultGroupId, Eclipse/git
GET /assets/trades/recent expanded to allow multiple otherAssetIds When GET /assets/balances is called with address(es) but no assetIDs then it will return balances for all assets, including zero balances for assets the addresses don't own. GET /addresses/{address} no long fakes a default groupID - in fact defaultGroupId now removed from blockchain config. Some Eclipse IDE files now hidden/removed from git repo.
This commit is contained in:
@@ -22,7 +22,6 @@ import org.qora.api.ApiErrors;
|
||||
import org.qora.api.ApiException;
|
||||
import org.qora.api.ApiExceptionFactory;
|
||||
import org.qora.asset.Asset;
|
||||
import org.qora.block.BlockChain;
|
||||
import org.qora.crypto.Crypto;
|
||||
import org.qora.data.account.AccountData;
|
||||
import org.qora.group.Group;
|
||||
@@ -62,11 +61,7 @@ public class AddressesResource {
|
||||
|
||||
// Not found?
|
||||
if (accountData == null)
|
||||
accountData = new AccountData(address, null, null, BlockChain.getInstance().getDefaultGroupId());
|
||||
|
||||
// If Blockchain config doesn't allow NO_GROUP for approval-needing tx type then change this to blockchain's default groupID
|
||||
if (accountData.getDefaultGroupId() == Group.NO_GROUP && BlockChain.getInstance().getRequireGroupForApproval())
|
||||
accountData.setDefaultGroupId(BlockChain.getInstance().getDefaultGroupId());
|
||||
accountData = new AccountData(address, null, null, Group.NO_GROUP);
|
||||
|
||||
return accountData;
|
||||
} catch (ApiException e) {
|
||||
|
@@ -10,6 +10,7 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -300,7 +301,7 @@ public class AssetsResource {
|
||||
@ApiErrors({
|
||||
ApiError.INVALID_ASSET_ID, ApiError.REPOSITORY_ISSUE
|
||||
})
|
||||
public List<RecentTradeData> getRecentTrades(@QueryParam("assetid") List<Long> assetIds, @QueryParam("otherassetid") Long otherAssetId, @Parameter(
|
||||
public List<RecentTradeData> getRecentTrades(@QueryParam("assetid") List<Long> assetIds, @QueryParam("otherassetid") List<Long> otherAssetIds, @Parameter(
|
||||
ref = "limit"
|
||||
) @QueryParam("limit") Integer limit, @Parameter(
|
||||
ref = "offset"
|
||||
@@ -308,17 +309,21 @@ public class AssetsResource {
|
||||
ref = "reverse"
|
||||
) @QueryParam("reverse") Boolean reverse) {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
for (long assetId : assetIds)
|
||||
if (!repository.getAssetRepository().assetExists(assetId))
|
||||
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_ASSET_ID);
|
||||
|
||||
if (otherAssetId == null)
|
||||
otherAssetId = Asset.QORA;
|
||||
if (assetIds.isEmpty())
|
||||
assetIds = Collections.singletonList(Asset.QORA);
|
||||
else
|
||||
if (!repository.getAssetRepository().assetExists(otherAssetId))
|
||||
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_ASSET_ID);
|
||||
for (long assetId : assetIds)
|
||||
if (!repository.getAssetRepository().assetExists(assetId))
|
||||
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_ASSET_ID);
|
||||
|
||||
return repository.getAssetRepository().getRecentTrades(assetIds, otherAssetId, limit, offset, reverse);
|
||||
if (otherAssetIds.isEmpty())
|
||||
otherAssetIds = Collections.singletonList(Asset.QORA);
|
||||
else
|
||||
for (long assetId : otherAssetIds)
|
||||
if (!repository.getAssetRepository().assetExists(assetId))
|
||||
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_ASSET_ID);
|
||||
|
||||
return repository.getAssetRepository().getRecentTrades(assetIds, otherAssetIds, limit, offset, reverse);
|
||||
} catch (DataException e) {
|
||||
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
|
||||
}
|
||||
|
@@ -24,7 +24,6 @@ import org.eclipse.persistence.exceptions.XMLMarshalException;
|
||||
import org.eclipse.persistence.jaxb.JAXBContextFactory;
|
||||
import org.eclipse.persistence.jaxb.UnmarshallerProperties;
|
||||
import org.qora.data.block.BlockData;
|
||||
import org.qora.group.Group;
|
||||
import org.qora.repository.BlockRepository;
|
||||
import org.qora.repository.DataException;
|
||||
import org.qora.repository.Repository;
|
||||
@@ -65,8 +64,6 @@ public class BlockChain {
|
||||
|
||||
/** Whether transactions with txGroupId of NO_GROUP are allowed */
|
||||
private boolean requireGroupForApproval;
|
||||
/** Default groupID when account's default groupID isn't set */
|
||||
private int defaultGroupId = Group.NO_GROUP;
|
||||
|
||||
private GenesisBlock.GenesisInfo genesisInfo;
|
||||
|
||||
@@ -216,10 +213,6 @@ public class BlockChain {
|
||||
return this.requireGroupForApproval;
|
||||
}
|
||||
|
||||
public int getDefaultGroupId() {
|
||||
return this.defaultGroupId;
|
||||
}
|
||||
|
||||
public boolean getUseBrokenMD160ForAddresses() {
|
||||
return this.useBrokenMD160ForAddresses;
|
||||
}
|
||||
@@ -276,14 +269,6 @@ public class BlockChain {
|
||||
LOGGER.error(String.format("Missing feature trigger \"%s\" in blockchain config", featureTrigger.name()));
|
||||
throw new RuntimeException("Missing feature trigger in blockchain config");
|
||||
}
|
||||
|
||||
// If approval-needing transactions require a group the defaultGroupId needs to be set
|
||||
// XXX we could also check groupID exists, or at least created in genesis block, or in blockchain config
|
||||
if (this.requireGroupForApproval && this.defaultGroupId == Group.NO_GROUP) {
|
||||
LOGGER.error("defaultGroupId must be set to valid groupID in blockchain config if approval-needing transactions require a group");
|
||||
throw new RuntimeException(
|
||||
"defaultGroupId must be set to valid groupID in blockchain config if approval-needing transactions require a group");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -37,6 +37,7 @@ public interface AssetRepository {
|
||||
|
||||
public List<OrderData> getOpenOrders(long haveAssetId, long wantAssetId, Integer limit, Integer offset, Boolean reverse) throws DataException;
|
||||
|
||||
// Internal, non-API use
|
||||
public default List<OrderData> getOpenOrders(long haveAssetId, long wantAssetId) throws DataException {
|
||||
return getOpenOrders(haveAssetId, wantAssetId, null, null, null);
|
||||
}
|
||||
@@ -49,6 +50,7 @@ public interface AssetRepository {
|
||||
public List<OrderData> getAccountsOrders(byte[] publicKey, long haveAssetId, long wantAssetId, Boolean optIsClosed, Boolean optIsFulfilled,
|
||||
Integer limit, Integer offset, Boolean reverse) throws DataException;
|
||||
|
||||
// Internal, non-API use
|
||||
public default List<OrderData> getAccountsOrders(byte[] publicKey, Boolean optIsClosed, Boolean optIsFulfilled) throws DataException {
|
||||
return getAccountsOrders(publicKey, optIsClosed, optIsFulfilled, null, null, null);
|
||||
}
|
||||
@@ -61,15 +63,17 @@ public interface AssetRepository {
|
||||
|
||||
public List<TradeData> getTrades(long haveAssetId, long wantAssetId, Integer limit, Integer offset, Boolean reverse) throws DataException;
|
||||
|
||||
// Internal, non-API use
|
||||
public default List<TradeData> getTrades(long haveAssetId, long wantAssetId) throws DataException {
|
||||
return getTrades(haveAssetId, wantAssetId, null, null, null);
|
||||
}
|
||||
|
||||
public List<RecentTradeData> getRecentTrades(List<Long> assetIds, Long otherAssetId, Integer limit, Integer offset, Boolean reverse) throws DataException;
|
||||
public List<RecentTradeData> getRecentTrades(List<Long> assetIds, List<Long> otherAssetIds, Integer limit, Integer offset, Boolean reverse) throws DataException;
|
||||
|
||||
/** Returns TradeData for trades where orderId was involved, i.e. either initiating OR target order */
|
||||
public List<TradeData> getOrdersTrades(byte[] orderId, Integer limit, Integer offset, Boolean reverse) throws DataException;
|
||||
|
||||
// Internal, non-API use
|
||||
public default List<TradeData> getOrdersTrades(byte[] orderId) throws DataException {
|
||||
return getOrdersTrades(orderId, null, null, null);
|
||||
}
|
||||
|
@@ -145,16 +145,19 @@ public class HSQLDBAccountRepository implements AccountRepository {
|
||||
@Override
|
||||
public List<AccountBalanceData> getAssetBalances(List<String> addresses, List<Long> assetIds, Integer limit, Integer offset, Boolean reverse)
|
||||
throws DataException {
|
||||
String sql = "SELECT account, asset_id, balance, asset_name FROM AccountBalances NATURAL JOIN Assets " + "WHERE ";
|
||||
String sql = "SELECT account, asset_id, IFNULL(balance, 0), asset_name FROM ";
|
||||
|
||||
if (!addresses.isEmpty())
|
||||
sql += "account IN (" + String.join(", ", Collections.nCopies(addresses.size(), "?")) + ") ";
|
||||
|
||||
if (!addresses.isEmpty() && !assetIds.isEmpty())
|
||||
sql += "AND ";
|
||||
if (!addresses.isEmpty()) {
|
||||
sql += "(VALUES " + String.join(", ", Collections.nCopies(addresses.size(), "(?)")) + ") AS Accounts (account) ";
|
||||
sql += "CROSS JOIN Assets LEFT OUTER JOIN AccountBalances USING (asset_id, account) ";
|
||||
} else {
|
||||
// Simplier, no-address query
|
||||
sql += "AccountBalances NATURAL JOIN Assets ";
|
||||
}
|
||||
|
||||
if (!assetIds.isEmpty())
|
||||
sql += "asset_id IN (" + String.join(", ", assetIds.stream().map(assetId -> assetId.toString()).collect(Collectors.toList())) + ") ";
|
||||
// longs are safe enough to use literally
|
||||
sql += "WHERE asset_id IN (" + String.join(", ", assetIds.stream().map(assetId -> assetId.toString()).collect(Collectors.toList())) + ") ";
|
||||
|
||||
sql += "ORDER BY account";
|
||||
if (reverse != null && reverse)
|
||||
|
@@ -6,8 +6,8 @@ import java.sql.SQLException;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.qora.data.asset.AssetData;
|
||||
import org.qora.data.asset.OrderData;
|
||||
@@ -379,17 +379,19 @@ public class HSQLDBAssetRepository implements AssetRepository {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RecentTradeData> getRecentTrades(List<Long> assetIds, Long otherAssetId, Integer limit, Integer offset, Boolean reverse) throws DataException {
|
||||
public List<RecentTradeData> getRecentTrades(List<Long> assetIds, List<Long> otherAssetIds, Integer limit, Integer offset, Boolean reverse) throws DataException {
|
||||
// Find assetID pairs that have actually been traded
|
||||
String tradedAssetsSubquery = "SELECT have_asset_id, want_asset_id " + "FROM AssetTrades JOIN AssetOrders ON asset_order_id = initiating_order_id ";
|
||||
|
||||
// Optionally limit traded assetID pairs
|
||||
if (!assetIds.isEmpty())
|
||||
tradedAssetsSubquery += "WHERE have_asset_id IN (" + String.join(", ", Collections.nCopies(assetIds.size(), "?")) + ")";
|
||||
// longs are safe enough to use literally
|
||||
tradedAssetsSubquery += "WHERE have_asset_id IN (" + String.join(", ", assetIds.stream().map(assetId -> assetId.toString()).collect(Collectors.toList())) + ")";
|
||||
|
||||
if (otherAssetId != null) {
|
||||
if (!otherAssetIds.isEmpty()) {
|
||||
tradedAssetsSubquery += assetIds.isEmpty() ? " WHERE " : " AND ";
|
||||
tradedAssetsSubquery += "want_asset_id = " + otherAssetId.toString();
|
||||
// longs are safe enough to use literally
|
||||
tradedAssetsSubquery += "want_asset_id IN (" + String.join(", ", otherAssetIds.stream().map(assetId -> assetId.toString()).collect(Collectors.toList())) + ")";
|
||||
}
|
||||
|
||||
tradedAssetsSubquery += " GROUP BY have_asset_id, want_asset_id";
|
||||
@@ -414,10 +416,9 @@ public class HSQLDBAssetRepository implements AssetRepository {
|
||||
|
||||
sql += HSQLDBRepository.limitOffsetSql(limit, offset);
|
||||
|
||||
Long[] assetIdsArray = assetIds.toArray(new Long[assetIds.size()]);
|
||||
List<RecentTradeData> recentTrades = new ArrayList<>();
|
||||
|
||||
try (ResultSet resultSet = this.repository.checkedExecute(sql, (Object[]) assetIdsArray)) {
|
||||
try (ResultSet resultSet = this.repository.checkedExecute(sql)) {
|
||||
if (resultSet == null)
|
||||
return recentTrades;
|
||||
|
||||
|
Reference in New Issue
Block a user