From e1833e75f69376dddbcb66023395a52b6c1cba92 Mon Sep 17 00:00:00 2001 From: Raphael Vullriede Date: Thu, 29 Feb 2024 20:43:39 +0100 Subject: [PATCH] add support for PRO and DEMO tokens --- .github/workflows/maven-publish-release.yml | 2 +- .github/workflows/maven.yml | 2 +- pom.xml | 24 ++++- .../litesoftwares/coingecko/CoinGeckoApi.java | 42 ++++++-- .../coingecko/constant/TokenType.java | 16 +++ .../coingecko/domain/ApiToken.java | 31 ++++++ .../impl/CoinGeckoApiClientImpl.java | 99 +++++++++++-------- .../coingecko/examples/SearchExample.java | 2 +- 8 files changed, 164 insertions(+), 54 deletions(-) create mode 100644 src/main/java/com/litesoftwares/coingecko/constant/TokenType.java create mode 100644 src/main/java/com/litesoftwares/coingecko/domain/ApiToken.java diff --git a/.github/workflows/maven-publish-release.yml b/.github/workflows/maven-publish-release.yml index 102cd60..11ed4aa 100644 --- a/.github/workflows/maven-publish-release.yml +++ b/.github/workflows/maven-publish-release.yml @@ -13,7 +13,7 @@ jobs: cat <(echo -e "${{ secrets.OSSRH_GPG_SECRET_KEY }}") | gpg --batch --import # Verify gpg secret key gpg --list-secret-keys --keyid-format LONG - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up JDK uses: actions/setup-java@v3 with: diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 3f4af37..d1f2ca0 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -12,7 +12,7 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up JDK uses: actions/setup-java@v3 with: diff --git a/pom.xml b/pom.xml index ad308f8..7374d77 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ net.osslabz coingecko-java - 1.0.1-SNAPSHOT + 1.1.0 ${project.groupId}:${project.artifactId} Java wrapper for the CoinGecko API @@ -24,6 +24,7 @@ MIT License https://opensource.org/license/mit/ + @@ -50,6 +51,17 @@ ${retrofit.version} + + com.squareup.okhttp3 + logging-interceptor + 4.12.0 + + + org.slf4j + slf4j-api + 2.0.9 + + com.squareup.retrofit2 converter-jackson @@ -63,6 +75,14 @@ provided + + + ch.qos.logback + logback-classic + 1.4.14 + test + + @@ -86,7 +106,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.5.0 + 3.6.3 attach-javadocs diff --git a/src/main/java/com/litesoftwares/coingecko/CoinGeckoApi.java b/src/main/java/com/litesoftwares/coingecko/CoinGeckoApi.java index 0e349d7..02029c1 100644 --- a/src/main/java/com/litesoftwares/coingecko/CoinGeckoApi.java +++ b/src/main/java/com/litesoftwares/coingecko/CoinGeckoApi.java @@ -1,7 +1,11 @@ package com.litesoftwares.coingecko; +import com.litesoftwares.coingecko.constant.TokenType; +import com.litesoftwares.coingecko.domain.ApiToken; import com.litesoftwares.coingecko.exception.CoinGeckoApiException; import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.logging.HttpLoggingInterceptor; import retrofit2.Call; import retrofit2.Response; import retrofit2.Retrofit; @@ -12,20 +16,38 @@ import java.util.concurrent.TimeUnit; public class CoinGeckoApi { - private final String API_BASE_URL = "https://api.coingecko.com/api/v3/"; + + private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(CoinGeckoApi.class); + private static final String API_BASE_URL_PUBLIC = "https://api.coingecko.com/api/v3/"; + + private static final String API_BASE_URL_PRO = "https://pro-api.coingecko.com/api/v3/"; private OkHttpClient okHttpClient = null; private Retrofit retrofit = null; - public S createService(Class serviceClass, Long connectionTimeoutSeconds, Long readTimeoutSeconds, Long writeTimeoutSeconds){ - okHttpClient = new OkHttpClient.Builder() + public S createService(Class serviceClass, Long connectionTimeoutSeconds, Long readTimeoutSeconds, Long writeTimeoutSeconds, ApiToken apiToken) { + OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder() .connectTimeout(connectionTimeoutSeconds, TimeUnit.SECONDS) .readTimeout(readTimeoutSeconds, TimeUnit.SECONDS) - .writeTimeout(writeTimeoutSeconds, TimeUnit.SECONDS) - .build(); + .writeTimeout(writeTimeoutSeconds, TimeUnit.SECONDS); + + if (apiToken != null) { + httpClientBuilder.addInterceptor(chain -> { + Request original = chain.request(); + Request request = original.newBuilder() + .header(apiToken.getType().getHeaderName(), apiToken.getValue()) + .method(original.method(), original.body()) + .build(); + + return chain.proceed(request); + }); + } + httpClientBuilder.addInterceptor(new HttpLoggingInterceptor(log::trace).setLevel(HttpLoggingInterceptor.Level.HEADERS)); + + okHttpClient = httpClientBuilder.build(); retrofit = new Retrofit.Builder() - .baseUrl(API_BASE_URL) + .baseUrl(apiToken != null && TokenType.PRO.equals(apiToken.getType()) ? API_BASE_URL_PRO : API_BASE_URL_PUBLIC) .client(okHttpClient) .addConverterFactory(JacksonConverterFactory.create()) .build(); @@ -38,7 +60,7 @@ public T executeSync(Call call) { Response response = call.execute(); if (response.isSuccessful()) { return response.body(); - } else if(response.code() == 429) { + } else if (response.code() == 429) { // When the client gets rate limited the response is a CloudFlare error page, // not a regular error body. CoinGeckoApiError apiError = new CoinGeckoApiError(); @@ -68,9 +90,9 @@ public void shutdown() { } } - private CoinGeckoApiError getCoinGeckoApiError(Response response) throws IOException{ - return (CoinGeckoApiError) retrofit.responseBodyConverter(CoinGeckoApiError.class,new Annotation[0]) + private CoinGeckoApiError getCoinGeckoApiError(Response response) throws IOException { + return (CoinGeckoApiError) retrofit.responseBodyConverter(CoinGeckoApiError.class, new Annotation[0]) .convert(response.errorBody()); } -} +} \ No newline at end of file diff --git a/src/main/java/com/litesoftwares/coingecko/constant/TokenType.java b/src/main/java/com/litesoftwares/coingecko/constant/TokenType.java new file mode 100644 index 0000000..dee9287 --- /dev/null +++ b/src/main/java/com/litesoftwares/coingecko/constant/TokenType.java @@ -0,0 +1,16 @@ +package com.litesoftwares.coingecko.constant; + +public enum TokenType { + DEMO("x-cg-demo-api-key"), + PRO("x-cg-demo-api-key"); + + private final String headerName; + + TokenType(String headerName) { + this.headerName = headerName; + } + + public String getHeaderName() { + return headerName; + } +} \ No newline at end of file diff --git a/src/main/java/com/litesoftwares/coingecko/domain/ApiToken.java b/src/main/java/com/litesoftwares/coingecko/domain/ApiToken.java new file mode 100644 index 0000000..b3ffed7 --- /dev/null +++ b/src/main/java/com/litesoftwares/coingecko/domain/ApiToken.java @@ -0,0 +1,31 @@ +package com.litesoftwares.coingecko.domain; + +import com.litesoftwares.coingecko.constant.TokenType; + +public class ApiToken { + + private TokenType type; + + private String value; + + public ApiToken(TokenType type, String value) { + this.type = type; + this.value = value; + } + + public static ApiToken demo(String value) { + return new ApiToken(TokenType.DEMO, value); + } + + public static ApiToken pro(String value) { + return new ApiToken(TokenType.PRO, value); + } + + public TokenType getType() { + return type; + } + + public String getValue() { + return value; + } +} \ No newline at end of file diff --git a/src/main/java/com/litesoftwares/coingecko/impl/CoinGeckoApiClientImpl.java b/src/main/java/com/litesoftwares/coingecko/impl/CoinGeckoApiClientImpl.java index 23661ed..3843a89 100644 --- a/src/main/java/com/litesoftwares/coingecko/impl/CoinGeckoApiClientImpl.java +++ b/src/main/java/com/litesoftwares/coingecko/impl/CoinGeckoApiClientImpl.java @@ -1,20 +1,30 @@ package com.litesoftwares.coingecko.impl; -import com.litesoftwares.coingecko.CoinGeckoApiService; import com.litesoftwares.coingecko.CoinGeckoApi; -import com.litesoftwares.coingecko.domain.*; -import com.litesoftwares.coingecko.domain.Coins.*; +import com.litesoftwares.coingecko.CoinGeckoApiClient; +import com.litesoftwares.coingecko.CoinGeckoApiService; +import com.litesoftwares.coingecko.domain.AssetPlatforms; +import com.litesoftwares.coingecko.domain.Coins.CoinFullData; +import com.litesoftwares.coingecko.domain.Coins.CoinHistoryById; +import com.litesoftwares.coingecko.domain.Coins.CoinList; +import com.litesoftwares.coingecko.domain.Coins.CoinMarkets; +import com.litesoftwares.coingecko.domain.Coins.CoinTickerById; +import com.litesoftwares.coingecko.domain.Coins.MarketChart; import com.litesoftwares.coingecko.domain.Events.EventCountries; import com.litesoftwares.coingecko.domain.Events.EventTypes; import com.litesoftwares.coingecko.domain.Events.Events; import com.litesoftwares.coingecko.domain.ExchangeRates.ExchangeRates; -import com.litesoftwares.coingecko.domain.Exchanges.*; +import com.litesoftwares.coingecko.domain.Exchanges.ExchangeById; +import com.litesoftwares.coingecko.domain.Exchanges.Exchanges; +import com.litesoftwares.coingecko.domain.Exchanges.ExchangesList; +import com.litesoftwares.coingecko.domain.Exchanges.ExchangesTickersById; import com.litesoftwares.coingecko.domain.Global.DecentralizedFinanceDefi; import com.litesoftwares.coingecko.domain.Global.Global; +import com.litesoftwares.coingecko.domain.Ping; import com.litesoftwares.coingecko.domain.Search.Search; import com.litesoftwares.coingecko.domain.Search.Trending; import com.litesoftwares.coingecko.domain.Status.StatusUpdates; -import com.litesoftwares.coingecko.CoinGeckoApiClient; +import com.litesoftwares.coingecko.domain.ApiToken; import java.util.List; import java.util.Map; @@ -31,43 +41,52 @@ public CoinGeckoApiClientImpl() { this(DEFAULT_CONNECTION_TIMEOUT, DEFAULT_READ_TIMEOUT, DEFAULT_WRITE_TIMEOUT); } - public CoinGeckoApiClientImpl(Long connectionTimeoutSeconds, Long readTimeoutSeconds, Long writeTimeoutSeconds){ + public CoinGeckoApiClientImpl(ApiToken apiToken) { + this(DEFAULT_CONNECTION_TIMEOUT, DEFAULT_READ_TIMEOUT, DEFAULT_WRITE_TIMEOUT, apiToken); + } + + public CoinGeckoApiClientImpl(Long connectionTimeoutSeconds, Long readTimeoutSeconds, Long writeTimeoutSeconds) { + this(connectionTimeoutSeconds, readTimeoutSeconds, writeTimeoutSeconds, null); + } + + public CoinGeckoApiClientImpl(Long connectionTimeoutSeconds, Long readTimeoutSeconds, Long writeTimeoutSeconds, ApiToken apiToken) { this.coinGeckoApi = new CoinGeckoApi(); this.coinGeckoApiService = coinGeckoApi.createService( CoinGeckoApiService.class, connectionTimeoutSeconds, readTimeoutSeconds, - writeTimeoutSeconds + writeTimeoutSeconds, + apiToken ); } @Override - public Ping ping(){ + public Ping ping() { return coinGeckoApi.executeSync(coinGeckoApiService.ping()); } @Override - public Map> getPrice(String ids, String vsCurrencies){ - return getPrice(ids, vsCurrencies, false, false, false, false); + public Map> getPrice(String ids, String vsCurrencies) { + return getPrice(ids, vsCurrencies, false, false, false, false); } @Override public Map> getPrice(String ids, String vsCurrencies, boolean includeMarketCap, boolean include24hrVol, boolean include24hrChange, boolean includeLastUpdatedAt) { - return coinGeckoApi.executeSync(coinGeckoApiService.getPrice(ids, vsCurrencies,includeMarketCap, include24hrVol, include24hrChange, includeLastUpdatedAt)); + return coinGeckoApi.executeSync(coinGeckoApiService.getPrice(ids, vsCurrencies, includeMarketCap, include24hrVol, include24hrChange, includeLastUpdatedAt)); } @Override public Map> getTokenPrice(String id, String contractAddress, String vsCurrencies) { - return getTokenPrice(id,contractAddress,vsCurrencies,false,false,false,false); + return getTokenPrice(id, contractAddress, vsCurrencies, false, false, false, false); } @Override public Map> getTokenPrice(String id, String contractAddress, String vsCurrencies, boolean includeMarketCap, boolean include24hrVol, boolean include24hrChange, boolean includeLastUpdatedAt) { - return coinGeckoApi.executeSync(coinGeckoApiService.getTokenPrice(id,contractAddress,vsCurrencies,includeMarketCap,include24hrVol,include24hrChange,includeLastUpdatedAt)); + return coinGeckoApi.executeSync(coinGeckoApiService.getTokenPrice(id, contractAddress, vsCurrencies, includeMarketCap, include24hrVol, include24hrChange, includeLastUpdatedAt)); } @Override - public List getSupportedVsCurrencies(){ + public List getSupportedVsCurrencies() { return coinGeckoApi.executeSync(coinGeckoApiService.getSupportedVsCurrencies()); } @@ -78,7 +97,7 @@ public List getCoinList() { @Override public List getCoinMarkets(String vsCurrency) { - return getCoinMarkets(vsCurrency,null,null,null,null,false,null); + return getCoinMarkets(vsCurrency, null, null, null, null, false, null); } @Override @@ -93,37 +112,37 @@ public List getCoinMarkets(String vsCurrency, String ids, String ca @Override public CoinFullData getCoinById(String id) { - return getCoinById(id,true,true,true,true,true,false); + return getCoinById(id, true, true, true, true, true, false); } @Override public CoinFullData getCoinById(String id, boolean localization, boolean tickers, boolean marketData, boolean communityData, boolean developerData, boolean sparkline) { - return coinGeckoApi.executeSync(coinGeckoApiService.getCoinById(id,localization,tickers,marketData,communityData,developerData,sparkline)); + return coinGeckoApi.executeSync(coinGeckoApiService.getCoinById(id, localization, tickers, marketData, communityData, developerData, sparkline)); } @Override public CoinTickerById getCoinTickerById(String id) { - return getCoinTickerById(id,null,null,null); + return getCoinTickerById(id, null, null, null); } @Override public CoinTickerById getCoinTickerById(String id, String exchangeIds, Integer page, String order) { - return coinGeckoApi.executeSync(coinGeckoApiService.getCoinTickerById(id,exchangeIds,page,order)); + return coinGeckoApi.executeSync(coinGeckoApiService.getCoinTickerById(id, exchangeIds, page, order)); } @Override public CoinHistoryById getCoinHistoryById(String id, String date) { - return getCoinHistoryById(id,date,true); + return getCoinHistoryById(id, date, true); } @Override public CoinHistoryById getCoinHistoryById(String id, String date, boolean localization) { - return coinGeckoApi.executeSync(coinGeckoApiService.getCoinHistoryById(id,date,localization)); + return coinGeckoApi.executeSync(coinGeckoApiService.getCoinHistoryById(id, date, localization)); } @Override public MarketChart getCoinMarketChartById(String id, String vsCurrency, Integer days) { - return coinGeckoApi.executeSync(coinGeckoApiService.getCoinMarketChartById(id,vsCurrency,days)); + return coinGeckoApi.executeSync(coinGeckoApiService.getCoinMarketChartById(id, vsCurrency, days)); } @Override @@ -133,31 +152,31 @@ public MarketChart getCoinMarketChartById(String id, String vsCurrency, Integer @Override public MarketChart getCoinMarketChartRangeById(String id, String vsCurrency, String from, String to) { - return coinGeckoApi.executeSync(coinGeckoApiService.getCoinMarketChartRangeById(id,vsCurrency,from,to)); + return coinGeckoApi.executeSync(coinGeckoApiService.getCoinMarketChartRangeById(id, vsCurrency, from, to)); } @Override public List> getCoinOHLC(String id, String vsCurrency, Integer days) { - return coinGeckoApi.executeSync(coinGeckoApiService.getCoinOHLC(id,vsCurrency,days)); + return coinGeckoApi.executeSync(coinGeckoApiService.getCoinOHLC(id, vsCurrency, days)); } @Override public StatusUpdates getCoinStatusUpdateById(String id) { - return getCoinStatusUpdateById(id,null,null); + return getCoinStatusUpdateById(id, null, null); } @Override public StatusUpdates getCoinStatusUpdateById(String id, Integer perPage, Integer page) { - return coinGeckoApi.executeSync(coinGeckoApiService.getCoinStatusUpdateById(id,perPage,page)); + return coinGeckoApi.executeSync(coinGeckoApiService.getCoinStatusUpdateById(id, perPage, page)); } @Override public CoinFullData getCoinInfoByContractAddress(String id, String contractAddress) { - return coinGeckoApi.executeSync(coinGeckoApiService.getCoinInfoByContractAddress(id,contractAddress)); + return coinGeckoApi.executeSync(coinGeckoApiService.getCoinInfoByContractAddress(id, contractAddress)); } @Override - public List getAssetPlatforms(){ + public List getAssetPlatforms() { return coinGeckoApi.executeSync(coinGeckoApiService.getAssetPlatforms()); } @@ -183,27 +202,27 @@ public ExchangeById getExchangesById(String id) { @Override public ExchangesTickersById getExchangesTickersById(String id) { - return getExchangesTickersById(id,null,null,null); + return getExchangesTickersById(id, null, null, null); } @Override public ExchangesTickersById getExchangesTickersById(String id, String coinIds, Integer page, String order) { - return coinGeckoApi.executeSync(coinGeckoApiService.getExchangesTickersById(id,coinIds,page,order)); + return coinGeckoApi.executeSync(coinGeckoApiService.getExchangesTickersById(id, coinIds, page, order)); } @Override public StatusUpdates getExchangesStatusUpdatesById(String id) { - return getExchangesStatusUpdatesById(id,null,null); + return getExchangesStatusUpdatesById(id, null, null); } @Override public StatusUpdates getExchangesStatusUpdatesById(String id, Integer perPage, Integer page) { - return coinGeckoApi.executeSync(coinGeckoApiService.getExchangesStatusUpdatesById(id,perPage,page)); + return coinGeckoApi.executeSync(coinGeckoApiService.getExchangesStatusUpdatesById(id, perPage, page)); } @Override public List> getExchangesVolumeChart(String id, Integer days) { - return coinGeckoApi.executeSync(coinGeckoApiService.getExchangesVolumeChart(id,days)); + return coinGeckoApi.executeSync(coinGeckoApiService.getExchangesVolumeChart(id, days)); } @Deprecated @@ -215,7 +234,7 @@ public StatusUpdates getStatusUpdates() { @Deprecated @Override public StatusUpdates getStatusUpdates(String category, String projectType, Integer perPage, Integer page) { - return coinGeckoApi.executeSync(coinGeckoApiService.getStatusUpdates(category, projectType,perPage,page)); + return coinGeckoApi.executeSync(coinGeckoApiService.getStatusUpdates(category, projectType, perPage, page)); } @Deprecated @@ -227,7 +246,7 @@ public Events getEvents() { @Deprecated @Override public Events getEvents(String countryCode, String type, Integer page, boolean upcomingEventsOnly, String fromDate, String toDate) { - return coinGeckoApi.executeSync(coinGeckoApiService.getEvents(countryCode,type,page,upcomingEventsOnly,fromDate,toDate)); + return coinGeckoApi.executeSync(coinGeckoApiService.getEvents(countryCode, type, page, upcomingEventsOnly, fromDate, toDate)); } @Deprecated @@ -248,12 +267,14 @@ public ExchangeRates getExchangeRates() { } @Override - public Trending getTrending(){ + public Trending getTrending() { return coinGeckoApi.executeSync(coinGeckoApiService.getTrending()); } @Override - public Search getSearchResult(String query) {return coinGeckoApi.executeSync(coinGeckoApiService.getSearch(query));} + public Search getSearchResult(String query) { + return coinGeckoApi.executeSync(coinGeckoApiService.getSearch(query)); + } @Override public Global getGlobal() { @@ -261,7 +282,7 @@ public Global getGlobal() { } @Override - public DecentralizedFinanceDefi getDecentralizedFinanceDefi(){ + public DecentralizedFinanceDefi getDecentralizedFinanceDefi() { return coinGeckoApi.executeSync(coinGeckoApiService.getDecentralizedFinanceDefi()); } @@ -269,4 +290,4 @@ public DecentralizedFinanceDefi getDecentralizedFinanceDefi(){ public void shutdown() { coinGeckoApi.shutdown(); } -} +} \ No newline at end of file diff --git a/src/test/java/com/litesoftwares/coingecko/examples/SearchExample.java b/src/test/java/com/litesoftwares/coingecko/examples/SearchExample.java index a1b021f..a1c75e7 100644 --- a/src/test/java/com/litesoftwares/coingecko/examples/SearchExample.java +++ b/src/test/java/com/litesoftwares/coingecko/examples/SearchExample.java @@ -16,4 +16,4 @@ public static void main(String[] args) { System.out.println(search); } -} +} \ No newline at end of file