猿问

如何获取交易结果和状态

我正在尝试使用以太坊区块链和 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)直到获得状态?


慕田峪4524236
浏览 132回答 2
2回答

海绵宝宝撒

我没有找到任何方法来订阅事务的特定状态更改,但有一个解决方法:该go-ethereum包提供了 2 个函数SubscribeFilterLogs和SubscribeNewHead.&nbsp;我们可以使用第一个来获取日志(如果相关),第二个来获取块信息:SubscribeNewHead 订阅有关给定通道上当前区块链头的通知。当开采区块时,可以验证或拒绝/恢复交易,因此我们可以使用这个“技巧”func checkTransactionReceipt(_txHash string) int {&nbsp; &nbsp; client, _ := getClient("https://ropsten.infura.io/v3/XXXXXX")&nbsp; &nbsp; txHash := common.HexToHash(_txHash)&nbsp; &nbsp; tx, err := client.TransactionReceipt(context.Background(), txHash)&nbsp; &nbsp; if (Error.HasError(err)) {&nbsp; &nbsp; &nbsp; &nbsp; return (-1)&nbsp; &nbsp; }&nbsp; &nbsp; return (int(tx.Status))}func&nbsp; &nbsp; WaitForBlockCompletation(data EthData, hashToRead string) int {&nbsp; &nbsp; soc := make(chan *types.Header)&nbsp; &nbsp; sub, err := data.WssClient.SubscribeNewHead(context.Background(), soc)&nbsp; &nbsp; if (err != nil) {&nbsp; &nbsp; &nbsp; &nbsp; return -1&nbsp; &nbsp; }&nbsp; &nbsp; for {&nbsp; &nbsp; &nbsp; &nbsp; select {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case err := <-sub.Err():&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _ = err&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return -1&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case header := <-soc:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; logs.Info(header.TxHash.Hex())&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; transactionStatus := checkTransactionReceipt(hashToRead)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (transactionStatus == 0) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //FAILURE&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sub.Unsubscribe()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return 0&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else if (transactionStatus == 1) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //SUCCESS&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sub.Unsubscribe()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return 1&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}基本上我们正在等待区块被开采,然后如果交易尚未验证/拒绝,我们会检查TransactionReceipt失败并出现错误( )。not found然后,如果有交易,我们可以取消订阅并返回交易状态(0失败,1成功)。不确定这是否是最差、最好、唯一的方法,但它确实有效!请随意改进此解决方案!

呼啦一阵风

更简单/更新的解决方案:我认为waitMined函数就是您正在寻找的函数。bind.WaitMined(context.Background(), client, signedTx)
随时随地看视频慕课网APP

相关分类

Go
我要回答