From 74bf930698609a1dfda40722d2439e0b1164239c Mon Sep 17 00:00:00 2001 From: catbref Date: Wed, 9 Jan 2019 16:03:07 +0000 Subject: [PATCH] API: added support for sell, cancel-sell and buy name transaction builders --- .../org/qora/api/resource/NamesResource.java | 135 ++++++++++++++++++ .../transaction/BuyNameTransactionData.java | 14 ++ .../CancelSellNameTransactionData.java | 3 + .../transaction/SellNameTransactionData.java | 9 ++ .../qora/transaction/BuyNameTransaction.java | 4 + .../CancelSellNameTransaction.java | 4 + .../qora/transaction/SellNameTransaction.java | 4 + 7 files changed, 173 insertions(+) diff --git a/src/main/java/org/qora/api/resource/NamesResource.java b/src/main/java/org/qora/api/resource/NamesResource.java index fde7429a..2df4a501 100644 --- a/src/main/java/org/qora/api/resource/NamesResource.java +++ b/src/main/java/org/qora/api/resource/NamesResource.java @@ -28,7 +28,10 @@ import org.qora.api.ApiExceptionFactory; import org.qora.api.model.NameSummary; import org.qora.crypto.Crypto; import org.qora.data.naming.NameData; +import org.qora.data.transaction.BuyNameTransactionData; +import org.qora.data.transaction.CancelSellNameTransactionData; import org.qora.data.transaction.RegisterNameTransactionData; +import org.qora.data.transaction.SellNameTransactionData; import org.qora.data.transaction.UpdateNameTransactionData; import org.qora.repository.DataException; import org.qora.repository.Repository; @@ -36,7 +39,10 @@ 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.BuyNameTransactionTransformer; +import org.qora.transform.transaction.CancelSellNameTransactionTransformer; import org.qora.transform.transaction.RegisterNameTransactionTransformer; +import org.qora.transform.transaction.SellNameTransactionTransformer; import org.qora.transform.transaction.UpdateNameTransactionTransformer; import org.qora.utils.Base58; @@ -215,4 +221,133 @@ public class NamesResource { } } + @POST + @Path("/sell") + @Operation( + summary = "Build raw, unsigned, SELL_NAME transaction", + requestBody = @RequestBody( + required = true, + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema( + implementation = SellNameTransactionData.class + ) + ) + ), + responses = { + @ApiResponse( + description = "raw, unsigned, SELL_NAME transaction encoded in Base58", + content = @Content( + mediaType = MediaType.TEXT_PLAIN, + schema = @Schema( + type = "string" + ) + ) + ) + } + ) + @ApiErrors({ApiError.TRANSACTION_INVALID, ApiError.TRANSFORMATION_ERROR, ApiError.REPOSITORY_ISSUE}) + public String sellName(SellNameTransactionData 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 = SellNameTransactionTransformer.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("/sell/cancel") + @Operation( + summary = "Build raw, unsigned, CANCEL_SELL_NAME transaction", + requestBody = @RequestBody( + required = true, + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema( + implementation = CancelSellNameTransactionData.class + ) + ) + ), + responses = { + @ApiResponse( + description = "raw, unsigned, CANCEL_SELL_NAME transaction encoded in Base58", + content = @Content( + mediaType = MediaType.TEXT_PLAIN, + schema = @Schema( + type = "string" + ) + ) + ) + } + ) + @ApiErrors({ApiError.TRANSACTION_INVALID, ApiError.TRANSFORMATION_ERROR, ApiError.REPOSITORY_ISSUE}) + public String cancelSellName(CancelSellNameTransactionData 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 = CancelSellNameTransactionTransformer.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("/buy") + @Operation( + summary = "Build raw, unsigned, BUY_NAME transaction", + requestBody = @RequestBody( + required = true, + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema( + implementation = BuyNameTransactionData.class + ) + ) + ), + responses = { + @ApiResponse( + description = "raw, unsigned, BUY_NAME transaction encoded in Base58", + content = @Content( + mediaType = MediaType.TEXT_PLAIN, + schema = @Schema( + type = "string" + ) + ) + ) + } + ) + @ApiErrors({ApiError.TRANSACTION_INVALID, ApiError.TRANSFORMATION_ERROR, ApiError.REPOSITORY_ISSUE}) + public String buyName(BuyNameTransactionData 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 = BuyNameTransactionTransformer.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); + } + } + } \ No newline at end of file diff --git a/src/main/java/org/qora/data/transaction/BuyNameTransactionData.java b/src/main/java/org/qora/data/transaction/BuyNameTransactionData.java index 743c895e..27bde460 100644 --- a/src/main/java/org/qora/data/transaction/BuyNameTransactionData.java +++ b/src/main/java/org/qora/data/transaction/BuyNameTransactionData.java @@ -4,6 +4,8 @@ import java.math.BigDecimal; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlTransient; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; import org.qora.transaction.Transaction.TransactionType; @@ -15,16 +17,28 @@ import io.swagger.v3.oas.annotations.media.Schema; public class BuyNameTransactionData extends TransactionData { // Properties + @Schema(description = "buyer's public key", example = "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP") private byte[] buyerPublicKey; + @Schema(description = "which name to buy", example = "my-name") private String name; + @Schema(description = "selling price", example = "123.456") + @XmlJavaTypeAdapter( + type = BigDecimal.class, + value = org.qora.api.BigDecimalTypeAdapter.class + ) private BigDecimal amount; + @Schema(description = "seller's address", example = "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v") private String seller; + // For internal use when orphaning + @XmlTransient + @Schema(hidden = true) private byte[] nameReference; // Constructors // For JAX-RS protected BuyNameTransactionData() { + super(TransactionType.BUY_NAME); } public BuyNameTransactionData(byte[] buyerPublicKey, String name, BigDecimal amount, String seller, byte[] nameReference, BigDecimal fee, long timestamp, diff --git a/src/main/java/org/qora/data/transaction/CancelSellNameTransactionData.java b/src/main/java/org/qora/data/transaction/CancelSellNameTransactionData.java index 02f650f5..e55da8c9 100644 --- a/src/main/java/org/qora/data/transaction/CancelSellNameTransactionData.java +++ b/src/main/java/org/qora/data/transaction/CancelSellNameTransactionData.java @@ -15,13 +15,16 @@ import io.swagger.v3.oas.annotations.media.Schema; public class CancelSellNameTransactionData extends TransactionData { // Properties + @Schema(description = "owner's public key", example = "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP") private byte[] ownerPublicKey; + @Schema(description = "which name to cancel selling", example = "my-name") private String name; // Constructors // For JAX-RS protected CancelSellNameTransactionData() { + super(TransactionType.CANCEL_SELL_NAME); } public CancelSellNameTransactionData(byte[] ownerPublicKey, String name, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) { diff --git a/src/main/java/org/qora/data/transaction/SellNameTransactionData.java b/src/main/java/org/qora/data/transaction/SellNameTransactionData.java index c68e66b0..e7f9cef7 100644 --- a/src/main/java/org/qora/data/transaction/SellNameTransactionData.java +++ b/src/main/java/org/qora/data/transaction/SellNameTransactionData.java @@ -4,6 +4,7 @@ import java.math.BigDecimal; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; import org.qora.transaction.Transaction.TransactionType; @@ -15,14 +16,22 @@ import io.swagger.v3.oas.annotations.media.Schema; public class SellNameTransactionData extends TransactionData { // Properties + @Schema(description = "owner's public key", example = "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP") private byte[] ownerPublicKey; + @Schema(description = "which name to sell", example = "my-name") private String name; + @Schema(description = "selling price", example = "123.456") + @XmlJavaTypeAdapter( + type = BigDecimal.class, + value = org.qora.api.BigDecimalTypeAdapter.class + ) private BigDecimal amount; // Constructors // For JAX-RS protected SellNameTransactionData() { + super(TransactionType.SELL_NAME); } public SellNameTransactionData(byte[] ownerPublicKey, String name, BigDecimal amount, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) { diff --git a/src/main/java/org/qora/transaction/BuyNameTransaction.java b/src/main/java/org/qora/transaction/BuyNameTransaction.java index c8c57d55..8858bafd 100644 --- a/src/main/java/org/qora/transaction/BuyNameTransaction.java +++ b/src/main/java/org/qora/transaction/BuyNameTransaction.java @@ -28,6 +28,10 @@ public class BuyNameTransaction extends Transaction { super(repository, transactionData); this.buyNameTransactionData = (BuyNameTransactionData) this.transactionData; + + // XXX This is horrible - thanks to JAXB unmarshalling not calling constructor + if (this.transactionData.getCreatorPublicKey() == null) + this.transactionData.setCreatorPublicKey(this.buyNameTransactionData.getBuyerPublicKey()); } // More information diff --git a/src/main/java/org/qora/transaction/CancelSellNameTransaction.java b/src/main/java/org/qora/transaction/CancelSellNameTransaction.java index 9492d6f5..d5ba488b 100644 --- a/src/main/java/org/qora/transaction/CancelSellNameTransaction.java +++ b/src/main/java/org/qora/transaction/CancelSellNameTransaction.java @@ -28,6 +28,10 @@ public class CancelSellNameTransaction extends Transaction { super(repository, transactionData); this.cancelSellNameTransactionData = (CancelSellNameTransactionData) this.transactionData; + + // XXX This is horrible - thanks to JAXB unmarshalling not calling constructor + if (this.transactionData.getCreatorPublicKey() == null) + this.transactionData.setCreatorPublicKey(this.cancelSellNameTransactionData.getOwnerPublicKey()); } // More information diff --git a/src/main/java/org/qora/transaction/SellNameTransaction.java b/src/main/java/org/qora/transaction/SellNameTransaction.java index ac3b01b3..4b18332a 100644 --- a/src/main/java/org/qora/transaction/SellNameTransaction.java +++ b/src/main/java/org/qora/transaction/SellNameTransaction.java @@ -29,6 +29,10 @@ public class SellNameTransaction extends Transaction { super(repository, transactionData); this.sellNameTransactionData = (SellNameTransactionData) this.transactionData; + + // XXX This is horrible - thanks to JAXB unmarshalling not calling constructor + if (this.transactionData.getCreatorPublicKey() == null) + this.transactionData.setCreatorPublicKey(this.sellNameTransactionData.getOwnerPublicKey()); } // More information