diff --git a/reddio-java/reddio-api/src/main/java/com/reddio/api/v1/requests/polling/OrderPoller.java b/reddio-java/reddio-api/src/main/java/com/reddio/api/v1/requests/polling/OrderPoller.java index 22c133c..7aa67b5 100644 --- a/reddio-java/reddio-api/src/main/java/com/reddio/api/v1/requests/polling/OrderPoller.java +++ b/reddio-java/reddio-api/src/main/java/com/reddio/api/v1/requests/polling/OrderPoller.java @@ -1,6 +1,6 @@ package com.reddio.api.v1.requests.polling; -import com.reddio.ReddioException; +import com.reddio.exception.ReddioException; import com.reddio.api.v1.requests.UnwrapCompletionExceptionKt; import com.reddio.api.v1.rest.*; import lombok.SneakyThrows; diff --git a/reddio-java/reddio-api/src/main/java/com/reddio/api/v1/requests/polling/RecordPoller.java b/reddio-java/reddio-api/src/main/java/com/reddio/api/v1/requests/polling/RecordPoller.java index dcd6e8b..3e14aea 100644 --- a/reddio-java/reddio-api/src/main/java/com/reddio/api/v1/requests/polling/RecordPoller.java +++ b/reddio-java/reddio-api/src/main/java/com/reddio/api/v1/requests/polling/RecordPoller.java @@ -1,6 +1,6 @@ package com.reddio.api.v1.requests.polling; -import com.reddio.ReddioException; +import com.reddio.exception.ReddioException; import com.reddio.api.v1.requests.UnwrapCompletionExceptionKt; import com.reddio.api.v1.rest.*; import lombok.SneakyThrows; diff --git a/reddio-java/reddio-api/src/main/java/com/reddio/api/v1/rest/DefaultReddioRestClient.java b/reddio-java/reddio-api/src/main/java/com/reddio/api/v1/rest/DefaultReddioRestClient.java index 743e51b..0bc7e74 100644 --- a/reddio-java/reddio-api/src/main/java/com/reddio/api/v1/rest/DefaultReddioRestClient.java +++ b/reddio-java/reddio-api/src/main/java/com/reddio/api/v1/rest/DefaultReddioRestClient.java @@ -4,8 +4,12 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; -import com.reddio.ReddioException; +import com.reddio.exception.ReddioBusinessException; +import com.reddio.exception.ReddioErrorCode; +import com.reddio.exception.ReddioException; +import com.reddio.exception.ReddioServiceException; import okhttp3.*; +import okhttp3.internal.http2.ErrorCode; import org.jetbrains.annotations.NotNull; import java.io.IOException; @@ -335,10 +339,10 @@ public static ResponseWrapper ensureSuccess(ResponseWrapper responseWr if ("OK".equals(responseWrapper.getStatus())) { return responseWrapper; } - throw new ReddioException("response status is not OK, status: " + responseWrapper.getStatus() + ", error: " + responseWrapper.error + ", messages: " + String.join(",", messages)); + throw new ReddioBusinessException(responseWrapper.getStatus(), responseWrapper.getError(), ReddioErrorCode.fromCode(responseWrapper.getErrorCode()), responseWrapper); } - private static class ToCompletableFutureCallback implements Callback { + static class ToCompletableFutureCallback implements Callback { private final CompletableFuture future; private final TypeReference typeReference; @@ -348,23 +352,35 @@ public ToCompletableFutureCallback(CompletableFuture future, TypeReference } @Override - public void onFailure(@NotNull Call call, IOException e) { + public void onFailure(Call call, IOException e) { this.future.completeExceptionally(e); } @Override - public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException { + public void onResponse(Call call, Response response) { try { + String responseBodyAsString = response.body() != null ? response.body().string() : ""; + ReddioErrorCode errCode = tryExtractErrorCode(responseBodyAsString); if (!response.isSuccessful()) { - this.future.completeExceptionally(new IOException("response is not successful, code: " + response.code())); + this.future.completeExceptionally(new ReddioServiceException("reddio service not respond as sucessful", response.code(), errCode, responseBodyAsString)); return; } - String jsonString = Objects.requireNonNull(response.body()).string(); - this.future.complete(objectMapper.readValue(jsonString, typeReference)); + this.future.complete(objectMapper.readValue(responseBodyAsString, typeReference)); } catch (Throwable e) { this.future.completeExceptionally(e); } } + + public static ReddioErrorCode tryExtractErrorCode(String responseJsonString) { + try { + final ResponseWrapper model = objectMapper.readValue(responseJsonString, new TypeReference>() { + }); + return ReddioErrorCode.fromCode(model.getErrorCode()); + } catch (Throwable e) { + // TODO: debug log + return null; + } + } } public static final class ReddioUAInterceptor implements Interceptor { diff --git a/reddio-java/reddio-api/src/main/java/com/reddio/api/v1/rest/GetNonceResponse.java b/reddio-java/reddio-api/src/main/java/com/reddio/api/v1/rest/GetNonceResponse.java index fac9cc4..725e25a 100644 --- a/reddio-java/reddio-api/src/main/java/com/reddio/api/v1/rest/GetNonceResponse.java +++ b/reddio-java/reddio-api/src/main/java/com/reddio/api/v1/rest/GetNonceResponse.java @@ -10,5 +10,5 @@ @AllArgsConstructor(staticName = "of") public class GetNonceResponse { @JsonProperty("nonce") - public long nonce; + public Long nonce; } diff --git a/reddio-java/reddio-api/src/main/java/com/reddio/api/v1/rest/ResponseWrapper.java b/reddio-java/reddio-api/src/main/java/com/reddio/api/v1/rest/ResponseWrapper.java index 4b38493..c0fc91e 100644 --- a/reddio-java/reddio-api/src/main/java/com/reddio/api/v1/rest/ResponseWrapper.java +++ b/reddio-java/reddio-api/src/main/java/com/reddio/api/v1/rest/ResponseWrapper.java @@ -10,10 +10,15 @@ @AllArgsConstructor(staticName = "of") public class ResponseWrapper { @JsonProperty("status") - public String status; + private String status; + @JsonProperty("error") - public String error; + private String error; + + @JsonProperty("error_code") + private Integer errorCode; + @JsonProperty("data") - public T data; + private T data; } diff --git a/reddio-java/reddio-api/src/main/java/com/reddio/api/v1/rest/SequenceRecord.java b/reddio-java/reddio-api/src/main/java/com/reddio/api/v1/rest/SequenceRecord.java index a35cd74..f967b03 100644 --- a/reddio-java/reddio-api/src/main/java/com/reddio/api/v1/rest/SequenceRecord.java +++ b/reddio-java/reddio-api/src/main/java/com/reddio/api/v1/rest/SequenceRecord.java @@ -43,7 +43,7 @@ public class SequenceRecord { public RecordType recordType; @JsonProperty("sequence_id") - public long sequenceId; + public Long sequenceId; @JsonProperty("stark_key") public String starkKey; @@ -55,7 +55,7 @@ public class SequenceRecord { public String resp; @JsonProperty("time") - public long time; + public Long time; @JsonProperty("to") public String to; diff --git a/reddio-java/reddio-api/src/main/java/com/reddio/api/v1/rest/TransferMessage.java b/reddio-java/reddio-api/src/main/java/com/reddio/api/v1/rest/TransferMessage.java index 4c11efe..8b3eb1c 100644 --- a/reddio-java/reddio-api/src/main/java/com/reddio/api/v1/rest/TransferMessage.java +++ b/reddio-java/reddio-api/src/main/java/com/reddio/api/v1/rest/TransferMessage.java @@ -16,7 +16,7 @@ public class TransferMessage { @JsonProperty("amount") public String amount; @JsonProperty("nonce") - public long nonce; + public Long nonce; @JsonProperty("vault_id") public String vaultId; @JsonProperty("receiver") @@ -24,7 +24,7 @@ public class TransferMessage { @JsonProperty("receiver_vault_id") public String receiverVaultId; @JsonProperty("expiration_timestamp") - public long expirationTimestamp; + public Long expirationTimestamp; @JsonProperty("signature") public Signature signature; diff --git a/reddio-java/reddio-api/src/main/java/com/reddio/api/v1/rest/TransferResponse.java b/reddio-java/reddio-api/src/main/java/com/reddio/api/v1/rest/TransferResponse.java index fdb11cc..ac6f096 100644 --- a/reddio-java/reddio-api/src/main/java/com/reddio/api/v1/rest/TransferResponse.java +++ b/reddio-java/reddio-api/src/main/java/com/reddio/api/v1/rest/TransferResponse.java @@ -11,5 +11,5 @@ public class TransferResponse { @JsonProperty("sequence_id") - public long sequenceId; + public Long sequenceId; } diff --git a/reddio-java/reddio-api/src/main/java/com/reddio/exception/ReddioBusinessException.java b/reddio-java/reddio-api/src/main/java/com/reddio/exception/ReddioBusinessException.java new file mode 100644 index 0000000..7a65612 --- /dev/null +++ b/reddio-java/reddio-api/src/main/java/com/reddio/exception/ReddioBusinessException.java @@ -0,0 +1,51 @@ +package com.reddio.exception; + +import com.reddio.api.v1.rest.ResponseWrapper; +import jnr.x86asm.RID; +import lombok.Getter; + + +/** + * ReddioBusinessException represents the business exception that return by the reddio service. + */ +public class ReddioBusinessException extends ReddioException { + private static final long serialVersionUID = -6477748788283734748L; + + /** + * The status in the response. + */ + @Getter + private final String status; + + /** + * Error message. + */ + @Getter + private final String error; + + /** + * Error code as enum, might be null if the error code is not recognized. + *

+ * You could still get the error code from raw response {@link #getResponse()}. + */ + @Getter + private final ReddioErrorCode errorCode; + + /** + * Raw response from the reddio service. + */ + @Getter + private final ResponseWrapper response; + + public ReddioBusinessException(String status, String error, ReddioErrorCode errorCode, ResponseWrapper response) { + this.status = status; + this.error = error; + this.errorCode = errorCode; + this.response = response; + } + + @Override + public String getMessage() { + return String.format("reddio business failure, status: %s, error: %s, error code: %s", status, error, errorCode); + } +} diff --git a/reddio-java/reddio-api/src/main/java/com/reddio/exception/ReddioErrorCode.java b/reddio-java/reddio-api/src/main/java/com/reddio/exception/ReddioErrorCode.java new file mode 100644 index 0000000..9a38706 --- /dev/null +++ b/reddio-java/reddio-api/src/main/java/com/reddio/exception/ReddioErrorCode.java @@ -0,0 +1,63 @@ +package com.reddio.exception; + +import lombok.Getter; + +public enum ReddioErrorCode { + Success(0), + StarkKeyMissing(1), + AmountInvalid(2), + TokenIDMissing(3), + TokenIDParseFailed(4), + NOSuchAccountID(5), + NoSuchAssetID(6), + NoMintableToken(7), + InsufficientAvailable(8), + InsufficientFrozen(9), + AddSequenceFailed(10), + FailedToGenerateNonce(11), + OrderFormatError(12), + DuplicateTransactionError(13), + FullWithdrawError(14), + NotSuchContract(15), + FailedToGenerateVaultID(16), + CancelOrderWrongOwner(17), + StarkKeyInvalid(18), + InvalidParam(19), + OrderConditionalCanceled(20), + FOKAndIOCCanceled(21), + TokenIDInvalid(22), + MintAmountInvalid(23), + DuplicateOrderInfoError(24), + NotSuchToken(25), + CanceledOrder(26), + ContractAddressMissing(27), + NoSuchContractType(28), + FailedToParseUint(29), + CommandToEventFailed(30), + EventNotMatch(31), + InvalidAPIKey(32), + InvalidOwnerOfContract(33), + FailedToVerifyParams(400), + FailedToJSONUnmarshal(401), + SystemError(500); + + ReddioErrorCode(int code) { + this.code = code; + } + + @Getter + private final int code; + + public static ReddioErrorCode fromCode(Integer code) { + if (code == null) { + return null; + } + for (ReddioErrorCode errorCode : ReddioErrorCode.values()) { + if (errorCode.getCode() == code) { + return errorCode; + } + } + return null; + } + +} diff --git a/reddio-java/reddio-api/src/main/java/com/reddio/ReddioException.java b/reddio-java/reddio-api/src/main/java/com/reddio/exception/ReddioException.java similarity index 76% rename from reddio-java/reddio-api/src/main/java/com/reddio/ReddioException.java rename to reddio-java/reddio-api/src/main/java/com/reddio/exception/ReddioException.java index 0350fcb..58c2140 100644 --- a/reddio-java/reddio-api/src/main/java/com/reddio/ReddioException.java +++ b/reddio-java/reddio-api/src/main/java/com/reddio/exception/ReddioException.java @@ -1,7 +1,14 @@ -package com.reddio; +package com.reddio.exception; +/** + * + */ public class ReddioException extends RuntimeException { + public ReddioException() { + super(); + } + public ReddioException(String message) { super(message); } diff --git a/reddio-java/reddio-api/src/main/java/com/reddio/exception/ReddioServiceException.java b/reddio-java/reddio-api/src/main/java/com/reddio/exception/ReddioServiceException.java new file mode 100644 index 0000000..aa3ed59 --- /dev/null +++ b/reddio-java/reddio-api/src/main/java/com/reddio/exception/ReddioServiceException.java @@ -0,0 +1,49 @@ +package com.reddio.exception; + +import lombok.Getter; + +/** + * ReddioServiceException represents the exception when the reddio service not respond successfully. + * + * @author strrl + */ +public class ReddioServiceException extends ReddioException { + public ReddioServiceException(String description, int httpStatusCode, ReddioErrorCode errorCode, String responseBody) { + this.description = description; + this.httpStatusCode = httpStatusCode; + this.errorCode = errorCode; + this.responseBody = responseBody; + } + + private static final long serialVersionUID = 1205765559865993637L; + + /** + * Description of the exception. + */ + @Getter + private final String description; + + /** + * Http status code. + */ + @Getter + private final int httpStatusCode; + + /** + * Error code as enum, might be null if the error code is not recognized. + */ + @Getter + private final ReddioErrorCode errorCode; + + /** + * The raw response body as string. + */ + @Getter + private final String responseBody; + + + @Override + public String getMessage() { + return String.format("reddio service not respond service, description: %s, http status code: %d, error code: %s, response body: %s", description, httpStatusCode, errorCode, responseBody); + } +} diff --git a/reddio-java/reddio-api/src/main/kotlin/com/reddio/api/v1/DefaultEthereumInteraction.kt b/reddio-java/reddio-api/src/main/kotlin/com/reddio/api/v1/DefaultEthereumInteraction.kt index 56dda25..b9f1b0d 100644 --- a/reddio-java/reddio-api/src/main/kotlin/com/reddio/api/v1/DefaultEthereumInteraction.kt +++ b/reddio-java/reddio-api/src/main/kotlin/com/reddio/api/v1/DefaultEthereumInteraction.kt @@ -2,7 +2,7 @@ package com.reddio.api.v1 import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.databind.ObjectMapper -import com.reddio.ReddioException +import com.reddio.exception.ReddioException import com.reddio.abi.Deposits import com.reddio.abi.Withdrawals import com.reddio.api.v1.rest.GetAssetIdMessage diff --git a/reddio-java/reddio-api/src/main/kotlin/com/reddio/api/v1/DefaultReddioClient.kt b/reddio-java/reddio-api/src/main/kotlin/com/reddio/api/v1/DefaultReddioClient.kt index ffb0b99..91ebf79 100644 --- a/reddio-java/reddio-api/src/main/kotlin/com/reddio/api/v1/DefaultReddioClient.kt +++ b/reddio-java/reddio-api/src/main/kotlin/com/reddio/api/v1/DefaultReddioClient.kt @@ -1,6 +1,6 @@ package com.reddio.api.v1 -import com.reddio.ReddioException +import com.reddio.exception.ReddioException import com.reddio.api.v1.rest.* import com.reddio.sign.PaymentSign import kotlinx.coroutines.delay diff --git a/reddio-java/reddio-api/src/main/kotlin/com/reddio/api/v1/TransferFailedException.kt b/reddio-java/reddio-api/src/main/kotlin/com/reddio/api/v1/TransferFailedException.kt index ecfe536..05bd884 100644 --- a/reddio-java/reddio-api/src/main/kotlin/com/reddio/api/v1/TransferFailedException.kt +++ b/reddio-java/reddio-api/src/main/kotlin/com/reddio/api/v1/TransferFailedException.kt @@ -1,6 +1,6 @@ package com.reddio.api.v1 -import com.reddio.ReddioException +import com.reddio.exception.ReddioException import com.reddio.api.v1.rest.GetRecordResponse class TransferFailedException(override val message: String?, val record: GetRecordResponse) : ReddioException(message) { diff --git a/reddio-java/reddio-api/src/main/kotlin/com/reddio/api/v1/requests/ReddioWithdrawalToApi.kt b/reddio-java/reddio-api/src/main/kotlin/com/reddio/api/v1/requests/ReddioWithdrawalToApi.kt index ce7564a..6a14565 100644 --- a/reddio-java/reddio-api/src/main/kotlin/com/reddio/api/v1/requests/ReddioWithdrawalToApi.kt +++ b/reddio-java/reddio-api/src/main/kotlin/com/reddio/api/v1/requests/ReddioWithdrawalToApi.kt @@ -1,6 +1,6 @@ package com.reddio.api.v1.requests -import com.reddio.ReddioException +import com.reddio.exception.ReddioException import com.reddio.api.v1.QuantizedHelper import com.reddio.api.v1.ReddioClient import com.reddio.api.v1.StarkExSigner diff --git a/reddio-java/reddio-api/src/main/kotlin/com/reddio/misc/BulkAssetsTransfer.kt b/reddio-java/reddio-api/src/main/kotlin/com/reddio/misc/BulkAssetsTransfer.kt index e94fbe4..de95fe5 100644 --- a/reddio-java/reddio-api/src/main/kotlin/com/reddio/misc/BulkAssetsTransfer.kt +++ b/reddio-java/reddio-api/src/main/kotlin/com/reddio/misc/BulkAssetsTransfer.kt @@ -1,6 +1,6 @@ package com.reddio.misc -import com.reddio.ReddioException +import com.reddio.exception.ReddioException import com.reddio.api.v1.StarkExSigner import com.reddio.api.v1.requests.ReddioCancelOrderApi import com.reddio.api.v1.requests.ReddioTransferToApi @@ -9,7 +9,6 @@ import com.reddio.api.v1.rest.GetBalancesResponse.BalanceRecord import kotlinx.coroutines.future.await import kotlinx.coroutines.runBlocking import java.util.stream.Collectors -import kotlin.streams.toList /** * BulkAssetsTransfer is a helper class which would transfer **all the assets** from sender to receiver as best effort. diff --git a/reddio-java/reddio-api/src/test/java/com/reddio/api/v1/DefaultReddioClientTest.java b/reddio-java/reddio-api/src/test/java/com/reddio/api/v1/DefaultReddioClientTest.java index 9b4d024..a139b6e 100644 --- a/reddio-java/reddio-api/src/test/java/com/reddio/api/v1/DefaultReddioClientTest.java +++ b/reddio-java/reddio-api/src/test/java/com/reddio/api/v1/DefaultReddioClientTest.java @@ -2,9 +2,14 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; +import com.reddio.api.v1.requests.ReddioOrderApi; +import com.reddio.api.v1.requests.ReddioTransferToApi; +import com.reddio.api.v1.requests.ReddioWithdrawalToApi; import com.reddio.api.v1.rest.*; import com.reddio.crypto.CryptoService; import com.reddio.crypto.Signature; +import com.reddio.exception.ReddioBusinessException; +import com.reddio.exception.ReddioErrorCode; import com.reddio.sign.PaymentSHA3; import org.junit.Assert; import org.junit.Ignore; @@ -14,6 +19,7 @@ import java.util.ArrayList; import java.util.List; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; @@ -24,17 +30,9 @@ public class DefaultReddioClientTest { public void testTransfer() throws ExecutionException, InterruptedException, JsonProcessingException { DefaultReddioClient client = DefaultReddioClient.testnet(); ReddioClient.WithStarkExSigner clientWithSigner = client.withStarkExSigner("0xa7b68cf2ee72b2a0789914daa8ae928aec21b6b0bf020e394833f4c732d99d"); - CompletableFuture> future = clientWithSigner.transfer( - "0x6736f7449da3bf44bf0f7bdd6463818e1ef272641d43021e8bca17b32ec2df0", - "1", - REDDIO721_CONTRACT_ADDRESS, - "497", - "ERC721", - "0x7865bc66b610d6196a7cbeb9bf066c64984f6f06b5ed3b6f5788bd9a6cb099c", - 4194303L - ); + CompletableFuture> future = clientWithSigner.transfer("0x6736f7449da3bf44bf0f7bdd6463818e1ef272641d43021e8bca17b32ec2df0", "1", REDDIO721_CONTRACT_ADDRESS, "497", "ERC721", "0x7865bc66b610d6196a7cbeb9bf066c64984f6f06b5ed3b6f5788bd9a6cb099c", 4194303L); ResponseWrapper result = future.get(); - Assert.assertEquals("OK", result.status); + Assert.assertEquals("OK", result.getStatus()); System.out.println(new ObjectMapper().writeValueAsString(result)); } @@ -43,7 +41,7 @@ public void testWaitingRecordGetApproved() throws ExecutionException, Interrupte DefaultReddioClient client = DefaultReddioClient.testnet(); CompletableFuture> future = client.waitingTransferGetApproved("0x6736f7449da3bf44bf0f7bdd6463818e1ef272641d43021e8bca17b32ec2df0", 300523); ResponseWrapper result = future.get(); - Assert.assertEquals("OK", result.status); + Assert.assertEquals("OK", result.getStatus()); System.out.println(new ObjectMapper().writeValueAsString(result)); } @@ -51,16 +49,9 @@ public void testWaitingRecordGetApproved() throws ExecutionException, Interrupte public void testWithdrawalGoerliETH() throws ExecutionException, InterruptedException, JsonProcessingException { DefaultReddioClient client = DefaultReddioClient.testnet(); ReddioClient.WithStarkExSigner clientWithSigner = client.withStarkExSigner("0x4d55b547af138c5b6200495d86ab6aed3e06c25fdd75b4b6a00e48515df2b3d"); - CompletableFuture> future = clientWithSigner.withdrawal("0x1c2847406b96310a32c379536374ec034b732633e8675860f20f4141e701ff4", - "0.00013", - "ETH", - "", - "ETH", - "0x76f2Fc7ed90039d986e3eb4DB294f05E160c8F03", - 4194303L - ); + CompletableFuture> future = clientWithSigner.withdrawal("0x1c2847406b96310a32c379536374ec034b732633e8675860f20f4141e701ff4", "0.00013", "ETH", "", "ETH", "0x76f2Fc7ed90039d986e3eb4DB294f05E160c8F03", 4194303L); ResponseWrapper result = future.get(); - Assert.assertEquals("OK", result.status); + Assert.assertEquals("OK", result.getStatus()); System.out.println(new ObjectMapper().writeValueAsString(result)); } @@ -71,7 +62,7 @@ public void testWithdrawalNTFERC721() throws ExecutionException, InterruptedExce ReddioClient.WithStarkExSigner clientWithSigner = client.withStarkExSigner("0x4d55b547af138c5b6200495d86ab6aed3e06c25fdd75b4b6a00e48515df2b3d"); CompletableFuture> future = clientWithSigner.withdrawal("0x1c2847406b96310a32c379536374ec034b732633e8675860f20f4141e701ff4", "1", REDDIO721_CONTRACT_ADDRESS, "1022", "ERC721", "0x76f2Fc7ed90039d986e3eb4DB294f05E160c8F03", 4194303L); ResponseWrapper result = future.get(); - Assert.assertEquals("OK", result.status); + Assert.assertEquals("OK", result.getStatus()); System.out.println(new ObjectMapper().writeValueAsString(result)); } @@ -82,7 +73,7 @@ public void testWithdrawalNTFERC721M() throws ExecutionException, InterruptedExc ReddioClient.WithStarkExSigner clientWithSigner = client.withStarkExSigner("0x4d55b547af138c5b6200495d86ab6aed3e06c25fdd75b4b6a00e48515df2b3d"); CompletableFuture> future = clientWithSigner.withdrawal("0x1c2847406b96310a32c379536374ec034b732633e8675860f20f4141e701ff4", "1", REDDIO721M_CONTRACT_ADDRESS, "7", "ERC721M", "0x76f2Fc7ed90039d986e3eb4DB294f05E160c8F03", 4194303L); ResponseWrapper result = future.get(); - Assert.assertEquals("OK", result.status); + Assert.assertEquals("OK", result.getStatus()); System.out.println(new ObjectMapper().writeValueAsString(result)); } @@ -91,31 +82,15 @@ public void testWithdrawalNTFERC721M() throws ExecutionException, InterruptedExc public void testOrder() throws ExecutionException, InterruptedException, JsonProcessingException { DefaultReddioClient client = DefaultReddioClient.testnet(); DefaultReddioRestClient restClient = DefaultReddioRestClient.testnet(); - CompletableFuture> balancesFuture = restClient.getBalances(GetBalancesMessage.of( - "0x1c2847406b96310a32c379536374ec034b732633e8675860f20f4141e701ff4", - REDDIO721_CONTRACT_ADDRESS, - 10L, - 1L) - ); + CompletableFuture> balancesFuture = restClient.getBalances(GetBalancesMessage.of("0x1c2847406b96310a32c379536374ec034b732633e8675860f20f4141e701ff4", REDDIO721_CONTRACT_ADDRESS, 10L, 1L)); ResponseWrapper balances = balancesFuture.get(); - Assert.assertEquals("OK", balances.status); - GetBalancesResponse.BalanceRecord toSell = balances.getData().getList().stream().filter((it) -> - it.getBalanceAvailable() > 0 - ).collect(Collectors.toList()).get(0); + Assert.assertEquals("OK", balances.getStatus()); + GetBalancesResponse.BalanceRecord toSell = balances.getData().getList().stream().filter((it) -> it.getBalanceAvailable() > 0).collect(Collectors.toList()).get(0); ReddioClient.WithStarkExSigner clientWithSigner = client.withStarkExSigner("0x4d55b547af138c5b6200495d86ab6aed3e06c25fdd75b4b6a00e48515df2b3d"); - CompletableFuture> future = clientWithSigner.order( - "0x1c2847406b96310a32c379536374ec034b732633e8675860f20f4141e701ff4", - "0.013", - "1", - REDDIO721_CONTRACT_ADDRESS, - toSell.getTokenId(), - "11ed793a-cc11-4e44-9738-97165c4e14a7", - "ERC721", - OrderBehavior.SELL - ); + CompletableFuture> future = clientWithSigner.order("0x1c2847406b96310a32c379536374ec034b732633e8675860f20f4141e701ff4", "0.013", "1", REDDIO721_CONTRACT_ADDRESS, toSell.getTokenId(), "11ed793a-cc11-4e44-9738-97165c4e14a7", "ERC721", OrderBehavior.SELL); ResponseWrapper result = future.get(); System.out.println(new ObjectMapper().writeValueAsString(result)); - Assert.assertEquals("OK", result.status); + Assert.assertEquals("OK", result.getStatus()); } @Test @@ -168,8 +143,8 @@ public void testListOrdersWithSequenceIds() throws ExecutionException, Interrupt Assert.assertEquals("OK", wrapper.getStatus()); Assert.assertEquals(2, wrapper.getData().getList().size()); Assert.assertEquals(2, wrapper.getData().getTotal().longValue()); - Assert.assertEquals(303531L, wrapper.getData().getList().get(0).getSequenceId()); - Assert.assertEquals(303530L, wrapper.getData().getList().get(1).getSequenceId()); + Assert.assertEquals(303531L, wrapper.getData().getList().get(0).getSequenceId().longValue()); + Assert.assertEquals(303530L, wrapper.getData().getList().get(1).getSequenceId().longValue()); } @Test @@ -177,33 +152,15 @@ public void testListOrdersWithSequenceIds() throws ExecutionException, Interrupt public void testOrderWithERC20() throws ExecutionException, InterruptedException, JsonProcessingException { DefaultReddioClient client = DefaultReddioClient.testnet(); DefaultReddioRestClient restClient = DefaultReddioRestClient.testnet(); - CompletableFuture> balancesFuture = restClient.getBalances(GetBalancesMessage.of( - "0x1c2847406b96310a32c379536374ec034b732633e8675860f20f4141e701ff4", - REDDIO721_CONTRACT_ADDRESS, - 100L, - 1L) - ); + CompletableFuture> balancesFuture = restClient.getBalances(GetBalancesMessage.of("0x1c2847406b96310a32c379536374ec034b732633e8675860f20f4141e701ff4", REDDIO721_CONTRACT_ADDRESS, 100L, 1L)); ResponseWrapper balances = balancesFuture.get(); - Assert.assertEquals("OK", balances.status); - GetBalancesResponse.BalanceRecord toSell = balances.getData().getList().stream().filter((it) -> - it.getBalanceAvailable() > 0 - ).collect(Collectors.toList()).get(0); + Assert.assertEquals("OK", balances.getStatus()); + GetBalancesResponse.BalanceRecord toSell = balances.getData().getList().stream().filter((it) -> it.getBalanceAvailable() > 0).collect(Collectors.toList()).get(0); ReddioClient.WithStarkExSigner clientWithSigner = client.withStarkExSigner("0x4d55b547af138c5b6200495d86ab6aed3e06c25fdd75b4b6a00e48515df2b3d"); - CompletableFuture> future = clientWithSigner.order( - "0x1c2847406b96310a32c379536374ec034b732633e8675860f20f4141e701ff4", - "ERC721", - REDDIO721_CONTRACT_ADDRESS, - toSell.getTokenId(), - "0.013", - "1", - OrderBehavior.SELL, - "ERC20", - RDD20_CONTRACT_ADDRESS, - "" - ); + CompletableFuture> future = clientWithSigner.order("0x1c2847406b96310a32c379536374ec034b732633e8675860f20f4141e701ff4", "ERC721", REDDIO721_CONTRACT_ADDRESS, toSell.getTokenId(), "0.013", "1", OrderBehavior.SELL, "ERC20", RDD20_CONTRACT_ADDRESS, ""); ResponseWrapper result = future.get(); System.out.println(new ObjectMapper().writeValueAsString(result)); - Assert.assertEquals("OK", result.status); + Assert.assertEquals("OK", result.getStatus()); } @Test @@ -212,15 +169,10 @@ public void testSellOrderWithRUSD() throws ExecutionException, InterruptedExcept DefaultReddioClient client = DefaultReddioClient.testnet(); DefaultReddioRestClient restClient = DefaultReddioRestClient.testnet(); ReddioClient.WithStarkExSigner clientWithSigner = client.withStarkExSigner("0x4d55b547af138c5b6200495d86ab6aed3e06c25fdd75b4b6a00e48515df2b3d"); - CompletableFuture> future = clientWithSigner.sellNFTWithRUSD("0x1c2847406b96310a32c379536374ec034b732633e8675860f20f4141e701ff4", - "ERC721", - REDDIO721_CONTRACT_ADDRESS, - "1210", - "0.013", - "1", ""); + CompletableFuture> future = clientWithSigner.sellNFTWithRUSD("0x1c2847406b96310a32c379536374ec034b732633e8675860f20f4141e701ff4", "ERC721", REDDIO721_CONTRACT_ADDRESS, "1210", "0.013", "1", ""); ResponseWrapper result = future.get(); System.out.println(new ObjectMapper().writeValueAsString(result)); - Assert.assertEquals("OK", result.status); + Assert.assertEquals("OK", result.getStatus()); } @Test @@ -229,39 +181,18 @@ public void testBuyOrderWithPayInfoBaseTokenRUSD() throws ExecutionException, In DefaultReddioClient client = DefaultReddioClient.testnet(); DefaultReddioRestClient restClient = DefaultReddioRestClient.testnet(); ReddioClient.WithStarkExSigner clientWithSigner = client.withStarkExSigner("5f6fbfbcd995e20f94a768193c42060f7e626e6ae8042cacc15e82031087a55"); - CompletableFuture> future = clientWithSigner.buyNFTWithPayInfoBaseTokenRUSD( - "0x13a69a1b7a5f033ee2358ebb8c28fd5a6b86d42e30a61845d655d3c7be4ad0e", - "ERC721", - REDDIO721_CONTRACT_ADDRESS, - "1209", - "0.013", - "1", - "", - Payment.PayInfo.of("123456789"), - "0x1a35ffa8bafc5c6656271bcae1f847bb6201705d7e2895c413cfb7d757a3111" - ); + CompletableFuture> future = clientWithSigner.buyNFTWithPayInfoBaseTokenRUSD("0x13a69a1b7a5f033ee2358ebb8c28fd5a6b86d42e30a61845d655d3c7be4ad0e", "ERC721", REDDIO721_CONTRACT_ADDRESS, "1209", "0.013", "1", "", Payment.PayInfo.of("123456789"), "0x1a35ffa8bafc5c6656271bcae1f847bb6201705d7e2895c413cfb7d757a3111"); ResponseWrapper result = future.get(); System.out.println(new ObjectMapper().writeValueAsString(result)); - Assert.assertEquals("OK", result.status); + Assert.assertEquals("OK", result.getStatus()); } @Test @Ignore("example usages, not a test") public void testGetSign() { - BigInteger hash = PaymentSHA3.getPaymentHash( - Payment.of( - Payment.PayInfo.of("123456789"), - "" - ), - 2 - ); + BigInteger hash = PaymentSHA3.getPaymentHash(Payment.of(Payment.PayInfo.of("123456789"), ""), 2); System.out.println("hash: 0x" + hash.toString(16)); - Signature sign = CryptoService.sign( - new BigInteger( - "0x1a35ffa8bafc5c6656271bcae1f847bb6201705d7e2895c413cfb7d757a3111".replace("0x", "").toLowerCase(), - 16 - ), hash, null - ); + Signature sign = CryptoService.sign(new BigInteger("0x1a35ffa8bafc5c6656271bcae1f847bb6201705d7e2895c413cfb7d757a3111".replace("0x", "").toLowerCase(), 16), hash, null); System.out.println("r: 0x" + sign.r); System.out.println("s: 0x" + sign.s); } @@ -274,7 +205,7 @@ public void testCancelOrder() throws ExecutionException, InterruptedException, J CompletableFuture> future = withStarkExSigner.cancelOrder("0x1c2847406b96310a32c379536374ec034b732633e8675860f20f4141e701ff4", 303590); ResponseWrapper result = future.get(); System.out.println(new ObjectMapper().writeValueAsString(result)); - Assert.assertEquals("OK", result.status); + Assert.assertEquals("OK", result.getStatus()); } @Test @@ -284,20 +215,92 @@ public void testMints() throws ExecutionException, InterruptedException, JsonPro CompletableFuture> future = client.mints("0x113536494406bc039586c1ad9b8f51af664d6ef8", "0x1c2847406b96310a32c379536374ec034b732633e8675860f20f4141e701ff4", 1); ResponseWrapper result = future.get(); System.out.println(new ObjectMapper().writeValueAsString(result)); - Assert.assertEquals("OK", result.status); + Assert.assertEquals("OK", result.getStatus()); } @Test - @Ignore("example usages, not a test, require api key") - public void testMintWithCertainTokenIds() throws ExecutionException, InterruptedException, JsonProcessingException { -// DefaultReddioClient client = DefaultReddioClient.testnet(""); + public void testMintWithInvalidAmount() { + DefaultReddioClient client = DefaultReddioClient.testnet("rk-1236d5fc-f4c1-4a19-a2ff-9c29e3a70e37"); + try { + CompletableFuture> future = client.mints("0x113536494406bc039586c1ad9b8f51af664d6ef8", "0x1c2847406b96310a32c379536374ec034b732633e8675860f20f4141e701ff4", -1); + future.join(); + Assert.fail(); + } catch (CompletionException e) { + Assert.assertEquals(ReddioErrorCode.MintAmountInvalid, ((ReddioBusinessException) e.getCause()).getErrorCode()); + } + } + + @Test + public void testMintMintAgainWithSameTokenId() throws ExecutionException, InterruptedException, JsonProcessingException { DefaultReddioClient client = DefaultReddioClient.testnet("rk-1236d5fc-f4c1-4a19-a2ff-9c29e3a70e37"); List tokenIds = new ArrayList<>(); tokenIds.add(300L); - tokenIds.add(301L); - CompletableFuture> future = client.mints("0x113536494406bc039586c1ad9b8f51af664d6ef8", "0x1c2847406b96310a32c379536374ec034b732633e8675860f20f4141e701ff4", tokenIds); - ResponseWrapper result = future.get(); - System.out.println(new ObjectMapper().writeValueAsString(result)); - Assert.assertEquals("OK", result.status); + try { + CompletableFuture> future = client.mints("0x113536494406bc039586c1ad9b8f51af664d6ef8", "0x1c2847406b96310a32c379536374ec034b732633e8675860f20f4141e701ff4", tokenIds); + future.join(); + Assert.fail(); + } catch (CompletionException e) { + Assert.assertEquals(ReddioErrorCode.TokenIDInvalid, ((ReddioBusinessException) e.getCause()).getErrorCode()); + } + } + + @Test + public void testTransferForNotSuchToken() { + final BigInteger senderPrivateKey = CryptoService.getRandomPrivateKey(); + final BigInteger receiverPrivateKey = CryptoService.getRandomPrivateKey(); + try { + ReddioTransferToApi.transferERC721( + DefaultReddioRestClient.testnet(), + "0x" + senderPrivateKey.toString(16), + "0x941661Bd1134DC7cc3D107BF006B8631F6E65Ad5", + "9999999", + "ERC721", + "0x" + receiverPrivateKey.toString(16), + 4194303L + ).callAndPollRecord(); + Assert.fail(); + } catch (Throwable t) { + Assert.assertEquals(ReddioErrorCode.NotSuchToken, ((ReddioBusinessException) t).getErrorCode()); + } + } + + @Test + public void testWithdrawalForNotSuchToken() { + final BigInteger senderPrivateKey = CryptoService.getRandomPrivateKey(); + final BigInteger receiverPrivateKey = CryptoService.getRandomPrivateKey(); + try { + ReddioWithdrawalToApi.withdrawalERC721( + DefaultReddioRestClient.testnet(), + "0x" + senderPrivateKey.toString(16), + "0x941661Bd1134DC7cc3D107BF006B8631F6E65Ad5", + "9999999", + "ERC721", + "0x" + receiverPrivateKey.toString(16), + 4194303L + ).callAndPollRecord(); + Assert.fail(); + } catch (Throwable t) { + Assert.assertEquals(ReddioErrorCode.NotSuchToken, ((ReddioBusinessException) t).getErrorCode()); + } + } + + @Test + public void testOrderForNoSuchToken() { + final BigInteger buyerPrivateKey = CryptoService.getRandomPrivateKey(); + final BigInteger receiverPrivateKey = CryptoService.getRandomPrivateKey(); + try { + ReddioOrderApi.orderWithETH( + DefaultReddioRestClient.testnet(), + "0x" + buyerPrivateKey.toString(16), + "ERC721", + "0x941661Bd1134DC7cc3D107BF006B8631F6E65Ad5", + "99999", + "0.01", + "1", + OrderBehavior.BUY + ).callAndPollOrder(); + } catch (Throwable t) { + Assert.assertEquals(ReddioErrorCode.NotSuchToken, ((ReddioBusinessException) t).getErrorCode()); + } } } diff --git a/reddio-java/reddio-api/src/test/java/com/reddio/api/v1/rest/DefaultReddioRestClientTest.java b/reddio-java/reddio-api/src/test/java/com/reddio/api/v1/rest/DefaultReddioRestClientTest.java index 8c4f5f4..76fd360 100644 --- a/reddio-java/reddio-api/src/test/java/com/reddio/api/v1/rest/DefaultReddioRestClientTest.java +++ b/reddio-java/reddio-api/src/test/java/com/reddio/api/v1/rest/DefaultReddioRestClientTest.java @@ -1,55 +1,60 @@ package com.reddio.api.v1.rest; import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; -import junit.framework.TestCase; +import com.reddio.exception.ReddioBusinessException; +import com.reddio.exception.ReddioErrorCode; +import com.reddio.exception.ReddioServiceException; +import okhttp3.Protocol; +import okhttp3.Request; +import okhttp3.Response; import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; import java.util.concurrent.ExecutionException; import static com.reddio.api.v1.DefaultEthereumInteractionTest.REDDIO721_CONTRACT_ADDRESS; -public class DefaultReddioRestClientTest extends TestCase { +public class DefaultReddioRestClientTest { + @Test public void testGetRecord() throws ExecutionException, InterruptedException { DefaultReddioRestClient client = DefaultReddioRestClient.testnet(); - ResponseWrapper response = client.getRecord( - GetRecordMessage.of("0x6736f7449da3bf44bf0f7bdd6463818e1ef272641d43021e8bca17b32ec2df0", 300523L)).get(); - Assert.assertEquals(RecordStatus.AcceptedByReddio, response.data.get(0).status); + ResponseWrapper response = client.getRecord(GetRecordMessage.of("0x6736f7449da3bf44bf0f7bdd6463818e1ef272641d43021e8bca17b32ec2df0", 300523L)).get(); + Assert.assertEquals(RecordStatus.AcceptedByReddio, response.getData().get(0).status); } + @Test public void testGetTxn() throws ExecutionException, InterruptedException { DefaultReddioRestClient client = DefaultReddioRestClient.testnet(); - ResponseWrapper response = client.getTxn( - GetTxnMessage.of(300523L)).get(); - Assert.assertEquals(RecordStatus.AcceptedByReddio, response.data.get(0).status); + ResponseWrapper response = client.getTxn(GetTxnMessage.of(300523L)).get(); + Assert.assertEquals(RecordStatus.AcceptedByReddio, response.getData().get(0).status); } + @Test public void testOrderList() throws ExecutionException, InterruptedException { DefaultReddioRestClient client = DefaultReddioRestClient.testnet(); - CompletableFuture> future = client.orderList(OrderListMessage.of( - "0x1c2847406b96310a32c379536374ec034b732633e8675860f20f4141e701ff4", - REDDIO721_CONTRACT_ADDRESS, - null, - null, - null, - null, - null)); + CompletableFuture> future = client.orderList(OrderListMessage.of("0x1c2847406b96310a32c379536374ec034b732633e8675860f20f4141e701ff4", REDDIO721_CONTRACT_ADDRESS, null, null, null, null, null)); ResponseWrapper result = future.get(); - Assert.assertEquals("OK", result.status); + Assert.assertEquals("OK", result.getStatus()); } + @Test public void testStarexContract() throws JsonProcessingException, ExecutionException, InterruptedException { DefaultReddioRestClient client = DefaultReddioRestClient.testnet(); CompletableFuture> future = client.starexContracts(); ResponseWrapper result = future.get(); - Assert.assertEquals("OK", result.status); + Assert.assertEquals("OK", result.getStatus()); ObjectMapper objectMapper = new ObjectMapper(); String jsonContent = objectMapper.writeValueAsString(result); System.out.println(jsonContent); } + @Test public void testGetRecordBySignature() throws ExecutionException, InterruptedException { DefaultReddioRestClient restClient = DefaultReddioRestClient.testnet(); ResponseWrapper wrapper = restClient.getRecordBySignature(Signature.of("0x603893549d9fbb1d710ca68f2e44aa8ae2f7c4353219cb662d94e48971dd15f", "0x7556a28be6f49fa896077b3bd96f909e07a226392e2af93852e4ecd8d56814d")).get(); @@ -59,10 +64,10 @@ public void testGetRecordBySignature() throws ExecutionException, InterruptedExc SequenceRecord record = wrapper.getData().get(0); Assert.assertEquals("1", record.getAmount()); Assert.assertEquals(RecordType.ASKOrderRecordType, record.getRecordType()); - Assert.assertEquals(304287L, record.getSequenceId()); + Assert.assertEquals(304287L, record.getSequenceId().longValue()); Assert.assertEquals("0x1ccc27877014bc1a81919fc855ebbd1b874603283c9ea93397d970b0704e581", record.getStarkKey()); Assert.assertEquals(RecordStatus.AcceptedByReddio, record.getStatus()); - Assert.assertEquals(1676261428L, record.getTime()); + Assert.assertEquals(1676261428L, record.getTime().longValue()); SequenceRecord.Order order = record.getOrder(); @@ -85,6 +90,7 @@ public void testGetRecordBySignature() throws ExecutionException, InterruptedExc } + @Test public void testGetRecordBySignature2() throws ExecutionException, InterruptedException { DefaultReddioRestClient restClient = DefaultReddioRestClient.testnet(); ResponseWrapper wrapper = restClient.getRecordBySignature(Signature.of("0x6314640fa3955fec989b9c8e85446d3f10fffad4f2df8b3a1f90d75e9649804", "0x70514b88e78028eacdaad5583bda1ecfd93d4fbe5f65eadaeb42e94201662e9")).get(); @@ -99,12 +105,107 @@ public void testGetRecordBySignature2() throws ExecutionException, InterruptedEx Assert.assertEquals("0x941661bd1134dc7cc3d107bf006b8631f6e65ad5", record.getContractAddress()); Assert.assertEquals("1", record.getDisplayValue()); Assert.assertEquals(RecordType.WithdrawRecordType, record.getRecordType()); - Assert.assertEquals(304312L, record.getSequenceId()); + Assert.assertEquals(304312L, record.getSequenceId().longValue()); Assert.assertEquals("0x7865bc66b610d6196a7cbeb9bf066c64984f6f06b5ed3b6f5788bd9a6cb099c", record.getStarkKey()); Assert.assertEquals(RecordStatus.AcceptedOnL1, record.getStatus()); - Assert.assertEquals(1676351391L, record.getTime()); - + Assert.assertEquals(1676351391L, record.getTime().longValue()); Assert.assertNull(record.getOrder()); } -} \ No newline at end of file + + @Test + public void testEnsureSuccess() { + ResponseWrapper wrapper = new ResponseWrapper<>(); + wrapper.setStatus("OK"); + DefaultReddioRestClient.ensureSuccess(wrapper); + } + + @Test + public void testEnsureSuccessWithFailure() { + ResponseWrapper wrapper = new ResponseWrapper<>(); + wrapper.setStatus("FAIL"); + wrapper.setErrorCode(ReddioErrorCode.NoMintableToken.getCode()); + try { + DefaultReddioRestClient.ensureSuccess(wrapper); + Assert.fail(); + } catch (ReddioBusinessException e) { + Assert.assertEquals(ReddioErrorCode.NoMintableToken, e.getErrorCode()); + } + } + + @Test + public void testEnsureSuccessWithUnrecognizedErrorCode() { + ResponseWrapper wrapper = new ResponseWrapper<>(); + wrapper.setStatus("FAIL"); + wrapper.setErrorCode(9999); + try { + DefaultReddioRestClient.ensureSuccess(wrapper); + Assert.fail(); + } catch (ReddioBusinessException e) { + Assert.assertNull(e.getErrorCode()); + Assert.assertEquals(9999, e.getResponse().getErrorCode().intValue()); + } catch (Throwable t) { + Assert.fail(); + } + } + + @Test + public void testToCompletableFutureCallbackOnResponse() { + CompletableFuture> future = new CompletableFuture<>(); + final DefaultReddioRestClient.ToCompletableFutureCallback callback = new DefaultReddioRestClient.ToCompletableFutureCallback(future, new TypeReference>() { + }); + final Request stubRequest = new Request.Builder().url("http://fake-url").build(); + final Response r = new Response.Builder().code(400).request(stubRequest).protocol(Protocol.HTTP_1_1).message("").build(); + callback.onResponse(null, r); + try { + future.join(); + Assert.fail(); + } catch (CompletionException e) { + final Throwable cause = e.getCause(); + Assert.assertTrue(cause instanceof ReddioServiceException); + Assert.assertEquals(400, ((ReddioServiceException) cause).getHttpStatusCode()); + } catch (Throwable t) { + Assert.fail(); + } + } + + @Test + public void testToCompletableFutureCallbackOnResponseUnrecognizedCode() { + CompletableFuture> future = new CompletableFuture<>(); + final DefaultReddioRestClient.ToCompletableFutureCallback callback = new DefaultReddioRestClient.ToCompletableFutureCallback(future, new TypeReference>() { + }); + final Request stubRequest = new Request.Builder().url("http://fake-url").build(); + final Response r = new Response.Builder().code(503).request(stubRequest).protocol(Protocol.HTTP_1_1).message("").build(); + callback.onResponse(null, r); + try { + future.join(); + Assert.fail(); + } catch (CompletionException e) { + final Throwable cause = e.getCause(); + Assert.assertTrue(cause instanceof ReddioServiceException); + Assert.assertEquals(503, ((ReddioServiceException) cause).getHttpStatusCode()); + } catch (Throwable t) { + Assert.fail(); + } + } + + @Test + @Ignore("Waiting backend update") + public void testMintWithInvalidApiKey() { + final DefaultReddioRestClient restClient = DefaultReddioRestClient.testnet("not a real api key"); + try { + restClient.mints( + MintsMessage.of( + "", + "", + "1" + ) + ).join(); + } catch (CompletionException e) { + final Throwable cause = e.getCause(); + Assert.assertTrue(cause instanceof ReddioServiceException); + Assert.assertEquals(403, ((ReddioServiceException) cause).getHttpStatusCode()); + Assert.assertEquals(ReddioErrorCode.InvalidAPIKey, ((ReddioServiceException) cause).getErrorCode()); + } + } +}