Skip to content

Commit 01a05a9

Browse files
committed
JetBrains annotation integrated
Exception improvements QueueManager integrated Model improvements Account Provider improvements
1 parent dddec66 commit 01a05a9

18 files changed

+324
-108
lines changed

pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@
3636
<version>2.8.5</version>
3737
</dependency>
3838

39+
<dependency>
40+
<groupId>org.jetbrains</groupId>
41+
<artifactId>annotations</artifactId>
42+
<version>13.0</version>
43+
</dependency>
44+
3945
<dependency>
4046
<groupId>com.jsoniter</groupId>
4147
<artifactId>jsoniter</artifactId>

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import io.api.core.EtherScanApi;
44
import io.api.model.Tx;
5+
import io.api.model.TxInternal;
6+
import io.api.model.TxToken;
57

68
import java.util.List;
79

@@ -12,6 +14,8 @@ public class App {
1214
public static void main(String[] args) {
1315
EtherScanApi api = new EtherScanApi(args[0]);
1416
List<Tx> txs = api.account().txs("0x8d4426f94e42f721C7116E81d6688cd935cB3b4F");
17+
List<TxInternal> txInternals = api.account().txsInternal("0x2c1ba59d6f58433fb1eaee7d20b26ed83bda51a3");
18+
List<TxToken> txTokens = api.account().txsToken("0xf261B3A60Ef40eE0B369B0705c1a2c58B02799DF");
1519
System.out.println("Test");
1620
}
1721
}

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

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import io.api.core.impl.AccountProvider;
44
import io.api.core.impl.ContractProvider;
5+
import io.api.manager.IQueueManager;
6+
import io.api.manager.impl.QueueManager;
57
import io.api.model.EthereumNetwork;
68

79
import java.util.HashMap;
@@ -24,8 +26,8 @@ public class EtherScanApi {
2426
HEADERS.put("cache-control", "max-age=0");
2527
}
2628

27-
private final ContractProvider contract;
28-
private final AccountProvider account;
29+
private final IContractProvider contract;
30+
private final IAccountProvider account;
2931

