mirror of
https://github.com/Qortal/qortal.git
synced 2025-02-12 02:05:50 +00:00
Added API call for creating an asset bid/ask order
Also added test for missing creator public key on API-submitted transaction creation calls, like /payments/pay or /asset/issue. (Needs to be an OpenAPI validator added at some point).
This commit is contained in:
parent
17f3958ad6
commit
2497ac256c
2
pom.xml
2
pom.xml
@ -4,7 +4,7 @@
|
||||
<groupId>org.qora</groupId>
|
||||
<artifactId>qora-core</artifactId>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
<packaging>bundle</packaging>
|
||||
<packaging>jar</packaging>
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<bouncycastle.version>1.60</bouncycastle.version>
|
||||
|
@ -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.CreateOrderTransactionData;
|
||||
import org.qora.data.transaction.IssueAssetTransactionData;
|
||||
import org.qora.repository.DataException;
|
||||
import org.qora.repository.Repository;
|
||||
@ -39,6 +40,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.CreateOrderTransactionTransformer;
|
||||
import org.qora.transform.transaction.IssueAssetTransactionTransformer;
|
||||
import org.qora.utils.Base58;
|
||||
|
||||
@ -243,7 +245,7 @@ public class AssetsResource {
|
||||
),
|
||||
responses = {
|
||||
@ApiResponse(
|
||||
description = "raw, unsigned payment transaction encoded in Base58",
|
||||
description = "raw, unsigned, ISSUE_ASSET transaction encoded in Base58",
|
||||
content = @Content(
|
||||
mediaType = MediaType.TEXT_PLAIN,
|
||||
schema = @Schema(
|
||||
@ -271,4 +273,45 @@ public class AssetsResource {
|
||||
}
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("/order")
|
||||
@Operation(
|
||||
summary = "Create asset order",
|
||||
requestBody = @RequestBody(
|
||||
required = true,
|
||||
content = @Content(
|
||||
mediaType = MediaType.APPLICATION_JSON,
|
||||
schema = @Schema(implementation = CreateOrderTransactionData.class)
|
||||
)
|
||||
),
|
||||
responses = {
|
||||
@ApiResponse(
|
||||
description = "raw, unsigned, CREATE_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 createOrder(CreateOrderTransactionData 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 = CreateOrderTransactionTransformer.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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ public class NamesResource {
|
||||
@POST
|
||||
@Path("/register")
|
||||
@Operation(
|
||||
summary = "Build raw, unsigned REGISTER_NAME transaction",
|
||||
summary = "Build raw, unsigned, REGISTER_NAME transaction",
|
||||
requestBody = @RequestBody(
|
||||
required = true,
|
||||
content = @Content(
|
||||
@ -50,7 +50,7 @@ public class NamesResource {
|
||||
),
|
||||
responses = {
|
||||
@ApiResponse(
|
||||
description = "raw, unsigned REGISTER_NAME transaction encoded in Base58",
|
||||
description = "raw, unsigned, REGISTER_NAME transaction encoded in Base58",
|
||||
content = @Content(
|
||||
mediaType = MediaType.TEXT_PLAIN,
|
||||
schema = @Schema(
|
||||
|
@ -38,7 +38,7 @@ public class PaymentsResource {
|
||||
@POST
|
||||
@Path("/pay")
|
||||
@Operation(
|
||||
summary = "Build raw, unsigned payment transaction",
|
||||
summary = "Build raw, unsigned, PAYMENT transaction",
|
||||
requestBody = @RequestBody(
|
||||
required = true,
|
||||
content = @Content(
|
||||
@ -50,7 +50,7 @@ public class PaymentsResource {
|
||||
),
|
||||
responses = {
|
||||
@ApiResponse(
|
||||
description = "raw, unsigned payment transaction encoded in Base58",
|
||||
description = "raw, unsigned, PAYMENT transaction encoded in Base58",
|
||||
content = @Content(
|
||||
mediaType = MediaType.TEXT_PLAIN,
|
||||
schema = @Schema(
|
||||
|
@ -4,10 +4,12 @@ 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.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)
|
||||
@ -15,15 +17,20 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
||||
public class CreateOrderTransactionData extends TransactionData {
|
||||
|
||||
// Properties
|
||||
@Schema(description = "asset on offer to give by order creator")
|
||||
private long haveAssetId;
|
||||
@Schema(description = "asset wanted to receive by order creator")
|
||||
private long wantAssetId;
|
||||
@Schema(description = "amount of \"have\" asset to trade")
|
||||
private BigDecimal amount;
|
||||
@Schema(description = "amount of \"want\" asset to receive per unit of \"have\" asset traded")
|
||||
private BigDecimal price;
|
||||
|
||||
// Constructors
|
||||
|
||||
// For JAX-RS
|
||||
protected CreateOrderTransactionData() {
|
||||
super(TransactionType.CREATE_ASSET_ORDER);
|
||||
}
|
||||
|
||||
public CreateOrderTransactionData(byte[] creatorPublicKey, long haveAssetId, long wantAssetId, BigDecimal amount, BigDecimal price, BigDecimal fee,
|
||||
@ -59,4 +66,17 @@ public class CreateOrderTransactionData extends TransactionData {
|
||||
return this.price;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -22,9 +22,9 @@ public class PaymentTransactionData extends TransactionData {
|
||||
private String recipient;
|
||||
@Schema(description = "amount to send", example = "123.456")
|
||||
@XmlJavaTypeAdapter(
|
||||
type = BigDecimal.class,
|
||||
value = org.qora.api.BigDecimalTypeAdapter.class
|
||||
)
|
||||
type = BigDecimal.class,
|
||||
value = org.qora.api.BigDecimalTypeAdapter.class
|
||||
)
|
||||
private BigDecimal amount;
|
||||
|
||||
// Constructors
|
||||
|
@ -108,6 +108,7 @@ public abstract class Transaction {
|
||||
AT_IS_FINISHED(40),
|
||||
ASSET_DOES_NOT_MATCH_AT(41),
|
||||
ASSET_ALREADY_EXISTS(43),
|
||||
MISSING_CREATOR(44),
|
||||
NOT_YET_RELEASED(1000);
|
||||
|
||||
public final int value;
|
||||
@ -364,6 +365,9 @@ public abstract class Transaction {
|
||||
* @throws DataException
|
||||
*/
|
||||
protected Account getCreator() throws DataException {
|
||||
if (this.transactionData.getCreatorPublicKey() == null)
|
||||
return null;
|
||||
|
||||
return new PublicKeyAccount(this.repository, this.transactionData.getCreatorPublicKey());
|
||||
}
|
||||
|
||||
@ -432,6 +436,9 @@ public abstract class Transaction {
|
||||
public ValidationResult isValidUnconfirmed() throws DataException {
|
||||
try {
|
||||
Account creator = this.getCreator();
|
||||
if (creator == null)
|
||||
return ValidationResult.MISSING_CREATOR;
|
||||
|
||||
creator.setLastReference(creator.getUnconfirmedLastReference());
|
||||
return this.isValid();
|
||||
} finally {
|
||||
|
Loading…
x
Reference in New Issue
Block a user