Skip to content

Commit

Permalink
feat!: ability to specify custom nonce generator (#16)
Browse files Browse the repository at this point in the history
  • Loading branch information
nyg committed Mar 28, 2024
1 parent ab3c048 commit 7bc46b8
Show file tree
Hide file tree
Showing 46 changed files with 185 additions and 162 deletions.
16 changes: 12 additions & 4 deletions README.md
Expand Up @@ -84,7 +84,17 @@ KrakenAPI api = new KrakenAPI(MyRestTemplateRestRequest(apiKey, apiSecret));

See `DefaultKrakenRestRequester` for the default implementation.

### Custom nonce generator (not yet implemented)
### Custom nonce generator

For private endpoint requests, the nonce value is set to `System.currentTimeMillis()`. If you wish to use another value, you can specify a custom nonce generator when creating the `KrakenAPI` instance:

```java
KrakenAPI api = new KrakenAPI(
new KrakenCredentials(key, secret),
() -> Long.toString(System.currentTimeMillis() / 1000));
```

The second parameter is of type `KrakenNonceGenerator`, an interface containing a single `generate()` method returning a string.

## Examples

Expand All @@ -98,11 +108,9 @@ mvn clean install

# run example classes
mvn -q -pl examples exec:java -Dexec.mainClass=dev.andstuff.kraken.example.SimpleExamples
mvn -q -pl examples exec:java -Dexec.mainClass=dev.andstuff.kraken.example.TotalRewards
mvn -q -pl examples exec:java -Dexec.mainClass=dev.andstuff.kraken.example.StakingRewardsSummaryExample
```

[1]: https://docs.kraken.com/rest/

[2]: https://github.com/FasterXML/jackson

[3]: https://github.com/nyg/kraken-api-java/blob/v1.0.0/examples/src/main/java/dev/andstuff/kraken/example/Examples.java
Expand Up @@ -8,12 +8,12 @@
import com.fasterxml.jackson.databind.JsonNode;

import dev.andstuff.kraken.api.KrakenAPI;
import dev.andstuff.kraken.api.model.KrakenCredentials;
import dev.andstuff.kraken.api.model.endpoint.market.params.AssetPairParams;
import dev.andstuff.kraken.api.model.endpoint.market.response.AssetInfo;
import dev.andstuff.kraken.api.model.endpoint.market.response.AssetPair;
import dev.andstuff.kraken.api.model.endpoint.market.response.ServerTime;
import dev.andstuff.kraken.api.model.endpoint.market.response.SystemStatus;
import dev.andstuff.kraken.api.endpoint.market.params.AssetPairParams;
import dev.andstuff.kraken.api.endpoint.market.response.AssetInfo;
import dev.andstuff.kraken.api.endpoint.market.response.AssetPair;
import dev.andstuff.kraken.api.endpoint.market.response.ServerTime;
import dev.andstuff.kraken.api.endpoint.market.response.SystemStatus;
import dev.andstuff.kraken.api.rest.KrakenCredentials;
import lombok.extern.slf4j.Slf4j;

@Slf4j
Expand Down Expand Up @@ -65,8 +65,8 @@ public static void main(String[] args) {
"price", "1000",
"oflags", "post,fciq",
"close[ordertype]", "limit",
"close[price]", "1500",
"validate", "true"));
"close[price]", "500",
"validate", "true")); // does not submit the order when set to true
log.info("{}", order);
}
}
Expand Up @@ -8,11 +8,11 @@
import java.util.Set;

import dev.andstuff.kraken.api.KrakenAPI;
import dev.andstuff.kraken.api.model.KrakenCredentials;
import dev.andstuff.kraken.api.model.KrakenException;
import dev.andstuff.kraken.api.model.endpoint.account.params.LedgerInfoParams;
import dev.andstuff.kraken.api.model.endpoint.account.response.LedgerEntry;
import dev.andstuff.kraken.api.model.endpoint.account.response.LedgerInfo;
import dev.andstuff.kraken.api.rest.KrakenCredentials;
import dev.andstuff.kraken.api.endpoint.KrakenException;
import dev.andstuff.kraken.api.endpoint.account.params.LedgerInfoParams;
import dev.andstuff.kraken.api.endpoint.account.response.LedgerEntry;
import dev.andstuff.kraken.api.endpoint.account.response.LedgerInfo;
import dev.andstuff.kraken.example.reward.AssetRates;
import dev.andstuff.kraken.example.reward.StakingRewards;
import dev.andstuff.kraken.example.reward.csv.CsvLedgerEntries;
Expand Down
Expand Up @@ -4,7 +4,7 @@
import java.io.InputStream;
import java.util.Properties;

import dev.andstuff.kraken.api.model.KrakenCredentials;
import dev.andstuff.kraken.api.rest.KrakenCredentials;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;

Expand Down
Expand Up @@ -7,7 +7,7 @@
import java.util.Map;
import java.util.Optional;

import dev.andstuff.kraken.api.model.endpoint.market.response.Ticker;
import dev.andstuff.kraken.api.endpoint.market.response.Ticker;
import lombok.Getter;

@Getter
Expand Down
Expand Up @@ -6,7 +6,7 @@
import java.util.List;
import java.util.Map;

import dev.andstuff.kraken.api.model.endpoint.account.response.LedgerEntry;
import dev.andstuff.kraken.api.endpoint.account.response.LedgerEntry;
import lombok.Getter;

/**
Expand Down
Expand Up @@ -6,7 +6,7 @@
import java.util.List;
import java.util.Set;

import dev.andstuff.kraken.api.model.endpoint.account.response.LedgerEntry;
import dev.andstuff.kraken.api.endpoint.account.response.LedgerEntry;
import lombok.Getter;

/**
Expand Down
Expand Up @@ -12,7 +12,7 @@
import com.opencsv.exceptions.CsvDataTypeMismatchException;
import com.opencsv.exceptions.CsvRequiredFieldEmptyException;

import dev.andstuff.kraken.api.model.endpoint.account.response.LedgerEntry;
import dev.andstuff.kraken.api.endpoint.account.response.LedgerEntry;
import dev.andstuff.kraken.example.helper.HeaderAndPositionMappingStrategy;

public class CsvLedgerEntries {
Expand Down
Expand Up @@ -6,7 +6,7 @@
import com.opencsv.bean.CsvBindByName;
import com.opencsv.bean.CsvBindByPosition;

import dev.andstuff.kraken.api.model.endpoint.account.response.LedgerEntry;
import dev.andstuff.kraken.api.endpoint.account.response.LedgerEntry;

public record CsvLedgerEntry(@CsvBindByPosition(position = 7) @CsvBindByName(column = "ledger_entry_id") String ledgerEntryId,
@CsvBindByPosition(position = 8) @CsvBindByName(column = "reference_id") String referenceId,
Expand Down
85 changes: 52 additions & 33 deletions library/src/main/java/dev/andstuff/kraken/api/KrakenAPI.java
Expand Up @@ -5,48 +5,65 @@

import com.fasterxml.jackson.databind.JsonNode;

import dev.andstuff.kraken.api.model.KrakenCredentials;
import dev.andstuff.kraken.api.model.endpoint.account.LedgerEntriesEndpoint;
import dev.andstuff.kraken.api.model.endpoint.account.LedgerInfoEndpoint;
import dev.andstuff.kraken.api.model.endpoint.account.params.LedgerEntriesParams;
import dev.andstuff.kraken.api.model.endpoint.account.params.LedgerInfoParams;
import dev.andstuff.kraken.api.model.endpoint.account.response.LedgerEntry;
import dev.andstuff.kraken.api.model.endpoint.account.response.LedgerInfo;
import dev.andstuff.kraken.api.model.endpoint.market.AssetInfoEndpoint;
import dev.andstuff.kraken.api.model.endpoint.market.AssetPairEndpoint;
import dev.andstuff.kraken.api.model.endpoint.market.ServerTimeEndpoint;
import dev.andstuff.kraken.api.model.endpoint.market.SystemStatusEndpoint;
import dev.andstuff.kraken.api.model.endpoint.market.TickerEndpoint;
import dev.andstuff.kraken.api.model.endpoint.market.params.AssetPairParams;
import dev.andstuff.kraken.api.model.endpoint.market.response.AssetInfo;
import dev.andstuff.kraken.api.model.endpoint.market.response.AssetPair;
import dev.andstuff.kraken.api.model.endpoint.market.response.ServerTime;
import dev.andstuff.kraken.api.model.endpoint.market.response.SystemStatus;
import dev.andstuff.kraken.api.model.endpoint.market.response.Ticker;
import dev.andstuff.kraken.api.model.endpoint.priv.JsonPrivateEndpoint;
import dev.andstuff.kraken.api.model.endpoint.pub.JsonPublicEndpoint;
import dev.andstuff.kraken.api.endpoint.account.LedgerEntriesEndpoint;
import dev.andstuff.kraken.api.endpoint.account.LedgerInfoEndpoint;
import dev.andstuff.kraken.api.endpoint.account.params.LedgerEntriesParams;
import dev.andstuff.kraken.api.endpoint.account.params.LedgerInfoParams;
import dev.andstuff.kraken.api.endpoint.account.response.LedgerEntry;
import dev.andstuff.kraken.api.endpoint.account.response.LedgerInfo;
import dev.andstuff.kraken.api.endpoint.market.AssetInfoEndpoint;
import dev.andstuff.kraken.api.endpoint.market.AssetPairEndpoint;
import dev.andstuff.kraken.api.endpoint.market.ServerTimeEndpoint;
import dev.andstuff.kraken.api.endpoint.market.SystemStatusEndpoint;
import dev.andstuff.kraken.api.endpoint.market.TickerEndpoint;
import dev.andstuff.kraken.api.endpoint.market.params.AssetPairParams;
import dev.andstuff.kraken.api.endpoint.market.response.AssetInfo;
import dev.andstuff.kraken.api.endpoint.market.response.AssetPair;
import dev.andstuff.kraken.api.endpoint.market.response.ServerTime;
import dev.andstuff.kraken.api.endpoint.market.response.SystemStatus;
import dev.andstuff.kraken.api.endpoint.market.response.Ticker;
import dev.andstuff.kraken.api.endpoint.priv.JsonPrivateEndpoint;
import dev.andstuff.kraken.api.endpoint.priv.PrivateEndpoint;
import dev.andstuff.kraken.api.endpoint.pub.JsonPublicEndpoint;
import dev.andstuff.kraken.api.rest.DefaultKrakenRestRequester;
import dev.andstuff.kraken.api.rest.EpochBasedNonceGenerator;
import dev.andstuff.kraken.api.rest.KrakenCredentials;
import dev.andstuff.kraken.api.rest.KrakenNonceGenerator;
import dev.andstuff.kraken.api.rest.KrakenRestRequester;
import lombok.Builder;
import lombok.Getter;
import lombok.RequiredArgsConstructor;

@Builder(toBuilder = true)
public class KrakenAPI {

private final KrakenCredentials credentials;
private final KrakenNonceGenerator nonceGenerator;
private final KrakenRestRequester restRequester;

public KrakenAPI() {
this(new DefaultKrakenRestRequester());
this(null, new DefaultKrakenRestRequester());
}

public KrakenAPI(String key, String secret) {
this(new KrakenCredentials(key, secret));
}

public KrakenAPI(KrakenCredentials credentials) {
this(new DefaultKrakenRestRequester(credentials));
this(credentials, new DefaultKrakenRestRequester());
}

public KrakenAPI(String key, String secret) {
this(new DefaultKrakenRestRequester(key, secret));
public KrakenAPI(KrakenCredentials credentials, KrakenNonceGenerator nonceGenerator) {
this(credentials, nonceGenerator, new DefaultKrakenRestRequester());
}

public KrakenAPI(KrakenCredentials credentials, KrakenRestRequester restRequester) {
this(credentials, new EpochBasedNonceGenerator(), restRequester);
}

public KrakenAPI(KrakenRestRequester restRequester) {
public KrakenAPI(KrakenCredentials credentials, KrakenNonceGenerator nonceGenerator, KrakenRestRequester restRequester) {
this.credentials = credentials;
this.nonceGenerator = nonceGenerator;
this.restRequester = restRequester;
}

Expand Down Expand Up @@ -83,11 +100,15 @@ public Map<String, Ticker> ticker(List<String> pairs) {
/* Implemented private endpoints */

public LedgerInfo ledgerInfo(LedgerInfoParams params) {
return restRequester.execute(new LedgerInfoEndpoint(params));
return executePrivate(new LedgerInfoEndpoint(params));
}

public Map<String, LedgerEntry> ledgerEntries(LedgerEntriesParams params) {
return restRequester.execute(new LedgerEntriesEndpoint(params));
return executePrivate(new LedgerEntriesEndpoint(params));
}

private <T> T executePrivate(PrivateEndpoint<T> endpoint) {
return restRequester.execute(endpoint, credentials, nonceGenerator);
}

/* Query unimplemented endpoints */
Expand All @@ -109,27 +130,26 @@ public JsonNode queryPublic(String path, Map<String, String> queryParams) {
}

public JsonNode query(Private endpoint) {
return restRequester.execute(new JsonPrivateEndpoint(endpoint.getPath()));
return executePrivate(new JsonPrivateEndpoint(endpoint.getPath()));
}

public JsonNode query(Private endpoint, Map<String, String> params) {
return restRequester.execute(new JsonPrivateEndpoint(endpoint.getPath(), params));
return executePrivate(new JsonPrivateEndpoint(endpoint.getPath(), params));
}

public JsonNode queryPrivate(String path) {
return restRequester.execute(new JsonPrivateEndpoint(path));
return executePrivate(new JsonPrivateEndpoint(path));
}

public JsonNode queryPrivate(String path, Map<String, String> params) {
return restRequester.execute(new JsonPrivateEndpoint(path, params));
return executePrivate(new JsonPrivateEndpoint(path, params));
}

/* All endpoints */

@Getter
@RequiredArgsConstructor
public enum Public {

ASSETS("Assets"),
ASSET_PAIRS("AssetPairs"),
DEPTH("Depth"),
Expand All @@ -146,7 +166,6 @@ public enum Public {
@Getter
@RequiredArgsConstructor
public enum Private {

ACCOUNT_TRANSFER("AccountTransfer"),
ADD_EXPORT("AddExport"),
ADD_ORDER("AddOrder"),
Expand Down
@@ -1,12 +1,11 @@
package dev.andstuff.kraken.api.model.endpoint;
package dev.andstuff.kraken.api.endpoint;

import java.net.URL;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.type.TypeFactory;

import dev.andstuff.kraken.api.model.KrakenResponse;
import lombok.Getter;
import lombok.RequiredArgsConstructor;

Expand Down
@@ -1,4 +1,4 @@
package dev.andstuff.kraken.api.model;
package dev.andstuff.kraken.api.endpoint;

import java.util.List;

Expand Down
@@ -1,4 +1,4 @@
package dev.andstuff.kraken.api.model;
package dev.andstuff.kraken.api.endpoint;

import java.util.List;
import java.util.Optional;
Expand Down
@@ -1,12 +1,12 @@
package dev.andstuff.kraken.api.model.endpoint.account;
package dev.andstuff.kraken.api.endpoint.account;

import java.util.Map;

import com.fasterxml.jackson.core.type.TypeReference;

import dev.andstuff.kraken.api.model.endpoint.account.params.LedgerEntriesParams;
import dev.andstuff.kraken.api.model.endpoint.account.response.LedgerEntry;
import dev.andstuff.kraken.api.model.endpoint.priv.PrivateEndpoint;
import dev.andstuff.kraken.api.endpoint.account.params.LedgerEntriesParams;
import dev.andstuff.kraken.api.endpoint.account.response.LedgerEntry;
import dev.andstuff.kraken.api.endpoint.priv.PrivateEndpoint;

public class LedgerEntriesEndpoint extends PrivateEndpoint<Map<String, LedgerEntry>> {

Expand Down
@@ -0,0 +1,14 @@
package dev.andstuff.kraken.api.endpoint.account;

import com.fasterxml.jackson.core.type.TypeReference;

import dev.andstuff.kraken.api.endpoint.account.params.LedgerInfoParams;
import dev.andstuff.kraken.api.endpoint.account.response.LedgerInfo;
import dev.andstuff.kraken.api.endpoint.priv.PrivateEndpoint;

public class LedgerInfoEndpoint extends PrivateEndpoint<LedgerInfo> {

public LedgerInfoEndpoint(LedgerInfoParams params) {
super("Ledgers", params, new TypeReference<>() {});
}
}
@@ -1,10 +1,10 @@
package dev.andstuff.kraken.api.model.endpoint.account.params;
package dev.andstuff.kraken.api.endpoint.account.params;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import dev.andstuff.kraken.api.model.endpoint.priv.PostParams;
import dev.andstuff.kraken.api.endpoint.priv.PostParams;
import lombok.Builder;
import lombok.Getter;

Expand Down
@@ -1,4 +1,4 @@
package dev.andstuff.kraken.api.model.endpoint.account.params;
package dev.andstuff.kraken.api.endpoint.account.params;

import java.time.Instant;
import java.util.HashMap;
Expand All @@ -7,7 +7,7 @@

import com.fasterxml.jackson.annotation.JsonEnumDefaultValue;

import dev.andstuff.kraken.api.model.endpoint.priv.PostParams;
import dev.andstuff.kraken.api.endpoint.priv.PostParams;
import lombok.Builder;
import lombok.Getter;
import lombok.With;
Expand Down
@@ -1,4 +1,4 @@
package dev.andstuff.kraken.api.model.endpoint.account.response;
package dev.andstuff.kraken.api.endpoint.account.response;

import java.math.BigDecimal;
import java.time.Instant;
Expand Down
@@ -1,4 +1,4 @@
package dev.andstuff.kraken.api.model.endpoint.account.response;
package dev.andstuff.kraken.api.endpoint.account.response;

import java.util.List;
import java.util.Map;
Expand Down
@@ -1,13 +1,13 @@
package dev.andstuff.kraken.api.model.endpoint.market;
package dev.andstuff.kraken.api.endpoint.market;

import java.util.List;
import java.util.Map;

import com.fasterxml.jackson.core.type.TypeReference;

import dev.andstuff.kraken.api.model.endpoint.market.params.AssetInfoParams;
import dev.andstuff.kraken.api.model.endpoint.market.response.AssetInfo;
import dev.andstuff.kraken.api.model.endpoint.pub.PublicEndpoint;
import dev.andstuff.kraken.api.endpoint.market.params.AssetInfoParams;
import dev.andstuff.kraken.api.endpoint.market.response.AssetInfo;
import dev.andstuff.kraken.api.endpoint.pub.PublicEndpoint;

public class AssetInfoEndpoint extends PublicEndpoint<Map<String, AssetInfo>> {

Expand Down

0 comments on commit 7bc46b8

Please sign in to comment.