3032
public EtherScanApi(final String apiKey) {
3133
this(apiKey, EthereumNetwork.MAINNET);
@@ -37,16 +39,19 @@ public EtherScanApi(final String apiKey,
3739
? EthereumNetwork.MAINNET
3840
: network;
3941

42+
// EtherScan 5req\sec limit support
43+
final IQueueManager masterQueue = new QueueManager(5, 1);
44+
4045
final String url = "https://" + usedNetwork.getDomain() + ".etherscan.io/api" + "?apikey=" + apiKey;
41-
this.contract = new ContractProvider(url, HEADERS);
42-
this.account = new AccountProvider(url, HEADERS);
46+
this.contract = new ContractProvider(masterQueue, url, HEADERS);
47+
this.account = new AccountProvider(masterQueue, url, HEADERS);
4348
}
4449

45-
public ContractProvider contract() {
50+
public IContractProvider contract() {
4651
return contract;
4752
}
4853

49-
public AccountProvider account() {
54+
public IAccountProvider account() {
5055
return account;
5156
}
5257
}
Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
package io.api.core;
22

3-
import io.api.model.Balance;
4-
import io.api.model.Block;
5-
import io.api.model.Tx;
3+
import io.api.error.ApiException;
4+
import io.api.model.*;
5+
import org.jetbrains.annotations.NotNull;
66

77
import java.util.List;
88

@@ -16,34 +16,34 @@
1616
public interface IAccountProvider {
1717

1818
/** Address ETH balance */
19-
Balance balance(String address);
19+
@NotNull Balance balance(String address) throws ApiException;
2020

2121
/**
2222
* Maximum 20 address for batch request
2323
* If address > 20, then there will be more than 1 request performed
2424
*/
25-
List<Balance> balances(List<String> addresses);
25+
@NotNull List<Balance> balances(List<String> addresses) throws ApiException;
2626

2727
/** All txs */
28-
List<Tx> txs(String address);
28+
@NotNull List<Tx> txs(String address) throws ApiException;
2929
/** Only last 10000 txs */
30-
List<Tx> txs(String address, long startBlock);
31-
List<Tx> txs(String address, long startBlock, long endBlock);
30+
@NotNull List<Tx> txs(String address, long startBlock);
31+
@NotNull List<Tx> txs(String address, long startBlock, long endBlock);
3232

3333
/** All internal txs */
34-
List<Tx> txsInternal(String address);
34+
@NotNull List<TxInternal> txsInternal(String address);
3535
/** Only last 10000 internal txs */
36-
List<Tx> txsInternal(String address, long startBlock);
37-
List<Tx> txsInternal(String address, long startBlock, long endBlock);
36+
@NotNull List<TxInternal> txsInternal(String address, long startBlock);
37+
@NotNull List<TxInternal> txsInternal(String address, long startBlock, long endBlock);
3838
/** Only last 10000 internal txs by txhash */
39-
List<Tx> txsInternalByHash(String txhash);
39+
@NotNull List<TxInternal> txsInternalByHash(String txhash);
4040

4141
/** All token txs */
42-
List<Tx> txsToken(String address);
42+
@NotNull List<TxToken> txsToken(String address);
4343
/** Only last 10000 token txs */
44-
List<Tx> txsToken(String address, long startBlock);
45-
List<Tx> txsToken(String address, long startBlock, long endBlock);
44+
@NotNull List<TxToken> txsToken(String address, long startBlock);
45+
@NotNull List<TxToken> txsToken(String address, long startBlock, long endBlock);
4646

4747
/** All blocks mined by address */
48-
List<Block> minedBlocks(String address);
48+
@NotNull List<Block> minedBlocks(String address);
4949
}

src/main/java/io/api/core/impl/AccountProvider.java

Lines changed: 84 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
package io.api.core.impl;
22

3-
import com.sun.istack.internal.NotNull;
43
import io.api.core.IAccountProvider;
54
import io.api.error.EtherScanException;
6-
import io.api.model.Balance;
7-
import io.api.model.Block;
8-
import io.api.model.Tx;
9-
import io.api.model.temporary.BalanceResponseTO;
10-
import io.api.model.temporary.StringResponseTO;
11-
import io.api.model.temporary.TxResponseTO;
5+
import io.api.manager.IQueueManager;
6+
import io.api.model.*;
7+
import io.api.model.temporary.*;
128
import io.api.util.BasicUtils;
9+
import org.jetbrains.annotations.NotNull;
1310

11+
import java.util.ArrayList;
1412
import java.util.Collections;
1513
import java.util.List;
1614
import java.util.Map;
@@ -45,9 +43,10 @@ public class AccountProvider extends BasicProvider implements IAccountProvider {
4543
private static final String OFFSET_PARAM = "&offset=";
4644
private static final String PAGE_PARAM = "&page=";
4745

48-
public AccountProvider(final String baseUrl,
46+
public AccountProvider(final IQueueManager queueManager,
47+
final String baseUrl,
4948
final Map<String, String> header) {
50-
super("account", baseUrl, header);
49+
super(queueManager, "account", baseUrl, header);
5150
}
5251

5352
@NotNull
@@ -56,28 +55,38 @@ public Balance balance(final String address) {
5655
BasicUtils.validateAddress(address);
5756

5857
final String urlParams = BALANCE_ACTION + TAG_LATEST_PARAM + ADDRESS_PARAM + address;
59-
final String response = getRequest(urlParams);
60-
final StringResponseTO converted = convert(response, StringResponseTO.class);
58+
final StringResponseTO converted = getRequest(urlParams, StringResponseTO.class);
6159
if (converted.getStatus() != 1)
62-
throw new EtherScanException(converted.getMessage() + " with status " + converted.getStatus());
60+
throw new EtherScanException(converted.getMessage() + ", with status " + converted.getStatus());
6361

6462
return new Balance(address, Long.valueOf(converted.getResult()));
6563
}
6664

6765
@NotNull
6866
@Override
6967
public List<Balance> balances(final List<String> addresses) {
70-
BasicUtils.validateAddresses(addresses);
71-
if (addresses.isEmpty())
68+
if (BasicUtils.isEmpty(addresses))
7269
return Collections.emptyList();
7370

74-
final String urlParams = BALANCE_MULTI_ACTION + TAG_LATEST_PARAM + ADDRESS_PARAM + toAddressParam(addresses);
75-
final String response = getRequest(urlParams);
76-
final BalanceResponseTO converted = convert(response, BalanceResponseTO.class);
77-
if (converted.getStatus() != 1)
78-
throw new EtherScanException(converted.getMessage() + " with status " + converted.getStatus());
71+
BasicUtils.validateAddresses(addresses);
72+
73+
// Maximum addresses in batch request - 20
74+
final List<Balance> balances = new ArrayList<>();
75+
final List<List<String>> addressesAsBatches = BasicUtils.partition(addresses, 20);
7976

80-
return converted.getBalances().stream().map(Balance::of).collect(Collectors.toList());
77+
for (final List<String> batch : addressesAsBatches) {
78+
final String urlParams = BALANCE_MULTI_ACTION + TAG_LATEST_PARAM + ADDRESS_PARAM + toAddressParam(batch);
79+
final BalanceResponseTO converted = getRequest(urlParams, BalanceResponseTO.class);
80+
if (converted.getStatus() != 1)
81+
throw new EtherScanException(converted.getMessage() + ", with status " + converted.getStatus());
82+
83+
if (!BasicUtils.isEmpty(converted.getBalances()))
84+
balances.addAll(converted.getBalances().stream()
85+
.map(Balance::of)
86+
.collect(Collectors.toList()));
87+
}
88+
89+
return balances;
8190
}
8291

8392
private String toAddressParam(final List<String> addresses) {
@@ -88,8 +97,7 @@ private String toAddressParam(final List<String> addresses) {
8897
@Override
8998
public List<Tx> txs(final String address) {
9099
//TODO all txs implementations with pagination
91-
92-
return txs(address, MIN_START_BLOCK, MAX_END_BLOCK);
100+
return txs(address, MIN_START_BLOCK);
93101
}
94102

95103
@NotNull
@@ -105,8 +113,7 @@ public List<Tx> txs(final String address, final long startBlock, final long endB
105113

106114
final String blockParam = START_BLOCK_PARAM + startBlock + END_BLOCK_PARAM + endBlock;
107115
final String urlParams = TX_ACTION + ADDRESS_PARAM + address + blockParam + SORT_ASC_PARAM;
108-
final String response = getRequest(urlParams);
109-
final TxResponseTO converted = convert(response, TxResponseTO.class);
116+
final TxResponseTO converted = getRequest(urlParams, TxResponseTO.class);
110117
if (converted.getStatus() != 1)
111118
throw new EtherScanException(converted.getMessage() + " with status " + converted.getStatus());
112119

@@ -117,49 +124,89 @@ public List<Tx> txs(final String address, final long startBlock, final long endB
117124

118125
@NotNull
119126
@Override
120-
public List<Tx> txsInternal(final String address) {
121-
return null;
127+
public List<TxInternal> txsInternal(final String address) {
128+
//TODO all txs implementations with pagination
129+
return txsInternal(address, MIN_START_BLOCK);
122130
}
123131

124132
@NotNull
125133
@Override
126-
public List<Tx> txsInternal(final String address, final long startBlock) {
134+
public List<TxInternal> txsInternal(final String address, final long startBlock) {
127135
return txsInternal(address, startBlock, MAX_END_BLOCK);
128136
}
129137

130138
@NotNull
131139
@Override
132-
public List<Tx> txsInternal(final String address, final long startBlock, final long endBlock) {
133-
return null;
140+
public List<TxInternal> txsInternal(final String address, final long startBlock, final long endBlock) {
141+
BasicUtils.validateAddress(address);
142+
143+
final String blockParam = START_BLOCK_PARAM + startBlock + END_BLOCK_PARAM + endBlock;
144+
final String urlParams = TX_INTERNAL_ACTION + ADDRESS_PARAM + address + blockParam + SORT_ASC_PARAM;
145+
final TxInternalResponseTO converted = getRequest(urlParams, TxInternalResponseTO.class);
146+
if (converted.getStatus() != 1)
147+
throw new EtherScanException(converted.getMessage() + " with status " + converted.getStatus());
148+
149+
return (converted.getResult() == null)
150+
? Collections.emptyList()
151+
: converted.getResult();
134152
}
135153

136154
@NotNull
137155
@Override
138-
public List<Tx> txsInternalByHash(String txhash) {
139-
return null;
156+
public List<TxInternal> txsInternalByHash(final String txhash) {
157+
BasicUtils.validateTxHash(txhash);
158+
159+
final String urlParams = TX_INTERNAL_ACTION + TXHASH_PARAM + txhash;
160+
final TxInternalResponseTO converted = getRequest(urlParams, TxInternalResponseTO.class);
161+
if (converted.getStatus() != 1)
162+
throw new EtherScanException(converted.getMessage() + " with status " + converted.getStatus());
163+
164+
return (converted.getResult() == null)
165+
? Collections.emptyList()
166+
: converted.getResult();
140167
}
141168

142169
@NotNull
143170
@Override
144-
public List<Tx> txsToken(final String address) {
145-
return null;
171+
public List<TxToken> txsToken(final String address) {
172+
//TODO all txs implementations with pagination
173+
return txsToken(address, MIN_START_BLOCK);
146174
}
147175

148176
@NotNull
149177
@Override
150-
public List<Tx> txsToken(final String address, final long startBlock) {
178+
public List<TxToken> txsToken(final String address, final long startBlock) {
151179
return txsToken(address, startBlock, MAX_END_BLOCK);
152180
}
153181

154182
@NotNull
155183
@Override
156-
public List<Tx> txsToken(final String address, final long startBlock, final long endBlock) {
157-
return null;
184+
public List<TxToken> txsToken(final String address, final long startBlock, final long endBlock) {
185+
BasicUtils.validateAddress(address);
186+
187+
final String blockParam = START_BLOCK_PARAM + startBlock + END_BLOCK_PARAM + endBlock;
188+
final String urlParams = TX_TOKEN_ACTION + ADDRESS_PARAM + address + blockParam + SORT_ASC_PARAM;
189+
final TxTokenResponseTO converted = getRequest(urlParams, TxTokenResponseTO.class);
190+
if (converted.getStatus() != 1)
191+
throw new EtherScanException(converted.getMessage() + " with status " + converted.getStatus());
192+
193+
return (converted.getResult() == null)
194+
? Collections.emptyList()
195+
: converted.getResult();
158196
}
159197

160198
@NotNull
161199
@Override
162200
public List<Block> minedBlocks(final String address) {
163-
return null;
201+
BasicUtils.validateAddress(address);
202+
203+
final String urlParams = MINED_ACTION + BLOCK_TYPE_PARAM + ADDRESS_PARAM + address;
204+
final BlockResponseTO converted = getRequest(urlParams, BlockResponseTO.class);
205+
if (converted.getStatus() != 1)
206+
throw new EtherScanException(converted.getMessage() + " with status " + converted.getStatus());
207+
208+
return (converted.getResult() == null)
209+
? Collections.emptyList()
210+
: converted.getResult();
164211
}
165212
}

0 commit comments

Comments
 (0)