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:
catbref 2019-04-10 13:09:30 +01:00
parent d5a2e5be19
commit cfbf5c12bf
10 changed files with 310 additions and 52 deletions

View File

@ -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();
}
}

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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());

View File

@ -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);
}

View File

@ -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;

View File

@ -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);
}