Hi there!
I am new to infura and want to play around with interacting with Ethereum. Now, I created an account on Infura.io, created my project, and started to code with Web3j (4.8.2) in Java 15 within a SpringBoot 2.4.1. Anyhow, I keep getting exceptions as soon as I attempt to interact with Infura/Ethereum.
First of all: I am assuming (and maybe here I am wrong) that I can simply use Web3j to connect to Ethereum via Infura? Anyhow, first, when attempting to connect to the Ropsten testnet, I got an Exception. Essentially, I worked out via some tutorials, that I needed to manually add the authHeader to the HttpService object, otherwise, I would get this exception:
java.lang.NoSuchMethodError: 'okhttp3.RequestBody okhttp3.RequestBody.create(java.lang.String, okhttp3.MediaType)'
Now, I managed to get the connection working as shown in my code below. Anyhow, any calls to my smart contract fail with the same exception. I already wrote and tested my smart contract, compiled it, deployed it to Ropsten, and built my Java class from it using web3j-cli. So far, no problems.
Now, my contract features a function run(string memory x)
that will return the string “ok” in case i pass the parameter “test” and “not ok” if any other string is passed. just for testing / exercise purposes for now.
Now what I am doing in my Java code is building a Web3j client and connect to Ethereum/Ropsten via my Infura account. All that works:
try {
HttpService httpService = new HttpService(INFURA_ENDPOINT); // Infura endpoint for ropsten
String auth = new String(":" + "yyyxxxzzz"); // Infura secret
byte[] encodedAuth = Base64.encodeBase64(auth.getBytes(StandardCharsets.ISO_8859_1));
String authHeader = "Basic " + new String(encodedAuth);
httpService.addHeader(HttpHeaders.AUTHORIZATION, authHeader);
Web3j web3j = Web3j.build(new HttpService(INFURA_ENDPOINT));
String privateKeyString = "xyz"; // private key as exported from Metamask for my account in ropsten
String address = "0xabc"; // addredd for said account
Credentials credentials = Credentials.create(privateKeyString);
String contractAddress = "0xabcdef"; // address of the deployed contract in ropsten
final BigInteger gasPrice = BigInteger.valueOf(2205000);
final BigInteger gasLimit = BigInteger.valueOf(14300000);
final ContractGasProvider gasProvider = new StaticGasProvider(gasPrice, gasLimit);
final Test contract = Test.load(contractAddress, web3j, credentials, gasProvider);
// NO PROBLEMS UNTIL HERE
String a = contract.run("xyz").send();
System.out.println("run(xyz): " + a);
} catch(Exception e) {
System.out.println("Web3j: " + e.getMessage() + "\n");
e.printStackTrace();
}
Now, explicitly calling the function run()
looks like this in my generated contract Java class:
public RemoteFunctionCall<String> run(String name) {
final Function function = new Function(FUNC_RUN,
Arrays.<Type>asList(new org.web3j.abi.datatypes.Utf8String(name)),
Arrays.<TypeReference<?>>asList(new TypeReference<Utf8String>() {}));
return executeRemoteCallSingleValueReturn(function, String.class);
}
Here’s the Solidity function from the smart contract:
function run(string memory name) public pure returns (string memory) {
if(strcmp(name, "test")) {
return "ok";
}
return "not ok";
}
Now, when I run this, a call such as contract.run("xyz")
runs without problems and is also received by Infura - as I can easily check and verify in my dashboard. Yet as soon as I append a send()
(same with sendAsync().get()
and the lot) I get the following exception:
Exception in thread "main" java.lang.NoSuchMethodError: 'okhttp3.RequestBody okhttp3.RequestBody.create(java.lang.String, okhttp3.MediaType)'
at org.web3j.protocol.http.HttpService.performIO(HttpService.java:154)
at org.web3j.protocol.Service.send(Service.java:48)
at org.web3j.protocol.core.Request.send(Request.java:87)
at org.web3j.tx.RawTransactionManager.sendCall(RawTransactionManager.java:155)
at org.web3j.tx.ManagedTransaction.call(ManagedTransaction.java:134)
at org.web3j.tx.Contract.executeCall(Contract.java:292)
at org.web3j.tx.Contract.executeCallSingleValueReturn(Contract.java:300)
at org.web3j.tx.Contract.executeCallSingleValueReturn(Contract.java:311)
at org.web3j.tx.Contract.lambda$executeRemoteCallSingleValueReturn$1(Contract.java:399)
at org.web3j.protocol.core.RemoteCall.send(RemoteCall.java:42)
at com.example.web3j.TestWeb3j.main(TestWeb3j.java:56)
I’m mostly following the tutorials https: //dzone. com/articles/blockchain-simplified-with-ethereum-example-with-j and https: //trimplement. com/blog/2020/03/coding-smart-contracts-tutorial-infura/ here. As far as I understand here, a send()
should call the contract’s function and get me the returned string. Anyhow, playing around with sendAsync().get()
will cause the same problems.
Is this again a problem where I need to manually add headers to the requests being sent? Is Web3j even compatible/usable with infura without all too much manual overhead?