map = stream(ApiError.values()).collect(toMap(apiError -> apiError.code, apiError -> apiError));
+
private final int code; // API error code
private final int status; // HTTP status code
@@ -117,20 +126,15 @@ public enum ApiError {
}
public static ApiError fromCode(int code) {
- for(ApiError apiError : ApiError.values()) {
- if(apiError.code == code)
- return apiError;
- }
-
- return null;
+ return map.get(code);
}
-
- int getCode() {
+
+ public int getCode() {
return this.code;
}
- int getStatus() {
+ public int getStatus() {
return this.status;
}
-
+
}
\ No newline at end of file
diff --git a/src/api/ApiErrorMessage.java b/src/main/java/api/ApiErrorMessage.java
similarity index 68%
rename from src/api/ApiErrorMessage.java
rename to src/main/java/api/ApiErrorMessage.java
index 161e1836..580bb9fa 100644
--- a/src/api/ApiErrorMessage.java
+++ b/src/main/java/api/ApiErrorMessage.java
@@ -7,15 +7,16 @@ import javax.xml.bind.annotation.XmlAccessorType;
@XmlAccessorType(XmlAccessType.FIELD)
public class ApiErrorMessage {
- public int error;
+ protected int error;
- public String message;
+ protected String message;
- ApiErrorMessage() {
+ protected ApiErrorMessage() {
}
- ApiErrorMessage(int errorCode, String message) {
+ public ApiErrorMessage(int errorCode, String message) {
this.error = errorCode;
this.message = message;
}
+
}
diff --git a/src/main/java/api/ApiErrors.java b/src/main/java/api/ApiErrors.java
new file mode 100644
index 00000000..53728601
--- /dev/null
+++ b/src/main/java/api/ApiErrors.java
@@ -0,0 +1,18 @@
+package api;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * This annotation lists potential ApiErrors that may be returned, or thrown, during the execution of this method.
+ *
+ * Value is expected to be an array of ApiError enum instances.
+ *
+ */
+@Target({ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface ApiErrors {
+ ApiError[] value() default {};
+}
diff --git a/src/api/ApiException.java b/src/main/java/api/ApiException.java
similarity index 84%
rename from src/api/ApiException.java
rename to src/main/java/api/ApiException.java
index b8419cc7..99e38a61 100644
--- a/src/api/ApiException.java
+++ b/src/main/java/api/ApiException.java
@@ -6,14 +6,16 @@ import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
public class ApiException extends WebApplicationException {
- // HTTP status code
- int status;
+ private static final long serialVersionUID = 4619299036312089050L;
+
+ // HTTP status code
+ public int status;
// API error code
- int error;
+ public int error;
- String message;
+ public String message;
public ApiException(int status, int error, String message) {
this(status, error, message, null);
diff --git a/src/main/java/api/ApiExceptionFactory.java b/src/main/java/api/ApiExceptionFactory.java
new file mode 100644
index 00000000..d5156148
--- /dev/null
+++ b/src/main/java/api/ApiExceptionFactory.java
@@ -0,0 +1,20 @@
+package api;
+
+import javax.servlet.http.HttpServletRequest;
+
+import globalization.Translator;
+
+public enum ApiExceptionFactory {
+ INSTANCE;
+
+ public ApiException createException(HttpServletRequest request, ApiError apiError, Throwable throwable, Object... args) {
+ String template = Translator.INSTANCE.translate("ApiError", request.getLocale().getLanguage(), apiError.name());
+ String message = String.format(template, args);
+ return new ApiException(apiError.getStatus(), apiError.getCode(), message, throwable);
+ }
+
+ public ApiException createException(HttpServletRequest request, ApiError apiError) {
+ return createException(request, apiError, null);
+ }
+
+}
diff --git a/src/api/ApiService.java b/src/main/java/api/ApiService.java
similarity index 76%
rename from src/api/ApiService.java
rename to src/main/java/api/ApiService.java
index 05c9788d..b2aed2d4 100644
--- a/src/api/ApiService.java
+++ b/src/main/java/api/ApiService.java
@@ -2,8 +2,6 @@ package api;
import io.swagger.v3.jaxrs2.integration.resources.OpenApiResource;
-import java.util.HashSet;
-import java.util.Set;
import org.eclipse.jetty.rewrite.handler.RedirectPatternRule;
import org.eclipse.jetty.rewrite.handler.RewriteHandler;
@@ -17,30 +15,21 @@ import org.eclipse.jetty.servlets.CrossOriginFilter;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.servlet.ServletContainer;
+import api.resource.AnnotationPostProcessor;
+import api.resource.ApiDefinition;
import settings.Settings;
public class ApiService {
private final Server server;
- private final Set> resources;
+ private final ResourceConfig config;
public ApiService() {
- // Resources to register
- this.resources = new HashSet>();
- this.resources.add(AddressesResource.class);
- this.resources.add(AdminResource.class);
- this.resources.add(AssetsResource.class);
- this.resources.add(BlocksResource.class);
- this.resources.add(NamesResource.class);
- this.resources.add(PaymentsResource.class);
- this.resources.add(TransactionsResource.class);
- this.resources.add(UtilsResource.class);
-
- this.resources.add(BlockExplorerResource.class); // block-explorer.html
- this.resources.add(OpenApiResource.class); // Swagger/OpenAPI
- this.resources.add(ApiDefinition.class); // API info
- this.resources.add(AnnotationPostProcessor.class); // For API resource annotations
- ResourceConfig config = new ResourceConfig(this.resources);
+ config = new ResourceConfig();
+ config.packages("api.resource");
+ config.register(OpenApiResource.class);
+ config.register(ApiDefinition.class);
+ config.register(AnnotationPostProcessor.class);
// Create RPC server
this.server = new Server(Settings.getInstance().getRpcPort());
@@ -94,8 +83,9 @@ public class ApiService {
return instance;
}
- Iterable> getResources() {
- return resources;
+ public Iterable> getResources() {
+ // return resources;
+ return config.getClasses();
}
public void start() {
diff --git a/src/api/Base58TypeAdapter.java b/src/main/java/api/Base58TypeAdapter.java
similarity index 100%
rename from src/api/Base58TypeAdapter.java
rename to src/main/java/api/Base58TypeAdapter.java
diff --git a/src/api/BigDecimalTypeAdapter.java b/src/main/java/api/BigDecimalTypeAdapter.java
similarity index 100%
rename from src/api/BigDecimalTypeAdapter.java
rename to src/main/java/api/BigDecimalTypeAdapter.java
diff --git a/src/api/Constants.java b/src/main/java/api/Constants.java
similarity index 100%
rename from src/api/Constants.java
rename to src/main/java/api/Constants.java
diff --git a/src/api/Security.java b/src/main/java/api/Security.java
similarity index 72%
rename from src/api/Security.java
rename to src/main/java/api/Security.java
index 2d981b2c..43463428 100644
--- a/src/api/Security.java
+++ b/src/main/java/api/Security.java
@@ -13,10 +13,10 @@ public class Security {
try {
remoteAddr = InetAddress.getByName(request.getRemoteAddr());
} catch (UnknownHostException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.UNAUTHORIZED);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.UNAUTHORIZED);
}
if (!remoteAddr.isLoopbackAddress())
- throw ApiErrorFactory.getInstance().createError(ApiError.UNAUTHORIZED);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.UNAUTHORIZED);
}
}
diff --git a/src/api/TransactionClassExtractor.java b/src/main/java/api/TransactionClassExtractor.java
similarity index 100%
rename from src/api/TransactionClassExtractor.java
rename to src/main/java/api/TransactionClassExtractor.java
diff --git a/src/api/TranslatableProperty.java b/src/main/java/api/TranslatableProperty.java
similarity index 100%
rename from src/api/TranslatableProperty.java
rename to src/main/java/api/TranslatableProperty.java
diff --git a/src/api/models/AssetWithHolders.java b/src/main/java/api/models/AssetWithHolders.java
similarity index 100%
rename from src/api/models/AssetWithHolders.java
rename to src/main/java/api/models/AssetWithHolders.java
diff --git a/src/api/models/BlockWithTransactions.java b/src/main/java/api/models/BlockWithTransactions.java
similarity index 100%
rename from src/api/models/BlockWithTransactions.java
rename to src/main/java/api/models/BlockWithTransactions.java
diff --git a/src/api/models/OrderWithTrades.java b/src/main/java/api/models/OrderWithTrades.java
similarity index 100%
rename from src/api/models/OrderWithTrades.java
rename to src/main/java/api/models/OrderWithTrades.java
diff --git a/src/api/models/SimpleTransactionSignRequest.java b/src/main/java/api/models/SimpleTransactionSignRequest.java
similarity index 100%
rename from src/api/models/SimpleTransactionSignRequest.java
rename to src/main/java/api/models/SimpleTransactionSignRequest.java
diff --git a/src/api/models/TradeWithOrderInfo.java b/src/main/java/api/models/TradeWithOrderInfo.java
similarity index 100%
rename from src/api/models/TradeWithOrderInfo.java
rename to src/main/java/api/models/TradeWithOrderInfo.java
diff --git a/src/api/AddressesResource.java b/src/main/java/api/resource/AddressesResource.java
similarity index 53%
rename from src/api/AddressesResource.java
rename to src/main/java/api/resource/AddressesResource.java
index f3dd6454..cfc0a4d1 100644
--- a/src/api/AddressesResource.java
+++ b/src/main/java/api/resource/AddressesResource.java
@@ -1,9 +1,7 @@
-package api;
+package api.resource;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
-import io.swagger.v3.oas.annotations.extensions.Extension;
-import io.swagger.v3.oas.annotations.extensions.ExtensionProperty;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
@@ -21,6 +19,10 @@ import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
+import api.ApiError;
+import api.ApiErrors;
+import api.ApiException;
+import api.ApiExceptionFactory;
import data.account.AccountBalanceData;
import data.account.AccountData;
import qora.account.Account;
@@ -32,12 +34,8 @@ import repository.RepositoryManager;
import transform.Transformer;
import utils.Base58;
-@Path("addresses")
+@Path("/addresses")
@Produces({MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN})
-@Extension(name = "translation", properties = {
- @ExtensionProperty(name="path", value="/Api/AddressesResource")
- }
-)
@Tag(name = "Addresses")
public class AddressesResource {
@@ -49,30 +47,17 @@ public class AddressesResource {
@Operation(
summary = "Fetch reference for next transaction to be created by address",
description = "Returns the base58-encoded signature of the last confirmed transaction created by address, failing that: the first incoming transaction to address. Returns \"false\" if there is no transactions.",
- extensions = {
- @Extension(name = "translation", properties = {
- @ExtensionProperty(name="path", value="GET lastreference:address"),
- @ExtensionProperty(name="description.key", value="operation:description")
- }),
- @Extension(properties = {
- @ExtensionProperty(name="apiErrors", value="[\"INVALID_ADDRESS\"]", parseValue = true),
- })
- },
responses = {
@ApiResponse(
description = "the base58-encoded transaction signature or \"false\"",
- content = @Content(mediaType = MediaType.TEXT_PLAIN, schema = @Schema(type = "string")),
- extensions = {
- @Extension(name = "translation", properties = {
- @ExtensionProperty(name="description.key", value="success_response:description")
- })
- }
+ content = @Content(mediaType = MediaType.TEXT_PLAIN, schema = @Schema(type = "string"))
)
}
)
+ @ApiErrors({ApiError.INVALID_ADDRESS, ApiError.REPOSITORY_ISSUE})
public String getLastReference(@Parameter(ref = "address") @PathParam("address") String address) {
if (!Crypto.isValidAddress(address))
- throw ApiErrorFactory.getInstance().createError(ApiError.INVALID_ADDRESS);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_ADDRESS);
byte[] lastReference = null;
try (final Repository repository = RepositoryManager.getRepository()) {
@@ -81,7 +66,7 @@ public class AddressesResource {
} catch (ApiException e) {
throw e;
} catch (DataException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.REPOSITORY_ISSUE, e);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
}
if(lastReference == null || lastReference.length == 0) {
@@ -95,31 +80,18 @@ public class AddressesResource {
@Path("/lastreference/{address}/unconfirmed")
@Operation(
summary = "Fetch reference for next transaction to be created by address, considering unconfirmed transactions",
- description = "Returns the base58-encoded signature of the last confirmed/unconfirmed transaction created by address, failing that: the first incoming transaction. Returns \\\"false\\\" if there is no transactions.",
- extensions = {
- @Extension(name = "translation", properties = {
- @ExtensionProperty(name="path", value="GET lastreference:address:unconfirmed"),
- @ExtensionProperty(name="description.key", value="operation:description")
- }),
- @Extension(properties = {
- @ExtensionProperty(name="apiErrors", value="[\"INVALID_ADDRESS\"]", parseValue = true),
- })
- },
+ description = "Returns the base58-encoded signature of the last confirmed/unconfirmed transaction created by address, failing that: the first incoming transaction. Returns \"false\" if there is no transactions.",
responses = {
@ApiResponse(
description = "the base58-encoded transaction signature",
- content = @Content(mediaType = MediaType.TEXT_PLAIN, schema = @Schema(type = "string")),
- extensions = {
- @Extension(name = "translation", properties = {
- @ExtensionProperty(name="description.key", value="success_response:description")
- })
- }
+ content = @Content(mediaType = MediaType.TEXT_PLAIN, schema = @Schema(type = "string"))
)
}
)
+ @ApiErrors({ApiError.INVALID_ADDRESS, ApiError.REPOSITORY_ISSUE})
public String getLastReferenceUnconfirmed(@PathParam("address") String address) {
if (!Crypto.isValidAddress(address))
- throw ApiErrorFactory.getInstance().createError(ApiError.INVALID_ADDRESS);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_ADDRESS);
byte[] lastReference = null;
try (final Repository repository = RepositoryManager.getRepository()) {
@@ -128,7 +100,7 @@ public class AddressesResource {
} catch (ApiException e) {
throw e;
} catch (DataException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.REPOSITORY_ISSUE, e);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
}
if(lastReference == null || lastReference.length == 0) {
@@ -143,21 +115,9 @@ public class AddressesResource {
@Operation(
summary = "Validates the given address",
description = "Returns true/false.",
- extensions = {
- @Extension(name = "translation", properties = {
- @ExtensionProperty(name="path", value="GET validate:address"),
- @ExtensionProperty(name="summary.key", value="operation:summary"),
- @ExtensionProperty(name="description.key", value="operation:description"),
- })
- },
responses = {
@ApiResponse(
- content = @Content(mediaType = MediaType.TEXT_PLAIN, schema = @Schema(type = "boolean")),
- extensions = {
- @Extension(name = "translation", properties = {
- @ExtensionProperty(name="description.key", value="success_response:description")
- })
- }
+ content = @Content(mediaType = MediaType.TEXT_PLAIN, schema = @Schema(type = "boolean"))
)
}
)
@@ -170,30 +130,17 @@ public class AddressesResource {
@Operation(
summary = "Return the generating balance of the given address",
description = "Returns the effective balance of the given address, used in Proof-of-Stake calculationgs when generating a new block.",
- extensions = {
- @Extension(name = "translation", properties = {
- @ExtensionProperty(name="path", value="GET generatingbalance:address"),
- @ExtensionProperty(name="description.key", value="operation:description")
- }),
- @Extension(properties = {
- @ExtensionProperty(name="apiErrors", value="[\"INVALID_ADDRESS\"]", parseValue = true),
- })
- },
responses = {
@ApiResponse(
description = "the generating balance",
- content = @Content(mediaType = MediaType.TEXT_PLAIN, schema = @Schema(type = "string", format = "number")),
- extensions = {
- @Extension(name = "translation", properties = {
- @ExtensionProperty(name="description.key", value="success_response:description")
- })
- }
+ content = @Content(mediaType = MediaType.TEXT_PLAIN, schema = @Schema(type = "string", format = "number"))
)
}
)
+ @ApiErrors({ApiError.INVALID_ADDRESS, ApiError.REPOSITORY_ISSUE})
public BigDecimal getGeneratingBalanceOfAddress(@PathParam("address") String address) {
if (!Crypto.isValidAddress(address))
- throw ApiErrorFactory.getInstance().createError(ApiError.INVALID_ADDRESS);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_ADDRESS);
try (final Repository repository = RepositoryManager.getRepository()) {
Account account = new Account(repository, address);
@@ -201,7 +148,7 @@ public class AddressesResource {
} catch (ApiException e) {
throw e;
} catch (DataException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.REPOSITORY_ISSUE, e);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
}
}
@@ -209,30 +156,17 @@ public class AddressesResource {
@Path("/balance/{address}")
@Operation(
summary = "Returns the confirmed balance of the given address",
- extensions = {
- @Extension(name = "translation", properties = {
- @ExtensionProperty(name="path", value="GET balance:address"),
- @ExtensionProperty(name="description.key", value="operation:description")
- }),
- @Extension(properties = {
- @ExtensionProperty(name="apiErrors", value="[\"INVALID_ADDRESS\"]", parseValue = true),
- })
- },
responses = {
@ApiResponse(
description = "the balance",
- content = @Content(mediaType = MediaType.TEXT_PLAIN, schema = @Schema(type = "string", format = "number")),
- extensions = {
- @Extension(name = "translation", properties = {
- @ExtensionProperty(name="description.key", value="success_response:description")
- })
- }
+ content = @Content(mediaType = MediaType.TEXT_PLAIN, schema = @Schema(type = "string", format = "number"))
)
}
)
+ @ApiErrors({ApiError.INVALID_ADDRESS, ApiError.REPOSITORY_ISSUE})
public BigDecimal getGeneratingBalance(@PathParam("address") String address) {
if (!Crypto.isValidAddress(address))
- throw ApiErrorFactory.getInstance().createError(ApiError.INVALID_ADDRESS);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_ADDRESS);
try (final Repository repository = RepositoryManager.getRepository()) {
Account account = new Account(repository, address);
@@ -240,7 +174,7 @@ public class AddressesResource {
} catch (ApiException e) {
throw e;
} catch (DataException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.REPOSITORY_ISSUE, e);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
}
}
@@ -249,30 +183,17 @@ public class AddressesResource {
@Operation(
summary = "Asset-specific balance request",
description = "Returns the confirmed balance of the given address for the given asset key.",
- extensions = {
- @Extension(name = "translation", properties = {
- @ExtensionProperty(name="path", value="GET assetbalance:assetid:address"),
- @ExtensionProperty(name="description.key", value="operation:description")
- }),
- @Extension(properties = {
- @ExtensionProperty(name="apiErrors", value="[\"INVALID_ADDRESS\", \"INVALID_ASSET_ID\"]", parseValue = true),
- })
- },
responses = {
@ApiResponse(
description = "the balance",
- content = @Content(mediaType = MediaType.TEXT_PLAIN, schema = @Schema(type = "string", format = "number")),
- extensions = {
- @Extension(name = "translation", properties = {
- @ExtensionProperty(name="description.key", value="success_response:description")
- })
- }
+ content = @Content(mediaType = MediaType.TEXT_PLAIN, schema = @Schema(type = "string", format = "number"))
)
}
)
+ @ApiErrors({ApiError.INVALID_ADDRESS, ApiError.REPOSITORY_ISSUE})
public BigDecimal getAssetBalance(@PathParam("assetid") long assetid, @PathParam("address") String address) {
if (!Crypto.isValidAddress(address))
- throw ApiErrorFactory.getInstance().createError(ApiError.INVALID_ADDRESS);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_ADDRESS);
try (final Repository repository = RepositoryManager.getRepository()) {
Account account = new Account(repository, address);
@@ -280,7 +201,7 @@ public class AddressesResource {
} catch (ApiException e) {
throw e;
} catch (DataException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.REPOSITORY_ISSUE, e);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
}
}
@@ -289,37 +210,24 @@ public class AddressesResource {
@Operation(
summary = "All assets owned by this address",
description = "Returns the list of assets for this address, with balances.",
- extensions = {
- @Extension(name = "translation", properties = {
- @ExtensionProperty(name="path", value="GET assets:address"),
- @ExtensionProperty(name="description.key", value="operation:description")
- }),
- @Extension(properties = {
- @ExtensionProperty(name="apiErrors", value="[\"INVALID_ADDRESS\"]", parseValue = true),
- })
- },
responses = {
@ApiResponse(
description = "the list of assets",
- content = @Content(array = @ArraySchema(schema = @Schema(implementation = AccountBalanceData.class))),
- extensions = {
- @Extension(name = "translation", properties = {
- @ExtensionProperty(name="description.key", value="success_response:description")
- })
- }
+ content = @Content(array = @ArraySchema(schema = @Schema(implementation = AccountBalanceData.class)))
)
}
)
+ @ApiErrors({ApiError.INVALID_ADDRESS, ApiError.REPOSITORY_ISSUE})
public List getAssets(@PathParam("address") String address) {
if (!Crypto.isValidAddress(address))
- throw ApiErrorFactory.getInstance().createError(ApiError.INVALID_ADDRESS);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_ADDRESS);
try (final Repository repository = RepositoryManager.getRepository()) {
return repository.getAccountRepository().getAllBalances(address);
} catch (ApiException e) {
throw e;
} catch (DataException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.REPOSITORY_ISSUE, e);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
}
}
@@ -327,24 +235,10 @@ public class AddressesResource {
@Path("/balance/{address}/{confirmations}")
@Operation(
summary = "Calculates the balance of the given address for the given confirmations",
- extensions = {
- @Extension(name = "translation", properties = {
- @ExtensionProperty(name="path", value="GET balance:address:confirmations"),
- @ExtensionProperty(name="description.key", value="operation:description")
- }),
- @Extension(properties = {
- @ExtensionProperty(name="apiErrors", value="[\"INVALID_ADDRESS\"]", parseValue = true),
- })
- },
responses = {
@ApiResponse(
description = "the balance",
- content = @Content(schema = @Schema(implementation = String.class)),
- extensions = {
- @Extension(name = "translation", properties = {
- @ExtensionProperty(name="description.key", value="success_response:description")
- })
- }
+ content = @Content(schema = @Schema(type = "string", format = "number"))
)
}
)
@@ -357,30 +251,17 @@ public class AddressesResource {
@Operation(
summary = "Get public key of address",
description = "Returns the base58-encoded account public key of the given address, or \"false\" if address not known or has no public key.",
- extensions = {
- @Extension(name = "translation", properties = {
- @ExtensionProperty(name="path", value="GET publickey:address"),
- @ExtensionProperty(name="description.key", value="operation:description")
- }),
- @Extension(properties = {
- @ExtensionProperty(name="apiErrors", value="[\"INVALID_ADDRESS\"]", parseValue = true),
- })
- },
responses = {
@ApiResponse(
description = "the public key",
- content = @Content(mediaType = MediaType.TEXT_PLAIN, schema = @Schema(type = "string")),
- extensions = {
- @Extension(name = "translation", properties = {
- @ExtensionProperty(name="description.key", value="success_response:description")
- })
- }
+ content = @Content(mediaType = MediaType.TEXT_PLAIN, schema = @Schema(type = "string"))
)
}
)
+ @ApiErrors({ApiError.INVALID_ADDRESS, ApiError.REPOSITORY_ISSUE})
public String getPublicKey(@PathParam("address") String address) {
if (!Crypto.isValidAddress(address))
- throw ApiErrorFactory.getInstance().createError(ApiError.INVALID_ADDRESS);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_ADDRESS);
try (final Repository repository = RepositoryManager.getRepository()) {
AccountData accountData = repository.getAccountRepository().getAccount(address);
@@ -396,7 +277,7 @@ public class AddressesResource {
} catch (ApiException e) {
throw e;
} catch (DataException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.REPOSITORY_ISSUE, e);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
}
}
@@ -405,46 +286,33 @@ public class AddressesResource {
@Operation(
summary = "Convert public key into address",
description = "Returns account address based on supplied public key. Expects base58-encoded, 32-byte public key.",
- extensions = {
- @Extension(name = "translation", properties = {
- @ExtensionProperty(name="path", value="GET publickey:address"),
- @ExtensionProperty(name="description.key", value="operation:description")
- }),
- @Extension(properties = {
- @ExtensionProperty(name="apiErrors", value="[\"INVALID_ADDRESS\"]", parseValue = true),
- })
- },
responses = {
@ApiResponse(
description = "the address",
- content = @Content(mediaType = MediaType.TEXT_PLAIN, schema = @Schema(type = "string")),
- extensions = {
- @Extension(name = "translation", properties = {
- @ExtensionProperty(name="description.key", value="success_response:description")
- })
- }
+ content = @Content(mediaType = MediaType.TEXT_PLAIN, schema = @Schema(type = "string"))
)
}
)
+ @ApiErrors({ApiError.INVALID_PUBLIC_KEY, ApiError.REPOSITORY_ISSUE})
public String fromPublicKey(@PathParam("publickey") String publicKey58) {
// Decode public key
byte[] publicKey;
try {
publicKey = Base58.decode(publicKey58);
} catch (NumberFormatException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.INVALID_PUBLIC_KEY, e);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_PUBLIC_KEY, e);
}
// Correct size for public key?
if (publicKey.length != Transformer.PUBLIC_KEY_LENGTH)
- throw ApiErrorFactory.getInstance().createError(ApiError.INVALID_PUBLIC_KEY);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_PUBLIC_KEY);
try (final Repository repository = RepositoryManager.getRepository()) {
return Crypto.toAddress(publicKey);
} catch (ApiException e) {
throw e;
} catch (DataException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.REPOSITORY_ISSUE, e);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
}
}
diff --git a/src/api/AdminResource.java b/src/main/java/api/resource/AdminResource.java
similarity index 71%
rename from src/api/AdminResource.java
rename to src/main/java/api/resource/AdminResource.java
index e701b3fb..cc4894ea 100644
--- a/src/api/AdminResource.java
+++ b/src/main/java/api/resource/AdminResource.java
@@ -1,10 +1,8 @@
-package api;
+package api.resource;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
-import io.swagger.v3.oas.annotations.extensions.Extension;
-import io.swagger.v3.oas.annotations.extensions.ExtensionProperty;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
@@ -17,14 +15,11 @@ import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
+import api.Security;
import controller.Controller;
-@Path("admin")
+@Path("/admin")
@Produces({MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN})
-@Extension(name = "translation", properties = {
- @ExtensionProperty(name="path", value="/Api/AdminResource")
- }
-)
@Tag(name = "Admin")
public class AdminResource {
@@ -52,25 +47,15 @@ public class AdminResource {
@Operation(
summary = "Fetch running time of server",
description = "Returns uptime in milliseconds",
- extensions = {
- @Extension(name = "translation", properties = {
- @ExtensionProperty(name="description.key", value="operation:description")
- })
- },
responses = {
@ApiResponse(
description = "uptime in milliseconds",
- content = @Content(schema = @Schema(implementation = String.class)),
- extensions = {
- @Extension(name = "translation", properties = {
- @ExtensionProperty(name="description.key", value="success_response:description")
- })
- }
+ content = @Content(schema = @Schema(type = "number"))
)
}
)
- public String uptime() {
- return Long.toString(System.currentTimeMillis() - Controller.startTime);
+ public long uptime() {
+ return System.currentTimeMillis() - Controller.startTime;
}
@GET
@@ -78,20 +63,10 @@ public class AdminResource {
@Operation(
summary = "Shutdown",
description = "Shutdown",
- extensions = {
- @Extension(name = "translation", properties = {
- @ExtensionProperty(name="description.key", value="operation:description")
- })
- },
responses = {
@ApiResponse(
description = "\"true\"",
- content = @Content(schema = @Schema(implementation = String.class)),
- extensions = {
- @Extension(name = "translation", properties = {
- @ExtensionProperty(name="description.key", value="success_response:description")
- })
- }
+ content = @Content(schema = @Schema(type = "string"))
)
}
)
diff --git a/src/main/java/api/resource/AnnotationPostProcessor.java b/src/main/java/api/resource/AnnotationPostProcessor.java
new file mode 100644
index 00000000..5f7e8fdd
--- /dev/null
+++ b/src/main/java/api/resource/AnnotationPostProcessor.java
@@ -0,0 +1,114 @@
+package api.resource;
+
+import globalization.Translator;
+import io.swagger.v3.core.converter.ModelConverters;
+import io.swagger.v3.jaxrs2.Reader;
+import io.swagger.v3.jaxrs2.ReaderListener;
+import io.swagger.v3.oas.models.Components;
+import io.swagger.v3.oas.models.OpenAPI;
+import io.swagger.v3.oas.models.Operation;
+import io.swagger.v3.oas.models.PathItem;
+import io.swagger.v3.oas.models.examples.Example;
+import io.swagger.v3.oas.models.media.Content;
+import io.swagger.v3.oas.models.media.MediaType;
+import io.swagger.v3.oas.models.media.Schema;
+import io.swagger.v3.oas.models.parameters.Parameter;
+import io.swagger.v3.oas.models.responses.ApiResponse;
+
+import java.lang.reflect.Method;
+import java.util.Locale;
+
+import javax.ws.rs.Path;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import api.ApiError;
+import api.ApiErrorMessage;
+import api.ApiErrors;
+import api.ApiService;
+
+public class AnnotationPostProcessor implements ReaderListener {
+
+ private static final Logger LOGGER = LogManager.getLogger(AnnotationPostProcessor.class);
+
+ @Override
+ public void beforeScan(Reader reader, OpenAPI openAPI) {
+ }
+
+ @Override
+ public void afterScan(Reader reader, OpenAPI openAPI) {
+ // Populate Components section with reusable parameters, like "limit" and "offset"
+ // We take the reusable parameters from AdminResource.globalParameters path "/admin/unused"
+ Components components = openAPI.getComponents();
+
+ PathItem globalParametersPathItem = openAPI.getPaths().get("/admin/unused");
+
+ if (globalParametersPathItem != null) {
+ for (Parameter parameter : globalParametersPathItem.getGet().getParameters())
+ components.addParameters(parameter.getName(), parameter);
+
+ openAPI.getPaths().remove("/admin/unused");
+ }
+
+ // Search all ApiService resources (classes) for @ApiErrors annotations
+ // to generate corresponding openAPI operation responses.
+ for (Class> clazz : ApiService.getInstance().getResources()) {
+ Path classPath = clazz.getAnnotation(Path.class);
+ if (classPath == null)
+ continue;
+
+ String classPathString = classPath.value();
+ if (classPathString.charAt(0) != '/')
+ classPathString = "/" + classPathString;
+
+ for (Method method : clazz.getDeclaredMethods()) {
+ ApiErrors apiErrors = method.getAnnotation(ApiErrors.class);
+ if (apiErrors == null)
+ continue;
+
+ LOGGER.info("Found @ApiErrors annotation on " + clazz.getSimpleName() + "." + method.getName());
+ PathItem pathItem = getPathItemFromMethod(openAPI, classPathString, method);
+
+ for (Operation operation : pathItem.readOperations())
+ for (ApiError apiError : apiErrors.value())
+ addApiErrorResponse(operation, apiError);
+ }
+ }
+ }
+
+ private PathItem getPathItemFromMethod(OpenAPI openAPI, String classPathString, Method method) {
+ Path path = method.getAnnotation(Path.class);
+ if (path == null)
+ throw new RuntimeException("API method has no @Path annotation?");
+
+ String pathString = path.value();
+ return openAPI.getPaths().get(classPathString + pathString);
+ }
+
+ private void addApiErrorResponse(Operation operation, ApiError apiError) {
+ String statusCode = Integer.toString(apiError.getStatus()) + " " + apiError.name();
+
+ // Create response for this HTTP response code if it doesn't already exist
+ ApiResponse apiResponse = operation.getResponses().get(statusCode);
+ if (apiResponse == null) {
+ Schema> errorMessageSchema = ModelConverters.getInstance().readAllAsResolvedSchema(ApiErrorMessage.class).schema;
+ MediaType mediaType = new MediaType().schema(errorMessageSchema);
+ Content content = new Content().addMediaType(javax.ws.rs.core.MediaType.APPLICATION_JSON, mediaType);
+ apiResponse = new ApiResponse().content(content);
+ operation.getResponses().addApiResponse(statusCode, apiResponse);
+ }
+
+ // Add this specific ApiError code as an example
+ int apiErrorCode = apiError.getCode();
+ String lang = Locale.getDefault().getLanguage();
+ ApiErrorMessage apiErrorMessage = new ApiErrorMessage(apiErrorCode, Translator.INSTANCE.translate("ApiError", lang, apiError.name()));
+ Example example = new Example().value(apiErrorMessage);
+
+ // XXX: addExamples(..) is not working in Swagger 2.0.4. This bug is referenced in https://github.com/swagger-api/swagger-ui/issues/2651
+ // Replace the call to .setExample(..) by .addExamples(..) when the bug is fixed.
+ apiResponse.getContent().get(javax.ws.rs.core.MediaType.APPLICATION_JSON).setExample(example);
+ //apiResponse.getContent().get(javax.ws.rs.core.MediaType.APPLICATION_JSON).addExamples(Integer.toString(apiErrorCode), example);
+ }
+
+}
diff --git a/src/api/ApiDefinition.java b/src/main/java/api/resource/ApiDefinition.java
similarity index 97%
rename from src/api/ApiDefinition.java
rename to src/main/java/api/resource/ApiDefinition.java
index 31239faf..0da2ad31 100644
--- a/src/api/ApiDefinition.java
+++ b/src/main/java/api/resource/ApiDefinition.java
@@ -1,4 +1,4 @@
-package api;
+package api.resource;
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.annotations.extensions.Extension;
@@ -25,5 +25,4 @@ import io.swagger.v3.oas.annotations.tags.Tag;
}
)
public class ApiDefinition {
-
-}
+}
\ No newline at end of file
diff --git a/src/api/AssetsResource.java b/src/main/java/api/resource/AssetsResource.java
similarity index 80%
rename from src/api/AssetsResource.java
rename to src/main/java/api/resource/AssetsResource.java
index 81e51ca2..97defed1 100644
--- a/src/api/AssetsResource.java
+++ b/src/main/java/api/resource/AssetsResource.java
@@ -1,4 +1,4 @@
-package api;
+package api.resource;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
@@ -30,6 +30,9 @@ import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
+import api.ApiError;
+import api.ApiErrors;
+import api.ApiExceptionFactory;
import api.models.AssetWithHolders;
import api.models.OrderWithTrades;
import api.models.TradeWithOrderInfo;
@@ -58,6 +61,7 @@ public class AssetsResource {
)
}
)
+ @ApiErrors({ApiError.REPOSITORY_ISSUE})
public List getAllAssets(@Parameter(ref = "limit") @QueryParam("limit") int limit, @Parameter(ref = "offset") @QueryParam("offset") int offset) {
try (final Repository repository = RepositoryManager.getRepository()) {
List assets = repository.getAssetRepository().getAllAssets();
@@ -69,7 +73,7 @@ public class AssetsResource {
return assets;
} catch (DataException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.REPOSITORY_ISSUE, e);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
}
}
@@ -85,9 +89,10 @@ public class AssetsResource {
)
}
)
+ @ApiErrors({ApiError.INVALID_CRITERIA, ApiError.INVALID_ASSET_ID, ApiError.REPOSITORY_ISSUE})
public AssetWithHolders getAssetInfo(@QueryParam("assetId") Integer assetId, @QueryParam("assetName") String assetName, @Parameter(ref = "includeHolders") @QueryParam("includeHolders") boolean includeHolders) {
if (assetId == null && (assetName == null || assetName.isEmpty()))
- throw ApiErrorFactory.getInstance().createError(ApiError.INVALID_CRITERIA);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_CRITERIA);
try (final Repository repository = RepositoryManager.getRepository()) {
AssetData assetData = null;
@@ -98,7 +103,7 @@ public class AssetsResource {
assetData = repository.getAssetRepository().fromAssetName(assetName);
if (assetData == null)
- throw ApiErrorFactory.getInstance().createError(ApiError.INVALID_ASSET_ID);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_ASSET_ID);
List holders = null;
if (includeHolders)
@@ -106,7 +111,7 @@ public class AssetsResource {
return new AssetWithHolders(assetData, holders);
} catch (DataException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.REPOSITORY_ISSUE, e);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
}
}
@@ -122,14 +127,15 @@ public class AssetsResource {
)
}
)
+ @ApiErrors({ApiError.INVALID_ASSET_ID, ApiError.REPOSITORY_ISSUE})
public List getAssetOrders(@Parameter(ref = "assetId") @PathParam("assetId") int assetId, @Parameter(ref = "otherAssetId") @PathParam("otherAssetId") int otherAssetId,
@Parameter(ref = "limit") @QueryParam("limit") int limit, @Parameter(ref = "offset") @QueryParam("offset") int offset) {
try (final Repository repository = RepositoryManager.getRepository()) {
if (!repository.getAssetRepository().assetExists(assetId))
- throw ApiErrorFactory.getInstance().createError(ApiError.INVALID_ASSET_ID);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_ASSET_ID);
if (!repository.getAssetRepository().assetExists(otherAssetId))
- throw ApiErrorFactory.getInstance().createError(ApiError.INVALID_ASSET_ID);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_ASSET_ID);
List orders = repository.getAssetRepository().getOpenOrders(assetId, otherAssetId);
@@ -140,7 +146,7 @@ public class AssetsResource {
return orders;
} catch (DataException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.REPOSITORY_ISSUE, e);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
}
}
@@ -158,14 +164,15 @@ public class AssetsResource {
)
}
)
+ @ApiErrors({ApiError.INVALID_ASSET_ID, ApiError.REPOSITORY_ISSUE})
public List getAssetTrades(@Parameter(ref = "assetId") @PathParam("assetId") int assetId, @Parameter(ref = "otherAssetId") @PathParam("otherAssetId") int otherAssetId,
@Parameter(ref = "limit") @QueryParam("limit") int limit, @Parameter(ref = "offset") @QueryParam("offset") int offset) {
try (final Repository repository = RepositoryManager.getRepository()) {
if (!repository.getAssetRepository().assetExists(assetId))
- throw ApiErrorFactory.getInstance().createError(ApiError.INVALID_ASSET_ID);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_ASSET_ID);
if (!repository.getAssetRepository().assetExists(otherAssetId))
- throw ApiErrorFactory.getInstance().createError(ApiError.INVALID_ASSET_ID);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_ASSET_ID);
List trades = repository.getAssetRepository().getTrades(assetId, otherAssetId);
@@ -184,7 +191,7 @@ public class AssetsResource {
return fullTrades;
} catch (DataException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.REPOSITORY_ISSUE, e);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
}
}
@@ -200,25 +207,26 @@ public class AssetsResource {
)
}
)
+ @ApiErrors({ApiError.INVALID_ORDER_ID, ApiError.ORDER_NO_EXISTS, ApiError.REPOSITORY_ISSUE})
public OrderWithTrades getAssetOrder(@PathParam("orderId") String orderId58) {
// Decode orderID
byte[] orderId;
try {
orderId = Base58.decode(orderId58);
} catch (NumberFormatException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.INVALID_ORDER_ID, e);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_ORDER_ID, e);
}
try (final Repository repository = RepositoryManager.getRepository()) {
OrderData orderData = repository.getAssetRepository().fromOrderId(orderId);
if (orderData == null)
- throw ApiErrorFactory.getInstance().createError(ApiError.ORDER_NO_EXISTS);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.ORDER_NO_EXISTS);
List trades = repository.getAssetRepository().getOrdersTrades(orderId);
return new OrderWithTrades(orderData, trades);
} catch (DataException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.REPOSITORY_ISSUE, e);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
}
}
@@ -245,20 +253,21 @@ public class AssetsResource {
)
}
)
+ @ApiErrors({ApiError.TRANSFORMATION_ERROR, ApiError.REPOSITORY_ISSUE, ApiError.TRANSACTION_INVALID})
public String issueAsset(IssueAssetTransactionData transactionData) {
try (final Repository repository = RepositoryManager.getRepository()) {
Transaction transaction = Transaction.fromData(repository, transactionData);
ValidationResult result = transaction.isValid();
if (result != ValidationResult.OK)
- throw new ApiException(400, ApiError.INVALID_DATA.getCode(), "Transaction invalid: " + result.name());
+ throw TransactionsResource.createTransactionInvalidException(request, result);
byte[] bytes = IssueAssetTransactionTransformer.toBytes(transactionData);
return Base58.encode(bytes);
} catch (TransformationException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.UNKNOWN, e);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.TRANSFORMATION_ERROR, e);
} catch (DataException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.REPOSITORY_ISSUE, e);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
}
}
diff --git a/src/main/java/api/resource/BlockExplorerResource.java b/src/main/java/api/resource/BlockExplorerResource.java
new file mode 100644
index 00000000..1cf236c7
--- /dev/null
+++ b/src/main/java/api/resource/BlockExplorerResource.java
@@ -0,0 +1,37 @@
+package api.resource;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.stream.Collectors;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Context;
+
+import io.swagger.v3.oas.annotations.Operation;
+
+@Path("/")
+public class BlockExplorerResource {
+
+ @Context
+ HttpServletRequest request;
+
+ @GET
+ @Path("/block-explorer.html")
+ @Operation(hidden = true)
+ public String getBlockExplorer() {
+ ClassLoader loader = this.getClass().getClassLoader();
+ try (InputStream inputStream = loader.getResourceAsStream("block-explorer.html")) {
+ if (inputStream == null)
+ return "block-explorer.html resource not found";
+
+ return new BufferedReader(new InputStreamReader(inputStream)).lines().collect(Collectors.joining("\n"));
+ } catch (IOException e) {
+ return "Error reading block-explorer.html resource";
+ }
+ }
+
+}
diff --git a/src/api/BlocksResource.java b/src/main/java/api/resource/BlocksResource.java
similarity index 52%
rename from src/api/BlocksResource.java
rename to src/main/java/api/resource/BlocksResource.java
index cae882e5..ae53c0ac 100644
--- a/src/api/BlocksResource.java
+++ b/src/main/java/api/resource/BlocksResource.java
@@ -1,11 +1,9 @@
-package api;
+package api.resource;
import data.block.BlockData;
import data.transaction.TransactionData;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
-import io.swagger.v3.oas.annotations.extensions.Extension;
-import io.swagger.v3.oas.annotations.extensions.ExtensionProperty;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
@@ -26,6 +24,10 @@ import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
+import api.ApiError;
+import api.ApiErrors;
+import api.ApiException;
+import api.ApiExceptionFactory;
import api.models.BlockWithTransactions;
import qora.block.Block;
import repository.DataException;
@@ -33,22 +35,9 @@ import repository.Repository;
import repository.RepositoryManager;
import utils.Base58;
-@Path("blocks")
-@Produces({
- MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN
-})
-@Extension(
- name = "translation",
- properties = {
- @ExtensionProperty(
- name = "path",
- value = "/Api/BlocksResource"
- )
- }
-)
-@Tag(
- name = "Blocks"
-)
+@Path("/blocks")
+@Produces({MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN})
+@Tag(name = "Blocks")
public class BlocksResource {
@Context
@@ -59,28 +48,6 @@ public class BlocksResource {
@Operation(
summary = "Fetch block using base58 signature",
description = "Returns the block that matches the given signature",
- extensions = {
- @Extension(
- name = "translation",
- properties = {
- @ExtensionProperty(
- name = "path",
- value = "GET signature"
- ), @ExtensionProperty(
- name = "description.key",
- value = "operation:description"
- )
- }
- ), @Extension(
- properties = {
- @ExtensionProperty(
- name = "apiErrors",
- value = "[\"INVALID_SIGNATURE\", \"BLOCK_NO_EXISTS\"]",
- parseValue = true
- ),
- }
- )
- },
responses = {
@ApiResponse(
description = "the block",
@@ -88,30 +55,18 @@ public class BlocksResource {
schema = @Schema(
implementation = BlockWithTransactions.class
)
- ),
- extensions = {
- @Extension(
- name = "translation",
- properties = {
- @ExtensionProperty(
- name = "description.key",
- value = "success_response:description"
- )
- }
- )
- }
+ )
)
}
)
- public BlockWithTransactions getBlock(@PathParam("signature") String signature58, @Parameter(
- ref = "includeTransactions"
- ) @QueryParam("includeTransactions") boolean includeTransactions) {
+ @ApiErrors({ApiError.INVALID_SIGNATURE, ApiError.BLOCK_NO_EXISTS, ApiError.REPOSITORY_ISSUE})
+ public BlockWithTransactions getBlock(@PathParam("signature") String signature58, @Parameter(ref = "includeTransactions") @QueryParam("includeTransactions") boolean includeTransactions) {
// Decode signature
byte[] signature;
try {
signature = Base58.decode(signature58);
} catch (NumberFormatException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.INVALID_SIGNATURE, e);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_SIGNATURE, e);
}
try (final Repository repository = RepositoryManager.getRepository()) {
@@ -120,7 +75,7 @@ public class BlocksResource {
} catch (ApiException e) {
throw e;
} catch (DataException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.REPOSITORY_ISSUE, e);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
}
}
@@ -129,18 +84,6 @@ public class BlocksResource {
@Operation(
summary = "Fetch genesis block",
description = "Returns the genesis block",
- extensions = @Extension(
- name = "translation",
- properties = {
- @ExtensionProperty(
- name = "path",
- value = "GET first"
- ), @ExtensionProperty(
- name = "description.key",
- value = "operation:description"
- )
- }
- ),
responses = {
@ApiResponse(
description = "the block",
@@ -148,31 +91,19 @@ public class BlocksResource {
schema = @Schema(
implementation = BlockWithTransactions.class
)
- ),
- extensions = {
- @Extension(
- name = "translation",
- properties = {
- @ExtensionProperty(
- name = "description.key",
- value = "success_response:description"
- )
- }
- )
- }
+ )
)
}
)
- public BlockWithTransactions getFirstBlock(@Parameter(
- ref = "includeTransactions"
- ) @QueryParam("includeTransactions") boolean includeTransactions) {
+ @ApiErrors({ApiError.BLOCK_NO_EXISTS, ApiError.REPOSITORY_ISSUE})
+ public BlockWithTransactions getFirstBlock(@Parameter(ref = "includeTransactions") @QueryParam("includeTransactions") boolean includeTransactions) {
try (final Repository repository = RepositoryManager.getRepository()) {
BlockData blockData = repository.getBlockRepository().fromHeight(1);
return packageBlockData(repository, blockData, includeTransactions);
} catch (ApiException e) {
throw e;
} catch (DataException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.REPOSITORY_ISSUE, e);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
}
}
@@ -181,18 +112,6 @@ public class BlocksResource {
@Operation(
summary = "Fetch last/newest block in blockchain",
description = "Returns the last valid block",
- extensions = @Extension(
- name = "translation",
- properties = {
- @ExtensionProperty(
- name = "path",
- value = "GET last"
- ), @ExtensionProperty(
- name = "description.key",
- value = "operation:description"
- )
- }
- ),
responses = {
@ApiResponse(
description = "the block",
@@ -200,31 +119,19 @@ public class BlocksResource {
schema = @Schema(
implementation = BlockWithTransactions.class
)
- ),
- extensions = {
- @Extension(
- name = "translation",
- properties = {
- @ExtensionProperty(
- name = "description.key",
- value = "success_response:description"
- )
- }
- )
- }
+ )
)
}
)
- public BlockWithTransactions getLastBlock(@Parameter(
- ref = "includeTransactions"
- ) @QueryParam("includeTransactions") boolean includeTransactions) {
+ @ApiErrors({ApiError.BLOCK_NO_EXISTS, ApiError.REPOSITORY_ISSUE})
+ public BlockWithTransactions getLastBlock(@Parameter(ref = "includeTransactions") @QueryParam("includeTransactions") boolean includeTransactions) {
try (final Repository repository = RepositoryManager.getRepository()) {
BlockData blockData = repository.getBlockRepository().getLastBlock();
return packageBlockData(repository, blockData, includeTransactions);
} catch (ApiException e) {
throw e;
} catch (DataException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.REPOSITORY_ISSUE, e);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
}
}
@@ -233,28 +140,6 @@ public class BlocksResource {
@Operation(
summary = "Fetch child block using base58 signature of parent block",
description = "Returns the child block of the block that matches the given signature",
- extensions = {
- @Extension(
- name = "translation",
- properties = {
- @ExtensionProperty(
- name = "path",
- value = "GET child:signature"
- ), @ExtensionProperty(
- name = "description.key",
- value = "operation:description"
- )
- }
- ), @Extension(
- properties = {
- @ExtensionProperty(
- name = "apiErrors",
- value = "[\"INVALID_SIGNATURE\", \"BLOCK_NO_EXISTS\"]",
- parseValue = true
- ),
- }
- )
- },
responses = {
@ApiResponse(
description = "the block",
@@ -262,30 +147,18 @@ public class BlocksResource {
schema = @Schema(
implementation = BlockWithTransactions.class
)
- ),
- extensions = {
- @Extension(
- name = "translation",
- properties = {
- @ExtensionProperty(
- name = "description.key",
- value = "success_response:description"
- )
- }
- )
- }
+ )
)
}
)
- public BlockWithTransactions getChild(@PathParam("signature") String signature58, @Parameter(
- ref = "includeTransactions"
- ) @QueryParam("includeTransactions") boolean includeTransactions) {
+ @ApiErrors({ApiError.INVALID_SIGNATURE, ApiError.BLOCK_NO_EXISTS, ApiError.REPOSITORY_ISSUE})
+ public BlockWithTransactions getChild(@PathParam("signature") String signature58, @Parameter(ref = "includeTransactions") @QueryParam("includeTransactions") boolean includeTransactions) {
// Decode signature
byte[] signature;
try {
signature = Base58.decode(signature58);
} catch (NumberFormatException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.INVALID_SIGNATURE, e);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_SIGNATURE, e);
}
try (final Repository repository = RepositoryManager.getRepository()) {
@@ -293,7 +166,7 @@ public class BlocksResource {
// Check block exists
if (blockData == null)
- throw ApiErrorFactory.getInstance().createError(ApiError.BLOCK_NO_EXISTS);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.BLOCK_NO_EXISTS);
BlockData childBlockData = repository.getBlockRepository().fromReference(signature);
@@ -302,7 +175,7 @@ public class BlocksResource {
} catch (ApiException e) {
throw e;
} catch (DataException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.REPOSITORY_ISSUE, e);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
}
}
@@ -311,18 +184,6 @@ public class BlocksResource {
@Operation(
summary = "Generating balance of next block",
description = "Calculates the generating balance of the block that will follow the last block",
- extensions = @Extension(
- name = "translation",
- properties = {
- @ExtensionProperty(
- name = "path",
- value = "GET generatingbalance"
- ), @ExtensionProperty(
- name = "description.key",
- value = "operation:description"
- )
- }
- ),
responses = {
@ApiResponse(
description = "the generating balance",
@@ -331,21 +192,11 @@ public class BlocksResource {
schema = @Schema(
implementation = BigDecimal.class
)
- ),
- extensions = {
- @Extension(
- name = "translation",
- properties = {
- @ExtensionProperty(
- name = "description.key",
- value = "success_response:description"
- )
- }
- )
- }
+ )
)
}
)
+ @ApiErrors({ApiError.REPOSITORY_ISSUE})
public BigDecimal getGeneratingBalance() {
try (final Repository repository = RepositoryManager.getRepository()) {
BlockData blockData = repository.getBlockRepository().getLastBlock();
@@ -354,7 +205,7 @@ public class BlocksResource {
} catch (ApiException e) {
throw e;
} catch (DataException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.REPOSITORY_ISSUE, e);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
}
}
@@ -363,28 +214,6 @@ public class BlocksResource {
@Operation(
summary = "Generating balance of block after specific block",
description = "Calculates the generating balance of the block that will follow the block that matches the signature",
- extensions = {
- @Extension(
- name = "translation",
- properties = {
- @ExtensionProperty(
- name = "path",
- value = "GET generatingbalance:signature"
- ), @ExtensionProperty(
- name = "description.key",
- value = "operation:description"
- )
- }
- ), @Extension(
- properties = {
- @ExtensionProperty(
- name = "apiErrors",
- value = "[\"INVALID_SIGNATURE\", \"BLOCK_NO_EXISTS\"]",
- parseValue = true
- ),
- }
- )
- },
responses = {
@ApiResponse(
description = "the block",
@@ -393,28 +222,18 @@ public class BlocksResource {
schema = @Schema(
implementation = BigDecimal.class
)
- ),
- extensions = {
- @Extension(
- name = "translation",
- properties = {
- @ExtensionProperty(
- name = "description.key",
- value = "success_response:description"
- )
- }
- )
- }
+ )
)
}
)
+ @ApiErrors({ApiError.INVALID_SIGNATURE, ApiError.BLOCK_NO_EXISTS, ApiError.REPOSITORY_ISSUE})
public BigDecimal getGeneratingBalance(@PathParam("signature") String signature58) {
// Decode signature
byte[] signature;
try {
signature = Base58.decode(signature58);
} catch (NumberFormatException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.INVALID_SIGNATURE, e);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_SIGNATURE, e);
}
try (final Repository repository = RepositoryManager.getRepository()) {
@@ -422,14 +241,14 @@ public class BlocksResource {
// Check block exists
if (blockData == null)
- throw ApiErrorFactory.getInstance().createError(ApiError.BLOCK_NO_EXISTS);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.BLOCK_NO_EXISTS);
Block block = new Block(repository, blockData);
return block.calcNextBlockGeneratingBalance();
} catch (ApiException e) {
throw e;
} catch (DataException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.REPOSITORY_ISSUE, e);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
}
}
@@ -438,42 +257,19 @@ public class BlocksResource {
@Operation(
summary = "Estimated time to forge next block",
description = "Calculates the time it should take for the network to generate the next block",
- extensions = @Extension(
- name = "translation",
- properties = {
- @ExtensionProperty(
- name = "path",
- value = "GET time"
- ), @ExtensionProperty(
- name = "description.key",
- value = "operation:description"
- )
- }
- ),
responses = {
@ApiResponse(
- description = "the time in seconds", // in
- // seconds?
+ description = "the time in seconds",
content = @Content(
mediaType = MediaType.TEXT_PLAIN,
schema = @Schema(
type = "number"
)
- ),
- extensions = {
- @Extension(
- name = "translation",
- properties = {
- @ExtensionProperty(
- name = "description.key",
- value = "success_response:description"
- )
- }
- )
- }
+ )
)
}
)
+ @ApiErrors({ApiError.REPOSITORY_ISSUE})
public long getTimePerBlock() {
try (final Repository repository = RepositoryManager.getRepository()) {
BlockData blockData = repository.getBlockRepository().getLastBlock();
@@ -481,7 +277,7 @@ public class BlocksResource {
} catch (ApiException e) {
throw e;
} catch (DataException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.REPOSITORY_ISSUE, e);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
}
}
@@ -490,18 +286,6 @@ public class BlocksResource {
@Operation(
summary = "Estimated time to forge block given generating balance",
description = "Calculates the time it should take for the network to generate blocks based on specified generating balance",
- extensions = @Extension(
- name = "translation",
- properties = {
- @ExtensionProperty(
- name = "path",
- value = "GET time:generatingbalance"
- ), @ExtensionProperty(
- name = "description.key",
- value = "operation:description"
- )
- }
- ),
responses = {
@ApiResponse(
description = "the time", // in seconds?
@@ -510,18 +294,7 @@ public class BlocksResource {
schema = @Schema(
type = "number"
)
- ),
- extensions = {
- @Extension(
- name = "translation",
- properties = {
- @ExtensionProperty(
- name = "description.key",
- value = "success_response:description"
- )
- }
- )
- }
+ )
)
}
)
@@ -534,18 +307,6 @@ public class BlocksResource {
@Operation(
summary = "Current blockchain height",
description = "Returns the block height of the last block.",
- extensions = @Extension(
- name = "translation",
- properties = {
- @ExtensionProperty(
- name = "path",
- value = "GET height"
- ), @ExtensionProperty(
- name = "description.key",
- value = "operation:description"
- )
- }
- ),
responses = {
@ApiResponse(
description = "the height",
@@ -554,28 +315,18 @@ public class BlocksResource {
schema = @Schema(
type = "number"
)
- ),
- extensions = {
- @Extension(
- name = "translation",
- properties = {
- @ExtensionProperty(
- name = "description.key",
- value = "success_response:description"
- )
- }
- )
- }
+ )
)
}
)
+ @ApiErrors({ApiError.REPOSITORY_ISSUE})
public int getHeight() {
try (final Repository repository = RepositoryManager.getRepository()) {
return repository.getBlockRepository().getBlockchainHeight();
} catch (ApiException e) {
throw e;
} catch (DataException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.REPOSITORY_ISSUE, e);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
}
}
@@ -584,28 +335,6 @@ public class BlocksResource {
@Operation(
summary = "Height of specific block",
description = "Returns the block height of the block that matches the given signature",
- extensions = {
- @Extension(
- name = "translation",
- properties = {
- @ExtensionProperty(
- name = "path",
- value = "GET height:signature"
- ), @ExtensionProperty(
- name = "description.key",
- value = "operation:description"
- )
- }
- ), @Extension(
- properties = {
- @ExtensionProperty(
- name = "apiErrors",
- value = "[\"INVALID_SIGNATURE\", \"BLOCK_NO_EXISTS\"]",
- parseValue = true
- ),
- }
- )
- },
responses = {
@ApiResponse(
description = "the height",
@@ -614,28 +343,18 @@ public class BlocksResource {
schema = @Schema(
type = "number"
)
- ),
- extensions = {
- @Extension(
- name = "translation",
- properties = {
- @ExtensionProperty(
- name = "description.key",
- value = "success_response:description"
- )
- }
- )
- }
+ )
)
}
)
+ @ApiErrors({ApiError.INVALID_SIGNATURE, ApiError.BLOCK_NO_EXISTS, ApiError.REPOSITORY_ISSUE})
public int getHeight(@PathParam("signature") String signature58) {
// Decode signature
byte[] signature;
try {
signature = Base58.decode(signature58);
} catch (NumberFormatException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.INVALID_SIGNATURE, e);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_SIGNATURE, e);
}
try (final Repository repository = RepositoryManager.getRepository()) {
@@ -643,13 +362,13 @@ public class BlocksResource {
// Check block exists
if (blockData == null)
- throw ApiErrorFactory.getInstance().createError(ApiError.BLOCK_NO_EXISTS);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.BLOCK_NO_EXISTS);
return blockData.getHeight();
} catch (ApiException e) {
throw e;
} catch (DataException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.REPOSITORY_ISSUE, e);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
}
}
@@ -658,28 +377,6 @@ public class BlocksResource {
@Operation(
summary = "Fetch block using block height",
description = "Returns the block with given height",
- extensions = {
- @Extension(
- name = "translation",
- properties = {
- @ExtensionProperty(
- name = "path",
- value = "GET byheight:height"
- ), @ExtensionProperty(
- name = "description.key",
- value = "operation:description"
- )
- }
- ), @Extension(
- properties = {
- @ExtensionProperty(
- name = "apiErrors",
- value = "[\"BLOCK_NO_EXISTS\"]",
- parseValue = true
- ),
- }
- )
- },
responses = {
@ApiResponse(
description = "the block",
@@ -687,31 +384,19 @@ public class BlocksResource {
schema = @Schema(
implementation = BlockWithTransactions.class
)
- ),
- extensions = {
- @Extension(
- name = "translation",
- properties = {
- @ExtensionProperty(
- name = "description.key",
- value = "success_response:description"
- )
- }
- )
- }
+ )
)
}
)
- public BlockWithTransactions getByHeight(@PathParam("height") int height, @Parameter(
- ref = "includeTransactions"
- ) @QueryParam("includeTransactions") boolean includeTransactions) {
+ @ApiErrors({ApiError.BLOCK_NO_EXISTS, ApiError.REPOSITORY_ISSUE})
+ public BlockWithTransactions getByHeight(@PathParam("height") int height, @Parameter(ref = "includeTransactions") @QueryParam("includeTransactions") boolean includeTransactions) {
try (final Repository repository = RepositoryManager.getRepository()) {
BlockData blockData = repository.getBlockRepository().fromHeight(height);
return packageBlockData(repository, blockData, includeTransactions);
} catch (ApiException e) {
throw e;
} catch (DataException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.REPOSITORY_ISSUE, e);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
}
}
@@ -720,28 +405,6 @@ public class BlocksResource {
@Operation(
summary = "Fetch blocks starting with given height",
description = "Returns blocks starting with given height.",
- extensions = {
- @Extension(
- name = "translation",
- properties = {
- @ExtensionProperty(
- name = "path",
- value = "GET byheight:height"
- ), @ExtensionProperty(
- name = "description.key",
- value = "operation:description"
- )
- }
- ), @Extension(
- properties = {
- @ExtensionProperty(
- name = "apiErrors",
- value = "[\"BLOCK_NO_EXISTS\"]",
- parseValue = true
- ),
- }
- )
- },
responses = {
@ApiResponse(
description = "blocks",
@@ -749,24 +412,12 @@ public class BlocksResource {
schema = @Schema(
implementation = BlockWithTransactions.class
)
- ),
- extensions = {
- @Extension(
- name = "translation",
- properties = {
- @ExtensionProperty(
- name = "description.key",
- value = "success_response:description"
- )
- }
- )
- }
+ )
)
}
)
- public List getBlockRange(@PathParam("height") int height, @Parameter(
- ref = "count"
- ) @QueryParam("count") int count) {
+ @ApiErrors({ApiError.BLOCK_NO_EXISTS, ApiError.REPOSITORY_ISSUE})
+ public List getBlockRange(@PathParam("height") int height, @Parameter(ref = "count") @QueryParam("count") int count) {
boolean includeTransactions = false;
try (final Repository repository = RepositoryManager.getRepository()) {
@@ -785,13 +436,25 @@ public class BlocksResource {
} catch (ApiException e) {
throw e;
} catch (DataException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.REPOSITORY_ISSUE, e);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
}
}
+ /**
+ * Returns block, optionally including transactions.
+ *
+ * Throws ApiException using ApiError.BLOCK_NO_EXISTS if blockData is null.
+ *
+ * @param repository
+ * @param blockData
+ * @param includeTransactions
+ * @return packaged block, with optional transactions
+ * @throws DataException
+ * @throws ApiException ApiError.BLOCK_NO_EXISTS
+ */
private BlockWithTransactions packageBlockData(Repository repository, BlockData blockData, boolean includeTransactions) throws DataException {
if (blockData == null)
- throw ApiErrorFactory.getInstance().createError(ApiError.BLOCK_NO_EXISTS);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.BLOCK_NO_EXISTS);
List transactions = null;
if (includeTransactions) {
diff --git a/src/api/NamesResource.java b/src/main/java/api/resource/NamesResource.java
similarity index 79%
rename from src/api/NamesResource.java
rename to src/main/java/api/resource/NamesResource.java
index 4631400d..2b6ebf37 100644
--- a/src/api/NamesResource.java
+++ b/src/main/java/api/resource/NamesResource.java
@@ -1,4 +1,4 @@
-package api;
+package api.resource;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
@@ -22,15 +22,14 @@ import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
+import api.ApiError;
+import api.ApiErrors;
+import api.ApiExceptionFactory;
import data.transaction.RegisterNameTransactionData;
@Path("/names")
-@Produces({
- MediaType.TEXT_PLAIN
-})
-@Tag(
- name = "Names"
-)
+@Produces({ MediaType.TEXT_PLAIN})
+@Tag(name = "Names")
public class NamesResource {
@Context
@@ -61,20 +60,21 @@ public class NamesResource {
)
}
)
+ @ApiErrors({ApiError.TRANSACTION_INVALID, ApiError.TRANSFORMATION_ERROR, ApiError.REPOSITORY_ISSUE})
public String buildTransaction(RegisterNameTransactionData transactionData) {
try (final Repository repository = RepositoryManager.getRepository()) {
Transaction transaction = Transaction.fromData(repository, transactionData);
ValidationResult result = transaction.isValid();
if (result != ValidationResult.OK)
- throw new ApiException(400, ApiError.INVALID_DATA.getCode(), "Transaction invalid: " + result.name());
+ throw TransactionsResource.createTransactionInvalidException(request, result);
byte[] bytes = RegisterNameTransactionTransformer.toBytes(transactionData);
return Base58.encode(bytes);
} catch (TransformationException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.UNKNOWN, e);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.TRANSFORMATION_ERROR, e);
} catch (DataException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.REPOSITORY_ISSUE, e);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
}
}
diff --git a/src/api/PaymentsResource.java b/src/main/java/api/resource/PaymentsResource.java
similarity index 79%
rename from src/api/PaymentsResource.java
rename to src/main/java/api/resource/PaymentsResource.java
index 5a8106e3..5f2f26f0 100644
--- a/src/api/PaymentsResource.java
+++ b/src/main/java/api/resource/PaymentsResource.java
@@ -1,4 +1,4 @@
-package api;
+package api.resource;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
@@ -22,15 +22,14 @@ import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
+import api.ApiError;
+import api.ApiErrors;
+import api.ApiExceptionFactory;
import data.transaction.PaymentTransactionData;
@Path("/payments")
-@Produces({
- MediaType.TEXT_PLAIN
-})
-@Tag(
- name = "Payments"
-)
+@Produces({MediaType.TEXT_PLAIN})
+@Tag(name = "Payments")
public class PaymentsResource {
@Context
@@ -61,20 +60,21 @@ public class PaymentsResource {
)
}
)
+ @ApiErrors({ApiError.TRANSACTION_INVALID, ApiError.TRANSFORMATION_ERROR, ApiError.REPOSITORY_ISSUE})
public String buildTransaction(PaymentTransactionData transactionData) {
try (final Repository repository = RepositoryManager.getRepository()) {
Transaction transaction = Transaction.fromData(repository, transactionData);
ValidationResult result = transaction.isValid();
if (result != ValidationResult.OK)
- throw new ApiException(400, ApiError.INVALID_DATA.getCode(), "Transaction invalid: " + result.name());
+ throw TransactionsResource.createTransactionInvalidException(request, result);
byte[] bytes = PaymentTransactionTransformer.toBytes(transactionData);
return Base58.encode(bytes);
} catch (TransformationException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.UNKNOWN, e);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.TRANSFORMATION_ERROR, e);
} catch (DataException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.REPOSITORY_ISSUE, e);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
}
}
diff --git a/src/api/TransactionsResource.java b/src/main/java/api/resource/TransactionsResource.java
similarity index 74%
rename from src/api/TransactionsResource.java
rename to src/main/java/api/resource/TransactionsResource.java
index 0d68f088..d20083ad 100644
--- a/src/api/TransactionsResource.java
+++ b/src/main/java/api/resource/TransactionsResource.java
@@ -1,9 +1,7 @@
-package api;
+package api.resource;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
-import io.swagger.v3.oas.annotations.extensions.Extension;
-import io.swagger.v3.oas.annotations.extensions.ExtensionProperty;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
@@ -30,10 +28,15 @@ import javax.ws.rs.core.MediaType;
import com.google.common.primitives.Bytes;
+import api.ApiError;
+import api.ApiErrors;
+import api.ApiException;
+import api.ApiExceptionFactory;
import api.models.SimpleTransactionSignRequest;
import data.transaction.GenesisTransactionData;
import data.transaction.PaymentTransactionData;
import data.transaction.TransactionData;
+import globalization.Translator;
import repository.DataException;
import repository.Repository;
import repository.RepositoryManager;
@@ -41,22 +44,9 @@ import transform.TransformationException;
import transform.transaction.TransactionTransformer;
import utils.Base58;
-@Path("transactions")
-@Produces({
- MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN
-})
-@Extension(
- name = "translation",
- properties = {
- @ExtensionProperty(
- name = "path",
- value = "/Api/TransactionsResource"
- )
- }
-)
-@Tag(
- name = "Transactions"
-)
+@Path("/transactions")
+@Produces({MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN})
+@Tag(name = "Transactions")
public class TransactionsResource {
@Context
@@ -67,17 +57,6 @@ public class TransactionsResource {
@Operation(
summary = "Fetch transaction using transaction signature",
description = "Returns transaction",
- extensions = {
- @Extension(
- properties = {
- @ExtensionProperty(
- name = "apiErrors",
- value = "[\"INVALID_SIGNATURE\", \"TRANSACTION_NO_EXISTS\"]",
- parseValue = true
- ),
- }
- )
- },
responses = {
@ApiResponse(
description = "a transaction",
@@ -85,39 +64,29 @@ public class TransactionsResource {
schema = @Schema(
implementation = TransactionData.class
)
- ),
- extensions = {
- @Extension(
- name = "translation",
- properties = {
- @ExtensionProperty(
- name = "description.key",
- value = "success_response:description"
- )
- }
- )
- }
+ )
)
}
)
+ @ApiErrors({ApiError.INVALID_SIGNATURE, ApiError.TRANSACTION_NO_EXISTS, ApiError.REPOSITORY_ISSUE})
public TransactionData getTransactions(@PathParam("signature") String signature58) {
byte[] signature;
try {
signature = Base58.decode(signature58);
} catch (NumberFormatException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.INVALID_SIGNATURE, e);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_SIGNATURE, e);
}
try (final Repository repository = RepositoryManager.getRepository()) {
TransactionData transactionData = repository.getTransactionRepository().fromSignature(signature);
if (transactionData == null)
- throw ApiErrorFactory.getInstance().createError(ApiError.TRANSACTION_NO_EXISTS);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.TRANSACTION_NO_EXISTS);
return transactionData;
} catch (ApiException e) {
throw e;
} catch (DataException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.REPOSITORY_ISSUE, e);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
}
}
@@ -126,28 +95,6 @@ public class TransactionsResource {
@Operation(
summary = "Fetch transactions using block signature",
description = "Returns list of transactions",
- extensions = {
- @Extension(
- name = "translation",
- properties = {
- @ExtensionProperty(
- name = "path",
- value = "GET block:signature"
- ), @ExtensionProperty(
- name = "description.key",
- value = "operation:description"
- )
- }
- ), @Extension(
- properties = {
- @ExtensionProperty(
- name = "apiErrors",
- value = "[\"INVALID_SIGNATURE\", \"BLOCK_NO_EXISTS\"]",
- parseValue = true
- ),
- }
- )
- },
responses = {
@ApiResponse(
description = "list of transactions",
@@ -159,31 +106,17 @@ public class TransactionsResource {
}
)
)
- ),
- extensions = {
- @Extension(
- name = "translation",
- properties = {
- @ExtensionProperty(
- name = "description.key",
- value = "success_response:description"
- )
- }
- )
- }
+ )
)
}
)
- public List getBlockTransactions(@PathParam("signature") String signature58, @Parameter(
- ref = "limit"
- ) @QueryParam("limit") int limit, @Parameter(
- ref = "offset"
- ) @QueryParam("offset") int offset) {
+ @ApiErrors({ApiError.INVALID_SIGNATURE, ApiError.BLOCK_NO_EXISTS, ApiError.REPOSITORY_ISSUE})
+ public List getBlockTransactions(@PathParam("signature") String signature58, @Parameter(ref = "limit") @QueryParam("limit") int limit, @Parameter(ref = "offset") @QueryParam("offset") int offset) {
byte[] signature;
try {
signature = Base58.decode(signature58);
} catch (NumberFormatException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.INVALID_SIGNATURE, e);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_SIGNATURE, e);
}
try (final Repository repository = RepositoryManager.getRepository()) {
@@ -191,7 +124,7 @@ public class TransactionsResource {
// check if block exists
if (transactions == null)
- throw ApiErrorFactory.getInstance().createError(ApiError.BLOCK_NO_EXISTS);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.BLOCK_NO_EXISTS);
// Pagination would take effect here (or as part of the repository access)
int fromIndex = Integer.min(offset, transactions.size());
@@ -202,7 +135,7 @@ public class TransactionsResource {
} catch (ApiException e) {
throw e;
} catch (DataException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.REPOSITORY_ISSUE, e);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
}
}
@@ -220,28 +153,18 @@ public class TransactionsResource {
implementation = TransactionData.class
)
)
- ),
- extensions = {
- @Extension(
- name = "translation",
- properties = {
- @ExtensionProperty(
- name = "description.key",
- value = "success_response:description"
- )
- }
- )
- }
+ )
)
}
)
+ @ApiErrors({ApiError.REPOSITORY_ISSUE})
public List getUnconfirmedTransactions() {
try (final Repository repository = RepositoryManager.getRepository()) {
return repository.getTransactionRepository().getAllUnconfirmedTransactions();
} catch (ApiException e) {
throw e;
} catch (DataException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.REPOSITORY_ISSUE, e);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
}
}
@@ -271,35 +194,25 @@ public class TransactionsResource {
implementation = TransactionData.class
)
)
- ),
- extensions = {
- @Extension(
- name = "translation",
- properties = {
- @ExtensionProperty(
- name = "description.key",
- value = "success_response:description"
- )
- }
- )
- }
+ )
)
}
)
- public List searchTransactions(@QueryParam("startBlock") Integer startBlock, @QueryParam("blockLimit") Integer blockLimit,
+ @ApiErrors({ApiError.INVALID_CRITERIA, ApiError.REPOSITORY_ISSUE})
+ public List searchTransactions(@QueryParam("startBlock") Integer startBlock, @QueryParam("blockLimit") Integer blockLimit,
@QueryParam("txType") Integer txTypeNum, @QueryParam("address") String address, @Parameter(
ref = "limit"
) @QueryParam("limit") int limit, @Parameter(
ref = "offset"
) @QueryParam("offset") int offset) {
if ((txTypeNum == null || txTypeNum == 0) && (address == null || address.isEmpty()))
- throw ApiErrorFactory.getInstance().createError(ApiError.INVALID_CRITERIA);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_CRITERIA);
TransactionType txType = null;
if (txTypeNum != null) {
txType = TransactionType.valueOf(txTypeNum);
if (txType == null)
- throw ApiErrorFactory.getInstance().createError(ApiError.INVALID_CRITERIA);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_CRITERIA);
}
try (final Repository repository = RepositoryManager.getRepository()) {
@@ -319,7 +232,7 @@ public class TransactionsResource {
} catch (ApiException e) {
throw e;
} catch (DataException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.REPOSITORY_ISSUE, e);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
}
}
@@ -348,6 +261,7 @@ public class TransactionsResource {
)
}
)
+ @ApiErrors({ApiError.TRANSFORMATION_ERROR})
public String signTransaction(SimpleTransactionSignRequest signRequest) {
try {
// Append null signature on the end before transformation
@@ -364,7 +278,7 @@ public class TransactionsResource {
return Base58.encode(signedBytes);
} catch (TransformationException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.UNKNOWN, e);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.TRANSFORMATION_ERROR, e);
}
}
@@ -395,6 +309,7 @@ public class TransactionsResource {
)
}
)
+ @ApiErrors({ApiError.INVALID_SIGNATURE, ApiError.INVALID_DATA, ApiError.TRANSFORMATION_ERROR, ApiError.REPOSITORY_ISSUE})
public String processTransaction(String rawBytes58) {
try (final Repository repository = RepositoryManager.getRepository()) {
byte[] rawBytes = Base58.decode(rawBytes58);
@@ -402,11 +317,11 @@ public class TransactionsResource {
Transaction transaction = Transaction.fromData(repository, transactionData);
if (!transaction.isSignatureValid())
- throw ApiErrorFactory.getInstance().createError(ApiError.INVALID_SIGNATURE);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_SIGNATURE);
ValidationResult result = transaction.isValid();
if (result != ValidationResult.OK)
- throw new ApiException(400, ApiError.INVALID_DATA.getCode(), "Transaction invalid: " + result.name());
+ throw createTransactionInvalidException(request, result);
repository.getTransactionRepository().save(transactionData);
repository.getTransactionRepository().unconfirmTransaction(transactionData);
@@ -414,11 +329,11 @@ public class TransactionsResource {
return "true";
} catch (TransformationException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.UNKNOWN, e);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.TRANSFORMATION_ERROR, e);
} catch (ApiException e) {
throw e;
} catch (DataException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.REPOSITORY_ISSUE, e);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
}
}
@@ -448,6 +363,7 @@ public class TransactionsResource {
)
}
)
+ @ApiErrors({ApiError.INVALID_SIGNATURE, ApiError.INVALID_DATA, ApiError.TRANSACTION_INVALID, ApiError.TRANSFORMATION_ERROR, ApiError.REPOSITORY_ISSUE})
public TransactionData decodeTransaction(String rawBytes58) {
try (final Repository repository = RepositoryManager.getRepository()) {
byte[] rawBytes = Base58.decode(rawBytes58);
@@ -465,23 +381,28 @@ public class TransactionsResource {
Transaction transaction = Transaction.fromData(repository, transactionData);
if (hasSignature && !transaction.isSignatureValid())
- throw ApiErrorFactory.getInstance().createError(ApiError.INVALID_SIGNATURE);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_SIGNATURE);
ValidationResult result = transaction.isValid();
if (result != ValidationResult.OK)
- throw new ApiException(400, ApiError.INVALID_DATA.getCode(), "Transaction invalid: " + result.name());
+ throw createTransactionInvalidException(request, result);
if (!hasSignature)
transactionData.setSignature(null);
return transactionData;
} catch (TransformationException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.UNKNOWN, e);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.TRANSFORMATION_ERROR, e);
} catch (ApiException e) {
throw e;
} catch (DataException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.REPOSITORY_ISSUE, e);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
}
}
+ public static ApiException createTransactionInvalidException(HttpServletRequest request, ValidationResult result) {
+ String translatedResult = Translator.INSTANCE.translate("TransactionValidity", request.getLocale().getLanguage(), result.name());
+ return ApiExceptionFactory.INSTANCE.createException(request, ApiError.TRANSACTION_INVALID, null, translatedResult);
+ }
+
}
diff --git a/src/api/UtilsResource.java b/src/main/java/api/resource/UtilsResource.java
similarity index 89%
rename from src/api/UtilsResource.java
rename to src/main/java/api/resource/UtilsResource.java
index 224b0b0e..5c48f5aa 100644
--- a/src/api/UtilsResource.java
+++ b/src/main/java/api/resource/UtilsResource.java
@@ -1,4 +1,4 @@
-package api;
+package api.resource;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
@@ -31,6 +31,10 @@ import com.google.common.hash.HashCode;
import com.google.common.primitives.Bytes;
import com.google.common.primitives.Longs;
+import api.ApiError;
+import api.ApiErrors;
+import api.ApiExceptionFactory;
+
@Path("/utils")
@Produces({
MediaType.TEXT_PLAIN
@@ -67,11 +71,12 @@ public class UtilsResource {
)
}
)
+ @ApiErrors({ApiError.INVALID_DATA})
public String fromBase64(String base64) {
try {
return HashCode.fromBytes(Base64.getDecoder().decode(base64.trim())).toString();
} catch (IllegalArgumentException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.INVALID_DATA);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_DATA);
}
}
@@ -99,11 +104,12 @@ public class UtilsResource {
)
}
)
+ @ApiErrors({ApiError.INVALID_DATA})
public String base64from58(String base58) {
try {
return HashCode.fromBytes(Base58.decode(base58.trim())).toString();
} catch (NumberFormatException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.INVALID_DATA);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_DATA);
}
}
@@ -189,6 +195,7 @@ public class UtilsResource {
)
}
)
+ @ApiErrors({ApiError.INVALID_DATA})
public String getMnemonic(@QueryParam("entropy") String suppliedEntropy) {
/*
* BIP39 word lists have 2048 entries so can be represented by 11 bits.
@@ -201,12 +208,12 @@ public class UtilsResource {
try {
entropy = Base58.decode(suppliedEntropy);
} catch (NumberFormatException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.INVALID_DATA);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_DATA);
}
// Must be 16-bytes
if (entropy.length != 16)
- throw ApiErrorFactory.getInstance().createError(ApiError.INVALID_DATA);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_DATA);
} else {
// Generate entropy internally
UUID uuid = UUID.randomUUID();
@@ -296,16 +303,17 @@ public class UtilsResource {
)
}
)
+ @ApiErrors({ApiError.INVALID_DATA})
public String privateKey(@PathParam("entropy") String entropy58) {
byte[] entropy;
try {
entropy = Base58.decode(entropy58);
} catch (NumberFormatException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.INVALID_DATA);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_DATA);
}
if (entropy.length != 16)
- throw ApiErrorFactory.getInstance().createError(ApiError.INVALID_DATA);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_DATA);
byte[] privateKey = Crypto.digest(entropy);
@@ -328,16 +336,17 @@ public class UtilsResource {
)
}
)
+ @ApiErrors({ApiError.INVALID_DATA})
public String publicKey(@PathParam("privateKey") String privateKey58) {
byte[] privateKey;
try {
privateKey = Base58.decode(privateKey58);
} catch (NumberFormatException e) {
- throw ApiErrorFactory.getInstance().createError(ApiError.INVALID_DATA);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_DATA);
}
if (privateKey.length != 32)
- throw ApiErrorFactory.getInstance().createError(ApiError.INVALID_DATA);
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_DATA);
byte[] publicKey = new PrivateKeyAccount(null, privateKey).getPublicKey();
diff --git a/src/blockgenerator.java b/src/main/java/blockgenerator.java
similarity index 100%
rename from src/blockgenerator.java
rename to src/main/java/blockgenerator.java
diff --git a/src/brokenmd160.java b/src/main/java/brokenmd160.java
similarity index 100%
rename from src/brokenmd160.java
rename to src/main/java/brokenmd160.java
diff --git a/src/controller/Controller.java b/src/main/java/controller/Controller.java
similarity index 100%
rename from src/controller/Controller.java
rename to src/main/java/controller/Controller.java
diff --git a/src/crosschain/BTC.java b/src/main/java/crosschain/BTC.java
similarity index 99%
rename from src/crosschain/BTC.java
rename to src/main/java/crosschain/BTC.java
index ce7a9e17..feb29dc5 100644
--- a/src/crosschain/BTC.java
+++ b/src/main/java/crosschain/BTC.java
@@ -30,7 +30,6 @@ import org.bitcoinj.core.Sha256Hash;
import org.bitcoinj.core.StoredBlock;
import org.bitcoinj.core.Transaction;
import org.bitcoinj.core.TransactionOutput;
-import org.bitcoinj.core.Utils;
import org.bitcoinj.core.VerificationException;
import org.bitcoinj.core.listeners.NewBestBlockListener;
import org.bitcoinj.net.discovery.DnsDiscovery;
@@ -109,6 +108,7 @@ public class BTC {
}
}
+ @SuppressWarnings("unused")
public void saveAsBinary(File file) throws IOException {
try (final FileOutputStream fileOutputStream = new FileOutputStream(file, false)) {
MessageDigest digest = Sha256Hash.newDigest();
diff --git a/src/data/PaymentData.java b/src/main/java/data/PaymentData.java
similarity index 100%
rename from src/data/PaymentData.java
rename to src/main/java/data/PaymentData.java
diff --git a/src/data/account/AccountBalanceData.java b/src/main/java/data/account/AccountBalanceData.java
similarity index 100%
rename from src/data/account/AccountBalanceData.java
rename to src/main/java/data/account/AccountBalanceData.java
diff --git a/src/data/account/AccountData.java b/src/main/java/data/account/AccountData.java
similarity index 100%
rename from src/data/account/AccountData.java
rename to src/main/java/data/account/AccountData.java
diff --git a/src/data/assets/AssetData.java b/src/main/java/data/assets/AssetData.java
similarity index 100%
rename from src/data/assets/AssetData.java
rename to src/main/java/data/assets/AssetData.java
diff --git a/src/data/assets/OrderData.java b/src/main/java/data/assets/OrderData.java
similarity index 100%
rename from src/data/assets/OrderData.java
rename to src/main/java/data/assets/OrderData.java
diff --git a/src/data/assets/TradeData.java b/src/main/java/data/assets/TradeData.java
similarity index 100%
rename from src/data/assets/TradeData.java
rename to src/main/java/data/assets/TradeData.java
diff --git a/src/data/at/ATData.java b/src/main/java/data/at/ATData.java
similarity index 100%
rename from src/data/at/ATData.java
rename to src/main/java/data/at/ATData.java
diff --git a/src/data/at/ATStateData.java b/src/main/java/data/at/ATStateData.java
similarity index 100%
rename from src/data/at/ATStateData.java
rename to src/main/java/data/at/ATStateData.java
diff --git a/src/data/block/BlockData.java b/src/main/java/data/block/BlockData.java
similarity index 100%
rename from src/data/block/BlockData.java
rename to src/main/java/data/block/BlockData.java
diff --git a/src/data/block/BlockTransactionData.java b/src/main/java/data/block/BlockTransactionData.java
similarity index 100%
rename from src/data/block/BlockTransactionData.java
rename to src/main/java/data/block/BlockTransactionData.java
diff --git a/src/data/naming/NameData.java b/src/main/java/data/naming/NameData.java
similarity index 100%
rename from src/data/naming/NameData.java
rename to src/main/java/data/naming/NameData.java
diff --git a/src/data/package-info.java b/src/main/java/data/package-info.java
similarity index 100%
rename from src/data/package-info.java
rename to src/main/java/data/package-info.java
diff --git a/src/data/transaction/ATTransactionData.java b/src/main/java/data/transaction/ATTransactionData.java
similarity index 100%
rename from src/data/transaction/ATTransactionData.java
rename to src/main/java/data/transaction/ATTransactionData.java
diff --git a/src/data/transaction/ArbitraryTransactionData.java b/src/main/java/data/transaction/ArbitraryTransactionData.java
similarity index 100%
rename from src/data/transaction/ArbitraryTransactionData.java
rename to src/main/java/data/transaction/ArbitraryTransactionData.java
diff --git a/src/data/transaction/BuyNameTransactionData.java b/src/main/java/data/transaction/BuyNameTransactionData.java
similarity index 100%
rename from src/data/transaction/BuyNameTransactionData.java
rename to src/main/java/data/transaction/BuyNameTransactionData.java
diff --git a/src/data/transaction/CancelOrderTransactionData.java b/src/main/java/data/transaction/CancelOrderTransactionData.java
similarity index 100%
rename from src/data/transaction/CancelOrderTransactionData.java
rename to src/main/java/data/transaction/CancelOrderTransactionData.java
diff --git a/src/data/transaction/CancelSellNameTransactionData.java b/src/main/java/data/transaction/CancelSellNameTransactionData.java
similarity index 100%
rename from src/data/transaction/CancelSellNameTransactionData.java
rename to src/main/java/data/transaction/CancelSellNameTransactionData.java
diff --git a/src/data/transaction/CreateOrderTransactionData.java b/src/main/java/data/transaction/CreateOrderTransactionData.java
similarity index 100%
rename from src/data/transaction/CreateOrderTransactionData.java
rename to src/main/java/data/transaction/CreateOrderTransactionData.java
diff --git a/src/data/transaction/CreatePollTransactionData.java b/src/main/java/data/transaction/CreatePollTransactionData.java
similarity index 100%
rename from src/data/transaction/CreatePollTransactionData.java
rename to src/main/java/data/transaction/CreatePollTransactionData.java
diff --git a/src/data/transaction/DeployATTransactionData.java b/src/main/java/data/transaction/DeployATTransactionData.java
similarity index 100%
rename from src/data/transaction/DeployATTransactionData.java
rename to src/main/java/data/transaction/DeployATTransactionData.java
diff --git a/src/data/transaction/GenesisTransactionData.java b/src/main/java/data/transaction/GenesisTransactionData.java
similarity index 100%
rename from src/data/transaction/GenesisTransactionData.java
rename to src/main/java/data/transaction/GenesisTransactionData.java
diff --git a/src/data/transaction/IssueAssetTransactionData.java b/src/main/java/data/transaction/IssueAssetTransactionData.java
similarity index 100%
rename from src/data/transaction/IssueAssetTransactionData.java
rename to src/main/java/data/transaction/IssueAssetTransactionData.java
diff --git a/src/data/transaction/MessageTransactionData.java b/src/main/java/data/transaction/MessageTransactionData.java
similarity index 100%
rename from src/data/transaction/MessageTransactionData.java
rename to src/main/java/data/transaction/MessageTransactionData.java
diff --git a/src/data/transaction/MultiPaymentTransactionData.java b/src/main/java/data/transaction/MultiPaymentTransactionData.java
similarity index 100%
rename from src/data/transaction/MultiPaymentTransactionData.java
rename to src/main/java/data/transaction/MultiPaymentTransactionData.java
diff --git a/src/data/transaction/PaymentTransactionData.java b/src/main/java/data/transaction/PaymentTransactionData.java
similarity index 100%
rename from src/data/transaction/PaymentTransactionData.java
rename to src/main/java/data/transaction/PaymentTransactionData.java
diff --git a/src/data/transaction/RegisterNameTransactionData.java b/src/main/java/data/transaction/RegisterNameTransactionData.java
similarity index 100%
rename from src/data/transaction/RegisterNameTransactionData.java
rename to src/main/java/data/transaction/RegisterNameTransactionData.java
diff --git a/src/data/transaction/SellNameTransactionData.java b/src/main/java/data/transaction/SellNameTransactionData.java
similarity index 100%
rename from src/data/transaction/SellNameTransactionData.java
rename to src/main/java/data/transaction/SellNameTransactionData.java
diff --git a/src/data/transaction/TransactionData.java b/src/main/java/data/transaction/TransactionData.java
similarity index 100%
rename from src/data/transaction/TransactionData.java
rename to src/main/java/data/transaction/TransactionData.java
diff --git a/src/data/transaction/TransferAssetTransactionData.java b/src/main/java/data/transaction/TransferAssetTransactionData.java
similarity index 100%
rename from src/data/transaction/TransferAssetTransactionData.java
rename to src/main/java/data/transaction/TransferAssetTransactionData.java
diff --git a/src/data/transaction/UpdateNameTransactionData.java b/src/main/java/data/transaction/UpdateNameTransactionData.java
similarity index 100%
rename from src/data/transaction/UpdateNameTransactionData.java
rename to src/main/java/data/transaction/UpdateNameTransactionData.java
diff --git a/src/data/transaction/VoteOnPollTransactionData.java b/src/main/java/data/transaction/VoteOnPollTransactionData.java
similarity index 100%
rename from src/data/transaction/VoteOnPollTransactionData.java
rename to src/main/java/data/transaction/VoteOnPollTransactionData.java
diff --git a/src/data/voting/PollData.java b/src/main/java/data/voting/PollData.java
similarity index 100%
rename from src/data/voting/PollData.java
rename to src/main/java/data/voting/PollData.java
diff --git a/src/data/voting/PollOptionData.java b/src/main/java/data/voting/PollOptionData.java
similarity index 100%
rename from src/data/voting/PollOptionData.java
rename to src/main/java/data/voting/PollOptionData.java
diff --git a/src/data/voting/VoteOnPollData.java b/src/main/java/data/voting/VoteOnPollData.java
similarity index 100%
rename from src/data/voting/VoteOnPollData.java
rename to src/main/java/data/voting/VoteOnPollData.java
diff --git a/src/database/NoDataFoundException.java b/src/main/java/database/NoDataFoundException.java
similarity index 100%
rename from src/database/NoDataFoundException.java
rename to src/main/java/database/NoDataFoundException.java
diff --git a/src/main/java/globalization/BIP39WordList.java b/src/main/java/globalization/BIP39WordList.java
new file mode 100644
index 00000000..3e5a8d32
--- /dev/null
+++ b/src/main/java/globalization/BIP39WordList.java
@@ -0,0 +1,52 @@
+package globalization;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+/** Providing multi-language BIP39 word lists, downloaded from https://github.com/bitcoin/bips/tree/master/bip-0039 */
+public enum BIP39WordList {
+ INSTANCE;
+
+ private Logger LOGGER = LogManager.getLogger(BIP39WordList.class);
+
+ private Map> wordListsByLang;
+
+ private BIP39WordList() {
+ wordListsByLang = new HashMap<>();
+ }
+
+ public synchronized List getByLang(String lang) {
+ List wordList = wordListsByLang.get(lang);
+
+ if (wordList == null) {
+ ClassLoader loader = this.getClass().getClassLoader();
+
+ try (InputStream inputStream = loader.getResourceAsStream("BIP39/wordlist_" + lang + ".txt")) {
+ if (inputStream == null) {
+ LOGGER.warn("Can't locate '" + lang + "' BIP39 wordlist");
+ return null;
+ }
+
+ wordList = new BufferedReader(new InputStreamReader(inputStream)).lines().collect(Collectors.toList());
+ } catch (IOException e) {
+ LOGGER.warn("Error reading '" + lang + "' BIP39 wordlist", e);
+ return null;
+ }
+
+ wordListsByLang.put(lang, wordList);
+ }
+
+ return Collections.unmodifiableList(wordList);
+ }
+
+}
diff --git a/src/main/java/globalization/Translator.java b/src/main/java/globalization/Translator.java
new file mode 100644
index 00000000..15291f91
--- /dev/null
+++ b/src/main/java/globalization/Translator.java
@@ -0,0 +1,52 @@
+package globalization;
+
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+public enum Translator {
+ INSTANCE;
+
+ private final Logger LOGGER = LogManager.getLogger(Translator.class);
+ private final String DEFAULT_LANG = Locale.getDefault().getLanguage();
+
+ private final Map resourceBundles = new HashMap<>();
+
+ private synchronized ResourceBundle getOrLoadResourceBundle(String className, String lang) {
+ final String bundleKey = className + ":" + lang;
+
+ ResourceBundle resourceBundle = resourceBundles.get(bundleKey);
+ if (resourceBundle != null)
+ return resourceBundle;
+
+ try {
+ resourceBundle = ResourceBundle.getBundle("i18n." + className, Locale.forLanguageTag(lang));
+ } catch (MissingResourceException e) {
+ LOGGER.warn("Can't locate '" + lang + "' translation resource bundle for " + className, e);
+ return null;
+ }
+
+ resourceBundles.put(bundleKey, resourceBundle);
+
+ return resourceBundle;
+ }
+
+ public String translate(final String className, final String key) {
+ return this.translate(className, DEFAULT_LANG, key);
+ }
+
+ public String translate(final String className, final String lang, final String key, final Object... args) {
+ ResourceBundle resourceBundle = getOrLoadResourceBundle(className, lang);
+
+ if (resourceBundle == null || !resourceBundle.containsKey(key))
+ return "!!" + lang + ":" + className + "." + key + "!!";
+
+ return String.format(resourceBundle.getString(key), args);
+ }
+
+}
diff --git a/src/org/whispersystems/curve25519/java/Arrays.java b/src/main/java/org/whispersystems/curve25519/java/Arrays.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/Arrays.java
rename to src/main/java/org/whispersystems/curve25519/java/Arrays.java
diff --git a/src/org/whispersystems/curve25519/java/Sha512.java b/src/main/java/org/whispersystems/curve25519/java/Sha512.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/Sha512.java
rename to src/main/java/org/whispersystems/curve25519/java/Sha512.java
diff --git a/src/org/whispersystems/curve25519/java/crypto_verify_32.java b/src/main/java/org/whispersystems/curve25519/java/crypto_verify_32.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/crypto_verify_32.java
rename to src/main/java/org/whispersystems/curve25519/java/crypto_verify_32.java
diff --git a/src/org/whispersystems/curve25519/java/curve_sigs.java b/src/main/java/org/whispersystems/curve25519/java/curve_sigs.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/curve_sigs.java
rename to src/main/java/org/whispersystems/curve25519/java/curve_sigs.java
diff --git a/src/org/whispersystems/curve25519/java/fe_0.java b/src/main/java/org/whispersystems/curve25519/java/fe_0.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/fe_0.java
rename to src/main/java/org/whispersystems/curve25519/java/fe_0.java
diff --git a/src/org/whispersystems/curve25519/java/fe_1.java b/src/main/java/org/whispersystems/curve25519/java/fe_1.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/fe_1.java
rename to src/main/java/org/whispersystems/curve25519/java/fe_1.java
diff --git a/src/org/whispersystems/curve25519/java/fe_add.java b/src/main/java/org/whispersystems/curve25519/java/fe_add.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/fe_add.java
rename to src/main/java/org/whispersystems/curve25519/java/fe_add.java
diff --git a/src/org/whispersystems/curve25519/java/fe_cmov.java b/src/main/java/org/whispersystems/curve25519/java/fe_cmov.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/fe_cmov.java
rename to src/main/java/org/whispersystems/curve25519/java/fe_cmov.java
diff --git a/src/org/whispersystems/curve25519/java/fe_copy.java b/src/main/java/org/whispersystems/curve25519/java/fe_copy.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/fe_copy.java
rename to src/main/java/org/whispersystems/curve25519/java/fe_copy.java
diff --git a/src/org/whispersystems/curve25519/java/fe_cswap.java b/src/main/java/org/whispersystems/curve25519/java/fe_cswap.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/fe_cswap.java
rename to src/main/java/org/whispersystems/curve25519/java/fe_cswap.java
diff --git a/src/org/whispersystems/curve25519/java/fe_frombytes.java b/src/main/java/org/whispersystems/curve25519/java/fe_frombytes.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/fe_frombytes.java
rename to src/main/java/org/whispersystems/curve25519/java/fe_frombytes.java
diff --git a/src/org/whispersystems/curve25519/java/fe_invert.java b/src/main/java/org/whispersystems/curve25519/java/fe_invert.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/fe_invert.java
rename to src/main/java/org/whispersystems/curve25519/java/fe_invert.java
diff --git a/src/org/whispersystems/curve25519/java/fe_isnegative.java b/src/main/java/org/whispersystems/curve25519/java/fe_isnegative.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/fe_isnegative.java
rename to src/main/java/org/whispersystems/curve25519/java/fe_isnegative.java
diff --git a/src/org/whispersystems/curve25519/java/fe_isnonzero.java b/src/main/java/org/whispersystems/curve25519/java/fe_isnonzero.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/fe_isnonzero.java
rename to src/main/java/org/whispersystems/curve25519/java/fe_isnonzero.java
diff --git a/src/org/whispersystems/curve25519/java/fe_mul.java b/src/main/java/org/whispersystems/curve25519/java/fe_mul.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/fe_mul.java
rename to src/main/java/org/whispersystems/curve25519/java/fe_mul.java
diff --git a/src/org/whispersystems/curve25519/java/fe_mul121666.java b/src/main/java/org/whispersystems/curve25519/java/fe_mul121666.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/fe_mul121666.java
rename to src/main/java/org/whispersystems/curve25519/java/fe_mul121666.java
diff --git a/src/org/whispersystems/curve25519/java/fe_neg.java b/src/main/java/org/whispersystems/curve25519/java/fe_neg.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/fe_neg.java
rename to src/main/java/org/whispersystems/curve25519/java/fe_neg.java
diff --git a/src/org/whispersystems/curve25519/java/fe_pow22523.java b/src/main/java/org/whispersystems/curve25519/java/fe_pow22523.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/fe_pow22523.java
rename to src/main/java/org/whispersystems/curve25519/java/fe_pow22523.java
diff --git a/src/org/whispersystems/curve25519/java/fe_sq.java b/src/main/java/org/whispersystems/curve25519/java/fe_sq.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/fe_sq.java
rename to src/main/java/org/whispersystems/curve25519/java/fe_sq.java
diff --git a/src/org/whispersystems/curve25519/java/fe_sq2.java b/src/main/java/org/whispersystems/curve25519/java/fe_sq2.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/fe_sq2.java
rename to src/main/java/org/whispersystems/curve25519/java/fe_sq2.java
diff --git a/src/org/whispersystems/curve25519/java/fe_sub.java b/src/main/java/org/whispersystems/curve25519/java/fe_sub.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/fe_sub.java
rename to src/main/java/org/whispersystems/curve25519/java/fe_sub.java
diff --git a/src/org/whispersystems/curve25519/java/fe_tobytes.java b/src/main/java/org/whispersystems/curve25519/java/fe_tobytes.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/fe_tobytes.java
rename to src/main/java/org/whispersystems/curve25519/java/fe_tobytes.java
diff --git a/src/org/whispersystems/curve25519/java/ge_add.java b/src/main/java/org/whispersystems/curve25519/java/ge_add.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/ge_add.java
rename to src/main/java/org/whispersystems/curve25519/java/ge_add.java
diff --git a/src/org/whispersystems/curve25519/java/ge_cached.java b/src/main/java/org/whispersystems/curve25519/java/ge_cached.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/ge_cached.java
rename to src/main/java/org/whispersystems/curve25519/java/ge_cached.java
diff --git a/src/org/whispersystems/curve25519/java/ge_double_scalarmult.java b/src/main/java/org/whispersystems/curve25519/java/ge_double_scalarmult.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/ge_double_scalarmult.java
rename to src/main/java/org/whispersystems/curve25519/java/ge_double_scalarmult.java
diff --git a/src/org/whispersystems/curve25519/java/ge_frombytes.java b/src/main/java/org/whispersystems/curve25519/java/ge_frombytes.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/ge_frombytes.java
rename to src/main/java/org/whispersystems/curve25519/java/ge_frombytes.java
diff --git a/src/org/whispersystems/curve25519/java/ge_madd.java b/src/main/java/org/whispersystems/curve25519/java/ge_madd.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/ge_madd.java
rename to src/main/java/org/whispersystems/curve25519/java/ge_madd.java
diff --git a/src/org/whispersystems/curve25519/java/ge_msub.java b/src/main/java/org/whispersystems/curve25519/java/ge_msub.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/ge_msub.java
rename to src/main/java/org/whispersystems/curve25519/java/ge_msub.java
diff --git a/src/org/whispersystems/curve25519/java/ge_p1p1.java b/src/main/java/org/whispersystems/curve25519/java/ge_p1p1.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/ge_p1p1.java
rename to src/main/java/org/whispersystems/curve25519/java/ge_p1p1.java
diff --git a/src/org/whispersystems/curve25519/java/ge_p1p1_to_p2.java b/src/main/java/org/whispersystems/curve25519/java/ge_p1p1_to_p2.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/ge_p1p1_to_p2.java
rename to src/main/java/org/whispersystems/curve25519/java/ge_p1p1_to_p2.java
diff --git a/src/org/whispersystems/curve25519/java/ge_p1p1_to_p3.java b/src/main/java/org/whispersystems/curve25519/java/ge_p1p1_to_p3.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/ge_p1p1_to_p3.java
rename to src/main/java/org/whispersystems/curve25519/java/ge_p1p1_to_p3.java
diff --git a/src/org/whispersystems/curve25519/java/ge_p2.java b/src/main/java/org/whispersystems/curve25519/java/ge_p2.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/ge_p2.java
rename to src/main/java/org/whispersystems/curve25519/java/ge_p2.java
diff --git a/src/org/whispersystems/curve25519/java/ge_p2_0.java b/src/main/java/org/whispersystems/curve25519/java/ge_p2_0.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/ge_p2_0.java
rename to src/main/java/org/whispersystems/curve25519/java/ge_p2_0.java
diff --git a/src/org/whispersystems/curve25519/java/ge_p2_dbl.java b/src/main/java/org/whispersystems/curve25519/java/ge_p2_dbl.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/ge_p2_dbl.java
rename to src/main/java/org/whispersystems/curve25519/java/ge_p2_dbl.java
diff --git a/src/org/whispersystems/curve25519/java/ge_p3.java b/src/main/java/org/whispersystems/curve25519/java/ge_p3.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/ge_p3.java
rename to src/main/java/org/whispersystems/curve25519/java/ge_p3.java
diff --git a/src/org/whispersystems/curve25519/java/ge_p3_0.java b/src/main/java/org/whispersystems/curve25519/java/ge_p3_0.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/ge_p3_0.java
rename to src/main/java/org/whispersystems/curve25519/java/ge_p3_0.java
diff --git a/src/org/whispersystems/curve25519/java/ge_p3_dbl.java b/src/main/java/org/whispersystems/curve25519/java/ge_p3_dbl.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/ge_p3_dbl.java
rename to src/main/java/org/whispersystems/curve25519/java/ge_p3_dbl.java
diff --git a/src/org/whispersystems/curve25519/java/ge_p3_to_cached.java b/src/main/java/org/whispersystems/curve25519/java/ge_p3_to_cached.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/ge_p3_to_cached.java
rename to src/main/java/org/whispersystems/curve25519/java/ge_p3_to_cached.java
diff --git a/src/org/whispersystems/curve25519/java/ge_p3_to_p2.java b/src/main/java/org/whispersystems/curve25519/java/ge_p3_to_p2.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/ge_p3_to_p2.java
rename to src/main/java/org/whispersystems/curve25519/java/ge_p3_to_p2.java
diff --git a/src/org/whispersystems/curve25519/java/ge_p3_tobytes.java b/src/main/java/org/whispersystems/curve25519/java/ge_p3_tobytes.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/ge_p3_tobytes.java
rename to src/main/java/org/whispersystems/curve25519/java/ge_p3_tobytes.java
diff --git a/src/org/whispersystems/curve25519/java/ge_precomp.java b/src/main/java/org/whispersystems/curve25519/java/ge_precomp.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/ge_precomp.java
rename to src/main/java/org/whispersystems/curve25519/java/ge_precomp.java
diff --git a/src/org/whispersystems/curve25519/java/ge_precomp_0.java b/src/main/java/org/whispersystems/curve25519/java/ge_precomp_0.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/ge_precomp_0.java
rename to src/main/java/org/whispersystems/curve25519/java/ge_precomp_0.java
diff --git a/src/org/whispersystems/curve25519/java/ge_precomp_base_0_7.java b/src/main/java/org/whispersystems/curve25519/java/ge_precomp_base_0_7.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/ge_precomp_base_0_7.java
rename to src/main/java/org/whispersystems/curve25519/java/ge_precomp_base_0_7.java
diff --git a/src/org/whispersystems/curve25519/java/ge_precomp_base_16_23.java b/src/main/java/org/whispersystems/curve25519/java/ge_precomp_base_16_23.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/ge_precomp_base_16_23.java
rename to src/main/java/org/whispersystems/curve25519/java/ge_precomp_base_16_23.java
diff --git a/src/org/whispersystems/curve25519/java/ge_precomp_base_24_31.java b/src/main/java/org/whispersystems/curve25519/java/ge_precomp_base_24_31.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/ge_precomp_base_24_31.java
rename to src/main/java/org/whispersystems/curve25519/java/ge_precomp_base_24_31.java
diff --git a/src/org/whispersystems/curve25519/java/ge_precomp_base_8_15.java b/src/main/java/org/whispersystems/curve25519/java/ge_precomp_base_8_15.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/ge_precomp_base_8_15.java
rename to src/main/java/org/whispersystems/curve25519/java/ge_precomp_base_8_15.java
diff --git a/src/org/whispersystems/curve25519/java/ge_scalarmult_base.java b/src/main/java/org/whispersystems/curve25519/java/ge_scalarmult_base.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/ge_scalarmult_base.java
rename to src/main/java/org/whispersystems/curve25519/java/ge_scalarmult_base.java
diff --git a/src/org/whispersystems/curve25519/java/ge_sub.java b/src/main/java/org/whispersystems/curve25519/java/ge_sub.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/ge_sub.java
rename to src/main/java/org/whispersystems/curve25519/java/ge_sub.java
diff --git a/src/org/whispersystems/curve25519/java/ge_tobytes.java b/src/main/java/org/whispersystems/curve25519/java/ge_tobytes.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/ge_tobytes.java
rename to src/main/java/org/whispersystems/curve25519/java/ge_tobytes.java
diff --git a/src/org/whispersystems/curve25519/java/open.java b/src/main/java/org/whispersystems/curve25519/java/open.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/open.java
rename to src/main/java/org/whispersystems/curve25519/java/open.java
diff --git a/src/org/whispersystems/curve25519/java/sc_muladd.java b/src/main/java/org/whispersystems/curve25519/java/sc_muladd.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/sc_muladd.java
rename to src/main/java/org/whispersystems/curve25519/java/sc_muladd.java
diff --git a/src/org/whispersystems/curve25519/java/sc_reduce.java b/src/main/java/org/whispersystems/curve25519/java/sc_reduce.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/sc_reduce.java
rename to src/main/java/org/whispersystems/curve25519/java/sc_reduce.java
diff --git a/src/org/whispersystems/curve25519/java/scalarmult.java b/src/main/java/org/whispersystems/curve25519/java/scalarmult.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/scalarmult.java
rename to src/main/java/org/whispersystems/curve25519/java/scalarmult.java
diff --git a/src/org/whispersystems/curve25519/java/sign_modified.java b/src/main/java/org/whispersystems/curve25519/java/sign_modified.java
similarity index 100%
rename from src/org/whispersystems/curve25519/java/sign_modified.java
rename to src/main/java/org/whispersystems/curve25519/java/sign_modified.java
diff --git a/src/orphan.java b/src/main/java/orphan.java
similarity index 100%
rename from src/orphan.java
rename to src/main/java/orphan.java
diff --git a/src/qora/account/Account.java b/src/main/java/qora/account/Account.java
similarity index 100%
rename from src/qora/account/Account.java
rename to src/main/java/qora/account/Account.java
diff --git a/src/qora/account/GenesisAccount.java b/src/main/java/qora/account/GenesisAccount.java
similarity index 100%
rename from src/qora/account/GenesisAccount.java
rename to src/main/java/qora/account/GenesisAccount.java
diff --git a/src/qora/account/PrivateKeyAccount.java b/src/main/java/qora/account/PrivateKeyAccount.java
similarity index 100%
rename from src/qora/account/PrivateKeyAccount.java
rename to src/main/java/qora/account/PrivateKeyAccount.java
diff --git a/src/qora/account/PublicKeyAccount.java b/src/main/java/qora/account/PublicKeyAccount.java
similarity index 100%
rename from src/qora/account/PublicKeyAccount.java
rename to src/main/java/qora/account/PublicKeyAccount.java
diff --git a/src/qora/assets/Asset.java b/src/main/java/qora/assets/Asset.java
similarity index 100%
rename from src/qora/assets/Asset.java
rename to src/main/java/qora/assets/Asset.java
diff --git a/src/qora/assets/Order.java b/src/main/java/qora/assets/Order.java
similarity index 100%
rename from src/qora/assets/Order.java
rename to src/main/java/qora/assets/Order.java
diff --git a/src/qora/assets/Trade.java b/src/main/java/qora/assets/Trade.java
similarity index 100%
rename from src/qora/assets/Trade.java
rename to src/main/java/qora/assets/Trade.java
diff --git a/src/qora/at/AT.java b/src/main/java/qora/at/AT.java
similarity index 100%
rename from src/qora/at/AT.java
rename to src/main/java/qora/at/AT.java
diff --git a/src/qora/at/BlockchainAPI.java b/src/main/java/qora/at/BlockchainAPI.java
similarity index 100%
rename from src/qora/at/BlockchainAPI.java
rename to src/main/java/qora/at/BlockchainAPI.java
diff --git a/src/qora/at/QoraATAPI.java b/src/main/java/qora/at/QoraATAPI.java
similarity index 100%
rename from src/qora/at/QoraATAPI.java
rename to src/main/java/qora/at/QoraATAPI.java
diff --git a/src/qora/at/QoraATLogger.java b/src/main/java/qora/at/QoraATLogger.java
similarity index 100%
rename from src/qora/at/QoraATLogger.java
rename to src/main/java/qora/at/QoraATLogger.java
diff --git a/src/qora/at/QoraFunctionCode.java b/src/main/java/qora/at/QoraFunctionCode.java
similarity index 100%
rename from src/qora/at/QoraFunctionCode.java
rename to src/main/java/qora/at/QoraFunctionCode.java
diff --git a/src/qora/block/Block.java b/src/main/java/qora/block/Block.java
similarity index 100%
rename from src/qora/block/Block.java
rename to src/main/java/qora/block/Block.java
diff --git a/src/qora/block/BlockChain.java b/src/main/java/qora/block/BlockChain.java
similarity index 100%
rename from src/qora/block/BlockChain.java
rename to src/main/java/qora/block/BlockChain.java
diff --git a/src/qora/block/BlockGenerator.java b/src/main/java/qora/block/BlockGenerator.java
similarity index 100%
rename from src/qora/block/BlockGenerator.java
rename to src/main/java/qora/block/BlockGenerator.java
diff --git a/src/qora/block/GenesisBlock.java b/src/main/java/qora/block/GenesisBlock.java
similarity index 100%
rename from src/qora/block/GenesisBlock.java
rename to src/main/java/qora/block/GenesisBlock.java
diff --git a/src/qora/crypto/BrokenMD160.java b/src/main/java/qora/crypto/BrokenMD160.java
similarity index 100%
rename from src/qora/crypto/BrokenMD160.java
rename to src/main/java/qora/crypto/BrokenMD160.java
diff --git a/src/qora/crypto/Crypto.java b/src/main/java/qora/crypto/Crypto.java
similarity index 100%
rename from src/qora/crypto/Crypto.java
rename to src/main/java/qora/crypto/Crypto.java
diff --git a/src/qora/crypto/CryptoBytes.java b/src/main/java/qora/crypto/CryptoBytes.java
similarity index 100%
rename from src/qora/crypto/CryptoBytes.java
rename to src/main/java/qora/crypto/CryptoBytes.java
diff --git a/src/qora/crypto/Ed25519.java b/src/main/java/qora/crypto/Ed25519.java
similarity index 100%
rename from src/qora/crypto/Ed25519.java
rename to src/main/java/qora/crypto/Ed25519.java
diff --git a/src/qora/naming/Name.java b/src/main/java/qora/naming/Name.java
similarity index 100%
rename from src/qora/naming/Name.java
rename to src/main/java/qora/naming/Name.java
diff --git a/src/qora/payment/Payment.java b/src/main/java/qora/payment/Payment.java
similarity index 100%
rename from src/qora/payment/Payment.java
rename to src/main/java/qora/payment/Payment.java
diff --git a/src/qora/transaction/ATTransaction.java b/src/main/java/qora/transaction/ATTransaction.java
similarity index 100%
rename from src/qora/transaction/ATTransaction.java
rename to src/main/java/qora/transaction/ATTransaction.java
diff --git a/src/qora/transaction/ArbitraryTransaction.java b/src/main/java/qora/transaction/ArbitraryTransaction.java
similarity index 100%
rename from src/qora/transaction/ArbitraryTransaction.java
rename to src/main/java/qora/transaction/ArbitraryTransaction.java
diff --git a/src/qora/transaction/BuyNameTransaction.java b/src/main/java/qora/transaction/BuyNameTransaction.java
similarity index 100%
rename from src/qora/transaction/BuyNameTransaction.java
rename to src/main/java/qora/transaction/BuyNameTransaction.java
diff --git a/src/qora/transaction/CancelOrderTransaction.java b/src/main/java/qora/transaction/CancelOrderTransaction.java
similarity index 100%
rename from src/qora/transaction/CancelOrderTransaction.java
rename to src/main/java/qora/transaction/CancelOrderTransaction.java
diff --git a/src/qora/transaction/CancelSellNameTransaction.java b/src/main/java/qora/transaction/CancelSellNameTransaction.java
similarity index 100%
rename from src/qora/transaction/CancelSellNameTransaction.java
rename to src/main/java/qora/transaction/CancelSellNameTransaction.java
diff --git a/src/qora/transaction/CreateOrderTransaction.java b/src/main/java/qora/transaction/CreateOrderTransaction.java
similarity index 100%
rename from src/qora/transaction/CreateOrderTransaction.java
rename to src/main/java/qora/transaction/CreateOrderTransaction.java
diff --git a/src/qora/transaction/CreatePollTransaction.java b/src/main/java/qora/transaction/CreatePollTransaction.java
similarity index 100%
rename from src/qora/transaction/CreatePollTransaction.java
rename to src/main/java/qora/transaction/CreatePollTransaction.java
diff --git a/src/qora/transaction/DeployATTransaction.java b/src/main/java/qora/transaction/DeployATTransaction.java
similarity index 100%
rename from src/qora/transaction/DeployATTransaction.java
rename to src/main/java/qora/transaction/DeployATTransaction.java
diff --git a/src/qora/transaction/GenesisTransaction.java b/src/main/java/qora/transaction/GenesisTransaction.java
similarity index 100%
rename from src/qora/transaction/GenesisTransaction.java
rename to src/main/java/qora/transaction/GenesisTransaction.java
diff --git a/src/qora/transaction/IssueAssetTransaction.java b/src/main/java/qora/transaction/IssueAssetTransaction.java
similarity index 100%
rename from src/qora/transaction/IssueAssetTransaction.java
rename to src/main/java/qora/transaction/IssueAssetTransaction.java
diff --git a/src/qora/transaction/MessageTransaction.java b/src/main/java/qora/transaction/MessageTransaction.java
similarity index 100%
rename from src/qora/transaction/MessageTransaction.java
rename to src/main/java/qora/transaction/MessageTransaction.java
diff --git a/src/qora/transaction/MultiPaymentTransaction.java b/src/main/java/qora/transaction/MultiPaymentTransaction.java
similarity index 100%
rename from src/qora/transaction/MultiPaymentTransaction.java
rename to src/main/java/qora/transaction/MultiPaymentTransaction.java
diff --git a/src/qora/transaction/PaymentTransaction.java b/src/main/java/qora/transaction/PaymentTransaction.java
similarity index 100%
rename from src/qora/transaction/PaymentTransaction.java
rename to src/main/java/qora/transaction/PaymentTransaction.java
diff --git a/src/qora/transaction/RegisterNameTransaction.java b/src/main/java/qora/transaction/RegisterNameTransaction.java
similarity index 100%
rename from src/qora/transaction/RegisterNameTransaction.java
rename to src/main/java/qora/transaction/RegisterNameTransaction.java
diff --git a/src/qora/transaction/SellNameTransaction.java b/src/main/java/qora/transaction/SellNameTransaction.java
similarity index 100%
rename from src/qora/transaction/SellNameTransaction.java
rename to src/main/java/qora/transaction/SellNameTransaction.java
diff --git a/src/qora/transaction/Transaction.java b/src/main/java/qora/transaction/Transaction.java
similarity index 100%
rename from src/qora/transaction/Transaction.java
rename to src/main/java/qora/transaction/Transaction.java
diff --git a/src/qora/transaction/TransferAssetTransaction.java b/src/main/java/qora/transaction/TransferAssetTransaction.java
similarity index 100%
rename from src/qora/transaction/TransferAssetTransaction.java
rename to src/main/java/qora/transaction/TransferAssetTransaction.java
diff --git a/src/qora/transaction/UpdateNameTransaction.java b/src/main/java/qora/transaction/UpdateNameTransaction.java
similarity index 100%
rename from src/qora/transaction/UpdateNameTransaction.java
rename to src/main/java/qora/transaction/UpdateNameTransaction.java
diff --git a/src/qora/transaction/VoteOnPollTransaction.java b/src/main/java/qora/transaction/VoteOnPollTransaction.java
similarity index 100%
rename from src/qora/transaction/VoteOnPollTransaction.java
rename to src/main/java/qora/transaction/VoteOnPollTransaction.java
diff --git a/src/qora/voting/Poll.java b/src/main/java/qora/voting/Poll.java
similarity index 100%
rename from src/qora/voting/Poll.java
rename to src/main/java/qora/voting/Poll.java
diff --git a/src/repository/ATRepository.java b/src/main/java/repository/ATRepository.java
similarity index 100%
rename from src/repository/ATRepository.java
rename to src/main/java/repository/ATRepository.java
diff --git a/src/repository/AccountRepository.java b/src/main/java/repository/AccountRepository.java
similarity index 100%
rename from src/repository/AccountRepository.java
rename to src/main/java/repository/AccountRepository.java
diff --git a/src/repository/AssetRepository.java b/src/main/java/repository/AssetRepository.java
similarity index 100%
rename from src/repository/AssetRepository.java
rename to src/main/java/repository/AssetRepository.java
diff --git a/src/repository/BlockRepository.java b/src/main/java/repository/BlockRepository.java
similarity index 100%
rename from src/repository/BlockRepository.java
rename to src/main/java/repository/BlockRepository.java
diff --git a/src/repository/DataException.java b/src/main/java/repository/DataException.java
similarity index 100%
rename from src/repository/DataException.java
rename to src/main/java/repository/DataException.java
diff --git a/src/repository/NameRepository.java b/src/main/java/repository/NameRepository.java
similarity index 100%
rename from src/repository/NameRepository.java
rename to src/main/java/repository/NameRepository.java
diff --git a/src/repository/Repository.java b/src/main/java/repository/Repository.java
similarity index 100%
rename from src/repository/Repository.java
rename to src/main/java/repository/Repository.java
diff --git a/src/repository/RepositoryFactory.java b/src/main/java/repository/RepositoryFactory.java
similarity index 100%
rename from src/repository/RepositoryFactory.java
rename to src/main/java/repository/RepositoryFactory.java
diff --git a/src/repository/RepositoryManager.java b/src/main/java/repository/RepositoryManager.java
similarity index 100%
rename from src/repository/RepositoryManager.java
rename to src/main/java/repository/RepositoryManager.java
diff --git a/src/repository/TransactionRepository.java b/src/main/java/repository/TransactionRepository.java
similarity index 100%
rename from src/repository/TransactionRepository.java
rename to src/main/java/repository/TransactionRepository.java
diff --git a/src/repository/VotingRepository.java b/src/main/java/repository/VotingRepository.java
similarity index 100%
rename from src/repository/VotingRepository.java
rename to src/main/java/repository/VotingRepository.java
diff --git a/src/repository/hsqldb/HSQLDBATRepository.java b/src/main/java/repository/hsqldb/HSQLDBATRepository.java
similarity index 100%
rename from src/repository/hsqldb/HSQLDBATRepository.java
rename to src/main/java/repository/hsqldb/HSQLDBATRepository.java
diff --git a/src/repository/hsqldb/HSQLDBAccountRepository.java b/src/main/java/repository/hsqldb/HSQLDBAccountRepository.java
similarity index 100%
rename from src/repository/hsqldb/HSQLDBAccountRepository.java
rename to src/main/java/repository/hsqldb/HSQLDBAccountRepository.java
diff --git a/src/repository/hsqldb/HSQLDBAssetRepository.java b/src/main/java/repository/hsqldb/HSQLDBAssetRepository.java
similarity index 100%
rename from src/repository/hsqldb/HSQLDBAssetRepository.java
rename to src/main/java/repository/hsqldb/HSQLDBAssetRepository.java
diff --git a/src/repository/hsqldb/HSQLDBBlockRepository.java b/src/main/java/repository/hsqldb/HSQLDBBlockRepository.java
similarity index 100%
rename from src/repository/hsqldb/HSQLDBBlockRepository.java
rename to src/main/java/repository/hsqldb/HSQLDBBlockRepository.java
diff --git a/src/repository/hsqldb/HSQLDBDatabaseUpdates.java b/src/main/java/repository/hsqldb/HSQLDBDatabaseUpdates.java
similarity index 100%
rename from src/repository/hsqldb/HSQLDBDatabaseUpdates.java
rename to src/main/java/repository/hsqldb/HSQLDBDatabaseUpdates.java
diff --git a/src/repository/hsqldb/HSQLDBNameRepository.java b/src/main/java/repository/hsqldb/HSQLDBNameRepository.java
similarity index 100%
rename from src/repository/hsqldb/HSQLDBNameRepository.java
rename to src/main/java/repository/hsqldb/HSQLDBNameRepository.java
diff --git a/src/repository/hsqldb/HSQLDBRepository.java b/src/main/java/repository/hsqldb/HSQLDBRepository.java
similarity index 100%
rename from src/repository/hsqldb/HSQLDBRepository.java
rename to src/main/java/repository/hsqldb/HSQLDBRepository.java
diff --git a/src/repository/hsqldb/HSQLDBRepositoryFactory.java b/src/main/java/repository/hsqldb/HSQLDBRepositoryFactory.java
similarity index 100%
rename from src/repository/hsqldb/HSQLDBRepositoryFactory.java
rename to src/main/java/repository/hsqldb/HSQLDBRepositoryFactory.java
diff --git a/src/repository/hsqldb/HSQLDBSaver.java b/src/main/java/repository/hsqldb/HSQLDBSaver.java
similarity index 100%
rename from src/repository/hsqldb/HSQLDBSaver.java
rename to src/main/java/repository/hsqldb/HSQLDBSaver.java
diff --git a/src/repository/hsqldb/HSQLDBVotingRepository.java b/src/main/java/repository/hsqldb/HSQLDBVotingRepository.java
similarity index 100%
rename from src/repository/hsqldb/HSQLDBVotingRepository.java
rename to src/main/java/repository/hsqldb/HSQLDBVotingRepository.java
diff --git a/src/repository/hsqldb/transaction/HSQLDBATTransactionRepository.java b/src/main/java/repository/hsqldb/transaction/HSQLDBATTransactionRepository.java
similarity index 100%
rename from src/repository/hsqldb/transaction/HSQLDBATTransactionRepository.java
rename to src/main/java/repository/hsqldb/transaction/HSQLDBATTransactionRepository.java
diff --git a/src/repository/hsqldb/transaction/HSQLDBArbitraryTransactionRepository.java b/src/main/java/repository/hsqldb/transaction/HSQLDBArbitraryTransactionRepository.java
similarity index 100%
rename from src/repository/hsqldb/transaction/HSQLDBArbitraryTransactionRepository.java
rename to src/main/java/repository/hsqldb/transaction/HSQLDBArbitraryTransactionRepository.java
diff --git a/src/repository/hsqldb/transaction/HSQLDBBuyNameTransactionRepository.java b/src/main/java/repository/hsqldb/transaction/HSQLDBBuyNameTransactionRepository.java
similarity index 100%
rename from src/repository/hsqldb/transaction/HSQLDBBuyNameTransactionRepository.java
rename to src/main/java/repository/hsqldb/transaction/HSQLDBBuyNameTransactionRepository.java
diff --git a/src/repository/hsqldb/transaction/HSQLDBCancelOrderTransactionRepository.java b/src/main/java/repository/hsqldb/transaction/HSQLDBCancelOrderTransactionRepository.java
similarity index 100%
rename from src/repository/hsqldb/transaction/HSQLDBCancelOrderTransactionRepository.java
rename to src/main/java/repository/hsqldb/transaction/HSQLDBCancelOrderTransactionRepository.java
diff --git a/src/repository/hsqldb/transaction/HSQLDBCancelSellNameTransactionRepository.java b/src/main/java/repository/hsqldb/transaction/HSQLDBCancelSellNameTransactionRepository.java
similarity index 100%
rename from src/repository/hsqldb/transaction/HSQLDBCancelSellNameTransactionRepository.java
rename to src/main/java/repository/hsqldb/transaction/HSQLDBCancelSellNameTransactionRepository.java
diff --git a/src/repository/hsqldb/transaction/HSQLDBCreateOrderTransactionRepository.java b/src/main/java/repository/hsqldb/transaction/HSQLDBCreateOrderTransactionRepository.java
similarity index 100%
rename from src/repository/hsqldb/transaction/HSQLDBCreateOrderTransactionRepository.java
rename to src/main/java/repository/hsqldb/transaction/HSQLDBCreateOrderTransactionRepository.java
diff --git a/src/repository/hsqldb/transaction/HSQLDBCreatePollTransactionRepository.java b/src/main/java/repository/hsqldb/transaction/HSQLDBCreatePollTransactionRepository.java
similarity index 100%
rename from src/repository/hsqldb/transaction/HSQLDBCreatePollTransactionRepository.java
rename to src/main/java/repository/hsqldb/transaction/HSQLDBCreatePollTransactionRepository.java
diff --git a/src/repository/hsqldb/transaction/HSQLDBDeployATTransactionRepository.java b/src/main/java/repository/hsqldb/transaction/HSQLDBDeployATTransactionRepository.java
similarity index 100%
rename from src/repository/hsqldb/transaction/HSQLDBDeployATTransactionRepository.java
rename to src/main/java/repository/hsqldb/transaction/HSQLDBDeployATTransactionRepository.java
diff --git a/src/repository/hsqldb/transaction/HSQLDBGenesisTransactionRepository.java b/src/main/java/repository/hsqldb/transaction/HSQLDBGenesisTransactionRepository.java
similarity index 100%
rename from src/repository/hsqldb/transaction/HSQLDBGenesisTransactionRepository.java
rename to src/main/java/repository/hsqldb/transaction/HSQLDBGenesisTransactionRepository.java
diff --git a/src/repository/hsqldb/transaction/HSQLDBIssueAssetTransactionRepository.java b/src/main/java/repository/hsqldb/transaction/HSQLDBIssueAssetTransactionRepository.java
similarity index 100%
rename from src/repository/hsqldb/transaction/HSQLDBIssueAssetTransactionRepository.java
rename to src/main/java/repository/hsqldb/transaction/HSQLDBIssueAssetTransactionRepository.java
diff --git a/src/repository/hsqldb/transaction/HSQLDBMessageTransactionRepository.java b/src/main/java/repository/hsqldb/transaction/HSQLDBMessageTransactionRepository.java
similarity index 100%
rename from src/repository/hsqldb/transaction/HSQLDBMessageTransactionRepository.java
rename to src/main/java/repository/hsqldb/transaction/HSQLDBMessageTransactionRepository.java
diff --git a/src/repository/hsqldb/transaction/HSQLDBMultiPaymentTransactionRepository.java b/src/main/java/repository/hsqldb/transaction/HSQLDBMultiPaymentTransactionRepository.java
similarity index 100%
rename from src/repository/hsqldb/transaction/HSQLDBMultiPaymentTransactionRepository.java
rename to src/main/java/repository/hsqldb/transaction/HSQLDBMultiPaymentTransactionRepository.java
diff --git a/src/repository/hsqldb/transaction/HSQLDBPaymentTransactionRepository.java b/src/main/java/repository/hsqldb/transaction/HSQLDBPaymentTransactionRepository.java
similarity index 100%
rename from src/repository/hsqldb/transaction/HSQLDBPaymentTransactionRepository.java
rename to src/main/java/repository/hsqldb/transaction/HSQLDBPaymentTransactionRepository.java
diff --git a/src/repository/hsqldb/transaction/HSQLDBRegisterNameTransactionRepository.java b/src/main/java/repository/hsqldb/transaction/HSQLDBRegisterNameTransactionRepository.java
similarity index 100%
rename from src/repository/hsqldb/transaction/HSQLDBRegisterNameTransactionRepository.java
rename to src/main/java/repository/hsqldb/transaction/HSQLDBRegisterNameTransactionRepository.java
diff --git a/src/repository/hsqldb/transaction/HSQLDBSellNameTransactionRepository.java b/src/main/java/repository/hsqldb/transaction/HSQLDBSellNameTransactionRepository.java
similarity index 100%
rename from src/repository/hsqldb/transaction/HSQLDBSellNameTransactionRepository.java
rename to src/main/java/repository/hsqldb/transaction/HSQLDBSellNameTransactionRepository.java
diff --git a/src/repository/hsqldb/transaction/HSQLDBTransactionRepository.java b/src/main/java/repository/hsqldb/transaction/HSQLDBTransactionRepository.java
similarity index 100%
rename from src/repository/hsqldb/transaction/HSQLDBTransactionRepository.java
rename to src/main/java/repository/hsqldb/transaction/HSQLDBTransactionRepository.java
diff --git a/src/repository/hsqldb/transaction/HSQLDBTransferAssetTransactionRepository.java b/src/main/java/repository/hsqldb/transaction/HSQLDBTransferAssetTransactionRepository.java
similarity index 100%
rename from src/repository/hsqldb/transaction/HSQLDBTransferAssetTransactionRepository.java
rename to src/main/java/repository/hsqldb/transaction/HSQLDBTransferAssetTransactionRepository.java
diff --git a/src/repository/hsqldb/transaction/HSQLDBUpdateNameTransactionRepository.java b/src/main/java/repository/hsqldb/transaction/HSQLDBUpdateNameTransactionRepository.java
similarity index 100%
rename from src/repository/hsqldb/transaction/HSQLDBUpdateNameTransactionRepository.java
rename to src/main/java/repository/hsqldb/transaction/HSQLDBUpdateNameTransactionRepository.java
diff --git a/src/repository/hsqldb/transaction/HSQLDBVoteOnPollTransactionRepository.java b/src/main/java/repository/hsqldb/transaction/HSQLDBVoteOnPollTransactionRepository.java
similarity index 100%
rename from src/repository/hsqldb/transaction/HSQLDBVoteOnPollTransactionRepository.java
rename to src/main/java/repository/hsqldb/transaction/HSQLDBVoteOnPollTransactionRepository.java
diff --git a/src/settings/Settings.java b/src/main/java/settings/Settings.java
similarity index 89%
rename from src/settings/Settings.java
rename to src/main/java/settings/Settings.java
index 63cb4f14..e9d75541 100644
--- a/src/settings/Settings.java
+++ b/src/main/java/settings/Settings.java
@@ -33,12 +33,6 @@ public class Settings {
private List rpcAllowed = new ArrayList(Arrays.asList("127.0.0.1", "::1")); // ipv4, ipv6
private boolean rpcEnabled = true;
- // Globalization
- private String translationsPath = "globalization/";
- private String[] translationsDefaultLocales = {
- "en"
- };
-
// Constants
private static final String SETTINGS_FILENAME = "settings.json";
@@ -122,19 +116,20 @@ public class Settings {
if (json.containsKey("rpcallowed")) {
JSONArray allowedArray = (JSONArray) json.get("rpcallowed");
- this.rpcAllowed = new ArrayList(allowedArray);
+
+ this.rpcAllowed = new ArrayList();
+
+ for (Object entry : allowedArray) {
+ if (!(entry instanceof String))
+ throw new RuntimeException("Entry inside 'rpcallowed' is not string");
+
+ this.rpcAllowed.add((String) entry);
+ }
}
if (json.containsKey("rpcenabled"))
this.rpcEnabled = ((Boolean) json.get("rpcenabled")).booleanValue();
- // Globalization
- if (json.containsKey("translationspath"))
- this.translationsPath = ((String) json.get("translationspath"));
-
- if (json.containsKey("translationsdefaultlocales"))
- this.translationsDefaultLocales = ((String[]) json.get("translationsdefaultlocales"));
-
if (json.containsKey("blockchainConfig")) {
String filename = (String) json.get("blockchainConfig");
File file = new File(this.userpath + filename);
@@ -173,14 +168,6 @@ public class Settings {
return this.rpcEnabled;
}
- public String translationsPath() {
- return this.translationsPath;
- }
-
- public String[] translationsDefaultLocales() {
- return this.translationsDefaultLocales;
- }
-
public boolean useBitcoinTestNet() {
return this.useBitcoinTestNet;
}
diff --git a/src/transform/PaymentTransformer.java b/src/main/java/transform/PaymentTransformer.java
similarity index 100%
rename from src/transform/PaymentTransformer.java
rename to src/main/java/transform/PaymentTransformer.java
diff --git a/src/transform/TransformationException.java b/src/main/java/transform/TransformationException.java
similarity index 100%
rename from src/transform/TransformationException.java
rename to src/main/java/transform/TransformationException.java
diff --git a/src/transform/Transformer.java b/src/main/java/transform/Transformer.java
similarity index 100%
rename from src/transform/Transformer.java
rename to src/main/java/transform/Transformer.java
diff --git a/src/transform/block/BlockTransformer.java b/src/main/java/transform/block/BlockTransformer.java
similarity index 100%
rename from src/transform/block/BlockTransformer.java
rename to src/main/java/transform/block/BlockTransformer.java
diff --git a/src/transform/transaction/ATTransactionTransformer.java b/src/main/java/transform/transaction/ATTransactionTransformer.java
similarity index 100%
rename from src/transform/transaction/ATTransactionTransformer.java
rename to src/main/java/transform/transaction/ATTransactionTransformer.java
diff --git a/src/transform/transaction/ArbitraryTransactionTransformer.java b/src/main/java/transform/transaction/ArbitraryTransactionTransformer.java
similarity index 100%
rename from src/transform/transaction/ArbitraryTransactionTransformer.java
rename to src/main/java/transform/transaction/ArbitraryTransactionTransformer.java
diff --git a/src/transform/transaction/BuyNameTransactionTransformer.java b/src/main/java/transform/transaction/BuyNameTransactionTransformer.java
similarity index 100%
rename from src/transform/transaction/BuyNameTransactionTransformer.java
rename to src/main/java/transform/transaction/BuyNameTransactionTransformer.java
diff --git a/src/transform/transaction/CancelOrderTransactionTransformer.java b/src/main/java/transform/transaction/CancelOrderTransactionTransformer.java
similarity index 100%
rename from src/transform/transaction/CancelOrderTransactionTransformer.java
rename to src/main/java/transform/transaction/CancelOrderTransactionTransformer.java
diff --git a/src/transform/transaction/CancelSellNameTransactionTransformer.java b/src/main/java/transform/transaction/CancelSellNameTransactionTransformer.java
similarity index 100%
rename from src/transform/transaction/CancelSellNameTransactionTransformer.java
rename to src/main/java/transform/transaction/CancelSellNameTransactionTransformer.java
diff --git a/src/transform/transaction/CreateOrderTransactionTransformer.java b/src/main/java/transform/transaction/CreateOrderTransactionTransformer.java
similarity index 100%
rename from src/transform/transaction/CreateOrderTransactionTransformer.java
rename to src/main/java/transform/transaction/CreateOrderTransactionTransformer.java
diff --git a/src/transform/transaction/CreatePollTransactionTransformer.java b/src/main/java/transform/transaction/CreatePollTransactionTransformer.java
similarity index 100%
rename from src/transform/transaction/CreatePollTransactionTransformer.java
rename to src/main/java/transform/transaction/CreatePollTransactionTransformer.java
diff --git a/src/transform/transaction/DeployATTransactionTransformer.java b/src/main/java/transform/transaction/DeployATTransactionTransformer.java
similarity index 100%
rename from src/transform/transaction/DeployATTransactionTransformer.java
rename to src/main/java/transform/transaction/DeployATTransactionTransformer.java
diff --git a/src/transform/transaction/GenesisTransactionTransformer.java b/src/main/java/transform/transaction/GenesisTransactionTransformer.java
similarity index 100%
rename from src/transform/transaction/GenesisTransactionTransformer.java
rename to src/main/java/transform/transaction/GenesisTransactionTransformer.java
diff --git a/src/transform/transaction/IssueAssetTransactionTransformer.java b/src/main/java/transform/transaction/IssueAssetTransactionTransformer.java
similarity index 100%
rename from src/transform/transaction/IssueAssetTransactionTransformer.java
rename to src/main/java/transform/transaction/IssueAssetTransactionTransformer.java
diff --git a/src/transform/transaction/MessageTransactionTransformer.java b/src/main/java/transform/transaction/MessageTransactionTransformer.java
similarity index 100%
rename from src/transform/transaction/MessageTransactionTransformer.java
rename to src/main/java/transform/transaction/MessageTransactionTransformer.java
diff --git a/src/transform/transaction/MultiPaymentTransactionTransformer.java b/src/main/java/transform/transaction/MultiPaymentTransactionTransformer.java
similarity index 100%
rename from src/transform/transaction/MultiPaymentTransactionTransformer.java
rename to src/main/java/transform/transaction/MultiPaymentTransactionTransformer.java
diff --git a/src/transform/transaction/PaymentTransactionTransformer.java b/src/main/java/transform/transaction/PaymentTransactionTransformer.java
similarity index 100%
rename from src/transform/transaction/PaymentTransactionTransformer.java
rename to src/main/java/transform/transaction/PaymentTransactionTransformer.java
diff --git a/src/transform/transaction/RegisterNameTransactionTransformer.java b/src/main/java/transform/transaction/RegisterNameTransactionTransformer.java
similarity index 100%
rename from src/transform/transaction/RegisterNameTransactionTransformer.java
rename to src/main/java/transform/transaction/RegisterNameTransactionTransformer.java
diff --git a/src/transform/transaction/SellNameTransactionTransformer.java b/src/main/java/transform/transaction/SellNameTransactionTransformer.java
similarity index 100%
rename from src/transform/transaction/SellNameTransactionTransformer.java
rename to src/main/java/transform/transaction/SellNameTransactionTransformer.java
diff --git a/src/transform/transaction/TransactionTransformer.java b/src/main/java/transform/transaction/TransactionTransformer.java
similarity index 100%
rename from src/transform/transaction/TransactionTransformer.java
rename to src/main/java/transform/transaction/TransactionTransformer.java
diff --git a/src/transform/transaction/TransferAssetTransactionTransformer.java b/src/main/java/transform/transaction/TransferAssetTransactionTransformer.java
similarity index 100%
rename from src/transform/transaction/TransferAssetTransactionTransformer.java
rename to src/main/java/transform/transaction/TransferAssetTransactionTransformer.java
diff --git a/src/transform/transaction/UpdateNameTransactionTransformer.java b/src/main/java/transform/transaction/UpdateNameTransactionTransformer.java
similarity index 100%
rename from src/transform/transaction/UpdateNameTransactionTransformer.java
rename to src/main/java/transform/transaction/UpdateNameTransactionTransformer.java
diff --git a/src/transform/transaction/VoteOnPollTransactionTransformer.java b/src/main/java/transform/transaction/VoteOnPollTransactionTransformer.java
similarity index 100%
rename from src/transform/transaction/VoteOnPollTransactionTransformer.java
rename to src/main/java/transform/transaction/VoteOnPollTransactionTransformer.java
diff --git a/src/txhex.java b/src/main/java/txhex.java
similarity index 100%
rename from src/txhex.java
rename to src/main/java/txhex.java
diff --git a/src/utils/BIP39.java b/src/main/java/utils/BIP39.java
similarity index 93%
rename from src/utils/BIP39.java
rename to src/main/java/utils/BIP39.java
index 6fbb8dfc..622f913c 100644
--- a/src/utils/BIP39.java
+++ b/src/main/java/utils/BIP39.java
@@ -14,7 +14,7 @@ public class BIP39 {
if (lang == null)
lang = "en";
- List wordList = BIP39WordList.getInstance().getByLang(lang);
+ List wordList = BIP39WordList.INSTANCE.getByLang(lang);
if (wordList == null)
throw new IllegalStateException("BIP39 word list for lang '" + lang + "' unavailable");
@@ -53,7 +53,7 @@ public class BIP39 {
if (lang == null)
lang = "en";
- List wordList = BIP39WordList.getInstance().getByLang(lang);
+ List wordList = BIP39WordList.INSTANCE.getByLang(lang);
if (wordList == null)
throw new IllegalStateException("BIP39 word list for lang '" + lang + "' unavailable");
diff --git a/src/utils/Base58.java b/src/main/java/utils/Base58.java
similarity index 100%
rename from src/utils/Base58.java
rename to src/main/java/utils/Base58.java
diff --git a/src/utils/NTP.java b/src/main/java/utils/NTP.java
similarity index 100%
rename from src/utils/NTP.java
rename to src/main/java/utils/NTP.java
diff --git a/src/utils/Pair.java b/src/main/java/utils/Pair.java
similarity index 100%
rename from src/utils/Pair.java
rename to src/main/java/utils/Pair.java
diff --git a/src/utils/Serialization.java b/src/main/java/utils/Serialization.java
similarity index 100%
rename from src/utils/Serialization.java
rename to src/main/java/utils/Serialization.java
diff --git a/src/utils/Triple.java b/src/main/java/utils/Triple.java
similarity index 100%
rename from src/utils/Triple.java
rename to src/main/java/utils/Triple.java
diff --git a/src/v1feeder.java b/src/main/java/v1feeder.java
similarity index 100%
rename from src/v1feeder.java
rename to src/main/java/v1feeder.java
diff --git a/globalization/BIP39.en.txt b/src/main/resources/BIP39/wordlist_en.txt
similarity index 100%
rename from globalization/BIP39.en.txt
rename to src/main/resources/BIP39/wordlist_en.txt
diff --git a/block-explorer.html b/src/main/resources/block-explorer.html
similarity index 100%
rename from block-explorer.html
rename to src/main/resources/block-explorer.html
diff --git a/globalization/BlocksResource.de.xml b/src/main/resources/globalization/BlocksResource.de.xml
similarity index 100%
rename from globalization/BlocksResource.de.xml
rename to src/main/resources/globalization/BlocksResource.de.xml
diff --git a/globalization/BlocksResource.en.xml b/src/main/resources/globalization/BlocksResource.en.xml
similarity index 100%
rename from globalization/BlocksResource.en.xml
rename to src/main/resources/globalization/BlocksResource.en.xml
diff --git a/src/main/resources/i18n/ApiError_de.properties b/src/main/resources/i18n/ApiError_de.properties
new file mode 100644
index 00000000..84b9f00d
--- /dev/null
+++ b/src/main/resources/i18n/ApiError_de.properties
@@ -0,0 +1,72 @@
+UNKNOWN=Unbekannter Fehler
+JSON=JSON Nachricht konnte nicht geparsed werden
+NO_BALANCE=Guthaben ungenügend
+NOT_YET_RELEASED=Feature wurde noch nicht veröffentlicht
+INVALID_SIGNATURE=Ungültige Signatur
+INVALID_ADDRESS=Ungültige Adresse
+INVALID_SEED=Ungültiger Seed
+INVALID_AMOUNT=Ungültiger Betrag
+INVALID_FEE=Ungültige Gebühr
+INVALID_SENDER=Ungültiger Sender
+INVALID_RECIPIENT=Ungültiger Empfänger
+INVALID_NAME_LENGTH=Ungültige Namenslänge
+INVALID_VALUE_LENGTH=Ungültige Wertlänge
+INVALID_NAME_OWNER=Ungültiger Namensbesitzer
+INVALID_BUYER=Ungültiger Käufer
+INVALID_PUBLIC_KEY=Ungültiger Public Key
+INVALID_OPTIONS_LENGTH=Ungültige Optionen-Länge
+INVALID_OPTION_LENGTH=Ungültige Optionslänge
+INVALID_DATA=Ungültige Daten
+INVALID_DATA_LENGTH=Ungültige Datenlänge
+INVALID_UPDATE_VALUE=Ungültiger Update-Wert
+KEY_ALREADY_EXISTS=Der Schlüssel existiert bereits, Editieren ist deaktiviert
+KEY_NOT_EXISTS=Der Schlüssel existiert nicht
+LAST_KEY_IS_DEFAULT_KEY_ERROR=Du kannst den Schlüssel '${key}' nicht löschen, wenn er der einzige ist
+FEE_LESS_REQUIRED=fee less required
+WALLET_NOT_IN_SYNC=Das Wallet muss synchronisiert werden
+INVALID_NETWORK_ADDRESS=Ungültige Netzwerkadresse
+WALLET_NO_EXISTS=Das Wallet existiert nicht
+WALLET_ADDRESS_NO_EXISTS=Die Adresse existiert nicht im Wallet
+WALLET_LOCKED=Das Wallet ist abgeschlossen
+WALLET_ALREADY_EXISTS=Das Wallet existiert bereits
+WALLET_API_CALL_FORBIDDEN_BY_USER=Der Benutzer hat den API-Aufruf abgelehnt
+BLOCK_NO_EXISTS=Der Block existiert nicht
+TRANSACTION_NO_EXISTS=Die Transaktion existiert nicht
+PUBLIC_KEY_NOT_FOUND=Public Key wurde nicht gefunden
+NAME_NO_EXISTS=Der Name existiert nicht
+NAME_ALREADY_EXISTS=Der Name existiert bereits
+NAME_ALREADY_FOR_SALE=Der Name steht bereits zum Verkauf
+NAME_NOT_LOWER_CASE=Der Name muss aus Kleinbuchstaben bestehen
+NAME_SALE_NO_EXISTS=Namensverkauf existiert nicht
+BUYER_ALREADY_OWNER=Der Käufer ist bereits Besitzer
+POLL_NO_EXISTS=Die Abstimmung existiert nicht
+POLL_ALREADY_EXISTS=Die Abstimmung existiert bereits
+DUPLICATE_OPTION=Nicht alle Optionen sind eindeutig
+POLL_OPTION_NO_EXISTS=Die option existiert nicht
+ALREADY_VOTED_FOR_THAT_OPTION=Bereits für diese Option abgestimmt
+INVALID_ASSET_ID=Ungültige Asset ID
+NAME_NOT_REGISTERED=?NAME_NOT_REGISTERED?
+NAME_FOR_SALE=?NAME_FOR_SALE?
+NAME_WITH_SPACE=?NAME_WITH_SPACE?
+INVALID_DESC_LENGTH=Ungültige Beschreibungslänge. Max. Länge ${MAX_LENGTH}
+EMPTY_CODE=Der Code ist leer
+DATA_SIZE=Ungültige Datenlänge
+NULL_PAGES=Ungültige Seiten
+INVALID_TYPE_LENGTH=Ungültige Typlänge
+INVALID_TAGS_LENGTH=Ungültige Tag-Länge
+INVALID_CREATION_BYTES=Fehler in Creation Bytes
+BODY_EMPTY=invalid body it must not be empty
+BLOG_DISABLED=Dieser Blog ist deaktiviert
+NAME_NOT_OWNER=the creator address does not own the author name
+TX_AMOUNT=the data size is too large - currently only ${BATCH_TX_AMOUNT} arbitrary transactions are allowed at once!
+BLOG_ENTRY_NO_EXISTS=transaction with this signature contains no entries!
+BLOG_EMPTY=this blog is empty
+POSTID_EMPTY=the attribute postid is empty! this is the signature of the post you want to comment
+POST_NOT_EXISTING=for the given postid no blogpost to comment was found
+COMMENTING_DISABLED=commenting is for this blog disabled
+COMMENT_NOT_EXISTING=for the given signature no comment was found
+INVALID_COMMENT_OWNER=invalid comment owner
+MESSAGE_FORMAT_NOT_HEX=the Message format is not hex - correct the text or use isTextMessage = true
+MESSAGE_BLANK=The message attribute is missing or content is blank
+NO_PUBLIC_KEY=The recipient has not yet performed any action in the blockchain.\nYou can't send an encrypted message to him.
+MESSAGESIZE_EXCEEDED=Message size exceeded!
diff --git a/src/main/resources/i18n/ApiError_en.properties b/src/main/resources/i18n/ApiError_en.properties
new file mode 100644
index 00000000..5a8c0c3c
--- /dev/null
+++ b/src/main/resources/i18n/ApiError_en.properties
@@ -0,0 +1,95 @@
+# Keys are from api.ApiError enum
+
+# Common
+UNKNOWN=unknown error
+JSON=failed to parse json message
+NO_BALANCE=not enough balance
+NOT_YET_RELEASED=that feature is not yet released
+UNAUTHORIZED=api call unauthorized
+REPOSITORY_ISSUE=repository error
+
+# Validation
+INVALID_SIGNATURE=invalid signature
+INVALID_ADDRESS=invalid address
+INVALID_SEED=invalid seed
+INVALID_AMOUNT=invalid amount
+INVALID_FEE=invalid fee
+INVALID_SENDER=invalid sender
+INVALID_RECIPIENT=invalid recipient
+INVALID_NAME_LENGTH=invalid name length
+INVALID_VALUE_LENGTH=invalid value length
+INVALID_NAME_OWNER=invalid name owner
+INVALID_BUYER=invalid buyer
+INVALID_PUBLIC_KEY=invalid public key
+INVALID_OPTIONS_LENGTH=invalid options length
+INVALID_OPTION_LENGTH=invalid option length
+INVALID_DATA=invalid data
+INVALID_DATA_LENGTH=invalid data length
+INVALID_UPDATE_VALUE=invalid update value
+KEY_ALREADY_EXISTS=key already exists, edit is false
+KEY_NOT_EXISTS=the key does not exist
+FEE_LESS_REQUIRED=fee less required
+WALLET_NOT_IN_SYNC=wallet needs to be synchronized
+INVALID_NETWORK_ADDRESS=invalid network address
+ADDRESS_NO_EXISTS=account address does not exist
+INVALID_CRITERIA=invalid search criteria
+
+# Wallet
+WALLET_NO_EXISTS=wallet does not exist
+WALLET_ADDRESS_NO_EXISTS=address does not exist in wallet
+WALLET_LOCKED=wallet is locked
+WALLET_ALREADY_EXISTS=wallet already exists
+WALLET_API_CALL_FORBIDDEN_BY_USER=wallet denied api call
+
+# Blocks
+BLOCK_NO_EXISTS=block does not exist
+
+# Transactions
+TRANSACTION_NO_EXISTS=transaction does not exist
+PUBLIC_KEY_NOT_FOUND=public key not found
+
+# Names
+NAME_NO_EXISTS=name does not exist
+NAME_ALREADY_EXISTS=name already exists
+NAME_ALREADY_FOR_SALE=name already for sale
+NAME_NOT_LOWER_CASE=name must be lower case
+NAME_SALE_NO_EXISTS=namesale does not exist
+BUYER_ALREADY_OWNER=buyer is already owner
+
+# Voting
+POLL_NO_EXISTS=poll does not exist
+POLL_ALREADY_EXISTS=poll already exists
+DUPLICATE_OPTION=not all options are unique
+POLL_OPTION_NO_EXISTS=option does not exist
+ALREADY_VOTED_FOR_THAT_OPTION=already voted for that option
+
+# Assets
+INVALID_ASSET_ID=invalid asset id
+INVALID_ORDER_ID=invalid asset order id
+ORDER_NO_EXISTS=unknown asset order id
+
+# ATs
+EMPTY_CODE=code is empty
+DATA_SIZE=invalid data length
+NULL_PAGES=invalid pages
+INVALID_TYPE_LENGTH=invalid type length
+INVALID_TAGS_LENGTH=invalid tags length
+INVALID_CREATION_BYTES=error in creation bytes
+
+# Blogs/Name-storage
+BODY_EMPTY=invalid body it must not be empty
+BLOG_DISABLED=this blog is disabled
+NAME_NOT_OWNER=the creator address does not own the author name
+BLOG_ENTRY_NO_EXISTS=transaction with this signature contains no entries!
+BLOG_EMPTY=this blog is empty
+POSTID_EMPTY=the attribute postid is empty! this is the signature of the post you want to comment
+POST_NOT_EXISTING=for the given postid no blogpost to comment was found
+COMMENTING_DISABLED=commenting is for this blog disabled
+COMMENT_NOT_EXISTING=for the given signature no comment was found
+INVALID_COMMENT_OWNER=invalid comment owner
+
+# Messages
+MESSAGE_FORMAT_NOT_HEX=the Message format is not hex - correct the text or use isTextMessage = true
+MESSAGE_BLANK=The message attribute is missing or content is blank
+NO_PUBLIC_KEY=The recipient has not yet performed any action in the blockchain.\nYou can't send an encrypted message to them.
+MESSAGESIZE_EXCEEDED=Message size exceeded!
diff --git a/src/main/resources/i18n/TransactionValidity_en.properties b/src/main/resources/i18n/TransactionValidity_en.properties
new file mode 100644
index 00000000..8f16b499
--- /dev/null
+++ b/src/main/resources/i18n/TransactionValidity_en.properties
@@ -0,0 +1,42 @@
+OK=OK
+INVALID_ADDRESS=INVALID_ADDRESS
+NEGATIVE_AMOUNT=NEGATIVE_AMOUNT
+NEGATIVE_FEE=NEGATIVE_FEE
+NO_BALANCE=NO_BALANCE
+INVALID_REFERENCE=INVALID_REFERENCE
+INVALID_NAME_LENGTH=INVALID_NAME_LENGTH
+INVALID_VALUE_LENGTH=INVALID_VALUE_LENGTH
+NAME_ALREADY_REGISTERED=NAME_ALREADY_REGISTERED
+NAME_DOES_NOT_EXIST=NAME_DOES_NOT_EXIST
+INVALID_NAME_OWNER=INVALID_NAME_OWNER
+NAME_ALREADY_FOR_SALE=NAME_ALREADY_FOR_SALE
+NAME_NOT_FOR_SALE=NAME_NOT_FOR_SALE
+BUYER_ALREADY_OWNER=BUYER_ALREADY_OWNER
+INVALID_AMOUNT=INVALID_AMOUNT
+INVALID_SELLER=INVALID_SELLER
+NAME_NOT_LOWER_CASE=NAME_NOT_LOWER_CASE
+INVALID_DESCRIPTION_LENGTH=INVALID_DESCRIPTION_LENGTH
+INVALID_OPTIONS_COUNT=INVALID_OPTIONS_COUNT
+INVALID_OPTION_LENGTH=INVALID_OPTION_LENGTH
+DUPLICATE_OPTION=DUPLICATE_OPTION
+POLL_ALREADY_EXISTS=POLL_ALREADY_EXISTS
+POLL_DOES_NOT_EXIST=POLL_DOES_NOT_EXIST
+POLL_OPTION_DOES_NOT_EXIST=POLL_OPTION_DOES_NOT_EXIST
+ALREADY_VOTED_FOR_THAT_OPTION=ALREADY_VOTED_FOR_THAT_OPTION
+INVALID_DATA_LENGTH=INVALID_DATA_LENGTH
+INVALID_QUANTITY=INVALID_QUANTITY
+ASSET_DOES_NOT_EXIST=ASSET_DOES_NOT_EXIST
+INVALID_RETURN=INVALID_RETURN
+HAVE_EQUALS_WANT=HAVE_EQUALS_WANT
+ORDER_DOES_NOT_EXIST=ORDER_DOES_NOT_EXIST
+INVALID_ORDER_CREATOR=INVALID_ORDER_CREATOR
+INVALID_PAYMENTS_COUNT=INVALID_PAYMENTS_COUNT
+NEGATIVE_PRICE=NEGATIVE_PRICE
+INVALID_CREATION_BYTES=INVALID_CREATION_BYTES
+INVALID_TAGS_LENGTH=INVALID_TAGS_LENGTH
+INVALID_AT_TYPE_LENGTH=INVALID_AT_TYPE_LENGTH
+INVALID_AT_TRANSACTION=INVALID_AT_TRANSACTION
+AT_IS_FINISHED=AT_IS_FINISHED
+ASSET_DOES_NOT_MATCH_AT=ASSET_DOES_NOT_MATCH_AT
+ASSET_ALREADY_EXISTS=ASSET_ALREADY_EXISTS
+NOT_YET_RELEASED=NOT_YET_RELEASED
diff --git a/tests/test/ATTests.java b/src/test/java/test/ATTests.java
similarity index 100%
rename from tests/test/ATTests.java
rename to src/test/java/test/ATTests.java
diff --git a/tests/test/BTCACCTTests.java b/src/test/java/test/BTCACCTTests.java
similarity index 99%
rename from tests/test/BTCACCTTests.java
rename to src/test/java/test/BTCACCTTests.java
index 881bcc26..ac1a6a96 100644
--- a/tests/test/BTCACCTTests.java
+++ b/src/test/java/test/BTCACCTTests.java
@@ -22,7 +22,6 @@ import org.bitcoinj.core.TransactionInput;
import org.bitcoinj.core.TransactionOutPoint;
import org.bitcoinj.crypto.TransactionSignature;
import org.bitcoinj.kits.WalletAppKit;
-import org.bitcoinj.params.RegTestParams;
import org.bitcoinj.params.TestNet3Params;
import org.bitcoinj.script.Script;
import org.bitcoinj.script.ScriptBuilder;
diff --git a/tests/test/BTCTests.java b/src/test/java/test/BTCTests.java
similarity index 100%
rename from tests/test/BTCTests.java
rename to src/test/java/test/BTCTests.java
diff --git a/tests/test/BlockTests.java b/src/test/java/test/BlockTests.java
similarity index 100%
rename from tests/test/BlockTests.java
rename to src/test/java/test/BlockTests.java
diff --git a/tests/test/BlockchainTests.java b/src/test/java/test/BlockchainTests.java
similarity index 100%
rename from tests/test/BlockchainTests.java
rename to src/test/java/test/BlockchainTests.java
diff --git a/tests/test/Common.java b/src/test/java/test/Common.java
similarity index 100%
rename from tests/test/Common.java
rename to src/test/java/test/Common.java
diff --git a/tests/test/CompatibilityTests.java b/src/test/java/test/CompatibilityTests.java
similarity index 100%
rename from tests/test/CompatibilityTests.java
rename to src/test/java/test/CompatibilityTests.java
diff --git a/tests/test/CryptoTests.java b/src/test/java/test/CryptoTests.java
similarity index 100%
rename from tests/test/CryptoTests.java
rename to src/test/java/test/CryptoTests.java
diff --git a/tests/test/ExceptionTests.java b/src/test/java/test/ExceptionTests.java
similarity index 100%
rename from tests/test/ExceptionTests.java
rename to src/test/java/test/ExceptionTests.java
diff --git a/tests/test/GenesisTests.java b/src/test/java/test/GenesisTests.java
similarity index 100%
rename from tests/test/GenesisTests.java
rename to src/test/java/test/GenesisTests.java
diff --git a/tests/test/LoadTests.java b/src/test/java/test/LoadTests.java
similarity index 100%
rename from tests/test/LoadTests.java
rename to src/test/java/test/LoadTests.java
diff --git a/tests/test/NavigationTests.java b/src/test/java/test/NavigationTests.java
similarity index 100%
rename from tests/test/NavigationTests.java
rename to src/test/java/test/NavigationTests.java
diff --git a/tests/test/RepositoryTests.java b/src/test/java/test/RepositoryTests.java
similarity index 100%
rename from tests/test/RepositoryTests.java
rename to src/test/java/test/RepositoryTests.java
diff --git a/tests/test/SaveTests.java b/src/test/java/test/SaveTests.java
similarity index 100%
rename from tests/test/SaveTests.java
rename to src/test/java/test/SaveTests.java
diff --git a/tests/test/SerializationTests.java b/src/test/java/test/SerializationTests.java
similarity index 100%
rename from tests/test/SerializationTests.java
rename to src/test/java/test/SerializationTests.java
diff --git a/tests/test/SignatureTests.java b/src/test/java/test/SignatureTests.java
similarity index 100%
rename from tests/test/SignatureTests.java
rename to src/test/java/test/SignatureTests.java
diff --git a/tests/test/TransactionTests.java b/src/test/java/test/TransactionTests.java
similarity index 100%
rename from tests/test/TransactionTests.java
rename to src/test/java/test/TransactionTests.java
diff --git a/src/test/java/test/utils/AssertExtensions.java b/src/test/java/test/utils/AssertExtensions.java
new file mode 100644
index 00000000..f0d9b4c9
--- /dev/null
+++ b/src/test/java/test/utils/AssertExtensions.java
@@ -0,0 +1,18 @@
+package test.utils;
+
+import java.util.Collection;
+
+import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+public class AssertExtensions {
+
+ public static void assertItemsEqual(Collection expected, Iterable actual) {
+ assertItemsEqual(expected, actual, (String) null);
+ }
+
+ public static void assertItemsEqual(Collection expected, Iterable actual, String message) {
+ assertThat(message, actual, containsInAnyOrder(expected.toArray()));
+ }
+
+}
diff --git a/tests/test/GlobalizationTests.java b/tests/test/GlobalizationTests.java
deleted file mode 100644
index 967cba08..00000000
--- a/tests/test/GlobalizationTests.java
+++ /dev/null
@@ -1,171 +0,0 @@
-package test;
-
-import globalization.TranslationEntry;
-import globalization.TranslationXmlStreamReader;
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-import java.nio.charset.Charset;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Locale;
-import javax.xml.stream.XMLStreamException;
-
-import org.junit.jupiter.api.Test;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-import static test.utils.AssertExtensions.*;
-import test.utils.EqualityComparer;
-
-public class GlobalizationTests {
-
- private class TranslationEntryEqualityComparer implements EqualityComparer {
-
- @Override
- public boolean equals(TranslationEntry first, TranslationEntry second) {
- if(first == null && second == null)
- return true;
- if(first == null && second != null || first != null && second == null)
- return false;
-
- if(!first.locale().equals(second.locale()))
- return false;
- if(!first.path().equals(second.path()))
- return false;
- if(!first.template().equals(second.template()))
- return false;
-
- return true;
- }
-
- @Override
- public int hashCode(TranslationEntry item) {
- int hash = 17;
- final int multiplier = 59;
-
- hash = hash * multiplier + item.locale().hashCode();
- hash = hash * multiplier + item.path().hashCode();
- hash = hash * multiplier + item.template().hashCode();
-
- return hash;
- }
-
- }
-
- @Test
- public void TestTranslationXmlReaderContextPaths() throws XMLStreamException {
- String xml =
- "\n" +
- "\n" +
- " \n" +
- " \n" +
- " \n" +
- " \n" +
- " \n" +
- " \n" +
- " \n" +
- " \n" +
- " \n" +
- " \n" +
- " \n" +
- "\n";
-
- List expected = new ArrayList<>();
- expected.add(new TranslationEntry(Locale.forLanguageTag("en-GB"), "/path1/key1", "1"));
- expected.add(new TranslationEntry(Locale.forLanguageTag("en-GB"), "/path1/path2/path3/key2", "2"));
- expected.add(new TranslationEntry(Locale.forLanguageTag("en-GB"), "/path1/path4/key3", "3"));
-
- InputStream is = new ByteArrayInputStream(xml.getBytes(Charset.forName("UTF-8")));
- TranslationXmlStreamReader reader = new TranslationXmlStreamReader();
- Iterable actual = reader.ReadFrom(is);
-
- for(TranslationEntry i:expected)System.out.println(i);for(TranslationEntry i:actual)System.out.println(i);
- assertItemsEqual(expected, actual, new TranslationEntryEqualityComparer());
- }
-
- @Test
- public void TestTranslationXmlReaderLocales() throws XMLStreamException {
- String xml =
- "\n" +
- "\n" +
- " \n" +
- " \n" +
- " \n" +
- " \n" +
- " \n" +
- " \n" +
- " \n" +
- "\n";
-
- List expected = new ArrayList();
- expected.add(new TranslationEntry(Locale.forLanguageTag("default"), "/key1", "1"));
- expected.add(new TranslationEntry(Locale.forLanguageTag("en-GB"), "/path1/key2", "2"));
- expected.add(new TranslationEntry(Locale.forLanguageTag("de-DE"), "/path1/path2/key3", "3"));
-
- InputStream is = new ByteArrayInputStream(xml.getBytes(Charset.forName("UTF-8")));
- TranslationXmlStreamReader reader = new TranslationXmlStreamReader();
- Iterable actual = reader.ReadFrom(is);
-
- assertItemsEqual(expected, actual, new TranslationEntryEqualityComparer());
- }
-
- @Test
- public void TestTranslationXmlReader_BadPath() {
- String xml =
- "\n" +
- "\n" +
- " \n" +
- " \n" +
- " \n" +
- " \n" +
- " \n" +
- " \n" +
- " \n" +
- "\n";
-
- InputStream is = new ByteArrayInputStream(xml.getBytes(Charset.forName("UTF-8")));
- TranslationXmlStreamReader reader = new TranslationXmlStreamReader();
-
- assertThrows(XMLStreamException.class, () -> reader.ReadFrom(is));
- }
-
- @Test
- public void TestTranslationXmlReader_BadKey1() {
- String xml =
- "\n" +
- "\n" +
- " \n" +
- " \n" +
- " \n" +
- " \n" +
- " \n" +
- " \n" +
- " \n" +
- "\n";
-
- InputStream is = new ByteArrayInputStream(xml.getBytes(Charset.forName("UTF-8")));
- TranslationXmlStreamReader reader = new TranslationXmlStreamReader();
-
- assertThrows(XMLStreamException.class, () -> reader.ReadFrom(is));
- }
-
- @Test
- public void TestTranslationXmlReader_BadKey2() {
- String xml =
- "\n" +
- "\n" +
- " \n" +
- " \n" +
- " \n" +
- " \n" +
- " \n" +
- " \n" +
- " \n" +
- "\n";
-
- InputStream is = new ByteArrayInputStream(xml.getBytes(Charset.forName("UTF-8")));
- TranslationXmlStreamReader reader = new TranslationXmlStreamReader();
-
- assertThrows(XMLStreamException.class, () -> reader.ReadFrom(is));
- }
-}
diff --git a/tests/test/utils/AssertExtensions.java b/tests/test/utils/AssertExtensions.java
deleted file mode 100644
index fabce6a0..00000000
--- a/tests/test/utils/AssertExtensions.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package test.utils;
-
-import com.google.common.collect.Iterables;
-import java.lang.reflect.Array;
-import java.lang.Class;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder;
-import static org.hamcrest.MatcherAssert.assertThat;
-
-public class AssertExtensions {
-
- public static void assertItemsEqual(Collection expected, Iterable actual, EqualityComparer comparer) {
- assertItemsEqual(expected, actual, comparer, (String)null);
- }
-
- public static void assertItemsEqual(Collection expected, Iterable actual, EqualityComparer comparer, String message) {
- List> expectedSet = new ArrayList>();
- for(T item: expected)
- expectedSet.add(new EquatableWrapper(item, comparer));
-
- List> actualSet = new ArrayList>();
- for(T item: actual)
- actualSet.add(new EquatableWrapper(item, comparer));
-
- assertItemsEqual(expectedSet, actualSet, message);
- }
-
- public static void assertItemsEqual(Collection expected, Iterable actual) {
- assertItemsEqual(expected, actual, (String)null);
- }
-
- public static void assertItemsEqual(Collection expected, Iterable actual, String message) {
- List list = new ArrayList();
- T[] expectedArray = (T[])expected.toArray();
- assertThat(message, actual, containsInAnyOrder(expectedArray));
- }
-}
diff --git a/tests/test/utils/EqualityComparer.java b/tests/test/utils/EqualityComparer.java
deleted file mode 100644
index c560c9ce..00000000
--- a/tests/test/utils/EqualityComparer.java
+++ /dev/null
@@ -1,6 +0,0 @@
-package test.utils;
-
-public interface EqualityComparer {
- boolean equals(T first, T second);
- int hashCode(T item);
-}
diff --git a/tests/test/utils/EquatableWrapper.java b/tests/test/utils/EquatableWrapper.java
deleted file mode 100644
index b719cf32..00000000
--- a/tests/test/utils/EquatableWrapper.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package test.utils;
-
-class EquatableWrapper {
-
- private final T item;
- private final EqualityComparer comparer;
-
- public EquatableWrapper(T item, EqualityComparer comparer) {
- this.item = item;
- this.comparer = comparer;
- }
-
- @Override
- public boolean equals(Object obj) {
- if(obj == null)
- return false;
- if (!(this.getClass().isInstance(obj)))
- return false;
- EquatableWrapper otherWrapper = (EquatableWrapper)obj;
- if (otherWrapper.item == this.item)
- return true;
- return this.comparer.equals(this.item, otherWrapper.item);
- }
-
- @Override
- public int hashCode() {
- return this.comparer.hashCode(this.item);
- }
-
- @Override
- public String toString() {
- return this.item.toString();
- }
-}
\ No newline at end of file