From 1559a3faf723dbc0d9bba75b1e7ab4a764f262b6 Mon Sep 17 00:00:00 2001 From: Abhay Gupta Date: Thu, 21 Jul 2022 13:31:07 +0530 Subject: [PATCH 1/5] added support for txsToken with contract address too --- .../io/api/etherscan/core/IAccountApi.java | 19 ++++++++++++++ .../core/impl/AccountApiProvider.java | 26 +++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/src/main/java/io/api/etherscan/core/IAccountApi.java b/src/main/java/io/api/etherscan/core/IAccountApi.java index 25254aa..b3e12fb 100644 --- a/src/main/java/io/api/etherscan/core/IAccountApi.java +++ b/src/main/java/io/api/etherscan/core/IAccountApi.java @@ -110,6 +110,25 @@ public interface IAccountApi { @NotNull List txsToken(String address) throws ApiException; + /** + * All ERC-20 token txs for given address and contract address + * + * @param address get txs for + * @param contractAddress contract address to get txs for + * @param startBlock tx from this blockNumber + * @param endBlock tx to this blockNumber + * @return txs for address + * @throws ApiException parent exception class + */ + @NotNull + List txsToken(String address, String contractAddress, long startBlock, long endBlock) throws ApiException; + + @NotNull + List txsToken(String address, String contractAddress, long startBlock) throws ApiException; + + @NotNull + List txsToken(String address, String contractAddress) throws ApiException; + /** * All ERC-721 (NFT) token txs for given address * diff --git a/src/main/java/io/api/etherscan/core/impl/AccountApiProvider.java b/src/main/java/io/api/etherscan/core/impl/AccountApiProvider.java index 77d8b88..dba413a 100644 --- a/src/main/java/io/api/etherscan/core/impl/AccountApiProvider.java +++ b/src/main/java/io/api/etherscan/core/impl/AccountApiProvider.java @@ -230,6 +230,32 @@ public List txsToken(final String address, final long startBlock, final return getRequestUsingOffset(urlParams, TxTokenResponseTO.class); } + @NotNull + @Override + public List txsToken(final String address, final String contractAddress) throws ApiException { + return txsToken(address, contractAddress, MIN_START_BLOCK); + } + + @NotNull + @Override + public List txsToken(final String address, final String contractAddress, final long startBlock) throws ApiException { + return txsToken(address, contractAddress, startBlock, MAX_END_BLOCK); + } + + @NotNull + @Override + public List txsToken(final String address, final String contractAddress, final long startBlock, final long endBlock) throws ApiException { + BasicUtils.validateAddress(address); + final BlockParam blocks = BasicUtils.compensateBlocks(startBlock, endBlock); + + final String offsetParam = PAGE_PARAM + "%s" + OFFSET_PARAM + OFFSET_MAX; + final String blockParam = START_BLOCK_PARAM + blocks.start() + END_BLOCK_PARAM + blocks.end(); + final String urlParams = ACT_TX_TOKEN_ACTION + offsetParam + ADDRESS_PARAM + address + + CONTRACT_PARAM + contractAddress + blockParam + SORT_ASC_PARAM; + + return getRequestUsingOffset(urlParams, TxTokenResponseTO.class); + } + @NotNull @Override public List txsNftToken(String address) throws ApiException { From 9fb7d918e63deaf349bbd09b5635935db995f4cd Mon Sep 17 00:00:00 2001 From: Abhay Gupta Date: Mon, 14 Nov 2022 17:59:49 +0530 Subject: [PATCH 2/5] gas tracker API implementation --- .../io/api/etherscan/core/IGasTrackerApi.java | 23 +++++++ .../api/etherscan/core/impl/EtherScanApi.java | 7 ++ .../core/impl/GasTrackerApiProvider.java | 39 +++++++++++ .../io/api/etherscan/model/GasOracle.java | 68 +++++++++++++++++++ .../model/utility/GasOracleResponseTO.java | 18 +++++ 5 files changed, 155 insertions(+) create mode 100644 src/main/java/io/api/etherscan/core/IGasTrackerApi.java create mode 100644 src/main/java/io/api/etherscan/core/impl/GasTrackerApiProvider.java create mode 100644 src/main/java/io/api/etherscan/model/GasOracle.java create mode 100644 src/main/java/io/api/etherscan/model/utility/GasOracleResponseTO.java diff --git a/src/main/java/io/api/etherscan/core/IGasTrackerApi.java b/src/main/java/io/api/etherscan/core/IGasTrackerApi.java new file mode 100644 index 0000000..894713f --- /dev/null +++ b/src/main/java/io/api/etherscan/core/IGasTrackerApi.java @@ -0,0 +1,23 @@ +package io.api.etherscan.core; + +import io.api.etherscan.error.ApiException; +import io.api.etherscan.model.GasOracle; +import org.jetbrains.annotations.NotNull; + +/** + * EtherScan - API Descriptions https://docs.etherscan.io/api-endpoints/gas-tracker + * + * @author Abhay Gupta + * @since 14.11.2022 + */ +public interface IGasTrackerApi { + + /** + * GasOracle details + * + * @return fast, suggested gas price + * @throws ApiException parent exception class + */ + @NotNull + GasOracle gasoracle() throws ApiException; +} diff --git a/src/main/java/io/api/etherscan/core/impl/EtherScanApi.java b/src/main/java/io/api/etherscan/core/impl/EtherScanApi.java index ba5dd83..957315d 100644 --- a/src/main/java/io/api/etherscan/core/impl/EtherScanApi.java +++ b/src/main/java/io/api/etherscan/core/impl/EtherScanApi.java @@ -34,6 +34,7 @@ public class EtherScanApi implements AutoCloseable { private final IProxyApi proxy; private final IStatisticApi stats; private final ITransactionApi txs; + private final IGasTrackerApi gastracker; public EtherScanApi() { this(DEFAULT_KEY, EthNetwork.MAINNET); @@ -96,6 +97,7 @@ public EtherScanApi(final String apiKey, this.proxy = new ProxyApiProvider(queue, baseUrl, executor); this.stats = new StatisticApiProvider(queue, baseUrl, executor); this.txs = new TransactionApiProvider(queue, baseUrl, executor); + this.gastracker = new GasTrackerApiProvider(queue, baseUrl, executor); } @NotNull @@ -133,6 +135,11 @@ public IStatisticApi stats() { return stats; } + @NotNull + public IGasTrackerApi gastracker() { + return gastracker; + } + @Override public void close() throws Exception { queueManager.close(); diff --git a/src/main/java/io/api/etherscan/core/impl/GasTrackerApiProvider.java b/src/main/java/io/api/etherscan/core/impl/GasTrackerApiProvider.java new file mode 100644 index 0000000..16d2e63 --- /dev/null +++ b/src/main/java/io/api/etherscan/core/impl/GasTrackerApiProvider.java @@ -0,0 +1,39 @@ +package io.api.etherscan.core.impl; + +import io.api.etherscan.core.IGasTrackerApi; +import io.api.etherscan.error.ApiException; +import io.api.etherscan.error.EtherScanException; +import io.api.etherscan.executor.IHttpExecutor; +import io.api.etherscan.manager.IQueueManager; +import io.api.etherscan.model.GasOracle; +import io.api.etherscan.model.utility.GasOracleResponseTO; +import org.jetbrains.annotations.NotNull; + +/** + * GasTracker API Implementation + * + * @see IGasTrackerApi + * + * @author Abhay Gupta + * @since 14.11.2022 + */ +public class GasTrackerApiProvider extends BasicProvider implements IGasTrackerApi { + + private static final String ACT_GAS_ORACLE_PARAM = ACT_PREFIX + "gasoracle"; + + GasTrackerApiProvider(final IQueueManager queue, + final String baseUrl, + final IHttpExecutor executor) { + super(queue, "gastracker", baseUrl, executor); + } + + @NotNull + @Override + public GasOracle gasoracle() throws ApiException { + final GasOracleResponseTO response = getRequest(ACT_GAS_ORACLE_PARAM, GasOracleResponseTO.class); + if (response.getStatus() != 1) + throw new EtherScanException(response); + + return response.getResult(); + } +} diff --git a/src/main/java/io/api/etherscan/model/GasOracle.java b/src/main/java/io/api/etherscan/model/GasOracle.java new file mode 100644 index 0000000..f3f66c2 --- /dev/null +++ b/src/main/java/io/api/etherscan/model/GasOracle.java @@ -0,0 +1,68 @@ +package io.api.etherscan.model; + +import java.math.BigInteger; +import java.util.Objects; + +/** + * ! NO DESCRIPTION ! + * + * @author Abhay Gupta + * @since 14.11.2022 + */ +public class GasOracle { + private Long LastBlock; + private Integer SafeGasPrice; + private Integer ProposeGasPrice; + private Integer FastGasPrice; + private Double suggestBaseFee; + private String gasUsedRatio; + + public Long getLastBlock() { + return LastBlock; + } + + public BigInteger getSafeGasPriceInWei() { + return BigInteger.valueOf(SafeGasPrice).multiply(BigInteger.TEN.pow(9)); + } + + public BigInteger getProposeGasPriceInWei() { + return BigInteger.valueOf(ProposeGasPrice).multiply(BigInteger.TEN.pow(9)); + } + + public BigInteger getFastGasPriceInWei() { + return BigInteger.valueOf(FastGasPrice).multiply(BigInteger.TEN.pow(9)); + } + + public Double getSuggestBaseFee() { + return suggestBaseFee; + } + + public String getGasUsedRatio() { + return gasUsedRatio; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + GasOracle gasOracle = (GasOracle) o; + return LastBlock.equals(gasOracle.LastBlock) && SafeGasPrice.equals(gasOracle.SafeGasPrice) && ProposeGasPrice.equals(gasOracle.ProposeGasPrice) && FastGasPrice.equals(gasOracle.FastGasPrice) && suggestBaseFee.equals(gasOracle.suggestBaseFee) && gasUsedRatio.equals(gasOracle.gasUsedRatio); + } + + @Override + public int hashCode() { + return Objects.hash(LastBlock, SafeGasPrice, ProposeGasPrice, FastGasPrice, suggestBaseFee, gasUsedRatio); + } + + @Override + public String toString() { + return "GasOracle{" + + "LastBlock=" + LastBlock + + ", SafeGasPrice=" + SafeGasPrice + + ", ProposeGasPrice=" + ProposeGasPrice + + ", FastGasPrice=" + FastGasPrice + + ", suggestBaseFee=" + suggestBaseFee + + ", gasUsedRatio='" + gasUsedRatio + '\'' + + '}'; + } +} diff --git a/src/main/java/io/api/etherscan/model/utility/GasOracleResponseTO.java b/src/main/java/io/api/etherscan/model/utility/GasOracleResponseTO.java new file mode 100644 index 0000000..f0c1fd5 --- /dev/null +++ b/src/main/java/io/api/etherscan/model/utility/GasOracleResponseTO.java @@ -0,0 +1,18 @@ +package io.api.etherscan.model.utility; + +import io.api.etherscan.model.GasOracle; + +/** + * ! NO DESCRIPTION ! + * + * @author Abhay Gupta + * @since 14.11.2022 + */ +public class GasOracleResponseTO extends BaseResponseTO { + + private GasOracle result; + + public GasOracle getResult() { + return result; + } +} From 2174387cf8c57e86e4303b5468a258e017c257e6 Mon Sep 17 00:00:00 2001 From: Abhay Gupta Date: Mon, 14 Nov 2022 18:11:34 +0530 Subject: [PATCH 3/5] debug url --- src/main/java/io/api/etherscan/core/impl/BasicProvider.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/io/api/etherscan/core/impl/BasicProvider.java b/src/main/java/io/api/etherscan/core/impl/BasicProvider.java index b36f406..b0fbe68 100644 --- a/src/main/java/io/api/etherscan/core/impl/BasicProvider.java +++ b/src/main/java/io/api/etherscan/core/impl/BasicProvider.java @@ -77,6 +77,7 @@ T convert(final String json, final Class tClass) { String getRequest(final String urlParameters) { queue.takeTurn(); final String url = baseUrl + module + urlParameters; + System.out.println("Url generated: " + url); final String result = executor.get(url); if (BasicUtils.isEmpty(result)) throw new EtherScanException("Server returned null value for GET request at URL - " + url); From bf59b713daddb826c01d292b900f4ce6a462b184 Mon Sep 17 00:00:00 2001 From: Abhay Gupta Date: Mon, 14 Nov 2022 19:01:50 +0530 Subject: [PATCH 4/5] fixed gas oracle base url --- src/main/java/io/api/etherscan/core/impl/EtherScanApi.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/io/api/etherscan/core/impl/EtherScanApi.java b/src/main/java/io/api/etherscan/core/impl/EtherScanApi.java index 957315d..028c52b 100644 --- a/src/main/java/io/api/etherscan/core/impl/EtherScanApi.java +++ b/src/main/java/io/api/etherscan/core/impl/EtherScanApi.java @@ -88,6 +88,7 @@ public EtherScanApi(final String apiKey, final String ending = EthNetwork.TOBALABA.equals(network) ? "com" : "io"; final String baseUrl = "https://" + network.getDomain() + ".etherscan." + ending + "/api" + "?apikey=" + apiKey; + final String mainnetBaseUrl = "https://" + EthNetwork.MAINNET.getDomain() + ".etherscan." + ending + "/api" + "?apikey=" + apiKey; this.queueManager = queue; this.account = new AccountApiProvider(queue, baseUrl, executor); @@ -97,7 +98,7 @@ public EtherScanApi(final String apiKey, this.proxy = new ProxyApiProvider(queue, baseUrl, executor); this.stats = new StatisticApiProvider(queue, baseUrl, executor); this.txs = new TransactionApiProvider(queue, baseUrl, executor); - this.gastracker = new GasTrackerApiProvider(queue, baseUrl, executor); + this.gastracker = new GasTrackerApiProvider(queue, mainnetBaseUrl, executor); } @NotNull From c462175c09a35d15e0c7641e77e2cbeb5e0e892b Mon Sep 17 00:00:00 2001 From: Abhay Gupta Date: Mon, 14 Nov 2022 19:04:10 +0530 Subject: [PATCH 5/5] removed sout --- src/main/java/io/api/etherscan/core/impl/BasicProvider.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/io/api/etherscan/core/impl/BasicProvider.java b/src/main/java/io/api/etherscan/core/impl/BasicProvider.java index b0fbe68..b36f406 100644 --- a/src/main/java/io/api/etherscan/core/impl/BasicProvider.java +++ b/src/main/java/io/api/etherscan/core/impl/BasicProvider.java @@ -77,7 +77,6 @@ T convert(final String json, final Class tClass) { String getRequest(final String urlParameters) { queue.takeTurn(); final String url = baseUrl + module + urlParameters; - System.out.println("Url generated: " + url); final String result = executor.get(url); if (BasicUtils.isEmpty(result)) throw new EtherScanException("Server returned null value for GET request at URL - " + url);