Skip to content

Commit 3795b6d

Browse files
committed
HttpExecutor gzip comparison support
EtherScan constructor tests Minor improvements & fixes
1 parent 2af17f0 commit 3795b6d

File tree

8 files changed

+217
-14
lines changed

8 files changed

+217
-14
lines changed

README.md

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,89 @@
11
# java-etherscan-api
2+
3+
[Etherscan](https://etherscan.io/apis) Java API implementation.
4+
5+
6+
![](https://media.giphy.com/media/1msHfmVdtuwkXww4ZC/giphy.gif)
7+
8+
## Dependency :rocket:
9+
**Maven**
10+
```xml
11+
<dependency>
12+
<groupId>com.github.goodforgod</groupId>
13+
<artifactId>java-etherscan-api</artifactId>
14+
<version>1.0.0</version>
15+
</dependency>
16+
```
17+
18+
**Gradle**
19+
```groovy
20+
dependencies {
21+
compile 'com.github.goodforgod:java-etherscan-api:1.0.0'
22+
}
23+
```
24+
25+
## Content
26+
- [Overall](#overall)
27+
- [API examples](#api-examples)
28+
- [Account](#account-api)
29+
- [Block](#block-api)
30+
- [Contract](#contract-api)
31+
- [Logs](#logs-api)
32+
- [Proxy](#proxy-api)
33+
- [Stats](#stats-api)
34+
- [Transactions](#transaction-api)
35+
- [Version History](#version-history)
36+
37+
## Overall
38+
39+
How all is linked together:
40+
41+
## Api Examples
42+
43+
You can read about all API methods on [Etherscan](https://etherscan.io/apis)
44+
45+
You can you API with you key or without key as well.
46+
```java
47+
EtherScanApi api = new EtherScanApi();
48+
EtherScanApi api = new EtherScanApi("YourApiKey");
49+
```
50+
51+
### Mainnet and Testnets
52+
API support: *MAINNET, ROPSTEN, KOVAN, RINKEBY* networks.
53+
```java
54+
EtherScanApi api = new EtherScanApi(EthNetwork.MAINNET);
55+
EtherScanApi api = new EtherScanApi("YourApiKey", EthNetwork.KOVAN);
56+
```
57+
58+
### Account Api
59+
**Get Ether Balance for a single Address Example**
60+
```java
61+
EtherScanApi api = new EtherScanApi();
62+
Balance balance = api.account().balance("0x8d4426f94e42f721C7116E81d6688cd935cB3b4F");
63+
```
64+
65+
### Block Api
66+
67+
### Contract Api
68+
69+
### Logs Api
70+
71+
### Proxy Api
72+
73+
### Stats Api
74+
75+
### Transaction Api
76+
77+
78+
### Token Api
79+
You can read account API [here](https://etherscan.io/apis#accounts)
80+
81+
Token API migrated to account & stats respectfully.
82+
83+
## Version History
84+
85+
**1.0.0** - Initial project with all API functionality.
86+
87+
## License
88+
89+
This project is licensed under the MIT - see the [LICENSE](LICENSE) file for details.

src/main/java/io/api/etherscan/App.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@
22

33
import io.api.etherscan.core.impl.EtherScanApi;
44
import io.api.etherscan.model.Balance;
5+
import io.api.etherscan.model.EthNetwork;
56

67
/**
78
*
89
*/
910
public class App {
1011
public static void main(String[] args) {
11-
EtherScanApi api = new EtherScanApi();
12+
EtherScanApi api = new EtherScanApi(EthNetwork.MAINNET);
1213
Balance balance = api.account().balance("0x8d4426f94e42f721C7116E81d6688cd935cB3b4F");
1314
System.out.println("Test");
1415
}

src/main/java/io/api/etherscan/core/impl/EtherScanApi.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package io.api.etherscan.core.impl;
22

33
import io.api.etherscan.core.*;
4+
import io.api.etherscan.error.ApiKeyException;
45
import io.api.etherscan.executor.IHttpExecutor;
56
import io.api.etherscan.executor.impl.HttpExecutor;
67
import io.api.etherscan.manager.IQueueManager;
@@ -50,8 +51,8 @@ public EtherScanApi(final String apiKey,
5051
public EtherScanApi(final String apiKey,
5152
final EthNetwork network,
5253
final Supplier<IHttpExecutor> executorSupplier) {
53-
if (BasicUtils.isEmpty(apiKey))
54-
throw new NullPointerException("API key can not be null");
54+
if (BasicUtils.isBlank(apiKey))
55+
throw new ApiKeyException("API key can not be null or empty");
5556

5657
// EtherScan 5request\sec limit support by queue manager
5758
final IQueueManager masterQueue = (apiKey.equals("YourApiKeyToken"))
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package io.api.etherscan.error;
2+
3+
/**
4+
* ! NO DESCRIPTION !
5+
*
6+
* @author GoodforGod
7+
* @since 05.11.2018
8+
*/
9+
public class ApiKeyException extends ApiException {
10+
11+
public ApiKeyException(String message) {
12+
super(message);
13+
}
14+
}

src/main/java/io/api/etherscan/executor/impl/HttpExecutor.java

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import java.net.URL;
1313
import java.util.HashMap;
1414
import java.util.Map;
15+
import java.util.zip.GZIPInputStream;
1516

1617
import static java.net.HttpURLConnection.HTTP_MOVED_PERM;
1718
import static java.net.HttpURLConnection.HTTP_MOVED_TEMP;
@@ -28,10 +29,11 @@ public class HttpExecutor implements IHttpExecutor {
2829
private static final Map<String, String> DEFAULT_HEADERS = new HashMap<>();
2930

3031
static {
31-
DEFAULT_HEADERS.put("accept-language", "en,ru;q=0.9");
32-
DEFAULT_HEADERS.put("accept-encoding", "gzip, deflate, br");
33-
DEFAULT_HEADERS.put("user-agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) Chrome/68.0.3440.106");
34-
DEFAULT_HEADERS.put("content-type", "application/x-www-form-urlencoded");
32+
DEFAULT_HEADERS.put("Accept-Language", "en;q=0.9");
33+
DEFAULT_HEADERS.put("Accept-Encoding", "deflate, gzip");
34+
DEFAULT_HEADERS.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) Chrome/68.0.3440.106");
35+
DEFAULT_HEADERS.put("Content-Type", "application/x-www-form-urlencoded");
36+
DEFAULT_HEADERS.put("Accept-Charset", "UTF-8");
3537
}
3638

3739
private final Map<String, String> headers;
@@ -113,7 +115,7 @@ public String post(final String urlAsString, final String dataToPost) {
113115

114116
private String readData(final HttpURLConnection connection) throws IOException {
115117
final StringBuilder content = new StringBuilder();
116-
try (BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
118+
try (BufferedReader in = new BufferedReader(getStreamReader(connection))) {
117119
String inputLine;
118120
while ((inputLine = in.readLine()) != null)
119121
content.append(inputLine);
@@ -123,4 +125,10 @@ private String readData(final HttpURLConnection connection) throws IOException {
123125

124126
return content.toString();
125127
}
128+
129+
private InputStreamReader getStreamReader(final HttpURLConnection connection) throws IOException {
130+
return ("gzip".equals(connection.getContentEncoding()))
131+
? new InputStreamReader(new GZIPInputStream(connection.getInputStream()), "utf-8")
132+
: new InputStreamReader(connection.getInputStream(), "utf-8");
133+
}
126134
}

src/main/java/io/api/etherscan/util/BasicUtils.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
import java.util.regex.Pattern;
1313

1414
/**
15-
* ! NO DESCRIPTION !
15+
* Basic utils for library
1616
*
1717
* @author GoodforGod
1818
* @since 28.10.2018
@@ -30,7 +30,7 @@ public static boolean isEmpty(String value) {
3030
return value == null || value.isEmpty();
3131
}
3232

33-
public static boolean isBlack(String value) {
33+
public static boolean isBlank(String value) {
3434
return value == null || value.isEmpty() || value.trim().isEmpty();
3535
}
3636

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package io.api.etherscan;
2+
3+
import io.api.etherscan.core.impl.EtherScanApi;
4+
import io.api.etherscan.error.ApiKeyException;
5+
import io.api.etherscan.model.EthNetwork;
6+
import org.junit.Assert;
7+
import org.junit.Test;
8+
9+
/**
10+
* ! NO DESCRIPTION !
11+
*
12+
* @author GoodforGod
13+
* @since 05.11.2018
14+
*/
15+
public class EtherScanApiTest extends Assert {
16+
17+
private EthNetwork network = EthNetwork.KOVAN;
18+
private String validKey = "YourKey";
19+
20+
@Test
21+
public void validKey() {
22+
EtherScanApi api = new EtherScanApi(validKey, network);
23+
assertNotNull(api);
24+
}
25+
26+
@Test(expected = ApiKeyException.class)
27+
public void emptyKey() {
28+
String emptyKey = "";
29+
EtherScanApi api = new EtherScanApi(emptyKey, network);
30+
}
31+
32+
@Test(expected = ApiKeyException.class)
33+
public void blankKey() {
34+
String blankKey = " ";
35+
EtherScanApi api = new EtherScanApi(blankKey, network);
36+
}
37+
38+
@Test
39+
public void nullNetwork() {
40+
EtherScanApi api = new EtherScanApi(validKey, null);
41+
assertNotNull(api);
42+
}
43+
}

src/test/java/io/api/etherscan/account/AccountBalanceTest.java

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,70 @@
33
import io.api.etherscan.core.impl.EtherScanApi;
44
import io.api.etherscan.error.InvalidAddressException;
55
import io.api.etherscan.model.Balance;
6+
import io.api.etherscan.model.EthNetwork;
67
import org.junit.Assert;
78
import org.junit.Test;
9+
import org.junit.runner.RunWith;
10+
import org.junit.runners.Parameterized;
11+
import org.junit.runners.Parameterized.Parameters;
12+
13+
import java.util.Arrays;
14+
import java.util.Collection;
815

916
/**
1017
* ! NO DESCRIPTION !
1118
*
1219
* @author GoodforGod
1320
* @since 03.11.2018
1421
*/
22+
@RunWith(Parameterized.class)
1523
public class AccountBalanceTest extends Assert {
1624

17-
private final EtherScanApi api = new EtherScanApi();
25+
private EtherScanApi api;
26+
private String addressCorrect;
27+
private String addressInvalid;
28+
private String addressNoResponse;
29+
30+
public AccountBalanceTest(EtherScanApi api, String addressCorrect, String addressInvalid, String addressNoResponse) {
31+
this.api = api;
32+
this.addressCorrect = addressCorrect;
33+
this.addressInvalid = addressInvalid;
34+
this.addressNoResponse = addressNoResponse;
35+
}
36+
37+
@Parameters
38+
public static Collection data() {
39+
return Arrays.asList(new Object[][]{
40+
{
41+
new EtherScanApi(),
42+
"0x8d4426f94e42f721C7116E81d6688cd935cB3b4F",
43+
"8d4426f94e42f721C7116E81d6688cd935cB3b4F",
44+
"0x1d4426f94e42f721C7116E81d6688cd935cB3b4F"
45+
},
46+
{
47+
new EtherScanApi(EthNetwork.ROPSTEN),
48+
"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a",
49+
"xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a",
50+
"0x1dbd2b932c763ba5b1b7ae3b362eac3e8d40121a"
51+
},
52+
{
53+
new EtherScanApi(EthNetwork.RINKEBY),
54+
"0xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a",
55+
"xddbd2b932c763ba5b1b7ae3b362eac3e8d40121a",
56+
"0x1dbd2b932c763ba5b1b7ae3b362eac3e8d40121a"
57+
},
58+
{
59+
new EtherScanApi(EthNetwork.KOVAN),
60+
"0xB9F36EE9df7E2A24B61b1738F4127BFDe8bA1A87",
61+
"xB9F36EE9df7E2A24B61b1738F4127BFDe8bA1A87",
62+
"0xB1F36EE9df7E2A24B61b1738F4127BFDe8bA1A87"
63+
},
64+
});
65+
}
1866

1967
@Test
2068
public void correct() {
21-
Balance balance = api.account().balance("0x8d4426f94e42f721C7116E81d6688cd935cB3b4F");
69+
Balance balance = api.account().balance(addressCorrect);
2270
assertNotNull(balance);
2371
assertNotNull(balance.getWei());
2472
assertNotNull(balance.getMwei());
@@ -31,12 +79,12 @@ public void correct() {
3179

3280
@Test(expected = InvalidAddressException.class)
3381
public void invalidParamWithError() {
34-
Balance balance = api.account().balance("8d4426f94e42f721C7116E81d6688cd935cB3b4F");
82+
Balance balance = api.account().balance(addressInvalid);
3583
}
3684

3785
@Test
3886
public void correctParamWithEmptyExpectedResult() {
39-
Balance balance = api.account().balance("0x8d4426f94e42f722C7116E81d6688cd935cB3b4F");
87+
Balance balance = api.account().balance(addressNoResponse);
4088
assertNotNull(balance);
4189
assertNotNull(balance.getWei());
4290
assertNotNull(balance.getAddress());

0 commit comments

Comments
 (0)
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