diff --git a/pom.xml b/pom.xml
index 53655871..1a0f6740 100644
--- a/pom.xml
+++ b/pom.xml
@@ -128,5 +128,15 @@
hamcrest-library
1.3
+
+ org.glassfish.jersey.media
+ jersey-media-multipart
+ 2.27
+
+
+ javax.mail
+ mail
+ 1.5.0-b01
+
\ No newline at end of file
diff --git a/src/Start.java b/src/Start.java
index 585f65c6..cbab3830 100644
--- a/src/Start.java
+++ b/src/Start.java
@@ -8,7 +8,7 @@ import repository.hsqldb.HSQLDBRepositoryFactory;
public class Start {
- private static final String connectionUrl = "jdbc:hsqldb:mem:db/test;create=true;close_result=true;sql.strict_exec=true;sql.enforce_names=true;sql.syntax_mys=true";
+ private static final String connectionUrl = "jdbc:hsqldb:file:db/test;create=true";
public static void main(String args[]) throws DataException {
RepositoryFactory repositoryFactory = new HSQLDBRepositoryFactory(connectionUrl);
@@ -19,7 +19,7 @@ public class Start {
//// testing the API client
//ApiClient client = ApiClient.getInstance();
- //String test = client.executeCommand("GET blocks/height");
+ //String test = client.executeCommand("GET blocks/first");
//System.out.println(test);
}
}
diff --git a/src/api/BlocksResource.java b/src/api/BlocksResource.java
index 5367b999..74db659c 100644
--- a/src/api/BlocksResource.java
+++ b/src/api/BlocksResource.java
@@ -1,5 +1,6 @@
package api;
+import data.block.BlockData;
import globalization.Translator;
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.annotations.Operation;
@@ -19,6 +20,7 @@ import javax.ws.rs.core.MediaType;
import repository.Repository;
import repository.RepositoryManager;
+import utils.Base58;
@Path("blocks")
@Produces({MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN})
@@ -156,7 +158,7 @@ public class BlocksResource {
responses = {
@ApiResponse(
description = "the block",
- //content = @Content(schema = @Schema(implementation = ???)),
+ content = @Content(schema = @Schema(implementation = BlockData.class)),
extensions = {
@Extension(name = "translation", properties = {
@ExtensionProperty(name="description.key", value="success_response:description")
@@ -191,10 +193,32 @@ public class BlocksResource {
)
}
)
- public String getBlock(@PathParam("signature") String signature) {
+ public BlockData getBlock(@PathParam("signature") String signature) {
Security.checkApiCallAllowed("GET blocks", request);
- throw new UnsupportedOperationException();
+ // decode signature
+ byte[] signatureBytes;
+ try
+ {
+ signatureBytes = Base58.decode(signature);
+ }
+ catch(Exception e)
+ {
+ throw this.apiErrorFactory.createError(ApiError.INVALID_SIGNATURE, e);
+ }
+
+ try (final Repository repository = RepositoryManager.getRepository()) {
+ BlockData blockData = repository.getBlockRepository().fromSignature(signatureBytes);
+
+ // check if block exists
+ if(blockData == null)
+ throw this.apiErrorFactory.createError(ApiError.BLOCK_NO_EXISTS);
+
+ return blockData;
+
+ } catch (Exception e) {
+ throw this.apiErrorFactory.createError(ApiError.UNKNOWN, e);
+ }
}
@GET
@@ -208,7 +232,7 @@ public class BlocksResource {
responses = {
@ApiResponse(
description = "the block",
- //content = @Content(schema = @Schema(implementation = ???)),
+ content = @Content(schema = @Schema(implementation = BlockData.class)),
extensions = {
@Extension(name = "translation", properties = {
@ExtensionProperty(name="description.key", value="success_response:description")
@@ -217,10 +241,21 @@ public class BlocksResource {
)
}
)
- public String getFirstBlock() {
+ public BlockData getFirstBlock() {
Security.checkApiCallAllowed("GET blocks/first", request);
- throw new UnsupportedOperationException();
+ try (final Repository repository = RepositoryManager.getRepository()) {
+ BlockData blockData = repository.getBlockRepository().fromHeight(1);
+
+ // check if block exists
+ if(blockData == null)
+ throw this.apiErrorFactory.createError(ApiError.BLOCK_NO_EXISTS);
+
+ return blockData;
+
+ } catch (Exception e) {
+ throw this.apiErrorFactory.createError(ApiError.UNKNOWN, e);
+ }
}
@GET
@@ -234,7 +269,7 @@ public class BlocksResource {
responses = {
@ApiResponse(
description = "the block",
- //content = @Content(schema = @Schema(implementation = ???)),
+ content = @Content(schema = @Schema(implementation = BlockData.class)),
extensions = {
@Extension(name = "translation", properties = {
@ExtensionProperty(name="description.key", value="success_response:description")
@@ -243,10 +278,21 @@ public class BlocksResource {
)
}
)
- public String getLastBlock() {
+ public BlockData getLastBlock() {
Security.checkApiCallAllowed("GET blocks/last", request);
- throw new UnsupportedOperationException();
+ try (final Repository repository = RepositoryManager.getRepository()) {
+ BlockData blockData = repository.getBlockRepository().getLastBlock();
+
+ // check if block exists
+ if(blockData == null)
+ throw this.apiErrorFactory.createError(ApiError.BLOCK_NO_EXISTS);
+
+ return blockData;
+
+ } catch (Exception e) {
+ throw this.apiErrorFactory.createError(ApiError.UNKNOWN, e);
+ }
}
@GET
@@ -295,10 +341,39 @@ public class BlocksResource {
)
}
)
- public String getChild(@PathParam("signature") String signature) {
+ public BlockData getChild(@PathParam("signature") String signature) {
Security.checkApiCallAllowed("GET blocks/child", request);
- throw new UnsupportedOperationException();
+ // decode signature
+ byte[] signatureBytes;
+ try
+ {
+ signatureBytes = Base58.decode(signature);
+ }
+ catch(Exception e)
+ {
+ throw this.apiErrorFactory.createError(ApiError.INVALID_SIGNATURE, e);
+ }
+
+ try (final Repository repository = RepositoryManager.getRepository()) {
+ BlockData blockData = repository.getBlockRepository().fromSignature(signatureBytes);
+
+ // check if block exists
+ if(blockData == null)
+ throw this.apiErrorFactory.createError(ApiError.BLOCK_NO_EXISTS);
+
+ int height = blockData.getHeight();
+ BlockData childBlockData = repository.getBlockRepository().fromHeight(height + 1);
+
+ // check if child exists
+ if(childBlockData == null)
+ throw this.apiErrorFactory.createError(ApiError.BLOCK_NO_EXISTS);
+
+ return childBlockData;
+
+ } catch (Exception e) {
+ throw this.apiErrorFactory.createError(ApiError.UNKNOWN, e);
+ }
}
@GET
@@ -510,7 +585,29 @@ public class BlocksResource {
public int getHeight(@PathParam("signature") String signature) {
Security.checkApiCallAllowed("GET blocks/height", request);
- throw new UnsupportedOperationException();
+ // decode signature
+ byte[] signatureBytes;
+ try
+ {
+ signatureBytes = Base58.decode(signature);
+ }
+ catch(Exception e)
+ {
+ throw this.apiErrorFactory.createError(ApiError.INVALID_SIGNATURE, e);
+ }
+
+ try (final Repository repository = RepositoryManager.getRepository()) {
+ BlockData blockData = repository.getBlockRepository().fromSignature(signatureBytes);
+
+ // check if block exists
+ if(blockData == null)
+ throw this.apiErrorFactory.createError(ApiError.BLOCK_NO_EXISTS);
+
+ return blockData.getHeight();
+
+ } catch (Exception e) {
+ throw this.apiErrorFactory.createError(ApiError.UNKNOWN, e);
+ }
}
@GET
@@ -546,9 +643,20 @@ public class BlocksResource {
)
}
)
- public String getbyHeight(@PathParam("height") int height) {
+ public BlockData getbyHeight(@PathParam("height") int height) {
Security.checkApiCallAllowed("GET blocks/byheight", request);
- throw new UnsupportedOperationException();
+ try (final Repository repository = RepositoryManager.getRepository()) {
+ BlockData blockData = repository.getBlockRepository().fromHeight(height);
+
+ // check if block exists
+ if(blockData == null)
+ throw this.apiErrorFactory.createError(ApiError.BLOCK_NO_EXISTS);
+
+ return blockData;
+
+ } catch (Exception e) {
+ throw this.apiErrorFactory.createError(ApiError.UNKNOWN, e);
+ }
}
}
diff --git a/src/data/block/BlockData.java b/src/data/block/BlockData.java
index 8c49b71b..ec98c594 100644
--- a/src/data/block/BlockData.java
+++ b/src/data/block/BlockData.java
@@ -3,8 +3,9 @@ package data.block;
import java.math.BigDecimal;
import com.google.common.primitives.Bytes;
+import java.io.Serializable;
-public class BlockData {
+public class BlockData implements Serializable {
private byte[] signature;
private int version;
@@ -20,6 +21,8 @@ public class BlockData {
private byte[] atBytes;
private BigDecimal atFees;
+ private BlockData() {} // necessary for JAX-RS serialization
+
public BlockData(int version, byte[] reference, int transactionCount, BigDecimal totalFees, byte[] transactionsSignature, int height, long timestamp,
BigDecimal generatingBalance, byte[] generatorPublicKey, byte[] generatorSignature, byte[] atBytes, BigDecimal atFees) {
this.version = version;