diff --git a/x/ibc/core/04-channel/client/utils/utils.go b/x/ibc/core/04-channel/client/utils/utils.go index 5657367f41..4aa1363d31 100644 --- a/x/ibc/core/04-channel/client/utils/utils.go +++ b/x/ibc/core/04-channel/client/utils/utils.go @@ -231,3 +231,36 @@ func queryNextSequenceRecvABCI(clientCtx client.Context, portID, channelID strin return types.NewQueryNextSequenceReceiveResponse(sequence, proofBz, proofHeight), nil } + +// QueryPacketAcknowledgement returns the data about a packet acknowledgement. +// If prove is true, it performs an ABCI store query in order to retrieve the merkle proof. Otherwise, +// it uses the gRPC query client +func QueryPacketAcknowledgement(clientCtx client.Context, portID, channelID string, sequence uint64, prove bool) (*types.QueryPacketAcknowledgementResponse, error) { + if prove { + return queryPacketAcknowledgementABCI(clientCtx, portID, channelID, sequence) + } + + queryClient := types.NewQueryClient(clientCtx) + req := &types.QueryPacketAcknowledgementRequest{ + PortId: portID, + ChannelId: channelID, + Sequence: sequence, + } + + return queryClient.PacketAcknowledgement(context.Background(), req) +} + +func queryPacketAcknowledgementABCI(clientCtx client.Context, portID, channelID string, sequence uint64) (*types.QueryPacketAcknowledgementResponse, error) { + key := host.KeyPacketAcknowledgement(portID, channelID, sequence) + + value, proofBz, proofHeight, err := ibcclient.QueryTendermintProof(clientCtx, key) + if err != nil { + return nil, err + } + + if len(value) == 0 { + return nil, sdkerrors.Wrapf(types.ErrInvalidAcknowledgement, "portID (%s), channelID (%s), sequence (%d)", portID, channelID, sequence) + } + + return types.NewQueryPacketAcknowledgementResponse(value, proofBz, proofHeight), nil +}