mirror of
https://github.com/Qortal/qortal.git
synced 2025-03-14 19:42:32 +00:00
Supply extra information fields to various asset-related API calls.
e.g. supply "assetName" in JSON for TRANSFER_ASSET transactions Also supply have/want asset names, amount asset ID/name, price-pair and creator address in asset orders. Show CREATE_ASSET_ORDER amount ID/name & price-pair in correct format depending on whether transaction was placed before/after 'new' asset pricing took effect. (Orders are always in 'new' form). Change API call /assets/transfers/{assetid}/{address} to /assets/transfers/{assetid} with optional "address" query param.
This commit is contained in:
parent
d5a2e5be19
commit
cfbf5c12bf
@ -2,6 +2,7 @@ package org.qora.api.model;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import javax.xml.bind.Marshaller;
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
@ -11,11 +12,18 @@ import org.qora.data.asset.OrderData;
|
||||
@XmlAccessorType(XmlAccessType.NONE)
|
||||
public class AggregatedOrder {
|
||||
|
||||
// Not exposed to API
|
||||
private OrderData orderData;
|
||||
|
||||
// Needed by JAXB for [un]marshalling
|
||||
protected AggregatedOrder() {
|
||||
}
|
||||
|
||||
public void beforeMarshal(Marshaller m) {
|
||||
// OrderData needs to calculate values for us
|
||||
this.orderData.beforeMarshal(m);
|
||||
}
|
||||
|
||||
public AggregatedOrder(OrderData orderData) {
|
||||
this.orderData = orderData;
|
||||
}
|
||||
@ -30,4 +38,19 @@ public class AggregatedOrder {
|
||||
return this.orderData.getAmount();
|
||||
}
|
||||
|
||||
@XmlElement(name = "unfulfilledAssetId")
|
||||
public long getUnfulfilledAssetId() {
|
||||
return this.orderData.getAmountAssetId();
|
||||
}
|
||||
|
||||
@XmlElement(name = "unfulfilledAssetName")
|
||||
public String getUnfulfilledAssetName() {
|
||||
return this.orderData.getAmountAssetName();
|
||||
}
|
||||
|
||||
@XmlElement(name = "pricePair")
|
||||
public String getPricePair() {
|
||||
return this.orderData.getPricePair();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -633,9 +633,9 @@ public class AssetsResource {
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/transfers/{assetid}/{address}")
|
||||
@Path("/transfers/{assetid}")
|
||||
@Operation(
|
||||
summary = "Asset transfers for specific asset and address combination",
|
||||
summary = "Asset transfers for specific asset, with optional address filter",
|
||||
responses = {
|
||||
@ApiResponse(
|
||||
description = "Asset transactions",
|
||||
@ -654,7 +654,7 @@ public class AssetsResource {
|
||||
})
|
||||
public List<TransferAssetTransactionData> getAssetTransfers(@Parameter(
|
||||
ref = "assetid"
|
||||
) @PathParam("assetid") int assetId, @PathParam("address") String address, @Parameter(
|
||||
) @PathParam("assetid") int assetId, @QueryParam("address") String address, @Parameter(
|
||||
ref = "limit"
|
||||
) @QueryParam("limit") Integer limit, @Parameter(
|
||||
ref = "offset"
|
||||
@ -665,7 +665,7 @@ public class AssetsResource {
|
||||
if (!repository.getAssetRepository().assetExists(assetId))
|
||||
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_ASSET_ID);
|
||||
|
||||
if (!Crypto.isValidAddress(address))
|
||||
if (address != null && !Crypto.isValidAddress(address))
|
||||
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_ADDRESS);
|
||||
|
||||
return repository.getTransactionRepository().getAssetTransfers(assetId, address, limit, offset, reverse);
|
||||
|
@ -2,12 +2,16 @@ package org.qora.data.asset;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import javax.xml.bind.Marshaller;
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import org.qora.crypto.Crypto;
|
||||
|
||||
// All properties to be converted to JSON via JAX-RS
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.media.Schema.AccessMode;
|
||||
|
||||
// All properties to be converted to JSON via JAXB
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
public class OrderData implements Comparable<OrderData> {
|
||||
|
||||
@ -38,13 +42,59 @@ public class OrderData implements Comparable<OrderData> {
|
||||
@Schema(description = "has this order been fully traded?")
|
||||
private boolean isFulfilled;
|
||||
|
||||
// Used by API - not always present
|
||||
|
||||
@Schema(accessMode = AccessMode.READ_ONLY)
|
||||
private String creator;
|
||||
|
||||
@Schema(accessMode = AccessMode.READ_ONLY)
|
||||
private String haveAssetName;
|
||||
|
||||
@Schema(accessMode = AccessMode.READ_ONLY)
|
||||
private String wantAssetName;
|
||||
|
||||
@Schema(accessMode = AccessMode.READ_ONLY)
|
||||
private long amountAssetId;
|
||||
|
||||
@Schema(accessMode = AccessMode.READ_ONLY)
|
||||
private String amountAssetName;
|
||||
|
||||
@Schema(accessMode = AccessMode.READ_ONLY)
|
||||
private String pricePair;
|
||||
|
||||
// Constructors
|
||||
|
||||
// necessary for JAX-RS serialization
|
||||
// Necessary for JAXB serialization
|
||||
protected OrderData() {
|
||||
}
|
||||
|
||||
public OrderData(byte[] orderId, byte[] creatorPublicKey, long haveAssetId, long wantAssetId, BigDecimal amount, BigDecimal fulfilled, BigDecimal price, long timestamp, boolean isClosed, boolean isFulfilled) {
|
||||
// Called before converting to JSON for API
|
||||
public void beforeMarshal(Marshaller m) {
|
||||
if (this.creator == null && this.creatorPublicKey != null)
|
||||
this.creator = Crypto.toAddress(this.creatorPublicKey);
|
||||
|
||||
// If we don't have the extra asset name fields then we can't fill in the others
|
||||
if (this.haveAssetName == null)
|
||||
return;
|
||||
|
||||
// 'old' pricing scheme is simpler so test for that first
|
||||
// XXX TODO
|
||||
|
||||
// 'new' pricing scheme
|
||||
if (this.haveAssetId < this.wantAssetId) {
|
||||
this.amountAssetId = this.wantAssetId;
|
||||
this.amountAssetName = this.wantAssetName;
|
||||
this.pricePair = this.haveAssetName + "/" + this.wantAssetName;
|
||||
} else {
|
||||
this.amountAssetId = this.haveAssetId;
|
||||
this.amountAssetName = this.haveAssetName;
|
||||
this.pricePair = this.wantAssetName + "/" + this.haveAssetName;
|
||||
}
|
||||
}
|
||||
|
||||
/** Constructs OrderData using data from repository, including optional API fields. */
|
||||
public OrderData(byte[] orderId, byte[] creatorPublicKey, long haveAssetId, long wantAssetId, BigDecimal amount, BigDecimal fulfilled, BigDecimal price, long timestamp,
|
||||
boolean isClosed, boolean isFulfilled, String haveAssetName, String wantAssetName) {
|
||||
this.orderId = orderId;
|
||||
this.creatorPublicKey = creatorPublicKey;
|
||||
this.haveAssetId = haveAssetId;
|
||||
@ -55,9 +105,17 @@ public class OrderData implements Comparable<OrderData> {
|
||||
this.timestamp = timestamp;
|
||||
this.isClosed = isClosed;
|
||||
this.isFulfilled = isFulfilled;
|
||||
|
||||
this.haveAssetName = haveAssetName;
|
||||
this.wantAssetName = wantAssetName;
|
||||
}
|
||||
|
||||
/** Constructs OrderData using typical deserialized network data */
|
||||
/** Constructs OrderData using data from repository, excluding optional API fields. */
|
||||
public OrderData(byte[] orderId, byte[] creatorPublicKey, long haveAssetId, long wantAssetId, BigDecimal amount, BigDecimal fulfilled, BigDecimal price, long timestamp, boolean isClosed, boolean isFulfilled) {
|
||||
this(orderId, creatorPublicKey, haveAssetId, wantAssetId, amount, fulfilled, price, timestamp, isClosed, isFulfilled, null, null);
|
||||
}
|
||||
|
||||
/** Constructs OrderData using data typically received from network. */
|
||||
public OrderData(byte[] orderId, byte[] creatorPublicKey, long haveAssetId, long wantAssetId, BigDecimal amount, BigDecimal price, long timestamp) {
|
||||
this(orderId, creatorPublicKey, haveAssetId, wantAssetId, amount, BigDecimal.ZERO.setScale(8), price, timestamp, false, false);
|
||||
}
|
||||
@ -116,6 +174,28 @@ public class OrderData implements Comparable<OrderData> {
|
||||
this.isFulfilled = isFulfilled;
|
||||
}
|
||||
|
||||
// Some JAXB/API-related getters
|
||||
|
||||
public String getHaveAssetName() {
|
||||
return this.haveAssetName;
|
||||
}
|
||||
|
||||
public String getWantAssetName() {
|
||||
return this.wantAssetName;
|
||||
}
|
||||
|
||||
public long getAmountAssetId() {
|
||||
return this.amountAssetId;
|
||||
}
|
||||
|
||||
public String getAmountAssetName() {
|
||||
return this.amountAssetName;
|
||||
}
|
||||
|
||||
public String getPricePair() {
|
||||
return this.pricePair;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(OrderData orderData) {
|
||||
// Compare using prices
|
||||
|
@ -2,13 +2,16 @@ package org.qora.data.transaction;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import javax.xml.bind.Marshaller;
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
|
||||
import org.qora.block.BlockChain;
|
||||
import org.qora.transaction.Transaction.TransactionType;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.media.Schema.AccessMode;
|
||||
|
||||
// All properties to be converted to JSON via JAXB
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
@ -25,6 +28,23 @@ public class CreateAssetOrderTransactionData extends TransactionData {
|
||||
@Schema(description = "price in lowest-assetID asset / highest-assetID asset")
|
||||
private BigDecimal price;
|
||||
|
||||
// Used by API - not always present
|
||||
|
||||
@Schema(accessMode = AccessMode.READ_ONLY)
|
||||
private String haveAssetName;
|
||||
|
||||
@Schema(accessMode = AccessMode.READ_ONLY)
|
||||
private String wantAssetName;
|
||||
|
||||
@Schema(accessMode = AccessMode.READ_ONLY)
|
||||
private long amountAssetId;
|
||||
|
||||
@Schema(accessMode = AccessMode.READ_ONLY)
|
||||
private String amountAssetName;
|
||||
|
||||
@Schema(accessMode = AccessMode.READ_ONLY)
|
||||
private String pricePair;
|
||||
|
||||
// Constructors
|
||||
|
||||
// For JAXB
|
||||
@ -32,16 +52,53 @@ public class CreateAssetOrderTransactionData extends TransactionData {
|
||||
super(TransactionType.CREATE_ASSET_ORDER);
|
||||
}
|
||||
|
||||
// Called before converting to JSON for API
|
||||
public void beforeMarshal(Marshaller m) {
|
||||
final boolean isNewPricing = this.timestamp > BlockChain.getInstance().getNewAssetPricingTimestamp();
|
||||
|
||||
this.amountAssetId = (isNewPricing && this.haveAssetId < this.wantAssetId) ? this.wantAssetId : this.haveAssetId;
|
||||
|
||||
// If we don't have the extra asset name fields then we can't fill in the others
|
||||
if (this.haveAssetName == null)
|
||||
return;
|
||||
|
||||
if (isNewPricing) {
|
||||
// 'new' pricing scheme
|
||||
if (this.haveAssetId < this.wantAssetId) {
|
||||
this.amountAssetName = this.wantAssetName;
|
||||
this.pricePair = this.haveAssetName + "/" + this.wantAssetName;
|
||||
} else {
|
||||
this.amountAssetName = this.haveAssetName;
|
||||
this.pricePair = this.wantAssetName + "/" + this.haveAssetName;
|
||||
}
|
||||
} else {
|
||||
// 'old' pricing scheme is simpler
|
||||
this.amountAssetName = this.haveAssetName;
|
||||
this.pricePair = this.wantAssetName + "/" + this.haveAssetName;
|
||||
}
|
||||
}
|
||||
|
||||
/** Constructs using data from repository, including optional asset names. */
|
||||
public CreateAssetOrderTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] creatorPublicKey, long haveAssetId, long wantAssetId,
|
||||
BigDecimal amount, BigDecimal price, BigDecimal fee, byte[] signature) {
|
||||
BigDecimal amount, BigDecimal price, BigDecimal fee, String haveAssetName, String wantAssetName, byte[] signature) {
|
||||
super(TransactionType.CREATE_ASSET_ORDER, timestamp, txGroupId, reference, creatorPublicKey, fee, signature);
|
||||
|
||||
this.haveAssetId = haveAssetId;
|
||||
this.wantAssetId = wantAssetId;
|
||||
this.amount = amount;
|
||||
this.price = price;
|
||||
|
||||
this.haveAssetName = haveAssetName;
|
||||
this.wantAssetName = wantAssetName;
|
||||
}
|
||||
|
||||
/** Constructs using data from repository, excluding optional asset names. */
|
||||
public CreateAssetOrderTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] creatorPublicKey, long haveAssetId, long wantAssetId,
|
||||
BigDecimal amount, BigDecimal price, BigDecimal fee, byte[] signature) {
|
||||
this(timestamp, txGroupId, reference, creatorPublicKey, haveAssetId, wantAssetId, amount, price, fee, null, null, signature);
|
||||
}
|
||||
|
||||
/** Constructor typically used with data from network. */
|
||||
public CreateAssetOrderTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] creatorPublicKey, long haveAssetId, long wantAssetId,
|
||||
BigDecimal amount, BigDecimal price, BigDecimal fee) {
|
||||
this(timestamp, txGroupId, reference, creatorPublicKey, haveAssetId, wantAssetId, amount, price, fee, null);
|
||||
|
@ -9,6 +9,7 @@ import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import org.qora.transaction.Transaction.TransactionType;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.media.Schema.AccessMode;
|
||||
|
||||
// All properties to be converted to JSON via JAXB
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
@ -21,6 +22,10 @@ public class TransferAssetTransactionData extends TransactionData {
|
||||
private BigDecimal amount;
|
||||
private long assetId;
|
||||
|
||||
// Used by API - not always present
|
||||
@Schema(accessMode = AccessMode.READ_ONLY)
|
||||
protected String assetName;
|
||||
|
||||
// Constructors
|
||||
|
||||
// For JAXB
|
||||
@ -32,16 +37,25 @@ public class TransferAssetTransactionData extends TransactionData {
|
||||
this.creatorPublicKey = this.senderPublicKey;
|
||||
}
|
||||
|
||||
/** Constructs using data from repository, including optional assetName. */
|
||||
public TransferAssetTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] senderPublicKey, String recipient, BigDecimal amount,
|
||||
long assetId, BigDecimal fee, byte[] signature) {
|
||||
long assetId, BigDecimal fee, String assetName, byte[] signature) {
|
||||
super(TransactionType.TRANSFER_ASSET, timestamp, txGroupId, reference, senderPublicKey, fee, signature);
|
||||
|
||||
this.senderPublicKey = senderPublicKey;
|
||||
this.recipient = recipient;
|
||||
this.amount = amount;
|
||||
this.assetId = assetId;
|
||||
this.assetName = assetName;
|
||||
}
|
||||
|
||||
/** Constructs using data from repository, excluding optional assetName. */
|
||||
public TransferAssetTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] senderPublicKey, String recipient, BigDecimal amount,
|
||||
long assetId, BigDecimal fee, byte[] signature) {
|
||||
this(timestamp, txGroupId, reference, senderPublicKey, recipient, amount, assetId, fee, null, signature);
|
||||
}
|
||||
|
||||
/** Constructs using data typically received over network. */
|
||||
public TransferAssetTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] senderPublicKey, String recipient, BigDecimal amount,
|
||||
long assetId, BigDecimal fee) {
|
||||
this(timestamp, txGroupId, reference, senderPublicKey, recipient, amount, assetId, fee, null);
|
||||
|
@ -63,7 +63,7 @@ public interface TransactionRepository {
|
||||
throws DataException;
|
||||
|
||||
/**
|
||||
* Returns list of TRANSFER_ASSET transactions relating to specific asset ID/address combination.
|
||||
* Returns list of TRANSFER_ASSET transactions relating to specific asset ID, with optional address filter.
|
||||
*
|
||||
* @param assetId
|
||||
* @param address
|
||||
|
@ -6,6 +6,7 @@ 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;
|
||||
|
||||
@ -191,9 +192,13 @@ public class HSQLDBAssetRepository implements AssetRepository {
|
||||
|
||||
@Override
|
||||
public OrderData fromOrderId(byte[] orderId) throws DataException {
|
||||
try (ResultSet resultSet = this.repository.checkedExecute(
|
||||
"SELECT creator, have_asset_id, want_asset_id, amount, fulfilled, price, ordered, is_closed, is_fulfilled FROM AssetOrders WHERE asset_order_id = ?",
|
||||
orderId)) {
|
||||
String sql = "SELECT creator, have_asset_id, want_asset_id, amount, fulfilled, price, ordered, is_closed, is_fulfilled, HaveAsset.asset_name, WantAsset.asset_name "
|
||||
+ "FROM AssetOrders "
|
||||
+ "JOIN Assets AS HaveAsset ON HaveAsset.asset_id = have_asset_id "
|
||||
+ "JOIN Assets AS WantAsset ON WantAsset.asset_id = want_asset_id "
|
||||
+ "WHERE asset_order_id = ?";
|
||||
|
||||
try (ResultSet resultSet = this.repository.checkedExecute(sql, orderId)) {
|
||||
if (resultSet == null)
|
||||
return null;
|
||||
|
||||
@ -206,8 +211,10 @@ public class HSQLDBAssetRepository implements AssetRepository {
|
||||
long timestamp = resultSet.getTimestamp(7, Calendar.getInstance(HSQLDBRepository.UTC)).getTime();
|
||||
boolean isClosed = resultSet.getBoolean(8);
|
||||
boolean isFulfilled = resultSet.getBoolean(9);
|
||||
String haveAssetName = resultSet.getString(10);
|
||||
String wantAssetName = resultSet.getString(11);
|
||||
|
||||
return new OrderData(orderId, creatorPublicKey, haveAssetId, wantAssetId, amount, fulfilled, price, timestamp, isClosed, isFulfilled);
|
||||
return new OrderData(orderId, creatorPublicKey, haveAssetId, wantAssetId, amount, fulfilled, price, timestamp, isClosed, isFulfilled, haveAssetName, wantAssetName);
|
||||
} catch (SQLException e) {
|
||||
throw new DataException("Unable to fetch asset order from repository", e);
|
||||
}
|
||||
@ -216,16 +223,30 @@ public class HSQLDBAssetRepository implements AssetRepository {
|
||||
@Override
|
||||
public List<OrderData> getOpenOrders(long haveAssetId, long wantAssetId, Integer limit, Integer offset,
|
||||
Boolean reverse) throws DataException {
|
||||
String sql = "SELECT creator, asset_order_id, amount, fulfilled, price, ordered FROM AssetOrders "
|
||||
+ "WHERE have_asset_id = ? AND want_asset_id = ? AND is_closed = FALSE AND is_fulfilled = FALSE ORDER BY price";
|
||||
List<OrderData> orders = new ArrayList<OrderData>();
|
||||
|
||||
// Cache have & want asset names for later use, which also saves a table join
|
||||
AssetData haveAssetData = this.fromAssetId(haveAssetId);
|
||||
if (haveAssetData == null)
|
||||
return orders;
|
||||
|
||||
AssetData wantAssetData = this.fromAssetId(wantAssetId);
|
||||
if (wantAssetData == null)
|
||||
return orders;
|
||||
|
||||
String sql = "SELECT creator, asset_order_id, amount, fulfilled, price, ordered "
|
||||
+ "FROM AssetOrders "
|
||||
+ "WHERE have_asset_id = ? AND want_asset_id = ? AND NOT is_closed AND NOT is_fulfilled ";
|
||||
|
||||
sql += "ORDER BY price";
|
||||
if (reverse != null && reverse)
|
||||
sql += " DESC";
|
||||
|
||||
sql += ", ordered";
|
||||
if (reverse != null && reverse)
|
||||
sql += " DESC";
|
||||
sql += HSQLDBRepository.limitOffsetSql(limit, offset);
|
||||
|
||||
List<OrderData> orders = new ArrayList<OrderData>();
|
||||
sql += HSQLDBRepository.limitOffsetSql(limit, offset);
|
||||
|
||||
try (ResultSet resultSet = this.repository.checkedExecute(sql, haveAssetId, wantAssetId)) {
|
||||
if (resultSet == null)
|
||||
@ -242,7 +263,7 @@ public class HSQLDBAssetRepository implements AssetRepository {
|
||||
boolean isFulfilled = false;
|
||||
|
||||
OrderData order = new OrderData(orderId, creatorPublicKey, haveAssetId, wantAssetId, amount, fulfilled,
|
||||
price, timestamp, isClosed, isFulfilled);
|
||||
price, timestamp, isClosed, isFulfilled, haveAssetData.getName(), wantAssetData.getName());
|
||||
orders.add(order);
|
||||
} while (resultSet.next());
|
||||
|
||||
@ -254,22 +275,24 @@ public class HSQLDBAssetRepository implements AssetRepository {
|
||||
|
||||
@Override
|
||||
public List<OrderData> getOpenOrdersForTrading(long haveAssetId, long wantAssetId, BigDecimal minimumPrice) throws DataException {
|
||||
Object[] bindParams;
|
||||
String sql = "SELECT creator, asset_order_id, amount, fulfilled, price, ordered FROM AssetOrders "
|
||||
List<Object> bindParams = new ArrayList<>(3);
|
||||
|
||||
String sql = "SELECT creator, asset_order_id, amount, fulfilled, price, ordered "
|
||||
+ "FROM AssetOrders "
|
||||
+ "WHERE have_asset_id = ? AND want_asset_id = ? AND NOT is_closed AND NOT is_fulfilled ";
|
||||
|
||||
Collections.addAll(bindParams, haveAssetId, wantAssetId);
|
||||
|
||||
if (minimumPrice != null) {
|
||||
sql += "AND price >= ? ";
|
||||
bindParams = new Object[] {haveAssetId, wantAssetId, minimumPrice};
|
||||
} else {
|
||||
bindParams = new Object[] {haveAssetId, wantAssetId};
|
||||
bindParams.add(minimumPrice);
|
||||
}
|
||||
|
||||
sql += "ORDER BY price DESC, ordered";
|
||||
|
||||
List<OrderData> orders = new ArrayList<OrderData>();
|
||||
|
||||
try (ResultSet resultSet = this.repository.checkedExecute(sql, bindParams)) {
|
||||
try (ResultSet resultSet = this.repository.checkedExecute(sql, bindParams.toArray())) {
|
||||
if (resultSet == null)
|
||||
return orders;
|
||||
|
||||
@ -283,6 +306,7 @@ public class HSQLDBAssetRepository implements AssetRepository {
|
||||
boolean isClosed = false;
|
||||
boolean isFulfilled = false;
|
||||
|
||||
// We don't need asset names so we can use simpler constructor
|
||||
OrderData order = new OrderData(orderId, creatorPublicKey, haveAssetId, wantAssetId, amount, fulfilled,
|
||||
price, timestamp, isClosed, isFulfilled);
|
||||
orders.add(order);
|
||||
@ -297,13 +321,27 @@ public class HSQLDBAssetRepository implements AssetRepository {
|
||||
@Override
|
||||
public List<OrderData> getAggregatedOpenOrders(long haveAssetId, long wantAssetId, Integer limit, Integer offset,
|
||||
Boolean reverse) throws DataException {
|
||||
String sql = "SELECT price, SUM(amount - fulfilled), MAX(ordered) FROM AssetOrders "
|
||||
+ "WHERE have_asset_id = ? AND want_asset_id = ? AND is_closed = FALSE AND is_fulfilled = FALSE GROUP BY price ORDER BY price";
|
||||
List<OrderData> orders = new ArrayList<OrderData>();
|
||||
|
||||
// Cache have & want asset names for later use, which also saves a table join
|
||||
AssetData haveAssetData = this.fromAssetId(haveAssetId);
|
||||
if (haveAssetData == null)
|
||||
return orders;
|
||||
|
||||
AssetData wantAssetData = this.fromAssetId(wantAssetId);
|
||||
if (wantAssetData == null)
|
||||
return orders;
|
||||
|
||||
String sql = "SELECT price, SUM(amount - fulfilled), MAX(ordered) "
|
||||
+ "FROM AssetOrders "
|
||||
+ "WHERE have_asset_id = ? AND want_asset_id = ? AND NOT is_closed AND NOT is_fulfilled "
|
||||
+ "GROUP BY price ";
|
||||
|
||||
sql += "ORDER BY price";
|
||||
if (reverse != null && reverse)
|
||||
sql += " DESC";
|
||||
sql += HSQLDBRepository.limitOffsetSql(limit, offset);
|
||||
|
||||
List<OrderData> orders = new ArrayList<OrderData>();
|
||||
sql += HSQLDBRepository.limitOffsetSql(limit, offset);
|
||||
|
||||
try (ResultSet resultSet = this.repository.checkedExecute(sql, haveAssetId, wantAssetId)) {
|
||||
if (resultSet == null)
|
||||
@ -315,7 +353,7 @@ public class HSQLDBAssetRepository implements AssetRepository {
|
||||
long timestamp = resultSet.getTimestamp(3).getTime();
|
||||
|
||||
OrderData order = new OrderData(null, null, haveAssetId, wantAssetId, totalUnfulfilled, BigDecimal.ZERO,
|
||||
price, timestamp, false, false);
|
||||
price, timestamp, false, false, haveAssetData.getName(), wantAssetData.getName());
|
||||
orders.add(order);
|
||||
} while (resultSet.next());
|
||||
|
||||
@ -328,15 +366,23 @@ public class HSQLDBAssetRepository implements AssetRepository {
|
||||
@Override
|
||||
public List<OrderData> getAccountsOrders(byte[] publicKey, Boolean optIsClosed, Boolean optIsFulfilled,
|
||||
Integer limit, Integer offset, Boolean reverse) throws DataException {
|
||||
String sql = "SELECT asset_order_id, have_asset_id, want_asset_id, amount, fulfilled, price, ordered, is_closed, is_fulfilled "
|
||||
+ "FROM AssetOrders WHERE creator = ?";
|
||||
// We have to join for have/want asset data as it might vary
|
||||
String sql = "SELECT asset_order_id, have_asset_id, want_asset_id, amount, fulfilled, price, ordered, is_closed, is_fulfilled, HaveAsset.asset_name, WantAsset.asset_name "
|
||||
+ "FROM AssetOrders "
|
||||
+ "JOIN Assets AS HaveAsset ON HaveAsset.asset_id = have_asset_id "
|
||||
+ "JOIN Assets AS WantAsset ON WantAsset.asset_id = want_asset_id "
|
||||
+ "WHERE creator = ?";
|
||||
|
||||
if (optIsClosed != null)
|
||||
sql += " AND is_closed = " + (optIsClosed ? "TRUE" : "FALSE");
|
||||
|
||||
if (optIsFulfilled != null)
|
||||
sql += " AND is_fulfilled = " + (optIsFulfilled ? "TRUE" : "FALSE");
|
||||
|
||||
sql += " ORDER BY ordered";
|
||||
if (reverse != null && reverse)
|
||||
sql += " DESC";
|
||||
|
||||
sql += HSQLDBRepository.limitOffsetSql(limit, offset);
|
||||
|
||||
List<OrderData> orders = new ArrayList<OrderData>();
|
||||
@ -355,9 +401,11 @@ public class HSQLDBAssetRepository implements AssetRepository {
|
||||
long timestamp = resultSet.getTimestamp(7, Calendar.getInstance(HSQLDBRepository.UTC)).getTime();
|
||||
boolean isClosed = resultSet.getBoolean(8);
|
||||
boolean isFulfilled = resultSet.getBoolean(9);
|
||||
String haveAssetName = resultSet.getString(10);
|
||||
String wantAssetName = resultSet.getString(11);
|
||||
|
||||
OrderData order = new OrderData(orderId, publicKey, haveAssetId, wantAssetId, amount, fulfilled,
|
||||
price, timestamp, isClosed, isFulfilled);
|
||||
price, timestamp, isClosed, isFulfilled, haveAssetName, wantAssetName);
|
||||
orders.add(order);
|
||||
} while (resultSet.next());
|
||||
|
||||
@ -370,18 +418,32 @@ public class HSQLDBAssetRepository implements AssetRepository {
|
||||
@Override
|
||||
public List<OrderData> getAccountsOrders(byte[] publicKey, long haveAssetId, long wantAssetId, Boolean optIsClosed,
|
||||
Boolean optIsFulfilled, Integer limit, Integer offset, Boolean reverse) throws DataException {
|
||||
List<OrderData> orders = new ArrayList<OrderData>();
|
||||
|
||||
// Cache have & want asset names for later use, which also saves a table join
|
||||
AssetData haveAssetData = this.fromAssetId(haveAssetId);
|
||||
if (haveAssetData == null)
|
||||
return orders;
|
||||
|
||||
AssetData wantAssetData = this.fromAssetId(wantAssetId);
|
||||
if (wantAssetData == null)
|
||||
return orders;
|
||||
|
||||
String sql = "SELECT asset_order_id, amount, fulfilled, price, ordered, is_closed, is_fulfilled "
|
||||
+ "FROM AssetOrders WHERE creator = ? AND have_asset_id = ? AND want_asset_id = ?";
|
||||
+ "FROM AssetOrders "
|
||||
+ "WHERE creator = ? AND have_asset_id = ? AND want_asset_id = ?";
|
||||
|
||||
if (optIsClosed != null)
|
||||
sql += " AND is_closed = " + (optIsClosed ? "TRUE" : "FALSE");
|
||||
|
||||
if (optIsFulfilled != null)
|
||||
sql += " AND is_fulfilled = " + (optIsFulfilled ? "TRUE" : "FALSE");
|
||||
|
||||
sql += " ORDER BY ordered";
|
||||
if (reverse != null && reverse)
|
||||
sql += " DESC";
|
||||
sql += HSQLDBRepository.limitOffsetSql(limit, offset);
|
||||
|
||||
List<OrderData> orders = new ArrayList<OrderData>();
|
||||
sql += HSQLDBRepository.limitOffsetSql(limit, offset);
|
||||
|
||||
try (ResultSet resultSet = this.repository.checkedExecute(sql, publicKey, haveAssetId, wantAssetId)) {
|
||||
if (resultSet == null)
|
||||
@ -397,7 +459,7 @@ public class HSQLDBAssetRepository implements AssetRepository {
|
||||
boolean isFulfilled = resultSet.getBoolean(7);
|
||||
|
||||
OrderData order = new OrderData(orderId, publicKey, haveAssetId, wantAssetId, amount, fulfilled,
|
||||
price, timestamp, isClosed, isFulfilled);
|
||||
price, timestamp, isClosed, isFulfilled, haveAssetData.getName(), wantAssetData.getName());
|
||||
orders.add(order);
|
||||
} while (resultSet.next());
|
||||
|
||||
|
@ -17,8 +17,13 @@ public class HSQLDBCreateAssetOrderTransactionRepository extends HSQLDBTransacti
|
||||
}
|
||||
|
||||
TransactionData fromBase(long timestamp, int txGroupId, byte[] reference, byte[] creatorPublicKey, BigDecimal fee, byte[] signature) throws DataException {
|
||||
try (ResultSet resultSet = this.repository
|
||||
.checkedExecute("SELECT have_asset_id, amount, want_asset_id, price FROM CreateAssetOrderTransactions WHERE signature = ?", signature)) {
|
||||
String sql = "SELECT have_asset_id, amount, want_asset_id, price, HaveAsset.asset_name, WantAsset.asset_name "
|
||||
+ "FROM CreateAssetOrderTransactions "
|
||||
+ "JOIN Assets AS HaveAsset ON HaveAsset.asset_id = have_asset_id "
|
||||
+ "JOIN Assets AS WantAsset ON WantAsset.asset_id = want_asset_id "
|
||||
+ "WHERE signature = ?";
|
||||
|
||||
try (ResultSet resultSet = this.repository.checkedExecute(sql, signature)) {
|
||||
if (resultSet == null)
|
||||
return null;
|
||||
|
||||
@ -26,8 +31,10 @@ public class HSQLDBCreateAssetOrderTransactionRepository extends HSQLDBTransacti
|
||||
BigDecimal amount = resultSet.getBigDecimal(2);
|
||||
long wantAssetId = resultSet.getLong(3);
|
||||
BigDecimal price = resultSet.getBigDecimal(4);
|
||||
String haveAssetName = resultSet.getString(5);
|
||||
String wantAssetName = resultSet.getString(6);
|
||||
|
||||
return new CreateAssetOrderTransactionData(timestamp, txGroupId, reference, creatorPublicKey, haveAssetId, wantAssetId, amount, price, fee, signature);
|
||||
return new CreateAssetOrderTransactionData(timestamp, txGroupId, reference, creatorPublicKey, haveAssetId, wantAssetId, amount, price, fee, haveAssetName, wantAssetName, signature);
|
||||
} catch (SQLException e) {
|
||||
throw new DataException("Unable to fetch create order transaction from repository", e);
|
||||
}
|
||||
|
@ -535,18 +535,30 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
|
||||
@Override
|
||||
public List<TransferAssetTransactionData> getAssetTransfers(long assetId, String address, Integer limit, Integer offset, Boolean reverse)
|
||||
throws DataException {
|
||||
String sql = "SELECT creation, tx_group_id, reference, fee, signature, sender, recipient, amount FROM TransferAssetTransactions "
|
||||
+ "JOIN Transactions USING (signature) "
|
||||
+ "JOIN Accounts ON public_key = sender "
|
||||
+ "WHERE asset_id = ? AND ? IN (account, recipient) "
|
||||
+ "ORDER by creation ";
|
||||
List<Object> bindParams = new ArrayList<>(3);
|
||||
|
||||
String sql = "SELECT creation, tx_group_id, reference, fee, signature, sender, recipient, amount, asset_name "
|
||||
+ "FROM TransferAssetTransactions JOIN Transactions USING (signature) ";
|
||||
|
||||
if (address != null)
|
||||
sql += "JOIN Accounts ON public_key = sender ";
|
||||
|
||||
sql += "JOIN Assets USING (asset_id) WHERE asset_id = ? ";
|
||||
bindParams.add(assetId);
|
||||
|
||||
if (address != null) {
|
||||
sql += "AND ? IN (account, recipient) ";
|
||||
bindParams.add(address);
|
||||
}
|
||||
|
||||
sql += "ORDER by creation ";
|
||||
|
||||
sql += (reverse == null || !reverse) ? "ASC" : "DESC";
|
||||
sql += HSQLDBRepository.limitOffsetSql(limit, offset);
|
||||
|
||||
List<TransferAssetTransactionData> assetTransfers = new ArrayList<>();
|
||||
|
||||
try (ResultSet resultSet = this.repository.checkedExecute(sql, assetId, address)) {
|
||||
try (ResultSet resultSet = this.repository.checkedExecute(sql, bindParams.toArray())) {
|
||||
if (resultSet == null)
|
||||
return assetTransfers;
|
||||
|
||||
@ -559,8 +571,9 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
|
||||
byte[] creatorPublicKey = resultSet.getBytes(6);
|
||||
String recipient = resultSet.getString(7);
|
||||
BigDecimal amount = resultSet.getBigDecimal(8);
|
||||
String assetName = resultSet.getString(9);
|
||||
|
||||
assetTransfers.add(new TransferAssetTransactionData(timestamp, txGroupId, reference, creatorPublicKey, recipient, amount, assetId, fee, signature));
|
||||
assetTransfers.add(new TransferAssetTransactionData(timestamp, txGroupId, reference, creatorPublicKey, recipient, amount, assetId, fee, assetName, signature));
|
||||
} while (resultSet.next());
|
||||
|
||||
return assetTransfers;
|
||||
|
@ -17,16 +17,18 @@ public class HSQLDBTransferAssetTransactionRepository extends HSQLDBTransactionR
|
||||
}
|
||||
|
||||
TransactionData fromBase(long timestamp, int txGroupId, byte[] reference, byte[] creatorPublicKey, BigDecimal fee, byte[] signature) throws DataException {
|
||||
try (ResultSet resultSet = this.repository
|
||||
.checkedExecute("SELECT recipient, asset_id, amount FROM TransferAssetTransactions WHERE signature = ?", signature)) {
|
||||
String sql = "SELECT recipient, asset_id, amount, asset_name FROM TransferAssetTransactions JOIN Assets USING (asset_id) WHERE signature = ?";
|
||||
|
||||
try (ResultSet resultSet = this.repository.checkedExecute(sql, signature)) {
|
||||
if (resultSet == null)
|
||||
return null;
|
||||
|
||||
String recipient = resultSet.getString(1);
|
||||
long assetId = resultSet.getLong(2);
|
||||
BigDecimal amount = resultSet.getBigDecimal(3);
|
||||
String assetName = resultSet.getString(4);
|
||||
|
||||
return new TransferAssetTransactionData(timestamp, txGroupId, reference, creatorPublicKey, recipient, amount, assetId, fee, signature);
|
||||
return new TransferAssetTransactionData(timestamp, txGroupId, reference, creatorPublicKey, recipient, amount, assetId, fee, assetName, signature);
|
||||
} catch (SQLException e) {
|
||||
throw new DataException("Unable to fetch transfer asset transaction from repository", e);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user