forked from Qortal/qortal
Add filtering by foreign blockchain to API crosschain calls
This commit is contained in:
parent
456bb3ca63
commit
31fa916156
@ -27,7 +27,7 @@ public class TradeBotCreateRequest {
|
|||||||
@XmlJavaTypeAdapter(value = org.qortal.api.AmountTypeAdapter.class)
|
@XmlJavaTypeAdapter(value = org.qortal.api.AmountTypeAdapter.class)
|
||||||
public Long bitcoinAmount;
|
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;
|
public SupportedBlockchain foreignBlockchain;
|
||||||
|
|
||||||
@Schema(description = "Foreign blockchain amount wanted in return", example = "0.00864200", type = "number")
|
@Schema(description = "Foreign blockchain amount wanted in return", example = "0.00864200", type = "number")
|
||||||
|
@ -80,7 +80,11 @@ public class CrossChainResource {
|
|||||||
)
|
)
|
||||||
@ApiErrors({ApiError.INVALID_CRITERIA, ApiError.REPOSITORY_ISSUE})
|
@ApiErrors({ApiError.INVALID_CRITERIA, ApiError.REPOSITORY_ISSUE})
|
||||||
public List<CrossChainTradeData> getTradeOffers(
|
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 = "limit") @QueryParam("limit") Integer limit,
|
||||||
@Parameter( ref = "offset" ) @QueryParam("offset") Integer offset,
|
@Parameter( ref = "offset" ) @QueryParam("offset") Integer offset,
|
||||||
@Parameter( ref = "reverse" ) @QueryParam("reverse") Boolean reverse) {
|
@Parameter( ref = "reverse" ) @QueryParam("reverse") Boolean reverse) {
|
||||||
@ -92,7 +96,7 @@ public class CrossChainResource {
|
|||||||
List<CrossChainTradeData> crossChainTradesData = new ArrayList<>();
|
List<CrossChainTradeData> crossChainTradesData = new ArrayList<>();
|
||||||
|
|
||||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
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()) {
|
for (Map.Entry<ByteArray, Supplier<ACCT>> acctInfo : acctsByCodeHash.entrySet()) {
|
||||||
byte[] codeHash = acctInfo.getKey().value;
|
byte[] codeHash = acctInfo.getKey().value;
|
||||||
@ -131,6 +135,11 @@ public class CrossChainResource {
|
|||||||
)
|
)
|
||||||
@ApiErrors({ApiError.INVALID_CRITERIA, ApiError.REPOSITORY_ISSUE})
|
@ApiErrors({ApiError.INVALID_CRITERIA, ApiError.REPOSITORY_ISSUE})
|
||||||
public List<CrossChainTradeSummary> getCompletedTrades(
|
public List<CrossChainTradeSummary> getCompletedTrades(
|
||||||
|
@Parameter(
|
||||||
|
description = "Limit to specific blockchain",
|
||||||
|
example = "LITECOIN",
|
||||||
|
schema = @Schema(implementation = SupportedBlockchain.class)
|
||||||
|
) @QueryParam("foreignBlockchain") SupportedBlockchain foreignBlockchain,
|
||||||
@Parameter(
|
@Parameter(
|
||||||
description = "Only return trades that completed on/after this timestamp (milliseconds since epoch)",
|
description = "Only return trades that completed on/after this timestamp (milliseconds since epoch)",
|
||||||
example = "1597310000000"
|
example = "1597310000000"
|
||||||
@ -165,7 +174,7 @@ public class CrossChainResource {
|
|||||||
|
|
||||||
List<CrossChainTradeSummary> crossChainTrades = new ArrayList<>();
|
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()) {
|
for (Map.Entry<ByteArray, Supplier<ACCT>> acctInfo : acctsByCodeHash.entrySet()) {
|
||||||
byte[] codeHash = acctInfo.getKey().value;
|
byte[] codeHash = acctInfo.getKey().value;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package org.qortal.api.resource;
|
package org.qortal.api.resource;
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
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.ArraySchema;
|
||||||
import io.swagger.v3.oas.annotations.media.Content;
|
import io.swagger.v3.oas.annotations.media.Content;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
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 io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.ws.rs.DELETE;
|
import javax.ws.rs.DELETE;
|
||||||
import javax.ws.rs.GET;
|
import javax.ws.rs.GET;
|
||||||
import javax.ws.rs.POST;
|
import javax.ws.rs.POST;
|
||||||
import javax.ws.rs.Path;
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.QueryParam;
|
||||||
import javax.ws.rs.core.Context;
|
import javax.ws.rs.core.Context;
|
||||||
import javax.ws.rs.core.MediaType;
|
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.AcctTradeBot;
|
||||||
import org.qortal.controller.tradebot.TradeBot;
|
import org.qortal.controller.tradebot.TradeBot;
|
||||||
import org.qortal.crosschain.ForeignBlockchain;
|
import org.qortal.crosschain.ForeignBlockchain;
|
||||||
|
import org.qortal.crosschain.SupportedBlockchain;
|
||||||
import org.qortal.crosschain.ACCT;
|
import org.qortal.crosschain.ACCT;
|
||||||
import org.qortal.crosschain.AcctMode;
|
import org.qortal.crosschain.AcctMode;
|
||||||
import org.qortal.crypto.Crypto;
|
import org.qortal.crypto.Crypto;
|
||||||
@ -65,13 +69,20 @@ public class CrossChainTradeBotResource {
|
|||||||
)
|
)
|
||||||
@ApiErrors({ApiError.REPOSITORY_ISSUE})
|
@ApiErrors({ApiError.REPOSITORY_ISSUE})
|
||||||
public List<TradeBotData> getTradeBotStates(
|
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);
|
Security.checkApiCallAllowed(request);
|
||||||
|
|
||||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||||
// TODO: maybe sub-class returned trade-bot data according to which trade-bot/ACCT applies?
|
List<TradeBotData> allTradeBotData = repository.getCrossChainRepository().getAllTradeBotData();
|
||||||
return repository.getCrossChainRepository().getAllTradeBotData();
|
|
||||||
|
if (foreignBlockchain == null)
|
||||||
|
return allTradeBotData;
|
||||||
|
|
||||||
|
return allTradeBotData.stream().filter(tradeBotData -> tradeBotData.getForeignBlockchain().equals(foreignBlockchain.name())).collect(Collectors.toList());
|
||||||
} catch (DataException e) {
|
} catch (DataException e) {
|
||||||
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
|
throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package org.qortal.crosschain;
|
package org.qortal.crosschain;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
@ -50,6 +51,9 @@ public enum SupportedBlockchain {
|
|||||||
.flatMap(List::stream)
|
.flatMap(List::stream)
|
||||||
.collect(Collectors.toUnmodifiableMap(Triple::getA, Triple::getC));
|
.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;
|
private final List<Triple<String, byte[], Supplier<ACCT>>> supportedAccts;
|
||||||
|
|
||||||
SupportedBlockchain(List<Triple<String, byte[], Supplier<ACCT>>> supportedAccts) {
|
SupportedBlockchain(List<Triple<String, byte[], Supplier<ACCT>>> supportedAccts) {
|
||||||
@ -63,6 +67,25 @@ public enum SupportedBlockchain {
|
|||||||
return supportedAcctsByCodeHash;
|
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) {
|
public static ACCT getAcctByCodeHash(byte[] codeHash) {
|
||||||
ByteArray wrappedCodeHash = new ByteArray(codeHash);
|
ByteArray wrappedCodeHash = new ByteArray(codeHash);
|
||||||
|
|
||||||
|
@ -4,10 +4,13 @@ import org.junit.Before;
|
|||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.qortal.api.ApiError;
|
import org.qortal.api.ApiError;
|
||||||
import org.qortal.api.resource.CrossChainResource;
|
import org.qortal.api.resource.CrossChainResource;
|
||||||
|
import org.qortal.crosschain.SupportedBlockchain;
|
||||||
import org.qortal.test.common.ApiCommon;
|
import org.qortal.test.common.ApiCommon;
|
||||||
|
|
||||||
public class CrossChainApiTests extends ApiCommon {
|
public class CrossChainApiTests extends ApiCommon {
|
||||||
|
|
||||||
|
private static final SupportedBlockchain SPECIFIC_BLOCKCHAIN = null;
|
||||||
|
|
||||||
private CrossChainResource crossChainResource;
|
private CrossChainResource crossChainResource;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
@ -17,12 +20,13 @@ public class CrossChainApiTests extends ApiCommon {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetTradeOffers() {
|
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
|
@Test
|
||||||
public void testGetCompletedTrades() {
|
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
|
@Test
|
||||||
@ -31,8 +35,8 @@ public class CrossChainApiTests extends ApiCommon {
|
|||||||
Integer offset = null;
|
Integer offset = null;
|
||||||
Boolean reverse = null;
|
Boolean reverse = null;
|
||||||
|
|
||||||
assertApiError(ApiError.INVALID_CRITERIA, () -> this.crossChainResource.getCompletedTrades(-1L /*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(0L /*minimumTimestamp*/, limit, offset, reverse));
|
assertApiError(ApiError.INVALID_CRITERIA, () -> this.crossChainResource.getCompletedTrades(SPECIFIC_BLOCKCHAIN, 0L /*minimumTimestamp*/, limit, offset, reverse));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user