Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@
* @see <a href="https://docs.kraken.com/rest/">Kraken REST API documentation</a>
*/
@Builder(toBuilder = true)
@SuppressWarnings("java:S6539")
public class KrakenAPI {

private final KrakenCredentials credentials;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ public class WalletAccountsParams extends PostParams {

@Override
protected Map<String, String> params() {
Map<String, String> params = new HashMap<>();
return params;
return new HashMap<>();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public DepositLimit deserialize(JsonParser parser, DeserializationContext contex
try {
return new DepositLimit(new BigDecimal(parser.getText()), false);
}
catch (NumberFormatException e) {
catch (NumberFormatException _) {
return context.reportInputMismatch(DepositLimit.class, "Expected a decimal deposit limit or false");
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public Map<String, String> toMap() {
*
* @return the body parameters, or {@code null} for an endpoint sending no body
*/
@SuppressWarnings("java:S1168")
protected Map<String, Object> body() {
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,10 @@ protected Map<String, Object> body() {
body.put("scope", scope.json());
body.put("address_id", addressId);
body.put("amount", rebasable("asset_amount", amount.json()));
putIfNonNull(body, "fee", fee());
Map<String, Object> fee = fee();
if (!fee.isEmpty()) {
body.put("fee", fee);
}
putIfNonNull(body, "expected_address", expectedAddress);
return body;
}
Expand All @@ -95,7 +98,7 @@ private Map<String, Object> fee() {
throw new IllegalArgumentException("Specify at most one of withdrawalFeeToken or maxFee");
}
if (withdrawalFeeToken == null && maxFee == null && feeIncluded == null) {
return null;
return Map.of();
}
if (feeIncluded == null) {
throw new IllegalArgumentException("feeIncluded is required with withdrawalFeeToken or maxFee");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public LimitValue deserialize(JsonParser parser, DeserializationContext context)
try {
return new LimitValue(Long.valueOf(parser.getText()), null);
}
catch (NumberFormatException e) {
catch (NumberFormatException _) {
return context.reportInputMismatch(LimitValue.class, "Expected a count or limit amounts");
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public abstract class JsonPostParams extends PostParams {
@Override
protected String encode(Map<String, Object> params) {
String nonce = (String) params.get("nonce");
BigInteger numericNonce = nonce != null && nonce.matches("0|[1-9][0-9]{0,19}") ? new BigInteger(nonce) : null;
BigInteger numericNonce = nonce != null && nonce.matches("0|[1-9]\\d{0,19}") ? new BigInteger(nonce) : null;
if (numericNonce == null || numericNonce.bitLength() > 64) {
throw new IllegalStateException("%s requires KrakenNonceGenerator to return an unsigned 64-bit integer in canonical decimal form".formatted(getClass().getSimpleName()));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public abstract class PostParams {
*
* @return the POST parameters
*/
@SuppressWarnings("java:S1452")
protected abstract Map<String, ?> params();

private String nonce;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
@Slf4j
public class DefaultKrakenRestRequester implements KrakenRestRequester {

private static final String CONTENT_TYPE = "Content-Type";
private static final ObjectMapper OBJECT_MAPPER;

static {
Expand Down Expand Up @@ -91,7 +92,7 @@ public <T> T execute(PrivateEndpoint<T> endpoint, KrakenCredentials credentials,
log.info("Fetching private endpoint: {}", connection.getURL());
connection.addRequestProperty("API-Key", credentials.getKey());
connection.addRequestProperty("API-Sign", credentials.sign(connection.getURL(), nonce, postData));
connection.addRequestProperty("Content-Type", endpoint.getContentType());
connection.addRequestProperty(CONTENT_TYPE, endpoint.getContentType());
connection.setDoOutput(true);

try (OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream())) {
Expand Down Expand Up @@ -124,7 +125,7 @@ public <T> T execute(FundingBetaEndpoint<T> endpoint, KrakenCredentials credenti
connection.addRequestProperty("API-Nonce", nonce);

if (!body.isEmpty()) {
connection.addRequestProperty("Content-Type", endpoint.getContentType());
connection.addRequestProperty(CONTENT_TYPE, endpoint.getContentType());
connection.setDoOutput(true);

try (OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream(), StandardCharsets.UTF_8)) {
Expand All @@ -147,7 +148,7 @@ private <T> HttpsURLConnection createHttpsConnection(Endpoint<T> endpoint) throw
}

private static <T> T parseResponse(HttpsURLConnection connection, Endpoint<T> endpoint) throws IOException {
String contentType = connection.getHeaderField("Content-Type");
String contentType = connection.getHeaderField(CONTENT_TYPE);
if ("application/json".equals(contentType)) {
JavaType krakenResponseType = endpoint.wrappedResponseType(OBJECT_MAPPER.getTypeFactory());
KrakenResponse<T> response = OBJECT_MAPPER.readValue(connection.getInputStream(), krakenResponseType);
Expand All @@ -169,7 +170,7 @@ private static <T> T parseFundingResponse(HttpsURLConnection connection, Funding
throw new KrakenException(List.of("HTTP %d %s".formatted(status, readErrorBody(connection)).strip()));
}

String contentType = connection.getHeaderField("Content-Type");
String contentType = connection.getHeaderField(CONTENT_TYPE);
if (contentType == null || !contentType.startsWith("application/json")) {
throw new IllegalStateException("Unsupported HTTP Content-Type");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ void should_route_accountBalance_defaults_when_called() {
void should_reject_accountBalance_when_credentials_are_missing() {
KrakenAPI unit = new KrakenAPI(null, nonceGenerator, requester);

assertThatThrownBy(() -> unit.accountBalance()).isInstanceOf(IllegalStateException.class);
assertThatThrownBy(unit::accountBalance).isInstanceOf(IllegalStateException.class);
verifyNoInteractions(requester);
}

Expand Down Expand Up @@ -156,7 +156,7 @@ void should_route_extendedBalance_defaults_when_called() {
void should_reject_extendedBalance_when_credentials_are_missing() {
KrakenAPI unit = new KrakenAPI(null, nonceGenerator, requester);

assertThatThrownBy(() -> unit.extendedBalance()).isInstanceOf(IllegalStateException.class);
assertThatThrownBy(unit::extendedBalance).isInstanceOf(IllegalStateException.class);
verifyNoInteractions(requester);
}

Expand Down Expand Up @@ -189,7 +189,7 @@ void should_route_creditLines_defaults_when_called() {
void should_reject_creditLines_when_credentials_are_missing() {
KrakenAPI unit = new KrakenAPI(null, nonceGenerator, requester);

assertThatThrownBy(() -> unit.creditLines()).isInstanceOf(IllegalStateException.class);
assertThatThrownBy(unit::creditLines).isInstanceOf(IllegalStateException.class);
verifyNoInteractions(requester);
}

Expand Down Expand Up @@ -222,7 +222,7 @@ void should_route_tradeBalance_defaults_when_called() {
void should_reject_tradeBalance_when_credentials_are_missing() {
KrakenAPI unit = new KrakenAPI(null, nonceGenerator, requester);

assertThatThrownBy(() -> unit.tradeBalance()).isInstanceOf(IllegalStateException.class);
assertThatThrownBy(unit::tradeBalance).isInstanceOf(IllegalStateException.class);
verifyNoInteractions(requester);
}

Expand Down Expand Up @@ -255,7 +255,7 @@ void should_route_openOrders_defaults_when_called() {
void should_reject_openOrders_when_credentials_are_missing() {
KrakenAPI unit = new KrakenAPI(null, nonceGenerator, requester);

assertThatThrownBy(() -> unit.openOrders()).isInstanceOf(IllegalStateException.class);
assertThatThrownBy(unit::openOrders).isInstanceOf(IllegalStateException.class);
verifyNoInteractions(requester);
}

Expand Down Expand Up @@ -288,7 +288,7 @@ void should_route_closedOrders_defaults_when_called() {
void should_reject_closedOrders_when_credentials_are_missing() {
KrakenAPI unit = new KrakenAPI(null, nonceGenerator, requester);

assertThatThrownBy(() -> unit.closedOrders()).isInstanceOf(IllegalStateException.class);
assertThatThrownBy(unit::closedOrders).isInstanceOf(IllegalStateException.class);
verifyNoInteractions(requester);
}

Expand Down Expand Up @@ -342,7 +342,7 @@ void should_route_orderAmends_defaults_when_called() {
void should_reject_orderAmends_when_credentials_are_missing() {
KrakenAPI unit = new KrakenAPI(null, nonceGenerator, requester);

assertThatThrownBy(() -> unit.orderAmends()).isInstanceOf(IllegalStateException.class);
assertThatThrownBy(unit::orderAmends).isInstanceOf(IllegalStateException.class);
verifyNoInteractions(requester);
}

Expand Down Expand Up @@ -375,7 +375,7 @@ void should_route_tradesHistory_defaults_when_called() {
void should_reject_tradesHistory_when_credentials_are_missing() {
KrakenAPI unit = new KrakenAPI(null, nonceGenerator, requester);

assertThatThrownBy(() -> unit.tradesHistory()).isInstanceOf(IllegalStateException.class);
assertThatThrownBy(unit::tradesHistory).isInstanceOf(IllegalStateException.class);
verifyNoInteractions(requester);
}

Expand Down Expand Up @@ -427,7 +427,7 @@ void should_route_openPositions_defaults_when_called() {
void should_reject_openPositions_when_credentials_are_missing() {
KrakenAPI unit = new KrakenAPI(null, nonceGenerator, requester);

assertThatThrownBy(() -> unit.openPositions()).isInstanceOf(IllegalStateException.class);
assertThatThrownBy(unit::openPositions).isInstanceOf(IllegalStateException.class);
verifyNoInteractions(requester);
}

Expand Down Expand Up @@ -460,7 +460,7 @@ void should_route_tradeVolume_defaults_when_called() {
void should_reject_tradeVolume_when_credentials_are_missing() {
KrakenAPI unit = new KrakenAPI(null, nonceGenerator, requester);

assertThatThrownBy(() -> unit.tradeVolume()).isInstanceOf(IllegalStateException.class);
assertThatThrownBy(unit::tradeVolume).isInstanceOf(IllegalStateException.class);
verifyNoInteractions(requester);
}

Expand Down Expand Up @@ -493,7 +493,7 @@ void should_route_apiKeyInfo_defaults_when_called() {
void should_reject_apiKeyInfo_when_credentials_are_missing() {
KrakenAPI unit = new KrakenAPI(null, nonceGenerator, requester);

assertThatThrownBy(() -> unit.apiKeyInfo()).isInstanceOf(IllegalStateException.class);
assertThatThrownBy(unit::apiKeyInfo).isInstanceOf(IllegalStateException.class);
verifyNoInteractions(requester);
}

Expand Down Expand Up @@ -526,7 +526,7 @@ void should_route_walletAccounts_defaults_when_called() {
void should_reject_walletAccounts_when_credentials_are_missing() {
KrakenAPI unit = new KrakenAPI(null, nonceGenerator, requester);

assertThatThrownBy(() -> unit.walletAccounts()).isInstanceOf(IllegalStateException.class);
assertThatThrownBy(unit::walletAccounts).isInstanceOf(IllegalStateException.class);
verifyNoInteractions(requester);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ void should_route_earnStrategies_defaults_when_called() {
void should_reject_earnStrategies_when_credentials_are_missing() {
KrakenAPI unit = new KrakenAPI(null, nonceGenerator, requester);

assertThatThrownBy(() -> unit.earnStrategies()).isInstanceOf(IllegalStateException.class).hasMessageContaining("Earn/Strategies");
assertThatThrownBy(unit::earnStrategies).isInstanceOf(IllegalStateException.class).hasMessageContaining("Earn/Strategies");
verifyNoInteractions(requester);
}

Expand Down Expand Up @@ -104,7 +104,7 @@ void should_route_earnAllocations_defaults_when_called() {
void should_reject_earnAllocations_when_credentials_are_missing() {
KrakenAPI unit = new KrakenAPI(null, nonceGenerator, requester);

assertThatThrownBy(() -> unit.earnAllocations()).isInstanceOf(IllegalStateException.class).hasMessageContaining("Earn/Allocations");
assertThatThrownBy(unit::earnAllocations).isInstanceOf(IllegalStateException.class).hasMessageContaining("Earn/Allocations");
verifyNoInteractions(requester);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ void should_route_depositStatus_defaults_when_called() {
void should_reject_depositStatus_when_credentials_are_missing() {
KrakenAPI unit = new KrakenAPI(null, nonceGenerator, requester);

assertThatThrownBy(() -> unit.depositStatus()).isInstanceOf(IllegalStateException.class);
assertThatThrownBy(unit::depositStatus).isInstanceOf(IllegalStateException.class);
verifyNoInteractions(requester);
}

Expand Down Expand Up @@ -164,7 +164,7 @@ void should_route_withdrawalMethods_defaults_when_called() {
void should_reject_withdrawalMethods_when_credentials_are_missing() {
KrakenAPI unit = new KrakenAPI(null, nonceGenerator, requester);

assertThatThrownBy(() -> unit.withdrawalMethods()).isInstanceOf(IllegalStateException.class);
assertThatThrownBy(unit::withdrawalMethods).isInstanceOf(IllegalStateException.class);
verifyNoInteractions(requester);
}

Expand Down Expand Up @@ -195,7 +195,7 @@ void should_route_withdrawalAddresses_defaults_when_called() {
void should_reject_withdrawalAddresses_when_credentials_are_missing() {
KrakenAPI unit = new KrakenAPI(null, nonceGenerator, requester);

assertThatThrownBy(() -> unit.withdrawalAddresses()).isInstanceOf(IllegalStateException.class);
assertThatThrownBy(unit::withdrawalAddresses).isInstanceOf(IllegalStateException.class);
verifyNoInteractions(requester);
}

Expand Down Expand Up @@ -272,7 +272,7 @@ void should_route_withdrawalStatus_defaults_when_called() {
void should_reject_withdrawalStatus_when_credentials_are_missing() {
KrakenAPI unit = new KrakenAPI(null, nonceGenerator, requester);

assertThatThrownBy(() -> unit.withdrawalStatus()).isInstanceOf(IllegalStateException.class);
assertThatThrownBy(unit::withdrawalStatus).isInstanceOf(IllegalStateException.class);
verifyNoInteractions(requester);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ void should_deserialize_typed_response_when_reading_kraken_fixture() throws Exce
assertThat(result.size()).isEqualTo(2);
assertThat(result.hasNext()).isFalse();
assertThat(result.asList()).extracting(LedgerEntry::id).containsExactlyInAnyOrder("L4UESK-KG3EQ-UFO4T5", "LMKZCZ-Z3GVL-CXKK4H");
assertThat(result.entries().get("L4UESK-KG3EQ-UFO4T5")).isEqualTo(new LedgerEntry(null, "TJKLXF-PGMUI-4NTLXU",
assertThat(result.entries()).containsEntry("L4UESK-KG3EQ-UFO4T5", new LedgerEntry(null, "TJKLXF-PGMUI-4NTLXU",
Instant.ofEpochSecond(1688464484L, 178_700_000L), LedgerEntry.Type.TRADE, "", "currency", null, "ZGBP", null,
new BigDecimal("-24.5000"), new BigDecimal("0.0490"), new BigDecimal("459567.9171")));
assertThat(result.entries().get("L4UESK-KG3EQ-UFO4T5").netAmount()).isEqualByComparingTo("-24.5490");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ void should_encode_all_options_when_supplied() {

@Test
void should_reject_missing_transactionIds_when_building_parameters() {
assertThatThrownBy(() -> QueryOrdersParams.builder().build()).isInstanceOf(NullPointerException.class).hasMessageContaining("transactionIds");
QueryOrdersParams.QueryOrdersParamsBuilder builder = QueryOrdersParams.builder();

assertThatThrownBy(builder::build).isInstanceOf(NullPointerException.class).hasMessageContaining("transactionIds");
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@ void should_encode_all_options_when_supplied() {

@Test
void should_reject_missing_transactionIds_when_building_parameters() {
assertThatThrownBy(() -> QueryTradesParams.builder().build()).isInstanceOf(NullPointerException.class).hasMessageContaining("transactionIds");
QueryTradesParams.QueryTradesParamsBuilder builder = QueryTradesParams.builder();

assertThatThrownBy(builder::build).isInstanceOf(NullPointerException.class).hasMessageContaining("transactionIds");
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ void should_preserve_unsigned_nonce_when_encoding_its_maximum_value() throws Exc
}

@Test
void should_reuse_json_encoding_when_parameters_are_encoded_directly() throws Exception {
void should_reuse_json_encoding_when_parameters_are_encoded_directly() {
TradeVolumeParams params = TradeVolumeParams.builder().pairs(List.of("XBTUSD")).feeSchedule(true).build();
TradeVolumeEndpoint unit = new TradeVolumeEndpoint(params);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,16 @@ void should_encode_all_options_when_supplied() {

@Test
void should_reject_missing_asset_when_building_parameters() {
assertThatThrownBy(() -> CancelWithdrawalParams.builder().referenceId("id +/&=").build()).isInstanceOf(NullPointerException.class).hasMessageContaining("asset");
CancelWithdrawalParams.CancelWithdrawalParamsBuilder builder = CancelWithdrawalParams.builder().referenceId("id +/&=");

assertThatThrownBy(builder::build).isInstanceOf(NullPointerException.class).hasMessageContaining("asset");
}

@Test
void should_reject_missing_referenceId_when_building_parameters() {
assertThatThrownBy(() -> CancelWithdrawalParams.builder().asset("id +/&=").build()).isInstanceOf(NullPointerException.class).hasMessageContaining("referenceId");
CancelWithdrawalParams.CancelWithdrawalParamsBuilder builder = CancelWithdrawalParams.builder().asset("id +/&=");

assertThatThrownBy(builder::build).isInstanceOf(NullPointerException.class).hasMessageContaining("referenceId");
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,16 @@ void should_encode_all_options_when_supplied() {

@Test
void should_reject_missing_asset_when_building_parameters() {
assertThatThrownBy(() -> DepositAddressesParams.builder().method("id +/&=").build()).isInstanceOf(NullPointerException.class).hasMessageContaining("asset");
DepositAddressesParams.DepositAddressesParamsBuilder builder = DepositAddressesParams.builder().method("id +/&=");

assertThatThrownBy(builder::build).isInstanceOf(NullPointerException.class).hasMessageContaining("asset");
}

@Test
void should_reject_missing_method_when_building_parameters() {
assertThatThrownBy(() -> DepositAddressesParams.builder().asset("id +/&=").build()).isInstanceOf(NullPointerException.class).hasMessageContaining("method");
DepositAddressesParams.DepositAddressesParamsBuilder builder = DepositAddressesParams.builder().asset("id +/&=");

assertThatThrownBy(builder::build).isInstanceOf(NullPointerException.class).hasMessageContaining("method");
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@ void should_encode_all_options_when_supplied() {

@Test
void should_reject_missing_asset_when_building_parameters() {
assertThatThrownBy(() -> DepositMethodsParams.builder().build()).isInstanceOf(NullPointerException.class).hasMessageContaining("asset");
DepositMethodsParams.DepositMethodsParamsBuilder builder = DepositMethodsParams.builder();

assertThatThrownBy(builder::build).isInstanceOf(NullPointerException.class).hasMessageContaining("asset");
}

@Test
Expand Down
Loading
Loading