-
Notifications
You must be signed in to change notification settings - Fork 41
/
Copy pathProxyAPIProvider.java
234 lines (200 loc) Β· 10.7 KB
/
ProxyAPIProvider.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
package io.goodforgod.api.etherscan;
import io.goodforgod.api.etherscan.error.EtherScanException;
import io.goodforgod.api.etherscan.error.EtherScanInvalidDataHexException;
import io.goodforgod.api.etherscan.error.EtherScanResponseException;
import io.goodforgod.api.etherscan.http.EthHttpClient;
import io.goodforgod.api.etherscan.manager.RequestQueueManager;
import io.goodforgod.api.etherscan.model.Wei;
import io.goodforgod.api.etherscan.model.proxy.BlockProxy;
import io.goodforgod.api.etherscan.model.proxy.ReceiptProxy;
import io.goodforgod.api.etherscan.model.proxy.TxProxy;
import io.goodforgod.api.etherscan.model.proxy.utility.BlockProxyTO;
import io.goodforgod.api.etherscan.model.proxy.utility.StringProxyTO;
import io.goodforgod.api.etherscan.model.proxy.utility.TxInfoProxyTO;
import io.goodforgod.api.etherscan.model.proxy.utility.TxProxyTO;
import io.goodforgod.api.etherscan.model.response.StringResponseTO;
import io.goodforgod.api.etherscan.util.BasicUtils;
import java.util.Optional;
import java.util.regex.Pattern;
import org.jetbrains.annotations.NotNull;
/**
* Proxy API Implementation
*
* @see ProxyAPI
* @author GoodforGod
* @since 28.10.2018
*/
final class ProxyAPIProvider extends BasicProvider implements ProxyAPI {
private static final String ACT_BLOCKNO_PARAM = ACT_PREFIX + "eth_blockNumber";
private static final String ACT_BY_BLOCKNO_PARAM = ACT_PREFIX + "eth_getBlockByNumber";
private static final String ACT_UNCLE_BY_BLOCKNOINDEX_PARAM = ACT_PREFIX + "eth_getUncleByBlockNumberAndIndex";
private static final String ACT_BLOCKTX_COUNT_PARAM = ACT_PREFIX + "eth_getBlockTransactionCountByNumber";
private static final String ACT_TX_BY_HASH_PARAM = ACT_PREFIX + "eth_getTransactionByHash";
private static final String ACT_TX_BY_BLOCKNOINDEX_PARAM = ACT_PREFIX + "eth_getTransactionByBlockNumberAndIndex";
private static final String ACT_TX_COUNT_PARAM = ACT_PREFIX + "eth_getTransactionCount";
private static final String ACT_SEND_RAW_TX_PARAM = ACT_PREFIX + "eth_sendRawTransaction";
private static final String ACT_TX_RECEIPT_PARAM = ACT_PREFIX + "eth_getTransactionReceipt";
private static final String ACT_CALL_PARAM = ACT_PREFIX + "eth_call";
private static final String ACT_CODE_PARAM = ACT_PREFIX + "eth_getCode";
private static final String ACT_STORAGEAT_PARAM = ACT_PREFIX + "eth_getStorageAt";
private static final String ACT_GASPRICE_PARAM = ACT_PREFIX + "eth_gasPrice";
private static final String ACT_ESTIMATEGAS_PARAM = ACT_PREFIX + "eth_estimateGas";
private static final String BOOLEAN_PARAM = "&boolean=true";
private static final String TAG_LAST_PARAM = "&tag=latest";
private static final String POSITION_PARAM = "&position=";
private static final String ADDRESS_PARAM = "&address=";
private static final String TXHASH_PARAM = "&txhash=";
private static final String INDEX_PARAM = "&index=";
private static final String DATA_PARAM = "&data=";
private static final String GAS_PARAM = "&gas=";
private static final String TAG_PARAM = "&tag=";
private static final String HEX_PARAM = "&hex=";
private static final String TO_PARAM = "&to=";
private static final Pattern EMPTY_HEX = Pattern.compile("0x0+");
ProxyAPIProvider(RequestQueueManager queue,
String baseUrl,
EthHttpClient executor,
Converter converter,
int retryCount) {
super(queue, "proxy", baseUrl, executor, converter, retryCount);
}
@Override
public long blockNoLast() throws EtherScanException {
final StringProxyTO response = getRequest(ACT_BLOCKNO_PARAM, StringProxyTO.class);
return (BasicUtils.isEmpty(response.getResult()))
? -1
: BasicUtils.parseHex(response.getResult()).longValue();
}
@NotNull
@Override
public Optional<BlockProxy> block(long blockNo) throws EtherScanException {
final long compBlockNo = BasicUtils.compensateMinBlock(blockNo);
final String urlParams = ACT_BY_BLOCKNO_PARAM + TAG_PARAM + compBlockNo + BOOLEAN_PARAM;
final BlockProxyTO response = getRequest(urlParams, BlockProxyTO.class);
return Optional.ofNullable(response.getResult());
}
@NotNull
@Override
public Optional<BlockProxy> blockUncle(long blockNo, long index) throws EtherScanException {
final long compBlockNo = BasicUtils.compensateMinBlock(blockNo);
final long compIndex = BasicUtils.compensateMinBlock(index);
final String urlParams = ACT_UNCLE_BY_BLOCKNOINDEX_PARAM + TAG_PARAM
+ "0x" + Long.toHexString(compBlockNo) + INDEX_PARAM + "0x" + Long.toHexString(compIndex);
final BlockProxyTO response = getRequest(urlParams, BlockProxyTO.class);
return Optional.ofNullable(response.getResult());
}
@NotNull
@Override
public Optional<TxProxy> tx(@NotNull String txhash) throws EtherScanException {
BasicUtils.validateTxHash(txhash);
final String urlParams = ACT_TX_BY_HASH_PARAM + TXHASH_PARAM + txhash;
final TxProxyTO response = getRequest(urlParams, TxProxyTO.class);
return Optional.ofNullable(response.getResult());
}
@NotNull
@Override
public Optional<TxProxy> tx(long blockNo, long index) throws EtherScanException {
final long compBlockNo = BasicUtils.compensateMinBlock(blockNo);
final long compIndex = (index < 1)
? 1
: index;
final String urlParams = ACT_TX_BY_BLOCKNOINDEX_PARAM + TAG_PARAM + compBlockNo + INDEX_PARAM + "0x"
+ Long.toHexString(compIndex);
final TxProxyTO response = getRequest(urlParams, TxProxyTO.class);
return Optional.ofNullable(response.getResult());
}
@Override
public int txCount(long blockNo) throws EtherScanException {
final long compensatedBlockNo = BasicUtils.compensateMinBlock(blockNo);
final String urlParams = ACT_BLOCKTX_COUNT_PARAM + TAG_PARAM + "0x" + Long.toHexString(compensatedBlockNo);
final StringProxyTO response = getRequest(urlParams, StringProxyTO.class);
return BasicUtils.parseHex(response.getResult()).intValue();
}
@Override
public int txSendCount(@NotNull String address) throws EtherScanException {
BasicUtils.validateAddress(address);
final String urlParams = ACT_TX_COUNT_PARAM + ADDRESS_PARAM + address + TAG_LAST_PARAM;
final StringProxyTO response = getRequest(urlParams, StringProxyTO.class);
return BasicUtils.parseHex(response.getResult()).intValue();
}
@Override
@NotNull
public Optional<String> txSendRaw(@NotNull String hexEncodedTx) throws EtherScanException {
if (BasicUtils.isNotHex(hexEncodedTx))
throw new EtherScanInvalidDataHexException("Data is not encoded in hex format - " + hexEncodedTx);
final String urlParams = ACT_SEND_RAW_TX_PARAM + HEX_PARAM + hexEncodedTx;
final StringProxyTO response = postRequest(urlParams, "", StringProxyTO.class);
if (response.getError() != null) {
final StringResponseTO responseError = StringResponseTO.builder()
.withStatus("0")
.withMessage(response.getError().getMessage())
.withResult(response.getError().getCode())
.build();
throw new EtherScanResponseException(responseError, "Error occurred with code " + response.getError().getCode()
+ " with message " + response.getError().getMessage()
+ ", error id " + response.getId() + ", jsonRPC " + response.getJsonrpc());
}
return Optional.ofNullable(response.getResult());
}
@NotNull
@Override
public Optional<ReceiptProxy> txReceipt(@NotNull String txhash) throws EtherScanException {
BasicUtils.validateTxHash(txhash);
final String urlParams = ACT_TX_RECEIPT_PARAM + TXHASH_PARAM + txhash;
final TxInfoProxyTO response = getRequest(urlParams, TxInfoProxyTO.class);
return Optional.ofNullable(response.getResult());
}
@NotNull
@Override
public Optional<String> call(@NotNull String address, @NotNull String data) throws EtherScanException {
BasicUtils.validateAddress(address);
if (BasicUtils.isNotHex(data))
throw new EtherScanInvalidDataHexException("Data is not hex encoded.");
final String urlParams = ACT_CALL_PARAM + TO_PARAM + address + DATA_PARAM + data + TAG_LAST_PARAM;
final StringProxyTO response = getRequest(urlParams, StringProxyTO.class);
return Optional.ofNullable(response.getResult());
}
@NotNull
@Override
public Optional<String> code(@NotNull String address) throws EtherScanException {
BasicUtils.validateAddress(address);
final String urlParams = ACT_CODE_PARAM + ADDRESS_PARAM + address + TAG_LAST_PARAM;
final StringProxyTO response = getRequest(urlParams, StringProxyTO.class);
return Optional.ofNullable(response.getResult());
}
@NotNull
@Override
public Optional<String> storageAt(@NotNull String address, long position) throws EtherScanException {
BasicUtils.validateAddress(address);
final long compPosition = BasicUtils.compensateMinBlock(position);
final String urlParams = ACT_STORAGEAT_PARAM + ADDRESS_PARAM + address + POSITION_PARAM + compPosition + TAG_LAST_PARAM;
final StringProxyTO response = getRequest(urlParams, StringProxyTO.class);
return (BasicUtils.isEmpty(response.getResult()) || EMPTY_HEX.matcher(response.getResult()).matches())
? Optional.empty()
: Optional.of(response.getResult());
}
@NotNull
@Override
public Wei gasPrice() throws EtherScanException {
final StringProxyTO response = getRequest(ACT_GASPRICE_PARAM, StringProxyTO.class);
return (BasicUtils.isEmpty(response.getResult()))
? Wei.ofWei(0)
: Wei.ofWei(BasicUtils.parseHex(response.getResult()));
}
@NotNull
@Override
public Wei gasEstimated() throws EtherScanException {
return gasEstimated("606060405260728060106000396000f360606040526000");
}
@NotNull
@Override
public Wei gasEstimated(@NotNull String hexData) throws EtherScanException {
if (!BasicUtils.isEmpty(hexData) && BasicUtils.isNotHex(hexData))
throw new EtherScanInvalidDataHexException("Data is not in hex format.");
final String urlParams = ACT_ESTIMATEGAS_PARAM + DATA_PARAM + hexData + GAS_PARAM + "2000000000000000";
final StringProxyTO response = getRequest(urlParams, StringProxyTO.class);
return (BasicUtils.isEmpty(response.getResult()))
? Wei.ofWei(0)
: Wei.ofWei(BasicUtils.parseHex(response.getResult()));
}
}