Skip to content

Commit 5021031

Browse files
implement adaptor for ethereum gas price (#33)
1 parent f223b25 commit 5021031

File tree

6 files changed

+120
-0
lines changed

6 files changed

+120
-0
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.blockchain.api.application.exception;
2+
3+
public class GasPriceRetrievalException extends RuntimeException {
4+
public GasPriceRetrievalException(String message, Throwable cause) {
5+
super(message, cause);
6+
}
7+
8+
public static GasPriceRetrievalException build(Throwable e) {
9+
return new GasPriceRetrievalException("error while retrieving gas price", e);
10+
}
11+
}

ethereum-app/src/main/java/com/blockchain/api/domain/service/transfer/TransferClient.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,6 @@ public interface TransferClient {
77
void transfer(TransferRequest transferRequest);
88

99
CompletableFuture<BigInteger> getNonce(String address);
10+
11+
CompletableFuture<BigInteger> getGasPrice();
1012
}

ethereum-app/src/main/java/com/blockchain/api/infrastructure/client/transfer/TransferAdaptor.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.blockchain.api.infrastructure.client.transfer;
22

3+
import com.blockchain.api.application.exception.GasPriceRetrievalException;
34
import com.blockchain.api.application.exception.NonceRetrievalException;
45
import com.blockchain.api.domain.service.transfer.TransferClient;
56
import com.blockchain.api.domain.service.transfer.TransferRequest;
@@ -39,4 +40,21 @@ public CompletableFuture<BigInteger> getNonce(String address) {
3940
throw NonceRetrievalException.withAddress(address);
4041
});
4142
}
43+
44+
@Override
45+
public CompletableFuture<BigInteger> getGasPrice() {
46+
return rpcClient
47+
.ethGasPrice()
48+
.sendAsync()
49+
.thenApply(
50+
gasPrice -> {
51+
log.info("Gas price request completed successfully");
52+
return gasPrice.getGasPrice();
53+
})
54+
.exceptionally(
55+
throwable -> {
56+
log.error("Error occurred while fetching gas price", throwable);
57+
throw GasPriceRetrievalException.build(throwable);
58+
});
59+
}
4260
}

ethereum-app/src/test/java/com/blockchain/api/application/EthereumITest.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import static org.junit.jupiter.api.Assertions.assertNotNull;
44

55
import com.blockchain.api.domain.service.balance.BalanceClient;
6+
import com.blockchain.api.domain.service.transfer.TransferClient;
67
import java.math.BigDecimal;
78
import lombok.extern.slf4j.Slf4j;
89
import org.junit.jupiter.api.Test;
@@ -17,6 +18,8 @@
1718
public class EthereumITest {
1819
@Autowired private BalanceClient balanceClient;
1920

21+
@Autowired private TransferClient transferClient;
22+
2023
@Test
2124
void shouldReturnBalance() {
2225
// given
@@ -29,4 +32,17 @@ void shouldReturnBalance() {
2932
assertNotNull(result);
3033
log.info("Balance BigInteger: {}", Convert.fromWei(new BigDecimal(result), Convert.Unit.ETHER));
3134
}
35+
36+
@Test
37+
void shouldGetGasPrice() {
38+
// when
39+
var result = transferClient.getGasPrice().join();
40+
41+
// then
42+
assertNotNull(result);
43+
log.info(
44+
"original value {} Gas price: {}",
45+
result,
46+
Convert.fromWei(new BigDecimal(result), Convert.Unit.ETHER));
47+
}
3248
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package com.blockchain.api.application.exception;
2+
3+
import static org.assertj.core.api.Assertions.assertThat;
4+
import static org.junit.jupiter.api.Assertions.*;
5+
6+
import org.junit.jupiter.api.Test;
7+
8+
class GasPriceRetrievalExceptionTest {
9+
10+
@Test
11+
void shouldReturnGasPriceRetrievalException() {
12+
// given
13+
var message = "error while retrieving gas price";
14+
var cause = new Throwable();
15+
16+
// when
17+
var result = new GasPriceRetrievalException(message, cause);
18+
19+
// then
20+
assertThat(result.getMessage()).isEqualTo(message);
21+
}
22+
23+
@Test
24+
void shouldCreateGasPriceRetrievalExceptionWithStaticMethod() {
25+
// Given
26+
var message = "error while retrieving gas price";
27+
var cause = new Throwable();
28+
29+
// When
30+
var result = GasPriceRetrievalException.build(cause);
31+
32+
// Then
33+
assertEquals(message, result.getMessage());
34+
}
35+
}

ethereum-app/src/test/java/com/blockchain/api/infrastructure/client/transfer/TransferAdaptorTest.java

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
package com.blockchain.api.infrastructure.client.transfer;
22

3+
import static org.assertj.core.api.Assertions.assertThat;
34
import static org.assertj.core.api.Assertions.assertThatThrownBy;
45
import static org.junit.jupiter.api.Assertions.*;
56
import static org.mockito.ArgumentMatchers.eq;
67
import static org.mockito.Mockito.*;
78

9+
import com.blockchain.api.application.exception.GasPriceRetrievalException;
810
import com.blockchain.api.application.exception.NonceRetrievalException;
911
import java.math.BigInteger;
1012
import java.util.concurrent.CompletableFuture;
@@ -18,6 +20,7 @@
1820
import org.web3j.protocol.Web3j;
1921
import org.web3j.protocol.core.DefaultBlockParameterName;
2022
import org.web3j.protocol.core.Request;
23+
import org.web3j.protocol.core.methods.response.EthGasPrice;
2124
import org.web3j.protocol.core.methods.response.EthGetTransactionCount;
2225

2326
@ExtendWith(MockitoExtension.class)
@@ -72,4 +75,39 @@ void shouldThrowNonceRetrievalException_whenNonceRequestFails() {
7275

7376
verify(rpcClient).ethGetTransactionCount(eq(address), eq(DefaultBlockParameterName.LATEST));
7477
}
78+
79+
@Test
80+
void shouldRetrieveGasPrice() {
81+
// given
82+
when(rpcClient.ethGasPrice()).thenReturn(mock(Request.class));
83+
var ethGasPrice = mock(EthGasPrice.class);
84+
var gasPrice = BigInteger.valueOf(42);
85+
when(ethGasPrice.getGasPrice()).thenReturn(gasPrice);
86+
when(rpcClient.ethGasPrice().sendAsync())
87+
.thenReturn(CompletableFuture.completedFuture(ethGasPrice));
88+
89+
// when
90+
var result = transferAdaptor.getGasPrice();
91+
92+
// then
93+
assertThat(result.join()).isEqualTo(gasPrice);
94+
}
95+
96+
@Test
97+
void shouldThrowGasPriceRetrievalException_whenGasPriceRequestFails() {
98+
// given
99+
when(rpcClient.ethGasPrice()).thenReturn(mock(Request.class));
100+
when(rpcClient.ethGasPrice().sendAsync())
101+
.thenReturn(CompletableFuture.failedFuture(new RuntimeException("RPC error")));
102+
103+
// when
104+
var result = transferAdaptor.getGasPrice();
105+
106+
// then
107+
assertThatThrownBy(result::join)
108+
.isInstanceOf(CompletionException.class)
109+
.hasCauseInstanceOf(GasPriceRetrievalException.class)
110+
.hasRootCauseInstanceOf(RuntimeException.class)
111+
.hasRootCauseMessage("RPC error");
112+
}
75113
}

0 commit comments

Comments
 (0)