@ -1,13 +1,14 @@
package com.sigmaflare.binancej ;
import com.codepoetics.ambivalence.Either ;
import com.fasterxml.jackson.databind.JavaType ;
import com.sigmaflare.binancej.entities.Candlestick ;
import com.sigmaflare.binancej.entities.Interval ;
import com.sigmaflare.binancej.entities.OrderBookDepth ;
import com.sigmaflare.binancej.entities.ServiceError ;
import com.sigmaflare.binancej.entities.TickerPrice ;
import com.sigmaflare.binancej.exceptions.BinanceServiceException ;
import com.sigmaflare.binancej.exceptions.BinanceServiceUnreachableException ;
import com.sigmaflare.binancej.exceptions.UnexpectedErrorException ;
import lombok.Builder ;
import lombok.extern.slf4j.Slf4j ;
import org.apache.http.HttpEntity ;
@ -18,12 +19,14 @@ import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils ;
import java.io.IOException ;
import java.util.ArrayList ;
import java.util.Arrays ;
import java.util.List ;
import static com.sigmaflare.binancej.Constant.NO_RESPONSE_TEXT ;
import static com.sigmaflare.binancej.Constant.NO_RESPONSE_TEXT_FORMATTED ;
import static com.sigmaflare.binancej.Constant.SYMBOL_AND_INTERVAL_MUST_BE_SUPPLIED ;
import static com.sigmaflare.binancej.Helper s.buildGetRequestFromEndpoint ;
import static com.sigmaflare.binancej.HttpRequest s.buildGetRequestFromEndpoint ;
@Slf4j
public class MarketData extends BaseBinanceApi {
@ -31,6 +34,9 @@ public class MarketData extends BaseBinanceApi {
private static final String CANDLESTICK_URL = "/api/v1/klines" ;
private static final String TICKER_PRICE_URL = "/api/v3/ticker/price" ;
private static final ArrayList < Integer > LIMITS = new ArrayList < > ( Arrays . asList ( 5 , 10 , 20 , 50 , 100 , 500 , 1000 ) ) ;
private static final String LIMIT_EXCEPTION_MESSAGE = "Limit must be in [5, 10, 20, 50, 100, 500, 1000]" ;
@Builder
MarketData ( String apiKey , String secretKey ) {
super ( apiKey , secretKey ) ;
@ -40,15 +46,24 @@ public class MarketData extends BaseBinanceApi {
super ( apiKey , secretKey , closeableHttpClient ) ;
}
private void checkCandlestickLimit ( int limit ) {
if ( limit < 0 | | limit > 500 ) {
throw new IllegalArgumentException ( "Limit must be greater than 0 and less than or equal to 500" ) ;
}
}
/ * *
* Overloaded version of getOrderBookDepth that uses the default limit of 100
*
* @param symbol The symbol
* @return A populated OrderBookDepth if successful , otherwise an ServiceError
* @throws BinanceServiceUnreachableException In the case the service is unreachable
* @throws com . sigmaflare . binancej . exceptions . IpBannedException If the IP is banned
* @throws com . sigmaflare . binancej . exceptions . RateLimitExceededException If the rate limit is exceeded
* @throws com . sigmaflare . binancej . exceptions . MalformedRequestException If the user ' s request is malformed
* @throws com . sigmaflare . binancej . exceptions . InternalServiceErrorException If the error occurs on Binance ' s side
* @throws com . sigmaflare . binancej . exceptions . BinanceServiceUnreachableException If the service is unreachable
* /
public Either < ServiceError , OrderBookDepth > getOrderBookDepth ( String symbol )
throws BinanceServiceUnreachableException {
public OrderBookDepth getOrderBookDepth ( String symbol ) throws BinanceServiceException {
return getOrderBookDepth ( symbol , 100 ) ;
}
@ -57,11 +72,19 @@ public class MarketData extends BaseBinanceApi {
*
* @param symbol The symbol
* @param limit The record limit ( default : 100 , maximum 1000 )
* @return A populated OrderBookDepth if successful , otherwise an ServiceError
* @throws BinanceServiceUnreachableException In the case the service is unreachable
* @return A populated OrderBookDepth
* @throws com . sigmaflare . binancej . exceptions . IpBannedException If the IP is banned
* @throws com . sigmaflare . binancej . exceptions . RateLimitExceededException If the rate limit is exceeded
* @throws com . sigmaflare . binancej . exceptions . MalformedRequestException If the user ' s request is malformed
* @throws com . sigmaflare . binancej . exceptions . InternalServiceErrorException If the error occurs on Binance ' s side
* @throws com . sigmaflare . binancej . exceptions . BinanceServiceUnreachableException If the service is unreachable
* @throws UnexpectedErrorException If an unexpected exception occurs
* /
public Either < ServiceError , OrderBookDepth > getOrderBookDepth ( String symbol , int limit )
throws BinanceServiceUnreachableException {
public OrderBookDepth getOrderBookDepth ( String symbol , int limit ) throws BinanceServiceException {
if ( ! LIMITS . contains ( limit ) ) {
throw new IllegalArgumentException ( LIMIT_EXCEPTION_MESSAGE ) ;
}
String urlWithParams = String . format ( "%s?symbol=%s&limit=%d" , ORDER_BOOK_URL , symbol , limit ) ;
final HttpGet request = buildGetRequestFromEndpoint ( urlWithParams , apiKey ) ;
@ -79,14 +102,15 @@ public class MarketData extends BaseBinanceApi {
String response = EntityUtils . toString ( httpEntity ) ;
if ( ! Helpers . statusCodeIsOk ( sl . getStatusCode ( ) ) ) {
return Either . ofLeft ( mapper . readValue ( response , ServiceError . class ) ) ;
if ( ! HttpRequests . statusCodeIsOk ( sl . getStatusCode ( ) ) ) {
ServiceError error = mapper . readValue ( response , ServiceError . class ) ;
throw HttpRequests . buildHttpException ( sl . getStatusCode ( ) , error ) ;
}
return Either . ofRight ( mapper . readValue ( response , OrderBookDepth . class ) ) ;
return mapper . readValue ( response , OrderBookDepth . class ) ;
}
} catch ( IOException e ) {
throw new BinanceServiceUnreachable Exception( e . getMessage ( ) , e . getCause ( ) ) ;
throw new UnexpectedError Exception( e . getMessage ( ) , e . getCause ( ) ) ;
}
}
@ -95,12 +119,16 @@ public class MarketData extends BaseBinanceApi {
*
* @param symbol The symbol
* @param interval The interval
* @return A list of candlesticks if successful , otherwise an ServiceError
* @throws BinanceServiceUnreachableException If the service is unreachable
* @return A list of candlesticks
* @throws com . sigmaflare . binancej . exceptions . IpBannedException If the IP is banned
* @throws com . sigmaflare . binancej . exceptions . RateLimitExceededException If the rate limit is exceeded
* @throws com . sigmaflare . binancej . exceptions . MalformedRequestException If the user ' s request is malformed
* @throws com . sigmaflare . binancej . exceptions . InternalServiceErrorException If the error occurs on Binance ' s side
* @throws com . sigmaflare . binancej . exceptions . BinanceServiceUnreachableException If the service is unreachable
* @throws IllegalArgumentException If the required arguments symbol and interval are not supplied
* /
public Either < ServiceError , List < Candlestick > > getCandleStickData ( String symbol , Interval interval )
throws BinanceServiceUnreachableException {
public List < Candlestick > getCandleStickData ( String symbol , Interval interval )
throws BinanceServiceException {
if ( symbol = = null | | interval = = null ) {
throw new IllegalArgumentException ( SYMBOL_AND_INTERVAL_MUST_BE_SUPPLIED ) ;
@ -122,11 +150,17 @@ public class MarketData extends BaseBinanceApi {
* @param interval The interval
* @param limit The output limit
* @return A list of candlesticks if successful , otherwise an ServiceError
* @throws BinanceServiceUnreachableException If the service is unreachable
* @throws com . sigmaflare . binancej . exceptions . IpBannedException If the IP is banned
* @throws com . sigmaflare . binancej . exceptions . RateLimitExceededException If the rate limit is exceeded
* @throws com . sigmaflare . binancej . exceptions . MalformedRequestException If the user ' s request is malformed
* @throws com . sigmaflare . binancej . exceptions . InternalServiceErrorException If the error occurs on Binance ' s side
* @throws com . sigmaflare . binancej . exceptions . BinanceServiceUnreachableException If the service is unreachable
* @throws IllegalArgumentException If the required arguments symbol and interval are not supplied
* /
public Either < ServiceError , List < Candlestick > > getCandleStickData ( String symbol , Interval interval , int limit )
throws BinanceServiceUnreachableException {
public List < Candlestick > getCandleStickData ( String symbol , Interval interval , int limit )
throws BinanceServiceException {
checkCandlestickLimit ( limit ) ;
if ( symbol = = null | | interval = = null ) {
throw new IllegalArgumentException ( SYMBOL_AND_INTERVAL_MUST_BE_SUPPLIED ) ;
@ -149,13 +183,17 @@ public class MarketData extends BaseBinanceApi {
* @param interval The interval
* @param time The start / end time
* @param isStartTime Indicates whether the time is a start or end time
* @return A list of candlesticks if successful , otherwise an ServiceError
* @throws BinanceServiceUnreachableException If the service is unreachable
* @return A list of candlesticks
* @throws com . sigmaflare . binancej . exceptions . IpBannedException If the IP is banned
* @throws com . sigmaflare . binancej . exceptions . RateLimitExceededException If the rate limit is exceeded
* @throws com . sigmaflare . binancej . exceptions . MalformedRequestException If the user ' s request is malformed
* @throws com . sigmaflare . binancej . exceptions . InternalServiceErrorException If the error occurs on Binance ' s side
* @throws com . sigmaflare . binancej . exceptions . BinanceServiceUnreachableException If the service is unreachable
* @throws IllegalArgumentException If the required arguments symbol and interval are not supplied
* /
public Either < ServiceError , List < Candlestick > >
public List < Candlestick >
getCandleStickData ( String symbol , Interval interval , long time , boolean isStartTime )
throws BinanceServiceUnreachable Exception {
throws BinanceServiceException {
if ( symbol = = null | | interval = = null ) {
throw new IllegalArgumentException ( SYMBOL_AND_INTERVAL_MUST_BE_SUPPLIED ) ;
@ -190,13 +228,19 @@ public class MarketData extends BaseBinanceApi {
* @param limit The output limit
* @param time The timeframe
* @param isStartTime indicates whether time is a startTime ( true ) or endTime ( false )
* @return A list of candlesticks if successful , otherwise an ServiceError
* @throws BinanceServiceUnreachableException If the service is unreachable
* @return A list of candlesticks
* @throws com . sigmaflare . binancej . exceptions . IpBannedException If the IP is banned
* @throws com . sigmaflare . binancej . exceptions . RateLimitExceededException If the rate limit is exceeded
* @throws com . sigmaflare . binancej . exceptions . MalformedRequestException If the user ' s request is malformed
* @throws com . sigmaflare . binancej . exceptions . InternalServiceErrorException If the error occurs on Binance ' s side
* @throws com . sigmaflare . binancej . exceptions . BinanceServiceUnreachableException If the service is unreachable
* @throws IllegalArgumentException If the required arguments symbol and interval are not supplied
* /
public Either < ServiceError , List < Candlestick > >
public List < Candlestick >
getCandleStickData ( String symbol , Interval interval , int limit , long time , boolean isStartTime )
throws BinanceServiceUnreachableException {
throws BinanceServiceException {
checkCandlestickLimit ( limit ) ;
if ( symbol = = null | | interval = = null ) {
throw new IllegalArgumentException ( SYMBOL_AND_INTERVAL_MUST_BE_SUPPLIED ) ;
@ -233,13 +277,19 @@ public class MarketData extends BaseBinanceApi {
* @param limit The output limit
* @param startTime The start timeframe
* @param endTime The end timeframe
* @return A list of candlesticks if successful , otherwise an ServiceError
* @throws BinanceServiceUnreachableException If the service is unreachable
* @return A list of candlesticks
* @throws com . sigmaflare . binancej . exceptions . IpBannedException If the IP is banned
* @throws com . sigmaflare . binancej . exceptions . RateLimitExceededException If the rate limit is exceeded
* @throws com . sigmaflare . binancej . exceptions . MalformedRequestException If the user ' s request is malformed
* @throws com . sigmaflare . binancej . exceptions . InternalServiceErrorException If the error occurs on Binance ' s side
* @throws com . sigmaflare . binancej . exceptions . BinanceServiceUnreachableException If the service is unreachable
* @throws IllegalArgumentException If the required arguments symbol and interval are not supplied
* /
public Either < ServiceError , List < Candlestick > >
public List < Candlestick >
getCandleStickData ( String symbol , Interval interval , int limit , long startTime , long endTime )
throws BinanceServiceUnreachableException {
throws BinanceServiceException {
checkCandlestickLimit ( limit ) ;
if ( symbol = = null | | interval = = null ) {
throw new IllegalArgumentException ( SYMBOL_AND_INTERVAL_MUST_BE_SUPPLIED ) ;
@ -263,11 +313,16 @@ public class MarketData extends BaseBinanceApi {
* Retrieves the current ticker price for the specified symbol
*
* @param symbol The symbol
* @return A TickerPrice if successful , otherwise an ServiceError
* @throws BinanceServiceUnreachableException If the service is unreachable
* @return A populated list of TickerPrice objects
* @throws com . sigmaflare . binancej . exceptions . IpBannedException If the IP is banned
* @throws com . sigmaflare . binancej . exceptions . RateLimitExceededException If the rate limit is exceeded
* @throws com . sigmaflare . binancej . exceptions . MalformedRequestException If the user ' s request is malformed
* @throws com . sigmaflare . binancej . exceptions . InternalServiceErrorException If the error occurs on Binance ' s side
* @throws com . sigmaflare . binancej . exceptions . BinanceServiceUnreachableException If the service is unreachable
* @throws UnexpectedErrorException If an unexpected exception occurs
* /
public Either < ServiceError , TickerPrice > getTickerPriceForSymbol ( String symbol )
throws BinanceServiceUnreachableException {
public TickerPrice getTickerPriceForSymbol ( String symbol )
throws BinanceServiceException {
if ( symbol = = null ) {
throw new IllegalArgumentException ( "Symbol must not be null" ) ;
}
@ -289,14 +344,15 @@ public class MarketData extends BaseBinanceApi {
String response = EntityUtils . toString ( httpEntity ) ;
if ( ! Helpers . statusCodeIsOk ( sl . getStatusCode ( ) ) ) {
return Either . ofLeft ( mapper . readValue ( response , ServiceError . class ) ) ;
if ( ! HttpRequests . statusCodeIsOk ( sl . getStatusCode ( ) ) ) {
ServiceError error = mapper . readValue ( response , ServiceError . class ) ;
throw HttpRequests . buildHttpException ( sl . getStatusCode ( ) , error ) ;
}
return Either . ofRight ( mapper . readValue ( response , TickerPrice . class ) ) ;
return mapper . readValue ( response , TickerPrice . class ) ;
}
} catch ( IOException e ) {
throw new BinanceServiceUnreachable Exception( e . getMessage ( ) , e . getCause ( ) ) ;
throw new UnexpectedError Exception( e . getMessage ( ) , e . getCause ( ) ) ;
}
}
@ -304,10 +360,15 @@ public class MarketData extends BaseBinanceApi {
* Retrieves ticker prices for all supported Binance symbols . This is good to use in terms of cost if you need
* more than one symbol ' s current ticker price .
*
* @return Either a list of TickerPrice objects if successful , or an ServiceError
* @throws BinanceServiceUnreachableException If the service is unreachable
* @return A populated list of TickerPrice objects
* @throws com . sigmaflare . binancej . exceptions . IpBannedException If the IP is banned
* @throws com . sigmaflare . binancej . exceptions . RateLimitExceededException If the rate limit is exceeded
* @throws com . sigmaflare . binancej . exceptions . MalformedRequestException If the user ' s request is malformed
* @throws com . sigmaflare . binancej . exceptions . InternalServiceErrorException If the error occurs on Binance ' s side
* @throws com . sigmaflare . binancej . exceptions . BinanceServiceUnreachableException If the service is unreachable
* @throws UnexpectedErrorException If an unexpected exception occurs
* /
public Either < ServiceError , List < TickerPrice > > getTickerPrices ( ) throws BinanceServiceUnreachableException {
public List < TickerPrice > getTickerPrices ( ) throws BinanceServiceException {
final HttpGet request = buildGetRequestFromEndpoint ( TICKER_PRICE_URL , apiKey ) ;
try {
@ -324,15 +385,16 @@ public class MarketData extends BaseBinanceApi {
String response = EntityUtils . toString ( httpEntity ) ;
if ( ! Helpers . statusCodeIsOk ( sl . getStatusCode ( ) ) ) {
return Either . ofLeft ( mapper . readValue ( response , ServiceError . class ) ) ;
if ( ! HttpRequests . statusCodeIsOk ( sl . getStatusCode ( ) ) ) {
ServiceError error = mapper . readValue ( response , ServiceError . class ) ;
throw HttpRequests . buildHttpException ( sl . getStatusCode ( ) , error ) ;
}
JavaType type = mapper . getTypeFactory ( ) . constructCollectionType ( List . class , TickerPrice . class ) ;
return Either . ofRight ( mapper . readValue ( response , type ) ) ;
return mapper . readValue ( response , type ) ;
}
} catch ( IOException e ) {
throw new BinanceServiceUnreachable Exception( e . getMessage ( ) , e . getCause ( ) ) ;
throw new UnexpectedError Exception( e . getMessage ( ) , e . getCause ( ) ) ;
}
}
@ -341,11 +403,16 @@ public class MarketData extends BaseBinanceApi {
* as glorified URL builders .
*
* @param endpoint The endpoint to use that has the associated parameters populated
* @return A list of candlesticks if successful , otherwise an ServiceError
* @throws BinanceServiceUnreachableException If the service is unreachable
* @return A list of candlesticks
* @throws com . sigmaflare . binancej . exceptions . IpBannedException If the IP is banned
* @throws com . sigmaflare . binancej . exceptions . RateLimitExceededException If the rate limit is exceeded
* @throws com . sigmaflare . binancej . exceptions . MalformedRequestException If the user ' s request is malformed
* @throws com . sigmaflare . binancej . exceptions . InternalServiceErrorException If the error occurs on Binance ' s side
* @throws com . sigmaflare . binancej . exceptions . BinanceServiceUnreachableException If the service is unreachable
* @throws UnexpectedErrorException If an unexpected exception occurs
* /
private Either < ServiceError , List < Candlestick > >
getCandleStickDataFromUrl ( String endpoint ) throws BinanceServiceUnreachableException {
private List < Candlestick >
getCandleStickDataFromUrl ( String endpoint ) throws BinanceServiceException {
final HttpGet request = buildGetRequestFromEndpoint ( endpoint , apiKey ) ;
try {
@ -362,15 +429,16 @@ public class MarketData extends BaseBinanceApi {
String response = EntityUtils . toString ( httpEntity ) ;
if ( ! Helpers . statusCodeIsOk ( sl . getStatusCode ( ) ) ) {
return Either . ofLeft ( mapper . readValue ( response , ServiceError . class ) ) ;
if ( ! HttpRequests . statusCodeIsOk ( sl . getStatusCode ( ) ) ) {
ServiceError error = mapper . readValue ( response , ServiceError . class ) ;
throw HttpRequests . buildHttpException ( sl . getStatusCode ( ) , error ) ;
}
JavaType type = mapper . getTypeFactory ( ) . constructCollectionType ( List . class , Candlestick . class ) ;
return Either . ofRight ( mapper . readValue ( response , type ) ) ;
return mapper . readValue ( response , type ) ;
}
} catch ( IOException e ) {
throw new BinanceServiceUnreachable Exception( e . getMessage ( ) , e . getCause ( ) ) ;
throw new UnexpectedError Exception( e . getMessage ( ) , e . getCause ( ) ) ;
}
}
}