Wert kann nicht von Web3j sendFunds Future abgerufen werden

Ich habe versucht, mit web3j Geld von einem Ethereum-Konto zu einem anderen zu senden, um zu testen, ob es auf Android funktioniert. Ich verwende eine Infura-Cloud-Instanz.

Zuerst scheint es, dass ich es asynchron senden muss, weil Android dies verlangt. Im Code unten habe ich es versucht - aber es schlägt im letzten Schritt fehl, wenn ich versuche, aus der Zukunft zu kommen. Wenn ich nicht versuche, den Wert zu erhalten, gibt es keine Ausnahme, aber ich kann offensichtlich nichts mit dem Wert tun, was ich tun möchte.

        final String FROM_ADDRESS = "0x6861B070f43842FC16eAD07854eE5D91B9D27C13";
    final String TO_ADDRESS = "0x31B98D14007bDEe637298086988A0bBd31184523";

    //Credentials credentials = obtainCredentials(WALLET_DIRECTORY);

    Callable<TransactionReceipt> task = new Callable<TransactionReceipt>() {
        @Override
        public TransactionReceipt call() throws Exception {
            Web3j web3 = Web3jFactory.build(
                    new HttpService("https://rinkeby.infura.io/SxLC8uFzMPfzwnlXHqx9")
            );
            Log.d(TAG, web3.ethGasPrice().getJsonrpc());

            ClientTransactionManager clientTransactionManager =
                    new ClientTransactionManager(web3, FROM_ADDRESS);
            Log.d(TAG, clientTransactionManager.getFromAddress());

            org.web3j.tx.Transfer tran = new org.web3j.tx.Transfer(web3, clientTransactionManager);
            Log.d(TAG, String.valueOf(tran.getSyncThreshold()));

            RemoteCall<TransactionReceipt> rc = tran.sendFunds(
                    TO_ADDRESS,
                    BigDecimal.valueOf(1.0),
                    Convert.Unit.ETHER
            );
            Log.d(TAG, String.valueOf(rc.toString()));
            return rc.send();
        }
    };
    Future<TransactionReceipt> future = Async.run(task);
    return future.get();

Es kommt mit dieser Ausnahme:

11-19 12:49:03.418 32442-32442/com.example.graeme.beamitup W/System.err: java.util.concurrent.ExecutionException: org.web3j.protocol.exceptions.ClientConnectionException: Invalid response received: okhttp3.internal.http.RealResponseBody@3c286ab
11-19 12:49:03.418 32442-32442/com.example.graeme.beamitup W/System.err:     at java.util.concurrent.FutureTask.report(FutureTask.java:94)
11-19 12:49:03.419 32442-32442/com.example.graeme.beamitup W/System.err:     at java.util.concurrent.FutureTask.get(FutureTask.java:164)
11-19 12:49:03.419 32442-32442/com.example.graeme.beamitup W/System.err:     at com.example.graeme.beamitup.Transfer.sendTransfer(Transfer.java:183)
11-19 12:49:03.419 32442-32442/com.example.graeme.beamitup W/System.err:     at com.example.graeme.beamitup.MainActivity.onCreate(MainActivity.java:26)
11-19 12:49:03.419 32442-32442/com.example.graeme.beamitup W/System.err:     at android.app.Activity.performCreate(Activity.java:6272)

Es weist auf eine ungültige Antwort der HTTP-Übertragung hin - aber sollte dies nicht auch ohne den Versuch von Future.get passieren? Der Code wird so oder so ausgeführt, richtig? Was habe ich falsch gemacht, um diesen Fehler zu erzeugen?

Antworten (1)

1) Diese Zeile tut wahrscheinlich nicht das, was Sie erwarten:

Log.d(TAG, String.valueOf(rc.toString()));

rc hat den Typ RemoteCall<TransactionReceipt>, was bedeutet, dass es ausgeführt werden muss. Stattdessen konvertiert Ihr Code den Aufruf in einen String (zweimal): einmal von toString()und einmal von String.valueOf.

