Am 11. November letzten Jahres fürte der Ausfall von Infura dazu, dass viele zentrale Börsen die Abhebung von ETH und ERC20-Token gestoppt hatten. Zudem ließen sich Metamask, Uniswap und auch andere Anwendungen auf Ethereum nicht mehr nutzen. Infura scheint ein beliebter Dienstleister für Ethereum Nodes zu sein, auf den sich nicht nur kleinere Unternehmen und Projekte verlassen, sondern auch milliardenschwere Börsen wie Binance.
Für dieses Projekt soll dennoch mal die Infura-API verwendet werden, um den Kontostand einer ETH-Adresse zu ermitteln. Mit dem web3j Framework ist das auch in Java realisierbar. Hier der Architektur Aufbau:
Wir starten (wie immer) mit einem JUnit 5 Test:
Wir verwenden dazu meine „Buy my a coffee Ethereum (ETH)“ Adresse 0x829F9e57c29ab683E964c76160B7B0BaB2727dD2 und meine ProjektID von Infura: eaa4f4c6b7ce453cba56b73b5d558bdc um schnelle Ergebnisse zu erhalten.
1 2 3 4 5 6 |
@Test void testenDesKontostandAufDemMainnet() throws Exception { String[] parmeter = { "-n", "mainnet", "-p", PROJEKT_ID, "-a", MAINNET_ADRESSE }; Kontostand.main(parmeter); } |
Wir erwarten keine Fehler, nur eine Log-Ausgabe in der Form (im CSV Format: Ether, Kommentar, ETH-Adresse, Kommentar, Netz):
1 |
[INFO ] 2021-10-20 23:35:41,100 Kontostand.call() - 0.004517710000000000 Ether, auf Adresse, 0x829F9e57c29ab683E964c76160B7B0BaB2727dD2, im Netz, mainnet |
Was müssen wir tun?
1. die web3j Abhängigkeit in der pom.xml eintragen
1 2 3 4 5 |
<dependency> <groupId>org.web3j</groupId> <artifactId>core</artifactId> <version>5.0.0</version> </dependency> |
2. die URL zusammenstellen aus dem Netzwerkname und Projekt ID.
final String ethUrl = „https://“ + netzwerkName + „.infura.io/v3/“ + projektId;
3. eine web3j Instanz erstellen mit der erstellten ethUrl
Web3j web3jClient = Web3j.build(new HttpService(ethUrl));
4. eine asyncrone Abfrage an Infura senden, mit Timeout von 10 Sekunden und der Adresse
EthGetBalance kontoAntwort = web3jClient.ethGetBalance(ethAdresse, DefaultBlockParameterName.LATEST).sendAsync().get(10, TimeUnit.SECONDS);
5. das Ergebnis auswerten
BigDecimal skalierterStand = new BigDecimal(kontoAntwort.getBalance()).divide(new BigDecimal(1000000000000000000L), 18, RoundingMode.HALF_UP);
Das ist schon alles. Hier die ganze Klasse, mit Auswertung der Kommandozeilen Parameter mit Picoli:
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 |
package de.wenzlaff.twetherscan; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.concurrent.Callable; import java.util.concurrent.TimeUnit; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.web3j.protocol.Web3j; import org.web3j.protocol.core.DefaultBlockParameterName; import org.web3j.protocol.core.methods.response.EthGetBalance; import org.web3j.protocol.http.HttpService; import picocli.CommandLine; import picocli.CommandLine.Command; import picocli.CommandLine.Option; /** * Abfragen eines Kontostands über * * https://infura.io/dashboard/ethereum/ * * mit Web3J. * * https://etherscan.io/address/0x829f9e57c29ab683e964c76160b7b0bab2727dd2 * * Parameter z,B. * * <pre> * -n mainnet -p eaa4f4c6b7ce453cba56b73b5d558bdc -a 0x829F9e57c29ab683E964c76160B7B0BaB2727dD2 -n rinkeby -p eaa4f4c6b7ce453cba56b73b5d558bdc -a 0x6f55a676d5862623bd79446133043AEf905718B8 * * </pre> * * @author Thomas Wenzlaff */ @Command(name = "Kontostand", mixinStandardHelpOptions = true, version = "Kontostand Version 1.0", showDefaultValues = true, description = "Kontostand abfragen", exitCodeList = { " 0:Successful program execution." }, footer = { "@|fg(green) Thomas Wenzlaff|@", "@|fg(red),bold http://www.wenzlaff.info|@" }) public class Kontostand implements Callable<Integer> { private static final Logger LOG = LogManager.getLogger(Kontostand.class); @Option(names = { "-n", "--netzwerk" }, required = true, description = "der Netzwerkname (z.B. mainnet oder rinkeby)", defaultValue = "mainnet") private static String netzwerkName; @Option(names = { "-p", "--projektid" }, required = true, description = "die Projekt Id von Influra.io") private static String projektId; @Option(names = { "-a", "--adresse" }, required = true, description = "die Adresse die abgefragt wird") private static String ethAdresse; @Option(names = { "-c", "--client" }, description = "die Web3j Client Info wird ausgegeben") private static boolean isClientVersion; public static void main(String[] args) throws Exception { new CommandLine(new Kontostand()).execute(args); } @Override public Integer call() throws Exception { final String ethUrl = "https://" + netzwerkName + ".infura.io/v3/" + projektId; Web3j web3jClient = getWeb3Client(ethUrl); if (isClientVersion) { Version.getClientVersion(web3jClient); } EthGetBalance kontoAntwort = web3jClient.ethGetBalance(ethAdresse, DefaultBlockParameterName.LATEST).sendAsync().get(10, TimeUnit.SECONDS); BigDecimal skalierterStand = new BigDecimal(kontoAntwort.getBalance()).divide(new BigDecimal(1000000000000000000L), 18, RoundingMode.HALF_UP); LOG.info(skalierterStand + " Ether, auf Adresse, " + ethAdresse + ", im Netz, " + netzwerkName); return 0; } public Web3j getWeb3Client(String ethUrl) { return Web3j.build(new HttpService(ethUrl)); } } |
Das ganze Projekt gibt es auf GitLab. Mal sehen ob sich der Kontostand auf 0x829F9e57c29ab683E964c76160B7B0BaB2727dD2 verändert. Freue mich über jede Veränderung 😉