opnx-api-client is a lightweight Java library, providing complete API coverage, and supporting synchronous and asynchronous requests, as well as event streaming using WebSockets.
- Support for synchronous and asynchronous REST requests to all endpoints.
- Support for User Data, Trade, and Depth event streaming
- Install library into your Maven's local repository by running
mvn install
- Add the following Maven dependency to your project's
pom.xml
:
<dependency>
<groupId>com.opnx.api</groupId>
<artifactId>opnx-api-client</artifactId>
<version>1.0.0</version>
</dependency>
Alternatively, you can clone this repository and run the examples
There are three main client classes that can be used to interact with the API:
OpnxApiRestClient
a synchronous/blocking Opnx API client;OpnxApiAsyncRestClient
an asynchronous/non-blocking Opnx API client;OpnxApiWebSocketClient
a data streaming client using Opnx WebSocket API.
These can be instantiated through the corresponding factory method of OpnxApiClientFactory
.
To use the client in the staging environment set the parameter to true, and set it to false to access the live environment.
OpnxApiClientFactory factory = OpnxApiClientFactory.newInstance("API_KEY", "API_KEY_SECRET",true);
OpnxApiRestClient client = factory.newRestClient();
Another way to access the live environment is to simply only pass your Api Key and Secret
OpnxApiClientFactory factory = OpnxApiClientFactory.newInstance("API_KEY", "API_KEY_SECRET");
OpnxApiRestClient client = factory.newRestClient();
If the client only needs to access endpoints which do not require additional authentication, then these parameters are optional.
Once the client is instantiated, it is possible to start making requests to the API.
OpnxV3RestResponse<List<AccountInfoV3Resp>> accountInfo = client.getAccountInfo(Arrays.asList("13670979-1621913298587", "PERMISSIONLESS_165"));
System.out.println(JSONObject.toJSONString(accountInfo));
View Response
{
"success": true,
"data": [
{
"accountId": "21213",
"name": "main",
"accountType": "LINEAR",
"balances": [
{
"asset": "BTC",
"total": "2.823",
"available": "2.823",
"reserved": "0",
"lastUpdatedAt": "1593627415234"
},
{
"asset": "FLEX",
"total": "1585.890",
"available": "325.890",
"reserved": "1260.0",
"lastUpdatedAt": "1593627415123"
}
],
"positions": [
{
"marketCode": "FLEX-oUSD-SWAP-LIN",
"baseAsset": "FLEX",
"counterAsset": "oUSD",
"position": "11411.1",
"entryPrice": "3.590",
"markPrice": "6.360",
"positionPnl": "31608.7470",
"estLiquidationPrice": "2.59",
"lastUpdatedAt": "1637876701404",
}
],
"collateral": "1231231",
"notionalPositionSize": "50000.0",
"portfolioVarMargin": "500",
"maintenanceMargin": "1231",
"marginRatio": "12.3179",
"liquidating": false,
"feeTier": "6",
"createdAt": "1611665624601"
}
]
}
OpnxV3RestResponse<List<SubAccountInfoV3Resp>> subAccounts = client.getSubAccounts();
System.out.println(JSONObject.toJSONString(subAccounts));
View Response
{
"success": true,
"data": [ {
"accountId": "21213",
"name": "Test 1"
},
{
"accountId": "21214",
"name": "Test 2"
}
]
}
OpnxV3RestResponse<List<PositionsV3Resp>> accountPositions = client.getAccountPositions(Arrays.asList("13670979-1621913298587", "test_opnx_api"), "BTC-oUSD-SWAP-LIN");
System.out.println(JSONObject.toJSONString(accountPositions));
View Response
{
"data": [
{
"accountId": "165",
"name": "main",
"positions": [
{
"baseAsset": "BTC",
"counterAsset": "oUSD",
"entryPrice": "22938.97488422",
"estLiquidationPrice": "12208536.690",
"lastUpdatedAt": "1677024022627",
"markPrice": "23571.790",
"marketCode": "BTC-oUSD-SWAP-LIN",
"position": "-1.795000000",
"positionPnl": "-1135.90313282510000000"
}
]
}
],
"success": true
}
OpnxV3RestResponse<List<PublicTradesV3Resp>> publicTrades = client.getPublicTrades("BTC-oUSD-SWAP-LIN", 6L, null, null);
System.out.println(JSONObject.toJSONString(publicTrades));
View Response
{
"success": true,
"data": [
{
"marketCode": "BTC-oUSD-SWAP-LIN",
"matchPrice": "9600.00000" ,
"matchQuantity": "0.100000" ,
"side": "BUY" ,
"matchType": "TAKER" ,
"matchedAt": "1662207330439"
}
]
}
OpnxV3RestResponse<List<CandlesV3Resp>> candles = client.getCandles("BTC-oUSD-SWAP-LIN", "60s", 10L, null, null);
System.out.println(JSONObject.toJSONString(candles));
View Response
{
"data": [
{
"close": "23565.09200000",
"currencyVolume": "0",
"high": "23566.45300000",
"low": "23563.03600000",
"open": "23563.50900000",
"openedAt": "1677486180000",
"volume": "0"
},
{
"close": "23563.40800000",
"currencyVolume": "0",
"high": "23568.46400000",
"low": "23561.99400000",
"open": "23568.46400000",
"openedAt": "1677486120000",
"volume": "0"
},
{
"close": "23568.88200000",
"currencyVolume": "0",
"high": "23573.66000000",
"low": "23568.88200000",
"open": "23570.14800000",
"openedAt": "1677486060000",
"volume": "0"
},
{
"close": "23570.20300000",
"currencyVolume": "0",
"high": "23574.24700000",
"low": "23570.20300000",
"open": "23572.48200000",
"openedAt": "1677486000000",
"volume": "0"
}
],
"success": true,
"timeframe": "60s"
}
To make an asynchronous request it is necessary to use the OpnxApiAsyncRestClient, and call the method with the same name as in the synchronous version, but passing a callback OpnxApiCallback that handles the response whenever it arrives.
client.getPublicTrades("FLEX-USDT", 6L, null, null,response -> System.out.println(JSONObject.toJSONString(response)));
View Response
{
"success": true,
"data": [
{
"orderId": "160067484555913076",
"clientOrderId": "123",
"matchId": "160067484555913077",
"marketCode": "FLEX-USDT",
"side": "SELL",
"matchedQuantity": "0.1",
"matchPrice": "0.065",
"total": "0.0065",
"leg1Price'": "0.0065",
"leg2Price": "0.0065",
"orderMatchType": "TAKER",
"feeAsset": "FLEX",
"fee":"0.0096",
"source": "10",
"matchedAt": "1595514663626"
}
]
}
client.getMarketsByMarketCode("BTC-oUSD-SWAP-LIN", response -> System.out.println(JSONObject.toJSONString(response)));
View Response
{
"data": [
{
"base": "BTC",
"counter": "oUSD",
"indexPrice": "23385.460",
"lastUpdatedAt": "1677485772175",
"listedAt": "1608621449015",
"lowerPriceBound": "11784.567",
"markPrice": "23569.135",
"marketCode": "BTC-oUSD-SWAP-LIN",
"minSize": "0.001",
"name": "BTC/USDT Perp",
"referencePair": "BTC/USDT",
"tickSize": "0.001",
"type": "FUTURE",
"upperPriceBound": "35078.190"
}
],
"success": true
}
client.getTickersByMarketCode("BTC-oUSD-SWAP-LIN", response -> System.out.println(JSONObject.toJSONString(response)));
View Response
{
"data": [
{
"currencyVolume24h": "0",
"high24h": "23680.460",
"lastTradedPrice": "23644.95",
"lastTradedQuantity": "0.001",
"lastUpdatedAt": "1677485905039",
"low24h": "23140.760",
"markPrice": "23569.916",
"marketCode": "BTC-oUSD-SWAP-LIN",
"open24h": "23160.130",
"openInterest": "0",
"volume24h": "0"
}
],
"success": true
}
There are two main ways to use it, one is to use the command without authenticating, and the other is to use the command after authenticating.
OpnxApiClientFactory factory = OpnxApiClientFactory.newInstance(true,true);
OpnxApiWebSocketClient webSocketClient = factory.newWebSocketClient();
String subscribeMessage = getSubscribeDepthCMD("BTC-USDT-REPO-LIN");
OpnxApiWebSocketListener<DepthEvent> listener = new OpnxApiWebSocketListener<>((result,listenerParam) -> {
if(result != null){
System.out.println("result ..."+ result.toString());
}
}, DepthEvent.class,subscribeMessage);
webSocketClient.onDepthUpdateEvent(listener);
System.out.println("websocket send msg: "+subscribeMessage);
View Response
{
"table": "depth",
"data": {
"seqNum": 2166539633781384,
"asks": [
[
19024.0,
1.0
],
[
19205.0,
4.207
],
[
19395.0,
8.414
]
],
"bids": [
[
18986.0,
1.0
],
[
18824.0,
4.207
],
[
18634.0,
8.414
]
],
"checksum": 3475315026,
"marketCode": "BTC-oUSD-SWAP-LIN",
"timestamp": 1665454814328
},
"action": "partial"
}
Multiple callbacks can be placed in callbackAndEventMap to handle the responses of different events. It should be noted that when the same event is placed, the more recent callbacks placed will overwrite the older callbacks, meaning the first callback placed will not be called.
You need to place an order in the login callback method body, because your order requests need to be authenticated.
OpnxApiClientFactory factory = OpnxApiClientFactory.newInstance(true,true);
OpnxApiWebSocketClient webSocketClient = factory.newWebSocketClient();
String loginMessage = JSON.toJSONString(getLoginCMD());
String limitOrderCMD = getLimitOrderCMD("BTC-USDT-REPO-LIN", 1, BigDecimal.ONE, OrderSide.BUY.name());
Map<String, CallbackAndEvent> callbackAndEventMap = new HashMap<>();
placeLimitOrder(callbackAndEventMap);
CallbackAndEvent<LoginEvent> loginCallbackAndEvent = new CallbackAndEvent();
loginCallbackAndEvent.setCallback((result,listenerParam) -> {
if(result != null && result instanceof LoginEvent){
System.out.println();
System.out.println("result ..." + result.toString());
System.out.println("result ..." + result.getEvent());
System.out.println();
isLogin = true;
if(isLogin){
listenerParam.send(limitOrderCMD);
}
}
});
loginCallbackAndEvent.setEventClass(LoginEvent.class,callbackAndEventMap);
MultipleCallbacksWebSocketListener loginListener = new MultipleCallbacksWebSocketListener(callbackAndEventMap,loginMessage);
webSocketClient.createNewWebSocket(loginListener);
View Response
{
"event": "placeorder",
"submitted": True,
"tag": "123",
"timestamp": "1592491945248",
"data": {
"clientOrderId": 1,
"marketCode": "BTC-oUSD-SWAP-LIN",
"side": "BUY",
"orderType": "LIMIT",
"quantity": "1.5",
"timeInForce": "GTC",
"orderId": "1000000700008",
"price": "9431.48",
"source": 0
}
}
An extensive set of examples, covering most aspects of the API, can be found at https://github.com/opnx-github/opnx-api-client/tree/main/src/test/java/com/opnx/api/client/examples