2) Du erschaffst eine Zukunft und wartest dann darauf, dass sie abgeschlossen ist, und ich weiß, dass du weißt, dass das sinnlos ist. Auf die Zukunft habe ich verzichtet, keine Ahnung warum Android auf eine Zukunft pocht. Mein einfacherer Code liefert das gleiche Ergebnis wie Ihr Code, sodass wir zumindest wissen, dass die Zukunft das von Ihnen gemeldete Problem nicht einführt.

3) Der Fehler tritt auf, nachdem diese JSON-RPC-Nutzdaten gesendet wurden:

{"jsonrpc":"2.0","method":"eth_gasPrice","params":[],"id":1}

Die ClientTransactionManager.sendTransaction()Methode stirbt, wenn sie versucht, Folgendes auszuführen:

return web3j.ethSendTransaction(transaction)
            .send();

Obwohl web3j.ethSendTransaction(transaction)es gut zu funktionieren scheint, gibt die verkettete send()Methode eine erfolglose Antwort zurück. Ich vermute, dass eine Authentifizierung erforderlich ist, aber natürlich wurden keine Anmeldeinformationen bereitgestellt, sodass die Transaktion abgelehnt wurde.

Ich arbeite nicht in Android, also hier ist der Code, mit dem ich gearbeitet habe:

import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.RemoteCall;
import org.web3j.protocol.core.methods.response.TransactionReceipt;
import org.web3j.protocol.http.HttpService;
import org.web3j.tx.ClientTransactionManager;
import org.web3j.utils.Convert;

import java.math.BigDecimal;

public class SO {
    private static final String FROM_ADDRESS = "0x6861B070f43842FC16eAD07854eE5D91B9D27C13";
    private static final String TO_ADDRESS = "0x31B98D14007bDEe637298086988A0bBd31184523";

    public static void main(String[] args) throws Exception {
        TransactionReceipt value = new SO().test();
        System.out.println(value);
    }

    private TransactionReceipt test() throws Exception {
        //Credentials credentials = obtainCredentials(WALLET_DIRECTORY);

        Web3j web3 = Web3j.build(
            new HttpService("https://rinkeby.infura.io/SxLC8uFzMPfzwnlXHqx9")
        );
        System.out.println("ethGasPrice=" + web3.ethGasPrice().getJsonrpc());

        ClientTransactionManager clientTransactionManager =
            new ClientTransactionManager(web3, FROM_ADDRESS);
        System.out.println("From address=" + clientTransactionManager.getFromAddress());

        org.web3j.tx.Transfer transfer = new org.web3j.tx.Transfer(web3, clientTransactionManager);
        System.out.println("transfer=" + String.valueOf(transfer.getSyncThreshold()));

        RemoteCall<TransactionReceipt> rc = transfer.sendFunds(
            TO_ADDRESS,
            BigDecimal.valueOf(1.0),
            Convert.Unit.ETHER
        );
        TransactionReceipt receipt = rc.send();
        System.out.println("receipt=" + receipt.toString());
        return receipt;
    }
}
Danke für deine Antwort. Sie hatten Recht, dass das Problem letztendlich mit der Autorisierung zusammenhängt - ich hatte nicht erkannt, dass Sie die Adresse eines Ethereum-Kontos aus dem öffentlichen Schlüssel ableiten können, also hatte ich das web3j-Autorisierungssystem nicht richtig verstanden. Dies führte dazu, dass ich nicht verstand, wie ich meine Überweisungen richtig autorisieren sollte. Ich habe es jetzt mit einer anderen sendFunds-Funktion von web3j implementiert, die eine Autorisierung erfordert und verwendet.
Als ich dies noch einmal betrachtete, meinte ich, dass Sie den öffentlichen Schlüssel / die öffentliche Adresse aus dem privaten Schlüssel ableiten können.
Ich habe dich gleich beim ersten Mal verstanden, kein Problem. Stimmen Sie für meine Antwort ab (klicken Sie oben auf den Aufwärtspfeil), wenn Sie so geneigt sind :)
Ich tat! Mein Ruf ist zu gering, als dass meine Stimmen noch angezeigt werden könnten :/