Search code examples
javaandroidrealmethereumweb3-java

Sending A Transaction Async | Cannot Resolve Method 'executeTransactionAsync'


I am attemping to send a transaction to the Ethereum blockchain using the Web3j library, I get an error that I must send it with Async. When I send it with Async I get an error that the function does not exist. I am using Android Studio, Java, and the Web3j library.

When calling the executeTransactionAsync method, part of web3.abi.datatypes.Function, I get an error saying the method can not be found. I figured out this means that the method executeTransactionAsync does not exist in the Web3j library. However, the Web3j documentation says to use that method. I am using the latest version of Web3j which is 3.1.1.

If I remove the Async so the method is executeTransaction, I get an error that the Transaction needs to be sent through Async.

Is there a way I could send this transaction with Realm or something else? Or maybe I am using Web3j wrong and I need to use it another way?


The code sending the transaction:

public TransactionReceipt approve() throws IOException, TransactionException {
    Function function = new Function("approve", Arrays.<Type>asList(), Collections.<TypeReference<?>>emptyList());
    return executeTransactionAsync (function);
}

Web3j API


Solution

  • You need to use an executeTransaction wrapped in a RemoteCall.

    Function function = new Function(...);
    RemoteCall<TransactionReceipt> remoteCall = new RemoteCall(() -> {
      //call to executeTransaction
    });
    TransactionReceipt receipt = remoteCall.send();
    

    You can make life easier for yourself by using web3j's code generation tools which creates simple wrappers for your smart contract. See this section of the web3j documentation on how to generate your code. The generated class handles the remote calls (and local calls for constant functions). Your client code becomes something like:

    Web3j web3j = Web3j.build(new HttpService());
    Credentials credentials = Credentials.create(<YOUR_PRIVATE_KEY>);
    SimpleContract contract = SimpleContract.load(<CONTRACT_ADDRESS>, web3j, credentials, BigInteger.valueOf(<GAS_PRICE>), BigInteger.valueOf(<GAS_LIMIT));
    RemoteCall<TransactionReceipt> remoteCall = contract.setValue(BigInteger.valueOf(5)); // Call to smart contract setValue(5)
    TransactionReceipt receipt = remoteCall.send();
    

    Edit to add code generation example

    $ solc --version
    solc, the solidity compiler commandline interface
    Version: 0.4.19+commit.c4cbbb05.Windows.msvc
    
    $ java -version
    java version "1.8.0_144"
    Java(TM) SE Runtime Environment (build 1.8.0_144-b01)
    Java HotSpot(TM) 64-Bit Server VM (build 25.144-b01, mixed mode)
    
    $ solc contracts/SimpleContract.sol --bin --abi --optimize -o build/
    
    $ web3j.bat solidity generate build/SimpleContract.bin build/SimpleContract.abi -o ./src -p mypackage
    
                  _      _____ _     _
                 | |    |____ (_)   (_)
    __      _____| |__      / /_     _   ___
    \ \ /\ / / _ \ '_ \     \ \ |   | | / _ \
     \ V  V /  __/ |_) |.___/ / | _ | || (_) |
      \_/\_/ \___|_.__/ \____/| |(_)|_| \___/
                             _/ |
                            |__/
    
    Generating mypackage.SimpleContract ... File written to .\src
    

    Note - I'm running on Windows with Cygwin. Hence, the web3j.bat usage.