Не удалось получить значение из Web3j sendFunds Future

Я пытался отправить средства с одной учетной записи ethereum на другую, используя web3j, чтобы проверить, работает ли он на Android. Я использую облачный экземпляр Infura.

Во-первых, похоже, мне нужно отправить его асинхронно, потому что Android требует этого. В приведенном ниже коде я пытался это сделать, но на последнем шаге, когда я пытаюсь добраться из Будущего, это не удается. Если я не попытаюсь получить значение, то исключения не будет, но я, очевидно, не смогу ничего сделать со значением, которое я хочу сделать.

        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();

Это происходит с этим исключением:

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)

Он указывает на недопустимый ответ от HTTP-передачи, но разве это не должно происходить даже без использования Future.get? Код выполняется в любом случае, верно? Что я сделал не так, чтобы создать эту ошибку?

Ответы (1)

1) Эта строка, вероятно, не делает того, что вы ожидаете:

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

rc имеет тип RemoteCall<TransactionReceipt>, а это значит, что его нужно выполнить. Вместо этого ваш код преобразует вызов в строку (дважды): один раз из toString()и один раз из String.valueOf.

2) Вы создаете будущее, затем ждете его завершения, и я знаю, что вы знаете, что это бессмысленно. Я отказался от будущего, понятия не имею, почему Android настаивает на будущем. Мой более простой код дает тот же результат, что и ваш код, так что, по крайней мере, мы знаем, что будущее не связано с проблемой, о которой вы сообщаете.

3) Ошибка возникает после отправки этой полезной нагрузки JSON-RPC:

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

Метод ClientTransactionManager.sendTransaction()умирает при попытке выполнить:

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

Хотя web3j.ethSendTransaction(transaction)кажется, что работает нормально, связанный send()метод возвращает неудачный ответ. Я подозреваю, что требуется аутентификация, но, конечно, учетные данные не были предоставлены, поэтому транзакция была отклонена.

Я не работаю в Android, поэтому вот код, с которым я работал:

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;
    }
}
Спасибо за ваш ответ. Вы были правы в том, что проблема в конечном итоге была связана с авторизацией - я не знал, что вы можете получить адрес учетной записи ethereum из открытого ключа, поэтому я не понимал должным образом систему авторизации web3j. Это привело к тому, что я не понял, как правильно авторизовать мои переводы. Теперь я реализовал его с другой функцией web3j sendFunds, которая требует и использует авторизацию.
Возвращаясь к этому, я имел в виду, что вы можете получить открытый ключ/адрес из закрытого ключа.
Я понял тебя с первого раза, без проблем. Проголосуйте за мой ответ (нажмите стрелку вверх выше), если вы так склонны :)
Я сделал! У меня слишком низкая репутация, чтобы мои голоса еще не отображались :/