Browse Source

Add filtering by foreign blockchain to API crosschain calls

pull/29/head
catbref 4 years ago
parent
commit
31fa916156
  1. 2
      src/main/java/org/qortal/api/model/crosschain/TradeBotCreateRequest.java
  2. 15
      src/main/java/org/qortal/api/resource/CrossChainResource.java
  3. 19
      src/main/java/org/qortal/api/resource/CrossChainTradeBotResource.java
  4. 23
      src/main/java/org/qortal/crosschain/SupportedBlockchain.java
  5. 12
      src/test/java/org/qortal/test/api/CrossChainApiTests.java

2
src/main/java/org/qortal/api/model/crosschain/TradeBotCreateRequest.java

@ -27,7 +27,7 @@ public class TradeBotCreateRequest {
@XmlJavaTypeAdapter(value = org.qortal.api.AmountTypeAdapter.class)
public Long bitcoinAmount;
@Schema(description = "Foreign blockchain. Note: default (BITCOIN) to be removed in the future", example = "BITCOIN", defaultValue = "BITCOIN")
@Schema(description = "Foreign blockchain. Note: default (BITCOIN) to be removed in the future", example = "BITCOIN", implementation = SupportedBlockchain.class)
public SupportedBlockchain foreignBlockchain;
@Schema(description = "Foreign blockchain amount wanted in return", example = "0.00864200", type = "number")

15
src/main/java/org/qortal/api/resource/CrossChainResource.java

@ -80,7 +80,11 @@ public class CrossChainResource {
)
@ApiErrors({ApiError.INVALID_CRITERIA, ApiError.REPOSITORY_ISSUE})
public List<CrossChainTradeData> getTradeOffers(
// TODO: we need a param to limit to specific foreign blockchain(s)
@Parameter(
description = "Limit to specific blockchain",
example = "LITECOIN",
schema = @Schema(implementation = SupportedBlockchain.class)
) @QueryParam("foreignBlockchain") SupportedBlockchain foreignBlockchain,
@Parameter( ref = "limit") @QueryParam("limit") Integer limit,
@Parameter( ref = "offset" ) @QueryParam("offset") Integer offset,
@Parameter( ref = "reverse" ) @QueryParam("reverse") Boolean reverse) {
@ -92,7 +96,7 @@ public class CrossChainResource {
List<CrossChainTradeData> crossChainTradesData = new ArrayList<>();
try (final Repository repository = RepositoryManager.getRepository()) {
Map<ByteArray, Supplier<ACCT>> acctsByCodeHash = SupportedBlockchain.getAcctMap();
Map<ByteArray, Supplier<ACCT>> acctsByCodeHash = SupportedBlockchain.getFilteredAcctMap(foreignBlockchain);
for (Map.Entry<ByteArray, Supplier<ACCT>> acctInfo : acctsByCodeHash.entrySet()) {
byte[] codeHash = acctInfo.getKey().value;
@ -131,6 +135,11 @@ public class CrossChainResource {
)
@ApiErrors({ApiError.INVALID_CRITERIA, ApiError.REPOSITORY_ISSUE})
public List<CrossChainTradeSummary> getCompletedTrades(
@Parameter(
description = "Limit to specific blockchain",
example = "LITECOIN",
schema = @Schema(implementation = SupportedBlockchain.class)
) @QueryParam("foreignBlockchain") SupportedBlockchain foreignBlockchain,
@Parameter(
description = "Only return trades that completed on/after this timestamp (milliseconds since epoch)",
example = "1597310000000"
@ -165,7 +174,7 @@ public class CrossChainResource {
List<CrossChainTradeSummary> crossChainTrades = new ArrayList<>();
Map<ByteArray, Supplier<ACCT>> acctsByCodeHash = SupportedBlockchain.getAcctMap();
Map<ByteArray, Supplier<ACCT>> acctsByCodeHash = SupportedBlockchain.getFilteredAcctMap(foreignBlockchain);
for (Map.Entry<ByteArray, Supplier<ACCT>> acctInfo : acctsByCodeHash.entrySet()) {
byte[] codeHash = acctInfo.getKey().value;

19
src/main/java/org/qortal/api/resource/CrossChainTradeBotResource.java

@ -1,6 +1,7 @@
package org.qortal.api.resource;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
@ -9,12 +10,14 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.List;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
@ -30,6 +33,7 @@ import org.qortal.asset.Asset;
import org.qortal.controller.tradebot.AcctTradeBot;
import org.qortal.controller.tradebot.TradeBot;
import org.qortal.crosschain.ForeignBlockchain;
import org.qortal.crosschain.SupportedBlockchain;
import org.qortal.crosschain.ACCT;
import org.qortal.crosschain.AcctMode;
import org.qortal.crypto.Crypto;
@ -65,13 +69,20 @@ public class CrossChainTradeBotResource {
)
@ApiErrors({ApiError.REPOSITORY_ISSUE})
public List<TradeBotData> getTradeBotStates(
// TODO: optional filter for foreign blockchain(s)?
) {
@Parameter(
description = "Limit to specific blockchain",
example = "LITECOIN",
schema = @Schema(implementation = SupportedBlockchain.class)
) @QueryParam("foreignBlockchain") SupportedBlockchain foreignBlockchain) {
Security.checkApiCallAllowed(request);
try (final Repository repository = RepositoryManager.getRepository()) {
// TODO: maybe sub-class returned trade-bot data according to which trade-bot/ACCT applies?
return repository.getCrossChainRepository().getAllTradeBotData();
List<TradeBotData> allTradeBotData = repository.getCrossChainRepository().getAllTradeBotData();
if (foreignBlockchain == null)
return allTradeBotData;
return allTradeBotData.stream().filter(tradeBotData -> tradeBotData.getForeignBlockchain().equals(foreignBlockchain.name())).collect(Collectors.toList());
} catch (DataException e) {
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
}

23
src/main/java/org/qortal/crosschain/SupportedBlockchain.java

@ -1,6 +1,7 @@
package org.qortal.crosschain;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
@ -50,6 +51,9 @@ public enum SupportedBlockchain {
.flatMap(List::stream)
.collect(Collectors.toUnmodifiableMap(Triple::getA, Triple::getC));
private static final Map<String, SupportedBlockchain> blockchainsByName = Arrays.stream(SupportedBlockchain.values())
.collect(Collectors.toUnmodifiableMap(Enum::name, blockchain -> blockchain));
private final List<Triple<String, byte[], Supplier<ACCT>>> supportedAccts;
SupportedBlockchain(List<Triple<String, byte[], Supplier<ACCT>>> supportedAccts) {
@ -63,6 +67,25 @@ public enum SupportedBlockchain {
return supportedAcctsByCodeHash;
}
public static Map<ByteArray, Supplier<ACCT>> getFilteredAcctMap(SupportedBlockchain blockchain) {
if (blockchain == null)
return getAcctMap();
return blockchain.supportedAccts.stream()
.collect(Collectors.toUnmodifiableMap(triple -> new ByteArray(triple.getB()), Triple::getC));
}
public static Map<ByteArray, Supplier<ACCT>> getFilteredAcctMap(String specificBlockchain) {
if (specificBlockchain == null)
return getAcctMap();
SupportedBlockchain blockchain = blockchainsByName.get(specificBlockchain);
if (blockchain == null)
return Collections.emptyMap();
return getFilteredAcctMap(blockchain);
}
public static ACCT getAcctByCodeHash(byte[] codeHash) {
ByteArray wrappedCodeHash = new ByteArray(codeHash);

12
src/test/java/org/qortal/test/api/CrossChainApiTests.java

@ -4,10 +4,13 @@ import org.junit.Before;
import org.junit.Test;
import org.qortal.api.ApiError;
import org.qortal.api.resource.CrossChainResource;
import org.qortal.crosschain.SupportedBlockchain;
import org.qortal.test.common.ApiCommon;
public class CrossChainApiTests extends ApiCommon {
private static final SupportedBlockchain SPECIFIC_BLOCKCHAIN = null;
private CrossChainResource crossChainResource;
@Before
@ -17,12 +20,13 @@ public class CrossChainApiTests extends ApiCommon {
@Test
public void testGetTradeOffers() {
assertNoApiError((limit, offset, reverse) -> this.crossChainResource.getTradeOffers(limit, offset, reverse));
assertNoApiError((limit, offset, reverse) -> this.crossChainResource.getTradeOffers(SPECIFIC_BLOCKCHAIN, limit, offset, reverse));
}
@Test
public void testGetCompletedTrades() {
assertNoApiError((limit, offset, reverse) -> this.crossChainResource.getCompletedTrades(System.currentTimeMillis() /*minimumTimestamp*/, limit, offset, reverse));
long minimumTimestamp = System.currentTimeMillis();
assertNoApiError((limit, offset, reverse) -> this.crossChainResource.getCompletedTrades(SPECIFIC_BLOCKCHAIN, minimumTimestamp, limit, offset, reverse));
}
@Test
@ -31,8 +35,8 @@ public class CrossChainApiTests extends ApiCommon {
Integer offset = null;
Boolean reverse = null;
assertApiError(ApiError.INVALID_CRITERIA, () -> this.crossChainResource.getCompletedTrades(-1L /*minimumTimestamp*/, limit, offset, reverse));
assertApiError(ApiError.INVALID_CRITERIA, () -> this.crossChainResource.getCompletedTrades(0L /*minimumTimestamp*/, limit, offset, reverse));
assertApiError(ApiError.INVALID_CRITERIA, () -> this.crossChainResource.getCompletedTrades(SPECIFIC_BLOCKCHAIN, -1L /*minimumTimestamp*/, limit, offset, reverse));
assertApiError(ApiError.INVALID_CRITERIA, () -> this.crossChainResource.getCompletedTrades(SPECIFIC_BLOCKCHAIN, 0L /*minimumTimestamp*/, limit, offset, reverse));
}
}

Loading…
Cancel
Save