diff --git a/src/main/java/org/qora/api/model/ProxyKeyRequest.java b/src/main/java/org/qora/api/model/ProxyKeyRequest.java new file mode 100644 index 00000000..f4b7f79e --- /dev/null +++ b/src/main/java/org/qora/api/model/ProxyKeyRequest.java @@ -0,0 +1,20 @@ +package org.qora.api.model; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; + +import io.swagger.v3.oas.annotations.media.Schema; + +@XmlAccessorType(XmlAccessType.FIELD) +public class ProxyKeyRequest { + + @Schema(example = "private_key") + public byte[] generatorPrivateKey; + + @Schema(example = "public_key") + public byte[] recipientPublicKey; + + public ProxyKeyRequest() { + } + +} diff --git a/src/main/java/org/qora/api/resource/AddressesResource.java b/src/main/java/org/qora/api/resource/AddressesResource.java index 63dd278d..aab503f5 100644 --- a/src/main/java/org/qora/api/resource/AddressesResource.java +++ b/src/main/java/org/qora/api/resource/AddressesResource.java @@ -27,6 +27,7 @@ import org.qora.api.ApiError; import org.qora.api.ApiErrors; import org.qora.api.ApiException; import org.qora.api.ApiExceptionFactory; +import org.qora.api.model.ProxyKeyRequest; import org.qora.api.resource.TransactionsResource; import org.qora.asset.Asset; import org.qora.crypto.Crypto; @@ -301,7 +302,7 @@ public class AddressesResource { ) } ) - @ApiErrors({ApiError.INVALID_ADDRESS, ApiError.REPOSITORY_ISSUE}) + @ApiErrors({ApiError.INVALID_ADDRESS, ApiError.INVALID_CRITERIA, ApiError.REPOSITORY_ISSUE}) public List getProxying(@QueryParam("proxiedFor") List recipients, @QueryParam("proxiedBy") List forgers, @Parameter( @@ -321,30 +322,42 @@ public class AddressesResource { } } - @GET - @Path("/proxykey/{generatorprivatekey}/{recipientpublickey}") + @POST + @Path("/proxykey") @Operation( summary = "Calculate proxy private key", + description = "Calculates proxy private key using passed generator's private key and recipient's public key", + requestBody = @RequestBody( + required = true, + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + schema = @Schema( + implementation = ProxyKeyRequest.class + ) + ) + ), responses = { @ApiResponse( content = @Content(mediaType = MediaType.TEXT_PLAIN, schema = @Schema(type = "string")) ) } ) - public String calculateProxyKey(@PathParam("generatorprivatekey") String generatorKey58, @PathParam("recipientpublickey") String recipientKey58) { - try { - byte[] generatorKey = Base58.decode(generatorKey58); - byte[] recipientKey = Base58.decode(recipientKey58); - if (generatorKey.length != Transformer.PRIVATE_KEY_LENGTH || recipientKey.length != Transformer.PRIVATE_KEY_LENGTH) - throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_PRIVATE_KEY); - PrivateKeyAccount generator = new PrivateKeyAccount(null, generatorKey); + @ApiErrors({ApiError.INVALID_PRIVATE_KEY, ApiError.INVALID_PUBLIC_KEY, ApiError.REPOSITORY_ISSUE}) + public String calculateProxyKey(ProxyKeyRequest proxyKeyRequest) { + byte[] generatorKey = proxyKeyRequest.generatorPrivateKey; + byte[] recipientKey = proxyKeyRequest.recipientPublicKey; - byte[] proxyPrivateKey = generator.getProxyPrivateKey(recipientKey); + if (generatorKey == null || generatorKey.length != Transformer.PRIVATE_KEY_LENGTH) + throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_PRIVATE_KEY); - return Base58.encode(proxyPrivateKey); - } catch (NumberFormatException e) { - throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_PRIVATE_KEY, e); - } + if (recipientKey == null || recipientKey.length != Transformer.PUBLIC_KEY_LENGTH) + throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_PUBLIC_KEY); + + PrivateKeyAccount generator = new PrivateKeyAccount(null, generatorKey); + + byte[] proxyPrivateKey = generator.getProxyPrivateKey(recipientKey); + + return Base58.encode(proxyPrivateKey); } @POST diff --git a/src/main/java/org/qora/api/resource/TransactionsResource.java b/src/main/java/org/qora/api/resource/TransactionsResource.java index d7f84542..6aa5f9f6 100644 --- a/src/main/java/org/qora/api/resource/TransactionsResource.java +++ b/src/main/java/org/qora/api/resource/TransactionsResource.java @@ -391,7 +391,7 @@ public class TransactionsResource { schema = @Schema( type = "string", description = "raw, signed transaction in base58 encoding", - example = "base58" + example = "raw transaction base58" ) ) ), @@ -447,7 +447,7 @@ public class TransactionsResource { @POST @Path("/decode") @Operation( - summary = "Decode a raw, signed transaction", + summary = "Decode a raw, signed/unsigned transaction", requestBody = @RequestBody( required = true, content = @Content( @@ -455,7 +455,7 @@ public class TransactionsResource { schema = @Schema( type = "string", description = "raw, unsigned/signed transaction in base58 encoding", - example = "base58" + example = "raw transaction base58" ) ) ), diff --git a/src/main/java/org/qora/api/resource/UtilsResource.java b/src/main/java/org/qora/api/resource/UtilsResource.java index bcf955e0..26169495 100644 --- a/src/main/java/org/qora/api/resource/UtilsResource.java +++ b/src/main/java/org/qora/api/resource/UtilsResource.java @@ -49,7 +49,7 @@ public class UtilsResource { HttpServletRequest request; @POST - @Path("/fromBase64") + @Path("/frombase64") @Operation( summary = "Convert base64 data to hex", requestBody = @RequestBody( @@ -85,7 +85,7 @@ public class UtilsResource { } @POST - @Path("/fromBase58") + @Path("/frombase58") @Operation( summary = "Convert base58 data to hex", requestBody = @RequestBody( @@ -121,7 +121,7 @@ public class UtilsResource { } @GET - @Path("/toBase64/{hex}") + @Path("/tobase64/{hex}") @Operation( summary = "Convert hex to base64", responses = { @@ -144,7 +144,7 @@ public class UtilsResource { } @GET - @Path("/toBase58/{hex}") + @Path("/tobase58/{hex}") @Operation( summary = "Convert hex to base58", responses = { @@ -313,10 +313,19 @@ public class UtilsResource { return Base58.encode(entropy); } - @GET - @Path("/privateKey/{entropy}") + @POST + @Path("/privatekey") @Operation( summary = "Calculate private key from supplied 16-byte entropy", + requestBody = @RequestBody( + required = true, + content = @Content( + mediaType = MediaType.TEXT_PLAIN, + schema = @Schema( + type = "string" + ) + ) + ), responses = { @ApiResponse( description = "private key in base58", @@ -330,7 +339,7 @@ public class UtilsResource { } ) @ApiErrors({ApiError.NON_PRODUCTION, ApiError.INVALID_DATA}) - public String privateKey(@PathParam("entropy") String entropy58) { + public String privateKey(String entropy58) { if (Settings.getInstance().isApiRestricted()) throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.NON_PRODUCTION); @@ -349,10 +358,19 @@ public class UtilsResource { return Base58.encode(privateKey); } - @GET - @Path("/publicKey/{privateKey}") + @POST + @Path("/publickey") @Operation( summary = "Calculate public key from supplied 32-byte private key", + requestBody = @RequestBody( + required = true, + content = @Content( + mediaType = MediaType.TEXT_PLAIN, + schema = @Schema( + type = "string" + ) + ) + ), responses = { @ApiResponse( description = "public key in base58", @@ -365,8 +383,8 @@ public class UtilsResource { ) } ) - @ApiErrors({ApiError.NON_PRODUCTION, ApiError.INVALID_DATA}) - public String publicKey(@PathParam("privateKey") String privateKey58) { + @ApiErrors({ApiError.NON_PRODUCTION, ApiError.INVALID_DATA, ApiError.INVALID_PRIVATE_KEY}) + public String publicKey(String privateKey58) { if (Settings.getInstance().isApiRestricted()) throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.NON_PRODUCTION); diff --git a/src/main/java/org/qora/data/transaction/ArbitraryTransactionData.java b/src/main/java/org/qora/data/transaction/ArbitraryTransactionData.java index 047dd5a0..074f291d 100644 --- a/src/main/java/org/qora/data/transaction/ArbitraryTransactionData.java +++ b/src/main/java/org/qora/data/transaction/ArbitraryTransactionData.java @@ -30,8 +30,13 @@ public class ArbitraryTransactionData extends TransactionData { // Properties private int version; + + @Schema(example = "sender_public_key") private byte[] senderPublicKey; + private int service; + + @Schema(example = "raw_data_in_base58") private byte[] data; private DataType dataType; private List payments; diff --git a/src/main/java/org/qora/data/transaction/GroupApprovalTransactionData.java b/src/main/java/org/qora/data/transaction/GroupApprovalTransactionData.java index 384a4143..7e12f168 100644 --- a/src/main/java/org/qora/data/transaction/GroupApprovalTransactionData.java +++ b/src/main/java/org/qora/data/transaction/GroupApprovalTransactionData.java @@ -27,7 +27,8 @@ public class GroupApprovalTransactionData extends TransactionData { ) private byte[] adminPublicKey; @Schema( - description = "transaction pending approval" + description = "transaction pending approval", + example = "transaction_signature" ) private byte[] pendingSignature; @Schema( diff --git a/src/main/java/org/qora/data/transaction/ProxyForgingTransactionData.java b/src/main/java/org/qora/data/transaction/ProxyForgingTransactionData.java index 8bb83360..44b2bb5b 100644 --- a/src/main/java/org/qora/data/transaction/ProxyForgingTransactionData.java +++ b/src/main/java/org/qora/data/transaction/ProxyForgingTransactionData.java @@ -16,10 +16,16 @@ import io.swagger.v3.oas.annotations.media.Schema; @Schema(allOf = {TransactionData.class}) public class ProxyForgingTransactionData extends TransactionData { + @Schema(example = "forger_public_key") private byte[] forgerPublicKey; + private String recipient; + + @Schema(example = "proxy_public_key") private byte[] proxyPublicKey; + private BigDecimal share; + // No need to ever expose this via API @XmlTransient @Schema(hidden = true) diff --git a/src/main/java/org/qora/data/transaction/TransferAssetTransactionData.java b/src/main/java/org/qora/data/transaction/TransferAssetTransactionData.java index f9bb7776..a8757fb3 100644 --- a/src/main/java/org/qora/data/transaction/TransferAssetTransactionData.java +++ b/src/main/java/org/qora/data/transaction/TransferAssetTransactionData.java @@ -17,7 +17,9 @@ import io.swagger.v3.oas.annotations.media.Schema.AccessMode; public class TransferAssetTransactionData extends TransactionData { // Properties + @Schema(example = "sender_public_key") private byte[] senderPublicKey; + private String recipient; private BigDecimal amount; private long assetId;