diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 03c2e11..613a39e 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -4,12 +4,10 @@ on: push: branches: - master - schedule: - - cron: "0 12 1 * *" pull_request: branches: - - master - - dev + - master + - dev jobs: build: @@ -20,21 +18,26 @@ jobs: name: Java ${{ matrix.java }} setup steps: - - uses: actions/checkout@v1 - - name: Set up JDK - uses: actions/setup-java@v1 - - with: - java-version: ${{ matrix.java }} - - - name: Build with Gradle - run: ./gradlew build jacocoTestReport - env: - API_KEY: ${{ secrets.API_KEY }} - - - name: Analyze with SonarQube - run: ./gradlew sonarqube - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - API_KEY: ${{ secrets.API_KEY }} + - uses: actions/checkout@v1 + - name: Set up JDK + uses: actions/setup-java@v1 + + with: + java-version: ${{ matrix.java }} + + - name: Build + run: ./gradlew classes + + - name: Codestyle + run: ./gradlew spotlessCheck + + - name: Test + run: ./gradlew test jacocoTestReport + env: + API_KEY: ${{ secrets.API_KEY }} + + - name: SonarQube + run: ./gradlew sonarqube + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} diff --git a/README.md b/README.md index 352952b..cd88aaa 100644 --- a/README.md +++ b/README.md @@ -11,22 +11,23 @@ Library supports all available EtherScan *API* calls for all available *Ethereum Networks* for *etherscan.io* ## Dependency :rocket: + +**Gradle** +```groovy +dependencies { + compile "com.github.goodforgod:java-etherscan-api:1.1.1" +} +``` + **Maven** ```xml com.github.goodforgod java-etherscan-api - 1.1.0 + 1.1.1 ``` -**Gradle** -```groovy -dependencies { - compile 'com.github.goodforgod:java-etherscan-api:1.1.0' -} -``` - ## Content - [Ethereum Networks](#mainnet-and-testnets) - [Custom HttpClient](#custom-httpclient) @@ -42,6 +43,7 @@ dependencies { - [Version History](#version-history) ## Mainnet and Testnets + API support Ethereum: *[MAINNET](https://etherscan.io), [ROPSTEN](https://ropsten.etherscan.io), [KOVAN](https://kovan.etherscan.io), @@ -88,14 +90,18 @@ EtherScanApi api = new EtherScanApi("YourApiKey"); Below are examples for each API category. ### Account Api + **Get Ether Balance for a single Address** + ```java EtherScanApi api = new EtherScanApi(); Balance balance = api.account().balance("0x8d4426f94e42f721C7116E81d6688cd935cB3b4F"); ``` ### Block Api + **Get uncles block for block height** + ```java EtherScanApi api = new EtherScanApi(); Optional uncles = api.block().uncles(200000); @@ -109,7 +115,9 @@ Abi abi = api.contract().contractAbi("0xBB9bc244D798123fDe783fCc1C72d3Bb8C189413 ``` ### Logs Api + **Get event logs for single topic** + ```java EtherScanApi api = new EtherScanApi(); LogQuery query = LogQueryBuilder.with("0x33990122638b9132ca29c723bdf037f1a891a70c") @@ -119,6 +127,7 @@ List logs = api.logs().logs(query); ``` **Get event logs for 3 topics with respectful operations** + ```java EtherScanApi api = new EtherScanApi(); LogQuery query = LogQueryBuilder.with("0x33990122638b9132ca29c723bdf037f1a891a70c", 379224, 400000) @@ -134,47 +143,45 @@ List logs = api.logs().logs(query); ``` ### Proxy Api + **Get tx detailds with proxy endpoint** + ```java EtherScanApi api = new EtherScanApi(EthNetwork.MAINNET); Optional tx = api.proxy().tx("0x1e2910a262b1008d0616a0beb24c1a491d78771baa54a33e66065e03b1f46bc1"); ``` **Get block info with proxy endpoint** + ```java EtherScanApi api = new EtherScanApi(EthNetwork.MAINNET); Optional block = api.proxy().block(15215); ``` ### Stats Api + **Statistic about last price** + ```java EtherScanApi api = new EtherScanApi(); Price price = api.stats().lastPrice(); ``` ### Transaction Api + **Request receipt status for tx** + ```java EtherScanApi api = new EtherScanApi(); Optional status = api.txs().receiptStatus("0x513c1ba0bebf66436b5fed86ab668452b7805593c05073eb2d51d3a52f480a76"); ``` ### Token Api + You can read about token API [here](https://etherscan.io/apis#tokens) Token API methods migrated to [Account](#account-api) & [Stats](#stats-api) respectfully. -## Version History - -**1.1.0** - Improved error handling, QueueManager improved, Gradle 6.7 instead of Maven, GitHub CI, Sonarcloud analyzer, dependencies updated. - -**1.0.2** - Minor http client improvements. - -**1.0.1** - Gorli & TOBALABA networks support. - -**1.0.0** - Initial project with all API functionality, for all available networks, with tests coverage for all cases. - ## License This project licensed under the MIT - see the [LICENSE](LICENSE) file for details. diff --git a/build.gradle b/build.gradle index 638baf3..0e3f321 100644 --- a/build.gradle +++ b/build.gradle @@ -1,27 +1,26 @@ plugins { - id 'jacoco' - id 'java-library' - id 'maven-publish' + id "jacoco" + id "java-library" + id "maven-publish" - id 'org.sonarqube' version '3.1.1' - id 'com.diffplug.spotless' version '5.11.0' + id "org.sonarqube" version "3.3" + id "com.diffplug.spotless" version "5.14.3" } repositories { mavenLocal() mavenCentral() - jcenter() } group = groupId version = artifactVersion -sourceCompatibility = 1.8 -targetCompatibility = 1.8 +sourceCompatibility = JavaVersion.VERSION_1_8 +targetCompatibility = JavaVersion.VERSION_1_8 spotless { java { - encoding 'UTF-8' + encoding "UTF-8" removeUnusedImports() eclipse().configFile "${projectDir}/config/codestyle.xml" } @@ -29,43 +28,30 @@ spotless { sonarqube { properties { - property 'sonar.host.url', 'https://sonarcloud.io' - property 'sonar.organization', 'goodforgod' - property 'sonar.projectKey', 'GoodforGod_java-etherscan-api' + property "sonar.host.url", "https://sonarcloud.io" + property "sonar.organization", "goodforgod" + property "sonar.projectKey", "GoodforGod_java-etherscan-api" } } dependencies { - implementation 'org.jetbrains:annotations:20.1.0' - implementation 'com.google.code.gson:gson:2.8.6' + implementation "org.jetbrains:annotations:22.0.0" + implementation "com.google.code.gson:gson:2.8.8" - testImplementation 'junit:junit:4.13.1' + testImplementation "junit:junit:4.13.1" } test { - failFast = true - useJUnit() testLogging { - events "passed", "skipped", "failed" - exceptionFormat "full" + events("passed", "skipped", "failed") + exceptionFormat("full") } -} -tasks.withType(JavaCompile) { - options.encoding = 'UTF-8' - options.incremental = true - options.fork = true -} - -tasks.withType(Test) { - reports.html.enabled = false - reports.junitXml.enabled = false -} - -java { - withJavadocJar() - withSourcesJar() + reports { + html.enabled(false) + junitXml.enabled(false) + } } publishing { @@ -74,27 +60,27 @@ publishing { from components.java pom { - name = 'Java Etherscan API' - url = 'https://github.com/GoodforGod/java-etherscan-api' - description = 'Library is a wrapper for EtherScan API.' + name = "Java Etherscan API" + url = "https://github.com/GoodforGod/java-etherscan-api" + description = "Library is a wrapper for EtherScan API." license { - name = 'MIT License' - url = 'https://github.com/GoodforGod/java-etherscan-api/blob/master/LICENSE' - distribution = 'repo' + name = "MIT License" + url = "https://github.com/GoodforGod/java-etherscan-api/blob/master/LICENSE" + distribution = "repo" } developer { - id = 'GoodforGod' - name = 'Anton Kurako' - email = 'goodforgod.dev@gmail.com' - url = 'https://github.com/GoodforGod' + id = "GoodforGod" + name = "Anton Kurako" + email = "goodforgod.dev@gmail.com" + url = "https://github.com/GoodforGod" } scm { - connection = 'scm:git:git://github.com/GoodforGod/java-etherscan-api.git' - developerConnection = 'scm:git:ssh://GoodforGod/java-etherscan-api.git' - url = 'https://github.com/GoodforGod/java-etherscan-api/tree/master' + connection = "scm:git:git://github.com/GoodforGod/java-etherscan-api.git" + developerConnection = "scm:git:ssh://GoodforGod/java-etherscan-api.git" + url = "https://github.com/GoodforGod/java-etherscan-api/tree/master" } } } @@ -103,7 +89,7 @@ publishing { maven { def releasesRepoUrl = "https://oss.sonatype.org/service/local/staging/deploy/maven2" def snapshotsRepoUrl = "https://oss.sonatype.org/content/repositories/snapshots/" - url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl + url = version.endsWith("SNAPSHOT") ? snapshotsRepoUrl : releasesRepoUrl credentials { username System.getenv("OSS_USERNAME") password System.getenv("OSS_PASSWORD") @@ -112,6 +98,17 @@ publishing { } } +java { + withJavadocJar() + withSourcesJar() +} + +tasks.withType(JavaCompile) { + options.encoding("UTF-8") + options.incremental(true) + options.fork = true +} + check.dependsOn jacocoTestReport jacocoTestReport { reports { @@ -120,16 +117,16 @@ jacocoTestReport { } } +javadoc { + options.encoding = "UTF-8" + if (JavaVersion.current().isJava9Compatible()) { + options.addBooleanOption("html5", true) + } +} + if (project.hasProperty("signing.keyId")) { - apply plugin: 'signing' + apply plugin: "signing" signing { sign publishing.publications.mavenJava } } - -javadoc { - options.encoding = "UTF-8" - if (JavaVersion.current().isJava9Compatible()) { - options.addBooleanOption('html5', true) - } -} \ No newline at end of file diff --git a/config/codestyle.xml b/config/codestyle.xml index 0c19beb..a90c4f5 100644 --- a/config/codestyle.xml +++ b/config/codestyle.xml @@ -74,7 +74,7 @@ - + diff --git a/gradle.properties b/gradle.properties index 1fa1ad4..e4aacfe 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ groupId=com.github.goodforgod artifactId=java-etherscan-api -artifactVersion=1.1.0 +artifactVersion=1.1.1 buildNumber=1 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index e708b1c..7454180 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index be52383..ffed3a2 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 4f906e0..744e882 100755 --- a/gradlew +++ b/gradlew @@ -72,7 +72,7 @@ case "`uname`" in Darwin* ) darwin=true ;; - MINGW* ) + MSYS* | MINGW* ) msys=true ;; NONSTOP* ) diff --git a/src/main/java/io/api/etherscan/core/IAccountApi.java b/src/main/java/io/api/etherscan/core/IAccountApi.java index 6eda869..642f289 100644 --- a/src/main/java/io/api/etherscan/core/IAccountApi.java +++ b/src/main/java/io/api/etherscan/core/IAccountApi.java @@ -36,8 +36,8 @@ public interface IAccountApi { TokenBalance balance(String address, String contract) throws ApiException; /** - * Maximum 20 address for single batch request If address MORE THAN 20, then - * there will be more than 1 request performed + * Maximum 20 address for single batch request If address MORE THAN 20, then there will be more than + * 1 request performed * * @param addresses addresses to get balances for * @return list of balances diff --git a/src/main/java/io/api/etherscan/core/ILogsApi.java b/src/main/java/io/api/etherscan/core/ILogsApi.java index dc7d8d8..37c5eac 100644 --- a/src/main/java/io/api/etherscan/core/ILogsApi.java +++ b/src/main/java/io/api/etherscan/core/ILogsApi.java @@ -16,8 +16,7 @@ public interface ILogsApi { /** - * alternative to the native eth_getLogs Read at EtherScan API description for - * full info! + * alternative to the native eth_getLogs Read at EtherScan API description for full info! * * @param query build log query * @return logs according to query diff --git a/src/main/java/io/api/etherscan/core/IProxyApi.java b/src/main/java/io/api/etherscan/core/IProxyApi.java index 58a70ed..e57f6ec 100644 --- a/src/main/java/io/api/etherscan/core/IProxyApi.java +++ b/src/main/java/io/api/etherscan/core/IProxyApi.java @@ -36,8 +36,7 @@ public interface IProxyApi { Optional block(long blockNo) throws ApiException; /** - * Returns information about a uncle by block number - * eth_getUncleByBlockNumberAndIndex + * Returns information about a uncle by block number eth_getUncleByBlockNumberAndIndex * * @param blockNo block number from 0 to last * @param index uncle block index @@ -59,8 +58,8 @@ public interface IProxyApi { Optional tx(String txhash) throws ApiException; /** - * Returns information about a transaction by block number and transaction index - * position eth_getTransactionByBlockNumberAndIndex + * Returns information about a transaction by block number and transaction index position + * eth_getTransactionByBlockNumberAndIndex * * @param blockNo block number from 0 to last * @param index tx index in block @@ -71,8 +70,8 @@ public interface IProxyApi { Optional tx(long blockNo, long index) throws ApiException; /** - * Returns the number of transactions in a block from a block matching the given - * block number eth_getBlockTransactionCountByNumber + * Returns the number of transactions in a block from a block matching the given block number + * eth_getBlockTransactionCountByNumber * * @param blockNo block number from 0 to last * @return transaction amount in block @@ -81,8 +80,7 @@ public interface IProxyApi { int txCount(long blockNo) throws ApiException; /** - * Returns the number of transactions sent from an address - * eth_getTransactionCount + * Returns the number of transactions sent from an address eth_getTransactionCount * * @param address eth address * @return transactions send amount from address @@ -91,8 +89,8 @@ public interface IProxyApi { int txSendCount(String address) throws ApiException; /** - * Creates new message call transaction or a contract creation for signed - * transactions eth_sendRawTransaction + * Creates new message call transaction or a contract creation for signed transactions + * eth_sendRawTransaction * * @param hexEncodedTx encoded hex data to send * @return optional string response @@ -102,8 +100,7 @@ public interface IProxyApi { Optional txSendRaw(String hexEncodedTx) throws ApiException; /** - * Returns the receipt of a transaction by transaction hash - * eth_getTransactionReceipt + * Returns the receipt of a transaction by transaction hash eth_getTransactionReceipt * * @param txhash transaction hash * @return optional tx receipt @@ -113,8 +110,8 @@ public interface IProxyApi { Optional txReceipt(String txhash) throws ApiException; /** - * Executes a new message call immediately without creating a transaction on the - * block chain eth_call + * Executes a new message call immediately without creating a transaction on the block chain + * eth_call * * @param address to call * @param data data to call address @@ -135,8 +132,7 @@ public interface IProxyApi { Optional code(String address) throws ApiException; /** - * (**experimental) Returns the value from a storage position at a given address - * eth_getStorageAt + * (**experimental) Returns the value from a storage position at a given address eth_getStorageAt * * @param address to get storage * @param position storage position @@ -156,9 +152,8 @@ public interface IProxyApi { BigInteger gasPrice() throws ApiException; /** - * Makes a call or transaction, which won't be added to the blockchain and - * returns the used gas, which can be used for estimating the used gas - * eth_estimateGas + * Makes a call or transaction, which won't be added to the blockchain and returns the used gas, + * which can be used for estimating the used gas eth_estimateGas * * @param hexData data to calc gas usage for * @return estimated gas usage diff --git a/src/main/java/io/api/etherscan/core/ITransactionApi.java b/src/main/java/io/api/etherscan/core/ITransactionApi.java index 51c108c..f545c2d 100644 --- a/src/main/java/io/api/etherscan/core/ITransactionApi.java +++ b/src/main/java/io/api/etherscan/core/ITransactionApi.java @@ -15,8 +15,7 @@ public interface ITransactionApi { /** - * Check Contract Execution Status (if there was an error during contract - * execution) + * Check Contract Execution Status (if there was an error during contract execution) * * @param txhash transaction hash * @return optional status result @@ -26,8 +25,7 @@ public interface ITransactionApi { Optional execStatus(String txhash) throws ApiException; /** - * Check Transaction Receipt Status (Only applicable for Post Byzantium fork - * transactions) + * Check Transaction Receipt Status (Only applicable for Post Byzantium fork transactions) * * @param txhash transaction hash * @return 0 = Fail, 1 = Pass, empty value for pre-byzantium fork 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 8cd5d46..ba5dd83 100644 --- a/src/main/java/io/api/etherscan/core/impl/EtherScanApi.java +++ b/src/main/java/io/api/etherscan/core/impl/EtherScanApi.java @@ -20,12 +20,13 @@ * @author GoodforGod * @since 28.10.2018 */ -public class EtherScanApi { +public class EtherScanApi implements AutoCloseable { private static final Supplier DEFAULT_SUPPLIER = HttpExecutor::new; public static final String DEFAULT_KEY = "YourApiKeyToken"; + private final IQueueManager queueManager; private final IAccountApi account; private final IBlockApi block; private final IContractApi contract; @@ -87,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; + this.queueManager = queue; this.account = new AccountApiProvider(queue, baseUrl, executor); this.block = new BlockApiProvider(queue, baseUrl, executor); this.contract = new ContractApiProvider(queue, baseUrl, executor); @@ -130,4 +132,9 @@ public IProxyApi proxy() { public IStatisticApi stats() { return stats; } + + @Override + public void close() throws Exception { + queueManager.close(); + } } diff --git a/src/main/java/io/api/etherscan/manager/IQueueManager.java b/src/main/java/io/api/etherscan/manager/IQueueManager.java index 3a65240..98a3172 100644 --- a/src/main/java/io/api/etherscan/manager/IQueueManager.java +++ b/src/main/java/io/api/etherscan/manager/IQueueManager.java @@ -1,13 +1,13 @@ package io.api.etherscan.manager; /** - * Queue manager to support API limits (EtherScan 5request\sec limit) Managers - * grants turn if the limit is not exhausted And resets queue each set period + * Queue manager to support API limits (EtherScan 5request\sec limit) Managers grants turn if the + * limit is not exhausted And resets queue each set period * * @author GoodforGod * @since 30.10.2018 */ -public interface IQueueManager { +public interface IQueueManager extends AutoCloseable { /** * Waits in queue for chance to take turn diff --git a/src/main/java/io/api/etherscan/manager/impl/FakeQueueManager.java b/src/main/java/io/api/etherscan/manager/impl/FakeQueueManager.java index e797f8b..620244c 100644 --- a/src/main/java/io/api/etherscan/manager/impl/FakeQueueManager.java +++ b/src/main/java/io/api/etherscan/manager/impl/FakeQueueManager.java @@ -15,4 +15,9 @@ public void takeTurn() { // no limit or await provided for fake impl so rate limit exception will be // thrown if too many calls } + + @Override + public void close() { + // do nothing + } } diff --git a/src/main/java/io/api/etherscan/manager/impl/QueueManager.java b/src/main/java/io/api/etherscan/manager/impl/QueueManager.java index 517883c..80f7c51 100644 --- a/src/main/java/io/api/etherscan/manager/impl/QueueManager.java +++ b/src/main/java/io/api/etherscan/manager/impl/QueueManager.java @@ -12,29 +12,53 @@ * @author GoodforGod * @since 30.10.2018 */ -public class QueueManager implements IQueueManager { +public class QueueManager implements IQueueManager, AutoCloseable { public static final QueueManager DEFAULT_KEY_QUEUE = new QueueManager(1, 7); - public static final QueueManager PERSONAL_KEY_QUEUE = new QueueManager(2, 1); + public static final QueueManager PERSONAL_KEY_QUEUE = new QueueManager(5, 1100L, 1100L, 5); + private final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor(); private final Semaphore semaphore; + private final long queueResetTimeInMillis; public QueueManager(int size, int resetInSec) { this(size, resetInSec, resetInSec); } public QueueManager(int size, int queueResetTimeInSec, int delayInSec) { - this.semaphore = new Semaphore(size); - Executors.newSingleThreadScheduledExecutor() - .scheduleAtFixedRate(releaseLocks(size), delayInSec, queueResetTimeInSec, TimeUnit.SECONDS); + this(size, queueResetTimeInSec, delayInSec, size); } + public QueueManager(int size, int queueResetTimeInSec, int delayInSec, int initialSize) { + this(size, + (long) queueResetTimeInSec * 1000, + (long) delayInSec * 1000, + initialSize); + } + + public QueueManager(int size, long queueResetTimeInMillis, long delayInMillis, int initialSize) { + this.queueResetTimeInMillis = queueResetTimeInMillis; + this.semaphore = new Semaphore(initialSize); + this.executorService.scheduleAtFixedRate(releaseLocks(size), delayInMillis, queueResetTimeInMillis, + TimeUnit.MILLISECONDS); + } + + @SuppressWarnings("java:S899") @Override public void takeTurn() { - semaphore.acquireUninterruptibly(); + try { + semaphore.tryAcquire(queueResetTimeInMillis, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } } private Runnable releaseLocks(int toRelease) { return () -> semaphore.release(toRelease); } + + @Override + public void close() { + executorService.shutdown(); + } } diff --git a/src/main/java/io/api/etherscan/model/Log.java b/src/main/java/io/api/etherscan/model/Log.java index 4649d6b..36d126b 100644 --- a/src/main/java/io/api/etherscan/model/Log.java +++ b/src/main/java/io/api/etherscan/model/Log.java @@ -68,11 +68,10 @@ public LocalDateTime getTimeStamp() { } /** - * Return the "timeStamp" field of the event record as a long-int representing - * the milliseconds since the Unix epoch (1970-01-01 00:00:00). + * Return the "timeStamp" field of the event record as a long-int representing the milliseconds + * since the Unix epoch (1970-01-01 00:00:00). * - * @return milliseconds between Unix epoch and `timeStamp`. If field is empty or - * null, returns null + * @return milliseconds between Unix epoch and `timeStamp`. If field is empty or null, returns null */ public Long getTimeStampAsMillis() { if (BasicUtils.isEmpty(timeStamp)) { diff --git a/src/test/java/io/api/ApiRunner.java b/src/test/java/io/api/ApiRunner.java index 6f608d8..5ccdf83 100644 --- a/src/test/java/io/api/ApiRunner.java +++ b/src/test/java/io/api/ApiRunner.java @@ -3,6 +3,7 @@ import io.api.etherscan.core.impl.EtherScanApi; import io.api.etherscan.manager.impl.QueueManager; import io.api.etherscan.model.EthNetwork; +import org.junit.AfterClass; import org.junit.Assert; public class ApiRunner extends Assert { @@ -11,26 +12,23 @@ public class ApiRunner extends Assert { private static final EtherScanApi apiRopsten; private static final EtherScanApi apiRinkeby; private static final EtherScanApi apiKovan; - private static final String key; + private static final String apiKey; static { - final String apiKey = System.getenv("API_KEY"); - key = (apiKey == null || apiKey.isEmpty()) + final String key = System.getenv("API_KEY"); + apiKey = (key == null || key.isEmpty()) ? EtherScanApi.DEFAULT_KEY - : apiKey; + : key; - final QueueManager queue = key.equals(EtherScanApi.DEFAULT_KEY) - ? QueueManager.DEFAULT_KEY_QUEUE - : new QueueManager(1, 2); - - api = new EtherScanApi(key, EthNetwork.MAINNET, queue); - apiRopsten = new EtherScanApi(key, EthNetwork.ROPSTEN, queue); - apiRinkeby = new EtherScanApi(key, EthNetwork.RINKEBY, queue); - apiKovan = new EtherScanApi(key, EthNetwork.KOVAN, queue); + final QueueManager queueManager = new QueueManager(1, 1200L, 1200L, 0); + api = new EtherScanApi(ApiRunner.apiKey, EthNetwork.MAINNET, queueManager); + apiKovan = new EtherScanApi(ApiRunner.apiKey, EthNetwork.KOVAN, queueManager); + apiRopsten = new EtherScanApi(ApiRunner.apiKey, EthNetwork.ROPSTEN, queueManager); + apiRinkeby = new EtherScanApi(ApiRunner.apiKey, EthNetwork.RINKEBY, queueManager); } - public static String getKey() { - return key; + public static String getApiKey() { + return apiKey; } public static EtherScanApi getApi() { @@ -48,4 +46,12 @@ public static EtherScanApi getApiRinkeby() { public static EtherScanApi getApiKovan() { return apiKovan; } + + @AfterClass + public static void cleanup() throws Exception { + api.close(); + apiRopsten.close(); + apiRinkeby.close(); + apiKovan.close(); + } } diff --git a/src/test/java/io/api/etherscan/EtherScanApiTest.java b/src/test/java/io/api/etherscan/EtherScanApiTest.java index 5071a68..be49435 100644 --- a/src/test/java/io/api/etherscan/EtherScanApiTest.java +++ b/src/test/java/io/api/etherscan/EtherScanApiTest.java @@ -79,7 +79,7 @@ public void noTimeoutUnlimitedAwait() { public void timeout() throws InterruptedException { TimeUnit.SECONDS.sleep(5); Supplier supplier = () -> new HttpExecutor(300, 300); - EtherScanApi api = new EtherScanApi(getKey(), EthNetwork.KOVAN, supplier); + EtherScanApi api = new EtherScanApi(getApiKey(), EthNetwork.KOVAN, supplier); List blocks = api.account().minedBlocks("0x0010f94b296A852aAac52EA6c5Ac72e03afD032D"); assertNotNull(blocks); } diff --git a/src/test/java/io/api/etherscan/proxy/ProxyBlockApiTest.java b/src/test/java/io/api/etherscan/proxy/ProxyBlockApiTest.java index 181a68d..5d3884d 100644 --- a/src/test/java/io/api/etherscan/proxy/ProxyBlockApiTest.java +++ b/src/test/java/io/api/etherscan/proxy/ProxyBlockApiTest.java @@ -1,6 +1,9 @@ package io.api.etherscan.proxy; import io.api.ApiRunner; +import io.api.etherscan.core.impl.EtherScanApi; +import io.api.etherscan.manager.impl.QueueManager; +import io.api.etherscan.model.EthNetwork; import io.api.etherscan.model.proxy.BlockProxy; import org.junit.Test; @@ -14,9 +17,16 @@ */ public class ProxyBlockApiTest extends ApiRunner { + private final EtherScanApi api; + + public ProxyBlockApiTest() { + final QueueManager queueManager = new QueueManager(1, 5100L, 5100L, 0); + this.api = new EtherScanApi(getApiKey(), EthNetwork.MAINNET, queueManager); + } + @Test public void correct() { - Optional block = getApi().proxy().block(5120); + Optional block = api.proxy().block(5120); assertTrue(block.isPresent()); BlockProxy proxy = block.get(); assertNotNull(proxy.getHash()); @@ -49,13 +59,13 @@ public void correct() { @Test public void correctParamWithEmptyExpectedResult() { - Optional block = getApi().proxy().block(99999999999L); + Optional block = api.proxy().block(99999999999L); assertFalse(block.isPresent()); } @Test public void correctParamNegativeNo() { - Optional block = getApi().proxy().block(-1); + Optional block = api.proxy().block(-1); assertTrue(block.isPresent()); assertNotNull(block.get().getHash()); } diff --git a/src/test/java/io/api/etherscan/proxy/ProxyCallApiTest.java b/src/test/java/io/api/etherscan/proxy/ProxyCallApiTest.java index c90850c..07d26bd 100644 --- a/src/test/java/io/api/etherscan/proxy/ProxyCallApiTest.java +++ b/src/test/java/io/api/etherscan/proxy/ProxyCallApiTest.java @@ -41,6 +41,6 @@ public void correctParamWithEmptyExpectedResult() { Optional call = getApi().proxy().call("0xAEEF16DB4855E25702F8237E8f403FddcaF931C0", "0x70a08231000000000000000000000000e16359506c028e51f16be38986ec5746251e9724"); assertTrue(call.isPresent()); - assertFalse(BasicUtils.isNotHex(call.get())); + assertFalse(call.get(), BasicUtils.isNotHex(call.get())); } } diff --git a/src/test/java/io/api/etherscan/proxy/ProxyCodeApiTest.java b/src/test/java/io/api/etherscan/proxy/ProxyCodeApiTest.java index 3120503..9e4910c 100644 --- a/src/test/java/io/api/etherscan/proxy/ProxyCodeApiTest.java +++ b/src/test/java/io/api/etherscan/proxy/ProxyCodeApiTest.java @@ -19,18 +19,18 @@ public class ProxyCodeApiTest extends ApiRunner { public void correct() { Optional call = getApi().proxy().code("0xf75e354c5edc8efed9b59ee9f67a80845ade7d0c"); assertTrue(call.isPresent()); - assertFalse(BasicUtils.isNotHex(call.get())); + assertFalse(call.get(), BasicUtils.isNotHex(call.get())); } @Test(expected = InvalidAddressException.class) public void invalidParamWithError() { - Optional call = getApi().proxy().code("0f75e354c5edc8efed9b59ee9f67a80845ade7d0c"); + getApi().proxy().code("0f75e354c5edc8efed9b59ee9f67a80845ade7d0c"); } @Test public void correctParamWithEmptyExpectedResult() { Optional call = getApi().proxy().code("0xf15e354c5edc8efed9b59ee9f67a80845ade7d0c"); assertTrue(call.isPresent()); - assertFalse(BasicUtils.isNotHex(call.get())); + assertFalse(call.get(), BasicUtils.isNotHex(call.get())); } } diff --git a/src/test/java/io/api/etherscan/proxy/ProxyStorageApiTest.java b/src/test/java/io/api/etherscan/proxy/ProxyStorageApiTest.java index fbfcf80..ecd7dca 100644 --- a/src/test/java/io/api/etherscan/proxy/ProxyStorageApiTest.java +++ b/src/test/java/io/api/etherscan/proxy/ProxyStorageApiTest.java @@ -24,12 +24,12 @@ public void correct() { @Test(expected = InvalidAddressException.class) public void invalidParamWithError() { - Optional call = getApi().proxy().storageAt("0xe03d9cce9d60f3e9f2597e13cd4c54c55330cfd", 0); + getApi().proxy().storageAt("0xe03d9cce9d60f3e9f2597e13cd4c54c55330cfd", 0); } @Test public void correctParamWithEmptyExpectedResult() { - Optional call = getApi().proxy().storageAt("0x6e03d9cce9d60f3e9f2597e13cd4c54c55330cfd", 100); + final Optional call = getApi().proxy().storageAt("0x6e03d9cce9d60f3e9f2597e13cd4c54c55330cfd", 10000); assertFalse(call.isPresent()); } } diff --git a/src/test/java/io/api/etherscan/proxy/ProxyTxCountApiTest.java b/src/test/java/io/api/etherscan/proxy/ProxyTxCountApiTest.java index 6a0778c..b81926f 100644 --- a/src/test/java/io/api/etherscan/proxy/ProxyTxCountApiTest.java +++ b/src/test/java/io/api/etherscan/proxy/ProxyTxCountApiTest.java @@ -32,12 +32,12 @@ public void invalidParamWithError() { @Test public void correctParamWithEmptyExpectedResultBlockNoExist() { int count = getApi().proxy().txCount(99999999999L); - assertEquals(0, count); + assertNotEquals(1, count); } @Test public void correctParamWithEmptyExpectedResult() { int count = getApi().proxy().txSendCount("0x1e03d9cce9d60f3e9f2597e13cd4c54c55330cfd"); - assertEquals(0, count); + assertNotEquals(1, count); } } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy