Skip to content

Commit ec0cf80

Browse files
committed
Higher-level API to read well-known ETH events as polymorphic classes
1 parent 235be0d commit ec0cf80

11 files changed

+250
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package io.api.etherscan.core;
2+
3+
import io.api.etherscan.error.ApiException;
4+
import io.api.etherscan.model.Log;
5+
import io.api.etherscan.model.event.IEvent;
6+
import io.api.etherscan.model.query.impl.LogQuery;
7+
import org.jetbrains.annotations.NotNull;
8+
9+
import java.util.List;
10+
11+
/**
12+
* EtherScan - API Descriptions
13+
* https://etherscan.io/apis#logs
14+
*/
15+
public interface IEventsApi {
16+
17+
/**
18+
* This is a high-level alternative to the ILogsApi and an alternative to the native eth_getLogs
19+
* Read at EtherScan API description for full info!
20+
* @param query build log query
21+
* @return logs according to query
22+
* @throws ApiException parent exception class
23+
*
24+
* @see io.api.etherscan.model.query.impl.LogQueryBuilder
25+
*/
26+
@NotNull
27+
List<IEvent> events(LogQuery query) throws ApiException;
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package io.api.etherscan.core.impl;
2+
3+
import io.api.etherscan.core.IEventsApi;
4+
import io.api.etherscan.core.ILogsApi;
5+
import io.api.etherscan.error.ApiException;
6+
import io.api.etherscan.executor.IHttpExecutor;
7+
import io.api.etherscan.manager.IQueueManager;
8+
import io.api.etherscan.model.Log;
9+
import io.api.etherscan.model.event.IEvent;
10+
import io.api.etherscan.model.event.impl.Event;
11+
import io.api.etherscan.model.query.impl.LogQuery;
12+
import io.api.etherscan.model.utility.LogResponseTO;
13+
import io.api.etherscan.util.BasicUtils;
14+
import org.jetbrains.annotations.NotNull;
15+
16+
import java.util.Collections;
17+
import java.util.List;
18+
import java.util.stream.Collectors;
19+
20+
/**
21+
* Logs API Implementation
22+
*
23+
* @see IEventsApi
24+
*
25+
*/
26+
public class EventsApiProvider extends BasicProvider implements IEventsApi {
27+
28+
private static final String ACT_LOGS_PARAM = ACT_PREFIX + "getLogs";
29+
30+
EventsApiProvider(final IQueueManager queue,
31+
final String baseUrl,
32+
final IHttpExecutor executor) {
33+
super(queue, "logs", baseUrl, executor);
34+
}
35+
36+
@NotNull
37+
@Override
38+
public List<IEvent> events(final LogQuery query) throws ApiException {
39+
final String urlParams = ACT_LOGS_PARAM + query.getParams();
40+
final LogResponseTO response = getRequest(urlParams, LogResponseTO.class);
41+
BasicUtils.validateTxResponse(response);
42+
43+
if (BasicUtils.isEmpty(response.getResult())) {
44+
return Collections.emptyList();
45+
};
46+
return response
47+
.getResult()
48+
.stream()
49+
.map((log) -> {
50+
String eventTypeHash = log.getTopics().get(0);
51+
return IEvent.createEvent(eventTypeHash, log);
52+
})
53+
.collect(Collectors.toList());
54+
}
55+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package io.api.etherscan.error;
2+
3+
public class EventModelException extends ApiException {
4+
public EventModelException(String message) {
5+
super(message);
6+
}
7+
8+
public EventModelException(String message, Throwable cause) {
9+
super(message, cause);
10+
}
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package io.api.etherscan.model.event;
2+
3+
import io.api.etherscan.error.ApiException;
4+
import io.api.etherscan.error.EventModelException;
5+
import io.api.etherscan.model.Log;
6+
7+
import java.util.HashMap;
8+
import java.util.Map;
9+
10+
public interface IEvent {
11+
static final Map<String, Class<?>> subTypes = new HashMap<>();
12+
13+
void setLog(Log log);
14+
15+
static void registerEventType(String typeHash, Class<?> clazz) {
16+
subTypes.put(typeHash, clazz);
17+
}
18+
19+
static IEvent createEvent(String typeHash, Log log) {
20+
if (null == typeHash) {
21+
throw new EventModelException("Event type hash cannot be null");
22+
}
23+
Class<?> clazz = subTypes.get(typeHash);
24+
try {
25+
IEvent evt = (IEvent) clazz.newInstance();
26+
evt.setLog(log);
27+
return evt;
28+
} catch (InstantiationException | IllegalAccessException ex) {
29+
throw new ApiException("Client-side error instantiating Event object", ex);
30+
}
31+
}
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package io.api.etherscan.model.event.impl;
2+
3+
import io.api.etherscan.model.event.IEvent;
4+
5+
public class ApprovalEvent extends Event {
6+
static final String eventTypeHash = "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925";
7+
static {
8+
IEvent.registerEventType(ApprovalEvent.eventTypeHash, ApprovalEvent.class);
9+
}
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package io.api.etherscan.model.event.impl;
2+
3+
import io.api.etherscan.model.event.IEvent;
4+
5+
public class DepositEvent extends Event {
6+
static final String eventTypeHash = "0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c";
7+
static {
8+
IEvent.registerEventType(DepositEvent.eventTypeHash, DepositEvent.class);
9+
}
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package io.api.etherscan.model.event.impl;
2+
3+
import io.api.etherscan.error.ApiException;
4+
import io.api.etherscan.error.EventModelException;
5+
import io.api.etherscan.model.Log;
6+
import io.api.etherscan.model.event.IEvent;
7+
8+
import java.util.HashMap;
9+
import java.util.Map;
10+
11+
/**
12+
* Base class for a higher-level API on top of {@link Log}. Each Event class has an identifying hash
13+
*/
14+
public class Event implements IEvent {
15+
16+
static String eventTypeHash;
17+
18+
private Log log;
19+
20+
String address;
21+
22+
public static String getEventTypeHash() {
23+
return eventTypeHash;
24+
}
25+
26+
public Log getLog() {
27+
return log;
28+
}
29+
30+
public String getAddress() {
31+
return address;
32+
}
33+
34+
public void setLog(Log log) {
35+
this.log = log;
36+
}
37+
38+
public void setAddress(String address) {
39+
this.address = address;
40+
}
41+
42+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package io.api.etherscan.model.event.impl;
2+
3+
import io.api.etherscan.model.event.IEvent;
4+
5+
public class MintEvent extends Event {
6+
static final String eventTypeHash = "0x4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f";
7+
static {
8+
IEvent.registerEventType(MintEvent.eventTypeHash, MintEvent.class);
9+
}
10+
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package io.api.etherscan.model.event.impl;
2+
3+
import io.api.etherscan.model.event.IEvent;
4+
5+
public class SyncEvent extends Event {
6+
static final String eventTypeHash = "0x1c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1";
7+
static {
8+
IEvent.registerEventType(SyncEvent.eventTypeHash, SyncEvent.class);
9+
}
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package io.api.etherscan.model.event.impl;
2+
3+
import io.api.etherscan.model.event.IEvent;
4+
5+
public class TransferErc20Event extends Event {
6+
static final String eventTypeHash = "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef";
7+
static {
8+
IEvent.registerEventType(TransferErc20Event.eventTypeHash, TransferErc20Event.class);
9+
}
10+
11+
String fromAddress;
12+
13+
String toAddress;
14+
15+
public String getFromAddress() {
16+
return fromAddress;
17+
}
18+
19+
public void setFromAddress(String fromAddress) {
20+
this.fromAddress = fromAddress;
21+
}
22+
23+
public String getToAddress() {
24+
return toAddress;
25+
}
26+
27+
public void setToAddress(String toAddress) {
28+
this.toAddress = toAddress;
29+
}
30+
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package io.api.etherscan.model.event.impl;
2+
3+
import io.api.etherscan.model.event.IEvent;
4+
5+
public class WithdrawEvent extends Event {
6+
static final String eventTypeHash = "0x7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65";
7+
static {
8+
IEvent.registerEventType(WithdrawEvent.eventTypeHash, WithdrawEvent.class);
9+
}
10+
}

0 commit comments

Comments
 (0)