From 0fd8ee3547fbd42a745f006b9183266c8475dadf Mon Sep 17 00:00:00 2001 From: catbref Date: Mon, 25 Mar 2019 11:55:03 +0000 Subject: [PATCH] Add API GET /assets/transfers/{assetid}/{address} --- .../org/qora/api/resource/AssetsResource.java | 44 +++++++++++++++++++ src/main/java/org/qora/data/PaymentData.java | 6 +-- .../repository/TransactionRepository.java | 17 ++++++- .../HSQLDBTransactionRepository.java | 40 ++++++++++++++++- 4 files changed, 102 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/qora/api/resource/AssetsResource.java b/src/main/java/org/qora/api/resource/AssetsResource.java index d1eaa280..cf71cdd4 100644 --- a/src/main/java/org/qora/api/resource/AssetsResource.java +++ b/src/main/java/org/qora/api/resource/AssetsResource.java @@ -623,6 +623,50 @@ public class AssetsResource { } } + @GET + @Path("/transfers/{assetid}/{address}") + @Operation( + summary = "Asset transfers for specific asset and address combination", + responses = { + @ApiResponse( + description = "Asset transactions", + content = @Content( + array = @ArraySchema( + schema = @Schema( + implementation = TransferAssetTransactionData.class + ) + ) + ) + ) + } + ) + @ApiErrors({ + ApiError.INVALID_ADDRESS, ApiError.INVALID_ASSET_ID, ApiError.REPOSITORY_ISSUE + }) + public List getAssetTransfers(@Parameter( + ref = "assetid" + ) @PathParam("assetid") int assetId, @PathParam("address") String address, @Parameter( + ref = "limit" + ) @QueryParam("limit") Integer limit, @Parameter( + ref = "offset" + ) @QueryParam("offset") Integer offset, @Parameter( + ref = "reverse" + ) @QueryParam("reverse") Boolean reverse) { + try (final Repository repository = RepositoryManager.getRepository()) { + if (!repository.getAssetRepository().assetExists(assetId)) + throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_ASSET_ID); + + if (!Crypto.isValidAddress(address)) + throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_ADDRESS); + + return repository.getTransactionRepository().getAssetTransfers(assetId, address, limit, offset, reverse); + } catch (ApiException e) { + throw e; + } catch (DataException e) { + throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e); + } + } + @POST @Path("/order/delete") @Operation( diff --git a/src/main/java/org/qora/data/PaymentData.java b/src/main/java/org/qora/data/PaymentData.java index 36a51476..424ef5a5 100644 --- a/src/main/java/org/qora/data/PaymentData.java +++ b/src/main/java/org/qora/data/PaymentData.java @@ -10,9 +10,9 @@ import javax.xml.bind.annotation.XmlAccessorType; public class PaymentData { // Properties - protected String recipient; - protected long assetId; - protected BigDecimal amount; + private String recipient; + private long assetId; + private BigDecimal amount; // Constructors diff --git a/src/main/java/org/qora/repository/TransactionRepository.java b/src/main/java/org/qora/repository/TransactionRepository.java index 5a63027c..18b684c2 100644 --- a/src/main/java/org/qora/repository/TransactionRepository.java +++ b/src/main/java/org/qora/repository/TransactionRepository.java @@ -6,6 +6,7 @@ import java.util.Map; import org.qora.api.resource.TransactionsResource.ConfirmationStatus; import org.qora.data.transaction.GroupApprovalTransactionData; import org.qora.data.transaction.TransactionData; +import org.qora.data.transaction.TransferAssetTransactionData; import org.qora.transaction.Transaction.TransactionType; public interface TransactionRepository { @@ -52,12 +53,26 @@ public interface TransactionRepository { * Returns list of transactions relating to specific asset ID. * * @param assetId + * @param confirmationStatus * @param limit * @param offset * @param reverse * @return list of transactions, or empty if none */ - public List getAssetTransactions(int assetId, ConfirmationStatus confirmationStatus, Integer limit, Integer offset, Boolean reverse) + public List getAssetTransactions(long assetId, ConfirmationStatus confirmationStatus, Integer limit, Integer offset, Boolean reverse) + throws DataException; + + /** + * Returns list of TRANSFER_ASSET transactions relating to specific asset ID/address combination. + * + * @param assetId + * @param address + * @param limit + * @param offset + * @param reverse + * @return list of transactions, or empty if none + */ + public List getAssetTransfers(long assetId, String address, Integer limit, Integer offset, Boolean reverse) throws DataException; /** diff --git a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBTransactionRepository.java b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBTransactionRepository.java index 993b20a0..855f1aec 100644 --- a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBTransactionRepository.java +++ b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBTransactionRepository.java @@ -22,6 +22,7 @@ import org.qora.api.resource.TransactionsResource.ConfirmationStatus; import org.qora.data.PaymentData; import org.qora.data.transaction.GroupApprovalTransactionData; import org.qora.data.transaction.TransactionData; +import org.qora.data.transaction.TransferAssetTransactionData; import org.qora.group.Group; import org.qora.repository.DataException; import org.qora.repository.TransactionRepository; @@ -446,7 +447,7 @@ public class HSQLDBTransactionRepository implements TransactionRepository { } @Override - public List getAssetTransactions(int assetId, ConfirmationStatus confirmationStatus, Integer limit, Integer offset, Boolean reverse) + public List getAssetTransactions(long assetId, ConfirmationStatus confirmationStatus, Integer limit, Integer offset, Boolean reverse) throws DataException { TransactionType[] transactionTypes = new TransactionType[] { ISSUE_ASSET, TRANSFER_ASSET, CREATE_ASSET_ORDER, CANCEL_ASSET_ORDER @@ -531,6 +532,43 @@ public class HSQLDBTransactionRepository implements TransactionRepository { } } + @Override + public List getAssetTransfers(long assetId, String address, Integer limit, Integer offset, Boolean reverse) + throws DataException { + String sql = "SELECT creation, tx_group_id, reference, fee, signature, sender, recipient, amount FROM TransferAssetTransactions " + + "JOIN Transactions USING (signature) " + + "JOIN Accounts ON public_key = sender " + + "WHERE asset_id = ? AND ? IN (account, recipient) " + + "ORDER by creation "; + + sql += (reverse == null || !reverse) ? "ASC" : "DESC"; + sql += HSQLDBRepository.limitOffsetSql(limit, offset); + + List assetTransfers = new ArrayList<>(); + + try (ResultSet resultSet = this.repository.checkedExecute(sql, assetId, address)) { + if (resultSet == null) + return assetTransfers; + + do { + long timestamp = resultSet.getTimestamp(1, Calendar.getInstance(HSQLDBRepository.UTC)).getTime(); + int txGroupId = resultSet.getInt(2); + byte[] reference = resultSet.getBytes(3); + BigDecimal fee = resultSet.getBigDecimal(4).setScale(8); + byte[] signature = resultSet.getBytes(5); + byte[] creatorPublicKey = resultSet.getBytes(6); + String recipient = resultSet.getString(7); + BigDecimal amount = resultSet.getBigDecimal(8); + + assetTransfers.add(new TransferAssetTransactionData(timestamp, txGroupId, reference, creatorPublicKey, recipient, amount, assetId, fee, signature)); + } while (resultSet.next()); + + return assetTransfers; + } catch (SQLException e) { + throw new DataException("Unable to fetch asset-transfer transactions from repository", e); + } + } + @Override public List getPendingTransactions(Integer txGroupId, Integer limit, Integer offset, Boolean reverse) throws DataException { String[] txTypesNeedingApproval = stream(Transaction.TransactionType.values())