Add cancel order and get orders by address API support.

Added getAccountsOrders asset repository call to facilitate the above.
This commit is contained in:
catbref 2019-01-07 09:31:27 +00:00
parent 2497ac256c
commit b2ca63ce88
6 changed files with 138 additions and 3 deletions

View File

@ -15,6 +15,7 @@ import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
@ -27,6 +28,7 @@ import org.qora.asset.Asset;
import org.qora.crypto.Crypto;
import org.qora.data.account.AccountBalanceData;
import org.qora.data.account.AccountData;
import org.qora.data.asset.OrderData;
import org.qora.repository.DataException;
import org.qora.repository.Repository;
import org.qora.repository.RepositoryManager;
@ -281,4 +283,38 @@ public class AddressesResource {
}
}
@GET
@Path("/assetorders/{address}")
@Operation(
summary = "Asset orders created by this address",
responses = {
@ApiResponse(
description = "Asset orders",
content = @Content(array = @ArraySchema(schema = @Schema(implementation = OrderData.class)))
)
}
)
@ApiErrors({ApiError.INVALID_ADDRESS, ApiError.ADDRESS_NO_EXISTS, ApiError.REPOSITORY_ISSUE})
public List<OrderData> getAssetOrders(@PathParam("address") String address, @QueryParam("includeClosed") boolean includeClosed, @QueryParam("includeFulfilled") boolean includeFulfilled) {
if (!Crypto.isValidAddress(address))
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_ADDRESS);
try (final Repository repository = RepositoryManager.getRepository()) {
AccountData accountData = repository.getAccountRepository().getAccount(address);
if (accountData == null)
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.ADDRESS_NO_EXISTS);
byte[] publicKey = accountData.getPublicKey();
if (publicKey == null)
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.ADDRESS_NO_EXISTS);
return repository.getAssetRepository().getAccountsOrders(publicKey, includeClosed, includeFulfilled);
} catch (ApiException e) {
throw e;
} catch (DataException e) {
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
}
}
}

View File

