Skip to content

Commit 6082624

Browse files
authored
Merge pull request #13 from cryptomkt/feat/ws-createorderlist-multi-response
Feat/ws createorderlist multi response
2 parents ed507bf + af0a972 commit 6082624

File tree

9 files changed

+132
-62
lines changed

9 files changed

+132
-62
lines changed

src/main/java/com/cryptomarket/sdk/models/NativeTransaction.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ public class NativeTransaction {
2323
private String confirmations;
2424
@Json(name = "public_comment")
2525
private String publicComment;
26+
@Json(name = "network_code")
27+
private String networkCode;
2628
@Json(name = "error_code")
2729
private String errorCode;
2830
private List<String> sender;
@@ -261,8 +263,8 @@ public void setSender(List<String> sender) {
261263
public String toString() {
262264
return "NativeTransaction [id=" + id + ", index=" + index + ", currency=" + currency + ", amount=" + amount
263265
+ ", fee=" + fee + ", address=" + address + ", paymentId=" + paymentId + ", hash=" + hash + ", offchainId="
264-
+ offchainId + ", confirmations=" + confirmations + ", publicComment=" + publicComment + ", errorCode="
265-
+ errorCode + ", sender=" + sender + "]";
266+
+ offchainId + ", confirmations=" + confirmations + ", publicComment=" + publicComment + ", networkCode="
267+
+ networkCode + ", errorCode=" + errorCode + ", sender=" + sender + "]";
266268
}
267269

268270
}

src/main/java/com/cryptomarket/sdk/websocket/ClientBase.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,13 @@ protected void sendUnsubscription(String method, Map<String, Object> params, Int
7373
}
7474

7575
protected void sendById(String method, Map<String, Object> params, Interceptor interceptor) {
76+
sendById(method, params, interceptor, 1);
77+
}
78+
79+
protected void sendById(String method, Map<String, Object> params, Interceptor interceptor, Integer callCount) {
7680
Payload payload = new Payload(method, params);
7781
if (interceptor != null) {
78-
Integer id = interceptorCache.storeInterceptor(interceptor);
82+
Integer id = interceptorCache.saveInterceptor(interceptor, callCount);
7983
payload.id = id;
8084
}
8185
String json = payloadAdapter.toJson(payload);
@@ -100,9 +104,11 @@ protected void handleNotification(WSJsonResponse response) {
100104
}
101105

102106
protected void handleResponse(WSJsonResponse response) {
103-
Interceptor interceptor = interceptorCache.popInterceptor(response.getId());
104-
if (interceptor != null)
105-
interceptor.makeCall(response);
107+
var interceptor = interceptorCache.getInterceptor(response.getId());
108+
if (interceptor.isEmpty()) {
109+
return;
110+
}
111+
interceptor.get().makeCall(response);
106112
}
107113

108114
protected String buildKey(String method) {

src/main/java/com/cryptomarket/sdk/websocket/CryptomarketWSMarketDataClientImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ private void subscriptionByChannel(String channel, Map<String, Object> params, I
6262
interceptorCache.storeSubscriptionInterceptor(key, feedInterceptor);
6363
Payload payload = new Payload("subscribe", channel, params);
6464
if (resultInterceptor != null) {
65-
Integer id = interceptorCache.storeInterceptor(resultInterceptor);
65+
Integer id = interceptorCache.saveInterceptor(resultInterceptor);
6666
payload.id = id;
6767
}
6868
String json = payloadAdapter.toJson(payload);

src/main/java/com/cryptomarket/sdk/websocket/CryptomarketWSSpotTradingClient.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public void subscribeToReports(BiConsumer<List<Report>, NotificationType> notifi
6161
* notifications are updates of the user orders
6262
* <p>
6363
* https://api.exchange.cryptomkt.com/#subscribe-to-spot-balances
64-
*
64+
*
6565
* @param mode Optional. SubscriptionMode.UPDATES to recieve a
6666
* notification on each balance update, and
6767
* SubscriptionMode.BATCHES to recieve
@@ -80,7 +80,7 @@ public void subscribeToSpotBalances(@Nullable SubscriptionMode mode,
8080
* stop recieving the balance feed subscription
8181
* <p>
8282
* https://api.exchange.cryptomkt.com/#subscribe-to-spot-balances
83-
*
83+
*
8484
* @param resultBiConsumer Optional. recieves true if the unsubscription is
8585
* successfull, and a CryptomarketSDKException if
8686
* there was a problem (or null if there was none)
@@ -175,6 +175,8 @@ public void createSpotOrder(
175175
/**
176176
* creates a list of spot orders
177177
* <p>
178+
* <b>calls the report consumer once per order in list</b>
179+
* <p>
178180
* <b>Types or contingency:</b>
179181
* <ul>
180182
* <li>ContingencyType.ALL_OR_NONE (AON)

src/main/java/com/cryptomarket/sdk/websocket/CryptomarketWSSpotTradingClientImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ public void createSpotOrderList(
198198
Interceptor interceptor = (resultBiConsumer == null)
199199
? null
200200
: InterceptorFactory.newOfWSResponseObject(resultBiConsumer, Report.class);
201-
sendById("spot_new_order_list", params.buildObjectMap(), interceptor);
201+
sendById("spot_new_order_list", params.buildObjectMap(), interceptor, orders.size());
202202
}
203203

204204
@Override

src/main/java/com/cryptomarket/sdk/websocket/interceptor/InterceptorCache.java

Lines changed: 46 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,41 +2,54 @@
22

33
import java.util.HashMap;
44
import java.util.Map;
5-
5+
import java.util.Optional;
66

77
public class InterceptorCache {
8-
Map<String, Interceptor> interceptors = new HashMap<String, Interceptor>();
9-
Integer nextId = 1;
10-
11-
private Integer getNextId() {
12-
int next = nextId;
13-
nextId++;
14-
if (nextId <= 0) nextId = 1;
15-
return next;
16-
}
17-
18-
public Integer storeInterceptor(Interceptor interceptor) {
19-
Integer id = getNextId();
20-
interceptors.put(id.toString(), interceptor);
21-
return id;
8+
private Map<String, Interceptor> subscriptionInterceptors = new HashMap<String, Interceptor>();
9+
private Map<String, RecallableIntercaptor> interceptors = new HashMap<String, RecallableIntercaptor>();
10+
private Integer nextId = 1;
11+
12+
private Integer getNextId() {
13+
int next = nextId;
14+
nextId++;
15+
if (nextId <= 0)
16+
nextId = 1;
17+
return next;
18+
}
19+
20+
public Integer saveInterceptor(Interceptor interceptor) {
21+
return saveInterceptor(interceptor, 1);
22+
}
23+
24+
public Integer saveInterceptor(Interceptor interceptor, Integer callCount) {
25+
Integer id = getNextId();
26+
interceptors.put(id.toString(), new RecallableIntercaptor(interceptor, callCount));
27+
return id;
28+
}
29+
30+
public Optional<Interceptor> getInterceptor(Integer id) {
31+
var recallableInterceptor = interceptors.get(id.toString());
32+
if (recallableInterceptor == null) {
33+
return Optional.empty();
2234
}
23-
public Interceptor popInterceptor(Integer id) {
24-
// if (!interceptors.containsKey(id)) throw CallbackCacheException.newIdException(id.toString());
25-
Interceptor callback = interceptors.get(id.toString());
26-
interceptors.remove(id.toString());
27-
return callback;
28-
}
29-
30-
public void storeSubscriptionInterceptor(String key, Interceptor interceptor) {
31-
this.interceptors.put(key, interceptor);
32-
}
33-
34-
public Interceptor getSubscriptionInterceptor(String key) {
35-
if (!this.interceptors.containsKey(key)) return null;
36-
return this.interceptors.get(key);
37-
}
38-
39-
public void deleteSubscriptionInterceptor(String key) {
40-
this.interceptors.remove(key);
35+
var interceptor = recallableInterceptor.getInterceptor();
36+
if (recallableInterceptor.doneRecalling()) {
37+
subscriptionInterceptors.remove(id.toString());
4138
}
39+
return interceptor;
40+
}
41+
42+
public void storeSubscriptionInterceptor(String key, Interceptor interceptor) {
43+
this.subscriptionInterceptors.put(key, interceptor);
44+
}
45+
46+
public Interceptor getSubscriptionInterceptor(String key) {
47+
if (!this.subscriptionInterceptors.containsKey(key))
48+
return null;
49+
return this.subscriptionInterceptors.get(key);
50+
}
51+
52+
public void deleteSubscriptionInterceptor(String key) {
53+
this.subscriptionInterceptors.remove(key);
54+
}
4255
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package com.cryptomarket.sdk.websocket.interceptor;
2+
3+
import java.util.Optional;
4+
5+
public class RecallableIntercaptor {
6+
private final Interceptor interceptor;
7+
private Integer callCount;
8+
9+
public RecallableIntercaptor(Interceptor interceptor) {
10+
this.interceptor = interceptor;
11+
this.callCount = 1;
12+
}
13+
14+
public RecallableIntercaptor(Interceptor interceptor, Integer callCount) {
15+
this.interceptor = interceptor;
16+
this.callCount = callCount;
17+
}
18+
19+
public Optional<Interceptor> getInterceptor() {
20+
if (callCount < 1) {
21+
return Optional.empty();
22+
}
23+
callCount--;
24+
return Optional.of(interceptor);
25+
}
26+
27+
public Boolean doneRecalling() {
28+
return callCount < 1;
29+
}
30+
}

src/test/java/com/cryptomarket/sdk/Helpers.java

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import java.util.List;
66
import java.util.Map;
7+
import java.util.Optional;
78
import java.util.concurrent.TimeUnit;
89
import java.util.function.BiConsumer;
910
import java.util.function.Consumer;
@@ -21,27 +22,31 @@ public static void sleep(int seconds) {
2122
}
2223

2324
public static class FailChecker {
24-
private Boolean _failed = false;
25+
private Optional<String> errMsg = Optional.empty();
2526

26-
public void fail() {
27-
_failed = true;
27+
public void fail(String errMsg) {
28+
this.errMsg = Optional.of(errMsg);
2829
}
2930

3031
public Boolean failed() {
31-
return _failed;
32+
return errMsg.isPresent();
33+
}
34+
35+
public Optional<String> getErrMsg() {
36+
return errMsg;
3237
}
3338
}
3439

3540
public static <T> BiConsumer<T, NotificationType> checker(FailChecker failChecker, Consumer<T> checker) {
3641
return (data, notificationType) -> {
3742
if (notificationType.isError()) {
38-
failChecker.fail();
43+
failChecker.fail("failed to parse notification");
3944
return;
4045
}
4146
try {
4247
checker.accept(data);
4348
} catch (AssertionError e) {
44-
failChecker.fail();
49+
failChecker.fail(e.getMessage());
4550
}
4651
};
4752
}
@@ -50,12 +55,12 @@ public static <T> BiConsumer<T, CryptomarketSDKException> objectAndExceptionChec
5055
Consumer<T> checker) {
5156
return (data, error) -> {
5257
if (error != null) {
53-
failChecker.fail();
58+
failChecker.fail(error.getMessage());
5459
}
5560
try {
5661
checker.accept(data);
5762
} catch (AssertionError e) {
58-
failChecker.fail();
63+
failChecker.fail(e.getMessage());
5964
}
6065
};
6166
}
@@ -64,12 +69,12 @@ public static <T> BiConsumer<List<T>, CryptomarketSDKException> listAndException
6469
Consumer<T> checker) {
6570
return (data, error) -> {
6671
if (error != null) {
67-
failChecker.fail();
72+
failChecker.fail(error.getMessage());
6873
}
6974
try {
7075
data.forEach(v -> checker.accept(v));
7176
} catch (AssertionError e) {
72-
failChecker.fail();
77+
failChecker.fail(e.getMessage());
7378
}
7479
};
7580
}
@@ -78,13 +83,13 @@ public static <T> BiConsumer<List<T>, NotificationType> notificationListChecker(
7883
Consumer<T> checker) {
7984
return (data, notificationType) -> {
8085
if (notificationType.isError()) {
81-
failChecker.fail();
86+
failChecker.fail("invalid notification type");
8287
return;
8388
}
8489
try {
8590
data.forEach(v -> checker.accept(v));
8691
} catch (AssertionError e) {
87-
failChecker.fail();
92+
failChecker.fail(e.getMessage());
8893
}
8994
};
9095
}
@@ -93,13 +98,13 @@ public static <T> BiConsumer<Map<String, T>, NotificationType> notificationMapCh
9398
Consumer<T> checker) {
9499
return (data, notificationType) -> {
95100
if (notificationType.isError()) {
96-
failChecker.fail();
101+
failChecker.fail("invalid notification type");
97102
return;
98103
}
99104
try {
100105
data.forEach((k, v) -> checker.accept(v));
101106
} catch (AssertionError e) {
102-
failChecker.fail();
107+
failChecker.fail(e.getMessage());
103108
}
104109
};
105110
}
@@ -109,13 +114,13 @@ public static <T> BiConsumer<Map<String, List<T>>, NotificationType> notificatio
109114
Consumer<T> checker) {
110115
return (data, notificationType) -> {
111116
if (notificationType.isError()) {
112-
failChecker.fail();
117+
failChecker.fail("invalid notification type");
113118
return;
114119
}
115120
try {
116121
data.forEach((k, v) -> v.forEach(checker));
117122
} catch (AssertionError e) {
118-
failChecker.fail();
123+
failChecker.fail(e.getMessage());
119124
}
120125
};
121126
}

src/test/java/com/cryptomarket/sdk/TestWSSpotTradingClient.java

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,22 @@
2424
import com.cryptomarket.sdk.websocket.CryptomarketWSSpotTradingClient;
2525
import com.cryptomarket.sdk.websocket.CryptomarketWSSpotTradingClientImpl;
2626

27+
import java.util.concurrent.FutureTask;
28+
import java.util.concurrent.ExecutionException;
29+
2730
public class TestWSSpotTradingClient {
2831

2932
CryptomarketWSSpotTradingClient wsClient;
3033
Boolean authenticated = false;
3134

3235
@Before
33-
public void before() throws IOException {
34-
wsClient = new CryptomarketWSSpotTradingClientImpl(KeyLoader.getApiKey(), KeyLoader.getApiSecret(), 10_000);
36+
public void before() throws IOException, InterruptedException, ExecutionException {
37+
wsClient = new CryptomarketWSSpotTradingClientImpl(KeyLoader.getApiKey(), KeyLoader.getApiSecret(), 60_000);
38+
var ft = new FutureTask<Object>(() -> {
39+
}, new Object());
40+
wsClient.onConnect(ft);
3541
wsClient.connect();
36-
Helpers.sleep(3);
42+
ft.get();
3743
}
3844

3945
@After
@@ -56,6 +62,9 @@ public void testSpotTradingBalance() {
5662
wsClient.getSpotTradingBalanceOfCurrency("EOS",
5763
Helpers.objectAndExceptionChecker(failChecker, Checker.checkBalance));
5864
Helpers.sleep(3);
65+
if (failChecker.failed()) {
66+
fail(failChecker.getErrMsg().get());
67+
}
5968
assertFalse(failChecker.failed());
6069
}
6170

@@ -204,6 +213,9 @@ public void testCreateOrderList() {
204213
Helpers.objectAndExceptionChecker(failChecker, Checker.checkReport));
205214

206215
Helpers.sleep(12);
216+
if (failChecker.failed()) {
217+
fail(failChecker.getErrMsg().get());
218+
}
207219
assertFalse(failChecker.failed());
208220
}
209221
}

0 commit comments

Comments
 (0)