diff --git a/block-explorer.html b/block-explorer.html
index f073e047..32ef6caa 100644
--- a/block-explorer.html
+++ b/block-explorer.html
@@ -88,7 +88,7 @@
document.body.innerHTML = html;
XHR({
- url: "/transactions/address/" + address,
+ url: "/transactions/search?address=" + address,
onload: renderAddressTransactions,
responseType: "json"
});
@@ -137,7 +137,7 @@
}
function renderBlockInfo(e) {
- var blockData = e.target.response;
+ var blockData = e.target.response.block;
// These properties are currently emitted as base64 by API but likely to be base58 in the future, so convert them
var props = [ "signature", "reference", "transactionsSignature", "generatorPublicKey", "generatorSignature" ];
@@ -196,7 +196,7 @@
}
function listBlock(e) {
- var blockData = e.target.response;
+ var blockData = e.target.response.block;
var ourHeight = blockData.height;
var blockTimestamp = new Date(blockData.timestamp).toUTCString();
diff --git a/src/api/AddressesResource.java b/src/api/AddressesResource.java
index f14d5480..7fdc768f 100644
--- a/src/api/AddressesResource.java
+++ b/src/api/AddressesResource.java
@@ -1,6 +1,5 @@
package api;
-import globalization.Translator;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.extensions.Extension;
@@ -45,16 +44,6 @@ public class AddressesResource {
@Context
HttpServletRequest request;
- private ApiErrorFactory apiErrorFactory;
-
- public AddressesResource() {
- this(new ApiErrorFactory(Translator.getInstance()));
- }
-
- public AddressesResource(ApiErrorFactory apiErrorFactory) {
- this.apiErrorFactory = apiErrorFactory;
- }
-
@GET
@Path("/lastreference/{address}")
@Operation(
@@ -72,7 +61,7 @@ public class AddressesResource {
responses = {
@ApiResponse(
description = "the base64-encoded transaction signature or \"false\"",
- content = @Content(schema = @Schema(implementation = String.class)),
+ content = @Content(mediaType = MediaType.TEXT_PLAIN, schema = @Schema(type = "string")),
extensions = {
@Extension(name = "translation", properties = {
@ExtensionProperty(name="description.key", value="success_response:description")
@@ -83,7 +72,7 @@ public class AddressesResource {
)
public String getLastReference(@Parameter(ref = "address") @PathParam("address") String address) {
if (!Crypto.isValidAddress(address))
- throw this.apiErrorFactory.createError(ApiError.INVALID_ADDRESS);
+ throw ApiErrorFactory.getInstance().createError(ApiError.INVALID_ADDRESS);
byte[] lastReference = null;
try (final Repository repository = RepositoryManager.getRepository()) {
@@ -92,7 +81,7 @@ public class AddressesResource {
} catch (ApiException e) {
throw e;
} catch (DataException e) {
- throw this.apiErrorFactory.createError(ApiError.REPOSITORY_ISSUE, e);
+ throw ApiErrorFactory.getInstance().createError(ApiError.REPOSITORY_ISSUE, e);
}
if(lastReference == null || lastReference.length == 0) {
@@ -119,7 +108,7 @@ public class AddressesResource {
responses = {
@ApiResponse(
description = "the base64-encoded transaction signature",
- content = @Content(schema = @Schema(implementation = String.class)),
+ content = @Content(mediaType = MediaType.TEXT_PLAIN, schema = @Schema(type = "string")),
extensions = {
@Extension(name = "translation", properties = {
@ExtensionProperty(name="description.key", value="success_response:description")
@@ -130,7 +119,7 @@ public class AddressesResource {
)
public String getLastReferenceUnconfirmed(@PathParam("address") String address) {
if (!Crypto.isValidAddress(address))
- throw this.apiErrorFactory.createError(ApiError.INVALID_ADDRESS);
+ throw ApiErrorFactory.getInstance().createError(ApiError.INVALID_ADDRESS);
byte[] lastReference = null;
try (final Repository repository = RepositoryManager.getRepository()) {
@@ -139,7 +128,7 @@ public class AddressesResource {
} catch (ApiException e) {
throw e;
} catch (DataException e) {
- throw this.apiErrorFactory.createError(ApiError.REPOSITORY_ISSUE, e);
+ throw ApiErrorFactory.getInstance().createError(ApiError.REPOSITORY_ISSUE, e);
}
if(lastReference == null || lastReference.length == 0) {
@@ -163,8 +152,7 @@ public class AddressesResource {
},
responses = {
@ApiResponse(
- //description = "",
- content = @Content(schema = @Schema(implementation = Boolean.class)),
+ content = @Content(mediaType = MediaType.TEXT_PLAIN, schema = @Schema(type = "boolean")),
extensions = {
@Extension(name = "translation", properties = {
@ExtensionProperty(name="description.key", value="success_response:description")
@@ -194,7 +182,7 @@ public class AddressesResource {
responses = {
@ApiResponse(
description = "the generating balance",
- content = @Content(schema = @Schema(implementation = BigDecimal.class)),
+ 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")
@@ -205,7 +193,7 @@ public class AddressesResource {
)
public BigDecimal getGeneratingBalanceOfAddress(@PathParam("address") String address) {
if (!Crypto.isValidAddress(address))
- throw this.apiErrorFactory.createError(ApiError.INVALID_ADDRESS);
+ throw ApiErrorFactory.getInstance().createError(ApiError.INVALID_ADDRESS);
try (final Repository repository = RepositoryManager.getRepository()) {
Account account = new Account(repository, address);
@@ -213,7 +201,7 @@ public class AddressesResource {
} catch (ApiException e) {
throw e;
} catch (DataException e) {
- throw this.apiErrorFactory.createError(ApiError.REPOSITORY_ISSUE, e);
+ throw ApiErrorFactory.getInstance().createError(ApiError.REPOSITORY_ISSUE, e);
}
}
@@ -233,7 +221,7 @@ public class AddressesResource {
responses = {
@ApiResponse(
description = "the balance",
- content = @Content(schema = @Schema(name = "balance", type = "number")),
+ 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")
@@ -244,7 +232,7 @@ public class AddressesResource {
)
public BigDecimal getGeneratingBalance(@PathParam("address") String address) {
if (!Crypto.isValidAddress(address))
- throw this.apiErrorFactory.createError(ApiError.INVALID_ADDRESS);
+ throw ApiErrorFactory.getInstance().createError(ApiError.INVALID_ADDRESS);
try (final Repository repository = RepositoryManager.getRepository()) {
Account account = new Account(repository, address);
@@ -252,7 +240,7 @@ public class AddressesResource {
} catch (ApiException e) {
throw e;
} catch (DataException e) {
- throw this.apiErrorFactory.createError(ApiError.REPOSITORY_ISSUE, e);
+ throw ApiErrorFactory.getInstance().createError(ApiError.REPOSITORY_ISSUE, e);
}
}
@@ -273,7 +261,7 @@ public class AddressesResource {
responses = {
@ApiResponse(
description = "the balance",
- content = @Content(schema = @Schema(implementation = BigDecimal.class)),
+ 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")
@@ -284,7 +272,7 @@ public class AddressesResource {
)
public BigDecimal getAssetBalance(@PathParam("assetid") long assetid, @PathParam("address") String address) {
if (!Crypto.isValidAddress(address))
- throw this.apiErrorFactory.createError(ApiError.INVALID_ADDRESS);
+ throw ApiErrorFactory.getInstance().createError(ApiError.INVALID_ADDRESS);
try (final Repository repository = RepositoryManager.getRepository()) {
Account account = new Account(repository, address);
@@ -292,7 +280,7 @@ public class AddressesResource {
} catch (ApiException e) {
throw e;
} catch (DataException e) {
- throw this.apiErrorFactory.createError(ApiError.REPOSITORY_ISSUE, e);
+ throw ApiErrorFactory.getInstance().createError(ApiError.REPOSITORY_ISSUE, e);
}
}
@@ -324,14 +312,14 @@ public class AddressesResource {
)
public List getAssets(@PathParam("address") String address) {
if (!Crypto.isValidAddress(address))
- throw this.apiErrorFactory.createError(ApiError.INVALID_ADDRESS);
+ throw ApiErrorFactory.getInstance().createError(ApiError.INVALID_ADDRESS);
try (final Repository repository = RepositoryManager.getRepository()) {
return repository.getAccountRepository().getAllBalances(address);
} catch (ApiException e) {
throw e;
} catch (DataException e) {
- throw this.apiErrorFactory.createError(ApiError.REPOSITORY_ISSUE, e);
+ throw ApiErrorFactory.getInstance().createError(ApiError.REPOSITORY_ISSUE, e);
}
}
@@ -381,7 +369,7 @@ public class AddressesResource {
responses = {
@ApiResponse(
description = "the public key",
- content = @Content(schema = @Schema(implementation = String.class)),
+ content = @Content(mediaType = MediaType.TEXT_PLAIN, schema = @Schema(type = "string")),
extensions = {
@Extension(name = "translation", properties = {
@ExtensionProperty(name="description.key", value="success_response:description")
@@ -392,7 +380,7 @@ public class AddressesResource {
)
public String getPublicKey(@PathParam("address") String address) {
if (!Crypto.isValidAddress(address))
- throw this.apiErrorFactory.createError(ApiError.INVALID_ADDRESS);
+ throw ApiErrorFactory.getInstance().createError(ApiError.INVALID_ADDRESS);
try (final Repository repository = RepositoryManager.getRepository()) {
AccountData accountData = repository.getAccountRepository().getAccount(address);
@@ -408,13 +396,12 @@ public class AddressesResource {
} catch (ApiException e) {
throw e;
} catch (DataException e) {
- throw this.apiErrorFactory.createError(ApiError.REPOSITORY_ISSUE, e);
+ throw ApiErrorFactory.getInstance().createError(ApiError.REPOSITORY_ISSUE, e);
}
}
@GET
@Path("/convert/{publickey}")
- @Produces(MediaType.TEXT_PLAIN)
@Operation(
summary = "Convert public key into address",
description = "Returns account address based on supplied public key. Expects base64-encoded, 32-byte public key.",
@@ -430,7 +417,7 @@ public class AddressesResource {
responses = {
@ApiResponse(
description = "the address",
- content = @Content(schema = @Schema(implementation = String.class)),
+ content = @Content(mediaType = MediaType.TEXT_PLAIN, schema = @Schema(type = "string")),
extensions = {
@Extension(name = "translation", properties = {
@ExtensionProperty(name="description.key", value="success_response:description")
@@ -445,19 +432,19 @@ public class AddressesResource {
try {
publicKeyBytes = Base64.getDecoder().decode(publicKey);
} catch (NumberFormatException e) {
- throw this.apiErrorFactory.createError(ApiError.INVALID_PUBLIC_KEY, e);
+ throw ApiErrorFactory.getInstance().createError(ApiError.INVALID_PUBLIC_KEY, e);
}
// Correct size for public key?
if (publicKeyBytes.length != Transformer.PUBLIC_KEY_LENGTH)
- throw this.apiErrorFactory.createError(ApiError.INVALID_PUBLIC_KEY);
+ throw ApiErrorFactory.getInstance().createError(ApiError.INVALID_PUBLIC_KEY);
try (final Repository repository = RepositoryManager.getRepository()) {
return Crypto.toAddress(publicKeyBytes);
} catch (ApiException e) {
throw e;
} catch (DataException e) {
- throw this.apiErrorFactory.createError(ApiError.REPOSITORY_ISSUE, e);
+ throw ApiErrorFactory.getInstance().createError(ApiError.REPOSITORY_ISSUE, e);
}
}
diff --git a/src/api/ApiError.java b/src/api/ApiError.java
index b29fe66d..a2b5ae2d 100644
--- a/src/api/ApiError.java
+++ b/src/api/ApiError.java
@@ -6,7 +6,7 @@ public enum ApiError {
JSON(1, 400),
NO_BALANCE(2, 422),
NOT_YET_RELEASED(3, 422),
- UNAUTHORIZED(4, 401),
+ UNAUTHORIZED(4, 403),
REPOSITORY_ISSUE(5, 500),
//VALIDATION
@@ -67,6 +67,8 @@ public enum ApiError {
//ASSET
INVALID_ASSET_ID(601, 400),
+ INVALID_ORDER_ID(602, 400),
+ ORDER_NO_EXISTS(603, 404),
//NAME PAYMENTS
NAME_NOT_REGISTERED(701, 422),
diff --git a/src/api/ApiErrorMessage.java b/src/api/ApiErrorMessage.java
index 0c84fe4a..161e1836 100644
--- a/src/api/ApiErrorMessage.java
+++ b/src/api/ApiErrorMessage.java
@@ -1,15 +1,14 @@
package api;
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
-@XmlRootElement
+// All properties to be converted to JSON via JAX-RS
+@XmlAccessorType(XmlAccessType.FIELD)
public class ApiErrorMessage {
- @XmlElement(name = "error")
public int error;
- @XmlElement(name = "message")
public String message;
ApiErrorMessage() {
diff --git a/src/api/AssetsResource.java b/src/api/AssetsResource.java
index 9f7cf111..1e0a2552 100644
--- a/src/api/AssetsResource.java
+++ b/src/api/AssetsResource.java
@@ -13,6 +13,7 @@ import repository.Repository;
import repository.RepositoryManager;
import java.util.ArrayList;
+import java.util.Base64;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
@@ -27,7 +28,9 @@ import javax.ws.rs.core.MediaType;
import api.models.AssetWithHolders;
import api.models.IssueAssetRequest;
+import api.models.OrderWithTrades;
import api.models.TradeWithOrderInfo;
+import data.account.AccountBalanceData;
import data.assets.AssetData;
import data.assets.OrderData;
import data.assets.TradeData;
@@ -78,7 +81,7 @@ public class AssetsResource {
)
}
)
- public AssetWithHolders getAssetInfo(@QueryParam("assetId") Integer assetId, @QueryParam("assetName") String assetName, @Parameter(ref = "includeHolders") @QueryParam("withHolders") boolean includeHolders) {
+ 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);
@@ -93,7 +96,11 @@ public class AssetsResource {
if (assetData == null)
throw ApiErrorFactory.getInstance().createError(ApiError.INVALID_ASSET_ID);
- return new AssetWithHolders(repository, assetData, includeHolders);
+ List holders = null;
+ if (includeHolders)
+ holders = repository.getAccountRepository().getAssetBalances(assetData.getAssetId());
+
+ return new AssetWithHolders(assetData, holders);
} catch (DataException e) {
throw ApiErrorFactory.getInstance().createError(ApiError.REPOSITORY_ISSUE, e);
}
@@ -165,8 +172,11 @@ public class AssetsResource {
// Expanding remaining entries
List fullTrades = new ArrayList<>();
- for (TradeData trade : trades)
- fullTrades.add(new TradeWithOrderInfo(repository, trade));
+ for (TradeData tradeData : trades) {
+ OrderData initiatingOrderData = repository.getAssetRepository().fromOrderId(tradeData.getInitiator());
+ OrderData targetOrderData = repository.getAssetRepository().fromOrderId(tradeData.getTarget());
+ fullTrades.add(new TradeWithOrderInfo(tradeData, initiatingOrderData, targetOrderData));
+ }
return fullTrades;
} catch (DataException e) {
@@ -174,6 +184,40 @@ public class AssetsResource {
}
}
+ @GET
+ @Path("/order/{orderId}")
+ @Operation(
+ summary = "Fetch asset order",
+ description = "Returns asset order info.",
+ responses = {
+ @ApiResponse(
+ description = "asset order",
+ content = @Content(schema = @Schema(implementation = OrderData.class))
+ )
+ }
+ )
+ public OrderWithTrades getAssetOrder(@PathParam("orderId") String orderId64) {
+ // Decode orderID
+ byte[] orderId;
+ try {
+ orderId = Base64.getDecoder().decode(orderId64);
+ } catch (NumberFormatException e) {
+ throw ApiErrorFactory.getInstance().createError(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);
+
+ List trades = repository.getAssetRepository().getOrdersTrades(orderId);
+
+ return new OrderWithTrades(orderData, trades);
+ } catch (DataException e) {
+ throw ApiErrorFactory.getInstance().createError(ApiError.REPOSITORY_ISSUE, e);
+ }
+ }
+
@POST
@Path("/issue")
@Operation(
diff --git a/src/api/BlocksResource.java b/src/api/BlocksResource.java
index 3b1d33cb..450adb1e 100644
--- a/src/api/BlocksResource.java
+++ b/src/api/BlocksResource.java
@@ -1,6 +1,7 @@
package api;
import data.block.BlockData;
+import data.transaction.TransactionData;
import globalization.Translator;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
@@ -15,6 +16,7 @@ import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
+import java.util.stream.Collectors;
import javax.servlet.http.HttpServletRequest;
@@ -33,11 +35,8 @@ import repository.Repository;
import repository.RepositoryManager;
@Path("blocks")
-@Produces({MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN})
-@Extension(name = "translation", properties = {
- @ExtensionProperty(name="path", value="/Api/BlocksResource")
- }
-)
+@Produces({ MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN })
+@Extension(name = "translation", properties = { @ExtensionProperty(name = "path", value = "/Api/BlocksResource") })
@Tag(name = "Blocks")
public class BlocksResource {
@@ -59,28 +58,23 @@ public class BlocksResource {
@Operation(
summary = "Fetch block using base64 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",
- content = @Content(schema = @Schema(implementation = BlockWithTransactions.class)),
- extensions = {
- @Extension(name = "translation", properties = {
- @ExtensionProperty(name="description.key", value="success_response:description")
- })
- }
- )
- }
+ 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",
+ content = @Content(schema = @Schema(implementation = BlockWithTransactions.class)),
+ extensions =
+ { @Extension(name = "translation", properties = { @ExtensionProperty(name = "description.key", value = "success_response:description") }) }
+ ) }
)
- public BlockWithTransactions getBlock(@PathParam("signature") String signature, @Parameter(ref = "includeTransactions") @QueryParam("includeTransactions") boolean includeTransactions) {
+ public BlockWithTransactions getBlock(@PathParam("signature") String signature,
+ @Parameter(ref = "includeTransactions") @QueryParam("includeTransactions") boolean includeTransactions) {
// Decode signature
byte[] signatureBytes;
try {
@@ -91,7 +85,7 @@ public class BlocksResource {
try (final Repository repository = RepositoryManager.getRepository()) {
BlockData blockData = repository.getBlockRepository().fromSignature(signatureBytes);
- return new BlockWithTransactions(repository, blockData, includeTransactions);
+ return packageBlockData(repository, blockData, includeTransactions);
} catch (ApiException e) {
throw e;
} catch (DataException e) {
@@ -104,26 +98,23 @@ 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",
- content = @Content(schema = @Schema(implementation = BlockWithTransactions.class)),
- extensions = {
- @Extension(name = "translation", properties = {
- @ExtensionProperty(name="description.key", value="success_response:description")
- })
- }
- )
- }
+ extensions = @Extension(
+ name = "translation",
+ properties =
+ { @ExtensionProperty(name = "path", value = "GET first"), @ExtensionProperty(name = "description.key", value = "operation:description") }
+ ),
+ responses =
+ { @ApiResponse(
+ description = "the block",
+ content = @Content(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) {
try (final Repository repository = RepositoryManager.getRepository()) {
BlockData blockData = repository.getBlockRepository().fromHeight(1);
- return new BlockWithTransactions(repository, blockData, includeTransactions);
+ return packageBlockData(repository, blockData, includeTransactions);
} catch (ApiException e) {
throw e;
} catch (DataException e) {
@@ -136,26 +127,23 @@ 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",
- content = @Content(schema = @Schema(implementation = BlockWithTransactions.class)),
- extensions = {
- @Extension(name = "translation", properties = {
- @ExtensionProperty(name="description.key", value="success_response:description")
- })
- }
- )
- }
+ extensions = @Extension(
+ name = "translation",
+ properties =
+ { @ExtensionProperty(name = "path", value = "GET last"), @ExtensionProperty(name = "description.key", value = "operation:description") }
+ ),
+ responses =
+ { @ApiResponse(
+ description = "the block",
+ content = @Content(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) {
try (final Repository repository = RepositoryManager.getRepository()) {
BlockData blockData = repository.getBlockRepository().getLastBlock();
- return new BlockWithTransactions(repository, blockData, includeTransactions);
+ return packageBlockData(repository, blockData, includeTransactions);
} catch (ApiException e) {
throw e;
} catch (DataException e) {
@@ -168,28 +156,23 @@ public class BlocksResource {
@Operation(
summary = "Fetch child block using base64 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",
- content = @Content(schema = @Schema(implementation = BlockWithTransactions.class)),
- extensions = {
- @Extension(name = "translation", properties = {
- @ExtensionProperty(name="description.key", value="success_response:description")
- })
- }
- )
- }
+ 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",
+ content = @Content(schema = @Schema(implementation = BlockWithTransactions.class)),
+ extensions =
+ { @Extension(name = "translation", properties = { @ExtensionProperty(name = "description.key", value = "success_response:description") }) }
+ ) }
)
- public BlockWithTransactions getChild(@PathParam("signature") String signature, @Parameter(ref = "includeTransactions") @QueryParam("includeTransactions") boolean includeTransactions) {
+ public BlockWithTransactions getChild(@PathParam("signature") String signature,
+ @Parameter(ref = "includeTransactions") @QueryParam("includeTransactions") boolean includeTransactions) {
// Decode signature
byte[] signatureBytes;
try {
@@ -202,16 +185,13 @@ public class BlocksResource {
BlockData blockData = repository.getBlockRepository().fromSignature(signatureBytes);
// Check block exists
- if(blockData == null)
+ if (blockData == null)
throw this.apiErrorFactory.createError(ApiError.BLOCK_NO_EXISTS);
BlockData childBlockData = repository.getBlockRepository().fromReference(signatureBytes);
- // Check child exists
- if(childBlockData == null)
- throw this.apiErrorFactory.createError(ApiError.BLOCK_NO_EXISTS);
-
- return new BlockWithTransactions(repository, childBlockData, includeTransactions);
+ // Checking child exists is handled by packageBlockData()
+ return packageBlockData(repository, childBlockData, includeTransactions);
} catch (ApiException e) {
throw e;
} catch (DataException e) {
@@ -224,21 +204,18 @@ 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",
- content = @Content(schema = @Schema(implementation = BigDecimal.class)),
- extensions = {
- @Extension(name = "translation", properties = {
- @ExtensionProperty(name="description.key", value="success_response:description")
- })
- }
- )
- }
+ extensions = @Extension(
+ name = "translation",
+ properties =
+ { @ExtensionProperty(name = "path", value = "GET generatingbalance"), @ExtensionProperty(name = "description.key", value = "operation:description") }
+ ),
+ responses =
+ { @ApiResponse(
+ description = "the generating balance",
+ content = @Content(schema = @Schema(implementation = BigDecimal.class)),
+ extensions =
+ { @Extension(name = "translation", properties = { @ExtensionProperty(name = "description.key", value = "success_response:description") }) }
+ ) }
)
public BigDecimal getGeneratingBalance() {
try (final Repository repository = RepositoryManager.getRepository()) {
@@ -257,26 +234,21 @@ 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",
- content = @Content(schema = @Schema(implementation = BigDecimal.class)),
- extensions = {
- @Extension(name = "translation", properties = {
- @ExtensionProperty(name="description.key", value="success_response:description")
- })
- }
- )
- }
+ 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",
+ content = @Content(schema = @Schema(implementation = BigDecimal.class)),
+ extensions =
+ { @Extension(name = "translation", properties = { @ExtensionProperty(name = "description.key", value = "success_response:description") }) }
+ ) }
)
public BigDecimal getGeneratingBalance(@PathParam("signature") String signature) {
// Decode signature
@@ -308,21 +280,18 @@ 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?
- content = @Content(schema = @Schema(implementation = long.class)),
- extensions = {
- @Extension(name = "translation", properties = {
- @ExtensionProperty(name="description.key", value="success_response:description")
- })
- }
- )
- }
+ 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?
+ content = @Content(schema = @Schema(implementation = long.class)),
+ extensions =
+ { @Extension(name = "translation", properties = { @ExtensionProperty(name = "description.key", value = "success_response:description") }) }
+ ) }
)
public long getTimePerBlock() {
try (final Repository repository = RepositoryManager.getRepository()) {
@@ -340,21 +309,18 @@ 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?
- content = @Content(schema = @Schema(implementation = long.class)),
- extensions = {
- @Extension(name = "translation", properties = {
- @ExtensionProperty(name="description.key", value="success_response:description")
- })
- }
- )
- }
+ 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?
+ content = @Content(schema = @Schema(implementation = long.class)),
+ extensions =
+ { @Extension(name = "translation", properties = { @ExtensionProperty(name = "description.key", value = "success_response:description") }) }
+ ) }
)
public long getTimePerBlock(@PathParam("generating") BigDecimal generatingbalance) {
return Block.calcForgingDelay(generatingbalance);
@@ -365,21 +331,18 @@ 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",
- content = @Content(schema = @Schema(implementation = int.class)),
- extensions = {
- @Extension(name = "translation", properties = {
- @ExtensionProperty(name="description.key", value="success_response:description")
- })
- }
- )
- }
+ extensions = @Extension(
+ name = "translation",
+ properties =
+ { @ExtensionProperty(name = "path", value = "GET height"), @ExtensionProperty(name = "description.key", value = "operation:description") }
+ ),
+ responses =
+ { @ApiResponse(
+ description = "the height",
+ content = @Content(schema = @Schema(implementation = int.class)),
+ extensions =
+ { @Extension(name = "translation", properties = { @ExtensionProperty(name = "description.key", value = "success_response:description") }) }
+ ) }
)
public int getHeight() {
try (final Repository repository = RepositoryManager.getRepository()) {
@@ -396,26 +359,20 @@ 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",
- content = @Content(schema = @Schema(implementation = int.class)),
- extensions = {
- @Extension(name = "translation", properties = {
- @ExtensionProperty(name="description.key", value="success_response:description")
- })
- }
- )
- }
+ 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",
+ content = @Content(schema = @Schema(implementation = int.class)),
+ extensions =
+ { @Extension(name = "translation", properties = { @ExtensionProperty(name = "description.key", value = "success_response:description") }) }
+ ) }
)
public int getHeight(@PathParam("signature") String signature) {
// Decode signature
@@ -446,31 +403,26 @@ 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",
- content = @Content(schema = @Schema(implementation = BlockWithTransactions.class)),
- extensions = {
- @Extension(name = "translation", properties = {
- @ExtensionProperty(name="description.key", value="success_response:description")
- })
- }
- )
- }
+ 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",
+ content = @Content(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) {
+ 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 new BlockWithTransactions(repository, blockData, includeTransactions);
+ return packageBlockData(repository, blockData, includeTransactions);
} catch (ApiException e) {
throw e;
} catch (DataException e) {
@@ -483,26 +435,20 @@ 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",
- content = @Content(schema = @Schema(implementation = BlockWithTransactions.class)),
- extensions = {
- @Extension(name = "translation", properties = {
- @ExtensionProperty(name="description.key", value="success_response:description")
- })
- }
- )
- }
+ 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",
+ content = @Content(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) {
boolean includeTransactions = false;
@@ -516,7 +462,7 @@ public class BlocksResource {
// Run out of blocks!
break;
- blocks.add(new BlockWithTransactions(repository, blockData, includeTransactions));
+ blocks.add(packageBlockData(repository, blockData, includeTransactions));
}
return blocks;
@@ -527,4 +473,17 @@ public class BlocksResource {
}
}
+ private BlockWithTransactions packageBlockData(Repository repository, BlockData blockData, boolean includeTransactions) throws DataException {
+ if (blockData == null)
+ throw this.apiErrorFactory.createError(ApiError.BLOCK_NO_EXISTS);
+
+ List transactions = null;
+ if (includeTransactions) {
+ Block block = new Block(repository, blockData);
+ transactions = block.getTransactions().stream().map(transaction -> transaction.getTransactionData()).collect(Collectors.toList());
+ }
+
+ return new BlockWithTransactions(blockData, transactions);
+ }
+
}
diff --git a/src/api/TransactionsResource.java b/src/api/TransactionsResource.java
index 1b022b1c..39505032 100644
--- a/src/api/TransactionsResource.java
+++ b/src/api/TransactionsResource.java
@@ -209,7 +209,7 @@ public class TransactionsResource {
}
)
public List searchTransactions(@QueryParam("startBlock") Integer startBlock, @QueryParam("blockLimit") Integer blockLimit,
- @QueryParam("txType") Integer txTypeNum, @QueryParam("address") String address, @Parameter(ref = "limit") @QueryParam("limit") Integer limit, @Parameter(ref = "offset") @QueryParam("offset") int offset) {
+ @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 this.apiErrorFactory.createError(ApiError.INVALID_CRITERIA);
diff --git a/src/api/models/AssetWithHolders.java b/src/api/models/AssetWithHolders.java
index d3e0978f..b499f605 100644
--- a/src/api/models/AssetWithHolders.java
+++ b/src/api/models/AssetWithHolders.java
@@ -2,17 +2,17 @@ package api.models;
import java.util.List;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
-import api.ApiError;
-import api.ApiErrorFactory;
import data.account.AccountBalanceData;
import data.assets.AssetData;
import io.swagger.v3.oas.annotations.media.Schema;
-import repository.DataException;
-import repository.Repository;
-@Schema(description = "Asset with (optional) asset holders")
+@Schema(description = "Asset info, maybe including asset holders")
+// All properties to be converted to JSON via JAX-RS
+@XmlAccessorType(XmlAccessType.FIELD)
public class AssetWithHolders {
@Schema(implementation = AssetData.class, name = "asset", title = "asset data")
@@ -22,18 +22,12 @@ public class AssetWithHolders {
public List holders;
// For JAX-RS
- @SuppressWarnings("unused")
- private AssetWithHolders() {
+ protected AssetWithHolders() {
}
- public AssetWithHolders(Repository repository, AssetData assetData, boolean includeHolders) throws DataException {
- if (assetData == null)
- throw ApiErrorFactory.getInstance().createError(ApiError.INVALID_ASSET_ID);
-
+ public AssetWithHolders(AssetData assetData, List holders) {
this.assetData = assetData;
-
- if (includeHolders)
- this.holders = repository.getAccountRepository().getAssetBalances(assetData.getAssetId());
+ this.holders = holders;
}
}
diff --git a/src/api/models/BlockWithTransactions.java b/src/api/models/BlockWithTransactions.java
index 0844a589..3a6f7854 100644
--- a/src/api/models/BlockWithTransactions.java
+++ b/src/api/models/BlockWithTransactions.java
@@ -1,22 +1,17 @@
package api.models;
import java.util.List;
-import java.util.stream.Collectors;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
-import api.ApiError;
-import api.ApiErrorFactory;
import data.block.BlockData;
import data.transaction.TransactionData;
import io.swagger.v3.oas.annotations.media.Schema;
-import qora.block.Block;
-import repository.DataException;
-import repository.Repository;
-@Schema(description = "Block with (optional) transactions")
+@Schema(description = "Block info, maybe including transactions")
+// All properties to be converted to JSON via JAX-RS
@XmlAccessorType(XmlAccessType.FIELD)
public class BlockWithTransactions {
@@ -30,16 +25,9 @@ public class BlockWithTransactions {
protected BlockWithTransactions() {
}
- public BlockWithTransactions(Repository repository, BlockData blockData, boolean includeTransactions) throws DataException {
- if (blockData == null)
- throw ApiErrorFactory.getInstance().createError(ApiError.BLOCK_NO_EXISTS);
-
+ public BlockWithTransactions(BlockData blockData, List transactions) {
this.blockData = blockData;
-
- if (includeTransactions) {
- Block block = new Block(repository, blockData);
- this.transactions = block.getTransactions().stream().map(transaction -> transaction.getTransactionData()).collect(Collectors.toList());
- }
+ this.transactions = transactions;
}
}
diff --git a/src/api/models/OrderWithTrades.java b/src/api/models/OrderWithTrades.java
new file mode 100644
index 00000000..e8c5731b
--- /dev/null
+++ b/src/api/models/OrderWithTrades.java
@@ -0,0 +1,33 @@
+package api.models;
+
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+
+import data.assets.OrderData;
+import data.assets.TradeData;
+import io.swagger.v3.oas.annotations.media.Schema;
+
+@Schema(description = "Asset order info, maybe including trades")
+// All properties to be converted to JSON via JAX-RS
+@XmlAccessorType(XmlAccessType.FIELD)
+public class OrderWithTrades {
+
+ @Schema(implementation = OrderData.class, name = "order", title = "order data")
+ @XmlElement(name = "order")
+ public OrderData orderData;
+
+ List trades;
+
+ // For JAX-RS
+ protected OrderWithTrades() {
+ }
+
+ public OrderWithTrades(OrderData orderData, List trades) {
+ this.orderData = orderData;
+ this.trades = trades;
+ }
+
+}
diff --git a/src/api/models/TradeWithOrderInfo.java b/src/api/models/TradeWithOrderInfo.java
index 51484352..c6c3d62b 100644
--- a/src/api/models/TradeWithOrderInfo.java
+++ b/src/api/models/TradeWithOrderInfo.java
@@ -1,14 +1,16 @@
package api.models;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import data.assets.OrderData;
import data.assets.TradeData;
import io.swagger.v3.oas.annotations.media.Schema;
-import repository.DataException;
-import repository.Repository;
-@Schema(description = "Asset trade, with order info")
+@Schema(description = "Asset trade, including order info")
+// All properties to be converted to JSON via JAX-RS
+@XmlAccessorType(XmlAccessType.FIELD)
public class TradeWithOrderInfo {
@Schema(implementation = TradeData.class, name = "trade", title = "trade data")
@@ -27,11 +29,10 @@ public class TradeWithOrderInfo {
protected TradeWithOrderInfo() {
}
- public TradeWithOrderInfo(Repository repository, TradeData tradeData) throws DataException {
+ public TradeWithOrderInfo(TradeData tradeData, OrderData initiatingOrderData, OrderData targetOrderData) {
this.tradeData = tradeData;
-
- this.initiatingOrderData = repository.getAssetRepository().fromOrderId(tradeData.getInitiator());
- this.targetOrderData = repository.getAssetRepository().fromOrderId(tradeData.getTarget());
+ this.initiatingOrderData = initiatingOrderData;
+ this.targetOrderData = targetOrderData;
}
}
diff --git a/src/api/models/TransactionClassExtractor.java b/src/api/models/TransactionClassExtractor.java
index d215c219..250caf3b 100644
--- a/src/api/models/TransactionClassExtractor.java
+++ b/src/api/models/TransactionClassExtractor.java
@@ -6,6 +6,7 @@ import org.eclipse.persistence.sessions.Session;
public class TransactionClassExtractor extends ClassExtractor {
+ @SuppressWarnings("rawtypes")
@Override
public Class extractClassFromRow(Record record, Session session) {
// Never called anyway?
diff --git a/src/data/PaymentData.java b/src/data/PaymentData.java
index 96b3eafd..04f25966 100644
--- a/src/data/PaymentData.java
+++ b/src/data/PaymentData.java
@@ -5,7 +5,7 @@ import java.math.BigDecimal;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
-//All properties to be converted to JSON via JAX-RS
+// All properties to be converted to JSON via JAX-RS
@XmlAccessorType(XmlAccessType.FIELD)
public class PaymentData {
diff --git a/src/qora/assets/Order.java b/src/qora/assets/Order.java
index e164b53c..da45badd 100644
--- a/src/qora/assets/Order.java
+++ b/src/qora/assets/Order.java
@@ -3,6 +3,7 @@ package qora.assets;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
+import java.util.Arrays;
import java.util.List;
import org.apache.logging.log4j.LogManager;
@@ -209,10 +210,11 @@ public class Order {
public void orphan() throws DataException {
// Orphan trades that occurred as a result of this order
- for (TradeData tradeData : getTrades()) {
- Trade trade = new Trade(this.repository, tradeData);
- trade.orphan();
- }
+ for (TradeData tradeData : getTrades())
+ if (Arrays.equals(this.orderData.getOrderId(), tradeData.getInitiator())) {
+ Trade trade = new Trade(this.repository, tradeData);
+ trade.orphan();
+ }
// Delete this order from repository
this.repository.getAssetRepository().delete(this.orderData.getOrderId());
diff --git a/src/repository/AssetRepository.java b/src/repository/AssetRepository.java
index 224c3484..f09ecdfa 100644
--- a/src/repository/AssetRepository.java
+++ b/src/repository/AssetRepository.java
@@ -40,6 +40,7 @@ public interface AssetRepository {
public List getTrades(long haveAssetId, long wantAssetId) throws DataException;
+ /** Returns TradeData for trades where orderId was involved, i.e. either initiating OR target order */
public List getOrdersTrades(byte[] orderId) throws DataException;
public void save(TradeData tradeData) throws DataException;
diff --git a/src/repository/hsqldb/HSQLDBAssetRepository.java b/src/repository/hsqldb/HSQLDBAssetRepository.java
index e1cd9279..cd63a09d 100644
--- a/src/repository/hsqldb/HSQLDBAssetRepository.java
+++ b/src/repository/hsqldb/HSQLDBAssetRepository.java
@@ -257,19 +257,21 @@ public class HSQLDBAssetRepository implements AssetRepository {
}
@Override
- public List getOrdersTrades(byte[] initiatingOrderId) throws DataException {
+ public List getOrdersTrades(byte[] orderId) throws DataException {
List trades = new ArrayList();
- try (ResultSet resultSet = this.repository
- .checkedExecute("SELECT target_order_id, amount, price, traded FROM AssetTrades WHERE initiating_order_id = ?", initiatingOrderId)) {
+ try (ResultSet resultSet = this.repository.checkedExecute(
+ "SELECT initiating_order_id, target_order_id, amount, price, traded FROM AssetTrades WHERE initiating_order_id = ? OR target_order_id = ?",
+ orderId, orderId)) {
if (resultSet == null)
return trades;
do {
- byte[] targetOrderId = resultSet.getBytes(1);
- BigDecimal amount = resultSet.getBigDecimal(2);
- BigDecimal price = resultSet.getBigDecimal(3);
- long timestamp = resultSet.getTimestamp(4, Calendar.getInstance(HSQLDBRepository.UTC)).getTime();
+ byte[] initiatingOrderId = resultSet.getBytes(1);
+ byte[] targetOrderId = resultSet.getBytes(2);
+ BigDecimal amount = resultSet.getBigDecimal(3);
+ BigDecimal price = resultSet.getBigDecimal(4);
+ long timestamp = resultSet.getTimestamp(5, Calendar.getInstance(HSQLDBRepository.UTC)).getTime();
TradeData trade = new TradeData(initiatingOrderId, targetOrderId, amount, price, timestamp);
trades.add(trade);
diff --git a/src/transform/block/BlockTransformer.java b/src/transform/block/BlockTransformer.java
index f73471ac..2ed501b5 100644
--- a/src/transform/block/BlockTransformer.java
+++ b/src/transform/block/BlockTransformer.java
@@ -310,11 +310,7 @@ public class BlockTransformer extends Transformer {
Order order = orderTransaction.getOrder();
List trades = order.getTrades();
- // Filter out trades with initiatingOrderId that don't match this order
- trades.removeIf((TradeData tradeData) -> !Arrays.equals(tradeData.getInitiator(), order.getOrderData().getOrderId()));
-
- // Any trades left?
- if (!trades.isEmpty()) {
+ if (trades.stream().anyMatch(tradeData -> Arrays.equals(tradeData.getInitiator(), order.getOrderData().getOrderId()))) {
tradesHappened = true;
// No need to check any further
break;