@ -32,6 +32,7 @@ import org.qora.data.account.AccountBalanceData;
import org.qora.data.asset.AssetData;
import org.qora.data.asset.OrderData;
import org.qora.data.asset.TradeData;
import org.qora.data.transaction.CancelOrderTransactionData;
import org.qora.data.transaction.CreateOrderTransactionData;
import org.qora.data.transaction.IssueAssetTransactionData;
import org.qora.repository.DataException;
@ -40,6 +41,7 @@ import org.qora.repository.RepositoryManager;
import org.qora.transaction.Transaction;
import org.qora.transaction.Transaction.ValidationResult;
import org.qora.transform.TransformationException;
import org.qora.transform.transaction.CancelOrderTransactionTransformer;
import org.qora.transform.transaction.CreateOrderTransactionTransformer;
import org.qora.transform.transaction.IssueAssetTransactionTransformer;
import org.qora.utils.Base58;
@ -232,6 +234,47 @@ public class AssetsResource {
}
}
@POST
@Path("/order/delete")
@Operation(
summary = "Cancel existing asset order",
requestBody = @RequestBody(
required = true,
content = @Content(
mediaType = MediaType.APPLICATION_JSON,
schema = @Schema(implementation = CancelOrderTransactionData.class)
)
),
responses = {
@ApiResponse(
description = "raw, unsigned, CANCEL_ORDER transaction encoded in Base58",
content = @Content(
mediaType = MediaType.TEXT_PLAIN,
schema = @Schema(
type = "string"
)
)
)
}
)
@ApiErrors({ApiError.TRANSFORMATION_ERROR, ApiError.REPOSITORY_ISSUE, ApiError.TRANSACTION_INVALID})
public String cancelOrder(CancelOrderTransactionData transactionData) {
try (final Repository repository = RepositoryManager.getRepository()) {
Transaction transaction = Transaction.fromData(repository, transactionData);
ValidationResult result = transaction.isValidUnconfirmed();
if (result != ValidationResult.OK)
throw TransactionsResource.createTransactionInvalidException(request, result);
byte[] bytes = CancelOrderTransactionTransformer.toBytes(transactionData);
return Base58.encode(bytes);
} catch (TransformationException e) {
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.TRANSFORMATION_ERROR, e);
} catch (DataException e) {
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
}
}
@POST
@Path("/issue")
@Operation(

View File

@ -4,8 +4,10 @@ import java.math.BigDecimal;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import org.qora.transaction.Transaction;
import org.qora.transaction.Transaction.TransactionType;
import io.swagger.v3.oas.annotations.media.Schema;
@ -15,12 +17,14 @@ import io.swagger.v3.oas.annotations.media.Schema;
public class CancelOrderTransactionData extends TransactionData {
// Properties
@Schema(description = "order ID to cancel", example = "2zYCM8P3PSzUxFNPAKFsSdwg9dWQcYTPCuKkuQbx3GVxTUVjXAUwEmEnvUUss11SZ3p38C16UfYb3cbXP9sRuqFx")
private byte[] orderId;
// Constructors
// For JAX-RS
protected CancelOrderTransactionData() {
super(TransactionType.CANCEL_ASSET_ORDER);
}
public CancelOrderTransactionData(byte[] creatorPublicKey, byte[] orderId, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
@ -39,4 +43,17 @@ public class CancelOrderTransactionData extends TransactionData {
return this.orderId;
}
// Re-expose creatorPublicKey for this transaction type for JAXB
@XmlElement(name = "creatorPublicKey")
@Schema(name = "creatorPublicKey", description = "order creator's public key", example = "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP")
public byte[] getOrderCreatorPublicKey() {
return this.creatorPublicKey;
}
@XmlElement(name = "creatorPublicKey")
@Schema(name = "creatorPublicKey", description = "order creator's public key", example = "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP")
public void setOrderCreatorPublicKey(byte[] creatorPublicKey) {
this.creatorPublicKey = creatorPublicKey;
}
}

View File

@ -9,7 +9,6 @@ import javax.xml.bind.annotation.XmlElement;
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 JAX-RS
@XmlAccessorType(XmlAccessType.FIELD)
@ -17,9 +16,9 @@ import io.swagger.v3.oas.annotations.media.Schema.AccessMode;
public class CreateOrderTransactionData extends TransactionData {
// Properties
@Schema(description = "asset on offer to give by order creator")
@Schema(description = "ID of asset on offer to give by order creator", example = "1")
private long haveAssetId;
@Schema(description = "asset wanted to receive by order creator")
@Schema(description = "ID of asset wanted to receive by order creator", example = "0")
private long wantAssetId;
@Schema(description = "amount of \"have\" asset to trade")
private BigDecimal amount;

View File

@ -32,6 +32,8 @@ public interface AssetRepository {
public List<OrderData> getOpenOrders(long haveAssetId, long wantAssetId) throws DataException;
public List<OrderData> getAccountsOrders(byte[] publicKey, boolean includeClosed, boolean includeFulfilled) throws DataException;
public void save(OrderData orderData) throws DataException;
public void delete(byte[] orderId) throws DataException;

View File

@ -201,6 +201,44 @@ public class HSQLDBAssetRepository implements AssetRepository {
}
}
@Override
public List<OrderData> getAccountsOrders(byte[] publicKey, boolean includeClosed, boolean includeFulfilled) throws DataException {
List<OrderData> orders = new ArrayList<OrderData>();
String sql = "SELECT asset_order_id, have_asset_id, want_asset_id, amount, fulfilled, price, ordered, is_closed, is_fulfilled "
+ "FROM AssetOrders WHERE creator = ?";
if (!includeClosed)
sql += " AND is_closed = FALSE";
if (!includeFulfilled)
sql += " AND is_fulfilled = FALSE";
sql += " ORDER BY ordered ASC";
try (ResultSet resultSet = this.repository.checkedExecute(sql, publicKey)) {
if (resultSet == null)
return orders;
do {
byte[] orderId = resultSet.getBytes(1);
long haveAssetId = resultSet.getLong(2);
long wantAssetId = resultSet.getLong(3);
BigDecimal amount = resultSet.getBigDecimal(4);
BigDecimal fulfilled = resultSet.getBigDecimal(5);
BigDecimal price = resultSet.getBigDecimal(6);
long timestamp = resultSet.getTimestamp(7, Calendar.getInstance(HSQLDBRepository.UTC)).getTime();
boolean isClosed = resultSet.getBoolean(8);
boolean isFulfilled = resultSet.getBoolean(9);
OrderData order = new OrderData(orderId, publicKey, haveAssetId, wantAssetId, amount, fulfilled, price, timestamp, isClosed,
isFulfilled);
orders.add(order);
} while (resultSet.next());
return orders;
} catch (SQLException e) {
throw new DataException("Unable to fetch account's asset orders from repository", e);
}
}
@Override
public void save(OrderData orderData) throws DataException {
HSQLDBSaver saveHelper = new HSQLDBSaver("AssetOrders");