Как получить результат и статус транзакции - PullRequest
0 голосов
/ 05 ноября 2019

Я пытаюсь работать с блокчейном Ethereum, с контрактами Solidity. В настоящее время я развертываю контракт и выполняю некоторые действия с ним, но мне хотелось бы знать, как получить некоторые «отзывы / обратные вызовы / возвраты» определенной транзакции.

Есть ли способ установить статустранзакция в 0 (ошибка) и по-прежнему получать события, например?

if (id.length <= 0) {
    emit Result("KO", "1");
    revert();
} 

Это не будет работать (нет события), потому что я все отменить, но статус будет установлен в 0

if (id.length <= 0) {
    emit Result("KO", "1");
    return;
} 

Я получу какое-то событие, но статус останется 1

if (id.length <= 0) {
    revert("KO_1");
} 

Статус будет 0, но у меня не будет никакого события

Вот мой код перехода навыполните действие:

func    testFunction(id []byte) {
    //...
    //...
    tx, err := instance.Action(opt, id)
    if (errors.HasError(err)) {
        return
    }
    callbackValue := subscribeToContract(tx.Hash().Hex())
    logs.Pretty(tx, callbackValue)
    //...
    //...
}

func    subscribeToContract(hashToRead string) myStruct {
    query := ethereum.FilterQuery{
        Addresses: []common.Address{address},
    }
    soc := make(chan types.Log)

    sub, err := WssClient.SubscribeFilterLogs(context.Background(), query, soc)
    if err != nil {
        logs.Error(err)
    }

    for {
        select {
        case err := <-sub.Err():
            logs.Info(`SOMETHING ERROR`)
            logs.Error(err)
        case vLog := <-soc:
        logs.Info(`SOMETHING`)
        contractAbi, _ := abi.JSON(strings.NewReader(string(SignABI)))  
        event := myStruct{}
    contractAbi.Unpack(&event, "Result", vLog.Data)
    logs.Info(`New Event from [` + vLog.TxHash.Hex() + `] : ` + event.Message)
        }
    }
}

Если id.length > 0, все хорошо. Но если id.length <= 0, у меня нет функции обратного вызова из функции subscribeToContract.

Есть ли способ напрямую получить статус результата, или я должен зацикливаться с tx, err := client.TransactionReceipt(context.Background(), txHash) до тех пор, пока не получу статус?

1 Ответ

0 голосов
/ 05 ноября 2019

Я не нашел способа подписаться на конкретное изменение статуса для транзакции, но обходной путь:
Пакет go-ethereum предоставляет 2 функции SubscribeFilterLogs и SubscribeNewHead. Мы можем использовать первый, чтобы получить журналы (если уместно), и второй, чтобы получить информацию о блоке:

SubscribeNewHead подписывается на уведомления о текущем заголовке цепочки блоков на данном канале.

Транзакция может быть проверена или отклонена / отменена при добыче блока, поэтому мы можем использовать этот «трюк»

func checkTransactionReceipt(_txHash string) int {
    client, _ := getClient("https://ropsten.infura.io/v3/XXXXXX")
    txHash := common.HexToHash(_txHash)
    tx, err := client.TransactionReceipt(context.Background(), txHash)
    if (Error.HasError(err)) {
        return (-1)
    }
    return (int(tx.Status))
}

func    WaitForBlockCompletation(data EthData, hashToRead string) int {
    soc := make(chan *types.Header)
    sub, err := data.WssClient.SubscribeNewHead(context.Background(), soc)
    if (err != nil) {
        return -1
    }

    for {
        select {
            case err := <-sub.Err():
                _ = err
                return -1
            case header := <-soc:
                logs.Info(header.TxHash.Hex())
                transactionStatus := checkTransactionReceipt(hashToRead)
                if (transactionStatus == 0) {
                    //FAILURE
                    sub.Unsubscribe()
                    return 0
                } else if (transactionStatus == 1) {
                    //SUCCESS
                    sub.Unsubscribe()
                    return 1
                }
        }
    }
}

В основном мы ожидаем, что блок будет добыт, затеммы проверяем TransactionReceipt, который завершается ошибкой (not found), если транзакция еще не подтверждена / отклонена. Затем, если транзакция есть, мы можем отменить подписку и вернуть статус транзакции (0 неудачных, 1 успешных).

Не уверен, что это худший, лучший, единственный метод, но он работает! Будьте свободны, чтобы улучшить это решение!

...